Element.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /*
  2. * This source file is part of RmlUi, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://github.com/mikke89/RmlUi
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. * Copyright (c) 2019 The RmlUi Team, and contributors
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. *
  27. */
  28. #include "precompiled.h"
  29. #include "Element.h"
  30. #include "ElementStyleProxy.h"
  31. #include "LuaEventListener.h"
  32. #include "ElementAttributesProxy.h"
  33. #include "ElementChildNodesProxy.h"
  34. #include <RmlUi/Core/Lua/Utilities.h>
  35. namespace Rml {
  36. namespace Core {
  37. namespace Lua {
  38. typedef ElementDocument Document;
  39. template<> void ExtraInit<Element>(lua_State* L, int metatable_index)
  40. {
  41. int top = lua_gettop(L);
  42. //guarantee the "Element.As" table exists
  43. lua_getfield(L,metatable_index-1,"As");
  44. if(lua_isnoneornil(L,-1)) //if it doesn't exist, create it
  45. {
  46. lua_newtable(L);
  47. lua_setfield(L,metatable_index-1,"As");
  48. }
  49. lua_pop(L,1); //pop the result of lua_getfield
  50. lua_pushcfunction(L,Elementnew);
  51. lua_setfield(L,metatable_index-1,"new");
  52. lua_settop(L,top);
  53. }
  54. int Elementnew(lua_State* L)
  55. {
  56. const char* tag = luaL_checkstring(L,1);
  57. Element* ele = new Element(tag);
  58. LuaType<Element>::push(L,ele,true);
  59. return 1;
  60. }
  61. //methods
  62. int ElementAddEventListener(lua_State* L, Element* obj)
  63. {
  64. int top = lua_gettop(L);
  65. bool capture = false;
  66. //default false if they didn't pass it in
  67. if (top > 2)
  68. capture = CHECK_BOOL(L,3);
  69. const char* event = luaL_checkstring(L,1);
  70. LuaEventListener* listener = nullptr;
  71. int type = lua_type(L,2);
  72. if(type == LUA_TFUNCTION)
  73. {
  74. listener = new LuaEventListener(L,2,obj);
  75. }
  76. else if(type == LUA_TSTRING)
  77. {
  78. const char* code = luaL_checkstring(L,2);
  79. listener = new LuaEventListener(code,obj);
  80. }
  81. else
  82. {
  83. Log::Message(Log::LT_WARNING, "Lua Context:AddEventLisener's 2nd argument can only be a Lua function or a string, you passed in a %s", lua_typename(L,type));
  84. }
  85. if(listener != nullptr)
  86. {
  87. obj->AddEventListener(event,listener,capture);
  88. }
  89. return 0;
  90. }
  91. int ElementAppendChild(lua_State* L, Element* obj)
  92. {
  93. ElementPtr* element = LuaType<ElementPtr>::check(L, 1);
  94. if (*element)
  95. obj->AppendChild(std::move(*element));
  96. else
  97. Log::Message(Log::LT_WARNING, "Could not append child to element '%s', as the child was null. Was it already moved from?", obj->GetAddress().c_str());
  98. return 0;
  99. }
  100. int ElementBlur(lua_State* /*L*/, Element* obj)
  101. {
  102. obj->Blur();
  103. return 0;
  104. }
  105. int ElementClick(lua_State* /*L*/, Element* obj)
  106. {
  107. obj->Click();
  108. return 0;
  109. }
  110. int ElementDispatchEvent(lua_State* L, Element* obj)
  111. {
  112. const char* event = luaL_checkstring(L,1);
  113. Dictionary params;
  114. lua_pushnil(L); //becauase lua_next pops a key from the stack first, we don't want to pop the table
  115. while(lua_next(L,2) != 0)
  116. {
  117. //[-1] is value, [-2] is key
  118. int type = lua_type(L,-1);
  119. const char* key = luaL_checkstring(L,-2); //key HAS to be a string, or things will go bad
  120. switch(type)
  121. {
  122. case LUA_TNUMBER:
  123. params[key] = (float)lua_tonumber(L,-1);
  124. break;
  125. case LUA_TBOOLEAN:
  126. params[key] = CHECK_BOOL(L,-1);
  127. break;
  128. case LUA_TSTRING:
  129. params[key] = luaL_checkstring(L,-1);
  130. break;
  131. case LUA_TUSERDATA:
  132. case LUA_TLIGHTUSERDATA:
  133. params[key] = lua_touserdata(L,-1);
  134. break;
  135. default:
  136. break;
  137. }
  138. }
  139. obj->DispatchEvent(event, params);
  140. return 0;
  141. }
  142. int ElementFocus(lua_State* /*L*/, Element* obj)
  143. {
  144. obj->Focus();
  145. return 0;
  146. }
  147. int ElementGetAttribute(lua_State* L, Element* obj)
  148. {
  149. const char* name = luaL_checkstring(L,1);
  150. Variant* var = obj->GetAttribute(name);
  151. PushVariant(L,var);
  152. return 1;
  153. }
  154. int ElementGetElementById(lua_State* L, Element* obj)
  155. {
  156. const char* id = luaL_checkstring(L,1);
  157. Element* ele = obj->GetElementById(id);
  158. LuaType<Element>::push(L,ele,false);
  159. return 1;
  160. }
  161. int ElementGetElementsByTagName(lua_State* L, Element* obj)
  162. {
  163. const char* tag = luaL_checkstring(L,1);
  164. ElementList list;
  165. obj->GetElementsByTagName(list,tag);
  166. lua_newtable(L);
  167. for(unsigned int i = 0; i < list.size(); i++)
  168. {
  169. lua_pushinteger(L,i);
  170. LuaType<Element>::push(L,list[i],false);
  171. lua_settable(L,-3); //-3 is the table
  172. }
  173. return 1;
  174. }
  175. int ElementHasAttribute(lua_State* L, Element* obj)
  176. {
  177. const char* name = luaL_checkstring(L,1);
  178. lua_pushboolean(L,obj->HasAttribute(name));
  179. return 1;
  180. }
  181. int ElementHasChildNodes(lua_State* L, Element* obj)
  182. {
  183. lua_pushboolean(L,obj->HasChildNodes());
  184. return 1;
  185. }
  186. int ElementInsertBefore(lua_State* L, Element* obj)
  187. {
  188. ElementPtr* element = LuaType<ElementPtr>::check(L,1);
  189. Element* adjacent = LuaType<Element>::check(L,2);
  190. if(*element)
  191. obj->InsertBefore(std::move(*element), adjacent);
  192. else
  193. Log::Message(Log::LT_WARNING, "Could not insert child to element '%s', as the child was null. Was it already moved from?", obj->GetAddress().c_str());
  194. return 0;
  195. }
  196. int ElementIsClassSet(lua_State* L, Element* obj)
  197. {
  198. const char* name = luaL_checkstring(L,1);
  199. lua_pushboolean(L,obj->IsClassSet(name));
  200. return 1;
  201. }
  202. int ElementRemoveAttribute(lua_State* L, Element* obj)
  203. {
  204. const char* name = luaL_checkstring(L,1);
  205. obj->RemoveAttribute(name);
  206. return 0;
  207. }
  208. int ElementRemoveChild(lua_State* L, Element* obj)
  209. {
  210. Element* element = LuaType<Element>::check(L,1);
  211. lua_pushboolean(L,static_cast<bool>(obj->RemoveChild(element)));
  212. return 1;
  213. }
  214. int ElementReplaceChild(lua_State* L, Element* obj)
  215. {
  216. ElementPtr* inserted = LuaType<ElementPtr>::check(L,1);
  217. Element* replaced = LuaType<Element>::check(L,2);
  218. if(*inserted)
  219. lua_pushboolean(L, static_cast<bool>(obj->ReplaceChild(std::move(*inserted),replaced)));
  220. else
  221. Log::Message(Log::LT_WARNING, "Could not replace child in element '%s', as the child was null. Was it already moved from?", obj->GetAddress().c_str());
  222. return 1;
  223. }
  224. int ElementScrollIntoView(lua_State* L, Element* obj)
  225. {
  226. bool align = CHECK_BOOL(L,1);
  227. obj->ScrollIntoView(align);
  228. return 0;
  229. }
  230. int ElementSetAttribute(lua_State* L, Element* obj)
  231. {
  232. const char* name = luaL_checkstring(L,1);
  233. const char* value = luaL_checkstring(L,2);
  234. obj->SetAttribute(name,String(value));
  235. return 0;
  236. }
  237. int ElementSetClass(lua_State* L, Element* obj)
  238. {
  239. const char* name = luaL_checkstring(L,1);
  240. bool value = CHECK_BOOL(L,2);
  241. obj->SetClass(name,value);
  242. return 0;
  243. }
  244. //getters
  245. int ElementGetAttrattributes(lua_State* L)
  246. {
  247. Element* ele = LuaType<Element>::check(L,1);
  248. LUACHECKOBJ(ele);
  249. ElementAttributesProxy* proxy = new ElementAttributesProxy();
  250. proxy->owner = ele;
  251. LuaType<ElementAttributesProxy>::push(L,proxy,true);
  252. return 1;
  253. }
  254. int ElementGetAttrchild_nodes(lua_State* L)
  255. {
  256. Element* ele = LuaType<Element>::check(L,1);
  257. LUACHECKOBJ(ele);
  258. ElementChildNodesProxy* ecnp = new ElementChildNodesProxy();
  259. ecnp->owner = ele;
  260. LuaType<ElementChildNodesProxy>::push(L,ecnp,true);
  261. return 1;
  262. }
  263. int ElementGetAttrclass_name(lua_State* L)
  264. {
  265. Element* ele = LuaType<Element>::check(L,1);
  266. LUACHECKOBJ(ele);
  267. Rml::Core::String classnames = ele->GetClassNames();
  268. lua_pushstring(L,classnames.c_str());
  269. return 1;
  270. }
  271. int ElementGetAttrclient_left(lua_State* L)
  272. {
  273. Element* ele = LuaType<Element>::check(L,1);
  274. LUACHECKOBJ(ele);
  275. lua_pushnumber(L,ele->GetClientLeft());
  276. return 1;
  277. }
  278. int ElementGetAttrclient_height(lua_State* L)
  279. {
  280. Element* ele = LuaType<Element>::check(L,1);
  281. LUACHECKOBJ(ele);
  282. lua_pushnumber(L,ele->GetClientHeight());
  283. return 1;
  284. }
  285. int ElementGetAttrclient_top(lua_State* L)
  286. {
  287. Element* ele = LuaType<Element>::check(L,1);
  288. LUACHECKOBJ(ele);
  289. lua_pushnumber(L,ele->GetClientTop());
  290. return 1;
  291. }
  292. int ElementGetAttrclient_width(lua_State* L)
  293. {
  294. Element* ele = LuaType<Element>::check(L,1);
  295. LUACHECKOBJ(ele);
  296. lua_pushnumber(L,ele->GetClientWidth());
  297. return 1;
  298. }
  299. int ElementGetAttrfirst_child(lua_State* L)
  300. {
  301. Element* ele = LuaType<Element>::check(L,1);
  302. LUACHECKOBJ(ele);
  303. Element* child = ele->GetFirstChild();
  304. if(child == nullptr)
  305. lua_pushnil(L);
  306. else
  307. LuaType<Element>::push(L,child,false);
  308. return 1;
  309. }
  310. int ElementGetAttrid(lua_State* L)
  311. {
  312. Element* ele = LuaType<Element>::check(L,1);
  313. LUACHECKOBJ(ele);
  314. lua_pushstring(L,ele->GetId().c_str());
  315. return 1;
  316. }
  317. int ElementGetAttrinner_rml(lua_State* L)
  318. {
  319. Element* ele = LuaType<Element>::check(L,1);
  320. LUACHECKOBJ(ele);
  321. lua_pushstring(L,ele->GetInnerRML().c_str());
  322. return 1;
  323. }
  324. int ElementGetAttrlast_child(lua_State* L)
  325. {
  326. Element* ele = LuaType<Element>::check(L,1);
  327. LUACHECKOBJ(ele);
  328. Element* child = ele->GetLastChild();
  329. if(child == nullptr)
  330. lua_pushnil(L);
  331. else
  332. LuaType<Element>::push(L,child,false);
  333. return 1;
  334. }
  335. int ElementGetAttrnext_sibling(lua_State* L)
  336. {
  337. Element* ele = LuaType<Element>::check(L,1);
  338. LUACHECKOBJ(ele);
  339. Element* sibling = ele->GetNextSibling();
  340. if(sibling == nullptr)
  341. lua_pushnil(L);
  342. else
  343. LuaType<Element>::push(L,sibling,false);
  344. return 1;
  345. }
  346. int ElementGetAttroffset_height(lua_State* L)
  347. {
  348. Element* ele = LuaType<Element>::check(L,1);
  349. LUACHECKOBJ(ele);
  350. lua_pushnumber(L,ele->GetOffsetHeight());
  351. return 1;
  352. }
  353. int ElementGetAttroffset_left(lua_State* L)
  354. {
  355. Element* ele = LuaType<Element>::check(L,1);
  356. LUACHECKOBJ(ele);
  357. lua_pushnumber(L,ele->GetOffsetLeft());
  358. return 1;
  359. }
  360. int ElementGetAttroffset_parent(lua_State* L)
  361. {
  362. Element* ele = LuaType<Element>::check(L,1);
  363. LUACHECKOBJ(ele);
  364. Element* parent = ele->GetOffsetParent();
  365. LuaType<Element>::push(L,parent,false);
  366. return 1;
  367. }
  368. int ElementGetAttroffset_top(lua_State* L)
  369. {
  370. Element* ele = LuaType<Element>::check(L,1);
  371. LUACHECKOBJ(ele);
  372. lua_pushnumber(L, ele->GetOffsetTop());
  373. return 1;
  374. }
  375. int ElementGetAttroffset_width(lua_State* L)
  376. {
  377. Element* ele = LuaType<Element>::check(L,1);
  378. LUACHECKOBJ(ele);
  379. lua_pushnumber(L,ele->GetOffsetWidth());
  380. return 1;
  381. }
  382. int ElementGetAttrowner_document(lua_State* L)
  383. {
  384. Element* ele = LuaType<Element>::check(L,1);
  385. LUACHECKOBJ(ele);
  386. Document* doc = ele->GetOwnerDocument();
  387. LuaType<Document>::push(L,doc,false);
  388. return 1;
  389. }
  390. int ElementGetAttrparent_node(lua_State* L)
  391. {
  392. Element* ele = LuaType<Element>::check(L,1);
  393. LUACHECKOBJ(ele);
  394. Element* parent = ele->GetParentNode();
  395. if(parent == nullptr)
  396. lua_pushnil(L);
  397. else
  398. LuaType<Element>::push(L,parent,false);
  399. return 1;
  400. }
  401. int ElementGetAttrprevious_sibling(lua_State* L)
  402. {
  403. Element* ele = LuaType<Element>::check(L,1);
  404. LUACHECKOBJ(ele);
  405. Element* sibling = ele->GetPreviousSibling();
  406. if(sibling == nullptr)
  407. lua_pushnil(L);
  408. else
  409. LuaType<Element>::push(L,sibling,false);
  410. return 1;
  411. }
  412. int ElementGetAttrscroll_height(lua_State* L)
  413. {
  414. Element* ele = LuaType<Element>::check(L,1);
  415. LUACHECKOBJ(ele);
  416. lua_pushnumber(L,ele->GetScrollHeight());
  417. return 1;
  418. }
  419. int ElementGetAttrscroll_left(lua_State* L)
  420. {
  421. Element* ele = LuaType<Element>::check(L,1);
  422. LUACHECKOBJ(ele);
  423. lua_pushnumber(L,ele->GetScrollLeft());
  424. return 1;
  425. }
  426. int ElementGetAttrscroll_top(lua_State* L)
  427. {
  428. Element* ele = LuaType<Element>::check(L,1);
  429. LUACHECKOBJ(ele);
  430. lua_pushnumber(L,ele->GetScrollTop());
  431. return 1;
  432. }
  433. int ElementGetAttrscroll_width(lua_State* L)
  434. {
  435. Element* ele = LuaType<Element>::check(L,1);
  436. LUACHECKOBJ(ele);
  437. lua_pushnumber(L,ele->GetScrollWidth());
  438. return 1;
  439. }
  440. int ElementGetAttrstyle(lua_State* L)
  441. {
  442. Element* ele = LuaType<Element>::check(L,1);
  443. LUACHECKOBJ(ele);
  444. ElementStyleProxy* prox = new ElementStyleProxy();
  445. prox->owner = ele;
  446. LuaType<ElementStyleProxy>::push(L,prox,true);
  447. return 1;
  448. }
  449. int ElementGetAttrtag_name(lua_State* L)
  450. {
  451. Element* ele = LuaType<Element>::check(L,1);
  452. LUACHECKOBJ(ele);
  453. lua_pushstring(L,ele->GetTagName().c_str());
  454. return 1;
  455. }
  456. //setters
  457. int ElementSetAttrclass_name(lua_State* L)
  458. {
  459. Element* ele = LuaType<Element>::check(L,1);
  460. LUACHECKOBJ(ele);
  461. const char* name = luaL_checkstring(L,2);
  462. ele->SetClassNames(name);
  463. return 0;
  464. }
  465. int ElementSetAttrid(lua_State* L)
  466. {
  467. Element* ele = LuaType<Element>::check(L,1);
  468. LUACHECKOBJ(ele);
  469. const char* id = luaL_checkstring(L,2);
  470. ele->SetId(id);
  471. return 0;
  472. }
  473. int ElementSetAttrinner_rml(lua_State* L)
  474. {
  475. Element* ele = LuaType<Element>::check(L,1);
  476. LUACHECKOBJ(ele);
  477. const char* rml = luaL_checkstring(L,2);
  478. ele->SetInnerRML(rml);
  479. return 0;
  480. }
  481. int ElementSetAttrscroll_left(lua_State* L)
  482. {
  483. Element* ele = LuaType<Element>::check(L,1);
  484. LUACHECKOBJ(ele);
  485. float scroll = (float)luaL_checknumber(L,2);
  486. ele->SetScrollLeft(scroll);
  487. return 0;
  488. }
  489. int ElementSetAttrscroll_top(lua_State* L)
  490. {
  491. Element* ele = LuaType<Element>::check(L,1);
  492. LUACHECKOBJ(ele);
  493. float scroll = (float)luaL_checknumber(L,2);
  494. ele->SetScrollTop(scroll);
  495. return 0;
  496. }
  497. RegType<Element> ElementMethods[] =
  498. {
  499. LUAMETHOD(Element,AddEventListener)
  500. LUAMETHOD(Element,AppendChild)
  501. LUAMETHOD(Element,Blur)
  502. LUAMETHOD(Element,Click)
  503. LUAMETHOD(Element,DispatchEvent)
  504. LUAMETHOD(Element,Focus)
  505. LUAMETHOD(Element,GetAttribute)
  506. LUAMETHOD(Element,GetElementById)
  507. LUAMETHOD(Element,GetElementsByTagName)
  508. LUAMETHOD(Element,HasAttribute)
  509. LUAMETHOD(Element,HasChildNodes)
  510. LUAMETHOD(Element,InsertBefore)
  511. LUAMETHOD(Element,IsClassSet)
  512. LUAMETHOD(Element,RemoveAttribute)
  513. LUAMETHOD(Element,RemoveChild)
  514. LUAMETHOD(Element,ReplaceChild)
  515. LUAMETHOD(Element,ScrollIntoView)
  516. LUAMETHOD(Element,SetAttribute)
  517. LUAMETHOD(Element,SetClass)
  518. { nullptr, nullptr },
  519. };
  520. luaL_Reg ElementGetters[] =
  521. {
  522. LUAGETTER(Element,attributes)
  523. LUAGETTER(Element,child_nodes)
  524. LUAGETTER(Element,class_name)
  525. LUAGETTER(Element,client_left)
  526. LUAGETTER(Element,client_height)
  527. LUAGETTER(Element,client_top)
  528. LUAGETTER(Element,client_width)
  529. LUAGETTER(Element,first_child)
  530. LUAGETTER(Element,id)
  531. LUAGETTER(Element,inner_rml)
  532. LUAGETTER(Element,last_child)
  533. LUAGETTER(Element,next_sibling)
  534. LUAGETTER(Element,offset_height)
  535. LUAGETTER(Element,offset_left)
  536. LUAGETTER(Element,offset_parent)
  537. LUAGETTER(Element,offset_top)
  538. LUAGETTER(Element,offset_width)
  539. LUAGETTER(Element,owner_document)
  540. LUAGETTER(Element,parent_node)
  541. LUAGETTER(Element,previous_sibling)
  542. LUAGETTER(Element,scroll_height)
  543. LUAGETTER(Element,scroll_left)
  544. LUAGETTER(Element,scroll_top)
  545. LUAGETTER(Element,scroll_width)
  546. LUAGETTER(Element,style)
  547. LUAGETTER(Element,tag_name)
  548. { nullptr, nullptr },
  549. };
  550. luaL_Reg ElementSetters[] =
  551. {
  552. LUASETTER(Element,class_name)
  553. LUASETTER(Element,id)
  554. LUASETTER(Element,inner_rml)
  555. LUASETTER(Element,scroll_left)
  556. LUASETTER(Element,scroll_top)
  557. { nullptr, nullptr },
  558. };
  559. LUACORETYPEDEFINE(Element)
  560. template<> void ExtraInit<ElementPtr>(lua_State* /*L*/, int /*metatable_index*/)
  561. {
  562. return;
  563. }
  564. RegType<ElementPtr> ElementPtrMethods[] =
  565. {
  566. { nullptr, nullptr },
  567. };
  568. luaL_Reg ElementPtrGetters[] =
  569. {
  570. { nullptr, nullptr },
  571. };
  572. luaL_Reg ElementPtrSetters[] =
  573. {
  574. { nullptr, nullptr },
  575. };
  576. LUACORETYPEDEFINE(ElementPtr)
  577. }
  578. }
  579. }