1 #include "windowmanagerimp.hpp" 2 3 #include <algorithm> 4 #include <cassert> 5 #include <chrono> 6 #include <thread> 7 8 #include <osgViewer/Viewer> 9 10 #include <MyGUI_UString.h> 11 #include <MyGUI_IPointer.h> 12 #include <MyGUI_FactoryManager.h> 13 #include <MyGUI_LanguageManager.h> 14 #include <MyGUI_PointerManager.h> 15 #include <MyGUI_InputManager.h> 16 #include <MyGUI_Gui.h> 17 #include <MyGUI_ClipboardManager.h> 18 #include <MyGUI_WidgetManager.h> 19 20 // For BT_NO_PROFILE 21 #include <LinearMath/btQuickprof.h> 22 23 #include <SDL_keyboard.h> 24 #include <SDL_clipboard.h> 25 26 #include <components/debug/debuglog.hpp> 27 28 #include <components/sdlutil/sdlcursormanager.hpp> 29 #include <components/sdlutil/sdlvideowrapper.hpp> 30 31 #include <components/esm/esmreader.hpp> 32 #include <components/esm/esmwriter.hpp> 33 34 #include <components/fontloader/fontloader.hpp> 35 36 #include <components/resource/resourcesystem.hpp> 37 #include <components/resource/imagemanager.hpp> 38 39 #include <components/sceneutil/workqueue.hpp> 40 41 #include <components/translation/translation.hpp> 42 43 #include <components/myguiplatform/myguiplatform.hpp> 44 #include <components/myguiplatform/myguirendermanager.hpp> 45 #include <components/myguiplatform/additivelayer.hpp> 46 #include <components/myguiplatform/scalinglayer.hpp> 47 48 #include <components/vfs/manager.hpp> 49 50 #include <components/widgets/tags.hpp> 51 52 #include <components/misc/resourcehelpers.hpp> 53 #include <components/misc/frameratelimiter.hpp> 54 55 #include "../mwbase/inputmanager.hpp" 56 #include "../mwbase/statemanager.hpp" 57 #include "../mwbase/soundmanager.hpp" 58 #include "../mwbase/world.hpp" 59 60 #include "../mwrender/vismask.hpp" 61 62 #include "../mwworld/class.hpp" 63 #include "../mwworld/player.hpp" 64 #include "../mwworld/cellstore.hpp" 65 #include "../mwworld/esmstore.hpp" 66 67 #include "../mwmechanics/npcstats.hpp" 68 #include "../mwmechanics/actorutil.hpp" 69 70 #include "../mwrender/localmap.hpp" 71 72 #include "console.hpp" 73 #include "journalwindow.hpp" 74 #include "journalviewmodel.hpp" 75 #include "charactercreation.hpp" 76 #include "dialogue.hpp" 77 #include "statswindow.hpp" 78 #include "messagebox.hpp" 79 #include "tooltips.hpp" 80 #include "scrollwindow.hpp" 81 #include "bookwindow.hpp" 82 #include "hud.hpp" 83 #include "mainmenu.hpp" 84 #include "countdialog.hpp" 85 #include "tradewindow.hpp" 86 #include "spellbuyingwindow.hpp" 87 #include "travelwindow.hpp" 88 #include "settingswindow.hpp" 89 #include "confirmationdialog.hpp" 90 #include "alchemywindow.hpp" 91 #include "spellwindow.hpp" 92 #include "quickkeysmenu.hpp" 93 #include "loadingscreen.hpp" 94 #include "levelupdialog.hpp" 95 #include "waitdialog.hpp" 96 #include "enchantingdialog.hpp" 97 #include "trainingwindow.hpp" 98 #include "recharge.hpp" 99 #include "exposedwindow.hpp" 100 #include "cursor.hpp" 101 #include "merchantrepair.hpp" 102 #include "repair.hpp" 103 #include "soulgemdialog.hpp" 104 #include "companionwindow.hpp" 105 #include "inventorywindow.hpp" 106 #include "bookpage.hpp" 107 #include "itemview.hpp" 108 #include "videowidget.hpp" 109 #include "backgroundimage.hpp" 110 #include "itemwidget.hpp" 111 #include "screenfader.hpp" 112 #include "debugwindow.hpp" 113 #include "spellview.hpp" 114 #include "draganddrop.hpp" 115 #include "container.hpp" 116 #include "controllers.hpp" 117 #include "jailscreen.hpp" 118 #include "itemchargeview.hpp" 119 #include "keyboardnavigation.hpp" 120 #include "resourceskin.hpp" 121 122 namespace MWGui 123 { WindowManager(SDL_Window * window,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::string & versionDescription,const std::string & userDataPath)124 WindowManager::WindowManager( 125 SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue, 126 const std::string& logpath, const std::string& resourcePath, bool consoleOnlyScripts, Translation::Storage& translationDataStorage, 127 ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& userDataPath) 128 : mOldUpdateMask(0) 129 , mOldCullMask(0) 130 , mStore(nullptr) 131 , mResourceSystem(resourceSystem) 132 , mWorkQueue(workQueue) 133 , mViewer(viewer) 134 , mConsoleOnlyScripts(consoleOnlyScripts) 135 , mCurrentModals() 136 , mHud(nullptr) 137 , mMap(nullptr) 138 , mLocalMapRender(nullptr) 139 , mToolTips(nullptr) 140 , mStatsWindow(nullptr) 141 , mMessageBoxManager(nullptr) 142 , mConsole(nullptr) 143 , mDialogueWindow(nullptr) 144 , mDragAndDrop(nullptr) 145 , mInventoryWindow(nullptr) 146 , mScrollWindow(nullptr) 147 , mBookWindow(nullptr) 148 , mCountDialog(nullptr) 149 , mTradeWindow(nullptr) 150 , mSettingsWindow(nullptr) 151 , mConfirmationDialog(nullptr) 152 , mSpellWindow(nullptr) 153 , mQuickKeysMenu(nullptr) 154 , mLoadingScreen(nullptr) 155 , mWaitDialog(nullptr) 156 , mSoulgemDialog(nullptr) 157 , mVideoBackground(nullptr) 158 , mVideoWidget(nullptr) 159 , mWerewolfFader(nullptr) 160 , mBlindnessFader(nullptr) 161 , mHitFader(nullptr) 162 , mScreenFader(nullptr) 163 , mDebugWindow(nullptr) 164 , mJailScreen(nullptr) 165 , mTranslationDataStorage (translationDataStorage) 166 , mCharGen(nullptr) 167 , mInputBlocker(nullptr) 168 , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) 169 , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) 170 , mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI")) 171 , mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI")) 172 , mHudEnabled(true) 173 , mCursorVisible(true) 174 , mCursorActive(true) 175 , mPlayerBounty(-1) 176 , mGui(nullptr) 177 , mGuiModes() 178 , mCursorManager(nullptr) 179 , mGarbageDialogs() 180 , mShown(GW_ALL) 181 , mForceHidden(GW_None) 182 , mAllowed(GW_ALL) 183 , mRestAllowed(true) 184 , mShowOwned(0) 185 , mEncoding(encoding) 186 , mVersionDescription(versionDescription) 187 , mWindowVisible(true) 188 { 189 mScalingFactor = std::clamp(Settings::Manager::getFloat("scaling factor", "GUI"), 0.5f, 8.f); 190 mGuiPlatform = new osgMyGUI::Platform(viewer, guiRoot, resourceSystem->getImageManager(), mScalingFactor); 191 mGuiPlatform->initialise(resourcePath, (boost::filesystem::path(logpath) / "MyGUI.log").generic_string()); 192 193 mGui = new MyGUI::Gui; 194 mGui->initialise(""); 195 196 createTextures(); 197 198 MyGUI::LanguageManager::getInstance().eventRequestTag = MyGUI::newDelegate(this, &WindowManager::onRetrieveTag); 199 200 // Load fonts 201 mFontLoader.reset(new Gui::FontLoader(encoding, resourceSystem->getVFS(), userDataPath, mScalingFactor)); 202 mFontLoader->loadBitmapFonts(exportFonts); 203 204 //Register own widgets with MyGUI 205 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSkill>("Widget"); 206 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWAttribute>("Widget"); 207 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpell>("Widget"); 208 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWEffectList>("Widget"); 209 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWSpellEffect>("Widget"); 210 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Widgets::MWDynamicStat>("Widget"); 211 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Window>("Widget"); 212 MyGUI::FactoryManager::getInstance().registerFactory<VideoWidget>("Widget"); 213 MyGUI::FactoryManager::getInstance().registerFactory<BackgroundImage>("Widget"); 214 MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::AdditiveLayer>("Layer"); 215 MyGUI::FactoryManager::getInstance().registerFactory<osgMyGUI::ScalingLayer>("Layer"); 216 BookPage::registerMyGUIComponents (); 217 ItemView::registerComponents(); 218 ItemChargeView::registerComponents(); 219 ItemWidget::registerComponents(); 220 SpellView::registerComponents(); 221 Gui::registerAllWidgets(); 222 223 MyGUI::FactoryManager::getInstance().registerFactory<MWGui::Controllers::ControllerFollowMouse>("Controller"); 224 225 MyGUI::FactoryManager::getInstance().registerFactory<ResourceImageSetPointerFix>("Resource", "ResourceImageSetPointer"); 226 MyGUI::FactoryManager::getInstance().registerFactory<AutoSizedResourceSkin>("Resource", "AutoSizedResourceSkin"); 227 MyGUI::ResourceManager::getInstance().load("core.xml"); 228 WindowManager::loadUserFonts(); 229 230 bool keyboardNav = Settings::Manager::getBool("keyboard navigation", "GUI"); 231 mKeyboardNavigation.reset(new KeyboardNavigation()); 232 mKeyboardNavigation->setEnabled(keyboardNav); 233 Gui::ImageButton::setDefaultNeedKeyFocus(keyboardNav); 234 235 mLoadingScreen = new LoadingScreen(mResourceSystem, mViewer); 236 mWindows.push_back(mLoadingScreen); 237 238 //set up the hardware cursor manager 239 mCursorManager = new SDLUtil::SDLCursorManager(); 240 241 MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); 242 243 MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); 244 245 // Create all cursors in advance 246 createCursors(); 247 onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); 248 mCursorManager->setEnabled(true); 249 250 // hide mygui's pointer 251 MyGUI::PointerManager::getInstance().setVisible(false); 252 253 mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal<MyGUI::ImageBox>("ImageBox", 0,0,1,1, 254 MyGUI::Align::Default, "InputBlocker"); 255 mVideoBackground->setImageTexture("black"); 256 mVideoBackground->setVisible(false); 257 mVideoBackground->setNeedMouseFocus(true); 258 mVideoBackground->setNeedKeyFocus(true); 259 260 mVideoWidget = mVideoBackground->createWidgetReal<VideoWidget>("ImageBox", 0,0,1,1, MyGUI::Align::Default); 261 mVideoWidget->setNeedMouseFocus(true); 262 mVideoWidget->setNeedKeyFocus(true); 263 mVideoWidget->setVFS(resourceSystem->getVFS()); 264 265 // Removes default MyGUI system clipboard implementation, which supports windows only 266 MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear(); 267 MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear(); 268 269 MyGUI::ClipboardManager::getInstance().eventClipboardChanged += MyGUI::newDelegate(this, &WindowManager::onClipboardChanged); 270 MyGUI::ClipboardManager::getInstance().eventClipboardRequested += MyGUI::newDelegate(this, &WindowManager::onClipboardRequested); 271 272 mShowOwned = Settings::Manager::getInt("show owned", "Game"); 273 274 mVideoWrapper = new SDLUtil::VideoWrapper(window, viewer); 275 mVideoWrapper->setGammaContrast(Settings::Manager::getFloat("gamma", "Video"), 276 Settings::Manager::getFloat("contrast", "Video")); 277 278 mStatsWatcher.reset(new StatsWatcher()); 279 } 280 loadUserFonts()281 void WindowManager::loadUserFonts() 282 { 283 mFontLoader->loadTrueTypeFonts(); 284 } 285 initUI()286 void WindowManager::initUI() 287 { 288 // Get size info from the Gui object 289 int w = MyGUI::RenderManager::getInstance().getViewSize().width; 290 int h = MyGUI::RenderManager::getInstance().getViewSize().height; 291 292 mTextColours.loadColours(); 293 294 mDragAndDrop = new DragAndDrop(); 295 296 Recharge* recharge = new Recharge(); 297 mGuiModeStates[GM_Recharge] = GuiModeState(recharge); 298 mWindows.push_back(recharge); 299 300 MainMenu* menu = new MainMenu(w, h, mResourceSystem->getVFS(), mVersionDescription); 301 mGuiModeStates[GM_MainMenu] = GuiModeState(menu); 302 mWindows.push_back(menu); 303 304 mLocalMapRender = new MWRender::LocalMap(mViewer->getSceneData()->asGroup()); 305 mMap = new MapWindow(mCustomMarkers, mDragAndDrop, mLocalMapRender, mWorkQueue); 306 mWindows.push_back(mMap); 307 mMap->renderGlobalMap(); 308 trackWindow(mMap, "map"); 309 310 mStatsWindow = new StatsWindow(mDragAndDrop); 311 mWindows.push_back(mStatsWindow); 312 trackWindow(mStatsWindow, "stats"); 313 314 mInventoryWindow = new InventoryWindow(mDragAndDrop, mViewer->getSceneData()->asGroup(), mResourceSystem); 315 mWindows.push_back(mInventoryWindow); 316 317 mSpellWindow = new SpellWindow(mDragAndDrop); 318 mWindows.push_back(mSpellWindow); 319 trackWindow(mSpellWindow, "spells"); 320 321 mGuiModeStates[GM_Inventory] = GuiModeState({mMap, mInventoryWindow, mSpellWindow, mStatsWindow}); 322 mGuiModeStates[GM_None] = GuiModeState({mMap, mInventoryWindow, mSpellWindow, mStatsWindow}); 323 324 mTradeWindow = new TradeWindow(); 325 mWindows.push_back(mTradeWindow); 326 trackWindow(mTradeWindow, "barter"); 327 mGuiModeStates[GM_Barter] = GuiModeState({mInventoryWindow, mTradeWindow}); 328 329 mConsole = new Console(w,h, mConsoleOnlyScripts); 330 mWindows.push_back(mConsole); 331 trackWindow(mConsole, "console"); 332 333 bool questList = mResourceSystem->getVFS()->exists("textures/tx_menubook_options_over.dds"); 334 JournalWindow* journal = JournalWindow::create(JournalViewModel::create (), questList, mEncoding); 335 mWindows.push_back(journal); 336 mGuiModeStates[GM_Journal] = GuiModeState(journal); 337 mGuiModeStates[GM_Journal].mCloseSound = "book close"; 338 mGuiModeStates[GM_Journal].mOpenSound = "book open"; 339 340 mMessageBoxManager = new MessageBoxManager(mStore->get<ESM::GameSetting>().find("fMessageTimePerChar")->mValue.getFloat()); 341 342 SpellBuyingWindow* spellBuyingWindow = new SpellBuyingWindow(); 343 mWindows.push_back(spellBuyingWindow); 344 mGuiModeStates[GM_SpellBuying] = GuiModeState(spellBuyingWindow); 345 346 TravelWindow* travelWindow = new TravelWindow(); 347 mWindows.push_back(travelWindow); 348 mGuiModeStates[GM_Travel] = GuiModeState(travelWindow); 349 350 mDialogueWindow = new DialogueWindow(); 351 mWindows.push_back(mDialogueWindow); 352 trackWindow(mDialogueWindow, "dialogue"); 353 mGuiModeStates[GM_Dialogue] = GuiModeState(mDialogueWindow); 354 mTradeWindow->eventTradeDone += MyGUI::newDelegate(mDialogueWindow, &DialogueWindow::onTradeComplete); 355 356 ContainerWindow* containerWindow = new ContainerWindow(mDragAndDrop); 357 mWindows.push_back(containerWindow); 358 trackWindow(containerWindow, "container"); 359 mGuiModeStates[GM_Container] = GuiModeState({containerWindow, mInventoryWindow}); 360 361 mHud = new HUD(mCustomMarkers, mDragAndDrop, mLocalMapRender); 362 mWindows.push_back(mHud); 363 364 mToolTips = new ToolTips(); 365 366 mScrollWindow = new ScrollWindow(); 367 mWindows.push_back(mScrollWindow); 368 mGuiModeStates[GM_Scroll] = GuiModeState(mScrollWindow); 369 mGuiModeStates[GM_Scroll].mOpenSound = "scroll"; 370 mGuiModeStates[GM_Scroll].mCloseSound = "scroll"; 371 372 mBookWindow = new BookWindow(); 373 mWindows.push_back(mBookWindow); 374 mGuiModeStates[GM_Book] = GuiModeState(mBookWindow); 375 mGuiModeStates[GM_Book].mOpenSound = "book open"; 376 mGuiModeStates[GM_Book].mCloseSound = "book close"; 377 378 mCountDialog = new CountDialog(); 379 mWindows.push_back(mCountDialog); 380 381 mSettingsWindow = new SettingsWindow(); 382 mWindows.push_back(mSettingsWindow); 383 mGuiModeStates[GM_Settings] = GuiModeState(mSettingsWindow); 384 385 mConfirmationDialog = new ConfirmationDialog(); 386 mWindows.push_back(mConfirmationDialog); 387 388 AlchemyWindow* alchemyWindow = new AlchemyWindow(); 389 mWindows.push_back(alchemyWindow); 390 trackWindow(alchemyWindow, "alchemy"); 391 mGuiModeStates[GM_Alchemy] = GuiModeState(alchemyWindow); 392 393 mQuickKeysMenu = new QuickKeysMenu(); 394 mWindows.push_back(mQuickKeysMenu); 395 mGuiModeStates[GM_QuickKeysMenu] = GuiModeState(mQuickKeysMenu); 396 397 LevelupDialog* levelupDialog = new LevelupDialog(); 398 mWindows.push_back(levelupDialog); 399 mGuiModeStates[GM_Levelup] = GuiModeState(levelupDialog); 400 401 mWaitDialog = new WaitDialog(); 402 mWindows.push_back(mWaitDialog); 403 mGuiModeStates[GM_Rest] = GuiModeState({mWaitDialog->getProgressBar(), mWaitDialog}); 404 405 SpellCreationDialog* spellCreationDialog = new SpellCreationDialog(); 406 mWindows.push_back(spellCreationDialog); 407 mGuiModeStates[GM_SpellCreation] = GuiModeState(spellCreationDialog); 408 409 EnchantingDialog* enchantingDialog = new EnchantingDialog(); 410 mWindows.push_back(enchantingDialog); 411 mGuiModeStates[GM_Enchanting] = GuiModeState(enchantingDialog); 412 413 TrainingWindow* trainingWindow = new TrainingWindow(); 414 mWindows.push_back(trainingWindow); 415 mGuiModeStates[GM_Training] = GuiModeState({trainingWindow->getProgressBar(), trainingWindow}); 416 417 MerchantRepair* merchantRepair = new MerchantRepair(); 418 mWindows.push_back(merchantRepair); 419 mGuiModeStates[GM_MerchantRepair] = GuiModeState(merchantRepair); 420 421 Repair* repair = new Repair(); 422 mWindows.push_back(repair); 423 mGuiModeStates[GM_Repair] = GuiModeState(repair); 424 425 mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); 426 427 CompanionWindow* companionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); 428 mWindows.push_back(companionWindow); 429 trackWindow(companionWindow, "companion"); 430 mGuiModeStates[GM_Companion] = GuiModeState({mInventoryWindow, companionWindow}); 431 432 mJailScreen = new JailScreen(); 433 mWindows.push_back(mJailScreen); 434 mGuiModeStates[GM_Jail] = GuiModeState(mJailScreen); 435 436 std::string werewolfFaderTex = "textures\\werewolfoverlay.dds"; 437 if (mResourceSystem->getVFS()->exists(werewolfFaderTex)) 438 { 439 mWerewolfFader = new ScreenFader(werewolfFaderTex); 440 mWindows.push_back(mWerewolfFader); 441 } 442 mBlindnessFader = new ScreenFader("black"); 443 mWindows.push_back(mBlindnessFader); 444 445 // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available 446 std::string hitFaderTexture = "textures\\bm_player_hit_01.dds"; 447 const std::string hitFaderLayout = "openmw_screen_fader_hit.layout"; 448 MyGUI::FloatCoord hitFaderCoord (0,0,1,1); 449 if(!mResourceSystem->getVFS()->exists(hitFaderTexture)) 450 { 451 hitFaderTexture = "textures\\player_hit_01.dds"; 452 hitFaderCoord = MyGUI::FloatCoord(0.2, 0.25, 0.6, 0.5); 453 } 454 mHitFader = new ScreenFader(hitFaderTexture, hitFaderLayout, hitFaderCoord); 455 mWindows.push_back(mHitFader); 456 457 mScreenFader = new ScreenFader("black"); 458 mWindows.push_back(mScreenFader); 459 460 mDebugWindow = new DebugWindow(); 461 mWindows.push_back(mDebugWindow); 462 463 mInputBlocker = MyGUI::Gui::getInstance().createWidget<MyGUI::Widget>("",0,0,w,h,MyGUI::Align::Stretch,"InputBlocker"); 464 465 mHud->setVisible(true); 466 467 mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); 468 469 updatePinnedWindows(); 470 471 // Set up visibility 472 updateVisible(); 473 474 mStatsWatcher->addListener(mHud); 475 mStatsWatcher->addListener(mStatsWindow); 476 mStatsWatcher->addListener(mCharGen); 477 } 478 getFontHeight() const479 int WindowManager::getFontHeight() const 480 { 481 return mFontLoader->getFontHeight(); 482 } 483 setNewGame(bool newgame)484 void WindowManager::setNewGame(bool newgame) 485 { 486 if (newgame) 487 { 488 disallowAll(); 489 490 mStatsWatcher->removeListener(mCharGen); 491 delete mCharGen; 492 mCharGen = new CharacterCreation(mViewer->getSceneData()->asGroup(), mResourceSystem); 493 mStatsWatcher->addListener(mCharGen); 494 } 495 else 496 allow(GW_ALL); 497 498 mStatsWatcher->forceUpdate(); 499 } 500 ~WindowManager()501 WindowManager::~WindowManager() 502 { 503 try 504 { 505 mStatsWatcher.reset(); 506 507 MyGUI::LanguageManager::getInstance().eventRequestTag.clear(); 508 MyGUI::PointerManager::getInstance().eventChangeMousePointer.clear(); 509 MyGUI::InputManager::getInstance().eventChangeKeyFocus.clear(); 510 MyGUI::ClipboardManager::getInstance().eventClipboardChanged.clear(); 511 MyGUI::ClipboardManager::getInstance().eventClipboardRequested.clear(); 512 513 for (WindowBase* window : mWindows) 514 delete window; 515 mWindows.clear(); 516 517 delete mMessageBoxManager; 518 delete mLocalMapRender; 519 delete mCharGen; 520 delete mDragAndDrop; 521 delete mSoulgemDialog; 522 delete mCursorManager; 523 delete mToolTips; 524 525 mKeyboardNavigation.reset(); 526 527 cleanupGarbage(); 528 529 mFontLoader.reset(); 530 531 mGui->shutdown(); 532 delete mGui; 533 534 mGuiPlatform->shutdown(); 535 delete mGuiPlatform; 536 delete mVideoWrapper; 537 } 538 catch(const MyGUI::Exception& e) 539 { 540 Log(Debug::Error) << "Error in the destructor: " << e.what(); 541 } 542 } 543 setStore(const MWWorld::ESMStore & store)544 void WindowManager::setStore(const MWWorld::ESMStore &store) 545 { 546 mStore = &store; 547 } 548 cleanupGarbage()549 void WindowManager::cleanupGarbage() 550 { 551 // Delete any dialogs which are no longer in use 552 if (!mGarbageDialogs.empty()) 553 { 554 for (Layout* widget : mGarbageDialogs) 555 { 556 delete widget; 557 } 558 mGarbageDialogs.clear(); 559 } 560 } 561 enableScene(bool enable)562 void WindowManager::enableScene(bool enable) 563 { 564 unsigned int disablemask = MWRender::Mask_GUI|MWRender::Mask_PreCompile; 565 if (!enable && mViewer->getCamera()->getCullMask() != disablemask) 566 { 567 mOldUpdateMask = mViewer->getUpdateVisitor()->getTraversalMask(); 568 mOldCullMask = mViewer->getCamera()->getCullMask(); 569 mViewer->getUpdateVisitor()->setTraversalMask(disablemask); 570 mViewer->getCamera()->setCullMask(disablemask); 571 } 572 else if (enable && mViewer->getCamera()->getCullMask() == disablemask) 573 { 574 mViewer->getUpdateVisitor()->setTraversalMask(mOldUpdateMask); 575 mViewer->getCamera()->setCullMask(mOldCullMask); 576 } 577 } 578 updateConsoleObjectPtr(const MWWorld::Ptr & currentPtr,const MWWorld::Ptr & newPtr)579 void WindowManager::updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) 580 { 581 mConsole->updateSelectedObjectPtr(currentPtr, newPtr); 582 } 583 updateVisible()584 void WindowManager::updateVisible() 585 { 586 bool loading = (getMode() == GM_Loading || getMode() == GM_LoadingWallpaper); 587 588 bool mainmenucover = containsMode(GM_MainMenu) && MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_NoGame; 589 590 enableScene(!loading && !mainmenucover); 591 592 if (!mMap) 593 return; // UI not created yet 594 595 mHud->setVisible(mHudEnabled && !loading); 596 mToolTips->setVisible(mHudEnabled && !loading); 597 598 bool gameMode = !isGuiMode(); 599 600 MWBase::Environment::get().getInputManager()->changeInputMode(!gameMode); 601 602 mInputBlocker->setVisible (gameMode); 603 604 if (loading) 605 setCursorVisible(mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); 606 else 607 setCursorVisible(!gameMode); 608 609 if (gameMode) 610 setKeyFocusWidget (nullptr); 611 612 // Icons of forced hidden windows are displayed 613 setMinimapVisibility((mAllowed & GW_Map) && (!mMap->pinned() || (mForceHidden & GW_Map))); 614 setWeaponVisibility((mAllowed & GW_Inventory) && (!mInventoryWindow->pinned() || (mForceHidden & GW_Inventory))); 615 setSpellVisibility((mAllowed & GW_Magic) && (!mSpellWindow->pinned() || (mForceHidden & GW_Magic))); 616 setHMSVisibility((mAllowed & GW_Stats) && (!mStatsWindow->pinned() || (mForceHidden & GW_Stats))); 617 618 mInventoryWindow->setGuiMode(getMode()); 619 620 // If in game mode (or interactive messagebox), show the pinned windows 621 if (mGuiModes.empty()) 622 { 623 mMap->setVisible(mMap->pinned() && !isConsoleMode() && !(mForceHidden & GW_Map) && (mAllowed & GW_Map)); 624 mStatsWindow->setVisible(mStatsWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Stats) && (mAllowed & GW_Stats)); 625 mInventoryWindow->setVisible(mInventoryWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Inventory) && (mAllowed & GW_Inventory)); 626 mSpellWindow->setVisible(mSpellWindow->pinned() && !isConsoleMode() && !(mForceHidden & GW_Magic) && (mAllowed & GW_Magic)); 627 return; 628 } 629 else if (getMode() != GM_Inventory) 630 { 631 mMap->setVisible(false); 632 mStatsWindow->setVisible(false); 633 mSpellWindow->setVisible(false); 634 mInventoryWindow->setVisible(getMode() == GM_Container || getMode() == GM_Barter || getMode() == GM_Companion); 635 } 636 637 GuiMode mode = mGuiModes.back(); 638 639 mInventoryWindow->setTrading(mode == GM_Barter); 640 641 if (getMode() == GM_Inventory) 642 { 643 // For the inventory mode, compute the effective set of windows to show. 644 // This is controlled both by what windows the 645 // user has opened/closed (the 'shown' variable) and by what 646 // windows we are allowed to show (the 'allowed' var.) 647 int eff = mShown & mAllowed & ~mForceHidden; 648 mMap->setVisible(eff & GW_Map); 649 mInventoryWindow->setVisible(eff & GW_Inventory); 650 mSpellWindow->setVisible(eff & GW_Magic); 651 mStatsWindow->setVisible(eff & GW_Stats); 652 } 653 654 switch (mode) 655 { 656 // FIXME: refactor chargen windows to use modes properly (or not use them at all) 657 case GM_Name: 658 case GM_Race: 659 case GM_Class: 660 case GM_ClassPick: 661 case GM_ClassCreate: 662 case GM_Birth: 663 case GM_ClassGenerate: 664 case GM_Review: 665 mCharGen->spawnDialog(mode); 666 break; 667 default: 668 break; 669 } 670 } 671 setDrowningTimeLeft(float time,float maxTime)672 void WindowManager::setDrowningTimeLeft (float time, float maxTime) 673 { 674 mHud->setDrowningTimeLeft(time, maxTime); 675 } 676 removeDialog(Layout * dialog)677 void WindowManager::removeDialog(Layout*dialog) 678 { 679 if (!dialog) 680 return; 681 dialog->setVisible(false); 682 mGarbageDialogs.push_back(dialog); 683 } 684 exitCurrentGuiMode()685 void WindowManager::exitCurrentGuiMode() 686 { 687 if (mDragAndDrop && mDragAndDrop->mIsOnDragAndDrop) 688 { 689 mDragAndDrop->finish(); 690 return; 691 } 692 693 GuiModeState& state = mGuiModeStates[mGuiModes.back()]; 694 for (WindowBase* window : state.mWindows) 695 { 696 if (!window->exit()) 697 { 698 // unable to exit window, but give access to main menu 699 if (!MyGUI::InputManager::getInstance().isModalAny() && getMode() != GM_MainMenu) 700 pushGuiMode (GM_MainMenu); 701 return; 702 } 703 } 704 705 popGuiMode(); 706 } 707 interactiveMessageBox(const std::string & message,const std::vector<std::string> & buttons,bool block)708 void WindowManager::interactiveMessageBox(const std::string &message, const std::vector<std::string> &buttons, bool block) 709 { 710 mMessageBoxManager->createInteractiveMessageBox(message, buttons); 711 updateVisible(); 712 713 if (block) 714 { 715 Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit()); 716 while (mMessageBoxManager->readPressedButton(false) == -1 717 && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) 718 { 719 const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count(); 720 721 mKeyboardNavigation->onFrame(); 722 mMessageBoxManager->onFrame(dt); 723 MWBase::Environment::get().getInputManager()->update(dt, true, false); 724 725 if (!mWindowVisible) 726 std::this_thread::sleep_for(std::chrono::milliseconds(5)); 727 else 728 { 729 mViewer->eventTraversal(); 730 mViewer->updateTraversal(); 731 mViewer->renderingTraversals(); 732 } 733 // at the time this function is called we are in the middle of a frame, 734 // so out of order calls are necessary to get a correct frameNumber for the next frame. 735 // refer to the advance() and frame() order in Engine::go() 736 mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); 737 738 frameRateLimiter.limit(); 739 } 740 } 741 } 742 messageBox(const std::string & message,enum MWGui::ShowInDialogueMode showInDialogueMode)743 void WindowManager::messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode) 744 { 745 if (getMode() == GM_Dialogue && showInDialogueMode != MWGui::ShowInDialogueMode_Never) { 746 mDialogueWindow->addMessageBox(MyGUI::LanguageManager::getInstance().replaceTags(message)); 747 } else if (showInDialogueMode != MWGui::ShowInDialogueMode_Only) { 748 mMessageBoxManager->createMessageBox(message); 749 } 750 } 751 staticMessageBox(const std::string & message)752 void WindowManager::staticMessageBox(const std::string& message) 753 { 754 mMessageBoxManager->createMessageBox(message, true); 755 } 756 removeStaticMessageBox()757 void WindowManager::removeStaticMessageBox() 758 { 759 mMessageBoxManager->removeStaticMessageBox(); 760 } 761 readPressedButton()762 int WindowManager::readPressedButton () 763 { 764 return mMessageBoxManager->readPressedButton(); 765 } 766 getGameSettingString(const std::string & id,const std::string & default_)767 std::string WindowManager::getGameSettingString(const std::string &id, const std::string &default_) 768 { 769 const ESM::GameSetting *setting = mStore->get<ESM::GameSetting>().search(id); 770 771 if (setting && setting->mValue.getType()==ESM::VT_String) 772 return setting->mValue.getString(); 773 774 return default_; 775 } 776 updateMap()777 void WindowManager::updateMap() 778 { 779 if (!mLocalMapRender) 780 return; 781 782 MWWorld::ConstPtr player = MWMechanics::getPlayer(); 783 784 osg::Vec3f playerPosition = player.getRefData().getPosition().asVec3(); 785 osg::Quat playerOrientation (-player.getRefData().getPosition().rot[2], osg::Vec3(0,0,1)); 786 787 osg::Vec3f playerdirection; 788 int x,y; 789 float u,v; 790 mLocalMapRender->updatePlayer(playerPosition, playerOrientation, u, v, x, y, playerdirection); 791 792 if (!player.getCell()->isExterior()) 793 { 794 setActiveMap(x, y, true); 795 } 796 // else: need to know the current grid center, call setActiveMap from changeCell 797 798 mMap->setPlayerDir(playerdirection.x(), playerdirection.y()); 799 mMap->setPlayerPos(x, y, u, v); 800 mHud->setPlayerDir(playerdirection.x(), playerdirection.y()); 801 mHud->setPlayerPos(x, y, u, v); 802 } 803 update(float frameDuration)804 void WindowManager::update (float frameDuration) 805 { 806 bool gameRunning = MWBase::Environment::get().getStateManager()->getState()!= 807 MWBase::StateManager::State_NoGame; 808 809 if (gameRunning) 810 updateMap(); 811 812 if (!mGuiModes.empty()) 813 { 814 GuiModeState& state = mGuiModeStates[mGuiModes.back()]; 815 for (WindowBase* window : state.mWindows) 816 window->onFrame(frameDuration); 817 } 818 else 819 { 820 // update pinned windows if visible 821 for (WindowBase* window : mGuiModeStates[GM_Inventory].mWindows) 822 if (window->isVisible()) 823 window->onFrame(frameDuration); 824 } 825 826 // Make sure message boxes are always in front 827 // This is an awful workaround for a series of awfully interwoven issues that couldn't be worked around 828 // in a better way because of an impressive number of even more awfully interwoven issues. 829 if (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox() && mCurrentModals.back() != mMessageBoxManager->getInteractiveMessageBox()) 830 { 831 std::vector<WindowModal*>::iterator found = std::find(mCurrentModals.begin(), mCurrentModals.end(), mMessageBoxManager->getInteractiveMessageBox()); 832 if (found != mCurrentModals.end()) 833 { 834 WindowModal* msgbox = *found; 835 std::swap(*found, mCurrentModals.back()); 836 MyGUI::InputManager::getInstance().addWidgetModal(msgbox->mMainWidget); 837 mKeyboardNavigation->setModalWindow(msgbox->mMainWidget); 838 mKeyboardNavigation->setDefaultFocus(msgbox->mMainWidget, msgbox->getDefaultKeyFocus()); 839 } 840 } 841 842 if (!mCurrentModals.empty()) 843 mCurrentModals.back()->onFrame(frameDuration); 844 845 mKeyboardNavigation->onFrame(); 846 847 if (mMessageBoxManager) 848 mMessageBoxManager->onFrame(frameDuration); 849 850 mToolTips->onFrame(frameDuration); 851 852 if (mLocalMapRender) 853 mLocalMapRender->cleanupCameras(); 854 855 if (!gameRunning) 856 return; 857 858 // We should display message about crime only once per frame, even if there are several crimes. 859 // Otherwise we will get message spam when stealing several items via Take All button. 860 const MWWorld::Ptr player = MWMechanics::getPlayer(); 861 int currentBounty = player.getClass().getNpcStats(player).getBounty(); 862 if (currentBounty != mPlayerBounty) 863 { 864 if (mPlayerBounty >= 0 && currentBounty > mPlayerBounty) 865 messageBox("#{sCrimeMessage}"); 866 867 mPlayerBounty = currentBounty; 868 } 869 870 mDragAndDrop->onFrame(); 871 872 mHud->onFrame(frameDuration); 873 874 mDebugWindow->onFrame(frameDuration); 875 876 if (mCharGen) 877 mCharGen->onFrame(frameDuration); 878 879 updateActivatedQuickKey(); 880 881 mStatsWatcher->update(); 882 883 cleanupGarbage(); 884 } 885 changeCell(const MWWorld::CellStore * cell)886 void WindowManager::changeCell(const MWWorld::CellStore* cell) 887 { 888 mMap->requestMapRender(cell); 889 890 std::string name = MWBase::Environment::get().getWorld()->getCellName (cell); 891 892 mMap->setCellName( name ); 893 mHud->setCellName( name ); 894 895 if (cell->getCell()->isExterior()) 896 { 897 if (!cell->getCell()->mName.empty()) 898 mMap->addVisitedLocation (name, cell->getCell()->getGridX (), cell->getCell()->getGridY ()); 899 900 mMap->cellExplored (cell->getCell()->getGridX(), cell->getCell()->getGridY()); 901 902 setActiveMap(cell->getCell()->getGridX(), cell->getCell()->getGridY(), false); 903 } 904 else 905 { 906 mMap->setCellPrefix (cell->getCell()->mName ); 907 mHud->setCellPrefix (cell->getCell()->mName ); 908 909 osg::Vec3f worldPos; 910 if (!MWBase::Environment::get().getWorld()->findInteriorPositionInWorldSpace(cell, worldPos)) 911 worldPos = MWBase::Environment::get().getWorld()->getPlayer().getLastKnownExteriorPosition(); 912 else 913 MWBase::Environment::get().getWorld()->getPlayer().setLastKnownExteriorPosition(worldPos); 914 mMap->setGlobalMapPlayerPosition(worldPos.x(), worldPos.y()); 915 916 setActiveMap(0, 0, true); 917 } 918 } 919 setActiveMap(int x,int y,bool interior)920 void WindowManager::setActiveMap(int x, int y, bool interior) 921 { 922 mMap->setActiveCell(x,y, interior); 923 mHud->setActiveCell(x,y, interior); 924 } 925 setDrowningBarVisibility(bool visible)926 void WindowManager::setDrowningBarVisibility(bool visible) 927 { 928 mHud->setDrowningBarVisible(visible); 929 } 930 setHMSVisibility(bool visible)931 void WindowManager::setHMSVisibility(bool visible) 932 { 933 mHud->setHmsVisible (visible); 934 } 935 setMinimapVisibility(bool visible)936 void WindowManager::setMinimapVisibility(bool visible) 937 { 938 mHud->setMinimapVisible (visible); 939 } 940 toggleFogOfWar()941 bool WindowManager::toggleFogOfWar() 942 { 943 mMap->toggleFogOfWar(); 944 return mHud->toggleFogOfWar(); 945 } 946 setFocusObject(const MWWorld::Ptr & focus)947 void WindowManager::setFocusObject(const MWWorld::Ptr& focus) 948 { 949 mToolTips->setFocusObject(focus); 950 951 if(mHud && (mShowOwned == 2 || mShowOwned == 3)) 952 { 953 bool owned = mToolTips->checkOwned(); 954 mHud->setCrosshairOwned(owned); 955 } 956 } 957 setFocusObjectScreenCoords(float min_x,float min_y,float max_x,float max_y)958 void WindowManager::setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) 959 { 960 mToolTips->setFocusObjectScreenCoords(min_x, min_y, max_x, max_y); 961 } 962 toggleFullHelp()963 bool WindowManager::toggleFullHelp() 964 { 965 return mToolTips->toggleFullHelp(); 966 } 967 getFullHelp() const968 bool WindowManager::getFullHelp() const 969 { 970 return mToolTips->getFullHelp(); 971 } 972 setWeaponVisibility(bool visible)973 void WindowManager::setWeaponVisibility(bool visible) 974 { 975 mHud->setWeapVisible (visible); 976 } 977 setSpellVisibility(bool visible)978 void WindowManager::setSpellVisibility(bool visible) 979 { 980 mHud->setSpellVisible (visible); 981 mHud->setEffectVisible (visible); 982 } 983 setSneakVisibility(bool visible)984 void WindowManager::setSneakVisibility(bool visible) 985 { 986 mHud->setSneakVisible(visible); 987 } 988 setDragDrop(bool dragDrop)989 void WindowManager::setDragDrop(bool dragDrop) 990 { 991 mToolTips->setEnabled(!dragDrop); 992 MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); 993 } 994 setCursorVisible(bool visible)995 void WindowManager::setCursorVisible(bool visible) 996 { 997 mCursorVisible = visible; 998 } 999 setCursorActive(bool active)1000 void WindowManager::setCursorActive(bool active) 1001 { 1002 mCursorActive = active; 1003 } 1004 onRetrieveTag(const MyGUI::UString & _tag,MyGUI::UString & _result)1005 void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) 1006 { 1007 std::string tag(_tag); 1008 1009 std::string MyGuiPrefix = "setting="; 1010 size_t MyGuiPrefixLength = MyGuiPrefix.length(); 1011 1012 std::string tokenToFind = "sCell="; 1013 size_t tokenLength = tokenToFind.length(); 1014 1015 if(tag.compare(0, MyGuiPrefixLength, MyGuiPrefix) == 0) 1016 { 1017 tag = tag.substr(MyGuiPrefixLength, tag.length()); 1018 size_t comma_pos = tag.find(','); 1019 std::string settingSection = tag.substr(0, comma_pos); 1020 std::string settingTag = tag.substr(comma_pos+1, tag.length()); 1021 1022 _result = Settings::Manager::getString(settingTag, settingSection); 1023 } 1024 else if (tag.compare(0, tokenLength, tokenToFind) == 0) 1025 { 1026 _result = mTranslationDataStorage.translateCellName(tag.substr(tokenLength)); 1027 _result = MyGUI::TextIterator::toTagsString(_result); 1028 } 1029 else if (Gui::replaceTag(tag, _result)) 1030 { 1031 return; 1032 } 1033 else 1034 { 1035 if (!mStore) 1036 { 1037 Log(Debug::Error) << "Error: WindowManager::onRetrieveTag: no Store set up yet, can not replace '" << tag << "'"; 1038 return; 1039 } 1040 const ESM::GameSetting *setting = mStore->get<ESM::GameSetting>().find(tag); 1041 1042 if (setting && setting->mValue.getType()==ESM::VT_String) 1043 _result = setting->mValue.getString(); 1044 else 1045 _result = tag; 1046 } 1047 } 1048 processChangedSettings(const Settings::CategorySettingVector & changed)1049 void WindowManager::processChangedSettings(const Settings::CategorySettingVector& changed) 1050 { 1051 mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); 1052 1053 bool changeRes = false; 1054 for (const auto& setting : changed) 1055 { 1056 if (setting.first == "HUD" && setting.second == "crosshair") 1057 mCrosshairEnabled = Settings::Manager::getBool ("crosshair", "HUD"); 1058 else if (setting.first == "GUI" && setting.second == "subtitles") 1059 mSubtitlesEnabled = Settings::Manager::getBool ("subtitles", "GUI"); 1060 else if (setting.first == "GUI" && setting.second == "menu transparency") 1061 setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); 1062 else if (setting.first == "Video" && ( 1063 setting.second == "resolution x" 1064 || setting.second == "resolution y" 1065 || setting.second == "fullscreen" 1066 || setting.second == "window border")) 1067 changeRes = true; 1068 1069 else if (setting.first == "Video" && setting.second == "vsync") 1070 mVideoWrapper->setSyncToVBlank(Settings::Manager::getBool("vsync", "Video")); 1071 else if (setting.first == "Video" && (setting.second == "gamma" || setting.second == "contrast")) 1072 mVideoWrapper->setGammaContrast(Settings::Manager::getFloat("gamma", "Video"), 1073 Settings::Manager::getFloat("contrast", "Video")); 1074 } 1075 1076 if (changeRes) 1077 { 1078 mVideoWrapper->setVideoMode(Settings::Manager::getInt("resolution x", "Video"), 1079 Settings::Manager::getInt("resolution y", "Video"), 1080 Settings::Manager::getBool("fullscreen", "Video"), 1081 Settings::Manager::getBool("window border", "Video")); 1082 } 1083 } 1084 windowResized(int x,int y)1085 void WindowManager::windowResized(int x, int y) 1086 { 1087 // Note: this is a side effect of resolution change or window resize. 1088 // There is no need to track these changes. 1089 Settings::Manager::setInt("resolution x", "Video", x); 1090 Settings::Manager::setInt("resolution y", "Video", y); 1091 Settings::Manager::resetPendingChange("resolution x", "Video"); 1092 Settings::Manager::resetPendingChange("resolution y", "Video"); 1093 1094 mGuiPlatform->getRenderManagerPtr()->setViewSize(x, y); 1095 1096 // scaled size 1097 const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); 1098 x = viewSize.width; 1099 y = viewSize.height; 1100 1101 sizeVideo(x, y); 1102 1103 if (!mHud) 1104 return; // UI not initialized yet 1105 1106 for (std::map<MyGUI::Window*, std::string>::iterator it = mTrackedWindows.begin(); it != mTrackedWindows.end(); ++it) 1107 { 1108 std::string settingName = it->second; 1109 if (Settings::Manager::getBool(settingName + " maximized", "Windows")) 1110 settingName += " maximized"; 1111 1112 MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(settingName + " x", "Windows") * x), 1113 static_cast<int>(Settings::Manager::getFloat(settingName + " y", "Windows") * y)); 1114 MyGUI::IntSize size(static_cast<int>(Settings::Manager::getFloat(settingName + " w", "Windows") * x), 1115 static_cast<int>(Settings::Manager::getFloat(settingName + " h", "Windows") * y)); 1116 it->first->setPosition(pos); 1117 it->first->setSize(size); 1118 } 1119 1120 for (WindowBase* window : mWindows) 1121 window->onResChange(x, y); 1122 1123 // We should reload TrueType fonts to fit new resolution 1124 loadUserFonts(); 1125 1126 // TODO: check if any windows are now off-screen and move them back if so 1127 } 1128 isWindowVisible()1129 bool WindowManager::isWindowVisible() 1130 { 1131 return mWindowVisible; 1132 } 1133 windowVisibilityChange(bool visible)1134 void WindowManager::windowVisibilityChange(bool visible) 1135 { 1136 mWindowVisible = visible; 1137 } 1138 windowClosed()1139 void WindowManager::windowClosed() 1140 { 1141 MWBase::Environment::get().getStateManager()->requestQuit(); 1142 } 1143 onCursorChange(const std::string & name)1144 void WindowManager::onCursorChange(const std::string &name) 1145 { 1146 mCursorManager->cursorChanged(name); 1147 } 1148 pushGuiMode(GuiMode mode)1149 void WindowManager::pushGuiMode(GuiMode mode) 1150 { 1151 pushGuiMode(mode, MWWorld::Ptr()); 1152 } 1153 pushGuiMode(GuiMode mode,const MWWorld::Ptr & arg)1154 void WindowManager::pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg) 1155 { 1156 if (mode==GM_Inventory && mAllowed==GW_None) 1157 return; 1158 1159 if (mGuiModes.empty() || mGuiModes.back() != mode) 1160 { 1161 // If this mode already exists somewhere in the stack, just bring it to the front. 1162 if (std::find(mGuiModes.begin(), mGuiModes.end(), mode) != mGuiModes.end()) 1163 { 1164 mGuiModes.erase(std::find(mGuiModes.begin(), mGuiModes.end(), mode)); 1165 } 1166 1167 if (!mGuiModes.empty()) 1168 { 1169 mKeyboardNavigation->saveFocus(mGuiModes.back()); 1170 mGuiModeStates[mGuiModes.back()].update(false); 1171 } 1172 mGuiModes.push_back(mode); 1173 1174 mGuiModeStates[mode].update(true); 1175 playSound(mGuiModeStates[mode].mOpenSound); 1176 } 1177 for (WindowBase* window : mGuiModeStates[mode].mWindows) 1178 window->setPtr(arg); 1179 1180 mKeyboardNavigation->restoreFocus(mode); 1181 1182 updateVisible(); 1183 } 1184 popGuiMode(bool noSound)1185 void WindowManager::popGuiMode(bool noSound) 1186 { 1187 if (mDragAndDrop && mDragAndDrop->mIsOnDragAndDrop) 1188 { 1189 mDragAndDrop->finish(); 1190 } 1191 1192 if (!mGuiModes.empty()) 1193 { 1194 const GuiMode mode = mGuiModes.back(); 1195 mKeyboardNavigation->saveFocus(mode); 1196 mGuiModes.pop_back(); 1197 mGuiModeStates[mode].update(false); 1198 if (!noSound) 1199 playSound(mGuiModeStates[mode].mCloseSound); 1200 } 1201 1202 if (!mGuiModes.empty()) 1203 { 1204 const GuiMode mode = mGuiModes.back(); 1205 mGuiModeStates[mode].update(true); 1206 mKeyboardNavigation->restoreFocus(mode); 1207 } 1208 1209 updateVisible(); 1210 1211 // To make sure that console window get focus again 1212 if (mConsole && mConsole->isVisible()) 1213 mConsole->onOpen(); 1214 } 1215 removeGuiMode(GuiMode mode,bool noSound)1216 void WindowManager::removeGuiMode(GuiMode mode, bool noSound) 1217 { 1218 if (!mGuiModes.empty() && mGuiModes.back() == mode) 1219 { 1220 popGuiMode(noSound); 1221 return; 1222 } 1223 1224 std::vector<GuiMode>::iterator it = mGuiModes.begin(); 1225 while (it != mGuiModes.end()) 1226 { 1227 if (*it == mode) 1228 it = mGuiModes.erase(it); 1229 else 1230 ++it; 1231 } 1232 1233 updateVisible(); 1234 } 1235 goToJail(int days)1236 void WindowManager::goToJail(int days) 1237 { 1238 pushGuiMode(MWGui::GM_Jail); 1239 mJailScreen->goToJail(days); 1240 } 1241 setSelectedSpell(const std::string & spellId,int successChancePercent)1242 void WindowManager::setSelectedSpell(const std::string& spellId, int successChancePercent) 1243 { 1244 mSelectedSpell = spellId; 1245 mSelectedEnchantItem = MWWorld::Ptr(); 1246 mHud->setSelectedSpell(spellId, successChancePercent); 1247 1248 const ESM::Spell* spell = mStore->get<ESM::Spell>().find(spellId); 1249 1250 mSpellWindow->setTitle(spell->mName); 1251 } 1252 setSelectedEnchantItem(const MWWorld::Ptr & item)1253 void WindowManager::setSelectedEnchantItem(const MWWorld::Ptr& item) 1254 { 1255 mSelectedEnchantItem = item; 1256 mSelectedSpell = ""; 1257 const ESM::Enchantment* ench = mStore->get<ESM::Enchantment>() 1258 .find(item.getClass().getEnchantment(item)); 1259 1260 int chargePercent = static_cast<int>(item.getCellRef().getNormalizedEnchantmentCharge(ench->mData.mCharge) * 100); 1261 mHud->setSelectedEnchantItem(item, chargePercent); 1262 mSpellWindow->setTitle(item.getClass().getName(item)); 1263 } 1264 getSelectedEnchantItem() const1265 const MWWorld::Ptr &WindowManager::getSelectedEnchantItem() const 1266 { 1267 return mSelectedEnchantItem; 1268 } 1269 setSelectedWeapon(const MWWorld::Ptr & item)1270 void WindowManager::setSelectedWeapon(const MWWorld::Ptr& item) 1271 { 1272 mSelectedWeapon = item; 1273 int durabilityPercent = 100; 1274 if (item.getClass().hasItemHealth(item)) 1275 { 1276 durabilityPercent = static_cast<int>(item.getClass().getItemNormalizedHealth(item) * 100); 1277 } 1278 mHud->setSelectedWeapon(item, durabilityPercent); 1279 mInventoryWindow->setTitle(item.getClass().getName(item)); 1280 } 1281 getSelectedWeapon() const1282 const MWWorld::Ptr &WindowManager::getSelectedWeapon() const 1283 { 1284 return mSelectedWeapon; 1285 } 1286 unsetSelectedSpell()1287 void WindowManager::unsetSelectedSpell() 1288 { 1289 mSelectedSpell = ""; 1290 mSelectedEnchantItem = MWWorld::Ptr(); 1291 mHud->unsetSelectedSpell(); 1292 1293 MWWorld::Player* player = &MWBase::Environment::get().getWorld()->getPlayer(); 1294 if (player->getDrawState() == MWMechanics::DrawState_Spell) 1295 player->setDrawState(MWMechanics::DrawState_Nothing); 1296 1297 mSpellWindow->setTitle("#{sNone}"); 1298 } 1299 unsetSelectedWeapon()1300 void WindowManager::unsetSelectedWeapon() 1301 { 1302 mSelectedWeapon = MWWorld::Ptr(); 1303 mHud->unsetSelectedWeapon(); 1304 mInventoryWindow->setTitle("#{sSkillHandtohand}"); 1305 } 1306 getMousePosition(int & x,int & y)1307 void WindowManager::getMousePosition(int &x, int &y) 1308 { 1309 const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); 1310 x = pos.left; 1311 y = pos.top; 1312 } 1313 getMousePosition(float & x,float & y)1314 void WindowManager::getMousePosition(float &x, float &y) 1315 { 1316 const MyGUI::IntPoint& pos = MyGUI::InputManager::getInstance().getMousePosition(); 1317 x = static_cast<float>(pos.left); 1318 y = static_cast<float>(pos.top); 1319 const MyGUI::IntSize& viewSize = MyGUI::RenderManager::getInstance().getViewSize(); 1320 x /= viewSize.width; 1321 y /= viewSize.height; 1322 } 1323 getWorldMouseOver()1324 bool WindowManager::getWorldMouseOver() 1325 { 1326 return mHud->getWorldMouseOver(); 1327 } 1328 getScalingFactor()1329 float WindowManager::getScalingFactor() 1330 { 1331 return mScalingFactor; 1332 } 1333 executeInConsole(const std::string & path)1334 void WindowManager::executeInConsole (const std::string& path) 1335 { 1336 mConsole->executeFile (path); 1337 } 1338 getInventoryWindow()1339 MWGui::InventoryWindow* WindowManager::getInventoryWindow() { return mInventoryWindow; } getCountDialog()1340 MWGui::CountDialog* WindowManager::getCountDialog() { return mCountDialog; } getConfirmationDialog()1341 MWGui::ConfirmationDialog* WindowManager::getConfirmationDialog() { return mConfirmationDialog; } getTradeWindow()1342 MWGui::TradeWindow* WindowManager::getTradeWindow() { return mTradeWindow; } 1343 useItem(const MWWorld::Ptr & item,bool bypassBeastRestrictions)1344 void WindowManager::useItem(const MWWorld::Ptr &item, bool bypassBeastRestrictions) 1345 { 1346 if (mInventoryWindow) 1347 mInventoryWindow->useItem(item, bypassBeastRestrictions); 1348 } 1349 isAllowed(GuiWindow wnd) const1350 bool WindowManager::isAllowed (GuiWindow wnd) const 1351 { 1352 return (mAllowed & wnd) != 0; 1353 } 1354 allow(GuiWindow wnd)1355 void WindowManager::allow (GuiWindow wnd) 1356 { 1357 mAllowed = (GuiWindow)(mAllowed | wnd); 1358 1359 if (wnd & GW_Inventory) 1360 { 1361 mBookWindow->setInventoryAllowed (true); 1362 mScrollWindow->setInventoryAllowed (true); 1363 } 1364 1365 updateVisible(); 1366 } 1367 disallowAll()1368 void WindowManager::disallowAll() 1369 { 1370 mAllowed = GW_None; 1371 mRestAllowed = false; 1372 1373 mBookWindow->setInventoryAllowed (false); 1374 mScrollWindow->setInventoryAllowed (false); 1375 1376 updateVisible(); 1377 } 1378 toggleVisible(GuiWindow wnd)1379 void WindowManager::toggleVisible (GuiWindow wnd) 1380 { 1381 if (getMode() != GM_Inventory) 1382 return; 1383 1384 std::string settingName; 1385 switch (wnd) 1386 { 1387 case GW_Inventory: 1388 settingName = "inventory"; 1389 break; 1390 case GW_Map: 1391 settingName = "map"; 1392 break; 1393 case GW_Magic: 1394 settingName = "spells"; 1395 break; 1396 case GW_Stats: 1397 settingName = "stats"; 1398 break; 1399 default: 1400 break; 1401 } 1402 1403 if (!settingName.empty()) 1404 { 1405 settingName += " hidden"; 1406 bool hidden = Settings::Manager::getBool(settingName, "Windows"); 1407 Settings::Manager::setBool(settingName, "Windows", !hidden); 1408 } 1409 1410 mShown = (GuiWindow)(mShown ^ wnd); 1411 updateVisible(); 1412 } 1413 forceHide(GuiWindow wnd)1414 void WindowManager::forceHide(GuiWindow wnd) 1415 { 1416 mForceHidden = (GuiWindow)(mForceHidden | wnd); 1417 updateVisible(); 1418 } 1419 unsetForceHide(GuiWindow wnd)1420 void WindowManager::unsetForceHide(GuiWindow wnd) 1421 { 1422 mForceHidden = (GuiWindow)(mForceHidden & ~wnd); 1423 updateVisible(); 1424 } 1425 isGuiMode() const1426 bool WindowManager::isGuiMode() const 1427 { 1428 return 1429 !mGuiModes.empty() || 1430 isConsoleMode() || 1431 (mMessageBoxManager && mMessageBoxManager->isInteractiveMessageBox()); 1432 } 1433 isConsoleMode() const1434 bool WindowManager::isConsoleMode() const 1435 { 1436 return mConsole && mConsole->isVisible(); 1437 } 1438 getMode() const1439 MWGui::GuiMode WindowManager::getMode() const 1440 { 1441 if (mGuiModes.empty()) 1442 return GM_None; 1443 return mGuiModes.back(); 1444 } 1445 disallowMouse()1446 void WindowManager::disallowMouse() 1447 { 1448 mInputBlocker->setVisible (true); 1449 } 1450 allowMouse()1451 void WindowManager::allowMouse() 1452 { 1453 mInputBlocker->setVisible (!isGuiMode ()); 1454 } 1455 notifyInputActionBound()1456 void WindowManager::notifyInputActionBound () 1457 { 1458 mSettingsWindow->updateControlsBox (); 1459 allowMouse(); 1460 } 1461 containsMode(GuiMode mode) const1462 bool WindowManager::containsMode(GuiMode mode) const 1463 { 1464 if(mGuiModes.empty()) 1465 return false; 1466 1467 return std::find(mGuiModes.begin(), mGuiModes.end(), mode) != mGuiModes.end(); 1468 } 1469 showCrosshair(bool show)1470 void WindowManager::showCrosshair (bool show) 1471 { 1472 if (mHud) 1473 mHud->setCrosshairVisible (show && mCrosshairEnabled); 1474 } 1475 updateActivatedQuickKey()1476 void WindowManager::updateActivatedQuickKey () 1477 { 1478 mQuickKeysMenu->updateActivatedQuickKey(); 1479 } 1480 activateQuickKey(int index)1481 void WindowManager::activateQuickKey (int index) 1482 { 1483 mQuickKeysMenu->activateQuickKey(index); 1484 } 1485 getSubtitlesEnabled()1486 bool WindowManager::getSubtitlesEnabled () 1487 { 1488 return mSubtitlesEnabled; 1489 } 1490 toggleHud()1491 bool WindowManager::toggleHud() 1492 { 1493 mHudEnabled = !mHudEnabled; 1494 updateVisible(); 1495 return mHudEnabled; 1496 } 1497 getRestEnabled()1498 bool WindowManager::getRestEnabled() 1499 { 1500 //Enable rest dialogue if character creation finished 1501 if(mRestAllowed==false && MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")==-1) 1502 mRestAllowed=true; 1503 return mRestAllowed; 1504 } 1505 getPlayerSleeping()1506 bool WindowManager::getPlayerSleeping () 1507 { 1508 return mWaitDialog->getSleeping(); 1509 } 1510 wakeUpPlayer()1511 void WindowManager::wakeUpPlayer() 1512 { 1513 mWaitDialog->wakeUp(); 1514 } 1515 addVisitedLocation(const std::string & name,int x,int y)1516 void WindowManager::addVisitedLocation(const std::string& name, int x, int y) 1517 { 1518 mMap->addVisitedLocation (name, x, y); 1519 } 1520 getTranslationDataStorage() const1521 const Translation::Storage& WindowManager::getTranslationDataStorage() const 1522 { 1523 return mTranslationDataStorage; 1524 } 1525 changePointer(const std::string & name)1526 void WindowManager::changePointer(const std::string &name) 1527 { 1528 MyGUI::PointerManager::getInstance().setPointer(name); 1529 onCursorChange(name); 1530 } 1531 showSoulgemDialog(MWWorld::Ptr item)1532 void WindowManager::showSoulgemDialog(MWWorld::Ptr item) 1533 { 1534 mSoulgemDialog->show(item); 1535 updateVisible(); 1536 } 1537 updatePlayer()1538 void WindowManager::updatePlayer() 1539 { 1540 mInventoryWindow->updatePlayer(); 1541 1542 const MWWorld::Ptr player = MWMechanics::getPlayer(); 1543 if (player.getClass().getNpcStats(player).isWerewolf()) 1544 { 1545 setWerewolfOverlay(true); 1546 forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); 1547 } 1548 } 1549 1550 // Remove this wrapper once onKeyFocusChanged call is rendered unnecessary setKeyFocusWidget(MyGUI::Widget * widget)1551 void WindowManager::setKeyFocusWidget(MyGUI::Widget *widget) 1552 { 1553 MyGUI::InputManager::getInstance().setKeyFocusWidget(widget); 1554 onKeyFocusChanged(widget); 1555 } 1556 onKeyFocusChanged(MyGUI::Widget * widget)1557 void WindowManager::onKeyFocusChanged(MyGUI::Widget *widget) 1558 { 1559 if (widget && widget->castType<MyGUI::EditBox>(false)) 1560 SDL_StartTextInput(); 1561 else 1562 SDL_StopTextInput(); 1563 } 1564 setEnemy(const MWWorld::Ptr & enemy)1565 void WindowManager::setEnemy(const MWWorld::Ptr &enemy) 1566 { 1567 mHud->setEnemy(enemy); 1568 } 1569 getMessagesCount() const1570 int WindowManager::getMessagesCount() const 1571 { 1572 int count = 0; 1573 if (mMessageBoxManager) 1574 count = mMessageBoxManager->getMessagesCount(); 1575 1576 return count; 1577 } 1578 getLoadingScreen()1579 Loading::Listener* WindowManager::getLoadingScreen() 1580 { 1581 return mLoadingScreen; 1582 } 1583 getCursorVisible()1584 bool WindowManager::getCursorVisible() 1585 { 1586 return mCursorVisible && mCursorActive; 1587 } 1588 trackWindow(Layout * layout,const std::string & name)1589 void WindowManager::trackWindow(Layout *layout, const std::string &name) 1590 { 1591 std::string settingName = name; 1592 MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); 1593 bool isMaximized = Settings::Manager::getBool(name + " maximized", "Windows"); 1594 if (isMaximized) 1595 settingName += " maximized"; 1596 1597 MyGUI::IntPoint pos(static_cast<int>(Settings::Manager::getFloat(settingName + " x", "Windows") * viewSize.width), 1598 static_cast<int>(Settings::Manager::getFloat(settingName + " y", "Windows") * viewSize.height)); 1599 MyGUI::IntSize size (static_cast<int>(Settings::Manager::getFloat(settingName + " w", "Windows") * viewSize.width), 1600 static_cast<int>(Settings::Manager::getFloat(settingName + " h", "Windows") * viewSize.height)); 1601 layout->mMainWidget->setPosition(pos); 1602 layout->mMainWidget->setSize(size); 1603 1604 MyGUI::Window* window = layout->mMainWidget->castType<MyGUI::Window>(); 1605 window->eventWindowChangeCoord += MyGUI::newDelegate(this, &WindowManager::onWindowChangeCoord); 1606 mTrackedWindows[window] = name; 1607 } 1608 toggleMaximized(Layout * layout)1609 void WindowManager::toggleMaximized(Layout *layout) 1610 { 1611 MyGUI::Window* window = layout->mMainWidget->castType<MyGUI::Window>(); 1612 std::string setting = mTrackedWindows[window]; 1613 if (setting.empty()) 1614 return; 1615 1616 bool maximized = !Settings::Manager::getBool(setting + " maximized", "Windows"); 1617 if (maximized) 1618 setting += " maximized"; 1619 1620 MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); 1621 float x = Settings::Manager::getFloat(setting + " x", "Windows") * float(viewSize.width); 1622 float y = Settings::Manager::getFloat(setting + " y", "Windows") * float(viewSize.height); 1623 float w = Settings::Manager::getFloat(setting + " w", "Windows") * float(viewSize.width); 1624 float h = Settings::Manager::getFloat(setting + " h", "Windows") * float(viewSize.height); 1625 window->setCoord(x, y, w, h); 1626 Settings::Manager::setBool(mTrackedWindows[window] + " maximized", "Windows", maximized); 1627 } 1628 onWindowChangeCoord(MyGUI::Window * _sender)1629 void WindowManager::onWindowChangeCoord(MyGUI::Window *_sender) 1630 { 1631 std::string setting = mTrackedWindows[_sender]; 1632 MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); 1633 float x = _sender->getPosition().left / float(viewSize.width); 1634 float y = _sender->getPosition().top / float(viewSize.height); 1635 float w = _sender->getSize().width / float(viewSize.width); 1636 float h = _sender->getSize().height / float(viewSize.height); 1637 Settings::Manager::setFloat(setting + " x", "Windows", x); 1638 Settings::Manager::setFloat(setting + " y", "Windows", y); 1639 Settings::Manager::setFloat(setting + " w", "Windows", w); 1640 Settings::Manager::setFloat(setting + " h", "Windows", h); 1641 bool maximized = Settings::Manager::getBool(setting + " maximized", "Windows"); 1642 if (maximized) 1643 Settings::Manager::setBool(setting + " maximized", "Windows", false); 1644 } 1645 clear()1646 void WindowManager::clear() 1647 { 1648 mPlayerBounty = -1; 1649 1650 for (WindowBase* window : mWindows) 1651 window->clear(); 1652 1653 if (mLocalMapRender) 1654 mLocalMapRender->clear(); 1655 1656 mMessageBoxManager->clear(); 1657 1658 mToolTips->clear(); 1659 1660 mSelectedSpell.clear(); 1661 mCustomMarkers.clear(); 1662 1663 mForceHidden = GW_None; 1664 mRestAllowed = true; 1665 1666 while (!mGuiModes.empty()) 1667 popGuiMode(); 1668 1669 updateVisible(); 1670 } 1671 write(ESM::ESMWriter & writer,Loading::Listener & progress)1672 void WindowManager::write(ESM::ESMWriter &writer, Loading::Listener& progress) 1673 { 1674 mMap->write(writer, progress); 1675 1676 mQuickKeysMenu->write(writer); 1677 1678 if (!mSelectedSpell.empty()) 1679 { 1680 writer.startRecord(ESM::REC_ASPL); 1681 writer.writeHNString("ID__", mSelectedSpell); 1682 writer.endRecord(ESM::REC_ASPL); 1683 } 1684 1685 for (CustomMarkerCollection::ContainerType::const_iterator it = mCustomMarkers.begin(); it != mCustomMarkers.end(); ++it) 1686 { 1687 writer.startRecord(ESM::REC_MARK); 1688 it->second.save(writer); 1689 writer.endRecord(ESM::REC_MARK); 1690 } 1691 } 1692 readRecord(ESM::ESMReader & reader,uint32_t type)1693 void WindowManager::readRecord(ESM::ESMReader &reader, uint32_t type) 1694 { 1695 if (type == ESM::REC_GMAP) 1696 mMap->readRecord(reader, type); 1697 else if (type == ESM::REC_KEYS) 1698 mQuickKeysMenu->readRecord(reader, type); 1699 else if (type == ESM::REC_ASPL) 1700 { 1701 reader.getSubNameIs("ID__"); 1702 std::string spell = reader.getHString(); 1703 if (mStore->get<ESM::Spell>().search(spell)) 1704 mSelectedSpell = spell; 1705 } 1706 else if (type == ESM::REC_MARK) 1707 { 1708 ESM::CustomMarker marker; 1709 marker.load(reader); 1710 mCustomMarkers.addMarker(marker, false); 1711 } 1712 } 1713 countSavedGameRecords() const1714 int WindowManager::countSavedGameRecords() const 1715 { 1716 return 1 // Global map 1717 + 1 // QuickKeysMenu 1718 + mCustomMarkers.size() 1719 + (!mSelectedSpell.empty() ? 1 : 0); 1720 } 1721 isSavingAllowed() const1722 bool WindowManager::isSavingAllowed() const 1723 { 1724 return !MyGUI::InputManager::getInstance().isModalAny() 1725 && !isConsoleMode() 1726 // TODO: remove this, once we have properly serialized the state of open windows 1727 && (!isGuiMode() || (mGuiModes.size() == 1 && (getMode() == GM_MainMenu || getMode() == GM_Rest))); 1728 } 1729 playVideo(const std::string & name,bool allowSkipping)1730 void WindowManager::playVideo(const std::string &name, bool allowSkipping) 1731 { 1732 mVideoWidget->playVideo("video\\" + name); 1733 1734 mVideoWidget->eventKeyButtonPressed.clear(); 1735 mVideoBackground->eventKeyButtonPressed.clear(); 1736 if (allowSkipping) 1737 { 1738 mVideoWidget->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed); 1739 mVideoBackground->eventKeyButtonPressed += MyGUI::newDelegate(this, &WindowManager::onVideoKeyPressed); 1740 } 1741 1742 enableScene(false); 1743 1744 MyGUI::IntSize screenSize = MyGUI::RenderManager::getInstance().getViewSize(); 1745 sizeVideo(screenSize.width, screenSize.height); 1746 1747 MyGUI::Widget* oldKeyFocus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); 1748 setKeyFocusWidget(mVideoWidget); 1749 1750 mVideoBackground->setVisible(true); 1751 1752 bool cursorWasVisible = mCursorVisible; 1753 setCursorVisible(false); 1754 1755 if (mVideoWidget->hasAudioStream()) 1756 MWBase::Environment::get().getSoundManager()->pauseSounds(MWSound::VideoPlayback, 1757 ~MWSound::Type::Movie & MWSound::Type::Mask 1758 ); 1759 1760 Misc::FrameRateLimiter frameRateLimiter = Misc::makeFrameRateLimiter(MWBase::Environment::get().getFrameRateLimit()); 1761 while (mVideoWidget->update() && !MWBase::Environment::get().getStateManager()->hasQuitRequest()) 1762 { 1763 const double dt = std::chrono::duration_cast<std::chrono::duration<double>>(frameRateLimiter.getLastFrameDuration()).count(); 1764 1765 MWBase::Environment::get().getInputManager()->update(dt, true, false); 1766 1767 if (!mWindowVisible) 1768 { 1769 mVideoWidget->pause(); 1770 std::this_thread::sleep_for(std::chrono::milliseconds(5)); 1771 } 1772 else 1773 { 1774 if (mVideoWidget->isPaused()) 1775 mVideoWidget->resume(); 1776 1777 mViewer->eventTraversal(); 1778 mViewer->updateTraversal(); 1779 mViewer->renderingTraversals(); 1780 } 1781 // at the time this function is called we are in the middle of a frame, 1782 // so out of order calls are necessary to get a correct frameNumber for the next frame. 1783 // refer to the advance() and frame() order in Engine::go() 1784 mViewer->advance(mViewer->getFrameStamp()->getSimulationTime()); 1785 1786 frameRateLimiter.limit(); 1787 } 1788 mVideoWidget->stop(); 1789 1790 MWBase::Environment::get().getSoundManager()->resumeSounds(MWSound::VideoPlayback); 1791 1792 setKeyFocusWidget(oldKeyFocus); 1793 1794 setCursorVisible(cursorWasVisible); 1795 1796 // Restore normal rendering 1797 updateVisible(); 1798 1799 mVideoBackground->setVisible(false); 1800 } 1801 sizeVideo(int screenWidth,int screenHeight)1802 void WindowManager::sizeVideo(int screenWidth, int screenHeight) 1803 { 1804 // Use black bars to correct aspect ratio 1805 bool stretch = Settings::Manager::getBool("stretch menu background", "GUI"); 1806 mVideoBackground->setSize(screenWidth, screenHeight); 1807 mVideoWidget->autoResize(stretch); 1808 } 1809 exitCurrentModal()1810 void WindowManager::exitCurrentModal() 1811 { 1812 if (!mCurrentModals.empty()) 1813 { 1814 WindowModal* window = mCurrentModals.back(); 1815 if (!window->exit()) 1816 return; 1817 window->setVisible(false); 1818 } 1819 } 1820 addCurrentModal(WindowModal * input)1821 void WindowManager::addCurrentModal(WindowModal *input) 1822 { 1823 if (mCurrentModals.empty()) 1824 mKeyboardNavigation->saveFocus(getMode()); 1825 1826 mCurrentModals.push_back(input); 1827 mKeyboardNavigation->restoreFocus(-1); 1828 1829 mKeyboardNavigation->setModalWindow(input->mMainWidget); 1830 mKeyboardNavigation->setDefaultFocus(input->mMainWidget, input->getDefaultKeyFocus()); 1831 } 1832 removeCurrentModal(WindowModal * input)1833 void WindowManager::removeCurrentModal(WindowModal* input) 1834 { 1835 if(!mCurrentModals.empty()) 1836 { 1837 if(input == mCurrentModals.back()) 1838 { 1839 mCurrentModals.pop_back(); 1840 mKeyboardNavigation->saveFocus(-1); 1841 } 1842 else 1843 { 1844 auto found = std::find(mCurrentModals.begin(), mCurrentModals.end(), input); 1845 if (found != mCurrentModals.end()) 1846 mCurrentModals.erase(found); 1847 else 1848 Log(Debug::Warning) << "Warning: can't find modal window " << input; 1849 } 1850 } 1851 if (mCurrentModals.empty()) 1852 { 1853 mKeyboardNavigation->setModalWindow(nullptr); 1854 mKeyboardNavigation->restoreFocus(getMode()); 1855 } 1856 else 1857 mKeyboardNavigation->setModalWindow(mCurrentModals.back()->mMainWidget); 1858 } 1859 onVideoKeyPressed(MyGUI::Widget * _sender,MyGUI::KeyCode _key,MyGUI::Char _char)1860 void WindowManager::onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char) 1861 { 1862 if (_key == MyGUI::KeyCode::Escape) 1863 mVideoWidget->stop(); 1864 } 1865 updatePinnedWindows()1866 void WindowManager::updatePinnedWindows() 1867 { 1868 mInventoryWindow->setPinned(Settings::Manager::getBool("inventory pin", "Windows")); 1869 if (Settings::Manager::getBool("inventory hidden", "Windows")) 1870 mShown = (GuiWindow)(mShown ^ GW_Inventory); 1871 1872 mMap->setPinned(Settings::Manager::getBool("map pin", "Windows")); 1873 if (Settings::Manager::getBool("map hidden", "Windows")) 1874 mShown = (GuiWindow)(mShown ^ GW_Map); 1875 1876 mSpellWindow->setPinned(Settings::Manager::getBool("spells pin", "Windows")); 1877 if (Settings::Manager::getBool("spells hidden", "Windows")) 1878 mShown = (GuiWindow)(mShown ^ GW_Magic); 1879 1880 mStatsWindow->setPinned(Settings::Manager::getBool("stats pin", "Windows")); 1881 if (Settings::Manager::getBool("stats hidden", "Windows")) 1882 mShown = (GuiWindow)(mShown ^ GW_Stats); 1883 } 1884 pinWindow(GuiWindow window)1885 void WindowManager::pinWindow(GuiWindow window) 1886 { 1887 switch (window) 1888 { 1889 case GW_Inventory: 1890 mInventoryWindow->setPinned(true); 1891 break; 1892 case GW_Map: 1893 mMap->setPinned(true); 1894 break; 1895 case GW_Magic: 1896 mSpellWindow->setPinned(true); 1897 break; 1898 case GW_Stats: 1899 mStatsWindow->setPinned(true); 1900 break; 1901 default: 1902 break; 1903 } 1904 1905 updateVisible(); 1906 } 1907 fadeScreenIn(const float time,bool clearQueue,float delay)1908 void WindowManager::fadeScreenIn(const float time, bool clearQueue, float delay) 1909 { 1910 if (clearQueue) 1911 mScreenFader->clearQueue(); 1912 mScreenFader->fadeOut(time, delay); 1913 } 1914 fadeScreenOut(const float time,bool clearQueue,float delay)1915 void WindowManager::fadeScreenOut(const float time, bool clearQueue, float delay) 1916 { 1917 if (clearQueue) 1918 mScreenFader->clearQueue(); 1919 mScreenFader->fadeIn(time, delay); 1920 } 1921 fadeScreenTo(const int percent,const float time,bool clearQueue,float delay)1922 void WindowManager::fadeScreenTo(const int percent, const float time, bool clearQueue, float delay) 1923 { 1924 if (clearQueue) 1925 mScreenFader->clearQueue(); 1926 mScreenFader->fadeTo(percent, time, delay); 1927 } 1928 setBlindness(const int percent)1929 void WindowManager::setBlindness(const int percent) 1930 { 1931 mBlindnessFader->notifyAlphaChanged(percent / 100.f); 1932 } 1933 activateHitOverlay(bool interrupt)1934 void WindowManager::activateHitOverlay(bool interrupt) 1935 { 1936 if (!mHitFaderEnabled) 1937 return; 1938 1939 if (!interrupt && !mHitFader->isEmpty()) 1940 return; 1941 1942 mHitFader->clearQueue(); 1943 mHitFader->fadeTo(100, 0.0f); 1944 mHitFader->fadeTo(0, 0.5f); 1945 } 1946 setWerewolfOverlay(bool set)1947 void WindowManager::setWerewolfOverlay(bool set) 1948 { 1949 if (!mWerewolfOverlayEnabled) 1950 return; 1951 1952 if (mWerewolfFader) 1953 mWerewolfFader->notifyAlphaChanged(set ? 1.0f : 0.0f); 1954 } 1955 onClipboardChanged(const std::string & _type,const std::string & _data)1956 void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) 1957 { 1958 if (_type == "Text") 1959 SDL_SetClipboardText(MyGUI::TextIterator::getOnlyText(MyGUI::UString(_data)).asUTF8().c_str()); 1960 } 1961 onClipboardRequested(const std::string & _type,std::string & _data)1962 void WindowManager::onClipboardRequested(const std::string &_type, std::string &_data) 1963 { 1964 if (_type != "Text") 1965 return; 1966 char* text=nullptr; 1967 text = SDL_GetClipboardText(); 1968 if (text) 1969 _data = MyGUI::TextIterator::toTagsString(text); 1970 1971 SDL_free(text); 1972 } 1973 toggleConsole()1974 void WindowManager::toggleConsole() 1975 { 1976 bool visible = mConsole->isVisible(); 1977 1978 if (!visible && !mGuiModes.empty()) 1979 mKeyboardNavigation->saveFocus(mGuiModes.back()); 1980 1981 mConsole->setVisible(!visible); 1982 1983 if (visible && !mGuiModes.empty()) 1984 mKeyboardNavigation->restoreFocus(mGuiModes.back()); 1985 1986 updateVisible(); 1987 } 1988 toggleDebugWindow()1989 void WindowManager::toggleDebugWindow() 1990 { 1991 #ifndef BT_NO_PROFILE 1992 mDebugWindow->setVisible(!mDebugWindow->isVisible()); 1993 #endif 1994 } 1995 cycleSpell(bool next)1996 void WindowManager::cycleSpell(bool next) 1997 { 1998 if (!isGuiMode()) 1999 mSpellWindow->cycle(next); 2000 } 2001 cycleWeapon(bool next)2002 void WindowManager::cycleWeapon(bool next) 2003 { 2004 if (!isGuiMode()) 2005 mInventoryWindow->cycle(next); 2006 } 2007 playSound(const std::string & soundId,float volume,float pitch)2008 void WindowManager::playSound(const std::string& soundId, float volume, float pitch) 2009 { 2010 if (soundId.empty()) 2011 return; 2012 2013 MWBase::Environment::get().getSoundManager()->playSound(soundId, volume, pitch, MWSound::Type::Sfx, MWSound::PlayMode::NoEnv); 2014 } 2015 updateSpellWindow()2016 void WindowManager::updateSpellWindow() 2017 { 2018 if (mSpellWindow) 2019 mSpellWindow->updateSpells(); 2020 } 2021 setConsoleSelectedObject(const MWWorld::Ptr & object)2022 void WindowManager::setConsoleSelectedObject(const MWWorld::Ptr &object) 2023 { 2024 mConsole->setSelectedObject(object); 2025 } 2026 correctIconPath(const std::string & path)2027 std::string WindowManager::correctIconPath(const std::string& path) 2028 { 2029 return Misc::ResourceHelpers::correctIconPath(path, mResourceSystem->getVFS()); 2030 } 2031 correctBookartPath(const std::string & path,int width,int height,bool * exists)2032 std::string WindowManager::correctBookartPath(const std::string& path, int width, int height, bool* exists) 2033 { 2034 std::string corrected = Misc::ResourceHelpers::correctBookartPath(path, width, height, mResourceSystem->getVFS()); 2035 if (exists) 2036 *exists = mResourceSystem->getVFS()->exists(corrected); 2037 return corrected; 2038 } 2039 correctTexturePath(const std::string & path)2040 std::string WindowManager::correctTexturePath(const std::string& path) 2041 { 2042 return Misc::ResourceHelpers::correctTexturePath(path, mResourceSystem->getVFS()); 2043 } 2044 textureExists(const std::string & path)2045 bool WindowManager::textureExists(const std::string &path) 2046 { 2047 std::string corrected = Misc::ResourceHelpers::correctTexturePath(path, mResourceSystem->getVFS()); 2048 return mResourceSystem->getVFS()->exists(corrected); 2049 } 2050 createCursors()2051 void WindowManager::createCursors() 2052 { 2053 // FIXME: currently we do not scale cursor since it is not a MyGUI widget. 2054 // In theory, we can do it manually (rescale the cursor image via osg::Imag::scaleImage() and scale the hotspot position). 2055 // Unfortunately, this apploach can lead to driver crashes on some setups (e.g. on laptops with nvidia-prime on Linux). 2056 MyGUI::ResourceManager::EnumeratorPtr enumerator = MyGUI::ResourceManager::getInstance().getEnumerator(); 2057 while (enumerator.next()) 2058 { 2059 MyGUI::IResource* resource = enumerator.current().second; 2060 ResourceImageSetPointerFix* imgSetPointer = resource->castType<ResourceImageSetPointerFix>(false); 2061 if (!imgSetPointer) 2062 continue; 2063 std::string tex_name = imgSetPointer->getImageSet()->getIndexInfo(0,0).texture; 2064 2065 osg::ref_ptr<osg::Image> image = mResourceSystem->getImageManager()->getImage(tex_name); 2066 2067 if(image.valid()) 2068 { 2069 //everything looks good, send it to the cursor manager 2070 Uint8 hotspot_x = imgSetPointer->getHotSpot().left; 2071 Uint8 hotspot_y = imgSetPointer->getHotSpot().top; 2072 int rotation = imgSetPointer->getRotation(); 2073 2074 mCursorManager->createCursor(imgSetPointer->getResourceName(), rotation, image, hotspot_x, hotspot_y); 2075 } 2076 } 2077 } 2078 createTextures()2079 void WindowManager::createTextures() 2080 { 2081 { 2082 MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("white"); 2083 tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8); 2084 unsigned char* data = reinterpret_cast<unsigned char*>(tex->lock(MyGUI::TextureUsage::Write)); 2085 for (int x=0; x<8; ++x) 2086 for (int y=0; y<8; ++y) 2087 { 2088 *(data++) = 255; 2089 *(data++) = 255; 2090 *(data++) = 255; 2091 } 2092 tex->unlock(); 2093 } 2094 2095 { 2096 MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("black"); 2097 tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8); 2098 unsigned char* data = reinterpret_cast<unsigned char*>(tex->lock(MyGUI::TextureUsage::Write)); 2099 for (int x=0; x<8; ++x) 2100 for (int y=0; y<8; ++y) 2101 { 2102 *(data++) = 0; 2103 *(data++) = 0; 2104 *(data++) = 0; 2105 } 2106 tex->unlock(); 2107 } 2108 2109 { 2110 MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().createTexture("transparent"); 2111 tex->createManual(8, 8, MyGUI::TextureUsage::Write, MyGUI::PixelFormat::R8G8B8A8); 2112 setMenuTransparency(Settings::Manager::getFloat("menu transparency", "GUI")); 2113 } 2114 } 2115 setMenuTransparency(float value)2116 void WindowManager::setMenuTransparency(float value) 2117 { 2118 MyGUI::ITexture* tex = MyGUI::RenderManager::getInstance().getTexture("transparent"); 2119 unsigned char* data = reinterpret_cast<unsigned char*>(tex->lock(MyGUI::TextureUsage::Write)); 2120 for (int x=0; x<8; ++x) 2121 for (int y=0; y<8; ++y) 2122 { 2123 *(data++) = 255; 2124 *(data++) = 255; 2125 *(data++) = 255; 2126 *(data++) = static_cast<unsigned char>(value*255); 2127 } 2128 tex->unlock(); 2129 } 2130 addCell(MWWorld::CellStore * cell)2131 void WindowManager::addCell(MWWorld::CellStore* cell) 2132 { 2133 mLocalMapRender->addCell(cell); 2134 } 2135 removeCell(MWWorld::CellStore * cell)2136 void WindowManager::removeCell(MWWorld::CellStore *cell) 2137 { 2138 mLocalMapRender->removeCell(cell); 2139 } 2140 writeFog(MWWorld::CellStore * cell)2141 void WindowManager::writeFog(MWWorld::CellStore *cell) 2142 { 2143 mLocalMapRender->saveFogOfWar(cell); 2144 } 2145 getTextColours()2146 const MWGui::TextColours& WindowManager::getTextColours() 2147 { 2148 return mTextColours; 2149 } 2150 injectKeyPress(MyGUI::KeyCode key,unsigned int text,bool repeat)2151 bool WindowManager::injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat) 2152 { 2153 if (!mKeyboardNavigation->injectKeyPress(key, text, repeat)) 2154 { 2155 MyGUI::Widget* focus = MyGUI::InputManager::getInstance().getKeyFocusWidget(); 2156 bool widgetActive = MyGUI::InputManager::getInstance().injectKeyPress(key, text); 2157 if (!widgetActive || !focus) 2158 return false; 2159 // FIXME: MyGUI doesn't allow widgets to state if a given key was actually used, so make a guess 2160 if (focus->getTypeName().find("Button") != std::string::npos) 2161 { 2162 switch (key.getValue()) 2163 { 2164 case MyGUI::KeyCode::ArrowDown: 2165 case MyGUI::KeyCode::ArrowUp: 2166 case MyGUI::KeyCode::ArrowLeft: 2167 case MyGUI::KeyCode::ArrowRight: 2168 case MyGUI::KeyCode::Return: 2169 case MyGUI::KeyCode::NumpadEnter: 2170 case MyGUI::KeyCode::Space: 2171 return true; 2172 default: 2173 return false; 2174 } 2175 } 2176 return false; 2177 } 2178 else 2179 return true; 2180 } 2181 injectKeyRelease(MyGUI::KeyCode key)2182 bool WindowManager::injectKeyRelease(MyGUI::KeyCode key) 2183 { 2184 return MyGUI::InputManager::getInstance().injectKeyRelease(key); 2185 } 2186 update(bool visible)2187 void WindowManager::GuiModeState::update(bool visible) 2188 { 2189 for (unsigned int i=0; i<mWindows.size(); ++i) 2190 mWindows[i]->setVisible(visible); 2191 } 2192 watchActor(const MWWorld::Ptr & ptr)2193 void WindowManager::watchActor(const MWWorld::Ptr& ptr) 2194 { 2195 mStatsWatcher->watchActor(ptr); 2196 } 2197 getWatchedActor() const2198 MWWorld::Ptr WindowManager::getWatchedActor() const 2199 { 2200 return mStatsWatcher->getWatchedActor(); 2201 } 2202 } 2203