diff --git a/Resources/Engine/Lua/Scene/Actor.lua b/Resources/Engine/Lua/Scene/Actor.lua index 9f70d651..6a40409c 100644 --- a/Resources/Engine/Lua/Scene/Actor.lua +++ b/Resources/Engine/Lua/Scene/Actor.lua @@ -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 diff --git a/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp index f73015be..25fa7e3f 100644 --- a/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp +++ b/Sources/OvCore/src/OvCore/Scripting/Lua/Bindings/LuaActorBindings.cpp @@ -4,7 +4,10 @@ * @licence: MIT */ +#include +#include #include +#include #include @@ -27,6 +30,77 @@ #include #include +namespace +{ + template + sol::object GetComponentByType(sol::state_view p_luaState, OvCore::ECS::Actor& p_actor) + { + if (auto component = p_actor.GetComponent()) + { + 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 + constexpr ComponentResolverEntry MakeComponentResolverEntry(const std::string_view p_type) + { + return { p_type, &GetComponentByType }; + } + + 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({ + MakeComponentResolverEntry("Transform"), + MakeComponentResolverEntry("PhysicalObject"), + MakeComponentResolverEntry("PhysicalBox"), + MakeComponentResolverEntry("PhysicalSphere"), + MakeComponentResolverEntry("PhysicalCapsule"), + MakeComponentResolverEntry("Camera"), + MakeComponentResolverEntry("Light"), + MakeComponentResolverEntry("PointLight"), + MakeComponentResolverEntry("SpotLight"), + MakeComponentResolverEntry("DirectionalLight"), + MakeComponentResolverEntry("AmbientBoxLight"), + MakeComponentResolverEntry("AmbientSphereLight"), + MakeComponentResolverEntry("ModelRenderer"), + MakeComponentResolverEntry("MaterialRenderer"), + MakeComponentResolverEntry("SkinnedMeshRenderer"), + MakeComponentResolverEntry("AudioSource"), + MakeComponentResolverEntry("AudioListener"), + MakeComponentResolverEntry("PostProcessStack"), + MakeComponentResolverEntry("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; @@ -69,14 +143,17 @@ void BindLuaActor(sol::state& p_luaState) "GetAudioListener", &Actor::GetComponent, "GetPostProcessStack", & Actor::GetComponent, "GetReflectionProbe", &Actor::GetComponent, + "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; @@ -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)