// Copyright (C) 2012-2013 Kornel Kisielewicz // This file is part of NV Libraries. // For conditions of distribution and use, see copyright notice in nv.hh #include "nv/gl/gl_window.hh" #include "nv/logging.hh" #include "nv/lib/gl.hh" #include "nv/lib/sdl12.hh" using namespace nv; static bool sdl_key_event_to_io_event( const SDL_KeyboardEvent& ke, io_event& kevent ) { kevent.type = EV_KEY; kevent.key.pressed = ( ke.state != SDL_RELEASED ); kevent.key.ascii = 0; kevent.key.code = KEY_NONE; // if result is a typable char place it into the structure if (ke.keysym.unicode >= 32 && ke.keysym.unicode < 128 ) { kevent.key.ascii = (char)ke.keysym.unicode; } // Get the Key value from the SDL Keyboard event int result = ke.keysym.sym; // Check the control and shift states kevent.key.alt = (ke.keysym.mod & KMOD_ALT ) != 0; kevent.key.control = (ke.keysym.mod & KMOD_CTRL ) != 0; kevent.key.shift = (ke.keysym.mod & KMOD_SHIFT ) != 0; // if result is a typable char from the directly transformable ranges if ( ( result >= KEY_A && result <= KEY_Z ) || ( result >= KEY_0 && result <= KEY_9 ) || result == ' ' ) { kevent.key.code = static_cast(result); } // if result is a typable char from the a..z range if ( result >= KEY_A + 32 && result <= KEY_Z + 32 ) { kevent.key.code = static_cast(result - 32); } if ( result >= SDLK_F1 && result <= SDLK_F12 ) { kevent.key.code = static_cast(result - SDLK_F1 + KEY_F1 ); } // other recognized codes switch ( result ) { case SDLK_BACKSPACE : kevent.key.code = KEY_BACK; break; case SDLK_TAB : kevent.key.code = KEY_TAB; break; case SDLK_RETURN : kevent.key.code = KEY_ENTER; break; case SDLK_PAGEUP : kevent.key.code = KEY_PGUP; break; case SDLK_PAGEDOWN : kevent.key.code = KEY_PGDOWN; break; case SDLK_END : kevent.key.code = KEY_END; break; case SDLK_HOME : kevent.key.code = KEY_HOME; break; case SDLK_LEFT : kevent.key.code = KEY_LEFT; break; case SDLK_UP : kevent.key.code = KEY_UP; break; case SDLK_RIGHT : kevent.key.code = KEY_RIGHT; break; case SDLK_DOWN : kevent.key.code = KEY_DOWN; break; case SDLK_DELETE : kevent.key.code = KEY_DELETE; break; case SDLK_INSERT : kevent.key.code = KEY_INSERT; break; case SDLK_KP5 : kevent.key.code = KEY_CENTER; break; case SDLK_ESCAPE : kevent.key.code = KEY_ESCAPE; break; case SDLK_QUOTE : kevent.key.code = KEY_QUOTE; break; case SDLK_COMMA : kevent.key.code = KEY_COMMA; break; case SDLK_MINUS : kevent.key.code = KEY_MINUS; break; case SDLK_PERIOD : kevent.key.code = KEY_PERIOD; break; case SDLK_SLASH : kevent.key.code = KEY_SLASH; break; case SDLK_SEMICOLON : kevent.key.code = KEY_SCOLON; break; case SDLK_LEFTBRACKET : kevent.key.code = KEY_LBRACKET; break; case SDLK_BACKSLASH : kevent.key.code = KEY_BSLASH; break; case SDLK_RIGHTBRACKET : kevent.key.code = KEY_RBRACKET; break; case SDLK_BACKQUOTE : kevent.key.code = KEY_BQUOTE; break; default : break; } // If key was understood by nv, then it's valid, otherwise ignored return kevent.key.ascii != 0 || kevent.key.code != 0; } static bool sdl_mouse_button_to_io_event( const SDL_MouseButtonEvent& mb, io_event& mevent ) { mevent.type = EV_MOUSE_BUTTON; mevent.mbutton.button = MOUSE_NONE; mevent.mbutton.pressed = (mb.state != SDL_RELEASED); mevent.mbutton.x = mb.x; mevent.mbutton.y = mb.y; switch ( mb.button ) { case SDL_BUTTON_LEFT : mevent.mbutton.button = MOUSE_LEFT; break; case SDL_BUTTON_MIDDLE : mevent.mbutton.button = MOUSE_MIDDLE; break; case SDL_BUTTON_RIGHT : mevent.mbutton.button = MOUSE_RIGHT; break; case SDL_BUTTON_WHEELUP : mevent.mbutton.button = MOUSE_WHEEL_UP; break; case SDL_BUTTON_WHEELDOWN : mevent.mbutton.button = MOUSE_WHEEL_DOWN; break; default : break; } return mevent.mbutton.button != MOUSE_NONE; } static bool sdl_mouse_motion_to_io_event( const SDL_MouseMotionEvent& mm, io_event& mevent ) { mevent.type = EV_MOUSE_MOVE; mevent.mmove.pressed = (mm.state != SDL_RELEASED); mevent.mmove.x = mm.x; mevent.mmove.y = mm.y; return true; } static bool sdl_event_to_io_event( const SDL_Event& e, io_event& ioevent ) { switch ( e.type ) { case SDL_KEYDOWN : return sdl_key_event_to_io_event( e.key, ioevent ); case SDL_KEYUP : return sdl_key_event_to_io_event( e.key, ioevent ); case SDL_MOUSEMOTION : return sdl_mouse_motion_to_io_event( e.motion, ioevent ); case SDL_MOUSEBUTTONDOWN : return sdl_mouse_button_to_io_event( e.button, ioevent ); case SDL_MOUSEBUTTONUP : return sdl_mouse_button_to_io_event( e.button, ioevent ); case SDL_ACTIVEEVENT : ioevent.type = EV_ACTIVE; ioevent.active.gain = (e.active.gain != 0); return e.active.state == SDL_APPINPUTFOCUS; case SDL_VIDEORESIZE : ioevent.type = EV_RESIZE; ioevent.resize.x = e.resize.w; ioevent.resize.y = e.resize.h; return true; case SDL_SYSWMEVENT : ioevent.type = EV_SYSTEM; return true; case SDL_QUIT : ioevent.type = EV_QUIT; return true; case SDL_NOEVENT : return false; case SDL_VIDEOEXPOSE : return false; case SDL_JOYAXISMOTION : return false; case SDL_JOYBALLMOTION : return false; case SDL_JOYHATMOTION : return false; case SDL_JOYBUTTONDOWN : return false; case SDL_JOYBUTTONUP : return false; default : return false; } } gl_window::gl_window( device* dev, uint16 width, uint16 height ) : m_device( dev ), m_width( width ), m_height( height ), m_title("NV Engine"), m_screen( nullptr ) { int flags = SDL_OPENGL; m_screen = SDL_SetVideoMode( width, height, 32, flags ); if ( m_screen == 0 ) { NV_LOG( LOG_CRITICAL, "Video mode set failed: " << SDL_GetError( ) ); return; // TODO: Error report } nv::load_gl_library(); NV_LOG( LOG_INFO, "OpenGL Vendor : " << glGetString(GL_VENDOR) ); NV_LOG( LOG_INFO, "OpenGL Renderer : " << glGetString(GL_RENDERER) ); NV_LOG( LOG_INFO, "OpenGL Version : " << glGetString(GL_VERSION) ); NV_LOG( LOG_INFO, "OpenGL GLSL Version : " << glGetString(GL_SHADING_LANGUAGE_VERSION) ); m_context = new gl_context(); m_context->set_viewport( nv::ivec4( 0, 0, m_width, m_height ) ); } uint16 gl_window::get_width() const { return m_width; } uint16 gl_window::get_height() const { return m_height; } string gl_window::get_title() const { return m_title; } void gl_window::set_title( const string& title ) { SDL_WM_SetCaption( title.c_str(), title.c_str() ); m_title = title; } bool gl_window::is_event_pending() { return SDL_PollEvent( nullptr ) != 0; } bool gl_window::poll_event( io_event& event ) { SDL_Event sdl_event; if ( SDL_PollEvent( &sdl_event ) == 0 ) return false; return sdl_event_to_io_event( sdl_event, event ); } void gl_window::swap_buffers() { SDL_GL_SwapBuffers(); } gl_window::~gl_window() { delete m_context; }