From 5a6589af0155b058fc63c095f38c8568c59f6c77 Mon Sep 17 00:00:00 2001 From: Jordan Milne Date: Sat, 12 Jan 2013 11:57:29 -0400 Subject: [PATCH] extract cursor management to a separate class, have windowmanager communicate with it. Initialize SDL during engine start --- apps/openmw/engine.cpp | 15 ++ apps/openmw/mwbase/windowmanager.hpp | 4 +- apps/openmw/mwgui/windowmanagerimp.cpp | 57 +++--- apps/openmw/mwgui/windowmanagerimp.hpp | 9 +- apps/openmw/mwinput/inputmanagerimp.cpp | 9 +- extern/sdl4ogre/CMakeLists.txt | 8 +- extern/sdl4ogre/cursormanager.hpp | 35 ++++ extern/sdl4ogre/sdlcursormanager.cpp | 189 ++++++++++++++++++++ extern/sdl4ogre/sdlcursormanager.hpp | 44 +++++ extern/sdl4ogre/sdlinputwrapper.cpp | 222 +++++------------------- extern/sdl4ogre/sdlinputwrapper.hpp | 41 +---- 11 files changed, 383 insertions(+), 250 deletions(-) create mode 100644 extern/sdl4ogre/cursormanager.hpp create mode 100644 extern/sdl4ogre/sdlcursormanager.cpp create mode 100644 extern/sdl4ogre/sdlcursormanager.hpp diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 4413e98f46..51dbabba51 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -36,6 +36,8 @@ #include "mwmechanics/mechanicsmanagerimp.hpp" +#include "SDL2/SDL.h" + void OMW::Engine::executeLocalScripts() { @@ -272,6 +274,9 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings) else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg")) nifOverrides.loadTransparencyOverrides(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"); + settings.setBool("hardware cursors", "GUI", true); + settings.setBool("debug", "Engine", mDebug); + return settingspath; } @@ -322,6 +327,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) loadBSA(); + Uint32 flags = SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE; + if(SDL_WasInit(flags) == 0) + { + //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(flags) != 0) + throw std::runtime_error("Couldn't initialize SDL!"); + } + // cursor replacer (converts the cursor from the bsa so they can be used by mygui) MWGui::CursorReplace replacer; diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c7dc06472c..06b1df7b9a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -57,7 +57,7 @@ namespace MWGui namespace SFO { - class CursorChangeClient; + class CursorManager; } namespace MWBase @@ -243,8 +243,6 @@ namespace MWBase virtual void startTraining(MWWorld::Ptr actor) = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0; - - virtual void setCursorChangeClient(SFO::CursorChangeClient* client) = 0; }; } diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 781f3c86c1..20301b1b22 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include @@ -115,7 +115,8 @@ WindowManager::WindowManager( , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mHudEnabled(true) , mTranslationDataStorage (translationDataStorage) - , mCursorChangeClient(NULL) + , mCursorManager(NULL) + , mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")) { // Set up the GUI system @@ -190,9 +191,6 @@ WindowManager::WindowManager( mInputBlocker = mGui->createWidget("",0,0,w,h,MyGUI::Align::Default,"Windows",""); - //make sure the cursor in the GL context isn't visible - MyGUI::PointerManager::getInstance().setVisible(false); - // The HUD is always on mHud->setVisible(true); @@ -212,6 +210,13 @@ WindowManager::WindowManager( unsetSelectedSpell(); unsetSelectedWeapon(); + //set up the hardware cursor manager + mCursorManager = new SFO::SDLCursorManager(Settings::Manager::getBool("debug", "Engine")); + + setUseHardwareCursors(mUseHardwareCursors); + onCursorChange(PointerManager::getInstance().getDefaultPointer()); + mCursorManager->cursorVisibilityChange(false); + // Set up visibility updateVisible(); } @@ -252,6 +257,7 @@ WindowManager::~WindowManager() cleanupGarbage(); delete mGuiManager; + delete mCursorManager; } void WindowManager::cleanupGarbage() @@ -740,15 +746,30 @@ void WindowManager::setSpellVisibility(bool visible) mHud->setEffectVisible (visible); } +void WindowManager::setUseHardwareCursors(bool use) +{ + mCursorManager->setEnabled(use); + + if(!use) + { + MyGUI::PointerManager::getInstance().setVisible(false); + } + else + { + MyGUI::PointerManager::getInstance().setVisible(mCursorVisible); + } +} + void WindowManager::setCursorVisible(bool visible) { - if(visible == mCursorVisible) + if(mCursorVisible == visible) return; mCursorVisible = visible; + mCursorManager->cursorVisibilityChange(visible); - if(mCursorChangeClient != NULL) - mCursorChangeClient->cursorVisible(visible); + if(!mUseHardwareCursors) + MyGUI::PointerManager::getInstance().setVisible(visible); } void WindowManager::setDragDrop(bool dragDrop) @@ -780,21 +801,10 @@ void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _r } } - void WindowManager::setCursorChangeClient(SFO::CursorChangeClient* client) - { - mCursorChangeClient = client; - onCursorChange(PointerManager::getInstance().getDefaultPointer()); - client->cursorVisible(mCursorVisible); - } - void WindowManager::onCursorChange(const std::string &name) { - //we have no client, don't care. - if(!mCursorChangeClient) - return; - - //the client doesn't want any more info about this cursor - if(!mCursorChangeClient->cursorChanged(name)) + //the cursor manager doesn't want any more info about this cursor + if(!mCursorManager->cursorChanged(name)) return; //See if we can get the information we need out of the cursor resource ResourceImageSetPointerFix* imgSetPtr = dynamic_cast(MyGUI::PointerManager::getInstance().getByName(name)); @@ -806,7 +816,7 @@ void WindowManager::onCursorChange(const std::string &name) Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName(tex_name); - //everything looks good, send it to the client + //everything looks good, send it to the cursor manager if(!tex.isNull()) { Uint8 size_x = imgSetPtr->getSize().width; @@ -814,7 +824,7 @@ void WindowManager::onCursorChange(const std::string &name) Uint8 hotspot_x = imgSetPtr->getHotSpot().left; Uint8 hotspot_y = imgSetPtr->getHotSpot().top; - mCursorChangeClient->receiveCursorInfo(name, tex, size_x, size_y, hotspot_x, hotspot_y); + mCursorManager->receiveCursorInfo(name, tex, size_x, size_y, hotspot_x, hotspot_y); } } } @@ -823,6 +833,7 @@ void WindowManager::processChangedSettings(const Settings::CategorySettingVector { mHud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); + setUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")); bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 4334de83fb..874de8af97 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -50,7 +50,7 @@ namespace OEngine namespace SFO { - class CursorChangeClient; + class CursorManager; } namespace MWGui @@ -233,8 +233,6 @@ namespace MWGui virtual const Translation::Storage& getTranslationDataStorage() const; - virtual void setCursorChangeClient(SFO::CursorChangeClient* client); - private: OEngine::GUI::MyGUIManager *mGuiManager; HUD *mHud; @@ -290,7 +288,7 @@ namespace MWGui MyGUI::Gui *mGui; // Gui std::vector mGuiModes; - SFO::CursorChangeClient* mCursorChangeClient; + SFO::CursorManager* mCursorManager; std::vector mGarbageDialogs; void cleanupGarbage(); @@ -315,6 +313,9 @@ namespace MWGui void onDialogueWindowBye(); + bool mUseHardwareCursors; + void setUseHardwareCursors(bool use); + /** * Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index c1f857b5f0..9d80de91e4 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -67,8 +68,6 @@ namespace MWInput mInputManager->setKeyboardEventCallback (this); mInputManager->setWindowEventCallback(this); - mWindows.setCursorChangeClient(mInputManager); - std::string file = userFileExists ? userFile : ""; mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last); @@ -225,6 +224,9 @@ namespace MWInput bool was_relative = mInputManager->getMouseRelative(); bool is_relative = !mWindows.isGuiMode(); + //we let the mouse escape in the main menu + mInputManager->setGrabPointer(!main_menu); + // don't keep the pointer away from the window edge in gui mode // stop using raw mouse motions and switch to system cursor movements mInputManager->setMouseRelative(is_relative); @@ -235,9 +237,6 @@ namespace MWInput { mInputManager->warpMouse(mMouseX, mMouseY); } - - //we let the mouse escape in the main menu - mInputManager->setGrabPointer(!main_menu); } // Disable movement in Gui mode diff --git a/extern/sdl4ogre/CMakeLists.txt b/extern/sdl4ogre/CMakeLists.txt index c52dd4cb43..493d1ce476 100644 --- a/extern/sdl4ogre/CMakeLists.txt +++ b/extern/sdl4ogre/CMakeLists.txt @@ -4,9 +4,15 @@ set(SDL4OGRE_LIBRARY "sdl4ogre") set(SDL4OGRE_SOURCE_FILES sdlinputwrapper.cpp + sdlcursormanager.cpp ) -add_library(${SDL4OGRE_LIBRARY} STATIC ${SDL4OGRE_SOURCE_FILES}) +set(SDL4OGRE_HEADER_FILES + OISCompat.h + cursormanager.hpp +) + +add_library(${SDL4OGRE_LIBRARY} STATIC ${SDL4OGRE_SOURCE_FILES} ${SDL4OGRE_HEADER_FILES}) link_directories(${CMAKE_CURRENT_BINARY_DIR}) diff --git a/extern/sdl4ogre/cursormanager.hpp b/extern/sdl4ogre/cursormanager.hpp new file mode 100644 index 0000000000..938f5f4c28 --- /dev/null +++ b/extern/sdl4ogre/cursormanager.hpp @@ -0,0 +1,35 @@ +#ifndef _SDL4OGRE_CURSOR_MANAGER_H +#define _SDL4OGRE_CURSOR_MANAGER_H + +#include "SDL2/SDL_types.h" +#include + +namespace Ogre +{ + class TexturePtr; +} + +namespace SFO +{ +class CursorManager +{ +public: + virtual ~CursorManager(){} + + /// \brief Tell the manager that the cursor has changed, giving the + /// name of the cursor we changed to ("arrow", "ibeam", etc) + /// \return Whether the manager is interested in more information about the cursor + virtual bool cursorChanged(const std::string &name) = 0; + + /// \brief Follow up a cursorChanged() call with enough info to create an cursor. + virtual void receiveCursorInfo(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) = 0; + + /// \brief Tell the manager when the cursor visibility changed + virtual void cursorVisibilityChange(bool visible) = 0; + + /// \brief sets whether to actively manage cursors or not + virtual void setEnabled(bool enabled) = 0; +}; +} + +#endif diff --git a/extern/sdl4ogre/sdlcursormanager.cpp b/extern/sdl4ogre/sdlcursormanager.cpp new file mode 100644 index 0000000000..4e24696ea1 --- /dev/null +++ b/extern/sdl4ogre/sdlcursormanager.cpp @@ -0,0 +1,189 @@ +#include "sdlcursormanager.hpp" + +#include +#include + +namespace SFO +{ + + SDLCursorManager::SDLCursorManager(bool debug) : + mDebug(debug), + mEnabled(false), + mCursorVisible(false), + mInitialized(false) + { + } + + SDLCursorManager::~SDLCursorManager() + { + CursorMap::const_iterator curs_iter = mCursorMap.begin(); + + while(curs_iter != mCursorMap.end()) + { + SDL_FreeCursor(curs_iter->second); + ++curs_iter; + } + + mCursorMap.clear(); + } + + void SDLCursorManager::setEnabled(bool enabled) + { + if(mInitialized && enabled == mEnabled) + return; + + mInitialized = true; + mEnabled = enabled; + + //turn on hardware cursors + if(enabled) + { + _setGUICursor(mCurrentCursor); + } + //turn off hardware cursors + else + { + if(!mDebug) + SDL_ShowCursor(SDL_FALSE); + } + } + + bool SDLCursorManager::cursorChanged(const std::string &name) + { + mCurrentCursor = name; + + CursorMap::const_iterator curs_iter = mCursorMap.find(name); + + //we have this cursor + if(curs_iter != mCursorMap.end()) + { + _setGUICursor(name); + + return false; + } + else + { + //they should get back to us with more info + return true; + } + } + + void SDLCursorManager::_setGUICursor(const std::string &name) + { + if(mEnabled && (mDebug || mCursorVisible)) + { + SDL_SetCursor(mCursorMap.find(name)->second); + _setCursorVisible(mCursorVisible); + } + } + + void SDLCursorManager::_setCursorVisible(bool visible) + { + if(!mEnabled) + return; + + if(mDebug) + visible = true; + + SDL_ShowCursor(visible ? SDL_TRUE : SDL_FALSE); + } + + void SDLCursorManager::cursorVisibilityChange(bool visible) + { + mCursorVisible = visible; + + _setGUICursor(mCurrentCursor); + _setCursorVisible(visible); + } + + void SDLCursorManager::receiveCursorInfo(const std::string& name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) + { + _createCursorFromResource(name, tex, size_x, size_y, hotspot_x, hotspot_y); + } + + /// \brief creates an SDL cursor from an Ogre texture + void SDLCursorManager::_createCursorFromResource(const std::string& name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) + { + //get the surfaces set up + Ogre::HardwarePixelBufferSharedPtr buffer = tex.get()->getBuffer(); + buffer.get()->lock(Ogre::HardwarePixelBuffer::HBL_READ_ONLY); + + std::string tempName = "_" + name + "_processing"; + + //we need to copy this to a temporary texture first because the cursors might be in DDS format, + //and Ogre doesn't have an interface to read DDS + Ogre::TexturePtr tempTexture = Ogre::TextureManager::getSingleton().createManual( + tempName, + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, + size_x, size_y, + 0, + Ogre::PF_FLOAT16_RGBA, + Ogre::TU_STATIC); + + tempTexture->getBuffer()->blit(buffer); + buffer->unlock(); + + // now blit to memory + Ogre::Image destImage; + tempTexture->convertToImage(destImage); + + SDL_Surface* surf = SDL_CreateRGBSurface(0,size_x,size_y,32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); + + + //copy the Ogre texture to an SDL surface + for(size_t x = 0; x < size_x; ++x) + { + for(size_t y = 0; y < size_y; ++y) + { + Ogre::ColourValue clr = destImage.getColourAt(x, y, 0); + + //set the pixel on the SDL surface to the same value as the Ogre texture's + _putPixel(surf, x, y, SDL_MapRGBA(surf->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255)); + } + } + + //set the cursor and store it for later + SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y); + mCursorMap.insert(CursorMap::value_type(std::string(name), curs)); + + //clean up + SDL_FreeSurface(surf); + Ogre::TextureManager::getSingleton().remove(tempName); + + _setGUICursor(name); + } + + void SDLCursorManager::_putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) + { + int bpp = surface->format->BytesPerPixel; + /* Here p is the address to the pixel we want to set */ + Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; + + switch(bpp) { + case 1: + *p = pixel; + break; + + case 2: + *(Uint16 *)p = pixel; + break; + + case 3: + if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { + p[0] = (pixel >> 16) & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = pixel & 0xff; + } else { + p[0] = pixel & 0xff; + p[1] = (pixel >> 8) & 0xff; + p[2] = (pixel >> 16) & 0xff; + } + break; + + case 4: + *(Uint32 *)p = pixel; + break; + } + } +} diff --git a/extern/sdl4ogre/sdlcursormanager.hpp b/extern/sdl4ogre/sdlcursormanager.hpp new file mode 100644 index 0000000000..2de1923775 --- /dev/null +++ b/extern/sdl4ogre/sdlcursormanager.hpp @@ -0,0 +1,44 @@ +#ifndef _SDL4OGRE_CURSORMANAGER_H +#define _SDL4OGRE_CURSORMANAGER_H + +#include "SDL.h" + +#include "cursormanager.hpp" +#include + +namespace SFO +{ + class SDLCursorManager : + public CursorManager + { + public: + SDLCursorManager(bool debug=false); + virtual ~SDLCursorManager(); + + virtual void setEnabled(bool enabled); + + virtual bool cursorChanged(const std::string &name); + virtual void receiveCursorInfo(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); + virtual void cursorVisibilityChange(bool visible); + + private: + void _createCursorFromResource(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); + void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); + + void _setGUICursor(const std::string& name); + void _setCursorVisible(bool visible); + + typedef std::map CursorMap; + CursorMap mCursorMap; + + SDL_Cursor* mDebugCursor; + std::string mCurrentCursor; + bool mEnabled; + bool mInitialized; + bool mCursorVisible; + bool mDebug; + + }; +} + +#endif diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index b6761e883e..529740d5ef 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX @@ -28,8 +27,8 @@ namespace SFO mMouseY(0), mMouseX(0) { - _start(); _setupOISKeys(); + _start(); } InputWrapper::~InputWrapper() @@ -38,82 +37,60 @@ namespace SFO SDL_DestroyWindow(mSDLWindow); mSDLWindow = NULL; - CursorMap::const_iterator curs_iter = mCursorMap.begin(); - - while(curs_iter != mCursorMap.end()) - { - SDL_FreeCursor(curs_iter->second); - ++curs_iter; - } - - mCursorMap.clear(); - 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); + //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); - //wrap our own event handler around ogre's - mSDLWindow = SDL_CreateWindowFrom((void*)windowHnd); - - if(mSDLWindow == NULL) - return false; + if(mSDLWindow == NULL) + return false; - //without this SDL will take ownership of the window and iconify it when - //we alt-tab away. - SDL_SetWindowFullscreen(mSDLWindow, 0); + //without this SDL will take ownership of the window and iconify it when + //we alt-tab away. + SDL_SetWindowFullscreen(mSDLWindow, 0); - //translate our keypresses into text - SDL_StartTextInput(); + //translate our keypresses into text + 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); + //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); + 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); } -#endif - SDL_ShowCursor(SDL_FALSE); - } + //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 return true; } @@ -209,10 +186,11 @@ namespace SFO //eep, wrap the pointer manually if the input driver doesn't support //relative positioning natively - if(SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE) == -1) + SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE); + + if(relative) { - if(relative) - mWrapPointer = true; + mWrapPointer = true; } //now remove all mouse events using the old setting from the queue @@ -222,118 +200,6 @@ namespace SFO SDL_PeepEvents(dummy, 20, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION); } - bool InputWrapper::cursorChanged(const std::string &name) - { - CursorMap::const_iterator curs_iter = mCursorMap.find(name); - - //we have this cursor - if(curs_iter != mCursorMap.end()) - { - SDL_SetCursor(curs_iter->second); - return false; - } - else - { - //they should get back to use with more info - return true; - } - } - - void InputWrapper::cursorVisible(bool visible) - { - SDL_ShowCursor(visible ? SDL_TRUE : SDL_FALSE); - } - - void InputWrapper::receiveCursorInfo(const std::string& name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) - { - _createCursorFromResource(name, tex, size_x, size_y, hotspot_x, hotspot_y); - } - - /// \brief creates an SDL cursor from an Ogre texture - void InputWrapper::_createCursorFromResource(const std::string& name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) - { - //get the surfaces set up - Ogre::HardwarePixelBufferSharedPtr buffer = tex.get()->getBuffer(); - buffer.get()->lock(Ogre::HardwarePixelBuffer::HBL_READ_ONLY); - - std::string tempName = "_" + name + "_processing"; - - //we need to copy this to a temporary texture first because the cursors might be in DDS format, - //and Ogre doesn't have an interface to read DDS - Ogre::TexturePtr tempTexture = Ogre::TextureManager::getSingleton().createManual( - tempName, - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - size_x, size_y, - 0, - Ogre::PF_FLOAT16_RGBA, - Ogre::TU_STATIC); - - tempTexture->getBuffer()->blit(buffer); - buffer->unlock(); - - // now blit to memory - Ogre::Image destImage; - tempTexture->convertToImage(destImage); - - SDL_Surface* surf = SDL_CreateRGBSurface(0,size_x,size_y,32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); - - - //copy the Ogre texture to an SDL surface - for(size_t x = 0; x < size_x; ++x) - { - for(size_t y = 0; y < size_y; ++y) - { - Ogre::ColourValue clr = destImage.getColourAt(x, y, 0); - - //set the pixel on the SDL surface to the same value as the Ogre texture's - _putPixel(surf, x, y, SDL_MapRGBA(surf->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255)); - } - } - - //set the cursor and store it for later - SDL_Cursor* curs = SDL_CreateColorCursor(surf, hotspot_x, hotspot_y); - SDL_SetCursor(curs); - mCursorMap.insert(CursorMap::value_type(std::string(name), curs)); - - //clean up - SDL_FreeSurface(surf); - Ogre::TextureManager::getSingleton().remove(tempName); - } - - void InputWrapper::_putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) - { - int bpp = surface->format->BytesPerPixel; - /* Here p is the address to the pixel we want to set */ - Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; - - switch(bpp) { - case 1: - *p = pixel; - break; - - case 2: - *(Uint16 *)p = pixel; - break; - - case 3: - if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { - p[0] = (pixel >> 16) & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = pixel & 0xff; - } else { - p[0] = pixel & 0xff; - p[1] = (pixel >> 8) & 0xff; - p[2] = (pixel >> 16) & 0xff; - } - break; - - case 4: - *(Uint32 *)p = pixel; - break; - } - } - /// \brief Internal method for ignoring relative motions as a side effect /// of warpMouse() bool InputWrapper::_handleWarpMotion(const SDL_MouseMotionEvent& evt) diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index d37a43e339..5233fee8b6 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -1,7 +1,8 @@ -#ifndef _MWINPUT_SDLINPUTWRAPPER_H -#define _MWINPUT_SDLINPUTWRAPPER_H +#ifndef _SDL4OGRE_SDLINPUTWRAPPER_H +#define _SDL4OGRE_SDLINPUTWRAPPER_H #include "SDL2/SDL_events.h" + #include #include @@ -9,36 +10,14 @@ #include "events.h" -namespace Ogre -{ - class Texture; -} namespace SFO { - - - class CursorChangeClient - { - public: - /// \brief Tell the client that the cursor has changed, giving the - /// name of the cursor we changed to ("arrow", "ibeam", etc) - /// \return Whether the client is interested in more information about the cursor - virtual bool cursorChanged(const std::string &name) = 0; - - /// \brief Follow up a cursorChanged() call with enough info to create an SDL cursor. - virtual void receiveCursorInfo(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) = 0; - - /// \brief Tell the client when the cursor visibility changed - virtual void cursorVisible(bool visible) = 0; - }; - - class InputWrapper : - public CursorChangeClient + class InputWrapper { public: InputWrapper(Ogre::RenderWindow* window); - virtual ~InputWrapper(); + ~InputWrapper(); void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; } void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; } @@ -51,10 +30,6 @@ namespace SFO bool getMouseRelative() { return mMouseRelative; } void setGrabPointer(bool grab); - virtual bool cursorChanged(const std::string &name); - virtual void receiveCursorInfo(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); - virtual void cursorVisible(bool visible); - OIS::KeyCode sdl2OISKeyCode(SDL_Keycode code); void warpMouse(int x, int y); @@ -66,9 +41,6 @@ namespace SFO void _wrapMousePointer(const SDL_MouseMotionEvent &evt); MouseMotionEvent _packageMouseMotion(const SDL_Event& evt); - void _createCursorFromResource(const std::string &name, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); - void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); - void _handleKeyPress(SDL_KeyboardEvent& evt); Uint32 _UTF8ToUTF32(const unsigned char *buf); void _setupOISKeys(); @@ -80,9 +52,6 @@ namespace SFO typedef boost::unordered_map KeyMap; KeyMap mKeyMap; - typedef std::map CursorMap; - CursorMap mCursorMap; - Uint16 mWarpX; Uint16 mWarpY; bool mWarpCompensate;