1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #ifndef NL_INTERFACE_MANAGER_H
24 #define NL_INTERFACE_MANAGER_H
28 #include "nel/misc/types_nl.h"
29 #include "nel/misc/cdb_manager.h"
30 #include "nel/misc/mutex.h"
31 #include "nel/3d/u_texture.h"
32 #include "nel/3d/u_text_context.h"
33 #include "nel/gui/interface_group.h"
34 #include "nel/gui/interface_link.h"
35 #include "nel/gui/group_list.h"
36 #include "nel/gui/view_base.h"
37 #include "nel/gui/view_pointer.h"
39 #include "nel/gui/ctrl_base.h"
40 #include "nel/gui/ctrl_scroll.h"
42 #include "nel/gui/view_renderer.h"
45 #include "nel/gui/interface_parser.h"
46 #include "nel/gui/ctrl_sheet_selection.h"
47 #include "nel/gui/interface_options.h"
48 #include "interface_config.h"
49 #include "interface_pointer.h"
50 #include "flying_text_manager.h"
52 #include "nel/gui/input_event_listener.h"
53 #include "nel/gui/db_manager.h"
56 #include "../string_manager_client.h"
58 #include "../ingame_database_manager.h"
60 #include "nel/gui/lua_manager.h"
62 //the network database node
63 extern CCDBSynchronised IngameDbMngr
;
65 ///\todo nico remove that
68 #define GROUP_BROWSER "ui:outgame:charsel:webstart:content:webstart_html"
70 ///max botchat distance
71 #define MAX_BOTCHAT_DISTANCE_SQUARE 25
73 #define MAX_NUM_MODES 6
75 #define RZ_CATEGORY_EDIT "edit"
77 // #define AJM_DEBUG_TRACK_INTERFACE_GROUPS
81 class CInterfaceOptions
;
82 class CGroupContainer
;
88 * class managing the interface
89 * \author Matthieu 'TrapII' Besson
90 * \author Nevrax France
93 class CInterfaceManager
: public NLGUI::CInterfaceParser::ISetupOptionCallbackClass
, public NLGUI::IInputEventListener
97 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
98 void DebugTrackGroupsCreated( CInterfaceGroup
*pIG
);
99 void DebugTrackGroupsDestroyed( CInterfaceGroup
*pIG
);
100 void DebugTrackGroupsDump();
101 int DebugTrackGroupsGetId( CInterfaceGroup
*pIG
);
103 typedef std::set
<CInterfaceGroup
*> setInterfaceGroupPtr
;
104 typedef std::map
<CInterfaceGroup
*, int> mapInterfaceGroupPtr2Int
;
106 setInterfaceGroupPtr _DebugTrackGroupSet
;
107 mapInterfaceGroupPtr2Int _DebugTrackGroupMap
;
108 int _DebugTrackGroupCreateCount
;
109 int _DebugTrackGroupDestroyCount
;
118 // Icon to use for validMessageBox() method
119 enum TValidMessageIcon
129 /// Singleton method : Get the unique interface loader instance
130 static CInterfaceManager
* getInstance();
132 /// Destroy singleton
133 static void destroy ();
136 ~CInterfaceManager();
142 void createLocalBranch (const std::string
&fileName
, NLMISC::IProgressCallback
&progressCallBack
);
146 // release all of the global db autocopy observers
147 void releaseServerToLocalAutoCopyObservers();
149 void setInGame( bool i
);
150 bool isInGame() const { return _InGame
; }
154 /// initialize the whole login interface
157 /// unload login interface
160 /// initialize the whole out game interface
163 /// unload out game interface
164 void uninitOutGame();
166 /// initialize the whole in game interface
169 /// Part of initInGame()
170 void loadIngameInterfaceTextures();
172 /// Part of initInGame()
175 /// Configure the Quit dialog box
176 void configureQuitDialogBox();
178 /// Part of initInGame()
181 /// Part of initInGame()
182 void loadInterfaceConfig();
184 /// Save the game interface (keys and interface config). Called before continent and entity manager are destroyed.
185 void uninitInGame0();
187 /// Uninit game interface. Called after continent and entity manager are destroyed.
188 void uninitInGame1();
190 /// update a frame Event: update the input handler manager
191 void updateFrameEvents();
193 // force to flush the debug window (also done when calling updateFrameEvents)
194 void flushDebugWindow();
196 /// update a frame View: check coordinates and draw view. The camera is used to draw in-scene interfaces. Can be NULL.
197 void updateFrameViews(NL3D::UCamera camera
);
201 * Config file loaders
204 /// Load texture grouping a set of small texture
205 void loadTextures (const std::string
&textFileName
, const std::string
&uvFileName
, bool uploadDXTC
= false);
208 void loadTexts (const std::string
&fileName
);
210 /// Load a set of xml files
211 bool parseInterface (const std::vector
<std::string
> &xmlFileNames
, bool reload
, bool isFilename
= true);
213 /// return new filename that can be used to backup original file
214 std::string
getNextBackupName(std::string filename
);
215 /// copy/rename filename for backup and show error in log
216 void createFileBackup(const std::string
&message
, const std::string
&filename
, bool useCopy
= false);
218 /// select player/shared file name from 'save' folder'
219 std::string
getSaveFileName(const std::string
&module
, const std::string
&ext
, bool useShared
= true) const;
221 /// Load / save user landmarks in .xml format
222 bool loadLandmarks ();
223 bool saveLandmarks (bool verbose
= false) const;
224 bool saveLandmarks (const std::string
&filename
) const;
226 // Load/Save position, size, etc.. of windows
227 bool loadConfig (const std::string
&filename
);
228 // Save config to default location, if verbose is true, display message in game sysinfo
229 bool saveConfig (bool verbose
= false);
230 bool saveConfig (const std::string
&filename
);
231 // delete the user config (give the player ident fileName)
232 bool deletePlayerConfig (const std::string
&playerFileIdent
);
234 // Save keys to default location, if verbose is true, display message in game sysinfo
235 bool saveKeys (bool verbose
= false);
236 // Save the keys config file
237 bool saveKeys (const std::string
&filename
);
238 // delete the user Keysconfig (give the player ident fileName)
239 bool deletePlayerKeys (const std::string
&playerFileIdent
);
241 // Log system (all chat/tell
242 void setLogState(bool state
) { _LogState
= state
; }
243 bool getLogState() const { return _LogState
; }
244 void log(const std::string
&str
, const std::string
&cat
= "");
246 /// Text from here and from server
251 virtual ~IStringProcess() { }
252 virtual bool cbIDStringReceived(std::string
&inOut
) = 0; // called when string or id is received (return true if valid the change)
255 void addServerString (const std::string
&sTarget
, uint32 id
, IStringProcess
*cb
= NULL
);
256 void addServerID (const std::string
&sTarget
, uint32 id
, IStringProcess
*cb
= NULL
);
257 void processServerIDString();
261 /// Enable/Disable window movement
262 //void enableMoveWindow (CInterfaceGroup *pWin);
263 //void disableMoveWindow ();
265 /// Enable/Disable the window resizing (0,TopLeft)(1,T)(2,TR)(3,R)(4,BR)(5,B)(6,BL)(7,L)
266 //void enableResizeWindow (CInterfaceGroup *pWin, uint8 nType, sint32 nMinW, sint32 nMaxW, sint32 nMinH, sint32 nMaxH,
267 // sint32 nStepW, sint32 nStepH);
268 //void disableResizeWindow ();
269 //void moveWindow (CInterfaceGroup *pWin, sint32 dx, sint32 dy);
271 /// Enable/Disbale capture of a control (combo box for example)
272 /// When capture is lost (by clicking outside of the control, the given property is toggled)
273 //void enableCaptureElement(CInterfaceElement *pElem, CInterfaceProperty *captureFlag);
274 //void disableCaptureElement();
276 /** Enable/Disable a single modal window (pointer cannot get out of the window).
277 * NB : the keyboard capture is released on both calls.
278 * NB : cascaded modal windows are disabled by the call
282 /// Handle The Event. return true if the interfaceManager catch it and if must not send to the Game Action Manager
283 bool handleEvent (const NLGUI::CEventDescriptor
&eventDesc
);
285 // InGame ContextMenu
286 void launchContextMenuInGame (const std::string
&nameOfCM
);
292 void drawViews (NL3D::UCamera camera
);
294 // display a debug info
295 void displayDebugInfo(const std::string
&str
, TSystemInfoMode mode
= InfoMsg
);
296 // get the color associated with the given system info mode
297 NLMISC::CRGBA
getDebugInfoColor(TSystemInfoMode mode
);
299 // display a system info string
300 void displaySystemInfo(const std::string
&str
, const std::string
&Category
= "SYS");
301 NLMISC::CRGBA
getSystemInfoColor(const std::string
&Category
= "SYS");
305 /** Open a MessageBox. this is a simple ModalWindow with a Ok button
306 * ui:interface:message_box must be defined in xml, with a "text" ViewText son
308 void messageBox(const std::string
&text
, const std::string
&masterGroup
="ui:interface", TCaseMode caseMode
= CaseFirstSentenceLetterUp
);
309 /** Open a MessageBox. this is a simple ModalWindow with a Ok and a HELP button.
310 * The help button with open a browser on ryzom.com faq
311 * ui:interface:message_box_with_help must be defined in xml, with a "text" ViewText son
313 void messageBoxWithHelp(const std::string
&text
, const std::string
&masterGroup
="ui:interface",
314 const std::string
&ahOnOk
= std::string(), const std::string
¶msOnOk
= std::string(),
315 TCaseMode caseMode
= CaseFirstSentenceLetterUp
);
317 /** Open a MessageBox with validation question. this is a simple ModalWindow with a Ok / Cancel button
318 * ui:interface:valid_message_box must be defined in xml, with a "text" ViewText son, and a "ok" button
319 * \param ahOnOk => the action handler to call if ok is pressed. NB: you don't have to call leave_modal in this ah (auto done).
320 * \param paramsOnOk => params passed to ahOnOk.
321 * \param ahOnCancel => the action handler to call if cancel is pressed. NB: you don't have to call leave_modal in this ah (auto done).
322 * \param paramsOnCancel => params passed to ahOnCancel.
324 void validMessageBox(TValidMessageIcon icon
, const std::string
&text
, const std::string
&ahOnOk
, const std::string
¶msOnOk
= std::string(),
325 const std::string
&ahOnCancel
= std::string(), const std::string
¶msOnCancel
= std::string(), const std::string
&masterGroup
="ui:interface");
327 /** Get the current running validMessageBox OnOk action. empty if no validMessageBox currently opened
328 * One can use it to know if it match its system and so if it needs to be closed (with disableModalWindow())
330 bool getCurrentValidMessageBoxOnOk(std::string
&ahOnOk
, const std::string
&masterGroup
="ui:interface");
333 void setMode(uint8 newMode
);
334 uint8
getMode() const { return _CurrentMode
; }
335 void resetMode(uint8 newMode
);
336 // Update image of a single group container in a virtual desktop.
337 // This is faster than switching to a new desktop using 'setMode' to update the changes
338 // \param mode Index of the virtual desktop
339 void updateGroupContainerImage(CGroupContainer
&gc
, uint8 mode
);
340 // Remove a group container from a virtual desktop image
341 // \param mode Index of the virtual desktop
342 void removeGroupContainerImage(const std::string
&groupName
, uint8 mode
);
343 // Remove group container from all virtual desktops
344 void removeGroupContainerImageFromDesktops(const std::string
&groupName
);
349 // debug : dump all the interface windows in the console
350 void dumpUI(bool indent
);
352 // debug : display box of all elements in the interface (plus hotspot)
353 void displayUIViewBBoxs(const std::string
&uiFilter
);
354 void displayUICtrlBBoxs(const std::string
&uiFilter
);
355 void displayUIGroupBBoxs(const std::string
&uiFilter
);
357 // visit all elements of the interface manager
358 void visit(CInterfaceElementVisitor
*visitor
);
360 // Display the only one web window at end of ryzom
361 void displayWebWindow(const std::string
&name
, const std::string
&url
);
363 // Initialize emote from TextEmotListSheet (create command and insert the GCM entry)
368 // For Drag And drop, return true if the "CopyDrag" key is pressed (actually the ctrl key!)
369 bool testDragCopyKey();
371 // Reset the view text index
372 void resetTextIndex();
374 // test if the config has been loaded in initInGame()
375 bool isConfigLoaded() const {return _ConfigLoaded
;}
378 /// Manager for flying text. use it to add
379 CFlyingTextManager FlyingTextManager
;
384 /// For debug: dump in the sysinfo and nlwarning state of lua. detail range from 0 to 2 (clamped).
385 void dumpLuaState(uint detail
);
388 // Get the list of InGame XML Interface files, with any AddOn ones
389 static std::vector
<std::string
> getInGameXMLInterfaceFiles();
391 /// \name Action Counter sync
394 void incLocalSyncActionCounter();
396 uint8
getLocalSyncActionCounter() const {return _LocalSyncActionCounter
;}
397 uint8
getLocalSyncActionCounterMask() const {return _LocalSyncActionCounterMask
;}
399 bool localActionCounterSynchronizedWith(NLMISC::CCDBNodeLeaf
*leaf
)
401 if (!leaf
) return false;
402 uint srvVal
= leaf
->getValue32();
403 uint locVal
= _LocalSyncActionCounter
;
404 srvVal
&= _LocalSyncActionCounterMask
;
405 locVal
&= _LocalSyncActionCounterMask
;
406 return srvVal
== locVal
;
409 void resetShardSpecificData();
414 // Item Carac Test, get the value
415 bool isItemCaracRequirementMet(CHARACTERISTICS::TCharacteristics type
, sint32 value
)
417 // carac requirement?
418 if( type
< CHARACTERISTICS::NUM_CHARACTERISTICS
)
419 return value
<= _CurrentPlayerCharac
[type
];
420 // no carac requirement => ok
426 sint32
getCurrentPlayerCarac(CHARACTERISTICS::TCharacteristics type
)
428 if( type
< CHARACTERISTICS::NUM_CHARACTERISTICS
)
429 return _CurrentPlayerCharac
[type
];
434 void notifyMailAvailable();
435 void notifyForumUpdated();
437 /** Queue up lua script to be run on next frame update
439 void queueLuaScript(const std::string
&script
);
441 /** Return true if 12-hour clock should be used
443 static bool use12hClock();
445 /** Returns a human readable timestamp with the given format.
447 static char* getTimestampHuman(const char* format
= "[%H:%M:%S] ");
449 /** Parses any tokens in the utf-8 string like $t$ or $g()$
451 static bool parseTokens(std::string
& ucstr
);
453 // ------------------------------------------------------------------------------------------------
456 // Observer for copying db branch changes
457 class CServerToLocalAutoCopy
460 CServerToLocalAutoCopy();
461 ~CServerToLocalAutoCopy() { release(); }
464 void init(const std::string
&dbPath
);
465 // unhook from everything we are tangled up in
468 // When something in the SERVER DB changes
469 void onServerChange(NLMISC::ICDBNode
*serverNode
);
470 // When something in the LOCAL DB changes
471 void onLocalChange(NLMISC::ICDBNode
*localNode
);
474 class CLocalDBObserver
: public NLMISC::ICDBNode::IPropertyObserver
477 CServerToLocalAutoCopy
&_Owner
;
478 CLocalDBObserver(CServerToLocalAutoCopy
&owner
) : _Owner(owner
) {}
479 virtual void update(NLMISC::ICDBNode
*node
) {_Owner
.onLocalChange(node
);}
481 class CServerDBObserver
: public NLMISC::ICDBNode::IPropertyObserver
484 CServerToLocalAutoCopy
&_Owner
;
485 CServerDBObserver(CServerToLocalAutoCopy
&owner
) : _Owner(owner
) {}
486 virtual void update(NLMISC::ICDBNode
*node
) {_Owner
.onServerChange(node
);}
489 // A node here is a pair Server<->Local
492 NLMISC::CCDBNodeLeaf
*ServerNode
;
493 NLMISC::CCDBNodeLeaf
*LocalNode
;
494 bool InsertedInUpdateList
;
499 InsertedInUpdateList
= false;
502 // Struct for comparing nodes, by either Local or Server pointer
503 struct CNodeLocalComp
506 bool operator<=(const CNodeLocalComp
&o
) const {return Node
->LocalNode
<= o
.Node
->LocalNode
;}
507 bool operator<(const CNodeLocalComp
&o
) const {return Node
->LocalNode
< o
.Node
->LocalNode
;}
509 struct CNodeServerComp
512 bool operator<=(const CNodeServerComp
&o
) const {return Node
->ServerNode
<= o
.Node
->ServerNode
;}
513 bool operator<(const CNodeServerComp
&o
) const {return Node
->ServerNode
< o
.Node
->ServerNode
;}
518 NLMISC::CCDBNodeLeaf
*_ServerCounter
;
520 CLocalDBObserver _LocalObserver
;
521 CServerDBObserver _ServerObserver
;
525 // Array of Nodes that have to be synchronized
526 std::vector
<CNode
> _Nodes
;
527 // Sorting of Nodes, by Server Node
528 std::vector
<CNodeServerComp
> _ServerNodeMap
;
529 // Sorting of Nodes, by Local Node
530 std::vector
<CNodeLocalComp
> _LocalNodeMap
;
531 // List of nodes to update until next synchonized client-server counter
532 std::vector
<CNode
*> _UpdateList
;
534 void buildRecursLocalLeaves(NLMISC::CCDBNodeBranch
*branch
, std::vector
<NLMISC::CCDBNodeLeaf
*> &leaves
);
537 // Database management stuff
538 class CDBLandmarkObs
: public NLMISC::ICDBNode::IPropertyObserver
541 virtual void update(NLMISC::ICDBNode
*node
);
545 // ----------------------------------------------------------------------------------
546 class CEmoteCmd
: public NLMISC::ICommand
549 CEmoteCmd(const char *cmdName
, const char *cmdHelp
, const char *cmdArgs
)
550 : NLMISC::ICommand("emotes", cmdName
, cmdHelp
, cmdArgs
)
554 bool execute(const std::string
&rawCommandString
, const std::vector
<std::string
> &args
, NLMISC::CLog
&log
, bool quiet
, bool human
=true);
556 uint32 Behaviour
; // State id from list.emot
560 // ------------------------------------------------------------------------------------------------
562 // cache and expose some commonly used db nodes
563 NLMISC::CCDBNodeBranch
*_DBB_UI_DUMMY
;
564 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_QUANTITY
;
565 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_QUALITY
;
566 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_SHEET
;
567 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_NAMEID
;
568 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_ENCHANT
;
569 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_SLOT_TYPE
;
570 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_PHRASE
;
571 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_WORNED
;
572 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_PREREQUISIT_VALID
;
573 NLMISC::CCDBNodeLeaf
*_DB_UI_DUMMY_FACTION_TYPE
;
575 void updateDesktops( uint32 newScreenW
, uint32 newScreenH
);
576 void setInterfaceScale( float scale
) { _InterfaceScaleChanged
= true; _InterfaceScale
= scale
; }
580 NLMISC::CCDBNodeLeaf
*_CheckMailNode
;
581 NLMISC::CCDBNodeLeaf
*_CheckForumNode
;
582 sint64 _UpdateWeatherTime
;
584 // WebIG notify thread is pushing lua code here
585 std::queue
<std::string
> _ScriptQueue
;
586 NLMISC::CMutex _ScriptQueueMutex
;
588 void flushScriptQueue();
592 /** This is the GLOBAL Action counter used to synchronize some systems (including INVENTORY) with the server.
594 uint8 _LocalSyncActionCounter
;
596 /// This is the Mask (4bits)
597 uint8 _LocalSyncActionCounterMask
;
603 ///the singleton's instance
604 static CInterfaceManager
* _Instance
;
606 NLMISC::CCDBNodeLeaf
*_DescTextTarget
;
608 /// Current waiting id and string from server
609 struct SIDStringWaiter
611 STRING_MANAGER::IStringWaiterRemover SWR
;
612 bool IdOrString
; // true == id, false == string
617 std::vector
<SIDStringWaiter
*> _IDStringWaiters
;
619 uint32 _ScreenW
, _ScreenH
; // Change res detection
620 sint32 _LastInGameScreenW
, _LastInGameScreenH
; // Resolution used for last InGame interface
621 float _InterfaceScale
;
622 bool _InterfaceScaleChanged
;
625 std::vector
<CInterfaceConfig::CDesktopImage
> _Modes
;
628 // true when interface manager is running 'ingame' content
631 // Does the interface config file as been loaded ?
635 // Does the keys config file for as been loaded ?
638 // clear all edit box in the ui
639 void clearAllEditBox();
640 // restore all backuped positions for containers
641 void restoreAllContainersBackupPosition();
644 NLMISC::CCDBNodeLeaf
*_NeutralColor
;
645 NLMISC::CCDBNodeLeaf
*_WarningColor
;
646 NLMISC::CCDBNodeLeaf
*_ErrorColor
;
648 CDBLandmarkObs _LandmarkObs
;
652 // str= printable version of value at stack index
653 void getLuaValueInfo(std::string
&str
, sint index
);
654 // display a string in SysInfo and nlinfo
655 void dumpLuaString(const std::string
&str
);
656 // dump printable version of pair key-index in top of stack. if value is a table, recurs (up to recursTableLevel times)
657 void dumpLuaKeyValueInfo(uint recursTableLevel
, uint tabLevel
);
660 bool _EmotesInitialized
;
661 std::vector
<CEmoteCmd
*> _EmoteCmds
;
663 // Item Carac requirement
664 sint32 _CurrentPlayerCharac
[CHARACTERISTICS::NUM_CHARACTERISTICS
];
665 NLMISC::CRefPtr
<NLMISC::CCDBNodeLeaf
> _CurrentPlayerCharacLeaf
[CHARACTERISTICS::NUM_CHARACTERISTICS
];
667 // observers for copying database branch changes
668 CServerToLocalAutoCopy ServerToLocalAutoCopyInventory
;
669 CServerToLocalAutoCopy ServerToLocalAutoCopyExchange
;
670 CServerToLocalAutoCopy ServerToLocalAutoCopyContextMenu
;
671 CServerToLocalAutoCopy ServerToLocalAutoCopySkillPoints
;
672 CServerToLocalAutoCopy ServerToLocalAutoCopyDMGift
;
674 // Pop a new message box. If the message box was found, returns a pointer on it
675 void messageBoxInternal(const std::string
&msgBoxGroup
, const std::string
&text
, const std::string
&masterGroup
, TCaseMode caseMode
);
677 CInterfaceLink::CInterfaceLinkUpdater
*interfaceLinkUpdater
;
680 #endif // NL_INTERFACE_MANAGER_H
682 /* End of interface_manager.h */