diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index 8293cbfa7..f69e1a152 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -39,6 +39,9 @@ namespace MWBase virtual int getNumActions() = 0; virtual void enableDetectingBindingMode (int action) = 0; virtual void resetToDefaultBindings() = 0; + + virtual void create () = 0; + virtual void destroy () = 0; }; } diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 343c96cec..75fc2b7a2 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -370,14 +370,10 @@ namespace MWGui apply(); } } - else if (_sender == mVSyncButton) - { - Settings::Manager::setBool("vsync", "Video", newState); - MWBase::Environment::get().getWindowManager()-> - messageBox("VSync will be applied after a restart", std::vector()); - } else { + if (_sender == mVSyncButton) + Settings::Manager::setBool("vsync", "Video", newState); if (_sender == mWaterShaderButton) Settings::Manager::setBool("shader", "Water", newState); else if (_sender == mRefractionButton) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 1f270df8b..95d221933 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -41,9 +41,11 @@ namespace MWInput , mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseY(ogre.getWindow()->getHeight ()/2.f) , mMouseWheel(0) - , mUserFile(userFile) , mDragDrop(false) , mGuiCursorEnabled(false) + , mDebug(debug) + , mUserFile(userFile) + , mUserFileExists(userFileExists) , mInvertY (Settings::Manager::getBool("invert y axis", "Input")) , mCameraSensitivity (Settings::Manager::getFloat("camera sensitivity", "Input")) , mUISensitivity (Settings::Manager::getFloat("ui sensitivity", "Input")) @@ -51,8 +53,15 @@ namespace MWInput , mUIYMultiplier (Settings::Manager::getFloat("ui y multiplier", "Input")) , mPreviewPOVDelay(0.f) , mTimeIdle(0.f) + , mCreated(false) + { + create(); + } + + + void InputManager::create() { - Ogre::RenderWindow* window = ogre.getWindow (); + Ogre::RenderWindow* window = mOgre.getWindow (); size_t windowHnd; resetIdleTime(); @@ -67,7 +76,7 @@ namespace MWInput // Set non-exclusive mouse and keyboard input if the user requested // it. - if (debug) + if (mDebug) { #if defined OIS_WIN32_PLATFORM pl.insert(std::make_pair(std::string("w32_mouse"), @@ -112,7 +121,7 @@ namespace MWInput MyGUI::InputManager::getInstance().injectMouseMove(mMouseX, mMouseY, mMouse->getMouseState ().Z.abs); - std::string file = userFileExists ? userFile : ""; + std::string file = mUserFileExists ? mUserFile : ""; mInputCtrl = new ICS::InputControlSystem(file, true, this, NULL, A_Last); loadKeyDefaults(); @@ -131,9 +140,11 @@ namespace MWInput mControlSwitch["vanitymode"] = true; changeInputMode(false); + + mCreated = true; } - InputManager::~InputManager() + void InputManager::destroy() { mInputCtrl->save (mUserFile); @@ -142,6 +153,12 @@ namespace MWInput mInputManager->destroyInputObject(mKeyboard); mInputManager->destroyInputObject(mMouse); OIS::InputManager::destroyInputSystem(mInputManager); + mCreated = false; + } + + InputManager::~InputManager() + { + destroy(); } void InputManager::channelChanged(ICS::Channel* channel, float currentValue, float previousValue) @@ -239,6 +256,7 @@ namespace MWInput void InputManager::update(float dt, bool loading) { + if (!mCreated) return; // Tell OIS to handle all input events mKeyboard->capture(); mMouse->capture(); diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 9deed1f28..100bba4fb 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -131,6 +131,8 @@ namespace MWInput std::string mUserFile; + bool mCreated; + bool mDragDrop; bool mInvertY; @@ -148,9 +150,15 @@ namespace MWInput float mMouseX; float mMouseY; int mMouseWheel; + bool mDebug; + bool mUserFileExists; std::map mControlSwitch; + public: + virtual void create(); + virtual void destroy(); + private: void adjustMouseRegion(int width, int height); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 69f3914e5..9e50b2bce 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -46,7 +46,8 @@ namespace MWRender { RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, OEngine::Physic::PhysicEngine* engine) - : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine) + : mRendering(_rend), mObjects(mRendering), mActors(mRendering), mAmbientMode(0), mSunEnabled(0), mPhysicsEngine(engine), + mRecreateWindowInNextFrame(false) { // select best shader mode bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos); @@ -323,6 +324,22 @@ RenderingManager::moveObjectToCell( void RenderingManager::update (float duration, bool paused) { + if (mRecreateWindowInNextFrame) + { + MWBase::Environment::get().getInputManager()->destroy(); + + OEngine::Render::WindowSettings windowSettings; + windowSettings.fullscreen = Settings::Manager::getBool("fullscreen", "Video"); + windowSettings.window_x = Settings::Manager::getInt("resolution x", "Video"); + windowSettings.window_y = Settings::Manager::getInt("resolution y", "Video"); + windowSettings.vsync = Settings::Manager::getBool("vsync", "Video"); + std::string aa = Settings::Manager::getString("antialiasing", "Video"); + windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; + mRendering.recreateWindow("OpenMW", windowSettings); + + MWBase::Environment::get().getInputManager()->create(); + mRecreateWindowInNextFrame = false; + } Ogre::Vector3 orig, dest; mPlayer->setCameraDistance(); if (!mPlayer->getPosition(orig, dest)) { @@ -756,6 +773,7 @@ Compositors* RenderingManager::getCompositors() void RenderingManager::processChangedSettings(const Settings::CategorySettingVector& settings) { bool changeRes = false; + bool recreateWindow = false; bool rebuild = false; // rebuild static geometry (necessary after any material changes) for (Settings::CategorySettingVector::const_iterator it=settings.begin(); it != settings.end(); ++it) @@ -774,6 +792,8 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec || it->second == "resolution y" || it->second == "fullscreen")) changeRes = true; + else if (it->first == "Video" && it->second == "vsync") + recreateWindow = 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") @@ -845,6 +865,13 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec mRendering.getWindow()->setFullscreen(Settings::Manager::getBool("fullscreen", "Video"), x, y); } + if (recreateWindow) + { + mRecreateWindowInNextFrame = true; + // We can not do this now, because this might get triggered from the input listener + // and destroying/recreating the input system at that point would cause a crash + } + if (mWater) mWater->processChangedSettings(settings); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 71ac742c2..670f3dc85 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -260,6 +260,8 @@ class RenderingManager: private RenderingInterface, public Ogre::WindowEventList MWRender::Compositors* mCompositors; VideoPlayer* mVideoPlayer; + + bool mRecreateWindowInNextFrame; }; } diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index 039aba226..e0abf420e 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -205,13 +205,31 @@ 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); mRoot->initialise(false); // create a hidden 1x1 background window to keep resources when recreating the secondary (real) window - /* NameValuePairList params_; params_.insert(std::make_pair("title", title)); params_.insert(std::make_pair("FSAA", "0")); @@ -219,7 +237,6 @@ void OgreRenderer::createWindow(const std::string &title, const WindowSettings& params_.insert(std::make_pair("hidden", "true")); Ogre::RenderWindow* hiddenWindow = mRoot->createRenderWindow("InactiveHidden", 1, 1, false, ¶ms_); hiddenWindow->setActive(false); - */ NameValuePairList params; params.insert(std::make_pair("title", title)); @@ -271,12 +288,12 @@ void OgreRenderer::adjustViewport() void OgreRenderer::setWindowEventListener(Ogre::WindowEventListener* listener) { - Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); + //Ogre::WindowEventUtilities::addWindowEventListener(mWindow, listener); } void OgreRenderer::removeWindowEventListener(Ogre::WindowEventListener* listener) { - Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); + //Ogre::WindowEventUtilities::removeWindowEventListener(mWindow, listener); } void OgreRenderer::setFov(float fov) diff --git a/libs/openengine/ogre/renderer.hpp b/libs/openengine/ogre/renderer.hpp index a8788dfca..251dc9c54 100644 --- a/libs/openengine/ogre/renderer.hpp +++ b/libs/openengine/ogre/renderer.hpp @@ -66,6 +66,7 @@ namespace OEngine #endif class Fader; + class OgreRenderer { #if defined(__APPLE__) && !defined(__LP64__) @@ -138,6 +139,8 @@ 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