Navigation Menu

Skip to content

Commit

Permalink
feat(ecs): add component property meta type data
Browse files Browse the repository at this point in the history
Add Lua bindings:
- ents.ComponentInfo.MemberInfo:FindTypeMetaData
- Add ents.ComponentInfo.MemberInfo.TypeMetaData, .RageTypeMetaData, .CoordinateTypeMetaData, .PoseTypeMetaData
- Add math.CoordinateSpace enums

- Add support for Transform and ScaledTransform component property types
  • Loading branch information
Silverlan committed Feb 5, 2023
1 parent 5bde6fc commit fed2d66
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 41 deletions.
22 changes: 4 additions & 18 deletions core/client/src/entities/components/eye/c_eye_component.cpp
Expand Up @@ -36,27 +36,13 @@ void CEyeComponent::RegisterMembers(pragma::EntityComponentManager &componentMan
using T = CEyeComponent;

{
auto coordMetaData = std::make_shared<ents::CoordinateTypeMetaData>();
coordMetaData->space = umath::CoordinateSpace::Local;

using TViewTarget = Vector3;
auto memberInfo = create_component_member_info<T, TViewTarget, static_cast<void (T::*)(const Vector3 &)>(&T::SetViewTarget), [](const ComponentMemberInfo &, T &c, TViewTarget &value) { value = c.m_viewTarget; }>("viewTarget", Vector3 {});
memberInfo.SetFlag(pragma::ComponentMemberFlags::ObjectSpace);
registerMember(std::move(memberInfo));
}

{
using TViewTarget = Vector3;
auto memberInfo = create_component_member_info<T, TViewTarget,
[](const ComponentMemberInfo &, T &c, TViewTarget value) {
auto pose = c.GetEntity().GetPose();
value = pose.GetInverse() * value;
c.m_viewTarget = value;
},
[](const ComponentMemberInfo &, T &c, TViewTarget &value) {
auto pose = c.GetEntity().GetPose();
value = pose * c.m_viewTarget;
}>("viewTargetWs", Vector3 {});
memberInfo.SetFlag(pragma::ComponentMemberFlags::HideInInterface | pragma::ComponentMemberFlags::Controller);
auto &meta = memberInfo.AddMetaData();
meta["controllerTarget"] = "ec/eye/viewTarget";
memberInfo.AddTypeMetaData(coordMetaData);
registerMember(std::move(memberInfo));
}

Expand Down
Expand Up @@ -128,11 +128,13 @@ namespace pragma {
const Vector3 *GetBonePosition(UInt32 boneId) const;
// Returns the bone rotation in bone space, or null if the bone doesn't exist.
const Quat *GetBoneRotation(UInt32 boneId) const;
const umath::ScaledTransform *GetBonePose(UInt32 boneId) const;
void SetBonePosition(UInt32 boneId, const Vector3 &pos, const Quat &rot, const Vector3 &scale);
void SetBonePosition(UInt32 boneId, const Vector3 &pos, const Quat &rot);
void SetBonePosition(UInt32 boneId, const Vector3 &pos, const EulerAngles &ang);
void SetBonePosition(UInt32 boneId, const Vector3 &pos);
void SetBoneRotation(UInt32 boneId, const Quat &rot);
void SetBonePose(UInt32 boneId, const umath::ScaledTransform &pose);
void SetLocalBonePosition(UInt32 boneId, const Vector3 &pos, const Quat &rot, const Vector3 &scale);
void SetLocalBonePosition(UInt32 boneId, const Vector3 &pos, const Quat &rot);
void SetLocalBonePosition(UInt32 boneId, const Vector3 &pos);
Expand Down
Expand Up @@ -17,7 +17,7 @@
class BaseEntity;
namespace pragma {
constexpr bool is_animatable_type(udm::Type type) { return panima::is_animatable_type(type); }
constexpr bool is_valid_component_property_type(udm::Type type) { return is_animatable_type(type) || type == udm::Type::String; }
constexpr bool is_valid_component_property_type(udm::Type type) { return is_animatable_type(type) || type == udm::Type::String || type == udm::Type::Transform || type == udm::Type::ScaledTransform; }
constexpr bool is_valid_component_property_type(pragma::ents::EntityMemberType type)
{
static_assert(umath::to_integral(pragma::ents::EntityMemberType::VersionIndex) == 0);
Expand Down
Expand Up @@ -10,6 +10,7 @@
#include "pragma/networkdefinitions.h"
#include <functional>
#include <optional>
#include <typeindex>

namespace udm {
enum class Type : uint8_t;
Expand All @@ -21,10 +22,29 @@ namespace udm {
namespace pragma {
namespace ents {
enum class EntityMemberType : uint8_t;

struct TypeMetaData {
virtual ~TypeMetaData() = default;
};
struct RangeTypeMetaData : public TypeMetaData {
std::optional<float> min {};
std::optional<float> max {};
std::optional<float> stepSize {};
};

struct CoordinateTypeMetaData : public TypeMetaData {
umath::CoordinateSpace space = umath::CoordinateSpace::World;
std::string parentProperty;
};

struct PoseTypeMetaData : public TypeMetaData {
std::string poseProperty;
};
};
class BaseEntityComponent;
enum class AttributeSpecializationType : uint8_t;
enum class ComponentMemberFlags : uint32_t;

struct DLLNETWORK ComponentMemberInfo {
struct DLLNETWORK EnumConverter {
using NameToEnumFunction = std::function<std::optional<int64_t>(const std::string &)>;
Expand Down Expand Up @@ -115,12 +135,18 @@ namespace pragma {
void SetMin(float min);
void SetMax(float max);
void SetStepSize(float stepSize);
std::optional<float> GetMin() const;
std::optional<float> GetMax() const;
std::optional<float> GetStepSize() const;
udm::Property &AddMetaData();
void AddMetaData(const udm::PProperty &prop);
const udm::PProperty &GetMetaData() const;
std::optional<float> GetMin() const { return m_min; }
std::optional<float> GetMax() const { return m_max; }
std::optional<float> GetStepSize() const { return m_stepSize; }
void AddTypeMetaData(const std::shared_ptr<ents::TypeMetaData> &typeMetaData);
const ents::TypeMetaData *FindTypeMetaData(std::type_index typeId) const;
template<class T>
T &AddTypeMetaData();
template<class T>
const T *FindTypeMetaData() const;
template<typename T>
bool GetDefault(T &outValue) const;
template<typename T>
Expand Down Expand Up @@ -160,12 +186,30 @@ namespace pragma {
std::unique_ptr<std::string> m_customSpecializationType = nullptr;

udm::PProperty m_metaData = nullptr;
std::optional<float> m_min {};
std::optional<float> m_max {};
std::optional<float> m_stepSize {};
std::vector<std::shared_ptr<ents::TypeMetaData>> m_typeMetaData;
std::unique_ptr<void, void (*)(void *)> m_default = std::unique_ptr<void, void (*)(void *)> {nullptr, [](void *) {}};
std::unique_ptr<EnumConverter> m_enumConverter = nullptr;
};
};

template<class T>
T &pragma::ComponentMemberInfo::AddTypeMetaData()
{
auto *data = const_cast<ComponentMemberInfo *>(this)->FindTypeMetaData<T>();
if(data)
return *const_cast<T *>(data);
auto newData = std::shared_ptr<ents::TypeMetaData>(new T {});
AddTypeMetaData(newData);
return *static_cast<T *>(newData.get());
}

template<class T>
const T *pragma::ComponentMemberInfo::FindTypeMetaData() const
{
auto *data = FindTypeMetaData(typeid(T));
if(!data)
return nullptr;
return static_cast<const T *>(data);
}

#endif
50 changes: 46 additions & 4 deletions core/shared/src/entities/components/base_animated_component.cpp
Expand Up @@ -12,6 +12,7 @@
#include "pragma/entities/components/base_physics_component.hpp"
#include "pragma/entities/components/base_sound_emitter_component.hpp"
#include "pragma/entities/components/panima_component.hpp"
#include "pragma/entities/components/component_member_flags.hpp"
#include "pragma/entities/entity_component_system_t.hpp"
#include "pragma/model/model.h"
#include "pragma/audio/alsound_type.h"
Expand Down Expand Up @@ -213,15 +214,45 @@ void BaseAnimatedComponent::OnModelChanged(const std::shared_ptr<Model> &mdl)
auto &skeleton = mdl->GetSkeleton();
auto &bones = skeleton.GetBones();
ReserveMembers(bones.size() * 3);
for(auto &bone : skeleton.GetBones()) {
const auto &name = bone->name;
std::function<void(const panima::Bone &, const std::string &)> fAddBone = nullptr;
fAddBone = [&](const panima::Bone &bone, const std::string &parentPathName) {
const auto &name = bone.name;
auto lname = name;
// ustring::to_lower(lname);

std::string posePathName = "bone/" + lname + "/pose";
auto poseMetaData = std::make_shared<ents::PoseTypeMetaData>();
poseMetaData->poseProperty = posePathName;

auto coordMetaData = std::make_shared<ents::CoordinateTypeMetaData>();
coordMetaData->space = umath::CoordinateSpace::Local;
coordMetaData->parentProperty = parentPathName;

auto memberInfoPose = pragma::ComponentMemberInfo::CreateDummy();
memberInfoPose.SetName(posePathName);
memberInfoPose.type = ents::EntityMemberType::ScaledTransform;
memberInfoPose.userIndex = bone.ID;
memberInfoPose.SetFlag(pragma::ComponentMemberFlags::HideInInterface);
memberInfoPose.AddTypeMetaData(coordMetaData);
memberInfoPose.SetGetterFunction<BaseAnimatedComponent, umath::ScaledTransform,
static_cast<void (*)(const pragma::ComponentMemberInfo &, BaseAnimatedComponent &, umath::ScaledTransform &)>([](const pragma::ComponentMemberInfo &memberInfo, BaseAnimatedComponent &component, umath::ScaledTransform &outValue) {
auto *pose = component.GetBonePose(memberInfo.userIndex);
if(!pose) {
outValue = {};
return;
}
outValue = *pose;
})>();
memberInfoPose.SetSetterFunction<BaseAnimatedComponent, umath::ScaledTransform,
static_cast<void (*)(const pragma::ComponentMemberInfo &, BaseAnimatedComponent &, const umath::ScaledTransform &)>(
[](const pragma::ComponentMemberInfo &memberInfo, BaseAnimatedComponent &component, const umath::ScaledTransform &value) { component.SetBonePose(memberInfo.userIndex, value); })>();

auto memberInfoPos = pragma::ComponentMemberInfo::CreateDummy();
memberInfoPos.SetName("bone/" + lname + "/position");
memberInfoPos.type = ents::EntityMemberType::Vector3;
memberInfoPos.userIndex = bone->ID;
memberInfoPos.userIndex = bone.ID;
memberInfoPos.AddTypeMetaData(coordMetaData);
memberInfoPos.AddTypeMetaData(poseMetaData);
memberInfoPos.SetGetterFunction<BaseAnimatedComponent, Vector3, static_cast<void (*)(const pragma::ComponentMemberInfo &, BaseAnimatedComponent &, Vector3 &)>([](const pragma::ComponentMemberInfo &memberInfo, BaseAnimatedComponent &component, Vector3 &outValue) {
auto *pos = component.GetBonePosition(memberInfo.userIndex);
if(!pos) {
Expand All @@ -236,6 +267,9 @@ void BaseAnimatedComponent::OnModelChanged(const std::shared_ptr<Model> &mdl)
auto memberInfoRot = memberInfoPos;
memberInfoRot.SetName("bone/" + lname + "/rotation");
memberInfoRot.type = ents::EntityMemberType::Quaternion;
memberInfoRot.userIndex = bone.ID;
memberInfoRot.AddTypeMetaData(coordMetaData);
memberInfoRot.AddTypeMetaData(poseMetaData);
memberInfoRot.SetGetterFunction<BaseAnimatedComponent, Quat, static_cast<void (*)(const pragma::ComponentMemberInfo &, BaseAnimatedComponent &, Quat &)>([](const pragma::ComponentMemberInfo &memberInfo, BaseAnimatedComponent &component, Quat &outValue) {
auto *rot = component.GetBoneRotation(memberInfo.userIndex);
if(!rot) {
Expand All @@ -249,6 +283,9 @@ void BaseAnimatedComponent::OnModelChanged(const std::shared_ptr<Model> &mdl)

auto memberInfoScale = memberInfoPos;
memberInfoScale.SetName("bone/" + lname + "/scale");
memberInfoScale.userIndex = bone.ID;
memberInfoScale.AddTypeMetaData(coordMetaData);
memberInfoScale.AddTypeMetaData(poseMetaData);
memberInfoScale.SetGetterFunction<BaseAnimatedComponent, Vector3, static_cast<void (*)(const pragma::ComponentMemberInfo &, BaseAnimatedComponent &, Vector3 &)>([](const pragma::ComponentMemberInfo &memberInfo, BaseAnimatedComponent &component, Vector3 &outValue) {
auto *scale = component.GetBoneScale(memberInfo.userIndex);
if(!scale) {
Expand All @@ -263,7 +300,12 @@ void BaseAnimatedComponent::OnModelChanged(const std::shared_ptr<Model> &mdl)
RegisterMember(std::move(memberInfoPos));
RegisterMember(std::move(memberInfoRot));
RegisterMember(std::move(memberInfoScale));
}

for(auto &pair : bone.children)
fAddBone(*pair.second, posePathName);
};
for(auto &pair : skeleton.GetRootBones())
fAddBone(*pair.second, "");
}

CallbackHandle BaseAnimatedComponent::BindAnimationEvent(AnimationEvent::Type eventId, const std::function<void(std::reference_wrapper<const AnimationEvent>)> &fCallback)
Expand Down
Expand Up @@ -120,6 +120,12 @@ const Quat *BaseAnimatedComponent::GetBoneRotation(UInt32 boneId) const
return nullptr;
return &m_bones[boneId].GetRotation();
}
const umath::ScaledTransform *BaseAnimatedComponent::GetBonePose(UInt32 boneId) const
{
if(boneId >= m_bones.size())
return nullptr;
return &m_bones[boneId];
}
// See also lanimation.cpp
Bool BaseAnimatedComponent::GetLocalBonePosition(UInt32 boneId, Vector3 &pos, Quat &rot, Vector3 *scale) const
{
Expand Down Expand Up @@ -240,6 +246,16 @@ void BaseAnimatedComponent::SetBoneRotation(UInt32 boneId, const Quat &rot)
CEOnBoneTransformChanged evData {boneId, nullptr, &rot, nullptr};
InvokeEventCallbacks(EVENT_ON_BONE_TRANSFORM_CHANGED, evData);
}
void BaseAnimatedComponent::SetBonePose(UInt32 boneId, const umath::ScaledTransform &pose)
{
if(boneId >= m_bones.size())
return;
m_bones[boneId] = pose;
umath::set_flag(m_stateFlags, StateFlags::AbsolutePosesDirty);

CEOnBoneTransformChanged evData {boneId, &pose.GetOrigin(), &pose.GetRotation(), nullptr};
InvokeEventCallbacks(EVENT_ON_BONE_TRANSFORM_CHANGED, evData);
}

void BaseAnimatedComponent::SetLocalBonePosition(UInt32 boneId, const Vector3 &pos, const Quat &rot, const Vector3 &scale)
{
Expand Down
26 changes: 22 additions & 4 deletions core/shared/src/entities/components/base_transform_component.cpp
Expand Up @@ -12,6 +12,7 @@
#include "pragma/entities/components/base_model_component.hpp"
#include "pragma/entities/components/base_observable_component.hpp"
#include "pragma/entities/components/panima_component.hpp"
#include "pragma/entities/components/component_member_flags.hpp"
#include "pragma/entities/baseentity_events.hpp"
#include "pragma/entities/entity_component_manager_t.hpp"
#include "pragma/lua/luacallback.h"
Expand All @@ -35,17 +36,34 @@ void BaseTransformComponent::RegisterMembers(pragma::EntityComponentManager &com
{
using T = BaseTransformComponent;

using TPose = umath::ScaledTransform;
constexpr auto *posePathName = "pose";
auto memberInfoPose = create_component_member_info<T, TPose, static_cast<void (T::*)(const TPose &)>(&T::SetPose), static_cast<const TPose &(T::*)() const>(&T::GetPose)>(posePathName, TPose {});
memberInfoPose.SetFlag(pragma::ComponentMemberFlags::HideInInterface);
registerMember(std::move(memberInfoPose));

auto poseMetaData = std::make_shared<ents::PoseTypeMetaData>();
poseMetaData->poseProperty = posePathName;

using TPosition = Vector3;
registerMember(create_component_member_info<T, TPosition, static_cast<void (T::*)(const TPosition &)>(&T::SetPosition), static_cast<const TPosition &(T::*)() const>(&T::GetPosition)>("position", TPosition {}));
auto memberInfoPos = create_component_member_info<T, TPosition, static_cast<void (T::*)(const TPosition &)>(&T::SetPosition), static_cast<const TPosition &(T::*)() const>(&T::GetPosition)>("position", TPosition {});
memberInfoPos.AddTypeMetaData(poseMetaData);
registerMember(std::move(memberInfoPos));

using TRotation = Quat;
registerMember(create_component_member_info<T, TRotation, static_cast<void (T::*)(const TRotation &)>(&T::SetRotation), static_cast<const TRotation &(T::*)() const>(&T::GetRotation)>("rotation", uquat::identity()));
auto memberInfoRot = create_component_member_info<T, TRotation, static_cast<void (T::*)(const TRotation &)>(&T::SetRotation), static_cast<const TRotation &(T::*)() const>(&T::GetRotation)>("rotation", uquat::identity());
memberInfoRot.AddTypeMetaData(poseMetaData);
registerMember(std::move(memberInfoRot));

using TAngles = EulerAngles;
registerMember(create_component_member_info<T, TAngles, static_cast<void (T::*)(const TAngles &)>(&T::SetAngles), static_cast<TAngles (T::*)() const>(&T::GetAngles)>("angles", TAngles {}));
auto memberInfoAng = create_component_member_info<T, TAngles, static_cast<void (T::*)(const TAngles &)>(&T::SetAngles), static_cast<TAngles (T::*)() const>(&T::GetAngles)>("angles", TAngles {});
memberInfoAng.AddTypeMetaData(poseMetaData);
registerMember(std::move(memberInfoAng));

using TScale = Vector3;
registerMember(create_component_member_info<T, TScale, static_cast<void (T::*)(const TScale &)>(&T::SetScale), static_cast<const TScale &(T::*)() const>(&T::GetScale)>("scale", TScale {1.f, 1.f, 1.f}));
auto memberInfoScale = create_component_member_info<T, TScale, static_cast<void (T::*)(const TScale &)>(&T::SetScale), static_cast<const TScale &(T::*)() const>(&T::GetScale)>("scale", TScale {1.f, 1.f, 1.f});
memberInfoScale.AddTypeMetaData(poseMetaData);
registerMember(std::move(memberInfoScale));
}
BaseTransformComponent::BaseTransformComponent(BaseEntity &ent) : BaseEntityComponent(ent) {}
void BaseTransformComponent::Initialize()
Expand Down
43 changes: 37 additions & 6 deletions core/shared/src/entities/entity_component_manager.cpp
Expand Up @@ -54,9 +54,7 @@ ComponentMemberInfo &ComponentMemberInfo::operator=(const ComponentMemberInfo &o
m_nameHash = other.m_nameHash;
m_specializationType = other.m_specializationType;
m_customSpecializationType = other.m_customSpecializationType ? std::make_unique<std::string>(*other.m_customSpecializationType) : nullptr;
m_min = other.m_min;
m_max = other.m_max;
m_stepSize = other.m_stepSize;
m_typeMetaData = other.m_typeMetaData;
m_metaData = other.m_metaData;
m_flags = other.m_flags;
m_enumConverter = other.m_enumConverter ? std::make_unique<EnumConverter>(*other.m_enumConverter) : nullptr;
Expand Down Expand Up @@ -84,9 +82,36 @@ void ComponentMemberInfo::SetSpecializationType(std::string customType)
m_specializationType = AttributeSpecializationType::Custom;
m_customSpecializationType = std::make_unique<std::string>(customType);
}
void ComponentMemberInfo::SetMin(float min) { m_min = min; }
void ComponentMemberInfo::SetMax(float max) { m_max = max; }
void ComponentMemberInfo::SetStepSize(float stepSize) { m_stepSize = stepSize; }
void ComponentMemberInfo::SetMin(float min)
{
auto &metaData = AddTypeMetaData<ents::RangeTypeMetaData>();
metaData.min = min;
}
void ComponentMemberInfo::SetMax(float max)
{
auto &metaData = AddTypeMetaData<ents::RangeTypeMetaData>();
metaData.max = max;
}
void ComponentMemberInfo::SetStepSize(float stepSize)
{
auto &metaData = AddTypeMetaData<ents::RangeTypeMetaData>();
metaData.stepSize = stepSize;
}
std::optional<float> ComponentMemberInfo::GetMin() const
{
auto *metaData = FindTypeMetaData<ents::RangeTypeMetaData>();
return metaData ? metaData->min : std::optional<float> {};
}
std::optional<float> ComponentMemberInfo::GetMax() const
{
auto *metaData = FindTypeMetaData<ents::RangeTypeMetaData>();
return metaData ? metaData->max : std::optional<float> {};
}
std::optional<float> ComponentMemberInfo::GetStepSize() const
{
auto *metaData = FindTypeMetaData<ents::RangeTypeMetaData>();
return metaData ? metaData->stepSize : std::optional<float> {};
}
udm::Property &ComponentMemberInfo::AddMetaData()
{
auto prop = udm::Property::Create(udm::Type::Element);
Expand All @@ -95,6 +120,12 @@ udm::Property &ComponentMemberInfo::AddMetaData()
}
void ComponentMemberInfo::AddMetaData(const udm::PProperty &prop) { m_metaData = prop; }
const udm::PProperty &ComponentMemberInfo::GetMetaData() const { return m_metaData; }
void ComponentMemberInfo::AddTypeMetaData(const std::shared_ptr<ents::TypeMetaData> &typeMetaData) { m_typeMetaData.push_back(typeMetaData); }
const ents::TypeMetaData *ComponentMemberInfo::FindTypeMetaData(std::type_index typeId) const
{
auto it = std::find_if(m_typeMetaData.begin(), m_typeMetaData.end(), [typeId](const std::shared_ptr<ents::TypeMetaData> &typeMetaData) { return typeId == typeid(*typeMetaData); });
return (it != m_typeMetaData.end()) ? it->get() : nullptr;
}
void ComponentMemberInfo::SetEnum(const EnumConverter::NameToEnumFunction &nameToEnum, const EnumConverter::EnumToNameFunction &enumToName, const EnumConverter::EnumValueGetFunction &getValues) { m_enumConverter = std::make_unique<EnumConverter>(nameToEnum, enumToName, getValues); }
bool ComponentMemberInfo::IsEnum() const { return m_enumConverter != nullptr; }
std::optional<int64_t> ComponentMemberInfo::EnumNameToValue(const std::string &name) const
Expand Down
5 changes: 5 additions & 0 deletions core/shared/src/lua/class.cpp
Expand Up @@ -1380,6 +1380,11 @@ void Game::RegisterLuaClasses()
modUtil[defSplashDamageInfo];

auto &modMath = m_lua->RegisterLibrary("math");

Lua::RegisterLibraryEnums(m_lua->GetState(), "math",
{{"COORDINATE_SPACE_LOCAL", umath::to_integral(umath::CoordinateSpace::Local)}, {"COORDINATE_SPACE_WORLD", umath::to_integral(umath::CoordinateSpace::World)}, {"COORDINATE_SPACE_VIEW", umath::to_integral(umath::CoordinateSpace::View)},
{"COORDINATE_SPACE_SCREEN", umath::to_integral(umath::CoordinateSpace::Screen)}});

auto defPlane = luabind::class_<umath::Plane>("Plane");
defPlane.def(luabind::constructor<Vector3, Vector3, Vector3>());
defPlane.def(luabind::constructor<Vector3, Vector3>());
Expand Down

0 comments on commit fed2d66

Please sign in to comment.