From 82ee05667e093de26104ee6a1bef15aa54125588 Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Wed, 23 May 2012 02:41:43 +0200 Subject: [PATCH] Added: #1471 CLuaManager, Singleton for the Lua state, the code parts that depend on a globally available Lua state now depend on this instead of CInterfaceManager. Also refactored the code so it's ready to be moved to the NELGUI lib. --- code/ryzom/client/src/commands.cpp | 3 +- code/ryzom/client/src/debug_client.cpp | 3 +- code/ryzom/client/src/init_main_loop.cpp | 3 +- .../client/src/interface_v3/ctrl_scroll.cpp | 5 +- .../src/interface_v3/ctrl_text_button.cpp | 3 +- .../client/src/interface_v3/dbctrl_sheet.cpp | 9 +- .../client/src/interface_v3/group_list.cpp | 19 +- .../client/src/interface_v3/group_menu.cpp | 19 +- .../client/src/interface_v3/group_tab.cpp | 9 +- .../client/src/interface_v3/group_tree.cpp | 3 +- .../src/interface_v3/interface_element.cpp | 26 +- .../src/interface_v3/interface_element.h | 13 - .../src/interface_v3/interface_group.cpp | 16 +- .../src/interface_v3/interface_manager.cpp | 4 +- .../src/interface_v3/interface_manager.h | 2 - .../src/interface_v3/interface_parser.cpp | 11 +- .../ryzom/client/src/interface_v3/lua_ihm.cpp | 826 +----------------- code/ryzom/client/src/interface_v3/lua_ihm.h | 19 - .../client/src/interface_v3/lua_ihm_ryzom.cpp | 738 +++++++++++++++- .../client/src/interface_v3/lua_ihm_ryzom.h | 21 + .../client/src/interface_v3/lua_manager.cpp | 34 + .../client/src/interface_v3/lua_manager.h | 57 ++ .../client/src/interface_v3/lua_object.cpp | 4 +- .../ryzom/client/src/interface_v3/reflect.cpp | 62 +- code/ryzom/client/src/interface_v3/reflect.h | 25 +- code/ryzom/client/src/main_loop.cpp | 16 +- code/ryzom/client/src/r2/editor.cpp | 5 +- code/ryzom/client/src/release.cpp | 3 + 28 files changed, 978 insertions(+), 980 deletions(-) create mode 100644 code/ryzom/client/src/interface_v3/lua_manager.cpp create mode 100644 code/ryzom/client/src/interface_v3/lua_manager.h diff --git a/code/ryzom/client/src/commands.cpp b/code/ryzom/client/src/commands.cpp index 433bd2d49..3f0855f87 100644 --- a/code/ryzom/client/src/commands.cpp +++ b/code/ryzom/client/src/commands.cpp @@ -99,6 +99,7 @@ #include "interface_v3/people_interraction.h" #include "far_tp.h" #include "zone_util.h" +#include "interface_v3/lua_manager.h" // @@ -5146,7 +5147,7 @@ NLMISC_COMMAND(luaObject, "Dump the content of a lua object", " [max pIM->displaySystemInfo( LuaHelperStuff::formatLuaErrorSysInfo(LUADebugNotEnabledMsg)); return false; } - CLuaState *luaState = pIM->getLuaState(); + CLuaState *luaState = CLuaManager::getInstance().getLuaState(); if (!luaState) return false; CLuaStackChecker lsc(luaState); // get the table diff --git a/code/ryzom/client/src/debug_client.cpp b/code/ryzom/client/src/debug_client.cpp index c12b2d6e0..c989a09f5 100644 --- a/code/ryzom/client/src/debug_client.cpp +++ b/code/ryzom/client/src/debug_client.cpp @@ -45,6 +45,7 @@ using namespace NLGUI; #include "character_cl.h" #include "r2/editor.h" #include "r2/dmc/client_edition_module.h" +#include "interface_v3/lua_manager.h" /////////// // USING // @@ -327,7 +328,7 @@ void displayStreamingDebug () SpfGraph.addOneValue (1000.f*(float)deltaTime); // lua memory - LuaMemGraph.addOneValue(CInterfaceManager::getInstance()->getLuaState()->getGCCount() / 1024.f); + LuaMemGraph.addOneValue(CLuaManager::getInstance().getLuaState()->getGCCount() / 1024.f); // Count of waitinf instance CurrentTaskGraph.addOneValue (CAsyncFileManager::getInstance().isTaskRunning()?1.f:0.f); diff --git a/code/ryzom/client/src/init_main_loop.cpp b/code/ryzom/client/src/init_main_loop.cpp index 45fa7b59e..fafb7ef34 100644 --- a/code/ryzom/client/src/init_main_loop.cpp +++ b/code/ryzom/client/src/init_main_loop.cpp @@ -104,6 +104,7 @@ #include "landscape_poly_drawer.h" #include "session_browser_impl.h" +#include "interface_v3/lua_manager.h" // ProgressBar steps in init main loop @@ -1320,7 +1321,7 @@ void initMainLoop() // init CSessionBrowserImpl - CSessionBrowserImpl::getInstance().init(CInterfaceManager::getInstance()->getLuaState()); + CSessionBrowserImpl::getInstance().init(CLuaManager::getInstance().getLuaState()); // active/desactive welcome window initWelcomeWindow(); diff --git a/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp b/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp index 252ff3236..f9abe1f3a 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp +++ b/code/ryzom/client/src/interface_v3/ctrl_scroll.cpp @@ -23,6 +23,7 @@ #include "group_menu.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" using namespace NLMISC; using namespace std; @@ -916,7 +917,7 @@ int CCtrlScroll::luaEnsureVisible(CLuaState &ls) { const char *funcName = "ensureVisible"; CLuaIHM::checkArgCount(ls, funcName, 3); - CLuaIHM::checkArgTypeUIElement(ls, funcName, 1); + CLuaIHMRyzom::checkArgTypeUIElement(ls, funcName, 1); CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING); CLuaIHM::checkArgType(ls, funcName, 3, LUA_TSTRING); THotSpot hs[2]; @@ -967,7 +968,7 @@ int CCtrlScroll::luaEnsureVisible(CLuaState &ls) } } } - ensureVisible(CLuaIHM::getUIOnStack(ls, 1), hs[0], hs[1]); + ensureVisible(CLuaIHMRyzom::getUIOnStack(ls, 1), hs[0], hs[1]); return 0; } diff --git a/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp b/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp index de302dbb1..17e713992 100644 --- a/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp +++ b/code/ryzom/client/src/interface_v3/ctrl_text_button.cpp @@ -27,6 +27,7 @@ #include "view_text_id.h" #include "group_container.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" // *************************************************************************** @@ -548,7 +549,7 @@ int CCtrlTextButton::luaGetViewText(CLuaState &ls) { const char *funcName = "getViewText"; CLuaIHM::checkArgCount(ls, funcName, 0); - CLuaIHM::pushUIOnStack(ls, getViewText()); + CLuaIHMRyzom::pushUIOnStack(ls, getViewText()); return 1; } diff --git a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp index 46efd5514..06f16e379 100644 --- a/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp +++ b/code/ryzom/client/src/interface_v3/dbctrl_sheet.cpp @@ -45,10 +45,13 @@ #include "../client_sheets/sphrase_sheet.h" #include "nel/misc/xml_auto_ptr.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "game_share/bot_chat_types.h" #include "../r2/editor.h" +#include "lua_manager.h" + extern CSheetManager SheetMngr; using namespace std; @@ -101,7 +104,7 @@ ucstring CControlSheetTooltipInfoWaiter::infoValidated(CDBCtrlSheet* ctrlSheet, // delegate setup of context he help ( & window ) to lua CInterfaceManager *im = CInterfaceManager::getInstance(); - CLuaState *ls= im->getLuaState(); + CLuaState *ls= CLuaManager::getInstance().getLuaState(); { CLuaStackRestorer lsr(ls, 0); @@ -128,7 +131,7 @@ ucstring CControlSheetTooltipInfoWaiter::infoValidated(CDBCtrlSheet* ctrlSheet, // *************************************************************************** int CDBCtrlSheet::luaGetDraggedSheet(CLuaState &ls) { - CLuaIHM::pushUIOnStack(ls, dynamic_cast(_LastDraggedSheet)); + CLuaIHMRyzom::pushUIOnStack(ls, dynamic_cast(_LastDraggedSheet)); return 1; } @@ -3160,7 +3163,7 @@ void CDBCtrlSheet::getContextHelp(ucstring &help) const { // delegate setup of context he help ( & window ) to lua CInterfaceManager *im = CInterfaceManager::getInstance(); - CLuaState *ls= im->getLuaState(); + CLuaState *ls= CLuaManager::getInstance().getLuaState(); { CLuaStackRestorer lsr(ls, 0); CSPhraseManager *pPM= CSPhraseManager::getInstance(); diff --git a/code/ryzom/client/src/interface_v3/group_list.cpp b/code/ryzom/client/src/interface_v3/group_list.cpp index d157543a7..792958295 100644 --- a/code/ryzom/client/src/interface_v3/group_list.cpp +++ b/code/ryzom/client/src/interface_v3/group_list.cpp @@ -26,8 +26,7 @@ #include "view_text_id.h" #include "group_container.h" #include "lua_ihm.h" - -#include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "nel/misc/xml_auto_ptr.h" @@ -916,7 +915,7 @@ sint32 CGroupList::getElementIndex(CViewBase* child) const int CGroupList::luaGetElementIndex(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "getElementIndex", 1); - CViewBase * viewBase = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase * viewBase = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); ls.push((double) getElementIndex(viewBase)); return 1; } @@ -968,7 +967,7 @@ void CGroupList::swapChildren(uint index1, uint index2) int CGroupList::luaUpChild(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "upChild", 1); - CViewBase * viewBase = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase * viewBase = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); sint32 indexUpChild = getElementIndex(viewBase); if(indexUpChild > 0) { @@ -981,7 +980,7 @@ int CGroupList::luaUpChild(CLuaState &ls) int CGroupList::luaDownChild(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "downChild", 1); - CViewBase * viewBase = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase * viewBase = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); sint32 indexDownChild = getElementIndex(viewBase); if(indexDownChild < (sint32) (_Elements.size()-1)) { @@ -1002,7 +1001,7 @@ int CGroupList::luaGetChild(CLuaState &ls) CLuaIHM::fails(ls, "getChild : trying to access element %d in list '%s', which has %d elements", index, getId().c_str(), (int) _Elements.size()); } - CLuaIHM::pushUIOnStack(ls, getChild((uint) index)); + CLuaIHMRyzom::pushUIOnStack(ls, getChild((uint) index)); return 1; } @@ -1091,7 +1090,7 @@ int CGroupList::luaAddChild(CLuaState &ls) { const char *funcName = "addChild"; CLuaIHM::checkArgCount(ls, funcName, 1); - CViewBase *vb = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase *vb = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (!vb) { CLuaIHM::fails(ls, "%s requires a view, group or control", funcName); @@ -1109,7 +1108,7 @@ int CGroupList::luaAddChildAtIndex(CLuaState &ls) const char *funcName = "addChildAtIndex"; CLuaIHM::checkArgCount(ls, funcName, 2); CLuaIHM::checkArgType(ls, funcName, 2, LUA_TNUMBER); - CViewBase *vb = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase *vb = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (!vb) { CLuaIHM::fails(ls, "%s requires a view, group or control", funcName); @@ -1126,7 +1125,7 @@ int CGroupList::luaDetachChild(CLuaState &ls) { const char *funcName = "detachChild"; CLuaIHM::checkArgCount(ls, funcName, 1); - CViewBase *vb = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase *vb = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (!vb) { nlwarning("%s requires a view, group or control", funcName); @@ -1143,7 +1142,7 @@ int CGroupList::luaDetachChild(CLuaState &ls) int CGroupList::luaDelChild(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "CGroupList::delChild", 1); - CViewBase *vb = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CViewBase *vb = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (vb) delChild(vb); updateCoords(); return 0; diff --git a/code/ryzom/client/src/interface_v3/group_menu.cpp b/code/ryzom/client/src/interface_v3/group_menu.cpp index 137dcec10..782c1f943 100644 --- a/code/ryzom/client/src/interface_v3/group_menu.cpp +++ b/code/ryzom/client/src/interface_v3/group_menu.cpp @@ -25,6 +25,7 @@ #include "view_bitmap.h" #include "action_handler.h" // Just for getAllParams #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "nel/misc/i18n.h" @@ -1692,7 +1693,7 @@ int CGroupSubMenu::luaGetSubMenu(CLuaState &ls) const char *funcName = "getSubMenu"; CLuaIHM::checkArgCount(ls, funcName, 1); CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER); - CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1))); + CLuaIHMRyzom::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1))); return 1; } @@ -1703,7 +1704,7 @@ int CGroupSubMenu::luaAddSubMenu(CLuaState &ls) CLuaIHM::checkArgCount(ls, funcName, 1); CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER); setSubMenu((uint) ls.toNumber(1), new CGroupSubMenu(CViewText::TCtorParam())); - CLuaIHM::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1))); + CLuaIHMRyzom::pushUIOnStack(ls, getSubMenu((uint) ls.toNumber(1))); return 1; } @@ -1803,11 +1804,11 @@ int CGroupSubMenu::luaSetUserGroupRight(CLuaState &ls) const char *funcName = "setUserGroupRight"; CLuaIHM::checkArgCount(ls, funcName, 2); CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER); - if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2))) + if (!(CLuaIHMRyzom::isUIOnStack(ls, 2) || ls.isNil(2))) { CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName); } - CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2); + CInterfaceElement *el = CLuaIHMRyzom::getUIOnStack(ls, 2); CInterfaceGroup *group = dynamic_cast(el); if (el && !group) { @@ -1823,11 +1824,11 @@ int CGroupSubMenu::luaSetUserGroupLeft(CLuaState &ls) const char *funcName = "setUserGroupLeft"; CLuaIHM::checkArgCount(ls, funcName, 2); CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER); - if (!(CLuaIHM::isUIOnStack(ls, 2) || ls.isNil(2))) + if (!(CLuaIHMRyzom::isUIOnStack(ls, 2) || ls.isNil(2))) { CLuaIHM::fails(ls, "%s : Group required as argument 2", funcName); } - CInterfaceElement *el = CLuaIHM::getUIOnStack(ls, 2); + CInterfaceElement *el = CLuaIHMRyzom::getUIOnStack(ls, 2); CInterfaceGroup *group = dynamic_cast(el); if (el && !group) { @@ -1844,7 +1845,7 @@ int CGroupSubMenu::luaGetUserGroupRight(CLuaState &ls) const char *funcName = "getUserGroupRight"; CLuaIHM::checkArgCount(ls, funcName, 1); CLuaIHM::checkArgType(ls, funcName, 1, LUA_TNUMBER); - CLuaIHM::pushUIOnStack(ls, getUserGroupRight((uint) ls.toNumber(1))); + CLuaIHMRyzom::pushUIOnStack(ls, getUserGroupRight((uint) ls.toNumber(1))); return 1; } @@ -1858,7 +1859,7 @@ int CGroupSubMenu::luaGetUserGroupLeft(CLuaState &ls) CInterfaceElement *pIE = getUserGroupLeft((uint) ls.toNumber(1)); if (pIE) { - CLuaIHM::pushUIOnStack(ls, pIE); + CLuaIHMRyzom::pushUIOnStack(ls, pIE); return 1; } else return 0; @@ -2281,7 +2282,7 @@ void CGroupMenu::setUserGroupLeft(uint line, CInterfaceGroup *gr, bool ownerShip int CGroupMenu::luaGetRootMenu(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "getRootMenu", 0); - CLuaIHM::pushUIOnStack(ls, getRootMenu()); + CLuaIHMRyzom::pushUIOnStack(ls, getRootMenu()); return 1; } diff --git a/code/ryzom/client/src/interface_v3/group_tab.cpp b/code/ryzom/client/src/interface_v3/group_tab.cpp index 00cb26a83..dd408b445 100644 --- a/code/ryzom/client/src/interface_v3/group_tab.cpp +++ b/code/ryzom/client/src/interface_v3/group_tab.cpp @@ -24,6 +24,7 @@ #include "interface_manager.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" using namespace std; @@ -234,7 +235,7 @@ void CGroupTab::addTab(CCtrlTabButton * tabB, sint index) int CGroupTab::luaAddTab(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "CGroupTab::addTab", 1); - CCtrlTabButton *tabB = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CCtrlTabButton *tabB = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (tabB) { // don't use addTab to avoid selection of new tab @@ -259,7 +260,7 @@ int CGroupTab::luaAddTabWithOrder(CLuaState &ls) CLuaIHM::checkArgCount(ls, funcName, 2); CLuaIHM::checkArgType(ls, funcName, 2, LUA_TNUMBER); - CCtrlTabButton *tabB = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CCtrlTabButton *tabB = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if (tabB) { // don't use addTab to avoid selection of new tab @@ -394,7 +395,7 @@ int CGroupTab::luaGetTabButton(CLuaState &ls) CCtrlTabButton* tab = getTabButton((uint) ls.toNumber(1)); if(tab != NULL) { - CLuaIHM::pushUIOnStack(ls, tab); + CLuaIHMRyzom::pushUIOnStack(ls, tab); return 1; } return 0; @@ -725,7 +726,7 @@ int CGroupTab::luaGetGroup(CLuaState &ls) CInterfaceGroup* group = getGroup((uint) ls.toNumber(1)); if(group != NULL) { - CLuaIHM::pushUIOnStack(ls, group); + CLuaIHMRyzom::pushUIOnStack(ls, group); return 1; } return 0; diff --git a/code/ryzom/client/src/interface_v3/group_tree.cpp b/code/ryzom/client/src/interface_v3/group_tree.cpp index 7c0be8016..9fe98e9c6 100644 --- a/code/ryzom/client/src/interface_v3/group_tree.cpp +++ b/code/ryzom/client/src/interface_v3/group_tree.cpp @@ -26,6 +26,7 @@ #include "group_container.h" #include "action_handler.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "nel/misc/i_xml.h" #include "nel/misc/i18n.h" @@ -1490,7 +1491,7 @@ int CGroupTree::SNode::luaGetParentTree(CLuaState &ls) CLuaIHM::checkArgCount(ls, "getParentTree", 0); if (ParentTree) { - CLuaIHM::pushUIOnStack(ls, ParentTree); + CLuaIHMRyzom::pushUIOnStack(ls, ParentTree); } else { diff --git a/code/ryzom/client/src/interface_v3/interface_element.cpp b/code/ryzom/client/src/interface_v3/interface_element.cpp index 7edc093ae..85bc0ba0f 100644 --- a/code/ryzom/client/src/interface_v3/interface_element.cpp +++ b/code/ryzom/client/src/interface_v3/interface_element.cpp @@ -26,6 +26,7 @@ #include "interface_link.h" #include "nel/misc/xml_auto_ptr.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "nel/misc/mem_stream.h" // @@ -34,29 +35,6 @@ using namespace NLMISC; CStringMapper *_UIStringMapper = NULL; -// ------------------------------------------------------------------------------------------------ -CReflectableRefPtrTarget::~CReflectableRefPtrTarget() -{ - CInterfaceManager *pIM= CInterfaceManager::getInstance(); - CLuaState *lua= pIM->getLuaState(); - if(!lua) return; - CLuaStackChecker lsc(lua); - // remove from the lua registry if i'm in - lua->pushLightUserData((void *) this); - lua->getTable(LUA_REGISTRYINDEX); - if (!lua->isNil(-1)) - { - lua->pop(); - lua->pushLightUserData((void *) this); - lua->pushNil(); - lua->setTable(LUA_REGISTRYINDEX); - } - else - { - lua->pop(); - } -} - // ------------------------------------------------------------------------------------------------ CInterfaceElement::~CInterfaceElement() { @@ -1198,7 +1176,7 @@ int CInterfaceElement::luaSetPosRef(CLuaState &ls) int CInterfaceElement::luaSetParentPos(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "setParentPos", 1); - CInterfaceElement *ie = CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *ie = CLuaIHMRyzom::getUIOnStack(ls, 1); if(ie) { setParentPos(ie); diff --git a/code/ryzom/client/src/interface_v3/interface_element.h b/code/ryzom/client/src/interface_v3/interface_element.h index 0202618ba..963cbb050 100644 --- a/code/ryzom/client/src/interface_v3/interface_element.h +++ b/code/ryzom/client/src/interface_v3/interface_element.h @@ -80,19 +80,6 @@ public: }; -/** Reflectable refcounted object - * NB nico : added this intermediate class so that the binding from lua to the reflection - * system that are found in CLuaIHM can be reused for other objects as well - * NOTE: The class is named 'CReflectableRefPtrTarget' and not 'CReflectableRefCount' - * because the refcount part is only used for ref pointing in the ui - */ -class CReflectableRefPtrTarget : public CReflectable, public NLMISC::CRefCount -{ -public: - virtual ~CReflectableRefPtrTarget(); -}; - - #define DECLARE_UI_CLASS(_class_) \ virtual std::string getClassName() {return #_class_;} \ static NLMISC::IClassable *creator() {return new _class_(CViewBase::TCtorParam());} diff --git a/code/ryzom/client/src/interface_v3/interface_group.cpp b/code/ryzom/client/src/interface_v3/interface_group.cpp index 1a75cf4cb..f1db4917d 100644 --- a/code/ryzom/client/src/interface_v3/interface_group.cpp +++ b/code/ryzom/client/src/interface_v3/interface_group.cpp @@ -25,9 +25,11 @@ #include "group_editbox.h" #include "group_scrolltext.h" #include "lua_ihm.h" +#include "lua_ihm_ryzom.h" #include "nel/misc/stream.h" +#include "lua_manager.h" using namespace std; using namespace NL3D; @@ -445,7 +447,7 @@ void CInterfaceGroup::addGroup (CInterfaceGroup *child, sint eltOrder /*= -1*/) int CInterfaceGroup::luaAddGroup (CLuaState &ls) { CLuaIHM::checkArgCount(ls, "CInterfaceGroup::addTab", 1); - CInterfaceGroup * group = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CInterfaceGroup * group = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if(group) { group->setParent(this); @@ -616,7 +618,7 @@ bool CInterfaceGroup::delGroup (CInterfaceGroup *child, bool dontDelete /* = fal int CInterfaceGroup::luaDelGroup (CLuaState &ls) { CLuaIHM::checkArgCount(ls, "CInterfaceGroup::delTab", 1); - CInterfaceGroup * group = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CInterfaceGroup * group = dynamic_cast(CLuaIHMRyzom::getUIOnStack(ls, 1)); if(group) { delGroup(group); @@ -643,7 +645,7 @@ int CInterfaceGroup::luaGetGroup(CLuaState &ls) { CLuaIHM::fails(ls, "getGroup : try to index group %s, but there are only %d son groups", ls.toString(1), (int) _ChildrenGroups.size()); } - CLuaIHM::pushUIOnStack(ls, _ChildrenGroups[index]); + CLuaIHMRyzom::pushUIOnStack(ls, _ChildrenGroups[index]); return 1; } @@ -1747,7 +1749,7 @@ void CInterfaceGroup::onFrameUpdateWindowPos(sint dx, sint dy) void CInterfaceGroup::pushLUAEnvTable() { CInterfaceManager *pIM= CInterfaceManager::getInstance(); - CLuaState *lua= pIM->getLuaState(); + CLuaState *lua= CLuaManager::getInstance().getLuaState(); nlassert(lua); if(!_LUAEnvTableCreated) @@ -1782,7 +1784,7 @@ void CInterfaceGroup::deleteLUAEnvTable(bool recurse) if(_LUAEnvTableCreated) { CInterfaceManager *pIM= CInterfaceManager::getInstance(); - CLuaState *lua= pIM->getLuaState(); + CLuaState *lua= CLuaManager::getInstance().getLuaState(); nlassert(lua); // replace simply the table with Nil, letting LUA Garbage collector do the realease stuff @@ -1866,7 +1868,7 @@ int CInterfaceGroup::luaFind(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, element); + CLuaIHMRyzom::pushUIOnStack(ls, element); } return 1; } @@ -1885,7 +1887,7 @@ CInterfaceElement* CInterfaceGroup::findFromShortId(const std::string &id) int CInterfaceGroup::luaGetEnclosingContainer(CLuaState &ls) { CLuaIHM::checkArgCount(ls, "CInterfaceGroup::getEnclosingContainer", 0); - CLuaIHM::pushUIOnStack(ls, getEnclosingContainer()); + CLuaIHMRyzom::pushUIOnStack(ls, getEnclosingContainer()); return 1; } diff --git a/code/ryzom/client/src/interface_v3/interface_manager.cpp b/code/ryzom/client/src/interface_v3/interface_manager.cpp index e162df279..d92d59354 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/code/ryzom/client/src/interface_v3/interface_manager.cpp @@ -5887,9 +5887,9 @@ void CInterfaceManager::getLuaValueInfo(std::string &str, sint index) // If its a Userdata, try to display UI info else if(type==LUA_TUSERDATA) { - if(CLuaIHM::isUIOnStack(ls, index)) + if(CLuaIHMRyzom::isUIOnStack(ls, index)) { - CInterfaceElement *ui= CLuaIHM::getUIOnStack(ls, index); + CInterfaceElement *ui= CLuaIHMRyzom::getUIOnStack(ls, index); str+= NLMISC::toString(" (ui=%p)", ui); } } diff --git a/code/ryzom/client/src/interface_v3/interface_manager.h b/code/ryzom/client/src/interface_v3/interface_manager.h index 75a33cc29..550a5e867 100644 --- a/code/ryzom/client/src/interface_v3/interface_manager.h +++ b/code/ryzom/client/src/interface_v3/interface_manager.h @@ -629,8 +629,6 @@ public: // @{ /// Execute a lua script (smallScript for speed optimisation, see lua_helper). return false if parse/execute error (warning/sysinfo displayed) bool executeLuaScript(const std::string &luaScript, bool smallScript= false); - /// Get the lua state (NULL if not inited) - class CLuaState *getLuaState() const {return _LuaState;} /// Reload all LUA scripts inserted through void reloadAllLuaFileScripts(); /// For debug: dump in the sysinfo and nlwarning state of lua. detail range from 0 to 2 (clamped). diff --git a/code/ryzom/client/src/interface_v3/interface_parser.cpp b/code/ryzom/client/src/interface_v3/interface_parser.cpp index 16232de19..bdf2c7050 100644 --- a/code/ryzom/client/src/interface_v3/interface_parser.cpp +++ b/code/ryzom/client/src/interface_v3/interface_parser.cpp @@ -110,6 +110,7 @@ using namespace NLGUI; #include "lua_ihm.h" #include "lua_ihm_ryzom.h" #include "../r2/editor.h" +#include "lua_manager.h" #ifdef LUA_NEVRAX_VERSION #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger @@ -496,7 +497,7 @@ CInterfaceParser::~CInterfaceParser() { // delete _Pointer; _Pointer = NULL; - delete _LuaState; + //delete _LuaState; _LuaState = NULL; } /** Convert a string into a memstream @@ -4663,7 +4664,9 @@ void CInterfaceParser::initLUA() // create a new LUA environnement nlassert(_LuaState==NULL); - _LuaState= new CLuaState( ClientCfg.LoadLuaDebugger ); + CLuaManager::enableLuaDebugging(); + CLuaManager::getInstance(); + _LuaState= CLuaManager::getInstance().getLuaState(); #ifdef LUA_NEVRAX_VERSION extern ILuaIDEInterface *LuaDebuggerIDE; @@ -4679,8 +4682,8 @@ void CInterfaceParser::initLUA() void CInterfaceParser::uninitLUA() { // Delete all LUA environnement (and hence variables) -// delete _LuaState; - _LuaState= NULL; + // delete _LuaState; + // _LuaState= NULL; // delete all .lua file loaded _LuaFileScripts.clear(); diff --git a/code/ryzom/client/src/interface_v3/lua_ihm.cpp b/code/ryzom/client/src/interface_v3/lua_ihm.cpp index c6cf16b37..5ee00ba4d 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm.cpp @@ -15,7 +15,6 @@ // along with this program. If not, see . -#include "stdpch.h" #include "nel/gui/lua_helper.h" using namespace NLGUI; @@ -62,70 +61,14 @@ using namespace NLGUI; #include "lua_ihm.h" #include "reflect.h" -#include "action_handler.h" -#include "action_handler_tools.h" -#include "interface_manager.h" -#include "interface_group.h" -#include "view_text.h" -#include "game_share/people_pd.h" -#include "group_tree.h" -#include "interface_link.h" -#include "interface_expr.h" -#include "people_interraction.h" #include "nel/misc/algo.h" #include "nel/misc/file.h" #include "nel/misc/i18n.h" #include "nel/misc/time_nl.h" -#include "skill_manager.h" -#include "group_html.h" -#include "../net_manager.h" -#include "../user_entity.h" -#include "sphrase_manager.h" -#include "guild_manager.h" -#include "../client_cfg.h" -#include "../sheet_manager.h" #include "lua_object.h" -#include "game_share/emote_list_parser.h" -#include "game_share/pvp_clan.h" -#include "../weather.h" -#include "../continent_manager.h" -#include "../zone_util.h" -#include "../motion/user_controls.h" -#include "group_html_cs.h" -#include "bonus_malus.h" -#include "group_editbox.h" -#include "../entities.h" -#include "../sheet_manager.h" // for emotes -#include "../global.h" // for emotes -#include "../entity_animation_manager.h" // for emotes -#include "../net_manager.h" // for emotes -#include "../client_chat_manager.h" // for emotes -#include "../login.h" -#include "lua_object.h" -#include "../actions.h" -#include "../bg_downloader_access.h" -#include "../connection.h" -#include "../login_patch.h" - -#include "bot_chat_page_all.h" -#include "bot_chat_page_ring_sessions.h" -#include "nel/georges/u_form_loader.h" -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" #include "nel/misc/polygon.h" -#include "game_share/scenario_entry_points.h" -#include "game_share/bg_downloader_msg.h" -#include "game_share/constants.h" -#include "game_share/visual_slot_manager.h" +#include "lua_manager.h" -#ifdef LUA_NEVRAX_VERSION - #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger -#endif - - -#ifdef LUA_NEVRAX_VERSION - extern ILuaIDEInterface *LuaDebuggerIDE; -#endif // *************************************************************************** /* @@ -136,15 +79,6 @@ Compilation is VERY SLOW // *************************************************************************** using namespace NLMISC; -using namespace NLGEORGES; -using namespace R2; - - -extern NLMISC::CLog g_log; -extern CContinentManager ContinentMngr; -extern uint8 PlayerSelectedSlot; -extern CClientChatManager ChatMngr; -extern void addWebIGParams (string &url, bool trustedDomain); // declare ostream << operator for ucstring -> registration of ucstring iin luabind will build a 'tostring' function from it std::ostream &operator<<(std::ostream &str, const ucstring &value) @@ -169,69 +103,6 @@ struct CMiscFunctions }; -/** - * Data structure pushed in lua (a userdata) to access CReflectableRefPtrTarget derived objects - * These includes element of the GUI. - * if holds a pointer to the reflectable object, and - * a cache to its CClassInfo for fast access to exported properties - * \see reflect.h - */ - -// -class CReflectableLuaRef -{ -public: - CReflectableLuaRef(CReflectableRefPtrTarget *ptr = NULL) : Ptr(ptr), _ClassInfo(NULL) {} - NLMISC::CRefPtr Ptr; - const CClassInfo &getClassInfo() const; - // IMPORTANT : luaStringPtr should have been obtained from lua, see remark in CClassInfo - const CReflectedProperty *getProp(const char *luaStringPtr) const; -private: - // cache to class definition of the pointee object (once a CReflectableLuaRef created in lua, it remains a *const* pointer) - mutable const CClassInfo *_ClassInfo; -}; - -inline const CClassInfo &CReflectableLuaRef::getClassInfo() const -{ - nlassert(Ptr); // class info should not be accessed for a null ptr - if (_ClassInfo) return *_ClassInfo; - _ClassInfo = Ptr->getClassInfo(); - return *_ClassInfo; -} - -const CReflectedProperty *CReflectableLuaRef::getProp(const char *luaStringPtr) const -{ - const CClassInfo &ci = getClassInfo(); - CClassInfo::TLuaStrToPropMap::const_iterator it = ci.LuaStrToProp.find(luaStringPtr); - if (it != ci.LuaStrToProp.end()) - { - return it->second.Prop; - } - // slowly retrieve property, and store in cache - // NB nico : this could also be done at startup... - const CReflectedProperty *prop = CReflectSystem::getProperty(ci.ClassName, luaStringPtr, false); - if (!prop) return NULL; - CLuaIndexedProperty lip; - lip.Id = CLuaString(luaStringPtr); // keep a ref on the lua string to ensure that its pointer always remains valid - lip.Prop = prop; - ci.LuaStrToProp[luaStringPtr] = lip; - return prop; -} - -// *************************************************************************** -static sint32 getTargetSlotNr() -{ - const char *dbPath = "UI:VARIABLES:TARGET:SLOT"; - CInterfaceManager *im = CInterfaceManager::getInstance(); - CCDBNodeLeaf *node = im->getDbProp(dbPath, false); - if (!node) return 0; - if ((uint8) node->getValue32() == (uint8) CLFECOMMON::INVALID_SLOT) - { - return 0; - } - return node->getValue32(); -} - // *************************************************************************** bool CLuaIHM::pop(CLuaState &ls, NLMISC::CRGBA &dest) { @@ -331,118 +202,6 @@ void CLuaIHM::push(CLuaState &ls, const ucstring &value) #endif } -// *************************************************************************** -// *************************************************************************** -// Special Action Handlers for Lua -// *************************************************************************** -// *************************************************************************** - - - -// *************************************************************************** -// Allow also to call script from expression -static DECLARE_INTERFACE_USER_FCT(lua) -{ - if(args.size()!=1 || !args[0].toString()) - { - nlwarning(" requires 1 arg (string=script)"); - return false; - } - - // Retrieve lua state - CInterfaceManager *pIM= CInterfaceManager::getInstance(); - CLuaState *state= pIM->getLuaState(); - if(!state) - return false; - CLuaState &ls= *state; - - // *** clear return value - const std::string retId= "__ui_internal_ret_"; - CLuaStackChecker lsc(&ls); - ls.push(retId); - ls.pushNil(); - ls.setTable(LUA_GLOBALSINDEX); - - - // *** execute script - std::string script= args[0].getString(); - // assign return value in retId. - script= retId + "= " + script; - // execute a small script here, because most often exprs are called from xml files => lot of redundant script - pIM->executeLuaScript(script, true); - - - // *** retrieve and convert return value - ls.push(retId); - ls.getTable(LUA_GLOBALSINDEX); - bool ok= false; - sint type= ls.type(); - if (type==LUA_TBOOLEAN) - { - // get and pop - bool val= ls.toBoolean(); - ls.pop(); - // set result - result.setBool(val); - ok= true; - } - else if(type==LUA_TNUMBER) - { - // get and pop - double val= ls.toNumber(); - ls.pop(); - // set double or integer? - if(val==floor(val)) - result.setInteger(sint64(floor(val))); - else - result.setDouble(val); - ok= true; - } - else if(type==LUA_TSTRING) - { - // get and pop - std::string val; - ls.toString(-1, val); - ls.pop(); - // set result - result.setString(val); - ok= true; - } - else if(type==LUA_TUSERDATA) - { - // NB: the value is poped in obj.set() (no need to do ls.pop()); - - // try with ucstring - ucstring ucstrVal; - if (CLuaIHM::pop(ls, ucstrVal)) - { - result.setUCString(ucstrVal); - ok= true; - } - - // try with RGBA - if(!ok) - { - NLMISC::CRGBA rgbaVal; - if (CLuaIHM::pop(ls, rgbaVal)) - { - result.setRGBA(rgbaVal); - ok= true; - } - } - } - else - { - // error (nil for instance) - ls.pop(); - } - - return ok; -} -REGISTER_INTERFACE_USER_FCT("lua", lua) - - - // *************************************************************************** // *************************************************************************** // CInterface To LUA Registry @@ -452,8 +211,7 @@ REGISTER_INTERFACE_USER_FCT("lua", lua) CLuaState * ELuaIHMException::getLuaState() { - CInterfaceManager *im = CInterfaceManager::getInstance(); - return im->getLuaState(); + return CLuaManager::getInstance().getLuaState(); } // *************************************************************************** @@ -539,45 +297,9 @@ void CLuaIHM::registerBasics(CLuaState &ls) .def_readwrite("y", &NLMISC::CVector2f::y) ]; - // MISC ui ctors - struct CUICtor - { - // CGroupTree::SNode - static int SNode(CLuaState &ls) - { - CLuaIHM::checkArgCount(ls, "SNode", 0); - CLuaIHM::pushReflectableOnStack(ls, new CGroupTree::SNode); - return 1; - } - }; - - ls.registerFunc("SNode", CUICtor::SNode); } -// *************************************************************************** -CInterfaceElement *CLuaIHM::getUIRelative(CInterfaceElement *pIE, const std::string &propName) -{ - //H_AUTO(Lua_CLuaIHM_getUIRelative) - if (pIE == NULL) return NULL; - // If the prop is "parent", then return the parent of the ui - if(propName=="parent") - { - return pIE->getParent(); - } - // else try to get a child (if group/exist) - else - { - CInterfaceGroup *group= dynamic_cast(pIE); - if(group) - { - return group->getElement(group->getId()+":"+propName); - } - } - - return NULL; -} - // *************************************************************************** int CLuaIHM::luaMethodCall(lua_State *ls) { @@ -688,71 +410,6 @@ void CLuaIHM::luaValueFromReflectedProperty(CLuaState &ls, CReflectable &reflect static CLuaString lstr_Env("Env"); static CLuaString lstr_isNil("isNil"); -// *************************************************************************** -int CLuaIHM::luaUIIndex(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaUIIndex) - nlassert(ls.getTop()==2); - // get the userdata and key - CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); - - const char *propName = ls.toString(2); - CReflectableRefPtrTarget *pRPT= (CReflectableRefPtrTarget*)(pRefElm->Ptr); - // ** try to get the Env Table (interface group only) - if(propName==lstr_isNil) - { - ls.push(pRPT==NULL); - return 1; - } - - // Check the object is not NULL or freed - if(pRPT==NULL) - { - return 0; - } - - // ** try to get the Env Table (interface group only) - if(propName==lstr_Env) - { - // Env can be bound to a CInterfaceGroup only - CInterfaceGroup *group= dynamic_cast(pRPT); - if(group==NULL) - { - ls.pushNil(); - return 1; - } - else - { - group->pushLUAEnvTable(); - return 1; - } - } - - // ** try to get the property - const CReflectedProperty *prop = pRefElm->getProp(propName); - if (prop) - { - luaValueFromReflectedProperty(ls, *pRPT, *prop); - return 1; - } - - // ** try to get a UI relative - CInterfaceElement *uiRelative= getUIRelative(dynamic_cast(pRPT), propName); - if(uiRelative) - { - // push the UI onto the stack - CLuaIHM::pushUIOnStack(ls, uiRelative); - return 1; - } - - - // Fail to find any Attributes or elements - // Yoyo: don't write any message or warning because this may be a feature (if user want to test that something exit in the ui) - ls.pushNil(); - return 1; -} - - // *************************************************************************** void CLuaIHM::luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflectable &target, const CReflectedProperty &property) throw(ELuaIHMException) { @@ -832,312 +489,6 @@ void CLuaIHM::luaValueToReflectedProperty(CLuaState &ls, int stackIndex, CReflec } -// *************************************************************************** -int CLuaIHM::luaUINewIndex(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaUINewIndex) - nlassert(ls.getTop()==3); - // get the userdata and key - CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); - nlassert(pRefElm); - CReflectableRefPtrTarget *pRPT= (CReflectableRefPtrTarget*)(pRefElm->Ptr); - // Check the UI is not NULL or freed - if(pRPT == NULL) - { - return 0; - } - - const char *propName = ls.toString(2); - // ** try to set the Env Table (interface group only) - if(propName == lstr_Env) - { - CInterfaceElement *pIE = dynamic_cast(pRPT); - std::string name ; - if (pIE) - { - name = pIE->getId(); - } - else - { - name = ""; - } - // Exception!!! not allowed - throw ELuaIHMException("You cannot change the Env Table of '%s'", name.c_str()); - } - - - // ** try to set the property - const CReflectedProperty *prop = pRefElm->getProp(propName); - if (prop) - { - luaValueToReflectedProperty(ls, 3, *pRPT, *prop); - return 0; - } - - CInterfaceElement *pIE = dynamic_cast(pRPT); - // ** try to get another UI (child or parent) - CInterfaceElement *uiRelative= getUIRelative(pIE, propName); - if(uiRelative) - { - // Exception!!! not allowed - throw ELuaIHMException("You cannot write into the UI '%s' of '%s'", propName, pIE->getId().c_str()); - } - - // ** Prop Not Found - throw ELuaIHMException("Property '%s' not found in '%s' of type %s", propName, pIE ? pIE->getId().c_str() : "", typeid(*pRPT).name()); - - // Fail to find any Attributes or elements - return 0; -} - -// *************************************************************************** -int CLuaIHM::luaUIEq(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaUIEq) - nlassert(ls.getTop() == 2); - // read lhs & rhs - // get the userdata and key - CReflectableLuaRef *lhs = (CReflectableLuaRef *) ls.toUserData(1); - CReflectableLuaRef *rhs = (CReflectableLuaRef *) ls.toUserData(2); - nlassert(lhs); - nlassert(rhs); - ls.push(lhs->Ptr == rhs->Ptr); - return 1; -} - - -// *************************************************************************** -int CLuaIHM::luaUIDtor(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaUIDtor) - nlassert(ls.getTop()==1); - // get the userdata - CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); - nlassert(pRefElm); - - // call dtor - pRefElm->~CReflectableLuaRef(); - - return 0; -} - -// *************************************************************************** -int CLuaIHM::luaUINext(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaUINext) - // Code below allow enumeration of properties of a reflectable object - // From lua standpoint, the object is seen as a table with (key, value) pairs - // If object is a CInterfaceGroup, iteration is also done on sons (groups, controls & view). - - if (ls.getTop() != 2) - { - CLuaIHM::fails(ls, "__next metamethod require 2 arguments (table & key)"); - } - CLuaIHM::check(ls, isReflectableOnStack(ls, 1), "__next : require ui element as first arg"); - CReflectableRefPtrTarget *reflectedObject = getReflectableOnStack(ls, 1); - // To traverse all properties / field of the object, we must be able to determine the next key from a previous key - // (keys are ordered) - // We use the 'TValueType' enum to know which kind of property we are traversing, and an index in this group of properties - // The key which uniquely identify an element / property in the reflectable object - struct CKey - { - enum TValueType - { - VTGroup = 0, // children groups (If the object is a CInterfaceGroup) - VTView, // children views (If the object is a CInterfaceView) - VTCtrl, // children controls (If the object is a CInterfaceCtrl) - VTProp // List of exported proeprties (For all relfectable objects) - }; - TValueType ValueType; - sint Index; - const CClassInfo *ClassInfo; // if ValueType is "VTProp" -> give the class for which property are currently enumerated - // - static int tostring(CLuaState &ls) // '__print' metamathod - { - CLuaIHM::checkArgCount(ls, "reflected object metatable:__print", 1); - CKey key; - key.pop(ls); - switch(key.ValueType) - { - case VTGroup: ls.push(toString("_Group %d", key.Index)); break; - case VTView: ls.push(toString("_View %d", key.Index)); break; - case VTCtrl: ls.push(toString("_Ctrl %d", key.Index)); break; - case VTProp: ls.push(key.ClassInfo->Properties[key.Index].Name); break; - } - return 1; - } - // push the key on the lua stack - void push(CLuaState &ls) - { - void *ud = ls.newUserData(sizeof(*this)); - *(CKey *) ud = *this; - getMetaTable(ls).push(); - ls.setMetaTable(-2); - } - // pop the key from the lua stack - void pop(CLuaState &ls) - { - CLuaStackChecker lsc(&ls, -1); - if (!ls.isUserData(-1)) - { - CLuaIHM::fails(ls, "Can't pop object, not a user data"); - } - // check that metatable is good (it is share between all keys) - ls.getMetaTable(-1); - getMetaTable(ls).push(); - if (!ls.rawEqual(-1, -2)) - { - CLuaIHM::fails(ls, "Bad metatable for reflectable object key"); - } - ls.pop(2); - // retrieve key - *this = *(CKey *) ls.toUserData(-1); - ls.pop(); - } - // get the metatable for a CKey - CLuaObject &getMetaTable(CLuaState &ls) - { - static CLuaObject metatable; - if (!metatable.isValid()) - { - // first build - CLuaStackChecker lsc(&ls); - ls.newTable(); - ls.push("__tostring"); - ls.push(CKey::tostring); - ls.setTable(-3); - metatable.pop(ls); - } - return metatable; - } - }; - // Pop the current key to continue enumeration - CKey key; - if (ls.isNil(2)) - { - // no key -> start of table - key.ValueType = CKey::VTGroup; - key.Index = -1; - } - else - { - key.pop(ls); - } - // - CInterfaceGroup *group = dynamic_cast(reflectedObject); - bool enumerate = true; - while (enumerate) - { - switch(key.ValueType) - { - case CKey::VTGroup: - if (!group || (key.Index + 1) == (sint) group->getGroups().size()) - { - key.Index = -1; - key.ValueType = CKey::VTView; // continue enumeration with views - } - else - { - ++ key.Index; - key.push(ls); - CLuaIHM::pushUIOnStack(ls, group->getGroups()[key.Index]); - return 2; - } - break; - case CKey::VTView: - if (!group || (key.Index + 1) == (sint) group->getViews().size()) - { - key.Index = -1; - key.ValueType = CKey::VTCtrl; // continue enumeration with controls - } - else - { - ++ key.Index; - key.push(ls); - CLuaIHM::pushUIOnStack(ls, group->getViews()[key.Index]); - return 2; - } - break; - case CKey::VTCtrl: - if (!group || (key.Index + 1) == (sint) group->getControls().size()) - { - key.Index = -1; - key.ValueType = CKey::VTProp; // continue enumeration with properties - key.ClassInfo = reflectedObject->getClassInfo(); - } - else - { - ++ key.Index; - key.push(ls); - CLuaIHM::pushUIOnStack(ls, group->getControls()[key.Index]); - return 2; - } - break; - case CKey::VTProp: - if (!key.ClassInfo) - { - enumerate = false; - break; - } - if ((sint) key.ClassInfo->Properties.size() == (key.Index + 1)) - { - key.ClassInfo = key.ClassInfo->ParentClass; // continue enumeration in parent class - key.Index = -1; - } - else - { - ++ key.Index; - key.push(ls); - luaValueFromReflectedProperty(ls, *reflectedObject, key.ClassInfo->Properties[key.Index]); - return 2; - } - break; - default: - nlassert(0); - break; - } - } - ls.pushNil(); - return 0; -} - -// *************************************************************************** -int CLuaIHM::luaClientCfgIndex(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaClientCfgIndex) - CConfigFile::CVar *v = ClientCfg.ConfigFile.getVarPtr(ls.toString(2)); - if (!v) return 0; - if (v->size() != 1) - { - // arrays not implemented (would require a second metatable).... - throw ELuaWrappedFunctionException(&ls, "Access to array inside client.cfg not supported."); - } - switch(v->Type) - { - case CConfigFile::CVar::T_REAL: - ls.push((double) v->asDouble()); - return 1; - break; - case CConfigFile::CVar::T_STRING: - ls.push(v->asString()); - return 1; - break; - default: // handle both T_INT && T_BOOL - case CConfigFile::CVar::T_INT: - ls.push((double) v->asInt()); - return 1; - break; - } - return 0; -} - -// *************************************************************************** -int CLuaIHM::luaClientCfgNewIndex(CLuaState &ls) -{ - //H_AUTO(Lua_CLuaIHM_luaClientCfgNewIndex) - throw ELuaWrappedFunctionException(&ls, "Can't write into config file from lua."); -} - // *************************************************************************** void CLuaIHM::createLuaEnumTable(CLuaState &ls, const std::string &str) { @@ -1175,50 +526,6 @@ void CLuaIHM::registerIHM(CLuaState &ls) //H_AUTO(Lua_CLuaIHM_registerIHM) CLuaStackChecker lsc(&ls); - // *** Register the metatable for access to client.cfg (nb nico this may be more general later -> access to any config file ...) - { - ls.pushValue(LUA_GLOBALSINDEX); - CLuaObject globals(ls); - CLuaObject clientCfg = globals.newTable("config"); - CLuaObject mt = globals.newTable("__cfmt"); - nlverify(clientCfg.setMetaTable(mt)); - mt.setValue("__index", luaClientCfgIndex); - mt.setValue("__newindex", luaClientCfgNewIndex); - globals.setNil("__cfmt"); // remove temp metatable - } - - // *** Register the MetaTable for UI userdata - ls.push(IHM_LUA_METATABLE); // "__ui_metatable" - ls.newTable(); // "__ui_metatable" {} - // set the '__index' method - ls.push("__index"); - ls.push(luaUIIndex); - nlassert(ls.isCFunction()); - ls.setTable(-3); // "__ui_metatable" {"__index"= CFunc_luaUIIndex} - // set the '__newindex' method - ls.push("__newindex"); - ls.push(luaUINewIndex); - nlassert(ls.isCFunction()); - ls.setTable(-3); - // set the '__newindex' method - ls.push("__gc"); - ls.push(luaUIDtor); - nlassert(ls.isCFunction()); - ls.setTable(-3); - // set the '__eq' method - ls.push("__eq"); - ls.push(luaUIEq); - nlassert(ls.isCFunction()); - ls.setTable(-3); - // set the custom '__next' method - ls.push("__next"); - ls.push(luaUINext); - nlassert(ls.isCFunction()); - ls.setTable(-3); - // set registry - ls.setTable(LUA_REGISTRYINDEX); - - // *** Register a Table for ui env. ls.push(IHM_LUA_ENVTABLE); // "__ui_envtable" ls.newTable(); // "__ui_envtable" {} @@ -1392,28 +699,6 @@ CReflectableRefPtrTarget *CLuaIHM::getReflectableOnStack(CLuaState &ls, sint } -// *************************************************************************** -void CLuaIHM::pushUIOnStack(CLuaState &ls, class CInterfaceElement *pIE) -{ - //H_AUTO(Lua_CLuaIHM_pushUIOnStack) - pushReflectableOnStack(ls, pIE); -} - -// *************************************************************************** -bool CLuaIHM::isUIOnStack(CLuaState &ls, sint index) -{ - //H_AUTO(Lua_CLuaIHM_isUIOnStack) - return getUIOnStack(ls, index) != NULL; -} - -// *************************************************************************** -CInterfaceElement *CLuaIHM::getUIOnStack(CLuaState &ls, sint index) -{ - //H_AUTO(Lua_CLuaIHM_getUIOnStack) - return dynamic_cast(getReflectableOnStack(ls, index)); -} - - // *************************************************************************** // *************************************************************************** // LUA IHM Functions @@ -1429,26 +714,6 @@ uint32 CLuaIHM::getLocalTime() } -// *************************************************************************** -static CEntityCL *getTargetEntity() -{ - const char *dbPath = "UI:VARIABLES:TARGET:SLOT"; - CInterfaceManager *im = CInterfaceManager::getInstance(); - CCDBNodeLeaf *node = im->getDbProp(dbPath, false); - if (!node) return NULL; - if ((uint8) node->getValue32() == (uint8) CLFECOMMON::INVALID_SLOT) - { - return NULL; - } - return EntitiesMngr.entity((uint) node->getValue32()); -} - -// *************************************************************************** -static CEntityCL *getSlotEntity(uint slot) -{ - return EntitiesMngr.entity(slot); -} - // *************************************************************************** std::string CLuaIHM::findReplaceAll(const std::string &str, const std::string &search, const std::string &replace) { @@ -1489,78 +754,6 @@ ucstring CLuaIHM::findReplaceAll(const ucstring &str, const ucstring &search, } -// *************************************************************************** -int CLuaIHM::runExprAndPushResult(CLuaState &ls, const std::string &expr) -{ - //H_AUTO(Lua_CLuaIHM_runExprAndPushResult) - // Execute expression - CInterfaceExprValue value; - if (CInterfaceExpr::eval(expr, value, NULL)) - { - switch(value.getType()) - { - case CInterfaceExprValue::Boolean: - ls.push(value.getBool()); - break; - case CInterfaceExprValue::Integer: - ls.push((double)value.getInteger()); - break; - case CInterfaceExprValue::Double: - ls.push(value.getDouble()); - break; - case CInterfaceExprValue::String: - { - ucstring ucstr= value.getUCString(); - // Yoyo: dynamically decide whether must return a string or a ucstring - bool mustUseUCString= false; - for (uint i = 0; i < ucstr.size (); i++) - { - if (ucstr[i] > 255) - { - mustUseUCString= true; - break; - } - } - // push a ucstring? - if(mustUseUCString) - { -#if LUABIND_VERSION > 600 - luabind::detail::push(ls.getStatePointer(), ucstr); -#else - luabind::object obj(ls.getStatePointer(), ucstr); - obj.pushvalue(); -#endif - } - else - { - ls.push(ucstr.toString()); - } - break; - } - case CInterfaceExprValue::RGBA: - { - CRGBA color = value.getRGBA(); -#if LUABIND_VERSION > 600 - luabind::detail::push(ls.getStatePointer(), color); -#else - luabind::object obj(ls.getStatePointer(), color); - obj.pushvalue(); -#endif - break; - } - break; - case CInterfaceExprValue::UserType: // Yoyo: don't care UserType... - default: - ls.pushNil(); - break; - } - } - else - ls.pushNil(); - - return 1; -} - // *************************************************************************** void CLuaIHM::fails(CLuaState &ls, const char *format, ...) { @@ -1646,21 +839,6 @@ void CLuaIHM::checkArgTypeRGBA(CLuaState &ls, const char *funcName, uint index) } } -// *************************************************************************** -void CLuaIHM::checkArgTypeUIElement(CLuaState &ls, const char *funcName, uint index) -{ - //H_AUTO(Lua_CLuaIHM_checkArgTypeUIElement) - nlassert(index > 0); - if (ls.getTop() < (int) index) - { - fails(ls, "%s : argument %d of expected type ui element was not defined", funcName, index); - } - if (!isUIOnStack(ls, index)) - { - fails(ls, "%s : argument %d of expected type ui element has bad type : %s", funcName, index, ls.getTypename(ls.type(index)), ls.type(index)); - } -} - // *************************************************************************** void CLuaIHM::checkArgTypeUCString(CLuaState &ls, const char *funcName, uint index) { diff --git a/code/ryzom/client/src/interface_v3/lua_ihm.h b/code/ryzom/client/src/interface_v3/lua_ihm.h index 6894cc224..557e984eb 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm.h +++ b/code/ryzom/client/src/interface_v3/lua_ihm.h @@ -74,11 +74,6 @@ class CLuaIHM public: static void registerAll(CLuaState &ls); - // CInterfaceElement management on stack, stored by a CRefPtr. - static void pushUIOnStack(CLuaState &ls, class CInterfaceElement *pIE); - static bool isUIOnStack(CLuaState &ls, sint index); - static CInterfaceElement *getUIOnStack(CLuaState &ls, sint index); - /** CReflectableInterfaceElement management on stack, stored by a CRefPtr. * May be called as well for ui element, because they derive from CReflectableRefPtrTarget */ @@ -110,7 +105,6 @@ public: static void check(CLuaState &ls, bool ok, const std::string &failReason); static void checkArgType(CLuaState &ls, const char *funcName, uint index, int argType); static void checkArgTypeRGBA(CLuaState &ls, const char *funcName, uint index); - static void checkArgTypeUIElement(CLuaState &ls, const char *funcName, uint index); static void checkArgTypeUCString(CLuaState &ls, const char *funcName, uint index); /** throw a lua expection (inside a C function called from lua) with the given reason, and the current call stack * The various check... function call this function when their test fails @@ -140,16 +134,6 @@ private: static void registerIHM(CLuaState &ls); static void createLuaEnumTable(CLuaState &ls, const std::string &str); - // Functions for the ui metatable - static class CInterfaceElement *getUIRelative(class CInterfaceElement *pIE, const std::string &propName); - static int luaUIIndex(CLuaState &ls); - static int luaUINewIndex(CLuaState &ls); - static int luaUIEq(CLuaState &ls); - static int luaUINext(CLuaState &ls); - static int luaUIDtor(CLuaState &ls); - static int luaClientCfgIndex(CLuaState &ls); - static int luaClientCfgNewIndex(CLuaState &ls); - /// \name Exported Functions // @{ @@ -169,9 +153,6 @@ private: // Function export tools // Function to forward lua call to C++ to a 'lua method' exported from a reflected object static int luaMethodCall(lua_State *ls); - -public: - static int runExprAndPushResult(CLuaState &ls, const std::string &expr); // Used by runExpr and runFct }; diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index cb9ceae2e..b96bcb72d 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -100,6 +100,7 @@ #include "game_share/bg_downloader_msg.h" #include "game_share/constants.h" #include "game_share/visual_slot_manager.h" +#include "lua_manager.h" #ifdef LUA_NEVRAX_VERSION #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger @@ -148,6 +149,109 @@ private: REGISTER_ACTION_HANDLER( CHandlerLUA, "lua"); std::deque > CHandlerLUA::_UICallerStack; +// *************************************************************************** +// Allow also to call script from expression +static DECLARE_INTERFACE_USER_FCT(lua) +{ + if(args.size()!=1 || !args[0].toString()) + { + nlwarning(" requires 1 arg (string=script)"); + return false; + } + + // Retrieve lua state + CInterfaceManager *pIM= CInterfaceManager::getInstance(); + CLuaState *state= CLuaManager::getInstance().getLuaState(); + if(!state) + return false; + CLuaState &ls= *state; + + // *** clear return value + const std::string retId= "__ui_internal_ret_"; + CLuaStackChecker lsc(&ls); + ls.push(retId); + ls.pushNil(); + ls.setTable(LUA_GLOBALSINDEX); + + + // *** execute script + std::string script= args[0].getString(); + // assign return value in retId. + script= retId + "= " + script; + // execute a small script here, because most often exprs are called from xml files => lot of redundant script + pIM->executeLuaScript(script, true); + + + // *** retrieve and convert return value + ls.push(retId); + ls.getTable(LUA_GLOBALSINDEX); + bool ok= false; + sint type= ls.type(); + if (type==LUA_TBOOLEAN) + { + // get and pop + bool val= ls.toBoolean(); + ls.pop(); + // set result + result.setBool(val); + ok= true; + } + else if(type==LUA_TNUMBER) + { + // get and pop + double val= ls.toNumber(); + ls.pop(); + // set double or integer? + if(val==floor(val)) + result.setInteger(sint64(floor(val))); + else + result.setDouble(val); + ok= true; + } + else if(type==LUA_TSTRING) + { + // get and pop + std::string val; + ls.toString(-1, val); + ls.pop(); + // set result + result.setString(val); + ok= true; + } + else if(type==LUA_TUSERDATA) + { + // NB: the value is poped in obj.set() (no need to do ls.pop()); + + // try with ucstring + ucstring ucstrVal; + if (CLuaIHM::pop(ls, ucstrVal)) + { + result.setUCString(ucstrVal); + ok= true; + } + + // try with RGBA + if(!ok) + { + NLMISC::CRGBA rgbaVal; + if (CLuaIHM::pop(ls, rgbaVal)) + { + result.setRGBA(rgbaVal); + ok= true; + } + } + } + else + { + // error (nil for instance) + ls.pop(); + } + + return ok; +} +REGISTER_INTERFACE_USER_FCT("lua", lua) + + CCtrlBase *CHandlerLUA::getUICaller() { if(_UICallerStack.empty()) @@ -169,6 +273,440 @@ CCtrlBase *CHandlerLUA::getUICaller() #define LUABIND_FUNC(__func__) luabind::def(#__func__, &__func__) +// *************************************************************************** +int CLuaIHMRyzom::luaClientCfgIndex(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaClientCfgIndex) + CConfigFile::CVar *v = ClientCfg.ConfigFile.getVarPtr(ls.toString(2)); + if (!v) return 0; + if (v->size() != 1) + { + // arrays not implemented (would require a second metatable).... + throw ELuaWrappedFunctionException(&ls, "Access to array inside client.cfg not supported."); + } + switch(v->Type) + { + case CConfigFile::CVar::T_REAL: + ls.push((double) v->asDouble()); + return 1; + break; + case CConfigFile::CVar::T_STRING: + ls.push(v->asString()); + return 1; + break; + default: // handle both T_INT && T_BOOL + case CConfigFile::CVar::T_INT: + ls.push((double) v->asInt()); + return 1; + break; + } + return 0; +} + +// *************************************************************************** +int CLuaIHMRyzom::luaClientCfgNewIndex(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaClientCfgNewIndex) + throw ELuaWrappedFunctionException(&ls, "Can't write into config file from lua."); +} + +// *************************************************************************** +CInterfaceElement *CLuaIHMRyzom::getUIRelative(CInterfaceElement *pIE, const std::string &propName) +{ + //H_AUTO(Lua_CLuaIHM_getUIRelative) + if (pIE == NULL) return NULL; + // If the prop is "parent", then return the parent of the ui + if(propName=="parent") + { + return pIE->getParent(); + } + // else try to get a child (if group/exist) + else + { + CInterfaceGroup *group= dynamic_cast(pIE); + if(group) + { + return group->getElement(group->getId()+":"+propName); + } + } + + return NULL; +} + +static CLuaString lstr_Env("Env"); +static CLuaString lstr_isNil("isNil"); + +// *************************************************************************** +int CLuaIHMRyzom::luaUIIndex(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaUIIndex) + nlassert(ls.getTop()==2); + // get the userdata and key + CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); + + const char *propName = ls.toString(2); + CReflectableRefPtrTarget *pRPT= (CReflectableRefPtrTarget*)(pRefElm->Ptr); + // ** try to get the Env Table (interface group only) + if(propName==lstr_isNil) + { + ls.push(pRPT==NULL); + return 1; + } + + // Check the object is not NULL or freed + if(pRPT==NULL) + { + return 0; + } + + // ** try to get the Env Table (interface group only) + if(propName==lstr_Env) + { + // Env can be bound to a CInterfaceGroup only + CInterfaceGroup *group= dynamic_cast(pRPT); + if(group==NULL) + { + ls.pushNil(); + return 1; + } + else + { + group->pushLUAEnvTable(); + return 1; + } + } + + // ** try to get the property + const CReflectedProperty *prop = pRefElm->getProp(propName); + if (prop) + { + CLuaIHM::luaValueFromReflectedProperty(ls, *pRPT, *prop); + return 1; + } + + // ** try to get a UI relative + CInterfaceElement *uiRelative= getUIRelative(dynamic_cast(pRPT), propName); + if(uiRelative) + { + // push the UI onto the stack + pushUIOnStack(ls, uiRelative); + return 1; + } + + + // Fail to find any Attributes or elements + // Yoyo: don't write any message or warning because this may be a feature (if user want to test that something exit in the ui) + ls.pushNil(); + return 1; +} + +// *************************************************************************** +int CLuaIHMRyzom::luaUINewIndex(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaUINewIndex) + nlassert(ls.getTop()==3); + // get the userdata and key + CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); + nlassert(pRefElm); + CReflectableRefPtrTarget *pRPT= (CReflectableRefPtrTarget*)(pRefElm->Ptr); + // Check the UI is not NULL or freed + if(pRPT == NULL) + { + return 0; + } + + const char *propName = ls.toString(2); + // ** try to set the Env Table (interface group only) + if(propName == lstr_Env) + { + CInterfaceElement *pIE = dynamic_cast(pRPT); + std::string name ; + if (pIE) + { + name = pIE->getId(); + } + else + { + name = ""; + } + // Exception!!! not allowed + throw ELuaIHMException("You cannot change the Env Table of '%s'", name.c_str()); + } + + + // ** try to set the property + const CReflectedProperty *prop = pRefElm->getProp(propName); + if (prop) + { + CLuaIHM::luaValueToReflectedProperty(ls, 3, *pRPT, *prop); + return 0; + } + + CInterfaceElement *pIE = dynamic_cast(pRPT); + // ** try to get another UI (child or parent) + CInterfaceElement *uiRelative= getUIRelative(pIE, propName); + if(uiRelative) + { + // Exception!!! not allowed + throw ELuaIHMException("You cannot write into the UI '%s' of '%s'", propName, pIE->getId().c_str()); + } + + // ** Prop Not Found + throw ELuaIHMException("Property '%s' not found in '%s' of type %s", propName, pIE ? pIE->getId().c_str() : "", typeid(*pRPT).name()); + + // Fail to find any Attributes or elements + return 0; +} + +// *************************************************************************** +int CLuaIHMRyzom::luaUIEq(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaUIEq) + nlassert(ls.getTop() == 2); + // read lhs & rhs + // get the userdata and key + CReflectableLuaRef *lhs = (CReflectableLuaRef *) ls.toUserData(1); + CReflectableLuaRef *rhs = (CReflectableLuaRef *) ls.toUserData(2); + nlassert(lhs); + nlassert(rhs); + ls.push(lhs->Ptr == rhs->Ptr); + return 1; +} + + +// *************************************************************************** +int CLuaIHMRyzom::luaUIDtor(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaUIDtor) + nlassert(ls.getTop()==1); + // get the userdata + CReflectableLuaRef *pRefElm = (CReflectableLuaRef *) ls.toUserData(1); + nlassert(pRefElm); + + // call dtor + pRefElm->~CReflectableLuaRef(); + + return 0; +} + +// *************************************************************************** +int CLuaIHMRyzom::luaUINext(CLuaState &ls) +{ + //H_AUTO(Lua_CLuaIHM_luaUINext) + // Code below allow enumeration of properties of a reflectable object + // From lua standpoint, the object is seen as a table with (key, value) pairs + // If object is a CInterfaceGroup, iteration is also done on sons (groups, controls & view). + + if (ls.getTop() != 2) + { + CLuaIHM::fails(ls, "__next metamethod require 2 arguments (table & key)"); + } + CLuaIHM::check(ls, CLuaIHM::isReflectableOnStack(ls, 1), "__next : require ui element as first arg"); + CReflectableRefPtrTarget *reflectedObject = CLuaIHM::getReflectableOnStack(ls, 1); + // To traverse all properties / field of the object, we must be able to determine the next key from a previous key + // (keys are ordered) + // We use the 'TValueType' enum to know which kind of property we are traversing, and an index in this group of properties + // The key which uniquely identify an element / property in the reflectable object + struct CKey + { + enum TValueType + { + VTGroup = 0, // children groups (If the object is a CInterfaceGroup) + VTView, // children views (If the object is a CInterfaceView) + VTCtrl, // children controls (If the object is a CInterfaceCtrl) + VTProp // List of exported proeprties (For all relfectable objects) + }; + TValueType ValueType; + sint Index; + const CClassInfo *ClassInfo; // if ValueType is "VTProp" -> give the class for which property are currently enumerated + // + static int tostring(CLuaState &ls) // '__print' metamathod + { + CLuaIHM::checkArgCount(ls, "reflected object metatable:__print", 1); + CKey key; + key.pop(ls); + switch(key.ValueType) + { + case VTGroup: ls.push(toString("_Group %d", key.Index)); break; + case VTView: ls.push(toString("_View %d", key.Index)); break; + case VTCtrl: ls.push(toString("_Ctrl %d", key.Index)); break; + case VTProp: ls.push(key.ClassInfo->Properties[key.Index].Name); break; + } + return 1; + } + // push the key on the lua stack + void push(CLuaState &ls) + { + void *ud = ls.newUserData(sizeof(*this)); + *(CKey *) ud = *this; + getMetaTable(ls).push(); + ls.setMetaTable(-2); + } + // pop the key from the lua stack + void pop(CLuaState &ls) + { + CLuaStackChecker lsc(&ls, -1); + if (!ls.isUserData(-1)) + { + CLuaIHM::fails(ls, "Can't pop object, not a user data"); + } + // check that metatable is good (it is share between all keys) + ls.getMetaTable(-1); + getMetaTable(ls).push(); + if (!ls.rawEqual(-1, -2)) + { + CLuaIHM::fails(ls, "Bad metatable for reflectable object key"); + } + ls.pop(2); + // retrieve key + *this = *(CKey *) ls.toUserData(-1); + ls.pop(); + } + // get the metatable for a CKey + CLuaObject &getMetaTable(CLuaState &ls) + { + static CLuaObject metatable; + if (!metatable.isValid()) + { + // first build + CLuaStackChecker lsc(&ls); + ls.newTable(); + ls.push("__tostring"); + ls.push(CKey::tostring); + ls.setTable(-3); + metatable.pop(ls); + } + return metatable; + } + }; + // Pop the current key to continue enumeration + CKey key; + if (ls.isNil(2)) + { + // no key -> start of table + key.ValueType = CKey::VTGroup; + key.Index = -1; + } + else + { + key.pop(ls); + } + // + CInterfaceGroup *group = dynamic_cast(reflectedObject); + bool enumerate = true; + while (enumerate) + { + switch(key.ValueType) + { + case CKey::VTGroup: + if (!group || (key.Index + 1) == (sint) group->getGroups().size()) + { + key.Index = -1; + key.ValueType = CKey::VTView; // continue enumeration with views + } + else + { + ++ key.Index; + key.push(ls); + pushUIOnStack(ls, group->getGroups()[key.Index]); + return 2; + } + break; + case CKey::VTView: + if (!group || (key.Index + 1) == (sint) group->getViews().size()) + { + key.Index = -1; + key.ValueType = CKey::VTCtrl; // continue enumeration with controls + } + else + { + ++ key.Index; + key.push(ls); + pushUIOnStack(ls, group->getViews()[key.Index]); + return 2; + } + break; + case CKey::VTCtrl: + if (!group || (key.Index + 1) == (sint) group->getControls().size()) + { + key.Index = -1; + key.ValueType = CKey::VTProp; // continue enumeration with properties + key.ClassInfo = reflectedObject->getClassInfo(); + } + else + { + ++ key.Index; + key.push(ls); + pushUIOnStack(ls, group->getControls()[key.Index]); + return 2; + } + break; + case CKey::VTProp: + if (!key.ClassInfo) + { + enumerate = false; + break; + } + if ((sint) key.ClassInfo->Properties.size() == (key.Index + 1)) + { + key.ClassInfo = key.ClassInfo->ParentClass; // continue enumeration in parent class + key.Index = -1; + } + else + { + ++ key.Index; + key.push(ls); + CLuaIHM::luaValueFromReflectedProperty(ls, *reflectedObject, key.ClassInfo->Properties[key.Index]); + return 2; + } + break; + default: + nlassert(0); + break; + } + } + ls.pushNil(); + return 0; +} + +// *************************************************************************** +void CLuaIHMRyzom::pushUIOnStack(CLuaState &ls, class CInterfaceElement *pIE) +{ + //H_AUTO(Lua_CLuaIHM_pushUIOnStack) + CLuaIHM::pushReflectableOnStack(ls, pIE); +} + +// *************************************************************************** +bool CLuaIHMRyzom::isUIOnStack(CLuaState &ls, sint index) +{ + //H_AUTO(Lua_CLuaIHM_isUIOnStack) + return getUIOnStack(ls, index) != NULL; +} + +// *************************************************************************** +CInterfaceElement *CLuaIHMRyzom::getUIOnStack(CLuaState &ls, sint index) +{ + //H_AUTO(Lua_CLuaIHM_getUIOnStack) + return dynamic_cast(CLuaIHM::getReflectableOnStack(ls, index)); +} + +// *************************************************************************** +void CLuaIHMRyzom::checkArgTypeUIElement(CLuaState &ls, const char *funcName, uint index) +{ + //H_AUTO(Lua_CLuaIHM_checkArgTypeUIElement) + nlassert(index > 0); + if (ls.getTop() < (int) index) + { + CLuaIHM::fails(ls, "%s : argument %d of expected type ui element was not defined", funcName, index); + } + if (!isUIOnStack(ls, index)) + { + CLuaIHM::fails(ls, "%s : argument %d of expected type ui element has bad type : %s", funcName, index, ls.getTypename(ls.type(index)), ls.type(index)); + } +} + + + // *************************************************************************** void CLuaIHMRyzom::createLuaEnumTable(CLuaState &ls, const std::string &str) { @@ -193,6 +731,62 @@ void CLuaIHMRyzom::RegisterRyzomFunctions( NLGUI::CLuaState &ls ) { CLuaStackChecker lsc( &ls ); + // MISC ui ctors + struct CUICtor + { + // CGroupTree::SNode + static int SNode(CLuaState &ls) + { + CLuaIHM::checkArgCount(ls, "SNode", 0); + CLuaIHM::pushReflectableOnStack(ls, new CGroupTree::SNode); + return 1; + } + }; + + ls.registerFunc("SNode", CUICtor::SNode); + + // *** Register the metatable for access to client.cfg (nb nico this may be more general later -> access to any config file ...) + ls.pushValue(LUA_GLOBALSINDEX); + CLuaObject globals(ls); + CLuaObject clientCfg = globals.newTable("config"); + CLuaObject mt = globals.newTable("__cfmt"); + nlverify(clientCfg.setMetaTable(mt)); + mt.setValue("__index", luaClientCfgIndex); + mt.setValue("__newindex", luaClientCfgNewIndex); + globals.setNil("__cfmt"); // remove temp metatable + + // *** Register the MetaTable for UI userdata + ls.push(IHM_LUA_METATABLE); // "__ui_metatable" + ls.newTable(); // "__ui_metatable" {} + // set the '__index' method + ls.push("__index"); + ls.push(luaUIIndex); + nlassert(ls.isCFunction()); + ls.setTable(-3); // "__ui_metatable" {"__index"= CFunc_luaUIIndex} + // set the '__newindex' method + ls.push("__newindex"); + ls.push(luaUINewIndex); + nlassert(ls.isCFunction()); + ls.setTable(-3); + // set the '__newindex' method + ls.push("__gc"); + ls.push(luaUIDtor); + nlassert(ls.isCFunction()); + ls.setTable(-3); + // set the '__eq' method + ls.push("__eq"); + ls.push(luaUIEq); + nlassert(ls.isCFunction()); + ls.setTable(-3); + // set the custom '__next' method + ls.push("__next"); + ls.push(luaUINext); + nlassert(ls.isCFunction()); + ls.setTable(-3); + // set registry + ls.setTable(LUA_REGISTRYINDEX); + + ls.registerFunc( "getUI", getUI ); ls.registerFunc("setOnDraw", setOnDraw); ls.registerFunc("setCaptureKeyboard", setCaptureKeyboard); @@ -438,7 +1032,7 @@ int CLuaIHMRyzom::getUI(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, pIE); + pushUIOnStack(ls, pIE); } return 1; } @@ -449,8 +1043,8 @@ int CLuaIHMRyzom::setCaptureKeyboard(CLuaState &ls) //H_AUTO(Lua_CLuaIHM_setCaptureKeyboard) const char *funcName = "setCaptureKeyboard"; CLuaIHM::checkArgCount(ls, funcName, 1); - CLuaIHM::checkArgTypeUIElement(ls, funcName, 1); - CCtrlBase *ctrl = dynamic_cast( CLuaIHM::getUIOnStack(ls, 1)); + checkArgTypeUIElement(ls, funcName, 1); + CCtrlBase *ctrl = dynamic_cast( getUIOnStack(ls, 1)); if (!ctrl) { CLuaIHM::fails(ls, "%s waits a ui control as arg 1", funcName); @@ -480,11 +1074,11 @@ int CLuaIHMRyzom::setOnDraw(CLuaState &ls) // params: CInterfaceGroup*, "script". // return: none CLuaIHM::checkArgCount(ls, "setOnDraw", 2); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "setOnDraw() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "setOnDraw() requires a UI object in param 1"); CLuaIHM::check(ls, ls.isString(2), "setOnDraw() requires a string in param 2"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); std::string script; ls.toString(2, script); @@ -507,12 +1101,12 @@ int CLuaIHMRyzom::addOnDbChange(CLuaState &ls) // params: CInterfaceGroup*, "dblist", "script". // return: none CLuaIHM::checkArgCount(ls, "addOnDbChange", 3); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "addOnDbChange() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "addOnDbChange() requires a UI object in param 1"); CLuaIHM::check(ls, ls.isString(2), "addOnDbChange() requires a string in param 2"); CLuaIHM::check(ls, ls.isString(3), "addOnDbChange() requires a string in param 3"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); std::string dbList, script; ls.toString(2, dbList); ls.toString(3, script); @@ -537,11 +1131,11 @@ int CLuaIHMRyzom::removeOnDbChange(CLuaState &ls) // params: CInterfaceGroup*, "dbList" // return: none CLuaIHM::checkArgCount(ls, "removeOnDbChange", 2); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "removeOnDbChange() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "removeOnDbChange() requires a UI object in param 1"); CLuaIHM::check(ls, ls.isString(2), "removeOnDbChange() requires a string in param 2"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); std::string dbList; ls.toString(2, dbList); @@ -565,12 +1159,12 @@ int CLuaIHMRyzom::runAH(CLuaState &ls) // params: CInterfaceElement *, "ah", "params". // return: none CLuaIHM::checkArgCount(ls, "runAH", 3); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1) || ls.isNil(1), "runAH() requires a UI object in param 1 (or Nil)"); + CLuaIHM::check(ls, isUIOnStack(ls, 1) || ls.isNil(1), "runAH() requires a UI object in param 1 (or Nil)"); CLuaIHM::check(ls, ls.isString(2), "runAH() requires a string in param 2"); CLuaIHM::check(ls, ls.isString(3), "runAH() requires a string in param 3"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); std::string ah, params; ls.toString(2, ah); ls.toString(3, params); @@ -606,7 +1200,7 @@ int CLuaIHMRyzom::runExpr(CLuaState &ls) ls.toString(1, expr); // run expression and push result - return CLuaIHM::runExprAndPushResult(ls, expr); + return runExprAndPushResult(ls, expr); } // *************************************************************************** @@ -654,7 +1248,7 @@ int CLuaIHMRyzom::runFct(CLuaState &ls) // run expression and push result - return CLuaIHM::runExprAndPushResult(ls, expr); + return runExprAndPushResult(ls, expr); } // *************************************************************************** @@ -780,10 +1374,10 @@ int CLuaIHMRyzom::deleteUI(CLuaState &ls) // params: CInterfaceElement * // return: none CLuaIHM::checkArgCount(ls, "deleteUI", 1); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "deleteUI() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "deleteUI() requires a UI object in param 1"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); if(!pIE) return 0; @@ -848,10 +1442,10 @@ int CLuaIHMRyzom::dumpUI(CLuaState &ls) // params: CInterfaceElement * // return: none CLuaIHM::checkArgCount(ls, "dumpUI", 1); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "dumpUI() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "dumpUI() requires a UI object in param 1"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); if(!pIE) debugInfo("UI: NULL"); else @@ -904,7 +1498,7 @@ int CLuaIHMRyzom::setTopWindow(CLuaState &ls) //H_AUTO(Lua_CLuaIHM_setTopWindow) const char *funcName = "setTopWindow"; CLuaIHM::checkArgCount(ls, funcName, 1); - CInterfaceGroup *wnd = dynamic_cast(CLuaIHM::getUIOnStack(ls, 1)); + CInterfaceGroup *wnd = dynamic_cast( getUIOnStack(ls, 1)); if (!wnd) { CLuaIHM::fails(ls, "%s : interface group expected as arg 1", funcName); @@ -1030,8 +1624,8 @@ int CLuaIHMRyzom::setTextFormatTaged(CLuaState &ls) CLuaIHM::checkArgCount(ls, "setTextFormatTaged", 2); // *** check and retrieve param 1 - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "setTextFormatTaged() requires a UI object in param 1"); - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "setTextFormatTaged() requires a UI object in param 1"); + CInterfaceElement *pIE= getUIOnStack(ls, 1); // *** check and retrieve param 2. must be a string or a ucstring ucstring text; @@ -1392,10 +1986,10 @@ int CLuaIHMRyzom::enableModalWindow(CLuaState &ls) const char *funcName = "enableModalWindow"; CLuaIHM::checkArgCount(ls, funcName, 2); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "enableModalWindow() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "enableModalWindow() requires a UI object in param 1"); CLuaIHM::checkArgType(ls, funcName, 2, LUA_TSTRING); - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); std::string modalId = ls.toString(2); // convert to id @@ -1612,10 +2206,10 @@ int CLuaIHMRyzom::disableContextHelpForControl(CLuaState &ls) // params: CCtrlBase* // return: none CLuaIHM::checkArgCount(ls, "disableContextHelpForControl", 1); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "disableContextHelpForControl() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "disableContextHelpForControl() requires a UI object in param 1"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); // go CInterfaceManager *pIM= CInterfaceManager::getInstance(); @@ -1815,7 +2409,7 @@ int CLuaIHMRyzom::getUICaller(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, pIE); + pushUIOnStack(ls, pIE); } return 1; } @@ -1833,7 +2427,7 @@ int CLuaIHMRyzom::getCurrentWindowUnder(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, pIE); + pushUIOnStack(ls, pIE); } return 1; } @@ -1847,10 +2441,10 @@ int CLuaIHMRyzom::getUIId(CLuaState &ls) // params: CInterfaceElement* // return: "ui:interface:...". (empty if error) CLuaIHM::checkArgCount(ls, "getUIId", 1); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "getUIId() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "getUIId() requires a UI object in param 1"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); // convert to id if(pIE) @@ -1870,10 +2464,10 @@ int CLuaIHMRyzom::getIndexInDB(CLuaState &ls) // params: CDBCtrlSheet* // return: index in DB of a dbctrlsheet (empty if error) CLuaIHM::checkArgCount(ls, "getIndexInDB", 1); - CLuaIHM::check(ls, CLuaIHM::isUIOnStack(ls, 1), "getIndexInDB() requires a UI object in param 1"); + CLuaIHM::check(ls, isUIOnStack(ls, 1), "getIndexInDB() requires a UI object in param 1"); // retrieve args - CInterfaceElement *pIE= CLuaIHM::getUIOnStack(ls, 1); + CInterfaceElement *pIE= getUIOnStack(ls, 1); CDBCtrlSheet *pCS= dynamic_cast(pIE); // get the index in db @@ -1919,7 +2513,7 @@ int CLuaIHMRyzom::createGroupInstance(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, result); + pushUIOnStack(ls, result); } return 1; } @@ -1966,7 +2560,7 @@ int CLuaIHMRyzom::createRootGroupInstance(CLuaState &ls) if (pRoot) pRoot->addGroup(result); result->setActive(true); - CLuaIHM::pushUIOnStack(ls, result); + pushUIOnStack(ls, result); } return 1; } @@ -2005,7 +2599,7 @@ int CLuaIHMRyzom::createUIElement(CLuaState &ls) } else { - CLuaIHM::pushUIOnStack(ls, result); + pushUIOnStack(ls, result); } return 1; } @@ -2256,7 +2850,7 @@ void CLuaIHMRyzom::debugInfo(const std::string &cstDbg) if (ClientCfg.LuaDebugInfoGotoButtonEnabled) { CInterfaceManager *pIM= CInterfaceManager::getInstance(); - lua_State *ls = pIM->getLuaState()->getStatePointer(); + lua_State *ls = CLuaManager::getInstance().getLuaState()->getStatePointer(); lua_Debug luaDbg; if(lua_getstack (ls, 1, &luaDbg)) { @@ -2305,7 +2899,7 @@ void CLuaIHMRyzom::dumpCallStack(int startStackLevel) { lua_Debug dbg; CInterfaceManager *pIM= CInterfaceManager::getInstance(); - lua_State *ls = pIM->getLuaState()->getStatePointer(); + lua_State *ls = CLuaManager::getInstance().getLuaState()->getStatePointer(); int stackLevel = startStackLevel; rawDebugInfo("Call stack : "); rawDebugInfo("-------------"); @@ -2328,7 +2922,7 @@ void CLuaIHMRyzom::getCallStackAsString(int startStackLevel /*=0*/,std::string & result.clear(); lua_Debug dbg; CInterfaceManager *pIM= CInterfaceManager::getInstance(); - lua_State *ls = pIM->getLuaState()->getStatePointer(); + lua_State *ls = CLuaManager::getInstance().getLuaState()->getStatePointer(); int stackLevel = startStackLevel; result += "Call stack : \n"; result += "-------------"; @@ -3269,3 +3863,75 @@ std::string CLuaIHMRyzom::createGotoFileButtonTag(const char *fileName, uint lin } return ""; } + +// *************************************************************************** +int CLuaIHMRyzom::runExprAndPushResult(CLuaState &ls, const std::string &expr) +{ + //H_AUTO(Lua_CLuaIHM_runExprAndPushResult) + // Execute expression + CInterfaceExprValue value; + if (CInterfaceExpr::eval(expr, value, NULL)) + { + switch(value.getType()) + { + case CInterfaceExprValue::Boolean: + ls.push(value.getBool()); + break; + case CInterfaceExprValue::Integer: + ls.push((double)value.getInteger()); + break; + case CInterfaceExprValue::Double: + ls.push(value.getDouble()); + break; + case CInterfaceExprValue::String: + { + ucstring ucstr= value.getUCString(); + // Yoyo: dynamically decide whether must return a string or a ucstring + bool mustUseUCString= false; + for (uint i = 0; i < ucstr.size (); i++) + { + if (ucstr[i] > 255) + { + mustUseUCString= true; + break; + } + } + // push a ucstring? + if(mustUseUCString) + { +#if LUABIND_VERSION > 600 + luabind::detail::push(ls.getStatePointer(), ucstr); +#else + luabind::object obj(ls.getStatePointer(), ucstr); + obj.pushvalue(); +#endif + } + else + { + ls.push(ucstr.toString()); + } + break; + } + case CInterfaceExprValue::RGBA: + { + CRGBA color = value.getRGBA(); +#if LUABIND_VERSION > 600 + luabind::detail::push(ls.getStatePointer(), color); +#else + luabind::object obj(ls.getStatePointer(), color); + obj.pushvalue(); +#endif + break; + } + break; + case CInterfaceExprValue::UserType: // Yoyo: don't care UserType... + default: + ls.pushNil(); + break; + } + } + else + ls.pushNil(); + + return 1; +} diff --git a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h index 200adbab6..3c046a38d 100644 --- a/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h +++ b/code/ryzom/client/src/interface_v3/lua_ihm_ryzom.h @@ -11,6 +11,25 @@ public: private: static void createLuaEnumTable(CLuaState &ls, const std::string &str); + static int luaClientCfgIndex(CLuaState &ls); + static int luaClientCfgNewIndex(CLuaState &ls); + + // Functions for the ui metatable + static class CInterfaceElement *getUIRelative(class CInterfaceElement *pIE, const std::string &propName); + static int luaUIIndex(CLuaState &ls); + static int luaUINewIndex(CLuaState &ls); + static int luaUIEq(CLuaState &ls); + static int luaUINext(CLuaState &ls); + static int luaUIDtor(CLuaState &ls); + + // CInterfaceElement management on stack, stored by a CRefPtr. +public: + static void pushUIOnStack(CLuaState &ls, class CInterfaceElement *pIE); + static bool isUIOnStack(CLuaState &ls, sint index); + static CInterfaceElement *getUIOnStack(CLuaState &ls, sint index); + static void checkArgTypeUIElement(CLuaState &ls, const char *funcName, uint index); + +private: static int getUI(CLuaState &ls); // params: "ui:interface:...". return: CInterfaceElement* (nil if error), an additionnal boolean parameter // LUA exported Functions with standard lua (because use ui object, use variable param number, or return dynamic-typed object) @@ -251,6 +270,8 @@ public: // Requires that 'ClientCfg.LuaDebugInfoGotoButtonEnabled' is set to 1, else // a, empty tag is returned static std::string createGotoFileButtonTag(const char *fileName, uint line); + + static int runExprAndPushResult(CLuaState &ls, const std::string &expr); // Used by runExpr and runFct }; #endif diff --git a/code/ryzom/client/src/interface_v3/lua_manager.cpp b/code/ryzom/client/src/interface_v3/lua_manager.cpp new file mode 100644 index 000000000..ccfeb147a --- /dev/null +++ b/code/ryzom/client/src/interface_v3/lua_manager.cpp @@ -0,0 +1,34 @@ +// 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 "lua_manager.h" +#include "nel/gui/lua_helper.h" + +bool CLuaManager::debugLua = false; +CLuaManager* CLuaManager::instance = NULL; + +CLuaManager::CLuaManager() +{ + luaState = new NLGUI::CLuaState( debugLua ); +} + +CLuaManager::~CLuaManager() +{ + luaState = NULL; +} + + diff --git a/code/ryzom/client/src/interface_v3/lua_manager.h b/code/ryzom/client/src/interface_v3/lua_manager.h new file mode 100644 index 000000000..246e7bbd6 --- /dev/null +++ b/code/ryzom/client/src/interface_v3/lua_manager.h @@ -0,0 +1,57 @@ +// 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 . + +#ifndef LUA_MANAGER_H +#define LUA_MANAGER_H + +#include "nel/misc/smart_ptr.h" + +namespace NLGUI +{ + class CLuaState; +} + +/// Provides a single global access point to the Lua state, and related stuff. :( +class CLuaManager +{ +public: + ~CLuaManager(); + + static CLuaManager& getInstance() + { + if( instance == NULL ) + { + instance = new CLuaManager(); + } + return *instance; + } + + /// Enables attaching the Lua debugger in the CLuaState instance, only matters on startup. + static void enableLuaDebugging(){ debugLua = true; } + + NLGUI::CLuaState* getLuaState() const{ return luaState; } + +private: + CLuaManager(); + + static CLuaManager *instance; + static bool debugLua; + + NLMISC::CSmartPtr< NLGUI::CLuaState > luaState; +}; + + +#endif diff --git a/code/ryzom/client/src/interface_v3/lua_object.cpp b/code/ryzom/client/src/interface_v3/lua_object.cpp index 209d7ba0c..109fce0a2 100644 --- a/code/ryzom/client/src/interface_v3/lua_object.cpp +++ b/code/ryzom/client/src/interface_v3/lua_object.cpp @@ -17,7 +17,7 @@ //#include "stdpch.h" #include "lua_object.h" #include "lua_ihm.h" -#include "lua_ihm_ryzom.h" +//#include "lua_ihm_ryzom.h" #include "nel/gui/lua_helper.h" using namespace NLGUI; // @@ -617,7 +617,7 @@ void CLuaObject::dump(uint maxDepth /*= 20*/, std::set *alreadySee } catch(const std::exception &e) { - CLuaIHMRyzom::dumpCallStack(); + //CLuaIHMRyzom::dumpCallStack(); nlwarning(e.what()); } } diff --git a/code/ryzom/client/src/interface_v3/reflect.cpp b/code/ryzom/client/src/interface_v3/reflect.cpp index 17476ca52..a99d26243 100644 --- a/code/ryzom/client/src/interface_v3/reflect.cpp +++ b/code/ryzom/client/src/interface_v3/reflect.cpp @@ -15,9 +15,6 @@ // along with this program. If not, see . - - -#include "stdpch.h" #include "reflect.h" // Yoyo: Act like a singleton, else registerClass may crash. @@ -132,4 +129,63 @@ const CReflectedProperty *CReflectable::getReflectedProperty(const std::string & } +#include "lua_manager.h" +CReflectableRefPtrTarget::~CReflectableRefPtrTarget() +{ + CLuaState *lua= CLuaManager::getInstance().getLuaState(); + if(!lua) + return; + CLuaStackChecker lsc(lua); + // remove from the lua registry if i'm in + lua->pushLightUserData((void *) this); + lua->getTable(LUA_REGISTRYINDEX); + if (!lua->isNil(-1)) + { + lua->pop(); + lua->pushLightUserData((void *) this); + lua->pushNil(); + lua->setTable(LUA_REGISTRYINDEX); + } + else + { + lua->pop(); + } +} + +/** + * Data structure pushed in lua (a userdata) to access CReflectableRefPtrTarget derived objects + * These includes element of the GUI. + * if holds a pointer to the reflectable object, and + * a cache to its CClassInfo for fast access to exported properties + * \see reflect.h + */ + +// + +inline const CClassInfo &CReflectableLuaRef::getClassInfo() const +{ + nlassert(Ptr); // class info should not be accessed for a null ptr + if (_ClassInfo) return *_ClassInfo; + _ClassInfo = Ptr->getClassInfo(); + return *_ClassInfo; +} + +const CReflectedProperty *CReflectableLuaRef::getProp(const char *luaStringPtr) const +{ + const CClassInfo &ci = getClassInfo(); + CClassInfo::TLuaStrToPropMap::const_iterator it = ci.LuaStrToProp.find(luaStringPtr); + if (it != ci.LuaStrToProp.end()) + { + return it->second.Prop; + } + // slowly retrieve property, and store in cache + // NB nico : this could also be done at startup... + const CReflectedProperty *prop = CReflectSystem::getProperty(ci.ClassName, luaStringPtr, false); + if (!prop) return NULL; + CLuaIndexedProperty lip; + lip.Id = CLuaString(luaStringPtr); // keep a ref on the lua string to ensure that its pointer always remains valid + lip.Prop = prop; + ci.LuaStrToProp[luaStringPtr] = lip; + return prop; +} diff --git a/code/ryzom/client/src/interface_v3/reflect.h b/code/ryzom/client/src/interface_v3/reflect.h index 5dbdbe554..6fbb8097f 100644 --- a/code/ryzom/client/src/interface_v3/reflect.h +++ b/code/ryzom/client/src/interface_v3/reflect.h @@ -340,10 +340,31 @@ private: +/** Reflectable refcounted object + * NB nico : added this intermediate class so that the binding from lua to the reflection + * system that are found in CLuaIHM can be reused for other objects as well + * NOTE: The class is named 'CReflectableRefPtrTarget' and not 'CReflectableRefCount' + * because the refcount part is only used for ref pointing in the ui + */ +class CReflectableRefPtrTarget : public CReflectable, public NLMISC::CRefCount +{ +public: + virtual ~CReflectableRefPtrTarget(); +}; - - +class CReflectableLuaRef +{ +public: + CReflectableLuaRef(CReflectableRefPtrTarget *ptr = NULL) : Ptr(ptr), _ClassInfo(NULL) {} + NLMISC::CRefPtr Ptr; + const CClassInfo &getClassInfo() const; + // IMPORTANT : luaStringPtr should have been obtained from lua, see remark in CClassInfo + const CReflectedProperty *getProp(const char *luaStringPtr) const; +private: + // cache to class definition of the pointee object (once a CReflectableLuaRef created in lua, it remains a *const* pointer) + mutable const CClassInfo *_ClassInfo; +}; #endif diff --git a/code/ryzom/client/src/main_loop.cpp b/code/ryzom/client/src/main_loop.cpp index 635e2476a..6ec4b99f4 100644 --- a/code/ryzom/client/src/main_loop.cpp +++ b/code/ryzom/client/src/main_loop.cpp @@ -112,6 +112,7 @@ #include "connection.h" #include "landscape_poly_drawer.h" #include "interface_v3/lua_ihm.h" +#include "interface_v3/lua_ihm_ryzom.h" #include "far_tp.h" #include "session_browser_impl.h" #include "bg_downloader_access.h" @@ -144,6 +145,8 @@ #include "interface_v3/bot_chat_manager.h" #include "string_manager_client.h" +#include "interface_v3/lua_manager.h" + /////////// // USING // @@ -1514,7 +1517,7 @@ bool mainLoop() R2::getEditor().waitScenario(); } - CSessionBrowserImpl::getInstance().init(CInterfaceManager::getInstance()->getLuaState()); + CSessionBrowserImpl::getInstance().init(CLuaManager::getInstance().getLuaState()); } CInterfaceManager::getInstance()->executeLuaScript("game:onMainLoopBegin()"); @@ -2977,7 +2980,7 @@ bool mainLoop() } // end of main loop CInterfaceManager *im = CInterfaceManager::getInstance(); - if (im->getLuaState()) + if (CLuaManager::getInstance().getLuaState()) { CInterfaceManager::getInstance()->executeLuaScript("game:onMainLoopEnd()"); } @@ -3228,11 +3231,10 @@ class CHandlerDebugUiDumpElementUnderMouse : public IActionHandler virtual void execute (CCtrlBase * /* pCaller */, const std::string &/* sParams */) { if (HighlightedDebugUI == NULL) return; - CInterfaceManager *pIM = CInterfaceManager::getInstance(); - CLuaState *lua = pIM->getLuaState(); + CLuaState *lua = CLuaManager::getInstance().getLuaState(); if (!lua) return; CLuaStackRestorer lsr(lua, 0); - CLuaIHM::pushUIOnStack(*lua, HighlightedDebugUI); + CLuaIHMRyzom::pushUIOnStack(*lua, HighlightedDebugUI); lua->pushValue(LUA_GLOBALSINDEX); CLuaObject env(*lua); env["inspect"].callNoThrow(1, 0); @@ -3403,9 +3405,9 @@ void displayDebug() line-= 2 * lineStep; // Lua stuffs CInterfaceManager *pIM = CInterfaceManager::getInstance(); - TextContext->printfAt(0.0f, line, "Lua mem (kb) : %d / %d", pIM->getLuaState()->getGCCount(), pIM->getLuaState()->getGCThreshold()); + TextContext->printfAt(0.0f, line, "Lua mem (kb) : %d / %d", CLuaManager::getInstance().getLuaState()->getGCCount(), CLuaManager::getInstance().getLuaState()->getGCThreshold()); line-= lineStep; - TextContext->printfAt(0.0f, line, "Lua stack size = %d", pIM->getLuaState()->getTop()); + TextContext->printfAt(0.0f, line, "Lua stack size = %d", CLuaManager::getInstance().getLuaState()->getTop()); line-= lineStep; #endif diff --git a/code/ryzom/client/src/r2/editor.cpp b/code/ryzom/client/src/r2/editor.cpp index f2a6119e6..f6c43b2f7 100644 --- a/code/ryzom/client/src/r2/editor.cpp +++ b/code/ryzom/client/src/r2/editor.cpp @@ -113,6 +113,7 @@ using namespace NLGUI; #include "../session_browser_impl.h" #include "../far_tp.h" +#include "../interface_v3/lua_manager.h" using namespace NLMISC; @@ -587,7 +588,7 @@ CLuaState &CEditor::getLua() { //H_AUTO(R2_CEditor_getLua) CHECK_EDITOR - CLuaState *ls = getUI().getLuaState(); + CLuaState *ls = CLuaManager::getInstance().getLuaState(); nlassert(ls); return *ls; } @@ -3953,7 +3954,7 @@ void CEditor::release() } // clear the environment - if (getUI().getLuaState()) + if (CLuaManager::getInstance().getLuaState()) { getLua().push(R2_LUA_PATH); getLua().pushNil(); diff --git a/code/ryzom/client/src/release.cpp b/code/ryzom/client/src/release.cpp index 3695ec1ac..e63dfa260 100644 --- a/code/ryzom/client/src/release.cpp +++ b/code/ryzom/client/src/release.cpp @@ -90,6 +90,7 @@ #include "faction_war_manager.h" #include "interface_v3/interface_ddx.h" #include "bg_downloader_access.h" +#include "interface_v3/lua_manager.h" /////////// @@ -633,6 +634,8 @@ void release() CInterfaceExpr::release(); CPdrTokenRegistry::releaseInstance(); NLNET::IModuleManager::releaseInstance(); + delete &CLuaManager::getInstance(); +