diff options
author | Andy Belle-Isle <drumsetmonkey@gmail.com> | 2019-08-29 01:39:40 -0400 |
---|---|---|
committer | Andy Belle-Isle <drumsetmonkey@gmail.com> | 2019-08-29 01:39:40 -0400 |
commit | e9758416b18b27a65337c28d9641afc0ee89b34b (patch) | |
tree | 2e4d3037aa5dbc71206c91a36ca7d00e108036ba | |
parent | 41addc2d6b600e9cade63884de1c13dba662dc31 (diff) |
Created (very messy) script system
-rw-r--r-- | Scripts/init.lua | 14 | ||||
-rw-r--r-- | src/Script/entityx/EntityLua.hpp | 242 | ||||
-rw-r--r-- | src/Script/entityx/LuaTypes.hpp | 96 | ||||
-rw-r--r-- | src/Script/entityx/entity_lua.cpp | 183 | ||||
-rw-r--r-- | src/Script/entityx/entity_lua.hpp | 13 | ||||
-rw-r--r-- | src/components/Component.hpp | 33 | ||||
-rw-r--r-- | src/components/Position.hpp | 47 | ||||
-rw-r--r-- | src/main.cpp | 118 | ||||
-rw-r--r-- | src/script.hpp | 154 |
9 files changed, 316 insertions, 584 deletions
diff --git a/Scripts/init.lua b/Scripts/init.lua index 20ea044..5b0f915 100644 --- a/Scripts/init.lua +++ b/Scripts/init.lua @@ -24,5 +24,19 @@ bird = { end } +dog = { + Position = { + x = 6.5, + y = 1.3 + }, + init = function(self) + print(self.Position.x .. "," .. self.Position.y) + end +} + birdSpawn = game.spawn(bird); birdSpawn:init() + +dogSpawn = game.spawn(dog); +dogSpawn:init() +dogSpawn.Position.x = 37.5 diff --git a/src/Script/entityx/EntityLua.hpp b/src/Script/entityx/EntityLua.hpp deleted file mode 100644 index 780f051..0000000 --- a/src/Script/entityx/EntityLua.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef ENTITYLUA_HPP -#define ENTITYLUA_HPP - -// Check is_trivially_destructible so we don't need __gc for userdata. -static_assert(std::is_trivially_destructible<entityx::Entity::Id>::value, "Entity::Id is not trivially destructible"); -// Check is_copy_constructible so that we can copy data onto memory for userdata created by lua. -static_assert(std::is_copy_constructible<entityx::Entity::Id>::value, "Entity::Id is not copy constructible"); - -namespace entityx -{ - namespace lua - { - typedef std::shared_ptr<entityx::EntityManager> EntityManagerSharedPtr; - - // This component is internally assigned to all entities created from lua. - // It is used to store the ref of the lua table - struct LuaComponent : entityx::Component<LuaComponent> - { - // ref of the lua object in LUA_REGISTRYINDEX - int ref; - LuaComponent(int ref = LUA_REFNIL) : ref(ref) {} - }; - - // This function should be called right after luaL_openlibs, to create global entityx table - void setup_entityx_api(lua_State* L); - - // This function add a new entity manager to lua global "entityx.xxx" where xxx is the name provided - void new_entity_manager(lua_State* L, const EntityManagerSharedPtr& manager, const char* name); - - // This function is used to push an entity manager to lua. - // It only pushes the userdata onto the stack, so use lua api such as lua_setglobal, - // lua_setfield, or lua_settable to really save it to lua. - void push_entity_manager(lua_State* L, const EntityManagerSharedPtr& manager); - - typedef std::map<std::string, std::function<void(lua_State*)>> ComponentList; - extern ComponentList components; - - template <typename C> - class MemberRegister - { - lua_State* L; - public: - MemberRegister(lua_State* L) : L(L) {} - - template <typename T> - void add(const char* name, T C::*ptr) - { - // Now the ComponentHandler should be at #-2 of stack (-1 is the metatable), this will be used as up-values - lua_pushvalue(L, -2); - // Also remember the offset - int offset = typename ComponentHelper<C>::offset(ptr); - lua_pushinteger(L, offset); - lua_pushcclosure(L, [](lua_State* L){ - // This function is used as both getter and setter: - // value = entity.comp.x() - // entity.comp.x(value) - // Note that self is not needed (that is, use comp.x() instead of comp:x()) - typename ComponentHelper<C>::ptr* pptr = static_cast<typename ComponentHelper<C>::ptr*>(lua_touserdata(L, lua_upvalueindex(1))); - int offset = lua_tointeger(L, lua_upvalueindex(2)); - - T& ref = typename ComponentHelper<C>::get(**pptr, offset); - if (lua_gettop(L) == 0 || lua_isnil(L, 1)) - { - // Getter mode, push value of at pptr - CToLua(L, ref); - } - else - { - // Setter mode, set value to pptr - LuaToC(L, ref); - } - return 1; - }, 2); - lua_setfield(L, -2, name); - } - }; - - template <typename C> - struct ComponentHelper - { - public: - // Use this ptr to get the ComponentHandle type, to support both 0.x and 1.x of entityx. - typedef decltype(entityx::Entity().assign<C>()) ptr; - - template <typename Member> - static ptrdiff_t offset(Member ptr) - { - C c; - return static_cast<char*>(static_cast<void*>(&(c.*ptr))) - static_cast<char*>(static_cast<void*>(&c)); - } - - template <typename T> - static T& get(C& c, ptrdiff_t offset) - { - return *static_cast<T*>(static_cast<void*>( - static_cast<char*>(static_cast<void*>(&c)) + offset - )); - } - - typedef std::function<void(MemberRegister<C>&)> memreg_func; - }; - - namespace lua_params - { - // gens<n>::type = seq<0, 1, ..., n-1> - template<int ...> - struct seq {}; - - template<int N, int ...S> - struct gens : gens<N - 1, N - 1, S...> { }; - - template<int ...S> - struct gens<0, S...> { - typedef seq<S...> type; - }; - - template <typename T> - T get_param_from_lua(lua_State* L, int n) - { - T ret; - lua_pushvalue(L, n); - LuaToC<T>(L, ret); - return ret; - } - - template <typename Func, typename Ret, typename... Args, int... N> - Ret call_func(lua_State* L, Func func, seq<N...>) - { - // This function is called with a table on top of the stack, - // first we call table.unpack to get the elements in the table - lua_getglobal(L, "table"); - lua_getfield(L, -1, "unpack"); - lua_remove(L, -2); // now function is pushed - lua_pushvalue(L, -2); // push the table - lua_call(L, 1, sizeof...(N)); // we only receive sizeof...(N) results - - // Then we call func with get_param_from_lua - int start_from = lua_gettop(L) - sizeof...(N)+1; - // Note that N... itself starts from 0 - return func(std::forward<Args>(get_param_from_lua<Args>(L, N + start_from))...); - } - - // std::function version - template <typename Ret, typename... Args> - Ret call_func(lua_State* L, const std::function<Ret(Args...)>& func) - { - return call_func<std::function<Ret(Args...)>, Ret, Args...>(L, func, gens<sizeof...(Args)>::type()); - } - } - - template <typename C, typename... Args> - std::function<C(lua_State*)> wrap_ctor(const std::function<C(Args...)>& func) - { - return [func](lua_State* L) { - return lua_params::call_func<C, Args...>(L, func); - }; - } - - template <typename C> - std::function<C(lua_State*)> wrap_ctor_no_args(C(*func)()) - { - return [func](lua_State* L) { - return lua_params::call_func<C>(L, func); - }; - } - - template <typename C> - std::function<C(lua_State*)> use_default_ctor() - { - static_assert(std::is_constructible<C>::value, "Not able to use default ctor here"); - return [](lua_State* L) { - return C(); - }; - } - - template <typename C, typename Str, typename Ctor> - void export_component(Str name, Ctor ctor, const std::function<void(MemberRegister<C>&)>& memreg) - { - static_assert(std::is_constructible<std::string, Str>::value, "Bad type of name"); - static_assert(std::is_same<Ctor, std::function<C(lua_State*)>>::value, "Bad type of ctor"); - - // Create memreg as a std::function - //ComponentHelper<C>::memreg_func memreg_func_save = memreg; - - std::function<void(lua_State*)> create_component = [ctor, memreg](lua_State* L) { - // This function is called with (name, entity_manager_weak_pointer, id, params) - EntityManagerSharedPtr* m = static_cast<EntityManagerSharedPtr*>(lua_touserdata(L, 2)); - entityx::Entity::Id* id = static_cast<entityx::Entity::Id*>(lua_touserdata(L, 3)); - entityx::Entity entity = (*m)->get(*id); - - typedef typename ComponentHelper<C>::ptr CompPtr; - // Create the c++ component - CompPtr component = entity.assign<C>(std::move(ctor(L))); - - // Create the component as a lightuserdata (although no data is stored in it) - lua_pushlightuserdata(L, 0); - - // Push CompPtr which will be used in MemberRegister (will be removed after pushing members) - lua_newuserdata(L, sizeof(CompPtr)); - new (lua_touserdata(L, -1)) CompPtr(component); - - // If needed, create metatable for it (we only need __gc) - if (!std::is_trivially_destructible<CompPtr>::value) - { - lua_newtable(L); - lua_pushcfunction(L, [](lua_State* L){ - CompPtr* component = static_cast<CompPtr*>(lua_touserdata(L, -1)); - component->~CompPtr(); - return 0; - }); - lua_setfield(L, -2, "__gc"); - lua_setmetatable(L, -2); - } - - // Stack: lightuserdata(0) | CompPtr - - // Create metatable for the lightuserdata - lua_newtable(L); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - - // Stack: lightuserdata(0) | CompPtr | metatable - - // Now we're ready to push members - MemberRegister<C> reg(L); - memreg(reg); - - // Stack: lightuserdata(0) | CompPtr | metatable - - // Remove the CompPtr - lua_remove(L, -2); - // Set metatable for the lightuserdata - lua_setmetatable(L, -2); - - // Leave the result on top of the stack - }; - components[name] = std::move(create_component); - } - } -} - -#endif//ENTITYLUA_HPP diff --git a/src/Script/entityx/LuaTypes.hpp b/src/Script/entityx/LuaTypes.hpp deleted file mode 100644 index 66d1f47..0000000 --- a/src/Script/entityx/LuaTypes.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef LUATYPES_HPP -#define LUATYPES_HPP - -#include "lua.hpp" - -namespace entityx -{ - namespace lua - { - /************* - * GENERIC * - *************/ - template<typename T> - inline void LuaToC(lua_State* L, T& ref); - - template<typename T> - inline void CToLua(lua_State* L, T& ref); - - /************ - * DOUBLE * - ************/ - template<> - inline void LuaToC<double>(lua_State* L, double& ref) - { - ref = lua_tonumber(L, -1); - } - - template<> - inline void CToLua(lua_State* L, double& ref) - { - lua_pushnumber(L, ref); - } - - /*********** - * FLOAT * - ***********/ - template<> - inline void LuaToC<float>(lua_State* L, float& ref) - { - ref = static_cast<float>(lua_tonumber(L, -1)); - } - - template<> - inline void CToLua<float>(lua_State* L, float& ref) - { - lua_pushnumber(L, ref); - } - - /************* - * INTEGER * - *************/ - template<> - inline void LuaToC<int>(lua_State* L, int& ref) - { - ref = lua_tointeger(L, -1); - } - - template<> - inline void CToLua<int>(lua_State* L, int& ref) - { - lua_pushnumber(L, ref); - } - - /************* - * BOOLEAN * - *************/ - template<> - inline void LuaToC<bool>(lua_State* L, bool& ref) - { - ref = lua_toboolean(L, -1); - } - - template<> - inline void CToLua<bool>(lua_State* L, bool& ref) - { - lua_pushboolean(L, ref); - } - - /************ - * STRING * - ************/ - template<> - inline void LuaToC<std::string>(lua_State* L, std::string& ref) - { - ref = lua_tostring(L, -1); - } - - template<> - inline void CToLua<std::string>(lua_State* L, std::string& ref) - { - lua_pushstring(L, ref.c_str()); - } - } -} - -#endif//LUATYPES_HPP diff --git a/src/Script/entityx/entity_lua.cpp b/src/Script/entityx/entity_lua.cpp deleted file mode 100644 index b23628b..0000000 --- a/src/Script/entityx/entity_lua.cpp +++ /dev/null @@ -1,183 +0,0 @@ -//#include "entityx_lua.h" -#include <Script/entityx/entity_lua.hpp> -#include <stdio.h> -#include <string.h> - -using namespace entityx::lua; -ComponentList entityx::lua::components; - -namespace { - int ref_EntityManagerSharedPtr = LUA_REFNIL; - int ref_EntityId = LUA_REFNIL; - const char* TypeName_EntityManagerSharedPtr = "EntityManagerSharedPtr"; - const char* TypeName_EntityId = "EntityId"; - const char* setup_lua_create_entity_factory = - "function entityx.create_entity_factory(entity_manager_pointer)\n" - " local c = {}\n" - " c.__index = c\n" - " function c:new()\n" - " local ret = {}\n" - " ret.__index = ret\n" - " function ret:init()\n" - " -- Empty\n" - " end\n" - " function ret:instance(param)\n" - " -- Make id const\n" - " local r = {}\n" - " local id = entityx.create_new_entity(entity_manager_pointer, r)\n" - " r.id = id\n" - " function r:component(name, params)\n" - " return entityx.create_new_component(name, entity_manager_pointer, id, params)\n" - " end\n" - " setmetatable(r, self)\n" - " r:init(param)\n" - " return r\n" - " end\n" - " return ret\n" - " end\n" - " function c:get(id)\n" - " return entityx.get_lua_object(entity_manager_pointer, id)\n" - " end\n" - " return c\n" - "end\n"; -} - -//TODO replace:entityx_lua:: settable->setfield/rawset -void entityx::lua::setup_entityx_api(lua_State* L) -{ - // Create metatables for userdata - // metatable for shared_ptr of EntityManager - lua_newtable(L); - lua_pushstring(L, TypeName_EntityManagerSharedPtr); - lua_setfield(L, -2, "type"); - lua_pushcfunction(L, [](lua_State* L){ - EntityManagerSharedPtr* ptr = static_cast<EntityManagerSharedPtr*>(lua_touserdata(L, 1)); - (*ptr).~EntityManagerSharedPtr(); - return 0; - }); - lua_setfield(L, -2, "__gc"); - ref_EntityManagerSharedPtr = luaL_ref(L, LUA_REGISTRYINDEX); - - // metatable for Entity::Id - lua_newtable(L); - lua_pushstring(L, TypeName_EntityId); - lua_setfield(L, -2, "type"); - // We don't need __gc for Entity::Id (with static_assert it is_trivially_destructible) - ref_EntityId = luaL_ref(L, LUA_REGISTRYINDEX); - - // Create global entityx table - lua_newtable(L); - - // create_new_entity - lua_pushcfunction(L, [](lua_State* L){ - // First check the type of the parameter - lua_getmetatable(L, 1); - lua_pushstring(L, "type"); - lua_rawget(L, -2); - if (!lua_isuserdata(L, 1) || strcmp(lua_tostring(L, -1), TypeName_EntityManagerSharedPtr) != 0 || !lua_istable(L, 2)) - { - lua_pushstring(L, "create_new_entity should be called with pointer of EntityManager and a table."); - return lua_error(L); - } - lua_pop(L, 2); - - lua_pushvalue(L, 2); - int ref = luaL_ref(L, LUA_REGISTRYINDEX); - - // Create an new entity - EntityManagerSharedPtr* ptr = static_cast<EntityManagerSharedPtr*>(lua_touserdata(L, 1)); - entityx::Entity entity = (*ptr)->create(); - - // Save the lua object (ref) in the entity - entity.assign<LuaComponent>(ref); - - // Return the Id of the entity - lua_newuserdata(L, sizeof(entityx::Entity::Id)); - lua_rawgeti(L, LUA_REGISTRYINDEX, ref_EntityId); - lua_setmetatable(L, -2); - new (lua_touserdata(L, -1)) entityx::Entity::Id(entity.id()); - - return 1; - }); - lua_setfield(L, -2, "create_new_entity"); - - // get_lua_object - lua_pushcfunction(L, [](lua_State* L){ - // First check the type of the parameters - lua_getmetatable(L, 1); - lua_pushstring(L, "type"); - lua_rawget(L, -2); - if (!lua_isuserdata(L, 1) || strcmp(lua_tostring(L, -1), TypeName_EntityManagerSharedPtr) != 0) - { - lua_pushstring(L, "get_lua_object should be called with pointer of EntityManager and an EntityId."); - return lua_error(L); - } - lua_pop(L, 2); - - lua_getmetatable(L, 2); - lua_pushstring(L, "type"); - lua_rawget(L, -2); - if (!lua_isuserdata(L, 2) || strcmp(lua_tostring(L, -1), TypeName_EntityId) != 0) - { - lua_pushstring(L, "get_lua_object should be called with pointer of EntityManager and an EntityId."); - return lua_error(L); - } - lua_pop(L, 2); - - // Get the object - EntityManagerSharedPtr* ptr = static_cast<EntityManagerSharedPtr*>(lua_touserdata(L, 1)); - entityx::Entity::Id* id = static_cast<entityx::Entity::Id*>(lua_touserdata(L, 2)); - - entityx::Entity entity = (*ptr)->get(*id); - int ref = entity.component<LuaComponent>()->ref; - - lua_rawgeti(L, LUA_REGISTRYINDEX, ref); - return 1; - }); - lua_setfield(L, -2, "get_lua_object"); - - // create_new_component - lua_pushcfunction(L, [](lua_State* L){ - ComponentList::iterator i; - //return 0; - if ((i = components.find(std::string(lua_tostring(L, 1)))) != components.end()) - { - i->second(L); - } - else - { - lua_pushstring(L, "Component not found."); - return lua_error(L); - } - return 1; - }); - lua_setfield(L, -2, "create_new_component"); - - lua_setglobal(L, "entityx"); - - luaL_loadstring(L, setup_lua_create_entity_factory); - lua_call(L, 0, 0); -} - -void entityx::lua::push_entity_manager(lua_State* L, const EntityManagerSharedPtr& manager) -{ - lua_newuserdata(L, sizeof(EntityManagerSharedPtr)); - lua_rawgeti(L, LUA_REGISTRYINDEX, ref_EntityManagerSharedPtr); - lua_setmetatable(L, -2); - - new (lua_touserdata(L, -1)) EntityManagerSharedPtr(manager); -} - -void entityx::lua::new_entity_manager(lua_State* L, const EntityManagerSharedPtr& manager, const char* name) -{ - lua_getglobal(L, "entityx"); - lua_getfield(L, -1, "create_entity_factory"); - lua_remove(L, -2); // _G["entityx"] - push_entity_manager(L, manager); - lua_pcall(L, 1, 1, 1); - - lua_getglobal(L, "entityx"); - lua_pushvalue(L, -2); - lua_setfield(L, -2, name); - lua_pop(L, 2); // original return value & entityx -} diff --git a/src/Script/entityx/entity_lua.hpp b/src/Script/entityx/entity_lua.hpp deleted file mode 100644 index bcad91c..0000000 --- a/src/Script/entityx/entity_lua.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ENTITY_LUA_HPP -#define ENTITY_LUA_HPP - -#include <map> -#include <type_traits> - -#include <lua.hpp> -#include <entityx/entityx.h> - -#include <Script/entityx/LuaTypes.hpp> -#include <Script/entityx/EntityLua.hpp> - -#endif//ENTITY_LUA_HPP diff --git a/src/components/Component.hpp b/src/components/Component.hpp new file mode 100644 index 0000000..84e860c --- /dev/null +++ b/src/components/Component.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * Author: Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef COMPONENT_HPP_ +#define COMPONENT_HPP_ + +#include "LuaBridge/LuaBridge.h" + +template <typename T> +class Component +{ + public: + Component(){}; + + virtual T FromLua(luabridge::LuaRef) = 0; +}; + +#endif//COMPONENT_HPP_ diff --git a/src/components/Position.hpp b/src/components/Position.hpp new file mode 100644 index 0000000..aaa99f9 --- /dev/null +++ b/src/components/Position.hpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2019 Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * Author: Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef POSITION_HPP_ +#define POSITION_HPP_ + +#include "components/Component.hpp" + +struct Position : Component<Position>, entityx::Component<Position> +{ + + public: + float x,y; + Position(float _x, float _y): x(_x), y(_y) {} + Position(void){x = y = 0.0;} + + Position FromLua(luabridge::LuaRef ref) + { + if (ref.isTable()){ + if (!ref["x"].isNil()) + this->x = ref["x"]; + if (!ref["y"].isNil()) + this->y = ref["y"]; + } else { + throw std::string("Position table not formatted properly"); + } + + return *this; + } +}; + +#endif//POSITION_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 57a4efb..23cfe2d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,6 @@ #include <lua.hpp> #include <entityx/entityx.h> -#include <Script/entityx/entity_lua.hpp> #include <LuaBridge/LuaBridge.h> #include <SDL2/SDL.h> @@ -31,6 +30,9 @@ #include <memory> #include <thread> +#include <components/Position.hpp> +#include <script.hpp> + class Window { private: constexpr static const char *title = "gamedev2"; @@ -140,16 +142,15 @@ void logicLoop(void) } } -struct Position : entityx::Component<Position> -{ - Position(float _x, float _y): x(_x), y(_y) {} - Position(void){x = y = 0.0;} - - float x,y; -}; +//struct Position : entityx::Component<Position> +//{ +// Position(float _x, float _y): x(_x), y(_y) {} +// Position(void){x = y = 0.0;} +// +// float x,y; +//}; using namespace entityx; -using namespace entityx::lua; namespace lb = luabridge; EventManager events; @@ -157,58 +158,75 @@ EntityManager entities(events); lua_State* L; +//lb::LuaRef spawn(lb::LuaRef ref) +//{ +// lb::LuaRef entity(L); +// entity = lb::newTable(L); +// +// if (ref.isTable()) { +// +// Entity e = entities.create(); +// +// for (auto &&comp : lb::pairs(ref)) { +// if (comp.first.cast<std::string>() == "Position") { +// entity["Position"] = +// e.assign<Position>(Position().FromLua(comp.second)).get(); +// } else if (comp.first.cast<std::string>() == "init") { +// entity["init"] = comp.second; +// } +// } +// } else { +// std::cerr << "Parameter to spawn() must be a table!" << std::endl; +// } +// +// return entity; +//} +// + +ScriptSystem sc; + lb::LuaRef spawn(lb::LuaRef ref) { - lb::LuaRef entity(L); - entity = lb::newTable(L); - - if (ref.isTable()) { - - Entity e = entities.create(); - - for (auto &&comp : lb::pairs(ref)) { - if (comp.first.cast<std::string>() == "Position") { - float x = comp.second["x"]; - float y = comp.second["y"]; - entity["Position"] = e.assign<Position>(x, y).get(); - } else if (comp.first.cast<std::string>() == "init") { - entity["init"] = comp.second; - } - } - } else { - std::cerr << "Parameter to spawn() must be a table!" << std::endl; - } - - return entity; + return sc.spawn(ref); } void LuaTest(void) { - - L = luaL_newstate(); - luaL_openlibs(L); - - lb::getGlobalNamespace(L). - beginNamespace("comp") - .beginClass<Position>("Position") - .addConstructor<void(*)(float, float)>() - .addProperty("x", &Position::x) - .addProperty("y", &Position::y) - .endClass() - .endNamespace(); - - lb::getGlobalNamespace(L) + + sc.configure(entities, events); + + // Functions export + lb::getGlobalNamespace(sc.getState()) .beginNamespace("game") .addFunction("spawn", spawn) .endNamespace(); - if (luaL_dofile(L, "Scripts/init.lua")) - { - std::cout << "Lua error: " << lua_tostring(L, -1) << std::endl; - } + sc.doFile(); + + + //L = luaL_newstate(); + //luaL_openlibs(L); + + //lb::getGlobalNamespace(L). + // beginNamespace("comp") + // .beginClass<Position>("Position") + // .addConstructor<void(*)(float, float)>() + // .addProperty("x", &Position::x) + // .addProperty("y", &Position::y) + // .endClass() + // .endNamespace(); + + //lb::getGlobalNamespace(L) + // .beginNamespace("game") + // .addFunction("spawn", spawn) + // .endNamespace(); + + //if (luaL_dofile(L, "Scripts/init.lua")) { + // std::cout << "Lua error: " << lua_tostring(L, -1) << std::endl; + //} - entities.each<Position>([&](Entity e, Position& p){ (void)e;std::cout << p.x << std::endl;}); + //entities.each<Position>([&](Entity, Position& p){std::cout << p.x << "," << p.y << std::endl;}); - lua_close(L); + //lua_close(L); } diff --git a/src/script.hpp b/src/script.hpp new file mode 100644 index 0000000..1dc2df2 --- /dev/null +++ b/src/script.hpp @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2019 Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * Author: Belle-Isle, Andrew <drumsetmonkey@gmail.com> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef SCRIPT_HPP_ +#define SCRIPT_HPP_ + +#include <entityx/entityx.h> +#include <lua.hpp> +#include <LuaBridge/LuaBridge.h> + +/**************** +* COMPONENTS * +****************/ +#include <components/Position.hpp> + +namespace lb = luabridge; + +struct EntitySpawnEvent { + EntitySpawnEvent (const lb::LuaRef ref) + : ref(ref){} + + lb::LuaRef ref; +}; + +/** + * @class ScriptSystem + * Handles all the game's scripting requests + */ +class ScriptSystem : public entityx::System<ScriptSystem> + , public entityx::Receiver<ScriptSystem> +{ + private: + /** + * The script systems internal lua state that handles all + * interactions between C and Lua + */ + std::unique_ptr<lua_State, void(*)(lua_State *)> state; + entityx::EventManager events; + entityx::EntityManager manager; + + public: + ScriptSystem(void) + : state(luaL_newstate(), lua_close), + manager(events){} + + ~ScriptSystem(void) + { + + } + + lua_State* getState() + { + return state.get(); + } + + int init(void) + { + luaL_openlibs(state.get()); + return 0; + } + + void configure([[maybe_unused]]entityx::EntityManager& entities, + [[maybe_unused]]entityx::EventManager& events) final + { + //manager = std::make_shared<entityx::EntityManager>(std::move(entities)); + + events.subscribe<EntitySpawnEvent>(*this); + + init(); + scriptExport(); + } + + void update([[maybe_unused]] entityx::EntityManager& entites, + [[maybe_unused]] entityx::EventManager& events, + [[maybe_unused]] entityx::TimeDelta dt) final + { + + } + + void doFile(void) + { + if (luaL_dofile(state.get(), "Scripts/init.lua")) { + std::cout << "Lua error: " << lua_tostring(state.get(), -1) << std::endl; + } + + manager.each<Position>([&](entityx::Entity, Position& p){std::cout << p.x << "," << p.y << std::endl;}); + + } + + lb::LuaRef spawn(lb::LuaRef ref) + { + lb::LuaRef entity(state.get()); + entity = lb::newTable(state.get()); + + if (ref.isTable()) { + + entityx::Entity e = manager.create(); + + for (auto &&comp : lb::pairs(ref)) { + if (comp.first.cast<std::string>() == "Position") { + entity["Position"] = + e.assign<Position>(Position().FromLua(comp.second)).get(); + } else if (comp.first.cast<std::string>() == "init") { + entity["init"] = comp.second; + } + } + } else { + std::cerr << "Parameter to spawn() must be a table!" << std::endl; + } + + return entity; + } + + void scriptExport() + { + // Components export + lb::getGlobalNamespace(state.get()). + beginNamespace("comp") + .beginClass<Position>("Position") + .addConstructor<void(*)(float, float)>() + .addProperty("x", &Position::x) + .addProperty("y", &Position::y) + .endClass() + .endNamespace(); + + // Functions export + //lb::getGlobalNamespace(state.get()) + // .beginNamespace("game") + // .addFunction("spawn", &ScriptSystem::spawn) + // .endNamespace(); + } + + void receive (const EntitySpawnEvent &spawn) + { + lb::push(state.get(), this->spawn(spawn.ref)); + } +}; + +#endif//SCRIPT_HPP_ |