mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 18:35:20 +00:00
2358 lines
81 KiB
C++
2358 lines
81 KiB
C++
#include "windowmanagerimp.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
#include <thread>
|
|
|
|
#include <osgViewer/Viewer>
|
|
|
|
#include <MyGUI_ClipboardManager.h>
|
|
#include <MyGUI_FactoryManager.h>
|
|
#include <MyGUI_InputManager.h>
|
|
#include <MyGUI_LanguageManager.h>
|
|
#include <MyGUI_PointerManager.h>
|
|
#include <MyGUI_UString.h>
|
|
|
|
// For BT_NO_PROFILE
|
|
#include <LinearMath/btQuickprof.h>
|
|
|
|
#include <SDL_clipboard.h>
|
|
#include <SDL_keyboard.h>
|
|
|
|
#include <components/debug/debuglog.hpp>
|
|
|
|
#include <components/esm3/esmreader.hpp>
|
|
#include <components/esm3/esmwriter.hpp>
|
|
|
|
#include <components/fontloader/fontloader.hpp>
|
|
|
|
#include <components/resource/imagemanager.hpp>
|
|
#include <components/resource/resourcesystem.hpp>
|
|
#include <components/resource/scenemanager.hpp>
|
|
|
|
#include <components/sceneutil/workqueue.hpp>
|
|
|
|
#include <components/translation/translation.hpp>
|
|
|
|
#include <components/myguiplatform/additivelayer.hpp>
|
|
#include <components/myguiplatform/myguiplatform.hpp>
|
|
#include <components/myguiplatform/myguirendermanager.hpp>
|
|
#include <components/myguiplatform/scalinglayer.hpp>
|
|
|
|
#include <components/vfs/manager.hpp>
|
|
|
|
#include <components/widgets/tags.hpp>
|
|
#include <components/widgets/widgets.hpp>
|
|
|
|
#include <components/misc/frameratelimiter.hpp>
|
|
|
|
#include <components/l10n/manager.hpp>
|
|
|
|
#include <components/lua_ui/util.hpp>
|
|
|
|
#include <components/settings/values.hpp>
|
|
|
|
#include "../mwbase/inputmanager.hpp"
|
|
#include "../mwbase/luamanager.hpp"
|
|
#include "../mwbase/soundmanager.hpp"
|
|
#include "../mwbase/statemanager.hpp"
|
|
#include "../mwbase/world.hpp"
|
|
|
|
#include "../mwrender/vismask.hpp"
|
|
|
|
#include "../mwworld/cellstore.hpp"
|
|
#include "../mwworld/class.hpp"
|
|
#include "../mwworld/esmstore.hpp"
|
|
#include "../mwworld/globals.hpp"
|
|
#include "../mwworld/player.hpp"
|
|
|
|
#include "../mwmechanics/actorutil.hpp"
|
|
#include "../mwmechanics/npcstats.hpp"
|
|
|
|
#include "../mwrender/postprocessor.hpp"
|
|
|
|
#include "alchemywindow.hpp"
|
|
#include "backgroundimage.hpp"
|
|
#include "bookpage.hpp"
|
|
#include "bookwindow.hpp"
|
|
#include "companionwindow.hpp"
|
|
#include "confirmationdialog.hpp"
|
|
#include "console.hpp"
|
|
#include "container.hpp"
|
|
#include "controllers.hpp"
|
|
#include "countdialog.hpp"
|
|
#include "cursor.hpp"
|
|
#include "debugwindow.hpp"
|
|
#include "dialogue.hpp"
|
|
#include "enchantingdialog.hpp"
|
|
#include "exposedwindow.hpp"
|
|
#include "hud.hpp"
|
|
#include "inventorywindow.hpp"
|
|
#include "itemchargeview.hpp"
|
|
#include "itemview.hpp"
|
|
#include "itemwidget.hpp"
|
|
#include "jailscreen.hpp"
|
|
#include "journalviewmodel.hpp"
|
|
#include "journalwindow.hpp"
|
|
#include "keyboardnavigation.hpp"
|
|
#include "levelupdialog.hpp"
|
|
#include "loadingscreen.hpp"
|
|
#include "mainmenu.hpp"
|
|
#include "merchantrepair.hpp"
|
|
#include "postprocessorhud.hpp"
|
|
#include "quickkeysmenu.hpp"
|
|
#include "recharge.hpp"
|
|
#include "repair.hpp"
|
|
#include "resourceskin.hpp"
|
|
#include "screenfader.hpp"
|
|
#include "scrollwindow.hpp"
|
|
#include "settingswindow.hpp"
|
|
#include "spellbuyingwindow.hpp"
|
|
#include "spellview.hpp"
|
|
#include "spellwindow.hpp"
|
|
#include "statswindow.hpp"
|
|
#include "tradewindow.hpp"
|
|
#include "trainingwindow.hpp"
|
|
#include "travelwindow.hpp"
|
|
#include "ustring.hpp"
|
|
#include "videowidget.hpp"
|
|
#include "waitdialog.hpp"
|
|
|
|
namespace MWGui
|
|
{
|
|
namespace
|
|
{
|
|
Settings::SettingValue<bool>* findHiddenSetting(GuiWindow window)
|
|
{
|
|
switch (window)
|
|
{
|
|
case GW_Inventory:
|
|
return &Settings::windows().mInventoryHidden;
|
|
case GW_Map:
|
|
return &Settings::windows().mMapHidden;
|
|
case GW_Magic:
|
|
return &Settings::windows().mSpellsHidden;
|
|
case GW_Stats:
|
|
return &Settings::windows().mStatsHidden;
|
|
default:
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
WindowManager::WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot,
|
|
Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, const std::filesystem::path& logpath,
|
|
bool consoleOnlyScripts, Translation::Storage& translationDataStorage, ToUTF8::FromType encoding,
|
|
const std::string& versionDescription, bool useShaders, Files::ConfigurationManager& cfgMgr)
|
|
: mOldUpdateMask(0)
|
|
, mOldCullMask(0)
|
|
, mStore(nullptr)
|
|
, mResourceSystem(resourceSystem)
|
|
, mWorkQueue(workQueue)
|
|
, mViewer(viewer)
|
|
, mConsoleOnlyScripts(consoleOnlyScripts)
|
|
, mCurrentModals()
|
|
, mHud(nullptr)
|
|
, mMap(nullptr)
|
|
, mStatsWindow(nullptr)
|
|
, mConsole(nullptr)
|
|
, mDialogueWindow(nullptr)
|
|
, mInventoryWindow(nullptr)
|
|
, mScrollWindow(nullptr)
|
|
, mBookWindow(nullptr)
|
|
, mCountDialog(nullptr)
|
|
, mTradeWindow(nullptr)
|
|
, mSettingsWindow(nullptr)
|
|
, mConfirmationDialog(nullptr)
|
|
, mSpellWindow(nullptr)
|
|
, mQuickKeysMenu(nullptr)
|
|
, mLoadingScreen(nullptr)
|
|
, mWaitDialog(nullptr)
|
|
, mVideoBackground(nullptr)
|
|
, mVideoWidget(nullptr)
|
|
, mWerewolfFader(nullptr)
|
|
, mBlindnessFader(nullptr)
|
|
, mHitFader(nullptr)
|
|
, mScreenFader(nullptr)
|
|
, mDebugWindow(nullptr)
|
|
, mPostProcessorHud(nullptr)
|
|
, mJailScreen(nullptr)
|
|
, mContainerWindow(nullptr)
|
|
, mTranslationDataStorage(translationDataStorage)
|
|
, mInputBlocker(nullptr)
|
|
, 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(true)
|
|
, mPlayerBounty(-1)
|
|
, mGuiModes()
|
|
, mGarbageDialogs()
|
|
, mShown(GW_ALL)
|
|
, mForceHidden(GW_None)
|
|
, mAllowed(GW_ALL)
|
|
, mRestAllowed(true)
|
|
, mEncoding(encoding)
|
|
, mVersionDescription(versionDescription)
|
|
, mWindowVisible(true)
|
|
, mCfgMgr(cfgMgr)
|
|
{
|
|
int w, h;
|
|
SDL_GetWindowSize(window, &w, &h);
|
|
int dw, dh;
|
|
SDL_GL_GetDrawableSize(window, &dw, &dh);
|
|
|
|
mScalingFactor = std::clamp(Settings::Manager::getFloat("scaling factor", "GUI"), 0.5f, 8.f) * (dw / w);
|
|
mGuiPlatform = std::make_unique<osgMyGUI::Platform>(viewer, guiRoot, resourceSystem->getImageManager(),
|
|
resourceSystem->getVFS(), mScalingFactor, "mygui", logpath / "MyGUI.log");
|
|
|
|
mGui = std::make_unique<MyGUI::Gui>();
|
|
mGui->initialise({});
|
|
|
|
createTextures();
|
|
|
|
MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag);
|
|
|
|
// Load fonts
|
|
mFontLoader = std::make_unique<Gui::FontLoader>(encoding, resourceSystem->getVFS(), mScalingFactor);
|
|
|
|
// Register own widgets with MyGUI
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWAttribute>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpell>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Window>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::AdditiveLayer>("Layer");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::ScalingLayer>("Layer");
|
|
BookPage::registerMyGUIComponents();
|
|
PostProcessorHud::registerMyGUIComponents();
|
|
ItemView::registerComponents();
|
|
ItemChargeView::registerComponents();
|
|
ItemWidget::registerComponents();
|
|
SpellView::registerComponents();
|
|
Gui::registerAllWidgets();
|
|
LuaUi::registerAllWidgets();
|
|
|
|
MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller");
|
|
|
|
MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>(
|
|
"Resource", "ResourceImageSetPointer");
|
|
MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>(
|
|
"Resource", "AutoSizedResourceSkin");
|
|
MyGUI::ResourceManager::getInstance().load("core.xml");
|
|
|
|
bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI");
|
|
mKeyboardNavigation = std::make_unique<KeyboardNavigation>();
|
|
mKeyboardNavigation->setEnabled(keyboardNav);
|
|
Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav);
|
|
|
|
auto loadingScreen = std::make_unique<LoadingScreen>(mResourceSystem, mViewer);
|
|
mLoadingScreen = loadingScreen.get();
|
|
mWindows.push_back(std::move(loadingScreen));
|
|
|
|
// set up the hardware cursor manager
|
|
mCursorManager = std::make_unique<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<MyGUI::ImageBox>(
|
|
"ImageBox", 0, 0, 1, 1, MyGUI::Align::Default, "Video");
|
|
mVideoBackground->setImageTexture("black");
|
|
mVideoBackground->setVisible(false);
|
|
mVideoBackground->setNeedMouseFocus(true);
|
|
mVideoBackground->setNeedKeyFocus(true);
|
|
|
|
mVideoWidget = mVideoBackground->createWidgetReal<VideoWidget>("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);
|
|
|
|
mVideoWrapper = std::make_unique<SDLUtil::VideoWrapper>(window, viewer);
|
|
mVideoWrapper->setGammaContrast(
|
|
Settings::Manager::getFloat("gamma", "Video"), Settings::Manager::getFloat("contrast", "Video"));
|
|
|
|
if (useShaders)
|
|
mGuiPlatform->getRenderManagerPtr()->enableShaders(mResourceSystem->getSceneManager()->getShaderManager());
|
|
|
|
mStatsWatcher = std::make_unique<StatsWatcher>();
|
|
}
|
|
|
|
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.loadColours();
|
|
|
|
mDragAndDrop = std::make_unique<DragAndDrop>();
|
|
|
|
auto recharge = std::make_unique<Recharge>();
|
|
mGuiModeStates[GM_Recharge] = GuiModeState(recharge.get());
|
|
mWindows.push_back(std::move(recharge));
|
|
|
|
auto menu = std::make_unique<MainMenu>(w, h, mResourceSystem->getVFS(), mVersionDescription);
|
|
mGuiModeStates[GM_MainMenu] = GuiModeState(menu.get());
|
|
mWindows.push_back(std::move(menu));
|
|
|
|
mLocalMapRender = std::make_unique<MWRender::LocalMap>(mViewer->getSceneData()->asGroup());
|
|
auto map = std::make_unique<MapWindow>(mCustomMarkers, mDragAndDrop.get(), mLocalMapRender.get(), mWorkQueue);
|
|
mMap = map.get();
|
|
mWindows.push_back(std::move(map));
|
|
mMap->renderGlobalMap();
|
|
trackWindow(mMap, makeMapWindowSettingValues());
|
|
|
|
auto statsWindow = std::make_unique<StatsWindow>(mDragAndDrop.get());
|
|
mStatsWindow = statsWindow.get();
|
|
mWindows.push_back(std::move(statsWindow));
|
|
trackWindow(mStatsWindow, makeStatsWindowSettingValues());
|
|
|
|
auto inventoryWindow = std::make_unique<InventoryWindow>(
|
|
mDragAndDrop.get(), mViewer->getSceneData()->asGroup(), mResourceSystem);
|
|
mInventoryWindow = inventoryWindow.get();
|
|
mWindows.push_back(std::move(inventoryWindow));
|
|
|
|
auto spellWindow = std::make_unique<SpellWindow>(mDragAndDrop.get());
|
|
mSpellWindow = spellWindow.get();
|
|
mWindows.push_back(std::move(spellWindow));
|
|
trackWindow(mSpellWindow, makeSpellsWindowSettingValues());
|
|
|
|
mGuiModeStates[GM_Inventory] = GuiModeState({ mMap, mInventoryWindow, mSpellWindow, mStatsWindow });
|
|
mGuiModeStates[GM_None] = GuiModeState({ mMap, mInventoryWindow, mSpellWindow, mStatsWindow });
|
|
|
|
auto tradeWindow = std::make_unique<TradeWindow>();
|
|
mTradeWindow = tradeWindow.get();
|
|
mWindows.push_back(std::move(tradeWindow));
|
|
trackWindow(mTradeWindow, makeBarterWindowSettingValues());
|
|
mGuiModeStates[GM_Barter] = GuiModeState({ mInventoryWindow, mTradeWindow });
|
|
|
|
auto console = std::make_unique<Console>(w, h, mConsoleOnlyScripts, mCfgMgr);
|
|
mConsole = console.get();
|
|
mWindows.push_back(std::move(console));
|
|
trackWindow(mConsole, makeConsoleWindowSettingValues());
|
|
|
|
bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds");
|
|
auto journal = JournalWindow::create(JournalViewModel::create(), questList, mEncoding);
|
|
mGuiModeStates[GM_Journal] = GuiModeState(journal.get());
|
|
mGuiModeStates[GM_Journal].mCloseSound = ESM::RefId::stringRefId("book close");
|
|
mGuiModeStates[GM_Journal].mOpenSound = ESM::RefId::stringRefId("book open");
|
|
mWindows.push_back(std::move(journal));
|
|
|
|
mMessageBoxManager = std::make_unique<MessageBoxManager>(
|
|
mStore->get<ESM::GameSetting>().find("fMessageTimePerChar")->mValue.getFloat());
|
|
|
|
auto spellBuyingWindow = std::make_unique<SpellBuyingWindow>();
|
|
mGuiModeStates[GM_SpellBuying] = GuiModeState(spellBuyingWindow.get());
|
|
mWindows.push_back(std::move(spellBuyingWindow));
|
|
|
|
auto travelWindow = std::make_unique<TravelWindow>();
|
|
mGuiModeStates[GM_Travel] = GuiModeState(travelWindow.get());
|
|
mWindows.push_back(std::move(travelWindow));
|
|
|
|
auto dialogueWindow = std::make_unique<DialogueWindow>();
|
|
mDialogueWindow = dialogueWindow.get();
|
|
mWindows.push_back(std::move(dialogueWindow));
|
|
trackWindow(mDialogueWindow, makeDialogueWindowSettingValues());
|
|
mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow);
|
|
mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete);
|
|
|
|
auto containerWindow = std::make_unique<ContainerWindow>(mDragAndDrop.get());
|
|
mContainerWindow = containerWindow.get();
|
|
mWindows.push_back(std::move(containerWindow));
|
|
trackWindow(mContainerWindow, makeContainerWindowSettingValues());
|
|
mGuiModeStates[GM_Container] = GuiModeState({ mContainerWindow, mInventoryWindow });
|
|
|
|
auto hud = std::make_unique<HUD>(mCustomMarkers, mDragAndDrop.get(), mLocalMapRender.get());
|
|
mHud = hud.get();
|
|
mWindows.push_back(std::move(hud));
|
|
|
|
mToolTips = std::make_unique<ToolTips>();
|
|
|
|
auto scrollWindow = std::make_unique<ScrollWindow>();
|
|
mScrollWindow = scrollWindow.get();
|
|
mWindows.push_back(std::move(scrollWindow));
|
|
mGuiModeStates[GM_Scroll] = GuiModeState(mScrollWindow);
|
|
mGuiModeStates[GM_Scroll].mOpenSound = ESM::RefId::stringRefId("scroll");
|
|
mGuiModeStates[GM_Scroll].mCloseSound = ESM::RefId::stringRefId("scroll");
|
|
|
|
auto bookWindow = std::make_unique<BookWindow>();
|
|
mBookWindow = bookWindow.get();
|
|
mWindows.push_back(std::move(bookWindow));
|
|
mGuiModeStates[GM_Book] = GuiModeState(mBookWindow);
|
|
mGuiModeStates[GM_Book].mOpenSound = ESM::RefId::stringRefId("book open");
|
|
mGuiModeStates[GM_Book].mCloseSound = ESM::RefId::stringRefId("book close");
|
|
|
|
auto countDialog = std::make_unique<CountDialog>();
|
|
mCountDialog = countDialog.get();
|
|
mWindows.push_back(std::move(countDialog));
|
|
|
|
auto settingsWindow = std::make_unique<SettingsWindow>();
|
|
mSettingsWindow = settingsWindow.get();
|
|
mWindows.push_back(std::move(settingsWindow));
|
|
trackWindow(mSettingsWindow, makeSettingsWindowSettingValues());
|
|
mGuiModeStates[GM_Settings] = GuiModeState(mSettingsWindow);
|
|
|
|
auto confirmationDialog = std::make_unique<ConfirmationDialog>();
|
|
mConfirmationDialog = confirmationDialog.get();
|
|
mWindows.push_back(std::move(confirmationDialog));
|
|
|
|
auto alchemyWindow = std::make_unique<AlchemyWindow>();
|
|
trackWindow(alchemyWindow.get(), makeAlchemyWindowSettingValues());
|
|
mGuiModeStates[GM_Alchemy] = GuiModeState(alchemyWindow.get());
|
|
mWindows.push_back(std::move(alchemyWindow));
|
|
|
|
auto quickKeysMenu = std::make_unique<QuickKeysMenu>();
|
|
mQuickKeysMenu = quickKeysMenu.get();
|
|
mWindows.push_back(std::move(quickKeysMenu));
|
|
mGuiModeStates[GM_QuickKeysMenu] = GuiModeState(mQuickKeysMenu);
|
|
|
|
auto levelupDialog = std::make_unique<LevelupDialog>();
|
|
mGuiModeStates[GM_Levelup] = GuiModeState(levelupDialog.get());
|
|
mWindows.push_back(std::move(levelupDialog));
|
|
|
|
auto waitDialog = std::make_unique<WaitDialog>();
|
|
mWaitDialog = waitDialog.get();
|
|
mWindows.push_back(std::move(waitDialog));
|
|
mGuiModeStates[GM_Rest] = GuiModeState({ mWaitDialog->getProgressBar(), mWaitDialog });
|
|
|
|
auto spellCreationDialog = std::make_unique<SpellCreationDialog>();
|
|
mGuiModeStates[GM_SpellCreation] = GuiModeState(spellCreationDialog.get());
|
|
mWindows.push_back(std::move(spellCreationDialog));
|
|
|
|
auto enchantingDialog = std::make_unique<EnchantingDialog>();
|
|
mGuiModeStates[GM_Enchanting] = GuiModeState(enchantingDialog.get());
|
|
mWindows.push_back(std::move(enchantingDialog));
|
|
|
|
auto trainingWindow = std::make_unique<TrainingWindow>();
|
|
mGuiModeStates[GM_Training] = GuiModeState({ trainingWindow->getProgressBar(), trainingWindow.get() });
|
|
mWindows.push_back(std::move(trainingWindow));
|
|
|
|
auto merchantRepair = std::make_unique<MerchantRepair>();
|
|
mGuiModeStates[GM_MerchantRepair] = GuiModeState(merchantRepair.get());
|
|
mWindows.push_back(std::move(merchantRepair));
|
|
|
|
auto repair = std::make_unique<Repair>();
|
|
mGuiModeStates[GM_Repair] = GuiModeState(repair.get());
|
|
mWindows.push_back(std::move(repair));
|
|
|
|
mSoulgemDialog = std::make_unique<SoulgemDialog>(mMessageBoxManager.get());
|
|
|
|
auto companionWindow = std::make_unique<CompanionWindow>(mDragAndDrop.get(), mMessageBoxManager.get());
|
|
trackWindow(companionWindow.get(), makeCompanionWindowSettingValues());
|
|
mGuiModeStates[GM_Companion] = GuiModeState({ mInventoryWindow, companionWindow.get() });
|
|
mWindows.push_back(std::move(companionWindow));
|
|
|
|
auto jailScreen = std::make_unique<JailScreen>();
|
|
mJailScreen = jailScreen.get();
|
|
mWindows.push_back(std::move(jailScreen));
|
|
mGuiModeStates[GM_Jail] = GuiModeState(mJailScreen);
|
|
|
|
std::string werewolfFaderTex = "textures\\werewolfoverlay.dds";
|
|
if (mResourceSystem->getVFS()->exists(werewolfFaderTex))
|
|
{
|
|
auto werewolfFader = std::make_unique<ScreenFader>(werewolfFaderTex);
|
|
mWerewolfFader = werewolfFader.get();
|
|
mWindows.push_back(std::move(werewolfFader));
|
|
}
|
|
auto blindnessFader = std::make_unique<ScreenFader>("black");
|
|
mBlindnessFader = blindnessFader.get();
|
|
mWindows.push_back(std::move(blindnessFader));
|
|
|
|
// 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);
|
|
}
|
|
auto hitFader = std::make_unique<ScreenFader>(hitFaderTexture, hitFaderLayout, hitFaderCoord);
|
|
mHitFader = hitFader.get();
|
|
mWindows.push_back(std::move(hitFader));
|
|
|
|
auto screenFader = std::make_unique<ScreenFader>("black");
|
|
mScreenFader = screenFader.get();
|
|
mWindows.push_back(std::move(screenFader));
|
|
|
|
auto debugWindow = std::make_unique<DebugWindow>();
|
|
mDebugWindow = debugWindow.get();
|
|
mWindows.push_back(std::move(debugWindow));
|
|
|
|
auto postProcessorHud = std::make_unique<PostProcessorHud>();
|
|
mPostProcessorHud = postProcessorHud.get();
|
|
mWindows.push_back(std::move(postProcessorHud));
|
|
trackWindow(mPostProcessorHud, makePostprocessorWindowSettingValues());
|
|
|
|
mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>(
|
|
{}, 0, 0, w, h, MyGUI::Align::Stretch, "InputBlocker");
|
|
|
|
mHud->setVisible(true);
|
|
|
|
mCharGen = std::make_unique<CharacterCreation>(mViewer->getSceneData()->asGroup(), mResourceSystem);
|
|
|
|
updatePinnedWindows();
|
|
|
|
// Set up visibility
|
|
updateVisible();
|
|
|
|
mStatsWatcher->addListener(mHud);
|
|
mStatsWatcher->addListener(mStatsWindow);
|
|
mStatsWatcher->addListener(mCharGen.get());
|
|
}
|
|
|
|
int WindowManager::getFontHeight() const
|
|
{
|
|
return mFontLoader->getFontHeight();
|
|
}
|
|
|
|
void WindowManager::setNewGame(bool newgame)
|
|
{
|
|
if (newgame)
|
|
{
|
|
disallowAll();
|
|
|
|
mStatsWatcher->removeListener(mCharGen.get());
|
|
mCharGen = std::make_unique<CharacterCreation>(mViewer->getSceneData()->asGroup(), mResourceSystem);
|
|
mStatsWatcher->addListener(mCharGen.get());
|
|
}
|
|
else
|
|
allow(GW_ALL);
|
|
|
|
mStatsWatcher->forceUpdate();
|
|
}
|
|
|
|
WindowManager::~WindowManager()
|
|
{
|
|
try
|
|
{
|
|
LuaUi::clearUserInterface();
|
|
|
|
mStatsWatcher.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();
|
|
|
|
mWindows.clear();
|
|
mMessageBoxManager.reset();
|
|
mToolTips.reset();
|
|
mCharGen.reset();
|
|
|
|
mKeyboardNavigation.reset();
|
|
|
|
cleanupGarbage();
|
|
|
|
mFontLoader.reset();
|
|
|
|
mGui->shutdown();
|
|
|
|
mGuiPlatform->shutdown();
|
|
}
|
|
catch (const MyGUI::Exception& e)
|
|
{
|
|
Log(Debug::Error) << "Error in the destructor: " << e.what();
|
|
}
|
|
}
|
|
|
|
void WindowManager::setStore(const MWWorld::ESMStore& store)
|
|
{
|
|
mStore = &store;
|
|
}
|
|
|
|
void WindowManager::cleanupGarbage()
|
|
{
|
|
// Delete any dialogs which are no longer in use
|
|
mGarbageDialogs.clear();
|
|
}
|
|
|
|
void WindowManager::enableScene(bool enable)
|
|
{
|
|
unsigned int disablemask = MWRender::Mask_GUI | MWRender::Mask_PreCompile;
|
|
if (!enable && getCullMask() != disablemask)
|
|
{
|
|
mOldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask();
|
|
mOldCullMask = getCullMask();
|
|
mViewer->getUpdateVisitor()->setTraversalMask(disablemask);
|
|
setCullMask(disablemask);
|
|
}
|
|
else if (enable && getCullMask() == disablemask)
|
|
{
|
|
mViewer->getUpdateVisitor()->setTraversalMask(mOldUpdateMask);
|
|
setCullMask(mOldCullMask);
|
|
}
|
|
}
|
|
|
|
void WindowManager::updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr)
|
|
{
|
|
mConsole->updateSelectedObjectPtr(currentPtr, newPtr);
|
|
}
|
|
|
|
void WindowManager::updateVisible()
|
|
{
|
|
bool loading = (getMode() == GM_Loading || getMode() == GM_LoadingWallpaper);
|
|
|
|
bool mainmenucover = containsMode(GM_MainMenu)
|
|
&& MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame;
|
|
|
|
enableScene(!loading && !mainmenucover);
|
|
|
|
if (!mMap)
|
|
return; // UI not created yet
|
|
|
|
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(nullptr);
|
|
|
|
// 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() && !isConsoleMode() && !(mForceHidden & GW_Map) && (mAllowed & GW_Map));
|
|
mStatsWindow->setVisible(
|
|
mStatsWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Stats) && (mAllowed & GW_Stats));
|
|
mInventoryWindow->setVisible(mInventoryWindow->pinned() && !isConsoleMode()
|
|
&& !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory));
|
|
mSpellWindow->setVisible(
|
|
mSpellWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic));
|
|
return;
|
|
}
|
|
else if (getMode() != GM_Inventory)
|
|
{
|
|
mMap->setVisible(false);
|
|
mStatsWindow->setVisible(false);
|
|
mSpellWindow->setVisible(false);
|
|
mHud->setDrowningBarVisible(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:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void WindowManager::setDrowningTimeLeft(float time, float maxTime)
|
|
{
|
|
mHud->setDrowningTimeLeft(time, maxTime);
|
|
}
|
|
|
|
void WindowManager::removeDialog(std::unique_ptr<Layout>&& dialog)
|
|
{
|
|
if (!dialog)
|
|
return;
|
|
dialog->setVisible(false);
|
|
mGarbageDialogs.push_back(std::move(dialog));
|
|
}
|
|
|
|
void WindowManager::exitCurrentGuiMode()
|
|
{
|
|
if (mDragAndDrop && mDragAndDrop->mIsOnDragAndDrop)
|
|
{
|
|
mDragAndDrop->finish();
|
|
return;
|
|
}
|
|
|
|
GuiModeState& state = mGuiModeStates[mGuiModes.back()];
|
|
for (const auto& 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(
|
|
std::string_view message, const std::vector<std::string>& buttons, bool block)
|
|
{
|
|
mMessageBoxManager->createInteractiveMessageBox(message, buttons);
|
|
updateVisible();
|
|
|
|
if (block)
|
|
{
|
|
Misc::FrameRateLimiter frameRateLimiter
|
|
= Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
|
|
while (mMessageBoxManager->readPressedButton(false) == -1
|
|
&& !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
|
{
|
|
const double dt
|
|
= std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration())
|
|
.count();
|
|
|
|
mKeyboardNavigation->onFrame();
|
|
mMessageBoxManager->onFrame(dt);
|
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
|
|
|
if (!mWindowVisible)
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
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());
|
|
|
|
frameRateLimiter.limit();
|
|
}
|
|
}
|
|
}
|
|
|
|
void WindowManager::messageBox(std::string_view message, enum MWGui::ShowInDialogueMode showInDialogueMode)
|
|
{
|
|
if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never)
|
|
{
|
|
MyGUI::UString text = MyGUI::LanguageManager::getInstance().replaceTags(toUString(message));
|
|
mDialogueWindow->addMessageBox(text.asUTF8());
|
|
}
|
|
else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only)
|
|
{
|
|
mMessageBoxManager->createMessageBox(message);
|
|
}
|
|
}
|
|
|
|
void WindowManager::scheduleMessageBox(std::string message, enum MWGui::ShowInDialogueMode showInDialogueMode)
|
|
{
|
|
mScheduledMessageBoxes.lock()->emplace_back(std::move(message), showInDialogueMode);
|
|
}
|
|
|
|
void WindowManager::staticMessageBox(std::string_view message)
|
|
{
|
|
mMessageBoxManager->createMessageBox(message, true);
|
|
}
|
|
|
|
void WindowManager::removeStaticMessageBox()
|
|
{
|
|
mMessageBoxManager->removeStaticMessageBox();
|
|
}
|
|
|
|
int WindowManager::readPressedButton()
|
|
{
|
|
return mMessageBoxManager->readPressedButton();
|
|
}
|
|
|
|
std::string_view WindowManager::getGameSettingString(std::string_view id, std::string_view default_)
|
|
{
|
|
const ESM::GameSetting* setting = mStore->get<ESM::GameSetting>().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::update(float frameDuration)
|
|
{
|
|
handleScheduledMessageBoxes();
|
|
|
|
bool gameRunning
|
|
= MWBase::Environment::get().getStateManager()->getState() != MWBase::StateManager::State_NoGame;
|
|
|
|
if (gameRunning)
|
|
updateMap();
|
|
|
|
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<WindowModal*>::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();
|
|
|
|
if (mMessageBoxManager)
|
|
mMessageBoxManager->onFrame(frameDuration);
|
|
|
|
mToolTips->onFrame(frameDuration);
|
|
|
|
if (mLocalMapRender)
|
|
mLocalMapRender->cleanupCameras();
|
|
|
|
mDebugWindow->onFrame(frameDuration);
|
|
|
|
if (isConsoleMode())
|
|
mConsole->onFrame(frameDuration);
|
|
|
|
if (!gameRunning)
|
|
return;
|
|
|
|
// We should display message about crime only once per frame, even if there are several crimes.
|
|
// Otherwise we will get message spam when stealing several items via Take All button.
|
|
const MWWorld::Ptr player = MWMechanics::getPlayer();
|
|
const MWWorld::Class& playerCls = player.getClass();
|
|
int currentBounty = playerCls.getNpcStats(player).getBounty();
|
|
if (currentBounty != mPlayerBounty)
|
|
{
|
|
if (mPlayerBounty >= 0 && currentBounty > mPlayerBounty)
|
|
messageBox("#{sCrimeMessage}");
|
|
|
|
mPlayerBounty = currentBounty;
|
|
}
|
|
|
|
MWBase::LuaManager::ActorControls* playerControls
|
|
= MWBase::Environment::get().getLuaManager()->getActorControls(player);
|
|
bool triedToMove = playerControls
|
|
&& (playerControls->mMovement != 0 || playerControls->mSideMovement != 0 || playerControls->mJump);
|
|
if (triedToMove && playerCls.getEncumbrance(player) > playerCls.getCapacity(player))
|
|
{
|
|
const auto& msgboxs = mMessageBoxManager->getActiveMessageBoxes();
|
|
auto it
|
|
= std::find_if(msgboxs.begin(), msgboxs.end(), [](const std::unique_ptr<MWGui::MessageBox>& msgbox) {
|
|
return (msgbox->getMessage() == "#{sNotifyMessage59}");
|
|
});
|
|
|
|
// if an overencumbered messagebox is already present, reset its expiry timer,
|
|
// otherwise create a new one.
|
|
if (it != msgboxs.end())
|
|
(*it)->mCurrentTime = 0;
|
|
else
|
|
messageBox("#{sNotifyMessage59}");
|
|
}
|
|
|
|
mDragAndDrop->onFrame();
|
|
|
|
mHud->onFrame(frameDuration);
|
|
|
|
mPostProcessorHud->onFrame(frameDuration);
|
|
|
|
if (mCharGen)
|
|
mCharGen->onFrame(frameDuration);
|
|
|
|
updateActivatedQuickKey();
|
|
|
|
mStatsWatcher->update();
|
|
|
|
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);
|
|
auto cellCommon = cell->getCell();
|
|
|
|
if (cellCommon->isExterior())
|
|
{
|
|
if (!cellCommon->getNameId().empty())
|
|
mMap->addVisitedLocation(name, cellCommon->getGridX(), cellCommon->getGridY());
|
|
|
|
mMap->cellExplored(cellCommon->getGridX(), cellCommon->getGridY());
|
|
|
|
setActiveMap(cellCommon->getGridX(), cellCommon->getGridY(), false);
|
|
}
|
|
else
|
|
{
|
|
mMap->setCellPrefix(std::string(cellCommon->getNameId()));
|
|
mHud->setCellPrefix(std::string(cellCommon->getNameId()));
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
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);
|
|
|
|
const int showOwned = Settings::game().mShowOwned;
|
|
if (mHud && (showOwned == 2 || showOwned == 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);
|
|
}
|
|
|
|
void WindowManager::setCursorVisible(bool visible)
|
|
{
|
|
mCursorVisible = visible;
|
|
}
|
|
|
|
void WindowManager::setCursorActive(bool active)
|
|
{
|
|
mCursorActive = active;
|
|
}
|
|
|
|
void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result)
|
|
{
|
|
std::string_view tag = _tag.asUTF8();
|
|
|
|
std::string_view MyGuiPrefix = "setting=";
|
|
|
|
std::string_view tokenToFind = "sCell=";
|
|
|
|
if (tag.starts_with(MyGuiPrefix))
|
|
{
|
|
tag = tag.substr(MyGuiPrefix.length());
|
|
size_t comma_pos = tag.find(',');
|
|
std::string_view settingSection = tag.substr(0, comma_pos);
|
|
std::string_view settingTag = tag.substr(comma_pos + 1, tag.length());
|
|
|
|
_result = Settings::Manager::getString(settingTag, settingSection);
|
|
}
|
|
else if (tag.starts_with(tokenToFind))
|
|
{
|
|
std::string_view cellName = mTranslationDataStorage.translateCellName(tag.substr(tokenToFind.length()));
|
|
_result.assign(cellName.data(), cellName.size());
|
|
_result = MyGUI::TextIterator::toTagsString(_result);
|
|
}
|
|
else if (Gui::replaceTag(tag, _result))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
std::vector<std::string> split;
|
|
Misc::StringUtils::split(std::string{ tag }, split, ":");
|
|
|
|
l10n::Manager& l10nManager = *MWBase::Environment::get().getL10nManager();
|
|
|
|
// If a key has a "Context:KeyName" format, use YAML to translate data
|
|
if (split.size() == 2)
|
|
{
|
|
_result = l10nManager.getContext(split[0])->formatMessage(split[1], {}, {});
|
|
return;
|
|
}
|
|
|
|
// If not, treat is as GMST name from legacy localization
|
|
if (!mStore)
|
|
{
|
|
Log(Debug::Error) << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '"
|
|
<< tag << "'";
|
|
_result.assign(tag.data(), tag.size());
|
|
return;
|
|
}
|
|
const ESM::GameSetting* setting = mStore->get<ESM::GameSetting>().search(tag);
|
|
|
|
if (setting && setting->mValue.getType() == ESM::VT_String)
|
|
_result = setting->mValue.getString();
|
|
else
|
|
_result.assign(tag.data(), tag.size());
|
|
}
|
|
}
|
|
|
|
void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed)
|
|
{
|
|
mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI"));
|
|
|
|
bool changeRes = false;
|
|
for (const auto& setting : changed)
|
|
{
|
|
if (setting.first == "HUD" && setting.second == "crosshair")
|
|
mCrosshairEnabled = Settings::Manager::getBool("crosshair", "HUD");
|
|
else if (setting.first == "GUI" && setting.second == "subtitles")
|
|
mSubtitlesEnabled = Settings::Manager::getBool("subtitles", "GUI");
|
|
else if (setting.first == "GUI" && setting.second == "menu transparency")
|
|
setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI"));
|
|
else if (setting.first == "Video"
|
|
&& (setting.second == "resolution x" || setting.second == "resolution y"
|
|
|| setting.second == "window mode" || setting.second == "window border"))
|
|
changeRes = true;
|
|
|
|
else if (setting.first == "Video" && setting.second == "vsync mode")
|
|
mVideoWrapper->setSyncToVBlank(Settings::Manager::getInt("vsync mode", "Video"));
|
|
else if (setting.first == "Video" && (setting.second == "gamma" || setting.second == "contrast"))
|
|
mVideoWrapper->setGammaContrast(
|
|
Settings::Manager::getFloat("gamma", "Video"), Settings::Manager::getFloat("contrast", "Video"));
|
|
}
|
|
|
|
if (changeRes)
|
|
{
|
|
mVideoWrapper->setVideoMode(Settings::Manager::getInt("resolution x", "Video"),
|
|
Settings::Manager::getInt("resolution y", "Video"),
|
|
static_cast<Settings::WindowMode>(Settings::Manager::getInt("window mode", "Video")),
|
|
Settings::Manager::getBool("window border", "Video"));
|
|
}
|
|
}
|
|
|
|
void WindowManager::windowResized(int x, int y)
|
|
{
|
|
Settings::Manager::setInt("resolution x", "Video", x);
|
|
Settings::Manager::setInt("resolution y", "Video", y);
|
|
|
|
// We only want to process changes to window-size related settings.
|
|
Settings::CategorySettingVector filter = { { "Video", "resolution x" }, { "Video", "resolution y" } };
|
|
|
|
// If the HUD has not been initialised, the World singleton will not be available.
|
|
if (mHud)
|
|
{
|
|
MWBase::Environment::get().getWorld()->processChangedSettings(Settings::Manager::getPendingChanges(filter));
|
|
}
|
|
|
|
Settings::Manager::resetPendingChanges(filter);
|
|
|
|
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 (const auto& [window, settings] : mTrackedWindows)
|
|
{
|
|
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mMaximized : settings.mRegular;
|
|
window->setPosition(MyGUI::IntPoint(static_cast<int>(rect.mX * x), static_cast<int>(rect.mY * y)));
|
|
window->setSize(MyGUI::IntSize(static_cast<int>(rect.mW * x), static_cast<int>(rect.mH * y)));
|
|
}
|
|
|
|
for (const auto& window : mWindows)
|
|
window->onResChange(x, y);
|
|
|
|
// TODO: check if any windows are now off-screen and move them back if so
|
|
}
|
|
|
|
bool WindowManager::isWindowVisible()
|
|
{
|
|
return mWindowVisible;
|
|
}
|
|
|
|
void WindowManager::windowVisibilityChange(bool visible)
|
|
{
|
|
mWindowVisible = visible;
|
|
}
|
|
|
|
void WindowManager::windowClosed()
|
|
{
|
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
|
}
|
|
|
|
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)
|
|
{
|
|
pushGuiMode(mode, arg, false);
|
|
}
|
|
|
|
void WindowManager::forceLootMode(const MWWorld::Ptr& ptr)
|
|
{
|
|
pushGuiMode(MWGui::GM_Container, ptr, true);
|
|
}
|
|
|
|
void WindowManager::pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg, bool force)
|
|
{
|
|
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);
|
|
}
|
|
if (force)
|
|
mContainerWindow->treatNextOpenAsLoot();
|
|
for (WindowBase* window : mGuiModeStates[mode].mWindows)
|
|
window->setPtr(arg);
|
|
|
|
mKeyboardNavigation->restoreFocus(mode);
|
|
|
|
updateVisible();
|
|
}
|
|
|
|
void WindowManager::setCullMask(uint32_t mask)
|
|
{
|
|
mViewer->getCamera()->setCullMask(mask);
|
|
|
|
// We could check whether stereo is enabled here, but these methods are
|
|
// trivial and have no effect in mono or multiview so just call them regardless.
|
|
mViewer->getCamera()->setCullMaskLeft(mask);
|
|
mViewer->getCamera()->setCullMaskRight(mask);
|
|
}
|
|
|
|
uint32_t WindowManager::getCullMask()
|
|
{
|
|
return mViewer->getCamera()->getCullMask();
|
|
}
|
|
|
|
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();
|
|
|
|
// To make sure that console window get focus again
|
|
if (mConsole && mConsole->isVisible())
|
|
mConsole->onOpen();
|
|
}
|
|
|
|
void WindowManager::removeGuiMode(GuiMode mode, bool noSound)
|
|
{
|
|
if (!mGuiModes.empty() && mGuiModes.back() == mode)
|
|
{
|
|
popGuiMode(noSound);
|
|
return;
|
|
}
|
|
|
|
std::vector<GuiMode>::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 ESM::RefId& spellId, int successChancePercent)
|
|
{
|
|
mSelectedSpell = spellId;
|
|
mSelectedEnchantItem = MWWorld::Ptr();
|
|
mHud->setSelectedSpell(spellId, successChancePercent);
|
|
|
|
const ESM::Spell* spell = mStore->get<ESM::Spell>().find(spellId);
|
|
|
|
mSpellWindow->setTitle(spell->mName);
|
|
}
|
|
|
|
void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item)
|
|
{
|
|
mSelectedEnchantItem = item;
|
|
mSelectedSpell = ESM::RefId();
|
|
const ESM::Enchantment* ench = mStore->get<ESM::Enchantment>().find(item.getClass().getEnchantment(item));
|
|
|
|
int chargePercent = static_cast<int>(item.getCellRef().getNormalizedEnchantmentCharge(*ench) * 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 = 100;
|
|
if (item.getClass().hasItemHealth(item))
|
|
{
|
|
durabilityPercent = static_cast<int>(item.getClass().getItemNormalizedHealth(item) * 100);
|
|
}
|
|
mHud->setSelectedWeapon(item, durabilityPercent);
|
|
mInventoryWindow->setTitle(item.getClass().getName(item));
|
|
}
|
|
|
|
const MWWorld::Ptr& WindowManager::getSelectedWeapon() const
|
|
{
|
|
return mSelectedWeapon;
|
|
}
|
|
|
|
void WindowManager::unsetSelectedSpell()
|
|
{
|
|
mSelectedSpell = ESM::RefId();
|
|
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("#{Interface:None}");
|
|
}
|
|
|
|
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<float>(pos.left);
|
|
y = static_cast<float>(pos.top);
|
|
const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
x /= viewSize.width;
|
|
y /= viewSize.height;
|
|
}
|
|
|
|
bool WindowManager::getWorldMouseOver()
|
|
{
|
|
return mHud->getWorldMouseOver();
|
|
}
|
|
|
|
float WindowManager::getScalingFactor() const
|
|
{
|
|
return mScalingFactor;
|
|
}
|
|
|
|
void WindowManager::executeInConsole(const std::filesystem::path& path)
|
|
{
|
|
mConsole->executeFile(path);
|
|
}
|
|
|
|
MWGui::InventoryWindow* WindowManager::getInventoryWindow()
|
|
{
|
|
return mInventoryWindow;
|
|
}
|
|
MWGui::CountDialog* WindowManager::getCountDialog()
|
|
{
|
|
return mCountDialog;
|
|
}
|
|
MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog()
|
|
{
|
|
return mConfirmationDialog;
|
|
}
|
|
MWGui::TradeWindow* WindowManager::getTradeWindow()
|
|
{
|
|
return mTradeWindow;
|
|
}
|
|
MWGui::PostProcessorHud* WindowManager::getPostProcessorHud()
|
|
{
|
|
return mPostProcessorHud;
|
|
}
|
|
|
|
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;
|
|
|
|
if (Settings::SettingValue<bool>* const hidden = findHiddenSetting(wnd))
|
|
hidden->set(!hidden->get());
|
|
|
|
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() || isConsoleMode() || (mPostProcessorHud && mPostProcessorHud->isVisible())
|
|
|| (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox());
|
|
}
|
|
|
|
bool WindowManager::isConsoleMode() const
|
|
{
|
|
return mConsole && mConsole->isVisible();
|
|
}
|
|
|
|
bool WindowManager::isPostProcessorHudVisible() const
|
|
{
|
|
return mPostProcessorHud->isVisible();
|
|
}
|
|
|
|
MWGui::GuiMode WindowManager::getMode() const
|
|
{
|
|
if (mGuiModes.empty())
|
|
return GM_None;
|
|
return mGuiModes.back();
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
bool WindowManager::getSubtitlesEnabled()
|
|
{
|
|
return mSubtitlesEnabled;
|
|
}
|
|
|
|
bool WindowManager::toggleHud()
|
|
{
|
|
mHudEnabled = !mHudEnabled;
|
|
updateVisible();
|
|
mMessageBoxManager->setVisible(mHudEnabled);
|
|
return mHudEnabled;
|
|
}
|
|
|
|
bool WindowManager::getRestEnabled()
|
|
{
|
|
// Enable rest dialogue if character creation finished
|
|
if (mRestAllowed == false
|
|
&& MWBase::Environment::get().getWorld()->getGlobalFloat(MWWorld::Globals::sCharGenState) == -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 wrapper once onKeyFocusChanged call is rendered unnecessary
|
|
void WindowManager::setKeyFocusWidget(MyGUI::Widget* widget)
|
|
{
|
|
MyGUI::InputManager::getInstance().setKeyFocusWidget(widget);
|
|
onKeyFocusChanged(widget);
|
|
}
|
|
|
|
void WindowManager::onKeyFocusChanged(MyGUI::Widget* widget)
|
|
{
|
|
if (widget && widget->castType<MyGUI::EditBox>(false))
|
|
SDL_StartTextInput();
|
|
else
|
|
SDL_StopTextInput();
|
|
}
|
|
|
|
void WindowManager::setEnemy(const MWWorld::Ptr& enemy)
|
|
{
|
|
mHud->setEnemy(enemy);
|
|
}
|
|
|
|
int WindowManager::getMessagesCount() const
|
|
{
|
|
int count = 0;
|
|
if (mMessageBoxManager)
|
|
count = mMessageBoxManager->getMessagesCount();
|
|
|
|
return count;
|
|
}
|
|
|
|
Loading::Listener* WindowManager::getLoadingScreen()
|
|
{
|
|
return mLoadingScreen;
|
|
}
|
|
|
|
bool WindowManager::getCursorVisible()
|
|
{
|
|
return mCursorVisible && mCursorActive;
|
|
}
|
|
|
|
void WindowManager::trackWindow(Layout* layout, const WindowSettingValues& settings)
|
|
{
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
|
|
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mMaximized : settings.mRegular;
|
|
|
|
layout->mMainWidget->setPosition(
|
|
MyGUI::IntPoint(static_cast<int>(rect.mX * viewSize.width), static_cast<int>(rect.mY * viewSize.height)));
|
|
layout->mMainWidget->setSize(
|
|
MyGUI::IntSize(static_cast<int>(rect.mW * viewSize.width), static_cast<int>(rect.mH * viewSize.height)));
|
|
|
|
MyGUI::Window* window = layout->mMainWidget->castType<MyGUI::Window>();
|
|
window->eventWindowChangeCoord += MyGUI::newDelegate(this, &WindowManager::onWindowChangeCoord);
|
|
mTrackedWindows.emplace(window, settings);
|
|
}
|
|
|
|
void WindowManager::toggleMaximized(Layout* layout)
|
|
{
|
|
MyGUI::Window* window = layout->mMainWidget->castType<MyGUI::Window>();
|
|
const auto it = mTrackedWindows.find(window);
|
|
if (it == mTrackedWindows.end())
|
|
return;
|
|
|
|
const WindowSettingValues& settings = it->second;
|
|
const WindowRectSettingValues& rect = settings.mIsMaximized ? settings.mRegular : settings.mMaximized;
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
const float x = rect.mX * viewSize.width;
|
|
const float y = rect.mY * viewSize.height;
|
|
const float w = rect.mW * viewSize.width;
|
|
const float h = rect.mH * viewSize.height;
|
|
window->setCoord(x, y, w, h);
|
|
|
|
settings.mIsMaximized.set(!settings.mIsMaximized.get());
|
|
}
|
|
|
|
void WindowManager::onWindowChangeCoord(MyGUI::Window* window)
|
|
{
|
|
const auto it = mTrackedWindows.find(window);
|
|
if (it == mTrackedWindows.end())
|
|
return;
|
|
|
|
const WindowSettingValues& settings = it->second;
|
|
|
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
|
settings.mRegular.mX.set(window->getPosition().left / static_cast<float>(viewSize.width));
|
|
settings.mRegular.mY.set(window->getPosition().top / static_cast<float>(viewSize.height));
|
|
settings.mRegular.mW.set(window->getSize().width / static_cast<float>(viewSize.width));
|
|
settings.mRegular.mH.set(window->getSize().height / static_cast<float>(viewSize.height));
|
|
|
|
settings.mIsMaximized.set(false);
|
|
}
|
|
|
|
void WindowManager::clear()
|
|
{
|
|
mPlayerBounty = -1;
|
|
|
|
for (const auto& window : mWindows)
|
|
window->clear();
|
|
|
|
if (mLocalMapRender)
|
|
mLocalMapRender->clear();
|
|
|
|
mMessageBoxManager->clear();
|
|
|
|
mToolTips->clear();
|
|
|
|
mSelectedSpell = ESM::RefId();
|
|
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.writeHNRefId("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__");
|
|
ESM::RefId spell = reader.getRefId();
|
|
if (mStore->get<ESM::Spell>().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()
|
|
&& !isConsoleMode()
|
|
// 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(std::string_view name, bool allowSkipping, bool overrideSounds)
|
|
{
|
|
mVideoWidget->playVideo("video\\" + std::string{ name });
|
|
|
|
mVideoWidget->eventKeyButtonPressed.clear();
|
|
mVideoBackground->eventKeyButtonPressed.clear();
|
|
if (allowSkipping)
|
|
{
|
|
mVideoWidget->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed);
|
|
mVideoBackground->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed);
|
|
}
|
|
|
|
enableScene(false);
|
|
|
|
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 (overrideSounds && mVideoWidget->hasAudioStream())
|
|
MWBase::Environment::get().getSoundManager()->pauseSounds(
|
|
MWSound::VideoPlayback, ~MWSound::Type::Movie & MWSound::Type::Mask);
|
|
|
|
Misc::FrameRateLimiter frameRateLimiter
|
|
= Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit());
|
|
while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest())
|
|
{
|
|
const double dt
|
|
= std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration())
|
|
.count();
|
|
|
|
MWBase::Environment::get().getInputManager()->update(dt, true, false);
|
|
|
|
if (!mWindowVisible)
|
|
{
|
|
mVideoWidget->pause();
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(5));
|
|
}
|
|
else
|
|
{
|
|
if (mVideoWidget->isPaused())
|
|
mVideoWidget->resume();
|
|
|
|
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());
|
|
|
|
frameRateLimiter.limit();
|
|
}
|
|
mVideoWidget->stop();
|
|
|
|
MWBase::Environment::get().getSoundManager()->resumeSounds(MWSound::VideoPlayback);
|
|
|
|
setKeyFocusWidget(oldKeyFocus);
|
|
|
|
setCursorVisible(cursorWasVisible);
|
|
|
|
// Restore normal rendering
|
|
updateVisible();
|
|
|
|
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
|
|
Log(Debug::Warning) << "Warning: can't find modal window " << input;
|
|
}
|
|
}
|
|
if (mCurrentModals.empty())
|
|
{
|
|
mKeyboardNavigation->setModalWindow(nullptr);
|
|
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::windows().mInventoryPin);
|
|
if (Settings::windows().mInventoryHidden)
|
|
mShown = (GuiWindow)(mShown ^ GW_Inventory);
|
|
|
|
mMap->setPinned(Settings::windows().mMapPin);
|
|
if (Settings::windows().mMapHidden)
|
|
mShown = (GuiWindow)(mShown ^ GW_Map);
|
|
|
|
mSpellWindow->setPinned(Settings::windows().mSpellsPin);
|
|
if (Settings::windows().mSpellsHidden)
|
|
mShown = (GuiWindow)(mShown ^ GW_Magic);
|
|
|
|
mStatsWindow->setPinned(Settings::windows().mStatsPin);
|
|
if (Settings::windows().mStatsHidden)
|
|
mShown = (GuiWindow)(mShown ^ GW_Stats);
|
|
}
|
|
|
|
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 = nullptr;
|
|
text = SDL_GetClipboardText();
|
|
if (text)
|
|
_data = MyGUI::TextIterator::toTagsString(text);
|
|
|
|
SDL_free(text);
|
|
}
|
|
|
|
void WindowManager::toggleConsole()
|
|
{
|
|
bool visible = mConsole->isVisible();
|
|
|
|
if (!visible && !mGuiModes.empty())
|
|
mKeyboardNavigation->saveFocus(mGuiModes.back());
|
|
|
|
mConsole->setVisible(!visible);
|
|
|
|
if (visible && !mGuiModes.empty())
|
|
mKeyboardNavigation->restoreFocus(mGuiModes.back());
|
|
|
|
updateVisible();
|
|
}
|
|
|
|
void WindowManager::toggleDebugWindow()
|
|
{
|
|
mDebugWindow->setVisible(!mDebugWindow->isVisible());
|
|
}
|
|
|
|
void WindowManager::togglePostProcessorHud()
|
|
{
|
|
if (!MWBase::Environment::get().getWorld()->getPostProcessor()->isEnabled())
|
|
{
|
|
messageBox("#{OMWEngine:PostProcessingIsNotEnabled}");
|
|
return;
|
|
}
|
|
|
|
bool visible = mPostProcessorHud->isVisible();
|
|
|
|
if (!visible && !mGuiModes.empty())
|
|
mKeyboardNavigation->saveFocus(mGuiModes.back());
|
|
|
|
mPostProcessorHud->setVisible(!visible);
|
|
|
|
if (visible && !mGuiModes.empty())
|
|
mKeyboardNavigation->restoreFocus(mGuiModes.back());
|
|
|
|
updateVisible();
|
|
}
|
|
|
|
void WindowManager::cycleSpell(bool next)
|
|
{
|
|
if (!isGuiMode())
|
|
mSpellWindow->cycle(next);
|
|
}
|
|
|
|
void WindowManager::cycleWeapon(bool next)
|
|
{
|
|
if (!isGuiMode())
|
|
mInventoryWindow->cycle(next);
|
|
}
|
|
|
|
void WindowManager::playSound(const ESM::RefId& soundId, float volume, float pitch)
|
|
{
|
|
if (soundId.empty())
|
|
return;
|
|
|
|
MWBase::Environment::get().getSoundManager()->playSound(
|
|
soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnvNoScaling);
|
|
}
|
|
|
|
void WindowManager::updateSpellWindow()
|
|
{
|
|
if (mSpellWindow)
|
|
mSpellWindow->updateSpells();
|
|
}
|
|
|
|
void WindowManager::setConsoleSelectedObject(const MWWorld::Ptr& object)
|
|
{
|
|
mConsole->setSelectedObject(object);
|
|
}
|
|
|
|
MWWorld::Ptr WindowManager::getConsoleSelectedObject() const
|
|
{
|
|
return mConsole->getSelectedObject();
|
|
}
|
|
|
|
void WindowManager::printToConsole(const std::string& msg, std::string_view color)
|
|
{
|
|
mConsole->print(msg, color);
|
|
}
|
|
|
|
void WindowManager::setConsoleMode(const std::string& mode)
|
|
{
|
|
mConsole->setConsoleMode(mode);
|
|
}
|
|
|
|
void WindowManager::createCursors()
|
|
{
|
|
MyGUI::ResourceManager::EnumeratorPtr enumerator = MyGUI::ResourceManager::getInstance().getEnumerator();
|
|
while (enumerator.next())
|
|
{
|
|
MyGUI::IResource* resource = enumerator.current().second;
|
|
ResourceImageSetPointerFix* imgSetPointer = resource->castType<ResourceImageSetPointerFix>(false);
|
|
if (!imgSetPointer)
|
|
continue;
|
|
std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0, 0).texture;
|
|
|
|
osg::ref_ptr<osg::Image> 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();
|
|
MyGUI::IntSize pointerSize = imgSetPointer->getSize();
|
|
|
|
mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, image, hotspot_x, hotspot_y,
|
|
pointerSize.width, pointerSize.height);
|
|
}
|
|
}
|
|
}
|
|
|
|
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<unsigned char*>(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<unsigned char*>(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<unsigned char*>(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<unsigned char>(value * 255);
|
|
}
|
|
tex->unlock();
|
|
}
|
|
|
|
void WindowManager::addCell(MWWorld::CellStore* cell)
|
|
{
|
|
mLocalMapRender->addCell(cell);
|
|
}
|
|
|
|
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, bool repeat)
|
|
{
|
|
if (!mKeyboardNavigation->injectKeyPress(key, text, repeat))
|
|
{
|
|
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;
|
|
}
|
|
|
|
bool WindowManager::injectKeyRelease(MyGUI::KeyCode key)
|
|
{
|
|
return MyGUI::InputManager::getInstance().injectKeyRelease(key);
|
|
}
|
|
|
|
void WindowManager::GuiModeState::update(bool visible)
|
|
{
|
|
for (const auto& window : mWindows)
|
|
window->setVisible(visible);
|
|
}
|
|
|
|
void WindowManager::watchActor(const MWWorld::Ptr& ptr)
|
|
{
|
|
mStatsWatcher->watchActor(ptr);
|
|
}
|
|
|
|
MWWorld::Ptr WindowManager::getWatchedActor() const
|
|
{
|
|
return mStatsWatcher->getWatchedActor();
|
|
}
|
|
|
|
const std::string& WindowManager::getVersionDescription() const
|
|
{
|
|
return mVersionDescription;
|
|
}
|
|
|
|
void WindowManager::handleScheduledMessageBoxes()
|
|
{
|
|
const auto scheduledMessageBoxes = mScheduledMessageBoxes.lock();
|
|
for (const ScheduledMessageBox& v : *scheduledMessageBoxes)
|
|
messageBox(v.mMessage, v.mShowInDialogueMode);
|
|
scheduledMessageBoxes->clear();
|
|
}
|
|
|
|
void WindowManager::onDeleteCustomData(const MWWorld::Ptr& ptr)
|
|
{
|
|
for (const auto& window : mWindows)
|
|
window->onDeleteCustomData(ptr);
|
|
}
|
|
|
|
void WindowManager::asyncPrepareSaveMap()
|
|
{
|
|
mMap->asyncPrepareSaveMap();
|
|
}
|
|
}
|