#include "windowmanagerimp.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Start of tes3mp addition Include additional headers for multiplayer purposes */ #include #include "../mwmp/Main.hpp" #include "../mwmp/GUIController.hpp" /* End of tes3mp addition */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../mwbase/inputmanager.hpp" #include "../mwbase/statemanager.hpp" #include "../mwbase/soundmanager.hpp" #include "../mwrender/vismask.hpp" #include "../mwworld/class.hpp" #include "../mwworld/player.hpp" #include "../mwworld/cellstore.hpp" #include "../mwworld/esmstore.hpp" #include "../mwmechanics/stat.hpp" #include "../mwmechanics/npcstats.hpp" #include "../mwmechanics/actorutil.hpp" #include "../mwrender/localmap.hpp" #include "console.hpp" #include "journalwindow.hpp" #include "journalviewmodel.hpp" #include "charactercreation.hpp" #include "dialogue.hpp" #include "statswindow.hpp" #include "messagebox.hpp" #include "tooltips.hpp" #include "scrollwindow.hpp" #include "bookwindow.hpp" #include "hud.hpp" #include "mainmenu.hpp" #include "countdialog.hpp" #include "tradewindow.hpp" #include "spellbuyingwindow.hpp" #include "travelwindow.hpp" #include "settingswindow.hpp" #include "confirmationdialog.hpp" #include "alchemywindow.hpp" #include "spellwindow.hpp" #include "quickkeysmenu.hpp" #include "loadingscreen.hpp" #include "levelupdialog.hpp" #include "waitdialog.hpp" #include "enchantingdialog.hpp" #include "trainingwindow.hpp" #include "recharge.hpp" #include "exposedwindow.hpp" #include "cursor.hpp" #include "merchantrepair.hpp" #include "repair.hpp" #include "soulgemdialog.hpp" #include "companionwindow.hpp" #include "inventorywindow.hpp" #include "bookpage.hpp" #include "itemview.hpp" #include "videowidget.hpp" #include "backgroundimage.hpp" #include "itemwidget.hpp" #include "screenfader.hpp" #include "debugwindow.hpp" #include "spellview.hpp" #include "draganddrop.hpp" #include "container.hpp" #include "controllers.hpp" #include "jailscreen.hpp" #include "itemchargeview.hpp" #include "keyboardnavigation.hpp" namespace { MyGUI::Colour getTextColour(const std::string& type) { return MyGUI::Colour::parse(MyGUI::LanguageManager::getInstance().replaceTags("#{fontcolour=" + type + "}")); } } namespace MWGui { WindowManager::WindowManager( osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map& fallbackMap, const std::string& versionDescription) : mStore(NULL) , mResourceSystem(resourceSystem) , mWorkQueue(workQueue) , mViewer(viewer) , mConsoleOnlyScripts(consoleOnlyScripts) , mCurrentModals() , mHud(NULL) , mMap(NULL) , mLocalMapRender(NULL) , mToolTips(NULL) , mStatsWindow(NULL) , mMessageBoxManager(NULL) , mConsole(NULL) , mDialogueWindow(NULL) , mDragAndDrop(NULL) , mInventoryWindow(NULL) , mScrollWindow(NULL) , mBookWindow(NULL) , mCountDialog(NULL) , mTradeWindow(NULL) , mSettingsWindow(NULL) , mConfirmationDialog(NULL) , mSpellWindow(NULL) , mQuickKeysMenu(NULL) , mLoadingScreen(NULL) , mWaitDialog(NULL) , mSoulgemDialog(NULL) , mVideoBackground(NULL) , mVideoWidget(NULL) , mWerewolfFader(NULL) , mBlindnessFader(NULL) , mHitFader(NULL) , mScreenFader(NULL) , mDebugWindow(NULL) , mJailScreen(NULL) , mTranslationDataStorage (translationDataStorage) , mCharGen(NULL) , mInputBlocker(NULL) , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) , mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI")) , mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI")) , mHudEnabled(true) , mCursorVisible(true) , mCursorActive(false) , mPlayerName() , mPlayerRaceId() , mPlayerAttributes() , mPlayerMajorSkills() , mPlayerMinorSkills() , mPlayerSkillValues() , mGui(NULL) , mGuiModes() , mCursorManager(NULL) , mGarbageDialogs() , mShown(GW_ALL) , mForceHidden(GW_None) , mAllowed(GW_ALL) , mRestAllowed(true) , mFallbackMap(fallbackMap) , mShowOwned(0) , mEncoding(encoding) , mVersionDescription(versionDescription) { float uiScale = Settings::Manager::getFloat("scaling factor", "GUI"); mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), uiScale); mGuiPlatform->initialise(resourcePath, logpath); mGui = new MyGUI::Gui; mGui->initialise(""); createTextures(); MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); // Load fonts mFontLoader.reset(new Gui::FontLoader(encoding, resourceSystem->getVFS())); mFontLoader->loadAllFonts(exportFonts); //Register own widgets with MyGUI MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Widget"); MyGUI::FactoryManager::getInstance().registerFactory("Layer"); MyGUI::FactoryManager::getInstance().registerFactory("Layer"); BookPage::registerMyGUIComponents (); ItemView::registerComponents(); ItemChargeView::registerComponents(); ItemWidget::registerComponents(); SpellView::registerComponents(); Gui::registerAllWidgets(); MyGUI::FactoryManager::getInstance().registerFactory("Controller"); MyGUI::FactoryManager::getInstance().registerFactory("Controller"); MyGUI::FactoryManager::getInstance().registerFactory("Resource", "ResourceImageSetPointer"); MyGUI::ResourceManager::getInstance().load("core.xml"); bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI"); mKeyboardNavigation.reset(new KeyboardNavigation()); mKeyboardNavigation->setEnabled(keyboardNav); Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav); mLoadingScreen = new LoadingScreen(mResourceSystem->getVFS(), mViewer); mWindows.push_back(mLoadingScreen); //set up the hardware cursor manager mCursorManager = new SDLUtil::SDLCursorManager(); MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); // Create all cursors in advance createCursors(); onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); mCursorManager->setEnabled(true); // hide mygui's pointer MyGUI::PointerManager::getInstance().setVisible(false); mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, MyGUI::Align::Default, "InputBlocker"); mVideoBackground->setImageTexture("black"); mVideoBackground->setVisible(false); mVideoBackground->setNeedMouseFocus(true); mVideoBackground->setNeedKeyFocus(true); mVideoWidget = mVideoBackground->createWidgetReal("ImageBox", 0,0,1,1, MyGUI::Align::Default); mVideoWidget->setNeedMouseFocus(true); mVideoWidget->setNeedKeyFocus(true); mVideoWidget->setVFS(resourceSystem->getVFS()); // Removes default MyGUI system clipboard implementation, which supports windows only MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardChanged += MyGUI::newDelegate(this, &WindowManager::onClipboardChanged); MyGUI::ClipboardManager::getInstance().eventClipboardRequested += MyGUI::newDelegate(this, &WindowManager::onClipboardRequested); mShowOwned = Settings::Manager::getInt("show owned", "Game"); } void WindowManager::initUI() { // Get size info from the Gui object int w = MyGUI::RenderManager::getInstance().getViewSize().width; int h = MyGUI::RenderManager::getInstance().getViewSize().height; mTextColours.header = getTextColour("header"); mTextColours.normal = getTextColour("normal"); mTextColours.notify = getTextColour("notify"); mTextColours.link = getTextColour("link"); mTextColours.linkOver = getTextColour("link_over"); mTextColours.linkPressed = getTextColour("link_pressed"); mTextColours.answer = getTextColour("answer"); mTextColours.answerOver = getTextColour("answer_over"); mTextColours.answerPressed = getTextColour("answer_pressed"); mTextColours.journalLink = getTextColour("journal_link"); mTextColours.journalLinkOver = getTextColour("journal_link_over"); mTextColours.journalLinkPressed = getTextColour("journal_link_pressed"); mTextColours.journalTopic = getTextColour("journal_topic"); mTextColours.journalTopicOver = getTextColour("journal_topic_over"); mTextColours.journalTopicPressed = getTextColour("journal_topic_pressed"); mDragAndDrop = new DragAndDrop(); Recharge* recharge = new Recharge(); mGuiModeStates[GM_Recharge] = GuiModeState(recharge); mWindows.push_back(recharge); MainMenu* menu = new MainMenu(w, h, mResourceSystem->getVFS(), mVersionDescription); mGuiModeStates[GM_MainMenu] = GuiModeState(menu); mWindows.push_back(menu); mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup()); mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue); mWindows.push_back(mMap); mMap->renderGlobalMap(); trackWindow(mMap, "map"); mStatsWindow = new StatsWindow(mDragAndDrop); mWindows.push_back(mStatsWindow); trackWindow(mStatsWindow, "stats"); mInventoryWindow = new InventoryWindow(mDragAndDrop, mViewer->getSceneData()->asGroup(), mResourceSystem); mWindows.push_back(mInventoryWindow); mSpellWindow = new SpellWindow(mDragAndDrop); mWindows.push_back(mSpellWindow); trackWindow(mSpellWindow, "spells"); mGuiModeStates[GM_Inventory] = GuiModeState({mMap, mInventoryWindow, mSpellWindow, mStatsWindow}); mGuiModeStates[GM_None] = GuiModeState({mMap, mInventoryWindow, mSpellWindow, mStatsWindow}); mTradeWindow = new TradeWindow(); mWindows.push_back(mTradeWindow); trackWindow(mTradeWindow, "barter"); mGuiModeStates[GM_Barter] = GuiModeState({mInventoryWindow, mTradeWindow}); mConsole = new Console(w,h, mConsoleOnlyScripts); mWindows.push_back(mConsole); trackWindow(mConsole, "console"); mGuiModeStates[GM_Console] = GuiModeState(mConsole); bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds"); JournalWindow* journal = JournalWindow::create(JournalViewModel::create (), questList, mEncoding); mWindows.push_back(journal); mGuiModeStates[GM_Journal] = GuiModeState(journal); mGuiModeStates[GM_Journal].mCloseSound = "book close"; mGuiModeStates[GM_Journal].mOpenSound = "book open"; mMessageBoxManager = new MessageBoxManager(mStore->get().find("fMessageTimePerChar")->getFloat()); SpellBuyingWindow* spellBuyingWindow = new SpellBuyingWindow(); mWindows.push_back(spellBuyingWindow); mGuiModeStates[GM_SpellBuying] = GuiModeState(spellBuyingWindow); TravelWindow* travelWindow = new TravelWindow(); mWindows.push_back(travelWindow); mGuiModeStates[GM_Travel] = GuiModeState(travelWindow); mDialogueWindow = new DialogueWindow(); mWindows.push_back(mDialogueWindow); trackWindow(mDialogueWindow, "dialogue"); mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow); mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete); /* Start of tes3mp change (major) Use a member variable (mContainerWIndow) instead of a local one so we can access it from elsewhere */ mContainerWindow = new ContainerWindow(mDragAndDrop); mWindows.push_back(mContainerWindow); trackWindow(mContainerWindow, "container"); mGuiModeStates[GM_Container] = GuiModeState({mContainerWindow, mInventoryWindow}); /* End of tes3mp change (major) */ mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender); mWindows.push_back(mHud); mToolTips = new ToolTips(); mScrollWindow = new ScrollWindow(); mWindows.push_back(mScrollWindow); mGuiModeStates[GM_Scroll] = GuiModeState(mScrollWindow); mGuiModeStates[GM_Scroll].mOpenSound = "scroll"; mGuiModeStates[GM_Scroll].mCloseSound = "scroll"; mBookWindow = new BookWindow(); mWindows.push_back(mBookWindow); mGuiModeStates[GM_Book] = GuiModeState(mBookWindow); mGuiModeStates[GM_Book].mOpenSound = "book open"; mGuiModeStates[GM_Book].mCloseSound = "book close"; mCountDialog = new CountDialog(); mWindows.push_back(mCountDialog); mSettingsWindow = new SettingsWindow(); mWindows.push_back(mSettingsWindow); mGuiModeStates[GM_Settings] = GuiModeState(mSettingsWindow); mConfirmationDialog = new ConfirmationDialog(); mWindows.push_back(mConfirmationDialog); AlchemyWindow* alchemyWindow = new AlchemyWindow(); mWindows.push_back(alchemyWindow); trackWindow(alchemyWindow, "alchemy"); mGuiModeStates[GM_Alchemy] = GuiModeState(alchemyWindow); mQuickKeysMenu = new QuickKeysMenu(); mWindows.push_back(mQuickKeysMenu); mGuiModeStates[GM_QuickKeysMenu] = GuiModeState(mQuickKeysMenu); LevelupDialog* levelupDialog = new LevelupDialog(); mWindows.push_back(levelupDialog); mGuiModeStates[GM_Levelup] = GuiModeState(levelupDialog); mWaitDialog = new WaitDialog(); mWindows.push_back(mWaitDialog); mGuiModeStates[GM_Rest] = GuiModeState({mWaitDialog->getProgressBar(), mWaitDialog}); SpellCreationDialog* spellCreationDialog = new SpellCreationDialog(); mWindows.push_back(spellCreationDialog); mGuiModeStates[GM_SpellCreation] = GuiModeState(spellCreationDialog); EnchantingDialog* enchantingDialog = new EnchantingDialog(); mWindows.push_back(enchantingDialog); mGuiModeStates[GM_Enchanting] = GuiModeState(enchantingDialog); TrainingWindow* trainingWindow = new TrainingWindow(); mWindows.push_back(trainingWindow); mGuiModeStates[GM_Training] = GuiModeState({trainingWindow->getProgressBar(), trainingWindow}); MerchantRepair* merchantRepair = new MerchantRepair(); mWindows.push_back(merchantRepair); mGuiModeStates[GM_MerchantRepair] = GuiModeState(merchantRepair); Repair* repair = new Repair(); mWindows.push_back(repair); mGuiModeStates[GM_Repair] = GuiModeState(repair); mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); CompanionWindow* companionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); mWindows.push_back(companionWindow); trackWindow(companionWindow, "companion"); mGuiModeStates[GM_Companion] = GuiModeState({mInventoryWindow, companionWindow}); mJailScreen = new JailScreen(); mWindows.push_back(mJailScreen); mGuiModeStates[GM_Jail] = GuiModeState(mJailScreen); std::string werewolfFaderTex = "textures\\werewolfoverlay.dds"; if (mResourceSystem->getVFS()->exists(werewolfFaderTex)) { mWerewolfFader = new ScreenFader(werewolfFaderTex); mWindows.push_back(mWerewolfFader); } mBlindnessFader = new ScreenFader("black"); mWindows.push_back(mBlindnessFader); // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available std::string hitFaderTexture = "textures\\bm_player_hit_01.dds"; const std::string hitFaderLayout = "openmw_screen_fader_hit.layout"; MyGUI::FloatCoord hitFaderCoord (0,0,1,1); if(!mResourceSystem->getVFS()->exists(hitFaderTexture)) { hitFaderTexture = "textures\\player_hit_01.dds"; hitFaderCoord = MyGUI::FloatCoord(0.2, 0.25, 0.6, 0.5); } mHitFader = new ScreenFader(hitFaderTexture, hitFaderLayout, hitFaderCoord); mWindows.push_back(mHitFader); mScreenFader = new ScreenFader("black"); mWindows.push_back(mScreenFader); mDebugWindow = new DebugWindow(); mWindows.push_back(mDebugWindow); mInputBlocker = MyGUI::Gui::getInstance().createWidget("",0,0,w,h,MyGUI::Align::Stretch,"InputBlocker"); mHud->setVisible(true); mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); // Setup player stats for (int i = 0; i < ESM::Attribute::Length; ++i) { mPlayerAttributes.insert(std::make_pair(ESM::Attribute::sAttributeIds[i], MWMechanics::AttributeValue())); } for (int i = 0; i < ESM::Skill::Length; ++i) { mPlayerSkillValues.insert(std::make_pair(ESM::Skill::sSkillIds[i], MWMechanics::SkillValue())); } updatePinnedWindows(); // Set up visibility updateVisible(); } void WindowManager::setNewGame(bool newgame) { if (newgame) { disallowAll(); delete mCharGen; mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); } else allow(GW_ALL); } WindowManager::~WindowManager() { mKeyboardNavigation.reset(); MyGUI::LanguageManager::getInstance().eventRequestTag.clear(); MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear(); MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear(); MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear(); for (WindowBase* window : mWindows) delete window; mWindows.clear(); delete mMessageBoxManager; delete mLocalMapRender; delete mCharGen; delete mDragAndDrop; delete mSoulgemDialog; delete mCursorManager; delete mToolTips; cleanupGarbage(); mFontLoader.reset(); mGui->shutdown(); delete mGui; mGuiPlatform->shutdown(); delete mGuiPlatform; } void WindowManager::setStore(const MWWorld::ESMStore &store) { mStore = &store; } void WindowManager::cleanupGarbage() { // Delete any dialogs which are no longer in use if (!mGarbageDialogs.empty()) { for (std::vector::iterator it = mGarbageDialogs.begin(); it != mGarbageDialogs.end(); ++it) { delete *it; } mGarbageDialogs.clear(); } } void WindowManager::updateVisible() { if (!mMap) return; // UI not created yet bool loading = (getMode() == GM_Loading || getMode() == GM_LoadingWallpaper); mHud->setVisible(mHudEnabled && !loading); mToolTips->setVisible(mHudEnabled && !loading); bool gameMode = !isGuiMode(); MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); mInputBlocker->setVisible (gameMode); if (loading) setCursorVisible(mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); else setCursorVisible(!gameMode); if (gameMode) setKeyFocusWidget (NULL); // Icons of forced hidden windows are displayed setMinimapVisibility((mAllowed & GW_Map) && (!mMap->pinned() || (mForceHidden & GW_Map))); setWeaponVisibility((mAllowed & GW_Inventory) && (!mInventoryWindow->pinned() || (mForceHidden & GW_Inventory))); setSpellVisibility((mAllowed & GW_Magic) && (!mSpellWindow->pinned() || (mForceHidden & GW_Magic))); setHMSVisibility((mAllowed & GW_Stats) && (!mStatsWindow->pinned() || (mForceHidden & GW_Stats))); mInventoryWindow->setGuiMode(getMode()); // If in game mode (or interactive messagebox), show the pinned windows if (mGuiModes.empty()) { mMap->setVisible(mMap->pinned() && !(mForceHidden & GW_Map) && (mAllowed & GW_Map)); mStatsWindow->setVisible(mStatsWindow->pinned() && !(mForceHidden & GW_Stats) && (mAllowed & GW_Stats)); mInventoryWindow->setVisible(mInventoryWindow->pinned() && !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory)); mSpellWindow->setVisible(mSpellWindow->pinned() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic)); return; } else if (getMode() != GM_Inventory) { mMap->setVisible(false); mStatsWindow->setVisible(false); mSpellWindow->setVisible(false); mInventoryWindow->setVisible(getMode() == GM_Container || getMode() == GM_Barter || getMode() == GM_Companion); } GuiMode mode = mGuiModes.back(); mInventoryWindow->setTrading(mode == GM_Barter); if (getMode() == GM_Inventory) { // For the inventory mode, compute the effective set of windows to show. // This is controlled both by what windows the // user has opened/closed (the 'shown' variable) and by what // windows we are allowed to show (the 'allowed' var.) int eff = mShown & mAllowed & ~mForceHidden; mMap->setVisible(eff & GW_Map); mInventoryWindow->setVisible(eff & GW_Inventory); mSpellWindow->setVisible(eff & GW_Magic); mStatsWindow->setVisible(eff & GW_Stats); } switch (mode) { // FIXME: refactor chargen windows to use modes properly (or not use them at all) case GM_Name: case GM_Race: case GM_Class: case GM_ClassPick: case GM_ClassCreate: case GM_Birth: case GM_ClassGenerate: case GM_Review: mCharGen->spawnDialog(mode); break; default: /* Start of tes3mp addition Pass the GuiMode further on to the multiplayer-specific GUI controller */ mwmp::Main::get().getGUIController()->WM_UpdateVisible(mode); /* End of tes3mp addition */ break; } } void WindowManager::setValue (const std::string& id, const MWMechanics::AttributeValue& value) { mStatsWindow->setValue (id, value); mCharGen->setValue(id, value); static const char *ids[] = { "AttribVal1", "AttribVal2", "AttribVal3", "AttribVal4", "AttribVal5", "AttribVal6", "AttribVal7", "AttribVal8" }; static ESM::Attribute::AttributeID attributes[] = { ESM::Attribute::Strength, ESM::Attribute::Intelligence, ESM::Attribute::Willpower, ESM::Attribute::Agility, ESM::Attribute::Speed, ESM::Attribute::Endurance, ESM::Attribute::Personality, ESM::Attribute::Luck }; for (size_t i = 0; i < sizeof(ids)/sizeof(ids[0]); ++i) { if (id != ids[i]) continue; mPlayerAttributes[attributes[i]] = value; break; } } void WindowManager::setValue (int parSkill, const MWMechanics::SkillValue& value) { /// \todo Don't use the skill enum as a parameter type (we will have to drop it anyway, once we /// allow custom skills. mStatsWindow->setValue(static_cast (parSkill), value); mCharGen->setValue(static_cast (parSkill), value); mPlayerSkillValues[parSkill] = value; } void WindowManager::setValue (const std::string& id, const MWMechanics::DynamicStat& value) { mStatsWindow->setValue (id, value); mHud->setValue (id, value); mCharGen->setValue(id, value); } void WindowManager::setValue (const std::string& id, const std::string& value) { mStatsWindow->setValue (id, value); if (id=="name") mPlayerName = value; else if (id=="race") mPlayerRaceId = value; } void WindowManager::setValue (const std::string& id, int value) { mStatsWindow->setValue (id, value); } void WindowManager::setDrowningTimeLeft (float time, float maxTime) { mHud->setDrowningTimeLeft(time, maxTime); } void WindowManager::setPlayerClass (const ESM::Class &class_) { mStatsWindow->setValue("class", class_.mName); } void WindowManager::configureSkills (const SkillList& major, const SkillList& minor) { mStatsWindow->configureSkills (major, minor); mCharGen->configureSkills(major, minor); mPlayerMajorSkills = major; mPlayerMinorSkills = minor; } void WindowManager::updateSkillArea() { mStatsWindow->updateSkillArea(); } void WindowManager::removeDialog(Layout*dialog) { if (!dialog) return; dialog->setVisible(false); mGarbageDialogs.push_back(dialog); } void WindowManager::exitCurrentGuiMode() { if (mDragAndDrop && mDragAndDrop->mIsOnDragAndDrop) { mDragAndDrop->finish(); return; } GuiModeState& state = mGuiModeStates[mGuiModes.back()]; for (WindowBase* window : state.mWindows) { if (!window->exit()) { // unable to exit window, but give access to main menu if (!MyGUI::InputManager::getInstance().isModalAny() && getMode() != GM_MainMenu) pushGuiMode (GM_MainMenu); return; } } popGuiMode(); } void WindowManager::interactiveMessageBox(const std::string &message, const std::vector &buttons, bool block) { mMessageBoxManager->createInteractiveMessageBox(message, buttons); updateVisible(); if (block) { osg::Timer frameTimer; while (mMessageBoxManager->readPressedButton(false) == -1 && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) { double dt = frameTimer.time_s(); frameTimer.setStartTick(); mKeyboardNavigation->onFrame(); mMessageBoxManager->onFrame(dt); MWBase::Environment::get().getInputManager()->update(dt, true, false); if (!MWBase::Environment::get().getInputManager()->isWindowVisible()) OpenThreads::Thread::microSleep(5000); else { mViewer->eventTraversal(); mViewer->updateTraversal(); mViewer->renderingTraversals(); } // at the time this function is called we are in the middle of a frame, // so out of order calls are necessary to get a correct frameNumber for the next frame. // refer to the advance() and frame() order in Engine::go() mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); MWBase::Environment::get().limitFrameRate(frameTimer.time_s()); } } } void WindowManager::messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode) { if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never) { mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); } else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only) { mMessageBoxManager->createMessageBox(message); } } void WindowManager::staticMessageBox(const std::string& message) { mMessageBoxManager->createMessageBox(message, true); } void WindowManager::removeStaticMessageBox() { mMessageBoxManager->removeStaticMessageBox(); } int WindowManager::readPressedButton () { return mMessageBoxManager->readPressedButton(); } /* Start of tes3mp addition Allow the reading of a pressed button without resetting it */ int WindowManager::readPressedButton(bool reset) { return mMessageBoxManager->readPressedButton(reset); } /* End of tes3mp addition */ std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_) { const ESM::GameSetting *setting = mStore->get().search(id); if (setting && setting->mValue.getType()==ESM::VT_String) return setting->mValue.getString(); return default_; } void WindowManager::updateMap() { if (!mLocalMapRender) return; MWWorld::ConstPtr player = MWMechanics::getPlayer(); osg::Vec3f playerPosition = player.getRefData().getPosition().asVec3(); osg::Quat playerOrientation (-player.getRefData().getPosition().rot[2], osg::Vec3(0,0,1)); osg::Vec3f playerdirection; int x,y; float u,v; mLocalMapRender->updatePlayer(playerPosition, playerOrientation, u, v, x, y, playerdirection); if (!player.getCell()->isExterior()) { setActiveMap(x, y, true); } // else: need to know the current grid center, call setActiveMap from changeCell mMap->setPlayerDir(playerdirection.x(), playerdirection.y()); mMap->setPlayerPos(x, y, u, v); mHud->setPlayerDir(playerdirection.x(), playerdirection.y()); mHud->setPlayerPos(x, y, u, v); } void WindowManager::onFrame (float frameDuration) { if (!mGuiModes.empty()) { GuiModeState& state = mGuiModeStates[mGuiModes.back()]; for (WindowBase* window : state.mWindows) window->onFrame(frameDuration); } else { // update pinned windows if visible for (WindowBase* window : mGuiModeStates[GM_Inventory].mWindows) if (window->isVisible()) window->onFrame(frameDuration); } // Make sure message boxes are always in front // This is an awful workaround for a series of awfully interwoven issues that couldn't be worked around // in a better way because of an impressive number of even more awfully interwoven issues. if (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox() && mCurrentModals.back() != mMessageBoxManager->getInteractiveMessageBox()) { std::vector::iterator found = std::find(mCurrentModals.begin(), mCurrentModals.end(), mMessageBoxManager->getInteractiveMessageBox()); if (found != mCurrentModals.end()) { WindowModal* msgbox = *found; std::swap(*found, mCurrentModals.back()); MyGUI::InputManager::getInstance().addWidgetModal(msgbox->mMainWidget); mKeyboardNavigation->setModalWindow(msgbox->mMainWidget); mKeyboardNavigation->setDefaultFocus(msgbox->mMainWidget, msgbox->getDefaultKeyFocus()); } } if (!mCurrentModals.empty()) mCurrentModals.back()->onFrame(frameDuration); mKeyboardNavigation->onFrame(); mMessageBoxManager->onFrame(frameDuration); mToolTips->onFrame(frameDuration); if (mLocalMapRender) mLocalMapRender->cleanupCameras(); if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) return; mDragAndDrop->onFrame(); updateMap(); if (!mMap->isVisible()) mMap->onFrame(frameDuration); mHud->onFrame(frameDuration); mDebugWindow->onFrame(frameDuration); if (mCharGen) mCharGen->onFrame(frameDuration); updateActivatedQuickKey (); cleanupGarbage(); } void WindowManager::changeCell(const MWWorld::CellStore* cell) { mMap->requestMapRender(cell); std::string name = MWBase::Environment::get().getWorld()->getCellName (cell); mMap->setCellName( name ); mHud->setCellName( name ); if (cell->getCell()->isExterior()) { if (!cell->getCell()->mName.empty()) mMap->addVisitedLocation (name, cell->getCell()->getGridX (), cell->getCell()->getGridY ()); mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY()); setActiveMap(cell->getCell()->getGridX(), cell->getCell()->getGridY(), false); } else { mMap->setCellPrefix (cell->getCell()->mName ); mHud->setCellPrefix (cell->getCell()->mName ); osg::Vec3f worldPos; if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos)) worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); else MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos); mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y()); setActiveMap(0, 0, true); } } /* Start of tes3mp addition Allow the setting of the image data for a global map tile from elsewhere in the code */ void WindowManager::setGlobalMapImage(int cellX, int cellY, const std::vector& imageData) { mMap->setGlobalMapImage(cellX, cellY, imageData); } /* End of tes3mp addition */ void WindowManager::setActiveMap(int x, int y, bool interior) { mMap->setActiveCell(x,y, interior); mHud->setActiveCell(x,y, interior); } void WindowManager::setDrowningBarVisibility(bool visible) { mHud->setDrowningBarVisible(visible); } void WindowManager::setHMSVisibility(bool visible) { mHud->setHmsVisible (visible); } void WindowManager::setMinimapVisibility(bool visible) { mHud->setMinimapVisible (visible); } bool WindowManager::toggleFogOfWar() { mMap->toggleFogOfWar(); return mHud->toggleFogOfWar(); } void WindowManager::setFocusObject(const MWWorld::Ptr& focus) { mToolTips->setFocusObject(focus); if(mHud && (mShowOwned == 2 || mShowOwned == 3)) { bool owned = mToolTips->checkOwned(); mHud->setCrosshairOwned(owned); } } void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) { mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y); } bool WindowManager::toggleFullHelp() { return mToolTips->toggleFullHelp(); } bool WindowManager::getFullHelp() const { return mToolTips->getFullHelp(); } void WindowManager::setWeaponVisibility(bool visible) { mHud->setWeapVisible (visible); } void WindowManager::setSpellVisibility(bool visible) { mHud->setSpellVisible (visible); mHud->setEffectVisible (visible); } void WindowManager::setSneakVisibility(bool visible) { mHud->setSneakVisible(visible); } void WindowManager::setDragDrop(bool dragDrop) { mToolTips->setEnabled(!dragDrop); MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); } /* Start of tes3mp addition Allow the completion of a drag and drop from elsewhere in the code */ void WindowManager::finishDragDrop() { if (mDragAndDrop->mIsOnDragAndDrop) mDragAndDrop->finish(); } /* End of tes3mp addition */ void WindowManager::setCursorVisible(bool visible) { if (visible == mCursorVisible) return; mCursorVisible = visible; if (!visible) mCursorActive = false; } void WindowManager::setCursorActive(bool active) { mCursorActive = active; } void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) { std::string tag(_tag); std::string MyGuiPrefix = "setting="; size_t MyGuiPrefixLength = MyGuiPrefix.length(); std::string tokenToFind = "sCell="; size_t tokenLength = tokenToFind.length(); if(tag.compare(0, MyGuiPrefixLength, MyGuiPrefix) == 0) { tag = tag.substr(MyGuiPrefixLength, tag.length()); std::string settingSection = tag.substr(0, tag.find(",")); std::string settingTag = tag.substr(tag.find(",")+1, tag.length()); _result = Settings::Manager::getString(settingTag, settingSection); } else if (tag.compare(0, tokenLength, tokenToFind) == 0) { _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength)); } else if (Gui::replaceTag(tag, _result, mFallbackMap)) { return; } else { if (!mStore) { std::cerr << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '" << tag << "'" << std::endl; return; } const ESM::GameSetting *setting = mStore->get().find(tag); if (setting && setting->mValue.getType()==ESM::VT_String) _result = setting->mValue.getString(); else _result = tag; } } void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) { mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it) { if (it->first == "HUD" && it->second == "crosshair") mCrosshairEnabled = Settings::Manager::getBool ("crosshair", "HUD"); else if (it->first == "GUI" && it->second == "subtitles") mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI"); else if (it->first == "GUI" && it->second == "menu transparency") setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } } void WindowManager::windowResized(int x, int y) { mGuiPlatform->getRenderManagerPtr()->setViewSize(x, y); // scaled size const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); x = viewSize.width; y = viewSize.height; sizeVideo(x, y); if (!mHud) return; // UI not initialized yet for (std::map::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it) { MyGUI::IntPoint pos(static_cast(Settings::Manager::getFloat(it->second + " x", "Windows") * x), static_cast( Settings::Manager::getFloat(it->second+ " y", "Windows") * y)); MyGUI::IntSize size(static_cast(Settings::Manager::getFloat(it->second + " w", "Windows") * x), static_cast(Settings::Manager::getFloat(it->second + " h", "Windows") * y)); it->first->setPosition(pos); it->first->setSize(size); } for (WindowBase* window : mWindows) window->onResChange(x, y); // TODO: check if any windows are now off-screen and move them back if so } void WindowManager::onCursorChange(const std::string &name) { mCursorManager->cursorChanged(name); } void WindowManager::pushGuiMode(GuiMode mode) { pushGuiMode(mode, MWWorld::Ptr()); } void WindowManager::pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg) { if (mode==GM_Inventory && mAllowed==GW_None) return; if (mGuiModes.empty() || mGuiModes.back() != mode) { // If this mode already exists somewhere in the stack, just bring it to the front. if (std::find(mGuiModes.begin(), mGuiModes.end(), mode) != mGuiModes.end()) { mGuiModes.erase(std::find(mGuiModes.begin(), mGuiModes.end(), mode)); } if (!mGuiModes.empty()) { mKeyboardNavigation->saveFocus(mGuiModes.back()); mGuiModeStates[mGuiModes.back()].update(false); } mGuiModes.push_back(mode); mGuiModeStates[mode].update(true); playSound(mGuiModeStates[mode].mOpenSound); } for (WindowBase* window : mGuiModeStates[mode].mWindows) window->setPtr(arg); mKeyboardNavigation->restoreFocus(mode); updateVisible(); } void WindowManager::popGuiMode(bool noSound) { if (mDragAndDrop && mDragAndDrop->mIsOnDragAndDrop) { mDragAndDrop->finish(); } if (!mGuiModes.empty()) { const GuiMode mode = mGuiModes.back(); mKeyboardNavigation->saveFocus(mode); mGuiModes.pop_back(); mGuiModeStates[mode].update(false); if (!noSound) playSound(mGuiModeStates[mode].mCloseSound); } if (!mGuiModes.empty()) { const GuiMode mode = mGuiModes.back(); mGuiModeStates[mode].update(true); mKeyboardNavigation->restoreFocus(mode); } updateVisible(); } void WindowManager::removeGuiMode(GuiMode mode, bool noSound) { if (!mGuiModes.empty() && mGuiModes.back() == mode) { popGuiMode(noSound); return; } std::vector::iterator it = mGuiModes.begin(); while (it != mGuiModes.end()) { if (*it == mode) it = mGuiModes.erase(it); else ++it; } updateVisible(); } void WindowManager::goToJail(int days) { pushGuiMode(MWGui::GM_Jail); mJailScreen->goToJail(days); } void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) { mSelectedSpell = spellId; mSelectedEnchantItem = MWWorld::Ptr(); mHud->setSelectedSpell(spellId, successChancePercent); const ESM::Spell* spell = mStore->get().find(spellId); mSpellWindow->setTitle(spell->mName); } void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item) { mSelectedEnchantItem = item; mSelectedSpell = ""; const ESM::Enchantment* ench = mStore->get() .find(item.getClass().getEnchantment(item)); int chargePercent = (item.getCellRef().getEnchantmentCharge() == -1) ? 100 : static_cast(item.getCellRef().getEnchantmentCharge() / static_cast(ench->mData.mCharge) * 100); mHud->setSelectedEnchantItem(item, chargePercent); mSpellWindow->setTitle(item.getClass().getName(item)); } const MWWorld::Ptr &WindowManager::getSelectedEnchantItem() const { return mSelectedEnchantItem; } void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) { mSelectedWeapon = item; int durabilityPercent = static_cast(item.getClass().getItemHealth(item) / static_cast(item.getClass().getItemMaxHealth(item)) * 100); mHud->setSelectedWeapon(item, durabilityPercent); mInventoryWindow->setTitle(item.getClass().getName(item)); } const MWWorld::Ptr &WindowManager::getSelectedWeapon() const { return mSelectedWeapon; } void WindowManager::unsetSelectedSpell() { mSelectedSpell = ""; mSelectedEnchantItem = MWWorld::Ptr(); mHud->unsetSelectedSpell(); MWWorld::Player* player = &MWBase::Environment::get().getWorld()->getPlayer(); if (player->getDrawState() == MWMechanics::DrawState_Spell) player->setDrawState(MWMechanics::DrawState_Nothing); mSpellWindow->setTitle("#{sNone}"); } void WindowManager::unsetSelectedWeapon() { mSelectedWeapon = MWWorld::Ptr(); mHud->unsetSelectedWeapon(); mInventoryWindow->setTitle("#{sSkillHandtohand}"); } void WindowManager::getMousePosition(int &x, int &y) { const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); x = pos.left; y = pos.top; } void WindowManager::getMousePosition(float &x, float &y) { const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); x = static_cast(pos.left); y = static_cast(pos.top); const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); x /= viewSize.width; y /= viewSize.height; } bool WindowManager::getWorldMouseOver() { return mHud->getWorldMouseOver(); } void WindowManager::executeInConsole (const std::string& path) { mConsole->executeFile (path); } /* Start of tes3mp addition Allow the execution of console commands from elsewhere in the code */ void WindowManager::executeCommandInConsole(const std::string& command) { mConsole->execute(command); } /* End of tes3mp addition */ MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } /* Start of tes3mp addition Make it possible to get the ContainerWindow from elsewhere in the code */ MWGui::ContainerWindow* WindowManager::getContainerWindow() { return mContainerWindow; } /* End of tes3mp addition */ void WindowManager::useItem(const MWWorld::Ptr &item, bool bypassBeastRestrictions) { if (mInventoryWindow) mInventoryWindow->useItem(item, bypassBeastRestrictions); } bool WindowManager::isAllowed (GuiWindow wnd) const { return (mAllowed & wnd) != 0; } void WindowManager::allow (GuiWindow wnd) { mAllowed = (GuiWindow)(mAllowed | wnd); if (wnd & GW_Inventory) { mBookWindow->setInventoryAllowed (true); mScrollWindow->setInventoryAllowed (true); } updateVisible(); } void WindowManager::disallowAll() { mAllowed = GW_None; mRestAllowed = false; mBookWindow->setInventoryAllowed (false); mScrollWindow->setInventoryAllowed (false); updateVisible(); } void WindowManager::toggleVisible (GuiWindow wnd) { if (getMode() != GM_Inventory) return; mShown = (GuiWindow)(mShown ^ wnd); updateVisible(); } void WindowManager::forceHide(GuiWindow wnd) { mForceHidden = (GuiWindow)(mForceHidden | wnd); updateVisible(); } void WindowManager::unsetForceHide(GuiWindow wnd) { mForceHidden = (GuiWindow)(mForceHidden & ~wnd); updateVisible(); } bool WindowManager::isGuiMode() const { return !mGuiModes.empty() || (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); } bool WindowManager::isConsoleMode() const { if (!mGuiModes.empty() && mGuiModes.back()==GM_Console) return true; return false; } MWGui::GuiMode WindowManager::getMode() const { if (mGuiModes.empty()) return GM_None; return mGuiModes.back(); } std::map WindowManager::getPlayerSkillValues() { return mPlayerSkillValues; } std::map WindowManager::getPlayerAttributeValues() { return mPlayerAttributes; } WindowManager::SkillList WindowManager::getPlayerMinorSkills() { return mPlayerMinorSkills; } WindowManager::SkillList WindowManager::getPlayerMajorSkills() { return mPlayerMajorSkills; } void WindowManager::disallowMouse() { mInputBlocker->setVisible (true); } void WindowManager::allowMouse() { mInputBlocker->setVisible (!isGuiMode ()); } void WindowManager::notifyInputActionBound () { mSettingsWindow->updateControlsBox (); allowMouse(); } bool WindowManager::containsMode(GuiMode mode) const { if(mGuiModes.empty()) return false; return std::find(mGuiModes.begin(), mGuiModes.end(), mode) != mGuiModes.end(); } void WindowManager::showCrosshair (bool show) { if (mHud) mHud->setCrosshairVisible (show && mCrosshairEnabled); } void WindowManager::updateActivatedQuickKey () { mQuickKeysMenu->updateActivatedQuickKey(); } void WindowManager::activateQuickKey (int index) { mQuickKeysMenu->activateQuickKey(index); } /* Start of tes3mp addition Make it possible to add quickKeys from elsewhere in the code */ void WindowManager::setQuickKey(int slot, int quickKeyType, MWWorld::Ptr item, const std::string& spellId) { if (slot > 0) { // The actual indexes recorded for quick keys are always 1 higher than their // indexes in the mKey vector, so adjust for the latter mQuickKeysMenu->setSelectedIndex(slot - 1); switch (quickKeyType) { case QuickKeysMenu::Type_Unassigned: mQuickKeysMenu->unassignIndex(slot); break; case QuickKeysMenu::Type_Item: mQuickKeysMenu->onAssignItem(item); break; case QuickKeysMenu::Type_MagicItem: mQuickKeysMenu->onAssignMagicItem(item); break; case QuickKeysMenu::Type_Magic: mQuickKeysMenu->onAssignMagic(spellId); break; } } } /* End of tes3mp addition */ bool WindowManager::getSubtitlesEnabled () { return mSubtitlesEnabled; } bool WindowManager::toggleHud() { mHudEnabled = !mHudEnabled; updateVisible(); return mHudEnabled; } bool WindowManager::getRestEnabled() { //Enable rest dialogue if character creation finished if(mRestAllowed==false && MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")==-1) mRestAllowed=true; return mRestAllowed; } bool WindowManager::getPlayerSleeping () { return mWaitDialog->getSleeping(); } void WindowManager::wakeUpPlayer() { mWaitDialog->wakeUp(); } void WindowManager::addVisitedLocation(const std::string& name, int x, int y) { mMap->addVisitedLocation (name, x, y); } const Translation::Storage& WindowManager::getTranslationDataStorage() const { return mTranslationDataStorage; } void WindowManager::changePointer(const std::string &name) { MyGUI::PointerManager::getInstance().setPointer(name); onCursorChange(name); } void WindowManager::showSoulgemDialog(MWWorld::Ptr item) { mSoulgemDialog->show(item); updateVisible(); } void WindowManager::updatePlayer() { mInventoryWindow->updatePlayer(); const MWWorld::Ptr player = MWMechanics::getPlayer(); if (player.getClass().getNpcStats(player).isWerewolf()) { setWerewolfOverlay(true); forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); } } // Remove this method for MyGUI 3.2.2 void WindowManager::setKeyFocusWidget(MyGUI::Widget *widget) { if (widget == NULL) MyGUI::InputManager::getInstance().resetKeyFocusWidget(); else MyGUI::InputManager::getInstance().setKeyFocusWidget(widget); onKeyFocusChanged(widget); } void WindowManager::onKeyFocusChanged(MyGUI::Widget *widget) { if (widget && widget->castType(false)) SDL_StartTextInput(); else SDL_StopTextInput(); } void WindowManager::setEnemy(const MWWorld::Ptr &enemy) { mHud->setEnemy(enemy); } Loading::Listener* WindowManager::getLoadingScreen() { return mLoadingScreen; } bool WindowManager::getCursorVisible() { return mCursorVisible && mCursorActive; } void WindowManager::trackWindow(Layout *layout, const std::string &name) { MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); MyGUI::IntPoint pos(static_cast(Settings::Manager::getFloat(name + " x", "Windows") * viewSize.width), static_cast(Settings::Manager::getFloat(name + " y", "Windows") * viewSize.height)); MyGUI::IntSize size (static_cast(Settings::Manager::getFloat(name + " w", "Windows") * viewSize.width), static_cast(Settings::Manager::getFloat(name + " h", "Windows") * viewSize.height)); layout->mMainWidget->setPosition(pos); layout->mMainWidget->setSize(size); MyGUI::Window* window = layout->mMainWidget->castType(); window->eventWindowChangeCoord += MyGUI::newDelegate(this, &WindowManager::onWindowChangeCoord); mTrackedWindows[window] = name; } void WindowManager::onWindowChangeCoord(MyGUI::Window *_sender) { std::string setting = mTrackedWindows[_sender]; MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); float x = _sender->getPosition().left / float(viewSize.width); float y = _sender->getPosition().top / float(viewSize.height); float w = _sender->getSize().width / float(viewSize.width); float h = _sender->getSize().height / float(viewSize.height); Settings::Manager::setFloat(setting + " x", "Windows", x); Settings::Manager::setFloat(setting + " y", "Windows", y); Settings::Manager::setFloat(setting + " w", "Windows", w); Settings::Manager::setFloat(setting + " h", "Windows", h); } void WindowManager::clear() { for (WindowBase* window : mWindows) window->clear(); if (mLocalMapRender) mLocalMapRender->clear(); mMessageBoxManager->clear(); mToolTips->setFocusObject(MWWorld::Ptr()); mSelectedSpell.clear(); mCustomMarkers.clear(); mForceHidden = GW_None; mRestAllowed = true; while (!mGuiModes.empty()) popGuiMode(); updateVisible(); } void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) { mMap->write(writer, progress); mQuickKeysMenu->write(writer); if (!mSelectedSpell.empty()) { writer.startRecord(ESM::REC_ASPL); writer.writeHNString("ID__", mSelectedSpell); writer.endRecord(ESM::REC_ASPL); } for (CustomMarkerCollection::ContainerType::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) { writer.startRecord(ESM::REC_MARK); it->second.save(writer); writer.endRecord(ESM::REC_MARK); } } void WindowManager::readRecord(ESM::ESMReader &reader, uint32_t type) { if (type == ESM::REC_GMAP) mMap->readRecord(reader, type); else if (type == ESM::REC_KEYS) mQuickKeysMenu->readRecord(reader, type); else if (type == ESM::REC_ASPL) { reader.getSubNameIs("ID__"); std::string spell = reader.getHString(); if (mStore->get().search(spell)) mSelectedSpell = spell; } else if (type == ESM::REC_MARK) { ESM::CustomMarker marker; marker.load(reader); mCustomMarkers.addMarker(marker, false); } } int WindowManager::countSavedGameRecords() const { return 1 // Global map + 1 // QuickKeysMenu + mCustomMarkers.size() + (!mSelectedSpell.empty() ? 1 : 0); } bool WindowManager::isSavingAllowed() const { return !MyGUI::InputManager::getInstance().isModalAny() // TODO: remove this, once we have properly serialized the state of open windows && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest))); } void WindowManager::playVideo(const std::string &name, bool allowSkipping) { mVideoWidget->playVideo("video\\" + name); mVideoWidget->eventKeyButtonPressed.clear(); mVideoBackground->eventKeyButtonPressed.clear(); if (allowSkipping) { mVideoWidget->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed); mVideoBackground->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed); } // Turn off all rendering except for the GUI int oldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask(); int oldCullMask = mViewer->getCamera()->getCullMask(); mViewer->getUpdateVisitor()->setTraversalMask(MWRender::Mask_GUI); mViewer->getCamera()->setCullMask(MWRender::Mask_GUI); MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize(); sizeVideo(screenSize.width, screenSize.height); MyGUI::Widget* oldKeyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); setKeyFocusWidget(mVideoWidget); mVideoBackground->setVisible(true); bool cursorWasVisible = mCursorVisible; setCursorVisible(false); if (mVideoWidget->hasAudioStream()) MWBase::Environment::get().getSoundManager()->pauseSounds( ~MWSound::Type::Movie & MWSound::Type::Mask ); osg::Timer frameTimer; while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) { double dt = frameTimer.time_s(); frameTimer.setStartTick(); MWBase::Environment::get().getInputManager()->update(dt, true, false); if (!MWBase::Environment::get().getInputManager()->isWindowVisible()) OpenThreads::Thread::microSleep(5000); else { mViewer->eventTraversal(); mViewer->updateTraversal(); mViewer->renderingTraversals(); } // at the time this function is called we are in the middle of a frame, // so out of order calls are necessary to get a correct frameNumber for the next frame. // refer to the advance() and frame() order in Engine::go() mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); MWBase::Environment::get().limitFrameRate(frameTimer.time_s()); } mVideoWidget->stop(); MWBase::Environment::get().getSoundManager()->resumeSounds(); setKeyFocusWidget(oldKeyFocus); setCursorVisible(cursorWasVisible); // Restore normal rendering mViewer->getUpdateVisitor()->setTraversalMask(oldUpdateMask); mViewer->getCamera()->setCullMask(oldCullMask); mVideoBackground->setVisible(false); } void WindowManager::sizeVideo(int screenWidth, int screenHeight) { // Use black bars to correct aspect ratio bool stretch = Settings::Manager::getBool("stretch menu background", "GUI"); mVideoBackground->setSize(screenWidth, screenHeight); mVideoWidget->autoResize(stretch); } void WindowManager::exitCurrentModal() { if (!mCurrentModals.empty()) { WindowModal* window = mCurrentModals.back(); if (!window->exit()) return; window->setVisible(false); } } void WindowManager::addCurrentModal(WindowModal *input) { if (mCurrentModals.empty()) mKeyboardNavigation->saveFocus(getMode()); mCurrentModals.push_back(input); mKeyboardNavigation->restoreFocus(-1); mKeyboardNavigation->setModalWindow(input->mMainWidget); mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus()); } void WindowManager::removeCurrentModal(WindowModal* input) { if(!mCurrentModals.empty()) { if(input == mCurrentModals.back()) { mCurrentModals.pop_back(); mKeyboardNavigation->saveFocus(-1); } else { auto found = std::find(mCurrentModals.begin(), mCurrentModals.end(), input); if (found != mCurrentModals.end()) mCurrentModals.erase(found); else std::cerr << " warning: can't find modal window " << input << std::endl; } } if (mCurrentModals.empty()) { mKeyboardNavigation->setModalWindow(NULL); mKeyboardNavigation->restoreFocus(getMode()); } else mKeyboardNavigation->setModalWindow(mCurrentModals.back()->mMainWidget); } void WindowManager::onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char) { if (_key == MyGUI::KeyCode::Escape) mVideoWidget->stop(); } void WindowManager::updatePinnedWindows() { mInventoryWindow->setPinned(Settings::Manager::getBool("inventory pin", "Windows")); mMap->setPinned(Settings::Manager::getBool("map pin", "Windows")); mSpellWindow->setPinned(Settings::Manager::getBool("spells pin", "Windows")); mStatsWindow->setPinned(Settings::Manager::getBool("stats pin", "Windows")); } void WindowManager::pinWindow(GuiWindow window) { switch (window) { case GW_Inventory: mInventoryWindow->setPinned(true); break; case GW_Map: mMap->setPinned(true); break; case GW_Magic: mSpellWindow->setPinned(true); break; case GW_Stats: mStatsWindow->setPinned(true); break; default: break; } updateVisible(); } void WindowManager::fadeScreenIn(const float time, bool clearQueue, float delay) { if (clearQueue) mScreenFader->clearQueue(); mScreenFader->fadeOut(time, delay); } void WindowManager::fadeScreenOut(const float time, bool clearQueue, float delay) { if (clearQueue) mScreenFader->clearQueue(); mScreenFader->fadeIn(time, delay); } void WindowManager::fadeScreenTo(const int percent, const float time, bool clearQueue, float delay) { if (clearQueue) mScreenFader->clearQueue(); mScreenFader->fadeTo(percent, time, delay); } void WindowManager::setBlindness(const int percent) { mBlindnessFader->notifyAlphaChanged(percent / 100.f); } void WindowManager::activateHitOverlay(bool interrupt) { if (!mHitFaderEnabled) return; if (!interrupt && !mHitFader->isEmpty()) return; mHitFader->clearQueue(); mHitFader->fadeTo(100, 0.0f); mHitFader->fadeTo(0, 0.5f); } void WindowManager::setWerewolfOverlay(bool set) { if (!mWerewolfOverlayEnabled) return; if (mWerewolfFader) mWerewolfFader->notifyAlphaChanged(set ? 1.0f : 0.0f); } void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) { if (_type == "Text") SDL_SetClipboardText(MyGUI::TextIterator::getOnlyText(MyGUI::UString(_data)).asUTF8().c_str()); } void WindowManager::onClipboardRequested(const std::string &_type, std::string &_data) { if (_type != "Text") return; char* text=0; text = SDL_GetClipboardText(); if (text) _data = MyGUI::TextIterator::toTagsString(text); SDL_free(text); } void WindowManager::toggleDebugWindow() { mDebugWindow->setVisible(!mDebugWindow->isVisible()); } void WindowManager::cycleSpell(bool next) { if (!isGuiMode()) mSpellWindow->cycle(next); } void WindowManager::cycleWeapon(bool next) { if (!isGuiMode()) mInventoryWindow->cycle(next); } void WindowManager::playSound(const std::string& soundId, float volume, float pitch) { if (soundId.empty()) return; MWBase::Environment::get().getSoundManager()->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv); } void WindowManager::updateSpellWindow() { if (mSpellWindow) mSpellWindow->updateSpells(); } void WindowManager::setConsoleSelectedObject(const MWWorld::Ptr &object) { mConsole->setSelectedObject(object); } /* Start of tes3mp addition Allow the direct setting of a console's Ptr, without the assumption that an object was clicked and that key focus should be restored to the console window, for console commands executed via server scripts */ void WindowManager::setConsolePtr(const MWWorld::Ptr &object) { mConsole->setPtr(object); } /* End of tes3mp addition */ /* Start of tes3mp addition Allow the clearing of the console's Ptr from elsewhere in the code, so that Ptrs used in console commands run from server scripts do not stay selected */ void WindowManager::clearConsolePtr() { mConsole->resetReference(); } /* End of tes3mp addition */ std::string WindowManager::correctIconPath(const std::string& path) { return Misc::ResourceHelpers::correctIconPath(path, mResourceSystem->getVFS()); } std::string WindowManager::correctBookartPath(const std::string& path, int width, int height, bool* exists) { std::string corrected = Misc::ResourceHelpers::correctBookartPath(path, width, height, mResourceSystem->getVFS()); if (exists) *exists = mResourceSystem->getVFS()->exists(corrected); return corrected; } std::string WindowManager::correctTexturePath(const std::string& path) { return Misc::ResourceHelpers::correctTexturePath(path, mResourceSystem->getVFS()); } bool WindowManager::textureExists(const std::string &path) { std::string corrected = Misc::ResourceHelpers::correctTexturePath(path, mResourceSystem->getVFS()); return mResourceSystem->getVFS()->exists(corrected); } void WindowManager::createCursors() { MyGUI::ResourceManager::EnumeratorPtr enumerator = MyGUI::ResourceManager::getInstance().getEnumerator(); while (enumerator.next()) { MyGUI::IResource* resource = enumerator.current().second; ResourceImageSetPointerFix* imgSetPointer = resource->castType(false); if (!imgSetPointer) continue; std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture; osg::ref_ptr image = mResourceSystem->getImageManager()->getImage(tex_name); if(image.valid()) { //everything looks good, send it to the cursor manager Uint8 hotspot_x = imgSetPointer->getHotSpot().left; Uint8 hotspot_y = imgSetPointer->getHotSpot().top; int rotation = imgSetPointer->getRotation(); mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, image, hotspot_x, hotspot_y); } } } void WindowManager::createTextures() { { MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("white"); tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8); unsigned char* data = reinterpret_cast(tex->lock(MyGUI::TextureUsage::Write)); for (int x=0; x<8; ++x) for (int y=0; y<8; ++y) { *(data++) = 255; *(data++) = 255; *(data++) = 255; } tex->unlock(); } { MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("black"); tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8); unsigned char* data = reinterpret_cast(tex->lock(MyGUI::TextureUsage::Write)); for (int x=0; x<8; ++x) for (int y=0; y<8; ++y) { *(data++) = 0; *(data++) = 0; *(data++) = 0; } tex->unlock(); } { MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("transparent"); tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8A8); setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); } } void WindowManager::setMenuTransparency(float value) { MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().getTexture("transparent"); unsigned char* data = reinterpret_cast(tex->lock(MyGUI::TextureUsage::Write)); for (int x=0; x<8; ++x) for (int y=0; y<8; ++y) { *(data++) = 255; *(data++) = 255; *(data++) = 255; *(data++) = static_cast(value*255); } tex->unlock(); } void WindowManager::removeCell(MWWorld::CellStore *cell) { mLocalMapRender->removeCell(cell); } void WindowManager::writeFog(MWWorld::CellStore *cell) { mLocalMapRender->saveFogOfWar(cell); } const MWGui::TextColours& WindowManager::getTextColours() { return mTextColours; } bool WindowManager::injectKeyPress(MyGUI::KeyCode key, unsigned int text) { if (!mKeyboardNavigation->injectKeyPress(key, text)) { MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); bool widgetActive = MyGUI::InputManager::getInstance().injectKeyPress(key, text); if (!widgetActive || !focus) return false; // FIXME: MyGUI doesn't allow widgets to state if a given key was actually used, so make a guess if (focus->getTypeName().find("Button") != std::string::npos) { switch (key.getValue()) { case MyGUI::KeyCode::ArrowDown: case MyGUI::KeyCode::ArrowUp: case MyGUI::KeyCode::ArrowLeft: case MyGUI::KeyCode::ArrowRight: case MyGUI::KeyCode::Return: case MyGUI::KeyCode::NumpadEnter: case MyGUI::KeyCode::Space: return true; default: return false; } } return false; } else return true; } void WindowManager::GuiModeState::update(bool visible) { for (unsigned int i=0; isetVisible(visible); } }