Created
April 18, 2017 06:52
-
-
Save shakesoda/bf2484483b536aaaf4536e48beafb093 to your computer and use it in GitHub Desktop.
basic binding of PECS to lua, using kaguya.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <lua.hpp> | |
#include "kaguya.hpp" | |
#include "pecs.hpp" | |
using namespace pecs; | |
using namespace std; | |
enum { | |
// NB: component 0 can't be used. | |
COMPONENT_NONE = ~0, | |
COMPONENT_PLAYER = 1 << 1 | |
}; | |
template <typename T> | |
static void resize(vector<T> &components, uint32_t id) { | |
size_t c = components.capacity(); | |
while (c <= id) { | |
c = max<size_t>(c, 1); | |
c = c << 1; | |
} | |
if (components.size() <= id) { | |
components.reserve(c); | |
components.resize(id+1); | |
} | |
} | |
#define GENERATE_COMPONENT(ENUM, TYPE, NAME) \ | |
vector<TYPE> NAME##s; \ | |
void assign(entity_t *entity, TYPE component) { \ | |
entity->mask |= ENUM ; \ | |
resize(this->NAME##s, entity->id); \ | |
this->NAME##s[entity->id] = component; \ | |
} \ | |
TYPE & get_##NAME (int id) { \ | |
return NAME##s[id]; \ | |
} \ | |
void add_##NAME (entity_t *entity, TYPE comp) { \ | |
this->assign(entity, comp); \ | |
} | |
struct LuaSystem : system_t { | |
kaguya::LuaFunction luaProcess; | |
kaguya::LuaFunction luaUpdate; | |
LuaSystem(int priority, uint64_t mask, kaguya::LuaFunction process_fn, kaguya::LuaFunction update_fn); | |
void update(double dt); | |
}; | |
// WRYYYYYYYYYYYYYYYYYY | |
struct za_warudo : world_t { | |
// GENERATE_COMPONENT(COMPONENT_PLAYER, component_player_t, player); | |
void add_lua_system(kaguya::LuaTable params); | |
void add_entity(entity_t ent); | |
// fixes lua binding. | |
entity_t get_entity() { | |
return world_t::get_entity(); | |
} | |
}; | |
#undef GENERATE_COMPONENT | |
LuaSystem::LuaSystem(int priority, uint64_t mask, kaguya::LuaFunction process_fn, kaguya::LuaFunction update_fn): | |
luaProcess(process_fn), | |
luaUpdate(update_fn) | |
{ | |
this->priority = priority; | |
this->mask = mask; | |
} | |
static lua_State *s_lua = nullptr; | |
void LuaSystem::update(double dt) { | |
za_warudo *world = (za_warudo*)this->world; | |
kaguya::State lua(s_lua); | |
this->luaUpdate(dt); | |
for (auto &entity : world->entities) { | |
PECS_SKIP_INVALID_ENTITY; | |
auto components = lua.newTable(); | |
#define PUSH_COMPONENT(MASK, NAME) if ((this->mask & MASK) == MASK) { components[#NAME] = &world->get_##NAME(entity.id); } | |
// PUSH_COMPONENT(COMPONENT_RENDER, drawable); | |
#undef PUSH_COMPONENT | |
this->luaProcess(dt, entity, components); | |
} | |
} | |
void za_warudo::add_lua_system(kaguya::LuaTable params) { | |
int priority = params["priority"]; | |
uint64_t mask = 0; | |
bool valid; | |
auto values = params["components"].get<vector<uint64_t>>(valid, true); | |
for (uint64_t v : values) { | |
mask |= v; | |
} | |
if (mask == 0) { | |
mask = COMPONENT_NONE; | |
} | |
kaguya::LuaFunction fn1 = params["process"]; | |
kaguya::LuaFunction fn2 = params["update"]; | |
if (fn1.isNilref()) { | |
fn1 = kaguya::LuaFunction(); | |
} | |
if (fn2.isNilref()) { | |
fn2 = kaguya::LuaFunction(); | |
} | |
auto sys = new LuaSystem(priority, mask, fn1, fn2); | |
this->add(sys); | |
} | |
void za_warudo::add_entity(entity_t ent) { | |
this->add(ent); | |
} | |
extern "C" int luaopen_ldex(lua_State *L) { | |
s_lua = L; | |
kaguya::State lua(L); | |
kaguya::LuaTable module = lua.newTable(); | |
// lua["Player"].setClass(kaguya::UserdataMetatable<component_player_t>() | |
// .setConstructors<component_player_t()>() | |
// .addProperty("index", &component_player_t::index) | |
// ); | |
auto mt = kaguya::UserdataMetatable<za_warudo, world_t>() | |
.addFunction("add_system", &za_warudo::add_lua_system) | |
.addFunction("new_entity", &za_warudo::get_entity) | |
.addFunction("add_entity", &za_warudo::add_entity) | |
// .addFunction("add_player", &za_warudo::add_player) | |
; | |
module["World"].setClass(mt); | |
#define LSET(NAME) module[#NAME] = NAME | |
LSET(COMPONENT_NONE); | |
#undef LSET | |
return module.push(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment