# Script to build source files
#
# Copyright (C) 2019 Clyne Sullivan
++# Copyright (C) 2019 Andy Belle-Isle
#
# 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
#
# 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
++# 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 <https://www.gnu.org/licenses/>.
++# along with this program. If not, see <https://www.gnu.org/licenses/>.
++#
++
++#
++# VARIABLES
#
CC = gcc
CXX = g++
++EXEC = main
++EXECDIR = .
++
++SRCDIR = src
++OUTDIR = out
++SRCEXT = cpp
++OBJEXT = o
++DEPEXT = d
++
LIBDIR = lib
--LIBS = -L$(LIBDIR) -lSDL2 -lpthread -lentityx -lluajit
++LIBS = -L$(LIBDIR) -lSDL2 -lpthread -lentityx -ldl -lluajit
--CXXFLAGS = -ggdb -std=c++17 \
-- -Wall -Wextra -Werror -pedantic \
- -Isrc -I$(LIBDIR)/LuaJIT -I$(LIBDIR)/entityx/entityx -I$(LIBDIR)/entityx
- -Isrc -I$(LIBDIR)/LuaJIT/src -I$(LIBDIR)/entityx
++CXXFLAGS = -ggdb -std=c++17 -Wall -Wextra -Werror -pedantic
--CXXSRCDIR = src
--CXXOUTDIR = out
--CXXSRC = $(wildcard $(CXXSRCDIR)/*.cpp) $(wildcard $(CXXSRCDIR)/*/*.cpp)
--CXXOBJ = $(patsubst $(CXXSRCDIR)/%.cpp, $(CXXOUTDIR)/%.o, $(CXXSRC))
++CXXINCS = -Isrc -I$(LIBDIR)/LuaJIT/src -I$(LIBDIR)/entityx
--EXEC = main
++CXXSRC := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
++CXXOBJ := $(patsubst $(SRCDIR)/%,$(OUTDIR)/%,$(CXXSRC:.$(SRCEXT)=.$(OBJEXT)))
++
++#
++# COMPILE STUFF
++#
++
++all: resources $(EXEC)
++
++resources: directories
--all: $(EXEC)
++directories:
++ @mkdir -p $(EXECDIR)
++ @mkdir -p $(OUTDIR)
clean:
-- @echo " CLEAN"
-- @rm -f $(EXEC)
-- @rm -rf out
++ @$(RM) -rf $(OUTDIR)
--$(EXEC): $(CXXOUTDIR) $(CXXOUTDIR)/$(CXXOBJ)
-- @echo " CXX/LD main"
-- @$(CXX) $(CXXFLAGS) -o $(EXEC) $(CXXOBJ) $(LIBS)
++cleaner: clean
++ @$(RM) -rf $(EXECDIR)
--$(CXXOUTDIR)/%.o: $(CXXSRCDIR)/%.cpp
-- @echo " CXX " $<
-- @$(CXX) $(CXXFLAGS) -c $< -o $@
++$(EXEC): $(CXXOBJ)
++ $(CXX) -o $(EXECDIR)/$(EXEC) $^ $(LIBS)
--$(CXXOUTDIR):
-- @mkdir $(CXXOUTDIR)
++$(OUTDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
++ @mkdir -p $(dir $@)
++ $(CXX) $(CXXFLAGS) $(CXXINCS) -c -o $@ $<
++ @$(CXX) $(CXXFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(OUTDIR)/$*.$(DEPEXT)
++ @cp -f $(OUTDIR)/$*.$(DEPEXT) $(OUTDIR)/$*.$(DEPEXT).tmp
++ @sed -e 's|.*:|$(OUTDIR)/$*.$(OBJEXT):|' < $(OUTDIR)/$*.$(DEPEXT).tmp > $(OUTDIR)/$*.$(DEPEXT)
++ @sed -e 's/.*://' -e 's/\\$$//' < $(OUTDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(OUTDIR)/$*.$(DEPEXT)
++ @rm -f $(OUTDIR)/$*.$(DEPEXT).tmp
++.PHONY: all remake clean cleaner resources
--- /dev/null
- #include "entityx_lua.h"
++//#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
+}