From ed644259ce71df3a3c61e54d8f92ebf6bfedfe14 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Thu, 10 Jan 2013 17:21:47 -0400 Subject: [PATCH] Move SDL helpers to their own package in extern/, allow conversion from sdl to ois keycodes, (maybe) fix unicode handling --- CMakeLists.txt | 1 + apps/openmw/CMakeLists.txt | 3 +- apps/openmw/mwinput/inputmanagerimp.cpp | 76 ++-- apps/openmw/mwinput/inputmanagerimp.hpp | 15 +- apps/openmw/mwinput/sdlinputwrapper.cpp | 254 ----------- apps/openmw/mwinput/sdlinputwrapper.hpp | 53 --- extern/oics/CMakeLists.txt | 1 - extern/oics/ICSInputControlSystem.h | 10 +- extern/oics/ICSInputControlSystem_mouse.cpp | 2 +- extern/sdl4ogre/CMakeLists.txt | 14 + extern/sdl4ogre/OISCompat.h | 159 +++++++ .../{oics/OISCompat.h => sdl4ogre/events.h} | 68 +-- extern/sdl4ogre/sdlinputwrapper.cpp | 420 ++++++++++++++++++ extern/sdl4ogre/sdlinputwrapper.hpp | 67 +++ 14 files changed, 734 insertions(+), 409 deletions(-) delete mode 100644 apps/openmw/mwinput/sdlinputwrapper.cpp delete mode 100644 apps/openmw/mwinput/sdlinputwrapper.hpp create mode 100644 extern/sdl4ogre/CMakeLists.txt create mode 100644 extern/sdl4ogre/OISCompat.h rename extern/{oics/OISCompat.h => sdl4ogre/events.h} (53%) create mode 100644 extern/sdl4ogre/sdlinputwrapper.cpp create mode 100644 extern/sdl4ogre/sdlinputwrapper.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index de4be3895..37023571b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -474,6 +474,7 @@ endif(WIN32) # Extern add_subdirectory (extern/shiny) add_subdirectory (extern/oics) +add_subdirectory (extern/sdl4ogre) # Components add_subdirectory (components) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 4aa744e3b..faab842c3 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -20,7 +20,7 @@ add_openmw_dir (mwrender ) add_openmw_dir (mwinput - inputmanagerimp sdlinputwrapper + inputmanagerimp ) add_openmw_dir (mwgui @@ -108,6 +108,7 @@ target_link_libraries(openmw "shiny" "shiny.OgrePlatform" "oics" + "sdl4ogre" components ) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 763e75ae7..6d25f7dc6 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -62,13 +62,13 @@ namespace MWInput Ogre::RenderWindow* window = ogre.getWindow (); - mInputManager = new MWSDLInputWrapper(window); + mInputManager = new SFO::InputWrapper(window); mInputManager->setMouseEventCallback (this); mInputManager->setKeyboardEventCallback (this); mInputManager->setWindowEventCallback(this); std::string file = userFileExists ? userFile : ""; - mInputCtrl = new ICS::InputControlSystem(file, true, this, NULL, A_Last); + mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last); adjustMouseRegion (window->getWidth(), window->getHeight()); @@ -78,7 +78,7 @@ namespace MWInput for (int i = 0; i < A_Last; ++i) { - mInputCtrl->getChannel (i)->addListener (this); + mInputBinder->getChannel (i)->addListener (this); } mControlSwitch["playercontrols"] = true; @@ -94,9 +94,9 @@ namespace MWInput InputManager::~InputManager() { - mInputCtrl->save (mUserFile); + mInputBinder->save (mUserFile); - delete mInputCtrl; + delete mInputBinder; delete mInputManager; } @@ -206,7 +206,7 @@ namespace MWInput // update values of channels (as a result of pressed keys) if (!loading) - mInputCtrl->update(dt); + mInputBinder->update(dt); // Update windows/gui as a result of input events // For instance this could mean opening a new window/dialog, @@ -396,12 +396,12 @@ namespace MWInput void InputManager::adjustMouseRegion(int width, int height) { - mInputCtrl->adjustMouseRegion(width, height); + mInputBinder->adjustMouseRegion(width, height); } bool InputManager::keyPressed( const SDL_KeyboardEvent &arg ) { - mInputCtrl->keyPressed (arg); + mInputBinder->keyPressed (arg); unsigned int text = arg.keysym.unicode; //TODO: Check if we need this with SDL @@ -414,23 +414,27 @@ namespace MWInput #endif */ - MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(arg.keysym.sym), text); + OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); + + MyGUI::InputManager::getInstance().injectKeyPress(MyGUI::KeyCode::Enum(kc), text); return true; } bool InputManager::keyReleased(const SDL_KeyboardEvent &arg ) { - mInputCtrl->keyReleased (arg); + mInputBinder->keyReleased (arg); + + OIS::KeyCode kc = mInputManager->sdl2OISKeyCode(arg.keysym.sym); - MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(arg.keysym.sym)); + MyGUI::InputManager::getInstance().injectKeyRelease(MyGUI::KeyCode::Enum(kc)); return true; } bool InputManager::mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) { - mInputCtrl->mousePressed (arg, id); + mInputBinder->mousePressed (arg, id); MyGUI::InputManager::getInstance().injectMousePress(mMouseX, mMouseY, sdlButtonToMyGUI(id)); @@ -448,16 +452,16 @@ namespace MWInput bool InputManager::mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) { - mInputCtrl->mouseReleased (arg, id); + mInputBinder->mouseReleased (arg, id); MyGUI::InputManager::getInstance().injectMouseRelease(mMouseX, mMouseY, sdlButtonToMyGUI(id)); return true; } - bool InputManager::mouseMoved( const ICS::MWSDLMouseMotionEvent &arg ) + bool InputManager::mouseMoved(const SFO::MouseMotionEvent &arg ) { - mInputCtrl->mouseMoved (arg); + mInputBinder->mouseMoved (arg); resetIdleTime (); @@ -683,7 +687,7 @@ namespace MWInput bool InputManager::actionIsActive (int id) { - return mInputCtrl->getChannel (id)->getValue () == 1; + return mInputBinder->getChannel (id)->getValue () == 1; } void InputManager::loadKeyDefaults (bool force) @@ -728,29 +732,29 @@ namespace MWInput for (int i = 0; i < A_Last; ++i) { ICS::Control* control; - bool controlExists = mInputCtrl->getChannel(i)->getControlsCount () != 0; + bool controlExists = mInputBinder->getChannel(i)->getControlsCount () != 0; if (!controlExists) { control = new ICS::Control(boost::lexical_cast(i), false, true, 0, ICS::ICS_MAX, ICS::ICS_MAX); - mInputCtrl->addControl(control); - control->attachChannel(mInputCtrl->getChannel(i), ICS::Channel::DIRECT); + mInputBinder->addControl(control); + control->attachChannel(mInputBinder->getChannel(i), ICS::Channel::DIRECT); } else { - control = mInputCtrl->getChannel(i)->getAttachedControls ().front().control; + control = mInputBinder->getChannel(i)->getAttachedControls ().front().control; } if (!controlExists || force || - ( mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE) == SDLK_UNKNOWN - && mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS + ( mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) == SDLK_UNKNOWN + && mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) == ICS_MAX_DEVICE_BUTTONS )) { clearAllBindings (control); if (defaultKeyBindings.find(i) != defaultKeyBindings.end()) - mInputCtrl->addKeyBinding(control, static_cast(defaultKeyBindings[i]), ICS::Control::INCREASE); + mInputBinder->addKeyBinding(control, static_cast(defaultKeyBindings[i]), ICS::Control::INCREASE); else if (defaultMouseButtonBindings.find(i) != defaultMouseButtonBindings.end()) - mInputCtrl->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); + mInputBinder->addMouseButtonBinding (control, defaultMouseButtonBindings[i], ICS::Control::INCREASE); } } } @@ -794,15 +798,15 @@ namespace MWInput std::string InputManager::getActionBindingName (int action) { - if (mInputCtrl->getChannel (action)->getControlsCount () == 0) + if (mInputBinder->getChannel (action)->getControlsCount () == 0) return "#{sNone}"; - ICS::Control* c = mInputCtrl->getChannel (action)->getAttachedControls ().front().control; + ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; - if (mInputCtrl->getKeyBinding (c, ICS::Control::INCREASE) != SDLK_UNKNOWN) - return mInputCtrl->keyCodeToString (mInputCtrl->getKeyBinding (c, ICS::Control::INCREASE)); - else if (mInputCtrl->getMouseButtonBinding (c, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) - return "#{sMouse} " + boost::lexical_cast(mInputCtrl->getMouseButtonBinding (c, ICS::Control::INCREASE)); + if (mInputBinder->getKeyBinding (c, ICS::Control::INCREASE) != SDLK_UNKNOWN) + return mInputBinder->keyCodeToString (mInputBinder->getKeyBinding (c, ICS::Control::INCREASE)); + else if (mInputBinder->getMouseButtonBinding (c, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) + return "#{sMouse} " + boost::lexical_cast(mInputBinder->getMouseButtonBinding (c, ICS::Control::INCREASE)); else return "#{sNone}"; } @@ -842,9 +846,9 @@ namespace MWInput void InputManager::enableDetectingBindingMode (int action) { - ICS::Control* c = mInputCtrl->getChannel (action)->getAttachedControls ().front().control; + ICS::Control* c = mInputBinder->getChannel (action)->getAttachedControls ().front().control; - mInputCtrl->enableDetectingBindingState (c, ICS::Control::INCREASE); + mInputBinder->enableDetectingBindingState (c, ICS::Control::INCREASE); } void InputManager::mouseAxisBindingDetected(ICS::InputControlSystem* ICS, ICS::Control* control @@ -905,10 +909,10 @@ namespace MWInput void InputManager::clearAllBindings (ICS::Control* control) { // right now we don't really need multiple bindings for the same action, so remove all others first - if (mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE) != SDLK_UNKNOWN) - mInputCtrl->removeKeyBinding (mInputCtrl->getKeyBinding (control, ICS::Control::INCREASE)); - if (mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) - mInputCtrl->removeMouseButtonBinding (mInputCtrl->getMouseButtonBinding (control, ICS::Control::INCREASE)); + if (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE) != SDLK_UNKNOWN) + mInputBinder->removeKeyBinding (mInputBinder->getKeyBinding (control, ICS::Control::INCREASE)); + if (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE) != ICS_MAX_DEVICE_BUTTONS) + mInputBinder->removeMouseButtonBinding (mInputBinder->getMouseButtonBinding (control, ICS::Control::INCREASE)); /// \todo add joysticks here once they are added } diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 9a7656a67..34ea92a37 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -6,7 +6,7 @@ #include #include "../mwbase/inputmanager.hpp" -#include "sdlinputwrapper.hpp" +#include namespace OEngine { @@ -43,7 +43,6 @@ namespace MyGUI #include #include -#include namespace MWInput { @@ -53,9 +52,9 @@ namespace MWInput */ class InputManager : public MWBase::InputManager, - public ICS::MWSDLKeyListener, - public ICS::MWSDLMouseListener, - public ICS::MWSDLWindowListener, + public SFO::KeyListener, + public SFO::MouseListener, + public SFO::WindowListener, public ICS::ChannelListener, public ICS::DetectingBindingListener { @@ -93,7 +92,7 @@ namespace MWInput virtual bool mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); - virtual bool mouseMoved( const ICS::MWSDLMouseMotionEvent &arg ); + virtual bool mouseMoved( const SFO::MouseMotionEvent &arg ); virtual bool windowVisibilityChange( bool visible ); virtual bool windowFocusChange( bool have_focus ); @@ -129,10 +128,10 @@ namespace MWInput MWBase::WindowManager &mWindows; OMW::Engine& mEngine; - ICS::InputControlSystem* mInputCtrl; + ICS::InputControlSystem* mInputBinder; - MWSDLInputWrapper* mInputManager; + SFO::InputWrapper* mInputManager; std::string mUserFile; diff --git a/apps/openmw/mwinput/sdlinputwrapper.cpp b/apps/openmw/mwinput/sdlinputwrapper.cpp deleted file mode 100644 index 56b3568f5..000000000 --- a/apps/openmw/mwinput/sdlinputwrapper.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "sdlinputwrapper.hpp" -#include -#include - -#include -#include - -#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX -# include -# include -# include -#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); - } -} diff --git a/apps/openmw/mwinput/sdlinputwrapper.hpp b/apps/openmw/mwinput/sdlinputwrapper.hpp deleted file mode 100644 index 6377d0bcf..000000000 --- a/apps/openmw/mwinput/sdlinputwrapper.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _MWINPUT_SDLINPUTWRAPPER_H -#define _MWINPUT_SDLINPUTWRAPPER_H - -#include "SDL2/SDL_events.h" -#include -#include - - -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 diff --git a/extern/oics/CMakeLists.txt b/extern/oics/CMakeLists.txt index 2e2a7a6d6..7c14387a4 100644 --- a/extern/oics/CMakeLists.txt +++ b/extern/oics/CMakeLists.txt @@ -9,7 +9,6 @@ set(OICS_SOURCE_FILES ICSInputControlSystem_keyboard.cpp ICSInputControlSystem_mouse.cpp ICSInputControlSystem_joystick.cpp - OISCompat.h tinyxml.cpp tinyxmlparser.cpp tinyxmlerror.cpp diff --git a/extern/oics/ICSInputControlSystem.h b/extern/oics/ICSInputControlSystem.h index 5d30b35cf..f42f9c0b5 100644 --- a/extern/oics/ICSInputControlSystem.h +++ b/extern/oics/ICSInputControlSystem.h @@ -32,7 +32,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "ICSControl.h" #include "ICSChannel.h" -#include "OISCompat.h" +#include "../sdl4ogre/events.h" #define ICS_LOG(text) if(mLog) mLog->logMessage( ("ICS: " + std::string(text)).c_str() ); #define ICS_MAX_JOYSTICK_AXIS 16 @@ -50,9 +50,9 @@ namespace ICS }; class DllExport InputControlSystem : - public MWSDLMouseListener, - public MWSDLKeyListener, - public MWSDLJoyStickListener + public SFO::MouseListener, + public SFO::KeyListener, + public SFO::JoyListener { public: @@ -102,7 +102,7 @@ namespace ICS JoystickIDList& getJoystickIdList(){ return mJoystickIDList; }; // MouseListener - bool mouseMoved(const MWSDLMouseMotionEvent &evt); + bool mouseMoved(const SFO::MouseMotionEvent &evt); bool mousePressed(const SDL_MouseButtonEvent &evt, Uint8); bool mouseReleased(const SDL_MouseButtonEvent &evt, Uint8); diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp index 96197426a..52eb894ed 100644 --- a/extern/oics/ICSInputControlSystem_mouse.cpp +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -219,7 +219,7 @@ namespace ICS } // mouse Listeners - bool InputControlSystem::mouseMoved(const MWSDLMouseMotionEvent& evt) + bool InputControlSystem::mouseMoved(const SFO::MouseMotionEvent& evt) { if(mActive) { diff --git a/extern/sdl4ogre/CMakeLists.txt b/extern/sdl4ogre/CMakeLists.txt new file mode 100644 index 000000000..c52dd4cb4 --- /dev/null +++ b/extern/sdl4ogre/CMakeLists.txt @@ -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}) diff --git a/extern/sdl4ogre/OISCompat.h b/extern/sdl4ogre/OISCompat.h new file mode 100644 index 000000000..04ba2c537 --- /dev/null +++ b/extern/sdl4ogre/OISCompat.h @@ -0,0 +1,159 @@ +#ifndef _OIS_SDL_COMPAT_H +#define _OIS_SDL_COMPAT_H + +#include +#include + +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 diff --git a/extern/oics/OISCompat.h b/extern/sdl4ogre/events.h similarity index 53% rename from extern/oics/OISCompat.h rename to extern/sdl4ogre/events.h index 5813c17bf..945daf49a 100644 --- a/extern/oics/OISCompat.h +++ b/extern/sdl4ogre/events.h @@ -1,53 +1,20 @@ -#ifndef _OIS_SDL_COMPAT_H -#define _OIS_SDL_COMPAT_H +#ifndef _SFO_EVENTS_H +#define _SFO_EVENTS_H -#include -#include +#include -//TODO: Remove this. Right now we want to remain as close to OIS as possible -//So we can easily test the SDL backend //////////// // Events // //////////// -namespace ICS { +namespace SFO { /** Extended mouse event struct where we treat the wheel like an axis, like everyone expects */ -struct MWSDLMouseMotionEvent : SDL_MouseMotionEvent { - - Sint16 zrel; - - MWSDLMouseMotionEvent() - { - _init(); - } - - MWSDLMouseMotionEvent( const SDL_MouseMotionEvent& evt) - { - _init(); - x = evt.x; - y = evt.y; - xrel = evt.xrel; - yrel = evt.yrel; - state = evt.state; - } - - MWSDLMouseMotionEvent (const SDL_MouseWheelEvent& evt) - { - _init(); - zrel = evt.y; - } - - void _init() - { - x = 0; - y = 0; - xrel = 0; - yrel = 0; - state = 0; - zrel = 0; - } +struct MouseMotionEvent : SDL_MouseMotionEvent { + + Sint32 zrel; + Sint32 z; }; @@ -55,27 +22,27 @@ struct MWSDLMouseMotionEvent : SDL_MouseMotionEvent { // Listeners // /////////////// -class MWSDLMouseListener +class MouseListener { public: - virtual ~MWSDLMouseListener() {} - virtual bool mouseMoved( const MWSDLMouseMotionEvent &arg ) = 0; + virtual ~MouseListener() {} + virtual bool mouseMoved( const MouseMotionEvent &arg ) = 0; virtual bool mousePressed( const SDL_MouseButtonEvent &arg, Uint8 id ) = 0; virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ) = 0; }; -class MWSDLKeyListener +class KeyListener { public: - virtual ~MWSDLKeyListener() {} + virtual ~KeyListener() {} virtual bool keyPressed(const SDL_KeyboardEvent &arg) = 0; virtual bool keyReleased(const SDL_KeyboardEvent &arg) = 0; }; -class MWSDLJoyStickListener +class JoyListener { public: - virtual ~MWSDLJoyStickListener() {} + virtual ~JoyListener() {} /** @remarks Joystick button down event */ virtual bool buttonPressed( const SDL_JoyButtonEvent &evt, int button ) = 0; @@ -91,10 +58,10 @@ public: virtual bool povMoved( const SDL_JoyHatEvent &arg, int index) {return true;} }; -class MWSDLWindowListener +class WindowListener { public: - virtual ~MWSDLWindowListener() {} + virtual ~WindowListener() {} /** @remarks The window's visibility changed */ virtual bool windowVisibilityChange( bool visible ) = 0; @@ -104,4 +71,5 @@ public: }; } + #endif diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp new file mode 100644 index 000000000..b7d1550c9 --- /dev/null +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -0,0 +1,420 @@ +#include "sdlinputwrapper.hpp" +#include + +#include +#include +#include + +#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX +# include +# include +# include +#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(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) ); + } +} diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp new file mode 100644 index 000000000..63b4c922b --- /dev/null +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -0,0 +1,67 @@ +#ifndef _MWINPUT_SDLINPUTWRAPPER_H +#define _MWINPUT_SDLINPUTWRAPPER_H + +#include "SDL2/SDL_events.h" +#include +#include + +#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 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