Lua script
This commit is contained in:
@@ -8,5 +8,8 @@
|
||||
<Entity classname="TempPlayer">
|
||||
<IsDisableled value="false" />
|
||||
</Entity>
|
||||
<Entity classname="game_object">
|
||||
<IsDisableled value="false" />
|
||||
</Entity>
|
||||
</Entities>
|
||||
</Level>
|
||||
</Level>
|
||||
@@ -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" }
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ientity.h"
|
||||
#include "entitymanager.h"
|
||||
#include "world.h"
|
||||
#include "game_object.h"
|
||||
|
||||
#include <pugixml.hpp>
|
||||
|
||||
@@ -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<LuaPrototype> 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<std::string, std::string> 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<LuaPrototype>::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<Entity*>(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()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
};
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
#include "game_object.h"
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
// 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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user