4#include "Engine/CollisionProfile.h"
5#include "Net/UnrealNetwork.h"
6#include "Serialization/CustomVersion.h"
22#if WITH_EDITORONLY_DATA
34 : Super(ObjectInitializer)
37 PrimaryComponentTick.bCanEverTick =
false;
38 PrimaryComponentTick.bStartWithTickEnabled =
false;
40 this->SetUsingAbsoluteScale(
true);
45#if WITH_EDITORONLY_DATA
48 bShowVisualizationMesh =
true;
49 bMirrorVisualizationMesh =
false;
50 bShowRangeVisualization =
false;
79 if (InAnimationSequence)
81 OutPoseSnapShot.SkeletalMeshName = InAnimationSequence->GetSkeleton()->GetFName();
82 OutPoseSnapShot.SnapshotName = InAnimationSequence->GetFName();
83 OutPoseSnapShot.BoneNames.Empty();
84 OutPoseSnapShot.LocalTransforms.Empty();
86 TArray<FName> AnimSeqNames;
88 if (USkeleton* AnimationSkele = InAnimationSequence->GetSkeleton())
91 OutPoseSnapShot.BoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
92 for (int32 i = 0; i < AnimationSkele->GetReferenceSkeleton().GetNum(); i++)
94 OutPoseSnapShot.BoneNames[i] = AnimationSkele->GetReferenceSkeleton().GetBoneName(i);
97 FString bName = OutPoseSnapShot.BoneNames[i].ToString();
99 if (bName.Contains(
"_r"))
101 bName = bName.Replace(TEXT(
"_r"), TEXT(
"_l"));
105 bName = bName.Replace(TEXT(
"_l"), TEXT(
"_r"));
108 OutPoseSnapShot.BoneNames[i] =
FName(bName);
117 const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->SkeletalMesh->GetRefSkeleton() : InAnimationSequence->GetSkeleton()->GetReferenceSkeleton();
118 FTransform LocalTransform;
120 const TArray<FTrackToSkeletonMap>& TrackMap = InAnimationSequence->GetCompressedTrackToSkeletonMapTable();
121 int32 TrackIndex = INDEX_NONE;
123 OutPoseSnapShot.LocalTransforms.Reserve(OutPoseSnapShot.BoneNames.Num());
125 for (int32 BoneNameIndex = 0; BoneNameIndex < OutPoseSnapShot.BoneNames.Num(); ++BoneNameIndex)
128 const FName& BoneName = OutPoseSnapShot.BoneNames[BoneNameIndex];
130 TrackIndex = INDEX_NONE;
131 if (BoneNameIndex != INDEX_NONE && BoneNameIndex < TrackMap.Num() && TrackMap[BoneNameIndex].BoneTreeIndex == BoneNameIndex)
133 TrackIndex = BoneNameIndex;
139 for (
int i = 0; i < TrackMap.Num(); ++i)
141 if (TrackMap[i].BoneTreeIndex == BoneNameIndex)
149 if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
151 InAnimationSequence->GetBoneTransform(LocalTransform, TrackIndex, 0.f,
false);
156 const int32 BoneIDX = RefSkeleton.FindBoneIndex(BoneName);
157 if (BoneIDX != INDEX_NONE)
159 LocalTransform = RefSkeleton.GetRefBonePose()[BoneIDX];
163 LocalTransform = FTransform::Identity;
167 if (bFlipHand && (!bSkipRootBone || TrackIndex != 0))
169 FMatrix M = LocalTransform.ToMatrixWithScale();
170 M.Mirror(EAxis::X, EAxis::X);
171 M.Mirror(EAxis::Y, EAxis::Y);
172 M.Mirror(EAxis::Z, EAxis::Z);
173 LocalTransform.SetFromMatrix(M);
176 OutPoseSnapShot.LocalTransforms.Add(LocalTransform);
179 OutPoseSnapShot.bIsValid =
true;
192 PoseSnapShot.BoneNames.Empty();
193 PoseSnapShot.LocalTransforms.Empty();
194 TArray<FName> OrigBoneNames;
199 PoseSnapShot.BoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
200 OrigBoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
201 for (int32 i = 0; i < AnimationSkele->GetReferenceSkeleton().GetNum(); i++)
203 PoseSnapShot.BoneNames[i] = AnimationSkele->GetReferenceSkeleton().GetBoneName(i);
204 OrigBoneNames[i] = PoseSnapShot.BoneNames[i];
207 FString bName = PoseSnapShot.BoneNames[i].ToString();
209 if (bName.Contains(
"_r"))
211 bName = bName.Replace(TEXT(
"_r"), TEXT(
"_l"));
215 bName = bName.Replace(TEXT(
"_l"), TEXT(
"_r"));
218 PoseSnapShot.BoneNames[i] =
FName(bName);
227 const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->SkeletalMesh->GetRefSkeleton() :
HandTargetAnimation->GetSkeleton()->GetReferenceSkeleton();
228 FTransform LocalTransform;
230 const TArray<FTrackToSkeletonMap>& TrackMap =
HandTargetAnimation->GetCompressedTrackToSkeletonMapTable();
231 int32 TrackIndex = INDEX_NONE;
233 for (int32 BoneNameIndex = 0; BoneNameIndex < PoseSnapShot.BoneNames.Num(); ++BoneNameIndex)
235 TrackIndex = INDEX_NONE;
236 if (BoneNameIndex < TrackMap.Num() && TrackMap[BoneNameIndex].BoneTreeIndex == BoneNameIndex)
238 TrackIndex = BoneNameIndex;
244 for (
int i = 0; i < TrackMap.Num(); ++i)
246 if (TrackMap[i].BoneTreeIndex == BoneNameIndex)
254 const FName& BoneName = PoseSnapShot.BoneNames[BoneNameIndex];
256 if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
263 const int32 BoneIDX = RefSkeleton.FindBoneIndex(BoneName);
264 if (BoneIDX != INDEX_NONE)
266 LocalTransform = RefSkeleton.GetRefBonePose()[BoneIDX];
270 LocalTransform = FTransform::Identity;
276 FQuat DeltaQuat = FQuat::Identity;
279 DeltaQuat = HandPair->DeltaPose;
282 LocalTransform.ConcatenateRotation(DeltaQuat);
283 LocalTransform.NormalizeRotation();
286 if (bFlipHand && (!bSkipRootBone || TrackIndex != 0))
288 FMatrix M = LocalTransform.ToMatrixWithScale();
289 M.Mirror(EAxis::X, EAxis::X);
290 M.Mirror(EAxis::Y, EAxis::Y);
291 M.Mirror(EAxis::Z, EAxis::Z);
292 LocalTransform.SetFromMatrix(M);
295 PoseSnapShot.LocalTransforms.Add(LocalTransform);
298 PoseSnapShot.bIsValid =
true;
303 PoseSnapShot.SkeletalMeshName = TargetMesh->SkeletalMesh->GetSkeleton()->GetFName();
304 PoseSnapShot.SnapshotName =
FName(TEXT(
"RawDeltaPose"));
305 PoseSnapShot.BoneNames.Empty();
306 PoseSnapShot.LocalTransforms.Empty();
307 TargetMesh->GetBoneNames(PoseSnapShot.BoneNames);
309 PoseSnapShot.LocalTransforms = TargetMesh->SkeletalMesh->GetSkeleton()->GetRefLocalPoses();
311 FQuat DeltaQuat = FQuat::Identity;
312 FName TargetBoneName = NAME_None;
318 FString bName = HandPair.BoneName.ToString();
320 if (bName.Contains(
"_r"))
322 bName = bName.Replace(TEXT(
"_r"), TEXT(
"_l"));
326 bName = bName.Replace(TEXT(
"_l"), TEXT(
"_r"));
329 TargetBoneName =
FName(bName);
333 TargetBoneName = HandPair.BoneName;
336 int32 BoneIdx = TargetMesh->GetBoneIndex(TargetBoneName);
337 if (BoneIdx != INDEX_NONE)
339 DeltaQuat = HandPair.DeltaPose;
343 FTransform DeltaTrans(DeltaQuat);
344 FMatrix M = DeltaTrans.ToMatrixWithScale();
345 M.Mirror(EAxis::X, EAxis::X);
346 M.Mirror(EAxis::Y, EAxis::Y);
347 M.Mirror(EAxis::Z, EAxis::Z);
348 DeltaTrans.SetFromMatrix(M);
349 DeltaQuat = DeltaTrans.GetRotation();
352 PoseSnapShot.LocalTransforms[BoneIdx].ConcatenateRotation(DeltaQuat);
353 PoseSnapShot.LocalTransforms[BoneIdx].NormalizeRotation();
358 PoseSnapShot.bIsValid =
true;
388 if (!QueryController)
391 UE_LOG(LogVRMotionController,
Warning, TEXT(
"HandSocketComponent::GetHandSocketTransform was missing required motion controller for bOnlySnapMesh! Check that you are passing a controller into GetClosestSocketInRange!"));
401 if (!QueryController)
404 UE_LOG(LogVRMotionController,
Warning, TEXT(
"HandSocketComponent::GetHandSocketTransform was missing required motion controller for bFlipForLeftand! Check that you are passing a controller into GetClosestSocketInRange!"));
408 EControllerHand HandType;
410 bool bIsRightHand = HandType == EControllerHand::Right;
413 FTransform ReturnTrans = this->GetRelativeTransform();
419 ReturnTrans.SetTranslation(this->GetRelativeLocation());
422 if (this->GetAttachSocketName() != NAME_None)
424 ReturnTrans = ReturnTrans * AttParent->GetSocketTransform(GetAttachSocketName(), RTS_Component);
427 ReturnTrans = ReturnTrans * AttParent->GetComponentTransform();
434 return this->GetComponentTransform();
442 if (!this->GetAttachParent())
443 return FTransform::Identity;
445 FTransform relTrans = this->GetRelativeTransform();
447 FTransform ReturnTrans = FTransform::Identity;
450 if (!bUseParentScale && this->IsUsingAbsoluteScale() )
452 FVector ParentScale = this->GetAttachParent()->GetComponentScale();
454 relTrans.ScaleTranslation(ParentScale);
455 ReturnTrans = HandTrans * relTrans;
457 ReturnTrans.ScaleTranslation((FVector(1.0f) / ParentScale));
458 ReturnTrans.SetScale3D(FVector(1.0f));
462 ReturnTrans = HandTrans * relTrans;
473 ReturnTrans.SetScale3D(ReturnTrans.GetScale3D() *
MirroredScale.GetSignVector());
479 ReturnTrans = ReturnTrans * GetAttachParent()->GetSocketTransform(GetAttachSocketName(), RTS_Component);
487 float tracklen = MyAnimSequence->GetPlayLength();
488 FTransform BoneTransform = FTransform::Identity;
489 const TArray<FTrackToSkeletonMap>& TrackToSkeletonMap = bUseRawDataOnly ? MyAnimSequence->GetRawTrackToSkeletonMapTable() : MyAnimSequence->GetCompressedTrackToSkeletonMapTable();
491 if ((TrackToSkeletonMap.Num() > BoneIdx) && (TrackToSkeletonMap[0].BoneTreeIndex == 0))
493 MyAnimSequence->GetBoneTransform(BoneTransform, BoneIdx, tracklen, bUseRawDataOnly);
494 return BoneTransform;
496 return FTransform::Identity;
501#if WITH_EDITORONLY_DATA
502 AActor* MyOwner = GetOwner();
503 if (bShowVisualizationMesh && (MyOwner !=
nullptr) && !IsRunningCommandlet())
505 if (HandVisualizerComponent ==
nullptr && bShowVisualizationMesh)
507 HandVisualizerComponent = NewObject<UPoseableMeshComponent>(MyOwner, NAME_None, RF_Transactional | RF_TextExportTransient);
508 HandVisualizerComponent->SetupAttachment(
this);
509 HandVisualizerComponent->SetIsVisualizationComponent(
true);
510 HandVisualizerComponent->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
511 HandVisualizerComponent->CastShadow =
false;
512 HandVisualizerComponent->CreationMethod = CreationMethod;
514 HandVisualizerComponent->SetComponentTickEnabled(
false);
515 HandVisualizerComponent->SetHiddenInGame(
true);
516 HandVisualizerComponent->RegisterComponentWithWorld(GetWorld());
519 else if (!bShowVisualizationMesh && HandVisualizerComponent)
521 HideVisualizationMesh();
524 if (HandVisualizerComponent)
528 if (VisualizationMesh)
530 HandVisualizerComponent->SetSkeletalMesh(VisualizationMesh);
531 if (HandPreviewMaterial)
533 HandVisualizerComponent->SetMaterial(0, (UMaterialInterface*)HandPreviewMaterial);
537 PositionVisualizationMesh();
538 PoseVisualizationToAnimation(
true);
547#if WITH_EDITORONLY_DATA
549void UHandSocketComponent::PositionVisualizationMesh()
551 if (!HandVisualizerComponent)
558 FTransform relTrans = this->GetRelativeTransform();
573 FTransform ReturnTrans = (HandPlacement * relTrans);
575 if (bMirrorVisualizationMesh)
582 ReturnTrans.SetScale3D(ReturnTrans.GetScale3D() *
MirroredScale);
585 HandVisualizerComponent->SetRelativeTransform(ReturnTrans.GetRelativeTransform(relTrans));
589void UHandSocketComponent::HideVisualizationMesh()
591 if (!bShowVisualizationMesh && HandVisualizerComponent)
593 HandVisualizerComponent->SetVisibility(
false);
594 HandVisualizerComponent->DestroyComponent();
595 HandVisualizerComponent =
nullptr;
601#if WITH_EDITORONLY_DATA
602void UHandSocketComponent::PoseVisualizationToAnimation(
bool bForceRefresh)
605 if (!HandVisualizerComponent || !HandVisualizerComponent->SkeletalMesh)
608 TArray<FTransform> LocalPoses;
612 LocalPoses = HandVisualizerComponent->SkeletalMesh->GetSkeleton()->GetRefLocalPoses();
615 TArray<FName> BonesNames;
616 HandVisualizerComponent->GetBoneNames(BonesNames);
617 int32 Bones = HandVisualizerComponent->GetNumBones();
619 for (int32 i = 0; i < Bones; i++)
623 HandVisualizerComponent->ResetBoneTransformByName(BonesNames[i]);
627 FName ParentBone = HandVisualizerComponent->GetParentBone(BonesNames[i]);
628 FTransform ParentTrans = FTransform::Identity;
629 if (ParentBone != NAME_None)
631 ParentTrans = HandVisualizerComponent->GetBoneTransformByName(ParentBone, EBoneSpaces::ComponentSpace);
635 FQuat DeltaQuat = FQuat::Identity;
640 if (BonePairC.BoneName == BonesNames[i])
642 DeltaQuat = BonePairC.DeltaPose;
643 DeltaQuat.Normalize();
649 FTransform BoneTrans = FTransform::Identity;
657 BoneTrans = LocalPoses[i];
660 BoneTrans = BoneTrans * ParentTrans;
661 BoneTrans.NormalizeRotation();
665 BoneTrans.ConcatenateRotation(DeltaQuat);
666 BoneTrans.NormalizeRotation();
667 HandVisualizerComponent->SetBoneTransformByName(BonesNames[i], BoneTrans, EBoneSpaces::ComponentSpace);
671 if (HandVisualizerComponent && (!bTickedPose || bForceRefresh))
674 if (HandVisualizerComponent->IsRegistered())
677 HandVisualizerComponent->TickPose(1.0f,
false);
678 if (HandVisualizerComponent->MasterPoseComponent.IsValid())
680 HandVisualizerComponent->UpdateSlaveComponent();
684 HandVisualizerComponent->RefreshBoneTransforms(&HandVisualizerComponent->PrimaryComponentTick);
690void UHandSocketComponent::AddReferencedObjects(
UObject* InThis, FReferenceCollector& Collector)
693 Collector.AddReferencedObject(This->HandVisualizerComponent);
695 Super::AddReferencedObjects(InThis, Collector);
698void UHandSocketComponent::OnComponentDestroyed(
bool bDestroyingHierarchy)
700 Super::OnComponentDestroyed(bDestroyingHierarchy);
702 if (HandVisualizerComponent)
704 HandVisualizerComponent->DestroyComponent();
710void UHandSocketComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps)
const
712 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
721 Super::PreReplication(ChangedPropertyTracker);
738void UHandSocketComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
740 Super::PostEditChangeProperty(PropertyChangedEvent);
742 FProperty* PropertyThatChanged = PropertyChangedEvent.Property;
744 if (PropertyThatChanged !=
nullptr)
746#if WITH_EDITORONLY_DATA
748 PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, VisualizationMesh)
751 PositionVisualizationMesh();
752 PoseVisualizationToAnimation(
true);
756 PoseVisualizationToAnimation(
true);
760 PositionVisualizationMesh();
762 else if (PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(
UHandSocketComponent, bShowVisualizationMesh))
764 HideVisualizationMesh();
DEFINE_LOG_CATEGORY(LogVRHandSocketComponent)
FCustomVersionRegistration GRegisterHandSocketCustomVersion(FVRHandSocketCustomVersion::GUID, FVRHandSocketCustomVersion::LatestVersion, TEXT("HandSocketVer"))
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
void GetHandType(EControllerHand &Hand)
UFUNCTION(BlueprintPure, Category = "VRExpansionFunctions", meta = (bIgnoreSelf = "true",...
FORCEINLINE FTransform GetPivotTransform()
UCLASS(Blueprintable, ClassGroup = (VRExpansionPlugin), hideCategories = ("Component Tick",...
TArray< FBPVRHandPoseBonePair > CustomPoseDeltas
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Animation")
bool GetBlendedPoseSnapShot(FPoseSnapshot &PoseSnapShot, USkeletalMeshComponent *TargetMesh=nullptr, bool bSkipRootBone=false, bool bFlipHand=false)
UFUNCTION(BlueprintCallable, Category = "Hand Socket Data")
bool bUseCustomPoseDeltas
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Animation")
virtual void PreReplication(IRepChangedPropertyTracker &ChangedPropertyTracker) override
FGameplayTagContainer GameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "GameplayTags")
bool bOnlyFlipRotation
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data|Mirroring",...
bool bOnlySnapMesh
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
TEnumAsByte< EVRAxis::Type > FlipAxis
UPROPERTY(VisibleDefaultsOnly, Category = "Hand Socket Data|Mirroring|Advanced")
bool bDisabled
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
void MirrorHandTransform(FTransform &ReturnTrans, FTransform &relTrans)
bool bIgnoreAttachBone
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
UAnimSequence * HandTargetAnimation
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Animation")
TEnumAsByte< EAxis::Type > GetAsEAxis(TEnumAsByte< EVRAxis::Type > InAxis)
bool bMatchRotation
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
UAnimSequence * GetTargetAnimation()
UFUNCTION(BlueprintCallable, Category = "Hand Socket Data")
virtual void OnRegister() override
float OverrideDistance
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
bool bFlipForLeftHand
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data|Mirroring",...
bool bRepGameplayTags
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface|Replication")
virtual FTransform GetHandSocketTransform(UGripMotionControllerComponent *QueryController, bool bIgnoreOnlySnapMesh=false)
bool bLeftHandDominant
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Hand Socket Data")
FTransform GetMeshRelativeTransform(bool bIsRightHand, bool bUseParentScale=false, bool bUseMirrorScale=false)
UFUNCTION(BlueprintCallable, Category = "Hand Socket Data")
FName SlotPrefix
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
bool bDecoupleMeshPlacement
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "Hand Socket Data")
FTransform GetHandRelativePlacement()
virtual void Serialize(FArchive &Ar) override
UHandSocketComponent(const FObjectInitializer &ObjectInitializer)
TEnumAsByte< EVRAxis::Type > MirrorAxis
UPROPERTY(EditDefaultsOnly, Category = "Hand Socket Data|Mirroring|Advanced")
bool bAlwaysInRange
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
FTransform GetBoneTransformAtTime(UAnimSequence *MyAnimSequence, int BoneIdx, bool bUseRawDataOnly)
FTransform HandRelativePlacement
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hand Socket Data")
FVector MirroredScale
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Hand Visualization")
static bool GetAnimationSequenceAsPoseSnapShot(UAnimSequence *InAnimationSequence, FPoseSnapshot &OutPoseSnapShot, USkeletalMeshComponent *TargetMesh=nullptr, bool bSkipRootBone=false, bool bFlipHand=false)
UFUNCTION(BlueprintCallable, Category = "Hand Socket Data", meta = (bIgnoreSelf = "true"))
bool bReplicateMovement
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "VRGripInterface|Replication")
USTRUCT(BlueprintType, Category = "VRExpansionLibrary")
@ HandSocketStoringSetState