I am trying to index into a user data called entity to get to another user data called transform component. I am relatively new to lua w/ c++ binding but after I got my entity up and running with metatables and an index method that would allow me to do stuff like this in Lua:
entity1 = Entity.create()
entity1:setID(4)
print(entity1)
This works perfectly but I also have a user data called TransformComponent that looks like this in LUA
transform1 = TransformComponent.create()
transform1:setPosition(4,3)
print(transform1)
Here is where I get stuck. What I WANT to be able to do in LUA is something like this:
entity1 = Entity.create()
entity1.transform:setPosition(4,3)
print(entity1)
How do I (in C++) set up this kind of relationship where Entity is a table that contains all its methods but also contains a key called "transform" that maps to the TransformComponent table. In C++ I tried setting it as a key and I tried reading the "transform" key from the index method and placing the TransformComponent methods in the table but that didn't work.
Any help is extremely appreciated.
EDIT
I initially didn't want to include the attempts I made because they were futile and I knew it but what I attempted to do was during the entity index, I would push the table for TransformComponent and hope the next part of the index (i.e. the methods for TransformComponent)
So here is the index method for Entity
static int _LUA_index(lua_State* L) {
assert(lua_isstring(L, -1));
Entity* luaEntity1 = (Entity*)lua_touserdata(L, -2); assert(luaEntity1);
std::string index = lua_tostring(L, -1);
if (index == "transform") {
lua_getglobal(L, "TransformComponent");
return 1;
}
lua_getglobal(L, "Entity");
lua_pushstring(L, index.c_str());
lua_rawget(L, -2);
return 1;
}
If i print out the result of "index" its just transform, I can never get it to try and parse "setPosition". I have no Idea how to progress here. Here is the code to setup the tables:
lua_State* L = luaL_newstate();
luaL_openlibs(L);
/* --------- Transform table ----------- */
lua_newtable(L);
int transformTableIndex = lua_gettop(L);
lua_pushvalue(L, transformTableIndex);
lua_setglobal(L, "TransformComponent");
lua_pushcfunction(L, TransformComponent::_LUA_CreateTransform);
lua_setfield(L, -2, "create");
lua_pushcfunction(L, TransformComponent::_LUA_SetPosition);
lua_setfield(L, -2, "setPosition");
/* --------- Transform Meta table ----------- */
luaL_newmetatable(L, "TransformComponentMetaTable");
lua_pushcfunction(L, TransformComponent::_LUA_gc);
lua_setfield(L, -2, "__gc");
lua_pushcfunction(L, TransformComponent::_LUA_eq);
lua_setfield(L, -2, "__eq");
lua_pushcfunction(L, TransformComponent::_LUA_tostring);
lua_setfield(L, -2, "__tostring");
lua_pushcfunction(L, TransformComponent::_LUA_index);
lua_setfield(L, -2, "__index");
/* --------- Entity table --------- */
lua_newtable(L);
int entityTableIndex = lua_gettop(L);
lua_pushvalue(L, entityTableIndex);
lua_setglobal(L, "Entity");
constexpr int NUM_OF_UPVALUES = 1;
lua_pushlightuserdata(L, &manager);
lua_pushcclosure(L, Entity::_LUA_CreateEntity, NUM_OF_UPVALUES);
//lua_pushcfunction(L, Entity::_LUA_CreateEntity);
lua_setfield(L, -2, "create");
lua_pushcfunction(L, Entity::_LUA_MoveEntity);
lua_setfield(L, -2, "move");
lua_pushcfunction(L, Entity::_LUA_DrawEntity);
lua_setfield(L, -2, "draw");
/* --------- Entity Meta table --------- */
luaL_newmetatable(L, "EntityMetaTable");
lua_pushstring(L, "__gc");
lua_pushcfunction(L, Entity::_LUA_gc);
lua_settable(L, -3);
lua_pushstring(L, "__eq");
lua_pushcfunction(L, Entity::_LUA_eq);
lua_settable(L, -3);
lua_pushstring(L, "__tostring");
lua_pushcfunction(L, Entity::_LUA_tostring);
lua_settable(L, -3);
lua_pushstring(L, "__index");
lua_pushcfunction(L, Entity::_LUA_index);
lua_settable(L, -3);
I started thinking this was impossible to accomplish or I am just unable to do this Lua. I am unsure but I am definitely not talented enough to figure this out.
EDIT2 EntityClass + TransformComponent:
struct _API SpriteComponent {
const char* fileName;
};
struct _API TransformComponent {
glm::vec2 position;
glm::vec3 rotation;
TransformComponent();
~TransformComponent();
static int _LUA_CreateTransform(lua_State* L);
static int _LUA_SetPosition(lua_State* L);
static int _LUA_gc(lua_State* L);
static int _LUA_eq(lua_State* L);
static int _LUA_index(lua_State* L);
static int _LUA_tostring(lua_State* L);
};
class _API Entity{
public:
TransformComponent transform;
SpriteComponent sprite;
Entity();
~Entity();
void moveEntity(float x, float y);
void drawEntity();
static int _LUA_CreateEntity(lua_State* L);
..etc etc
EDIT3
_LUA_CreateTransform method
int TransformComponent::_LUA_CreateTransform(lua_State* L) {
void* entityPointer = lua_newuserdata(L, sizeof(TransformComponent));
new(entityPointer) TransformComponent(); assert(entityPointer);
luaL_getmetatable(L, "TransformComponentMetaTable");
lua_setmetatable(L, -2);
return 1;
}
Again any help is super appreciated.