Add SetMasterPoseModel to Animated Model for modular characters
This commit is contained in:
@@ -64,7 +64,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets the amount of loaded model LODs.
|
||||
/// </summary>
|
||||
/// <returns>Loaded LODs count</returns>
|
||||
API_PROPERTY() FORCE_INLINE int32 GetLoadedLODs() const
|
||||
{
|
||||
return _loadedLODs;
|
||||
@@ -93,7 +92,6 @@ public:
|
||||
/// <summary>
|
||||
/// Gets index of the highest resident LOD (may be equal to LODs.Count if no LOD has been uploaded). Note: LOD=0 is the highest (top quality)
|
||||
/// </summary>
|
||||
/// <returns>LOD index</returns>
|
||||
FORCE_INLINE int32 HighestResidentLODIndex() const
|
||||
{
|
||||
return GetLODsCount() - _loadedLODs;
|
||||
|
||||
@@ -44,7 +44,8 @@ void AnimatedModel::UpdateAnimation()
|
||||
|| !IsActiveInHierarchy()
|
||||
|| SkinnedModel == nullptr
|
||||
|| !SkinnedModel->IsLoaded()
|
||||
|| _lastUpdateFrame == Engine::FrameCount)
|
||||
|| _lastUpdateFrame == Engine::FrameCount
|
||||
|| _masterPose)
|
||||
return;
|
||||
_lastUpdateFrame = Engine::FrameCount;
|
||||
|
||||
@@ -183,6 +184,17 @@ int32 AnimatedModel::FindClosestNode(const Vector3& location, bool worldSpace) c
|
||||
return result;
|
||||
}
|
||||
|
||||
void AnimatedModel::SetMasterPoseModel(AnimatedModel* masterPose)
|
||||
{
|
||||
if (masterPose == _masterPose)
|
||||
return;
|
||||
if (_masterPose)
|
||||
_masterPose->AnimationUpdated.Unbind<AnimatedModel, &AnimatedModel::OnAnimationUpdated>(this);
|
||||
_masterPose = masterPose;
|
||||
if (_masterPose)
|
||||
_masterPose->AnimationUpdated.Bind<AnimatedModel, &AnimatedModel::OnAnimationUpdated>(this);
|
||||
}
|
||||
|
||||
#define CHECK_ANIM_GRAPH_PARAM_ACCESS() \
|
||||
if (!AnimationGraph) \
|
||||
{ \
|
||||
@@ -378,6 +390,7 @@ void AnimatedModel::BeginPlay(SceneBeginData* data)
|
||||
void AnimatedModel::EndPlay()
|
||||
{
|
||||
AnimationManager::RemoveFromUpdate(this);
|
||||
SetMasterPoseModel(nullptr);
|
||||
|
||||
// Base
|
||||
ModelInstanceActor::EndPlay();
|
||||
@@ -443,11 +456,21 @@ void AnimatedModel::UpdateBounds()
|
||||
void AnimatedModel::OnAnimationUpdated()
|
||||
{
|
||||
ANIM_GRAPH_PROFILE_EVENT("OnAnimationUpdated");
|
||||
auto& skeleton = SkinnedModel->Skeleton;
|
||||
|
||||
// Copy pose from the master
|
||||
if (_masterPose && _masterPose->SkinnedModel->Skeleton.Nodes.Count() == skeleton.Nodes.Count())
|
||||
{
|
||||
ANIM_GRAPH_PROFILE_EVENT("Copy Master Pose");
|
||||
const auto& masterInstance = _masterPose->GraphInstance;
|
||||
GraphInstance.NodesPose = masterInstance.NodesPose;
|
||||
GraphInstance.RootTransform = masterInstance.RootTransform;
|
||||
GraphInstance.RootMotion = masterInstance.RootMotion;
|
||||
}
|
||||
|
||||
// Calculate the final bones transformations and update skinning
|
||||
{
|
||||
ANIM_GRAPH_PROFILE_EVENT("Final Pose");
|
||||
auto& skeleton = SkinnedModel->Skeleton;
|
||||
UpdateBones.Resize(skeleton.Bones.Count(), false);
|
||||
for (int32 boneIndex = 0; boneIndex < skeleton.Bones.Count(); boneIndex++)
|
||||
{
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
float _lastMinDstSqr;
|
||||
uint64 _lastUpdateFrame;
|
||||
BlendShapesInstance _blendShapes;
|
||||
ScriptingObjectReference<AnimatedModel> _masterPose;
|
||||
|
||||
public:
|
||||
|
||||
@@ -224,6 +225,12 @@ public:
|
||||
/// <returns>The zero-based index of the found node. Returns -1 if skeleton is missing.</returns>
|
||||
API_FUNCTION() int32 FindClosestNode(const Vector3& location, bool worldSpace = false) const;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the master pose model that will be used to copy the skeleton nodes animation. Useful for modular characters.
|
||||
/// </summary>
|
||||
/// <param name="masterPose">The master pose actor to use.</param>
|
||||
API_FUNCTION() void SetMasterPoseModel(AnimatedModel* masterPose);
|
||||
|
||||
public:
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user