1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-06-23 00:28:08 +02:00
Files
.github
AI
CI
Mods
android
client
clientapp
cmake_modules
config
debian
docker
docs
include
ios
launcher
lib
lobby
mapeditor
osx
rpm
scripting
erm
lua
api
CMakeLists.txt
LuaCallWrapper.h
LuaFunctor.h
LuaReference.cpp
LuaReference.h
LuaScriptModule.cpp
LuaScriptModule.h
LuaScriptingContext.cpp
LuaScriptingContext.h
LuaSpellEffect.cpp
LuaSpellEffect.h
LuaStack.cpp
LuaStack.h
LuaWrapper.h
StdInc.cpp
StdInc.h
scripts
server
serverapp
test
vcmiqt
win
xcode
.editorconfig
.gitattributes
.gitignore
.gitmodules
.travis.yml
AUTHORS.h
CCallback.cpp
CCallback.h
CMakeLists.txt
CMakePresets.json
ChangeLog.md
Global.h
Version.cpp.in
Version.h
conanfile.py
fuzzylite.pc.in
license.txt
vcmibuilder
vcmi/scripting/lua/LuaWrapper.h

238 lines
4.5 KiB
C++
Raw Normal View History

/*
* LuaWrapper.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
2021-02-16 17:07:30 +03:00
#include "LuaCallWrapper.h"
/*
* Original code is LunaWrapper by nornagon.
* https://lua-users.org/wiki/LunaWrapper
* Published under the BSD 2-clause license
* https://opensource.org/licenses/BSD-2-Clause
*
*/
2022-08-15 14:38:17 +03:00
VCMI_LIB_NAMESPACE_BEGIN
namespace scripting
{
namespace detail
{
struct CustomRegType
{
const char * name;
lua_CFunction functor;
bool isStatic;
};
template <typename P, typename U>
struct Dispatcher
{
using ProxyType = P;
using UDataType = U;
static void setIndexTable(lua_State * L)
{
lua_pushstring(L, "__index");
lua_newtable(L);
for(auto & reg : ProxyType::REGISTER_CUSTOM)
{
if(!reg.isStatic)
{
lua_pushstring(L, reg.name);
lua_pushcclosure(L, reg.functor, 0);
lua_rawset(L, -3);
}
}
lua_rawset(L, -3);
}
static void pushStaticTable(lua_State * L)
{
lua_newtable(L);
lua_newtable(L);
lua_pushstring(L, "__index");
{
lua_newtable(L);
for(auto & reg : ProxyType::REGISTER_CUSTOM)
{
if(reg.isStatic)
{
lua_pushstring(L, reg.name);
lua_pushcclosure(L, reg.functor, 0);
lua_rawset(L, -3);
}
}
}
lua_rawset(L, -3);
lua_pushstring(L, "__newindex");
lua_pushnil(L);
lua_rawset(L, -3);
lua_setmetatable(L, -2);
}
static int destructor(lua_State * L)
{
static auto KEY = api::TypeRegistry::get()->getKey<UDataType>();
void * objPtr = luaL_checkudata(L, 1, KEY);
if(objPtr)
{
auto obj = static_cast<UDataType *>(objPtr);
obj->reset();
}
lua_settop(L, 0);
return 0;
}
};
}
class RegistarBase : public api::Registar
{
public:
protected:
virtual void adjustMetatable(lua_State * L) const
{
}
virtual void adjustStaticTable(lua_State * L) const
{
}
};
template<class T, class Proxy = T>
class OpaqueWrapper : public RegistarBase
{
public:
using ObjectType = typename std::remove_cv_t<T>;
2021-02-15 17:16:41 +03:00
using UDataType = ObjectType *;
using CUDataType = const ObjectType *;
using CustomRegType = detail::CustomRegType;
void pushMetatable(lua_State * L) const override final
{
static auto KEY = api::TypeRegistry::get()->getKey<UDataType>();
2021-02-15 17:16:41 +03:00
static auto S_KEY = api::TypeRegistry::get()->getKey<CUDataType>();
LuaStack S(L);
if(luaL_newmetatable(L, KEY) != 0)
adjustMetatable(L);
S.balance();
2021-02-15 17:16:41 +03:00
if(luaL_newmetatable(L, S_KEY) != 0)
adjustMetatable(L);
S.balance();
detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L);
adjustStaticTable(L);
}
protected:
void adjustMetatable(lua_State * L) const override
{
detail::Dispatcher<Proxy, UDataType>::setIndexTable(L);
}
};
template<class T, class Proxy = T>
class SharedWrapper : public RegistarBase
{
public:
using ObjectType = typename std::remove_cv_t<T>;
using UDataType = std::shared_ptr<T>;
using CustomRegType = detail::CustomRegType;
static int constructor(lua_State * L)
{
LuaStack S(L);
S.clear();//we do not accept any parameters in constructor
auto obj = std::make_shared<T>();
S.push(obj);
return 1;
}
void pushMetatable(lua_State * L) const override final
{
static auto KEY = api::TypeRegistry::get()->getKey<UDataType>();
LuaStack S(L);
if(luaL_newmetatable(L, KEY) != 0)
{
adjustMetatable(L);
S.push("__gc");
lua_pushcfunction(L, &(detail::Dispatcher<Proxy, UDataType>::destructor));
lua_rawset(L, -3);
}
S.balance();
detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L);
adjustStaticTable(L);
}
protected:
void adjustMetatable(lua_State * L) const override
{
detail::Dispatcher<Proxy, UDataType>::setIndexTable(L);
}
};
template<class T, class Proxy = T>
class UniqueOpaqueWrapper : public api::Registar
{
public:
using ObjectType = typename std::remove_cv_t<T>;
using UDataType = std::unique_ptr<T>;
using CustomRegType = detail::CustomRegType;
void pushMetatable(lua_State * L) const override final
{
static auto KEY = api::TypeRegistry::get()->getKey<UDataType>();
LuaStack S(L);
if(luaL_newmetatable(L, KEY) != 0)
{
// detail::Dispatcher<Proxy, UDataType>::setIndexTable(L);
S.push("__gc");
lua_pushcfunction(L, &(detail::Dispatcher<Proxy, UDataType>::destructor));
lua_rawset(L, -3);
}
S.balance();
detail::Dispatcher<Proxy, UDataType>::pushStaticTable(L);
}
};
}
2022-08-15 14:38:17 +03:00
VCMI_LIB_NAMESPACE_END