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

Last change on this file since 245 was 245, checked in by epyon, 11 years ago
  • gl library wgl support
  • gl context and window adoption
File size: 11.2 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        return true;
132}
133
134static bool sdl_joy_button_event_to_io_event( const SDL_JoyButtonEvent& jb, io_event& jevent )
135{
136        jevent.type            = EV_JOY_BUTTON;
137        jevent.jbutton.id      = jb.which;
138        jevent.jbutton.button  = jb.button;
139        jevent.jbutton.pressed = (jb.type == SDL_PRESSED);
140        return true;
141}
142
143static bool sdl_joy_axis_event_to_io_event( const SDL_JoyAxisEvent& ja, io_event& jevent )
144{
145        jevent.type          = EV_JOY_AXIS;
146        jevent.jaxis.id      = ja.which;
147        jevent.jaxis.axis    = ja.axis;
148        jevent.jaxis.value   = ja.value;
149        return true;
150}
151
152static bool sdl_joy_hat_event_to_io_event( const SDL_JoyHatEvent& jh, io_event& jevent )
153{
154        jevent.type          = EV_JOY_HAT;
155        jevent.jhat.id       = jh.which;
156        jevent.jhat.hat      = jh.hat;
157        jevent.jhat.value    = jh.value;
158        return true;
159}
160
161static bool sdl_joy_ball_event_to_io_event( const SDL_JoyBallEvent& jb, io_event& jevent )
162{
163        jevent.type          = EV_JOY_HAT;
164        jevent.jball.id      = jb.which;
165        jevent.jball.ball    = jb.ball;
166        jevent.jball.rx      = jb.xrel;
167        jevent.jball.ry      = jb.yrel;
168        return true;
169}
170
171static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent )
172{
173        switch ( e.type )
174        {
175        case SDL_KEYDOWN         : return sdl_key_event_to_io_event( e.key, ioevent );
176        case SDL_KEYUP           : return sdl_key_event_to_io_event( e.key, ioevent );
177        case SDL_MOUSEMOTION     : return sdl_mouse_motion_to_io_event( e.motion, ioevent );
178        case SDL_MOUSEBUTTONDOWN : return sdl_mouse_button_to_io_event( e.button, ioevent );
179        case SDL_MOUSEBUTTONUP   : return sdl_mouse_button_to_io_event( e.button, ioevent );
180/* // SDL 2.0 incompatible
181        case SDL_ACTIVEEVENT     :
182                ioevent.type = EV_ACTIVE;
183                ioevent.active.gain = (e.active.gain != 0);
184                return e.active.state == SDL_APPINPUTFOCUS;
185        case SDL_VIDEORESIZE     :
186                ioevent.type     = EV_RESIZE;
187                ioevent.resize.x = e.resize.w;
188                ioevent.resize.y = e.resize.h;
189                return true;
190        case SDL_NOEVENT         : return false;
191        case SDL_VIDEOEXPOSE     : return false;
192*/
193        case SDL_SYSWMEVENT      : ioevent.type = EV_SYSTEM; return true;
194        case SDL_QUIT            : ioevent.type = EV_QUIT;   return true;
195        case SDL_JOYAXISMOTION   : return sdl_joy_axis_event_to_io_event( e.jaxis, ioevent );
196        case SDL_JOYBALLMOTION   : return sdl_joy_ball_event_to_io_event( e.jball, ioevent );
197        case SDL_JOYHATMOTION    : return sdl_joy_hat_event_to_io_event( e.jhat, ioevent );
198        case SDL_JOYBUTTONDOWN   : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
199        case SDL_JOYBUTTONUP     : return sdl_joy_button_event_to_io_event( e.jbutton, ioevent );
200        default : return false;
201        }
202}
203
204
205gl_window::gl_window( device* dev, uint16 width, uint16 height, bool fullscreen )
206        : m_device( dev ), m_width( width ), m_height( height ), m_title("NV Engine"), m_handle( nullptr ), m_adopted( false )
207{
208        //      bpp = m_info->vfmt->BitsPerPixel;
209
210        SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
211        SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
212        SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
213        SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 24 );
214        SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
215
216        //      SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
217        //      SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, 4 );
218
219#if NV_SDL_VERSION == NV_SDL_20
220        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
221        SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
222        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
223        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
224#endif
225
226
227#if NV_SDL_VERSION == NV_SDL_12
228        uint32 flags = SDL_OPENGL;
229        if (fullscreen) flags |= SDL_FULLSCREEN;
230        m_handle = SDL_SetVideoMode( width, height, 32, flags );
231#elif NV_SDL_VERSION == NV_SDL_20
232        uint32 flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
233        if (fullscreen) flags |= SDL_WINDOW_FULLSCREEN;
234        m_handle = SDL_CreateWindow("Nova Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
235                width, height, flags );
236#endif
237        if ( m_handle == 0 )
238        {
239                NV_LOG( LOG_CRITICAL, "Video mode set failed: " << SDL_GetError( ) );
240                return; // TODO: Error report
241        }
242
243//      NV_LOG( LOG_INFO, "Joystick count : " << SDL_NumJoysticks() );
244//      SDL_Joystick* j = SDL_JoystickOpen(0);
245//      if (j)
246//      {
247//              NV_LOG( LOG_INFO, "Joystick Name: " << SDL_JoystickNameForIndex(0) );
248//              NV_LOG( LOG_INFO, "Joystick Number of Axes: " << SDL_JoystickNumAxes(j));
249//              NV_LOG( LOG_INFO, "Joystick Number of Buttons: " << SDL_JoystickNumButtons(j));
250//              NV_LOG( LOG_INFO, "Joystick Number of Balls: " << SDL_JoystickNumBalls(j));
251//      }
252
253
254        m_context = new sdl_gl_context( m_device, m_handle );
255        m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) );
256}
257
258uint16 gl_window::get_width() const
259{
260        return m_width;
261}
262
263uint16 gl_window::get_height() const
264{
265        return m_height;
266}
267
268string gl_window::get_title() const
269{
270        return m_title;
271}
272
273void gl_window::set_title( const string& title )
274{
275        if ( m_adopted ) return;
276#if NV_SDL_VERSION == NV_SDL_20
277        SDL_SetWindowTitle( static_cast<SDL_Window*>( m_handle ), title.c_str() );
278#else
279        SDL_WM_SetCaption( title.c_str(), title.c_str() );
280#endif
281        m_title = title;
282}
283
284bool gl_window::is_event_pending()
285{
286        return SDL_PollEvent( nullptr ) != 0;
287}
288
289bool gl_window::poll_event( io_event& event )
290{
291        SDL_Event sdl_event;
292        if ( SDL_PollEvent( &sdl_event ) == 0 ) return false;
293        return sdl_event_to_io_event( sdl_event, event );
294}
295
296void gl_window::swap_buffers()
297{
298        if ( m_adopted ) return; // NOT SURE
299#if NV_SDL_VERSION == NV_SDL_20
300        SDL_GL_SwapWindow( static_cast<SDL_Window*>( m_handle ) );
301#else
302        SDL_GL_SwapBuffers();
303#endif
304}
305
306gl_window::~gl_window()
307{
308        delete m_context;
309#if NV_SDL_VERSION == NV_SDL_20
310        if ( !m_adopted ) SDL_DestroyWindow( static_cast<SDL_Window*>( m_handle ) );
311#endif
312}
313
314nv::gl_window::gl_window( device* dev, void* handle, void* dc )
315        : m_device( dev ), m_width( 0 ), m_height( 0 ), m_title(), m_handle( nullptr ), m_adopted( true )
316{
317#if NV_PLATFORM == NV_WINDOWS
318#if NV_SDL_VERSION == NV_SDL_20
319        nv::load_gl_no_context();
320        m_context = new native_gl_context( m_device, dc );
321        SDL_Window* window = SDL_CreateWindowFrom( handle );
322        // Doesn't work :/
323//      RECT rect;
324//      GetClientRect( (HWND)handle, &rect );
325//      m_width   = (uint16)rect.right;
326//      m_height  = (uint16)rect.bottom;
327        m_handle  = window;
328        m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) );
329#else
330        NV_ASSERT( false, "Native GL context only working with SDL 2.0!" );
331#endif
332#else
333        NV_ASSERT( false, "Native GL context adoption not implemented for this platform!" );
334#endif
335}
Note: See TracBrowser for help on using the repository browser.