Move SDL helpers to their own package in extern/, allow conversion from sdl to ois keycodes, (maybe) fix unicode handling
parent
cb01df49c0
commit
ed644259ce
@ -1,254 +0,0 @@
|
||||
#include "sdlinputwrapper.hpp"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
|
||||
#include <OgrePlatform.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/Xutil.h>
|
||||
# include <X11/Xos.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace MWInput
|
||||
{
|
||||
MWSDLInputWrapper::MWSDLInputWrapper(Ogre::RenderWindow *window) :
|
||||
mWindow(window),
|
||||
mSDLWindow(NULL),
|
||||
mWarpCompensate(false),
|
||||
mMouseRelative(false),
|
||||
mGrabPointer(false),
|
||||
mWrapPointer(false)
|
||||
{
|
||||
_start();
|
||||
}
|
||||
|
||||
MWSDLInputWrapper::~MWSDLInputWrapper()
|
||||
{
|
||||
if(mSDLWindow != NULL)
|
||||
SDL_DestroyWindow(mSDLWindow);
|
||||
mSDLWindow = NULL;
|
||||
SDL_StopTextInput();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
bool MWSDLInputWrapper::_start()
|
||||
{
|
||||
Uint32 flags = SDL_INIT_VIDEO;
|
||||
if(SDL_WasInit(flags) == 0)
|
||||
{
|
||||
//get the HWND from ogre's renderwindow
|
||||
size_t windowHnd;
|
||||
mWindow->getCustomAttribute("WINDOW", &windowHnd);
|
||||
|
||||
//kindly ask SDL not to trash our OGL context
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||
if(SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
return false;
|
||||
|
||||
//wrap our own event handler around ogre's
|
||||
mSDLWindow = SDL_CreateWindowFrom((void*)windowHnd);
|
||||
|
||||
if(mSDLWindow == NULL)
|
||||
return false;
|
||||
|
||||
SDL_StartTextInput();
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
//linux-specific event-handling fixups
|
||||
SDL_SysWMinfo wm_info;
|
||||
SDL_VERSION(&wm_info.version);
|
||||
|
||||
if(SDL_GetWindowWMInfo(mSDLWindow,&wm_info))
|
||||
{
|
||||
Display* display = wm_info.info.x11.display;
|
||||
Window w = wm_info.info.x11.window;
|
||||
|
||||
// Set the input hints so we get keyboard input
|
||||
XWMHints *wmhints = XAllocWMHints();
|
||||
if (wmhints) {
|
||||
wmhints->input = True;
|
||||
wmhints->flags = InputHint;
|
||||
XSetWMHints(display, w, wmhints);
|
||||
XFree(wmhints);
|
||||
}
|
||||
|
||||
//make sure to subscribe to XLib's events
|
||||
XSelectInput(display, w,
|
||||
(FocusChangeMask | EnterWindowMask | LeaveWindowMask |
|
||||
ExposureMask | ButtonPressMask | ButtonReleaseMask |
|
||||
PointerMotionMask | KeyPressMask | KeyReleaseMask |
|
||||
PropertyChangeMask | StructureNotifyMask |
|
||||
KeymapStateMask));
|
||||
|
||||
XFlush(display);
|
||||
}
|
||||
#endif
|
||||
SDL_ShowCursor(SDL_FALSE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::capture()
|
||||
{
|
||||
if(!_start())
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
|
||||
SDL_Event evt;
|
||||
while(SDL_PollEvent(&evt))
|
||||
{
|
||||
switch(evt.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
//ignore this if it happened due to a warp
|
||||
if(!_handleWarpMotion(evt.motion))
|
||||
{
|
||||
mMouseListener->mouseMoved(ICS::MWSDLMouseMotionEvent(evt.motion));
|
||||
|
||||
//try to keep the mouse inside the window
|
||||
_wrapMousePointer(evt.motion);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
mMouseListener->mouseMoved(ICS::MWSDLMouseMotionEvent(evt.wheel));
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
mMouseListener->mousePressed(evt.button, evt.button.button);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
mMouseListener->mouseReleased(evt.button, evt.button.button);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
_handleKeyPress(evt.key);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
mKeyboardListener->keyReleased(evt.key);
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
mWindowListener->windowFocusChange(true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
mWindowListener->windowFocusChange(false);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
mWindowListener->windowVisibilityChange(true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
mWindowListener->windowVisibilityChange(false);
|
||||
break;
|
||||
|
||||
//SDL traps ^C signals, pass it to OGRE.
|
||||
case SDL_QUIT:
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MWSDLInputWrapper::isModifierHeld(int mod)
|
||||
{
|
||||
return SDL_GetModState() & mod;
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::warpMouse(int x, int y)
|
||||
{
|
||||
SDL_WarpMouseInWindow(mSDLWindow, x, y);
|
||||
mWarpCompensate = true;
|
||||
mWarpX = x;
|
||||
mWarpY = y;
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::setGrabPointer(bool grab)
|
||||
{
|
||||
SDL_bool sdlGrab = grab ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
mGrabPointer = grab;
|
||||
SDL_SetWindowGrab(mSDLWindow, sdlGrab);
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::setMouseRelative(bool relative)
|
||||
{
|
||||
if(mMouseRelative == relative)
|
||||
return;
|
||||
|
||||
mMouseRelative = relative;
|
||||
|
||||
mWrapPointer = false;
|
||||
|
||||
//eep, wrap the pointer manually if the input driver doesn't support
|
||||
//relative positioning natively
|
||||
if(SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == -1)
|
||||
{
|
||||
if(relative)
|
||||
mWrapPointer = true;
|
||||
}
|
||||
|
||||
//now remove all mouse events using the old setting from the queue
|
||||
SDL_PumpEvents();
|
||||
|
||||
SDL_Event dummy[20];
|
||||
SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION);
|
||||
}
|
||||
|
||||
bool MWSDLInputWrapper::_handleWarpMotion(const SDL_MouseMotionEvent& evt)
|
||||
{
|
||||
if(!mWarpCompensate)
|
||||
return false;
|
||||
|
||||
//this was a warp event, signal the caller to eat it.
|
||||
if(evt.x == mWarpX && evt.y == mWarpY)
|
||||
{
|
||||
mWarpCompensate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::_wrapMousePointer(const SDL_MouseMotionEvent& evt)
|
||||
{
|
||||
//don't wrap if we don't want relative movements, support relative
|
||||
//movements natively, or aren't grabbing anyways
|
||||
if(!mMouseRelative || !mWrapPointer || !mGrabPointer)
|
||||
return;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
SDL_GetWindowSize(mSDLWindow, &width, &height);
|
||||
|
||||
const int FUDGE_FACTOR_X = width / 4;
|
||||
const int FUDGE_FACTOR_Y = height / 4;
|
||||
|
||||
//warp the mouse if it's about to go outside the window
|
||||
if(evt.x - FUDGE_FACTOR_X < 0 || evt.x + FUDGE_FACTOR_X > width
|
||||
|| evt.y - FUDGE_FACTOR_Y < 0 || evt.y + FUDGE_FACTOR_Y > height)
|
||||
{
|
||||
warpMouse(width / 2, height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void MWSDLInputWrapper::_handleKeyPress(SDL_KeyboardEvent &evt)
|
||||
{
|
||||
//SDL keyboard events are followed by the actual text those keys would generate
|
||||
//to account for languages that require multiple keystrokes to produce a key.
|
||||
//Look for an event immediately following ours, assuming each key produces exactly
|
||||
//one character.
|
||||
|
||||
//TODO: This won't work for multibyte characters, but MyGUI is the only consumer
|
||||
//of these, does it even support multibyte characters?
|
||||
|
||||
SDL_Event text_evts[1];
|
||||
if(SDL_PeepEvents(text_evts, 1, SDL_GETEVENT, SDL_TEXTINPUT, SDL_TEXTINPUT) != 0)
|
||||
{
|
||||
evt.keysym.unicode = text_evts[0].text.text[0];
|
||||
}
|
||||
|
||||
mKeyboardListener->keyPressed(evt);
|
||||
}
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
#ifndef _MWINPUT_SDLINPUTWRAPPER_H
|
||||
#define _MWINPUT_SDLINPUTWRAPPER_H
|
||||
|
||||
#include "SDL2/SDL_events.h"
|
||||
#include <extern/oics/OISCompat.h>
|
||||
#include <OGRE/OgreRenderWindow.h>
|
||||
|
||||
|
||||
namespace MWInput
|
||||
{
|
||||
class MWSDLInputWrapper
|
||||
{
|
||||
public:
|
||||
MWSDLInputWrapper(Ogre::RenderWindow* window);
|
||||
~MWSDLInputWrapper();
|
||||
|
||||
void setMouseEventCallback(ICS::MWSDLMouseListener* listen) { mMouseListener = listen; }
|
||||
void setKeyboardEventCallback(ICS::MWSDLKeyListener* listen) { mKeyboardListener = listen; }
|
||||
void setWindowEventCallback(ICS::MWSDLWindowListener* listen) { mWindowListener = listen; }
|
||||
|
||||
void capture();
|
||||
bool isModifierHeld(int mod);
|
||||
|
||||
void setMouseRelative(bool relative);
|
||||
bool getMouseRelative() { return mMouseRelative; }
|
||||
void setGrabPointer(bool grab);
|
||||
|
||||
void warpMouse(int x, int y);
|
||||
private:
|
||||
bool _handleWarpMotion(const SDL_MouseMotionEvent& evt);
|
||||
void _wrapMousePointer(const SDL_MouseMotionEvent &evt);
|
||||
|
||||
void _handleKeyPress(SDL_KeyboardEvent& evt);
|
||||
|
||||
bool _start();
|
||||
|
||||
ICS::MWSDLMouseListener* mMouseListener;
|
||||
ICS::MWSDLKeyListener* mKeyboardListener;
|
||||
ICS::MWSDLWindowListener* mWindowListener;
|
||||
|
||||
Uint16 mWarpX;
|
||||
Uint16 mWarpY;
|
||||
bool mWarpCompensate;
|
||||
bool mMouseRelative;
|
||||
bool mWrapPointer;
|
||||
bool mGrabPointer;
|
||||
|
||||
Ogre::RenderWindow* mWindow;
|
||||
SDL_Window* mSDLWindow;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -0,0 +1,14 @@
|
||||
set(SDL4OGRE_LIBRARY "sdl4ogre")
|
||||
|
||||
# Sources
|
||||
|
||||
set(SDL4OGRE_SOURCE_FILES
|
||||
sdlinputwrapper.cpp
|
||||
)
|
||||
|
||||
add_library(${SDL4OGRE_LIBRARY} STATIC ${SDL4OGRE_SOURCE_FILES})
|
||||
|
||||
link_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
target_link_libraries(${SDL4OGRE_LIBRARY} ${SDL2_LIBRARY})
|
@ -0,0 +1,159 @@
|
||||
#ifndef _OIS_SDL_COMPAT_H
|
||||
#define _OIS_SDL_COMPAT_H
|
||||
|
||||
#include <SDL2/SDL_events.h>
|
||||
#include <SDL2/SDL_types.h>
|
||||
|
||||
namespace OIS
|
||||
{
|
||||
//! Keyboard scan codes
|
||||
enum KeyCode
|
||||
{
|
||||
KC_UNASSIGNED = 0x00,
|
||||
KC_ESCAPE = 0x01,
|
||||
KC_1 = 0x02,
|
||||
KC_2 = 0x03,
|
||||
KC_3 = 0x04,
|
||||
KC_4 = 0x05,
|
||||
KC_5 = 0x06,
|
||||
KC_6 = 0x07,
|
||||
KC_7 = 0x08,
|
||||
KC_8 = 0x09,
|
||||
KC_9 = 0x0A,
|
||||
KC_0 = 0x0B,
|
||||
KC_MINUS = 0x0C, // - on main keyboard
|
||||
KC_EQUALS = 0x0D,
|
||||
KC_BACK = 0x0E, // backspace
|
||||
KC_TAB = 0x0F,
|
||||
KC_Q = 0x10,
|
||||
KC_W = 0x11,
|
||||
KC_E = 0x12,
|
||||
KC_R = 0x13,
|
||||
KC_T = 0x14,
|
||||
KC_Y = 0x15,
|
||||
KC_U = 0x16,
|
||||
KC_I = 0x17,
|
||||
KC_O = 0x18,
|
||||
KC_P = 0x19,
|
||||
KC_LBRACKET = 0x1A,
|
||||
KC_RBRACKET = 0x1B,
|
||||
KC_RETURN = 0x1C, // Enter on main keyboard
|
||||
KC_LCONTROL = 0x1D,
|
||||
KC_A = 0x1E,
|
||||
KC_S = 0x1F,
|
||||
KC_D = 0x20,
|
||||
KC_F = 0x21,
|
||||
KC_G = 0x22,
|
||||
KC_H = 0x23,
|
||||
KC_J = 0x24,
|
||||
KC_K = 0x25,
|
||||
KC_L = 0x26,
|
||||
KC_SEMICOLON = 0x27,
|
||||
KC_APOSTROPHE = 0x28,
|
||||
KC_GRAVE = 0x29, // accent
|
||||
KC_LSHIFT = 0x2A,
|
||||
KC_BACKSLASH = 0x2B,
|
||||
KC_Z = 0x2C,
|
||||
KC_X = 0x2D,
|
||||
KC_C = 0x2E,
|
||||
KC_V = 0x2F,
|
||||
KC_B = 0x30,
|
||||
KC_N = 0x31,
|
||||
KC_M = 0x32,
|
||||
KC_COMMA = 0x33,
|
||||
KC_PERIOD = 0x34, // . on main keyboard
|
||||
KC_SLASH = 0x35, // / on main keyboard
|
||||
KC_RSHIFT = 0x36,
|
||||
KC_MULTIPLY = 0x37, // * on numeric keypad
|
||||
KC_LMENU = 0x38, // left Alt
|
||||
KC_SPACE = 0x39,
|
||||
KC_CAPITAL = 0x3A,
|
||||
KC_F1 = 0x3B,
|
||||
KC_F2 = 0x3C,
|
||||
KC_F3 = 0x3D,
|
||||
KC_F4 = 0x3E,
|
||||
KC_F5 = 0x3F,
|
||||
KC_F6 = 0x40,
|
||||
KC_F7 = 0x41,
|
||||
KC_F8 = 0x42,
|
||||
KC_F9 = 0x43,
|
||||
KC_F10 = 0x44,
|
||||
KC_NUMLOCK = 0x45,
|
||||
KC_SCROLL = 0x46, // Scroll Lock
|
||||
KC_NUMPAD7 = 0x47,
|
||||
KC_NUMPAD8 = 0x48,
|
||||
KC_NUMPAD9 = 0x49,
|
||||
KC_SUBTRACT = 0x4A, // - on numeric keypad
|
||||
KC_NUMPAD4 = 0x4B,
|
||||
KC_NUMPAD5 = 0x4C,
|
||||
KC_NUMPAD6 = 0x4D,
|
||||
KC_ADD = 0x4E, // + on numeric keypad
|
||||
KC_NUMPAD1 = 0x4F,
|
||||
KC_NUMPAD2 = 0x50,
|
||||
KC_NUMPAD3 = 0x51,
|
||||
KC_NUMPAD0 = 0x52,
|
||||
KC_DECIMAL = 0x53, // . on numeric keypad
|
||||
KC_OEM_102 = 0x56, // < > | on UK/Germany keyboards
|
||||
KC_F11 = 0x57,
|
||||
KC_F12 = 0x58,
|
||||
KC_F13 = 0x64, // (NEC PC98)
|
||||
KC_F14 = 0x65, // (NEC PC98)
|
||||
KC_F15 = 0x66, // (NEC PC98)
|
||||
KC_KANA = 0x70, // (Japanese keyboard)
|
||||
KC_ABNT_C1 = 0x73, // / ? on Portugese (Brazilian) keyboards
|
||||
KC_CONVERT = 0x79, // (Japanese keyboard)
|
||||
KC_NOCONVERT = 0x7B, // (Japanese keyboard)
|
||||
KC_YEN = 0x7D, // (Japanese keyboard)
|
||||
KC_ABNT_C2 = 0x7E, // Numpad . on Portugese (Brazilian) keyboards
|
||||
KC_NUMPADEQUALS= 0x8D, // = on numeric keypad (NEC PC98)
|
||||
KC_PREVTRACK = 0x90, // Previous Track (KC_CIRCUMFLEX on Japanese keyboard)
|
||||
KC_AT = 0x91, // (NEC PC98)
|
||||
KC_COLON = 0x92, // (NEC PC98)
|
||||
KC_UNDERLINE = 0x93, // (NEC PC98)
|
||||
KC_KANJI = 0x94, // (Japanese keyboard)
|
||||
KC_STOP = 0x95, // (NEC PC98)
|
||||
KC_AX = 0x96, // (Japan AX)
|
||||
KC_UNLABELED = 0x97, // (J3100)
|
||||
KC_NEXTTRACK = 0x99, // Next Track
|
||||
KC_NUMPADENTER = 0x9C, // Enter on numeric keypad
|
||||
KC_RCONTROL = 0x9D,
|
||||
KC_MUTE = 0xA0, // Mute
|
||||
KC_CALCULATOR = 0xA1, // Calculator
|
||||
KC_PLAYPAUSE = 0xA2, // Play / Pause
|
||||
KC_MEDIASTOP = 0xA4, // Media Stop
|
||||
KC_VOLUMEDOWN = 0xAE, // Volume -
|
||||
KC_VOLUMEUP = 0xB0, // Volume +
|
||||
KC_WEBHOME = 0xB2, // Web home
|
||||
KC_NUMPADCOMMA = 0xB3, // , on numeric keypad (NEC PC98)
|
||||
KC_DIVIDE = 0xB5, // / on numeric keypad
|
||||
KC_SYSRQ = 0xB7,
|
||||
KC_RMENU = 0xB8, // right Alt
|
||||
KC_PAUSE = 0xC5, // Pause
|
||||
KC_HOME = 0xC7, // Home on arrow keypad
|
||||
KC_UP = 0xC8, // UpArrow on arrow keypad
|
||||
KC_PGUP = 0xC9, // PgUp on arrow keypad
|
||||
KC_LEFT = 0xCB, // LeftArrow on arrow keypad
|
||||
KC_RIGHT = 0xCD, // RightArrow on arrow keypad
|
||||
KC_END = 0xCF, // End on arrow keypad
|
||||
KC_DOWN = 0xD0, // DownArrow on arrow keypad
|
||||
KC_PGDOWN = 0xD1, // PgDn on arrow keypad
|
||||
KC_INSERT = 0xD2, // Insert on arrow keypad
|
||||
KC_DELETE = 0xD3, // Delete on arrow keypad
|
||||
KC_LWIN = 0xDB, // Left Windows key
|
||||
KC_RWIN = 0xDC, // Right Windows key
|
||||
KC_APPS = 0xDD, // AppMenu key
|
||||
KC_POWER = 0xDE, // System Power
|
||||
KC_SLEEP = 0xDF, // System Sleep
|
||||
KC_WAKE = 0xE3, // System Wake
|
||||
KC_WEBSEARCH = 0xE5, // Web Search
|
||||
KC_WEBFAVORITES= 0xE6, // Web Favorites
|
||||
KC_WEBREFRESH = 0xE7, // Web Refresh
|
||||
KC_WEBSTOP = 0xE8, // Web Stop
|
||||
KC_WEBFORWARD = 0xE9, // Web Forward
|
||||
KC_WEBBACK = 0xEA, // Web Back
|
||||
KC_MYCOMPUTER = 0xEB, // My Computer
|
||||
KC_MAIL = 0xEC, // Mail
|
||||
KC_MEDIASELECT = 0xED // Media Select
|
||||
};
|
||||
}
|
||||
#endif
|
@ -0,0 +1,420 @@
|
||||
#include "sdlinputwrapper.hpp"
|
||||
#include <SDL2/SDL_syswm.h>
|
||||
|
||||
#include <OgrePlatform.h>
|
||||
#include <OgreRoot.h>
|
||||
#include <boost/locale.hpp>
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/Xutil.h>
|
||||
# include <X11/Xos.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
InputWrapper::InputWrapper(Ogre::RenderWindow *window) :
|
||||
mWindow(window),
|
||||
mSDLWindow(NULL),
|
||||
mWarpCompensate(false),
|
||||
mMouseRelative(false),
|
||||
mGrabPointer(false),
|
||||
mWrapPointer(false),
|
||||
mMouseZ(0),
|
||||
mMouseY(0),
|
||||
mMouseX(0)
|
||||
{
|
||||
_start();
|
||||
_setupOISKeys();
|
||||
}
|
||||
|
||||
InputWrapper::~InputWrapper()
|
||||
{
|
||||
if(mSDLWindow != NULL)
|
||||
SDL_DestroyWindow(mSDLWindow);
|
||||
mSDLWindow = NULL;
|
||||
SDL_StopTextInput();
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
bool InputWrapper::_start()
|
||||
{
|
||||
Uint32 flags = SDL_INIT_VIDEO;
|
||||
if(SDL_WasInit(flags) == 0)
|
||||
{
|
||||
//get the HWND from ogre's renderwindow
|
||||
size_t windowHnd;
|
||||
mWindow->getCustomAttribute("WINDOW", &windowHnd);
|
||||
|
||||
//kindly ask SDL not to trash our OGL context
|
||||
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ?
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||
if(SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
return false;
|
||||
|
||||
//wrap our own event handler around ogre's
|
||||
mSDLWindow = SDL_CreateWindowFrom((void*)windowHnd);
|
||||
|
||||
if(mSDLWindow == NULL)
|
||||
return false;
|
||||
|
||||
SDL_StartTextInput();
|
||||
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
|
||||
//linux-specific event-handling fixups
|
||||
//see http://bugzilla.libsdl.org/show_bug.cgi?id=730
|
||||
SDL_SysWMinfo wm_info;
|
||||
SDL_VERSION(&wm_info.version);
|
||||
|
||||
if(SDL_GetWindowWMInfo(mSDLWindow,&wm_info))
|
||||
{
|
||||
Display* display = wm_info.info.x11.display;
|
||||
Window w = wm_info.info.x11.window;
|
||||
|
||||
// Set the input hints so we get keyboard input
|
||||
XWMHints *wmhints = XAllocWMHints();
|
||||
if (wmhints) {
|
||||
wmhints->input = True;
|
||||
wmhints->flags = InputHint;
|
||||
XSetWMHints(display, w, wmhints);
|
||||
XFree(wmhints);
|
||||
}
|
||||
|
||||
//make sure to subscribe to XLib's events
|
||||
XSelectInput(display, w,
|
||||
(FocusChangeMask | EnterWindowMask | LeaveWindowMask |
|
||||
ExposureMask | ButtonPressMask | ButtonReleaseMask |
|
||||
PointerMotionMask | KeyPressMask | KeyReleaseMask |
|
||||
PropertyChangeMask | StructureNotifyMask |
|
||||
KeymapStateMask));
|
||||
|
||||
XFlush(display);
|
||||
}
|
||||
#endif
|
||||
SDL_ShowCursor(SDL_FALSE);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InputWrapper::capture()
|
||||
{
|
||||
if(!_start())
|
||||
throw std::runtime_error(SDL_GetError());
|
||||
|
||||
SDL_Event evt;
|
||||
while(SDL_PollEvent(&evt))
|
||||
{
|
||||
switch(evt.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
//ignore this if it happened due to a warp
|
||||
if(!_handleWarpMotion(evt.motion))
|
||||
{
|
||||
mMouseListener->mouseMoved(_packageMouseMotion(evt));
|
||||
|
||||
//try to keep the mouse inside the window
|
||||
_wrapMousePointer(evt.motion);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
mMouseListener->mouseMoved(_packageMouseMotion(evt));
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
mMouseListener->mousePressed(evt.button, evt.button.button);
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
mMouseListener->mouseReleased(evt.button, evt.button.button);
|
||||
break;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
_handleKeyPress(evt.key);
|
||||
break;
|
||||
case SDL_KEYUP:
|
||||
mKeyboardListener->keyReleased(evt.key);
|
||||
break;
|
||||
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
mWindowListener->windowFocusChange(true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
mWindowListener->windowFocusChange(false);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
mWindowListener->windowVisibilityChange(true);
|
||||
break;
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
mWindowListener->windowVisibilityChange(false);
|
||||
break;
|
||||
|
||||
//SDL traps ^C signals, pass it to OGRE.
|
||||
case SDL_QUIT:
|
||||
Ogre::Root::getSingleton().queueEndRendering();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InputWrapper::isModifierHeld(int mod)
|
||||
{
|
||||
return SDL_GetModState() & mod;
|
||||
}
|
||||
|
||||
void InputWrapper::warpMouse(int x, int y)
|
||||
{
|
||||
SDL_WarpMouseInWindow(mSDLWindow, x, y);
|
||||
mWarpCompensate = true;
|
||||
mWarpX = x;
|
||||
mWarpY = y;
|
||||
}
|
||||
|
||||
void InputWrapper::setGrabPointer(bool grab)
|
||||
{
|
||||
SDL_bool sdlGrab = grab ? SDL_TRUE : SDL_FALSE;
|
||||
|
||||
mGrabPointer = grab;
|
||||
SDL_SetWindowGrab(mSDLWindow, sdlGrab);
|
||||
}
|
||||
|
||||
void InputWrapper::setMouseRelative(bool relative)
|
||||
{
|
||||
if(mMouseRelative == relative)
|
||||
return;
|
||||
|
||||
mMouseRelative = relative;
|
||||
|
||||
mWrapPointer = false;
|
||||
|
||||
//eep, wrap the pointer manually if the input driver doesn't support
|
||||
//relative positioning natively
|
||||
if(SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == -1)
|
||||
{
|
||||
if(relative)
|
||||
mWrapPointer = true;
|
||||
}
|
||||
|
||||
//now remove all mouse events using the old setting from the queue
|
||||
SDL_PumpEvents();
|
||||
|
||||
SDL_Event dummy[20];
|
||||
SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION);
|
||||
}
|
||||
|
||||
bool InputWrapper::_handleWarpMotion(const SDL_MouseMotionEvent& evt)
|
||||
{
|
||||
if(!mWarpCompensate)
|
||||
return false;
|
||||
|
||||
//this was a warp event, signal the caller to eat it.
|
||||
if(evt.x == mWarpX && evt.y == mWarpY)
|
||||
{
|
||||
mWarpCompensate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputWrapper::_wrapMousePointer(const SDL_MouseMotionEvent& evt)
|
||||
{
|
||||
//don't wrap if we don't want relative movements, support relative
|
||||
//movements natively, or aren't grabbing anyways
|
||||
if(!mMouseRelative || !mWrapPointer || !mGrabPointer)
|
||||
return;
|
||||
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
SDL_GetWindowSize(mSDLWindow, &width, &height);
|
||||
|
||||
const int FUDGE_FACTOR_X = width / 4;
|
||||
const int FUDGE_FACTOR_Y = height / 4;
|
||||
|
||||
//warp the mouse if it's about to go outside the window
|
||||
if(evt.x - FUDGE_FACTOR_X < 0 || evt.x + FUDGE_FACTOR_X > width
|
||||
|| evt.y - FUDGE_FACTOR_Y < 0 || evt.y + FUDGE_FACTOR_Y > height)
|
||||
{
|
||||
warpMouse(width / 2, height / 2);
|
||||
}
|
||||
}
|
||||
|
||||
void InputWrapper::_handleKeyPress(SDL_KeyboardEvent &evt)
|
||||
{
|
||||
//SDL keyboard events are followed by the actual text those keys would generate
|
||||
//to account for languages that require multiple keystrokes to produce a key.
|
||||
//Look for an event immediately following ours, assuming each key produces exactly
|
||||
//one character or none at all.
|
||||
|
||||
//TODO: Check if this works properly for multibyte symbols
|
||||
//do we have to worry about endian-ness?
|
||||
//for that matter, check if we even need to do any of this.
|
||||
|
||||
SDL_Event text_evts[1];
|
||||
if(SDL_PeepEvents(text_evts, 1, SDL_GETEVENT, SDL_TEXTINPUT, SDL_TEXTINPUT) != 0)
|
||||
{
|
||||
const char* symbol = text_evts[0].text.text;
|
||||
|
||||
Uint32 num_bytes = strlen(symbol);
|
||||
|
||||
//no valid character is more than 4 bytes
|
||||
if(num_bytes > 0 && num_bytes <= 4)
|
||||
{
|
||||
Uint32 u32_symbol = boost::locale::conv::utf_to_utf<Uint32>(symbol)[0];
|
||||
|
||||
evt.keysym.unicode = u32_symbol;
|
||||
}
|
||||
}
|
||||
|
||||
mKeyboardListener->keyPressed(evt);
|
||||
}
|
||||
|
||||
MouseMotionEvent InputWrapper::_packageMouseMotion(const SDL_Event &evt)
|
||||
{
|
||||
MouseMotionEvent pack_evt;
|
||||
pack_evt.x = mMouseX;
|
||||
pack_evt.xrel = 0;
|
||||
pack_evt.y = mMouseY;
|
||||
pack_evt.yrel = 0;
|
||||
pack_evt.z = mMouseZ;
|
||||
pack_evt.zrel = 0;
|
||||
|
||||
if(evt.type == SDL_MOUSEMOTION)
|
||||
{
|
||||
pack_evt.x = mMouseX = evt.motion.x;
|
||||
pack_evt.y = mMouseY = evt.motion.y;
|
||||
pack_evt.xrel = evt.motion.xrel;
|
||||
pack_evt.yrel = evt.motion.yrel;
|
||||
}
|
||||
else if(evt.type == SDL_MOUSEWHEEL)
|
||||
{
|
||||
mMouseZ += pack_evt.zrel = evt.wheel.y;
|
||||
pack_evt.z = mMouseZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new std::runtime_error("Tried to package non-motion event!");
|
||||
}
|
||||
|
||||
return pack_evt;
|
||||
}
|
||||
|
||||
OIS::KeyCode InputWrapper::sdl2OISKeyCode(SDL_Keycode code)
|
||||
{
|
||||
OIS::KeyCode kc = OIS::KC_UNASSIGNED;
|
||||
|
||||
KeyMap::const_iterator ois_equiv = mKeyMap.find(code);
|
||||
|
||||
if(ois_equiv != mKeyMap.end())
|
||||
kc = ois_equiv->second;
|
||||
|
||||
return kc;
|
||||
}
|
||||
|
||||
void InputWrapper::_setupOISKeys()
|
||||
{
|
||||
//lifted from OIS's SDLKeyboard.cpp
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_UNKNOWN, OIS::KC_UNASSIGNED));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_ESCAPE, OIS::KC_ESCAPE) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_1, OIS::KC_1) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_2, OIS::KC_2) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_3, OIS::KC_3) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_4, OIS::KC_4) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_5, OIS::KC_5) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_6, OIS::KC_6) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_7, OIS::KC_7) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_8, OIS::KC_8) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_9, OIS::KC_9) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_0, OIS::KC_0) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_MINUS, OIS::KC_MINUS) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_EQUALS, OIS::KC_EQUALS) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_BACKSPACE, OIS::KC_BACK) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_TAB, OIS::KC_TAB) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_q, OIS::KC_Q) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_w, OIS::KC_W) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_e, OIS::KC_E) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_r, OIS::KC_R) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_t, OIS::KC_T) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_y, OIS::KC_Y) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_u, OIS::KC_U) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_i, OIS::KC_I) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_o, OIS::KC_O) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_p, OIS::KC_P) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_RETURN, OIS::KC_RETURN) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_LCTRL, OIS::KC_LCONTROL));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_a, OIS::KC_A) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_s, OIS::KC_S) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_d, OIS::KC_D) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_f, OIS::KC_F) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_g, OIS::KC_G) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_h, OIS::KC_H) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_j, OIS::KC_J) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_k, OIS::KC_K) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_l, OIS::KC_L) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_SEMICOLON, OIS::KC_SEMICOLON) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_COLON, OIS::KC_COLON) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_QUOTE, OIS::KC_APOSTROPHE) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_BACKQUOTE, OIS::KC_GRAVE) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_LSHIFT, OIS::KC_LSHIFT) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_BACKSLASH, OIS::KC_BACKSLASH) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_SLASH, OIS::KC_SLASH) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_z, OIS::KC_Z) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_x, OIS::KC_X) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_c, OIS::KC_C) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_v, OIS::KC_V) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_b, OIS::KC_B) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_n, OIS::KC_N) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_m, OIS::KC_M) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_COMMA, OIS::KC_COMMA) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_PERIOD, OIS::KC_PERIOD));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_RSHIFT, OIS::KC_RSHIFT));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_MULTIPLY, OIS::KC_MULTIPLY) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_LALT, OIS::KC_LMENU) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_SPACE, OIS::KC_SPACE));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_CAPSLOCK, OIS::KC_CAPITAL) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F1, OIS::KC_F1) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F2, OIS::KC_F2) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F3, OIS::KC_F3) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F4, OIS::KC_F4) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F5, OIS::KC_F5) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F6, OIS::KC_F6) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F7, OIS::KC_F7) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F8, OIS::KC_F8) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F9, OIS::KC_F9) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F10, OIS::KC_F10) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_NUMLOCKCLEAR, OIS::KC_NUMLOCK) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_SCROLLLOCK, OIS::KC_SCROLL));
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_7, OIS::KC_NUMPAD7) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_8, OIS::KC_NUMPAD8) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_9, OIS::KC_NUMPAD9) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_MINUS, OIS::KC_SUBTRACT) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_4, OIS::KC_NUMPAD4) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_5, OIS::KC_NUMPAD5) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_6, OIS::KC_NUMPAD6) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_PLUS, OIS::KC_ADD) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_1, OIS::KC_NUMPAD1) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_2, OIS::KC_NUMPAD2) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_3, OIS::KC_NUMPAD3) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_0, OIS::KC_NUMPAD0) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_PERIOD, OIS::KC_DECIMAL) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F11, OIS::KC_F11) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F12, OIS::KC_F12) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F13, OIS::KC_F13) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F14, OIS::KC_F14) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_F15, OIS::KC_F15) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_EQUALS, OIS::KC_NUMPADEQUALS) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_KP_DIVIDE, OIS::KC_DIVIDE) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_SYSREQ, OIS::KC_SYSRQ) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_RALT, OIS::KC_RMENU) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_HOME, OIS::KC_HOME) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_UP, OIS::KC_UP) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_PAGEUP, OIS::KC_PGUP) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_LEFT, OIS::KC_LEFT) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_RIGHT, OIS::KC_RIGHT) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_END, OIS::KC_END) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_DOWN, OIS::KC_DOWN) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_PAGEDOWN, OIS::KC_PGDOWN) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_INSERT, OIS::KC_INSERT) );
|
||||
mKeyMap.insert( KeyMap::value_type(SDLK_DELETE, OIS::KC_DELETE) );
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
#ifndef _MWINPUT_SDLINPUTWRAPPER_H
|
||||
#define _MWINPUT_SDLINPUTWRAPPER_H
|
||||
|
||||
#include "SDL2/SDL_events.h"
|
||||
#include <OGRE/OgreRenderWindow.h>
|
||||
#include <boost/unordered_map.hpp>
|
||||
|
||||
#include "OISCompat.h"
|
||||
#include "events.h"
|
||||
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
class InputWrapper
|
||||
{
|
||||
public:
|
||||
InputWrapper(Ogre::RenderWindow* window);
|
||||
~InputWrapper();
|
||||
|
||||
void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; }
|
||||
void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; }
|
||||
void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; }
|
||||
|
||||
void capture();
|
||||
bool isModifierHeld(int mod);
|
||||
|
||||
void setMouseRelative(bool relative);
|
||||
bool getMouseRelative() { return mMouseRelative; }
|
||||
void setGrabPointer(bool grab);
|
||||
|
||||
OIS::KeyCode sdl2OISKeyCode(SDL_Keycode code);
|
||||
|
||||
void warpMouse(int x, int y);
|
||||
private:
|
||||
bool _handleWarpMotion(const SDL_MouseMotionEvent& evt);
|
||||
void _wrapMousePointer(const SDL_MouseMotionEvent &evt);
|
||||
|
||||
MouseMotionEvent _packageMouseMotion(const SDL_Event& evt);
|
||||
void _handleKeyPress(SDL_KeyboardEvent& evt);
|
||||
|
||||
bool _start();
|
||||
void _setupOISKeys();
|
||||
|
||||
SFO::MouseListener* mMouseListener;
|
||||
SFO::KeyListener* mKeyboardListener;
|
||||
SFO::WindowListener* mWindowListener;
|
||||
|
||||
typedef boost::unordered::unordered_map<SDL_Keycode, OIS::KeyCode> KeyMap;
|
||||
KeyMap mKeyMap;
|
||||
|
||||
Uint16 mWarpX;
|
||||
Uint16 mWarpY;
|
||||
bool mWarpCompensate;
|
||||
bool mMouseRelative;
|
||||
bool mWrapPointer;
|
||||
bool mGrabPointer;
|
||||
|
||||
Sint32 mMouseZ;
|
||||
Sint32 mMouseX;
|
||||
Sint32 mMouseY;
|
||||
|
||||
Ogre::RenderWindow* mWindow;
|
||||
SDL_Window* mSDLWindow;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue