1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2019 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2019-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/gui/lua_helper.h"
24 #include "nel/gui/interface_group.h"
28 // to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages
38 // Warning: cannot use namespace std, when using luabind
40 # ifndef NL_EXTENDED_FOR_SCOPE
46 # define assert(x) nlassert(x)
51 // Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20,
52 // since the setting is not stored in build_information.hpp
53 #ifndef LUABIND_USE_CXX11
54 #define LUABIND_USE_CXX11
57 #include <luabind/luabind.hpp>
58 // in luabind > 0.6, LUABIND_MAX_ARITY is set to 10
59 #if LUABIND_MAX_ARITY == 10
60 # include <luabind/operator.hpp>
61 // only luabind > 0.7 have version.hpp (file checked with build system)
62 # ifdef HAVE_LUABIND_VERSION
63 # include <luabind/version.hpp>
65 # ifndef LUABIND_VERSION
66 // luabind 0.7 doesn't define LUABIND_VERSION
67 # define LUABIND_VERSION 700
69 // luabind 0.6 doesn't define LUABIND_VERSION but LUABIND_MAX_ARITY is set to 5
70 #elif LUABIND_MAX_ARITY == 5
71 # define LUABIND_VERSION 600
73 # pragma error("luabind version not recognized")
77 #include "nel/gui/lua_ihm.h"
78 #include "nel/gui/reflect.h"
79 #include "nel/misc/algo.h"
80 #include "nel/misc/file.h"
81 #include "nel/misc/i18n.h"
82 #include "nel/misc/time_nl.h"
83 #include "nel/misc/path.h"
84 #include "nel/misc/sstring.h"
85 #include "nel/misc/command.h"
86 #include "nel/gui/lua_object.h"
87 #include "nel/misc/polygon.h"
88 #include "nel/gui/lua_manager.h"
89 #include "nel/gui/widget_manager.h"
90 #include "nel/gui/action_handler.h"
91 #include "nel/gui/view_renderer.h"
92 #include "nel/gui/interface_expr.h"
93 #include "nel/misc/debug.h"
95 // ***************************************************************************
97 IMPORTANT NOTE: we do this heavy double registration in this file because we DON'T want
98 to include luabind.hpp in every file.
99 Compilation is VERY SLOW
101 // ***************************************************************************
103 using namespace NLMISC
;
106 #define new DEBUG_NEW
109 #ifdef RYZOM_LUA_UCSTRING
110 // declare ostream << operator for ucstring -> registration of ucstring iin luabind will build a 'tostring' function from it
111 std::ostream
&operator<<(std::ostream
&str
, const ucstring
&value
)
113 return str
<< value
.toString();
120 struct CMiscFunctions
122 static std::string
fileLookup(const std::string
&fileName
)
124 return NLMISC::CPath::lookup(fileName
, false);
126 static void shellExecute(const std::string
&operation
, const std::string
&fileName
, const std::string
¶meters
)
130 ShellExecuteW(NULL
, nlUtf8ToWide(operation
), nlUtf8ToWide(fileName
), nlUtf8ToWide(parameters
), NULL
, SW_SHOWDEFAULT
);
137 // ***************************************************************************
138 bool CLuaIHM::pop(CLuaState
&ls
, NLMISC::CRGBA
&dest
)
140 //H_AUTO(Lua_CLuaIHM_pop)
143 if (ls
.isNil(-1)) return false;
144 #if LUABIND_VERSION > 600
145 luabind::object
obj(luabind::from_stack(ls
.getStatePointer(), -1));
148 luabind::object
obj(ls
.getStatePointer());
151 dest
= luabind::object_cast
<NLMISC::CRGBA
>(obj
);
153 catch(const luabind::cast_failed
&)
160 // ***************************************************************************
161 bool CLuaIHM::pop(CLuaState
&ls
,NLMISC::CVector2f
&dest
)
163 //H_AUTO(Lua_CLuaIHM_pop)
166 if (ls
.isNil(-1)) return false;
167 #if LUABIND_VERSION > 600
168 luabind::object
obj(luabind::from_stack(ls
.getStatePointer(), -1));
171 luabind::object
obj(ls
.getStatePointer());
174 dest
= luabind::object_cast
<NLMISC::CVector2f
>(obj
);
176 catch(const luabind::cast_failed
&)
183 #ifdef RYZOM_LUA_UCSTRING
184 // ***************************************************************************
185 bool CLuaIHM::pop(CLuaState
&ls
, ucstring
&dest
)
187 //H_AUTO(Lua_CLuaIHM_pop)
190 if (ls
.isNil(-1)) return false;
191 #if LUABIND_VERSION > 600
192 luabind::object
obj(luabind::from_stack(ls
.getStatePointer(), -1));
195 luabind::object
obj(ls
.getStatePointer());
198 dest
= luabind::object_cast
<ucstring
>(obj
);
200 catch(const luabind::cast_failed
&)
207 // ***************************************************************************
208 bool CLuaIHM::isUCStringOnStack(CLuaState
&ls
, sint index
)
210 //H_AUTO(Lua_CLuaIHM_isUCStringOnStack)
213 return pop(ls
, dummy
);
216 // ***************************************************************************
217 bool CLuaIHM::getUCStringOnStack(CLuaState
&ls
, sint index
, ucstring
&dest
)
219 //H_AUTO(Lua_CLuaIHM_getUCStringOnStack)
221 return pop(ls
, dest
);
225 // ***************************************************************************
226 void CLuaIHM::push(CLuaState
&ls
, const ucstring
&value
)
228 //H_AUTO(Lua_CLuaIHM_push)
229 #if defined(LUABIND_STACK_HPP_INCLUDED)
230 luabind::push(ls
.getStatePointer(), value
);
231 #elif (LUABIND_VERSION > 600)
232 luabind::detail::push(ls
.getStatePointer(), value
);
234 luabind::object
obj(ls
.getStatePointer(), value
);
240 // ***************************************************************************
241 // ***************************************************************************
242 // CInterface To LUA Registry
243 // ***************************************************************************
244 // ***************************************************************************
247 CLuaState
* ELuaIHMException::getLuaState()
249 return CLuaManager::getInstance().getLuaState();
254 // ***************************************************************************
255 #define LUA_REGISTER_BASIC(_type_) \
256 luabind::detail::yes_t is_user_defined(luabind::detail::by_value<_type_>); \
257 _type_ convert_lua_to_cpp(lua_State* L, luabind::detail::by_value<_type_>, int index) \
259 return (_type_)lua_tointeger(L, index); \
261 int match_lua_to_cpp(lua_State* L, luabind::detail::by_value<_type_>, int index) \
263 return lua_isnumber(L, index) ? 0:-1; \
265 void convert_cpp_to_lua(lua_State* L, const _type_& v) \
267 lua_pushinteger(L, (lua_Integer)v); \
275 LUA_REGISTER_BASIC(sint8
)
276 LUA_REGISTER_BASIC(uint8
)
277 LUA_REGISTER_BASIC(sint16
)
278 LUA_REGISTER_BASIC(uint16
)
279 LUA_REGISTER_BASIC(sint32
)
280 LUA_REGISTER_BASIC(uint32
)
286 static CLuaString
lstr_Env("Env");
287 static CLuaString
lstr_isNil("isNil");
289 // ***************************************************************************
290 int CLuaIHM::luaUIIndex(CLuaState
&ls
)
292 //H_AUTO(Lua_CLuaIHM_luaUIIndex)
293 nlassert(ls
.getTop()==2);
294 // get the userdata and key
295 CReflectableLuaRef
*pRefElm
= (CReflectableLuaRef
*) ls
.toUserData(1);
297 const char *propName
= ls
.toString(2);
298 CReflectableRefPtrTarget
*pRPT
= (CReflectableRefPtrTarget
*)(pRefElm
->Ptr
);
299 // ** try to get the Env Table (interface group only)
300 if(propName
==lstr_isNil
)
306 // Check the object is not NULL or freed
312 // ** try to get the Env Table (interface group only)
313 if(propName
==lstr_Env
)
315 // Env can be bound to a CInterfaceGroup only
316 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pRPT
);
324 group
->pushLUAEnvTable();
329 // ** try to get the property
330 const CReflectedProperty
*prop
= pRefElm
->getProp(propName
);
333 CLuaIHM::luaValueFromReflectedProperty(ls
, *pRPT
, *prop
);
337 // ** try to get a UI relative
338 CInterfaceElement
*uiRelative
= getUIRelative(dynamic_cast<CInterfaceElement
*>(pRPT
), propName
);
341 // push the UI onto the stack
342 pushUIOnStack(ls
, uiRelative
);
347 // Fail to find any Attributes or elements
348 // 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)
353 // ***************************************************************************
354 int CLuaIHM::luaUINewIndex(CLuaState
&ls
)
356 //H_AUTO(Lua_CLuaIHM_luaUINewIndex)
357 nlassert(ls
.getTop()==3);
358 // get the userdata and key
359 CReflectableLuaRef
*pRefElm
= (CReflectableLuaRef
*) ls
.toUserData(1);
361 CReflectableRefPtrTarget
*pRPT
= (CReflectableRefPtrTarget
*)(pRefElm
->Ptr
);
362 // Check the UI is not NULL or freed
368 const char *propName
= ls
.toString(2);
369 // ** try to set the Env Table (interface group only)
370 if(propName
== lstr_Env
)
372 CInterfaceElement
*pIE
= dynamic_cast<CInterfaceElement
*>(pRPT
);
380 name
= "<reflectable element>";
382 // Exception!!! not allowed
383 throw ELuaIHMException("You cannot change the Env Table of '%s'", name
.c_str());
387 // ** try to set the property
388 const CReflectedProperty
*prop
= pRefElm
->getProp(propName
);
391 CLuaIHM::luaValueToReflectedProperty(ls
, 3, *pRPT
, *prop
);
395 CInterfaceElement
*pIE
= dynamic_cast<CInterfaceElement
*>(pRPT
);
396 // ** try to get another UI (child or parent)
397 CInterfaceElement
*uiRelative
= getUIRelative(pIE
, propName
);
400 // Exception!!! not allowed
401 throw ELuaIHMException("You cannot write into the UI '%s' of '%s'", propName
, pIE
->getId().c_str());
405 throw ELuaIHMException("Property '%s' not found in '%s' of type %s", propName
, pIE
? pIE
->getId().c_str() : "<reflectable element>", typeid(*pRPT
).name());
407 // Fail to find any Attributes or elements
411 // ***************************************************************************
412 int CLuaIHM::luaUIEq(CLuaState
&ls
)
414 //H_AUTO(Lua_CLuaIHM_luaUIEq)
415 nlassert(ls
.getTop() == 2);
417 // get the userdata and key
418 CReflectableLuaRef
*lhs
= (CReflectableLuaRef
*) ls
.toUserData(1);
419 CReflectableLuaRef
*rhs
= (CReflectableLuaRef
*) ls
.toUserData(2);
422 ls
.push(lhs
->Ptr
== rhs
->Ptr
);
427 // ***************************************************************************
428 int CLuaIHM::luaUIDtor(CLuaState
&ls
)
430 //H_AUTO(Lua_CLuaIHM_luaUIDtor)
431 nlassert(ls
.getTop()==1);
433 CReflectableLuaRef
*pRefElm
= (CReflectableLuaRef
*) ls
.toUserData(1);
437 pRefElm
->~CReflectableLuaRef();
442 // ***************************************************************************
443 int CLuaIHM::luaUINext(CLuaState
&ls
)
445 //H_AUTO(Lua_CLuaIHM_luaUINext)
446 // Code below allow enumeration of properties of a reflectable object
447 // From lua standpoint, the object is seen as a table with (key, value) pairs
448 // If object is a CInterfaceGroup, iteration is also done on sons (groups, controls & view).
450 if (ls
.getTop() != 2)
452 CLuaIHM::fails(ls
, "__next metamethod require 2 arguments (table & key)");
454 CLuaIHM::check(ls
, CLuaIHM::isReflectableOnStack(ls
, 1), "__next : require ui element as first arg");
455 CReflectableRefPtrTarget
*reflectedObject
= CLuaIHM::getReflectableOnStack(ls
, 1);
456 // To traverse all properties / field of the object, we must be able to determine the next key from a previous key
457 // (keys are ordered)
458 // We use the 'TValueType' enum to know which kind of property we are traversing, and an index in this group of properties
459 // The key which uniquely identify an element / property in the reflectable object
464 VTGroup
= 0, // children groups (If the object is a CInterfaceGroup)
465 VTView
, // children views (If the object is a CInterfaceView)
466 VTCtrl
, // children controls (If the object is a CInterfaceCtrl)
467 VTProp
// List of exported proeprties (For all relfectable objects)
469 TValueType ValueType
;
471 const CClassInfo
*ClassInfo
; // if ValueType is "VTProp" -> give the class for which property are currently enumerated
473 static int tostring(CLuaState
&ls
) // '__print' metamathod
475 CLuaIHM::checkArgCount(ls
, "reflected object metatable:__print", 1);
478 switch(key
.ValueType
)
480 case VTGroup
: ls
.push(toString("_Group %d", key
.Index
)); break;
481 case VTView
: ls
.push(toString("_View %d", key
.Index
)); break;
482 case VTCtrl
: ls
.push(toString("_Ctrl %d", key
.Index
)); break;
483 case VTProp
: ls
.push(key
.ClassInfo
->Properties
[key
.Index
].Name
); break;
487 // push the key on the lua stack
488 void push(CLuaState
&ls
)
490 void *ud
= ls
.newUserData(sizeof(*this));
491 *(CKey
*) ud
= *this;
492 getMetaTable(ls
).push();
495 // pop the key from the lua stack
496 void pop(CLuaState
&ls
)
498 CLuaStackChecker
lsc(&ls
, -1);
499 if (!ls
.isUserData(-1))
501 CLuaIHM::fails(ls
, "Can't pop object, not a user data");
503 // check that metatable is good (it is share between all keys)
505 getMetaTable(ls
).push();
506 if (!ls
.rawEqual(-1, -2))
508 CLuaIHM::fails(ls
, "Bad metatable for reflectable object key");
512 *this = *(CKey
*) ls
.toUserData(-1);
515 // get the metatable for a CKey
516 CLuaObject
&getMetaTable(CLuaState
&ls
)
518 static CLuaObject metatable
;
519 if (!metatable
.isValid())
522 CLuaStackChecker
lsc(&ls
);
524 ls
.push("__tostring");
525 ls
.push(CKey::tostring
);
532 // Pop the current key to continue enumeration
536 // no key -> start of table
537 key
.ValueType
= CKey::VTGroup
;
545 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(reflectedObject
);
546 bool enumerate
= true;
549 switch(key
.ValueType
)
552 if (!group
|| (key
.Index
+ 1) == (sint
) group
->getGroups().size())
555 key
.ValueType
= CKey::VTView
; // continue enumeration with views
561 pushUIOnStack(ls
, group
->getGroups()[key
.Index
]);
566 if (!group
|| (key
.Index
+ 1) == (sint
) group
->getViews().size())
569 key
.ValueType
= CKey::VTCtrl
; // continue enumeration with controls
575 pushUIOnStack(ls
, group
->getViews()[key
.Index
]);
580 if (!group
|| (key
.Index
+ 1) == (sint
) group
->getControls().size())
583 key
.ValueType
= CKey::VTProp
; // continue enumeration with properties
584 key
.ClassInfo
= reflectedObject
->getClassInfo();
590 pushUIOnStack(ls
, group
->getControls()[key
.Index
]);
600 if ((sint
) key
.ClassInfo
->Properties
.size() == (key
.Index
+ 1))
602 key
.ClassInfo
= key
.ClassInfo
->ParentClass
; // continue enumeration in parent class
609 CLuaIHM::luaValueFromReflectedProperty(ls
, *reflectedObject
, key
.ClassInfo
->Properties
[key
.Index
]);
622 // ***************************************************************************
623 void CLuaIHM::pushUIOnStack(CLuaState
&ls
, CInterfaceElement
*pIE
)
625 //H_AUTO(Lua_CLuaIHM_pushUIOnStack)
626 CLuaIHM::pushReflectableOnStack(ls
, pIE
);
629 // ***************************************************************************
630 bool CLuaIHM::isUIOnStack(CLuaState
&ls
, sint index
)
632 //H_AUTO(Lua_CLuaIHM_isUIOnStack)
633 return getUIOnStack(ls
, index
) != NULL
;
636 // ***************************************************************************
637 CInterfaceElement
*CLuaIHM::getUIOnStack(CLuaState
&ls
, sint index
)
639 //H_AUTO(Lua_CLuaIHM_getUIOnStack)
640 return dynamic_cast<CInterfaceElement
*>(CLuaIHM::getReflectableOnStack(ls
, index
));
643 // ***************************************************************************
644 void CLuaIHM::checkArgTypeUIElement(CLuaState
&ls
, const char *funcName
, uint index
)
646 //H_AUTO(Lua_CLuaIHM_checkArgTypeUIElement)
648 if (ls
.getTop() < (int) index
)
650 CLuaIHM::fails(ls
, "%s : argument %d of expected type ui element was not defined", funcName
, index
);
652 if (!isUIOnStack(ls
, index
))
654 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
));
659 // ***************************************************************************
660 CInterfaceElement
*CLuaIHM::getUIRelative(CInterfaceElement
*pIE
, const std::string
&propName
)
662 //H_AUTO(Lua_CLuaIHM_getUIRelative)
663 if (pIE
== NULL
) return NULL
;
664 // If the prop is "parent", then return the parent of the ui
665 if(propName
=="parent")
667 return pIE
->getParent();
669 // else try to get a child (if group/exist)
672 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pIE
);
675 return group
->getElement(group
->getId()+":"+propName
);
683 // ***************************************************************************
684 void CLuaIHM::registerBasics(CLuaState
&ls
)
686 //H_AUTO(Lua_CLuaIHM_registerBasics)
687 using namespace luabind
;
688 lua_State
*L
= ls
.getStatePointer();
693 class_
<NLMISC::CRGBA
>("CRGBA")
694 .def(constructor
<>())
695 .def(constructor
<const NLMISC::CRGBA
&>())
696 .def(constructor
<uint8
, uint8
, uint8
>())
697 .def(constructor
<uint8
, uint8
, uint8
, uint8
>())
698 .def_readwrite("R", &NLMISC::CRGBA::R
)
699 .def_readwrite("G", &NLMISC::CRGBA::G
)
700 .def_readwrite("B", &NLMISC::CRGBA::B
)
701 .def_readwrite("A", &NLMISC::CRGBA::A
)
704 #ifdef RYZOM_LUA_UCSTRING
708 class_
<ucstring
>("ucstring")
709 .def(constructor
<>())
710 .def(constructor
<const ucstring
&>())
711 .def(constructor
<const std::string
&>())
712 .def(const_self
+ other
<const std::string
>())
713 .def(other
<const std::string
>() + const_self
)
714 // NB nico : luabind crash not solved here -> use concatUCString as a replacement
715 // .def(const_self + other<const ucstring &>())
716 .def(const_self
< other
<const ucstring
&>())
717 .def(const_self
== other
<const ucstring
&>())
718 .def("toUtf8", &ucstring::toUtf8
)
719 .def("fromUtf8", &ucstring::fromUtf8
)
720 .def("substr", &ucstring::luabind_substr
)
721 .def(luabind::tostring(const_self
)) // __string metamethod
722 .def("toString", (std::string(ucstring::*)()const)&ucstring::toString
)
723 //.def(self + other<ucstring>())
730 class_
<NLMISC::CVector2f
>("CVector2f")
731 .def(constructor
<float ,float>())
732 .def_readwrite("x", &NLMISC::CVector2f::x
)
733 .def_readwrite("y", &NLMISC::CVector2f::y
)
739 // ***************************************************************************
740 int CLuaIHM::luaMethodCall(lua_State
*ls
)
742 //H_AUTO(Lua_CLuaIHM_luaMethodCall)
744 const CReflectedProperty
*prop
= (const CReflectedProperty
*) lua_touserdata(ls
, lua_upvalueindex(1));
745 CLuaState
*state
= (CLuaState
*) lua_touserdata(ls
, lua_upvalueindex(2));
747 nlassert(prop
->Type
== CReflectedProperty::LuaMethod
);
751 state
->push(NLMISC::toString("Error while calling lua method %s:%s : no 'self' reference provided, did you you function call '.' instead of method call ':' ?",
752 prop
->ParentClass
->ClassName
.c_str(), prop
->Name
.c_str())
756 // because this is a method, first parameter is the 'this'
757 CReflectableRefPtrTarget
*pRPT
= getReflectableOnStack(*state
, 1);
760 state
->push(NLMISC::toString("Error while calling lua method %s:%s : 'self' pointer is nil or of bad type, can't make the call.",
761 prop
->ParentClass
->ClassName
.c_str(), prop
->Name
.c_str())
766 state
->remove(1); // remove 'self' reference from parameters stack
771 sint initialStackSize
= state
->getTop();
774 // call the actual method
775 numResults
= (pRPT
->*(prop
->GetMethod
.GetLuaMethod
))(*state
);
777 catch (const std::exception
& e
)
779 // restore stack to its initial size
780 state
->setTop(initialStackSize
);
781 lua_pushstring(ls
, e
.what());
782 // TODO : see if this is safe to call lua error there" ... (it does a long jump)
791 // ***************************************************************************
792 int CLuaIHM::setOnDraw(CLuaState
&ls
)
794 //H_AUTO(Lua_CLuaIHM_setOnDraw)
795 CLuaStackChecker
lsc(&ls
, 0);
797 // params: CInterfaceGroup*, "script".
799 CLuaIHM::checkArgCount(ls
, "setOnDraw", 2);
800 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "setOnDraw() requires a UI object in param 1");
801 CLuaIHM::check(ls
, ls
.isString(2), "setOnDraw() requires a string in param 2");
804 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
806 ls
.toString(2, script
);
810 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pIE
);
812 throw ELuaIHMException("setOnDraw(): '%s' is not a group", pIE
->getId().c_str());
813 // Set the script to be executed at each draw
814 group
->setLuaScriptOnDraw(script
);
819 // ***************************************************************************
820 int CLuaIHM::getOnDraw(CLuaState
&ls
)
822 //H_AUTO(Lua_CLuaIHM_getOnDraw
823 CLuaStackChecker
lsc(&ls
, 1);
825 // params: CInterfaceElement*.
826 // return: "script" (nil if empty)
827 CLuaIHM::checkArgCount(ls
, "getOnDraw", 1);
828 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "getOnDraw() requires a UI object in param 1");
830 // retrieve arguments
831 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
835 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pIE
);
838 if (!group
->getLuaScriptOnDraw().empty()) {
839 ls
.push(group
->getLuaScriptOnDraw());
848 // ***************************************************************************
849 int CLuaIHM::addOnDbChange(CLuaState
&ls
)
851 //H_AUTO(Lua_CLuaIHM_addOnDbChange)
852 CLuaStackChecker
lsc(&ls
, 0);
854 // params: CInterfaceGroup*, "dblist", "script".
856 CLuaIHM::checkArgCount(ls
, "addOnDbChange", 3);
857 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "addOnDbChange() requires a UI object in param 1");
858 CLuaIHM::check(ls
, ls
.isString(2), "addOnDbChange() requires a string in param 2");
859 CLuaIHM::check(ls
, ls
.isString(3), "addOnDbChange() requires a string in param 3");
862 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
863 std::string dbList
, script
;
864 ls
.toString(2, dbList
);
865 ls
.toString(3, script
);
869 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pIE
);
871 throw ELuaIHMException("addOnDbChange(): '%s' is not a group", pIE
->getId().c_str());
872 // Set the script to be executed when the given DB change
873 group
->addLuaScriptOnDBChange(dbList
, script
);
879 // ***************************************************************************
880 int CLuaIHM::removeOnDbChange(CLuaState
&ls
)
882 //H_AUTO(Lua_CLuaIHM_removeOnDbChange)
883 CLuaStackChecker
lsc(&ls
, 0);
885 // params: CInterfaceGroup*, "dbList"
887 CLuaIHM::checkArgCount(ls
, "removeOnDbChange", 2);
888 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "removeOnDbChange() requires a UI object in param 1");
889 CLuaIHM::check(ls
, ls
.isString(2), "removeOnDbChange() requires a string in param 2");
892 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
894 ls
.toString(2, dbList
);
898 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(pIE
);
900 throw ELuaIHMException("removeOnDbChange(): '%s' is not a group", pIE
->getId().c_str());
901 // Remove the script to be executed when the given DB change
902 group
->removeLuaScriptOnDBChange(dbList
);
909 // ***************************************************************************
910 int CLuaIHM::setCaptureKeyboard(CLuaState
&ls
)
912 //H_AUTO(Lua_CLuaIHM_setCaptureKeyboard)
913 const char *funcName
= "setCaptureKeyboard";
914 CLuaIHM::checkArgCount(ls
, funcName
, 1);
915 CLuaIHM::checkArgTypeUIElement(ls
, funcName
, 1);
916 CCtrlBase
*ctrl
= dynamic_cast<CCtrlBase
*>( CLuaIHM::getUIOnStack(ls
, 1));
919 CLuaIHM::fails(ls
, "%s waits a ui control as arg 1", funcName
);
921 CWidgetManager::getInstance()->setCaptureKeyboard(ctrl
);
925 // ***************************************************************************
926 int CLuaIHM::resetCaptureKeyboard(CLuaState
&ls
)
928 //H_AUTO(Lua_CLuaIHM_resetCaptureKeyboard)
929 const char *funcName
= "resetCaptureKeyboard";
930 CLuaIHM::checkArgCount(ls
, funcName
, 0);
931 CWidgetManager::getInstance()->resetCaptureKeyboard();
935 // ***************************************************************************
936 int CLuaIHM::getUIId(CLuaState
&ls
)
938 //H_AUTO(Lua_CLuaIHM_getUIId)
939 CLuaStackChecker
lsc(&ls
, 1);
941 // params: CInterfaceElement*
942 // return: "ui:interface:...". (empty if error)
943 CLuaIHM::checkArgCount(ls
, "getUIId", 1);
944 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "getUIId() requires a UI object in param 1");
947 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
951 ls
.push(pIE
->getId());
960 // ***************************************************************************
961 int CLuaIHM::runAH(CLuaState
&ls
)
963 //H_AUTO(Lua_CLuaIHM_runAH)
964 CLuaStackChecker
lsc(&ls
, 0);
966 // params: CInterfaceElement *, "ah", "params".
968 CLuaIHM::checkArgCount(ls
, "runAH", 3);
969 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1) || ls
.isNil(1), "runAH() requires a UI object in param 1 (or Nil)");
970 CLuaIHM::check(ls
, ls
.isString(2), "runAH() requires a string in param 2");
971 CLuaIHM::check(ls
, ls
.isString(3), "runAH() requires a string in param 3");
974 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
975 std::string ah
, params
;
977 ls
.toString(3, params
);
980 // The element must be ctrl (or NULL)
981 CCtrlBase
*ctrl
= NULL
;
984 ctrl
= dynamic_cast<CCtrlBase
*>(pIE
);
986 throw ELuaIHMException("runAH(): '%s' is not a ctrl", pIE
->getId().c_str());
988 CAHManager::getInstance()->runActionHandler(ah
, ctrl
, params
);
993 // ***************************************************************************
994 int CLuaIHM::getWindowSize(CLuaState
&ls
)
996 //H_AUTO(Lua_CLuaIHM_getWindowSize)
997 CLuaIHM::checkArgCount(ls
, "getWindowSize", 0);
999 CViewRenderer::getInstance()->getScreenSize(w
, h
);
1005 // ***************************************************************************
1006 int CLuaIHM::setTopWindow(CLuaState
&ls
)
1008 //H_AUTO(Lua_CLuaIHM_setTopWindow)
1009 const char *funcName
= "setTopWindow";
1010 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1011 CInterfaceGroup
*wnd
= dynamic_cast<CInterfaceGroup
*>( CLuaIHM::getUIOnStack(ls
, 1));
1014 CLuaIHM::fails(ls
, "%s : interface group expected as arg 1", funcName
);
1016 CWidgetManager::getInstance()->setTopWindow(wnd
);
1020 int CLuaIHM::getTextureSize(CLuaState
&ls
)
1022 //H_AUTO(Lua_CLuaIHM_getTextureSize)
1023 const char *funcName
= "getTextureSize";
1024 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1025 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TSTRING
);
1026 std::string textureName
= ls
.toString(1);
1029 CIFile
fs(CPath::lookup(textureName
).c_str());
1032 ls
.push(bitmap
.getWidth());
1033 ls
.push(bitmap
.getHeight());
1040 // ***************************************************************************
1041 int CLuaIHM::disableModalWindow(CLuaState
&ls
)
1043 //H_AUTO(Lua_CLuaIHM_disableModalWindow)
1044 CLuaIHM::checkArgCount(ls
, "disableModalWindow", 0);
1045 CWidgetManager::getInstance()->disableModalWindow();
1049 // ***************************************************************************
1050 int CLuaIHM::deleteUI(CLuaState
&ls
)
1052 //H_AUTO(Lua_CLuaIHM_deleteUI)
1053 CLuaStackChecker
lsc(&ls
, 0);
1055 // params: CInterfaceElement *
1057 CLuaIHM::checkArgCount(ls
, "deleteUI", 1);
1058 CLuaIHM::check(ls
, CLuaIHM::isUIOnStack(ls
, 1), "deleteUI() requires a UI object in param 1");
1061 CInterfaceElement
*pIE
= CLuaIHM::getUIOnStack(ls
, 1);
1066 CInterfaceGroup
*parent
= pIE
->getParent();
1069 // correctly remove from parent
1070 parent
->delElement(pIE
);
1081 // ***************************************************************************
1082 int CLuaIHM::deleteReflectable(CLuaState
&ls
)
1084 //H_AUTO(Lua_CLuaIHM_deleteReflectable)
1085 CLuaStackChecker
lsc(&ls
, 0);
1087 // params: CInterfaceElement *
1089 CLuaIHM::checkArgCount(ls
, "deleteReflectable", 1);
1090 CLuaIHM::check(ls
, CLuaIHM::isReflectableOnStack(ls
, 1), "deleteReflectable() requires a reflectable C++ object in param 1");
1093 CReflectableRefPtrTarget
*pRPT
= CLuaIHM::getReflectableOnStack(ls
, 1);
1098 CInterfaceElement
*pIE
= dynamic_cast<CInterfaceElement
*>(pRPT
);
1103 CInterfaceGroup
*parent
= pIE
->getParent();
1106 // correctly remove from parent
1107 parent
->delElement(pIE
);
1118 int CLuaIHM::getCurrentWindowUnder(CLuaState
&ls
)
1120 //H_AUTO(Lua_CLuaIHM_getCurrentWindowUnder)
1121 CLuaStackChecker
lsc(&ls
, 1);
1122 CInterfaceElement
*pIE
= CWidgetManager::getInstance()->getCurrentWindowUnder();
1126 nlerror("getCurrentWindowUnder(): No UICaller found. return Nil");
1130 CLuaIHM::pushUIOnStack(ls
, pIE
);
1135 // ***************************************************************************
1136 bool CLuaIHM::fileExists(const std::string
&fileName
)
1138 //H_AUTO(Lua_CLuaIHM_fileExists)
1139 return CPath::exists(fileName
);
1142 // ***************************************************************************
1143 int CLuaIHM::runExprAndPushResult(CLuaState
&ls
, const std::string
&expr
)
1145 //H_AUTO(Lua_CLuaIHM_runExprAndPushResult)
1146 // Execute expression
1147 CInterfaceExprValue value
;
1148 if (CInterfaceExpr::eval(expr
, value
, NULL
))
1150 switch(value
.getType())
1152 case CInterfaceExprValue::Boolean
:
1153 ls
.push(value
.getBool());
1155 case CInterfaceExprValue::Integer
:
1156 ls
.push(value
.getInteger());
1158 case CInterfaceExprValue::Double
:
1159 ls
.push(value
.getDouble());
1161 case CInterfaceExprValue::String
:
1162 ls
.push(value
.getString());
1164 case CInterfaceExprValue::RGBA
:
1166 CRGBA color
= value
.getRGBA();
1167 #if defined(LUABIND_STACK_HPP_INCLUDED)
1168 luabind::push(ls
.getStatePointer(), color
);
1169 #elif (LUABIND_VERSION > 600)
1170 luabind::detail::push(ls
.getStatePointer(), color
);
1172 luabind::object
obj(ls
.getStatePointer(), color
);
1178 case CInterfaceExprValue::UserType
: // Yoyo: don't care UserType...
1190 // ***************************************************************************
1191 int CLuaIHM::runExpr(CLuaState
&ls
)
1193 //H_AUTO(Lua_CLuaIHM_runExpr)
1194 CLuaStackChecker
lsc(&ls
, 1);
1197 // return: any of: nil, bool, string, number, RGBA, UCString
1198 CLuaIHM::checkArgCount(ls
, "runExpr", 1);
1199 CLuaIHM::check(ls
, ls
.isString(1), "runExpr() requires a string in param 1");
1203 ls
.toString(1, expr
);
1205 // run expression and push result
1206 return runExprAndPushResult(ls
, expr
);
1209 // ***************************************************************************
1210 int CLuaIHM::runFct(CLuaState
&ls
)
1212 //H_AUTO(Lua_CLuaIHM_runFct)
1213 CLuaStackChecker
lsc(&ls
, 1);
1215 // params: "expr", param1, param2...
1216 // return: any of: nil, bool, string, number, RGBA, UCString
1217 CLuaIHM::checkArgMin(ls
, "runFct", 1);
1218 CLuaIHM::check(ls
, ls
.isString(1), "runExpr() requires a string in param 1");
1222 ls
.toString(1, expr
);
1226 uint top
= ls
.getTop();
1227 for(uint i
=2;i
<=top
;i
++)
1232 // If it is a number
1233 if(ls
.type(i
)==LUA_TNUMBER
)
1235 std::string paramValue
;
1236 ls
.toString(i
, paramValue
); // nb: transformed to a string in the stack
1239 // else suppose a string
1242 // must enclose with "'"
1243 std::string paramValue
;
1244 ls
.toString(i
, paramValue
);
1245 expr
+= std::string("'") + paramValue
+ std::string("'") ;
1253 // run expression and push result
1254 return runExprAndPushResult(ls
, expr
);
1257 // ***************************************************************************
1258 int CLuaIHM::runCommand(CLuaState
&ls
)
1260 //H_AUTO(Lua_CLuaIHM_runCommand)
1261 CLuaStackChecker
lsc(&ls
, 1);
1264 nlwarning("'runCommand' : Command name expected");
1268 const char *commandName
= ls
.toString(1);
1271 nlwarning("'runCommand' : Bad command name");
1275 if (!NLMISC::ICommand::LocalCommands
|| !NLMISC::ICommand::LocalCommands
->count(ls
.toString(1)))
1277 nlwarning("'runCommand' : Command %s not found", ls
.toString(1));
1281 std::string rawCommandString
= ls
.toString(1);
1282 NLMISC::ICommand
*command
= (*NLMISC::ICommand::LocalCommands
)[ls
.toString(1)];
1284 std::vector
<std::string
> args(ls
.getTop() - 1);
1285 for(uint k
= 2; k
<= (uint
) ls
.getTop(); ++k
)
1289 args
[k
- 2] = ls
.toString(k
);
1290 rawCommandString
+= " " + std::string(ls
.toString(k
));
1294 ls
.push(command
->execute(rawCommandString
, args
, NLMISC::ErrorLog(), false, true));
1298 #ifdef RYZOM_LUA_UCSTRING
1299 // ***************************************************************************
1300 int CLuaIHM::isUCString(CLuaState
&ls
)
1302 //H_AUTO(Lua_CLuaIHM_isUCString)
1303 const char *funcName
= "isUCString";
1304 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1305 ls
.push(CLuaIHM::isUCStringOnStack(ls
, 1));
1309 // ***************************************************************************
1310 int CLuaIHM::concatUCString(CLuaState
&ls
)
1312 //H_AUTO(Lua_CLuaIHM_concatUCString)
1313 const char *funcName
= "concatUCString";
1315 for (uint k
= 1; k
<= (uint
) ls
.getTop(); ++k
)
1317 //nlwarning("arg %d = %s", k, ls.getTypename(ls.type(k)));
1321 part
.fromUtf8(ls
.toString(k
));
1325 CLuaIHM::checkArgTypeUCString(ls
, funcName
, k
);
1326 nlverify(CLuaIHM::getUCStringOnStack(ls
, k
, part
));
1330 CLuaIHM::push(ls
, result
);
1335 // ***************************************************************************
1336 int CLuaIHM::concatString(CLuaState
&ls
)
1338 //H_AUTO(Lua_CLuaIHM_concatUCString)
1339 const char *funcName
= "concatString";
1341 uint stackSize
= ls
.getTop();
1342 for (uint k
= 1; k
<= stackSize
; ++k
)
1344 CLuaIHM::checkArgType(ls
, funcName
, k
, LUA_TSTRING
);
1345 result
+= ls
.toString(k
);
1351 // ***************************************************************************
1352 int CLuaIHM::tableToString(CLuaState
&ls
)
1354 const char *funcName
= "tableToString";
1355 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1356 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TTABLE
);
1363 length
+= (uint
)ls
.strlen(-1);
1367 result
.resize(length
);
1368 char *dest
= &result
[0];
1373 uint length
= (uint
)ls
.strlen(-1);
1376 memcpy(dest
, ls
.toString(-1), length
);
1386 int CLuaIHM::getPathContent(CLuaState
&ls
)
1388 //H_AUTO(Lua_CLuaIHM_getPathContent)
1389 const char *funcName
= "getPathContent";
1390 CLuaIHM::checkArgCount(ls
, funcName
, 1);
1391 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TSTRING
);
1392 std::vector
<std::string
> files
;
1393 NLMISC::CPath::getPathContent(ls
.toString(1), false, false, true, files
);
1395 for(uint k
= 0; k
< files
.size(); ++k
)
1407 // ***************************************************************************
1408 void CLuaIHM::luaValueFromReflectedProperty(CLuaState
&ls
, CReflectable
&reflectedObject
, const CReflectedProperty
&property
)
1410 //H_AUTO(Lua_CLuaIHM_luaValueFromReflectedProperty)
1411 switch(property
.Type
)
1413 case CReflectedProperty::Boolean
:
1414 ls
.push( (reflectedObject
.*(property
.GetMethod
.GetBool
))() );
1416 case CReflectedProperty::SInt32
:
1417 ls
.push( (reflectedObject
.*(property
.GetMethod
.GetSInt32
))() );
1419 case CReflectedProperty::Float
:
1420 ls
.push( (reflectedObject
.*(property
.GetMethod
.GetFloat
))() );
1422 case CReflectedProperty::String
:
1423 ls
.push( (reflectedObject
.*(property
.GetMethod
.GetString
))() );
1425 #ifdef RYZOM_LUA_UCSTRING
1426 case CReflectedProperty::UCString
:
1428 ucstring str
= (reflectedObject
.*(property
.GetMethod
.GetUCString
))();
1429 #if defined(LUABIND_STACK_HPP_INCLUDED)
1430 luabind::push(ls
.getStatePointer(), str
);
1431 #elif (LUABIND_VERSION > 600)
1432 luabind::detail::push(ls
.getStatePointer(), str
);
1434 luabind::object
obj(ls
.getStatePointer(), str
);
1439 case CReflectedProperty::UCStringRef
:
1441 ucstring str
= (reflectedObject
.*(property
.GetMethod
.GetUCStringRef
))();
1442 #if defined(LUABIND_STACK_HPP_INCLUDED)
1443 luabind::push(ls
.getStatePointer(), str
);
1444 #elif (LUABIND_VERSION > 600)
1445 luabind::detail::push(ls
.getStatePointer(), str
);
1447 luabind::object
obj(ls
.getStatePointer(), str
);
1453 case CReflectedProperty::StringRef
:
1454 ls
.push( (reflectedObject
.*(property
.GetMethod
.GetStringRef
))() );
1456 case CReflectedProperty::RGBA
:
1458 CRGBA color
= (reflectedObject
.*(property
.GetMethod
.GetRGBA
))();
1459 #if defined(LUABIND_STACK_HPP_INCLUDED)
1460 luabind::push(ls
.getStatePointer(), color
);
1461 #elif (LUABIND_VERSION > 600)
1462 luabind::detail::push(ls
.getStatePointer(), color
);
1464 luabind::object
obj(ls
.getStatePointer(), color
);
1469 case CReflectedProperty::LuaMethod
:
1471 // must create a closure that will forward the call to the real method
1472 if (!property
.LuaMethodRef
.isValid())
1474 ls
.pushLightUserData((void *) &property
);
1475 ls
.pushLightUserData((void *) &ls
);
1476 ls
.pushCClosure(luaMethodCall
, 2);
1477 property
.LuaMethodRef
.pop(ls
);
1479 nlassert(property
.LuaMethodRef
.getLuaState() == &ls
); // only one single lua state supported for now
1480 property
.LuaMethodRef
.push();
1489 // ***************************************************************************
1490 void CLuaIHM::luaValueToReflectedProperty(CLuaState
&ls
, int stackIndex
, CReflectable
&target
, const CReflectedProperty
&property
)
1492 //H_AUTO(Lua_property_throw)
1493 if(ls
.isNil(stackIndex
))
1494 throw ELuaIHMException("Trying to set nil to UI property '%s'", property
.Name
.c_str());
1495 switch(property
.Type
)
1497 case CReflectedProperty::Boolean
:
1499 bool val
= ls
.toBoolean(stackIndex
);
1500 (target
.*(property
.SetMethod
.SetBool
))(val
);
1503 case CReflectedProperty::SInt32
:
1505 sint32 val
= (sint32
)ls
.toInteger(stackIndex
);
1506 (target
.*(property
.SetMethod
.SetSInt32
))(val
);
1509 case CReflectedProperty::UInt32
:
1511 uint32 val
= (uint32
)ls
.toInteger(stackIndex
);
1512 (target
.*(property
.SetMethod
.SetUInt32
))(val
);
1515 case CReflectedProperty::Float
:
1517 float val
= (float)ls
.toNumber(stackIndex
);
1518 (target
.*(property
.SetMethod
.SetFloat
))(val
);
1521 case CReflectedProperty::String
:
1522 case CReflectedProperty::StringRef
:
1525 ls
.toString(stackIndex
, val
);
1526 (target
.*(property
.SetMethod
.SetString
))(val
);
1529 #ifdef RYZOM_LUA_UCSTRING
1530 case CReflectedProperty::UCString
:
1531 case CReflectedProperty::UCStringRef
:
1534 // Additionaly return of CInterfaceExpr may be std::string... test std string too
1535 if(ls
.isString() || ls
.isNumber() || ls
.isInteger())
1538 ls
.toString(stackIndex
, str
);
1541 #ifdef RYZOM_LUA_UCSTRING
1544 // else this should be a ucstring
1547 throw ELuaIHMException("You must set a string, number or ucstring to UI property '%s'", property
.Name
.c_str());
1551 (target
.*(property
.SetMethod
.SetUCString
))(val
);
1555 case CReflectedProperty::RGBA
:
1560 (target
.*(property
.SetMethod
.SetRGBA
))(color
);
1564 throw ELuaIHMException("You must set a CRGBA to UI property '%s'", property
.Name
.c_str());
1574 // ***************************************************************************
1575 void CLuaIHM::createLuaEnumTable(CLuaState
&ls
, const std::string
&str
)
1577 //H_AUTO(Lua_CLuaIHM_createLuaEnumTable)
1578 std::string path
= "", script
, p
;
1580 // Create table recursively (ex: 'game.TPVPClan' will check/create the table 'game' and 'game.TPVPClan')
1581 p
= s
.splitTo('.', true);
1588 script
= "if (" + path
+ " == nil) then " + path
+ " = {}; end";
1589 ls
.executeScript(script
);
1590 p
= s
.splitTo('.', true);
1594 #define LUABIND_ENUM(__enum__, __name__, __num__, __toStringFunc__) \
1595 createLuaEnumTable(ls, __name__); \
1596 for (uint e=0 ; e<__num__ ; e++) \
1598 std::string str = __toStringFunc__((__enum__)e); \
1599 std::string temp = __name__ + toString(".") + __toStringFunc__((__enum__)e) + " = " + toString("%u;", e); \
1600 ls.executeScript(temp); \
1603 // ***************************************************************************
1604 #define LUABIND_FUNC(__func__) luabind::def(#__func__, &__func__)
1606 void CLuaIHM::registerIHM(CLuaState
&ls
)
1608 //H_AUTO(Lua_CLuaIHM_registerIHM)
1609 CLuaStackChecker
lsc(&ls
);
1611 // *** Register a Table for ui env.
1612 ls
.push(IHM_LUA_ENVTABLE
); // "__ui_envtable"
1613 ls
.newTable(); // "__ui_envtable" {}
1614 ls
.setTable(LUA_REGISTRYINDEX
);
1617 // *** Register the MetaTable for UI userdata
1618 ls
.push(IHM_LUA_METATABLE
); // "__ui_metatable"
1619 ls
.newTable(); // "__ui_metatable" {}
1620 // set the '__index' method
1622 ls
.push(luaUIIndex
);
1623 nlassert(ls
.isCFunction());
1624 ls
.setTable(-3); // "__ui_metatable" {"__index"= CFunc_luaUIIndex}
1625 // set the '__newindex' method
1626 ls
.push("__newindex");
1627 ls
.push(luaUINewIndex
);
1628 nlassert(ls
.isCFunction());
1630 // set the '__newindex' method
1633 nlassert(ls
.isCFunction());
1635 // set the '__eq' method
1638 nlassert(ls
.isCFunction());
1640 // set the custom '__next' method
1643 nlassert(ls
.isCFunction());
1646 ls
.setTable(LUA_REGISTRYINDEX
);
1649 // *** Register Functions
1650 ls
.registerFunc("setOnDraw", setOnDraw
);
1651 ls
.registerFunc("getOnDraw", getOnDraw
);
1652 ls
.registerFunc("setCaptureKeyboard", setCaptureKeyboard
);
1653 ls
.registerFunc("resetCaptureKeyboard", resetCaptureKeyboard
);
1654 ls
.registerFunc("setTopWindow", setTopWindow
);
1655 ls
.registerFunc("addOnDbChange", addOnDbChange
);
1656 ls
.registerFunc("removeOnDbChange", removeOnDbChange
);
1657 ls
.registerFunc("getUIId", getUIId
);
1658 ls
.registerFunc("runAH", runAH
);
1659 ls
.registerFunc("deleteUI", deleteUI
);
1660 ls
.registerFunc("deleteReflectable", deleteReflectable
);
1661 ls
.registerFunc("getWindowSize", getWindowSize
);
1662 ls
.registerFunc("getTextureSize", getTextureSize
);
1663 ls
.registerFunc("disableModalWindow", disableModalWindow
);
1664 #ifdef RYZOM_LUA_UCSTRING
1665 ls
.registerFunc("isUCString", isUCString
);
1666 ls
.registerFunc("concatUCString", concatUCString
);
1668 ls
.registerFunc("concatString", concatString
);
1669 ls
.registerFunc("tableToString", tableToString
);
1670 ls
.registerFunc("getCurrentWindowUnder", getCurrentWindowUnder
);
1671 ls
.registerFunc("runExpr", runExpr
);
1672 ls
.registerFunc("runFct", runFct
);
1673 ls
.registerFunc("runCommand", runCommand
);
1674 ls
.registerFunc("getPathContent", getPathContent
);
1676 // Through LUABind API
1677 lua_State
*L
= ls
.getStatePointer();
1681 luabind::def("findReplaceAll", (std::string(*)(const std::string
&, const std::string
&, const std::string
&)) &findReplaceAll
),
1682 luabind::def("findReplaceAll", (ucstring(*)(const ucstring
&, const ucstring
&, const ucstring
&)) &findReplaceAll
),
1683 luabind::def("findReplaceAll", (ucstring(*)(const ucstring
&, const std::string
&, const std::string
&)) &findReplaceAll
),
1684 luabind::def("findReplaceAll", (ucstring(*)(const ucstring
&, const ucstring
&, const std::string
&)) &findReplaceAll
),
1685 luabind::def("findReplaceAll", (ucstring(*)(const ucstring
&, const std::string
&, const ucstring
&)) &findReplaceAll
),
1688 LUABIND_FUNC(openDoc
),
1689 LUABIND_FUNC(launchProgram
),
1692 luabind::def("fileLookup", CMiscFunctions::fileLookup
),
1693 luabind::def("shellExecute", CMiscFunctions::shellExecute
),
1694 LUABIND_FUNC(fileExists
)
1697 // inside i18n table
1698 luabind::module(L
, "i18n")
1700 #ifdef RYZOM_LUA_UCSTRING
1701 luabind::def("get", &CI18N::getAsUtf16
), // Compatibility
1703 luabind::def("get", &CI18N::get
),
1705 luabind::def("hasTranslation", &CI18N::hasTranslation
)
1707 // inside 'nlfile' table
1708 luabind::module(L
, "nlfile")
1710 luabind::def("getFilename", NLMISC::CFile::getFilename
),
1711 luabind::def("getExtension", NLMISC::CFile::getExtension
),
1712 luabind::def("getFilenameWithoutExtension", NLMISC::CFile::getFilenameWithoutExtension
)
1714 // inside 'nltime' table
1715 luabind::module(L
, "nltime")
1717 luabind::def("getPreciseLocalTime", getPreciseLocalTime
),
1718 luabind::def("getSecondsSince1970", NLMISC::CTime::getSecondsSince1970
),
1719 luabind::def("getLocalTime", getLocalTime
) // NB : use CLuaIHM::getLocalTime instead of NLMISC::CTime::getLocalTime, because the NLMISC
1720 // version returns a uint64, which can't be casted into lua numbers (doubles ...)
1725 // ***************************************************************************
1726 double CLuaIHM::getPreciseLocalTime()
1728 //H_AUTO(Lua_CLuaIHM_getPreciseLocalTime)
1729 // don't export these 2 function to lua directly here, because all uint64 can't be represented with lua 'numbers'
1730 return NLMISC::CTime::ticksToSecond(NLMISC::CTime::getPerformanceTime());
1733 // ***************************************************************************
1734 void CLuaIHM::registerAll(CLuaState
&ls
)
1736 //H_AUTO(Lua_CLuaIHM_registerAll)
1743 //#define CHECK_REFLECTABLE_MT
1746 // ***************************************************************************
1747 void CLuaIHM::pushReflectableOnStack(CLuaState
&ls
, class CReflectableRefPtrTarget
*pRPT
)
1749 //H_AUTO(Lua_CLuaIHM_pushReflectableOnStack)
1751 CLuaStackChecker
lsc(&ls
, 1);
1760 /** if there's already a ref ptr for this object in the registry, then use it,
1761 * else create a new one to avoid costly allocations
1763 ls
.pushLightUserData(pRPT
);
1764 ls
.getTable(LUA_REGISTRYINDEX
);
1770 // allocate the user data where to put the ref ptr
1771 void *ptr
= ls
.newUserData(sizeof(CReflectableLuaRef
));
1775 // disable memory leaks detection for placement new
1780 // initialize it, and copy the given element
1781 new (ptr
) CReflectableLuaRef(pRPT
);
1783 // reenable memory leaks detection for placement new
1785 #define new DEBUG_NEW
1788 // Assign to this user data the __ui_metatable
1790 ls
.push(IHM_LUA_METATABLE
); // userdata "__ui_metatable"
1792 ls
.getTable(LUA_REGISTRYINDEX
); // userdata __ui_metatable
1794 nlverify(ls
.setMetaTable(-2)); // userdata
1797 // cache in registry
1798 ls
.pushLightUserData(pRPT
);
1799 ls
.pushValue(-2); // copy for table insertion
1801 ls
.setTable(LUA_REGISTRYINDEX
);
1805 // Check that the metatable is correct
1806 #ifdef CHECK_REFLECTABLE_MT
1807 nlverify(ls
.getMetaTable(-1)); // userdata __ui_metatable
1810 ls
.push("__newindex");
1814 nlassert(ls
.isCFunction(-1));
1815 nlassert(ls
.isCFunction(-2));
1816 nlassert(ls
.isCFunction(-3));
1822 // ***************************************************************************
1823 bool CLuaIHM::isReflectableOnStack(CLuaState
&ls
, sint index
)
1825 //H_AUTO(Lua_CLuaIHM_isReflectableOnStack)
1826 CLuaStackChecker
lsc(&ls
);
1828 if(!ls
.isUserData(index
))
1830 // verify that it is a UI with its metatable
1831 if(!ls
.getMetaTable(index
)) // ??? object_metatable
1833 ls
.push(IHM_LUA_METATABLE
); // ??? object_metatable "__ui_metatable"
1834 ls
.getTable(LUA_REGISTRYINDEX
); // ??? object_metatable __ui_metatable
1836 bool ok
= ls
.rawEqual(-2, -1);
1837 // Also must not be nil (maybe nil in case of LuaIHM still not registered)
1838 ok
= ok
&& !ls
.isNil(-1);
1845 // ***************************************************************************
1846 CReflectableRefPtrTarget
*CLuaIHM::getReflectableOnStack(CLuaState
&ls
, sint index
)
1848 //H_AUTO(Lua_CLuaIHM_getReflectableOnStack)
1849 if(!isReflectableOnStack(ls
, index
))
1852 CReflectableLuaRef
*p
= (CReflectableLuaRef
*) ls
.toUserData(index
);
1858 // ***************************************************************************
1859 // ***************************************************************************
1860 // LUA IHM Functions
1861 // ***************************************************************************
1862 // ***************************************************************************
1865 // ***************************************************************************
1866 uint32
CLuaIHM::getLocalTime()
1868 //H_AUTO(Lua_CLuaIHM_getLocalTime)
1869 return (uint32
) NLMISC::CTime::getLocalTime();
1873 // ***************************************************************************
1874 std::string
CLuaIHM::findReplaceAll(const std::string
&str
, const std::string
&search
, const std::string
&replace
)
1876 //H_AUTO(Lua_CLuaIHM_findReplaceAll)
1877 std::string ret
= str
;
1878 while(strFindReplace(ret
, search
, replace
));
1882 #ifdef RYZOM_LUA_UCSTRING
1883 // ***************************************************************************
1884 ucstring
CLuaIHM::findReplaceAll(const ucstring
&str
, const ucstring
&search
, const ucstring
&replace
)
1886 //H_AUTO(Lua_CLuaIHM_findReplaceAll)
1887 return strFindReplaceAll(str
, search
, replace
);
1890 // ***************************************************************************
1891 ucstring
CLuaIHM::findReplaceAll(const ucstring
&str
, const std::string
&search
, const std::string
&replace
)
1893 //H_AUTO(Lua_CLuaIHM_findReplaceAll)
1894 return findReplaceAll(str
, ucstring::makeFromUtf8(search
), ucstring::makeFromUtf8(replace
));
1897 // ***************************************************************************
1898 ucstring
CLuaIHM::findReplaceAll(const ucstring
&str
, const std::string
&search
, const ucstring
&replace
)
1900 //H_AUTO(Lua_CLuaIHM_findReplaceAll)
1901 return findReplaceAll(str
, ucstring::makeFromUtf8(search
), replace
);
1904 // ***************************************************************************
1905 ucstring
CLuaIHM::findReplaceAll(const ucstring
&str
, const ucstring
&search
, const std::string
&replace
)
1907 //H_AUTO(Lua_CLuaIHM_findReplaceAll)
1908 return findReplaceAll(str
, search
, ucstring::makeFromUtf8(replace
));
1912 // ***************************************************************************
1913 void CLuaIHM::fails(CLuaState
&ls
, const char *format
, ...)
1915 //H_AUTO(Lua_CLuaIHM_fails)
1917 NLMISC_CONVERT_VARGS (reason
, format
, NLMISC::MaxCStringSize
);
1919 ls
.getStackAsString(stack
);
1920 // use a std::exception, to avoid Nel Exception warning
1921 throw ELuaIHMException("%s. Lua stack = \n %s", reason
.c_str(), stack
.c_str());
1925 // ***************************************************************************
1926 void CLuaIHM::checkArgCount(CLuaState
&ls
, const char* funcName
, uint nArgs
)
1928 //H_AUTO(Lua_CLuaIHM_checkArgCount)
1929 if(ls
.getTop()!=(sint
)nArgs
)
1931 fails(ls
, "%s() need exactly %d arguments (tips : check between method & function call)", funcName
, nArgs
);
1935 // ***************************************************************************
1936 void CLuaIHM::checkArgMin(CLuaState
&ls
, const char* funcName
, uint nArgs
)
1938 //H_AUTO(Lua_CLuaIHM_checkArgMin)
1939 if(ls
.getTop()<(sint
)nArgs
)
1941 fails(ls
, "%s() need at least %d arguments (tips : check between method & function call)", funcName
, nArgs
);
1945 // ***************************************************************************
1946 void CLuaIHM::checkArgMax(CLuaState
&ls
,const char* funcName
,uint nArgs
)
1948 //H_AUTO(Lua_CLuaIHM_checkArgMax)
1949 if(ls
.getTop()>(sint
)nArgs
)
1951 fails(ls
, "%s() need at most %d arguments.", funcName
, nArgs
);
1955 // ***************************************************************************
1956 void CLuaIHM::check(CLuaState
&ls
, bool ok
, const std::string
&failReason
)
1958 //H_AUTO(Lua_CLuaIHM_check)
1961 fails(ls
, failReason
.c_str());
1965 // ***************************************************************************
1966 void CLuaIHM::checkArgType(CLuaState
&ls
, const char *funcName
, uint index
, int argType
)
1968 //H_AUTO(Lua_CLuaIHM_checkArgType)
1969 nlassert(index
> 0);
1970 if (ls
.getTop() < (int) index
)
1972 fails(ls
, "%s : argument %d of expected type %s was not defined", funcName
, index
, ls
.getTypename(argType
));
1974 if (ls
.type(index
) != argType
)
1976 fails(ls
, "%s : argument %d of expected type %s has bad type : %s", funcName
, index
, ls
.getTypename(argType
), ls
.getTypename(ls
.type(index
)), ls
.type(index
));
1980 // ***************************************************************************
1981 void CLuaIHM::checkArgTypeRGBA(CLuaState
&ls
, const char *funcName
, uint index
)
1983 //H_AUTO(Lua_CLuaIHM_checkArgTypeRGBA)
1984 nlassert(index
> 0);
1985 if (ls
.getTop() < (int) index
)
1987 fails(ls
, "%s : argument %d of expected type RGBA was not defined", funcName
, index
);
1989 ls
.pushValue(index
);
1991 if (!pop(ls
, dummy
))
1993 fails(ls
, "%s : argument %d of expected type RGBA has bad type : %s", funcName
, index
, ls
.getTypename(ls
.type(index
)), ls
.type(index
));
1997 #ifdef RYZOM_LUA_UCSTRING
1998 // ***************************************************************************
1999 void CLuaIHM::checkArgTypeUCString(CLuaState
&ls
, const char *funcName
, uint index
)
2001 //H_AUTO(Lua_CLuaIHM_checkArgTypeUCString)
2002 nlassert(index
> 0);
2003 if (ls
.getTop() < (int) index
)
2005 fails(ls
, "%s : argument %d of expected type ucstring was not defined", funcName
, index
);
2007 ls
.pushValue(index
);
2009 if (!pop(ls
, dummy
))
2011 fails(ls
, "%s : argument %d of expected type ucstring has bad type : %s", funcName
, index
, ls
.getTypename(ls
.type(index
)), ls
.type(index
));
2017 // ***************************************************************************
2018 bool CLuaIHM::popString(CLuaState
&ls
, std::string
& dest
)
2020 //H_AUTO(Lua_CLuaIHM_popString)
2023 #if LUABIND_VERSION > 600
2024 luabind::object
obj(luabind::from_stack(ls
.getStatePointer(), -1));
2027 luabind::object
obj(ls
.getStatePointer());
2030 dest
= luabind::object_cast
<std::string
>(obj
);
2032 catch(const luabind::cast_failed
&)
2039 // ***************************************************************************
2040 bool CLuaIHM::popSINT32(CLuaState
&ls
, sint32
& dest
)
2042 //H_AUTO(Lua_CLuaIHM_popSINT32)
2045 #if LUABIND_VERSION > 600
2046 luabind::object
obj(luabind::from_stack(ls
.getStatePointer(), -1));
2049 luabind::object
obj(ls
.getStatePointer());
2052 dest
= luabind::object_cast
<sint32
>(obj
);
2054 catch(const luabind::cast_failed
&)
2061 // ***************************************************************************
2062 void CLuaIHM::getPoly2DOnStack(CLuaState
&ls
, sint index
, NLMISC::CPolygon2D
&dest
)
2064 //H_AUTO(Lua_CLuaIHM_getPoly2DOnStack)
2065 ls
.pushValue(index
);
2068 dest
.Vertices
.clear();
2069 ENUM_LUA_TABLE(poly
, it
)
2071 it
.nextValue().push();
2072 NLMISC::CVector2f pos
;
2075 fails(ls
, "2D polygon expects CVector2f for poly coordinates");
2077 dest
.Vertices
.push_back(pos
);