Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Resources/Engine/Lua/Scene/Actor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,15 @@ function Actor:GetPostProcessStack() end
---@return ReflectionProbe|nil
function Actor:GetReflectionProbe() end

--- Returns the component of the given type attached to this actor (If any)
---@param type string
---@return Component|nil
function Actor:GetComponent(type) end

--- Returns the Behaviour of the given type attached to this actor (If any)
---@param name string
---@param type string
---@return table|nil
function Actor:GetBehaviour(name) end
function Actor:GetBehaviour(type) end

--- Adds a Transform component to the actor and returns it
---@return Transform
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
* @licence: MIT
*/

#include <algorithm>
#include <array>
#include <filesystem>
#include <string_view>

#include <sol/sol.hpp>

Expand All @@ -27,6 +30,77 @@
#include <OvCore/ECS/Components/CSpotLight.h>
#include <OvCore/Scripting/Lua/LuaScriptEngine.h>

namespace
{
template<typename TComponent>
sol::object GetComponentByType(sol::state_view p_luaState, OvCore::ECS::Actor& p_actor)
{
if (auto component = p_actor.GetComponent<TComponent>())
{
return sol::make_object(p_luaState, component);
}

return sol::make_object(p_luaState, sol::nil);
}

using ComponentResolver = sol::object(*)(sol::state_view, OvCore::ECS::Actor&);

struct ComponentResolverEntry
{
std::string_view type;
ComponentResolver resolver;
};

template<typename TComponent>
constexpr ComponentResolverEntry MakeComponentResolverEntry(const std::string_view p_type)
{
return { p_type, &GetComponentByType<TComponent> };
}

sol::object ResolveComponentByType(sol::this_state p_luaState, OvCore::ECS::Actor& p_actor, const std::string& p_type)
{
using namespace OvCore::ECS::Components;

static const auto kComponentResolvers = std::to_array<ComponentResolverEntry>({
MakeComponentResolverEntry<CTransform>("Transform"),
MakeComponentResolverEntry<CPhysicalObject>("PhysicalObject"),
MakeComponentResolverEntry<CPhysicalBox>("PhysicalBox"),
MakeComponentResolverEntry<CPhysicalSphere>("PhysicalSphere"),
MakeComponentResolverEntry<CPhysicalCapsule>("PhysicalCapsule"),
MakeComponentResolverEntry<CCamera>("Camera"),
MakeComponentResolverEntry<CLight>("Light"),
MakeComponentResolverEntry<CPointLight>("PointLight"),
MakeComponentResolverEntry<CSpotLight>("SpotLight"),
MakeComponentResolverEntry<CDirectionalLight>("DirectionalLight"),
MakeComponentResolverEntry<CAmbientBoxLight>("AmbientBoxLight"),
MakeComponentResolverEntry<CAmbientSphereLight>("AmbientSphereLight"),
MakeComponentResolverEntry<CModelRenderer>("ModelRenderer"),
MakeComponentResolverEntry<CMaterialRenderer>("MaterialRenderer"),
MakeComponentResolverEntry<CSkinnedMeshRenderer>("SkinnedMeshRenderer"),
MakeComponentResolverEntry<CAudioSource>("AudioSource"),
MakeComponentResolverEntry<CAudioListener>("AudioListener"),
MakeComponentResolverEntry<CPostProcessStack>("PostProcessStack"),
MakeComponentResolverEntry<CReflectionProbe>("ReflectionProbe")
});

sol::state_view lua(p_luaState);

if (auto resolver = std::find_if(
kComponentResolvers.begin(),
kComponentResolvers.end(),
[&p_type](const ComponentResolverEntry& p_entry)
{
return p_entry.type == p_type;
}
); resolver != kComponentResolvers.end())
{
return resolver->resolver(lua, p_actor);
}

return sol::make_object(lua, sol::nil);
}
}

void BindLuaActor(sol::state& p_luaState)
{
using namespace OvCore::ECS;
Expand Down Expand Up @@ -69,14 +143,17 @@ void BindLuaActor(sol::state& p_luaState)
"GetAudioListener", &Actor::GetComponent<CAudioListener>,
"GetPostProcessStack", & Actor::GetComponent<CPostProcessStack>,
"GetReflectionProbe", &Actor::GetComponent<CReflectionProbe>,
"GetComponent", [](sol::this_state p_luaState, Actor& p_this, const std::string& p_type) -> sol::object {
return ResolveComponentByType(p_luaState, p_this, p_type);
},

/* Behaviours relatives */
"GetBehaviour", [](Actor& p_this, const std::string& p_name) -> sol::table {
"GetBehaviour", [](Actor& p_this, const std::string& p_type) -> sol::table {
// First try matching by script name (stem without path or extension)
OvCore::ECS::Components::Behaviour* behaviour = nullptr;
for (auto& [key, b] : p_this.GetBehaviours())
{
if (std::filesystem::path(b.name).stem().string() == p_name)
if (std::filesystem::path(b.name).stem().string() == p_type)
{
behaviour = &b;
break;
Expand All @@ -86,12 +163,12 @@ void BindLuaActor(sol::state& p_luaState)
// Fall back to path-based match: try as-is, then with .lua appended if no extension given
if (!behaviour)
{
behaviour = p_this.GetBehaviour(p_name);
behaviour = p_this.GetBehaviour(p_type);
}

if (!behaviour && std::filesystem::path(p_name).extension().empty())
if (!behaviour && std::filesystem::path(p_type).extension().empty())
{
behaviour = p_this.GetBehaviour(p_name + ".lua");
behaviour = p_this.GetBehaviour(p_type + ".lua");
}

if (behaviour)
Expand Down