1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2010-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 // Copyright (C) 2011 Robert TIMM (rti) <mail@rtti.de>
7 // Copyright (C) 2012 Matt RAYKOWSKI (sfb) <matt.raykowski@gmail.com>
8 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
10 // This program is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Affero General Public License as
12 // published by the Free Software Foundation, either version 3 of the
13 // License, or (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Affero General Public License for more details.
20 // You should have received a copy of the GNU Affero General Public License
21 // along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include "nel/misc/i_xml.h"
31 #include "nel/misc/o_xml.h"
32 #include "nel/misc/algo.h"
34 #include "nel/net/tcp_sock.h"
37 #include "interface_manager.h"
38 #include "interface_config.h"
39 #include "task_bar_manager.h"
40 #include "guild_manager.h"
41 #include "../client_cfg.h"
42 #include "encyclopedia_manager.h"
44 #include "nel/gui/interface_expr.h"
45 #include "register_interface_elements.h"
47 #include "nel/gui/action_handler.h"
48 #include "action_handler_misc.h"
49 #include "interface_observer.h"
50 #include "nel/gui/interface_anim.h"
51 #include "interface_ddx.h"
52 #include "action_handler_help.h"
53 #include "action_handler_item.h"
55 #include "nel/gui/view_bitmap.h"
56 //#include "view_bitmap_progress.h"
57 #include "view_bitmap_faber_mp.h"
58 #include "nel/gui/view_bitmap_combo.h"
59 #include "nel/gui/view_text.h"
60 #include "nel/gui/view_text_id.h"
61 #include "nel/gui/view_text_formated.h"
63 #include "nel/gui/ctrl_scroll.h"
64 #include "nel/gui/ctrl_button.h"
65 #include "nel/gui/ctrl_text_button.h"
67 #include "dbctrl_sheet.h"
69 #include "nel/gui/group_list.h"
70 #include "nel/gui/group_menu.h"
71 #include "nel/gui/group_container.h"
72 #include "nel/gui/group_modal.h"
73 #include "nel/gui/group_editbox.h"
74 #include "group_in_scene_bubble.h"
75 #include "group_skills.h"
76 #include "group_compas.h"
77 #include "nel/gui/group_html.h"
81 #include "bot_chat_manager.h"
82 #include "bot_chat_page_all.h"
83 #include "chat_displayer.h"
84 #include "skill_manager.h"
85 #include "../sound_manager.h"
86 #include "../actions.h"
87 #include "../actions_client.h"
89 #include "../weather_manager_client.h"
90 #include "../weather.h"
92 #include "../user_entity.h"
93 #include "../motion/user_controls.h"
94 #include "people_interraction.h"
95 #include "macrocmd_manager.h"
96 #include "inventory_manager.h"
98 #include "../connection.h" // needed for loading config file (PlayerSelectedFileName)
100 #include "sbrick_manager.h"
101 #include "sphrase_manager.h"
102 #include "bar_manager.h"
104 #include "../continent_manager.h"
105 #include "../entity_cl.h"
106 #include "../login.h"
108 #include "../sheet_manager.h" // for emotes
109 #include "../entity_animation_manager.h" // for emotes
110 #include "../net_manager.h" // for emotes
111 #include "../client_chat_manager.h" // for emotes
112 #include "../entities.h"
114 #include "../../common/src/game_share/ryzom_database_banks.h"
116 #include "chat_text_manager.h"
117 #include "../npc_icon.h"
119 #include "nel/gui/lua_helper.h"
120 using namespace NLGUI
;
121 #include "nel/gui/lua_ihm.h"
122 #include "nel/web/curl_certificates.h"
124 #include "lua_ihm_ryzom.h"
126 #include "add_on_manager.h"
128 #include "game_share/r2_share_itf.h"
130 #include "../time_client.h"
132 #include "../r2/editor.h"
133 #include "../r2/dmc/client_edition_module.h"
135 #include "../bg_downloader_access.h"
137 #include "parser_modules.h"
139 #include "../global.h"
140 #include "user_agent.h"
141 #include "../item_group_manager.h"
143 #include "group_html_webig.h"
145 using namespace NLMISC
;
149 extern void luaDebuggerMainLoop();
152 extern CClientChatManager ChatMngr
;
153 extern CContinentManager ContinentMngr
;
154 extern bool IsInRingSession
;
155 extern CEventsListener EventsListener
;
159 extern bool ReloadUIFlag
;
162 // ***************************************************************************
164 Version 11: - Dyn chat in user tab
165 Version 10: - Last screen resolution serialisation
166 Version 9: UI_DB_SAVE_VERSION system
167 Version 8: - serialInSceneBubbleInfo (for ignore context help)
168 Version 7: - serialMacroMemory
169 Version 6: DEPRECATED - Info about friend/ignore list
170 Version 5: - Info Windows pos
171 Version 4: - User landmark serialisation
172 Version 3: - Added a Hack for CInterfaceConfig version miss
173 Version 2: - TaskBar serialisation
174 Version 1: - people interraction
175 Version 0: - base version
177 #define ICFG_STREAM_VERSION 11
179 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
180 #define FOREACH(__itvar,__conttype,__contvar) \
181 for (__conttype::iterator __itvar(__contvar.begin()),__itvar##end(__contvar.end()); __itvar!=__itvar##end; ++__itvar)
184 // ***************************************************************************
187 using namespace NLMISC
;
188 using namespace NLNET
;
190 // ------------------------------------------------------------------------------------------------
192 extern bool loginFinished
;
193 void setLoginFinished( bool f
);
195 CActionsManager EditActions
;
197 CInterfaceManager
* CInterfaceManager::_Instance
= NULL
;
199 CChatDisplayer
* ChatDisplayer
= NULL
;
203 void uninitActions();
205 ///\todo nico: remove this dummy displayer
213 // Hierarchical timer
214 H_AUTO_DECL ( RZ_Client_Update_Frame_Events
)
216 // ------------------------------------------------------------------------------------------------
217 // AJM TEMP TEMP TEMP TEMP
218 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
220 // track creation of an interface group
221 void CInterfaceManager::DebugTrackGroupsCreated( CInterfaceGroup
*pIG
)
224 _DebugTrackGroupSet
.insert( pIG
);
226 // add to map and increment create counter
227 _DebugTrackGroupMap
[pIG
] = _DebugTrackGroupCreateCount
++;
230 // track destruction of an interface group
231 void CInterfaceManager::DebugTrackGroupsDestroyed( CInterfaceGroup
*pIG
)
233 // lookup id of the group being destroyed (for debugging)
234 int foo
= DebugTrackGroupsGetId( pIG
);
237 setInterfaceGroupPtr::iterator it
= _DebugTrackGroupSet
.find( pIG
);
238 if( it
== _DebugTrackGroupSet
.end() )
240 nldebug( "AJM DEBUG: Interface Group %x Destroyed twice", pIG
);
243 _DebugTrackGroupSet
.erase( pIG
);
245 // remove from map and increment destroy counter
246 _DebugTrackGroupMap
.erase(pIG
);
247 _DebugTrackGroupDestroyCount
++;
250 // display the count of undestroyed interface groups
251 void CInterfaceManager::DebugTrackGroupsDump()
254 nldebug( "AJM DEBUG: %d Interface Groups remaining", _DebugTrackGroupCreateCount
-_DebugTrackGroupDestroyCount
);
256 FOREACH( itIG
, mapInterfaceGroupPtr2Int
, _DebugTrackGroupMap
)
258 nldebug( " %d", itIG
->second
);
262 // return the index for an interface group
263 int CInterfaceManager::DebugTrackGroupsGetId( CInterfaceGroup
*pIG
)
265 mapInterfaceGroupPtr2Int::iterator it
= _DebugTrackGroupMap
.find( pIG
);
266 if( it
!= _DebugTrackGroupMap
.end() )
271 #endif // AJM_DEBUG_TRACK_INTERFACE_GROUPS
273 class CDesktopUpdater
: public CWidgetManager::INewScreenSizeHandler
276 void process( uint32 w
, uint32 h
)
278 CInterfaceManager::getInstance()->updateDesktops( w
, h
);
282 class CDrawDraggedSheet
: public CWidgetManager::IOnWidgetsDrawnHandler
287 if ( CWidgetManager::getInstance()->getPointer()->show())
289 CDBCtrlSheet
*pCS
= dynamic_cast<CDBCtrlSheet
*>( CWidgetManager::getInstance()->getCapturePointerLeft() );
290 if ((pCS
!= NULL
) && (pCS
->isDragged()))
292 sint x
= CWidgetManager::getInstance()->getPointer()->getX() - pCS
->getDeltaDragX();
293 sint y
= CWidgetManager::getInstance()->getPointer()->getY() - pCS
->getDeltaDragY();
294 pCS
->drawSheet (x
, y
, false, false);
296 // if the control support CopyDrag, and if copy key pressed, display a tiny "+"
297 if(pCS
->canDragCopy() && CInterfaceManager::getInstance()->testDragCopyKey())
299 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
300 sint w
= rVR
.getSystemTextureW(CViewRenderer::DragCopyTexture
);
301 sint h
= rVR
.getSystemTextureW(CViewRenderer::DragCopyTexture
);
302 rVR
.draw11RotFlipBitmap (pCS
->getRenderLayer()+1, x
-w
/2, y
-h
/2, 0, false,
303 rVR
.getSystemTextureId(CViewRenderer::DragCopyTexture
));
311 class CStringManagerTextProvider
: public CViewTextID::IViewTextProvider
313 bool getString( uint32 stringId
, string
&result
)
315 return STRING_MANAGER::CStringManagerClient::instance()->getString( stringId
, result
);
318 bool getDynString( uint32 dynStringId
, string
&result
)
320 return STRING_MANAGER::CStringManagerClient::instance()->getDynString( dynStringId
, result
);
324 class CRyzomTextFormatter
: public CViewTextFormated::IViewTextFormatter
327 std::string
formatString( const std::string
&inputString
, const std::string
¶mString
)
329 std::string formatedResult
;
332 for(std::string::const_iterator it
= inputString
.begin(); it
!= inputString
.end();)
337 if (it
== inputString
.end())
339 formatedResult
+= '$';
346 case 't': // add text ID
348 formatedResult
+= paramString
;
352 case 'p': // add player name
354 if (ClientCfg
.Local
|| !UserEntity
)
356 if (*it
== 'P') formatedResult
+= "PLAYER";
357 else formatedResult
+= "Player";
361 std::string name
= UserEntity
->getEntityName();
362 if (*it
== 'P') name
= toUpper(name
);
363 formatedResult
+= name
;
368 case 'b': // add bot name
371 bool womanTitle
= false;
378 CLFECOMMON::TCLEntityId trader
= CLFECOMMON::INVALID_SLOT
;
380 trader
= UserEntity
->trader();
381 if (trader
!= CLFECOMMON::INVALID_SLOT
)
383 CEntityCL
*entity
= EntitiesMngr
.entity(trader
);
386 uint32 nDBid
= entity
->getNameId();
389 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
390 pSMC
->getString(nDBid
, botName
);
394 botName
= entity
->getDisplayName();
396 CCharacterCL
*pChar
= dynamic_cast<CCharacterCL
*>(entity
);
398 womanTitle
= pChar
->getGender() == GSGENDER::female
;
402 // get the title translated
403 string sTitleTranslated
= botName
; // FIXME: UTF-8
404 CStringPostProcessRemoveName spprn
;
405 spprn
.Woman
= womanTitle
;
406 spprn
.cbIDStringReceived(sTitleTranslated
);
408 botName
= CEntityCL::removeTitleAndShardFromName(botName
);
410 // short name (with no title such as 'guard', 'merchant' ...)
413 // But if there is no name, display only the title
415 botName
= sTitleTranslated
;
419 // Else we want the title !
420 if (!botName
.empty())
422 botName
+= sTitleTranslated
;
425 formatedResult
+= botName
;
430 formatedResult
+= '$';
439 formatedResult
+= *it
;
444 return formatedResult
;
450 CStringManagerTextProvider SMTextProvider
;
451 CRyzomTextFormatter RyzomTextFormatter
;
454 CInterfaceManager
* CInterfaceManager::getInstance()
456 if( _Instance
== NULL
)
457 _Instance
= new CInterfaceManager();
461 // ------------------------------------------------------------------------------------------------
462 CInterfaceManager::CInterfaceManager()
464 CWidgetManager::getInstance()->registerNewScreenSizeHandler( new CDesktopUpdater() );
465 CWidgetManager::getInstance()->registerOnWidgetsDrawnHandler( new CDrawDraggedSheet() );
467 CInterfaceParser
*parser
= dynamic_cast< CInterfaceParser
* >( CWidgetManager::getInstance()->getParser() );
469 parser
->setSetupOptionsCallback( this );
470 parser
->addModule( "scene3d", new CIF3DSceneParser() );
471 parser
->addModule( "ddx", new CIFDDXParser() );
472 parser
->addModule( "action_category", new CActionCategoryParser() );
473 parser
->addModule( "command", new CCommandParser() );
474 parser
->addModule( "key", new CKeyParser() );
475 parser
->addModule( "macro", new CMacroParser() );
476 parser
->addModule( "landmarks", new CLandmarkParser() );
477 parser
->setCacheUIParsing( ClientCfg
.CacheUIParsing
);
479 CViewRenderer::setDriver( Driver
);
480 CViewRenderer::setTextContext( TextContext
);
481 CViewRenderer::hwCursorScale
= ClientCfg
.HardwareCursorScale
;
482 CViewRenderer::hwCursors
= &ClientCfg
.HardwareCursors
;
483 CViewRenderer::getInstance();
484 CViewTextID::setTextProvider( &SMTextProvider
);
485 CViewTextFormated::setFormatter( &RyzomTextFormatter
);
487 CGroupHTML::options
.trustedDomains
= ClientCfg
.WebIgTrustedDomains
;
488 CGroupHTML::options
.languageCode
= ClientCfg
.getHtmlLanguageCode();
489 CGroupHTML::options
.appName
= getUserAgentName();
490 CGroupHTML::options
.appVersion
= getUserAgentVersion();
491 CGroupHTML::options
.curlMaxConnections
= ClientCfg
.CurlMaxConnections
;
493 if (!ClientCfg
.CurlCABundle
.empty())
495 // specify custom CA certs, lookup will be made in this function
496 NLWEB::CCurlCertificates::addCertificateFile(ClientCfg
.CurlCABundle
);
499 NLGUI::CDBManager::getInstance()->resizeBanks( NB_CDB_BANKS
);
500 interfaceLinkUpdater
= new CInterfaceLink::CInterfaceLinkUpdater();
501 _ScreenW
= _ScreenH
= 0;
502 _LastInGameScreenW
= _LastInGameScreenH
= 0;
503 _InterfaceScaleChanged
= false;
504 _InterfaceScale
= 1.0f
;
505 _DescTextTarget
= NULL
;
506 _ConfigLoaded
= false;
509 CWidgetManager::getInstance()->resetColorProps();
510 CWidgetManager::getInstance()->resetAlphaRolloverSpeedProps();
511 CWidgetManager::getInstance()->resetGlobalAlphasProps();
512 _NeutralColor
= NULL
;
513 _WarningColor
= NULL
;
515 _EmotesInitialized
= false;
518 // Global initialization
519 // *********************
521 // Interface Manager init
522 CViewRenderer::getInstance()->checkNewScreenSize();
525 CViewRenderer::getInstance()->getScreenSize(w
, h
);
526 CWidgetManager::getInstance()->setScreenWH(w
, h
);
528 CViewRenderer::getInstance()->init();
531 _Modes
.resize(MAX_NUM_MODES
);
535 _LocalSyncActionCounter
= 0;
537 _LocalSyncActionCounterMask
= 15;
539 for(uint i
=0;i
<CHARACTERISTICS::NUM_CHARACTERISTICS
;i
++)
541 _CurrentPlayerCharac
[i
]= 0;
544 _CheckMailNode
= NULL
;
545 _CheckForumNode
= NULL
;
546 _UpdateWeatherTime
= 0;
548 _DBB_UI_DUMMY
= NULL
;
549 _DB_UI_DUMMY_QUANTITY
= NULL
;
550 _DB_UI_DUMMY_QUALITY
= NULL
;
551 _DB_UI_DUMMY_SHEET
= NULL
;
552 _DB_UI_DUMMY_NAMEID
= NULL
;
553 _DB_UI_DUMMY_ENCHANT
= NULL
;
554 _DB_UI_DUMMY_SLOT_TYPE
= NULL
;
555 _DB_UI_DUMMY_PHRASE
= NULL
;
556 _DB_UI_DUMMY_WORNED
= NULL
;
557 _DB_UI_DUMMY_PREREQUISIT_VALID
= NULL
;
558 _DB_UI_DUMMY_FACTION_TYPE
= NULL
;
560 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
561 _DebugTrackGroupSet
.clear();
562 _DebugTrackGroupMap
.clear();
563 _DebugTrackGroupCreateCount
= 0;
564 _DebugTrackGroupDestroyCount
= 0;
565 #endif // AJM_DEBUG_TRACK_INTERFACE_GROUPS
569 // ------------------------------------------------------------------------------------------------
570 CInterfaceManager::~CInterfaceManager()
572 CViewTextID::setTextProvider( NULL
);
573 CViewTextFormated::setFormatter( NULL
);
574 reset(); // to flush IDStringWaiters
576 // release the database observers
577 releaseServerToLocalAutoCopyObservers();
580 removeFlushObserver( interfaceLinkUpdater );
581 delete interfaceLinkUpdater;
582 interfaceLinkUpdater = NULL;
587 // ------------------------------------------------------------------------------------------------
588 void CInterfaceManager::reset()
590 CViewRenderer::getInstance()->reset();
591 CWidgetManager::getInstance()->reset();
593 for (uint32 i
= 0; i
< _IDStringWaiters
.size(); ++i
)
594 delete _IDStringWaiters
[i
];
595 _IDStringWaiters
.clear();
596 CGroupFrame::resetDisplayTypes();
598 _NeutralColor
= NULL
;
599 _WarningColor
= NULL
;
604 // ------------------------------------------------------------------------------------------------
605 // unhook from observers we are tangled up in
606 void CInterfaceManager::releaseServerToLocalAutoCopyObservers()
608 ServerToLocalAutoCopyInventory
.release();
609 ServerToLocalAutoCopyExchange
.release();
610 ServerToLocalAutoCopyContextMenu
.release();
611 ServerToLocalAutoCopySkillPoints
.release();
614 void CInterfaceManager::setInGame( bool i
)
617 CWidgetManager::getInstance()->setIngame( i
);
620 // ------------------------------------------------------------------------------------------------
621 void CInterfaceManager::resetShardSpecificData()
623 _LocalSyncActionCounter
= 0;
624 CGroupSkills::InhibitSkillUpFX
= true;
625 CBarManager::getInstance()->resetShardSpecificData();
626 CBotChatManager::getInstance()->setCurrPage(NULL
);
628 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
629 pPM
->setEquipInvalidation(0, 0);
631 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(CWidgetManager::getInstance()->getElementFromId(WIN_TEMPINV
));
633 pGC
->setActive(false);
636 // ------------------------------------------------------------------------------------------------
638 // ------------------------------------------------------------------------------------------------
639 void CInterfaceManager::destroy ()
645 void CInterfaceManager::initLUA()
647 CInterfaceParser
*parser
= dynamic_cast< CInterfaceParser
* >( CWidgetManager::getInstance()->getParser() );
648 if( parser
->isLuaInitialized() )
653 if( !parser
->isLuaInitialized() )
656 CLuaIHMRyzom::RegisterRyzomFunctions( *( CLuaManager::getInstance().getLuaState() ) );
659 // ------------------------------------------------------------------------------------------------
660 void CInterfaceManager::initLogin()
662 // Init LUA Scripting
665 // Clear the action manager
669 // Register action in the action manager
670 ActionsContext
.addActionsManager(&Actions
, "");
671 ActionsContext
.addActionsManager(&EditActions
, RZ_CATEGORY_EDIT
);
674 if (ClientCfg
.XMLLoginInterfaceFiles
.empty())
676 nlinfo("no xml login config files in client.cfg");
680 nldebug("Textures Login Interface");
682 for (vector
<string
>::iterator it
= ClientCfg
.TexturesLoginInterface
.begin(), end
= ClientCfg
.TexturesLoginInterface
.end(); it
!= end
; ++it
)
684 nldebug("Textures Login Interface: %s", (*it
).c_str());
685 loadTextures(*it
+ ".tga", *it
+ ".txt", false);
688 for (vector
<string
>::iterator it
= ClientCfg
.TexturesLoginInterfaceDXTC
.begin(), end
= ClientCfg
.TexturesLoginInterfaceDXTC
.end(); it
!= end
; ++it
)
690 nldebug("Textures Login Interface DXTC: %s", (*it
).c_str());
691 loadTextures(*it
+ ".tga", *it
+ ".txt", true);
694 parseInterface (ClientCfg
.XMLLoginInterfaceFiles
, false);
696 CWidgetManager::getInstance()->updateAllLocalisedElements();
698 CWidgetManager::getInstance()->activateMasterGroup ("ui:login", true);
705 // ------------------------------------------------------------------------------------------------
706 void CInterfaceManager::uninitLogin()
708 CInterfaceParser
*parser
= dynamic_cast< CInterfaceParser
* >( CWidgetManager::getInstance()->getParser() );
710 CWidgetManager::getInstance()->activateMasterGroup ("ui:login", false);
715 CWidgetManager::getInstance()->setPointer( NULL
);
717 CInterfaceLink::removeAllLinks();
719 ICDBNode::CTextId
textId("UI");
720 NLGUI::CDBManager::getInstance()->getDB()->removeNode(textId
);
726 // Close LUA Scripting
730 // ------------------------------------------------------------------------------------------------
731 void CInterfaceManager::initOutGame()
733 // Clear the action manager
737 // Register action in the action manager
738 ActionsContext
.addActionsManager(&Actions
, "");
739 ActionsContext
.addActionsManager(&EditActions
, RZ_CATEGORY_EDIT
);
741 // Init LUA Scripting
744 if (ClientCfg
.SelectCharacter
!= -1)
748 if (SoundMngr
!= NULL
)
750 NLSOUND::UAudioMixer
*pMixer
= SoundMngr
->getMixer();
751 pMixer
->loadSampleBank(false, "ui_outgame");
752 CVector
initpos ( 0.0f
, 0.0f
, 0.0f
);
753 pMixer
->setListenerPos(initpos
);
758 //NLMEMORY::CheckHeap (true);
760 if (ClientCfg
.XMLOutGameInterfaceFiles
.empty())
762 nlinfo("no xml outgame config files in client.cfg");
766 nldebug("Textures OutGame Interface");
768 for (vector
<string
>::iterator it
= ClientCfg
.TexturesOutGameInterface
.begin(), end
= ClientCfg
.TexturesOutGameInterface
.end(); it
!= end
; ++it
)
770 nldebug("Textures OutGame Interface: %s", (*it
).c_str());
771 loadTextures(*it
+ ".tga", *it
+ ".txt", false);
774 for (vector
<string
>::iterator it
= ClientCfg
.TexturesOutGameInterfaceDXTC
.begin(), end
= ClientCfg
.TexturesOutGameInterfaceDXTC
.end(); it
!= end
; ++it
)
776 nldebug("Textures OutGame Interface DXTC: %s", (*it
).c_str());
777 loadTextures(*it
+ ".tga", *it
+ ".txt", true);
780 parseInterface (ClientCfg
.XMLOutGameInterfaceFiles
, false);
782 CWidgetManager::getInstance()->updateAllLocalisedElements();
784 CWidgetManager::getInstance()->activateMasterGroup ("ui:outgame", true);
786 // if (!ClientCfg.FSHost.empty())
788 // // Hide the Launch Editor button, it works only with a Shard Unifier and web pages
789 // CInterfaceElement *elt = getElementFromId("ui:outgame:edit_session_but");
790 // elt->setActive(false);
793 // Init the action manager
798 //NLMEMORY::CheckHeap (true);
800 // Initialize the web browser
802 CGroupHTML
*pGH
= dynamic_cast<CGroupHTML
*>( CWidgetManager::getInstance()->getElementFromId(GROUP_BROWSER
));
806 pGH
->setActive(true);
807 pGH
->browse(ClientCfg
.PatchletUrl
.c_str());
812 // ------------------------------------------------------------------------------------------------
813 void CInterfaceManager::uninitOutGame()
816 if (ClientCfg
.SelectCharacter
!= -1)
819 CWidgetManager::getInstance()->disableModalWindow();
821 //_Database->display("");
822 CBotChatManager::getInstance()->setCurrPage(NULL
);
824 CInterfaceItemEdition::getInstance()->setCurrWindow(NULL
);
826 // NLMISC::TTime initStart;
827 // initStart = ryzomGetLocalTime ();
828 if (SoundMngr
!= NULL
)
830 NLSOUND::UAudioMixer
*pMixer
= SoundMngr
->getMixer();
831 pMixer
->unloadSampleBank("ui_outgame");
833 //nlinfo ("%d seconds for uninitOutGame", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
835 // initStart = ryzomGetLocalTime ();
836 CWidgetManager::getInstance()->activateMasterGroup ("ui:outgame", false);
838 CInterfaceParser
*parser
= dynamic_cast< CInterfaceParser
* >( CWidgetManager::getInstance()->getParser() );
839 //nlinfo ("%d seconds for activateMasterGroup", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
840 // initStart = ryzomGetLocalTime ();
842 //nlinfo ("%d seconds for removeAll", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
843 // initStart = ryzomGetLocalTime ();
845 //nlinfo ("%d seconds for reset", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
846 // reset the mouse pointer to avoid invalid pointer access
847 CWidgetManager::getInstance()->setPointer( NULL
);
848 // initStart = ryzomGetLocalTime ();
849 CInterfaceLink::removeAllLinks();
850 //nlinfo ("%d seconds for removeAllLinks", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
851 // initStart = ryzomGetLocalTime ();
852 ICDBNode::CTextId
textId("UI");
853 NLGUI::CDBManager::getInstance()->getDB()->removeNode(textId
);
854 //nlinfo ("%d seconds for removeNode", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
856 // Init the action manager
859 // initStart = ryzomGetLocalTime ();
861 // nlinfo ("%d seconds for uninitActions", (uint32)(ryzomGetLocalTime ()-initStart)/1000);
864 // Close LUA Scripting
867 //NLMEMORY::CheckHeap (true);
871 void badXMLParseMessageBox()
873 NL3D::UDriver
*driver
= CViewRenderer::getInstance()->getDriver();
874 NL3D::UDriver::TMessageBoxId ret
= driver
->systemMessageBox( "Interface XML reading failed!\n"
875 "Some XML files are corrupted and may have been removed.\n"
876 "Ryzom may need to be restarted to run properly.\n"
877 "Would you like to quit now?",
878 "XML reading failed!",
879 NL3D::UDriver::yesNoType
,
880 NL3D::UDriver::exclamationIcon
);
881 if (ret
== NL3D::UDriver::yesId
)
883 extern void quitCrashReport ();
889 // ------------------------------------------------------------------------------------------------
890 void CInterfaceManager::initInGame()
892 setLoginFinished( true );
895 // Whole initInGame profile
896 NLMISC::TTime initStart
;
897 initStart
= ryzomGetLocalTime ();
899 // Init LUA Scripting
902 // Clear the action manager
906 // Register action in the action manager
907 ActionsContext
.addActionsManager(&Actions
, "");
908 ActionsContext
.addActionsManager(&EditActions
, RZ_CATEGORY_EDIT
);
911 if (SoundMngr
!= NULL
)
913 NLSOUND::UAudioMixer
*pMixer
= SoundMngr
->getMixer();
914 pMixer
->loadSampleBank(false, "ui_ingame");
918 // NLMEMORY::CheckHeap (true);
920 if (ClientCfg
.XMLInterfaceFiles
.empty())
922 nlinfo("no xml config files in client.cfg");
927 loadIngameInterfaceTextures();
929 // NLMEMORY::CheckHeap (true);
931 // Skill Manager Init
932 CSkillManager
*pSM
= CSkillManager::getInstance();
935 // SBrick Manager Init
936 CSBrickManager
*pSBM
= CSBrickManager::getInstance();
940 // SPhrase Manager DB Init (BEFORE loading). Must be init AFTER skill and brick init
941 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
948 // Initialize armour color (config.xml)
949 CDBCtrlSheet::initArmourColors();
951 // Initialize inventory manager : link to DB and to interface element so must be here
952 getInventory().init();
953 // Same for temp inventory manager
954 CTempInvManager::getInstance();
955 // Initialize guild manager
956 CGuildManager::getInstance();
958 // NLMEMORY::CheckHeap (true);
961 ChatDisplayer
= new CChatDisplayer
;
962 g_log
.addDisplayer (ChatDisplayer
);
963 NLMISC::ErrorLog
->addDisplayer (ChatDisplayer
);
964 NLMISC::WarningLog
->addDisplayer (ChatDisplayer
);
965 NLMISC::InfoLog
->addDisplayer (ChatDisplayer
);
966 NLMISC::DebugLog
->addDisplayer (ChatDisplayer
);
967 NLMISC::AssertLog
->addDisplayer (ChatDisplayer
);
969 // load bot chat datas
973 nlassert (BotChatPageAll
== NULL
);
974 BotChatPageAll
= new CBotChatPageAll
;
975 BotChatPageAll
->init();
977 // NLMEMORY::CheckHeap (true);
979 // init the list of people
980 PeopleInterraction
.init();
982 // flush system msg buffer
983 for( uint i
=0; i
<PeopleInterraction
.SystemMessageBuffer
.size(); ++i
)
985 displaySystemInfo(PeopleInterraction
.SystemMessageBuffer
[i
].Str
, PeopleInterraction
.SystemMessageBuffer
[i
].Cat
);
987 PeopleInterraction
.SystemMessageBuffer
.clear();
989 // Init macro manager
990 CMacroCmdManager::getInstance()->initInGame();
995 CWidgetManager::getInstance()->updateAllLocalisedElements(); // To init all things
999 loadInterfaceConfig();
1001 //Load user landmarks
1004 // Must do extra init for people interaction after load
1005 PeopleInterraction
.initAfterLoad();
1007 //CBotChatUI::refreshActiveWindows(); // bot chat windows are saved too..
1009 CWidgetManager::getInstance()->activateMasterGroup ("ui:interface", true);
1011 // Update the time in the ui database
1012 _CheckMailNode
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MAIL_WAITING");
1013 _CheckForumNode
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:FORUM_UPDATED");
1015 // Init the action manager
1022 // Init bubble manager
1023 InSceneBubbleManager
.init();
1025 // Init Memory Bar for phraseManager. DB and ctrl gray state
1026 pPM
->updateMemoryBar();
1029 _EmotesInitialized
= false;
1032 // init chat manager
1033 ChatMngr
.initInGame();
1035 // Init FlyingText manager
1036 FlyingTextManager
.initInGame();
1038 // Init Bar Manager (HP, SAP etc... Bars)
1039 CBarManager::getInstance()->initInGame();
1041 // Init interface props linked to client time
1044 // Whole initInGame profile
1045 nlinfo ("%d seconds for initInGame", (uint32
)(ryzomGetLocalTime ()-initStart
)/1000);
1047 // reset the compass target
1048 CGroupCompas
*gc
= dynamic_cast<CGroupCompas
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:compass"));
1049 if (gc
&& gc
->isSavedTargetValid())
1051 gc
->setTarget(gc
->getSavedTarget());
1054 // rebuild mp3 player playlist if user reselected a char (songs are already scanned)
1055 CAHManager::getInstance()->runActionHandler("music_player", NULL
, "update_playlist");
1056 CAHManager::getInstance()->runActionHandler("music_player", NULL
, "stop");
1058 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:CHATLOG_STATE", false);
1061 _LogState
= (node
->getValue32() != 0);
1066 displaySystemInfo(CI18N::get("uiLogTurnedOn"));
1070 displaySystemInfo(CI18N::get("uiLogTurnedOff"));
1073 startWebIgNotificationThread();
1076 // ------------------------------------------------------------------------------------------------
1077 void CInterfaceManager::loadIngameInterfaceTextures()
1079 nldebug("Textures Ingame Interface");
1081 for (vector
<string
>::iterator it
= ClientCfg
.TexturesInterface
.begin(), end
= ClientCfg
.TexturesInterface
.end(); it
!= end
; ++it
)
1083 nldebug("Textures Ingame Interface: %s", (*it
).c_str());
1084 loadTextures(*it
+ ".tga", *it
+ ".txt", false);
1087 for (vector
<string
>::iterator it
= ClientCfg
.TexturesInterfaceDXTC
.begin(), end
= ClientCfg
.TexturesInterfaceDXTC
.end(); it
!= end
; ++it
)
1089 nldebug("Textures Ingame Interface DXTC: %s", (*it
).c_str());
1090 loadTextures(*it
+ ".tga", *it
+ ".txt", true);
1094 // ------------------------------------------------------------------------------------------------
1095 void CInterfaceManager::loadUI()
1097 // Copy the array of file to load
1098 vector
<string
> xmlFilesToParse
= getInGameXMLInterfaceFiles();
1100 if (!parseInterface (xmlFilesToParse
, false))
1102 badXMLParseMessageBox();
1105 configureQuitDialogBox();
1108 // ------------------------------------------------------------------------------------------------
1109 void CInterfaceManager::configureQuitDialogBox()
1111 // Configure the quit dialog box according to the server
1112 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
1113 string quitDialogMainStr
= "ui:interface:quit_dialog";
1114 string quitDialogStr
= quitDialogMainStr
+ ":indent_middle";
1115 CInterfaceGroup
*quitDlg
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(quitDialogStr
));
1118 CInterfaceElement
*eltRet
, *eltQuit
, *eltQuitNow
;
1119 eltRet
= quitDlg
->getElement(quitDialogStr
+":return_mainland");
1120 eltQuit
= quitDlg
->getElement(quitDialogStr
+":ryzom");
1121 eltQuitNow
= quitDlg
->getElement(quitDialogStr
+":ryzom_now");
1123 fromString( CWidgetManager::getInstance()->getParser()->getDefine("quit_button_delta_y"), buttonDeltaY
);
1124 extern R2::TUserRole UserRoleInSession
;
1126 bool sessionOwner
= (R2::getEditor().getMode() != R2::CEditor::NotInitialized
&& R2::getEditor().getDMC().getEditionModule().isSessionOwner());
1128 // Show Launch Editor if not in editor mode
1129 CInterfaceElement
*eltCancel
= quitDlg
->getElement(quitDialogStr
+":cancel");
1130 CInterfaceElement
*eltEdit
= quitDlg
->getElement(quitDialogStr
+":launch_editor");
1133 if (UserRoleInSession
!= R2::TUserRole::ur_editor
&& !sessionOwner
)
1135 eltEdit
->setY(buttonDeltaY
);
1136 eltEdit
->setActive(true);
1139 (safe_cast
<CCtrlTextButton
*>(eltCancel
))->setText(CI18N::get("uittQuitCancel"));
1143 eltEdit
->setY(0); // prevent from displaying a gap between two shown buttons
1144 eltEdit
->setActive(false);
1147 (safe_cast
<CCtrlTextButton
*>(eltCancel
))->setText(sessionOwner
? CI18N::get("uittQuitCancel") : CI18N::get("uittQuitCancelEditor"));
1152 if (IsInRingSession
|| (ClientCfg
.Local
&& ClientCfg
.R2EDEnabled
))
1154 // display "return to mainland", unless we are the scenario owner (player or 'aventure master')
1157 if (!sessionOwner
|| R2::getEditor().getMode()==R2::CEditor::EditionMode
)
1159 //eltRet->setY(buttonDeltaY);
1160 const char *textLabel
= (UserRoleInSession
== R2::TUserRole::ur_editor
) ? "uittLeaveEditor" : "uittReturnToMainland";
1161 (safe_cast
<CCtrlTextButton
*>(eltRet
))->setText(CI18N::get(textLabel
));
1162 eltRet
->setY(buttonDeltaY
);
1163 eltRet
->setActive(true); // show Return to Mainland / PLAY
1168 // when an owner of the session, there's an additionnal 'stop' button
1169 eltRet
->setActive(false);
1175 eltQuit
->setActive(false);
1179 eltQuitNow
->setY(buttonDeltaY
);
1180 eltQuitNow
->setActive(true); // show Quit (Now)
1187 eltRet
->setY(0); // prevent from displaying a gap between two shown buttons
1188 eltRet
->setActive(false);
1192 eltQuit
->setY(buttonDeltaY
);
1193 eltQuit
->setActive(true); // show Quit (with progress bar)
1197 eltQuitNow
->setY(0);
1198 eltQuitNow
->setActive(false);
1203 // Make all controls have the same size
1204 CInterfaceGroup
*quitDlgMain
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(quitDialogMainStr
));
1208 quitDlgMain
->invalidateCoords();
1209 for (uint k
= 0; k
< 3; ++k
)
1211 quitDlgMain
->updateCoords(); // calculate the width of the text buttons
1214 const std::vector
<CCtrlBase
*>& controls
= quitDlg
->getControls();
1215 sint32 biggestWidth
= 0;
1216 for ( std::vector
<CCtrlBase
*>::const_iterator ic
=controls
.begin(); ic
!=controls
.end(); ++ic
)
1218 CCtrlTextButton
*ctb
= dynamic_cast<CCtrlTextButton
*>(*ic
);
1222 if ( ctb
->getW() > biggestWidth
)
1223 biggestWidth
= ctb
->getW();
1225 for ( std::vector
<CCtrlBase
*>::const_iterator ic
=controls
.begin(); ic
!=controls
.end(); ++ic
)
1227 CCtrlTextButton
*ctb
= dynamic_cast<CCtrlTextButton
*>(*ic
);
1231 ctb
->setWMin( biggestWidth
);
1237 quitDlgMain
->invalidateCoords();
1238 for (uint k
= 0; k
< 3; ++k
)
1240 quitDlgMain
->updateCoords(); // calculate the width of the text buttons
1245 // ------------------------------------------------------------------------------------------------
1247 std::string
CInterfaceManager::getSaveFileName(const std::string
&module
, const std::string
&ext
, bool useShared
) const
1249 string filename
= "save/" + module
+ "_" + PlayerSelectedFileName
+ "." + ext
;
1250 if (useShared
&& !CFile::fileExists(filename
))
1252 string sharedFile
= "save/shared_" + module
+ "." + ext
;
1253 if (CFile::fileExists(sharedFile
))
1261 // ------------------------------------------------------------------------------------------------
1262 void CInterfaceManager::loadKeys()
1264 if (ClientCfg
.R2EDEnabled
) // in R2ED mode the CEditor class deals with it
1267 CMacroCmdManager::getInstance()->removeAllMacros();
1269 vector
<string
> xmlFilesToParse
;
1271 // Does the keys file exist ?
1272 string userKeyFileName
= getSaveFileName("keys", "xml");
1273 if (CFile::fileExists(userKeyFileName
) && CFile::getFileSize(userKeyFileName
) > 0)
1275 // Load the user key file
1276 xmlFilesToParse
.push_back (userKeyFileName
);
1279 // Load the default key (but don't replace existings bounds, see keys.xml "key_def_no_replace")
1280 xmlFilesToParse
.push_back ("keys.xml");
1282 if (!parseInterface (xmlFilesToParse
, true))
1284 createFileBackup("Error loading keys", userKeyFileName
);
1290 // ------------------------------------------------------------------------------------------------
1291 void CInterfaceManager::loadInterfaceConfig()
1293 // Load interface.cfg
1294 if (ClientCfg
.R2EDEnabled
) // in R2ED mode the CEditor class deals with it
1297 string filename
= getSaveFileName("interface", "icfg");
1298 loadConfig(filename
); // Invalidate coords of changed groups
1300 _ConfigLoaded
= true;
1303 // ------------------------------------------------------------------------------------------------
1304 void CInterfaceManager::uninitInGame0 ()
1306 // Autosave of the keys
1311 _KeysLoaded
= false;
1314 // Autosave of the interface in interface.cfg
1319 _ConfigLoaded
= false;
1324 // ------------------------------------------------------------------------------------------------
1325 void CInterfaceManager::uninitInGame1 ()
1327 stopWebIgNotificationThread();
1329 // release Bar Manager (HP, SAP etc... Bars)
1330 CBarManager::getInstance()->releaseInGame();
1332 // release FlyingTextManager
1333 FlyingTextManager
.releaseInGame();
1335 // release chat manager
1336 ChatMngr
.releaseInGame();
1338 // Reset the chat text manager
1339 CChatTextManager::getInstance().reset();
1344 // release bubble manager
1345 InSceneBubbleManager
.release();
1347 // kill chat displayer
1350 DebugLog
->removeDisplayer (ChatDisplayer
);
1351 InfoLog
->removeDisplayer (ChatDisplayer
);
1352 WarningLog
->removeDisplayer (ChatDisplayer
);
1353 ErrorLog
->removeDisplayer (ChatDisplayer
);
1354 AssertLog
->removeDisplayer (ChatDisplayer
);
1355 g_log
.removeDisplayer(ChatDisplayer
);
1356 delete ChatDisplayer
;
1357 ChatDisplayer
= NULL
;
1360 // Release inventory manager
1361 CInventoryManager::releaseInstance();
1362 // Same for temp inventory manager
1363 CTempInvManager::releaseInstance();
1364 // Release guild manager
1365 CGuildManager::release();
1367 // release bot chat and manager
1368 CBotChatManager::getInstance()->setCurrPage(NULL
);
1369 delete BotChatPageAll
;
1370 BotChatPageAll
= NULL
;
1371 CBotChatManager::releaseInstance();
1373 //release CInterfaceItemEdition
1374 CInterfaceItemEdition::getInstance()->setCurrWindow(NULL
);
1375 CInterfaceItemEdition::releaseInstance();
1377 // release task bar manager
1378 CTaskBarManager::releaseInstance();
1380 // People inetrraction release
1381 PeopleInterraction
.release();
1383 if (SoundMngr
!= NULL
)
1385 NLSOUND::UAudioMixer
*pMixer
= SoundMngr
->getMixer();
1386 pMixer
->unloadSampleBank("ui_ingame");
1389 // disable the game_quitting modal window
1390 CWidgetManager::getInstance()->disableModalWindow();
1392 // Remove all interface objects (containers, groups, variables, defines, ...)
1393 CWidgetManager::getInstance()->activateMasterGroup ("ui:interface", false);
1395 CInterfaceParser
*parser
= dynamic_cast< CInterfaceParser
* >( CWidgetManager::getInstance()->getParser() );
1397 parser
->removeAll();
1399 CInterfaceLink::removeAllLinks();
1401 CWidgetManager::getInstance()->setPointer( NULL
);
1403 // Release DDX manager, before DB remove
1404 CDDXManager::getInstance()->release();
1406 // Release client time, before DB remove
1407 releaseClientTime();
1410 ICDBNode::CTextId
textId("UI");
1411 NLGUI::CDBManager::getInstance()->getDB()->removeNode(textId
);
1413 // Uninit the action manager
1419 // uninit phrase mgr
1420 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1422 CSPhraseManager::releaseInstance(); // must release before BrickManager, SkillManager
1424 // uninit brick manager
1425 // Don't release the instance because must not lost brick map and data
1426 CSBrickManager::getInstance()->uninitInGame();
1428 // Uninit skill manager (after phrase mgr)
1429 // AJM don't release SkillManager, else impulse msg update guild title will crash :(
1430 CSkillManager::getInstance()->uninitTitles();
1432 // Uninit macro manager
1433 CMacroCmdManager::getInstance()->uninitInGame();
1435 // Release interface help
1436 CInterfaceHelp::release();
1438 // Release guild manager
1439 CGuildManager::release();
1441 // Close LUA Scripting
1442 parser
->uninitLUA();
1445 _NeutralColor
= NULL
;
1446 _WarningColor
= NULL
;
1448 CWidgetManager::getInstance()->resetColorProps();
1449 CWidgetManager::getInstance()->resetAlphaRolloverSpeedProps();
1450 CWidgetManager::getInstance()->resetGlobalAlphasProps();
1452 #ifdef AJM_DEBUG_TRACK_INTERFACE_GROUPS
1453 CInterfaceManager::getInstance()->DebugTrackGroupsDump();
1455 // NLMEMORY::ReportMemoryLeak();
1461 // ------------------------------------------------------------------------------------------------
1462 void CInterfaceManager::flushDebugWindow()
1464 if (ChatDisplayer
!= NULL
)
1465 ChatDisplayer
->update();
1468 // ------------------------------------------------------------------------------------------------
1469 // Make sure 0.166 is displayed as 16% and 0.167 as 17%
1470 // because they belong to different weather conditions
1471 static float roundWeatherValue(float weatherValue
)
1473 // Number of possible weather setups in server
1474 const static uint NB_WEATHER_SETUPS
= 6;
1475 float floorValue
= floorf(weatherValue
* 100.f
) / 100.f
;
1476 uint weatherIndex
= min((uint
)(weatherValue
* NB_WEATHER_SETUPS
), NB_WEATHER_SETUPS
- 1);
1477 uint floorIndex
= min((uint
)(floorValue
* NB_WEATHER_SETUPS
), NB_WEATHER_SETUPS
- 1);
1479 if (weatherIndex
> floorIndex
)
1480 return ceilf(weatherValue
* 100.f
) / 100.f
;
1482 return weatherValue
;
1485 // ------------------------------------------------------------------------------------------------
1486 void CInterfaceManager::updateFrameEvents()
1489 H_AUTO_USE ( RZ_Client_Update_Frame_Events
)
1491 // lua scripts from different thread
1496 // Handle anims done in 2 times because some AH can add or remove anims
1497 // First ensure we are working on a safe vector and update all anims
1498 CWidgetManager::getInstance()->updateAnims();
1500 IngameDbMngr
.flushObserverCalls();
1501 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1503 CWidgetManager::getInstance()->removeFinishedAnims();
1506 IngameDbMngr
.flushObserverCalls();
1507 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1509 // Handle waiting texts from server
1510 processServerIDString();
1514 // Execute current macro
1515 CMacroCmdManager::getInstance()->updateMacroExecution();
1517 // Update guild handling (check if we have to rebuild)
1518 CGuildManager::getInstance()->update();
1520 // Update contact list with incoming server string ids
1521 PeopleInterraction
.updateWaitingContacts();
1523 // Update string if some waiting
1524 CEncyclopediaManager::getInstance()->updateAllFrame();
1526 // Setup the weather setup in the player's map every 3 sec (1 ingame minute)
1527 if ((T0
- _UpdateWeatherTime
) > (1 * 3 * 1000))
1529 _UpdateWeatherTime
= T0
;
1530 string str
= CI18N::get ("uiTheSeasonIs") +
1531 CI18N::get ("uiSeason"+toStringEnum(computeCurrSeason())) +
1532 CI18N::get ("uiAndTheWeatherIs") +
1533 CI18N::get (WeatherManager
.getCurrWeatherState().LocalizedName
) +
1534 toString(", %d", (uint
)(roundWeatherValue(WeatherManager
.getWeatherValue()) * 100.f
)) + "% " +CI18N::get("uiHumidity");
1538 CViewText
*pVT
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:weather"));
1542 CCtrlBase
*pTooltip
= dynamic_cast<CCtrlBase
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:weather_tt"));
1543 if (pTooltip
!= NULL
)
1545 string tt
= toString("%02d", WeatherManager
.getNextWeatherHour()) + CI18N::get("uiMissionTimerHour") +
1546 " - " + CI18N::get("uiHumidity") + " " +
1547 toString("%d", (uint
)(roundWeatherValue(WeatherManager
.getNextWeatherValue()) * 100.f
)) + "%";
1548 pTooltip
->setDefaultContextHelp(tt
);
1551 // The date feature is temporarily disabled
1555 //str = CI18N::get("uiDate");
1556 //str += toString("%04d", RT.getRyzomYear()) + "/";
1557 //str += toString("%01d", RT.getRyzomCycle()+1) + " : ";
1558 //str += toString("%02d", RT.getRyzomMonthInCurrentCycle()+1) + "/";
1559 //str += toString("%02d", RT.getRyzomDayOfMonth()+1) + " - "; // Start at 1 for January
1560 //str += toString("%02d", (sint)RT.getRyzomTime()) + " " + CI18N::get("uiMissionTimerHour");
1563 // str = CI18N::get("uiDate");
1564 uint minutes
= ((RT
.getRyzomTime() - (sint
)RT
.getRyzomTime()) * (float) RYZOM_HOUR_IN_MINUTES
);
1565 str
+= toString("%02d:%02d", (sint
)RT
.getRyzomTime(), minutes
) + " - ";
1566 str
+= CI18N::get("ui"+WEEKDAY::toString( (WEEKDAY::EWeekDay
)RT
.getRyzomDayOfWeek() )) + ", ";
1567 str
+= CI18N::get("ui"+MONTH::toString( (MONTH::EMonth
)RT
.getRyzomMonthInCurrentCycle() )) + " ";
1568 str
+= toString("%02d", RT
.getRyzomDayOfMonth()+1) + ", ";
1569 str
+= CI18N::get("uiAtysianCycle" + toString(RT
.getRyzomCycle()+1) + "Ordinal") + " " + CI18N::get("uiAtysianCycle") + " ";
1570 str
+= toString("%04d", RT
.getRyzomYear());
1572 pVT
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:time"));
1577 // Update the clock in the compass if enabled.
1578 pVT
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:compass:clock:time"));
1581 if (pVT
->getActive())
1584 str
= getTimestampHuman("%I:%M %p");
1586 str
= getTimestampHuman("%H:%M");
1593 CWidgetManager::getInstance()->sendClockTickEvent();
1595 IngameDbMngr
.flushObserverCalls();
1596 NLGUI::CDBManager::getInstance()->flushObserverCalls();
1598 // Update SPhrase manager
1599 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1602 // if there's an external lua debugger, update it
1603 luaDebuggerMainLoop();
1605 // handle gc for lua
1606 CLuaManager::getInstance().getLuaState()->handleGC();
1608 #ifdef RYZOM_BG_DOWNLOADER
1609 CBGDownloaderAccess::getInstance().update();
1612 CItemGroupManager::getInstance()->update();
1616 // ------------------------------------------------------------------------------------------------
1617 void CInterfaceManager::updateFrameViews(NL3D::UCamera camera
)
1620 H_AUTO ( RZ_Interface_updateFrameViews
)
1622 if (!camera
.empty())
1623 CViewRenderer::getInstance()->setWorldSpaceFrustum (camera
.getFrustum());
1625 CWidgetManager::getInstance()->checkCoords();
1628 // The interface manager may change usual Global setup. reset them.
1629 CViewRenderer::getTextContext()->setShadeColor(CRGBA::Black
);
1633 void CInterfaceManager::setupOptions()
1635 CWidgetManager
*wm
= CWidgetManager::getInstance();
1638 // Try to change font if any
1639 string sFont
= wm
->getSystemOption( CWidgetManager::OptionFont
).getValStr();
1641 if ((!sFont
.empty()) && (Driver
!= NULL
))
1642 resetTextContext(sFont
.c_str(), true);
1643 // Continue to parse the rest of the interface
1645 sFont
= wm
->getSystemOption (CWidgetManager::OptionMonospaceFont
).getValStr();
1646 if ((!sFont
.empty()) && (Driver
!= NULL
))
1647 CViewRenderer::registerFont("monospace", sFont
);
1650 // ------------------------------------------------------------------------------------------------
1651 bool CInterfaceManager::parseInterface (const std::vector
<std::string
> &xmlFileNames
, bool reload
, bool isFilename
)
1653 // cache some commonly used db nodes
1654 _DBB_UI_DUMMY
= NLGUI::CDBManager::getInstance()->getDbBranch( "UI:DUMMY" );
1655 _DB_UI_DUMMY_QUANTITY
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:QUANTITY", true );
1656 _DB_UI_DUMMY_QUALITY
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:QUALITY", true );
1657 _DB_UI_DUMMY_SHEET
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:SHEET", true );
1658 _DB_UI_DUMMY_NAMEID
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:NAMEID", true );
1659 _DB_UI_DUMMY_ENCHANT
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:ENCHANT", true );
1660 _DB_UI_DUMMY_SLOT_TYPE
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:SLOT_TYPE", true );
1661 _DB_UI_DUMMY_PHRASE
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:PHRASE", true );
1662 _DB_UI_DUMMY_WORNED
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:WORNED", true );
1663 _DB_UI_DUMMY_PREREQUISIT_VALID
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:PREREQUISIT_VALID", true );
1664 _DB_UI_DUMMY_FACTION_TYPE
= NLGUI::CDBManager::getInstance()->getDbProp( "UI:DUMMY:FACTION_TYPE", true );
1666 _DB_UI_DUMMY_QUANTITY
->setValue64(0);
1667 _DB_UI_DUMMY_QUALITY
->setValue64(0);
1668 _DB_UI_DUMMY_SHEET
->setValue64(0);
1669 _DB_UI_DUMMY_NAMEID
->setValue64(0);
1670 _DB_UI_DUMMY_ENCHANT
->setValue64(0);
1671 _DB_UI_DUMMY_SLOT_TYPE
->setValue64(0);
1672 _DB_UI_DUMMY_PHRASE
->setValue64(0);
1673 _DB_UI_DUMMY_WORNED
->setValue64(0);
1674 _DB_UI_DUMMY_PREREQUISIT_VALID
->setValueBool(true);
1675 _DB_UI_DUMMY_FACTION_TYPE
->setValue64(0);
1677 return CWidgetManager::getInstance()->getParser()->parseInterface (xmlFileNames
, reload
, isFilename
);
1680 // ------------------------------------------------------------------------------------------------
1681 void CInterfaceManager::loadTextures (const string
&textFileName
, const string
&uvFileName
, bool uploadDXTC
)
1683 CViewRenderer::getInstance()->loadTextures (textFileName
, uvFileName
, uploadDXTC
);
1686 // ------------------------------------------------------------------------------------------------
1687 bool CInterfaceManager::loadConfig (const string
&filename
)
1689 // reset the interface
1691 if (ClientCfg
.R2EDEnabled
)
1693 CWidgetManager::getInstance()->runProcedure ("proc_reset_r2ed_interface", NULL
, v
);
1697 CWidgetManager::getInstance()->runProcedure ("proc_reset_interface", NULL
, v
);
1700 // By default, consider the reset interface has been set with the current resolution
1703 // NB: even if minimzed, getScreenSize() no more return 0 values (return the last setuped screen size)
1704 CViewRenderer::getInstance()->getScreenSize(w
, h
);
1705 // Windows are positioned according to resolution, and we must backup W/H for the system that move windows when the resolution change
1706 _LastInGameScreenW
= w
;
1707 _LastInGameScreenH
= h
;
1710 // if the config file doesn't exist,just quit
1713 sFileName
= NLMISC::CPath::lookup (filename
, false);
1714 if (sFileName
.empty() || !f
.open(sFileName
))
1718 // *** Load the config file
1720 CInterfaceConfig ic
;
1721 bool lastInGameScreenResLoaded
= false;
1722 uint32 nbLandmarks
= 0;
1725 sint ver
= f
.serialVersion(ICFG_STREAM_VERSION
);
1727 // serial user chats info (serial it before position of windows so that they can be updated properly)
1730 f
.serialCheck(NELID("_ICU"));
1731 if (!PeopleInterraction
.loadUserChatsInfos(f
))
1733 nlwarning("Bad user chat saving");
1738 f
.serialCheck(NELID("GFCI"));
1740 f
.serial(_CurrentMode
);
1741 if (_CurrentMode
> nNbMode
)
1748 f
.serial(_LastInGameScreenW
);
1749 f
.serial(_LastInGameScreenH
);
1750 lastInGameScreenResLoaded
= true;
1753 // Initialize at least number of modes that are saved in stream
1754 _Modes
.resize(std::max((uint32
)MAX_NUM_MODES
, nNbMode
));
1755 for (uint32 i
= 0; i
< _Modes
.size(); ++i
)
1757 NLMISC::contReset(_Modes
[i
]);
1760 // Load All Window configuration of all Modes
1761 for (uint32 i
= 0; i
< nNbMode
; ++i
)
1763 // must create a tmp mem stream because desktop image expect its datas to occupy the whole stream
1764 // This is because of old system that manipulated desktop image direclty as a mem stream
1766 if (!ms
.isReading()) ms
.invert();
1771 // HACK. if the version is <=2, then the CInterfaceConfig has no serialVersion. append here a 0
1774 uint8
*pBuffer
= ms
.bufferToFill(length
+1);
1776 f
.serialBuffer(pBuffer
+1, length
);
1780 uint8
*pBuffer
= ms
.bufferToFill(length
);
1781 f
.serialBuffer(pBuffer
, length
);
1784 ms
.seek(0, NLMISC::IStream::begin
);
1785 _Modes
[i
].serial(ms
); // build desktop image from stream
1788 // load UI_DB_SAVE_VERSION
1789 uint32 uiDbSaveVersion
= 0; // default to 0 for old version of .icfg
1792 f
.serial(uiDbSaveVersion
);
1796 ic
.streamToDataBase(f
, uiDbSaveVersion
);
1799 // special for in game: backup last mission because of delayed update
1801 CCDBNodeLeaf
*pNL
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:MISSION_SELECTED", false);
1804 CCDBNodeLeaf
*pSelectedMissionBackup
= NLGUI::CDBManager::getInstance()->getDbProp("UI:VARIABLES:MISSION_SELECTED_PREV_SESSION", true);
1805 pSelectedMissionBackup
->setValue64(pNL
->getValue64());
1810 // Deprecated. for Compatibility purpose: Load TaskBar.
1813 CTaskBarManager
*pTBM
= CTaskBarManager::getInstance();
1817 // Load user landmarks
1818 nbLandmarks
= ContinentMngr
.serialUserLandMarks(f
);
1820 CCDBNodeLeaf
*pNL
= NLGUI::CDBManager::getInstance()->getDbProp( "SERVER:INTERFACES:NB_BONUS_LANDMARKS" );
1823 ICDBNode::CTextId textId
;
1824 pNL
->addObserver( &_LandmarkObs
, textId
);
1827 // Info Windows position.
1829 CInterfaceHelp::serialInfoWindows(f
);
1831 CInterfaceHelp::resetWindowPos(-100);
1833 // Macro On Memory Position
1834 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
1836 pPM
->serialMacroMemory(f
);
1839 CGroupInSceneBubbleManager::serialInSceneBubbleInfo(f
);
1843 if ( ! PeopleInterraction
.loadUserDynChatsInfos(f
))
1845 nlwarning("Bad user dyn chat saving");
1849 catch(const NLMISC::EStream
&)
1853 createFileBackup("Config loading failed", sFileName
);
1855 nlwarning("Config loading failed : restore default");
1857 if (!ClientCfg
.R2EDEnabled
)
1859 CWidgetManager::getInstance()->runProcedure ("proc_reset_interface", NULL
, v
);
1865 if (nbLandmarks
> 0)
1867 // use copy for backup so on save proper shared/player icfg file is used
1868 createFileBackup("Landmarks will be migrated to xml", sFileName
, true);
1870 // if icfg is interface_player.icfg, then landmarks must also be loaded/saved to player file
1871 if (nlstricmp(sFileName
.substr(0, 12), "save/shared_") != 0)
1873 string lmfile
= getSaveFileName("landmarks", "xml", false);
1874 if (!CFile::fileExists(lmfile
))
1876 // create placeholder player landmarks file so saveLandmarks will use it
1877 // even if shared landmarks file exists
1879 if (f
.open(lmfile
, false, false, true))
1882 xml
= "<?xml version=\"1.0\"?>\n<interface_config />";
1883 f
.serialBuffer((uint8
*)xml
.c_str(), xml
.size());
1889 // merge .icfg landmarks with landmarks.xml
1894 // *** If saved resolution is different from the current one setuped, must fix positions in _Modes
1895 if(lastInGameScreenResLoaded
)
1897 // Temporarily set screen to saved size so that positions are correctly calculated
1898 CWidgetManager::getInstance()->setScreenWH(_LastInGameScreenW
, _LastInGameScreenH
);
1899 // NB: we are typically InGame here (even though the _InGame flag is not yet set)
1900 // Use the screen size of the config file. Don't update current UI, just _Modes
1902 uint32 width
, height
;
1903 // get non-scaled width/height
1904 Driver
->getWindowSize(width
, height
);
1905 // convert to scaled width/height for ui
1906 sint32 scaledW
= width
/ ClientCfg
.InterfaceScale
;
1907 sint32 scaledH
= height
/ ClientCfg
.InterfaceScale
;
1908 CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(scaledW
, scaledH
, false);
1909 updateDesktops(scaledW
, scaledH
);
1912 // *** apply the current mode
1913 _Modes
[_CurrentMode
].toCurrentDesktop();
1915 // *** Apply the NPC icon display mode
1916 CNPCIconCache::getInstance().init(!ClientCfg
.R2EDEnabled
&& NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:INSCENE:FRIEND:MISSION_ICON")->getValueBool());
1922 // ------------------------------------------------------------------------------------------------
1923 void CInterfaceManager::CDBLandmarkObs::update(ICDBNode
*node
)
1925 ContinentMngr
.updateUserLandMarks();
1929 // visitor to send onQuit msg on all element
1930 class CQuitVisitor
: public CInterfaceElementVisitor
1934 bool BadWindowFound
; //
1936 virtual void visit(CInterfaceElement
*elem
) { elem
->onQuit(); }
1937 virtual void visitGroup(CInterfaceGroup
*group
)
1939 if (!IsR2ED
) return;
1940 if (Desktop
!= 0) return;
1941 if (group
->getShortId() == "gestionsets")
1943 if (group
->getActive())
1945 BadWindowFound
= true;
1951 bool CInterfaceManager::saveLandmarks(bool verbose
) const
1955 if (!ClientCfg
.R2EDEnabled
)
1957 uint8 currMode
= getMode();
1959 string filename
= getSaveFileName("landmarks", "xml");
1960 if (verbose
) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename
);
1961 ret
= saveLandmarks(filename
);
1967 bool CInterfaceManager::loadLandmarks()
1969 // Does the keys file exist ?
1970 string filename
= getSaveFileName("landmarks", "xml");
1974 sFileName
= NLMISC::CPath::lookup (filename
, false);
1975 if (sFileName
.empty() || !f
.open(sFileName
))
1979 vector
<string
> xmlFilesToParse
;
1980 xmlFilesToParse
.push_back (filename
);
1982 //ContinentMngr.serialUserLandMarks(node);
1983 if (!parseInterface (xmlFilesToParse
, true))
1987 createFileBackup("Error while loading landmarks", filename
);
1995 bool CInterfaceManager::saveLandmarks(const std::string
&filename
) const
1997 nlinfo( "Saving landmarks : %s", filename
.c_str() );
2004 // using temporary file, so no f.close() unless its a success
2005 if (f
.open(filename
, false, false, true))
2008 xmlStream
.init (&f
);
2010 xmlDocPtr doc
= xmlStream
.getDocument ();
2011 xmlNodePtr node
= xmlNewDocNode(doc
, NULL
, (const xmlChar
*)"interface_config", NULL
);
2012 xmlDocSetRootElement (doc
, node
);
2014 ContinentMngr
.writeTo(node
);
2025 catch (const Exception
&e
)
2027 nlwarning ("Error while writing the file %s : %s.", filename
.c_str(), e
.what ());
2033 // ------------------------------------------------------------------------------------------------
2035 bool CInterfaceManager::saveConfig (bool verbose
)
2039 if (!ClientCfg
.R2EDEnabled
)
2041 uint8 currMode
= getMode();
2043 string filename
= getSaveFileName("interface", "icfg");
2045 if (verbose
) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename
);
2046 ret
= saveConfig(filename
);
2048 if (currMode
!= getMode())
2055 // ------------------------------------------------------------------------------------------------
2056 bool CInterfaceManager::saveConfig (const string
&filename
)
2059 CQuitVisitor quitVisitor
;
2061 quitVisitor
.IsR2ED
= false;
2062 if (nlstricmp(NLMISC::CFile::getFilename(filename
).substr(0, 5), "r2ed_") == 0)
2064 quitVisitor
.IsR2ED
= true;
2066 quitVisitor
.BadWindowFound
= false;
2068 nlinfo( "Saving interface config : %s", filename
.c_str() );
2072 // using temporary file, so no f.close() unless its a success
2073 if (!f
.open(filename
, false, false, true)) return false;
2075 CInterfaceConfig ic
;
2079 // cleanup all desktops
2080 for(uint k
= 0; k
< _Modes
.size(); ++k
)
2082 quitVisitor
.Desktop
= k
;
2084 visit(&quitVisitor
);
2085 CWidgetManager::getInstance()->checkCoords();
2088 setMode(_CurrentMode
);
2090 if (quitVisitor
.BadWindowFound
)
2095 // tmp patch : when trying to overwrite the r2ed_ config, if a bad window is found, just do nothing ...
2100 _Modes[_CurrentMode].clear();
2101 if (_Modes[_CurrentMode].isReading()) _Modes[_CurrentMode].invert();
2103 restoreAllContainersBackupPosition();
2104 ic.interfaceManagerToStream(_Modes[_CurrentMode]);
2112 f
.serialVersion(ICFG_STREAM_VERSION
);
2114 // serial user chats info (serial it before position of windows so that they can be updated properly)
2115 f
.serialCheck(NELID("_ICU"));
2116 if (!PeopleInterraction
.saveUserChatsInfos(f
))
2118 nlwarning("Config saving failed");
2119 // couldn't save result so do not continue
2124 f
.serialCheck(NELID("GFCI"));
2126 f
.serial(_CurrentMode
);
2127 f
.serial(_LastInGameScreenW
);
2128 f
.serial(_LastInGameScreenH
);
2130 // Save All Window configuration of all Modes
2131 for (i
= 0; i
< _Modes
.size(); ++i
)
2133 // must create a tmp mem stream because desktop image expect its datas to occupy the whole stream
2134 // This is because of old system that manipulated desktop image direclty as a mem stream
2136 if (ms
.isReading()) ms
.invert();
2137 _Modes
[i
].serial(ms
);
2138 uint32 length
= ms
.length();
2142 f
.serialBuffer(const_cast<uint8
*>(ms
.buffer()), length
);
2146 // write UI_DB_SAVE_VERSION
2147 uint32 uiDbSaveVersion
;
2148 fromString( CWidgetManager::getInstance()->getParser()->getDefine("UI_DB_SAVE_VERSION"), uiDbSaveVersion
);
2149 f
.serial(uiDbSaveVersion
);
2152 ic
.dataBaseToStream(f
);
2154 // Deprecated. for Compatibility purpose: Save TaskBar.
2155 CTaskBarManager
*pTBM
= CTaskBarManager::getInstance();
2158 //ContinentMngr.serialUserLandMarks(f);
2159 // empty landmarks block for compatibility
2166 // Info Windows position.
2167 CInterfaceHelp::serialInfoWindows(f
);
2169 // Macro On Memory Position
2170 CSPhraseManager
*pPM
= CSPhraseManager::getInstance();
2171 pPM
->serialMacroMemory(f
);
2173 CGroupInSceneBubbleManager::serialInSceneBubbleInfo(f
);
2175 if ( ! PeopleInterraction
.saveUserDynChatsInfos(f
))
2177 nlwarning("Bad user dyn chat saving");
2183 catch(const NLMISC::EStream
&)
2185 nlwarning("Config saving failed.");
2189 ContinentMngr
.serialFOWMaps();
2194 // ------------------------------------------------------------------------------------------------
2195 void CInterfaceManager::drawViews(NL3D::UCamera camera
)
2197 IngameDbMngr
.flushObserverCalls();
2198 NLGUI::CDBManager::getInstance()->flushObserverCalls();
2200 // Update Player characteristics (for Item carac requirement Redifying)
2201 nlctassert(CHARACTERISTICS::NUM_CHARACTERISTICS
==8);
2202 for (uint i
=0; i
<CHARACTERISTICS::NUM_CHARACTERISTICS
; ++i
)
2204 if (!_CurrentPlayerCharacLeaf
[i
])
2205 _CurrentPlayerCharacLeaf
[i
] = NLGUI::CDBManager::getInstance()->getDbProp(toString("SERVER:CHARACTER_INFO:CHARACTERISTICS%d:VALUE", i
), false);
2207 NLMISC::CCDBNodeLeaf
*node
= NULL
;
2209 if (_CurrentPlayerCharacLeaf
[i
])
2210 node
= &*_CurrentPlayerCharacLeaf
[i
];
2212 _CurrentPlayerCharac
[i
] = node
? node
->getValue32() : 0;
2215 // scale must be updated right before widget manager checks it
2216 if (_InterfaceScaleChanged
)
2218 CViewRenderer::getInstance()->setInterfaceScale(_InterfaceScale
);
2219 _InterfaceScaleChanged
= false;
2222 CWidgetManager::getInstance()->drawViews( camera
);
2225 IngameDbMngr
.flushObserverCalls();
2229 // ------------------------------------------------------------------------------------------------
2230 bool CInterfaceManager::handleEvent (const NLGUI::CEventDescriptor
& event
)
2232 bool handled
= false;
2234 handled
= CWidgetManager::getInstance()->handleEvent( event
);
2236 if( event
.getType() == NLGUI::CEventDescriptor::mouse
)
2238 NLGUI::CEventDescriptorMouse
&eventDesc
= (NLGUI::CEventDescriptorMouse
&)event
;
2240 if( ( eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightup
) && handled
)
2242 // prevent 'click in scene' as mouse was previously captured
2243 // (more a patch that anything, but 'UserControls' test for 'mouse up'
2244 // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled...
2245 if( CWidgetManager::getInstance()->getCapturePointerRight() == NULL
)
2246 EventsListener
.addUIHandledButtonMask(rightButton
);
2248 if( ( eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup
) && handled
)
2250 // prevent 'click in scene' as mouse was previously captured
2251 // (more a patch that anything, but 'UserControls' test for 'mouse up'
2252 // directly later in the main loop (not through message queue), so it has no way of knowing that the event was handled...
2253 if( CWidgetManager::getInstance()->getCapturePointerLeft() == NULL
)
2254 EventsListener
.addUIHandledButtonMask(leftButton
);
2259 IngameDbMngr
.flushObserverCalls();
2264 void CInterfaceManager::updateDesktops( uint32 newScreenW
, uint32 newScreenH
)
2266 // *** Do it for All Backuped Desktops
2267 for(uint md
=0; md
<_Modes
.size(); md
++)
2269 CInterfaceConfig::CDesktopImage
&mode
= _Modes
[md
];
2270 // For all containers of this mode
2271 for(uint gc
=0;gc
<mode
.GCImages
.size();gc
++)
2273 CInterfaceConfig::SCont
&gcCont
= mode
.GCImages
[gc
];
2274 // Compute the new coordinate, directly in the X/Y fields of the structure
2275 CWidgetManager::getInstance()->getNewWindowCoordToNewScreenSize(gcCont
.X
, gcCont
.Y
, gcCont
.W
, gcCont
.H
,newScreenW
, newScreenH
);
2279 _LastInGameScreenW
= newScreenW
;
2280 _LastInGameScreenH
= newScreenH
;
2283 class InvalidateTextVisitor
: public CInterfaceElementVisitor
2286 InvalidateTextVisitor( bool reset
)
2288 this->reset
= reset
;
2291 void visitGroup( CInterfaceGroup
*group
)
2293 const std::vector
< CViewBase
* > &vs
= group
->getViews();
2294 for( std::vector
< CViewBase
* >::const_iterator itr
= vs
.begin(); itr
!= vs
.end(); ++itr
)
2296 CViewText
*vt
= dynamic_cast< CViewText
* >( *itr
);
2300 vt
->resetTextIndex();
2301 vt
->updateTextContext();
2311 // ------------------------------------------------------------------------------------------------
2312 void CInterfaceManager::addServerString (const std::string
&sTarget
, uint32 id
, IStringProcess
*cb
)
2316 CInterfaceExprValue val
;
2317 val
.setString (std::string());
2318 CInterfaceLink::setTargetProperty (sTarget
, val
);
2321 SIDStringWaiter
*pISW
= new SIDStringWaiter
;
2323 pISW
->IdOrString
= false;
2324 pISW
->Target
= sTarget
;
2326 _IDStringWaiters
.push_back(pISW
);
2329 // ------------------------------------------------------------------------------------------------
2330 void CInterfaceManager::addServerID (const std::string
&sTarget
, uint32 id
, IStringProcess
*cb
)
2334 CInterfaceExprValue val
;
2335 val
.setString (std::string());
2336 CInterfaceLink::setTargetProperty (sTarget
, val
);
2339 SIDStringWaiter
*pISW
= new SIDStringWaiter
;
2341 pISW
->IdOrString
= true;
2342 pISW
->Target
= sTarget
;
2344 _IDStringWaiters
.push_back(pISW
);
2347 // ------------------------------------------------------------------------------------------------
2348 void CInterfaceManager::processServerIDString()
2350 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
2352 for (uint32 i
= 0; i
< _IDStringWaiters
.size(); ++i
)
2354 bool bAffect
= false;
2355 string ucstrToAffect
;
2356 SIDStringWaiter
*pISW
= _IDStringWaiters
[i
];
2357 if (pISW
->IdOrString
== true) // ID !
2359 if (pSMC
->getString (pISW
->Id
, ucstrToAffect
))
2364 if (pSMC
->getDynString (pISW
->Id
, ucstrToAffect
))
2370 CInterfaceExprValue val
;
2373 if (pISW
->Cb
!= NULL
)
2375 bValid
= pISW
->Cb
->cbIDStringReceived(ucstrToAffect
);
2381 ucstrToAffect
= STRING_MANAGER::CStringManagerClient::getLocalizedName(ucstrToAffect
);
2382 val
.setString (ucstrToAffect
);
2383 CInterfaceLink::setTargetProperty (pISW
->Target
, val
);
2387 _IDStringWaiters
.erase (_IDStringWaiters
.begin()+i
);
2394 // ------------------------------------------------------------------------------------------------
2395 void CInterfaceManager::messageBoxInternal(const string
&msgBoxGroup
, const string
&text
, const string
&masterGroup
, TCaseMode caseMode
)
2397 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":" + msgBoxGroup
));
2398 CViewText
*viewText
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":" + msgBoxGroup
+ ":text"));
2400 if (group
&& viewText
)
2402 viewText
->setCaseMode(caseMode
);
2403 viewText
->setText(text
);
2404 CWidgetManager::getInstance()->enableModalWindow(NULL
, group
);
2405 // don't understand why but need to update coords here
2406 group
->updateCoords();
2407 group
->updateCoords();
2411 // ------------------------------------------------------------------------------------------------
2412 void CInterfaceManager::messageBox(const string
&text
, const string
&masterGroup
, TCaseMode caseMode
)
2414 messageBoxInternal("message_box", text
, masterGroup
, caseMode
);
2418 // ------------------------------------------------------------------------------------------------
2419 void CInterfaceManager::messageBoxWithHelp(const std::string
&text
, const std::string
&masterGroup
,
2420 const std::string
&ahOnOk
, const std::string
¶msOnOk
,
2423 // replace the procedure "proc_valid_message_box_ok" action
2424 CWidgetManager::getInstance()->setProcedureAction("proc_message_box_with_help_ok", 1, ahOnOk
, paramsOnOk
);
2425 const char *mbName
= "message_box_with_help";
2426 // if no action handler is wanted, then assume that
2427 // clicking 'ok' do not have any consequence, so allow exiting the message box by clicking
2428 // outside of it (this behavior is wanted on the login page, to allow to reclick on 'login' without
2429 // having to click 'ok' in the message box each time)
2430 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":" + mbName
));
2431 CGroupModal
*gm
= dynamic_cast<CGroupModal
*>(group
);
2434 gm
->ExitClickOut
= ahOnOk
.empty();
2436 messageBoxInternal(mbName
, text
, masterGroup
, caseMode
);
2440 // ------------------------------------------------------------------------------------------------
2441 void CInterfaceManager::validMessageBox(TValidMessageIcon icon
, const std::string
&text
, const std::string
&ahOnOk
,
2442 const std::string
¶msOnOk
, const std::string
&ahOnCancel
, const std::string
¶msOnCancel
, const string
&masterGroup
)
2444 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":valid_message_box"));
2445 CViewText
*viewText
= dynamic_cast<CViewText
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":valid_message_box:text"));
2446 CViewBitmap
*viewBitmap
= dynamic_cast<CViewBitmap
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":valid_message_box:icon_group:icon"));
2448 if (group
&& viewText
)
2450 // replace the procedure "proc_valid_message_box_ok" action
2451 CWidgetManager::getInstance()->setProcedureAction("proc_valid_message_box_ok", 1, ahOnOk
, paramsOnOk
);
2452 // replace the procedure "proc_valid_message_box_cancel" action
2453 CWidgetManager::getInstance()->setProcedureAction("proc_valid_message_box_cancel", 1, ahOnCancel
, paramsOnCancel
);
2455 // set text and icon
2456 viewText
->setText(text
);
2460 if(icon
==QuestionIconMsg
)
2461 viewBitmap
->setTexture("brick_default.tga");
2462 else if(icon
==WarningIconMsg
)
2463 viewBitmap
->setTexture("W_warning.tga");
2464 else if(icon
==ErrorIconMsg
)
2465 viewBitmap
->setTexture("No_Action.tga");
2468 viewBitmap
->setActive(active
);
2472 CWidgetManager::getInstance()->enableModalWindow(NULL
, group
);
2473 // don't understand why but need to update coords here
2474 group
->updateCoords();
2475 group
->updateCoords();
2480 // ------------------------------------------------------------------------------------------------
2481 bool CInterfaceManager::getCurrentValidMessageBoxOnOk(string
&ahOnOk
, const std::string
&masterGroup
)
2483 // any modal window opened?
2484 CInterfaceGroup
*mw
= CWidgetManager::getInstance()->getModalWindow();
2488 // Is this modal window the valid_message_box window?
2489 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(masterGroup
+":valid_message_box"));
2492 // Ok, get the current procedure OnOk action
2494 if( CWidgetManager::getInstance()->getParser()->getProcedureAction("proc_valid_message_box_ok", 1, ahOnOk
, dummyParams
))
2502 // ***************************************************************************
2503 void CInterfaceManager::displayDebugInfo(const string
&str
, TSystemInfoMode mode
/*=InfoMsg*/)
2505 if (PeopleInterraction
.DebugInfo
)
2506 PeopleInterraction
.ChatInput
.DebugInfo
.displayMessage(str
, getDebugInfoColor(mode
), 2);
2509 // ***************************************************************************
2510 NLMISC::CRGBA
CInterfaceManager::getDebugInfoColor(TSystemInfoMode mode
)
2512 if (_NeutralColor
== NULL
) // not initialised ?
2514 #define SYSTEM_INFO_COLOR_DB_PATH "UI:VARIABLES:SYSTEM_INFOS:COLORS"
2515 _NeutralColor
= NLGUI::CDBManager::getInstance()->getDbProp(SYSTEM_INFO_COLOR_DB_PATH
":NEUTRAL");
2516 _WarningColor
= NLGUI::CDBManager::getInstance()->getDbProp(SYSTEM_INFO_COLOR_DB_PATH
":WARNING");
2517 _ErrorColor
= NLGUI::CDBManager::getInstance()->getDbProp(SYSTEM_INFO_COLOR_DB_PATH
":ERROR");
2519 NLMISC::CRGBA color
;
2522 case InfoMsg
: color
.setPacked(_NeutralColor
->getValue32()); break;
2523 case WarningMsg
: color
.setPacked(_WarningColor
->getValue32()); break;
2524 case ErrorMsg
: color
.setPacked(_ErrorColor
->getValue32()); break;
2526 color
= CRGBA::White
;
2532 // ***************************************************************************
2533 void CInterfaceManager::displaySystemInfo(const string
&str
, const string
&cat
)
2535 CClientConfig::SSysInfoParam::TMode mode
= CClientConfig::SSysInfoParam::Normal
;
2536 CRGBA color
= CRGBA::White
;
2539 map
<string
, CClientConfig::SSysInfoParam
>::const_iterator it
= ClientCfg
.SystemInfoParams
.find(toLowerAscii(cat
));
2540 if (it
!= ClientCfg
.SystemInfoParams
.end())
2542 mode
= it
->second
.Mode
;
2543 color
= it
->second
.Color
;
2546 if (mode
!= CClientConfig::SSysInfoParam::OverOnly
&& mode
!= CClientConfig::SSysInfoParam::Around
)
2548 if (PeopleInterraction
.SystemInfo
)
2549 PeopleInterraction
.ChatInput
.SystemInfo
.displayMessage(str
, color
, 2);
2552 CPeopleInterraction::CSysMsg sysMsg
;
2555 PeopleInterraction
.SystemMessageBuffer
.push_back( sysMsg
);
2559 if (mode
== CClientConfig::SSysInfoParam::Center
|| mode
== CClientConfig::SSysInfoParam::CenterAround
)
2560 InSceneBubbleManager
.addMessagePopupCenter(str
, color
);
2562 // If over popup a string at the bottom of the screen
2563 if ((mode
== CClientConfig::SSysInfoParam::Over
) || (mode
== CClientConfig::SSysInfoParam::OverOnly
))
2564 InSceneBubbleManager
.addMessagePopup(str
, color
);
2565 else if ( (mode
== CClientConfig::SSysInfoParam::Around
|| mode
== CClientConfig::SSysInfoParam::CenterAround
)
2566 && PeopleInterraction
.AroundMe
.Window
)
2567 PeopleInterraction
.ChatInput
.AroundMe
.displayMessage(str
, color
, 2);
2570 // ***************************************************************************
2571 CRGBA
CInterfaceManager::getSystemInfoColor(const std::string
&cat
)
2573 CRGBA col
= CRGBA::White
;
2574 map
<string
, CClientConfig::SSysInfoParam
>::const_iterator it
= ClientCfg
.SystemInfoParams
.find(toLowerAscii(cat
));
2575 if (it
!= ClientCfg
.SystemInfoParams
.end())
2576 col
= it
->second
.Color
;
2580 // ***************************************************************************
2581 void CInterfaceManager::launchContextMenuInGame (const std::string
&nameOfCM
)
2583 // Launch the context menu in-game: can't appear while dragging an item
2584 if (CCtrlDraggable::getDraggedSheet() == NULL
)
2586 if ( !CWidgetManager::getInstance()->hasModal() )
2588 // We must be in-game !
2589 CInterfaceGroup
*pMG
= CWidgetManager::getInstance()->getMasterGroupFromId("ui:interface");
2590 // TMP nico : try with login screen:
2593 pMG
= CWidgetManager::getInstance()->getMasterGroupFromId("ui:login");
2597 pMG
= CWidgetManager::getInstance()->getMasterGroupFromId("ui:outgame");
2599 if ((pMG
!= NULL
) && (pMG
->getActive()))
2601 CInterfaceElement
*pIE
= CWidgetManager::getInstance()->getElementFromId(nameOfCM
);
2602 CInterfaceGroup
*pIG
= dynamic_cast<CInterfaceGroup
*>(pIE
);
2605 CWidgetManager::getInstance()->enableModalWindow (NULL
, pIG
);
2613 // ***************************************************************************
2614 void CInterfaceManager::updateGroupContainerImage(CGroupContainer
&gc
, uint8 mode
)
2616 if (mode
>= _Modes
.size())
2618 nlwarning("wrong desktop");
2621 _Modes
[mode
].updateGroupContainerImage(gc
);
2624 // ***************************************************************************
2625 void CInterfaceManager::removeGroupContainerImage(const std::string
&groupName
, uint8 mode
)
2627 if (mode
>= _Modes
.size())
2629 nlwarning("wrong desktop");
2632 _Modes
[mode
].removeGroupContainerImage(groupName
);
2636 // ***************************************************************************
2637 void CInterfaceManager::removeGroupContainerImageFromDesktops(const std::string
&groupName
)
2639 for (uint i
= 0; i
< _Modes
.size(); i
++)
2641 _Modes
[i
].removeGroupContainerImage(groupName
);
2645 // ***************************************************************************
2646 void CInterfaceManager::setMode(uint8 newMode
)
2648 if (newMode
>= _Modes
.size())
2651 if (newMode
== _CurrentMode
)
2654 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
2656 // Check if we can change vdesk !
2657 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
2659 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
2660 if (rMG
.Group
->getActive())
2662 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
2664 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
2665 list
<CInterfaceGroup
*>::const_iterator itw
;
2666 for (itw
= rList
.begin(); itw
!= rList
.end(); itw
++)
2668 CGroupContainer
*pGC
= dynamic_cast<CGroupContainer
*>(*itw
);
2669 if ((pGC
!= NULL
)&&(pGC
->getActive()))
2671 // if this GC is a Full modal window, or if it is a modal son of another GC,
2672 if (pGC
->isModal() || pGC
->isModalSon())
2674 CWidgetManager::getInstance()->setTopWindow(pGC
);
2675 pGC
->enableBlink(2);
2679 if (pGC
->isGrayed())
2681 // Make the corresponding child blink
2682 pGC
->blinkAllSons();
2691 // check if there's a special behaviour with current captured ctrl that prevent from changing desktop
2692 if ( CWidgetManager::getInstance()->getCapturePointerLeft() != NULL
)
2694 if (!CWidgetManager::getInstance()->getCapturePointerLeft()->canChangeVirtualDesktop()) return;
2696 if ( CWidgetManager::getInstance()->getCapturePointerRight() != NULL
)
2698 if (!CWidgetManager::getInstance()->getCapturePointerRight()->canChangeVirtualDesktop()) return;
2702 _Modes
[_CurrentMode
].fromCurrentDesktop();
2703 _Modes
[newMode
].toCurrentDesktop();
2704 //CBotChatUI::refreshActiveWindows();
2706 _CurrentMode
= newMode
;
2707 CWidgetManager::getInstance()->checkCoords();
2710 // ***************************************************************************
2711 void CInterfaceManager::resetMode(uint8 newMode
)
2713 if (newMode
>= _Modes
.size())
2715 NLMISC::contReset(_Modes
[newMode
]);
2719 // for dump of interface content
2722 CInterfaceGroup
*Group
;
2723 uint Depth
; // depth in the tree
2726 // ***************************************************************************
2727 void CInterfaceManager::dumpUI(bool /* indent */)
2729 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
2730 std::vector
<CDumpedGroup
> left
;
2731 left
.resize(_MasterGroups
.size());
2732 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
2734 left
[nMasterGroup
].Group
= _MasterGroups
[nMasterGroup
].Group
;
2735 left
[nMasterGroup
].Depth
= 0;
2738 while (!left
.empty())
2740 CInterfaceGroup
*ig
= left
.back().Group
;
2743 uint currDepth
= left
.back().Depth
;
2744 std::string id
= ig
->getId();
2745 std::string::size_type pos
= id
.find_last_of(':');
2746 if (pos
!= std::string::npos
)
2748 id
= id
.substr(pos
+ 1);
2750 std::string
info(currDepth
* 4, ' ');
2752 info
+= toString(", address=0x%p", ig
);
2753 nlinfo(info
.c_str());
2754 // dump view & controls for this group
2755 for(uint k
= 0; k
< ig
->getViews().size(); ++k
)
2757 std::string
info(currDepth
* 4, ' ');
2758 info
+= toString("View %d / %d : ", (int) k
+ 1, (int) ig
->getViews().size());
2759 if (ig
->getViews()[k
])
2762 NLGUI::CViewBase
*view
= ig
->getViews()[k
];
2763 info
+= toString(", type = %s, address=0x%p", typeid(*view
).name(), view
);
2769 nlinfo(info
.c_str());
2772 for(uint k
= 0; k
< ig
->getControls().size(); ++k
)
2774 std::string
info(currDepth
* 4, ' ');
2775 info
+= toString("Ctrl %d / %d : ", (int) k
+ 1, (int) ig
->getControls().size());
2776 if (ig
->getControls()[k
])
2779 NLGUI::CCtrlBase
*control
= ig
->getControls()[k
];
2780 info
+= toString(", type = %s, address=0x%p", typeid(*control
).name(), control
);
2786 nlinfo(info
.c_str());
2792 for(uint k
= 0; k
< ig
->getNumGroup(); ++k
)
2795 dg
.Group
= ig
->getGroup(k
);
2796 dg
.Depth
= currDepth
+ 1;
2803 // ***************************************************************************
2804 void CInterfaceManager::displayUIViewBBoxs(const std::string
&uiFilter
)
2806 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
2807 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
2809 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
2810 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
2812 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
2813 list
<CInterfaceGroup
*>::iterator it
;
2814 for(it
= rList
.begin(); it
!= rList
.end(); ++it
)
2816 if (*it
) (*it
)->renderWiredQuads(CInterfaceElement::RenderView
, uiFilter
);
2822 // ***************************************************************************
2823 void CInterfaceManager::displayUICtrlBBoxs(const std::string
&uiFilter
)
2825 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
2826 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
2828 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
2829 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
2831 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
2832 list
<CInterfaceGroup
*>::iterator it
;
2833 for(it
= rList
.begin(); it
!= rList
.end(); ++it
)
2835 if (*it
) (*it
)->renderWiredQuads(CInterfaceElement::RenderCtrl
, uiFilter
);
2841 // ***************************************************************************
2842 void CInterfaceManager::displayUIGroupBBoxs(const std::string
&uiFilter
)
2844 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
2845 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
2847 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
2848 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
2850 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
2851 list
<CInterfaceGroup
*>::iterator it
;
2852 for(it
= rList
.begin(); it
!= rList
.end(); ++it
)
2854 if (*it
) (*it
)->renderWiredQuads(CInterfaceElement::RenderGroup
, uiFilter
);
2860 // ***************************************************************************
2861 void writeComboActionMap (const CActionsManager
&actions
, xmlNodePtr node
, const string
&context
)
2863 // Get the combo defined
2864 const CActionsManager::TComboActionMap
&combos
= actions
.getComboActionMap ();
2865 CActionsManager::TComboActionMap::const_iterator ite
= combos
.begin ();
2866 while (ite
!= combos
.end ())
2869 xmlNodePtr keyNode
= xmlNewChild ( node
, NULL
, (const xmlChar
*)"key", NULL
);
2872 xmlSetProp (keyNode
, (const xmlChar
*)"name", (const xmlChar
*)CEventKey::getStringFromKey(ite
->first
.Key
).c_str());
2874 if (ite
->first
.KeyButtons
&shiftKeyButton
)
2875 xmlSetProp (keyNode
, (const xmlChar
*)"shift", (const xmlChar
*)"1");
2876 if (ite
->first
.KeyButtons
&ctrlKeyButton
)
2877 xmlSetProp (keyNode
, (const xmlChar
*)"ctrl", (const xmlChar
*)"1");
2878 if (ite
->first
.KeyButtons
&altKeyButton
)
2879 xmlSetProp (keyNode
, (const xmlChar
*)"menu", (const xmlChar
*)"1");
2881 xmlSetProp (keyNode
, (const xmlChar
*)"action", (const xmlChar
*)ite
->second
.Name
.c_str());
2882 if (!(const xmlChar
*)ite
->second
.Argu
.empty())
2883 xmlSetProp (keyNode
, (const xmlChar
*)"params", (const xmlChar
*)ite
->second
.Argu
.c_str());
2886 if (!context
.empty ())
2887 xmlSetProp (keyNode
, (const xmlChar
*)"context", (const xmlChar
*)context
.c_str());
2893 // ***************************************************************************
2895 void writeMacros (xmlNodePtr node
)
2897 const std::vector
<CMacroCmd
> ¯os
= CMacroCmdManager::getInstance()->getMacros();
2898 for (uint i
= 0; i
< macros
.size(); ++i
)
2900 macros
[i
].writeTo(node
);
2904 // ***************************************************************************
2905 bool CInterfaceManager::saveKeys(bool verbose
)
2909 if (!ClientCfg
.R2EDEnabled
)
2911 string filename
= "save/keys_" + PlayerSelectedFileName
+ ".xml";
2912 if (!CFile::fileExists(filename
) && CFile::fileExists("save/shared_keys.xml"))
2913 filename
= "save/shared_keys.xml";
2915 if (verbose
) CInterfaceManager::getInstance()->displaySystemInfo("Saving " + filename
);
2917 ret
= saveKeys(filename
);
2923 // ***************************************************************************
2924 bool CInterfaceManager::saveKeys(const std::string
&filename
)
2931 // using temporary file, so no file.close() unless its a success
2932 if (file
.open (filename
, false, false, true))
2935 xmlStream
.init (&file
);
2937 xmlDocPtr doc
= xmlStream
.getDocument ();
2938 xmlNodePtr node
= xmlNewDocNode(doc
, NULL
, (const xmlChar
*)"interface_config", NULL
);
2939 xmlDocSetRootElement (doc
, node
);
2941 writeComboActionMap (Actions
, node
, "");
2942 writeComboActionMap (EditActions
, node
, RZ_CATEGORY_EDIT
);
2957 nlwarning ("Can't open the file %s", filename
.c_str());
2960 catch (const Exception
&e
)
2962 nlwarning ("Error while writing the file %s : %s.", filename
.c_str(), e
.what ());
2967 // ***************************************************************************
2968 bool CInterfaceManager::deletePlayerConfig (const std::string
&playerFileIdent
)
2970 string fileName
= "save/interface_" + playerFileIdent
+ ".icfg";
2971 return CFile::deleteFile(fileName
);
2975 // ***************************************************************************
2976 bool CInterfaceManager::deletePlayerKeys (const std::string
&playerFileIdent
)
2978 string fileName
= "save/keys_"+playerFileIdent
+".xml";
2979 string fileNameEditor
= "save/keys_r2ed_"+playerFileIdent
+".xml";
2980 return CFile::deleteFile(fileName
) && CFile::deleteFile(fileNameEditor
);
2983 // ***************************************************************************
2984 void CInterfaceManager::log(const std::string
&str
, const std::string
&cat
)
2988 // Open file with the name of the player
2989 const string fileName
= "save/log_" + PlayerSelectedFileName
+ ".txt";
2990 FILE *f
= nlfopen(fileName
, "at");
2993 const string finalString
= string(NLMISC::IDisplayer::dateToHumanString()) + " (" + NLMISC::toUpperAscii(cat
) + ") * " + str
;
2994 fprintf(f
, "%s\n", finalString
.c_str());
3000 // ***************************************************************************
3001 void CInterfaceManager::clearAllEditBox()
3003 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
3004 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
3006 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
3007 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
3009 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
3010 list
<CInterfaceGroup
*>::iterator it
;
3011 for(it
= rList
.begin(); it
!= rList
.end(); ++it
)
3013 CInterfaceGroup
*pIG
= *it
;
3015 pIG
->clearAllEditBox();
3021 // ***************************************************************************
3022 void CInterfaceManager::restoreAllContainersBackupPosition()
3024 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
3025 for (uint32 nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
3027 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
3028 for (uint8 nPriority
=0; nPriority
< WIN_PRIORITY_MAX
; ++nPriority
)
3030 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
3031 list
<CInterfaceGroup
*>::iterator it
;
3032 for(it
= rList
.begin(); it
!= rList
.end(); ++it
)
3034 if (*it
) (*it
)->restoreAllContainersBackupPosition();
3040 // ***************************************************************************
3041 void CInterfaceManager::visit(CInterfaceElementVisitor
*visitor
)
3044 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
3045 for (uint nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
3047 if (_MasterGroups
[nMasterGroup
].Group
)
3049 _MasterGroups
[nMasterGroup
].Group
->visit(visitor
);
3054 // ***************************************************************************
3055 void CInterfaceManager::incLocalSyncActionCounter()
3057 _LocalSyncActionCounter
++;
3064 // ***************************************************************************
3065 NLMISC_COMMAND( localCounter
, "Get value of local counter", "" )
3067 if (args
.size() != 0) return false;
3068 CInterfaceManager
*im
= CInterfaceManager::getInstance();
3069 im
->displaySystemInfo(toString(im
->getLocalSyncActionCounter()));
3075 // ***************************************************************************
3077 NLMISC_COMMAND(loadui
, "Load an interface file", "<loadui [all]/interface.xml>")
3079 if (args
.size() != 1)
3082 CInterfaceManager
*im
= CInterfaceManager::getInstance();
3084 std::vector
<std::string
> xmlFileNames
;
3086 if (args
[0] == "all")
3087 xmlFileNames
= CInterfaceManager::getInGameXMLInterfaceFiles();
3089 xmlFileNames
.push_back (args
[0]);
3091 bool result
= im
->parseInterface (xmlFileNames
, true);
3094 CInterfaceManager::getInstance()->displaySystemInfo("File "+xmlFileNames
.back()+" loaded successfully.");
3096 CInterfaceManager::getInstance()->displaySystemInfo("File "+xmlFileNames
.back()+" NOT loaded successully.");
3099 // Invalidate the texts
3100 CWidgetManager::getInstance()->updateAllLocalisedElements();
3103 CWidgetManager::getInstance()->setCapturePointerLeft(NULL
);
3104 CWidgetManager::getInstance()->setCapturePointerRight(NULL
);
3105 CWidgetManager::getInstance()->setOldCaptureKeyboard(NULL
);
3106 CWidgetManager::getInstance()->setCaptureKeyboard(NULL
);
3111 // ***************************************************************************
3112 void CInterfaceManager::displayWebWindow(const string
& name
, const string
& url
)
3114 CInterfaceGroup
*pIG
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(name
));
3117 pIG
->setActive(true);
3118 pIG
->updateCoords();
3122 CAHManager::getInstance()->runActionHandler("browse", NULL
, "name="+name
+":content:html|url="+url
);
3125 // ***************************************************************************
3126 class CAHSaveUI
: public IActionHandler
3128 virtual void execute (CCtrlBase
*pCaller
, const string
&Params
)
3130 CInterfaceManager::getInstance()->saveKeys(true);
3131 CInterfaceManager::getInstance()->saveConfig(true);
3134 REGISTER_ACTION_HANDLER (CAHSaveUI
, "save_ui");
3137 // ***************************************************************************
3138 class CHandlerDispWebOnQuit : public IActionHandler
3140 virtual void execute (CCtrlBase *pCaller, const string &Params)
3142 if (ClientCfg.Local)
3143 CAHManager::getInstance()->runActionHandler("enter_modal", pCaller, "group=ui:interface:quit_dialog");
3145 CInterfaceManager::getInstance()->displayWebWindow("ui:interface:web_on_quit", "http://213.208.119.190/igpoll/poll_form.php");
3148 REGISTER_ACTION_HANDLER (CHandlerDispWebOnQuit, "disp_web_on_quit");
3150 // ***************************************************************************
3151 class CHandlerExitWebOnQuit : public IActionHandler
3153 virtual void execute (CCtrlBase *pCaller, const string &Params)
3155 CAHManager::getInstance()->runActionHandler("quit_ryzom", pCaller);
3158 REGISTER_ACTION_HANDLER (CHandlerExitWebOnQuit, "exit_web_on_quit");
3161 // ***************************************************************************
3163 // ***************************************************************************
3170 bool UsableFromClientUI
;
3172 bool operator< (const CEmoteEntry
& entry
) const
3174 string path1
= Path
;
3175 string path2
= entry
.Path
;
3179 string::size_type pos1
= path1
.find('|');
3180 string::size_type pos2
= path2
.find('|');
3182 string s1
= toUpper(CI18N::get(path1
.substr(0, pos1
)));
3183 string s2
= toUpper(CI18N::get(path2
.substr(0, pos2
)));
3185 sint result
= s1
.compare(s2
);
3187 return (result
< 0);
3189 if (pos1
== string::npos
)
3190 return (pos2
!= string::npos
);
3191 if (pos2
== string::npos
)
3194 path1
= path1
.substr(pos1
+ 1);
3195 path2
= path2
.substr(pos2
+ 1);
3201 static bool translateEmote(const std::string
&id
, std::string
&translatedName
, std::string
&commandName
, std::string
&commandNameAlt
)
3203 if (CI18N::hasTranslation(id
))
3205 translatedName
= CI18N::get(id
);
3207 // convert command to utf8 since emote translation can have strange chars
3208 commandName
= toLower(translatedName
);
3210 // replace all spaces by _
3211 while (strFindReplace(commandName
, " ", "_"));
3213 // TODO: remove accents
3214 commandNameAlt
= commandName
;
3216 if (commandNameAlt
== commandName
) commandNameAlt
.clear();
3221 translatedName
= id
;
3227 // ***************************************************************************
3228 void CInterfaceManager::initEmotes()
3230 _EmotesInitialized
= true;
3231 CTextEmotListSheet
*pTELS
= dynamic_cast<CTextEmotListSheet
*>(SheetMngr
.get(CSheetId("list.text_emotes")));
3235 static list
<CEmoteEntry
> entries
;
3236 if (entries
.empty())
3238 for (uint i
= 0; i
< pTELS
->TextEmotList
.size(); i
++)
3242 entry
.Path
= pTELS
->TextEmotList
[i
].Path
;
3243 entry
.Anim
= pTELS
->TextEmotList
[i
].Anim
;
3244 entry
.UsableFromClientUI
= pTELS
->TextEmotList
[i
].UsableFromClientUI
;
3245 entries
.push_back(entry
);
3250 // The list of behaviour missnames emotList
3251 CEmotListSheet
*pEmotList
= dynamic_cast<CEmotListSheet
*>(SheetMngr
.get(CSheetId("list.emot")));
3252 nlassert (pEmotList
!= NULL
);
3253 nlassert (pEmotList
->Emots
.size() <= 255);
3255 // Get the focus beta tester flag
3256 bool betaTester
= false;
3258 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3259 CSkillManager
*pSM
= CSkillManager::getInstance();
3261 betaTester
= pSM
->isTitleUnblocked(CHARACTER_TITLE::FBT
);
3262 string previousMind
;
3263 CGroupSubMenu
*pFirstMenu
= 0;
3265 for (list
<CEmoteEntry
>::const_iterator it
= entries
.begin(); it
!= entries
.end(); it
++)
3267 uint32 nEmoteNb
= (*it
).EmoteId
;
3268 string sState
= (*it
).Anim
;
3269 string sName
= (*it
).Path
;
3271 // Check that the emote can be added to UI
3272 // ---------------------------------------
3273 if( (*it
).UsableFromClientUI
== false )
3278 // Check the emote reserved for FBT (hardcoded)
3279 // --------------------------------------------
3280 if (sState
== "FBT" && !betaTester
)
3283 // Get the behaviour from the list of emotes
3284 // -----------------------------------------
3287 for (i
= 0; i
< pEmotList
->Emots
.size(); ++i
)
3288 if (CAnimationStateSheet::getAnimationStateName(pEmotList
->Emots
[i
]) == sState
)
3294 // Add to the game context menu
3295 // ----------------------------
3297 for (i
= 0; i
< sName
.size(); ++i
)
3298 if (sName
[i
] == '|')
3301 CGroupMenu
*pRootMenu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:user_chat_emote_menu"));
3302 nlassert(pRootMenu
);
3304 CGroupSubMenu
*pMenu
= pRootMenu
->getRootMenu();
3307 std::string sTranslatedName
;
3308 std::string sCommandName
;
3309 std::string sCommandNameAlt
;
3311 // Add to the game context menu
3312 // ----------------------------
3313 for (i
= 0; i
< nbToken
; ++i
)
3316 if (i
!= (nbToken
-1))
3317 sTmp
= sName
.substr(0,sName
.find('|'));
3321 // Look if this part of the path is already present
3322 bool bFound
= false;
3323 for (j
= 0; j
< pMenu
->getNumLine(); ++j
)
3325 if (sTmp
== pMenu
->getLineId(j
))
3333 if (!bFound
) // Create it
3335 if (i
!= (nbToken
-1))
3337 pMenu
->addLine (CI18N::get(sTmp
), "", "", sTmp
);
3339 // Create a sub menu
3340 CGroupSubMenu
*pNewSubMenu
= new CGroupSubMenu(CViewBase::TCtorParam());
3341 pMenu
->setSubMenu(j
, pNewSubMenu
);
3343 if (pFirstMenu
== 0)
3344 pFirstMenu
= pNewSubMenu
;
3348 translateEmote(sTmp
, sTranslatedName
, sCommandName
, sCommandNameAlt
);
3351 pMenu
->addLine (sTranslatedName
+ " (/" + sCommandName
+ ")", "emote",
3352 "nb="+toString(nEmoteNb
)+"|behav="+toString(nBehav
), sTmp
);
3357 if (i
!= (nbToken
-1))
3359 pMenu
= pMenu
->getSubMenu(j
);
3360 sName
= sName
.substr(sName
.find('|')+1,sName
.size());
3364 if (sTranslatedName
.empty())
3365 translateEmote(sName
, sTranslatedName
, sCommandName
, sCommandNameAlt
);
3367 // Create new command
3368 // ------------------
3369 if (!sTranslatedName
.empty())
3371 if(ICommand::exists(sCommandName
))
3373 nlwarning("Translation for emote %s already exist: '%s' exist twice", sName
.c_str(), sCommandName
.c_str());
3377 CEmoteCmd
*pNewCmd
= new CEmoteCmd(sCommandName
.c_str(), "", "");
3378 pNewCmd
->EmoteNb
= nEmoteNb
;
3379 pNewCmd
->Behaviour
= nBehav
;
3380 _EmoteCmds
.push_back(pNewCmd
);
3382 // add alternative command if defined
3383 if (!sCommandNameAlt
.empty())
3385 if(ICommand::exists(sCommandNameAlt
))
3387 nlwarning("Translation for emote %s already exist: '%s' exist twice", sName
.c_str(), sCommandName
.c_str());
3391 CEmoteCmd
*pNewCmd
= new CEmoteCmd(sCommandNameAlt
.c_str(), "", "");
3392 pNewCmd
->EmoteNb
= nEmoteNb
;
3393 pNewCmd
->Behaviour
= nBehav
;
3394 _EmoteCmds
.push_back(pNewCmd
);
3398 CGroupSubMenu
*pMenu
= pRootMenu
->getRootMenu();
3400 // Quick-Emote too ?
3401 for (i
= 0; i
< pMenu
->getNumLine (); i
++)
3403 if (sName
== pMenu
->getLineId (i
))
3405 // Yeah that's a quick emote too; set command
3406 pMenu
->addLineAtIndex (i
,
3407 "@{FFFF}/" + sCommandName
,
3408 "emote", "nb="+toString(nEmoteNb
)+"|behav="+toString(nBehav
),
3409 "", "", "", false, false, true);
3411 pMenu
->removeLine (i
+1);
3419 nlwarning("No translation for emote %s", sName
.c_str());
3423 // Insert separators
3426 pFirstMenu
->addSeparatorAtIndex (0, "Positive");
3427 pFirstMenu
->addSeparatorAtIndex (4, "Neutral");
3428 pFirstMenu
->addSeparatorAtIndex (8, "Negative");
3433 // ***************************************************************************
3434 void CInterfaceManager::uninitEmotes()
3436 if( !_EmotesInitialized
)
3438 _EmotesInitialized
= false;
3440 // reset the emotes menu
3441 CTextEmotListSheet
*pTELS
= dynamic_cast<CTextEmotListSheet
*>(SheetMngr
.get(CSheetId("list.text_emotes")));
3442 if (pTELS
!= NULL
&& !pTELS
->TextEmotList
.empty())
3444 // get the emotes menu id
3445 string sPath
= pTELS
->TextEmotList
[0].Path
;
3446 string sId
= sPath
.substr(0, sPath
.find('|'));
3448 // get the emotes menu
3449 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3450 CGroupMenu
*pRootMenu
= dynamic_cast<CGroupMenu
*>(CWidgetManager::getInstance()->getElementFromId("ui:interface:game_context_menu"));
3453 CGroupSubMenu
*pMenu
= pRootMenu
->getRootMenu();
3454 for (uint i
= 0; i
< pMenu
->getNumLine(); ++i
)
3456 if (pMenu
->getLineId(i
) == sId
)
3458 pMenu
= pMenu
->getSubMenu(i
);
3467 for (uint32 i
= 0; i
< _EmoteCmds
.size(); ++i
)
3468 delete _EmoteCmds
[i
];
3472 // ***************************************************************************
3473 void CInterfaceManager::updateEmotes()
3479 // ***************************************************************************
3480 // Just call the action handler with good params
3481 bool CInterfaceManager::CEmoteCmd::execute(const std::string
&/* rawCommandString */, const vector
<string
> &args
, CLog
&/* log */, bool /* quiet */, bool /* human */)
3483 string customPhrase
;
3486 customPhrase
= args
[0];
3488 for(uint i
= 1; i
< args
.size(); ++i
)
3490 customPhrase
+= " ";
3491 customPhrase
+= args
[i
];
3493 CAHManager::getInstance()->runActionHandler("emote", NULL
, "nb="+toString(EmoteNb
)+"|behav="+toString(Behaviour
)+"|custom_phrase="+customPhrase
);
3497 // ***************************************************************************
3498 bool CInterfaceManager::testDragCopyKey()
3500 // hardcoded for now
3501 return Driver
->AsyncListener
.isKeyDown(KeyCONTROL
) ||
3502 Driver
->AsyncListener
.isKeyDown(KeyLCONTROL
) ||
3503 Driver
->AsyncListener
.isKeyDown(KeyRCONTROL
);
3506 // ***************************************************************************
3507 void CInterfaceManager::notifyMailAvailable()
3509 if (_CheckMailNode
!= NULL
)
3510 _CheckMailNode
->setValue32(1);
3513 void CInterfaceManager::notifyForumUpdated()
3515 if (_CheckForumNode
!= NULL
)
3516 _CheckForumNode
->setValue32(1);
3519 void CInterfaceManager::queueLuaScript(const std::string
&script
)
3521 CAutoMutex
<CMutex
> autoMutex(_ScriptQueueMutex
);
3523 _ScriptQueue
.push(script
);
3526 void CInterfaceManager::flushScriptQueue()
3528 CAutoMutex
<CMutex
> autoMutex(_ScriptQueueMutex
);
3530 while(!_ScriptQueue
.empty())
3532 CLuaManager::getInstance().executeLuaScript(_ScriptQueue
.front());
3538 // ***************************************************************************
3539 void CInterfaceManager::resetTextIndex()
3541 uint32 nMasterGroup
;
3542 std::vector
< CWidgetManager::SMasterGroup
> &_MasterGroups
= CWidgetManager::getInstance()->getAllMasterGroup();
3543 for (nMasterGroup
= 0; nMasterGroup
< _MasterGroups
.size(); nMasterGroup
++)
3545 CWidgetManager::SMasterGroup
&rMG
= _MasterGroups
[nMasterGroup
];
3547 InvalidateTextVisitor
inv( true );
3548 rMG
.Group
->visitGroupAndChildren( &inv
);
3549 for (uint8 nPriority
= 0; nPriority
< WIN_PRIORITY_MAX
; nPriority
++)
3551 list
<CInterfaceGroup
*> &rList
= rMG
.PrioritizedWindows
[nPriority
];
3552 list
<CInterfaceGroup
*>::const_iterator itw
;
3553 for (itw
= rList
.begin(); itw
!= rList
.end(); itw
++)
3555 CInterfaceGroup
*pIG
= *itw
;
3556 pIG
->visitGroupAndChildren( &inv
);
3562 // ***************************************************************************
3563 CInterfaceElement
*getInterfaceResource(const std::string
&key
)
3565 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3566 return CWidgetManager::getInstance()->getElementFromId (key
);
3569 // ***************************************************************************
3570 std::vector
<std::string
> CInterfaceManager::getInGameXMLInterfaceFiles()
3574 ret
= ClientCfg
.XMLInterfaceFiles
;
3576 // Resolve any conflict (with CPath scheme, AddOn Should take the precedence)
3577 // But still preserve order given in XMLInterfaceFiles (important for config.xml for instance)
3578 set
<string
> fileSet
;
3579 for(uint i
=0;i
<ret
.size();i
++)
3581 fileSet
.insert(ret
[i
]);
3584 // Add R2 Editor .xml. This is removed as it will not be done when initializing CEditor
3585 // if (ClientCfg.R2EDEnabled)
3587 // // Add them to 'ret', only if not already inserted
3588 // // since parser will crash on any duplicates
3589 // for(uint i=0;i<ClientCfg.XMLR2EDInterfaceFiles.size();i++)
3591 // if(fileSet.find(ClientCfg.XMLR2EDInterfaceFiles[i])==fileSet.end())
3593 // fileSet.insert(ClientCfg.XMLR2EDInterfaceFiles[i]);
3594 // ret.push_back(ClientCfg.XMLR2EDInterfaceFiles[i]);
3600 vector
<string
> adds
;
3601 InterfaceAddOnManager
.getFiles("*.xml", adds
);
3603 // Add them to 'ret', only if not already inserted
3604 for(uint i
=0;i
<adds
.size();i
++)
3606 if(fileSet
.find(adds
[i
])==fileSet
.end())
3608 fileSet
.insert(adds
[i
]);
3609 ret
.push_back(adds
[i
]);
3616 // ***************************************************************************
3617 void CInterfaceManager::dumpLuaString(const std::string
&str
)
3619 nlinfo(str
.c_str());
3620 displaySystemInfo(LuaHelperStuff::formatLuaErrorSysInfo(str
));
3623 // ***************************************************************************
3624 void CInterfaceManager::getLuaValueInfo(std::string
&str
, sint index
)
3626 CLuaState
&ls
= *( CLuaManager::getInstance().getLuaState() );
3628 sint type
= ls
.type(index
);
3633 else if(type
==LUA_TNUMBER
)
3635 str
= NLMISC::toString(ls
.isInteger(index
) ? ls
.toInteger(index
):ls
.toNumber(index
));
3637 else if(type
==LUA_TBOOLEAN
)
3639 str
= ls
.toBoolean(index
)?"true":"false";
3641 else if(type
==LUA_TSTRING
)
3643 ls
.toString(index
, str
);
3644 str
= toString("'") + str
+ toString("'");
3648 str
= ls
.getTypename(type
);
3650 str
+= NLMISC::toString("%p", ls
.toPointer(index
));
3651 // If its a table, append the size.
3652 if(type
==LUA_TTABLE
)
3654 ls
.pushNil(); // first key
3656 while (ls
.next(index
-1))
3658 ls
.pop(); // remove 'value'; keeps `key' for next iteration
3661 str
+= NLMISC::toString(" (size=%d)", count
);
3663 // If its a Userdata, try to display UI info
3664 else if(type
==LUA_TUSERDATA
)
3666 if(CLuaIHM::isUIOnStack(ls
, index
))
3668 CInterfaceElement
*ui
= CLuaIHM::getUIOnStack(ls
, index
);
3669 str
+= NLMISC::toString(" (ui=%p)", ui
);
3675 // ***************************************************************************
3676 void CInterfaceManager::dumpLuaKeyValueInfo(uint recursTableLevel
, uint tabLevel
)
3678 CLuaState
&ls
= *( CLuaManager::getInstance().getLuaState() );
3679 CLuaStackChecker
lsc(&ls
);
3683 getLuaValueInfo(key
, -2);
3686 getLuaValueInfo(value
, -1);
3690 // append tab for table hierarchy
3691 for(uint i
=0;i
<tabLevel
;i
++)
3693 // display key and value
3694 res
+= key
+ " == " + value
;
3697 // If the value is a table, and can recurs dumping
3698 if(recursTableLevel
>0 && ls
.type(-1)==LUA_TTABLE
)
3700 ls
.pushNil(); // first key
3703 // display the key value pair of this table (recurs)
3704 dumpLuaKeyValueInfo(recursTableLevel
-1, tabLevel
+1);
3705 ls
.pop(); // remove 'value'; keeps `key' for next iteration
3711 // ***************************************************************************
3712 void CInterfaceManager::dumpLuaState(uint detail
)
3714 CLuaState
*_LuaState
= CLuaManager::getInstance().getLuaState();
3716 // clamp detailed info to 2 (display at max content of eaxh Env of each group)
3717 clamp(detail
, 0U, 2U);
3719 // Dump the Memory State
3720 dumpLuaString(NLMISC::toString("Memory Used : %d Kb", _LuaState
->getGCCount()));
3721 dumpLuaString(NLMISC::toString("GC Threshold: %d Kb", _LuaState
->getGCThreshold()));
3723 // If want to display some detailed info
3726 CLuaState
&ls
= *_LuaState
;
3727 CLuaStackChecker
lsc(&ls
);
3729 // *** Dump all Lua Env Tables
3730 ls
.push(IHM_LUA_ENVTABLE
);
3731 ls
.getTable(LUA_REGISTRYINDEX
); // __ui_envtable
3732 ls
.pushNil(); // first key
3736 // `key' is at index -2 and `value' at index -1
3737 dumpLuaKeyValueInfo(detail
-1, 1);
3738 ls
.pop(); // remove 'value'; keeps `key' for next iteration
3744 dumpLuaString(NLMISC::toString("Number of EnvTable for ui groups: %d", count
));
3748 // ------------------------------------------------------------------------------------------------
3749 void CInterfaceManager::createLocalBranch(const std::string
&fileName
, NLMISC::IProgressCallback
&progressCallBack
)
3754 if (file
.open (fileName
))
3756 // Init an xml stream
3760 //Parse the parser output!!!
3761 CCDBNodeBranch
*localNode
= new CCDBNodeBranch("LOCAL");
3762 localNode
->init( read
.getRootNode (), progressCallBack
);
3763 NLGUI::CDBManager::getInstance()->getDB()->attachChild(localNode
,"LOCAL");
3765 // Create the observers for auto-copy SERVER->LOCAL of inventory
3766 ServerToLocalAutoCopyInventory
.init("INVENTORY");
3768 // Create the observers for auto-copy SERVER->LOCAL of exchange
3769 ServerToLocalAutoCopyExchange
.init("EXCHANGE");
3771 // Create the observers for auto-copy SERVER->LOCAL of dm (animator) gift
3772 ServerToLocalAutoCopyDMGift
.init("DM_GIFT");
3774 // Create the observers for auto-copy SERVER->LOCAL of context menu
3775 ServerToLocalAutoCopyContextMenu
.init("TARGET:CONTEXT_MENU");
3777 // Create the observers for auto-copy SERVER->LOCAL of Skill Points
3778 ServerToLocalAutoCopySkillPoints
.init("USER");
3781 catch (const Exception
&e
)
3784 nlwarning ("CFormLoader: Error while loading the form %s: %s", fileName
.c_str(), e
.what());
3788 // ------------------------------------------------------------------------------------------------
3789 #ifdef NL_OS_WINDOWS
3790 # pragma warning (push)
3791 # pragma warning (disable : 4355) // 'this' used in base member initializer list
3793 CInterfaceManager::CServerToLocalAutoCopy::CServerToLocalAutoCopy() : _LocalObserver(*this), _ServerObserver(*this)
3795 _ServerCounter
= NULL
;
3796 _UpdateList
.reserve(300);
3797 _LocalUpdating
= false;
3799 #ifdef NL_OS_WINDOWS
3800 # pragma warning (pop)
3803 // ------------------------------------------------------------------------------------------------
3804 // unhook from everything we are tangled up in
3805 void CInterfaceManager::CServerToLocalAutoCopy::release()
3808 _ServerCounter
= NULL
;
3809 _ServerNodeMap
.clear();
3810 _LocalNodeMap
.clear();
3811 _UpdateList
.clear();
3814 // ------------------------------------------------------------------------------------------------
3815 void CInterfaceManager::CServerToLocalAutoCopy::buildRecursLocalLeaves(CCDBNodeBranch
*branch
, std::vector
<CCDBNodeLeaf
*> &leaves
)
3817 for(uint i
=0;i
<branch
->getNbNodes();i
++)
3819 ICDBNode
*node
= branch
->getNode(i
);
3822 CCDBNodeLeaf
*leaf
= dynamic_cast<CCDBNodeLeaf
*>(node
);
3825 // just append to list
3826 leaves
.push_back(leaf
);
3830 // recurs if a branch (should be...)
3831 CCDBNodeBranch
*sonBranch
= dynamic_cast<CCDBNodeBranch
*>(node
);
3833 buildRecursLocalLeaves(sonBranch
, leaves
);
3839 // ------------------------------------------------------------------------------------------------
3840 void CInterfaceManager::CServerToLocalAutoCopy::init(const std::string
&dbPath
)
3842 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3844 // Get the synchronisation Counter in Server DB
3845 _ServerCounter
= NLGUI::CDBManager::getInstance()->getDbProp(string("SERVER:") + dbPath
+ ":COUNTER", false);
3850 ICDBNode::CTextId textId
;
3852 // **** Add Observers on all nodes
3853 // add the observers when server node change
3854 textId
= ICDBNode::CTextId( string("SERVER:") + dbPath
);
3855 NLGUI::CDBManager::getInstance()->getDB()->addObserver(&_ServerObserver
, textId
);
3857 // add the observers when local node change
3858 textId
= ICDBNode::CTextId( string("LOCAL:") + dbPath
);
3859 NLGUI::CDBManager::getInstance()->getDB()->addObserver(&_LocalObserver
, textId
);
3861 // **** Init the Nodes shortcut
3862 // Parse all Local Nodes
3863 CCDBNodeBranch
*localBranch
= NLGUI::CDBManager::getInstance()->getDbBranch(string("LOCAL:") + dbPath
);
3867 std::vector
<CCDBNodeLeaf
*> leaves
;
3868 buildRecursLocalLeaves(localBranch
, leaves
);
3871 _Nodes
.reserve(leaves
.size());
3872 for(i
=0;i
<leaves
.size();i
++)
3874 CCDBNodeLeaf
*localLeaf
= leaves
[i
];
3876 // get the SERVER associated node name
3877 string serverLeafStr
= *localLeaf
->getName();
3878 CCDBNodeBranch
* parent
= localLeaf
->getParent();
3879 while( *parent
->getName()!="LOCAL" )
3881 serverLeafStr
= *parent
->getName()+":"+serverLeafStr
;
3882 parent
= parent
->getParent();
3884 serverLeafStr
= "SERVER:" + serverLeafStr
;
3886 // try then to get this server node
3887 CCDBNodeLeaf
*serverLeaf
= NLGUI::CDBManager::getInstance()->getDbProp(serverLeafStr
, false);
3890 // Both server and local leaves exist, ok, append to _Nodes
3892 node
.ServerNode
= serverLeaf
;
3893 node
.LocalNode
= localLeaf
;
3894 _Nodes
.push_back(node
);
3898 // --- Init the maps
3899 _ServerNodeMap
.reserve(leaves
.size());
3900 _LocalNodeMap
.reserve(leaves
.size());
3901 // For all valid _Nodes, insert in "map"
3902 for(i
=0;i
<_Nodes
.size();i
++)
3906 lc
.Node
= &_Nodes
[i
];
3907 sc
.Node
= &_Nodes
[i
];
3908 _LocalNodeMap
.push_back(lc
);
3909 _ServerNodeMap
.push_back(sc
);
3912 sort(_LocalNodeMap
.begin(), _LocalNodeMap
.end());
3913 sort(_ServerNodeMap
.begin(), _ServerNodeMap
.end());
3919 // ------------------------------------------------------------------------------------------------
3920 void CInterfaceManager::CServerToLocalAutoCopy::onServerChange(ICDBNode
*serverNode
)
3924 CCDBNodeLeaf
*serverLeaf
= safe_cast
<CCDBNodeLeaf
*>(serverNode
);
3925 CInterfaceManager
*pIM
= CInterfaceManager::getInstance();
3927 // Add the leaf to the update list. only if not the counter
3928 if(serverLeaf
!= _ServerCounter
)
3930 // build the map key
3933 nodeComp
.ServerNode
= serverLeaf
;
3935 // try to find the node associated to this server leaf
3936 uint index
= searchLowerBound(_ServerNodeMap
, sc
);
3938 if( index
>0 || _ServerNodeMap
[0].Node
->ServerNode
==serverLeaf
)
3940 CNode
*node
= _ServerNodeMap
[index
].Node
;
3941 // if this node is not already inserted
3942 if(!node
->InsertedInUpdateList
)
3945 node
->InsertedInUpdateList
= true;
3946 _UpdateList
.push_back(node
);
3951 // if the client and server are synchonized.
3952 if( ClientCfg
.Local
|| pIM
->localActionCounterSynchronizedWith(_ServerCounter
) )
3954 // update all leaves
3955 for(uint i
=0;i
<_UpdateList
.size();i
++)
3957 CNode
*node
= _UpdateList
[i
];
3959 _LocalUpdating
= true;
3960 node
->LocalNode
->setValue64(node
->ServerNode
->getValue64());
3961 _LocalUpdating
= false;
3963 // reset inserted flag
3964 node
->InsertedInUpdateList
= false;
3967 // clear update list
3968 _UpdateList
.clear();
3972 // ------------------------------------------------------------------------------------------------
3973 void CInterfaceManager::CServerToLocalAutoCopy::onLocalChange(ICDBNode
*localNode
)
3978 // if the local changes because of localLeaf->setValue64() in onServerChange(), no-op !!!
3982 CCDBNodeLeaf
*localLeaf
= safe_cast
<CCDBNodeLeaf
*>(localNode
);
3984 // Add the leaf to the update list
3985 // build the map key
3988 nodeComp
.LocalNode
= localLeaf
;
3990 // try to find the node associated to this local leaf
3991 uint index
= searchLowerBound(_LocalNodeMap
, lc
);
3993 if( index
>0 || _LocalNodeMap
[0].Node
->LocalNode
==localLeaf
)
3995 CNode
*node
= _LocalNodeMap
[index
].Node
;
3996 // if this node is not already inserted
3997 if(!node
->InsertedInUpdateList
)
4000 node
->InsertedInUpdateList
= true;
4001 _UpdateList
.push_back(node
);
4006 // ------------------------------------------------------------------------------------------------
4007 bool CInterfaceManager::use12hClock()
4009 CCDBNodeLeaf
*node
= NLGUI::CDBManager::getInstance()->getDbProp("UI:SAVE:SHOW_CLOCK_12H", false);
4011 return (node
&& node
->getValueBool());
4014 // ------------------------------------------------------------------------------------------------
4015 char* CInterfaceManager::getTimestampHuman(const char* format
/* "[%H:%M:%S] " */)
4017 static char cstime
[25];
4020 struct tm
*tms
= localtime(&date
);
4023 strftime(cstime
, 25, format
, tms
);
4035 * Parse tokens in a chatmessage or emote
4048 * $<subject>.gs(m/f/n)$
4050 * Default parameter if parameter result is empty:
4051 * $<subject>.<parameter>/<default>$
4053 * All \d's in default parameter remove a following character.
4055 bool CInterfaceManager::parseTokens(string
& ucstr
)
4058 string
start_token("$");
4059 string
end_token("$");
4060 size_t start_pos
= 0;
4063 sint endless_loop_protector
= 0;
4064 while ((start_pos
< str
.length() - 1) &&
4065 ((start_pos
= str
.find(start_token
, start_pos
)) != string::npos
))
4067 endless_loop_protector
++;
4068 if (endless_loop_protector
> 100)
4073 // Get the whole token substring first
4074 end_pos
= str
.find(end_token
, start_pos
+ 1);
4076 if ((start_pos
== string::npos
) ||
4077 (end_pos
== string::npos
) ||
4078 (end_pos
<= start_pos
+ 1))
4080 // Wrong formatting; give up on this one.
4081 start_pos
= max(start_pos
, end_pos
);
4085 // Get everything between the two "$"
4086 size_t token_start_pos
= start_pos
+ start_token
.length();
4087 size_t token_end_pos
= end_pos
- end_token
.length();
4088 if (token_start_pos
> token_end_pos
)
4090 // Wrong formatting; give up on this one.
4091 start_pos
= end_pos
;
4095 string token_whole
= str
.substr(start_pos
, end_pos
- start_pos
+ 1);
4096 string token_string
= token_whole
.substr(1, token_whole
.length() - 2);
4097 string token_replacement
= token_whole
;
4098 string token_default
= token_whole
;
4100 string token_subject
;
4103 // Does the token have a parameter?
4104 // If not it is 'name' by default
4105 vector
<string
> token_vector
;
4106 vector
<string
> param_vector
;
4107 splitString(token_string
, ".", token_vector
);
4108 if (token_vector
.empty())
4110 // Wrong formatting; give up on this one.
4111 start_pos
= end_pos
;
4114 token_subject
= token_vector
[0];
4115 if (token_vector
.size() == 1)
4117 splitString(token_subject
, "/", param_vector
);
4118 token_subject
= !param_vector
.empty() ? param_vector
[0] : string();
4119 token_param
= string("name");
4121 else if (token_vector
.size() > 1)
4123 token_param
= token_vector
[1];
4124 if (token_param
.substr(0, 3) != "gs(")
4126 splitString(token_vector
[1], "/", param_vector
);
4127 token_param
= !param_vector
.empty() ? param_vector
[0] : string();
4131 // Get any default value, if not gs
4132 sint extra_replacement
= 0;
4133 if (token_param
.substr(0, 3) != "gs(")
4135 if (param_vector
.size() == 2)
4137 // Set default value
4138 token_replacement
= param_vector
[1];
4139 // Delete following chars for every '\d' in default
4140 string::size_type token_replacement_pos
;
4141 while ((token_replacement_pos
= token_replacement
.find(string("\\d"))) != string::npos
)
4143 token_replacement
.replace(token_replacement_pos
, 2, string());
4144 extra_replacement
++;
4146 token_default
= token_replacement
;
4150 CEntityCL
*pTokenSubjectEntity
= NULL
;
4152 if (token_subject
== "me")
4154 pTokenSubjectEntity
= static_cast<CEntityCL
*>(UserEntity
);
4156 else if (token_subject
== "t")
4159 uint targetSlot
= UserEntity
->targetSlot();
4160 pTokenSubjectEntity
= EntitiesMngr
.entity(targetSlot
);
4162 else if (token_subject
== "tt")
4165 uint targetSlot
= UserEntity
->targetSlot();
4166 CEntityCL
*target
= EntitiesMngr
.entity(targetSlot
);
4170 // Check the new slot.
4171 CLFECOMMON::TCLEntityId newSlot
= target
->targetSlot();
4172 CEntityCL
* pE
= EntitiesMngr
.entity(newSlot
);
4175 pTokenSubjectEntity
= pE
;
4179 else if ((token_subject
.length() == 3) &&
4180 (token_subject
.substr(0, 2) == "tm"))
4183 uint indexInTeam
= 0;
4184 fromString(token_subject
.substr(2, 1), indexInTeam
);
4188 if (indexInTeam
< PeopleInterraction
.TeamList
.getNumPeople() )
4190 // Index is the database index (serverIndex() not used for team list)
4191 CCDBNodeLeaf
*pNL
= NLGUI::CDBManager::getInstance()->getDbProp( NLMISC::toString(TEAM_DB_PATH
":%hu:NAME", indexInTeam
), false);
4192 if (pNL
&& pNL
->getValueBool() )
4194 // There is a character corresponding to this index
4195 pNL
= NLGUI::CDBManager::getInstance()->getDbProp( NLMISC::toString( TEAM_DB_PATH
":%hu:UID", indexInTeam
), false );
4198 CLFECOMMON::TClientDataSetIndex compressedIndex
= pNL
->getValue32();
4200 // Search entity in vision
4201 CEntityCL
*entity
= EntitiesMngr
.getEntityByCompressedIndex( compressedIndex
);
4204 pTokenSubjectEntity
= entity
;
4212 // Unknown token subject, skip it
4213 start_pos
= end_pos
;
4217 if (pTokenSubjectEntity
!= NULL
)
4219 // Parse the parameter
4220 if (token_param
== "name")
4222 string name
= pTokenSubjectEntity
->getDisplayName();
4223 // special case where there is only a title, very rare case for some NPC
4226 name
= pTokenSubjectEntity
->getTitle();
4228 token_replacement
= name
.empty() ? token_replacement
: name
;
4230 else if (token_param
== "title")
4232 string title
= pTokenSubjectEntity
->getTitle();
4233 token_replacement
= title
.empty() ? token_replacement
: title
;
4235 else if (token_param
== "race")
4237 CCharacterCL
*pC
= dynamic_cast<CCharacterCL
*>(pTokenSubjectEntity
);
4240 EGSPD::CPeople::TPeople race
= pC
->people();
4241 if (race
>= EGSPD::CPeople::Playable
&& race
<= EGSPD::CPeople::EndPlayable
)
4243 string srace
= NLMISC::CI18N::get("io" + EGSPD::CPeople::toString(race
));
4244 token_replacement
= srace
.empty() ? token_replacement
: srace
;
4248 else if (token_param
== "guild")
4250 STRING_MANAGER::CStringManagerClient
*pSMC
= STRING_MANAGER::CStringManagerClient::instance();
4252 if (pSMC
->getString(pTokenSubjectEntity
->getGuildNameID(), ucGuildName
))
4254 token_replacement
= ucGuildName
.empty() ? token_replacement
: ucGuildName
;
4257 else if (token_param
.substr(0, 3) == "gs(" &&
4258 token_param
.substr(token_param
.length() - 1 , 1) == ")")
4261 vector
<string
> strList
;
4262 string gender_string
= token_param
.substr(3, token_param
.length() - 4);
4263 splitString(gender_string
, "/", strList
);
4265 if (strList
.size() <= 1)
4267 start_pos
= end_pos
;
4271 // We only care about the gender if the subject is humanoid.
4272 GSGENDER::EGender gender
= GSGENDER::neutral
;
4273 if (pTokenSubjectEntity
->isUser() || pTokenSubjectEntity
->isPlayer() || pTokenSubjectEntity
->isNPC())
4275 CCharacterCL
*pC
= dynamic_cast<CCharacterCL
*>(pTokenSubjectEntity
);
4278 gender
= pC
->getGender();
4282 // The neuter part is optional. Fallback to male if something is wrong.
4283 GSGENDER::EGender g
= ((uint
)gender
>= strList
.size()) ? GSGENDER::male
: gender
;
4284 token_replacement
= strList
[g
];
4288 if (token_whole
== token_replacement
)
4290 // Nothing to replace; show message and exit
4291 CInterfaceManager
*im
= CInterfaceManager::getInstance();
4292 string message
= CI18N::get("uiUntranslatedToken");
4293 message
.replace(message
.find("%s"), 2, token_whole
);
4294 im
->displaySystemInfo(message
);
4299 size_t token_whole_pos
= str
.find(token_whole
);
4301 // Only do extra replacement spaces if using default
4302 extra_replacement
= (token_replacement
== token_default
) ? extra_replacement
: 0;
4303 if (str
.find(token_whole
, start_pos
) != string::npos
)
4305 str
= str
.replace(token_whole_pos
, token_whole
.length() + extra_replacement
, token_replacement
);
4306 start_pos
= token_whole_pos
+ token_replacement
.length();
4314 std::string
CInterfaceManager::getNextBackupName(std::string filename
)
4316 std::string ts
= getTimestampHuman("%Y-%m-%d");
4320 std::string::size_type pos
= filename
.find_last_of('.');
4321 if (pos
== std::string::npos
)
4322 filename
= filename
+ "_" + ts
+ "_";
4324 filename
= filename
.substr(0, pos
) + "_" + ts
+ "_" + filename
.substr(pos
);
4327 // filename_YYYY-MM-DD_000.ext
4328 return CFile::findNewFile(filename
);
4331 void CInterfaceManager::createFileBackup(const std::string
&message
, const std::string
&filename
, bool useCopy
)
4333 std::string backupName
= getNextBackupName(filename
);
4334 nlwarning("%s: '%s'.", message
.c_str(), filename
.c_str());
4335 if (!backupName
.empty())
4339 nlwarning("Backup copy saved as '%s'", backupName
.c_str());
4340 CFile::copyFile(backupName
, filename
);
4344 nlwarning("File renamed to '%s'", backupName
.c_str());
4345 CFile::moveFile(backupName
, filename
);