| @@ -10,6 +10,7 @@ liblolcore_a_SOURCES = \ | |||||
| audio.cpp audio.h scene.cpp scene.h font.cpp font.h \ | audio.cpp audio.h scene.cpp scene.h font.cpp font.h \ | ||||
| entity.cpp entity.h ticker.cpp ticker.h lolgl.h \ | entity.cpp entity.h ticker.cpp ticker.h lolgl.h \ | ||||
| tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h \ | tileset.cpp tileset.h forge.cpp forge.h video.cpp video.h \ | ||||
| baselua.cpp baselua.h \ | |||||
| world.cpp world.h sample.cpp sample.h sampler.cpp sampler.h \ | world.cpp world.h sample.cpp sample.h sampler.cpp sampler.h \ | ||||
| profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h \ | profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h \ | ||||
| numeric.h utils.h messageservice.cpp messageservice.h \ | numeric.h utils.h messageservice.cpp messageservice.h \ | ||||
| @@ -74,6 +74,7 @@ Application::Application(char const *name, ivec2 resolution, float framerate) | |||||
| data = new ApplicationData(name, resolution, framerate); | data = new ApplicationData(name, resolution, framerate); | ||||
| g_world.ExecLua("lua/init.lua"); | g_world.ExecLua("lua/init.lua"); | ||||
| int32_t gravity = g_world.GetVar<int32_t>("gravity"); | |||||
| } | } | ||||
| bool Application::MustTick() | bool Application::MustTick() | ||||
| @@ -0,0 +1,112 @@ | |||||
| // | |||||
| // Base Lua class for Lua script loading | |||||
| // | |||||
| // Copyright: (c) 2009-2015 Sam Hocevar <sam@hocevar.net> | |||||
| // 2009-2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // | |||||
| // This program is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #include <lol/engine-internal.h> | |||||
| #include <cstring> | |||||
| #include <cstdlib> | |||||
| #include <ctype.h> | |||||
| namespace lol | |||||
| { | |||||
| //----------------------------------------------------------------------------- | |||||
| class LuaBaseData | |||||
| { | |||||
| friend class LuaLoader; | |||||
| static int LuaPanic(lua_State* L) | |||||
| { | |||||
| char const *message = lua_tostring(L, -1); | |||||
| Log::Error("%s\n", message); | |||||
| DebugAbort(); | |||||
| return 0; | |||||
| } | |||||
| static int LuaDoFile(lua_State *L) | |||||
| { | |||||
| if (lua_isnoneornil(L, 1)) | |||||
| return LUA_ERRFILE; | |||||
| LuaVar<char const*> var(L, 1); | |||||
| char const *filename = var.V();// lua_tostring(L, 1); | |||||
| int status = LUA_ERRFILE; | |||||
| array<String> pathlist = System::GetPathList(filename); | |||||
| File f; | |||||
| for (int i = 0; i < pathlist.Count(); ++i) | |||||
| { | |||||
| f.Open(pathlist[i], FileAccess::Read); | |||||
| if (f.IsValid()) | |||||
| { | |||||
| String s = f.ReadString(); | |||||
| f.Close(); | |||||
| Log::Debug("loading Lua file %s\n", pathlist[i].C()); | |||||
| status = luaL_dostring(L, s.C()); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (status == LUA_ERRFILE) | |||||
| Log::Error("could not find Lua file %s\n", filename); | |||||
| lua_pop(L, 1); | |||||
| return status; | |||||
| } | |||||
| }; | |||||
| //----------------------------------------------------------------------------- | |||||
| LuaLoader::LuaLoader() | |||||
| { | |||||
| m_lua_state = luaL_newstate(); | |||||
| lua_atpanic(m_lua_state, LuaBaseData::LuaPanic); | |||||
| luaL_openlibs(m_lua_state); | |||||
| /* Override dofile() */ | |||||
| LuaFunction do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile); | |||||
| } | |||||
| //----------------------------------------------------------------------------- | |||||
| LuaLoader::~LuaLoader() | |||||
| { | |||||
| lua_close(m_lua_state); | |||||
| } | |||||
| //----------------------------------------------------------------------------- | |||||
| bool LuaLoader::ExecLua(String const &lua) | |||||
| { | |||||
| const char* c = lua_pushstring(m_lua_state, lua.C()); | |||||
| int status = LuaBaseData::LuaDoFile(m_lua_state); | |||||
| return status == 0; | |||||
| } | |||||
| //----------------------------------------------------------------------------- | |||||
| double LuaLoader::GetLuaNumber(String const &var) | |||||
| { | |||||
| double ret; | |||||
| lua_getglobal(m_lua_state, var.C()); | |||||
| ret = lua_tonumber(m_lua_state, -1); | |||||
| lua_pop(m_lua_state, 1); | |||||
| return ret; | |||||
| } | |||||
| //----------------------------------------------------------------------------- | |||||
| lua_State* LuaLoader::GetLuaState() | |||||
| { | |||||
| return m_lua_state; | |||||
| } | |||||
| } /* namespace lol */ | |||||
| @@ -0,0 +1,210 @@ | |||||
| // | |||||
| // Base Lua class for Lua script loading | |||||
| // | |||||
| // Copyright: (c) 2009-2015 Sam Hocevar <sam@hocevar.net> | |||||
| // 2009-2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
| // | |||||
| // This program is free software. It comes without any warranty, to | |||||
| // the extent permitted by applicable law. You can redistribute it | |||||
| // and/or modify it under the terms of the Do What the Fuck You Want | |||||
| // to Public License, Version 2, as published by the WTFPL Task Force. | |||||
| // See http://www.wtfpl.net/ for more details. | |||||
| // | |||||
| #include "lua/lua.hpp" | |||||
| #include "lua/luawrapper.hpp" | |||||
| #pragma once | |||||
| namespace lol | |||||
| { | |||||
| //----------------------------------------------------------------------------- | |||||
| #define LOLUA_CLASS_STATIC(ClassType, FuncName) Static ## ClassType ## FuncName | |||||
| #define LOLUA_CLASS_METHOD(ClassType, FuncName) Method ## ClassType ## FuncName | |||||
| #define LOLUA_CLASS_STATIC_C(ClassType, FuncName) Static ## #ClassType ## #FuncName | |||||
| #define LOLUA_CLASS_METHOD_C(ClassType, FuncName) Method ## #ClassType ## #FuncName | |||||
| #define LOLUA_BEGIN_CTOR(ClassType) \ | |||||
| ClassType* ClassType##New(lua_State* L) \ | |||||
| { \ | |||||
| int arg_idx = 1; \ | |||||
| #define LOLUA_END_CTOR(ClassType, ...) \ | |||||
| return new ClassType(__VA_ARGS__); \ | |||||
| } \ | |||||
| #define LOLUA_BEGIN_STATIC(FuncName) \ | |||||
| int FuncName(lua_State* L) \ | |||||
| { \ | |||||
| int arg_idx = 1; \ | |||||
| #define LOLUA_BEGIN_CLASS_STATIC(ClassType, FuncName) \ | |||||
| int LOLUA_CLASS_STATIC(ClassType, FuncName)(lua_State* L) \ | |||||
| { \ | |||||
| int arg_idx = 1; \ | |||||
| #define LOLUA_BEGIN_CLASS_METHOD(ClassType, FuncName) \ | |||||
| int LOLUA_CLASS_METHOD(ClassType, FuncName)(lua_State* L) \ | |||||
| { \ | |||||
| int arg_idx = 1; \ | |||||
| ClassType* this_ptr = luaW_check<ClassType>(L, arg_idx); \ | |||||
| #define LOLUA_CALL_FUNC(FuncName, ...) FuncName(__VA_ARGS__); | |||||
| #define LOLUA_CALL_FUNC_RET(FuncName, ...) auto result = FuncName(__VA_ARGS__); | |||||
| #define LOLUA_CALL_STATIC(ClassType, FuncName, ...) ClassType::FuncName(__VA_ARGS__); | |||||
| #define LOLUA_CALL_STATIC_RET(ClassType, FuncName, ...) auto result = ClassType::FuncName(__VA_ARGS__); | |||||
| #define LOLUA_CALL_METHOD(FuncName, ...) this_ptr->FuncName(__VA_ARGS__); | |||||
| #define LOLUA_CALL_METHOD_RET(FuncName, ...) auto result = this_ptr->FuncName(__VA_ARGS__); | |||||
| #define LOLUA_ARG_STRING(VarName) String VarName = luaL_checkstring(L, arg_idx++); | |||||
| #define LOLUA_ARG_CHAR(VarName) const char* VarName = luaL_checkstring(L, arg_idx++); | |||||
| #define LOLUA_ARG_DOUBLE(VarName) double VarName = luaL_checknumber(L, arg_idx++); | |||||
| #define LOLUA_ARG_INT(VarName) int32_t VarName = luaL_checkinteger(L, arg_idx++); | |||||
| #define LOLUA_ARG_UINT(VarName) uint32_t VarName = luaL_checkunsigned(L, arg_idx++); | |||||
| #define LOLUA_ARG_OBJ(VarType, VarName) VarType* VarName = luaW_check<VarType>(L, arg_idx++); | |||||
| #define LOLUA_END_FUNC_STRING(VarName) lua_pushstring(L, VarName.C()); return 1; } | |||||
| #define LOLUA_END_FUNC_CHAR(VarName) lua_pushstring(L, VarName); return 1; } | |||||
| #define LOLUA_END_FUNC_FLOAT(VarName) lua_pushnumber(L, VarName); return 1; } | |||||
| #define LOLUA_END_FUNC_INT(VarName) lua_pushinteger(L, VarName); return 1; } | |||||
| #define LOLUA_END_FUNC_UINT(VarName) lua_pushunsigned(L, VarName); return 1; } | |||||
| #define LOLUA_END_FUNC_OBJ(VarName) luaW_push<VarType>(L, VarName); return 1; } | |||||
| #define LOLUA_END_FUNC_STRING_RESULT LOLUA_END_FUNC_STRING(result) | |||||
| #define LOLUA_END_FUNC_CHAR_RESULT LOLUA_END_FUNC_CHAR(result) | |||||
| #define LOLUA_END_FUNC_FLOAT_RESULT LOLUA_END_FUNC_FLOAT(result) | |||||
| #define LOLUA_END_FUNC_INT_RESULT LOLUA_END_FUNC_INT(result) | |||||
| #define LOLUA_END_FUNC_UINT_RESULT LOLUA_END_FUNC_UINT(result) | |||||
| #define LOLUA_END_FUNC_OBJ_RESULT LOLUA_END_FUNC_OBJ(result) | |||||
| #define LOLUA_END_FUNC_VOID return 0; } | |||||
| #define LOLUA_BEGIN_TABLE_STATIC(ClassType) static luaL_Reg ClassType##StaticTable[] = { | |||||
| #define LOLUA_BEGIN_TABLE_METHOD(ClassType) static luaL_Reg ClassType##MethodTable[] = { | |||||
| #define LOLUA_ADD_TABLE_STATIC(ClassType, FuncName) { LOLUA_CLASS_STATIC_C(ClassType, FuncName), LOLUA_CLASS_STATIC(ClassType, FuncName) }, | |||||
| #define LOLUA_ADD_TABLE_METHOD(ClassType, FuncName) { LOLUA_CLASS_METHOD_C(ClassType, FuncName), LOLUA_CLASS_METHOD(ClassType, FuncName) }, | |||||
| #define LOLUA_END_TABLE { NULL, NULL } }; | |||||
| #define LOLUA_DEFINE_CLASS_LIBRARY(ClassType) \ | |||||
| static int luaopen_##ClassType(lua_State* L) \ | |||||
| { luaW_register<ClassType>(L, #ClassType, ClassType##StaticTable, ClassType##MethodTable, ClassType##New); return 1; }\ | |||||
| #define LOLUA_NEW_STATE(VarName) lua_State* L = (VarName = luaL_newstate()); | |||||
| #define LOLUA_USE_STATE(VarName) lua_State* L = VarName; | |||||
| #define LOLUA_REGISTER_CLASS_LIBRARY(ClassType) luaopen_##ClassType(L); | |||||
| #define LOLUA_REGISTER_STATIC(LuaFuncName, CppFuncName) lua_pushcfunction(L, CppFuncName); lua_setglobal(L, #LuaFuncName); | |||||
| //----------------------------------------------------------------------------- | |||||
| class LuaObject | |||||
| { | |||||
| protected: | |||||
| template<typename T, const char* name, const luaL_Reg* statics, const luaL_Reg* methods, T* (*ctor)(lua_State*)> | |||||
| struct LuaLibrary | |||||
| { | |||||
| LuaLibrary() { } | |||||
| void LoadTo(lua_State* l) { luaW_register<T>(l, name, statics, methods, ctor); } | |||||
| }; | |||||
| }; | |||||
| //----------------------------------------------------------------------------- | |||||
| struct LuaFunction | |||||
| { | |||||
| LuaFunction(lua_State* l, const char* name, int (*function)(lua_State*)) | |||||
| { | |||||
| lua_pushcfunction(l, function); | |||||
| lua_setglobal(l, name); | |||||
| } | |||||
| }; | |||||
| //----------------------------------------------------------------------------- | |||||
| template<typename T> | |||||
| struct LuaVar | |||||
| { | |||||
| private: | |||||
| T m_value = T(0); | |||||
| public: | |||||
| LuaVar() { } | |||||
| LuaVar(T value) { m_value = value; } | |||||
| LuaVar(lua_State* l, int index) { InnerGet(l, index); } | |||||
| inline T& V() { return m_value; } | |||||
| inline T& operator=(const T& value) { m_value = value; } | |||||
| inline int Return(lua_State* l) { InnerPush(l); return 1; } | |||||
| private: | |||||
| void InnerGet(lua_State* l, int index) { ASSERT(false); } | |||||
| void InnerPush(lua_State* l) { ASSERT(false); } | |||||
| }; | |||||
| //----------------------------------------------------------------------------- | |||||
| template<typename T> | |||||
| struct LuaPtr | |||||
| { | |||||
| private: | |||||
| T* m_value = nullptr; | |||||
| public: | |||||
| LuaPtr() { } | |||||
| LuaPtr(T* value) { m_value = value; } | |||||
| LuaPtr(lua_State* l, int index) { InnerGet(l, index); } | |||||
| inline T* V() { return m_value; } | |||||
| inline T* operator=(T* value) { m_value = value; } | |||||
| inline int Return(lua_State* l) { InnerPush(l); return 1; } | |||||
| private: | |||||
| void InnerGet(lua_State* l, int index) { m_value = luaW_check<T>(l, index); } | |||||
| void InnerPush(lua_State* l) { luaW_push<T>(l, m_value); } | |||||
| }; | |||||
| //----------------------------------------------------------------------------- | |||||
| template<> inline void LuaVar<String> ::InnerGet(lua_State* l, int index) { m_value = lua_tostring(l, index); } | |||||
| template<> inline void LuaVar<char const*>::InnerGet(lua_State* l, int index) { m_value = lua_tostring(l, index); } | |||||
| template<> inline void LuaVar<double> ::InnerGet(lua_State* l, int index) { m_value = lua_tonumber(l, index); } | |||||
| template<> inline void LuaVar<float> ::InnerGet(lua_State* l, int index) { m_value = (float)lua_tonumber(l, index); } | |||||
| template<> inline void LuaVar<int32_t> ::InnerGet(lua_State* l, int index) { m_value = (int32_t)lua_tointeger(l, index); } | |||||
| template<> inline void LuaVar<int64_t> ::InnerGet(lua_State* l, int index) { m_value = lua_tointeger(l, index); } | |||||
| template<> inline void LuaVar<uint32_t> ::InnerGet(lua_State* l, int index) { m_value = lua_tounsigned(l, index); } | |||||
| template<> inline void LuaVar<String> ::InnerPush(lua_State* l) { lua_pushstring(l, m_value.C()); } | |||||
| template<> inline void LuaVar<char const*>::InnerPush(lua_State* l) { lua_pushstring(l, m_value); } | |||||
| template<> inline void LuaVar<double> ::InnerPush(lua_State* l) { lua_pushnumber(l, m_value); } | |||||
| template<> inline void LuaVar<float> ::InnerPush(lua_State* l) { lua_pushnumber(l, m_value); } | |||||
| template<> inline void LuaVar<int32_t> ::InnerPush(lua_State* l) { lua_pushinteger(l, m_value); } | |||||
| template<> inline void LuaVar<int64_t> ::InnerPush(lua_State* l) { lua_pushinteger(l, m_value); } | |||||
| template<> inline void LuaVar<uint32_t> ::InnerPush(lua_State* l) { lua_pushunsigned(l, m_value); } | |||||
| //----------------------------------------------------------------------------- | |||||
| class LuaLoader | |||||
| { | |||||
| public: | |||||
| LuaLoader(); | |||||
| virtual ~LuaLoader(); | |||||
| bool ExecLua(String const &lua); | |||||
| double GetLuaNumber(String const &var); | |||||
| template<typename T> | |||||
| T GetVar(String const &name) | |||||
| { | |||||
| lua_getglobal(m_lua_state, name.C()); | |||||
| LuaVar<T> var(m_lua_state, -1); | |||||
| lua_pop(m_lua_state, 1); | |||||
| return var.V(); | |||||
| } | |||||
| template<typename T> | |||||
| T* GetPtr(String const &name) | |||||
| { | |||||
| lua_getglobal(m_lua_state, name.C()); | |||||
| LuaPtr<T> var(m_lua_state, -1); | |||||
| lua_pop(m_lua_state, 1); | |||||
| return var.V(); | |||||
| } | |||||
| protected: | |||||
| lua_State* GetLuaState(); | |||||
| private: | |||||
| lua_State* m_lua_state; | |||||
| }; | |||||
| } /* namespace lol */ | |||||
| @@ -59,6 +59,16 @@ VertexData EasyMesh::GetLerpVertex(VertexData const &vi, VertexData const &vj, f | |||||
| void EasyMesh::AddQuad(int i1, int i2, int i3, int i4, int base, bool duplicate) | void EasyMesh::AddQuad(int i1, int i2, int i3, int i4, int base, bool duplicate) | ||||
| { | { | ||||
| if (duplicate) | if (duplicate) | ||||
| { | |||||
| int vbase = (int)m_vert.Count(); | |||||
| AddDupVertex(base + i1); | |||||
| AddDupVertex(base + i2); | |||||
| AddDupVertex(base + i3); | |||||
| AddDupVertex(base + i4); | |||||
| AddQuad(0, 1, 2, 3, vbase); | |||||
| } | |||||
| else | |||||
| { | { | ||||
| if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) && | if (BD()->IsEnabled(MeshBuildOperation::QuadWeighting) && | ||||
| !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting)) | !BD()->IsEnabled(MeshBuildOperation::IgnoreQuadWeighting)) | ||||
| @@ -93,33 +103,23 @@ void EasyMesh::AddQuad(int i1, int i2, int i3, int i4, int base, bool duplicate) | |||||
| m_indices << i3 + base; | m_indices << i3 + base; | ||||
| } | } | ||||
| } | } | ||||
| else | |||||
| { | |||||
| int vbase = (int)m_vert.Count(); | |||||
| AddDupVertex(base + i1); | |||||
| AddDupVertex(base + i2); | |||||
| AddDupVertex(base + i3); | |||||
| AddDupVertex(base + i4); | |||||
| AddQuad(0, 1, 2, 3, vbase); | |||||
| } | |||||
| } | } | ||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
| void EasyMesh::AddTriangle(int i1, int i2, int i3, int base, bool duplicate) | void EasyMesh::AddTriangle(int i1, int i2, int i3, int base, bool duplicate) | ||||
| { | { | ||||
| if (duplicate) | if (duplicate) | ||||
| { | |||||
| m_indices << base + i1; | |||||
| m_indices << base + i2; | |||||
| m_indices << base + i3; | |||||
| } | |||||
| else | |||||
| { | { | ||||
| m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i1); | m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i1); | ||||
| m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i2); | m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i2); | ||||
| m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i3); | m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i3); | ||||
| } | } | ||||
| else | |||||
| { | |||||
| m_indices << base + i1; | |||||
| m_indices << base + i2; | |||||
| m_indices << base + i3; | |||||
| } | |||||
| } | } | ||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
| @@ -43,6 +43,7 @@ | |||||
| #include <lol/../sprite.h> | #include <lol/../sprite.h> | ||||
| #include <lol/../text.h> | #include <lol/../text.h> | ||||
| #include <lol/../tileset.h> | #include <lol/../tileset.h> | ||||
| #include <lol/../application/baselua.h> | |||||
| #include <lol/../world.h> | #include <lol/../world.h> | ||||
| // Other objects | // Other objects | ||||
| @@ -88,6 +88,7 @@ | |||||
| </ItemDefinitionGroup> | </ItemDefinitionGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <ClCompile Include="application\application.cpp" /> | <ClCompile Include="application\application.cpp" /> | ||||
| <ClCompile Include="application\baselua.cpp" /> | |||||
| <ClCompile Include="audio.cpp" /> | <ClCompile Include="audio.cpp" /> | ||||
| <ClCompile Include="camera.cpp" /> | <ClCompile Include="camera.cpp" /> | ||||
| <ClCompile Include="base\assert.cpp" /> | <ClCompile Include="base\assert.cpp" /> | ||||
| @@ -231,6 +232,7 @@ | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <ClInclude Include="application\application.h" /> | <ClInclude Include="application\application.h" /> | ||||
| <ClInclude Include="application\baselua.h" /> | |||||
| <ClInclude Include="audio.h" /> | <ClInclude Include="audio.h" /> | ||||
| <ClInclude Include="camera.h" /> | <ClInclude Include="camera.h" /> | ||||
| <ClInclude Include="commandstack.h" /> | <ClInclude Include="commandstack.h" /> | ||||
| @@ -403,6 +403,9 @@ | |||||
| <ClCompile Include="easymesh\easymeshcursor.cpp"> | <ClCompile Include="easymesh\easymeshcursor.cpp"> | ||||
| <Filter>easymesh</Filter> | <Filter>easymesh</Filter> | ||||
| </ClCompile> | </ClCompile> | ||||
| <ClCompile Include="application\baselua.cpp"> | |||||
| <Filter>application</Filter> | |||||
| </ClCompile> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <ClInclude Include="debug\fps.h"> | <ClInclude Include="debug\fps.h"> | ||||
| @@ -754,6 +757,9 @@ | |||||
| <ClInclude Include="lol\algorithm\portal.h"> | <ClInclude Include="lol\algorithm\portal.h"> | ||||
| <Filter>lol\algorithm</Filter> | <Filter>lol\algorithm</Filter> | ||||
| </ClInclude> | </ClInclude> | ||||
| <ClInclude Include="application\baselua.h"> | |||||
| <Filter>application</Filter> | |||||
| </ClInclude> | |||||
| </ItemGroup> | </ItemGroup> | ||||
| <ItemGroup> | <ItemGroup> | ||||
| <LolFxCompile Include="gpu\emptymaterial.lolfx"> | <LolFxCompile Include="gpu\emptymaterial.lolfx"> | ||||
| @@ -1,129 +1,130 @@ | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <ItemGroup Label="ProjectConfigurations"> | |||||
| <ProjectConfiguration Include="Debug|ORBIS"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>ORBIS</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|Win32"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>Win32</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|x64"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>x64</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|Xbox 360"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>Xbox 360</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|ORBIS"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>ORBIS</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|Win32"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>Win32</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|x64"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>x64</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|Xbox 360"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>Xbox 360</Platform> | |||||
| </ProjectConfiguration> | |||||
| </ItemGroup> | |||||
| <PropertyGroup Label="Globals"> | |||||
| <ProjectGuid>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</ProjectGuid> | |||||
| <ConfigurationType>StaticLibrary</ConfigurationType> | |||||
| <Keyword>Win32Proj</Keyword> | |||||
| </PropertyGroup> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.config.props" /> | |||||
| <PropertyGroup Label="Configuration"> | |||||
| <CharacterSet>MultiByte</CharacterSet> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> | |||||
| <UseDebugLibraries>true</UseDebugLibraries> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> | |||||
| <UseDebugLibraries>false</UseDebugLibraries> | |||||
| <WholeProgramOptimization>true</WholeProgramOptimization> | |||||
| </PropertyGroup> | |||||
| <ImportGroup Label="PropertySheets"> | |||||
| <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.vars.props" /> | |||||
| </ImportGroup> | |||||
| <PropertyGroup Label="UserMacros" /> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.rules.props" /> | |||||
| <ItemDefinitionGroup> | |||||
| <ClCompile> | |||||
| <PreprocessorDefinitions>LUA_ANSI;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
| </ClCompile> | |||||
| </ItemDefinitionGroup> | |||||
| <ItemGroup> | |||||
| <ClCompile Include="lapi.c" /> | |||||
| <ClCompile Include="lauxlib.c" /> | |||||
| <ClCompile Include="lbaselib.c" /> | |||||
| <ClCompile Include="lbitlib.c" /> | |||||
| <ClCompile Include="lcode.c" /> | |||||
| <ClCompile Include="lcorolib.c" /> | |||||
| <ClCompile Include="lctype.c" /> | |||||
| <ClCompile Include="ldblib.c" /> | |||||
| <ClCompile Include="ldebug.c" /> | |||||
| <ClCompile Include="ldo.c" /> | |||||
| <ClCompile Include="ldump.c" /> | |||||
| <ClCompile Include="lfunc.c" /> | |||||
| <ClCompile Include="lgc.c" /> | |||||
| <ClCompile Include="linit.c" /> | |||||
| <ClCompile Include="liolib.c" /> | |||||
| <ClCompile Include="llex.c" /> | |||||
| <ClCompile Include="lmathlib.c" /> | |||||
| <ClCompile Include="lmem.c" /> | |||||
| <ClCompile Include="loadlib.c" /> | |||||
| <ClCompile Include="lobject.c" /> | |||||
| <ClCompile Include="lopcodes.c" /> | |||||
| <ClCompile Include="loslib.c" /> | |||||
| <ClCompile Include="lparser.c" /> | |||||
| <ClCompile Include="lstate.c" /> | |||||
| <ClCompile Include="lstring.c" /> | |||||
| <ClCompile Include="lstrlib.c" /> | |||||
| <ClCompile Include="ltable.c" /> | |||||
| <ClCompile Include="ltablib.c" /> | |||||
| <ClCompile Include="ltm.c" /> | |||||
| <ClCompile Include="lundump.c" /> | |||||
| <ClCompile Include="lvm.c" /> | |||||
| <ClCompile Include="lzio.c" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ClInclude Include="lapi.h" /> | |||||
| <ClInclude Include="lauxlib.h" /> | |||||
| <ClInclude Include="lcode.h" /> | |||||
| <ClInclude Include="lctype.h" /> | |||||
| <ClInclude Include="ldebug.h" /> | |||||
| <ClInclude Include="ldo.h" /> | |||||
| <ClInclude Include="lfunc.h" /> | |||||
| <ClInclude Include="lgc.h" /> | |||||
| <ClInclude Include="llex.h" /> | |||||
| <ClInclude Include="llimits.h" /> | |||||
| <ClInclude Include="lmem.h" /> | |||||
| <ClInclude Include="lobject.h" /> | |||||
| <ClInclude Include="lopcodes.h" /> | |||||
| <ClInclude Include="lparser.h" /> | |||||
| <ClInclude Include="lstate.h" /> | |||||
| <ClInclude Include="lstring.h" /> | |||||
| <ClInclude Include="ltable.h" /> | |||||
| <ClInclude Include="ltm.h" /> | |||||
| <ClInclude Include="luaconf.h" /> | |||||
| <ClInclude Include="lua.h" /> | |||||
| <ClInclude Include="lua.hpp" /> | |||||
| <ClInclude Include="lualib.h" /> | |||||
| <ClInclude Include="lundump.h" /> | |||||
| <ClInclude Include="lvm.h" /> | |||||
| <ClInclude Include="lzio.h" /> | |||||
| </ItemGroup> | |||||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||||
| <ImportGroup Label="ExtensionTargets"> | |||||
| <Import Project="$(SolutionDir)\msbuild\lolfx.targets" /> | |||||
| </ImportGroup> | |||||
| </Project> | |||||
| <?xml version="1.0" encoding="utf-8"?> | |||||
| <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||||
| <ItemGroup Label="ProjectConfigurations"> | |||||
| <ProjectConfiguration Include="Debug|ORBIS"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>ORBIS</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|Win32"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>Win32</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|x64"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>x64</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Debug|Xbox 360"> | |||||
| <Configuration>Debug</Configuration> | |||||
| <Platform>Xbox 360</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|ORBIS"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>ORBIS</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|Win32"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>Win32</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|x64"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>x64</Platform> | |||||
| </ProjectConfiguration> | |||||
| <ProjectConfiguration Include="Release|Xbox 360"> | |||||
| <Configuration>Release</Configuration> | |||||
| <Platform>Xbox 360</Platform> | |||||
| </ProjectConfiguration> | |||||
| </ItemGroup> | |||||
| <PropertyGroup Label="Globals"> | |||||
| <ProjectGuid>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</ProjectGuid> | |||||
| <ConfigurationType>StaticLibrary</ConfigurationType> | |||||
| <Keyword>Win32Proj</Keyword> | |||||
| </PropertyGroup> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.config.props" /> | |||||
| <PropertyGroup Label="Configuration"> | |||||
| <CharacterSet>MultiByte</CharacterSet> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> | |||||
| <UseDebugLibraries>true</UseDebugLibraries> | |||||
| </PropertyGroup> | |||||
| <PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> | |||||
| <UseDebugLibraries>false</UseDebugLibraries> | |||||
| <WholeProgramOptimization>true</WholeProgramOptimization> | |||||
| </PropertyGroup> | |||||
| <ImportGroup Label="PropertySheets"> | |||||
| <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.vars.props" /> | |||||
| </ImportGroup> | |||||
| <PropertyGroup Label="UserMacros" /> | |||||
| <Import Project="$(SolutionDir)\msbuild\lol.rules.props" /> | |||||
| <ItemDefinitionGroup> | |||||
| <ClCompile> | |||||
| <PreprocessorDefinitions>LUA_ANSI;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
| </ClCompile> | |||||
| </ItemDefinitionGroup> | |||||
| <ItemGroup> | |||||
| <ClCompile Include="lapi.c" /> | |||||
| <ClCompile Include="lauxlib.c" /> | |||||
| <ClCompile Include="lbaselib.c" /> | |||||
| <ClCompile Include="lbitlib.c" /> | |||||
| <ClCompile Include="lcode.c" /> | |||||
| <ClCompile Include="lcorolib.c" /> | |||||
| <ClCompile Include="lctype.c" /> | |||||
| <ClCompile Include="ldblib.c" /> | |||||
| <ClCompile Include="ldebug.c" /> | |||||
| <ClCompile Include="ldo.c" /> | |||||
| <ClCompile Include="ldump.c" /> | |||||
| <ClCompile Include="lfunc.c" /> | |||||
| <ClCompile Include="lgc.c" /> | |||||
| <ClCompile Include="linit.c" /> | |||||
| <ClCompile Include="liolib.c" /> | |||||
| <ClCompile Include="llex.c" /> | |||||
| <ClCompile Include="lmathlib.c" /> | |||||
| <ClCompile Include="lmem.c" /> | |||||
| <ClCompile Include="loadlib.c" /> | |||||
| <ClCompile Include="lobject.c" /> | |||||
| <ClCompile Include="lopcodes.c" /> | |||||
| <ClCompile Include="loslib.c" /> | |||||
| <ClCompile Include="lparser.c" /> | |||||
| <ClCompile Include="lstate.c" /> | |||||
| <ClCompile Include="lstring.c" /> | |||||
| <ClCompile Include="lstrlib.c" /> | |||||
| <ClCompile Include="ltable.c" /> | |||||
| <ClCompile Include="ltablib.c" /> | |||||
| <ClCompile Include="ltm.c" /> | |||||
| <ClCompile Include="lundump.c" /> | |||||
| <ClCompile Include="lvm.c" /> | |||||
| <ClCompile Include="lzio.c" /> | |||||
| </ItemGroup> | |||||
| <ItemGroup> | |||||
| <ClInclude Include="lapi.h" /> | |||||
| <ClInclude Include="lauxlib.h" /> | |||||
| <ClInclude Include="lcode.h" /> | |||||
| <ClInclude Include="lctype.h" /> | |||||
| <ClInclude Include="ldebug.h" /> | |||||
| <ClInclude Include="ldo.h" /> | |||||
| <ClInclude Include="lfunc.h" /> | |||||
| <ClInclude Include="lgc.h" /> | |||||
| <ClInclude Include="llex.h" /> | |||||
| <ClInclude Include="llimits.h" /> | |||||
| <ClInclude Include="lmem.h" /> | |||||
| <ClInclude Include="lobject.h" /> | |||||
| <ClInclude Include="lopcodes.h" /> | |||||
| <ClInclude Include="lparser.h" /> | |||||
| <ClInclude Include="lstate.h" /> | |||||
| <ClInclude Include="lstring.h" /> | |||||
| <ClInclude Include="ltable.h" /> | |||||
| <ClInclude Include="ltm.h" /> | |||||
| <ClInclude Include="luaconf.h" /> | |||||
| <ClInclude Include="lua.h" /> | |||||
| <ClInclude Include="lua.hpp" /> | |||||
| <ClInclude Include="lualib.h" /> | |||||
| <ClInclude Include="luawrapper.hpp" /> | |||||
| <ClInclude Include="lundump.h" /> | |||||
| <ClInclude Include="lvm.h" /> | |||||
| <ClInclude Include="lzio.h" /> | |||||
| </ItemGroup> | |||||
| <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||||
| <ImportGroup Label="ExtensionTargets"> | |||||
| <Import Project="$(SolutionDir)\msbuild\lolfx.targets" /> | |||||
| </ImportGroup> | |||||
| </Project> | |||||
| @@ -0,0 +1,731 @@ | |||||
| /* | |||||
| * Copyright (c) 2010-2013 Alexander Ames | |||||
| * Alexander.Ames@gmail.com | |||||
| * See Copyright Notice at the end of this file | |||||
| */ | |||||
| // API Summary: | |||||
| // | |||||
| // LuaWrapper is a library designed to help bridge the gab between Lua and | |||||
| // C++. It is designed to be small (a single header file), simple, fast, | |||||
| // and typesafe. It has no external dependencies, and does not need to be | |||||
| // precompiled; the header can simply be dropped into a project and used | |||||
| // immediately. It even supports class inheritance to a certain degree. Objects | |||||
| // can be created in either Lua or C++, and passed back and forth. | |||||
| // | |||||
| // The main functions of interest are the following: | |||||
| // luaW_is<T> | |||||
| // luaW_to<T> | |||||
| // luaW_check<T> | |||||
| // luaW_push<T> | |||||
| // luaW_register<T> | |||||
| // luaW_setfuncs<T> | |||||
| // luaW_extend<T, U> | |||||
| // luaW_hold<T> | |||||
| // luaW_release<T> | |||||
| // | |||||
| // These functions allow you to manipulate arbitrary classes just like you | |||||
| // would the primitive types (e.g. numbers or strings). If you are familiar | |||||
| // with the normal Lua API the behavior of these functions should be very | |||||
| // intuative. | |||||
| // | |||||
| // For more information see the README and the comments below | |||||
| #ifndef LUA_WRAPPER_H_ | |||||
| #define LUA_WRAPPER_H_ | |||||
| // If you are linking against Lua compiled in C++, define LUAW_NO_EXTERN_C | |||||
| #ifndef LUAW_NO_EXTERN_C | |||||
| extern "C" | |||||
| { | |||||
| #endif // LUAW_NO_EXTERN_C | |||||
| #include "lua.h" | |||||
| #include "lauxlib.h" | |||||
| #ifndef LUAW_NO_EXTERN_C | |||||
| } | |||||
| #endif // LUAW_NO_EXTERN_C | |||||
| #define LUAW_POSTCTOR_KEY "__postctor" | |||||
| #define LUAW_EXTENDS_KEY "__extends" | |||||
| #define LUAW_STORAGE_KEY "storage" | |||||
| #define LUAW_CACHE_KEY "cache" | |||||
| #define LUAW_CACHE_METATABLE_KEY "cachemetatable" | |||||
| #define LUAW_HOLDS_KEY "holds" | |||||
| #define LUAW_WRAPPER_KEY "LuaWrapper" | |||||
| // A simple utility function to adjust a given index | |||||
| // Useful for when a parameter index needs to be adjusted | |||||
| // after pushing or popping things off the stack | |||||
| inline int luaW_correctindex(lua_State* L, int index, int correction) | |||||
| { | |||||
| return index < 0 ? index - correction : index; | |||||
| } | |||||
| // These are the default allocator and deallocator. If you would prefer an | |||||
| // alternative option, you may select a different function when registering | |||||
| // your class. | |||||
| template <typename T> | |||||
| T* luaW_defaultallocator(lua_State*) | |||||
| { | |||||
| return new T(); | |||||
| } | |||||
| template <typename T> | |||||
| void luaW_defaultdeallocator(lua_State*, T* obj) | |||||
| { | |||||
| delete obj; | |||||
| } | |||||
| // The identifier function is responsible for pushing a value unique to each | |||||
| // object on to the stack. Most of the time, this can simply be the address | |||||
| // of the pointer, but sometimes that is not adaquate. For example, if you | |||||
| // are using shared_ptr you would need to push the address of the object the | |||||
| // shared_ptr represents, rather than the address of the shared_ptr itself. | |||||
| template <typename T> | |||||
| void luaW_defaultidentifier(lua_State* L, T* obj) | |||||
| { | |||||
| lua_pushlightuserdata(L, obj); | |||||
| } | |||||
| // This class is what is used by LuaWrapper to contain the userdata. data | |||||
| // stores a pointer to the object itself, and cast is used to cast toward the | |||||
| // base class if there is one and it is necessary. Rather than use RTTI and | |||||
| // typid to compare types, I use the clever trick of using the cast to compare | |||||
| // types. Because there is at most one cast per type, I can use it to identify | |||||
| // when and object is the type I want. This is only used internally. | |||||
| struct luaW_Userdata | |||||
| { | |||||
| luaW_Userdata(void* vptr = NULL, luaW_Userdata(*udcast)(const luaW_Userdata&) = NULL) | |||||
| : data(vptr), cast(udcast) {} | |||||
| void* data; | |||||
| luaW_Userdata(*cast)(const luaW_Userdata&); | |||||
| }; | |||||
| // This class cannot actually to be instantiated. It is used only hold the | |||||
| // table name and other information. | |||||
| template <typename T> | |||||
| class LuaWrapper | |||||
| { | |||||
| public: | |||||
| static const char* classname; | |||||
| static void(*identifier)(lua_State*, T*); | |||||
| static T* (*allocator)(lua_State*); | |||||
| static void(*deallocator)(lua_State*, T*); | |||||
| static luaW_Userdata(*cast)(const luaW_Userdata&); | |||||
| static void(*postconstructorrecurse)(lua_State* L, int numargs); | |||||
| private: | |||||
| LuaWrapper(); | |||||
| }; | |||||
| template <typename T> const char* LuaWrapper<T>::classname; | |||||
| template <typename T> void(*LuaWrapper<T>::identifier)(lua_State*, T*); | |||||
| template <typename T> T* (*LuaWrapper<T>::allocator)(lua_State*); | |||||
| template <typename T> void(*LuaWrapper<T>::deallocator)(lua_State*, T*); | |||||
| template <typename T> luaW_Userdata(*LuaWrapper<T>::cast)(const luaW_Userdata&); | |||||
| template <typename T> void(*LuaWrapper<T>::postconstructorrecurse)(lua_State* L, int numargs); | |||||
| // Cast from an object of type T to an object of type U. This template | |||||
| // function is instantiated by calling luaW_extend<T, U>(L). This is only used | |||||
| // internally. | |||||
| template <typename T, typename U> | |||||
| luaW_Userdata luaW_cast(const luaW_Userdata& obj) | |||||
| { | |||||
| return luaW_Userdata(static_cast<U*>(static_cast<T*>(obj.data)), LuaWrapper<U>::cast); | |||||
| } | |||||
| template <typename T, typename U> | |||||
| void luaW_identify(lua_State* L, T* obj) | |||||
| { | |||||
| LuaWrapper<U>::identifier(L, static_cast<U*>(obj)); | |||||
| } | |||||
| template <typename T> | |||||
| inline void luaW_wrapperfield(lua_State* L, const char* field) | |||||
| { | |||||
| lua_getfield(L, LUA_REGISTRYINDEX, LUAW_WRAPPER_KEY); // ... LuaWrapper | |||||
| lua_getfield(L, -1, field); // ... LuaWrapper LuaWrapper.field | |||||
| lua_getfield(L, -1, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.field LuaWrapper.field.class | |||||
| lua_replace(L, -3); // ... LuaWrapper.field.class LuaWrapper.field | |||||
| lua_pop(L, 1); // ... LuaWrapper.field.class | |||||
| } | |||||
| // Analogous to lua_is(boolean|string|*) | |||||
| // | |||||
| // Returns 1 if the value at the given acceptable index is of type T (or if | |||||
| // strict is false, convertable to type T) and 0 otherwise. | |||||
| template <typename T> | |||||
| bool luaW_is(lua_State *L, int index, bool strict = false) | |||||
| { | |||||
| bool equal = false;// lua_isnil(L, index); | |||||
| if (!equal && lua_isuserdata(L, index) && lua_getmetatable(L, index)) | |||||
| { | |||||
| // ... ud ... udmt | |||||
| luaL_getmetatable(L, LuaWrapper<T>::classname); // ... ud ... udmt Tmt | |||||
| equal = lua_rawequal(L, -1, -2) != 0; | |||||
| if (!equal && !strict) | |||||
| { | |||||
| lua_getfield(L, -2, LUAW_EXTENDS_KEY); // ... ud ... udmt Tmt udmt.extends | |||||
| for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) | |||||
| { | |||||
| // ... ud ... udmt Tmt udmt.extends k v | |||||
| equal = lua_rawequal(L, -1, -4) != 0; | |||||
| if (equal) | |||||
| { | |||||
| lua_pop(L, 2); // ... ud ... udmt Tmt udmt.extends | |||||
| break; | |||||
| } | |||||
| } | |||||
| lua_pop(L, 1); // ... ud ... udmt Tmt | |||||
| } | |||||
| lua_pop(L, 2); // ... ud ... | |||||
| } | |||||
| return equal; | |||||
| } | |||||
| // Analogous to lua_to(boolean|string|*) | |||||
| // | |||||
| // Converts the given acceptable index to a T*. That value must be of (or | |||||
| // convertable to) type T; otherwise, returns NULL. | |||||
| template <typename T> | |||||
| T* luaW_to(lua_State* L, int index, bool strict = false) | |||||
| { | |||||
| if (luaW_is<T>(L, index, strict)) | |||||
| { | |||||
| luaW_Userdata* pud = static_cast<luaW_Userdata*>(lua_touserdata(L, index)); | |||||
| luaW_Userdata ud; | |||||
| while (!strict && LuaWrapper<T>::cast != pud->cast) | |||||
| { | |||||
| ud = pud->cast(*pud); | |||||
| pud = &ud; | |||||
| } | |||||
| return static_cast<T*>(pud->data); | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| // Analogous to luaL_check(boolean|string|*) | |||||
| // | |||||
| // Converts the given acceptable index to a T*. That value must be of (or | |||||
| // convertable to) type T; otherwise, an error is raised. | |||||
| template <typename T> | |||||
| T* luaW_check(lua_State* L, int index, bool strict = false) | |||||
| { | |||||
| T* obj = NULL; | |||||
| if (luaW_is<T>(L, index, strict)) | |||||
| { | |||||
| luaW_Userdata* pud = static_cast<luaW_Userdata*>(lua_touserdata(L, index)); | |||||
| luaW_Userdata ud; | |||||
| while (!strict && LuaWrapper<T>::cast != pud->cast) | |||||
| { | |||||
| ud = pud->cast(*pud); | |||||
| pud = &ud; | |||||
| } | |||||
| obj = (T*)pud->data; | |||||
| } | |||||
| else | |||||
| { | |||||
| const char *msg = lua_pushfstring(L, "%s expected, got %s", LuaWrapper<T>::classname, luaL_typename(L, index)); | |||||
| luaL_argerror(L, index, msg); | |||||
| } | |||||
| return obj; | |||||
| } | |||||
| template <typename T> | |||||
| T* luaW_opt(lua_State* L, int index, T* fallback = NULL, bool strict = false) | |||||
| { | |||||
| if (lua_isnil(L, index)) | |||||
| { | |||||
| return fallback; | |||||
| } | |||||
| else | |||||
| { | |||||
| return luaW_check<T>(L, index, strict); | |||||
| } | |||||
| } | |||||
| // Analogous to lua_push(boolean|string|*) | |||||
| // | |||||
| // Pushes a userdata of type T onto the stack. If this object already exists in | |||||
| // the Lua environment, it will assign the existing storage table to it. | |||||
| // Otherwise, a new storage table will be created for it. | |||||
| template <typename T> | |||||
| void luaW_push(lua_State* L, T* obj) | |||||
| { | |||||
| if (obj) | |||||
| { | |||||
| LuaWrapper<T>::identifier(L, obj); // ... id | |||||
| luaW_wrapperfield<T>(L, LUAW_CACHE_KEY); // ... id cache | |||||
| lua_pushvalue(L, -2); // ... id cache id | |||||
| lua_gettable(L, -2); // ... id cache obj | |||||
| if (lua_isnil(L, -1)) | |||||
| { | |||||
| // Create the new luaW_userdata and place it in the cache | |||||
| lua_pop(L, 1); // ... id cache | |||||
| lua_insert(L, -2); // ... cache id | |||||
| luaW_Userdata* ud = static_cast<luaW_Userdata*>(lua_newuserdata(L, sizeof(luaW_Userdata))); // ... cache id obj | |||||
| ud->data = obj; | |||||
| ud->cast = LuaWrapper<T>::cast; | |||||
| lua_pushvalue(L, -1); // ... cache id obj obj | |||||
| lua_insert(L, -4); // ... obj cache id obj | |||||
| lua_settable(L, -3); // ... obj cache | |||||
| luaL_getmetatable(L, LuaWrapper<T>::classname); // ... obj cache mt | |||||
| lua_setmetatable(L, -3); // ... obj cache | |||||
| lua_pop(L, 1); // ... obj | |||||
| } | |||||
| else | |||||
| { | |||||
| lua_replace(L, -3); // ... obj cache | |||||
| lua_pop(L, 1); // ... obj | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| lua_pushnil(L); | |||||
| } | |||||
| } | |||||
| // Instructs LuaWrapper that it owns the userdata, and can manage its memory. | |||||
| // When all references to the object are removed, Lua is free to garbage | |||||
| // collect it and delete the object. | |||||
| // | |||||
| // Returns true if luaW_hold took hold of the object, and false if it was | |||||
| // already held | |||||
| template <typename T> | |||||
| bool luaW_hold(lua_State* L, T* obj) | |||||
| { | |||||
| luaW_wrapperfield<T>(L, LUAW_HOLDS_KEY); // ... holds | |||||
| LuaWrapper<T>::identifier(L, obj); // ... holds id | |||||
| lua_pushvalue(L, -1); // ... holds id id | |||||
| lua_gettable(L, -3); // ... holds id hold | |||||
| // If it's not held, hold it | |||||
| if (!lua_toboolean(L, -1)) | |||||
| { | |||||
| // Apply hold boolean | |||||
| lua_pop(L, 1); // ... holds id | |||||
| lua_pushboolean(L, true); // ... holds id true | |||||
| lua_settable(L, -3); // ... holds | |||||
| lua_pop(L, 1); // ... | |||||
| return true; | |||||
| } | |||||
| lua_pop(L, 3); // ... | |||||
| return false; | |||||
| } | |||||
| // Releases LuaWrapper's hold on an object. This allows the user to remove | |||||
| // all references to an object in Lua and ensure that Lua will not attempt to | |||||
| // garbage collect it. | |||||
| // | |||||
| // This function takes the index of the identifier for an object rather than | |||||
| // the object itself. This is because needs to be able to run after the object | |||||
| // has already been deallocated. A wrapper is provided for when it is more | |||||
| // convenient to pass in the object directly. | |||||
| template <typename T> | |||||
| void luaW_release(lua_State* L, int index) | |||||
| { | |||||
| luaW_wrapperfield<T>(L, LUAW_HOLDS_KEY); // ... id ... holds | |||||
| lua_pushvalue(L, luaW_correctindex(L, index, 1)); // ... id ... holds id | |||||
| lua_pushnil(L); // ... id ... holds id nil | |||||
| lua_settable(L, -3); // ... id ... holds | |||||
| lua_pop(L, 1); // ... id ... | |||||
| } | |||||
| template <typename T> | |||||
| void luaW_release(lua_State* L, T* obj) | |||||
| { | |||||
| LuaWrapper<T>::identifier(L, obj); // ... id | |||||
| luaW_release<T>(L, -1); // ... id | |||||
| lua_pop(L, 1); // ... | |||||
| } | |||||
| template <typename T> | |||||
| void luaW_postconstructorinternal(lua_State* L, int numargs) | |||||
| { | |||||
| // ... ud args... | |||||
| if (LuaWrapper<T>::postconstructorrecurse) | |||||
| { | |||||
| LuaWrapper<T>::postconstructorrecurse(L, numargs); | |||||
| } | |||||
| luaL_getmetatable(L, LuaWrapper<T>::classname); // ... ud args... mt | |||||
| lua_getfield(L, -1, LUAW_POSTCTOR_KEY); // ... ud args... mt postctor | |||||
| if (lua_type(L, -1) == LUA_TFUNCTION) | |||||
| { | |||||
| for (int i = 0; i < numargs + 1; i++) | |||||
| { | |||||
| lua_pushvalue(L, -3 - numargs); // ... ud args... mt postctor ud args... | |||||
| } | |||||
| lua_call(L, numargs + 1, 0); // ... ud args... mt | |||||
| lua_pop(L, 1); // ... ud args... | |||||
| } | |||||
| else | |||||
| { | |||||
| lua_pop(L, 2); // ... ud args... | |||||
| } | |||||
| } | |||||
| // This function is called from Lua, not C++ | |||||
| // | |||||
| // Calls the lua post-constructor (LUAW_POSTCTOR_KEY or "__postctor") on a | |||||
| // userdata. Assumes the userdata is on the stack and numargs arguments follow | |||||
| // it. This runs the LUAW_POSTCTOR_KEY function on T's metatable, using the | |||||
| // object as the first argument and whatever else is below it as the rest of the | |||||
| // arguments This exists to allow types to adjust values in thier storage table, | |||||
| // which can not be created until after the constructor is called. | |||||
| template <typename T> | |||||
| void luaW_postconstructor(lua_State* L, int numargs) | |||||
| { | |||||
| // ... ud args... | |||||
| luaW_postconstructorinternal<T>(L, numargs); // ... ud args... | |||||
| lua_pop(L, numargs); // ... ud | |||||
| } | |||||
| // This function is generally called from Lua, not C++ | |||||
| // | |||||
| // Creates an object of type T using the constructor and subsequently calls the | |||||
| // post-constructor on it. | |||||
| template <typename T> | |||||
| inline int luaW_new(lua_State* L, int numargs) | |||||
| { | |||||
| // ... args... | |||||
| T* obj = LuaWrapper<T>::allocator(L); | |||||
| luaW_push<T>(L, obj); // ... args... ud | |||||
| luaW_hold<T>(L, obj); | |||||
| lua_insert(L, -1 - numargs); // ... ud args... | |||||
| luaW_postconstructor<T>(L, numargs); // ... ud | |||||
| return 1; | |||||
| } | |||||
| template <typename T> | |||||
| int luaW_new(lua_State* L) | |||||
| { | |||||
| return luaW_new<T>(L, lua_gettop(L)); | |||||
| } | |||||
| // This function is called from Lua, not C++ | |||||
| // | |||||
| // The default metamethod to call when indexing into lua userdata representing | |||||
| // an object of type T. This will first check the userdata's environment table | |||||
| // and if it's not found there it will check the metatable. This is done so | |||||
| // individual userdata can be treated as a table, and can hold thier own | |||||
| // values. | |||||
| template <typename T> | |||||
| int luaW_index(lua_State* L) | |||||
| { | |||||
| // obj key | |||||
| T* obj = luaW_to<T>(L, 1); | |||||
| luaW_wrapperfield<T>(L, LUAW_STORAGE_KEY); // obj key storage | |||||
| LuaWrapper<T>::identifier(L, obj); // obj key storage id | |||||
| lua_gettable(L, -2); // obj key storage store | |||||
| // Check if storage table exists | |||||
| if (!lua_isnil(L, -1)) | |||||
| { | |||||
| lua_pushvalue(L, -3); // obj key storage store key | |||||
| lua_gettable(L, -2); // obj key storage store store[k] | |||||
| } | |||||
| // If either there is no storage table or the key wasn't found | |||||
| // then fall back to the metatable | |||||
| if (lua_isnil(L, -1)) | |||||
| { | |||||
| lua_settop(L, 2); // obj key | |||||
| lua_getmetatable(L, -2); // obj key mt | |||||
| lua_pushvalue(L, -2); // obj key mt k | |||||
| lua_gettable(L, -2); // obj key mt mt[k] | |||||
| } | |||||
| return 1; | |||||
| } | |||||
| // This function is called from Lua, not C++ | |||||
| // | |||||
| // The default metamethod to call when creating a new index on lua userdata | |||||
| // representing an object of type T. This will index into the the userdata's | |||||
| // environment table that it keeps for personal storage. This is done so | |||||
| // individual userdata can be treated as a table, and can hold thier own | |||||
| // values. | |||||
| template <typename T> | |||||
| int luaW_newindex(lua_State* L) | |||||
| { | |||||
| // obj key value | |||||
| T* obj = luaW_check<T>(L, 1); | |||||
| luaW_wrapperfield<T>(L, LUAW_STORAGE_KEY); // obj key value storage | |||||
| LuaWrapper<T>::identifier(L, obj); // obj key value storage id | |||||
| lua_pushvalue(L, -1); // obj key value storage id id | |||||
| lua_gettable(L, -3); // obj key value storage id store | |||||
| // Add the storage table if there isn't one already | |||||
| if (lua_isnil(L, -1)) | |||||
| { | |||||
| lua_pop(L, 1); // obj key value storage id | |||||
| lua_newtable(L); // obj key value storage id store | |||||
| lua_pushvalue(L, -1); // obj key value storage id store store | |||||
| lua_insert(L, -3); // obj key value storage store id store | |||||
| lua_settable(L, -4); // obj key value storage store | |||||
| } | |||||
| lua_pushvalue(L, 2); // obj key value ... store key | |||||
| lua_pushvalue(L, 3); // obj key value ... store key value | |||||
| lua_settable(L, -3); // obj key value ... store | |||||
| return 0; | |||||
| } | |||||
| // This function is called from Lua, not C++ | |||||
| // | |||||
| // The __gc metamethod handles cleaning up userdata. The userdata's reference | |||||
| // count is decremented and if this is the final reference to the userdata its | |||||
| // environment table is nil'd and pointer deleted with the destructor callback. | |||||
| template <typename T> | |||||
| int luaW_gc(lua_State* L) | |||||
| { | |||||
| // obj | |||||
| T* obj = luaW_to<T>(L, 1); | |||||
| LuaWrapper<T>::identifier(L, obj); // obj key value storage id | |||||
| luaW_wrapperfield<T>(L, LUAW_HOLDS_KEY); // obj id counts count holds | |||||
| lua_pushvalue(L, 2); // obj id counts count holds id | |||||
| lua_gettable(L, -2); // obj id counts count holds hold | |||||
| if (lua_toboolean(L, -1) && LuaWrapper<T>::deallocator) | |||||
| { | |||||
| LuaWrapper<T>::deallocator(L, obj); | |||||
| } | |||||
| luaW_wrapperfield<T>(L, LUAW_STORAGE_KEY); // obj id counts count holds hold storage | |||||
| lua_pushvalue(L, 2); // obj id counts count holds hold storage id | |||||
| lua_pushnil(L); // obj id counts count holds hold storage id nil | |||||
| lua_settable(L, -3); // obj id counts count holds hold storage | |||||
| luaW_release<T>(L, 2); | |||||
| return 0; | |||||
| } | |||||
| // Thakes two tables and registers them with Lua to the table on the top of the | |||||
| // stack. | |||||
| // | |||||
| // This function is only called from LuaWrapper internally. | |||||
| inline void luaW_registerfuncs(lua_State* L, const luaL_Reg defaulttable[], const luaL_Reg table[]) | |||||
| { | |||||
| // ... T | |||||
| #if LUA_VERSION_NUM == 502 | |||||
| if (defaulttable) | |||||
| luaL_setfuncs(L, defaulttable, 0); // ... T | |||||
| if (table) | |||||
| luaL_setfuncs(L, table, 0); // ... T | |||||
| #else | |||||
| if (defaulttable) | |||||
| luaL_register(L, NULL, defaulttable); // ... T | |||||
| if (table) | |||||
| luaL_register(L, NULL, table); // ... T | |||||
| #endif | |||||
| } | |||||
| // Initializes the LuaWrapper tables used to track internal state. | |||||
| // | |||||
| // This function is only called from LuaWrapper internally. | |||||
| inline void luaW_initialize(lua_State* L) | |||||
| { | |||||
| // Ensure that the LuaWrapper table is set up | |||||
| lua_getfield(L, LUA_REGISTRYINDEX, LUAW_WRAPPER_KEY); // ... LuaWrapper | |||||
| if (lua_isnil(L, -1)) | |||||
| { | |||||
| lua_newtable(L); // ... nil {} | |||||
| lua_pushvalue(L, -1); // ... nil {} {} | |||||
| lua_setfield(L, LUA_REGISTRYINDEX, LUAW_WRAPPER_KEY); // ... nil LuaWrapper | |||||
| // Create a storage table | |||||
| lua_newtable(L); // ... LuaWrapper nil {} | |||||
| lua_setfield(L, -2, LUAW_STORAGE_KEY); // ... nil LuaWrapper | |||||
| // Create a holds table | |||||
| lua_newtable(L); // ... LuaWrapper {} | |||||
| lua_setfield(L, -2, LUAW_HOLDS_KEY); // ... nil LuaWrapper | |||||
| // Create a cache table, with weak values so that the userdata will not | |||||
| // be ref counted | |||||
| lua_newtable(L); // ... nil LuaWrapper {} | |||||
| lua_setfield(L, -2, LUAW_CACHE_KEY); // ... nil LuaWrapper | |||||
| lua_newtable(L); // ... nil LuaWrapper {} | |||||
| lua_pushstring(L, "v"); // ... nil LuaWrapper {} "v" | |||||
| lua_setfield(L, -2, "__mode"); // ... nil LuaWrapper {} | |||||
| lua_setfield(L, -2, LUAW_CACHE_METATABLE_KEY); // ... nil LuaWrapper | |||||
| lua_pop(L, 1); // ... nil | |||||
| } | |||||
| lua_pop(L, 1); // ... | |||||
| } | |||||
| // Run luaW_register or luaW_setfuncs to create a table and metatable for your | |||||
| // class. These functions create a table with filled with the function from | |||||
| // the table argument in addition to the functions new and build (This is | |||||
| // generally for things you think of as static methods in C++). The given | |||||
| // metatable argument becomes a metatable for each object of your class. These | |||||
| // can be thought of as member functions or methods. | |||||
| // | |||||
| // You may also supply constructors and destructors for classes that do not | |||||
| // have a default constructor or that require special set up or tear down. You | |||||
| // may specify NULL as the constructor, which means that you will not be able | |||||
| // to call the new function on your class table. You will need to manually push | |||||
| // objects from C++. By default, the default constructor is used to create | |||||
| // objects and a simple call to delete is used to destroy them. | |||||
| // | |||||
| // By default LuaWrapper uses the address of C++ object to identify unique | |||||
| // objects. In some cases this is not desired, such as in the case of | |||||
| // shared_ptrs. Two shared_ptrs may themselves have unique locations in memory | |||||
| // but still represent the same object. For cases like that, you may specify an | |||||
| // identifier function which is responsible for pushing a key representing your | |||||
| // object on to the stack. | |||||
| // | |||||
| // luaW_register will set table as the new value of the global of the given | |||||
| // name. luaW_setfuncs is identical to luaW_register, but it does not set the | |||||
| // table globally. As with luaL_register and luaL_setfuncs, both funcstions | |||||
| // leave the new table on the top of the stack. | |||||
| template <typename T> | |||||
| void luaW_setfuncs(lua_State* L, const char* classname, const luaL_Reg* table, const luaL_Reg* metatable, T* (*allocator)(lua_State*) = luaW_defaultallocator<T>, void(*deallocator)(lua_State*, T*) = luaW_defaultdeallocator<T>, void(*identifier)(lua_State*, T*) = luaW_defaultidentifier<T>) | |||||
| { | |||||
| luaW_initialize(L); | |||||
| LuaWrapper<T>::classname = classname; | |||||
| LuaWrapper<T>::identifier = identifier; | |||||
| LuaWrapper<T>::allocator = allocator; | |||||
| LuaWrapper<T>::deallocator = deallocator; | |||||
| const luaL_Reg defaulttable[] = | |||||
| { | |||||
| { "new", luaW_new<T> }, | |||||
| { NULL, NULL } | |||||
| }; | |||||
| const luaL_Reg defaultmetatable[] = | |||||
| { | |||||
| { "__index", luaW_index<T> }, | |||||
| { "__newindex", luaW_newindex<T> }, | |||||
| { "__gc", luaW_gc<T> }, | |||||
| { NULL, NULL } | |||||
| }; | |||||
| // Set up per-type tables | |||||
| lua_getfield(L, LUA_REGISTRYINDEX, LUAW_WRAPPER_KEY); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_STORAGE_KEY); // ... LuaWrapper LuaWrapper.storage | |||||
| lua_newtable(L); // ... LuaWrapper LuaWrapper.storage {} | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.storage | |||||
| lua_pop(L, 1); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_HOLDS_KEY); // ... LuaWrapper LuaWrapper.holds | |||||
| lua_newtable(L); // ... LuaWrapper LuaWrapper.holds {} | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.holds | |||||
| lua_pop(L, 1); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_CACHE_KEY); // ... LuaWrapper LuaWrapper.cache | |||||
| lua_newtable(L); // ... LuaWrapper LuaWrapper.cache {} | |||||
| luaW_wrapperfield<T>(L, LUAW_CACHE_METATABLE_KEY); // ... LuaWrapper LuaWrapper.cache {} cmt | |||||
| lua_setmetatable(L, -2); // ... LuaWrapper LuaWrapper.cache {} | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.cache | |||||
| lua_pop(L, 2); // ... | |||||
| // Open table | |||||
| lua_newtable(L); // ... T | |||||
| luaW_registerfuncs(L, allocator ? defaulttable : NULL, table); // ... T | |||||
| // Open metatable, set up extends table | |||||
| luaL_newmetatable(L, classname); // ... T mt | |||||
| lua_newtable(L); // ... T mt {} | |||||
| lua_setfield(L, -2, LUAW_EXTENDS_KEY); // ... T mt | |||||
| luaW_registerfuncs(L, defaultmetatable, metatable); // ... T mt | |||||
| lua_setfield(L, -2, "metatable"); // ... T | |||||
| } | |||||
| template <typename T> | |||||
| void luaW_register(lua_State* L, const char* classname, const luaL_Reg* table, const luaL_Reg* metatable, T* (*allocator)(lua_State*) = luaW_defaultallocator<T>, void(*deallocator)(lua_State*, T*) = luaW_defaultdeallocator<T>, void(*identifier)(lua_State*, T*) = luaW_defaultidentifier<T>) | |||||
| { | |||||
| luaW_setfuncs(L, classname, table, metatable, allocator, deallocator, identifier); // ... T | |||||
| lua_pushvalue(L, -1); // ... T T | |||||
| lua_setglobal(L, classname); // ... T | |||||
| } | |||||
| // luaW_extend is used to declare that class T inherits from class U. All | |||||
| // functions in the base class will be available to the derived class (except | |||||
| // when they share a function name, in which case the derived class's function | |||||
| // wins). This also allows luaW_to<T> to cast your object apropriately, as | |||||
| // casts straight through a void pointer do not work. | |||||
| template <typename T, typename U> | |||||
| void luaW_extend(lua_State* L) | |||||
| { | |||||
| if (!LuaWrapper<T>::classname) | |||||
| luaL_error(L, "attempting to call extend on a type that has not been registered"); | |||||
| if (!LuaWrapper<U>::classname) | |||||
| luaL_error(L, "attempting to extend %s by a type that has not been registered", LuaWrapper<T>::classname); | |||||
| LuaWrapper<T>::cast = luaW_cast<T, U>; | |||||
| LuaWrapper<T>::identifier = luaW_identify<T, U>; | |||||
| LuaWrapper<T>::postconstructorrecurse = luaW_postconstructorinternal<U>; | |||||
| luaL_getmetatable(L, LuaWrapper<T>::classname); // mt | |||||
| luaL_getmetatable(L, LuaWrapper<U>::classname); // mt emt | |||||
| // Point T's metatable __index at U's metatable for inheritance | |||||
| lua_newtable(L); // mt emt {} | |||||
| lua_pushvalue(L, -2); // mt emt {} emt | |||||
| lua_setfield(L, -2, "__index"); // mt emt {} | |||||
| lua_setmetatable(L, -3); // mt emt | |||||
| // Set up per-type tables to point at parent type | |||||
| lua_getfield(L, LUA_REGISTRYINDEX, LUAW_WRAPPER_KEY); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_STORAGE_KEY); // ... LuaWrapper LuaWrapper.storage | |||||
| lua_getfield(L, -1, LuaWrapper<U>::classname); // ... LuaWrapper LuaWrapper.storage U | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.storage | |||||
| lua_pop(L, 1); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_HOLDS_KEY); // ... LuaWrapper LuaWrapper.holds | |||||
| lua_getfield(L, -1, LuaWrapper<U>::classname); // ... LuaWrapper LuaWrapper.holds U | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.holds | |||||
| lua_pop(L, 1); // ... LuaWrapper | |||||
| lua_getfield(L, -1, LUAW_CACHE_KEY); // ... LuaWrapper LuaWrapper.cache | |||||
| lua_getfield(L, -1, LuaWrapper<U>::classname); // ... LuaWrapper LuaWrapper.cache U | |||||
| lua_setfield(L, -2, LuaWrapper<T>::classname); // ... LuaWrapper LuaWrapper.cache | |||||
| lua_pop(L, 2); // ... | |||||
| // Make a list of all types that inherit from U, for type checking | |||||
| lua_getfield(L, -2, LUAW_EXTENDS_KEY); // mt emt mt.extends | |||||
| lua_pushvalue(L, -2); // mt emt mt.extends emt | |||||
| lua_setfield(L, -2, LuaWrapper<U>::classname); // mt emt mt.extends | |||||
| lua_getfield(L, -2, LUAW_EXTENDS_KEY); // mt emt mt.extends emt.extends | |||||
| for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) | |||||
| { | |||||
| // mt emt mt.extends emt.extends k v | |||||
| lua_pushvalue(L, -2); // mt emt mt.extends emt.extends k v k | |||||
| lua_pushvalue(L, -2); // mt emt mt.extends emt.extends k v k | |||||
| lua_rawset(L, -6); // mt emt mt.extends emt.extends k v | |||||
| } | |||||
| lua_pop(L, 4); // mt emt | |||||
| } | |||||
| /* | |||||
| * Copyright (c) 2010-2013 Alexander Ames | |||||
| * | |||||
| * Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
| * of this software and associated documentation files (the "Software"), to | |||||
| * deal in the Software without restriction, including without limitation the | |||||
| * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
| * sell copies of the Software, and to permit persons to whom the Software is | |||||
| * furnished to do so, subject to the following conditions: | |||||
| * | |||||
| * The above copyright notice and this permission notice shall be included in | |||||
| * all copies or substantial portions of the Software. | |||||
| * | |||||
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
| * FROM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||||
| * IN THE SOFTWARE. | |||||
| */ | |||||
| #endif // LUA_WRAPPER_H_ | |||||
| @@ -14,7 +14,7 @@ | |||||
| #include <cstdlib> | #include <cstdlib> | ||||
| #include <ctype.h> | #include <ctype.h> | ||||
| #include "lua/lua.hpp" | |||||
| //#include "lua/lua.hpp" | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -26,47 +26,6 @@ namespace lol | |||||
| class WorldData | class WorldData | ||||
| { | { | ||||
| friend class World; | friend class World; | ||||
| static int LuaPanic(lua_State* L) | |||||
| { | |||||
| char const *message = lua_tostring(L, -1); | |||||
| Log::Error("%s\n", message); | |||||
| DebugAbort(); | |||||
| return 0; | |||||
| } | |||||
| static int LuaDoFile(lua_State *L) | |||||
| { | |||||
| if (lua_isnoneornil(L, 1)) | |||||
| return LUA_ERRFILE; | |||||
| char const *filename = lua_tostring(L, 1); | |||||
| int status = LUA_ERRFILE; | |||||
| array<String> pathlist = System::GetPathList(filename); | |||||
| File f; | |||||
| for (int i = 0; i < pathlist.Count(); ++i) | |||||
| { | |||||
| f.Open(pathlist[i], FileAccess::Read); | |||||
| if (f.IsValid()) | |||||
| { | |||||
| String s = f.ReadString(); | |||||
| f.Close(); | |||||
| Log::Debug("loading Lua file %s\n", pathlist[i].C()); | |||||
| status = luaL_dostring(L, s.C()); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (status == LUA_ERRFILE) | |||||
| Log::Error("could not find Lua file %s\n", filename); | |||||
| lua_pop(L, 1); | |||||
| return status; | |||||
| } | |||||
| lua_State *m_lua_state; | lua_State *m_lua_state; | ||||
| }; | }; | ||||
| @@ -77,37 +36,23 @@ World g_world; | |||||
| * Public World class | * Public World class | ||||
| */ | */ | ||||
| const luaL_Reg test1Lua::m_statics[] = { { "getTest", getTest }, { NULL, NULL } }; | |||||
| const luaL_Reg test1Lua::m_methods[] = { { NULL, NULL } }; | |||||
| const char test1Lua::m_class[] = "test1"; | |||||
| World::World() | World::World() | ||||
| : LuaLoader() | |||||
| { | { | ||||
| /* Initialise the Lua engine */ | |||||
| g_world_data.m_lua_state = luaL_newstate(); | |||||
| lua_atpanic(g_world_data.m_lua_state, WorldData::LuaPanic); | |||||
| luaL_openlibs(g_world_data.m_lua_state); | |||||
| g_world_data.m_lua_state = GetLuaState(); | |||||
| //m_test1.LoadTo(GetLuaState()); | |||||
| //luaL_loadfile(GetLuaState(), "lua/init.lua"); | |||||
| //LuaVar<int32_t> var(GetLuaState(), 1); | |||||
| //test1Lua::Library m_test1(GetLuaState()); | |||||
| /* Override dofile() */ | |||||
| lua_pushcfunction(g_world_data.m_lua_state, WorldData::LuaDoFile); | |||||
| lua_setglobal(g_world_data.m_lua_state, "dofile"); | |||||
| } | } | ||||
| World::~World() | World::~World() | ||||
| { | { | ||||
| lua_close(g_world_data.m_lua_state); | |||||
| } | |||||
| bool World::ExecLua(String const &lua) | |||||
| { | |||||
| lua_pushstring(g_world_data.m_lua_state, lua.C()); | |||||
| int status = WorldData::LuaDoFile(g_world_data.m_lua_state); | |||||
| return status == 0; | |||||
| } | |||||
| double World::GetLuaNumber(String const &var) | |||||
| { | |||||
| double ret; | |||||
| lua_getglobal(g_world_data.m_lua_state, var.C()); | |||||
| ret = lua_tonumber(g_world_data.m_lua_state, -1); | |||||
| lua_pop(g_world_data.m_lua_state, 1); | |||||
| return ret; | |||||
| } | } | ||||
| } /* namespace lol */ | } /* namespace lol */ | ||||
| @@ -18,15 +18,51 @@ | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| class World | |||||
| class test1 | |||||
| { | { | ||||
| public: | public: | ||||
| bool ExecLua(String const &lua); | |||||
| double GetLuaNumber(String const &var); | |||||
| test1() {} | |||||
| static int getTest(int i1, String s2) | |||||
| { | |||||
| return -1; | |||||
| } | |||||
| }; | |||||
| class test1Lua : public LuaObject | |||||
| { | |||||
| public: | |||||
| test1Lua() | |||||
| { | |||||
| } | |||||
| static test1* New(lua_State* L) | |||||
| { | |||||
| return new test1(); | |||||
| } | |||||
| private: | |||||
| static const luaL_Reg m_statics[]; | |||||
| static const luaL_Reg m_methods[]; | |||||
| static const char m_class[]; | |||||
| public: | |||||
| typedef LuaLibrary<test1, m_class, m_statics, m_methods, test1Lua::New> Library; | |||||
| }; | |||||
| static int getTest(lua_State* L) | |||||
| { | |||||
| LuaVar<int> i1(L, 1); | |||||
| LuaVar<String> s2(L, 2); | |||||
| LuaVar<int64_t> res = (int64_t)test1::getTest(i1.V(), s2.V()); | |||||
| return res.Return(L); | |||||
| } | |||||
| //private: | |||||
| class World : public LuaLoader | |||||
| { | |||||
| public: | |||||
| World(); | World(); | ||||
| ~World(); | |||||
| virtual ~World(); | |||||
| protected: | |||||
| test1Lua::Library m_test1; | |||||
| }; | }; | ||||
| extern World g_world; | extern World g_world; | ||||