// Ryzom - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . // ---------------------------------------------------------------------------- #include "stdpch.h" #include "nel/misc/i_xml.h" #include "nel/misc/file.h" #include "nel/misc/algo.h" #include "nel/misc/mem_stream.h" #include "nel/misc/factory.h" #include "game_share/xml_auto_ptr.h" #include "interface_parser.h" #include "interface_observer.h" #include "interface_options.h" #include "interface_anim.h" #include "interface_3d_scene.h" // View #include "view_bitmap.h" #include "view_bitmap_faber_mp.h" #include "view_bitmap_combo.h" #include "view_text.h" #include "view_text_formated.h" #include "view_text_id.h" #include "view_text_id_formated.h" #include "view_radar.h" #include "view_pointer.h" // DBView (View linked to the database) #include "dbview_bar.h" #include "dbview_bar3.h" #include "dbview_number.h" #include "dbview_quantity.h" #include "dbview_digit.h" // Ctrl #include "ctrl_scroll.h" #include "ctrl_button.h" #include "ctrl_col_pick.h" #include "ctrl_tooltip.h" #include "ctrl_text_button.h" #include "group_paragraph.h" // For CCtrlLink // DBCtrl #include "dbctrl_sheet.h" // Group #include "group_frame.h" #include "group_career.h" #include "group_modal.h" #include "group_modal_get_key.h" #include "group_list.h" #include "group_tree.h" #include "group_menu.h" #include "group_container.h" #include "group_scrolltext.h" #include "group_editbox.h" #include "group_skills.h" #include "group_html_forum.h" #include "group_html_mail.h" #include "group_html_qcm.h" #include "group_html_cs.h" #include "group_quick_help.h" #include "group_compas.h" #include "group_map.h" #include "group_in_scene_user_info.h" #include "group_in_scene_bubble.h" #include "group_phrase_skill_filter.h" #include "group_tab.h" #include "group_table.h" // DBGroup #include "dbgroup_select_number.h" #include "dbgroup_list_sheet.h" #include "dbgroup_combo_box.h" #include "dbgroup_list_sheet_trade.h" #include "dbgroup_list_sheet_mission.h" #include "guild_manager.h" // for CDBGroupListAscensor #include "dbgroup_build_phrase.h" #include "dbgroup_list_sheet_text_phrase.h" #include "dbgroup_list_sheet_text_phrase_id.h" #include "dbgroup_list_sheet_text_brick_composition.h" #include "dbgroup_list_sheet_text_share.h" #include "dbgroup_list_sheet_bonus_malus.h" #include "dbgroup_list_sheet_icon_phrase.h" // Misc. #include "interface_link.h" #include "interface_ddx.h" #include "../actions.h" #include "macrocmd_manager.h" #include "inventory_manager.h" #include "task_bar_manager.h" #include "../commands.h" #include "lua_helper.h" #include "lua_ihm.h" #ifdef LUA_NEVRAX_VERSION #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger #endif const uint32 UI_CACHE_SERIAL_CHECK = (uint32) 'IUG_'; void saveXMLTree(COFile &f, xmlNodePtr node) { // save node name std::string name = (const char *) node->name; f.serial(name); // save properties uint32 numProp = 0; xmlAttrPtr currProp = node->properties; while (currProp) { ++ numProp; currProp = currProp->next; } f.serial(numProp); currProp = node->properties; while (currProp) { std::string name = (const char *) currProp->name; f.serial(name); CXMLAutoPtr ptr(xmlGetProp(node, currProp->name)); std::string value = (const char *) ptr; f.serial(value); currProp = currProp->next; } uint32 numChildren = 0; xmlNodePtr currChild = node->children; while (currChild) { ++ numChildren; currChild = currChild->next; } f.serial(numChildren); currChild = node->children; while (currChild) { saveXMLTree(f, currChild); currChild = currChild->next; } } xmlNodePtr buildTree(CIFile &f) { // load node name std::string name; f.serial(name); xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *) name.c_str()); // slod properties uint32 numProp; f.serial(numProp); for(uint k = 0; k < numProp; ++k) { std::string name, value; f.serial(name, value); xmlSetProp(node, (const xmlChar *) name.c_str(), (const xmlChar *) value.c_str()); } uint32 numChildren; f.serial(numChildren); for(uint k = 0; k < numChildren; ++k) { xmlAddChild(node, buildTree(f)); } return node; } // ---------------------------------------------------------------------------- extern CActionsManager Actions; // Actions Manager. extern CActionsManager EditActions; // Actions Manager. extern CActionsContext ActionsContext; // Actions context. // ---------------------------------------------------------------------------- using namespace NLMISC; using namespace std; // ---------------------------------------------------------------------------- // CRootGroup // ---------------------------------------------------------------------------- class CRootGroup : public CInterfaceGroup { public: CRootGroup(const TCtorParam ¶m) : CInterfaceGroup(param) { } /// Destructor virtual ~CRootGroup() { } virtual CInterfaceElement* getElement (const std::string &id) { if (_Id == id) return this; if (id.substr(0, _Id.size()) != _Id) return NULL; vector::const_iterator itv; for (itv = _Views.begin(); itv != _Views.end(); itv++) { CViewBase *pVB = *itv; if (pVB->getId() == id) return pVB; } vector::const_iterator itc; for (itc = _Controls.begin(); itc != _Controls.end(); itc++) { CCtrlBase* ctrl = *itc; if (ctrl->getId() == id) return ctrl; } // Accelerate string sTmp = id; sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); string::size_type pos = sTmp.find(':'); if (pos != string::npos) sTmp = sTmp.substr(0,pos); map::iterator it = _Accel.find(sTmp); if (it != _Accel.end()) { CInterfaceGroup *pIG = it->second; return pIG->getElement(id); } return NULL; } virtual void addGroup (CInterfaceGroup *child, sint eltOrder = -1) { string sTmp = child->getId(); sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); _Accel.insert(pair(sTmp, child)); CInterfaceGroup::addGroup(child,eltOrder); } virtual bool delGroup (CInterfaceGroup *child, bool dontDelete = false) { string sTmp = child->getId(); sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); map::iterator it = _Accel.find(sTmp); if (it != _Accel.end()) { _Accel.erase(it); } return CInterfaceGroup::delGroup(child,dontDelete); } private: map _Accel; }; // ---------------------------------------------------------------------------- // SMasterGroup // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::addWindow(CInterfaceGroup *pIG, uint8 nPrio) { nlassert(nPrio(pIG)!=NULL)); for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { // If the element already exists in the list return ! if (*it == pIG) return; it++; } } PrioritizedWindows[nPrio].push_back(pIG); } // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::delWindow(CInterfaceGroup *pIG) { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { if ((*it) == pIG) { PrioritizedWindows[i].erase(it); return; } it++; } } } // ---------------------------------------------------------------------------- CInterfaceGroup* CInterfaceParser::SMasterGroup::getWindowFromId(const std::string &winID) { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { if ((*it)->getId() == winID) return *it; it++; } } return NULL; } // ---------------------------------------------------------------------------- bool CInterfaceParser::SMasterGroup::isWindowPresent(CInterfaceGroup *pIG) { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { if ((*it) == pIG) return true; it++; } } return false; } // Set a window top in its priority queue // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::setTopWindow(CInterfaceGroup *pIG) { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { if (*it == pIG) { PrioritizedWindows[i].erase(it); PrioritizedWindows[i].push_back(pIG); LastTopWindowPriority= i; return; } it++; } } // todo hulud interface syntax error nlwarning("window %s do not exist in a priority list", pIG->getId().c_str()); } // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::setBackWindow(CInterfaceGroup *pIG) { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { if (*it == pIG) { PrioritizedWindows[i].erase(it); PrioritizedWindows[i].push_front(pIG); return; } it++; } } // todo hulud interface syntax error nlwarning("window %s do not exist in a priority list", pIG->getId().c_str()); } // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::deactiveAllContainers() { vector gcs; // Make first a list of all window (Warning: all group container are not window!) for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { CGroupContainer *pGC = dynamic_cast(*it); if (pGC != NULL) gcs.push_back(pGC); it++; } } // Then hide them. Must do this in 2 times, because setActive(false) change PrioritizedWindows, // and hence invalidate its. for (uint32 i = 0; i < gcs.size(); ++i) { gcs[i]->setActive(false); } } // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::centerAllContainers() { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { CGroupContainer *pGC = dynamic_cast(*it); if ((pGC != NULL) && (pGC->getParent() != NULL)) { sint32 wParent = pGC->getParent()->getW(false); sint32 w = pGC->getW(false); pGC->setXAndInvalidateCoords((wParent - w) / 2); sint32 hParent = pGC->getParent()->getH(false); sint32 h = pGC->getH(false); pGC->setYAndInvalidateCoords(h+(hParent - h) / 2); } it++; } } } // ---------------------------------------------------------------------------- void CInterfaceParser::SMasterGroup::unlockAllContainers() { for (uint8 i = 0; i < WIN_PRIORITY_MAX; ++i) { list::iterator it = PrioritizedWindows[i].begin(); while (it != PrioritizedWindows[i].end()) { CGroupContainer *pGC = dynamic_cast(*it); if (pGC != NULL) pGC->setLocked(false); it++; } } } // ---------------------------------------------------------------------------- // CInterfaceParser // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- CInterfaceParser::CInterfaceParser() { _Pointer= NULL; // LUA _LuaState= NULL; } CInterfaceParser::~CInterfaceParser() { // delete _Pointer; _Pointer = NULL; delete _LuaState; _LuaState = NULL; } /** Convert a string into a memstream */ static void interfaceScriptAsMemStream(const std::string &script, CMemStream &destStream) { NLMISC::contReset(destStream); if (destStream.isReading()) // we must be sure that we are reading the stream { destStream.invert(); } destStream.seek(0, NLMISC::IStream::begin); if (script.empty()) return; destStream.serialBuffer(const_cast((const uint8 *) &script[0]), script.size()); destStream.invert(); destStream.seek(0, NLMISC::IStream::begin); } // ---------------------------------------------------------------------------- bool CInterfaceParser::parseInterface (const std::vector & strings, bool reload, bool isFilename) { bool ok; // TestYoyo. UnHide For Parsing Profile /* NLMISC::CHTimer::startBench(); { H_AUTO(parseInterface); */ //ignore the content of tags containing only white space xmlKeepBlanksDefault(0); //parse all interface files and build a single xml document xmlNodePtr globalEnclosing; nlassert (strings.size()); CIXml read; string nextFileName; static const char *SCRIPT_AS_STRING = "