Add initial support for skeletal entities / components
This commit is contained in:
96
src/Nazara/Utility/Components/SharedSkeletonComponent.cpp
Normal file
96
src/Nazara/Utility/Components/SharedSkeletonComponent.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Components/SharedSkeletonComponent.hpp>
|
||||
#include <Nazara/Utility/Joint.hpp>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SharedSkeletonComponent::SharedSkeletonComponent(std::shared_ptr<Skeleton> skeleton) :
|
||||
SkeletonComponentBase(std::move(skeleton)),
|
||||
m_skeletonJointInvalidated(true)
|
||||
{
|
||||
SetupSkeleton();
|
||||
}
|
||||
|
||||
SharedSkeletonComponent::SharedSkeletonComponent(const SharedSkeletonComponent& sharedSkeletalComponent) :
|
||||
SkeletonComponentBase(sharedSkeletalComponent),
|
||||
m_attachedSkeleton(sharedSkeletalComponent.m_attachedSkeleton),
|
||||
m_skeletonJointInvalidated(true)
|
||||
{
|
||||
SetupSkeleton();
|
||||
}
|
||||
|
||||
SharedSkeletonComponent::SharedSkeletonComponent(SharedSkeletonComponent&& sharedSkeletalComponent) noexcept :
|
||||
SkeletonComponentBase(std::move(sharedSkeletalComponent)),
|
||||
m_attachedSkeleton(std::move(sharedSkeletalComponent.m_attachedSkeleton)),
|
||||
m_skeletonJointInvalidated(sharedSkeletalComponent.m_skeletonJointInvalidated)
|
||||
{
|
||||
SetupSkeleton();
|
||||
}
|
||||
|
||||
const Joint& SharedSkeletonComponent::GetAttachedJoint(std::size_t jointIndex) const
|
||||
{
|
||||
return *m_attachedSkeleton.GetJoint(jointIndex);
|
||||
}
|
||||
|
||||
SharedSkeletonComponent& SharedSkeletonComponent::operator=(const SharedSkeletonComponent& sharedSkeletalComponent)
|
||||
{
|
||||
SkeletonComponentBase::operator=(sharedSkeletalComponent);
|
||||
|
||||
m_attachedSkeleton = sharedSkeletalComponent.m_attachedSkeleton;
|
||||
m_skeletonJointInvalidated = true;
|
||||
SetupSkeleton();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SharedSkeletonComponent& SharedSkeletonComponent::operator=(SharedSkeletonComponent&& sharedSkeletalComponent) noexcept
|
||||
{
|
||||
SkeletonComponentBase::operator=(std::move(sharedSkeletalComponent));
|
||||
|
||||
m_attachedSkeleton = std::move(sharedSkeletalComponent.m_attachedSkeleton);
|
||||
m_skeletonJointInvalidated = sharedSkeletalComponent.m_skeletonJointInvalidated;
|
||||
SetupSkeleton();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SharedSkeletonComponent::OnReferenceJointsInvalidated(const Skeleton* skeleton)
|
||||
{
|
||||
m_skeletonJointInvalidated = true;
|
||||
}
|
||||
|
||||
void SharedSkeletonComponent::SetSkeletonParent(Node* parent)
|
||||
{
|
||||
m_attachedSkeleton.GetRootJoint()->SetParent(parent);
|
||||
}
|
||||
|
||||
void SharedSkeletonComponent::SetupSkeleton()
|
||||
{
|
||||
assert(m_referenceSkeleton);
|
||||
m_attachedSkeleton = *m_referenceSkeleton;
|
||||
m_referenceSkeleton->OnSkeletonJointsInvalidated.Connect(this, &SharedSkeletonComponent::OnReferenceJointsInvalidated);
|
||||
}
|
||||
|
||||
void SharedSkeletonComponent::UpdateAttachedSkeletonJoints()
|
||||
{
|
||||
assert(m_referenceSkeleton->GetJointCount() == m_attachedSkeleton.GetJointCount());
|
||||
std::size_t jointCount = m_referenceSkeleton->GetJointCount();
|
||||
|
||||
// TODO: This will trigger a lot of invalidation which can be avoided
|
||||
for (std::size_t i = 0; i < jointCount; ++i)
|
||||
{
|
||||
const Joint* referenceJoint = m_referenceSkeleton->GetJoint(i);
|
||||
Joint* attachedJoint = m_attachedSkeleton.GetJoint(i);
|
||||
|
||||
attachedJoint->SetPosition(referenceJoint->GetPosition());
|
||||
attachedJoint->SetRotation(referenceJoint->GetRotation());
|
||||
attachedJoint->SetScale(referenceJoint->GetScale());
|
||||
}
|
||||
|
||||
m_skeletonJointInvalidated = false;
|
||||
}
|
||||
}
|
||||
24
src/Nazara/Utility/Components/SkeletonComponent.cpp
Normal file
24
src/Nazara/Utility/Components/SkeletonComponent.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Components/SkeletonComponent.hpp>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SkeletonComponent::SkeletonComponent(std::shared_ptr<Skeleton> skeleton) :
|
||||
SkeletonComponentBase(std::move(skeleton))
|
||||
{
|
||||
}
|
||||
|
||||
const Joint& SkeletonComponent::GetAttachedJoint(std::size_t jointIndex) const
|
||||
{
|
||||
return *m_referenceSkeleton->GetJoint(jointIndex);
|
||||
}
|
||||
|
||||
Node* SkeletonComponent::GetRootNode()
|
||||
{
|
||||
return m_referenceSkeleton->GetRootJoint();
|
||||
}
|
||||
}
|
||||
10
src/Nazara/Utility/Components/SkeletonComponentBase.cpp
Normal file
10
src/Nazara/Utility/Components/SkeletonComponentBase.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Components/SkeletonComponentBase.hpp>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
@@ -217,15 +217,15 @@ namespace Nz
|
||||
m_impl->joints = skeleton.m_impl->joints;
|
||||
|
||||
// Restore parent hierarchy
|
||||
const Node* firstJoint = skeleton.m_impl->joints.data();
|
||||
const Joint* firstJoint = skeleton.m_impl->joints.data();
|
||||
|
||||
std::size_t jointCount = skeleton.m_impl->joints.size();
|
||||
for (std::size_t i = 0; i < jointCount; ++i)
|
||||
{
|
||||
const Node* parent = skeleton.m_impl->joints[i].GetParent();
|
||||
const Joint* parent = SafeCast<const Joint*>(skeleton.m_impl->joints[i].GetParent());
|
||||
if (parent)
|
||||
{
|
||||
std::size_t parentIndex = SafeCast<std::size_t>(firstJoint - parent);
|
||||
std::size_t parentIndex = SafeCast<std::size_t>(parent - firstJoint);
|
||||
m_impl->joints[i].SetParent(m_impl->joints[parentIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
56
src/Nazara/Utility/Systems/SkeletonSystem.cpp
Normal file
56
src/Nazara/Utility/Systems/SkeletonSystem.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com)
|
||||
// This file is part of the "Nazara Engine - Utility module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Utility/Systems/SkeletonSystem.hpp>
|
||||
#include <Nazara/Utility/Components/NodeComponent.hpp>
|
||||
#include <Nazara/Utility/Components/SharedSkeletonComponent.hpp>
|
||||
#include <Nazara/Utility/Components/SkeletonComponent.hpp>
|
||||
#include <Nazara/Utility/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
SkeletonSystem::SkeletonSystem(entt::registry& registry) :
|
||||
m_registry(registry),
|
||||
m_sharedSkeletonConstructObserver(registry, entt::collector.group<NodeComponent, SharedSkeletonComponent>(entt::exclude<SkeletonComponent>)),
|
||||
m_skeletonConstructObserver(registry, entt::collector.group<NodeComponent, SkeletonComponent>(entt::exclude<SharedSkeletonComponent>))
|
||||
{
|
||||
}
|
||||
|
||||
SkeletonSystem::~SkeletonSystem()
|
||||
{
|
||||
m_sharedSkeletonConstructObserver.disconnect();
|
||||
m_skeletonConstructObserver.disconnect();
|
||||
}
|
||||
|
||||
void SkeletonSystem::Update(float /*elapsedTime*/)
|
||||
{
|
||||
m_sharedSkeletonConstructObserver.each([&](entt::entity entity)
|
||||
{
|
||||
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
|
||||
SharedSkeletonComponent& entitySkeleton = m_registry.get<SharedSkeletonComponent>(entity);
|
||||
|
||||
entitySkeleton.SetSkeletonParent(&entityNode);
|
||||
});
|
||||
|
||||
m_skeletonConstructObserver.each([&](entt::entity entity)
|
||||
{
|
||||
NodeComponent& entityNode = m_registry.get<NodeComponent>(entity);
|
||||
SkeletonComponent& entitySkeleton = m_registry.get<SkeletonComponent>(entity);
|
||||
|
||||
// TODO: When attaching for the first time, set the skeleton to the position of the node before attaching the node
|
||||
Node* skeletonRoot = entitySkeleton.GetRootNode();
|
||||
|
||||
entityNode.SetParent(entitySkeleton.GetRootNode());
|
||||
});
|
||||
|
||||
// Updated attached skeleton joints (TODO: Only do this if necessary)
|
||||
auto view = m_registry.view<NodeComponent, SharedSkeletonComponent>();
|
||||
for (auto entity : view)
|
||||
{
|
||||
auto& sharedSkeletonComponent = view.get<SharedSkeletonComponent>(entity);
|
||||
if (sharedSkeletonComponent.IsAttachedSkeletonOutdated())
|
||||
sharedSkeletonComponent.UpdateAttachedSkeletonJoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user