291 rivejä
9.2 KiB

  1. //
  2. // Lol Engine - Graphing tutorial
  3. //
  4. // Copyright: (c) 2012-2013 Sam Hocevar <sam@hocevar.net>
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the Do What The Fuck You Want To
  7. // Public License, Version 2, as published by Sam Hocevar. See
  8. // http://www.wtfpl.net/ for more details.
  9. //
  10. #if HAVE_CONFIG_H
  11. # include "config.h"
  12. #endif
  13. #include <lol/engine.h>
  14. #include "loldebug.h"
  15. #include <cstdio>
  16. using namespace lol;
  17. //-----------------------------------------------------------------------------
  18. class FooTest
  19. {
  20. public:
  21. FooTest()
  22. {
  23. }
  24. static int New(Lolua::State* l)
  25. {
  26. int n_args = lua_gettop(l); // Number of arguments
  27. // We could actually allocate Foo itself as a user data but
  28. // since user data can be GC'ed and we gain unity by using CRT's heap
  29. // all along.
  30. FooTest** udata = (FooTest**)lua_newuserdata(l, sizeof(FooTest*));
  31. *udata = new FooTest();
  32. // Usually, we'll just use "Foo" as the second parameter, but I
  33. // say luaL_Foo here to distinguish the difference:
  34. //
  35. // This 2nd parameter here is an _internal label_ for luaL, it is
  36. // _not_ exposed to Lua by default.
  37. //
  38. // Effectively, this metatable is not accessible by Lua by default.
  39. //luaL_getmetatable(l, m_table_name);
  40. // The Lua stack at this point looks like this:
  41. //
  42. // 3| metatable "luaL_foo" |-1
  43. // 2| userdata |-2
  44. // 1| string parameter |-3
  45. //
  46. // So the following line sets the metatable for the user data to the luaL_Foo
  47. // metatable
  48. //
  49. // We must set the metatable here because Lua prohibits setting
  50. // the metatable of a userdata in Lua. The only way to set a metatable
  51. // of a userdata is to do it in C.
  52. //lua_setmetatable(l, -2);
  53. luaL_getmetatable(l, m_table2_name);
  54. lua_setmetatable(l, -2);
  55. // The Lua stack at this point looks like this:
  56. //
  57. // 2| userdata |-1
  58. // 1| string parameter |-2
  59. //
  60. // We return 1 so Lua callsite will get the user data and
  61. // Lua will clean the stack after that.
  62. return 1;
  63. }
  64. static FooTest* Check(Lolua::State* l, int n)
  65. {
  66. // This checks that the argument is a userdata
  67. // with the metatable "luaL_Foo"
  68. return *(FooTest**)luaL_testudata(l, n, m_table2_name);
  69. }
  70. static int Del(Lolua::State * l)
  71. {
  72. FooTest* foo = Check(l, 1);
  73. delete foo;
  74. return 0;
  75. }
  76. static void Register(Lolua::State * l)
  77. {
  78. // Create a luaL metatable. This metatable is not
  79. // exposed to Lua. The "luaL_Foo" label is used by luaL
  80. // internally to identity things.
  81. luaL_newmetatable(l, m_table2_name);
  82. luaL_setfuncs(l, FooTest::m_statics2, 0);
  83. lua_pushvalue(l, -1);
  84. lua_setfield(l, -1, "__index");
  85. //lua_setglobal(l, m_class2_name);
  86. lua_pop(l, 1);
  87. // Create a luaL metatable. This metatable is not
  88. // exposed to Lua. The "luaL_Foo" label is used by luaL
  89. // internally to identity things.
  90. luaL_newmetatable(l, m_table_name);
  91. // Register the C functions _into_ the metatable we just created.
  92. luaL_setfuncs(l, FooTest::m_statics, 0);
  93. // The Lua stack at this point looks like this:
  94. //
  95. // 1| metatable "luaL_Foo" |-1
  96. lua_pushvalue(l, -1);
  97. // The Lua stack at this point looks like this:
  98. //
  99. // 2| metatable "luaL_Foo" |-1
  100. // 1| metatable "luaL_Foo" |-2
  101. // Set the "__index" field of the metatable to point to itself
  102. // This pops the stack
  103. lua_setfield(l, -1, "__index");
  104. // The Lua stack at this point looks like this:
  105. //
  106. // 1| metatable "luaL_Foo" |-1
  107. // The luaL_Foo metatable now has the following fields
  108. // - __gc
  109. // - __index
  110. // - new
  111. // Now we use setglobal to officially expose the luaL_Foo metatable
  112. // to Lua. And we use the name "Foo".
  113. //
  114. // This allows Lua scripts to _override_ the metatable of Foo.
  115. // For high security code this may not be called for but
  116. // we'll do this to get greater flexibility.
  117. lua_setglobal(l, m_class_name);
  118. }
  119. static int Test1(Lolua::State* L)
  120. {
  121. Lolua::Var<int> i1(L, 1);
  122. i1 += 5;
  123. return i1.Return(L);
  124. }
  125. static int Test2(Lolua::State* L)
  126. {
  127. FooTest* foo = Check(L, 1);
  128. Lolua::Var<float> i1(L, 2);
  129. i1 = foo->Test2Inst(i1.V());
  130. return i1.Return(L);
  131. }
  132. float Test2Inst(float f)
  133. {
  134. return (f + 10);
  135. }
  136. static const char m_class_name[];
  137. static const char m_class2_name[];
  138. static const char m_table_name[];
  139. static const char m_table2_name[];
  140. static const luaL_Reg m_statics[];
  141. static const luaL_Reg m_statics2[];
  142. static const luaL_Reg m_methods[];
  143. };
  144. const luaL_Reg FooTest::m_statics[] = {
  145. { "New", &FooTest::New },
  146. { "__gc", &FooTest::Del },
  147. { "Test1", &FooTest::Test1 },
  148. { NULL, NULL } };
  149. const luaL_Reg FooTest::m_statics2[] = {
  150. { "Test2", &FooTest::Test2 },
  151. { NULL, NULL } };
  152. const luaL_Reg FooTest::m_methods[] = { { NULL, NULL } };
  153. const char FooTest::m_class_name[] = "FooTest";
  154. const char FooTest::m_class2_name[] = "FooTest2";
  155. const char FooTest::m_table_name[] = "FooTest_mt";
  156. const char FooTest::m_table2_name[] = "FooTest_mt2";
  157. typedef Lolua::ObjectDef<FooTest> FooTestLuaBase;
  158. class FooTestLua : public FooTestLuaBase
  159. {
  160. public:
  161. FooTestLua() : FooTestLuaBase() {}
  162. virtual ~FooTestLua() {}
  163. static FooTestLua* New(Lolua::State* l, int arg_nb)
  164. {
  165. return new FooTestLua();
  166. }
  167. static const char* GetClassName();
  168. static const char* GetClassLibName();
  169. static const char* GetClassInstName();
  170. static const Lolua::ClassMethod* GetStaticMethods();
  171. static const Lolua::ClassMethod* GetInstanceMethods();
  172. static int Test1(Lolua::State* L)
  173. {
  174. Lolua::Var<int> i1(L, 1);
  175. i1 += 5;
  176. return i1.Return(L);
  177. }
  178. static int Test2(Lolua::State* L)
  179. {
  180. Lolua::VarPtr<FooTestLua> foo(L, 1);
  181. Lolua::Var<float> i1(L, 2);
  182. i1 = foo.V()->Test2Inst(i1.V());
  183. return i1.Return(L);
  184. }
  185. float Test2Inst(float f)
  186. {
  187. return (f + 10);
  188. }
  189. };
  190. static const Lolua::ClassMethod FooTest_statics[] = { { "Test1", &FooTestLua::Test1 }, { NULL, NULL } };
  191. const Lolua::ClassMethod FooTest_methods[] = { { "Test2", &FooTestLua::Test2 }, { NULL, NULL } };
  192. const char* FooTestLua::GetClassName() { static const char name[] = "FooTest"; return name; }
  193. const char* FooTestLua::GetClassLibName() { static const char name[] = "FooTestLib"; return name; }
  194. const char* FooTestLua::GetClassInstName() { static const char name[] = "FooTestInst"; return name; }
  195. const Lolua::ClassMethod* FooTestLua::GetStaticMethods() { return FooTest_statics; }
  196. const Lolua::ClassMethod* FooTestLua::GetInstanceMethods() { return FooTest_methods; }
  197. //-----------------------------------------------------------------------------
  198. class LoluaDemoLoader : public Lolua::Loader
  199. {
  200. public:
  201. LoluaDemoLoader() : Lolua::Loader()
  202. {
  203. Lolua::State* l = GetLuaState();
  204. Lolua::Object::Register<FooTestLua>(l);
  205. ExecLua("14_lol_lua.lua");
  206. }
  207. virtual ~LoluaDemoLoader()
  208. {
  209. }
  210. };
  211. //-----------------------------------------------------------------------------
  212. class LoluaDemo : public WorldEntity
  213. {
  214. public:
  215. LoluaDemo()
  216. {
  217. }
  218. virtual void TickGame(float seconds)
  219. {
  220. WorldEntity::TickGame(seconds);
  221. LoluaDemoLoader* demo_loader = new LoluaDemoLoader();
  222. float TestValueNum = demo_loader->GetVar<float>("TestValueNum");
  223. int32_t TestValueInt = demo_loader->GetVar<int32_t>("TestValueInt");
  224. uint32_t TestValueUint = demo_loader->GetVar<uint32_t>("TestValueUint");
  225. String TestValueStr = demo_loader->GetVar<String>("TestValueStr");
  226. //String test_return2 = demo_loader->GetVar<String>("test_return2");
  227. //String test_return3 = demo_loader->GetVar<String>("test_return3");
  228. int32_t testtruc_return = demo_loader->GetVar<int32_t>("footest_return");
  229. float testtruc_return2 = demo_loader->GetVar<float>("footest_return2");
  230. //int32_t testtruc2_return = demo_loader->GetVar<int32_t>("testtruc_return2");
  231. String::Printf("Lua Vars: TestValueNum: %.2f, TestValueInt: %i, TestValueUint: %i, TestValueStr: %s.",
  232. TestValueNum, TestValueInt, TestValueUint, TestValueStr);
  233. delete demo_loader;
  234. Ticker::Shutdown();
  235. }
  236. virtual void TickDraw(float seconds, Scene &scene)
  237. {
  238. WorldEntity::TickDraw(seconds, scene);
  239. }
  240. };
  241. //-----------------------------------------------------------------------------
  242. int main(int argc, char **argv)
  243. {
  244. System::Init(argc, argv);
  245. Application app("Tutorial 14: Lolua Demo", ivec2(800, 600), 60.0f);
  246. new LoluaDemo();
  247. app.Run();
  248. return EXIT_SUCCESS;
  249. }