extract cursor management to a separate class, have windowmanager communicate with it. Initialize SDL during engine start

actorid
Jordan Milne 12 years ago
parent b746e7842f
commit 5a6589af01

@ -36,6 +36,8 @@
#include "mwmechanics/mechanicsmanagerimp.hpp" #include "mwmechanics/mechanicsmanagerimp.hpp"
#include "SDL2/SDL.h"
void OMW::Engine::executeLocalScripts() 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")) else if (boost::filesystem::exists(mCfgMgr.getGlobalPath().string() + "/transparency-overrides.cfg"))
nifOverrides.loadTransparencyOverrides(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; return settingspath;
} }
@ -322,6 +327,16 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
loadBSA(); 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) // cursor replacer (converts the cursor from the bsa so they can be used by mygui)
MWGui::CursorReplace replacer; MWGui::CursorReplace replacer;

@ -57,7 +57,7 @@ namespace MWGui
namespace SFO namespace SFO
{ {
class CursorChangeClient; class CursorManager;
} }
namespace MWBase namespace MWBase
@ -243,8 +243,6 @@ namespace MWBase
virtual void startTraining(MWWorld::Ptr actor) = 0; virtual void startTraining(MWWorld::Ptr actor) = 0;
virtual const Translation::Storage& getTranslationDataStorage() const = 0; virtual const Translation::Storage& getTranslationDataStorage() const = 0;
virtual void setCursorChangeClient(SFO::CursorChangeClient* client) = 0;
}; };
} }

@ -11,7 +11,7 @@
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
#include <openengine/gui/manager.hpp> #include <openengine/gui/manager.hpp>
#include <extern/sdl4ogre/sdlinputwrapper.hpp> #include <extern/sdl4ogre/sdlcursormanager.hpp>
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
#include <components/translation/translation.hpp> #include <components/translation/translation.hpp>
@ -115,7 +115,8 @@ WindowManager::WindowManager(
, mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI"))
, mHudEnabled(true) , mHudEnabled(true)
, mTranslationDataStorage (translationDataStorage) , mTranslationDataStorage (translationDataStorage)
, mCursorChangeClient(NULL) , mCursorManager(NULL)
, mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI"))
{ {
// Set up the GUI system // Set up the GUI system
@ -190,9 +191,6 @@ WindowManager::WindowManager(
mInputBlocker = mGui->createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Default,"Windows",""); mInputBlocker = mGui->createWidget<MyGUI::Widget>("",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 // The HUD is always on
mHud->setVisible(true); mHud->setVisible(true);
@ -212,6 +210,13 @@ WindowManager::WindowManager(
unsetSelectedSpell(); unsetSelectedSpell();
unsetSelectedWeapon(); 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 // Set up visibility
updateVisible(); updateVisible();
} }
@ -252,6 +257,7 @@ WindowManager::~WindowManager()
cleanupGarbage(); cleanupGarbage();
delete mGuiManager; delete mGuiManager;
delete mCursorManager;
} }
void WindowManager::cleanupGarbage() void WindowManager::cleanupGarbage()
@ -740,15 +746,30 @@ void WindowManager::setSpellVisibility(bool visible)
mHud->setEffectVisible (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) void WindowManager::setCursorVisible(bool visible)
{ {
if(visible == mCursorVisible) if(mCursorVisible == visible)
return; return;
mCursorVisible = visible; mCursorVisible = visible;
mCursorManager->cursorVisibilityChange(visible);
if(mCursorChangeClient != NULL) if(!mUseHardwareCursors)
mCursorChangeClient->cursorVisible(visible); MyGUI::PointerManager::getInstance().setVisible(visible);
} }
void WindowManager::setDragDrop(bool dragDrop) 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) void WindowManager::onCursorChange(const std::string &name)
{ {
//we have no client, don't care. //the cursor manager doesn't want any more info about this cursor
if(!mCursorChangeClient) if(!mCursorManager->cursorChanged(name))
return;
//the client doesn't want any more info about this cursor
if(!mCursorChangeClient->cursorChanged(name))
return; return;
//See if we can get the information we need out of the cursor resource //See if we can get the information we need out of the cursor resource
ResourceImageSetPointerFix* imgSetPtr = dynamic_cast<ResourceImageSetPointerFix*>(MyGUI::PointerManager::getInstance().getByName(name)); ResourceImageSetPointerFix* imgSetPtr = dynamic_cast<ResourceImageSetPointerFix*>(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); 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()) if(!tex.isNull())
{ {
Uint8 size_x = imgSetPtr->getSize().width; 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_x = imgSetPtr->getHotSpot().left;
Uint8 hotspot_y = imgSetPtr->getHotSpot().top; 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")); mHud->setFpsLevel(Settings::Manager::getInt("fps", "HUD"));
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
setUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI"));
bool changeRes = false; bool changeRes = false;
for (Settings::CategorySettingVector::const_iterator it = changed.begin(); for (Settings::CategorySettingVector::const_iterator it = changed.begin();

@ -50,7 +50,7 @@ namespace OEngine
namespace SFO namespace SFO
{ {
class CursorChangeClient; class CursorManager;
} }
namespace MWGui namespace MWGui
@ -233,8 +233,6 @@ namespace MWGui
virtual const Translation::Storage& getTranslationDataStorage() const; virtual const Translation::Storage& getTranslationDataStorage() const;
virtual void setCursorChangeClient(SFO::CursorChangeClient* client);
private: private:
OEngine::GUI::MyGUIManager *mGuiManager; OEngine::GUI::MyGUIManager *mGuiManager;
HUD *mHud; HUD *mHud;
@ -290,7 +288,7 @@ namespace MWGui
MyGUI::Gui *mGui; // Gui MyGUI::Gui *mGui; // Gui
std::vector<GuiMode> mGuiModes; std::vector<GuiMode> mGuiModes;
SFO::CursorChangeClient* mCursorChangeClient; SFO::CursorManager* mCursorManager;
std::vector<OEngine::GUI::Layout*> mGarbageDialogs; std::vector<OEngine::GUI::Layout*> mGarbageDialogs;
void cleanupGarbage(); void cleanupGarbage();
@ -315,6 +313,9 @@ namespace MWGui
void onDialogueWindowBye(); void onDialogueWindowBye();
bool mUseHardwareCursors;
void setUseHardwareCursors(bool use);
/** /**
* Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, * 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 * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result

@ -13,6 +13,7 @@
#include <MyGUI_RenderManager.h> #include <MyGUI_RenderManager.h>
#include <MyGUI_Widget.h> #include <MyGUI_Widget.h>
#include <MyGUI_Button.h> #include <MyGUI_Button.h>
#include <MyGUI_PointerManager.h>
#include <openengine/ogre/renderer.hpp> #include <openengine/ogre/renderer.hpp>
@ -67,8 +68,6 @@ namespace MWInput
mInputManager->setKeyboardEventCallback (this); mInputManager->setKeyboardEventCallback (this);
mInputManager->setWindowEventCallback(this); mInputManager->setWindowEventCallback(this);
mWindows.setCursorChangeClient(mInputManager);
std::string file = userFileExists ? userFile : ""; std::string file = userFileExists ? userFile : "";
mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last); mInputBinder = new ICS::InputControlSystem(file, true, this, NULL, A_Last);
@ -225,6 +224,9 @@ namespace MWInput
bool was_relative = mInputManager->getMouseRelative(); bool was_relative = mInputManager->getMouseRelative();
bool is_relative = !mWindows.isGuiMode(); 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 // don't keep the pointer away from the window edge in gui mode
// stop using raw mouse motions and switch to system cursor movements // stop using raw mouse motions and switch to system cursor movements
mInputManager->setMouseRelative(is_relative); mInputManager->setMouseRelative(is_relative);
@ -235,9 +237,6 @@ namespace MWInput
{ {
mInputManager->warpMouse(mMouseX, mMouseY); mInputManager->warpMouse(mMouseX, mMouseY);
} }
//we let the mouse escape in the main menu
mInputManager->setGrabPointer(!main_menu);
} }
// Disable movement in Gui mode // Disable movement in Gui mode

@ -4,9 +4,15 @@ set(SDL4OGRE_LIBRARY "sdl4ogre")
set(SDL4OGRE_SOURCE_FILES set(SDL4OGRE_SOURCE_FILES
sdlinputwrapper.cpp 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}) link_directories(${CMAKE_CURRENT_BINARY_DIR})

@ -0,0 +1,35 @@
#ifndef _SDL4OGRE_CURSOR_MANAGER_H
#define _SDL4OGRE_CURSOR_MANAGER_H
#include "SDL2/SDL_types.h"
#include <string>
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

@ -0,0 +1,189 @@
#include "sdlcursormanager.hpp"
#include <OgreHardwarePixelBuffer.h>
#include <OgreRoot.h>
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;
}
}
}

@ -0,0 +1,44 @@
#ifndef _SDL4OGRE_CURSORMANAGER_H
#define _SDL4OGRE_CURSORMANAGER_H
#include "SDL.h"
#include "cursormanager.hpp"
#include <map>
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<std::string, SDL_Cursor*> CursorMap;
CursorMap mCursorMap;
SDL_Cursor* mDebugCursor;
std::string mCurrentCursor;
bool mEnabled;
bool mInitialized;
bool mCursorVisible;
bool mDebug;
};
}
#endif

@ -3,7 +3,6 @@
#include <OgrePlatform.h> #include <OgrePlatform.h>
#include <OgreRoot.h> #include <OgreRoot.h>
#include <OgreHardwarePixelBuffer.h>
#include <cstdint> #include <cstdint>
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
@ -28,8 +27,8 @@ namespace SFO
mMouseY(0), mMouseY(0),
mMouseX(0) mMouseX(0)
{ {
_start();
_setupOISKeys(); _setupOISKeys();
_start();
} }
InputWrapper::~InputWrapper() InputWrapper::~InputWrapper()
@ -38,82 +37,60 @@ namespace SFO
SDL_DestroyWindow(mSDLWindow); SDL_DestroyWindow(mSDLWindow);
mSDLWindow = NULL; 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_StopTextInput();
SDL_Quit(); SDL_Quit();
} }
bool InputWrapper::_start() bool InputWrapper::_start()
{ {
Uint32 flags = SDL_INIT_VIDEO; //get the HWND from ogre's renderwindow
if(SDL_WasInit(flags) == 0) 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 //wrap our own event handler around ogre's
//might this be related to http://bugzilla.libsdl.org/show_bug.cgi?id=748 ? mSDLWindow = SDL_CreateWindowFrom((void*)windowHnd);
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
if(SDL_Init(SDL_INIT_VIDEO) != 0)
return false;
//wrap our own event handler around ogre's if(mSDLWindow == NULL)
mSDLWindow = SDL_CreateWindowFrom((void*)windowHnd); return false;
if(mSDLWindow == NULL)
return false;
//without this SDL will take ownership of the window and iconify it when //without this SDL will take ownership of the window and iconify it when
//we alt-tab away. //we alt-tab away.
SDL_SetWindowFullscreen(mSDLWindow, 0); SDL_SetWindowFullscreen(mSDLWindow, 0);
//translate our keypresses into text //translate our keypresses into text
SDL_StartTextInput(); SDL_StartTextInput();
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX #if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
//linux-specific event-handling fixups //linux-specific event-handling fixups
//see http://bugzilla.libsdl.org/show_bug.cgi?id=730 //see http://bugzilla.libsdl.org/show_bug.cgi?id=730
SDL_SysWMinfo wm_info; SDL_SysWMinfo wm_info;
SDL_VERSION(&wm_info.version); SDL_VERSION(&wm_info.version);
if(SDL_GetWindowWMInfo(mSDLWindow,&wm_info)) if(SDL_GetWindowWMInfo(mSDLWindow,&wm_info))
{ {
Display* display = wm_info.info.x11.display; Display* display = wm_info.info.x11.display;
Window w = wm_info.info.x11.window; Window w = wm_info.info.x11.window;
// Set the input hints so we get keyboard input // Set the input hints so we get keyboard input
XWMHints *wmhints = XAllocWMHints(); XWMHints *wmhints = XAllocWMHints();
if (wmhints) { if (wmhints) {
wmhints->input = True; wmhints->input = True;
wmhints->flags = InputHint; wmhints->flags = InputHint;
XSetWMHints(display, w, wmhints); XSetWMHints(display, w, wmhints);
XFree(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);
}
//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; return true;
} }
@ -209,10 +186,11 @@ namespace SFO
//eep, wrap the pointer manually if the input driver doesn't support //eep, wrap the pointer manually if the input driver doesn't support
//relative positioning natively //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 //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); 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 /// \brief Internal method for ignoring relative motions as a side effect
/// of warpMouse() /// of warpMouse()
bool InputWrapper::_handleWarpMotion(const SDL_MouseMotionEvent& evt) bool InputWrapper::_handleWarpMotion(const SDL_MouseMotionEvent& evt)

@ -1,7 +1,8 @@
#ifndef _MWINPUT_SDLINPUTWRAPPER_H #ifndef _SDL4OGRE_SDLINPUTWRAPPER_H
#define _MWINPUT_SDLINPUTWRAPPER_H #define _SDL4OGRE_SDLINPUTWRAPPER_H
#include "SDL2/SDL_events.h" #include "SDL2/SDL_events.h"
#include <OGRE/OgreRenderWindow.h> #include <OGRE/OgreRenderWindow.h>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
@ -9,36 +10,14 @@
#include "events.h" #include "events.h"
namespace Ogre
{
class Texture;
}
namespace SFO namespace SFO
{ {
class InputWrapper
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
{ {
public: public:
InputWrapper(Ogre::RenderWindow* window); InputWrapper(Ogre::RenderWindow* window);
virtual ~InputWrapper(); ~InputWrapper();
void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; } void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; }
void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; } void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; }
@ -51,10 +30,6 @@ namespace SFO
bool getMouseRelative() { return mMouseRelative; } bool getMouseRelative() { return mMouseRelative; }
void setGrabPointer(bool grab); 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); OIS::KeyCode sdl2OISKeyCode(SDL_Keycode code);
void warpMouse(int x, int y); void warpMouse(int x, int y);
@ -66,9 +41,6 @@ namespace SFO
void _wrapMousePointer(const SDL_MouseMotionEvent &evt); void _wrapMousePointer(const SDL_MouseMotionEvent &evt);
MouseMotionEvent _packageMouseMotion(const SDL_Event& 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); void _handleKeyPress(SDL_KeyboardEvent& evt);
Uint32 _UTF8ToUTF32(const unsigned char *buf); Uint32 _UTF8ToUTF32(const unsigned char *buf);
void _setupOISKeys(); void _setupOISKeys();
@ -80,9 +52,6 @@ namespace SFO
typedef boost::unordered_map<SDL_Keycode, OIS::KeyCode> KeyMap; typedef boost::unordered_map<SDL_Keycode, OIS::KeyCode> KeyMap;
KeyMap mKeyMap; KeyMap mKeyMap;
typedef std::map<std::string, SDL_Cursor*> CursorMap;
CursorMap mCursorMap;
Uint16 mWarpX; Uint16 mWarpX;
Uint16 mWarpY; Uint16 mWarpY;
bool mWarpCompensate; bool mWarpCompensate;

Loading…
Cancel
Save