source: abuse/trunk/src/sdlport/event.cpp @ 577

Last change on this file since 577 was 577, checked in by Sam Hocevar, 11 years ago

game: get rid of milli_wait() and rewrite the fixed framerate handling.

File size: 15.1 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 2001 Anthony Kruize <trandor@labyrinth.net.au>
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 2 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, write to the Free Software Foundation,
18 *  Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 */
20
21#if defined HAVE_CONFIG_H
22#   include "config.h"
23#endif
24
25#include <SDL.h>
26
27#include "common.h"
28
29#include "image.h"
30#include "palette.h"
31#include "video.h"
32#include "mouse.h"
33#include "event.h"
34#include "timing.h"
35#include "sprite.h"
36#include "game.h"
37
38extern int get_key_binding( char const *dir, int i );
39extern int mouse_xscale, mouse_yscale;
40short mouse_buttons[5] = { 0, 0, 0, 0, 0 };
41
42// Pre-declarations
43void handle_mouse( event &ev );
44
45//
46// Constructor
47//
48event_handler::event_handler( image *screen, palette *pal )
49{
50    CHECK( screen && pal );
51    mouse = new JCMouse( screen, pal );
52    mhere = mouse->exsist();
53    last_keystat = get_key_flags();
54    ewaiting = 0;
55
56    // Ignore activate events
57    SDL_EventState( SDL_ACTIVEEVENT, SDL_IGNORE );
58}
59
60//
61// Destructor
62//
63event_handler::~event_handler()
64{
65    delete mouse;
66}
67
68//
69// flush_screen()
70// Redraw the screen
71//
72void event_handler::flush_screen()
73{
74    update_dirty( screen );
75}
76
77//
78// get_key_flags()
79// Return the flag for the key modifiers
80//
81int event_handler::get_key_flags()
82{
83    SDLMod key_flag;
84
85    key_flag = SDL_GetModState();
86
87    return ( ( key_flag & KMOD_SHIFT ) != 0 ) << 3 |
88           ( ( key_flag & KMOD_CTRL ) != 0 ) << 2 |
89           ( ( key_flag & KMOD_ALT ) != 0 ) << 1;
90}
91
92//
93// event_waiting()
94// Are there any events in the queue?
95//
96int event_handler::event_waiting()
97{
98    if( ewaiting )
99    {
100        return 1;
101    }
102    if( SDL_PollEvent( NULL ) )
103    {
104        ewaiting = 1;
105    }
106    return ewaiting;
107}
108
109//
110// add_redraw()
111// Add a redraw rectangle.
112//
113void event_handler::add_redraw( int X1, int Y1, int X2, int Y2, void *Start )
114{
115    event *ev;
116    ev = new event;
117    ev->type = EV_REDRAW;
118    ev->redraw.x1 = X1;
119    ev->redraw.x2 = X2;
120    ev->redraw.y1 = Y1;
121    ev->redraw.y2 = Y2;
122    ev->redraw.start = Start;
123    events.add_end(ev);
124}
125
126//
127// get_event()
128// Get and handle waiting events
129//
130void event_handler::get_event( event &ev )
131{
132    event *ep;
133    while( !ewaiting )
134    {
135        event_waiting();
136
137        if (!ewaiting)
138        {
139            // Sleep for 1 millisecond if there are no events
140            Timer tmp; tmp.WaitMs(1);
141        }
142    }
143
144    ep = (event *)events.first();
145    if( ep )
146    {
147        ev = *ep;
148        events.unlink(ep);
149        delete ep;
150        ewaiting = events.first() != NULL;
151    }
152    else
153    {
154        // NOTE : that the mouse status should be known
155        // even if another event has occurred.
156        ev.mouse_move.x = mouse->x();
157        ev.mouse_move.y = mouse->y();
158        ev.mouse_button = mouse->button();
159
160        // Gather events
161        SDL_Event event;
162        if( SDL_PollEvent( &event ) )
163        {
164            // always sort the mouse out
165            handle_mouse( ev );
166            mouse->update( ev.mouse_move.x, ev.mouse_move.y, ev.mouse_button );
167
168            switch( event.type )
169            {
170                case SDL_QUIT:
171                {
172                    exit(0);
173                    break;
174                }
175                case SDL_MOUSEBUTTONUP:
176                {
177                    switch( event.button.button )
178                    {
179                        case 4:        // Mouse wheel goes up...
180                        {
181                            ev.key = get_key_binding( "b4", 0 );
182                            ev.type = EV_KEYRELEASE;
183                            break;
184                        }
185                        case 5:        // Mouse wheel goes down...
186                        {
187                            ev.key = get_key_binding( "b3", 0 );
188                            ev.type = EV_KEYRELEASE;
189                            break;
190                        }
191                    }
192                    break;
193                }
194                case SDL_MOUSEBUTTONDOWN:
195                {
196                    switch( event.button.button )
197                    {
198                        case 4:        // Mouse wheel goes up...
199                        {
200                            ev.key = get_key_binding( "b4", 0 );
201                            ev.type = EV_KEY;
202                            break;
203                        }
204                        case 5:        // Mouse wheel goes down...
205                        {
206                            ev.key = get_key_binding( "b3", 0 );
207                            ev.type = EV_KEY;
208                            break;
209                        }
210                    }
211                    break;
212                }
213                case SDL_KEYDOWN:
214                case SDL_KEYUP:
215                {
216                    // Default to EV_SPURIOUS
217                    ev.key = EV_SPURIOUS;
218                    if( event.type == SDL_KEYDOWN )
219                    {
220                        ev.type = EV_KEY;
221                    }
222                    else
223                    {
224                        ev.type = EV_KEYRELEASE;
225                    }
226                    switch( event.key.keysym.sym )
227                    {
228                        case SDLK_DOWN:            ev.key = JK_DOWN; break;
229                        case SDLK_UP:            ev.key = JK_UP; break;
230                        case SDLK_LEFT:            ev.key = JK_LEFT; break;
231                        case SDLK_RIGHT:        ev.key = JK_RIGHT; break;
232                        case SDLK_LCTRL:        ev.key = JK_CTRL_L; break;
233                        case SDLK_RCTRL:        ev.key = JK_CTRL_R; break;
234                        case SDLK_LALT:            ev.key = JK_ALT_L; break;
235                        case SDLK_RALT:            ev.key = JK_ALT_R; break;
236                        case SDLK_LSHIFT:        ev.key = JK_SHIFT_L; break;
237                        case SDLK_RSHIFT:        ev.key = JK_SHIFT_R; break;
238                        case SDLK_NUMLOCK:        ev.key = JK_NUM_LOCK; break;
239                        case SDLK_HOME:            ev.key = JK_HOME; break;
240                        case SDLK_END:            ev.key = JK_END; break;
241                        case SDLK_BACKSPACE:    ev.key = JK_BACKSPACE; break;
242                        case SDLK_TAB:            ev.key = JK_TAB; break;
243                        case SDLK_RETURN:        ev.key = JK_ENTER; break;
244                        case SDLK_SPACE:        ev.key = JK_SPACE; break;
245                        case SDLK_CAPSLOCK:        ev.key = JK_CAPS; break;
246                        case SDLK_ESCAPE:        ev.key = JK_ESC; break;
247                        case SDLK_F1:            ev.key = JK_F1; break;
248                        case SDLK_F2:            ev.key = JK_F2; break;
249                        case SDLK_F3:            ev.key = JK_F3; break;
250                        case SDLK_F4:            ev.key = JK_F4; break;
251                        case SDLK_F5:            ev.key = JK_F5; break;
252                        case SDLK_F6:            ev.key = JK_F6; break;
253                        case SDLK_F7:            ev.key = JK_F7; break;
254                        case SDLK_F8:            ev.key = JK_F8; break;
255                        case SDLK_F9:            ev.key = JK_F9; break;
256                        case SDLK_F10:            ev.key = JK_F10; break;
257                        case SDLK_INSERT:        ev.key = JK_INSERT; break;
258                        case SDLK_KP0:            ev.key = JK_INSERT; break;
259                        case SDLK_PAGEUP:        ev.key = JK_PAGEUP; break;
260                        case SDLK_PAGEDOWN:        ev.key = JK_PAGEDOWN; break;
261                        case SDLK_KP8:            ev.key = JK_UP; break;
262                        case SDLK_KP2:            ev.key = JK_DOWN; break;
263                        case SDLK_KP4:            ev.key = JK_LEFT; break;
264                        case SDLK_KP6:            ev.key = JK_RIGHT; break;
265                        case SDLK_F11:
266                        {
267                            // Only handle key down
268                            if( ev.type == EV_KEY )
269                            {
270                                // Toggle fullscreen
271                                SDL_WM_ToggleFullScreen( SDL_GetVideoSurface() );
272                            }
273                            ev.key = EV_SPURIOUS;
274                            break;
275                        }
276                        case SDLK_F12:
277                        {
278                            // Only handle key down
279                            if( ev.type == EV_KEY )
280                            {
281                                // Toggle grab mouse
282                                if( SDL_WM_GrabInput( SDL_GRAB_QUERY ) == SDL_GRAB_ON )
283                                {
284                                    the_game->show_help( "Grab Mouse: OFF\n" );
285                                    SDL_WM_GrabInput( SDL_GRAB_OFF );
286                                }
287                                else
288                                {
289                                    the_game->show_help( "Grab Mouse: ON\n" );
290                                    SDL_WM_GrabInput( SDL_GRAB_ON );
291                                }
292                            }
293                            ev.key = EV_SPURIOUS;
294                            break;
295                        }
296                        case SDLK_PRINT:    // print-screen key
297                        {
298                            // Only handle key down
299                            if( ev.type == EV_KEY )
300                            {
301                                // Grab a screenshot
302                                SDL_SaveBMP( SDL_GetVideoSurface(), "screenshot.bmp" );
303                                the_game->show_help( "Screenshot saved to: screenshot.bmp.\n" );
304                            }
305                            ev.key = EV_SPURIOUS;
306                            break;
307                        }
308                        default:
309                        {
310                            ev.key = (int)event.key.keysym.sym;
311                            // Need to handle the case of shift being pressed
312                            // There has to be a better way
313                            if( (event.key.keysym.mod & KMOD_SHIFT) != 0 )
314                            {
315                                if( event.key.keysym.sym >= SDLK_a &&
316                                    event.key.keysym.sym <= SDLK_z )
317                                {
318                                    ev.key -= 32;
319                                }
320                                else if( event.key.keysym.sym >= SDLK_1 &&
321                                         event.key.keysym.sym <= SDLK_5 )
322                                {
323                                    ev.key -= 16;
324                                }
325                                else
326                                {
327                                    switch( event.key.keysym.sym )
328                                    {
329                                        case SDLK_6:
330                                            ev.key = SDLK_CARET; break;
331                                        case SDLK_7:
332                                        case SDLK_9:
333                                        case SDLK_0:
334                                            ev.key -= 17; break;
335                                        case SDLK_8:
336                                            ev.key = SDLK_ASTERISK; break;
337                                        case SDLK_MINUS:
338                                            ev.key = SDLK_UNDERSCORE; break;
339                                        case SDLK_EQUALS:
340                                            ev.key = SDLK_PLUS; break;
341                                        case SDLK_COMMA:
342                                            ev.key = SDLK_LESS; break;
343                                        case SDLK_PERIOD:
344                                            ev.key = SDLK_GREATER; break;
345                                        case SDLK_SLASH:
346                                            ev.key = SDLK_QUESTION; break;
347                                        case SDLK_SEMICOLON:
348                                            ev.key = SDLK_COLON; break;
349                                        case SDLK_QUOTE:
350                                            ev.key = SDLK_QUOTEDBL; break;
351                                        default:
352                                            break;
353                                    }
354                                }
355                            }
356                        }
357                    }
358                    break;
359                }
360            }
361        }
362        // No more events
363        ewaiting = 0;
364    }
365}
366
367//
368// Handle mouse motion and button presses
369// We don't handle the mousewheel here as
370// SDL_GetMouseState doesn't seem to be
371// able to detect that.
372//
373void handle_mouse( event &ev )
374{
375    Uint8 buttons;
376    int x, y;
377
378    // always sort the mouse out
379    buttons = SDL_GetMouseState( &x, &y );
380    x = (x << 16) / mouse_xscale;
381    y = (y << 16) / mouse_yscale;
382    if( x > screen->Size().x - 1 )
383    {
384        x = screen->Size().x - 1;
385    }
386    if( y > screen->Size().y - 1 )
387    {
388        y = screen->Size().y - 1;
389    }
390    ev.mouse_move.x = x;
391    ev.mouse_move.y = y;
392    ev.type = EV_MOUSE_MOVE;
393
394    // Left button
395    if( (buttons & SDL_BUTTON(1)) && !mouse_buttons[1] )
396    {
397        ev.type = EV_MOUSE_BUTTON;
398        mouse_buttons[1] = !mouse_buttons[1];
399        ev.mouse_button |= LEFT_BUTTON;
400    }
401    else if( !(buttons & SDL_BUTTON(1)) && mouse_buttons[1] )
402    {
403        ev.type = EV_MOUSE_BUTTON;
404        mouse_buttons[1] = !mouse_buttons[1];
405        ev.mouse_button &= ( 0xff - LEFT_BUTTON );
406    }
407
408    // Middle button
409    if( (buttons & SDL_BUTTON(2)) && !mouse_buttons[2] )
410    {
411        ev.type = EV_MOUSE_BUTTON;
412        mouse_buttons[2] = !mouse_buttons[2];
413        ev.mouse_button |= LEFT_BUTTON;
414        ev.mouse_button |= RIGHT_BUTTON;
415    }
416    else if( !(buttons & SDL_BUTTON(2)) && mouse_buttons[2] )
417    {
418        ev.type = EV_MOUSE_BUTTON;
419        mouse_buttons[2] = !mouse_buttons[2];
420        ev.mouse_button &= ( 0xff - LEFT_BUTTON );
421        ev.mouse_button &= ( 0xff - RIGHT_BUTTON );
422    }
423
424    // Right button
425    if( (buttons & SDL_BUTTON(3)) && !mouse_buttons[3] )
426    {
427        ev.type = EV_MOUSE_BUTTON;
428        mouse_buttons[3] = !mouse_buttons[3];
429        ev.mouse_button |= RIGHT_BUTTON;
430    }
431    else if( !(buttons & SDL_BUTTON(3)) && mouse_buttons[3] )
432    {
433        ev.type = EV_MOUSE_BUTTON;
434        mouse_buttons[3] = !mouse_buttons[3];
435        ev.mouse_button &= ( 0xff - RIGHT_BUTTON );
436    }
437}
Note: See TracBrowser for help on using the repository browser.