mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
* Merged Source Code from Development Trunk: Revision 4063 * ************************************************************ - Source Code is merged from: https://81.169.133.124/source/ja2/branches/Wanne/JA2%201.13%20MP - This will be the Source for the Beta 2011 Test git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@4064 3b4a5df2-a311-0410-b5c6-a8a6f20db521
248 lines
5.4 KiB
C++
248 lines
5.4 KiB
C++
#include "lua_class_interface.h"
|
|
|
|
#include <Debug.h>
|
|
|
|
#define ARRAY_INDEX " idx" // The space is intentional to make this an out-of-band field
|
|
|
|
luaL_Reg LuaInterface::s_ClassList[] = {
|
|
{ "__index", LuaInterface::luaGetObject, },
|
|
{ "__newindex", LuaInterface::luaSetObject, },
|
|
{ NULL, },
|
|
};
|
|
|
|
const char* LuaInterface::luaClassName = "ja2_LuaInterface";
|
|
|
|
LuaInterface::LuaInterface()
|
|
: luaObject(NULL)
|
|
{
|
|
}
|
|
|
|
LuaInterface::~LuaInterface()
|
|
{
|
|
}
|
|
|
|
LuaInterface::SInterfaceData* LuaInterface::luaGetInterface()
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void* LuaInterface::luaIsOfType(LuaState state, int index, const char* sClassName)
|
|
{
|
|
lua_State* L = state();
|
|
void *p = lua_touserdata(L, index);
|
|
LuaInterface::SInterfaceData* iface = NULL;
|
|
if( lua_getmetatable(L, index) ) /* does it have a metatable? */
|
|
{
|
|
lua_getfield(L, -1, "__ClassInterface");
|
|
iface = (LuaInterface::SInterfaceData*) lua_touserdata(L, -1);
|
|
if( !iface )
|
|
{
|
|
return NULL;
|
|
}
|
|
lua_pop(L,2);
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
LuaInterface::SInterfaceData::tClassInterface::iterator it = iface->ClassHierarchy.begin();
|
|
for(; it != iface->ClassHierarchy.end(); ++it)
|
|
{
|
|
if( *it == sClassName )
|
|
{
|
|
return p;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LuaInterface::SInterfaceData* LuaInterface::luaGetExportedInterface( SInterfaceData* iface )
|
|
{
|
|
//iface.Attribs.push_back(s_attrClassList);
|
|
//iface.ClassHierarchy.push_back(LuaInterface::luaClassName);
|
|
return iface;
|
|
}
|
|
|
|
void LuaInterface::luaExportInterface(LuaState state, LuaInterface::SInterfaceData& iface )
|
|
{
|
|
luaL_Reg *i;
|
|
LuaAttrib *idx;
|
|
lua_State* L = state();
|
|
|
|
LuaInterface::SInterfaceData::tClassInterface::iterator it_class = iface.ClassHierarchy.begin();
|
|
|
|
luaL_newmetatable( L, (*it_class).c_str() );
|
|
for (i = s_ClassList; i->name; i++)
|
|
{
|
|
lua_pushstring(L, i->name);
|
|
lua_pushlightuserdata(L, &iface);
|
|
lua_pushcclosure(L, i->func, 1);
|
|
lua_rawset(L, -3);
|
|
}
|
|
lua_pushlightuserdata(L, &iface);
|
|
lua_setfield(L, -2, "__ClassInterface");
|
|
|
|
LuaInterface::SInterfaceData::tAttribs::iterator it_attrib = iface.Attribs.begin();
|
|
for(;it_attrib != iface.Attribs.end(); ++it_attrib)
|
|
{
|
|
for (idx=*it_attrib; idx->name; idx++)
|
|
{
|
|
if (idx->staticcall)
|
|
{
|
|
lua_pushstring(L, idx->name);
|
|
lua_pushcfunction(L, idx->staticcall);
|
|
lua_rawset(L, -3 );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
LuaAttrib* LuaInterface::luaCommonGetSet(LuaState state)
|
|
{
|
|
const char *AttrToFind;
|
|
typedef std::list<LuaAttrib*> tAttributes;
|
|
lua_State* L = state();
|
|
|
|
LuaInterface::SInterfaceData* iface = (LuaInterface::SInterfaceData*) lua_touserdata(L, lua_upvalueindex( 1));
|
|
if(!iface)
|
|
{
|
|
return NULL;
|
|
}
|
|
tAttributes* Attributes = &iface->Attribs;
|
|
|
|
if (lua_isnumber(L, 2) )
|
|
{
|
|
AttrToFind = ARRAY_INDEX;
|
|
}
|
|
else if (lua_isstring(L, 2) )
|
|
{
|
|
AttrToFind = lua_tostring(L, 2);
|
|
}
|
|
else
|
|
{
|
|
luaL_argcheck(L, 0, 2, "Invalid index to the table" );
|
|
// The last function doesn't return, but gotta keep the compiler happy
|
|
return NULL;
|
|
}
|
|
|
|
tAttributes::iterator it = Attributes->begin();
|
|
for(;it != Attributes->end(); ++it)
|
|
{
|
|
LuaAttrib* attrib = (*it);
|
|
for ( ; attrib->name; attrib++ )
|
|
{
|
|
if ( strcmp( attrib->name, AttrToFind) == 0 )
|
|
{
|
|
return attrib;
|
|
}
|
|
}
|
|
}
|
|
std::string err = "No such field : " + std::string(AttrToFind);
|
|
luaL_error(L, err.c_str());
|
|
return NULL;
|
|
}
|
|
|
|
//int LuaInterface::luaGetObject(lua_State* L)
|
|
DEFINE_LUA_CFUNCTION(LuaInterface, luaGetObject)
|
|
{
|
|
LuaAttrib *Attributes;
|
|
|
|
Attributes = LuaInterface::luaCommonGetSet(L);
|
|
if (!Attributes)
|
|
{
|
|
lua_pushnil( L );
|
|
return 1;
|
|
}
|
|
|
|
if (!Attributes->get)
|
|
{
|
|
if (!Attributes->call)
|
|
{
|
|
lua_pushnil( L );
|
|
}
|
|
else
|
|
{
|
|
lua_pushcfunction(L, Attributes->call);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
return Attributes->get( L );
|
|
}
|
|
|
|
//int LuaInterface::luaSetObject(lua_State* L)
|
|
DEFINE_LUA_CFUNCTION(LuaInterface, luaSetObject)
|
|
{
|
|
LuaAttrib *Attributes;
|
|
|
|
Attributes = LuaInterface::luaCommonGetSet(L);
|
|
|
|
if (!Attributes)
|
|
{
|
|
lua_rawset( L, 1 );
|
|
return 0;
|
|
}
|
|
|
|
if (!Attributes->set)
|
|
{
|
|
luaL_error( L, "The attribute is not writable" );
|
|
}
|
|
|
|
return Attributes->set(L);
|
|
}
|
|
|
|
|
|
void LuaInterface::luaCreateObject( LuaState state, void *Ptr )
|
|
{
|
|
lua_State* L = state();
|
|
// Create the object and initialize its pointer
|
|
void **ud;
|
|
ud = (void**)lua_newuserdata( L, sizeof( void*) );
|
|
*ud = Ptr;
|
|
// save user data
|
|
state.registry().GetUserDataTable();
|
|
lua_pushlightuserdata(L, this);
|
|
lua_pushvalue(L, -3);
|
|
lua_rawset(L, -3);
|
|
lua_pop(L, 1);
|
|
// Swap the table and metatable for stack arg purposes
|
|
lua_insert( L, -2 );
|
|
lua_setmetatable( L, -2 );
|
|
}
|
|
|
|
void LuaInterface::luaPushObject( LuaState state, const char* sClassName, void *Ptr )
|
|
{
|
|
lua_State* L = state();
|
|
state.registry().GetUserDataTable();
|
|
lua_pushlightuserdata(L, Ptr);
|
|
lua_rawget(L,-2);
|
|
if(lua_isnil(L,-1))
|
|
{
|
|
lua_pop(L, 1);
|
|
luaL_getmetatable( L, sClassName );
|
|
if (lua_istable( L, -1 ) )
|
|
{
|
|
this->luaCreateObject( state, Ptr );
|
|
}
|
|
}
|
|
if(!lua_isuserdata(L,-1))
|
|
{
|
|
SGP_THROW(L"Could not create User Data");
|
|
}
|
|
lua_insert(L, -2);
|
|
lua_pop(L, 1);
|
|
}
|
|
|
|
void LuaInterface::luaPushObject( LuaState state, const char* luaName )
|
|
{
|
|
LuaInterface::SInterfaceData* iface = this->luaGetInterface();
|
|
this->luaPushObject(state, iface->ClassHierarchy.front().c_str(), this);
|
|
if(luaName != NULL)
|
|
{
|
|
lua_setglobal( state(), luaName );
|
|
}
|
|
}
|
|
|
|
|