@@ -1,7 +1,7 @@ | |||||
| | ||||
Microsoft Visual Studio Solution File, Format Version 12.00 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
# Visual Studio 2013 | # Visual Studio 2013 | ||||
VisualStudioVersion = 12.0.31101.0 | |||||
VisualStudioVersion = 12.0.21005.1 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deushax", "..\games\deushax\deushax.vcxproj", "{EF1A4E80-63FA-4EB0-B834-12B6C500F31C}" | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "deushax", "..\games\deushax\deushax.vcxproj", "{EF1A4E80-63FA-4EB0-B834-12B6C500F31C}" | ||||
EndProject | EndProject | ||||
@@ -153,6 +153,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Doc", "Doc", "{65FD48E9-C93 | |||||
EndProject | EndProject | ||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "..\people\touky\shared\shared.vcxproj", "{EE203B88-44CF-4859-9D42-7A4F43FEDB52}" | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shared", "..\people\touky\shared\shared.vcxproj", "{EE203B88-44CF-4859-9D42-7A4F43FEDB52}" | ||||
EndProject | EndProject | ||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14_lol_lua", "..\doc\tutorial\14_lol_lua.vcxproj", "{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}" | |||||
EndProject | |||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
Debug|ORBIS = Debug|ORBIS | Debug|ORBIS = Debug|ORBIS | ||||
@@ -626,6 +628,16 @@ Global | |||||
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|Win32.Build.0 = Release|Win32 | {EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|Win32.Build.0 = Release|Win32 | ||||
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.ActiveCfg = Release|x64 | {EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.ActiveCfg = Release|x64 | ||||
{EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.Build.0 = Release|x64 | {EE203B88-44CF-4859-9D42-7A4F43FEDB52}.Release|x64.Build.0 = Release|x64 | ||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|ORBIS.ActiveCfg = Debug|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|Win32.ActiveCfg = Debug|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|Win32.Build.0 = Debug|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|x64.ActiveCfg = Debug|x64 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Debug|x64.Build.0 = Debug|x64 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|ORBIS.ActiveCfg = Release|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.ActiveCfg = Release|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|Win32.Build.0 = Release|Win32 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.ActiveCfg = Release|x64 | |||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}.Release|x64.Build.0 = Release|x64 | |||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(SolutionProperties) = preSolution | GlobalSection(SolutionProperties) = preSolution | ||||
HideSolutionNode = FALSE | HideSolutionNode = FALSE | ||||
@@ -667,6 +679,7 @@ Global | |||||
{572E5B9C-7E19-489C-BD8A-E8401CFBBC47} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | {572E5B9C-7E19-489C-BD8A-E8401CFBBC47} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | ||||
{E05E23A5-67DE-42B5-98A3-E63CCE0CC0AF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | {E05E23A5-67DE-42B5-98A3-E63CCE0CC0AF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | ||||
{F59FA82C-DDB9-4EE2-80AE-CB0E4C6567A4} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | {F59FA82C-DDB9-4EE2-80AE-CB0E4C6567A4} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | ||||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||||
{32F3F8CF-D22E-45E4-BEB8-AD909E8C5515} = {33704AA4-F2B5-4138-A40D-E3E77F89ED46} | {32F3F8CF-D22E-45E4-BEB8-AD909E8C5515} = {33704AA4-F2B5-4138-A40D-E3E77F89ED46} | ||||
{EE203B88-44CF-4859-9D42-7A5F40FECB52} = {8C77EAA8-1077-4EF7-AE53-97C6C60A3601} | {EE203B88-44CF-4859-9D42-7A5F40FECB52} = {8C77EAA8-1077-4EF7-AE53-97C6C60A3601} | ||||
{B357514A-7881-422D-8358-161B689E7620} = {3D341D8A-E400-4B1D-BC05-B5C35487D9B5} | {B357514A-7881-422D-8358-161B689E7620} = {3D341D8A-E400-4B1D-BC05-B5C35487D9B5} | ||||
@@ -0,0 +1,290 @@ | |||||
// | |||||
// Lol Engine - Graphing tutorial | |||||
// | |||||
// Copyright: (c) 2012-2013 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; 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 Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// | |||||
#if HAVE_CONFIG_H | |||||
# include "config.h" | |||||
#endif | |||||
#include <lol/engine.h> | |||||
#include "loldebug.h" | |||||
#include <cstdio> | |||||
using namespace lol; | |||||
//----------------------------------------------------------------------------- | |||||
class FooTest | |||||
{ | |||||
public: | |||||
FooTest() | |||||
{ | |||||
} | |||||
static int New(Lolua::State* l) | |||||
{ | |||||
int n_args = lua_gettop(l); // Number of arguments | |||||
// We could actually allocate Foo itself as a user data but | |||||
// since user data can be GC'ed and we gain unity by using CRT's heap | |||||
// all along. | |||||
FooTest** udata = (FooTest**)lua_newuserdata(l, sizeof(FooTest*)); | |||||
*udata = new FooTest(); | |||||
// Usually, we'll just use "Foo" as the second parameter, but I | |||||
// say luaL_Foo here to distinguish the difference: | |||||
// | |||||
// This 2nd parameter here is an _internal label_ for luaL, it is | |||||
// _not_ exposed to Lua by default. | |||||
// | |||||
// Effectively, this metatable is not accessible by Lua by default. | |||||
//luaL_getmetatable(l, m_table_name); | |||||
// The Lua stack at this point looks like this: | |||||
// | |||||
// 3| metatable "luaL_foo" |-1 | |||||
// 2| userdata |-2 | |||||
// 1| string parameter |-3 | |||||
// | |||||
// So the following line sets the metatable for the user data to the luaL_Foo | |||||
// metatable | |||||
// | |||||
// We must set the metatable here because Lua prohibits setting | |||||
// the metatable of a userdata in Lua. The only way to set a metatable | |||||
// of a userdata is to do it in C. | |||||
//lua_setmetatable(l, -2); | |||||
luaL_getmetatable(l, m_table2_name); | |||||
lua_setmetatable(l, -2); | |||||
// The Lua stack at this point looks like this: | |||||
// | |||||
// 2| userdata |-1 | |||||
// 1| string parameter |-2 | |||||
// | |||||
// We return 1 so Lua callsite will get the user data and | |||||
// Lua will clean the stack after that. | |||||
return 1; | |||||
} | |||||
static FooTest* Check(Lolua::State* l, int n) | |||||
{ | |||||
// This checks that the argument is a userdata | |||||
// with the metatable "luaL_Foo" | |||||
return *(FooTest**)luaL_testudata(l, n, m_table2_name); | |||||
} | |||||
static int Del(Lolua::State * l) | |||||
{ | |||||
FooTest* foo = Check(l, 1); | |||||
delete foo; | |||||
return 0; | |||||
} | |||||
static void Register(Lolua::State * l) | |||||
{ | |||||
// Create a luaL metatable. This metatable is not | |||||
// exposed to Lua. The "luaL_Foo" label is used by luaL | |||||
// internally to identity things. | |||||
luaL_newmetatable(l, m_table2_name); | |||||
luaL_setfuncs(l, FooTest::m_statics2, 0); | |||||
lua_pushvalue(l, -1); | |||||
lua_setfield(l, -1, "__index"); | |||||
//lua_setglobal(l, m_class2_name); | |||||
lua_pop(l, 1); | |||||
// Create a luaL metatable. This metatable is not | |||||
// exposed to Lua. The "luaL_Foo" label is used by luaL | |||||
// internally to identity things. | |||||
luaL_newmetatable(l, m_table_name); | |||||
// Register the C functions _into_ the metatable we just created. | |||||
luaL_setfuncs(l, FooTest::m_statics, 0); | |||||
// The Lua stack at this point looks like this: | |||||
// | |||||
// 1| metatable "luaL_Foo" |-1 | |||||
lua_pushvalue(l, -1); | |||||
// The Lua stack at this point looks like this: | |||||
// | |||||
// 2| metatable "luaL_Foo" |-1 | |||||
// 1| metatable "luaL_Foo" |-2 | |||||
// Set the "__index" field of the metatable to point to itself | |||||
// This pops the stack | |||||
lua_setfield(l, -1, "__index"); | |||||
// The Lua stack at this point looks like this: | |||||
// | |||||
// 1| metatable "luaL_Foo" |-1 | |||||
// The luaL_Foo metatable now has the following fields | |||||
// - __gc | |||||
// - __index | |||||
// - new | |||||
// Now we use setglobal to officially expose the luaL_Foo metatable | |||||
// to Lua. And we use the name "Foo". | |||||
// | |||||
// This allows Lua scripts to _override_ the metatable of Foo. | |||||
// For high security code this may not be called for but | |||||
// we'll do this to get greater flexibility. | |||||
lua_setglobal(l, m_class_name); | |||||
} | |||||
static int Test1(Lolua::State* L) | |||||
{ | |||||
Lolua::Var<int> i1(L, 1); | |||||
i1 += 5; | |||||
return i1.Return(L); | |||||
} | |||||
static int Test2(Lolua::State* L) | |||||
{ | |||||
FooTest* foo = Check(L, 1); | |||||
Lolua::Var<float> i1(L, 2); | |||||
i1 = foo->Test2Inst(i1.V()); | |||||
return i1.Return(L); | |||||
} | |||||
float Test2Inst(float f) | |||||
{ | |||||
return (f + 10); | |||||
} | |||||
static const char m_class_name[]; | |||||
static const char m_class2_name[]; | |||||
static const char m_table_name[]; | |||||
static const char m_table2_name[]; | |||||
static const luaL_Reg m_statics[]; | |||||
static const luaL_Reg m_statics2[]; | |||||
static const luaL_Reg m_methods[]; | |||||
}; | |||||
const luaL_Reg FooTest::m_statics[] = { | |||||
{ "New", &FooTest::New }, | |||||
{ "__gc", &FooTest::Del }, | |||||
{ "Test1", &FooTest::Test1 }, | |||||
{ NULL, NULL } }; | |||||
const luaL_Reg FooTest::m_statics2[] = { | |||||
{ "Test2", &FooTest::Test2 }, | |||||
{ NULL, NULL } }; | |||||
const luaL_Reg FooTest::m_methods[] = { { NULL, NULL } }; | |||||
const char FooTest::m_class_name[] = "FooTest"; | |||||
const char FooTest::m_class2_name[] = "FooTest2"; | |||||
const char FooTest::m_table_name[] = "FooTest_mt"; | |||||
const char FooTest::m_table2_name[] = "FooTest_mt2"; | |||||
typedef Lolua::ObjectDef<FooTest> FooTestLuaBase; | |||||
class FooTestLua : public FooTestLuaBase | |||||
{ | |||||
public: | |||||
FooTestLua() : FooTestLuaBase() {} | |||||
virtual ~FooTestLua() {} | |||||
static FooTestLua* New(Lolua::State* l, int arg_nb) | |||||
{ | |||||
return new FooTestLua(); | |||||
} | |||||
static const char* GetClassName(); | |||||
static const char* GetClassLibName(); | |||||
static const char* GetClassInstName(); | |||||
static const Lolua::ClassMethod* GetStaticMethods(); | |||||
static const Lolua::ClassMethod* GetInstanceMethods(); | |||||
static int Test1(Lolua::State* L) | |||||
{ | |||||
Lolua::Var<int> i1(L, 1); | |||||
i1 += 5; | |||||
return i1.Return(L); | |||||
} | |||||
static int Test2(Lolua::State* L) | |||||
{ | |||||
Lolua::VarPtr<FooTestLua> foo(L, 1); | |||||
Lolua::Var<float> i1(L, 2); | |||||
i1 = foo.V()->Test2Inst(i1.V()); | |||||
return i1.Return(L); | |||||
} | |||||
float Test2Inst(float f) | |||||
{ | |||||
return (f + 10); | |||||
} | |||||
}; | |||||
static const Lolua::ClassMethod FooTest_statics[] = { { "Test1", &FooTestLua::Test1 }, { NULL, NULL } }; | |||||
const Lolua::ClassMethod FooTest_methods[] = { { "Test2", &FooTestLua::Test2 }, { NULL, NULL } }; | |||||
const char* FooTestLua::GetClassName() { static const char name[] = "FooTest"; return name; } | |||||
const char* FooTestLua::GetClassLibName() { static const char name[] = "FooTestLib"; return name; } | |||||
const char* FooTestLua::GetClassInstName() { static const char name[] = "FooTestInst"; return name; } | |||||
const Lolua::ClassMethod* FooTestLua::GetStaticMethods() { return FooTest_statics; } | |||||
const Lolua::ClassMethod* FooTestLua::GetInstanceMethods() { return FooTest_methods; } | |||||
//----------------------------------------------------------------------------- | |||||
class LoluaDemoLoader : public Lolua::Loader | |||||
{ | |||||
public: | |||||
LoluaDemoLoader() : Lolua::Loader() | |||||
{ | |||||
Lolua::State* l = GetLuaState(); | |||||
Lolua::Object::Register<FooTestLua>(l); | |||||
ExecLua("14_lol_lua.lua"); | |||||
} | |||||
virtual ~LoluaDemoLoader() | |||||
{ | |||||
} | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
class LoluaDemo : public WorldEntity | |||||
{ | |||||
public: | |||||
LoluaDemo() | |||||
{ | |||||
} | |||||
virtual void TickGame(float seconds) | |||||
{ | |||||
WorldEntity::TickGame(seconds); | |||||
LoluaDemoLoader* demo_loader = new LoluaDemoLoader(); | |||||
float TestValueNum = demo_loader->GetVar<float>("TestValueNum"); | |||||
int32_t TestValueInt = demo_loader->GetVar<int32_t>("TestValueInt"); | |||||
uint32_t TestValueUint = demo_loader->GetVar<uint32_t>("TestValueUint"); | |||||
String TestValueStr = demo_loader->GetVar<String>("TestValueStr"); | |||||
//String test_return2 = demo_loader->GetVar<String>("test_return2"); | |||||
//String test_return3 = demo_loader->GetVar<String>("test_return3"); | |||||
int32_t testtruc_return = demo_loader->GetVar<int32_t>("footest_return"); | |||||
float testtruc_return2 = demo_loader->GetVar<float>("footest_return2"); | |||||
//int32_t testtruc2_return = demo_loader->GetVar<int32_t>("testtruc_return2"); | |||||
String::Printf("Lua Vars: TestValueNum: %.2f, TestValueInt: %i, TestValueUint: %i, TestValueStr: %s.", | |||||
TestValueNum, TestValueInt, TestValueUint, TestValueStr); | |||||
delete demo_loader; | |||||
Ticker::Shutdown(); | |||||
} | |||||
virtual void TickDraw(float seconds, Scene &scene) | |||||
{ | |||||
WorldEntity::TickDraw(seconds, scene); | |||||
} | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
int main(int argc, char **argv) | |||||
{ | |||||
System::Init(argc, argv); | |||||
Application app("Tutorial 14: Lolua Demo", ivec2(800, 600), 60.0f); | |||||
new LoluaDemo(); | |||||
app.Run(); | |||||
return EXIT_SUCCESS; | |||||
} | |||||
@@ -0,0 +1,16 @@ | |||||
-- Number | |||||
TestValueNum = 900.0 | |||||
-- Integer | |||||
TestValueInt = -900 | |||||
-- Unsigned | |||||
TestValueUint = 900 | |||||
-- String | |||||
TestValueStr = "900" | |||||
footest_return = FooTest.Test1(1); | |||||
footest_inst = FooTest.New(1,2); | |||||
footest_return2 = footest_inst:Test2(2.0); | |||||
-- test_return3 = sTest2("bruttruc"); | |||||
-- testtruc_return2 = Testtruc.Test2(2); | |||||
-- test_return2 = Testtruc:Test2("brut"); | |||||
-- test_return = LoluaTestObj:getTest(1, "brut"); |
@@ -0,0 +1,76 @@ | |||||
<?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> | |||||
<ItemGroup> | |||||
<ProjectReference Include="$(SolutionDir)\..\src\lolcore.vcxproj"> | |||||
<Project>{9e62f2fe-3408-4eae-8238-fd84238ceeda}</Project> | |||||
</ProjectReference> | |||||
<ProjectReference Include="$(SolutionDir)\..\src\bullet\lolbullet.vcxproj"> | |||||
<Project>{83d3b207-c601-4025-8f41-01dedc354661}</Project> | |||||
</ProjectReference> | |||||
<ProjectReference Include="$(SolutionDir)\..\src\lua\lollua.vcxproj"> | |||||
<Project>{d84021ca-b233-4e0f-8a52-071b83bbccc4}</Project> | |||||
</ProjectReference> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<ClCompile Include="14_lol_lua.cpp" /> | |||||
</ItemGroup> | |||||
<ItemGroup> | |||||
<None Include="14_lol_lua.lua"> | |||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild> | |||||
</None> | |||||
</ItemGroup> | |||||
<PropertyGroup Label="Globals"> | |||||
<ProjectGuid>{81C83B42-D00A-4FA3-9A3D-80F9D46524BF}</ProjectGuid> | |||||
<ConfigurationType>Application</ConfigurationType> | |||||
<Keyword>Win32Proj</Keyword> | |||||
</PropertyGroup> | |||||
<Import Project="$(SolutionDir)\msbuild\lol.config.props" /> | |||||
<ImportGroup Label="ExtensionSettings"> | |||||
<Import Project="$(SolutionDir)\msbuild\lolfx.props" /> | |||||
</ImportGroup> | |||||
<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 /> | |||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||||
<ImportGroup Label="ExtensionTargets"> | |||||
<Import Project="$(SolutionDir)\msbuild\lolfx.targets" /> | |||||
</ImportGroup> | |||||
</Project> |
@@ -3,7 +3,7 @@ include $(top_srcdir)/build/autotools/common.am | |||||
noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ | noinst_PROGRAMS = 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ | ||||
06_sprite 07_input 08_fbo 11_fractal \ | 06_sprite 07_input 08_fbo 11_fractal \ | ||||
12_voronoi 13_shader_builder | |||||
12_voronoi 13_shader_builder 14_lol_lua | |||||
01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | 01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | ||||
01_triangle_CPPFLAGS = $(AM_CPPFLAGS) | 01_triangle_CPPFLAGS = $(AM_CPPFLAGS) | ||||
@@ -55,3 +55,7 @@ endif | |||||
13_shader_builder_CPPFLAGS = $(AM_CPPFLAGS) | 13_shader_builder_CPPFLAGS = $(AM_CPPFLAGS) | ||||
13_shader_builder_DEPENDENCIES = @LOL_DEPS@ | 13_shader_builder_DEPENDENCIES = @LOL_DEPS@ | ||||
14_lol_lua_SOURCES = 14_lol_lua.cpp | |||||
14_lol_lua_CPPFLAGS = $(AM_CPPFLAGS) | |||||
14_lol_lua_DEPENDENCIES = @LOL_DEPS@ | |||||
@@ -23,9 +23,9 @@ namespace lol | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
class LuaBaseData | class LuaBaseData | ||||
{ | { | ||||
friend class LuaLoader; | |||||
friend class Lolua::Loader; | |||||
static int LuaPanic(lua_State* L) | |||||
static int LuaPanic(Lolua::State* L) | |||||
{ | { | ||||
char const *message = lua_tostring(L, -1); | char const *message = lua_tostring(L, -1); | ||||
Log::Error("%s\n", message); | Log::Error("%s\n", message); | ||||
@@ -33,12 +33,12 @@ class LuaBaseData | |||||
return 0; | return 0; | ||||
} | } | ||||
static int LuaDoFile(lua_State *L) | |||||
static int LuaDoFile(Lolua::State *L) | |||||
{ | { | ||||
if (lua_isnoneornil(L, 1)) | if (lua_isnoneornil(L, 1)) | ||||
return LUA_ERRFILE; | return LUA_ERRFILE; | ||||
LuaVar<char const*> var(L, 1); | |||||
Lolua::Var<char const*> var(L, 1); | |||||
char const *filename = var.V();// lua_tostring(L, 1); | char const *filename = var.V();// lua_tostring(L, 1); | ||||
int status = LUA_ERRFILE; | int status = LUA_ERRFILE; | ||||
@@ -67,25 +67,28 @@ class LuaBaseData | |||||
} | } | ||||
}; | }; | ||||
namespace Lolua | |||||
{ | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
LuaLoader::LuaLoader() | |||||
Loader::Loader() | |||||
{ | { | ||||
m_lua_state = luaL_newstate(); | m_lua_state = luaL_newstate(); | ||||
lua_atpanic(m_lua_state, LuaBaseData::LuaPanic); | lua_atpanic(m_lua_state, LuaBaseData::LuaPanic); | ||||
luaL_openlibs(m_lua_state); | luaL_openlibs(m_lua_state); | ||||
/* Override dofile() */ | /* Override dofile() */ | ||||
LuaFunction do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile); | |||||
Lolua::Function do_file(m_lua_state, "dofile", LuaBaseData::LuaDoFile); | |||||
} | } | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
LuaLoader::~LuaLoader() | |||||
Loader::~Loader() | |||||
{ | { | ||||
lua_close(m_lua_state); | lua_close(m_lua_state); | ||||
} | } | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
bool LuaLoader::ExecLua(String const &lua) | |||||
bool Loader::ExecLua(String const &lua) | |||||
{ | { | ||||
const char* c = lua_pushstring(m_lua_state, lua.C()); | const char* c = lua_pushstring(m_lua_state, lua.C()); | ||||
int status = LuaBaseData::LuaDoFile(m_lua_state); | int status = LuaBaseData::LuaDoFile(m_lua_state); | ||||
@@ -93,10 +96,12 @@ bool LuaLoader::ExecLua(String const &lua) | |||||
} | } | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
lua_State* LuaLoader::GetLuaState() | |||||
Lolua::State* Loader::GetLuaState() | |||||
{ | { | ||||
return m_lua_state; | return m_lua_state; | ||||
} | } | ||||
} /* namespace Lolua */ | |||||
} /* namespace lol */ | } /* namespace lol */ | ||||
@@ -12,42 +12,137 @@ | |||||
// | // | ||||
#include "lua/lua.hpp" | #include "lua/lua.hpp" | ||||
#include "lua/luawrapper.hpp" | |||||
//#include "lua/luawrapper.hpp" | |||||
#pragma once | #pragma once | ||||
namespace lol | namespace lol | ||||
{ | { | ||||
//----------------------------------------------------------------------------- | |||||
namespace Lolua | |||||
{ | |||||
//----------------------------------------------------------------------------- | |||||
typedef luaL_Reg ClassMethod; | |||||
typedef lua_State State; | |||||
//----------------------------------------------------------------------------- | |||||
template <typename T> | |||||
class ObjectDef | |||||
{ | |||||
public: | |||||
ObjectDef() { } | |||||
virtual ~ObjectDef() { } | |||||
static ObjectDef<T>* New(State* l, int arg_nb) | |||||
{ | |||||
UNUSED(l); | |||||
UNUSED(arg_nb); | |||||
ASSERT(false); | |||||
return nullptr; | |||||
} | |||||
static const char* GetClassName() { ASSERT(false); return nullptr; } | |||||
static const char* GetClassLibName() { ASSERT(false); return nullptr;; } | |||||
static const char* GetClassInstName() { ASSERT(false); return nullptr; } | |||||
static const ClassMethod* GetStaticMethods() { ASSERT(false); return nullptr; } | |||||
static const ClassMethod* GetInstanceMethods() { ASSERT(false); return nullptr; } | |||||
protected: | |||||
T* m_instance = nullptr; | |||||
}; | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
// Class available to link C++ class to Lua methods | // Class available to link C++ class to Lua methods | ||||
//-- | //-- | ||||
class LuaObject | |||||
class Object | |||||
{ | { | ||||
protected: | |||||
template<typename T, const char* name, const luaL_Reg* statics, const luaL_Reg* methods, T* (*ctor)(lua_State*)> | |||||
struct LuaLibrary | |||||
public: | |||||
//------------------------------------------------------------------------- | |||||
Object() { } | |||||
virtual ~Object() { } | |||||
//------------------------------------------------------------------------- | |||||
template <typename TLuaClass> | |||||
static void Register(State *l) | |||||
{ | { | ||||
LuaLibrary() { } | |||||
void LoadTo(lua_State* l) | |||||
//Default statics | |||||
static const luaL_Reg default_statics[] | |||||
{ | { | ||||
#define LOLUA_WRAPPER 1 | |||||
#if LOLUA_WRAPPER | |||||
luaW_register<T>(l, name, statics, methods, ctor); | |||||
#else | |||||
luaL_newlib(L, statics); | |||||
luaL_newlib(L, methods); | |||||
#endif | |||||
} | |||||
}; | |||||
{ "New", New<TLuaClass> }, | |||||
{ "__gc", Del<TLuaClass> }, | |||||
{ NULL, NULL } | |||||
}; | |||||
//TODO: Touky: Implement that | |||||
//__tostring : ToString | |||||
//__add : Addition(+) | |||||
//__sub : Subtraction(-) | |||||
//__mul : Multiplication(*) | |||||
//__div : Division(/ ) | |||||
//__mod : Modulos(%) | |||||
//__unm : Unary - , used for negation on numbers | |||||
//__concat : Concatenation(..) | |||||
//__eq : Equality(== ) | |||||
//__lt : Less than(<) | |||||
//__le : Less than or equal to(<= ) | |||||
//Create Static metatable | |||||
luaL_newmetatable(l, TLuaClass::GetClassLibName()); | |||||
//Register default statics and template one | |||||
luaL_setfuncs(l, default_statics, 0); | |||||
luaL_setfuncs(l, TLuaClass::GetStaticMethods(), 0); | |||||
//Push funcs on metatable | |||||
lua_pushvalue(l, -1); | |||||
//Set the "__index" field of the metatable to point to itself, pops the stack | |||||
lua_setfield(l, -1, "__index"); | |||||
//Set it global to validate the operation | |||||
lua_setglobal(l, TLuaClass::GetClassName()); | |||||
//Repeat all the operations for instance metatable | |||||
luaL_newmetatable(l, TLuaClass::GetClassInstName()); | |||||
luaL_setfuncs(l, TLuaClass::GetInstanceMethods(), 0); | |||||
lua_pushvalue(l, -1); | |||||
lua_setfield(l, -1, "__index"); | |||||
//Don't set it to global, but pop the stack to hide the metatable | |||||
lua_pop(l, 1); | |||||
} | |||||
protected: | |||||
//------------------------------------------------------------------------- | |||||
template <typename TLuaClass> | |||||
static int New(State* l) | |||||
{ | |||||
//Number of arguments | |||||
int n_args = lua_gettop(l); | |||||
//Create user data | |||||
TLuaClass** data = (TLuaClass**)lua_newuserdata(l, sizeof(TLuaClass*)); | |||||
*data = TLuaClass::New(l, n_args); | |||||
//Retrieve instance table | |||||
luaL_getmetatable(l, TLuaClass::GetClassInstName()); | |||||
//Set metatable to instance | |||||
lua_setmetatable(l, -2); | |||||
//Return 1 so Lua will get the UserData and clean the stack. | |||||
return 1; | |||||
} | |||||
//------------------------------------------------------------------------- | |||||
template <typename TLuaClass> | |||||
static int Del(State * l) | |||||
{ | |||||
VarPtr<TLuaClass> obj(l, 1); | |||||
ASSERT(obj.V()); | |||||
delete obj.V(); | |||||
return 0; | |||||
} | |||||
}; | }; | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
// | // | ||||
//-- | //-- | ||||
struct LuaFunction | |||||
struct Function | |||||
{ | { | ||||
LuaFunction(lua_State* l, const char* name, int (*function)(lua_State*)) | |||||
Function(State* l, const char* name, int(*function)(State*)) | |||||
{ | { | ||||
lua_pushcfunction(l, function); | lua_pushcfunction(l, function); | ||||
lua_setglobal(l, name); | lua_setglobal(l, name); | ||||
@@ -56,67 +151,113 @@ struct LuaFunction | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
template<typename T> | template<typename T> | ||||
struct LuaVar | |||||
struct VarPtr | |||||
{ | { | ||||
private: | |||||
T m_value = T(0); | |||||
protected: | |||||
T* m_value = nullptr; | |||||
public: | 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; } | |||||
VarPtr() { } | |||||
VarPtr(T* value) { m_value = value; } | |||||
VarPtr(State* l, int index) { InnerGet(l, index); } | |||||
inline T* V() { return m_value; } | |||||
inline T* operator=(T* value) { m_value = value; } | |||||
inline int Return(State* l) { InnerPush(l); return 1; } | |||||
private: | |||||
void InnerGet(lua_State* l, int index) { ASSERT(false); } | |||||
void InnerPush(lua_State* l) { ASSERT(false); } | |||||
protected: | |||||
virtual void InnerGet(State* l, int index) | |||||
{ | |||||
T** obj = static_cast<T**>(luaL_checkudata(l, index, T::GetClassInstName())); | |||||
m_value = obj ? *obj : nullptr; | |||||
} | |||||
void InnerPush(State* l) | |||||
{ | |||||
T** data = (T**)lua_newuserdata(l, sizeof(T*)); | |||||
*data = m_value; | |||||
} | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
template<typename T> | |||||
struct VarPtrLight | |||||
{ | |||||
public: | |||||
VarPtrLight() : VarPtr() { } | |||||
VarPtrLight(T* value) : VarPtr(T* value) { } | |||||
VarPtrLight(State* l, int index) : VarPtr(State* l, int index) { } | |||||
protected: | |||||
virtual void InnerGet(State* l, int index) | |||||
{ | |||||
T** obj = static_cast<T**>(luaL_testudata(l, index, T::GetClassInstName())); | |||||
m_value = obj ? *obj : nullptr; | |||||
} | |||||
}; | }; | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
template<typename T> | template<typename T> | ||||
struct LuaPtr | |||||
struct Var | |||||
{ | { | ||||
private: | private: | ||||
T* m_value = nullptr; | |||||
T m_value; | |||||
public: | 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; } | |||||
Var() { InnerInit(); } | |||||
Var(T value) { m_value = value; } | |||||
Var(State* l, int index) { InnerGet(l, index); } | |||||
inline T& V() { return m_value; } | |||||
inline int Return(State* l) { InnerPush(l); return 1; } | |||||
inline Var<T>& operator-(const T& value) { m_value - value; return *this; } | |||||
inline Var<T>& operator+(const T& value) { m_value + value; return *this; } | |||||
inline Var<T>& operator*(const T& value) { m_value * value; return *this; } | |||||
inline Var<T>& operator/(const T& value) { m_value / value; return *this; } | |||||
inline Var<T>& operator=(const T& value) { m_value = value; return *this; } | |||||
inline Var<T>& operator-=(const T& value) { m_value -= value; return *this; } | |||||
inline Var<T>& operator+=(const T& value) { m_value += value; return *this; } | |||||
inline Var<T>& operator*=(const T& value) { m_value *= value; return *this; } | |||||
inline Var<T>& operator/=(const T& value) { m_value /= value; return *this; } | |||||
inline Var<T>& operator-(const Var<T>& o) { m_value - o.m_value; return *this; } | |||||
inline Var<T>& operator+(const Var<T>& o) { m_value + o.m_value; return *this; } | |||||
inline Var<T>& operator*(const Var<T>& o) { m_value * o.m_value; return *this; } | |||||
inline Var<T>& operator/(const Var<T>& o) { m_value / o.m_value; return *this; } | |||||
inline Var<T>& operator=(const Var<T>& o) { m_value = o.m_value; return *this; } | |||||
inline Var<T>& operator-=(const Var<T>& o) { m_value -= o.m_value; return *this; } | |||||
inline Var<T>& operator+=(const Var<T>& o) { m_value += o.m_value; return *this; } | |||||
inline Var<T>& operator*=(const Var<T>& o) { m_value *= o.m_value; return *this; } | |||||
inline Var<T>& operator/=(const Var<T>& o) { m_value /= o.m_value; return *this; } | |||||
inline bool operator==(const T& value) { return m_value == value; } | |||||
inline bool operator!=(const T& value) { return m_value != value; } | |||||
inline bool operator==(const Var<T>& o) { return m_value == o.m_value; } | |||||
inline bool operator!=(const Var<T>& o) { return m_value != o.m_value; } | |||||
private: | 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); } | |||||
void InnerInit() { m_value = T(0); } | |||||
void InnerGet(State* l, int index) { ASSERT(false); } | |||||
void InnerPush(State* l) { ASSERT(false); } | |||||
}; | }; | ||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
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); } | |||||
template<> inline void Var<String> ::InnerInit() { m_value = String(); } | |||||
template<> inline void Var<String> ::InnerGet(State* l, int index) { m_value = lua_tostring(l, index); } | |||||
template<> inline void Var<char const*>::InnerGet(State* l, int index) { m_value = lua_tostring(l, index); } | |||||
template<> inline void Var<double> ::InnerGet(State* l, int index) { m_value = lua_tonumber(l, index); } | |||||
template<> inline void Var<float> ::InnerGet(State* l, int index) { m_value = (float)lua_tonumber(l, index); } | |||||
template<> inline void Var<int32_t> ::InnerGet(State* l, int index) { m_value = (int32_t)lua_tointeger(l, index); } | |||||
template<> inline void Var<int64_t> ::InnerGet(State* l, int index) { m_value = lua_tointeger(l, index); } | |||||
template<> inline void Var<uint32_t> ::InnerGet(State* l, int index) { m_value = lua_tounsigned(l, index); } | |||||
template<> inline void Var<String> ::InnerPush(State* l) { lua_pushstring(l, m_value.C()); } | |||||
template<> inline void Var<char const*>::InnerPush(State* l) { lua_pushstring(l, m_value); } | |||||
template<> inline void Var<double> ::InnerPush(State* l) { lua_pushnumber(l, m_value); } | |||||
template<> inline void Var<float> ::InnerPush(State* l) { lua_pushnumber(l, m_value); } | |||||
template<> inline void Var<int32_t> ::InnerPush(State* l) { lua_pushinteger(l, m_value); } | |||||
template<> inline void Var<int64_t> ::InnerPush(State* l) { lua_pushinteger(l, m_value); } | |||||
template<> inline void Var<uint32_t> ::InnerPush(State* l) { lua_pushunsigned(l, m_value); } | |||||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||
class LuaLoader | |||||
class Loader | |||||
{ | { | ||||
public: | public: | ||||
LuaLoader(); | |||||
virtual ~LuaLoader(); | |||||
Loader(); | |||||
virtual ~Loader(); | |||||
bool ExecLua(String const &lua); | bool ExecLua(String const &lua); | ||||
@@ -124,7 +265,7 @@ public: | |||||
T GetVar(String const &name) | T GetVar(String const &name) | ||||
{ | { | ||||
lua_getglobal(m_lua_state, name.C()); | lua_getglobal(m_lua_state, name.C()); | ||||
LuaVar<T> var(m_lua_state, -1); | |||||
Var<T> var(m_lua_state, -1); | |||||
lua_pop(m_lua_state, 1); | lua_pop(m_lua_state, 1); | ||||
return var.V(); | return var.V(); | ||||
} | } | ||||
@@ -138,10 +279,357 @@ public: | |||||
} | } | ||||
protected: | protected: | ||||
lua_State* GetLuaState(); | |||||
Lolua::State* GetLuaState(); | |||||
private: | private: | ||||
lua_State* m_lua_state; | |||||
Lolua::State* m_lua_state; | |||||
}; | }; | ||||
//----------------------------------------------------------------------------- | |||||
//class T definition | |||||
//class T | |||||
//{ | |||||
//public: | |||||
// int Ctor(lua_State* l) { return 0; } | |||||
// static const char* m_class_name; | |||||
// static const Class<T>::Variable* m_variables; | |||||
// static const Class<T>::Method* m_methods; | |||||
//}; | |||||
/* | |||||
//----------------------------------------------------------------------------- | |||||
template<typename T> | |||||
class ClassTest | |||||
{ | |||||
public: | |||||
//----------------------------------------------------------------------------- | |||||
struct Variable | |||||
{ | |||||
const char* m_name; | |||||
int(*Getter)(lua_State*); | |||||
int(*Setter)(lua_State*); | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
struct Method | |||||
{ | |||||
const char* m_name; | |||||
int(*Func)(lua_State*); | |||||
}; | |||||
//Register: Register class in Lua. Leave library empty to store class in global scope. | |||||
static void Register(lua_State* l, const char *library = NULL) | |||||
{ | |||||
if (library && strlen(library)) | |||||
{ | |||||
lua_getglobal(l, library); | |||||
//Create library if not present | |||||
if (lua_isnil(l, -1)) | |||||
{ | |||||
lua_newtable(l); | |||||
//Duplicate table pointer since setglobal pops the value | |||||
lua_pushvalue(l, -1); | |||||
lua_setglobal(l, library); | |||||
} | |||||
//lua_pushcfunction(l, &Class<T>::Ctor); | |||||
//lua_setfield(l, -2, T::m_class_name); | |||||
//lua_pop(l, 1); | |||||
} | |||||
else | |||||
{ | |||||
//lua_pushcfunction(l, &Class<T>::Ctor); | |||||
//lua_setglobal(l, T::m_class_name); | |||||
} | |||||
luaL_newmetatable(l, T::m_class_name); | |||||
int metatable = lua_gettop(l); | |||||
//Register all m_methods: Register Name for fun_call and number for choice | |||||
for (int i = 0; T::m_methods[i].m_name; i++) | |||||
{ | |||||
lua_pushstring(l, T::m_methods[i].m_name); | |||||
lua_pushcfunction(l, T::m_methods[i].Func); | |||||
lua_settable(l, metatable); | |||||
} | |||||
//lua_pushstring(l, "__gc"); | |||||
//lua_pushcfunction(l, &Class<T>::Dtor); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__tostring"); | |||||
//lua_pushcfunction(l, &Class<T>::ToString); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__eq"); | |||||
//lua_pushcfunction(l, &Class<T>::Equals); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__index"); | |||||
//lua_pushcfunction(l, &Class<T>::Getter); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__newindex"); | |||||
//lua_pushcfunction(l, &Class<T>::Setter); | |||||
//lua_settable(l, metatable); | |||||
////Register all properties: Register Name for fun_call and number for choice | |||||
//for (int i = 0; T::m_variables[i].m_name; i++) | |||||
//{ | |||||
// lua_pushstring(l, T::m_variables[i].m_name); | |||||
// lua_pushnumber(l, i); | |||||
// lua_settable(l, metatable); | |||||
//} | |||||
////Register all m_methods: Register Name for fun_call and number for choice | |||||
//for (int i = 0; T::m_methods[i].m_name; i++) | |||||
//{ | |||||
// lua_pushstring(l, T::m_methods[i].m_name); | |||||
// //Add (1 << 8) to identify function on call | |||||
// lua_pushnumber(l, i | (1 << 8)); | |||||
// lua_settable(l, metatable); | |||||
//} | |||||
} | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
template<typename T> | |||||
class Class | |||||
{ | |||||
public: | |||||
//----------------------------------------------------------------------------- | |||||
struct Variable | |||||
{ | |||||
const char* m_name; | |||||
int (T::*Getter)(lua_State*); | |||||
int (T::*Setter)(lua_State*); | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
struct Method | |||||
{ | |||||
const char* m_name; | |||||
int (T::*Func)(lua_State*); | |||||
}; | |||||
//----------------------------------------------------------------------------- | |||||
//Check: Raise an exception if FAIL | |||||
static T* Check(lua_State * l, int narg) | |||||
{ | |||||
T** obj = static_cast <T **>(luaL_checkudata(l, narg, T::m_class_name)); | |||||
return !obj ? nullptr : *obj; | |||||
} | |||||
//LightCheck: Returns nullptr if FAIL | |||||
static T* LightCheck(lua_State* l, int num_args) | |||||
{ | |||||
T** obj = static_cast <T **>(luaL_testudata(l, num_args, T::m_class_name)); | |||||
return !obj ? nullptr : *obj; | |||||
} | |||||
//Register: Register class in Lua. Leave library empty to store class in global scope. | |||||
static void Register(lua_State* l, const char *library = NULL) | |||||
{ | |||||
if (library && strlen(library)) | |||||
{ | |||||
lua_getglobal(l, library); | |||||
//Create library if not present | |||||
if (lua_isnil(l, -1)) | |||||
{ | |||||
lua_newtable(l); | |||||
//Duplicate table pointer since setglobal pops the value | |||||
lua_pushvalue(l, -1); | |||||
lua_setglobal(l, library); | |||||
} | |||||
lua_pushcfunction(l, &Class<T>::Ctor); | |||||
lua_setfield(l, -2, T::m_class_name); | |||||
lua_pop(l, 1); | |||||
} | |||||
else | |||||
{ | |||||
lua_pushcfunction(l, &Class<T>::Ctor); | |||||
lua_setglobal(l, T::m_class_name); | |||||
} | |||||
luaL_newmetatable(l, T::m_class_name); | |||||
int metatable = lua_gettop(l); | |||||
//lua_pushstring(l, "__gc"); | |||||
//lua_pushcfunction(l, &Class<T>::Dtor); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__tostring"); | |||||
//lua_pushcfunction(l, &Class<T>::ToString); | |||||
//lua_settable(l, metatable); | |||||
//lua_pushstring(l, "__eq"); | |||||
//lua_pushcfunction(l, &Class<T>::Equals); | |||||
//lua_settable(l, metatable); | |||||
lua_pushstring(l, "__index"); | |||||
lua_pushcfunction(l, &Class<T>::Getter); | |||||
lua_settable(l, metatable); | |||||
lua_pushstring(l, "__newindex"); | |||||
lua_pushcfunction(l, &Class<T>::Setter); | |||||
lua_settable(l, metatable); | |||||
//Register all properties: Register Name for fun_call and number for choice | |||||
for (int i = 0; T::m_variables[i].m_name; i++) | |||||
{ | |||||
lua_pushstring(l, T::m_variables[i].m_name); | |||||
lua_pushnumber(l, i); | |||||
lua_settable(l, metatable); | |||||
} | |||||
//Register all m_methods: Register Name for fun_call and number for choice | |||||
for (int i = 0; T::m_methods[i].m_name; i++) | |||||
{ | |||||
lua_pushstring(l, T::m_methods[i].m_name); | |||||
//Add (1 << 8) to identify function on call | |||||
lua_pushnumber(l, i | (1 << 8)); | |||||
lua_settable(l, metatable); | |||||
} | |||||
} | |||||
private: | |||||
//Ctor | |||||
static int Ctor(lua_State* l) | |||||
{ | |||||
T* obj = new T(l); | |||||
T** lua_obj = static_cast<T**>(lua_newuserdata(l, sizeof(T*))); // Push value = userdata | |||||
*lua_obj = obj; | |||||
luaL_getmetatable(l, T::m_class_name); // Fetch global metatable T::classname | |||||
lua_setmetatable(l, -2); | |||||
return 1; | |||||
} | |||||
//Dtor | |||||
static int Dtor(lua_State* l) | |||||
{ | |||||
T** lua_obj = static_cast<T**>(lua_touserdata(l, -1)); | |||||
if (lua_obj && *lua_obj) | |||||
delete(*lua_obj); | |||||
return 0; | |||||
} | |||||
//AddInstance | |||||
static void AddInstance(lua_State* l, T* instance) | |||||
{ | |||||
T** a = (T**)lua_newuserdata(l, sizeof(T*)); // Create userdata | |||||
*a = instance; | |||||
luaL_getmetatable(l, T::m_class_name); | |||||
lua_setmetatable(l, -2); | |||||
} | |||||
//---- | |||||
static void GetVarIndex(lua_State* l) | |||||
{ | |||||
lua_getmetatable(l, 1); //Look up the index of a m_name | |||||
lua_pushvalue(l, 2); //Push the m_name | |||||
lua_rawget(l, -2); //Get the index | |||||
} | |||||
//---- | |||||
static void PrepareGetSet(lua_State* l) | |||||
{ | |||||
lua_pop(l, 2); // Pop metatable and idx | |||||
lua_remove(l, 1); // Remove userdata | |||||
lua_remove(l, 1); // Remove [key] | |||||
} | |||||
//Getter: Call a func or a getter var | |||||
static int Getter(lua_State* l) | |||||
{ | |||||
GetVarIndex(l); | |||||
//Check if we got a valid index | |||||
if (lua_isnumber(l, -1)) | |||||
{ | |||||
int idx = lua_tonumber(l, -1); | |||||
T** obj = static_cast<T**>(lua_touserdata(l, 1)); | |||||
lua_pushvalue(l, 3); | |||||
//It's a method | |||||
if (idx & (1 << 8)) | |||||
{ | |||||
//Push the Method index and call the function | |||||
lua_pushnumber(l, idx ^ (1 << 8)); | |||||
lua_pushlightuserdata(l, obj); | |||||
lua_pushcclosure(l, &Class<T>::CallMethod, 2); | |||||
// Return a Method | |||||
return 1; | |||||
} | |||||
else | |||||
{ | |||||
PrepareGetSet(l); | |||||
return ((*obj)->*(T::m_variables[idx].Getter))(l); | |||||
} | |||||
} | |||||
return 1; | |||||
} | |||||
//Getter: Class a setter var or error if func | |||||
static int Setter(lua_State* l) | |||||
{ | |||||
GetVarIndex(l); | |||||
//Check if we got a valid index | |||||
if (lua_isnumber(l, -1)) | |||||
{ | |||||
int idx = lua_tonumber(l, -1); | |||||
T** obj = static_cast<T**>(lua_touserdata(l, 1)); | |||||
if (!obj || !*obj) | |||||
{ | |||||
luaL_error(l, "Internal error, no object given!"); | |||||
return 0; | |||||
} | |||||
//Try to set a Method - FAIL | |||||
if (idx & (1 << 8)) | |||||
{ | |||||
String s = String::Printf("Trying to set the method [%s] of class [%s]", (*obj)->T::m_methods[idx ^ (1 << 8)].m_name, T::m_class_name); | |||||
luaL_error(l, s.C()); | |||||
return 0; | |||||
} | |||||
else | |||||
{ | |||||
PrepareGetSet(l); | |||||
return ((*obj)->*(T::m_variables[idx].Setter))(l); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
//CallMethod: Actually calls the method on the object | |||||
static int CallMethod(lua_State* l) | |||||
{ | |||||
int i = (int)lua_tonumber(l, lua_upvalueindex(1)); | |||||
T** obj = static_cast <T**>(lua_touserdata(l, lua_upvalueindex(2))); | |||||
return ((*obj)->*(T::m_methods[i].Func))(l); | |||||
} | |||||
//ToString: | |||||
static int ToString(lua_State* l) | |||||
{ | |||||
T** obj = static_cast<T**>(lua_touserdata(l, -1)); | |||||
if (obj) | |||||
lua_pushfstring(l, "%s (%p)", T::m_class_name, (void*)*obj); | |||||
else | |||||
lua_pushstring(l, "Empty object"); | |||||
return 1; | |||||
} | |||||
//Equals: | |||||
static int Equals(lua_State* l) | |||||
{ | |||||
T** obj1 = static_cast<T**>(lua_touserdata(l, -1)); | |||||
T** obj2 = static_cast<T**>(lua_touserdata(l, 1)); | |||||
lua_pushboolean(l, *obj1 == *obj2); | |||||
return 1; | |||||
} | |||||
}; | |||||
*/ | |||||
} /* namespace Lolua */ | |||||
} /* namespace lol */ | } /* namespace lol */ |
@@ -14,8 +14,6 @@ | |||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <ctype.h> | #include <ctype.h> | ||||
//#include "lua/lua.hpp" | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -36,21 +34,10 @@ World g_world; | |||||
* Public World class | * Public World class | ||||
*/ | */ | ||||
const luaL_Reg test1Lua::m_statics[] = { { "getTest", test1Lua::getTest }, { NULL, NULL } }; | |||||
const luaL_Reg test1Lua::m_methods[] = { { NULL, NULL } }; | |||||
const char test1Lua::m_class[] = "test1"; | |||||
World::World() | World::World() | ||||
: LuaLoader() | |||||
: Lolua::Loader() | |||||
{ | { | ||||
g_world_data.m_lua_state = GetLuaState(); | g_world_data.m_lua_state = GetLuaState(); | ||||
//------ DEBUG TEST | |||||
//m_test1.LoadTo(GetLuaState()); | |||||
//luaL_loadfile(GetLuaState(), "lua/init.lua"); | |||||
//LuaVar<int32_t> var(GetLuaState(), 1); | |||||
//test1Lua::Library m_test1(GetLuaState()); | |||||
//------ DEBUG TEST | |||||
} | } | ||||
World::~World() | World::~World() | ||||
@@ -18,51 +18,11 @@ | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
class test1 | |||||
{ | |||||
public: | |||||
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(); | |||||
} | |||||
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: | |||||
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; | |||||
}; | |||||
class World : public LuaLoader | |||||
class World : public Lolua::Loader | |||||
{ | { | ||||
public: | public: | ||||
World(); | World(); | ||||
virtual ~World(); | virtual ~World(); | ||||
protected: | |||||
test1Lua::Library m_test1; | |||||
}; | }; | ||||
extern World g_world; | extern World g_world; | ||||