Pārlūkot izejas kodu

Added first pass for Base Lua setup

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> pirms 10 gadiem
vecāks
revīzija
596e74c78c
12 mainītis faili ar 1262 papildinājumiem un 216 dzēšanām
  1. +1
    -0
      src/Makefile.am
  2. +1
    -0
      src/application/application.cpp
  3. +112
    -0
      src/application/baselua.cpp
  4. +210
    -0
      src/application/baselua.h
  5. +16
    -16
      src/easymesh/easymeshinternal.cpp
  6. +1
    -0
      src/lol/extras.h
  7. +2
    -0
      src/lolcore.vcxproj
  8. +6
    -0
      src/lolcore.vcxproj.filters
  9. +130
    -129
      src/lua/lollua.vcxproj
  10. +731
    -0
      src/lua/luawrapper.hpp
  11. +11
    -66
      src/world.cpp
  12. +41
    -5
      src/world.h

+ 1
- 0
src/Makefile.am Parādīt failu

@@ -10,6 +10,7 @@ liblolcore_a_SOURCES = \
audio.cpp audio.h scene.cpp scene.h font.cpp font.h \
entity.cpp entity.h ticker.cpp ticker.h lolgl.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 \
profiler.cpp profiler.h text.cpp text.h emitter.cpp emitter.h \
numeric.h utils.h messageservice.cpp messageservice.h \


+ 1
- 0
src/application/application.cpp Parādīt failu

@@ -74,6 +74,7 @@ Application::Application(char const *name, ivec2 resolution, float framerate)
data = new ApplicationData(name, resolution, framerate);

g_world.ExecLua("lua/init.lua");
int32_t gravity = g_world.GetVar<int32_t>("gravity");
}

bool Application::MustTick()


+ 112
- 0
src/application/baselua.cpp Parādīt failu

@@ -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 */


+ 210
- 0
src/application/baselua.h Parādīt failu

@@ -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 */

+ 16
- 16
src/easymesh/easymeshinternal.cpp Parādīt failu

@@ -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)
{
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) &&
!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;
}
}
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)
{
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 + i2);
m_indices << (uint16_t)m_vert.Count(); AddDupVertex(base + i3);
}
else
{
m_indices << base + i1;
m_indices << base + i2;
m_indices << base + i3;
}
}

//-----------------------------------------------------------------------------


+ 1
- 0
src/lol/extras.h Parādīt failu

@@ -43,6 +43,7 @@
#include <lol/../sprite.h>
#include <lol/../text.h>
#include <lol/../tileset.h>
#include <lol/../application/baselua.h>
#include <lol/../world.h>

// Other objects


+ 2
- 0
src/lolcore.vcxproj Parādīt failu

@@ -88,6 +88,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="application\application.cpp" />
<ClCompile Include="application\baselua.cpp" />
<ClCompile Include="audio.cpp" />
<ClCompile Include="camera.cpp" />
<ClCompile Include="base\assert.cpp" />
@@ -231,6 +232,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="application\application.h" />
<ClInclude Include="application\baselua.h" />
<ClInclude Include="audio.h" />
<ClInclude Include="camera.h" />
<ClInclude Include="commandstack.h" />


+ 6
- 0
src/lolcore.vcxproj.filters Parādīt failu

@@ -403,6 +403,9 @@
<ClCompile Include="easymesh\easymeshcursor.cpp">
<Filter>easymesh</Filter>
</ClCompile>
<ClCompile Include="application\baselua.cpp">
<Filter>application</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="debug\fps.h">
@@ -754,6 +757,9 @@
<ClInclude Include="lol\algorithm\portal.h">
<Filter>lol\algorithm</Filter>
</ClInclude>
<ClInclude Include="application\baselua.h">
<Filter>application</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<LolFxCompile Include="gpu\emptymaterial.lolfx">


+ 130
- 129
src/lua/lollua.vcxproj Parādīt failu

@@ -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>

+ 731
- 0
src/lua/luawrapper.hpp Parādīt failu

@@ -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_

+ 11
- 66
src/world.cpp Parādīt failu

@@ -14,7 +14,7 @@
#include <cstdlib>
#include <ctype.h>

#include "lua/lua.hpp"
//#include "lua/lua.hpp"

namespace lol
{
@@ -26,47 +26,6 @@ namespace lol
class WorldData
{
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;
};

@@ -77,37 +36,23 @@ World g_world;
* 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()
: 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()
{
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 */


+ 41
- 5
src/world.h Parādīt failu

@@ -18,15 +18,51 @@
namespace lol
{

class World
class test1
{
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();
virtual ~World();

protected:
test1Lua::Library m_test1;
};

extern World g_world;


Notiek ielāde…
Atcelt
Saglabāt