1 #ifndef MWGUI_WINDOWMANAGERIMP_H
2 #define MWGUI_WINDOWMANAGERIMP_H
3 
4 /**
5    This class owns and controls all the MW specific windows in the
6    GUI. It can enable/disable Gui mode, and is responsible for sending
7    and retrieving information from the Gui.
8 **/
9 
10 #include <stack>
11 
12 #include <osg/ref_ptr>
13 
14 #include "../mwbase/windowmanager.hpp"
15 
16 #include <components/sdlutil/events.hpp>
17 #include <components/settings/settings.hpp>
18 #include <components/to_utf8/to_utf8.hpp>
19 
20 #include "mapwindow.hpp"
21 #include "statswatcher.hpp"
22 #include "textcolours.hpp"
23 
24 #include <MyGUI_KeyCode.h>
25 #include <MyGUI_Types.h>
26 
27 namespace MyGUI
28 {
29     class Gui;
30     class Widget;
31     class Window;
32     class UString;
33     class ImageBox;
34 }
35 
36 namespace MWWorld
37 {
38     class ESMStore;
39 }
40 
41 namespace Compiler
42 {
43     class Extensions;
44 }
45 
46 namespace Translation
47 {
48     class Storage;
49 }
50 
51 namespace osg
52 {
53     class Group;
54 }
55 namespace osgViewer
56 {
57     class Viewer;
58 }
59 
60 namespace Resource
61 {
62     class ResourceSystem;
63 }
64 
65 namespace SceneUtil
66 {
67     class WorkQueue;
68 }
69 
70 namespace SDLUtil
71 {
72     class SDLCursorManager;
73     class VideoWrapper;
74 }
75 
76 namespace osgMyGUI
77 {
78     class Platform;
79 }
80 
81 namespace Gui
82 {
83     class FontLoader;
84 }
85 
86 namespace MWRender
87 {
88     class LocalMap;
89 }
90 
91 namespace MWGui
92 {
93   class WindowBase;
94   class HUD;
95   class MapWindow;
96   class MainMenu;
97   class StatsWindow;
98   class InventoryWindow;
99   struct JournalWindow;
100   class CharacterCreation;
101   class DragAndDrop;
102   class ToolTips;
103   class TextInputDialog;
104   class InfoBoxDialog;
105   class MessageBoxManager;
106   class SettingsWindow;
107   class AlchemyWindow;
108   class QuickKeysMenu;
109   class LoadingScreen;
110   class LevelupDialog;
111   class WaitDialog;
112   class SpellCreationDialog;
113   class EnchantingDialog;
114   class TrainingWindow;
115   class SpellIcons;
116   class MerchantRepair;
117   class SoulgemDialog;
118   class Recharge;
119   class CompanionWindow;
120   class VideoWidget;
121   class WindowModal;
122   class ScreenFader;
123   class DebugWindow;
124   class JailScreen;
125   class KeyboardNavigation;
126 
127   class WindowManager :
128       public MWBase::WindowManager
129   {
130   public:
131     typedef std::pair<std::string, int> Faction;
132     typedef std::vector<Faction> FactionList;
133 
134     WindowManager(SDL_Window* window, osgViewer::Viewer* viewer, osg::Group* guiRoot, Resource::ResourceSystem* resourceSystem, SceneUtil::WorkQueue* workQueue,
135                   const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts, Translation::Storage& translationDataStorage,
136                   ToUTF8::FromType encoding, bool exportFonts, const std::string& versionDescription, const std::string& localPath);
137     virtual ~WindowManager();
138 
139     /// Set the ESMStore to use for retrieving of GUI-related strings.
140     void setStore (const MWWorld::ESMStore& store);
141 
142     void initUI();
143     void loadUserFonts() override;
144 
145     Loading::Listener* getLoadingScreen() override;
146 
147     /// @note This method will block until the video finishes playing
148     /// (and will continually update the window while doing so)
149     void playVideo(const std::string& name, bool allowSkipping) override;
150 
151     /// Warning: do not use MyGUI::InputManager::setKeyFocusWidget directly. Instead use this.
152     void setKeyFocusWidget (MyGUI::Widget* widget) override;
153 
154     void setNewGame(bool newgame) override;
155 
156     void pushGuiMode(GuiMode mode, const MWWorld::Ptr& arg) override;
157     void pushGuiMode (GuiMode mode) override;
158     void popGuiMode(bool noSound=false) override;
159     void removeGuiMode(GuiMode mode, bool noSound=false) override; ///< can be anywhere in the stack
160 
161     void goToJail(int days) override;
162 
163     GuiMode getMode() const override;
164     bool containsMode(GuiMode mode) const override;
165 
166     bool isGuiMode() const override;
167 
168     bool isConsoleMode() const override;
169 
170     void toggleVisible(GuiWindow wnd) override;
171 
172     void forceHide(MWGui::GuiWindow wnd) override;
173     void unsetForceHide(MWGui::GuiWindow wnd) override;
174 
175     /// Disallow all inventory mode windows
176     void disallowAll() override;
177 
178     /// Allow one or more windows
179     void allow(GuiWindow wnd) override;
180 
181     bool isAllowed(GuiWindow wnd) const override;
182 
183     /// \todo investigate, if we really need to expose every single lousy UI element to the outside world
184     MWGui::InventoryWindow* getInventoryWindow() override;
185     MWGui::CountDialog* getCountDialog() override;
186     MWGui::ConfirmationDialog* getConfirmationDialog() override;
187     MWGui::TradeWindow* getTradeWindow() override;
188 
189     /// Make the player use an item, while updating GUI state accordingly
190     void useItem(const MWWorld::Ptr& item, bool bypassBeastRestrictions=false) override;
191 
192     void updateSpellWindow() override;
193 
194     void setConsoleSelectedObject(const MWWorld::Ptr& object) override;
195 
196     /// Set time left for the player to start drowning (update the drowning bar)
197     /// @param time time left to start drowning
198     /// @param maxTime how long we can be underwater (in total) until drowning starts
199     void setDrowningTimeLeft (float time, float maxTime) override;
200 
201     void changeCell(const MWWorld::CellStore* cell) override; ///< change the active cell
202 
203     void setFocusObject(const MWWorld::Ptr& focus) override;
204     void setFocusObjectScreenCoords(float min_x, float min_y, float max_x, float max_y) override;
205 
206     void getMousePosition(int &x, int &y) override;
207     void getMousePosition(float &x, float &y) override;
208     void setDragDrop(bool dragDrop) override;
209     bool getWorldMouseOver() override;
210 
211     float getScalingFactor() override;
212 
213     bool toggleFogOfWar() override;
214     bool toggleFullHelp() override; ///< show extra info in item tooltips (owner, script)
215     bool getFullHelp() const override;
216 
217     void setActiveMap(int x, int y, bool interior) override;
218     ///< set the indices of the map texture that should be used
219 
220     /// sets the visibility of the drowning bar
221     void setDrowningBarVisibility(bool visible) override;
222 
223     // sets the visibility of the hud health/magicka/stamina bars
224     void setHMSVisibility(bool visible) override;
225     // sets the visibility of the hud minimap
226     void setMinimapVisibility(bool visible) override;
227     void setWeaponVisibility(bool visible) override;
228     void setSpellVisibility(bool visible) override;
229     void setSneakVisibility(bool visible) override;
230 
231     /// activate selected quick key
232     void activateQuickKey (int index) override;
233     /// update activated quick key state (if action executing was delayed for some reason)
234     void updateActivatedQuickKey () override;
235 
getSelectedSpell()236     std::string getSelectedSpell() override { return mSelectedSpell; }
237     void setSelectedSpell(const std::string& spellId, int successChancePercent) override;
238     void setSelectedEnchantItem(const MWWorld::Ptr& item) override;
239     const MWWorld::Ptr& getSelectedEnchantItem() const override;
240     void setSelectedWeapon(const MWWorld::Ptr& item) override;
241     const MWWorld::Ptr& getSelectedWeapon() const override;
242     int getFontHeight() const override;
243     void unsetSelectedSpell() override;
244     void unsetSelectedWeapon() override;
245 
246     void updateConsoleObjectPtr(const MWWorld::Ptr& currentPtr, const MWWorld::Ptr& newPtr) override;
247 
248     void showCrosshair(bool show) override;
249     bool getSubtitlesEnabled() override;
250 
251     /// Turn visibility of HUD on or off
252     bool toggleHud() override;
253 
254     void disallowMouse() override;
255     void allowMouse() override;
256     void notifyInputActionBound() override;
257 
258     void addVisitedLocation(const std::string& name, int x, int y) override;
259 
260     ///Hides dialog and schedules dialog to be deleted.
261     void removeDialog(Layout* dialog) override;
262 
263     ///Gracefully attempts to exit the topmost GUI mode
264     void exitCurrentGuiMode() override;
265 
266     void messageBox (const std::string& message, enum MWGui::ShowInDialogueMode showInDialogueMode = MWGui::ShowInDialogueMode_IfPossible) override;
267     void staticMessageBox(const std::string& message) override;
268     void removeStaticMessageBox() override;
269     void interactiveMessageBox (const std::string& message,
270                                         const std::vector<std::string>& buttons = std::vector<std::string>(), bool block=false) override;
271 
272     int readPressedButton () override; ///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
273 
274     void update (float duration) override;
275 
276     /**
277      * Fetches a GMST string from the store, if there is no setting with the given
278      * ID or it is not a string the default string is returned.
279      *
280      * @param id Identifier for the GMST setting, e.g. "aName"
281      * @param default Default value if the GMST setting cannot be used.
282      */
283     std::string getGameSettingString(const std::string &id, const std::string &default_) override;
284 
285     void processChangedSettings(const Settings::CategorySettingVector& changed) override;
286 
287     void windowVisibilityChange(bool visible) override;
288     void windowResized(int x, int y) override;
289     void windowClosed() override;
290     bool isWindowVisible() override;
291 
292     void watchActor(const MWWorld::Ptr& ptr) override;
293     MWWorld::Ptr getWatchedActor() const override;
294 
295     void executeInConsole (const std::string& path) override;
296 
enableRest()297     void enableRest() override { mRestAllowed = true; }
298     bool getRestEnabled() override;
299 
getJournalAllowed()300     bool getJournalAllowed() override { return (mAllowed & GW_Magic) != 0; }
301 
302     bool getPlayerSleeping() override;
303     void wakeUpPlayer() override;
304 
305     void updatePlayer() override;
306 
307     void showSoulgemDialog (MWWorld::Ptr item) override;
308 
309     void changePointer (const std::string& name) override;
310 
311     void setEnemy (const MWWorld::Ptr& enemy) override;
312 
313     int getMessagesCount() const override;
314 
315     const Translation::Storage& getTranslationDataStorage() const override;
316 
317     void onSoulgemDialogButtonPressed (int button);
318 
319     bool getCursorVisible() override;
320 
321     /// Call when mouse cursor or buttons are used.
322     void setCursorActive(bool active) override;
323 
324     /// Clear all savegame-specific data
325     void clear() override;
326 
327     void write (ESM::ESMWriter& writer, Loading::Listener& progress) override;
328     void readRecord (ESM::ESMReader& reader, uint32_t type) override;
329     int countSavedGameRecords() const override;
330 
331     /// Does the current stack of GUI-windows permit saving?
332     bool isSavingAllowed() const override;
333 
334     /// Send exit command to active Modal window **/
335     void exitCurrentModal() override;
336 
337     /// Sets the current Modal
338     /** Used to send exit command to active Modal when Esc is pressed **/
339     void addCurrentModal(WindowModal* input) override;
340 
341     /// Removes the top Modal
342     /** Used when one Modal adds another Modal
343         \param input Pointer to the current modal, to ensure proper modal is removed **/
344     void removeCurrentModal(WindowModal* input) override;
345 
346     void pinWindow (MWGui::GuiWindow window) override;
347     void toggleMaximized(Layout *layout) override;
348 
349     /// Fade the screen in, over \a time seconds
350     void fadeScreenIn(const float time, bool clearQueue, float delay) override;
351     /// Fade the screen out to black, over \a time seconds
352     void fadeScreenOut(const float time, bool clearQueue, float delay) override;
353     /// Fade the screen to a specified percentage of black, over \a time seconds
354     void fadeScreenTo(const int percent, const float time, bool clearQueue, float delay) override;
355     /// Darken the screen to a specified percentage
356     void setBlindness(const int percent) override;
357 
358     void activateHitOverlay(bool interrupt) override;
359     void setWerewolfOverlay(bool set) override;
360 
361     void toggleConsole() override;
362     void toggleDebugWindow() override;
363 
364     /// Cycle to next or previous spell
365     void cycleSpell(bool next) override;
366     /// Cycle to next or previous weapon
367     void cycleWeapon(bool next) override;
368 
369     void playSound(const std::string& soundId, float volume = 1.f, float pitch = 1.f) override;
370 
371     // In WindowManager for now since there isn't a VFS singleton
372     std::string correctIconPath(const std::string& path) override;
373     std::string correctBookartPath(const std::string& path, int width, int height, bool* exists = nullptr) override;
374     std::string correctTexturePath(const std::string& path) override;
375     bool textureExists(const std::string& path) override;
376 
377     void addCell(MWWorld::CellStore* cell) override;
378     void removeCell(MWWorld::CellStore* cell) override;
379     void writeFog(MWWorld::CellStore* cell) override;
380 
381     const MWGui::TextColours& getTextColours() override;
382 
383     bool injectKeyPress(MyGUI::KeyCode key, unsigned int text, bool repeat=false) override;
384     bool injectKeyRelease(MyGUI::KeyCode key) override;
385 
386   private:
387     unsigned int mOldUpdateMask; unsigned int mOldCullMask;
388 
389     const MWWorld::ESMStore* mStore;
390     Resource::ResourceSystem* mResourceSystem;
391     osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
392 
393     osgMyGUI::Platform* mGuiPlatform;
394     osgViewer::Viewer* mViewer;
395 
396     std::unique_ptr<Gui::FontLoader> mFontLoader;
397     std::unique_ptr<StatsWatcher> mStatsWatcher;
398 
399     bool mConsoleOnlyScripts;
400 
401     std::map<MyGUI::Window*, std::string> mTrackedWindows;
402     void trackWindow(Layout* layout, const std::string& name);
403     void onWindowChangeCoord(MyGUI::Window* _sender);
404 
405     std::string mSelectedSpell;
406     MWWorld::Ptr mSelectedEnchantItem;
407     MWWorld::Ptr mSelectedWeapon;
408 
409     std::vector<WindowModal*> mCurrentModals;
410 
411     // Markers placed manually by the player. Must be shared between both map views (the HUD map and the map window).
412     CustomMarkerCollection mCustomMarkers;
413 
414     HUD *mHud;
415     MapWindow *mMap;
416     MWRender::LocalMap* mLocalMapRender;
417     ToolTips *mToolTips;
418     StatsWindow *mStatsWindow;
419     MessageBoxManager *mMessageBoxManager;
420     Console *mConsole;
421     DialogueWindow *mDialogueWindow;
422     DragAndDrop* mDragAndDrop;
423     InventoryWindow *mInventoryWindow;
424     ScrollWindow* mScrollWindow;
425     BookWindow* mBookWindow;
426     CountDialog* mCountDialog;
427     TradeWindow* mTradeWindow;
428     SettingsWindow* mSettingsWindow;
429     ConfirmationDialog* mConfirmationDialog;
430     SpellWindow* mSpellWindow;
431     QuickKeysMenu* mQuickKeysMenu;
432     LoadingScreen* mLoadingScreen;
433     WaitDialog* mWaitDialog;
434     SoulgemDialog* mSoulgemDialog;
435     MyGUI::ImageBox* mVideoBackground;
436     VideoWidget* mVideoWidget;
437     ScreenFader* mWerewolfFader;
438     ScreenFader* mBlindnessFader;
439     ScreenFader* mHitFader;
440     ScreenFader* mScreenFader;
441     DebugWindow* mDebugWindow;
442     JailScreen* mJailScreen;
443 
444     std::vector<WindowBase*> mWindows;
445 
446     Translation::Storage& mTranslationDataStorage;
447 
448     CharacterCreation* mCharGen;
449 
450     MyGUI::Widget* mInputBlocker;
451 
452     bool mCrosshairEnabled;
453     bool mSubtitlesEnabled;
454     bool mHitFaderEnabled;
455     bool mWerewolfOverlayEnabled;
456     bool mHudEnabled;
457     bool mCursorVisible;
458     bool mCursorActive;
459 
460     int mPlayerBounty;
461 
462     void setCursorVisible(bool visible) override;
463 
464     MyGUI::Gui *mGui; // Gui
465 
466     struct GuiModeState
467     {
GuiModeStateMWGui::WindowManager::GuiModeState468         GuiModeState(WindowBase* window)
469         {
470             mWindows.push_back(window);
471         }
GuiModeStateMWGui::WindowManager::GuiModeState472         GuiModeState(const std::vector<WindowBase*>& windows)
473             : mWindows(windows) {}
GuiModeStateMWGui::WindowManager::GuiModeState474         GuiModeState() {}
475 
476         void update(bool visible);
477 
478         std::vector<WindowBase*> mWindows;
479 
480         std::string mCloseSound;
481         std::string mOpenSound;
482     };
483     // Defines the windows that should be shown in a particular GUI mode.
484     std::map<GuiMode, GuiModeState> mGuiModeStates;
485     // The currently active stack of GUI modes (top mode is the one we are in).
486     std::vector<GuiMode> mGuiModes;
487 
488     SDLUtil::SDLCursorManager* mCursorManager;
489 
490     std::vector<Layout*> mGarbageDialogs;
491     void cleanupGarbage();
492 
493     GuiWindow mShown; // Currently shown windows in inventory mode
494     GuiWindow mForceHidden; // Hidden windows (overrides mShown)
495 
496     /* Currently ALLOWED windows in inventory mode. This is used at
497        the start of the game, when windows are enabled one by one
498        through script commands. You can manipulate this through using
499        allow() and disableAll().
500      */
501     GuiWindow mAllowed;
502     // is the rest window allowed?
503     bool mRestAllowed;
504 
505     void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
506 
507     void updateMap();
508 
509     int mShowOwned;
510 
511     ToUTF8::FromType mEncoding;
512 
513     std::string mVersionDescription;
514 
515     bool mWindowVisible;
516 
517     MWGui::TextColours mTextColours;
518 
519     std::unique_ptr<KeyboardNavigation> mKeyboardNavigation;
520 
521     SDLUtil::VideoWrapper* mVideoWrapper;
522 
523     float mScalingFactor;
524 
525     /**
526      * Called when MyGUI tries to retrieve a tag's value. Tags must be denoted in #{tag} notation and will be replaced upon setting a user visible text/property.
527      * Supported syntax:
528      * #{GMSTName}: retrieves String value of the GMST called GMSTName
529      * #{setting=CATEGORY_NAME,SETTING_NAME}: retrieves String value of SETTING_NAME under category CATEGORY_NAME from settings.cfg
530      * #{sCell=CellID}: retrieves translated name of the given CellID (used only by some Morrowind localisations, in others cell ID is == cell name)
531      * #{fontcolour=FontColourName}: retrieves the value of the fallback setting "FontColor_color_<FontColourName>" from openmw.cfg,
532      *                              in the format "r g b a", float values in range 0-1. Useful for "Colour" and "TextColour" properties in skins.
533      * #{fontcolourhtml=FontColourName}: retrieves the value of the fallback setting "FontColor_color_<FontColourName>" from openmw.cfg,
534      *                              in the format "#xxxxxx" where x are hexadecimal numbers. Useful in an EditBox's caption to change the color of following text.
535      */
536     void onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result);
537 
538     void onCursorChange(const std::string& name);
539     void onKeyFocusChanged(MyGUI::Widget* widget);
540 
541     // Key pressed while playing a video
542     void onVideoKeyPressed(MyGUI::Widget *_sender, MyGUI::KeyCode _key, MyGUI::Char _char);
543 
544     void sizeVideo(int screenWidth, int screenHeight);
545 
546     void onClipboardChanged(const std::string& _type, const std::string& _data);
547     void onClipboardRequested(const std::string& _type, std::string& _data);
548 
549     void createTextures();
550     void createCursors();
551     void setMenuTransparency(float value);
552 
553     void updatePinnedWindows();
554 
555     void enableScene(bool enable);
556   };
557 }
558 
559 #endif
560