Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 57 additions & 1 deletion src/script/component.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ template<typename T> class ComponentHandler
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, luaNewIndex);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, luaPairs);
lua_setfield(L, -2, "__pairs");
lua_pushcfunction(L, [](lua_State* L) {
if (!array_count_func) luaL_error(L, "Tried to get length of component %s that has no array", component_name);
auto ptr = luaToComponent(L, -1);
Expand Down Expand Up @@ -93,6 +95,27 @@ template<typename T> class ComponentHandler
return 0;
});
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, [](lua_State* L) {
IndexedComponent* icptr = static_cast<IndexedComponent*>(lua_touserdata(L, -1));
if (!icptr) return 0;
if (!icptr->entity) return 0;
auto ptr = icptr->entity.template getComponent<T>();
if (!ptr) return 0;
if (array_count_func(*ptr) <= icptr->index) return luaL_error(L, "Index out of range for pairs on component %s", component_name);

lua_newtable(L);
int tbl = lua_gettop(L);
for (auto mem : indexed_members) {
mem.second.getter(L, ptr, icptr->index);
lua_setfield(L, tbl, mem.first.c_str());
}
lua_settop(L, tbl);
lua_getglobal(L, "next");
lua_rotate(L, 2, -1);
lua_pushnil(L);
return 3; // next, tbl, nil
});
lua_setfield(L, -2, "__pairs");
lua_pushstring(L, "sandboxed");
lua_setfield(L, -2, "__metatable");
lua_pop(L, 1);
Expand Down Expand Up @@ -163,6 +186,39 @@ template<typename T> class ComponentHandler
return 0;
}

static int luaPairs(lua_State* L) {
auto eptr = lua_touserdata(L, -1);
if (!eptr) return 0;
auto e = *static_cast<ecs::Entity*>(eptr);
if (!e) return 0;
auto ptr = e.getComponent<T>();
if (!ptr) return 0;

lua_newtable(L);
int tbl = lua_gettop(L);
if (array_count_func) {
int count = array_count_func(*ptr);
for (int i = 0; i < count; i++) {
auto ic = static_cast<IndexedComponent*>(lua_newuserdata(L, sizeof(IndexedComponent)));
ic->entity = e;
ic->index = i;
luaL_getmetatable(L, array_metatable_name.c_str());
lua_setmetatable(L, -2);
lua_seti(L, tbl, i + 1);
}
}
for (auto mem : members) {
mem.second.getter(L, ptr);
lua_setfield(L, tbl, mem.first.c_str());
}

lua_settop(L, tbl);
lua_getglobal(L, "next");
lua_rotate(L, 2, -1);
lua_pushnil(L);
return 3; // next, tbl, nil
}

static T* luaToComponent(lua_State* L, int index) {
auto eptr = lua_touserdata(L, index);
if (!eptr) return nullptr;
Expand Down Expand Up @@ -236,4 +292,4 @@ template<typename T> class ComponentHandler

}

#endif//SP_SCRIPT_ENVIRONMENT
#endif//SP_SCRIPT_ENVIRONMENT
68 changes: 68 additions & 0 deletions src/script/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,47 @@ static int luaEntityNewIndex(lua_State* L) {
return 0;
}

static int luaEntityPairsNext(lua_State* L) {
lua_settop(L, 2); // ensure we have a (possibly nil) key, as we may have been called with just (entity)

auto e = Convert<ecs::Entity>::fromLua(L, 1);
if (!e) return 0;

if (lua_type(L, 2) == LUA_TNIL) {
// nil => first call; return components first
lua_pop(L, 1);
lua_pushstring(L, "components");
*static_cast<ecs::Entity*>(lua_newuserdata(L, sizeof(ecs::Entity))) = e;
luaL_getmetatable(L, "entity_components");
lua_setmetatable(L, -2);
return 2;
}
if (lua_type(L, 2) == LUA_TSTRING && !strcmp(lua_tostring(L, 2), "components")) {
// second call, give lua_next a nil to get the first LTC key.
// from the third call onwards, we'll pass the previous key directly to lua_next.
lua_pop(L, 1);
lua_pushnil(L);
}

auto ltc = e.getComponent<LuaTableComponent>();
if (!ltc) return 0;

lua_rawgetp(L, LUA_REGISTRYINDEX, ltc);
lua_rotate(L, 2, -1);

return lua_next(L, -2) ? 2 : 0;
}

static int luaEntityPairs(lua_State* L) {
auto e = Convert<ecs::Entity>::fromLua(L, 1);
if (!e) return 0;

lua_pushcfunction(L, luaEntityPairsNext);
lua_pushvalue(L, -2);
lua_pushnil(L);
return 3;
}

static int luaEntityComponentsIndex(lua_State* L) {
auto eptr = lua_touserdata(L, -2);
if (!eptr) return 0;
Expand Down Expand Up @@ -165,6 +206,29 @@ static int luaEntityComponentsNewIndex(lua_State* L) {
return luaL_error(L, "Tried to set non-exsisting component %s", key);
}

static int luaEntityComponentsPairs(lua_State* L) {
auto eptr = lua_touserdata(L, -1);
if (!eptr) return 0;
auto e = *static_cast<ecs::Entity*>(eptr);
if (!e) return 0;

lua_newtable(L);
int tbl = lua_gettop(L);

for (auto entry : ComponentRegistry::components) {
int n = entry.second.getter(L, e, entry.first.c_str());
if (n == 1) {
lua_setfield(L, tbl, entry.first.c_str());
}
}

lua_settop(L, tbl);
lua_getglobal(L, "next");
lua_rotate(L, 2, -1);
lua_pushnil(L);
return 3; // next, tbl, nil
}

static int luaEntityEqual(lua_State* L) {
auto e1 = Convert<ecs::Entity>::fromLua(L, -2);
if (!e1) return 0;
Expand Down Expand Up @@ -209,6 +273,8 @@ lua_State* Environment::getLuaState()
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, luaEntityNewIndex);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, luaEntityPairs);
lua_setfield(L, -2, "__pairs");
lua_pushcfunction(L, luaEntityEqual);
lua_setfield(L, -2, "__eq");
lua_pushstring(L, "sandboxed");
Expand All @@ -221,6 +287,8 @@ lua_State* Environment::getLuaState()
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, luaEntityComponentsNewIndex);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, luaEntityComponentsPairs);
lua_setfield(L, -2, "__pairs");
lua_pushstring(L, "sandboxed");
lua_setfield(L, -2, "__metatable");
lua_pop(L, 1);
Expand Down
Loading