You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
175 lines
5.3 KiB
C++
175 lines
5.3 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BoneProxy.h"
|
|
#include "IPersonaPreviewScene.h"
|
|
#include "BoneControllers/AnimNode_ModifyBone.h"
|
|
#include "AnimPreviewInstance.h"
|
|
#include "ScopedTransaction.h"
|
|
#include "Animation/DebugSkelMeshComponent.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "BoneProxy"
|
|
|
|
UBoneProxy::UBoneProxy()
|
|
: bLocalLocation(true)
|
|
, bLocalRotation(true)
|
|
, PreviousLocation(FVector::ZeroVector)
|
|
, PreviousRotation(FRotator::ZeroRotator)
|
|
, PreviousScale(FVector::ZeroVector)
|
|
, bManipulating(false)
|
|
, bIsTickable(false)
|
|
{
|
|
}
|
|
|
|
void UBoneProxy::Tick(float DeltaTime)
|
|
{
|
|
if (!bManipulating)
|
|
{
|
|
if (UDebugSkelMeshComponent* Component = SkelMeshComponent.Get())
|
|
{
|
|
int32 BoneIndex = Component->GetBoneIndex(BoneName);
|
|
if (Component->BoneSpaceTransforms.IsValidIndex(BoneIndex))
|
|
{
|
|
FTransform LocalTransform = Component->BoneSpaceTransforms[BoneIndex];
|
|
FTransform BoneTransform = Component->GetBoneTransform(BoneIndex);
|
|
|
|
if (bLocalLocation)
|
|
{
|
|
Location = LocalTransform.GetLocation();
|
|
}
|
|
else
|
|
{
|
|
Location = BoneTransform.GetLocation();
|
|
}
|
|
|
|
if (bLocalRotation)
|
|
{
|
|
Rotation = LocalTransform.GetRotation().Rotator();
|
|
}
|
|
else
|
|
{
|
|
Rotation = BoneTransform.GetRotation().Rotator();
|
|
}
|
|
|
|
Scale = LocalTransform.GetScale3D();
|
|
|
|
FTransform ReferenceTransform = Component->SkeletalMesh->RefSkeleton.GetRefBonePose()[BoneIndex];
|
|
ReferenceLocation = ReferenceTransform.GetLocation();
|
|
ReferenceRotation = ReferenceTransform.GetRotation().Rotator();
|
|
ReferenceScale = ReferenceTransform.GetScale3D();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool UBoneProxy::IsTickable() const
|
|
{
|
|
return bIsTickable;
|
|
}
|
|
|
|
TStatId UBoneProxy::GetStatId() const
|
|
{
|
|
RETURN_QUICK_DECLARE_CYCLE_STAT(UBoneProxy, STATGROUP_Tickables);
|
|
}
|
|
|
|
void UBoneProxy::PreEditChange(FEditPropertyChain& PropertyAboutToChange)
|
|
{
|
|
if (UDebugSkelMeshComponent* Component = SkelMeshComponent.Get())
|
|
{
|
|
if (Component->PreviewInstance && Component->AnimScriptInstance == Component->PreviewInstance)
|
|
{
|
|
bManipulating = true;
|
|
|
|
Component->PreviewInstance->Modify();
|
|
|
|
if (PropertyAboutToChange.GetActiveMemberNode()->GetValue()->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Location))
|
|
{
|
|
PreviousLocation = Location;
|
|
}
|
|
else if (PropertyAboutToChange.GetActiveMemberNode()->GetValue()->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Rotation))
|
|
{
|
|
PreviousRotation = Rotation;
|
|
}
|
|
else if (PropertyAboutToChange.GetActiveMemberNode()->GetValue()->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Scale))
|
|
{
|
|
PreviousScale = Scale;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UBoneProxy::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
|
|
{
|
|
if(PropertyChangedEvent.Property != nullptr)
|
|
{
|
|
if (UDebugSkelMeshComponent* Component = SkelMeshComponent.Get())
|
|
{
|
|
if (Component->PreviewInstance && Component->AnimScriptInstance == Component->PreviewInstance)
|
|
{
|
|
bManipulating = (PropertyChangedEvent.ChangeType == EPropertyChangeType::Interactive);
|
|
|
|
int32 BoneIndex = Component->GetBoneIndex(BoneName);
|
|
if (BoneIndex != INDEX_NONE && BoneIndex < Component->GetNumComponentSpaceTransforms())
|
|
{
|
|
FTransform BoneTransform = Component->GetBoneTransform(BoneIndex);
|
|
FMatrix BoneLocalCoordSystem = Component->GetBoneTransform(BoneIndex).ToMatrixNoScale().RemoveTranslation();
|
|
Component->PreviewInstance->SetFlags(RF_Transactional);
|
|
Component->PreviewInstance->Modify();
|
|
FAnimNode_ModifyBone& ModifyBone = Component->PreviewInstance->ModifyBone(BoneName);
|
|
FTransform ModifyBoneTransform(ModifyBone.Rotation, ModifyBone.Translation, ModifyBone.Scale);
|
|
FTransform BaseTransform = BoneTransform.GetRelativeTransformReverse(ModifyBoneTransform);
|
|
|
|
if (PropertyChangedEvent.MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Location))
|
|
{
|
|
FVector Delta = (Location - PreviousLocation);
|
|
if (!Delta.IsNearlyZero())
|
|
{
|
|
if (bLocalLocation)
|
|
{
|
|
Delta = BoneLocalCoordSystem.TransformPosition(Delta);
|
|
}
|
|
|
|
FVector BoneSpaceDelta = BaseTransform.TransformVector(Delta);
|
|
ModifyBone.Translation += BoneSpaceDelta;
|
|
}
|
|
}
|
|
else if (PropertyChangedEvent.MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Rotation))
|
|
{
|
|
FRotator Delta = (Rotation - PreviousRotation);
|
|
if (!Delta.IsNearlyZero())
|
|
{
|
|
if (bLocalRotation)
|
|
{
|
|
// get delta in current coord space
|
|
Delta = (BoneLocalCoordSystem.Inverse() * FRotationMatrix(Delta) * BoneLocalCoordSystem).Rotator();
|
|
}
|
|
|
|
FVector RotAxis;
|
|
float RotAngle;
|
|
Delta.Quaternion().ToAxisAndAngle(RotAxis, RotAngle);
|
|
|
|
FVector4 BoneSpaceAxis = BaseTransform.TransformVectorNoScale(RotAxis);
|
|
|
|
//Calculate the new delta rotation
|
|
FQuat NewDeltaQuat(BoneSpaceAxis, RotAngle);
|
|
NewDeltaQuat.Normalize();
|
|
|
|
FRotator NewRotation = (ModifyBoneTransform * FTransform(NewDeltaQuat)).Rotator();
|
|
ModifyBone.Rotation = NewRotation;
|
|
}
|
|
}
|
|
else if (PropertyChangedEvent.MemberProperty->GetFName() == GET_MEMBER_NAME_CHECKED(UBoneProxy, Scale))
|
|
{
|
|
FVector Delta = (Scale - PreviousScale);
|
|
if (!Delta.IsNearlyZero())
|
|
{
|
|
ModifyBone.Scale += Delta;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE
|