source: trunk/src/gl/gl_window.cc @ 246

Last change on this file since 246 was 246, checked in by epyon, 11 years ago
  • sdl mouse move event didn't record relative values - fixed
File size: 11.3 KB
Line 
1// Copyright (C) 2012-2013 Kornel Kisielewicz
2// This file is part of NV Libraries.
3// For conditions of distribution and use, see copyright notice in nv.hh
4
5#include "nv/gl/gl_window.hh"
6
7#include "nv/logging.hh"
8#include "nv/lib/gl.hh"
9#include "nv/lib/sdl.hh"
10
11using namespace nv;
12
13static bool sdl_key_event_to_io_event( const SDL_KeyboardEvent& ke, io_event& kevent )
14{
15        kevent.type        = EV_KEY;
16        kevent.key.pressed = ( ke.state != SDL_RELEASED );
17        kevent.key.ascii   = 0;
18        kevent.key.code    = KEY_NONE;
19
20#if NV_SDL_VERSION == NV_SDL_20
21        uint32 ucode = ke.keysym.sym;
22#else
23        uint32 ucode = ke.keysym.unicode;
24#endif
25
26        // if result is a typable char place it into the structure
27        if (ucode >= 32 && ucode < 128 )
28        {
29                kevent.key.ascii = static_cast<char8>( ucode );
30#if NV_SDL_VERSION == NV_SDL_20
31                if (ucode >= 'a' && ucode <= 'z')
32                {
33                        int shifted = !!(ke.keysym.mod & KMOD_SHIFT);
34                        int capslock = !!(ke.keysym.mod & KMOD_CAPS);
35                        if ((shifted ^ capslock) != 0) {
36                                kevent.key.ascii = (char8)SDL_toupper(ucode);
37                        }
38                }
39#endif
40        }
41
42        // Get the Key value from the SDL Keyboard event
43        int result = ke.keysym.sym;
44
45        // Check the control and shift states
46        kevent.key.alt     = (ke.keysym.mod & KMOD_ALT ) != 0;
47        kevent.key.control = (ke.keysym.mod & KMOD_CTRL ) != 0;
48        kevent.key.shift   = (ke.keysym.mod & KMOD_SHIFT ) != 0;
49
50        // if result is a typable char from the directly transformable ranges
51        if ( ( result >= KEY_A && result <= KEY_Z ) ||
52                ( result >= KEY_0 && result <= KEY_9 ) ||
53                result == ' ' )
54        {
55                kevent.key.code = static_cast<key_code>(result);
56        }
57
58        // if result is a typable char from the a..z range
59        if ( result >= KEY_A + 32 && result <= KEY_Z + 32 )
60        {
61                kevent.key.code = static_cast<key_code>(result - 32);
62        }
63
64        if ( result >= SDLK_F1 && result <= SDLK_F12 )
65        {
66                kevent.key.code = static_cast<key_code>(result - SDLK_F1 + KEY_F1 );
67        }
68
69        // other recognized codes
70        switch ( result )
71        {
72        case SDLK_BACKSPACE    : kevent.key.code = KEY_BACK; break;
73        case SDLK_TAB          : kevent.key.code = KEY_TAB; break;
74        case SDLK_RETURN       : kevent.key.code = KEY_ENTER; break;
75        case SDLK_PAGEUP       : kevent.key.code = KEY_PGUP; break;
76        case SDLK_PAGEDOWN     : kevent.key.code = KEY_PGDOWN; break;
77        case SDLK_END          : kevent.key.code = KEY_END; break;
78        case SDLK_HOME         : kevent.key.code = KEY_HOME; break;
79        case SDLK_LEFT         : kevent.key.code = KEY_LEFT; break;
80        case SDLK_UP           : kevent.key.code = KEY_UP; break;
81        case SDLK_RIGHT        : kevent.key.code = KEY_RIGHT; break;
82        case SDLK_DOWN         : kevent.key.code = KEY_DOWN; break;
83        case SDLK_DELETE       : kevent.key.code = KEY_DELETE; break;
84        case SDLK_INSERT       : kevent.key.code = KEY_INSERT; break;
85        //case SDLK_KP5          : kevent.key.code = KEY_CENTER; break;
86        case SDLK_ESCAPE       : kevent.key.code = KEY_ESCAPE; break;
87        case SDLK_QUOTE        : kevent.key.code = KEY_QUOTE; break;
88        case SDLK_COMMA        : kevent.key.code = KEY_COMMA; break;
89        case SDLK_MINUS        : kevent.key.code = KEY_MINUS; break;
90        case SDLK_PERIOD       : kevent.key.code = KEY_PERIOD; break;
91        case SDLK_SLASH        : kevent.key.code = KEY_SLASH; break;
92        case SDLK_SEMICOLON    : kevent.key.code = KEY_SCOLON; break;
93        case SDLK_LEFTBRACKET  : kevent.key.code = KEY_LBRACKET; break;
94        case SDLK_BACKSLASH    : kevent.key.code = KEY_BSLASH; break;
95        case SDLK_RIGHTBRACKET : kevent.key.code = KEY_RBRACKET; break;
96        case SDLK_BACKQUOTE    : kevent.key.code = KEY_BQUOTE; break;
97        default : break;
98        }
99
100        // If key was understood by nv, then it's valid, otherwise ignored
101        return kevent.key.ascii != 0 || kevent.key.code != 0;
102}
103
104static bool sdl_mouse_button_to_io_event( const SDL_MouseButtonEvent& mb, io_event& mevent )
105{
106        mevent.type            = EV_MOUSE_BUTTON;
107        mevent.mbutton.button  = MOUSE_NONE;
108        mevent.mbutton.pressed = (mb.state != SDL_RELEASED);
109        mevent.mbutton.x       = static_cast< uint16 >( mb.x );
110        mevent.mbutton.y       = static_cast< uint16 >( mb.y );
111
112        switch ( mb.button )
113        {
114        case SDL_BUTTON_LEFT      : mevent.mbutton.button = MOUSE_LEFT; break;
115        case SDL_BUTTON_MIDDLE    : mevent.mbutton.button = MOUSE_MIDDLE; break;
116        case SDL_BUTTON_RIGHT     : mevent.mbutton.button = MOUSE_RIGHT; break;
117        //case SDL_BUTTON_WHEELUP   : mevent.mbutton.button = MOUSE_WHEEL_UP; break;
118        //case SDL_BUTTON_WHEELDOWN : mevent.mbutton.button = MOUSE_WHEEL_DOWN; break;
119        default : break;
120        }
121
122        return mevent.mbutton.button != MOUSE_NONE;
123}
124
125static bool sdl_mouse_motion_to_io_event( const SDL_MouseMotionEvent& mm, io_event& mevent )
126{
127        mevent.type          = EV_MOUSE_MOVE;
128        mevent.mmove.pressed = (mm.state != SDL_RELEASED);
129        mevent.mmove.x       = static_cast< uint16 >( mm.x );
130        mevent.mmove.y       = static_cast< uint16 >( mm.y );
131        mevent.mmove.rx      = static_cast< sint16 >( mm.xrel );
132        mevent.mmove.ry      = static_cast< sint16 >( mm.yrel );
133        return true;
134}
135
136static bool sdl_joy_button_event_to_io_event( const SDL_JoyButtonEvent& jb, io_event& jevent )
137{
138        jevent.type            = EV_JOY_BUTTON;
139        jevent.jbutton.id      = jb.which;
140        jevent.jbutton.button  = jb.button;
141        jevent.jbutton.pressed = (jb.type == SDL_PRESSED);
142        return true;
143}
144
145static bool sdl_joy_axis_event_to_io_event( const SDL_JoyAxisEvent& ja, io_event& jevent )
146{
147        jevent.type          = EV_JOY_AXIS;
148        jevent.jaxis.id      = ja.which;
149        jevent.jaxis.axis    = ja.axis;
150        jevent.jaxis.value   = ja.value;
151        return true;
152}
153
154static bool sdl_joy_hat_event_to_io_event( const SDL_JoyHatEvent& jh, io_event& jevent )
155{
156        jevent.type          = EV_JOY_HAT;
157        jevent.jhat.id       = jh.which;
158        jevent.jhat.hat      = jh.hat;
159        jevent.jhat.value    = jh.value;
160        return true;
161}
162
163static bool sdl_joy_ball_event_to_io_event( const SDL_JoyBallEvent& jb, io_event& jevent )
164{
165        jevent.type          = EV_JOY_HAT;
166        jevent.jball.id      = jb.which;
167        jevent.jball.ball    = jb.ball;
168        jevent.jball.rx      = jb.xrel;
169        jevent.jball.ry      = jb.yrel;
170        return true;
171}
172
173static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent )
174{
175        switch ( e.type )
176        {
177        case SDL_KEYDOWN         : return sdl_key_event_to_io_event( e.key, ioevent );
178        case SDL_KEYUP           : return sdl_key_event_to_io_event( e.key, ioevent );
179        case SDL_MOUSEMOTION     : return sdl_mouse_motion_to_io_event( e.motion, ioevent );
180        case SDL_MOUSEBUTTONDOWN : return sdl_mouse_button_to_io_event( e.button, ioevent );
181        case SDL_MOUSEBUTTONUP   : return sdl_mouse_button_to_io_event( e.button, ioevent );
182/* // SDL 2.0 incompatible
183        case SDL_ACTIVEEVENT     :
184                ioevent.type = EV_ACTIVE;
185                ioevent.active.gain = (e.active.gain != 0);
186                return e.active.state == SDL_APPINPUTFOCUS;
187        case SDL_VIDEORESIZE     :
188                ioevent.type     = EV_RESIZE;
189                ioevent.resize.x = e.resize.w;
190                ioevent.resize.y = e.resize.h;
191                return true;
192        case SDL_NOEVENT         : return false;
193        case SDL_VIDEOEXPOSE     : return false;
194*/
195        case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
196        case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
197        case SDL_JOYAXISMOTION   : return sdl_joy_axis_event_to_io_event( e.jaxis, ioevent );
198        case SDL_JOYBALLMOTION   : return sdl_joy_ball_event_to_io_event( e.jball, ioevent );
199        case SDL_JOYHATMOTION    : return sdl_joy_hat_event_to_io_event( e.jhat, ioevent );
200        case SDL_JOYBUTTONDOWN   : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
201        case SDL_JOYBUTTONUP     : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
202        default : return false;
203        }
204}
205
206
207gl_window::gl_window( device* dev, uint16 width, uint16 height, bool fullscreen )
208        : m_device( dev ), m_width( width ), m_height( height ), m_title("NV Engine"), m_handle( nullptr ), m_adopted( false )
209{
210        //      bpp = m_info->vfmt->BitsPerPixel;
211
212        SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
213        SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
214        SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
215        SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
216        SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
217
218        //      SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
219        //      SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );
220
221#if NV_SDL_VERSION == NV_SDL_20
222        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
223        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
224        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
225        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
226#endif
227
228
229#if NV_SDL_VERSION == NV_SDL_12
230        uint32 flags = SDL_OPENGL;
231        if (fullscreen) flags |= SDL_FULLSCREEN;
232        m_handle = SDL_SetVideoMode( width, height, 32, flags );
233#elif NV_SDL_VERSION == NV_SDL_20
234        uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
235        if (fullscreen) flags |= SDL_WINDOW_FULLSCREEN;
236        m_handle = SDL_CreateWindow("Nova Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
237                width, height, flags );
238#endif
239        if ( m_handle == 0 )
240        {
241                NV_LOG( LOG_CRITICAL, "Video mode set failed: " << SDL_GetError( ) );
242                return; // TODO: Error report
243        }
244
245//      NV_LOG( LOG_INFO, "Joystick count : " << SDL_NumJoysticks() );
246//      SDL_Joystick* j = SDL_JoystickOpen(0);
247//      if (j)
248//      {
249//              NV_LOG( LOG_INFO, "Joystick Name: " << SDL_JoystickNameForIndex(0) );
250//              NV_LOG( LOG_INFO, "Joystick Number of Axes: " << SDL_JoystickNumAxes(j));
251//              NV_LOG( LOG_INFO, "Joystick Number of Buttons: " << SDL_JoystickNumButtons(j));
252//              NV_LOG( LOG_INFO, "Joystick Number of Balls: " << SDL_JoystickNumBalls(j));
253//      }
254
255
256        m_context = new sdl_gl_context( m_device, m_handle );
257        m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) );
258}
259
260uint16 gl_window::get_width() const
261{
262        return m_width;
263}
264
265uint16 gl_window::get_height() const
266{
267        return m_height;
268}
269
270string gl_window::get_title() const
271{
272        return m_title;
273}
274
275void gl_window::set_title( const string& title )
276{
277        if ( m_adopted ) return;
278#if NV_SDL_VERSION == NV_SDL_20
279        SDL_SetWindowTitle( static_cast<SDL_Window*>( m_handle ), title.c_str() );
280#else
281        SDL_WM_SetCaption( title.c_str(), title.c_str() );
282#endif
283        m_title = title;
284}
285
286bool gl_window::is_event_pending()
287{
288        return SDL_PollEvent( nullptr ) != 0;
289}
290
291bool gl_window::poll_event( io_event& event )
292{
293        SDL_Event sdl_event;
294        if ( SDL_PollEvent( &sdl_event ) == 0 ) return false;
295        return sdl_event_to_io_event( sdl_event, event );
296}
297
298void gl_window::swap_buffers()
299{
300        if ( m_adopted ) return; // NOT SURE
301#if NV_SDL_VERSION == NV_SDL_20
302        SDL_GL_SwapWindow( static_cast<SDL_Window*>( m_handle ) );
303#else
304        SDL_GL_SwapBuffers();
305#endif
306}
307
308gl_window::~gl_window()
309{
310        delete m_context;
311#if NV_SDL_VERSION == NV_SDL_20
312        if ( !m_adopted ) SDL_DestroyWindow( static_cast<SDL_Window*>( m_handle ) );
313#endif
314}
315
316nv::gl_window::gl_window( device* dev, void* handle, void* dc )
317        : m_device( dev ), m_width( 0 ), m_height( 0 ), m_title(), m_handle( nullptr ), m_adopted( true )
318{
319#if NV_PLATFORM == NV_WINDOWS
320#if NV_SDL_VERSION == NV_SDL_20
321        nv::load_gl_no_context();
322        m_context = new native_gl_context( m_device, dc );
323        SDL_Window* window = SDL_CreateWindowFrom( handle );
324        // Doesn't work :/
325//      RECT rect;
326//      GetClientRect( (HWND)handle, &rect );
327//      m_width   = (uint16)rect.right;
328//      m_height  = (uint16)rect.bottom;
329        m_handle  = window;
330        m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) );
331#else
332        NV_ASSERT( false, "Native GL context only working with SDL 2.0!" );
333#endif
334#else
335        NV_ASSERT( false, "Native GL context adoption not implemented for this platform!" );
336#endif
337}
Note: See TracBrowser for help on using the repository browser.