source: trunk/src/sdl/sdl_input.cc @ 538

Last change on this file since 538 was 505, checked in by epyon, 9 years ago
  • several STL updates
  • several minor fixes
File size: 9.4 KB
Line 
1// Copyright (C) 2014-2015 ChaosForge Ltd
2// http://chaosforge.org/
3//
4// This file is part of Nova libraries.
5// For conditions of distribution and use, see copying.txt file in root folder.
6
7#include "nv/sdl/sdl_input.hh"
8
9#include "nv/lib/sdl.hh"
10#include "nv/core/logging.hh"
11
12using namespace nv;
13
14nv::sdl::input::input()
15{
16        if ( ! SDL_WasInit( SDL_INIT_JOYSTICK ) ) SDL_InitSubSystem( SDL_INIT_JOYSTICK );
17        if ( ! SDL_WasInit( SDL_INIT_GAMECONTROLLER ) ) SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER );
18}
19
20static bool sdl_key_event_to_io_event( const SDL_KeyboardEvent& ke, io_event& kevent )
21{
22        kevent.type          = EV_KEY;
23        kevent.key.window_id = ke.windowID;
24        kevent.key.pressed   = ( ke.state != SDL_RELEASED );
25        kevent.key.ascii     = 0;
26        kevent.key.code      = KEY_NONE;
27
28        uint32 ucode = static_cast<uint32>( ke.keysym.sym );
29
30        // if result is a typable char place it into the structure
31        if (ucode >= 32 && ucode < 128 )
32        {
33                kevent.key.ascii = static_cast<uchar8>( ucode );
34                if (ucode >= 'a' && ucode <= 'z')
35                {
36                        int shifted = !!(ke.keysym.mod & KMOD_SHIFT);
37                        int capslock = !!(ke.keysym.mod & KMOD_CAPS);
38                        if ((shifted ^ capslock) != 0) {
39                                kevent.key.ascii = static_cast<uchar8>( SDL_toupper( static_cast<int>( ucode ) ) );
40                        }
41                }
42        }
43
44        // Get the Key value from the SDL Keyboard event
45        int result = ke.keysym.sym;
46
47        // Check the control and shift states
48        kevent.key.alt     = (ke.keysym.mod & KMOD_ALT ) != 0;
49        kevent.key.control = (ke.keysym.mod & KMOD_CTRL ) != 0;
50        kevent.key.shift   = (ke.keysym.mod & KMOD_SHIFT ) != 0;
51
52        // if result is a typable char from the directly transformable ranges
53        if ( ( result >= KEY_A && result <= KEY_Z ) ||
54                ( result >= KEY_0 && result <= KEY_9 ) ||
55                result == ' ' )
56        {
57                kevent.key.code = static_cast<key_code>(result);
58        }
59
60        // if result is a typable char from the a..z range
61        if ( result >= KEY_A + 32 && result <= KEY_Z + 32 )
62        {
63                kevent.key.code = static_cast<key_code>(result - 32);
64        }
65
66        if ( result >= SDLK_F1 && result <= SDLK_F12 )
67        {
68                kevent.key.code = static_cast<key_code>(result - SDLK_F1 + KEY_F1 );
69        }
70
71        // other recognized codes
72        switch ( result )
73        {
74        case SDLK_BACKSPACE    : kevent.key.code = KEY_BACK; break;
75        case SDLK_TAB          : kevent.key.code = KEY_TAB; break;
76        case SDLK_RETURN       : kevent.key.code = KEY_ENTER; break;
77        case SDLK_PAGEUP       : kevent.key.code = KEY_PGUP; break;
78        case SDLK_PAGEDOWN     : kevent.key.code = KEY_PGDOWN; break;
79        case SDLK_END          : kevent.key.code = KEY_END; break;
80        case SDLK_HOME         : kevent.key.code = KEY_HOME; break;
81        case SDLK_LEFT         : kevent.key.code = KEY_LEFT; break;
82        case SDLK_UP           : kevent.key.code = KEY_UP; break;
83        case SDLK_RIGHT        : kevent.key.code = KEY_RIGHT; break;
84        case SDLK_DOWN         : kevent.key.code = KEY_DOWN; break;
85        case SDLK_DELETE       : kevent.key.code = KEY_DELETE; break;
86        case SDLK_INSERT       : kevent.key.code = KEY_INSERT; break;
87        //case SDLK_KP5          : kevent.key.code = KEY_CENTER; break;
88        case SDLK_ESCAPE       : kevent.key.code = KEY_ESCAPE; break;
89        case SDLK_QUOTE        : kevent.key.code = KEY_QUOTE; break;
90        case SDLK_COMMA        : kevent.key.code = KEY_COMMA; break;
91        case SDLK_MINUS        : kevent.key.code = KEY_MINUS; break;
92        case SDLK_PERIOD       : kevent.key.code = KEY_PERIOD; break;
93        case SDLK_SLASH        : kevent.key.code = KEY_SLASH; break;
94        case SDLK_SEMICOLON    : kevent.key.code = KEY_SCOLON; break;
95        case SDLK_LEFTBRACKET  : kevent.key.code = KEY_LBRACKET; break;
96        case SDLK_BACKSLASH    : kevent.key.code = KEY_BSLASH; break;
97        case SDLK_RIGHTBRACKET : kevent.key.code = KEY_RBRACKET; break;
98        case SDLK_BACKQUOTE    : kevent.key.code = KEY_BQUOTE; break;
99        default : break;
100        }
101
102        kevent.key.native = ke.keysym.scancode;
103
104        // If key was understood by nv, then it's valid, otherwise ignored
105        return kevent.key.ascii != 0 || kevent.key.code != 0;
106}
107
108static bool sdl_mouse_button_to_io_event( const SDL_MouseButtonEvent& mb, io_event& mevent )
109{
110        mevent.type              = EV_MOUSE_BUTTON;
111        mevent.mbutton.window_id = mb.windowID;
112        mevent.mbutton.button    = MOUSE_NONE;
113        mevent.mbutton.pressed   = (mb.state != SDL_RELEASED);
114        mevent.mbutton.x         = static_cast< uint16 >( mb.x );
115        mevent.mbutton.y         = static_cast< uint16 >( mb.y );
116
117        switch ( mb.button )
118        {
119        case SDL_BUTTON_LEFT      : mevent.mbutton.button = MOUSE_LEFT; break;
120        case SDL_BUTTON_MIDDLE    : mevent.mbutton.button = MOUSE_MIDDLE; break;
121        case SDL_BUTTON_RIGHT     : mevent.mbutton.button = MOUSE_RIGHT; break;
122        default : break;
123        }
124
125        return mevent.mbutton.button != MOUSE_NONE;
126}
127
128static bool sdl_mouse_wheel_to_io_event( const SDL_MouseWheelEvent& mm, io_event& mevent )
129{
130        mevent.type             = EV_MOUSE_WHEEL;
131        mevent.mwheel.window_id = mm.windowID;
132        mevent.mwheel.x         = static_cast< sint32 >( mm.x );
133        mevent.mwheel.y         = static_cast< sint32 >( mm.y );
134        return true;
135}
136
137static bool sdl_mouse_motion_to_io_event( const SDL_MouseMotionEvent& mm, io_event& mevent )
138{
139        mevent.type            = EV_MOUSE_MOVE;
140        mevent.mmove.window_id = mm.windowID;
141        mevent.mmove.pressed   = (mm.state != SDL_RELEASED);
142        mevent.mmove.x         = static_cast< uint16 >( mm.x );
143        mevent.mmove.y         = static_cast< uint16 >( mm.y );
144        mevent.mmove.rx        = static_cast< sint16 >( mm.xrel );
145        mevent.mmove.ry        = static_cast< sint16 >( mm.yrel );
146        return true;
147}
148
149static bool sdl_pad_button_event_to_io_event( const SDL_ControllerButtonEvent& cb, io_event& cevent )
150{
151        cevent.type            = EV_PAD_BUTTON;
152        cevent.pbutton.id      = cb.which;
153        cevent.pbutton.button  = cb.button;
154        cevent.pbutton.pressed = (cb.type == SDL_PRESSED);
155        return true;
156}
157
158static bool sdl_pad_axis_event_to_io_event( const SDL_ControllerAxisEvent& ca, io_event& cevent )
159{
160        cevent.type          = EV_PAD_AXIS;
161        cevent.paxis.id      = ca.which;
162        cevent.paxis.axis    = ca.axis;
163        cevent.paxis.value   = ca.value;
164        return true;
165}
166
167
168static bool sdl_joy_button_event_to_io_event( const SDL_JoyButtonEvent& jb, io_event& jevent )
169{
170        jevent.type            = EV_JOY_BUTTON;
171        jevent.jbutton.id      = jb.which;
172        jevent.jbutton.button  = jb.button;
173        jevent.jbutton.pressed = (jb.type == SDL_PRESSED);
174        return true;
175}
176
177static bool sdl_joy_axis_event_to_io_event( const SDL_JoyAxisEvent& ja, io_event& jevent )
178{
179        jevent.type          = EV_JOY_AXIS;
180        jevent.jaxis.id      = ja.which;
181        jevent.jaxis.axis    = ja.axis;
182        jevent.jaxis.value   = ja.value;
183        return true;
184}
185
186static bool sdl_joy_hat_event_to_io_event( const SDL_JoyHatEvent& jh, io_event& jevent )
187{
188        jevent.type          = EV_JOY_HAT;
189        jevent.jhat.id       = jh.which;
190        jevent.jhat.hat      = jh.hat;
191        jevent.jhat.value    = jh.value;
192        return true;
193}
194
195static bool sdl_joy_ball_event_to_io_event( const SDL_JoyBallEvent& jb, io_event& jevent )
196{
197        jevent.type          = EV_JOY_HAT;
198        jevent.jball.id      = jb.which;
199        jevent.jball.ball    = jb.ball;
200        jevent.jball.rx      = jb.xrel;
201        jevent.jball.ry      = jb.yrel;
202        return true;
203}
204
205static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent )
206{
207        switch ( e.type )
208        {
209        case SDL_KEYDOWN         : return sdl_key_event_to_io_event( e.key, ioevent );
210        case SDL_KEYUP           : return sdl_key_event_to_io_event( e.key, ioevent );
211        case SDL_MOUSEMOTION     : return sdl_mouse_motion_to_io_event( e.motion, ioevent );
212        case SDL_MOUSEBUTTONDOWN : return sdl_mouse_button_to_io_event( e.button, ioevent );
213        case SDL_MOUSEBUTTONUP   : return sdl_mouse_button_to_io_event( e.button, ioevent );
214        case SDL_MOUSEWHEEL      : return sdl_mouse_wheel_to_io_event( e.wheel, ioevent );
215/* // SDL 2.0 incompatible
216        case SDL_ACTIVEEVENT     :
217                ioevent.type = EV_ACTIVE;
218                ioevent.active.gain = (e.active.gain != 0);
219                return e.active.state == SDL_APPINPUTFOCUS;
220        case SDL_VIDEORESIZE     :
221                ioevent.type     = EV_RESIZE;
222                ioevent.resize.x = e.resize.w;
223                ioevent.resize.y = e.resize.h;
224                return true;
225        case SDL_NOEVENT         : return false;
226        case SDL_VIDEOEXPOSE     : return false;
227*/
228        case SDL_WINDOWEVENT_ENTER: ioevent.type = EV_SYSTEM; ioevent.system.param1 = 1; ioevent.system.param1 = e.window.windowID; return true;
229        case SDL_WINDOWEVENT_LEAVE: ioevent.type = EV_SYSTEM; ioevent.system.param1 = 0; ioevent.system.param1 = e.window.windowID; return true;
230        case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
231        case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
232        case SDL_CONTROLLERAXISMOTION : return sdl_pad_axis_event_to_io_event( e.caxis, ioevent );
233        case SDL_CONTROLLERBUTTONDOWN : return sdl_pad_button_event_to_io_event( e.cbutton, ioevent );
234        case SDL_CONTROLLERBUTTONUP   :
235        case SDL_JOYAXISMOTION   : return sdl_joy_axis_event_to_io_event( e.jaxis, ioevent );
236        case SDL_JOYBALLMOTION   : return sdl_joy_ball_event_to_io_event( e.jball, ioevent );
237        case SDL_JOYHATMOTION    : return sdl_joy_hat_event_to_io_event( e.jhat, ioevent );
238        case SDL_JOYBUTTONDOWN   : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
239        case SDL_JOYBUTTONUP     : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
240        default : return false;
241        }
242}
243
244bool sdl::input::is_event_pending()
245{
246        return SDL_PollEvent( nullptr ) != 0;
247}
248
249bool sdl::input::poll_event( io_event& event )
250{
251        SDL_Event sdl_event;
252        if ( SDL_PollEvent( &sdl_event ) == 0 ) return false;
253        return sdl_event_to_io_event( sdl_event, event );
254}
255
Note: See TracBrowser for help on using the repository browser.