A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
HandSocketComponent.cpp
Go to the documentation of this file.
1// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
2
4#include "Engine/CollisionProfile.h"
5#include "Net/UnrealNetwork.h"
6#include "Serialization/CustomVersion.h"
7
8DEFINE_LOG_CATEGORY(LogVRHandSocketComponent);
9
10const FGuid FVRHandSocketCustomVersion::GUID(0x1EB5FDBD, 0x11AC4D10, 0x1136F38F, 0x1393A5DA);
11
12// Register the custom version with core
14
15
17{
18 Super::Serialize(Ar);
19
20 Ar.UsingCustomVersion(FVRHandSocketCustomVersion::GUID);
21
22#if WITH_EDITORONLY_DATA
23 const int32 CustomHandSocketVersion = Ar.CustomVer(FVRHandSocketCustomVersion::GUID);
24
26 {
27 bDecoupled = bDecoupleMeshPlacement;
28 }
29#endif
30}
31
32 //=============================================================================
33UHandSocketComponent::UHandSocketComponent(const FObjectInitializer& ObjectInitializer)
34 : Super(ObjectInitializer)
35{
36 bReplicateMovement = false;
37 PrimaryComponentTick.bCanEverTick = false;
38 PrimaryComponentTick.bStartWithTickEnabled = false;
39 // Setting absolute scale so we don't have to care about our parents scale
40 this->SetUsingAbsoluteScale(true);
41 //this->bReplicates = true;
42
43 bRepGameplayTags = true;
44
45#if WITH_EDITORONLY_DATA
46 bTickedPose = false;
47 bDecoupled = false;
48 bShowVisualizationMesh = true;
49 bMirrorVisualizationMesh = false;
50 bShowRangeVisualization = false;
51#endif
52
53 HandRelativePlacement = FTransform::Identity;
54 bAlwaysInRange = false;
55 bDisabled = false;
56 bMatchRotation = false;
57 OverrideDistance = 0.0f;
58 SlotPrefix = FName("VRGripP");
60 HandTargetAnimation = nullptr;
61 MirroredScale = FVector(1.f, 1.f, -1.f);
62 bOnlySnapMesh = false;
63 bIgnoreAttachBone = false;
64 bFlipForLeftHand = false;
65 bLeftHandDominant = false;
66 bOnlyFlipRotation = false;
67
70}
71
76
77bool UHandSocketComponent::GetAnimationSequenceAsPoseSnapShot(UAnimSequence* InAnimationSequence, FPoseSnapshot& OutPoseSnapShot, USkeletalMeshComponent* TargetMesh, bool bSkipRootBone, bool bFlipHand)
78{
79 if (InAnimationSequence)
80 {
81 OutPoseSnapShot.SkeletalMeshName = /*TargetMesh ? TargetMesh->SkeletalMesh->GetFName(): */InAnimationSequence->GetSkeleton()->GetFName();
82 OutPoseSnapShot.SnapshotName = InAnimationSequence->GetFName();
83 OutPoseSnapShot.BoneNames.Empty();
84 OutPoseSnapShot.LocalTransforms.Empty();
85
86 TArray<FName> AnimSeqNames;
87
88 if (USkeleton* AnimationSkele = InAnimationSequence->GetSkeleton())
89 {
90 // pre-size the array to avoid unnecessary reallocation
91 OutPoseSnapShot.BoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
92 for (int32 i = 0; i < AnimationSkele->GetReferenceSkeleton().GetNum(); i++)
93 {
94 OutPoseSnapShot.BoneNames[i] = AnimationSkele->GetReferenceSkeleton().GetBoneName(i);
95 if (bFlipHand)
96 {
97 FString bName = OutPoseSnapShot.BoneNames[i].ToString();
98
99 if (bName.Contains("_r"))
100 {
101 bName = bName.Replace(TEXT("_r"), TEXT("_l"));
102 }
103 else
104 {
105 bName = bName.Replace(TEXT("_l"), TEXT("_r"));
106 }
107
108 OutPoseSnapShot.BoneNames[i] = FName(bName);
109 }
110 }
111 }
112 else
113 {
114 return false;
115 }
116
117 const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->SkeletalMesh->GetRefSkeleton() : InAnimationSequence->GetSkeleton()->GetReferenceSkeleton();
118 FTransform LocalTransform;
119
120 const TArray<FTrackToSkeletonMap>& TrackMap = InAnimationSequence->GetCompressedTrackToSkeletonMapTable();
121 int32 TrackIndex = INDEX_NONE;
122
123 OutPoseSnapShot.LocalTransforms.Reserve(OutPoseSnapShot.BoneNames.Num());
124
125 for (int32 BoneNameIndex = 0; BoneNameIndex < OutPoseSnapShot.BoneNames.Num(); ++BoneNameIndex)
126 {
127
128 const FName& BoneName = OutPoseSnapShot.BoneNames[BoneNameIndex];
129
130 TrackIndex = INDEX_NONE;
131 if (BoneNameIndex != INDEX_NONE && BoneNameIndex < TrackMap.Num() && TrackMap[BoneNameIndex].BoneTreeIndex == BoneNameIndex)
132 {
133 TrackIndex = BoneNameIndex;
134 }
135 else
136 {
137 // This shouldn't happen but I need a fallback
138 // Don't currently want to reconstruct the map inversely
139 for (int i = 0; i < TrackMap.Num(); ++i)
140 {
141 if (TrackMap[i].BoneTreeIndex == BoneNameIndex)
142 {
143 TrackIndex = i;
144 break;
145 }
146 }
147 }
148
149 if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
150 {
151 InAnimationSequence->GetBoneTransform(LocalTransform, TrackIndex, 0.f, false);
152 }
153 else
154 {
155 // otherwise, get ref pose if exists
156 const int32 BoneIDX = RefSkeleton.FindBoneIndex(BoneName);
157 if (BoneIDX != INDEX_NONE)
158 {
159 LocalTransform = RefSkeleton.GetRefBonePose()[BoneIDX];
160 }
161 else
162 {
163 LocalTransform = FTransform::Identity;
164 }
165 }
166
167 if (bFlipHand && (!bSkipRootBone || TrackIndex != 0))
168 {
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);
174 }
175
176 OutPoseSnapShot.LocalTransforms.Add(LocalTransform);
177 }
178
179 OutPoseSnapShot.bIsValid = true;
180 return true;
181 }
182
183 return false;
184}
185
186bool UHandSocketComponent::GetBlendedPoseSnapShot(FPoseSnapshot& PoseSnapShot, USkeletalMeshComponent* TargetMesh, bool bSkipRootBone, bool bFlipHand)
187{
188 if (HandTargetAnimation)// && bUseCustomPoseDeltas && CustomPoseDeltas.Num() > 0)
189 {
190 PoseSnapShot.SkeletalMeshName = HandTargetAnimation->GetSkeleton()->GetFName();
191 PoseSnapShot.SnapshotName = HandTargetAnimation->GetFName();
192 PoseSnapShot.BoneNames.Empty();
193 PoseSnapShot.LocalTransforms.Empty();
194 TArray<FName> OrigBoneNames;
195
196 if(USkeleton * AnimationSkele = HandTargetAnimation->GetSkeleton())
197 {
198 // pre-size the array to avoid unnecessary reallocation
199 PoseSnapShot.BoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
200 OrigBoneNames.AddUninitialized(AnimationSkele->GetReferenceSkeleton().GetNum());
201 for (int32 i = 0; i < AnimationSkele->GetReferenceSkeleton().GetNum(); i++)
202 {
203 PoseSnapShot.BoneNames[i] = AnimationSkele->GetReferenceSkeleton().GetBoneName(i);
204 OrigBoneNames[i] = PoseSnapShot.BoneNames[i];
205 if (bFlipHand)
206 {
207 FString bName = PoseSnapShot.BoneNames[i].ToString();
208
209 if (bName.Contains("_r"))
210 {
211 bName = bName.Replace(TEXT("_r"), TEXT("_l"));
212 }
213 else
214 {
215 bName = bName.Replace(TEXT("_l"), TEXT("_r"));
216 }
217
218 PoseSnapShot.BoneNames[i] = FName(bName);
219 }
220 }
221 }
222 else
223 {
224 return false;
225 }
226
227 const FReferenceSkeleton& RefSkeleton = (TargetMesh) ? TargetMesh->SkeletalMesh->GetRefSkeleton() : HandTargetAnimation->GetSkeleton()->GetReferenceSkeleton();
228 FTransform LocalTransform;
229
230 const TArray<FTrackToSkeletonMap>& TrackMap = HandTargetAnimation->GetCompressedTrackToSkeletonMapTable();
231 int32 TrackIndex = INDEX_NONE;
232
233 for (int32 BoneNameIndex = 0; BoneNameIndex < PoseSnapShot.BoneNames.Num(); ++BoneNameIndex)
234 {
235 TrackIndex = INDEX_NONE;
236 if (BoneNameIndex < TrackMap.Num() && TrackMap[BoneNameIndex].BoneTreeIndex == BoneNameIndex)
237 {
238 TrackIndex = BoneNameIndex;
239 }
240 else
241 {
242 // This shouldn't happen but I need a fallback
243 // Don't currently want to reconstruct the map inversely
244 for (int i = 0; i < TrackMap.Num(); ++i)
245 {
246 if (TrackMap[i].BoneTreeIndex == BoneNameIndex)
247 {
248 TrackIndex = i;
249 break;
250 }
251 }
252 }
253
254 const FName& BoneName = PoseSnapShot.BoneNames[BoneNameIndex];
255
256 if (TrackIndex != INDEX_NONE && (!bSkipRootBone || TrackIndex != 0))
257 {
258 HandTargetAnimation->GetBoneTransform(LocalTransform, TrackIndex, 0.f, false);
259 }
260 else
261 {
262 // otherwise, get ref pose if exists
263 const int32 BoneIDX = RefSkeleton.FindBoneIndex(BoneName);
264 if (BoneIDX != INDEX_NONE)
265 {
266 LocalTransform = RefSkeleton.GetRefBonePose()[BoneIDX];
267 }
268 else
269 {
270 LocalTransform = FTransform::Identity;
271 }
272 }
273
275 {
276 FQuat DeltaQuat = FQuat::Identity;
277 if (FBPVRHandPoseBonePair* HandPair = CustomPoseDeltas.FindByKey(OrigBoneNames[BoneNameIndex]))
278 {
279 DeltaQuat = HandPair->DeltaPose;
280 }
281
282 LocalTransform.ConcatenateRotation(DeltaQuat);
283 LocalTransform.NormalizeRotation();
284 }
285
286 if (bFlipHand && (!bSkipRootBone || TrackIndex != 0))
287 {
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);
293 }
294
295 PoseSnapShot.LocalTransforms.Add(LocalTransform);
296 }
297
298 PoseSnapShot.bIsValid = true;
299 return true;
300 }
301 else if (bUseCustomPoseDeltas && CustomPoseDeltas.Num() && TargetMesh)
302 {
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);
308
309 PoseSnapShot.LocalTransforms = TargetMesh->SkeletalMesh->GetSkeleton()->GetRefLocalPoses();
310
311 FQuat DeltaQuat = FQuat::Identity;
312 FName TargetBoneName = NAME_None;
313
315 {
316 if (bFlipHand)
317 {
318 FString bName = HandPair.BoneName.ToString();
319
320 if (bName.Contains("_r"))
321 {
322 bName = bName.Replace(TEXT("_r"), TEXT("_l"));
323 }
324 else
325 {
326 bName = bName.Replace(TEXT("_l"), TEXT("_r"));
327 }
328
329 TargetBoneName = FName(bName);
330 }
331 else
332 {
333 TargetBoneName = HandPair.BoneName;
334 }
335
336 int32 BoneIdx = TargetMesh->GetBoneIndex(TargetBoneName);
337 if (BoneIdx != INDEX_NONE)
338 {
339 DeltaQuat = HandPair.DeltaPose;
340
341 if (bFlipHand)
342 {
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();
350 }
351
352 PoseSnapShot.LocalTransforms[BoneIdx].ConcatenateRotation(DeltaQuat);
353 PoseSnapShot.LocalTransforms[BoneIdx].NormalizeRotation();
354
355 }
356 }
357
358 PoseSnapShot.bIsValid = true;
359 return true;
360 }
361
362 return false;
363}
364
366{
367 // Optionally mirror for left hand
368
370 {
371 if (USceneComponent* ParentComp = GetAttachParent())
372 {
373 return HandRelativePlacement.GetRelativeTransform(this->GetRelativeTransform());
374 //FTransform curTrans = HandRelativePlacement * ParentComp->GetComponentTransform();
375 //return curTrans.GetRelativeTransform(this->GetComponentTransform());
376 }
377 }
378
380}
381
382FTransform UHandSocketComponent::GetHandSocketTransform(UGripMotionControllerComponent* QueryController, bool bIgnoreOnlySnapMesh)
383{
384 // Optionally mirror for left hand
385
386 if (!bIgnoreOnlySnapMesh && bOnlySnapMesh)
387 {
388 if (!QueryController)
389 {
390 // No controller input
391 UE_LOG(LogVRMotionController, Warning, TEXT("HandSocketComponent::GetHandSocketTransform was missing required motion controller for bOnlySnapMesh! Check that you are passing a controller into GetClosestSocketInRange!"));
392 }
393 else
394 {
395 return QueryController->GetPivotTransform();
396 }
397 }
398
400 {
401 if (!QueryController)
402 {
403 // No controller input
404 UE_LOG(LogVRMotionController, Warning, TEXT("HandSocketComponent::GetHandSocketTransform was missing required motion controller for bFlipForLeftand! Check that you are passing a controller into GetClosestSocketInRange!"));
405 }
406 else
407 {
408 EControllerHand HandType;
409 QueryController->GetHandType(HandType);
410 bool bIsRightHand = HandType == EControllerHand::Right;
411 if (bLeftHandDominant == bIsRightHand)
412 {
413 FTransform ReturnTrans = this->GetRelativeTransform();
414 if (USceneComponent* AttParent = this->GetAttachParent())
415 {
416 ReturnTrans.Mirror(GetAsEAxis(MirrorAxis), GetAsEAxis(FlipAxis));
418 {
419 ReturnTrans.SetTranslation(this->GetRelativeLocation());
420 }
421
422 if (this->GetAttachSocketName() != NAME_None)
423 {
424 ReturnTrans = ReturnTrans * AttParent->GetSocketTransform(GetAttachSocketName(), RTS_Component);
425 }
426
427 ReturnTrans = ReturnTrans * AttParent->GetComponentTransform();
428 }
429 return ReturnTrans;
430 }
431 }
432 }
433
434 return this->GetComponentTransform();
435}
436
437FTransform UHandSocketComponent::GetMeshRelativeTransform(bool bIsRightHand, bool bUseParentScale, bool bUseMirrorScale)
438{
439 // Optionally mirror for left hand
440
441 // Failsafe
442 if (!this->GetAttachParent())
443 return FTransform::Identity;
444
445 FTransform relTrans = this->GetRelativeTransform();
446 FTransform HandTrans = GetHandRelativePlacement();
447 FTransform ReturnTrans = FTransform::Identity;
448
449 // Fix the scale
450 if (!bUseParentScale && this->IsUsingAbsoluteScale() /*&& !bDecoupleMeshPlacement*/)
451 {
452 FVector ParentScale = this->GetAttachParent()->GetComponentScale();
453 // Take parent scale out of our relative transform early
454 relTrans.ScaleTranslation(ParentScale);
455 ReturnTrans = HandTrans * relTrans;
456 // We add in the inverse of the parent scale to adjust the hand mesh
457 ReturnTrans.ScaleTranslation((FVector(1.0f) / ParentScale));
458 ReturnTrans.SetScale3D(FVector(1.0f));
459 }
460 else
461 {
462 ReturnTrans = HandTrans * relTrans;
463 }
464
465 // If we should mirror the transform, do it now that it is in our parent relative space
466 if ((bFlipForLeftHand && (bLeftHandDominant == bIsRightHand)))
467 {
468 //FTransform relTrans = this->GetRelativeTransform();
469 MirrorHandTransform(ReturnTrans, relTrans);
470
471 if (bUseMirrorScale)
472 {
473 ReturnTrans.SetScale3D(ReturnTrans.GetScale3D() * MirroredScale.GetSignVector());
474 }
475 }
476
477 if (bIgnoreAttachBone && this->GetAttachSocketName() != NAME_None)
478 {
479 ReturnTrans = ReturnTrans * GetAttachParent()->GetSocketTransform(GetAttachSocketName(), RTS_Component);
480 }
481
482 return ReturnTrans;
483}
484
485FTransform UHandSocketComponent::GetBoneTransformAtTime(UAnimSequence* MyAnimSequence, /*float AnimTime,*/ int BoneIdx, bool bUseRawDataOnly)
486{
487 float tracklen = MyAnimSequence->GetPlayLength();
488 FTransform BoneTransform = FTransform::Identity;
489 const TArray<FTrackToSkeletonMap>& TrackToSkeletonMap = bUseRawDataOnly ? MyAnimSequence->GetRawTrackToSkeletonMapTable() : MyAnimSequence->GetCompressedTrackToSkeletonMapTable();
490
491 if ((TrackToSkeletonMap.Num() > BoneIdx) && (TrackToSkeletonMap[0].BoneTreeIndex == 0))
492 {
493 MyAnimSequence->GetBoneTransform(BoneTransform, BoneIdx, /*AnimTime*/ tracklen, bUseRawDataOnly);
494 return BoneTransform;
495 }
496 return FTransform::Identity;
497}
498
500{
501#if WITH_EDITORONLY_DATA
502 AActor* MyOwner = GetOwner();
503 if (bShowVisualizationMesh && (MyOwner != nullptr) && !IsRunningCommandlet())
504 {
505 if (HandVisualizerComponent == nullptr && bShowVisualizationMesh)
506 {
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;
513 //HandVisualizerComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
514 HandVisualizerComponent->SetComponentTickEnabled(false);
515 HandVisualizerComponent->SetHiddenInGame(true);
516 HandVisualizerComponent->RegisterComponentWithWorld(GetWorld());
517 //HandVisualizerComponent->SetUsingAbsoluteScale(true);
518 }
519 else if (!bShowVisualizationMesh && HandVisualizerComponent)
520 {
521 HideVisualizationMesh();
522 }
523
524 if (HandVisualizerComponent)
525 {
526 bTickedPose = false;
527
528 if (VisualizationMesh)
529 {
530 HandVisualizerComponent->SetSkeletalMesh(VisualizationMesh);
531 if (HandPreviewMaterial)
532 {
533 HandVisualizerComponent->SetMaterial(0, (UMaterialInterface*)HandPreviewMaterial);
534 }
535 }
536
537 PositionVisualizationMesh();
538 PoseVisualizationToAnimation(true);
539 }
540 }
541
542#endif // WITH_EDITORONLY_DATA
543
544 Super::OnRegister();
545}
546
547#if WITH_EDITORONLY_DATA
548
549void UHandSocketComponent::PositionVisualizationMesh()
550{
551 if (!HandVisualizerComponent)
552 {
553 return;
554 }
555
556 if (USceneComponent* ParentAttach = this->GetAttachParent())
557 {
558 FTransform relTrans = this->GetRelativeTransform();
559
560 if (bDecoupled != bDecoupleMeshPlacement)
561 {
563 {
564 HandRelativePlacement = HandRelativePlacement * GetRelativeTransform();
565 }
566 else
567 {
568 HandRelativePlacement = HandRelativePlacement.GetRelativeTransform(GetRelativeTransform());
569 }
570 }
571
572 FTransform HandPlacement = GetHandRelativePlacement();
573 FTransform ReturnTrans = (HandPlacement * relTrans);
574
575 if (bMirrorVisualizationMesh)//(bFlipForLeftHand && !bIsRightHand))
576 {
577 MirrorHandTransform(ReturnTrans, relTrans);
578 }
579
580 if ((bLeftHandDominant && !bMirrorVisualizationMesh) || (!bLeftHandDominant && bMirrorVisualizationMesh))
581 {
582 ReturnTrans.SetScale3D(ReturnTrans.GetScale3D() * MirroredScale);
583 }
584
585 HandVisualizerComponent->SetRelativeTransform(ReturnTrans.GetRelativeTransform(relTrans)/*newRel*/);
586 }
587}
588
589void UHandSocketComponent::HideVisualizationMesh()
590{
591 if (!bShowVisualizationMesh && HandVisualizerComponent)
592 {
593 HandVisualizerComponent->SetVisibility(false);
594 HandVisualizerComponent->DestroyComponent();
595 HandVisualizerComponent = nullptr;
596 }
597}
598
599#endif
600
601#if WITH_EDITORONLY_DATA
602void UHandSocketComponent::PoseVisualizationToAnimation(bool bForceRefresh)
603{
604
605 if (!HandVisualizerComponent || !HandVisualizerComponent->SkeletalMesh)
606 return;
607
608 TArray<FTransform> LocalPoses;
610 {
611 // Store local poses for posing
612 LocalPoses = HandVisualizerComponent->SkeletalMesh->GetSkeleton()->GetRefLocalPoses();
613 }
614
615 TArray<FName> BonesNames;
616 HandVisualizerComponent->GetBoneNames(BonesNames);
617 int32 Bones = HandVisualizerComponent->GetNumBones();
618
619 for (int32 i = 0; i < Bones; i++)
620 {
622 {
623 HandVisualizerComponent->ResetBoneTransformByName(BonesNames[i]);
624 continue;
625 }
626
627 FName ParentBone = HandVisualizerComponent->GetParentBone(BonesNames[i]);
628 FTransform ParentTrans = FTransform::Identity;
629 if (ParentBone != NAME_None)
630 {
631 ParentTrans = HandVisualizerComponent->GetBoneTransformByName(ParentBone, EBoneSpaces::ComponentSpace);
632 }
633
634
635 FQuat DeltaQuat = FQuat::Identity;
637 {
639 {
640 if (BonePairC.BoneName == BonesNames[i])
641 {
642 DeltaQuat = BonePairC.DeltaPose;
643 DeltaQuat.Normalize();
644 break;
645 }
646 }
647 }
648
649 FTransform BoneTrans = FTransform::Identity;
650
652 {
653 BoneTrans = GetBoneTransformAtTime(HandTargetAnimation, /*FLT_MAX,*/ i, false); // true;
654 }
655 else
656 {
657 BoneTrans = LocalPoses[i];
658 }
659
660 BoneTrans = BoneTrans * ParentTrans;// *HandVisualizerComponent->GetComponentTransform();
661 BoneTrans.NormalizeRotation();
662
663 //DeltaQuat *= HandVisualizerComponent->GetComponentTransform().GetRotation().Inverse();
664
665 BoneTrans.ConcatenateRotation(DeltaQuat);
666 BoneTrans.NormalizeRotation();
667 HandVisualizerComponent->SetBoneTransformByName(BonesNames[i], BoneTrans, EBoneSpaces::ComponentSpace);
668
669 }
670
671 if (HandVisualizerComponent && (!bTickedPose || bForceRefresh))
672 {
673 // Tick Pose first
674 if (HandVisualizerComponent->IsRegistered())
675 {
676 bTickedPose = true;
677 HandVisualizerComponent->TickPose(1.0f, false);
678 if (HandVisualizerComponent->MasterPoseComponent.IsValid())
679 {
680 HandVisualizerComponent->UpdateSlaveComponent();
681 }
682 else
683 {
684 HandVisualizerComponent->RefreshBoneTransforms(&HandVisualizerComponent->PrimaryComponentTick);
685 }
686 }
687 }
688}
689
690void UHandSocketComponent::AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector)
691{
692 UHandSocketComponent* This = CastChecked<UHandSocketComponent>(InThis);
693 Collector.AddReferencedObject(This->HandVisualizerComponent);
694
695 Super::AddReferencedObjects(InThis, Collector);
696}
697
698void UHandSocketComponent::OnComponentDestroyed(bool bDestroyingHierarchy)
699{
700 Super::OnComponentDestroyed(bDestroyingHierarchy);
701
702 if (HandVisualizerComponent)
703 {
704 HandVisualizerComponent->DestroyComponent();
705 }
706}
707
708#endif
709
710void UHandSocketComponent::GetLifetimeReplicatedProps(TArray< class FLifetimeProperty > & OutLifetimeProps) const
711{
712 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
713
716 DOREPLIFETIME_CONDITION(UHandSocketComponent, GameplayTags, COND_Custom);
717}
718
719void UHandSocketComponent::PreReplication(IRepChangedPropertyTracker & ChangedPropertyTracker)
720{
721 Super::PreReplication(ChangedPropertyTracker);
722
723 // Don't replicate if set to not do it
724 DOREPLIFETIME_ACTIVE_OVERRIDE(UHandSocketComponent, GameplayTags, bRepGameplayTags);
725
726 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeLocation, bReplicateMovement);
727 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeRotation, bReplicateMovement);
728 DOREPLIFETIME_ACTIVE_OVERRIDE_PRIVATE_PROPERTY(USceneComponent, RelativeScale3D, bReplicateMovement);
729}
730
731//=============================================================================
735
736#if WITH_EDITOR
737
738void UHandSocketComponent::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
739{
740 Super::PostEditChangeProperty(PropertyChangedEvent);
741
742 FProperty* PropertyThatChanged = PropertyChangedEvent.Property;
743
744 if (PropertyThatChanged != nullptr)
745 {
746#if WITH_EDITORONLY_DATA
747 if (PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(UHandSocketComponent, HandTargetAnimation) ||
748 PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(UHandSocketComponent, VisualizationMesh)
749 )
750 {
751 PositionVisualizationMesh();
752 PoseVisualizationToAnimation(true);
753 }
754 else if (PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(UHandSocketComponent, CustomPoseDeltas))
755 {
756 PoseVisualizationToAnimation(true);
757 }
758 else if (PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(UHandSocketComponent, HandRelativePlacement))
759 {
760 PositionVisualizationMesh();
761 }
762 else if (PropertyThatChanged->GetFName() == GET_MEMBER_NAME_CHECKED(UHandSocketComponent, bShowVisualizationMesh))
763 {
764 HideVisualizationMesh();
765 }
766#endif
767 }
768}
769#endif
770
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",...
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")
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")