Entity component access and manipulation in wren scripts working!

master
Joey Pollack 3 years ago
parent 204f0d294c
commit d2608b4851

@ -10,12 +10,13 @@
foreign class VelocityComponent { foreign class VelocityComponent {
// The parameter will be used on the C++ side to set the correct C++ component // The parameter will be used on the C++ side to set the correct C++ component
construct new(entity_id) { construct new(entity_id) {}
super.EntityID = entity_id
}
// maybe wrap these in non-foreign methods // maybe wrap these in non-foreign methods
// to abstract pulling data out of slots? // to abstract pulling data out of slots?
foreign GetVelocity() foreign GetVelocityX()
foreign GetVelocityY()
foreign SetVelocity(x, y) foreign SetVelocity(x, y)
} }

@ -6,6 +6,8 @@
* Description - The main interface for scripts to interact with the game world * Description - The main interface for scripts to interact with the game world
******************************************************************************/ ******************************************************************************/
import "Components" for VelocityComponent
// Manages all of the EntityBehaviors // Manages all of the EntityBehaviors
class WorldInterface { class WorldInterface {
@ -46,7 +48,9 @@ class WorldInterface {
// API // API
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
//foreign static GetVelocityComponent(entity_id) static GetVelocityComponent(entity_id) {
return VelocityComponent.new(entity_id)
}
} }

@ -16,6 +16,7 @@
namespace lunarium namespace lunarium
{ {
std::vector<WrenState::ForeignMethodDesc> WrenState::mForeignMethods; std::vector<WrenState::ForeignMethodDesc> WrenState::mForeignMethods;
std::vector<WrenState::ForeignClassDesc> WrenState::mForeignClasses;
WrenState::~WrenState() WrenState::~WrenState()
{ {
@ -36,6 +37,7 @@ namespace lunarium
config.writeFn = WrenState::WriteFN; config.writeFn = WrenState::WriteFN;
config.errorFn = WrenState::ErrorFN; config.errorFn = WrenState::ErrorFN;
config.bindForeignMethodFn = WrenState::BindForeignMethodFN; config.bindForeignMethodFn = WrenState::BindForeignMethodFN;
config.bindForeignClassFn = WrenState::BindForeignClassFN;
mpVM = wrenNewVM(&config); mpVM = wrenNewVM(&config);
@ -54,6 +56,11 @@ namespace lunarium
mForeignMethods.push_back(method_desc); mForeignMethods.push_back(method_desc);
} }
void WrenState::RegisterForeignClass(ForeignClassDesc class_desc)
{
mForeignClasses.push_back(class_desc);
}
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// HANDLES // HANDLES
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
@ -185,6 +192,7 @@ namespace lunarium
{ {
if (FMID == (*iter)) if (FMID == (*iter))
{ {
Logger::Trace(mLogCat, "Successfully bound foreign method: %s::%s", class_name, signature);
return iter->FM; return iter->FM;
} }
} }
@ -192,4 +200,21 @@ namespace lunarium
Logger::Error(mLogCat, "Failed to bind foreign method: %s::%s", class_name, signature); Logger::Error(mLogCat, "Failed to bind foreign method: %s::%s", class_name, signature);
return nullptr; return nullptr;
} }
WrenForeignClassMethods WrenState::BindForeignClassFN(WrenVM* vm, const char* module, const char* class_name)
{
ForeignClassDesc FCD = { module, class_name };
for (auto iter = mForeignClasses.begin(); iter != mForeignClasses.end(); iter++)
{
if (FCD == (*iter))
{
Logger::Trace(mLogCat, "Successfully bound foreign class: %s in module %s", class_name, module);
return iter->FCM;
}
}
Logger::Error(mLogCat, "Could not find foreign class: %s in module %s", class_name, module);
return WrenForeignClassMethods { nullptr, nullptr };
}
} }

@ -84,6 +84,7 @@ namespace lunarium
u32 GetLogCat() const; u32 GetLogCat() const;
void RegisterForeignMethod(ForeignMethodDesc method_desc); void RegisterForeignMethod(ForeignMethodDesc method_desc);
void RegisterForeignClass(ForeignClassDesc class_desc);
void RunScript(WrenScript* script); void RunScript(WrenScript* script);
void RunSnippet(std::string name, std::string code); void RunSnippet(std::string name, std::string code);
@ -100,7 +101,7 @@ public:
static void WriteFN(WrenVM* vm, const char* text); static void WriteFN(WrenVM* vm, const char* text);
static void ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message); static void ErrorFN(WrenVM* vm, WrenErrorType type, const char* module, int line, const char* message);
static WrenForeignMethodFn BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature); static WrenForeignMethodFn BindForeignMethodFN(WrenVM* vm, const char* module, const char* className, bool isStatic, const char* signature);
static WrenForeignClassMethods BindForeignClass(WrenVM* vm, const char* module, const char* className); static WrenForeignClassMethods BindForeignClassFN(WrenVM* vm, const char* module, const char* className);

@ -41,35 +41,9 @@ namespace lunarium
{ {
} }
void World::InitScriptState()
{
// mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state");
// // Register foreign methods
// mScriptState.RegisterForeignMethod({"WorldInterface", "WorldInterface", true, "GetComponent(_,_)", (WrenForeignMethodFn)&World::GetVelocityComponent});
// // Load the world interface script
// mWorldInterface.SetModuleName("WorldInterface");
// std::string code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data
// mWorldInterface.SetScriptCode(code);
// mScriptState.RunScript(&mWorldInterface);
// // Get class and method handles
// mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface");
// mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()");
// mWIDoOnLoadMethod = mScriptState.GetWrenMethodHandle("DoOnLoad()");
// mWIDoOnUnloadMethod = mScriptState.GetWrenMethodHandle("DoOnUnload()");
// mWIUpdateMethod = mScriptState.GetWrenMethodHandle("Update(_)");
// // Init the interface
// mScriptState.CallWrenMethod(mWIInitMethod, mWIHandle, {}, "WorldInterface.Init()");
}
void World::OnLoad() void World::OnLoad()
{ {
// InitScriptState();
WorldAPI::Initialize(this).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialized the world scripting api"); WorldAPI::Initialize(this).LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialized the world scripting api");
@ -90,17 +64,13 @@ namespace lunarium
} }
// Call OnLoad for each registered EntityBehavior class object // Call OnLoad for each registered EntityBehavior class object
//mScriptState.CallWrenMethod(mWIDoOnLoadMethod, mWIHandle, {}, "WorldInterface.DoOnLoad()");
WorldAPI::InvokeEvent(WorldAPI::Event::ON_LOAD); WorldAPI::InvokeEvent(WorldAPI::Event::ON_LOAD);
} }
void World::OnUnload() void World::OnUnload()
{ {
// TODO: Call OnUnLoad for each registered EntityBehavior class object // Call OnUnLoad for each registered EntityBehavior class object
//mScriptState.CallWrenMethod(mWIDoOnUnloadMethod, mWIHandle, {}, "WorldInterface.DoOnUnload()");
WorldAPI::InvokeEvent(WorldAPI::Event::ON_UNLOAD); WorldAPI::InvokeEvent(WorldAPI::Event::ON_UNLOAD);
//mScriptState.Shutdown();
WorldAPI::Shutdown(); WorldAPI::Shutdown();
} }
@ -118,7 +88,6 @@ namespace lunarium
{ {
// Update all scripts // Update all scripts
// Call Update for each registered EntityBehavior class object // Call Update for each registered EntityBehavior class object
//mScriptState.CallWrenMethod(mWIUpdateMethod, mWIHandle, { {WrenParamType::WPT_DOUBLE, (double)dt} }, "WorldInterface.Update(dt)");
WorldAPI::InvokeEvent(WorldAPI::Event::ON_UPDATE, dt); WorldAPI::InvokeEvent(WorldAPI::Event::ON_UPDATE, dt);
@ -176,6 +145,10 @@ namespace lunarium
mpActiveCamera = pCam; mpActiveCamera = pCam;
} }
/////////////////////////////////////////////////////////////////////
// ENTITY API
/////////////////////////////////////////////////////////////////////
entt::registry* World::GetEntityRegistry() entt::registry* World::GetEntityRegistry()
{ {
return &mECSRegistry; return &mECSRegistry;
@ -245,37 +218,37 @@ namespace lunarium
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
void World::DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform) // void World::DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform)
{ // {
// Draw current entity // // Draw current entity
Rectangle rect(my_trans.Position.x, my_trans.Position.y, bo_comp.Size.x, bo_comp.Size.y); // Rectangle rect(my_trans.Position.x, my_trans.Position.y, bo_comp.Size.x, bo_comp.Size.y);
Color color(bo_comp.Color.x, bo_comp.Color.y, bo_comp.Color.z, bo_comp.Color.w); // Color color(bo_comp.Color.x, bo_comp.Color.y, bo_comp.Color.z, bo_comp.Color.w);
g->DrawQuad(rect, color, nullptr, -my_trans.Rotation.z, Rectangle(-1, -1, -1, -1), current_transform); // g->DrawQuad(rect, color, nullptr, -my_trans.Rotation.z, Rectangle(-1, -1, -1, -1), current_transform);
// Apply transform to children's transforms // // Apply transform to children's transforms
current_transform *= my_trans.GetTransform(); // current_transform *= my_trans.GetTransform();
// Iterate and draw children // // Iterate and draw children
if (mECSRegistry.all_of<ChildrenComponent>(entity)) // if (mECSRegistry.all_of<ChildrenComponent>(entity))
{ // {
ChildrenComponent& children_comp = mECSRegistry.get<ChildrenComponent>(entity); // ChildrenComponent& children_comp = mECSRegistry.get<ChildrenComponent>(entity);
for (int i = 0; i < children_comp.Children.size(); i++) // for (int i = 0; i < children_comp.Children.size(); i++)
{ // {
Entity* pEnt = GetEntity(children_comp.Children[i]); // Entity* pEnt = GetEntity(children_comp.Children[i]);
entt::entity handle = pEnt->GetEnttHandle(); // entt::entity handle = pEnt->GetEnttHandle();
if (pEnt->HasComponent<TransformComponent>() && pEnt->HasComponent<BlockOutComponent>()) // if (pEnt->HasComponent<TransformComponent>() && pEnt->HasComponent<BlockOutComponent>())
{ // {
TransformComponent& trans_comp = pEnt->GetComponent<TransformComponent>(); // TransformComponent& trans_comp = pEnt->GetComponent<TransformComponent>();
BlockOutComponent& bo_comp = pEnt->GetComponent<BlockOutComponent>(); // BlockOutComponent& bo_comp = pEnt->GetComponent<BlockOutComponent>();
DrawHeirarchy(g, handle, trans_comp, bo_comp, current_transform); // DrawHeirarchy(g, handle, trans_comp, bo_comp, current_transform);
} // }
} // }
} // }
} // }
glm::mat4 World::GetParentTransform(LUUID parent) glm::mat4 World::GetParentTransform(LUUID parent)
{ {

@ -134,7 +134,7 @@ namespace lunarium
void InitScriptState(); void InitScriptState();
void RenderEditor(lunarium::Renderer2D* pGraphics) const; void RenderEditor(lunarium::Renderer2D* pGraphics) const;
glm::mat4 GetParentTransform(LUUID parent); glm::mat4 GetParentTransform(LUUID parent);
void DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform); //void DrawHeirarchy(lunarium::Renderer2D* g, entt::entity& entity, TransformComponent& my_trans, BlockOutComponent& bo_comp, glm::mat4 current_transform);
}; };
} }

@ -8,6 +8,7 @@
#include "world_api.h" #include "world_api.h"
#include "world.h" #include "world.h"
#include "entity.h"
#include <utils/logger.h> #include <utils/logger.h>
#include <utils/helpers.h> #include <utils/helpers.h>
@ -26,16 +27,27 @@ namespace lunarium
mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state"); mScriptState.Initialize().LogIfFailed(LogCategory::GAME_SYSTEM, "Failed to initialize the world script state");
// Register foreign methods // Register foreign methods
mScriptState.RegisterForeignMethod({"WorldInterface", "WorldInterface", true, "GetComponent(_,_)", (WrenForeignMethodFn)&WorldAPI::GetVelocityComponent}); //mScriptState.RegisterForeignMethod({"WorldInterface", "WorldInterface", true, "GetComponent(_,_)", (WrenForeignMethodFn)&WorldAPI::GetVelocityComponent});
// Register foreign classes
SetupForeignClassVelocityComp();
// Load the component script
WrenScript components;
components.SetModuleName("Components");
std::string code = File::ReadTextFile("components.wren"); // This will eventually move to internal data
components.SetScriptCode(code);
mScriptState.RunScript(&components);
// Load the world interface script // Load the world interface script
WrenScript world_interface; WrenScript world_interface;
world_interface.SetModuleName("WorldInterface"); world_interface.SetModuleName("WorldInterface");
std::string code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data code = File::ReadTextFile("world_interface.wren"); // This will eventually move to internal data
world_interface.SetScriptCode(code); world_interface.SetScriptCode(code);
mScriptState.RunScript(&world_interface); mScriptState.RunScript(&world_interface);
// Get class and method handles // Get class and method handles
mEventHandles.mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface"); mEventHandles.mWIHandle = mScriptState.GetWrenClassHandle("WorldInterface", "WorldInterface");
mEventHandles.mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()"); mEventHandles.mWIInitMethod = mScriptState.GetWrenMethodHandle("Init()");
@ -94,4 +106,62 @@ namespace lunarium
} }
/////////////////////////////////////////////////////////////////////
// FOREIGN CLASSES
/////////////////////////////////////////////////////////////////////
void WorldAPI::SetupForeignClassVelocityComp()
{
mScriptState.RegisterForeignClass({"Components", "VelocityComponent", sizeof(VelocityComponent*),
{(WrenForeignMethodFn)&WorldAPI::VelocityCompAllocate, &WorldAPI::VelocityCompFinalise}});
mScriptState.RegisterForeignMethod({"Components", "VelocityComponent", false, "GetVelocityX()",&WorldAPI::GetVelocityXFM});
mScriptState.RegisterForeignMethod({"Components", "VelocityComponent", false, "GetVelocityY()",(WrenForeignMethodFn)&WorldAPI::GetVelocityYFM});
mScriptState.RegisterForeignMethod({"Components", "VelocityComponent", false, "SetVelocity(_,_)", (WrenForeignMethodFn)&WorldAPI::SetVelocityFM});
}
void WorldAPI::VelocityCompAllocate(WrenVM* vm)
{
VelocityComponent** vcp = (VelocityComponent**)wrenSetSlotNewForeign(vm, 0, 0, sizeof(VelocityComponent*));
std::string str_entity_id = wrenGetSlotString(vm, 1);
LUUID entity_id = std::stoull(str_entity_id);
Entity* pEnt = mpWorld->GetEntity(entity_id);
if (!pEnt->HasComponent<VelocityComponent>())
{
Logger::Error(LogCategory::SCRIPTING, "Cannot allocate foreign class VelocityComponent - the entity does not have the component");
(*vcp) = nullptr;
}
(*vcp) = &pEnt->GetComponent<VelocityComponent>();
}
void WorldAPI::VelocityCompFinalise(void* data)
{
// Nothing to clean up
}
void WorldAPI::GetVelocityXFM(WrenVM* vm)
{
VelocityComponent** vcp = (VelocityComponent**)wrenGetSlotForeign(vm, 0);
wrenEnsureSlots(vm, 1);
wrenSetSlotDouble(vm, 0, (*vcp)->Velocity.x);
}
void WorldAPI::GetVelocityYFM(WrenVM* vm)
{
VelocityComponent** vcp = (VelocityComponent**)wrenGetSlotForeign(vm, 0);
wrenEnsureSlots(vm, 1);
wrenSetSlotDouble(vm, 0, (*vcp)->Velocity.y);
}
void WorldAPI::SetVelocityFM(WrenVM* vm)
{
VelocityComponent** vcp = (VelocityComponent**)wrenGetSlotForeign(vm, 0);
double x = wrenGetSlotDouble(vm, 1);
double y = wrenGetSlotDouble(vm, 2);
(*vcp)->Velocity.x = x;
(*vcp)->Velocity.y = y;
}
} }

@ -48,6 +48,14 @@ namespace lunarium
private: // SCRIPTING API private: // SCRIPTING API
static void GetVelocityComponent(WrenVM* vm); static void GetVelocityComponent(WrenVM* vm);
// Foreign classes
static void SetupForeignClassVelocityComp();
static void VelocityCompAllocate(WrenVM* vm);
static void VelocityCompFinalise(void* data);
static void GetVelocityXFM(WrenVM* vm);
static void GetVelocityYFM(WrenVM* vm);
static void SetVelocityFM(WrenVM* vm);
private: private:
static WrenState mScriptState; static WrenState mScriptState;
static World* mpWorld; static World* mpWorld;

Loading…
Cancel
Save