From 6164e5bae632015478ed8120fac599390bf4c9a0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 29 Jul 2013 02:32:08 +0200 Subject: [PATCH] Restored window resizing --- apps/openmw/mwbase/windowmanager.hpp | 2 + apps/openmw/mwgui/settingswindow.cpp | 8 -- apps/openmw/mwgui/windowmanagerimp.cpp | 52 +++----- apps/openmw/mwgui/windowmanagerimp.hpp | 2 + apps/openmw/mwinput/inputmanagerimp.cpp | 20 ++- apps/openmw/mwinput/inputmanagerimp.hpp | 5 +- apps/openmw/mwrender/renderingmanager.cpp | 52 ++++---- apps/openmw/mwrender/renderingmanager.hpp | 5 +- apps/openmw/mwworld/weather.cpp | 3 +- extern/sdl4ogre/CMakeLists.txt | 1 + extern/sdl4ogre/events.h | 6 +- extern/sdl4ogre/sdlinputwrapper.cpp | 76 ++++++++++-- extern/sdl4ogre/sdlinputwrapper.hpp | 6 +- extern/sdl4ogre/sdlwindowhelper.cpp | 115 ++++++++++++++++++ extern/sdl4ogre/sdlwindowhelper.hpp | 31 +++++ libs/openengine/gui/manager.cpp | 5 + libs/openengine/gui/manager.hpp | 2 + libs/openengine/ogre/renderer.cpp | 141 ++-------------------- libs/openengine/ogre/renderer.hpp | 20 +-- 19 files changed, 307 insertions(+), 245 deletions(-) create mode 100644 extern/sdl4ogre/sdlwindowhelper.cpp create mode 100644 extern/sdl4ogre/sdlwindowhelper.hpp diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 36d4ab8bb5..d85c28fe24 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -237,6 +237,8 @@ namespace MWBase virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0; + virtual void windowResized(int x, int y) = 0; + virtual void executeInConsole (const std::string& path) = 0; virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total) = 0; diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 8443aaf30c..eada151a43 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -272,15 +272,12 @@ namespace MWGui if (index == MyGUI::ITEM_NONE) return; - /* ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); dialog->open("#{sNotifyMessage67}"); dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionAccept); dialog->eventCancelClicked.clear(); dialog->eventCancelClicked += MyGUI::newDelegate(this, &SettingsWindow::onResolutionCancel); - */ - onResolutionAccept(); } void SettingsWindow::onResolutionAccept() @@ -293,9 +290,6 @@ namespace MWGui Settings::Manager::setInt("resolution y", "Video", resY); apply(); - - MWBase::Environment::get().getWindowManager()-> - messageBox("New resolution will be applied after a restart", std::vector()); } void SettingsWindow::onResolutionCancel() @@ -364,8 +358,6 @@ namespace MWGui { Settings::Manager::setBool("fullscreen", "Video", newState); apply(); - MWBase::Environment::get().getWindowManager()-> - messageBox("Fullscreen will be applied after a restart", std::vector()); } } else if (_sender == mVSyncButton) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 38bc0481d4..6fcc19a477 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -877,49 +877,31 @@ namespace MWGui setUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")); - //bool changeRes = false; - bool windowRecreated = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it) { - /*if (it->first == "Video" && ( - it->second == "resolution x" - || it->second == "resolution y")) - { - changeRes = true; - }*/ - if (it->first == "Video" && it->second == "vsync") - windowRecreated = true; - else if (it->first == "HUD" && it->second == "crosshair") + if (it->first == "HUD" && it->second == "crosshair") mCrosshairEnabled = Settings::Manager::getBool ("crosshair", "HUD"); else if (it->first == "GUI" && it->second == "subtitles") mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI"); } + } - /* - if (changeRes) - { - int x = Settings::Manager::getInt("resolution x", "Video"); - int y = Settings::Manager::getInt("resolution y", "Video"); - mHud->onResChange(x, y); - mConsole->onResChange(x, y); - mMenu->onResChange(x, y); - mSettingsWindow->center(); - mAlchemyWindow->center(); - mScrollWindow->center(); - mBookWindow->center(); - mQuickKeysMenu->center(); - mSpellBuyingWindow->center(); - mLoadingScreen->onResChange (x,y); - mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); - mInputBlocker->setSize(MyGUI::IntSize(x,y)); - } - */ - if (windowRecreated) - { - mGuiManager->updateWindow (mRendering->getWindow ()); - mLoadingScreen->updateWindow (mRendering->getWindow ()); - } + void WindowManager::windowResized(int x, int y) + { + mHud->onResChange(x, y); + mConsole->onResChange(x, y); + mMenu->onResChange(x, y); + mSettingsWindow->center(); + mAlchemyWindow->center(); + mScrollWindow->center(); + mBookWindow->center(); + mQuickKeysMenu->center(); + mSpellBuyingWindow->center(); + mLoadingScreen->onResChange (x,y); + mDragAndDrop->mDragAndDropWidget->setSize(MyGUI::IntSize(x, y)); + mInputBlocker->setSize(MyGUI::IntSize(x,y)); + mGuiManager->windowResized(); } void WindowManager::pushGuiMode(GuiMode mode) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 42f2f4dc27..6395b1bb57 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -225,6 +225,8 @@ namespace MWGui virtual void processChangedSettings(const Settings::CategorySettingVector& changed); + virtual void windowResized(int x, int y); + virtual void executeInConsole (const std::string& path); virtual void setLoadingProgress (const std::string& stage, int depth, int current, int total); diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 0addc7daf3..eae5d7d193 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -385,7 +385,7 @@ namespace MWInput if (mControlSwitch["playerviewswitch"]) { // work around preview mode toggle when pressing Alt+Tab - if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(KMOD_ALT)) { + if (actionIsActive(A_TogglePOV) && !mInputManager->isModifierHeld(SDL_Keymod(KMOD_ALT))) { if (mPreviewPOVDelay <= 0.5 && (mPreviewPOVDelay += dt) > 0.5) { @@ -434,13 +434,9 @@ namespace MWInput void InputManager::processChangedSettings(const Settings::CategorySettingVector& changed) { - bool changeRes = false; for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it) { - if (it->first == "Video" && (it->second == "resolution x" || it->second == "resolution y")) - changeRes = true; - if (it->first == "Input" && it->second == "invert y axis") mInvertY = Settings::Manager::getBool("invert y axis", "Input"); @@ -451,9 +447,6 @@ namespace MWInput mUISensitivity = Settings::Manager::getFloat("ui sensitivity", "Input"); } - - if (changeRes) - adjustMouseRegion(Settings::Manager::getInt("resolution x", "Video"), Settings::Manager::getInt("resolution y", "Video")); } bool InputManager::getControlSwitch (const std::string& sw) @@ -617,15 +610,18 @@ namespace MWInput return true; } - bool InputManager::windowFocusChange(bool have_focus) + void InputManager::windowFocusChange(bool have_focus) { - return true; } - bool InputManager::windowVisibilityChange(bool visible) + void InputManager::windowVisibilityChange(bool visible) { //TODO: Pause game? - return true; + } + + void InputManager::windowResized(int x, int y) + { + mOgre.windowResized(x,y); } void InputManager::toggleMainMenu() diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 0c7940fd65..ef7ef75a89 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -94,8 +94,9 @@ namespace MWInput virtual bool mouseReleased( const SDL_MouseButtonEvent &arg, Uint8 id ); virtual bool mouseMoved( const SFO::MouseMotionEvent &arg ); - virtual bool windowVisibilityChange( bool visible ); - virtual bool windowFocusChange( bool have_focus ); + virtual void windowVisibilityChange( bool visible ); + virtual void windowFocusChange( bool have_focus ); + virtual void windowResized (int x, int y); virtual void channelChanged(ICS::Channel* channel, float currentValue, float previousValue); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index de4eafd6d9..4a9de259f7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -16,6 +16,8 @@ #include #include +#include + #include #include @@ -77,9 +79,9 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b } mRendering.createScene("PlayerCam", Settings::Manager::getFloat("field of view", "General"), 5); - mRendering.setWindowEventListener(this); mRendering.getWindow()->addListener(this); + mRendering.setWindowListener(this); mCompositors = new Compositors(mRendering.getViewport()); @@ -186,7 +188,6 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b RenderingManager::~RenderingManager () { mRendering.getWindow()->removeListener(this); - mRendering.removeWindowEventListener(this); delete mPlayerAnimation; delete mCamera; @@ -718,7 +719,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { - //bool changeRes = false; + bool changeRes = false; bool rebuild = false; // rebuild static geometry (necessary after any material changes) for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) @@ -732,11 +733,11 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec if (!MWBase::Environment::get().getWorld()->isCellExterior() && !MWBase::Environment::get().getWorld()->isCellQuasiExterior()) configureFog(*MWBase::Environment::get().getWorld()->getPlayer().getPlayer().getCell()); } - /*else if (it->first == "Video" && ( + else if (it->first == "Video" && ( it->second == "resolution x" || it->second == "resolution y" || it->second == "fullscreen")) - changeRes = true;*/ + changeRes = true; else if (it->second == "field of view" && it->first == "General") mRendering.setFov(Settings::Manager::getFloat("field of view", "General")); else if ((it->second == "texture filtering" && it->first == "General") @@ -790,24 +791,31 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec } } - /* if (changeRes) { unsigned int x = Settings::Manager::getInt("resolution x", "Video"); unsigned int y = Settings::Manager::getInt("resolution y", "Video"); + bool fullscreen = Settings::Manager::getBool("fullscreen", "Video"); + + SDL_Window* window = mRendering.getSDLWindow(); + + SDL_SetWindowFullscreen(window, 0); - SDL_SetWindowFullscreen(mRendering.getSDLWindow(), 0); + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MAXIMIZED) + SDL_RestoreWindow(window); - if (x != mRendering.getWindow()->getWidth() || y != mRendering.getWindow()->getHeight()) + if (fullscreen) { - SDL_SetWindowSize(mRendering.getSDLWindow(), x, y); - mRendering.getWindow()->resize(x, y); + SDL_DisplayMode mode; + SDL_GetWindowDisplayMode(window, &mode); + mode.w = x; + mode.h = y; + SDL_SetWindowDisplayMode(window, &mode); + SDL_SetWindowFullscreen(window, fullscreen); } - - SDL_SetWindowFullscreen(mRendering.getSDLWindow(), Settings::Manager::getBool("fullscreen", "Video") ? SDL_WINDOW_FULLSCREEN : 0); - //mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); + else + SDL_SetWindowSize(window, x, y); } - */ mWater->processChangedSettings(settings); @@ -825,24 +833,14 @@ void RenderingManager::setMenuTransparency(float val) tex->getBuffer()->unlock(); } -void RenderingManager::windowResized(Ogre::RenderWindow* rw) +void RenderingManager::windowResized(int x, int y) { - Settings::Manager::setInt("resolution x", "Video", rw->getWidth()); - Settings::Manager::setInt("resolution y", "Video", rw->getHeight()); - mRendering.adjustViewport(); mCompositors->recreate(); - mVideoPlayer->setResolution (rw->getWidth(), rw->getHeight()); - - const Settings::CategorySettingVector& changed = Settings::Manager::apply(); - MWBase::Environment::get().getInputManager()->processChangedSettings(changed); - MWBase::Environment::get().getWindowManager()->processChangedSettings(changed); -} + mVideoPlayer->setResolution (x, y); -void RenderingManager::windowClosed(Ogre::RenderWindow* rw) -{ - Ogre::Root::getSingleton ().queueEndRendering (); + MWBase::Environment::get().getWindowManager()->windowResized(x,y); } void RenderingManager::applyCompositors() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index cdcde8246e..8b55d90bfc 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -50,7 +50,7 @@ namespace MWRender class VideoPlayer; class Animation; -class RenderingManager: private RenderingInterface, public Ogre::WindowEventListener, public Ogre::RenderTargetListener +class RenderingManager: private RenderingInterface, public Ogre::RenderTargetListener, public OEngine::Render::WindowSizeListener { private: virtual MWRender::Objects& getObjects(); @@ -204,8 +204,7 @@ public: void frameStarted(float dt); protected: - virtual void windowResized(Ogre::RenderWindow* rw); - virtual void windowClosed(Ogre::RenderWindow* rw); + virtual void windowResized(int x, int y); private: sh::Factory* mFactory; diff --git a/apps/openmw/mwworld/weather.cpp b/apps/openmw/mwworld/weather.cpp index c8283fe0db..587b7847bc 100644 --- a/apps/openmw/mwworld/weather.cpp +++ b/apps/openmw/mwworld/weather.cpp @@ -551,7 +551,6 @@ void WeatherManager::stopSounds(bool stopAll) Ogre::String WeatherManager::nextWeather(const ESM::Region* region) const { - const MWBase::World *world = MWBase::Environment::get().getWorld(); std::vector probability; RegionModMap::const_iterator iter = mRegionMods.find(Misc::StringUtils::lowerCase(region->mId)); @@ -581,7 +580,7 @@ Ogre::String WeatherManager::nextWeather(const ESM::Region* region) const int chance = (rand() % 100) + 1; // 1..100 int sum = 0; - int i = 0; + unsigned int i = 0; for (; i < probability.size(); ++i) { sum += probability[i]; diff --git a/extern/sdl4ogre/CMakeLists.txt b/extern/sdl4ogre/CMakeLists.txt index 493d1ce476..5b31974e5f 100644 --- a/extern/sdl4ogre/CMakeLists.txt +++ b/extern/sdl4ogre/CMakeLists.txt @@ -5,6 +5,7 @@ set(SDL4OGRE_LIBRARY "sdl4ogre") set(SDL4OGRE_SOURCE_FILES sdlinputwrapper.cpp sdlcursormanager.cpp + sdlwindowhelper.cpp ) set(SDL4OGRE_HEADER_FILES diff --git a/extern/sdl4ogre/events.h b/extern/sdl4ogre/events.h index 13f8b31011..e6e8434cb9 100644 --- a/extern/sdl4ogre/events.h +++ b/extern/sdl4ogre/events.h @@ -65,10 +65,12 @@ public: virtual ~WindowListener() {} /** @remarks The window's visibility changed */ - virtual bool windowVisibilityChange( bool visible ) = 0; + virtual void windowVisibilityChange( bool visible ) {}; /** @remarks The window got / lost input focus */ - virtual bool windowFocusChange( bool have_focus ) = 0; + virtual void windowFocusChange( bool have_focus ) {} + + virtual void windowResized (int x, int y) {} }; } diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index 89dc650650..a30f10d6a3 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -4,13 +4,6 @@ #include #include -/* -#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX -# include -# include -# include -#endif -*/ namespace SFO { @@ -19,7 +12,6 @@ namespace SFO InputWrapper::InputWrapper(SDL_Window* window, Ogre::RenderWindow* ogreWindow) : mSDLWindow(window), mOgreWindow(ogreWindow), - mOwnWindow(false), mWarpCompensate(false), mMouseRelative(false), mGrabPointer(false), @@ -27,14 +19,18 @@ namespace SFO mMouseZ(0), mMouseY(0), mMouseX(0), - mMouseInWindow(true) + mMouseInWindow(true), + mJoyListener(NULL), + mKeyboardListener(NULL), + mMouseListener(NULL), + mWindowListener(NULL) { _setupOISKeys(); } InputWrapper::~InputWrapper() { - if(mSDLWindow != NULL && mOwnWindow) + if(mSDLWindow != NULL) SDL_DestroyWindow(mSDLWindow); mSDLWindow = NULL; } @@ -76,6 +72,25 @@ namespace SFO case SDL_TEXTINPUT: mKeyboardListener->textInput(evt.text); break; + case SDL_JOYAXISMOTION: + if (mJoyListener) + mJoyListener->axisMoved(evt.jaxis, evt.jaxis.axis); + break; + case SDL_JOYBUTTONDOWN: + if (mJoyListener) + mJoyListener->buttonPressed(evt.jbutton, evt.jbutton.button); + break; + case SDL_JOYBUTTONUP: + if (mJoyListener) + mJoyListener->buttonReleased(evt.jbutton, evt.jbutton.button); + break; + case SDL_JOYDEVICEADDED: + //SDL_JoystickOpen(evt.jdevice.which); + //std::cout << "Detected a new joystick: " << SDL_JoystickNameForIndex(evt.jdevice.which) << std::endl; + break; + case SDL_JOYDEVICEREMOVED: + //std::cout << "A joystick has been removed" << std::endl; + break; case SDL_WINDOWEVENT: handleWindowEvent(evt); break; @@ -100,25 +115,62 @@ namespace SFO SDL_SetWindowGrab(mSDLWindow, SDL_FALSE); SDL_SetRelativeMouseMode(SDL_FALSE); break; - case SDL_WINDOWEVENT_RESIZED: + case SDL_WINDOWEVENT_SIZE_CHANGED: + int w,h; + SDL_GetWindowSize(mSDLWindow, &w, &h); + // TODO: Fix Ogre to handle this more consistently +#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + mOgreWindow->windowMovedOrResized(); +#else + mOgreWindow->resize(w, h); +#endif + if (mWindowListener) + mWindowListener->windowResized(evt.window.data1, evt.window.data2); + + case SDL_WINDOWEVENT_RESIZED: + // TODO: Fix Ogre to handle this more consistently + #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 + mOgreWindow->windowMovedOrResized(); + #else + mOgreWindow->resize(evt.window.data1, evt.window.data2); + #endif + if (mWindowListener) + mWindowListener->windowResized(evt.window.data1, evt.window.data2); + break; + case SDL_WINDOWEVENT_FOCUS_GAINED: + if (mWindowListener) + mWindowListener->windowFocusChange(true); + break; case SDL_WINDOWEVENT_FOCUS_LOST: + if (mWindowListener) + mWindowListener->windowFocusChange(false); + break; case SDL_WINDOWEVENT_CLOSE: break; case SDL_WINDOWEVENT_SHOWN: mOgreWindow->setVisible(true); + if (mWindowListener) + mWindowListener->windowVisibilityChange(true); break; case SDL_WINDOWEVENT_HIDDEN: mOgreWindow->setVisible(false); + if (mWindowListener) + mWindowListener->windowVisibilityChange(false); break; } } - bool InputWrapper::isModifierHeld(int mod) + bool InputWrapper::isModifierHeld(SDL_Keymod mod) { return SDL_GetModState() & mod; } + bool InputWrapper::isKeyDown(SDL_Scancode key) + { + return SDL_GetKeyboardState(NULL)[key]; + } + /// \brief Moves the mouse to the specified point within the viewport void InputWrapper::warpMouse(int x, int y) { diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index 08b329925f..66bf60c7c3 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -22,9 +22,11 @@ namespace SFO void setMouseEventCallback(MouseListener* listen) { mMouseListener = listen; } void setKeyboardEventCallback(KeyListener* listen) { mKeyboardListener = listen; } void setWindowEventCallback(WindowListener* listen) { mWindowListener = listen; } + void setJoyEventCallback(JoyListener* listen) { mJoyListener = listen; } void capture(); - bool isModifierHeld(int mod); + bool isModifierHeld(SDL_Keymod mod); + bool isKeyDown(SDL_Scancode key); void setMouseRelative(bool relative); bool getMouseRelative() { return mMouseRelative; } @@ -47,6 +49,7 @@ namespace SFO SFO::MouseListener* mMouseListener; SFO::KeyListener* mKeyboardListener; SFO::WindowListener* mWindowListener; + SFO::JoyListener* mJoyListener; typedef boost::unordered_map KeyMap; KeyMap mKeyMap; @@ -66,7 +69,6 @@ namespace SFO SDL_Window* mSDLWindow; Ogre::RenderWindow* mOgreWindow; - bool mOwnWindow; }; } diff --git a/extern/sdl4ogre/sdlwindowhelper.cpp b/extern/sdl4ogre/sdlwindowhelper.cpp new file mode 100644 index 0000000000..14371c947d --- /dev/null +++ b/extern/sdl4ogre/sdlwindowhelper.cpp @@ -0,0 +1,115 @@ +#include "sdlwindowhelper.hpp" + +#include +#include + +#include +#include + +namespace SFO +{ + +SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, + const std::string& title, bool fullscreen, Ogre::NameValuePairList params) + : mSDLWindow(window) +{ + //get the native whnd + struct SDL_SysWMinfo wmInfo; + SDL_VERSION(&wmInfo.version); + + if (SDL_GetWindowWMInfo(mSDLWindow, &wmInfo) == -1) + throw std::runtime_error("Couldn't get WM Info!"); + + Ogre::String winHandle; + + switch (wmInfo.subsystem) + { +#ifdef WIN32 + case SDL_SYSWM_WINDOWS: + // Windows code + winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.win.window); + break; +#elif __MACOSX__ + case SDL_SYSWM_COCOA: + //required to make OGRE play nice with our window + params.insert(std::make_pair("macAPI", "cocoa")); + params.insert(std::make_pair("macAPICocoaUseNSView", "true")); + + winHandle = Ogre::StringConverter::toString(WindowContentViewHandle(wmInfo)); + break; +#else + case SDL_SYSWM_X11: + winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window); + break; +#endif + default: + throw std::runtime_error("Unexpected WM!"); + break; + } + + /// \todo externalWindowHandle is deprecated according to the source code. Figure out a way to get parentWindowHandle + /// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error. + params.insert(std::make_pair("externalWindowHandle", winHandle)); + + mWindow = Ogre::Root::getSingleton().createRenderWindow(title, w, h, fullscreen, ¶ms); +} + +void SDLWindowHelper::setWindowIcon(const std::string &name) +{ + Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().load(name, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); + if (texture.isNull()) + { + std::stringstream error; + error << "Window icon not found: " << name; + throw std::runtime_error(error.str()); + } + Ogre::Image image; + texture->convertToImage(image); + + SDL_Surface* surface = SDL_CreateRGBSurface(0,texture->getWidth(),texture->getHeight(),32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); + + //copy the Ogre texture to an SDL surface + for(size_t x = 0; x < texture->getWidth(); ++x) + { + for(size_t y = 0; y < texture->getHeight(); ++y) + { + Ogre::ColourValue clr = image.getColourAt(x, y, 0); + + //set the pixel on the SDL surface to the same value as the Ogre texture's + 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; + Uint32 pixel = SDL_MapRGBA(surface->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255); + 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; + } + } + } + + SDL_SetWindowIcon(mSDLWindow, surface); + SDL_FreeSurface(surface); +} + +} diff --git a/extern/sdl4ogre/sdlwindowhelper.hpp b/extern/sdl4ogre/sdlwindowhelper.hpp new file mode 100644 index 0000000000..834716b223 --- /dev/null +++ b/extern/sdl4ogre/sdlwindowhelper.hpp @@ -0,0 +1,31 @@ +#ifndef SDL4OGRE_SDLWINDOWHELPER_H +#define SDL4OGRE_SDLWINDOWHELPER_H + +#include + +namespace Ogre +{ + class RenderWindow; +} +struct SDL_Window; + +namespace SFO +{ + + /// @brief Creates an Ogre window from an SDL window and allows setting an Ogre texture as window icon + class SDLWindowHelper + { + public: + SDLWindowHelper (SDL_Window* window, int w, int h, const std::string& title, bool fullscreen, Ogre::NameValuePairList params); + void setWindowIcon(const std::string& name); + Ogre::RenderWindow* getWindow() { return mWindow; } + + private: + Ogre::RenderWindow* mWindow; + SDL_Window* mSDLWindow; + }; + +} + + +#endif diff --git a/libs/openengine/gui/manager.cpp b/libs/openengine/gui/manager.cpp index a0a4ab0aea..9fd57e2c15 100644 --- a/libs/openengine/gui/manager.cpp +++ b/libs/openengine/gui/manager.cpp @@ -612,6 +612,11 @@ void MyGUIManager::updateWindow (Ogre::RenderWindow *wnd) } } +void MyGUIManager::windowResized() +{ + mRenderManager->setActiveViewport(0); +} + void MyGUIManager::shutdown() { mGui->shutdown (); diff --git a/libs/openengine/gui/manager.hpp b/libs/openengine/gui/manager.hpp index 9535f2a24e..cca70dfcfe 100644 --- a/libs/openengine/gui/manager.hpp +++ b/libs/openengine/gui/manager.hpp @@ -43,6 +43,8 @@ namespace GUI void updateWindow (Ogre::RenderWindow* wnd); + void windowResized(); + void setup(Ogre::RenderWindow *wnd, Ogre::SceneManager *mgr, bool logging=false, const std::string& logDir = std::string("")); void shutdown(); diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index de090a0f1d..f0d6bdb0fa 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -3,7 +3,6 @@ #include "particles.hpp" #include -#include #include "OgreRoot.h" #include "OgreRenderWindow.h" @@ -19,6 +18,8 @@ #include +#include + #include #include #include @@ -54,9 +55,6 @@ void OgreRenderer::cleanup() delete mRoot; mRoot = NULL; - if (mWindowIconSurface) - SDL_FreeSurface(mWindowIconSurface); - // If we don't do this, the desktop resolution is not restored on exit SDL_SetWindowFullscreen(mSDLWindow, 0); @@ -237,25 +235,6 @@ void OgreRenderer::configure(const std::string &logPath, rs->setConfigOption ("RTT Preferred Mode", rttMode); } -void OgreRenderer::recreateWindow(const std::string &title, const WindowSettings &settings) -{ - Ogre::ColourValue viewportBG = mView->getBackgroundColour(); - - mRoot->destroyRenderTarget(mWindow); - NameValuePairList params; - params.insert(std::make_pair("title", title)); - params.insert(std::make_pair("FSAA", settings.fsaa)); - params.insert(std::make_pair("vsync", settings.vsync ? "true" : "false")); - - mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); - - // Create one viewport, entire window - mView = mWindow->addViewport(mCamera); - mView->setBackgroundColour(viewportBG); - - adjustViewport(); -} - void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings) { assert(mRoot); @@ -286,55 +265,14 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& settings.window_x, // width, in pixels settings.window_y, // height, in pixels SDL_WINDOW_SHOWN - | (settings.fullscreen ? SDL_WINDOW_FULLSCREEN : 0) + | (settings.fullscreen ? SDL_WINDOW_FULLSCREEN : 0) | SDL_WINDOW_RESIZABLE ); - //get the native whnd - struct SDL_SysWMinfo wmInfo; - SDL_VERSION(&wmInfo.version); - - if(SDL_FALSE == SDL_GetWindowWMInfo(mSDLWindow, &wmInfo)) - throw std::runtime_error("Couldn't get WM Info!"); - - Ogre::String winHandle; - - switch(wmInfo.subsystem) - { -#ifdef WIN32 - case SDL_SYSWM_WINDOWS: - // Windows code - winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.win.window); - break; -#elif __MACOSX__ - case SDL_SYSWM_COCOA: - //required to make OGRE play nice with our window - params.insert(std::make_pair("macAPI", "cocoa")); - params.insert(std::make_pair("macAPICocoaUseNSView", "true")); - - winHandle = Ogre::StringConverter::toString(WindowContentViewHandle(wmInfo)); - break; -#else - case SDL_SYSWM_X11: - winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.x11.window); - break; -#endif - default: - throw std::runtime_error("Unexpected WM!"); - break; - } - - /// \todo externalWindowHandle is deprecated according to the source code. Figure out a way to get parentWindowHandle - /// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error. - params.insert(std::make_pair("externalWindowHandle", winHandle)); - - mWindow = mRoot->createRenderWindow(title, settings.window_x, settings.window_y, settings.fullscreen, ¶ms); - - // Set the window icon + SFO::SDLWindowHelper helper(mSDLWindow, settings.window_x, settings.window_y, title, settings.fullscreen, params); if (settings.icon != "") - { - mWindowIconSurface = ogreTextureToSDLSurface(settings.icon); - SDL_SetWindowIcon(mSDLWindow, mWindowIconSurface); - } + helper.setWindowIcon(settings.icon); + mWindow = helper.getWindow(); + // create the semi-transparent black background texture used by the GUI. // has to be created in code with TU_DYNAMIC_WRITE_ONLY param @@ -380,73 +318,12 @@ void OgreRenderer::adjustViewport() } } -void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) -{ - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); -} - -void OgreRenderer::removeWindowEventListener(Ogre::WindowEventListener* listener) -{ - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); -} - void OgreRenderer::setFov(float fov) { mCamera->setFOVy(Degree(fov)); } -SDL_Surface* OgreRenderer::ogreTextureToSDLSurface(const std::string& name) +void OgreRenderer::windowResized(int x, int y) { - Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().load(name, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME); - if (texture.isNull()) - { - std::stringstream error; - error << "Window icon not found: " << name; - throw std::runtime_error(error.str()); - } - Ogre::Image image; - texture->convertToImage(image); - - SDL_Surface* surface = SDL_CreateRGBSurface(0,texture->getWidth(),texture->getHeight(),32,0xFF000000,0x00FF0000,0x0000FF00,0x000000FF); - - //copy the Ogre texture to an SDL surface - for(size_t x = 0; x < texture->getWidth(); ++x) - { - for(size_t y = 0; y < texture->getHeight(); ++y) - { - Ogre::ColourValue clr = image.getColourAt(x, y, 0); - - //set the pixel on the SDL surface to the same value as the Ogre texture's - 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; - Uint32 pixel = SDL_MapRGBA(surface->format, clr.r*255, clr.g*255, clr.b*255, clr.a*255); - 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; - } - } - } - return surface; + mWindowListener->windowResized(x,y); } diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index f4b38c52d8..9e83bf4f67 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -74,6 +74,12 @@ namespace OEngine class Fader; + class WindowSizeListener + { + public: + virtual void windowResized (int x, int y) = 0; + }; + class OgreRenderer { #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE @@ -83,7 +89,6 @@ namespace OEngine #endif Ogre::RenderWindow *mWindow; SDL_Window *mSDLWindow; - SDL_Surface *mWindowIconSurface; Ogre::SceneManager *mScene; Ogre::Camera *mCamera; Ogre::Viewport *mView; @@ -107,7 +112,7 @@ namespace OEngine std::vector mAffectorFactories; bool logging; - SDL_Surface* ogreTextureToSDLSurface(const std::string& name); + WindowSizeListener* mWindowListener; public: OgreRenderer() @@ -117,7 +122,7 @@ namespace OEngine , mScene(NULL) , mCamera(NULL) , mView(NULL) - , mWindowIconSurface(NULL) + , mWindowListener(NULL) #ifdef ENABLE_PLUGIN_CgProgramManager , mCgPlugin(NULL) #endif @@ -140,9 +145,6 @@ namespace OEngine ~OgreRenderer() { cleanup(); } - void setWindowEventListener(Ogre::WindowEventListener* listener); - void removeWindowEventListener(Ogre::WindowEventListener* listener); - /** Configure the renderer. This will load configuration files and set up the Root and logging classes. */ void configure( @@ -154,8 +156,6 @@ namespace OEngine /// Create a window with the given title void createWindow(const std::string &title, const WindowSettings& settings); - void recreateWindow (const std::string &title, const WindowSettings& settings); - /// Set up the scene manager, camera and viewport void createScene(const std::string& camName="Camera",// Camera name float fov=55, // Field of view angle @@ -181,6 +181,8 @@ namespace OEngine float getFPS(); + void windowResized(int x, int y); + /// Get the Root Ogre::Root *getRoot() { return mRoot; } @@ -202,6 +204,8 @@ namespace OEngine /// Viewport Ogre::Viewport *getViewport() { return mView; } + void setWindowListener(WindowSizeListener* listener) { mWindowListener = listener; } + void adjustViewport(); }; }