diff --git a/data/levels/test/test.xml b/data/levels/test/test.xml
index 5edc3c9..b2a7dcd 100644
--- a/data/levels/test/test.xml
+++ b/data/levels/test/test.xml
@@ -8,5 +8,8 @@
+
+
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/data/scripts/game_init.lua b/data/scripts/game_init.lua
index 374d35f..cfd0924 100644
--- a/data/scripts/game_init.lua
+++ b/data/scripts/game_init.lua
@@ -1,8 +1,13 @@
-- Game initialization script
+-- загружаем скрипты
+load_script("game_object.lua")
+
-- глобальная таблица сущностей
g_entity_table = {
-- Lua class -- CPP class -- Description
- { "actor_player", "ActorBase", "Player actor entity" }
+ { "game_object", "Entity", "Test Lua Entity" }
+
+
}
\ No newline at end of file
diff --git a/src/engine/world.cpp b/src/engine/world.cpp
index ec6e91b..60e2125 100644
--- a/src/engine/world.cpp
+++ b/src/engine/world.cpp
@@ -62,8 +62,8 @@ void World::Render()
// Render entities
for (int i = 0; i < m_entities.size(); i++)
{
- if (frustum.CullBoundingBox(m_entities[i]->GetBoundingBox()))
- continue;
+ //if (frustum.CullBoundingBox(m_entities[i]->GetBoundingBox()))
+ // continue;
m_entities[i]->Render();
}
diff --git a/src/game/game.cpp b/src/game/game.cpp
index d9327fd..dbd74ce 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -6,6 +6,7 @@
#include "ientity.h"
#include "entitymanager.h"
#include "world.h"
+#include "game_object.h"
#include
@@ -67,10 +68,20 @@ void registerClasses()
// base thing
GetLuaState().GetGlobals().RegisterDirect("load_script", &luaLoadScript);
+ GetLuaState().DoString("g_factory = {}");
registerEngine();
}
+struct LuaPrototype
+{
+ std::string m_luaname;
+ std::string m_enginename;
+ std::string m_description;
+};
+
+std::vector g_prototypes;
+
void initializeEntityPrototypesFromLua()
{
using namespace LuaPlus;
@@ -80,9 +91,27 @@ void initializeEntityPrototypesFromLua()
LuaObject entityTable = it.GetValue();
assert(entityTable.IsTable());
- for (LuaTableIterator it2(entityTable); it2; it2.Next()) {
- Logger::Msg("%s", it2.GetValue().ToString());
+ if (entityTable.GetTableCount() < 3)
+ {
+ Core::Error("Entry in entity prototype table is bad, missing argument");
}
+
+ LuaObject luaname = entityTable[1];
+ LuaObject classname = entityTable[2];
+ LuaObject description = entityTable[3];
+
+ Logger::Msg("lua ent: name: %s classname: %s description: %s", luaname.ToString(), classname.ToString(), description.ToString());
+
+ LuaPrototype prototype;
+ prototype.m_luaname = luaname.ToString();
+ prototype.m_enginename = classname.ToString();
+ prototype.m_description = description.ToString();
+ g_prototypes.push_back(prototype);
+
+
+ /*for (LuaTableIterator it2(entityTable); it2; it2.Next()) {
+ Logger::Msg("%s", it2.GetValue().ToString());
+ }*/
}
}
@@ -149,6 +178,8 @@ void Game::LoadLevelXML(const char* mapname)
buffer, result.description(), result.offset);
}
+// std::map properties;
+
for (pugi::xml_node entity : doc.child("Level").child("Entities").children("Entity")) {
pugi::xml_attribute entityname = entity.attribute("name");
pugi::xml_attribute classname = entity.attribute("classname");
@@ -162,11 +193,75 @@ void Game::LoadLevelXML(const char* mapname)
}
}
- IEntityBase* entity = g_entityManager->CreateEntity(classname.as_string());
+ IEntityBase* entity = Lua_CreateEntity(classname.as_string());
+
+ // this is pure C++ entity :)
+ if (!entity)
+ entity = g_entityManager->CreateEntity(classname.as_string());
+
+ //IEntityBase* entity = g_entityManager->CreateEntity(classname.as_string());
g_world->AddEntity(entity);
}
}
+IEntityBase* Game::Lua_CreateEntity(const char* classname)
+{
+ using namespace LuaPlus;
+
+ //if (!classname)
+ // classname = "Entity";
+
+ SDL_assert_always(classname);
+
+ LuaPrototype* pluaprototype = nullptr;
+
+ // find a prototype
+ for (std::vector::iterator it = g_prototypes.begin();
+ it != g_prototypes.end();
+ ++it)
+ {
+ if (strcmp((*it).m_luaname.c_str(), classname) == 0)
+ {
+ pluaprototype = &(*it);
+ break;
+ }
+ }
+
+ if (pluaprototype)
+ {
+ Entity* entity = static_cast(g_entityManager->CreateEntity(pluaprototype->m_enginename.c_str()));
+ SDL_assert_always(entity);
+
+ // get a prototype
+ LuaObject prototype = GetLuaState().GetGlobal(pluaprototype->m_luaname.c_str());
+ SDL_assert_always(!prototype.IsNil());
+ prototype.SetObject("__index", prototype);
+
+ // generate table
+ LuaObject factory = GetLuaState().GetGlobal("g_factory");
+
+ // generate name
+ std::string entityname = pluaprototype->m_luaname + "_" + std::to_string(factory.GetTableCount());
+
+ // create an table
+ LuaObject entityTable = GetLuaState().GetGlobals().CreateTable(entityname.c_str());
+ entityTable.SetMetatable(prototype);
+ entityTable.SetString("m_name", entityname.c_str());
+
+ // push in to the factory
+ factory.SetObject(entityname.c_str(), entityTable);
+
+ // link to the entity
+ entity->InitFromTable(entityTable);
+
+ return entity;
+ }
+
+ //IEntityBase* entity = g_entityManager->CreateEntity(classname);
+
+ return nullptr;
+}
+
void Game::Shutdown()
{
}
diff --git a/src/game/game.h b/src/game/game.h
index 549f78f..ae74b81 100644
--- a/src/game/game.h
+++ b/src/game/game.h
@@ -1,6 +1,8 @@
#ifndef GAME_H
#define GAME_H
+class IEntityBase;
+
class Game
{
public:
@@ -9,6 +11,8 @@ public:
void LoadLevelXML(const char* mapname);
+ IEntityBase* Lua_CreateEntity(const char* classname);
+
void Shutdown();
};
diff --git a/src/game/game_object.cpp b/src/game/game_object.cpp
index 363901a..5d33cb1 100644
--- a/src/game/game_object.cpp
+++ b/src/game/game_object.cpp
@@ -2,6 +2,15 @@
#include "game_object.h"
#include
+// Lua wrappers
+void Entity_LoadModel(LuaPlus::LuaState* state)
+{
+ LuaPlus::LuaStack stack(state);
+
+ Entity* entity = (Entity*)stack[1].GetByName("__object").GetLightUserdata();
+ entity->LoadModel(stack[2].GetString());
+}
+
REGISTER_ENTITY(Entity);
Entity::Entity() :
@@ -11,6 +20,32 @@ Entity::Entity() :
Entity::~Entity()
{
+ if (m_onShutdownFunction.IsFunction())
+ {
+ LuaPlus::LuaFunctionVoid function = m_onShutdownFunction;
+ function(m_luaObject);
+ }
+
+ if (m_luaObject.IsTable())
+ {
+ LuaPlus::LuaObject name = m_luaObject["m_name"];
+ if (name.IsString())
+ {
+ LuaPlus::LuaObject factory = GetLuaState().GetGlobal("g_factory");
+ factory.SetNil(m_luaObject);
+ }
+
+ m_luaObject.AssignNil();
+ }
+}
+
+void Entity::Update(float dt)
+{
+ if ( m_onUpdateFunction.IsFunction())
+ {
+ LuaPlus::LuaFunctionVoid function = m_onUpdateFunction;
+ function(m_luaObject, dt);
+ }
}
void Entity::Render()
@@ -24,6 +59,43 @@ void Entity::LoadModel(const char* filename)
m_model = g_modelSystem->LoadModel(filename);
}
+void Entity::SetVisible(bool visible)
+{
+}
+
+bool Entity::GetVisible()
+{
+ return true;
+}
+
+void Entity::InitFromTable(LuaPlus::LuaObject& _object)
+{
+ SDL_assert_always(!_object.IsNil() && "Invalid object passed");
+
+ // catch table instance
+ m_luaObject = _object;
+
+ // find functions
+ m_onInitFunction = m_luaObject.GetByName("on_init");
+ m_onShutdownFunction = m_luaObject.GetByName("on_shutdown");
+ m_onUpdateFunction = m_luaObject.GetByName("on_update");
+
+ // check
+ SDL_assert_always(m_onInitFunction.IsFunction() || m_onShutdownFunction.IsFunction() || m_onUpdateFunction.IsFunction());
+
+ // register entity functions
+ m_luaObject.RegisterDirect("load_model", &Entity_LoadModel);
+ //m_luaObject.RegisterDirect("set_visible", &Entity::SetVisible);
+ //m_luaObject.RegisterDirect("get_visible", &Entity::GetVisible);
+
+ // assign C++ object
+ m_luaObject.SetLightUserdata("__object", this);
+
+ // call init
+ LuaPlus::LuaFunctionVoid onInitFunction = m_onInitFunction;
+ onInitFunction(m_luaObject);
+}
+
REGISTER_ENTITY(TempPlayer);
TempPlayer::TempPlayer()
diff --git a/src/game/game_object.h b/src/game/game_object.h
index c9732e5..423f9c6 100644
--- a/src/game/game_object.h
+++ b/src/game/game_object.h
@@ -7,6 +7,8 @@
#include "render/model.h"
#include "render/modelsystem.h"
+#include "game_lua_help.h"
+
enum EMovmentDir
{
EMovementDir_None = 1 << 0,
@@ -22,12 +24,24 @@ public:
Entity();
virtual ~Entity();
+ virtual void Update(float dt);
virtual void Render();
+ // Game entity extensions
virtual void LoadModel(const char* filename);
+ void SetVisible(bool visible);
+ bool GetVisible();
+
+
+ void InitFromTable(LuaPlus::LuaObject& _object);
protected:
Model* m_model;
+
+ LuaPlus::LuaObject m_luaObject;
+ LuaPlus::LuaObject m_onInitFunction;
+ LuaPlus::LuaObject m_onShutdownFunction;
+ LuaPlus::LuaObject m_onUpdateFunction;
};
class TempPlayer : public Entity
diff --git a/src/render/render.cpp b/src/render/render.cpp
index 27e4bec..0b808cf 100644
--- a/src/render/render.cpp
+++ b/src/render/render.cpp
@@ -87,6 +87,8 @@ void Render::Init(SDL_Window* pWindow)
m_pWindow = pWindow;
SDL_assert(m_pWindow);
+ Msg("Initializing renderer ...");
+
// Create OpenGL context
m_pGLContext = SDL_GL_CreateContext(m_pWindow);
SDL_GL_MakeCurrent(m_pWindow, m_pGLContext);