From 452b522bc3105b3aba95aeab86124ddc0839347e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 22 Mar 2014 19:01:41 +0100 Subject: [PATCH 01/18] Fix typos --- components/compiler/lineparser.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/compiler/lineparser.cpp b/components/compiler/lineparser.cpp index 5457d7625..98bd63ba1 100644 --- a/components/compiler/lineparser.cpp +++ b/components/compiler/lineparser.cpp @@ -86,7 +86,7 @@ namespace Compiler { if (mState==PotentialEndState) { - getErrorHandler().warning ("stay string argument (ignoring it)", loc); + getErrorHandler().warning ("stray string argument (ignoring it)", loc); mState = EndState; return true; } @@ -377,19 +377,19 @@ namespace Compiler case Scanner::K_else: - getErrorHandler().warning ("stay else (ignoring it)", loc); + getErrorHandler().warning ("stray else (ignoring it)", loc); mState = EndState; return true; case Scanner::K_endif: - getErrorHandler().warning ("stay endif (ignoring it)", loc); + getErrorHandler().warning ("stray endif (ignoring it)", loc); mState = EndState; return true; case Scanner::K_begin: - getErrorHandler().warning ("stay begin (ignoring it)", loc); + getErrorHandler().warning ("stray begin (ignoring it)", loc); mState = EndState; return true; } From 0a17245633a10d3583d684fa92a5ac0b61c0fa83 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 22 Mar 2014 19:02:14 +0100 Subject: [PATCH 02/18] Refactored settings window --- CMakeLists.txt | 1 + apps/openmw/mwgui/settingswindow.cpp | 380 +++++++++------------- apps/openmw/mwgui/settingswindow.hpp | 37 +-- apps/openmw/mwrender/water.cpp | 6 +- files/mygui/openmw_settings_window.layout | 170 ++++++++-- files/settings-default.cfg | 2 - 6 files changed, 295 insertions(+), 301 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb3827588..392fdfc66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,6 +132,7 @@ set(OENGINE_OGRE set(OENGINE_GUI ${LIBDIR}/openengine/gui/manager.cpp + ${LIBDIR}/openengine/gui/layout.hpp ) set(OENGINE_BULLET diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index c99e2d0de..78adecd3e 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -83,91 +83,116 @@ namespace } return false; } + + const char* checkButtonType = "CheckButton"; + const char* sliderType = "Slider"; + + std::string getSettingType(MyGUI::Widget* widget) + { + return widget->getUserString("SettingType"); + } + + std::string getSettingName(MyGUI::Widget* widget) + { + return widget->getUserString("SettingName"); + } + + std::string getSettingCategory(MyGUI::Widget* widget) + { + return widget->getUserString("SettingCategory"); + } + + std::string getSettingValueType(MyGUI::Widget* widget) + { + return widget->getUserString("SettingValueType"); + } + + void getSettingMinMax(MyGUI::Widget* widget, float& min, float& max) + { + const char* settingMin = "SettingMin"; + const char* settingMax = "SettingMax"; + min = 0.f; + max = 1.f; + if (!widget->getUserString(settingMin).empty()) + min = boost::lexical_cast(widget->getUserString(settingMin)); + if (!widget->getUserString(settingMax).empty()) + max = boost::lexical_cast(widget->getUserString(settingMax)); + } } namespace MWGui { + void SettingsWindow::configureWidgets(MyGUI::Widget* widget) + { + MyGUI::EnumeratorWidgetPtr widgets = widget->getEnumerator(); + while (widgets.next()) + { + MyGUI::Widget* current = widgets.current(); + + std::string type = getSettingType(current); + if (type == checkButtonType) + { + std::string initialValue = Settings::Manager::getBool(getSettingName(current), + getSettingCategory(current)) + ? "#{sOn}" : "#{sOff}"; + current->castType()->setCaptionWithReplacing(initialValue); + current->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); + } + if (type == sliderType) + { + MyGUI::ScrollBar* scroll = current->castType(); + if (getSettingValueType(current) == "Float") + { + // TODO: ScrollBar isn't meant for this. should probably use a dedicated FloatSlider widget + float min,max; + getSettingMinMax(scroll, min, max); + float value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current)); + value = (value-min)/(max-min); + + scroll->setScrollPosition( value * (scroll->getScrollRange()-1)); + } + else + { + int value = Settings::Manager::getFloat(getSettingName(current), getSettingCategory(current)); + scroll->setScrollPosition(value); + } + scroll->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); + } + + configureWidgets(current); + } + } + SettingsWindow::SettingsWindow() : WindowBase("openmw_settings_window.layout") { + configureWidgets(mMainWidget); + getWidget(mOkButton, "OkButton"); - getWidget(mBestAttackButton, "BestAttackButton"); - getWidget(mGrabCursorButton, "GrabCursorButton"); - getWidget(mSubtitlesButton, "SubtitlesButton"); - getWidget(mCrosshairButton, "CrosshairButton"); getWidget(mResolutionList, "ResolutionList"); - getWidget(mMenuTransparencySlider, "MenuTransparencySlider"); - getWidget(mToolTipDelaySlider, "ToolTipDelaySlider"); - getWidget(mViewDistanceSlider, "ViewDistanceSlider"); getWidget(mFullscreenButton, "FullscreenButton"); getWidget(mVSyncButton, "VSyncButton"); getWidget(mFPSButton, "FPSButton"); getWidget(mFOVSlider, "FOVSlider"); - getWidget(mMasterVolumeSlider, "MasterVolume"); - getWidget(mVoiceVolumeSlider, "VoiceVolume"); - getWidget(mEffectsVolumeSlider, "EffectsVolume"); - getWidget(mFootstepsVolumeSlider, "FootstepsVolume"); - getWidget(mMusicVolumeSlider, "MusicVolume"); getWidget(mAnisotropySlider, "AnisotropySlider"); getWidget(mTextureFilteringButton, "TextureFilteringButton"); getWidget(mAnisotropyLabel, "AnisotropyLabel"); getWidget(mAnisotropyBox, "AnisotropyBox"); - getWidget(mWaterShaderButton, "WaterShaderButton"); - getWidget(mReflectObjectsButton, "ReflectObjectsButton"); - getWidget(mReflectActorsButton, "ReflectActorsButton"); - getWidget(mReflectTerrainButton, "ReflectTerrainButton"); getWidget(mShadersButton, "ShadersButton"); getWidget(mShaderModeButton, "ShaderModeButton"); getWidget(mShadowsEnabledButton, "ShadowsEnabledButton"); - getWidget(mShadowsLargeDistance, "ShadowsLargeDistance"); getWidget(mShadowsTextureSize, "ShadowsTextureSize"); - getWidget(mActorShadows, "ActorShadows"); - getWidget(mStaticsShadows, "StaticsShadows"); - getWidget(mMiscShadows, "MiscShadows"); - getWidget(mTerrainShadows, "TerrainShadows"); getWidget(mControlsBox, "ControlsBox"); getWidget(mResetControlsButton, "ResetControlsButton"); - getWidget(mInvertYButton, "InvertYButton"); - getWidget(mCameraSensitivitySlider, "CameraSensitivitySlider"); getWidget(mRefractionButton, "RefractionButton"); - mSubtitlesButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mCrosshairButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mBestAttackButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mGrabCursorButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mInvertYButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mOkButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onOkButtonClicked); - mShadersButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShadersToggled); mShaderModeButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onShaderModeToggled); - mFullscreenButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mWaterShaderButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mRefractionButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mReflectObjectsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mReflectTerrainButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mReflectActorsButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mTextureFilteringButton->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onTextureFilteringChanged); - mVSyncButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mFPSButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onFpsToggled); - mMenuTransparencySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mFOVSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mToolTipDelaySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mViewDistanceSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); mResolutionList->eventListChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onResolutionSelected); - mAnisotropySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mShadowsEnabledButton->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mShadowsLargeDistance->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); mShadowsTextureSize->eventComboChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onShadowTextureSizeChanged); - mActorShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mStaticsShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mMiscShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - mTerrainShadows->eventMouseButtonClick += MyGUI::newDelegate(this, &SettingsWindow::onButtonToggled); - - mMasterVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mVoiceVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mEffectsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mFootstepsVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mMusicVolumeSlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); center(); @@ -194,73 +219,25 @@ namespace MWGui mResolutionList->addItem(str); } - // read settings - int menu_transparency = (mMenuTransparencySlider->getScrollRange()-1) * Settings::Manager::getFloat("menu transparency", "GUI"); - mMenuTransparencySlider->setScrollPosition(menu_transparency); - int tooltip_delay = (mToolTipDelaySlider->getScrollRange()-1) * Settings::Manager::getFloat("tooltip delay", "GUI"); - mToolTipDelaySlider->setScrollPosition(tooltip_delay); - - mSubtitlesButton->setCaptionWithReplacing(Settings::Manager::getBool("subtitles", "GUI") ? "#{sOn}" : "#{sOff}"); - mCrosshairButton->setCaptionWithReplacing(Settings::Manager::getBool("crosshair", "HUD") ? "#{sOn}" : "#{sOff}"); - mBestAttackButton->setCaptionWithReplacing(Settings::Manager::getBool("best attack", "Game") ? "#{sOn}" : "#{sOff}"); - mGrabCursorButton->setCaptionWithReplacing(Settings::Manager::getBool("grab cursor", "Input") ? "#{sOn}" : "#{sOff}"); - - float fovVal = (Settings::Manager::getFloat("field of view", "General")-sFovMin)/(sFovMax-sFovMin); - mFOVSlider->setScrollPosition(fovVal * (mFOVSlider->getScrollRange()-1)); - MyGUI::TextBox* fovText; - getWidget(fovText, "FovText"); - fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getFloat("field of view", "General"))) + ")"); - - float anisotropyVal = Settings::Manager::getInt("anisotropy", "General") / 16.0; - mAnisotropySlider->setScrollPosition(anisotropyVal * (mAnisotropySlider->getScrollRange()-1)); std::string tf = Settings::Manager::getString("texture filtering", "General"); mTextureFilteringButton->setCaption(textureFilteringToStr(tf)); mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(Settings::Manager::getInt("anisotropy", "General")) + ")"); - float val = (Settings::Manager::getFloat("max viewing distance", "Viewing distance")-sViewDistMin)/(sViewDistMax-sViewDistMin); - int viewdist = (mViewDistanceSlider->getScrollRange()-1) * val; - mViewDistanceSlider->setScrollPosition(viewdist); - - mMasterVolumeSlider->setScrollPosition(Settings::Manager::getFloat("master volume", "Sound") * (mMasterVolumeSlider->getScrollRange()-1)); - mMusicVolumeSlider->setScrollPosition(Settings::Manager::getFloat("music volume", "Sound") * (mMusicVolumeSlider->getScrollRange()-1)); - mEffectsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("sfx volume", "Sound") * (mEffectsVolumeSlider->getScrollRange()-1)); - mFootstepsVolumeSlider->setScrollPosition(Settings::Manager::getFloat("footsteps volume", "Sound") * (mFootstepsVolumeSlider->getScrollRange()-1)); - mVoiceVolumeSlider->setScrollPosition(Settings::Manager::getFloat("voice volume", "Sound") * (mVoiceVolumeSlider->getScrollRange()-1)); - - mWaterShaderButton->setCaptionWithReplacing(Settings::Manager::getBool("shader", "Water") ? "#{sOn}" : "#{sOff}"); - mReflectObjectsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect statics", "Water") ? "#{sOn}" : "#{sOff}"); - mReflectActorsButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect actors", "Water") ? "#{sOn}" : "#{sOff}"); - mReflectTerrainButton->setCaptionWithReplacing(Settings::Manager::getBool("reflect terrain", "Water") ? "#{sOn}" : "#{sOff}"); - mShadowsTextureSize->setCaption (Settings::Manager::getString ("texture size", "Shadows")); - mShadowsLargeDistance->setCaptionWithReplacing(Settings::Manager::getBool("split", "Shadows") ? "#{sOn}" : "#{sOff}"); - - mShadowsEnabledButton->setCaptionWithReplacing(Settings::Manager::getBool("enabled", "Shadows") ? "#{sOn}" : "#{sOff}"); - mActorShadows->setCaptionWithReplacing(Settings::Manager::getBool("actor shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); - mStaticsShadows->setCaptionWithReplacing(Settings::Manager::getBool("statics shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); - mMiscShadows->setCaptionWithReplacing(Settings::Manager::getBool("misc shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); - mTerrainShadows->setCaptionWithReplacing(Settings::Manager::getBool("terrain shadows", "Shadows") ? "#{sOn}" : "#{sOff}"); - - float cameraSens = (Settings::Manager::getFloat("camera sensitivity", "Input")-0.2)/(5.0-0.2); - mCameraSensitivitySlider->setScrollPosition (cameraSens * (mCameraSensitivitySlider->getScrollRange()-1)); - mCameraSensitivitySlider->eventScrollChangePosition += MyGUI::newDelegate(this, &SettingsWindow::onSliderChangePosition); - mInvertYButton->setCaptionWithReplacing(Settings::Manager::getBool("invert y axis", "Input") ? "#{sOn}" : "#{sOff}"); - - mShadersButton->setCaptionWithReplacing (Settings::Manager::getBool("shaders", "Objects") ? "#{sOn}" : "#{sOff}"); mShaderModeButton->setCaption (Settings::Manager::getString("shader mode", "General")); - mRefractionButton->setCaptionWithReplacing (Settings::Manager::getBool("refraction", "Water") ? "#{sOn}" : "#{sOff}"); - if (!Settings::Manager::getBool("shaders", "Objects")) { mRefractionButton->setEnabled(false); mShadowsEnabledButton->setEnabled(false); } - mFullscreenButton->setCaptionWithReplacing(Settings::Manager::getBool("fullscreen", "Video") ? "#{sOn}" : "#{sOff}"); - mVSyncButton->setCaptionWithReplacing(Settings::Manager::getBool("vsync", "Video") ? "#{sOn}": "#{sOff}"); mFPSButton->setCaptionWithReplacing(fpsLevelToStr(Settings::Manager::getInt("fps", "HUD"))); + + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + fovText->setCaption("Field of View (" + boost::lexical_cast(int(Settings::Manager::getInt("field of view", "General"))) + ")"); } void SettingsWindow::onOkButtonClicked(MyGUI::Widget* _sender) @@ -320,6 +297,39 @@ namespace MWGui newState = true; } + if (_sender == mVSyncButton) + { + // Ogre::Window::setVSyncEnabled is bugged in 1.8 +#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0) + MWBase::Environment::get().getWindowManager()-> + messageBox("VSync will be applied after a restart", std::vector()); +#endif + } + + if (_sender == mShadersButton) + { + if (newState == false) + { + // refraction needs shaders to display underwater fog + mRefractionButton->setCaptionWithReplacing("#{sOff}"); + mRefractionButton->setEnabled(false); + + Settings::Manager::setBool("refraction", "Water", false); + + // shadows not supported + mShadowsEnabledButton->setEnabled(false); + mShadowsEnabledButton->setCaptionWithReplacing("#{sOff}"); + Settings::Manager::setBool("enabled", "Shadows", false); + } + else + { + // re-enable + mRefractionButton->setEnabled(true); + + mShadowsEnabledButton->setEnabled(true); + } + } + if (_sender == mFullscreenButton) { // check if this resolution is supported in fullscreen @@ -341,64 +351,15 @@ namespace MWGui MWBase::Environment::get().getWindowManager()-> messageBox(msg); _sender->castType()->setCaption(off); + return; } - else - { - Settings::Manager::setBool("fullscreen", "Video", newState); - apply(); - } - } - else if (_sender == mVSyncButton) - { - Settings::Manager::setBool("vsync", "Video", newState); - // Ogre::Window::setVSyncEnabled is bugged in 1.8 -#if OGRE_VERSION < (1 << 16 | 9 << 8 | 0) - MWBase::Environment::get().getWindowManager()-> - messageBox("VSync will be applied after a restart", std::vector()); -#endif - apply(); } - else + + if (getSettingType(_sender) == checkButtonType) { - if (_sender == mVSyncButton) - Settings::Manager::setBool("vsync", "Video", newState); - if (_sender == mWaterShaderButton) - Settings::Manager::setBool("shader", "Water", newState); - else if (_sender == mRefractionButton) - Settings::Manager::setBool("refraction", "Water", newState); - else if (_sender == mReflectObjectsButton) - { - Settings::Manager::setBool("reflect misc", "Water", newState); - Settings::Manager::setBool("reflect statics", "Water", newState); - Settings::Manager::setBool("reflect statics small", "Water", newState); - } - else if (_sender == mReflectActorsButton) - Settings::Manager::setBool("reflect actors", "Water", newState); - else if (_sender == mReflectTerrainButton) - Settings::Manager::setBool("reflect terrain", "Water", newState); - else if (_sender == mShadowsEnabledButton) - Settings::Manager::setBool("enabled", "Shadows", newState); - else if (_sender == mShadowsLargeDistance) - Settings::Manager::setBool("split", "Shadows", newState); - else if (_sender == mActorShadows) - Settings::Manager::setBool("actor shadows", "Shadows", newState); - else if (_sender == mStaticsShadows) - Settings::Manager::setBool("statics shadows", "Shadows", newState); - else if (_sender == mMiscShadows) - Settings::Manager::setBool("misc shadows", "Shadows", newState); - else if (_sender == mTerrainShadows) - Settings::Manager::setBool("terrain shadows", "Shadows", newState); - else if (_sender == mInvertYButton) - Settings::Manager::setBool("invert y axis", "Input", newState); - else if (_sender == mCrosshairButton) - Settings::Manager::setBool("crosshair", "HUD", newState); - else if (_sender == mSubtitlesButton) - Settings::Manager::setBool("subtitles", "GUI", newState); - else if (_sender == mBestAttackButton) - Settings::Manager::setBool("best attack", "Game", newState); - else if (_sender == mGrabCursorButton) - Settings::Manager::setBool("grab cursor", "Input", newState); + Settings::Manager::setBool(getSettingName(_sender), getSettingCategory(_sender), newState); apply(); + return; } } @@ -419,50 +380,6 @@ namespace MWGui apply(); } - void SettingsWindow::onShadersToggled(MyGUI::Widget* _sender) - { - std::string on = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOn", "On"); - std::string off = MWBase::Environment::get().getWindowManager()->getGameSettingString("sOff", "On"); - - std::string val = static_cast(_sender)->getCaption(); - if (val == off) - val = on; - else - val = off; - static_cast(_sender)->setCaptionWithReplacing (val); - - if (val == off) - { - Settings::Manager::setBool("shaders", "Objects", false); - - // refraction needs shaders to display underwater fog - mRefractionButton->setCaptionWithReplacing("#{sOff}"); - mRefractionButton->setEnabled(false); - - Settings::Manager::setBool("refraction", "Water", false); - Settings::Manager::setBool("underwater effect", "Water", false); - - // shadows not supported - mShadowsEnabledButton->setEnabled(false); - mShadowsEnabledButton->setCaptionWithReplacing("#{sOff}"); - Settings::Manager::setBool("enabled", "Shadows", false); - } - else - { - Settings::Manager::setBool("shaders", "Objects", true); - - // re-enable - mReflectObjectsButton->setEnabled(true); - mReflectActorsButton->setEnabled(true); - mReflectTerrainButton->setEnabled(true); - mRefractionButton->setEnabled(true); - - mShadowsEnabledButton->setEnabled(true); - } - - apply(); - } - void SettingsWindow::onFpsToggled(MyGUI::Widget* _sender) { int newLevel = (Settings::Manager::getInt("fps", "HUD") + 1) % 3; @@ -479,39 +396,34 @@ namespace MWGui void SettingsWindow::onSliderChangePosition(MyGUI::ScrollBar* scroller, size_t pos) { - float val = pos / float(scroller->getScrollRange()-1); - if (scroller == mMenuTransparencySlider) - Settings::Manager::setFloat("menu transparency", "GUI", val); - else if (scroller == mToolTipDelaySlider) - Settings::Manager::setFloat("tooltip delay", "GUI", val); - else if (scroller == mViewDistanceSlider) - Settings::Manager::setFloat("max viewing distance", "Viewing distance", (1-val) * sViewDistMin + val * sViewDistMax); - else if (scroller == mFOVSlider) + if (getSettingType(scroller) == "Slider") { - MyGUI::TextBox* fovText; - getWidget(fovText, "FovText"); - fovText->setCaption("Field of View (" + boost::lexical_cast(int((1-val) * sFovMin + val * sFovMax)) + ")"); - Settings::Manager::setFloat("field of view", "General", (1-val) * sFovMin + val * sFovMax); - } - else if (scroller == mAnisotropySlider) - { - mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(int(val*16)) + ")"); - Settings::Manager::setInt("anisotropy", "General", val * 16); + if (getSettingValueType(scroller) == "Float") + { + float value = pos / float(scroller->getScrollRange()-1); + + float min,max; + getSettingMinMax(scroller, min, max); + value = min + (max-min) * value; + Settings::Manager::setFloat(getSettingName(scroller), getSettingCategory(scroller), value); + + if (scroller == mFOVSlider) + { + MyGUI::TextBox* fovText; + getWidget(fovText, "FovText"); + fovText->setCaption("Field of View (" + boost::lexical_cast(int(value)) + ")"); + } + } + else + { + Settings::Manager::setInt(getSettingName(scroller), getSettingCategory(scroller), pos); + if (scroller == mAnisotropySlider) + { + mAnisotropyLabel->setCaption("Anisotropy (" + boost::lexical_cast(pos) + ")"); + } + } + apply(); } - else if (scroller == mMasterVolumeSlider) - Settings::Manager::setFloat("master volume", "Sound", val); - else if (scroller == mVoiceVolumeSlider) - Settings::Manager::setFloat("voice volume", "Sound", val); - else if (scroller == mEffectsVolumeSlider) - Settings::Manager::setFloat("sfx volume", "Sound", val); - else if (scroller == mFootstepsVolumeSlider) - Settings::Manager::setFloat("footsteps volume", "Sound", val); - else if (scroller == mMusicVolumeSlider) - Settings::Manager::setFloat("music volume", "Sound", val); - else if (scroller == mCameraSensitivitySlider) - Settings::Manager::setFloat("camera sensitivity", "Input", (1-val) * 0.2 + val * 5.f); - - apply(); } void SettingsWindow::apply() diff --git a/apps/openmw/mwgui/settingswindow.hpp b/apps/openmw/mwgui/settingswindow.hpp index 6b9ce414b..7a6c1a5ed 100644 --- a/apps/openmw/mwgui/settingswindow.hpp +++ b/apps/openmw/mwgui/settingswindow.hpp @@ -19,61 +19,29 @@ namespace MWGui void updateControlsBox(); - private: - static int const sFovMin = 30; - static int const sFovMax = 140; - static int const sViewDistMin = 2000; - static int const sViewDistMax = 5600; - - protected: + protected: MyGUI::Button* mOkButton; - MyGUI::ScrollBar* mMenuTransparencySlider; - MyGUI::ScrollBar* mToolTipDelaySlider; - MyGUI::Button* mSubtitlesButton; - MyGUI::Button* mCrosshairButton; - MyGUI::Button* mBestAttackButton; - MyGUI::Button* mGrabCursorButton; - // graphics MyGUI::ListBox* mResolutionList; MyGUI::Button* mFullscreenButton; MyGUI::Button* mVSyncButton; MyGUI::Button* mFPSButton; - MyGUI::ScrollBar* mViewDistanceSlider; MyGUI::ScrollBar* mFOVSlider; MyGUI::ScrollBar* mAnisotropySlider; MyGUI::ComboBox* mTextureFilteringButton; MyGUI::TextBox* mAnisotropyLabel; MyGUI::Widget* mAnisotropyBox; - MyGUI::Button* mWaterShaderButton; - MyGUI::Button* mReflectObjectsButton; - MyGUI::Button* mReflectActorsButton; - MyGUI::Button* mReflectTerrainButton; MyGUI::Button* mShadersButton; MyGUI::Button* mShaderModeButton; MyGUI::Button* mRefractionButton; MyGUI::Button* mShadowsEnabledButton; - MyGUI::Button* mShadowsLargeDistance; MyGUI::ComboBox* mShadowsTextureSize; - MyGUI::Button* mActorShadows; - MyGUI::Button* mStaticsShadows; - MyGUI::Button* mMiscShadows; - MyGUI::Button* mTerrainShadows; - - // audio - MyGUI::ScrollBar* mMasterVolumeSlider; - MyGUI::ScrollBar* mVoiceVolumeSlider; - MyGUI::ScrollBar* mEffectsVolumeSlider; - MyGUI::ScrollBar* mFootstepsVolumeSlider; - MyGUI::ScrollBar* mMusicVolumeSlider; // controls MyGUI::ScrollView* mControlsBox; MyGUI::Button* mResetControlsButton; - MyGUI::Button* mInvertYButton; - MyGUI::ScrollBar* mCameraSensitivitySlider; void onOkButtonClicked(MyGUI::Widget* _sender); void onFpsToggled(MyGUI::Widget* _sender); @@ -84,7 +52,6 @@ namespace MWGui void onResolutionAccept(); void onResolutionCancel(); - void onShadersToggled(MyGUI::Widget* _sender); void onShaderModeToggled(MyGUI::Widget* _sender); void onShadowTextureSizeChanged(MyGUI::ComboBox* _sender, size_t pos); @@ -94,6 +61,8 @@ namespace MWGui void onResetDefaultBindingsAccept (); void apply(); + + void configureWidgets(MyGUI::Widget* widget); }; } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 1fa5d8834..5368cbe68 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -418,10 +418,8 @@ void Water::applyRTT() void Water::applyVisibilityMask() { mVisibilityFlags = RV_Terrain * Settings::Manager::getBool("reflect terrain", "Water") - + RV_Statics * Settings::Manager::getBool("reflect statics", "Water") - + RV_StaticsSmall * Settings::Manager::getBool("reflect small statics", "Water") + + (RV_Statics + RV_StaticsSmall + RV_Misc) * Settings::Manager::getBool("reflect statics", "Water") + RV_Actors * Settings::Manager::getBool("reflect actors", "Water") - + RV_Misc * Settings::Manager::getBool("reflect misc", "Water") + RV_Sky; if (mReflection) @@ -444,8 +442,6 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin if ( it->first == "Water" && ( it->second == "reflect actors" || it->second == "reflect terrain" - || it->second == "reflect misc" - || it->second == "reflect small statics" || it->second == "reflect statics")) applyVisMask = true; } diff --git a/files/mygui/openmw_settings_window.layout b/files/mygui/openmw_settings_window.layout index 61103963d..adf9f1557 100644 --- a/files/mygui/openmw_settings_window.layout +++ b/files/mygui/openmw_settings_window.layout @@ -18,6 +18,10 @@ + + + + @@ -34,6 +38,10 @@ + + + + @@ -45,28 +53,44 @@ - + + + + + - + + + + + - + + + + + - + + + + + @@ -81,6 +105,10 @@ + + + + @@ -89,6 +117,10 @@ + + + + @@ -97,6 +129,10 @@ + + + + @@ -105,6 +141,10 @@ + + + + @@ -113,6 +153,10 @@ + + + + @@ -127,7 +171,11 @@ - + + + + + @@ -139,6 +187,12 @@ + + + + + + @@ -149,8 +203,6 @@ - - @@ -163,16 +215,23 @@ - - + + + + + - + + + + + @@ -186,7 +245,11 @@ - + + + + + @@ -205,6 +268,12 @@ + + + + + + @@ -233,8 +302,10 @@ - - + + + + @@ -244,6 +315,12 @@ + + + + + + @@ -260,7 +337,11 @@ - + + + + + @@ -269,21 +350,33 @@ - + + + + + - + + + + + - + + + + + @@ -291,7 +384,11 @@ - + + + + + @@ -302,7 +399,11 @@ - + + + + + @@ -311,35 +412,52 @@ - + + + + + - - - + + + + - + + + + + - + + + + + - + + + + + diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 4fb7097f8..5dfc05455 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -137,9 +137,7 @@ refraction = true rtt size = 512 reflect terrain = true reflect statics = false -reflect small statics = false reflect actors = false -reflect misc = false [Sound] # Device name. Blank means default From 688415ce5476aeeb9bf91962f2294868e9d858e6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 18:55:16 +0100 Subject: [PATCH 03/18] Play deathknockout/deathknockdown animations when appropriate --- apps/openmw/mwmechanics/character.cpp | 10 ++++++++++ apps/openmw/mwmechanics/character.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 2db3bacf0..93c789af1 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -414,6 +414,16 @@ void CharacterController::playRandomDeath(float startpoint) mDeathState = CharState_SwimDeath; mCurrentDeath = "swimdeath"; } + else if (mHitState == CharState_KnockDown) + { + mDeathState = CharState_DeathKnockDown; + mCurrentDeath = "deathknockdown"; + } + else if (mHitState == CharState_KnockOut) + { + mDeathState = CharState_DeathKnockOut; + mCurrentDeath = "deathknockout"; + } else { int selected=0; diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 4009744ef..5aea0210f 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -90,6 +90,8 @@ enum CharacterState { CharState_Death4, CharState_Death5, CharState_SwimDeath, + CharState_DeathKnockDown, + CharState_DeathKnockOut, CharState_Hit, CharState_KnockDown, From 793649c854d759a40fcb8b0421295a6f23c3ac2f Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 19:55:52 +0100 Subject: [PATCH 04/18] ToggleAI: Report current status on toggle --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 3 ++- apps/openmw/mwmechanics/mechanicsmanagerimp.hpp | 2 +- apps/openmw/mwscript/aiextensions.cpp | 7 ++++++- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index 22dda0ce0..e4c480a8c 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -156,7 +156,7 @@ namespace MWBase /// paused we may want to do it manually (after equipping permanent enchantment) virtual void updateMagicEffects (const MWWorld::Ptr& ptr) = 0; - virtual void toggleAI() = 0; + virtual bool toggleAI() = 0; virtual bool isAIActive() = 0; virtual void getObjectsInRange (const Ogre::Vector3& position, float radius, std::vector& objects) = 0; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 4c8f35edb..3164ca155 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -750,9 +750,10 @@ namespace MWMechanics mActors.updateMagicEffects(ptr); } - void MechanicsManager::toggleAI() + bool MechanicsManager::toggleAI() { mAI = !mAI; + return mAI; } bool MechanicsManager::isAIActive() diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 761caf586..5dd758377 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -137,7 +137,7 @@ namespace MWMechanics virtual std::list getActorsFollowing(const MWWorld::Ptr& actor); - virtual void toggleAI(); + virtual bool toggleAI(); virtual bool isAIActive(); virtual void playerLoaded(); diff --git a/apps/openmw/mwscript/aiextensions.cpp b/apps/openmw/mwscript/aiextensions.cpp index 8314d011a..a34c5476c 100644 --- a/apps/openmw/mwscript/aiextensions.cpp +++ b/apps/openmw/mwscript/aiextensions.cpp @@ -464,7 +464,12 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { - MWBase::Environment::get().getMechanicsManager()->toggleAI(); + InterpreterContext& context + = static_cast (runtime.getContext()); + + bool enabled = MWBase::Environment::get().getMechanicsManager()->toggleAI(); + + context.report (enabled ? "AI -> On" : "AI -> Off"); } }; From 53ba23e3031e20ebd71d3af178cd9fcb95461702 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 19:56:12 +0100 Subject: [PATCH 05/18] Fixes #1224: Store class name instead of id in savegame header --- apps/openmw/mwgui/savegamedialog.cpp | 2 +- apps/openmw/mwstate/statemanagerimp.cpp | 2 +- components/esm/savedgame.cpp | 4 ++-- components/esm/savedgame.hpp | 7 ++++++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 77ad98121..894cbe0a3 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -86,7 +86,7 @@ namespace MWGui { std::stringstream title; title << it->getSignature().mPlayerName; - title << " (Level " << it->getSignature().mPlayerLevel << " " << it->getSignature().mPlayerClass << ")"; + title << " (Level " << it->getSignature().mPlayerLevel << " " << it->getSignature().mPlayerClassName << ")"; mCharacterSelection->addItem (title.str()); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index d6309c1c9..a0d482f0a 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -155,7 +155,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot profile.mPlayerName = player.getClass().getName (player); profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); - profile.mPlayerClass = player.get()->mBase->mClass; + profile.mPlayerClassName = world.getStore().get().find(player.get()->mBase->mClass)->mName; profile.mPlayerCell = world.getCellName(); diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index d6887f170..813865e25 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -11,7 +11,7 @@ void ESM::SavedGame::load (ESMReader &esm) { mPlayerName = esm.getHNString("PLNA"); esm.getHNOT (mPlayerLevel, "PLLE"); - mPlayerClass = esm.getHNString("PLCL"); + mPlayerClassName = esm.getHNString("PLCL"); mPlayerCell = esm.getHNString("PLCE"); esm.getHNT (mInGameTime, "TSTM", 16); esm.getHNT (mTimePlayed, "TIME"); @@ -30,7 +30,7 @@ void ESM::SavedGame::save (ESMWriter &esm) const { esm.writeHNString ("PLNA", mPlayerName); esm.writeHNT ("PLLE", mPlayerLevel); - esm.writeHNString ("PLCL", mPlayerClass); + esm.writeHNString ("PLCL", mPlayerClassName); esm.writeHNString ("PLCE", mPlayerCell); esm.writeHNT ("TSTM", mInGameTime, 16); esm.writeHNT ("TIME", mTimePlayed); diff --git a/components/esm/savedgame.hpp b/components/esm/savedgame.hpp index 9c7bf551d..b8615a6bc 100644 --- a/components/esm/savedgame.hpp +++ b/components/esm/savedgame.hpp @@ -26,7 +26,12 @@ namespace ESM std::vector mContentFiles; std::string mPlayerName; int mPlayerLevel; - std::string mPlayerClass; // this is the ID and not the name of the class + // The (translated) name of the player class. So it will be displayed in the MW language + // the savegame was made in, not the currently running language of MW. + // However, savegames from a different MW language are not compatible anyway. + // And if only the ID was stored here, we would need to + // peek into the savegame to look for a class record in case it is a custom class. + std::string mPlayerClassName; std::string mPlayerCell; TimeStamp mInGameTime; double mTimePlayed; From ecfaa41e93699b0c20a717d76daf1f0e4ebf7661 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 20:56:39 +0100 Subject: [PATCH 06/18] Savegame dialog: use locale-aware datetime format --- apps/openmw/mwgui/savegamedialog.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 894cbe0a3..e897c5a6b 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -241,7 +241,13 @@ namespace MWGui struct tm* timeinfo; timeinfo = localtime(&time); - text << asctime(timeinfo) << "\n"; + // Use system/environment locale settings for datetime formatting + std::setlocale(LC_TIME, ""); + + const int size=1024; + char buffer[size]; + if (std::strftime(buffer, size, "%x %X", timeinfo) > 0) + text << buffer << "\n"; text << "Level " << slot->mProfile.mPlayerLevel << "\n"; text << slot->mProfile.mPlayerCell << "\n"; // text << "Time played: " << slot->mProfile.mTimePlayed << "\n"; From 5562c78ac4933456b4e17e197b98b813bfa747e1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 21:11:39 +0100 Subject: [PATCH 07/18] Ask for confirmation when selecting 'New Game' --- apps/openmw/mwgui/mainmenu.cpp | 17 ++++++++++++++++- apps/openmw/mwgui/mainmenu.hpp | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 4ad260fd9..655663eb6 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -13,6 +13,7 @@ #include "../mwstate/character.hpp" #include "savegamedialog.hpp" +#include "confirmationdialog.hpp" namespace MWGui { @@ -62,6 +63,11 @@ namespace MWGui OEngine::GUI::Layout::setVisible (visible); } + void MainMenu::onNewGameConfirmed() + { + MWBase::Environment::get().getStateManager()->newGame(); + } + void MainMenu::onButtonClicked(MyGUI::Widget *sender) { std::string name = *sender->getUserData(); @@ -77,7 +83,16 @@ namespace MWGui MWBase::Environment::get().getStateManager()->requestQuit(); else if (name == "newgame") { - MWBase::Environment::get().getStateManager()->newGame(); + if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame) + onNewGameConfirmed(); + else + { + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); + dialog->open("#{sNotifyMessage54}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onNewGameConfirmed); + dialog->eventCancelClicked.clear(); + } } else diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index 722b329de..f38b2b751 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -32,6 +32,7 @@ namespace MWGui std::map mButtons; void onButtonClicked (MyGUI::Widget* sender); + void onNewGameConfirmed(); void updateMenu(); From 23f4bbc5b00c569ff542e86c13da827ce79b5b6c Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 21:36:57 +0100 Subject: [PATCH 08/18] Videoplayer: only pause previous sounds if there is an audio stream --- apps/openmw/mwrender/videoplayer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index f3c0971e7..7abc8140a 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -994,6 +994,9 @@ void VideoState::init(const std::string& resourceName) audio_index = i; } + if (audio_index != -1) + MWBase::Environment::get().getSoundManager()->pauseSounds(); + this->external_clock_base = av_gettime(); if(audio_index >= 0) this->stream_open(audio_index, this->format_ctx); @@ -1164,8 +1167,6 @@ void VideoPlayer::playVideo(const std::string &resourceName, bool allowSkipping) } mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); - MWBase::Environment::get().getSoundManager()->pauseSounds(); - try { mState = new VideoState; mState->init(resourceName); From a5598e9c2e5e6f9b74a938ae45a9da87569fc628 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 21:38:57 +0100 Subject: [PATCH 09/18] Add Credits button to main menu (plays mw_credits.bik) --- apps/openmw/mwgui/mainmenu.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 655663eb6..4e4599e06 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -27,7 +27,7 @@ namespace MWGui std::stringstream sstream; sstream << "OpenMW version: " << OPENMW_VERSION; - // adding info about git hash if availible + // adding info about git hash if available std::string rev = OPENMW_VERSION_COMMITHASH; std::string tag = OPENMW_VERSION_TAGHASH; if (!rev.empty() && !tag.empty()) @@ -79,6 +79,8 @@ namespace MWGui } else if (name == "options") MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); + else if (name == "credits") + MWBase::Environment::get().getWorld()->playVideo("mw_credits.bik", true); else if (name == "exitgame") MWBase::Environment::get().getStateManager()->requestQuit(); else if (name == "newgame") @@ -135,7 +137,10 @@ namespace MWGui buttons.push_back("savegame"); buttons.push_back("options"); - //buttons.push_back("credits"); + + if (state==MWBase::StateManager::State_NoGame) + buttons.push_back("credits"); + buttons.push_back("exitgame"); // Create new buttons if needed From e5e1e84c5270f9120a39e7b7d676ba8c7298a516 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 26 Mar 2014 22:05:21 +0100 Subject: [PATCH 10/18] Ask for confirmation to exit OpenMW --- apps/openmw/mwgui/mainmenu.cpp | 18 +++++++++++++++++- apps/openmw/mwgui/mainmenu.hpp | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 4e4599e06..25821663d 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -68,6 +68,11 @@ namespace MWGui MWBase::Environment::get().getStateManager()->newGame(); } + void MainMenu::onExitConfirmed() + { + MWBase::Environment::get().getStateManager()->requestQuit(); + } + void MainMenu::onButtonClicked(MyGUI::Widget *sender) { std::string name = *sender->getUserData(); @@ -82,7 +87,18 @@ namespace MWGui else if (name == "credits") MWBase::Environment::get().getWorld()->playVideo("mw_credits.bik", true); else if (name == "exitgame") - MWBase::Environment::get().getStateManager()->requestQuit(); + { + if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame) + onExitConfirmed(); + else + { + ConfirmationDialog* dialog = MWBase::Environment::get().getWindowManager()->getConfirmationDialog(); + dialog->open("#{sMessage2}"); + dialog->eventOkClicked.clear(); + dialog->eventOkClicked += MyGUI::newDelegate(this, &MainMenu::onExitConfirmed); + dialog->eventCancelClicked.clear(); + } + } else if (name == "newgame") { if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame) diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index f38b2b751..1850c473c 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -33,6 +33,7 @@ namespace MWGui void onButtonClicked (MyGUI::Widget* sender); void onNewGameConfirmed(); + void onExitConfirmed(); void updateMenu(); From 0e78ffe8c0b317e38e358d0b57504403ab5acf8b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 00:10:46 +0100 Subject: [PATCH 11/18] Add option to disable SDL's "minimize on focus loss" in fullscreen --- files/settings-default.cfg | 3 +++ 1 file changed, 3 insertions(+) diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 5dfc05455..6361476e3 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -8,6 +8,9 @@ resolution y = 600 fullscreen = false screen = 0 +# Minimize the window if it loses key focus? +minimize on focus loss = true + # Render system # blank means default # Valid values: From 27956f362431127d92f2bafc7008c55d37241db6 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 02:36:21 +0100 Subject: [PATCH 12/18] Savegame dialog: Hide main menu after successful load --- apps/openmw/mwgui/savegamedialog.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index e897c5a6b..6971358c1 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -169,7 +169,10 @@ namespace MWGui else { if (mCurrentCharacter && slot) + { MWBase::Environment::get().getStateManager()->loadGame (mCurrentCharacter, slot); + MWBase::Environment::get().getWindowManager()->removeGuiMode (MWGui::GM_MainMenu); + } } setVisible(false); From 2e4ef93b28630f6f2ec8ccbe7eb2627e3912d6d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 04:15:47 +0100 Subject: [PATCH 13/18] Add proper main menu (background image, logo animation, title music) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/engine.cpp | 31 +++++++++++++++-- apps/openmw/mwgui/mainmenu.cpp | 61 +++++++++++++++++++++++++++++++--- apps/openmw/mwgui/mainmenu.hpp | 4 +++ files/mygui/openmw_layers.xml | 2 +- 5 files changed, 91 insertions(+), 9 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 20011b0d9..19f3473f7 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -33,7 +33,7 @@ add_openmw_dir (mwgui merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog - recharge + recharge mode ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 47e0d016f..a710ce59a 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -339,6 +339,9 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) std::string aa = settings.getString("antialiasing", "Video"); windowSettings.fsaa = (aa.substr(0, 4) == "MSAA") ? aa.substr(5, aa.size()-5) : "0"; + SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, + settings.getBool("minimize on focus loss", "Video") ? "1" : "0"); + mOgre->createWindow("OpenMW", windowSettings); Bsa::registerResources (mFileCollections, mArchives, true, mFSStrict); @@ -356,6 +359,18 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding); mEnvironment.setWindowManager (window); + // Create sound system + mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); + + // TODO: play pre-load intro videos. Need to find a way to have them receive input. + // Make videoplayer a MyGUI widget? + /* + { + MWRender::VideoPlayer player(mOgre->getScene(), mOgre->getWindow()); + player.playVideo("mw_logo.bik", 1); + } + */ + // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, mResDir, mCfgMgr.getCachePath(), mEncoder, mFallbackMap, @@ -373,9 +388,6 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) Compiler::registerExtensions (mExtensions); - // Create sound system - mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); - // Create script system mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full); mScriptContext->setExtensions (&mExtensions); @@ -434,7 +446,20 @@ void OMW::Engine::go() // start in main menu if (!mSkipMenu) + { MWBase::Environment::get().getWindowManager()->pushGuiMode (MWGui::GM_MainMenu); + try + { + // Is there an ini setting for this filename or something? + MWBase::Environment::get().getSoundManager()->streamMusic("Special/morrowind title.mp3"); + + // TODO: there are other intro videos, too. They need to be imported from Morrowind.ini. + // Unfortunately those must play BEFORE any loading is done, which will currently not work. + // The videoplayer is created by World, so all content files must be loaded first... + MWBase::Environment::get().getWorld()->playVideo("mw_logo.bik", true); + } + catch (...) {} + } else MWBase::Environment::get().getStateManager()->newGame (true); diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 25821663d..0bc8b07d1 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -22,6 +22,7 @@ namespace MWGui : OEngine::GUI::Layout("openmw_mainmenu.layout") , mButtonBox(0), mWidth (w), mHeight (h) , mSaveGameDialog(NULL) + , mBackground(NULL) { getWidget(mVersionText, "VersionText"); std::stringstream sstream; @@ -59,6 +60,10 @@ namespace MWGui { if (visible) updateMenu(); + else + showBackground( + MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) && + MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame); OEngine::GUI::Layout::setVisible (visible); } @@ -125,11 +130,42 @@ namespace MWGui } } + void MainMenu::showBackground(bool show) + { + if (mBackground) + { + MyGUI::Gui::getInstance().destroyWidget(mBackground); + mBackground = NULL; + } + if (show) + { + if (!mBackground) + { + mBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Stretch, "Menu"); + mBackground->setImageTexture("black.png"); + + // Use black bars to correct aspect ratio. The video player also does it, so we need to do it + // for mw_logo.bik to align correctly with menu_morrowind.dds. + MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize(); + + // No way to un-hardcode this right now, menu_morrowind.dds is 1024x512 but was designed for 4:3 + double imageaspect = 4.0/3.0; + + int leftPadding = std::max(0.0, (screenSize.width - screenSize.height * imageaspect) / 2); + int topPadding = std::max(0.0, (screenSize.height - screenSize.width / imageaspect) / 2); + + MyGUI::ImageBox* image = mBackground->createWidget("ImageBox", + leftPadding, topPadding, screenSize.width - leftPadding*2, screenSize.height - topPadding*2, MyGUI::Align::Default); + image->setImageTexture("textures\\menu_morrowind.dds"); + } + } + } + void MainMenu::updateMenu() { setCoord(0,0, mWidth, mHeight); - if (!mButtonBox) mButtonBox = mMainWidget->createWidget("", MyGUI::IntCoord(0, 0, 0, 0), MyGUI::Align::Default); @@ -137,6 +173,8 @@ namespace MWGui MWBase::StateManager::State state = MWBase::Environment::get().getStateManager()->getState(); + showBackground(state == MWBase::StateManager::State_NoGame); + std::vector buttons; if (state==MWBase::StateManager::State_Running) @@ -191,12 +229,27 @@ namespace MWGui assert(mButtons.find(*it) != mButtons.end()); MWGui::ImageButton* button = mButtons[*it]; button->setVisible(true); + MyGUI::IntSize requested = button->getRequestedSize(); - button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, requested.height); - curH += requested.height; + + // Trim off some of the excessive padding + // TODO: perhaps do this within ImageButton? + int trim = 8; + button->setImageCoord(MyGUI::IntCoord(0, trim, requested.width, requested.height-trim)); + int height = requested.height-trim*2; + button->setImageTile(MyGUI::IntSize(requested.width, height)); + button->setCoord((maxwidth-requested.width) / 2, curH, requested.width, height); + curH += height; } - mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH); + if (state == MWBase::StateManager::State_NoGame) + { + // Align with the background image + int bottomPadding=48; + mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight - curH - bottomPadding, maxwidth, curH); + } + else + mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight/2 - curH/2, maxwidth, curH); } } diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index 1850c473c..c571fda86 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -29,12 +29,16 @@ namespace MWGui MyGUI::Widget* mButtonBox; MyGUI::TextBox* mVersionText; + MyGUI::ImageBox* mBackground; + std::map mButtons; void onButtonClicked (MyGUI::Widget* sender); void onNewGameConfirmed(); void onExitConfirmed(); + void showBackground(bool show); + void updateMenu(); SaveGameDialog* mSaveGameDialog; diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 84ec6f7c5..8bd95e2cd 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -1,8 +1,8 @@ - + From 5906d795c0dc936a17e51a3fe37b12faada56160 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 19:10:15 +0100 Subject: [PATCH 14/18] Refactored video player (now a MyGUI widget) --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/engine.cpp | 2 +- apps/openmw/mwbase/windowmanager.hpp | 4 + apps/openmw/mwbase/world.hpp | 2 - apps/openmw/mwgui/mainmenu.cpp | 2 +- apps/openmw/mwgui/mode.hpp | 4 +- apps/openmw/mwgui/videowidget.cpp | 45 ++++++ apps/openmw/mwgui/videowidget.hpp | 39 +++++ apps/openmw/mwgui/windowmanagerimp.cpp | 71 +++++++- apps/openmw/mwgui/windowmanagerimp.hpp | 10 ++ apps/openmw/mwinput/inputmanagerimp.cpp | 4 +- apps/openmw/mwrender/renderingmanager.cpp | 19 --- apps/openmw/mwrender/renderingmanager.hpp | 5 - apps/openmw/mwrender/videoplayer.cpp | 188 +++++++--------------- apps/openmw/mwrender/videoplayer.hpp | 31 ++-- apps/openmw/mwscript/miscextensions.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 12 +- apps/openmw/mwworld/worldimp.hpp | 2 - files/mygui/openmw_layers.xml | 1 + 19 files changed, 242 insertions(+), 203 deletions(-) create mode 100644 apps/openmw/mwgui/videowidget.cpp create mode 100644 apps/openmw/mwgui/videowidget.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 19f3473f7..511435108 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -33,7 +33,7 @@ add_openmw_dir (mwgui merchantrepair repair soulgemdialog companionwindow bookpage journalviewmodel journalbooks keywordsearch itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview tradeitemmodel companionitemmodel pickpocketitemmodel fontloader controllers savegamedialog - recharge mode + recharge mode videowidget ) add_openmw_dir (mwdialogue diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a710ce59a..a118152ed 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -456,7 +456,7 @@ void OMW::Engine::go() // TODO: there are other intro videos, too. They need to be imported from Morrowind.ini. // Unfortunately those must play BEFORE any loading is done, which will currently not work. // The videoplayer is created by World, so all content files must be loaded first... - MWBase::Environment::get().getWorld()->playVideo("mw_logo.bik", true); + MWBase::Environment::get().getWindowManager()->playVideo("mw_logo.bik", true); } catch (...) {} } diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 4fce19e33..e3bd428e2 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -96,6 +96,10 @@ namespace MWBase */ virtual void update() = 0; + /// @note This method will block until the video finishes playing + /// (and will continually update the window while doing so) + virtual void playVideo(const std::string& name, bool allowSkipping) = 0; + virtual void setNewGame(bool newgame) = 0; virtual void pushGuiMode (MWGui::GuiMode mode) = 0; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index bb6f5741d..f03a9197d 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -420,8 +420,6 @@ namespace MWBase virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0; /// \todo this does not belong here - virtual void playVideo(const std::string& name, bool allowSkipping) = 0; - virtual void stopVideo() = 0; virtual void frameStarted (float dt, bool paused) = 0; virtual void screenshot (Ogre::Image& image, int w, int h) = 0; diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index 0bc8b07d1..00e124f6c 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -90,7 +90,7 @@ namespace MWGui else if (name == "options") MWBase::Environment::get().getWindowManager ()->pushGuiMode (GM_Settings); else if (name == "credits") - MWBase::Environment::get().getWorld()->playVideo("mw_credits.bik", true); + MWBase::Environment::get().getWindowManager()->playVideo("mw_credits.bik", true); else if (name == "exitgame") { if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame) diff --git a/apps/openmw/mwgui/mode.hpp b/apps/openmw/mwgui/mode.hpp index 50d53abac..a1688d2e5 100644 --- a/apps/openmw/mwgui/mode.hpp +++ b/apps/openmw/mwgui/mode.hpp @@ -47,9 +47,7 @@ namespace MWGui GM_Loading, GM_LoadingWallpaper, - GM_QuickKeysMenu, - - GM_Video + GM_QuickKeysMenu }; // Windows shown in inventory mode diff --git a/apps/openmw/mwgui/videowidget.cpp b/apps/openmw/mwgui/videowidget.cpp new file mode 100644 index 000000000..566c7cadb --- /dev/null +++ b/apps/openmw/mwgui/videowidget.cpp @@ -0,0 +1,45 @@ +#include "videowidget.hpp" + +namespace MWGui +{ + +VideoWidget::VideoWidget() + : mAllowSkipping(true) +{ + eventKeyButtonPressed += MyGUI::newDelegate(this, &VideoWidget::onKeyPressed); + + setNeedKeyFocus(true); +} + +void VideoWidget::playVideo(const std::string &video, bool allowSkipping) +{ + mAllowSkipping = allowSkipping; + + mPlayer.playVideo(video); + + setImageTexture(mPlayer.getTextureName()); +} + +int VideoWidget::getVideoWidth() +{ + return mPlayer.getVideoWidth(); +} + +int VideoWidget::getVideoHeight() +{ + return mPlayer.getVideoHeight(); +} + +void VideoWidget::onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char) +{ + if (_key == MyGUI::KeyCode::Escape && mAllowSkipping) + mPlayer.stopVideo(); +} + +bool VideoWidget::update() +{ + mPlayer.update(); + return mPlayer.isPlaying(); +} + +} diff --git a/apps/openmw/mwgui/videowidget.hpp b/apps/openmw/mwgui/videowidget.hpp new file mode 100644 index 000000000..16a71d367 --- /dev/null +++ b/apps/openmw/mwgui/videowidget.hpp @@ -0,0 +1,39 @@ +#ifndef OPENMW_MWGUI_VIDEOWIDGET_H +#define OPENMW_MWGUI_VIDEOWIDGET_H + +#include + +#include "../mwrender/videoplayer.hpp" + +namespace MWGui +{ + + /** + * Widget that plays a video. Can be skipped by pressing Esc. + */ + class VideoWidget : public MyGUI::ImageBox + { + public: + MYGUI_RTTI_DERIVED(VideoWidget) + + VideoWidget(); + + void playVideo (const std::string& video, bool allowSkipping); + + int getVideoWidth(); + int getVideoHeight(); + + /// @return Is the video still playing? + bool update(); + + private: + bool mAllowSkipping; + + MWRender::VideoPlayer mPlayer; + + void onKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char); + }; + +} + +#endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 1b71157a7..ca8459fa1 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "MyGUI_UString.h" #include "MyGUI_IPointer.h" @@ -59,6 +60,7 @@ #include "bookpage.hpp" #include "itemview.hpp" #include "fontloader.hpp" +#include "videowidget.hpp" namespace MWGui { @@ -104,6 +106,8 @@ namespace MWGui , mRecharge(NULL) , mRepair(NULL) , mCompanionWindow(NULL) + , mVideoBackground(NULL) + , mVideoWidget(NULL) , mTranslationDataStorage (translationDataStorage) , mCharGen(NULL) , mInputBlocker(NULL) @@ -155,6 +159,7 @@ namespace MWGui MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); + MyGUI::FactoryManager::getInstance().registerFactory("Widget"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); @@ -186,6 +191,13 @@ namespace MWGui // hide mygui's pointer MyGUI::PointerManager::getInstance().setVisible(false); + + mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Default, "Overlay"); + mVideoBackground->setImageTexture("black.png"); + mVideoBackground->setVisible(false); + + mVideoWidget = mVideoBackground->createWidgetReal("ImageBox", 0,0,1,1, MyGUI::Align::Default); } void WindowManager::initUI() @@ -391,6 +403,7 @@ namespace MWGui mCompanionWindow->setVisible(false); mInventoryWindow->setTrading(false); mRecharge->setVisible(false); + mVideoBackground->setVisible(false); mHud->setVisible(mHudEnabled); @@ -539,10 +552,6 @@ namespace MWGui setCursorVisible(false); break; - case GM_Video: - setCursorVisible(false); - mHud->setVisible(false); - break; default: // Unsupported mode, switch back to game break; @@ -894,6 +903,7 @@ namespace MWGui void WindowManager::windowResized(int x, int y) { + sizeVideo(x, y); mGuiManager->windowResized(); mLoadingScreen->onResChange (x,y); if (!mHud) @@ -1401,4 +1411,57 @@ namespace MWGui mMap->readRecord(reader, type); } + void WindowManager::playVideo(const std::string &name, bool allowSkipping) + { + mVideoWidget->playVideo("video\\" + name, allowSkipping); + + // Turn off all rendering except for the GUI + mRendering->getScene()->clearSpecialCaseRenderQueues(); + // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work? + for(int i = 0;i < Ogre::RENDER_QUEUE_MAX;++i) + { + if(i > 0 && i < 96) + mRendering->getScene()->addSpecialCaseRenderQueue(i); + } + mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); + + MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize(); + sizeVideo(screenSize.width, screenSize.height); + + setKeyFocusWidget(mVideoWidget); + + mVideoBackground->setVisible(true); + + bool cursorWasVisible = mCursorVisible; + setCursorVisible(false); + + while (mVideoWidget->update()) + { + MWBase::Environment::get().getInputManager()->update(0, false); + + mRendering->getWindow()->update(); + } + + setCursorVisible(cursorWasVisible); + + // Restore normal rendering + mRendering->getScene()->clearSpecialCaseRenderQueues(); + mRendering->getScene()->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); + + mVideoBackground->setVisible(false); + } + + void WindowManager::sizeVideo(int screenWidth, int screenHeight) + { + // Use black bars to correct aspect ratio + mVideoBackground->setSize(screenWidth, screenHeight); + + double imageaspect = static_cast(mVideoWidget->getVideoWidth())/mVideoWidget->getVideoHeight(); + + int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2); + int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2); + + mVideoWidget->setCoord(leftPadding, topPadding, + screenWidth - leftPadding*2, screenHeight - topPadding*2); + } } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index dafb65e47..ab9770a41 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -18,6 +18,7 @@ namespace MyGUI class Widget; class Window; class UString; + class ImageBox; } namespace Compiler @@ -80,6 +81,7 @@ namespace MWGui class SoulgemDialog; class Recharge; class CompanionWindow; + class VideoWidget; class WindowManager : public MWBase::WindowManager { @@ -98,6 +100,10 @@ namespace MWGui virtual Loading::Listener* getLoadingScreen(); + /// @note This method will block until the video finishes playing + /// (and will continually update the window while doing so) + virtual void playVideo(const std::string& name, bool allowSkipping); + /** * Should be called each frame to update windows/gui elements. * This could mean updating sizes of gui elements or opening @@ -332,6 +338,8 @@ namespace MWGui Repair* mRepair; Recharge* mRecharge; CompanionWindow* mCompanionWindow; + MyGUI::ImageBox* mVideoBackground; + VideoWidget* mVideoWidget; Translation::Storage& mTranslationDataStorage; Cursor* mSoftwareCursor; @@ -390,6 +398,8 @@ namespace MWGui void onCursorChange(const std::string& name); void onKeyFocusChanged(MyGUI::Widget* widget); + + void sizeVideo(int screenWidth, int screenHeight); }; } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 4bfd3f465..840a3f71a 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -626,9 +626,7 @@ namespace MWInput if (MyGUI::InputManager::getInstance ().isModalAny()) return; - if (MWBase::Environment::get().getWindowManager()->isGuiMode () && MWBase::Environment::get().getWindowManager()->getMode () == MWGui::GM_Video) - MWBase::Environment::get().getWorld ()->stopVideo (); - else if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) + if (MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu)) { MWBase::Environment::get().getWindowManager()->popGuiMode(); MWBase::Environment::get().getSoundManager()->resumeSounds (MWBase::SoundManager::Play_TypeSfx); diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 15d56b8a9..fa7b17a7c 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -43,7 +43,6 @@ #include "water.hpp" #include "npcanimation.hpp" #include "globalmap.hpp" -#include "videoplayer.hpp" #include "terrainstorage.hpp" #include "effectmanager.hpp" @@ -171,9 +170,6 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); - mVideoPlayer = new VideoPlayer(mRendering.getScene (), mRendering.getWindow()); - mVideoPlayer->setResolution (Settings::Manager::getInt ("resolution x", "Video"), Settings::Manager::getInt ("resolution y", "Video")); - mSun = 0; mDebugging = new Debugging(mRootNode, engine); @@ -197,7 +193,6 @@ RenderingManager::~RenderingManager () delete mLocalMap; delete mOcclusionQuery; delete mWater; - delete mVideoPlayer; delete mActors; delete mObjects; delete mEffectManager; @@ -333,8 +328,6 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr) void RenderingManager::update (float duration, bool paused) { - mVideoPlayer->update (); - if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) return; @@ -884,8 +877,6 @@ void RenderingManager::windowResized(int x, int y) Settings::Manager::setInt("resolution y", "Video", y); mRendering.adjustViewport(); - mVideoPlayer->setResolution (x, y); - MWBase::Environment::get().getWindowManager()->windowResized(x,y); } @@ -1001,16 +992,6 @@ void RenderingManager::screenshot(Image &image, int w, int h) mRendering.getCamera()->setAspectRatio(oldAspect); } -void RenderingManager::playVideo(const std::string& name, bool allowSkipping) -{ - mVideoPlayer->playVideo ("video/" + name, allowSkipping); -} - -void RenderingManager::stopVideo() -{ - mVideoPlayer->stopVideo (); -} - void RenderingManager::addWaterRippleEmitter (const MWWorld::Ptr& ptr, float scale, float force) { mWater->addEmitter (ptr, scale, force); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 115a94786..423a7078a 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -46,7 +46,6 @@ namespace MWRender class LocalMap; class Water; class GlobalMap; - class VideoPlayer; class Animation; class EffectManager; @@ -209,8 +208,6 @@ public: Animation* getAnimation(const MWWorld::Ptr &ptr); - void playVideo(const std::string& name, bool allowSkipping); - void stopVideo(); void frameStarted(float dt, bool paused); void screenshot(Ogre::Image& image, int w, int h); @@ -271,8 +268,6 @@ private: MWRender::LocalMap* mLocalMap; MWRender::Shadows* mShadows; - - VideoPlayer* mVideoPlayer; }; } diff --git a/apps/openmw/mwrender/videoplayer.cpp b/apps/openmw/mwrender/videoplayer.cpp index 7abc8140a..80704ca7c 100644 --- a/apps/openmw/mwrender/videoplayer.cpp +++ b/apps/openmw/mwrender/videoplayer.cpp @@ -17,7 +17,6 @@ #include -#include "../mwbase/windowmanager.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwsound/sound_decoder.hpp" @@ -126,7 +125,7 @@ struct VideoState { int stream_open(int stream_index, AVFormatContext *pFormatCtx); - bool update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height); + bool update(); static void video_thread_loop(VideoState *is); static void decode_thread_loop(VideoState *is); @@ -163,6 +162,7 @@ struct VideoState { static int OgreResource_Write(void *user_data, uint8_t *buf, int buf_size); static int64_t OgreResource_Seek(void *user_data, int64_t offset, int whence); + Ogre::TexturePtr mTexture; Ogre::DataStreamPtr stream; AVFormatContext* format_ctx; @@ -599,22 +599,17 @@ void VideoState::video_display() if((*this->video_st)->codec->width != 0 && (*this->video_st)->codec->height != 0) { - Ogre::TexturePtr texture = Ogre::TextureManager::getSingleton().getByName("VideoTexture"); - if(texture.isNull() || static_cast(texture->getWidth()) != (*this->video_st)->codec->width - || static_cast(texture->getHeight()) != (*this->video_st)->codec->height) + + if(static_cast(mTexture->getWidth()) != (*this->video_st)->codec->width || + static_cast(mTexture->getHeight()) != (*this->video_st)->codec->height) { - Ogre::TextureManager::getSingleton ().remove ("VideoTexture"); - texture = Ogre::TextureManager::getSingleton().createManual( - "VideoTexture", - Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, - Ogre::TEX_TYPE_2D, - (*this->video_st)->codec->width, (*this->video_st)->codec->height, - 0, - Ogre::PF_BYTE_RGBA, - Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + mTexture->unload(); + mTexture->setWidth((*this->video_st)->codec->width); + mTexture->setHeight((*this->video_st)->codec->height); + mTexture->createInternalResources(); } Ogre::PixelBox pb((*this->video_st)->codec->width, (*this->video_st)->codec->height, 1, Ogre::PF_BYTE_RGBA, &vp->data[0]); - Ogre::HardwarePixelBufferSharedPtr buffer = texture->getBuffer(); + Ogre::HardwarePixelBufferSharedPtr buffer = mTexture->getBuffer(); buffer->blitFromMemory(pb); this->display_ready = true; } @@ -851,7 +846,7 @@ void VideoState::decode_thread_loop(VideoState *self) } -bool VideoState::update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int screen_width, int screen_height) +bool VideoState::update() { if(this->quit) return false; @@ -860,21 +855,6 @@ bool VideoState::update(Ogre::MaterialPtr &mat, Ogre::Rectangle2D *rect, int scr { this->refresh = false; this->video_refresh_timer(); - // Would be nice not to do this all the time... - if(this->display_ready) - mat->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("VideoTexture"); - - // Correct aspect ratio by adding black bars - double videoaspect = av_q2d((*this->video_st)->codec->sample_aspect_ratio); - if(videoaspect == 0.0) - videoaspect = 1.0; - videoaspect *= static_cast((*this->video_st)->codec->width) / (*this->video_st)->codec->height; - - double screenaspect = static_cast(screen_width) / screen_height; - double aspect_correction = videoaspect / screenaspect; - - rect->setCorners(std::max(-1.0, -1.0 * aspect_correction), std::min( 1.0, 1.0 / aspect_correction), - std::min( 1.0, 1.0 * aspect_correction), std::max(-1.0, -1.0 / aspect_correction)); } return true; } @@ -1001,8 +981,29 @@ void VideoState::init(const std::string& resourceName) if(audio_index >= 0) this->stream_open(audio_index, this->format_ctx); if(video_index >= 0) + { this->stream_open(video_index, this->format_ctx); + int width = (*this->video_st)->codec->width; + int height = (*this->video_st)->codec->height; + static int i = 0; + this->mTexture = Ogre::TextureManager::getSingleton().createManual( + "OpenMW/VideoTexture" + Ogre::StringConverter::toString(++i), + Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, + Ogre::TEX_TYPE_2D, + width, height, // TEST + 0, + Ogre::PF_BYTE_RGBA, + Ogre::TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); + + // initialize to (0,0,0,0) + std::vector buffer; + buffer.resize(width * height, 0); + Ogre::PixelBox pb(width, height, 1, Ogre::PF_BYTE_RGBA, &buffer[0]); + this->mTexture->getBuffer()->blitFromMemory(pb); + } + + this->parse_thread = boost::thread(decode_thread_loop, this); } @@ -1073,111 +1074,26 @@ public: #endif // defined OPENMW_USE_FFMPEG -VideoPlayer::VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window) +VideoPlayer::VideoPlayer() : mState(NULL) - , mSceneMgr(sceneMgr) - , mRectangle(NULL) - , mNode(NULL) - , mAllowSkipping(false) - , mWindow(window) - , mWidth(0) - , mHeight(0) { - mVideoMaterial = Ogre::MaterialManager::getSingleton().getByName("VideoMaterial", "General"); - if (mVideoMaterial.isNull ()) - { - mVideoMaterial = Ogre::MaterialManager::getSingleton().create("VideoMaterial", "General"); - mVideoMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - mVideoMaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - mVideoMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); - mVideoMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(); - mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); - } - mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("black.png"); - Ogre::MaterialPtr blackMaterial = Ogre::MaterialManager::getSingleton().getByName("BlackBarsMaterial", "General"); - if (blackMaterial.isNull ()) - { - blackMaterial = Ogre::MaterialManager::getSingleton().create("BlackBarsMaterial", "General"); - blackMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false); - blackMaterial->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false); - blackMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); - blackMaterial->getTechnique(0)->getPass(0)->createTextureUnitState()->setTextureName("black.png"); - } - - mRectangle = new Ogre::Rectangle2D(true); - mRectangle->setCorners(-1.0, 1.0, 1.0, -1.0); - mRectangle->setMaterial("VideoMaterial"); - mRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY+2); - mBackgroundRectangle = new Ogre::Rectangle2D(true); - mBackgroundRectangle->setCorners(-1.0, 1.0, 1.0, -1.0); - mBackgroundRectangle->setMaterial("BlackBarsMaterial"); - mBackgroundRectangle->setRenderQueueGroup(Ogre::RENDER_QUEUE_OVERLAY+1); - - // Use infinite AAB to always stay visible - Ogre::AxisAlignedBox aabInf; - aabInf.setInfinite(); - mRectangle->setBoundingBox(aabInf); - mBackgroundRectangle->setBoundingBox(aabInf); - - // Attach background to the scene - mNode = sceneMgr->getRootSceneNode()->createChildSceneNode(); - mNode->attachObject(mRectangle); - mBackgroundNode = sceneMgr->getRootSceneNode()->createChildSceneNode(); - mBackgroundNode->attachObject(mBackgroundRectangle); - - mRectangle->setVisible(false); - mRectangle->setVisibilityFlags(RV_Overlay); - mBackgroundRectangle->setVisible(false); - mBackgroundRectangle->setVisibilityFlags(RV_Overlay); } VideoPlayer::~VideoPlayer() { if(mState) close(); - - mSceneMgr->destroySceneNode(mNode); - mSceneMgr->destroySceneNode(mBackgroundNode); - - delete mRectangle; - delete mBackgroundRectangle; } -void VideoPlayer::playVideo(const std::string &resourceName, bool allowSkipping) +void VideoPlayer::playVideo(const std::string &resourceName) { - mAllowSkipping = allowSkipping; - if(mState) close(); - mRectangle->setVisible(true); - mBackgroundRectangle->setVisible(true); - mVideoMaterial->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("black.png"); - - MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Video); - - // Turn off rendering except the GUI - mSceneMgr->clearSpecialCaseRenderQueues(); - // SCRQM_INCLUDE with RENDER_QUEUE_OVERLAY does not work. - for(int i = 0;i < Ogre::RENDER_QUEUE_MAX;++i) - { - if(i > 0 && i < 96) - mSceneMgr->addSpecialCaseRenderQueue(i); - } - mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); - try { mState = new VideoState; mState->init(resourceName); - - while (isPlaying()) - { - MWBase::Environment::get().getInputManager()->update(0, false); - update(); - mWindow->update(); - } - } catch(std::exception& e) { std::cerr<< "Failed to play video: "<update(mVideoMaterial, mRectangle, mWidth, mHeight)) + if(!mState->update()) close(); } } +std::string VideoPlayer::getTextureName() +{ + std::string name; + if (mState) + name = mState->mTexture->getName(); + return name; +} + +int VideoPlayer::getVideoWidth() +{ + int width=0; + if (mState) + width = mState->mTexture->getWidth(); + return width; +} + +int VideoPlayer::getVideoHeight() +{ + int height=0; + if (mState) + height = mState->mTexture->getHeight(); + return height; +} + void VideoPlayer::stopVideo () { - if (mAllowSkipping) - close(); + close(); } void VideoPlayer::close() @@ -1211,13 +1150,6 @@ void VideoPlayer::close() } MWBase::Environment::get().getSoundManager()->resumeSounds(); - - mRectangle->setVisible(false); - mBackgroundRectangle->setVisible(false); - MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Video); - - mSceneMgr->clearSpecialCaseRenderQueues(); - mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); } bool VideoPlayer::isPlaying () diff --git a/apps/openmw/mwrender/videoplayer.hpp b/apps/openmw/mwrender/videoplayer.hpp index 0e548e23e..47e252cc1 100644 --- a/apps/openmw/mwrender/videoplayer.hpp +++ b/apps/openmw/mwrender/videoplayer.hpp @@ -1,27 +1,22 @@ #ifndef VIDEOPLAYER_H #define VIDEOPLAYER_H -#include - -namespace Ogre -{ - class SceneManager; - class SceneNode; - class Rectangle2D; - class RenderWindow; -} +#include namespace MWRender { struct VideoState; + /** + * @brief Plays a video on an Ogre texture. + */ class VideoPlayer { public: - VideoPlayer(Ogre::SceneManager* sceneMgr, Ogre::RenderWindow* window); + VideoPlayer(); ~VideoPlayer(); - void playVideo (const std::string& resourceName, bool allowSkipping); + void playVideo (const std::string& resourceName); void update(); @@ -30,22 +25,14 @@ namespace MWRender bool isPlaying(); - void setResolution (int w, int h) { mWidth = w; mHeight = h; } + std::string getTextureName(); + int getVideoWidth(); + int getVideoHeight(); private: VideoState* mState; - bool mAllowSkipping; - - Ogre::SceneManager* mSceneMgr; - Ogre::MaterialPtr mVideoMaterial; - Ogre::Rectangle2D* mRectangle; - Ogre::Rectangle2D* mBackgroundRectangle; - Ogre::SceneNode* mNode; - Ogre::SceneNode* mBackgroundNode; - Ogre::RenderWindow* mWindow; - int mWidth; int mHeight; }; diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index fa8441aa5..89a5ceec1 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -47,7 +47,7 @@ namespace MWScript bool allowSkipping = runtime[0].mInteger; runtime.pop(); - MWBase::Environment::get().getWorld ()->playVideo (name, allowSkipping); + MWBase::Environment::get().getWindowManager()->playVideo (name, allowSkipping); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 62bdd38ea..f884f69af 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1305,7 +1305,7 @@ namespace MWWorld { --mPlayIntro; if (mPlayIntro == 0) - mRendering->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); + MWBase::Environment::get().getWindowManager()->playVideo(mFallback.getFallbackString("Movies_New_Game"), true); } if (mGoToJail && !paused) @@ -1776,16 +1776,6 @@ namespace MWWorld return mRendering->getAnimation(ptr); } - void World::playVideo (const std::string &name, bool allowSkipping) - { - mRendering->playVideo(name, allowSkipping); - } - - void World::stopVideo () - { - mRendering->stopVideo(); - } - void World::frameStarted (float dt, bool paused) { mRendering->frameStarted(dt, paused); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 42f52cb61..f1e89bf6b 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -523,8 +523,6 @@ namespace MWWorld virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr); /// \todo this does not belong here - virtual void playVideo(const std::string& name, bool allowSkipping); - virtual void stopVideo(); virtual void frameStarted (float dt, bool paused); virtual void screenshot (Ogre::Image& image, int w, int h); diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 8bd95e2cd..6f7736994 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -9,5 +9,6 @@ + From f2cd37edd0ee8903f0d4f2bd53214bf16a7290dd Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 19:51:48 +0100 Subject: [PATCH 15/18] Play company logo movie --- apps/openmw/engine.cpp | 18 ++++++------------ apps/openmw/mwbase/inputmanager.hpp | 2 +- apps/openmw/mwgui/loadingscreen.cpp | 2 +- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- apps/openmw/mwinput/inputmanagerimp.cpp | 16 ++++++++-------- apps/openmw/mwinput/inputmanagerimp.hpp | 2 +- files/mygui/openmw_layers.xml | 2 +- 7 files changed, 19 insertions(+), 25 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index a118152ed..f02432ba8 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -362,14 +362,9 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); - // TODO: play pre-load intro videos. Need to find a way to have them receive input. - // Make videoplayer a MyGUI widget? - /* - { - MWRender::VideoPlayer player(mOgre->getScene(), mOgre->getWindow()); - player.playVideo("mw_logo.bik", 1); - } - */ + std::string logo = mFallbackMap["Movies_Company_Logo"]; + if (!logo.empty()) + window->playVideo(logo, 1); // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, @@ -453,10 +448,9 @@ void OMW::Engine::go() // Is there an ini setting for this filename or something? MWBase::Environment::get().getSoundManager()->streamMusic("Special/morrowind title.mp3"); - // TODO: there are other intro videos, too. They need to be imported from Morrowind.ini. - // Unfortunately those must play BEFORE any loading is done, which will currently not work. - // The videoplayer is created by World, so all content files must be loaded first... - MWBase::Environment::get().getWindowManager()->playVideo("mw_logo.bik", true); + std::string logo = mFallbackMap["Movies_Morrowind_Logo"]; + if (!logo.empty()) + MWBase::Environment::get().getWindowManager()->playVideo(logo, true); } catch (...) {} } diff --git a/apps/openmw/mwbase/inputmanager.hpp b/apps/openmw/mwbase/inputmanager.hpp index 42922a5b3..d44da4974 100644 --- a/apps/openmw/mwbase/inputmanager.hpp +++ b/apps/openmw/mwbase/inputmanager.hpp @@ -25,7 +25,7 @@ namespace MWBase virtual ~InputManager() {} - virtual void update(float dt, bool loading) = 0; + virtual void update(float dt, bool disableControls, bool disableEvents=false) = 0; virtual void changeInputMode(bool guiMode) = 0; diff --git a/apps/openmw/mwgui/loadingscreen.cpp b/apps/openmw/mwgui/loadingscreen.cpp index 37e29591b..b3f70a5ab 100644 --- a/apps/openmw/mwgui/loadingscreen.cpp +++ b/apps/openmw/mwgui/loadingscreen.cpp @@ -226,7 +226,7 @@ namespace MWGui } mSceneMgr->setSpecialCaseRenderQueueMode(Ogre::SceneManager::SCRQM_EXCLUDE); - MWBase::Environment::get().getInputManager()->update(0, true); + MWBase::Environment::get().getInputManager()->update(0, true, true); // First, swap buffers from last draw, then, queue an update of the // window contents, but don't swap buffers (which would have diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ca8459fa1..1e019aaa9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1437,7 +1437,7 @@ namespace MWGui while (mVideoWidget->update()) { - MWBase::Environment::get().getInputManager()->update(0, false); + MWBase::Environment::get().getInputManager()->update(0, true, false); mRendering->getWindow()->update(); } diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 840a3f71a..e2d4f8cb2 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -96,12 +96,12 @@ namespace MWInput : mOgre(ogre) , mPlayer(NULL) , mEngine(engine) - , mMouseLookEnabled(true) + , mMouseLookEnabled(false) , mMouseX(ogre.getWindow()->getWidth ()/2.f) , mMouseY(ogre.getWindow()->getHeight ()/2.f) , mMouseWheel(0) , mDragDrop(false) - , mGuiCursorEnabled(false) + , mGuiCursorEnabled(true) , mUserFile(userFile) , mUserFileExists(userFileExists) , mInvertY (Settings::Manager::getBool("invert y axis", "Input")) @@ -256,18 +256,21 @@ namespace MWInput } } - void InputManager::update(float dt, bool loading) + void InputManager::update(float dt, bool disableControls, bool disableEvents) { mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible()); - mInputManager->capture(loading); + mInputManager->capture(disableEvents); // inject some fake mouse movement to force updating MyGUI's widget states MyGUI::InputManager::getInstance().injectMouseMove( int(mMouseX), int(mMouseY), mMouseWheel); // update values of channels (as a result of pressed keys) - if (!loading) + if (!disableControls) mInputBinder->update(dt); + if (disableControls) + return; + bool grab = !MWBase::Environment::get().getWindowManager()->containsMode(MWGui::GM_MainMenu) && MWBase::Environment::get().getWindowManager()->getMode() != MWGui::GM_Console; @@ -288,9 +291,6 @@ namespace MWInput mInputManager->warpMouse(mMouseX, mMouseY); } - if (loading) - return; - // Disable movement in Gui mode if (MWBase::Environment::get().getWindowManager()->isGuiMode() || MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_Running) diff --git a/apps/openmw/mwinput/inputmanagerimp.hpp b/apps/openmw/mwinput/inputmanagerimp.hpp index 2eab03a34..87fbda25c 100644 --- a/apps/openmw/mwinput/inputmanagerimp.hpp +++ b/apps/openmw/mwinput/inputmanagerimp.hpp @@ -68,7 +68,7 @@ namespace MWInput /// Clear all savegame-specific data virtual void clear(); - virtual void update(float dt, bool loading); + virtual void update(float dt, bool disableControls, bool disableEvents=false); void setPlayer (MWWorld::Player* player) { mPlayer = player; } diff --git a/files/mygui/openmw_layers.xml b/files/mygui/openmw_layers.xml index 6f7736994..e66f3fc01 100644 --- a/files/mygui/openmw_layers.xml +++ b/files/mygui/openmw_layers.xml @@ -9,6 +9,6 @@ - + From 4f852daf45cfd9ee5e199edd25b924909e08f103 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 19:59:33 +0100 Subject: [PATCH 16/18] Don't play company logo when using --skip-menu --- apps/openmw/engine.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f02432ba8..508b195e9 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -362,9 +362,12 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings) // Create sound system mEnvironment.setSoundManager (new MWSound::SoundManager(mUseSound)); - std::string logo = mFallbackMap["Movies_Company_Logo"]; - if (!logo.empty()) - window->playVideo(logo, 1); + if (!mSkipMenu) + { + std::string logo = mFallbackMap["Movies_Company_Logo"]; + if (!logo.empty()) + window->playVideo(logo, 1); + } // Create the world mEnvironment.setWorld( new MWWorld::World (*mOgre, mFileCollections, mContentFiles, From ea357cfed086154766808d54da9d62db9da9eb14 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 20:39:56 +0100 Subject: [PATCH 17/18] Fix crash when resizing while company logo is playing --- libs/openengine/ogre/renderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/openengine/ogre/renderer.cpp b/libs/openengine/ogre/renderer.cpp index c816f2060..5f9578988 100644 --- a/libs/openengine/ogre/renderer.cpp +++ b/libs/openengine/ogre/renderer.cpp @@ -157,5 +157,6 @@ void OgreRenderer::setFov(float fov) void OgreRenderer::windowResized(int x, int y) { - mWindowListener->windowResized(x,y); + if (mWindowListener) + mWindowListener->windowResized(x,y); } From d7df9cae21dd4946901f01769a5f4f702cc01d09 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 22:32:42 +0100 Subject: [PATCH 18/18] Bug #1224: Changed fix to potentially allow for language independent saves --- apps/openmw/mwgui/savegamedialog.cpp | 16 +++++++++++++++- apps/openmw/mwstate/statemanagerimp.cpp | 7 ++++++- apps/openmw/mwworld/store.hpp | 8 ++++++++ components/esm/savedgame.cpp | 12 ++++++++++-- components/esm/savedgame.hpp | 11 ++++++----- 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 6971358c1..caa082646 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -86,7 +86,21 @@ namespace MWGui { std::stringstream title; title << it->getSignature().mPlayerName; - title << " (Level " << it->getSignature().mPlayerLevel << " " << it->getSignature().mPlayerClassName << ")"; + + // For a custom class, we will not find it in the store (unless we loaded the savegame first). + // Fall back to name stored in savegame header in that case. + std::string className; + if (it->getSignature().mPlayerClassId.empty()) + className = it->getSignature().mPlayerClassName; + else + { + // Find the localised name for this class from the store + const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().find( + it->getSignature().mPlayerClassId); + className = class_->mName; + } + + title << " (Level " << it->getSignature().mPlayerLevel << " " << className << ")"; mCharacterSelection->addItem (title.str()); diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index a0d482f0a..7793cc960 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -155,7 +155,12 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot profile.mPlayerName = player.getClass().getName (player); profile.mPlayerLevel = player.getClass().getNpcStats (player).getLevel(); - profile.mPlayerClassName = world.getStore().get().find(player.get()->mBase->mClass)->mName; + + std::string classId = player.get()->mBase->mClass; + if (world.getStore().get().isDynamic(classId)) + profile.mPlayerClassName = world.getStore().get().find(classId)->mName; + else + profile.mPlayerClassId = classId; profile.mPlayerCell = world.getCellName(); diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 6b99c0a0c..0fc2d547c 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -157,6 +157,14 @@ namespace MWWorld return 0; } + /** + * Does the record with this ID come from the dynamic store? + */ + bool isDynamic(const std::string &id) const { + typename Dynamic::const_iterator dit = mDynamic.find(id); + return (dit != mDynamic.end()); + } + /** Returns a random record that starts with the named ID, or NULL if not found. */ const T *searchRandom(const std::string &id) const { diff --git a/components/esm/savedgame.cpp b/components/esm/savedgame.cpp index 813865e25..b5e0810db 100644 --- a/components/esm/savedgame.cpp +++ b/components/esm/savedgame.cpp @@ -11,7 +11,10 @@ void ESM::SavedGame::load (ESMReader &esm) { mPlayerName = esm.getHNString("PLNA"); esm.getHNOT (mPlayerLevel, "PLLE"); - mPlayerClassName = esm.getHNString("PLCL"); + + mPlayerClassId = esm.getHNOString("PLCL"); + mPlayerClassName = esm.getHNOString("PLCN"); + mPlayerCell = esm.getHNString("PLCE"); esm.getHNT (mInGameTime, "TSTM", 16); esm.getHNT (mTimePlayed, "TIME"); @@ -30,7 +33,12 @@ void ESM::SavedGame::save (ESMWriter &esm) const { esm.writeHNString ("PLNA", mPlayerName); esm.writeHNT ("PLLE", mPlayerLevel); - esm.writeHNString ("PLCL", mPlayerClassName); + + if (!mPlayerClassId.empty()) + esm.writeHNString ("PLCL", mPlayerClassId); + else + esm.writeHNString ("PLCN", mPlayerClassName); + esm.writeHNString ("PLCE", mPlayerCell); esm.writeHNT ("TSTM", mInGameTime, 16); esm.writeHNT ("TIME", mTimePlayed); diff --git a/components/esm/savedgame.hpp b/components/esm/savedgame.hpp index b8615a6bc..3e7cae775 100644 --- a/components/esm/savedgame.hpp +++ b/components/esm/savedgame.hpp @@ -26,12 +26,13 @@ namespace ESM std::vector mContentFiles; std::string mPlayerName; int mPlayerLevel; - // The (translated) name of the player class. So it will be displayed in the MW language - // the savegame was made in, not the currently running language of MW. - // However, savegames from a different MW language are not compatible anyway. - // And if only the ID was stored here, we would need to - // peek into the savegame to look for a class record in case it is a custom class. + + // ID of class + std::string mPlayerClassId; + // Name of the class. When using a custom class, the ID is not really meaningful prior + // to loading the savegame, so the name is stored separately. std::string mPlayerClassName; + std::string mPlayerCell; TimeStamp mInGameTime; double mTimePlayed;