From 2e4ef93b28630f6f2ec8ccbe7eb2627e3912d6d1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 27 Mar 2014 04:15:47 +0100 Subject: [PATCH] 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 @@ - +