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

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

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

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#include "config.h"
22
23#include <SDL.h>
24
25#include "common.h"
26
27#include "system.h"
28#include "image.h"
29#include "palette.h"
30#include "video.h"
31#include "macs.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( (linked_node *)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            milli_wait( 1 );    // Sleep for 1 millisecond if there are no events
139    }
140
141    ep = (event *)events.first();
142    if( ep )
143    {
144        ev = *ep;
145        events.unlink( (linked_node *)ep );
146        delete ep;
147        ewaiting = events.first() != NULL;
148    }
149    else
150    {
151        // NOTE : that the mouse status should be known
152        // even if another event has occurred.
153        ev.mouse_move.x = mouse->x();
154        ev.mouse_move.y = mouse->y();
155        ev.mouse_button = mouse->button();
156
157        // Gather events
158        SDL_Event event;
159        if( SDL_PollEvent( &event ) )
160        {
161            // always sort the mouse out
162            handle_mouse( ev );
163            mouse->update( ev.mouse_move.x, ev.mouse_move.y, ev.mouse_button );
164
165            switch( event.type )
166            {
167                case SDL_QUIT:
168                {
169                    exit(0);
170                    break;
171                }
172                case SDL_MOUSEBUTTONUP:
173                {
174                    switch( event.button.button )
175                    {
176                        case 4:        // Mouse wheel goes up...
177                        {
178                            ev.key = get_key_binding( "b4", 0 );
179                            ev.type = EV_KEYRELEASE;
180                            break;
181                        }
182                        case 5:        // Mouse wheel goes down...
183                        {
184                            ev.key = get_key_binding( "b3", 0 );
185                            ev.type = EV_KEYRELEASE;
186                            break;
187                        }
188                    }
189                    break;
190                }
191                case SDL_MOUSEBUTTONDOWN:
192                {
193                    switch( event.button.button )
194                    {
195                        case 4:        // Mouse wheel goes up...
196                        {
197                            ev.key = get_key_binding( "b4", 0 );
198                            ev.type = EV_KEY;
199                            break;
200                        }
201                        case 5:        // Mouse wheel goes down...
202                        {
203                            ev.key = get_key_binding( "b3", 0 );
204                            ev.type = EV_KEY;
205                            break;
206                        }
207                    }
208                    break;
209                }
210                case SDL_KEYDOWN:
211                case SDL_KEYUP:
212                {
213                    // Default to EV_SPURIOUS
214                    ev.key = EV_SPURIOUS;
215                    if( event.type == SDL_KEYDOWN )
216                    {
217                        ev.type = EV_KEY;
218                    }
219                    else
220                    {
221                        ev.type = EV_KEYRELEASE;
222                    }
223                    switch( event.key.keysym.sym )
224                    {
225                        case SDLK_DOWN:            ev.key = JK_DOWN; break;
226                        case SDLK_UP:            ev.key = JK_UP; break;
227                        case SDLK_LEFT:            ev.key = JK_LEFT; break;
228                        case SDLK_RIGHT:        ev.key = JK_RIGHT; break;
229                        case SDLK_LCTRL:        ev.key = JK_CTRL_L; break;
230                        case SDLK_RCTRL:        ev.key = JK_CTRL_R; break;
231                        case SDLK_LALT:            ev.key = JK_ALT_L; break;
232                        case SDLK_RALT:            ev.key = JK_ALT_R; break;
233                        case SDLK_LSHIFT:        ev.key = JK_SHIFT_L; break;
234                        case SDLK_RSHIFT:        ev.key = JK_SHIFT_R; break;
235                        case SDLK_NUMLOCK:        ev.key = JK_NUM_LOCK; break;
236                        case SDLK_HOME:            ev.key = JK_HOME; break;
237                        case SDLK_END:            ev.key = JK_END; break;
238                        case SDLK_BACKSPACE:    ev.key = JK_BACKSPACE; break;
239                        case SDLK_TAB:            ev.key = JK_TAB; break;
240                        case SDLK_RETURN:        ev.key = JK_ENTER; break;
241                        case SDLK_SPACE:        ev.key = JK_SPACE; break;
242                        case SDLK_CAPSLOCK:        ev.key = JK_CAPS; break;
243                        case SDLK_ESCAPE:        ev.key = JK_ESC; break;
244                        case SDLK_F1:            ev.key = JK_F1; break;
245                        case SDLK_F2:            ev.key = JK_F2; break;
246                        case SDLK_F3:            ev.key = JK_F3; break;
247                        case SDLK_F4:            ev.key = JK_F4; break;
248                        case SDLK_F5:            ev.key = JK_F5; break;
249                        case SDLK_F6:            ev.key = JK_F6; break;
250                        case SDLK_F7:            ev.key = JK_F7; break;
251                        case SDLK_F8:            ev.key = JK_F8; break;
252                        case SDLK_F9:            ev.key = JK_F9; break;
253                        case SDLK_F10:            ev.key = JK_F10; break;
254                        case SDLK_INSERT:        ev.key = JK_INSERT; break;
255                        case SDLK_KP0:            ev.key = JK_INSERT; break;
256                        case SDLK_PAGEUP:        ev.key = JK_PAGEUP; break;
257                        case SDLK_PAGEDOWN:        ev.key = JK_PAGEDOWN; break;
258                        case SDLK_KP8:            ev.key = JK_UP; break;
259                        case SDLK_KP2:            ev.key = JK_DOWN; break;
260                        case SDLK_KP4:            ev.key = JK_LEFT; break;
261                        case SDLK_KP6:            ev.key = JK_RIGHT; break;
262                        case SDLK_F11:
263                        {
264                            // Only handle key down
265                            if( ev.type == EV_KEY )
266                            {
267                                // Toggle fullscreen
268                                SDL_WM_ToggleFullScreen( SDL_GetVideoSurface() );
269                            }
270                            ev.key = EV_SPURIOUS;
271                            break;
272                        }
273                        case SDLK_F12:
274                        {
275                            // Only handle key down
276                            if( ev.type == EV_KEY )
277                            {
278                                // Toggle grab mouse
279                                if( SDL_WM_GrabInput( SDL_GRAB_QUERY ) == SDL_GRAB_ON )
280                                {
281                                    the_game->show_help( "Grab Mouse: OFF\n" );
282                                    SDL_WM_GrabInput( SDL_GRAB_OFF );
283                                }
284                                else
285                                {
286                                    the_game->show_help( "Grab Mouse: ON\n" );
287                                    SDL_WM_GrabInput( SDL_GRAB_ON );
288                                }
289                            }
290                            ev.key = EV_SPURIOUS;
291                            break;
292                        }
293                        case SDLK_PRINT:    // print-screen key
294                        {
295                            // Only handle key down
296                            if( ev.type == EV_KEY )
297                            {
298                                // Grab a screenshot
299                                SDL_SaveBMP( SDL_GetVideoSurface(), "screenshot.bmp" );
300                                the_game->show_help( "Screenshot saved to: screenshot.bmp.\n" );
301                            }
302                            ev.key = EV_SPURIOUS;
303                            break;
304                        }
305                        default:
306                        {
307                            ev.key = (int)event.key.keysym.sym;
308                            // Need to handle the case of shift being pressed
309                            // There has to be a better way
310                            if( (event.key.keysym.mod & KMOD_SHIFT) != 0 )
311                            {
312                                if( event.key.keysym.sym >= SDLK_a &&
313                                    event.key.keysym.sym <= SDLK_z )
314                                {
315                                    ev.key -= 32;
316                                }
317                                else if( event.key.keysym.sym >= SDLK_1 &&
318                                         event.key.keysym.sym <= SDLK_5 )
319                                {
320                                    ev.key -= 16;
321                                }
322                                else
323                                {
324                                    switch( event.key.keysym.sym )
325                                    {
326                                        case SDLK_6:
327                                            ev.key = SDLK_CARET; break;
328                                        case SDLK_7:
329                                        case SDLK_9:
330                                        case SDLK_0:
331                                            ev.key -= 17; break;
332                                        case SDLK_8:
333                                            ev.key = SDLK_ASTERISK; break;
334                                        case SDLK_MINUS:
335                                            ev.key = SDLK_UNDERSCORE; break;
336                                        case SDLK_EQUALS:
337                                            ev.key = SDLK_PLUS; break;
338                                        case SDLK_COMMA:
339                                            ev.key = SDLK_LESS; break;
340                                        case SDLK_PERIOD:
341                                            ev.key = SDLK_GREATER; break;
342                                        case SDLK_SLASH:
343                                            ev.key = SDLK_QUESTION; break;
344                                        case SDLK_SEMICOLON:
345                                            ev.key = SDLK_COLON; break;
346                                        case SDLK_QUOTE:
347                                            ev.key = SDLK_QUOTEDBL; break;
348                                        default:
349                                            break;
350                                    }
351                                }
352                            }
353                        }
354                    }
355                    break;
356                }
357            }
358        }
359        // No more events
360        ewaiting = 0;
361    }
362}
363
364//
365// Handle mouse motion and button presses
366// We don't handle the mousewheel here as
367// SDL_GetMouseState doesn't seem to be
368// able to detect that.
369//
370void handle_mouse( event &ev )
371{
372    Uint8 buttons;
373    int x, y;
374
375    // always sort the mouse out
376    buttons = SDL_GetMouseState( &x, &y );
377    x = (x << 16) / mouse_xscale;
378    y = (y << 16) / mouse_yscale;
379    if( x > screen->Size().x - 1 )
380    {
381        x = screen->Size().x - 1;
382    }
383    if( y > screen->Size().y - 1 )
384    {
385        y = screen->Size().y - 1;
386    }
387    ev.mouse_move.x = x;
388    ev.mouse_move.y = y;
389    ev.type = EV_MOUSE_MOVE;
390
391    // Left button
392    if( (buttons & SDL_BUTTON(1)) && !mouse_buttons[1] )
393    {
394        ev.type = EV_MOUSE_BUTTON;
395        mouse_buttons[1] = !mouse_buttons[1];
396        ev.mouse_button |= LEFT_BUTTON;
397    }
398    else if( !(buttons & SDL_BUTTON(1)) && mouse_buttons[1] )
399    {
400        ev.type = EV_MOUSE_BUTTON;
401        mouse_buttons[1] = !mouse_buttons[1];
402        ev.mouse_button &= ( 0xff - LEFT_BUTTON );
403    }
404
405    // Middle button
406    if( (buttons & SDL_BUTTON(2)) && !mouse_buttons[2] )
407    {
408        ev.type = EV_MOUSE_BUTTON;
409        mouse_buttons[2] = !mouse_buttons[2];
410        ev.mouse_button |= LEFT_BUTTON;
411        ev.mouse_button |= RIGHT_BUTTON;
412    }
413    else if( !(buttons & SDL_BUTTON(2)) && mouse_buttons[2] )
414    {
415        ev.type = EV_MOUSE_BUTTON;
416        mouse_buttons[2] = !mouse_buttons[2];
417        ev.mouse_button &= ( 0xff - LEFT_BUTTON );
418        ev.mouse_button &= ( 0xff - RIGHT_BUTTON );
419    }
420
421    // Right button
422    if( (buttons & SDL_BUTTON(3)) && !mouse_buttons[3] )
423    {
424        ev.type = EV_MOUSE_BUTTON;
425        mouse_buttons[3] = !mouse_buttons[3];
426        ev.mouse_button |= RIGHT_BUTTON;
427    }
428    else if( !(buttons & SDL_BUTTON(3)) && mouse_buttons[3] )
429    {
430        ev.type = EV_MOUSE_BUTTON;
431        mouse_buttons[3] = !mouse_buttons[3];
432        ev.mouse_button &= ( 0xff - RIGHT_BUTTON );
433    }
434}
Note: See TracBrowser for help on using the repository browser.