A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
PixoVRHand.cpp
Go to the documentation of this file.
1// Copyright(c) Pixo Group. All Rights Reserved.
2#include "PixoVRHand.h"
4#include "PixoVRCharacter.h"
7#include "Kismet/GameplayStatics.h"
8#include "Kismet/KismetMathLibrary.h"
9#include "Kismet/KismetSystemLibrary.h"
10
11// Sets default values
13{
14 // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
15 PrimaryActorTick.bCanEverTick = true;
16
17 Root = CreateDefaultSubobject<USceneComponent>("Root");
18 Root->SetupAttachment(RootComponent);
19
20 MotionController = CreateDefaultSubobject<UGripMotionControllerComponent>("MotionController");
22 {
23 MotionController->SetupAttachment(Root);
24 MotionController->SetGenerateOverlapEvents(false);
25 MotionController->SetRelativeLocation(FVector(65.0f, -43.25f, -11.51f));
26 }
27
28 GrabSphere = CreateDefaultSubobject<USphereComponent>("GrabSphere");
29 GrabSphere->SetupAttachment(MotionController);
30 GrabSphere->SetCollisionProfileName("OverlapAll");
31 GrabSphere->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
32 GrabSphere->SetVisibility(true, true);
33 GrabSphere->SetHiddenInGame(false, true);
34 GrabSphere->SetSphereRadius(4.0f);
35 GrabSphere->SetRelativeLocation(FVector(2.0f, 0.0f, -2.5f));
36 GrabSphere->SetIsReplicated(true);
37
38 HandMesh = CreateDefaultSubobject<USkeletalMeshComponent>("HandMesh");
39 HandMesh->SetupAttachment(MotionController);
40
41 LaserMesh = CreateDefaultSubobject<UStaticMeshComponent>("Laser");
42 LaserMesh->SetupAttachment(HandMesh, "LaserSocket");
43 static ConstructorHelpers::FObjectFinder<UStaticMesh> LaserMeshFinder(TEXT("StaticMesh'/PixoCore/Meshes/Tools/SM_LaserPointer.SM_LaserPointer'"));
44 LaserMesh->SetStaticMesh(LaserMeshFinder.Object);
45 LaserMesh->SetVisibility(false);
46
47 static ConstructorHelpers::FObjectFinder<USoundCue> LaserSoundFinder(TEXT("SoundCue'/PixoCore/Audio/SFX/LaserToggle_Cue.LaserToggle_Cue'"));
48 LaserSound = NewObject<USoundCue>();
49 LaserSound = LaserSoundFinder.Object;
50
51 TouchComponent = CreateDefaultSubobject<UWidgetInteractionComponent>("TouchComponent");
52 TouchComponent->SetupAttachment(HandMesh, "TouchIntr");
53 TouchComponent->SetRelativeLocation(FVector(6.8, -1.3, 0));
54 TouchComponent->SetRelativeRotation(FRotator(0.0,170.0, 0.0));
55 TouchComponent->TraceChannel = ECollisionChannel::ECC_Visibility;
56 TouchComponent->InteractionDistance = 10.0;
57 TouchComponent->bEnableHitTesting = true;
58 TouchComponent->OnHoveredWidgetChanged.AddDynamic(this, &APixoVRHand::OnTouchWidget);
59 TouchComponent->SetAutoActivate(false);
60
61 //Right now it's implemented in blueprint class
62 /*ThumbSpline = CreateDefaultSubobject<USplineComponent>("ThumbSpline");
63 ThumbSpline->SetupAttachment(HandMesh);
64 IndexSpline = CreateDefaultSubobject<USplineComponent>("IndexSpline");
65 IndexSpline->SetupAttachment(HandMesh);
66 MiddleSpline = CreateDefaultSubobject<USplineComponent>("MiddleSpline");
67 MiddleSpline->SetupAttachment(HandMesh);
68 RingSpline = CreateDefaultSubobject<USplineComponent>("RingSpline");
69 RingSpline->SetupAttachment(HandMesh);
70 PinkySpline = CreateDefaultSubobject<USplineComponent>("PinkySpline");
71 PinkySpline->SetupAttachment(HandMesh);*/
72}
73
75{
76 FOverlappingInfo OverlappingInfo;
77 GetOverlappingActor(OverlappingInfo);
78 if (!OverlappingInfo.OverlapActor)
79 {
80 return;
81 }
82
83 if (OverlappingInfo.OverlapComponent == nullptr)
84 {
85 if (OverlappingInfo.OverlapActor->GetClass()->ImplementsInterface(UPixoVRStoryObject::StaticClass()) && IPixoVRStoryObject::Execute_CouldBeGrabbedByOtherHand(OverlappingInfo.OverlapActor))
87
88 if (MotionController->GripObjectByInterface(OverlappingInfo.OverlapActor, OverlappingInfo.OverlapActor->GetTransform()))
89 HandHoldingObject = OverlappingInfo.OverlapActor;
90 }
91 else
92 {
93 MotionController->GripObjectByInterface(OverlappingInfo.OverlapComponent, OverlappingInfo.OverlapActor->GetTransform());
94 HandHoldingObject = OverlappingInfo.OverlapComponent;
95 }
96 //Do we need this ???
97 //ClientSetHoldingActor(HandHoldingObject, EControllerHand::Left);
99}
100
102{
104
105 HandHoldingObject = nullptr;
106 //Do we need this ???
107 //ClientReleaseHoldingActor(EControllerHand::Left);
108
109 FingerData.Index = 0.0;
110 FingerData.Middle = 0.0;
111 FingerData.Pinky = 0.0;
112 FingerData.Ring = 0.0;
113 FingerData.Thumb = 0.0;
114}
115
117{
118 if (ActorRef)
119 {
120 if (MotionController->GripObjectByInterface(ActorRef, ActorRef->GetTransform()))
121 GetWorldTimerManager().SetTimerForNextTick([this, ActorRef](){HandHoldingObject = ActorRef;});
122 }
124}
125
126void APixoVRHand::OnTouchWidget(UWidgetComponent* WidgetComponent, UWidgetComponent* PreviousWidgetComponent)
127{
128 if (WidgetComponent && WidgetComponent->GetUserWidgetObject() && !TouchComponentCooldownActive)
129 {
130 TouchComponent->PressPointerKey("LeftMouseButton");
132 FTimerHandle TimerHandle;
133 GetWorld()->GetTimerManager().SetTimer(TimerHandle, this, &APixoVRHand::DeactivateTouchCooldown, 0.2);
134 }
135}
136
138{
139 TouchComponent->ReleasePointerKey("LeftMouseButton");
141}
142
144{
145 if (!HeldActor)
146 {
147 UE_LOG(LogTemp, Error, TEXT("PixoVrHand - ReleaseHeldedObjectOnOtherHand - Actor reference is invalid"));
148 return;
149 }
150 TArray<FBPGripPair> HoldingControllers;
151 bool IsHeld;
152 IVRGripInterface::Execute_IsHeld(HeldActor, HoldingControllers, IsHeld);
153 if (IsHeld)
154 {
155 APixoVRCharacter* PlayerRef = Cast<APixoVRCharacter>(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
156 APixoVRHand* HandHoldingItem = HandMotionSource == EControllerHand::Right ? PlayerRef->VRHandLeft : PlayerRef->VRHandRight;
157 if (IPixoVRStoryObject::Execute_HoldItemByClick(HeldActor))
158 {
159 if (HandMotionSource == EControllerHand::Right)
160 {
161 PlayerRef->HoldToolLeft = true;
162 PlayerRef->HoldToolRight = false;
163 PlayerRef->GrabLeftReleased();
164 }
165 else
166 {
167 PlayerRef->HoldToolLeft = false;
168 PlayerRef->HoldToolRight = true;
169 PlayerRef->GrabRightReleased();
170 }
171 }
172 HandHoldingItem->ReleaseObject();
173 }
174}
175
176void APixoVRHand::ToggleLaser(bool Visible)
177{
178 LaserMesh->SetVisibility(Visible);
179
180 UGameplayStatics::PlaySound2D(this, LaserSound);
181}
182
183TArray<FVector> APixoVRHand::GetRelativePointsArray(USplineComponent* FingerSpline, float Precision)
184{
185 if (Precision <= 0)
186 {
187 UE_LOG(LogTemp, Error, TEXT("Grab precision can not be less then 1"));
188 return TArray<FVector>();
189 }
190 if (FingerSpline)
191 {
192 float stepSize = FingerSpline->Duration / Precision;
193 TArray<FVector> relativePointsArray;
194 for (int i = 0; i < Precision - 1; i++)
195 {
196 float splineTime = UKismetMathLibrary::FClamp(i * stepSize, 0.0, 1.0);
197 relativePointsArray.Add(UKismetMathLibrary::TransformLocation(
198 FingerSpline->GetRelativeTransform(),
199 FingerSpline->GetLocationAtTime(splineTime, ESplineCoordinateSpace::Local, true)));
200 }
201 return relativePointsArray;
202 }
203 UE_LOG(LogTemp, Error, TEXT("Spline reference is not valid"));
204 return TArray<FVector>();
205}
206
207float APixoVRHand::TraceFingerForObstacle(TArray<FVector> RelativePointsArray)
208{
209 FVector splinePointLocation;
210 FVector nextSplinePointLocation;
211 float hitLenght = 0;
212 float totalLenght = 0;
213 bool didHit = false;
214 FHitResult hitResult;
215 TArray<TEnumAsByte<EObjectTypeQuery>> traceObjectTypes;
216 traceObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));
217 traceObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldDynamic));
218 traceObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_PhysicsBody));
219 FCollisionQueryParams queryParams;
220 queryParams.AddIgnoredActor(this);
221
222 for (int i = 0; i < RelativePointsArray.Num() - 2; i++)
223 {
224 splinePointLocation = UKismetMathLibrary::TransformLocation(HandMesh->GetComponentTransform(),
225 RelativePointsArray[i]);
226 nextSplinePointLocation = UKismetMathLibrary::TransformLocation(HandMesh->GetComponentTransform(),
227 RelativePointsArray[i + 1]);
228
229 //Trace grabbed Component for Finger Positioning
230 if (!didHit)
231 {
232 bool didTraceHit = GetWorld()->LineTraceSingleByObjectType(hitResult, splinePointLocation,
233 nextSplinePointLocation, traceObjectTypes,
234 queryParams);
235 if (didTraceHit)
236 {
237 didHit = true;
238 hitLenght = totalLenght + hitResult.Distance;
239 }
240 }
241 //Calculate Total Length of the Trace and update Hit Length if necessary
242 totalLenght = totalLenght + UKismetMathLibrary::Vector_Distance(splinePointLocation, nextSplinePointLocation);
243 if (!didHit)
244 {
245 hitLenght = totalLenght;
246 }
247 }
248 return UKismetMathLibrary::FClamp(hitLenght / totalLenght, 0.0, 1.0);
249}
250
260
269
270// Called when the game starts or when spawned
272{
273 Super::BeginPlay();
274
275 //Can be used when init of splines would be in c++
276 //SetupFingerTracePoints();
277}
278
279// Called every frame
280void APixoVRHand::Tick(float DeltaTime)
281{
282 Super::Tick(DeltaTime);
283
284 auto IsObjectHasGripType = [](const FOverlappingInfo &OverlapInfo, const EGrippableTypeChecker &GripTypeChecker)->bool
285 {
286 switch (GripTypeChecker)
287 {
289 return true;
291 if (OverlapInfo.OverlapActor->GetClass()->ImplementsInterface(UPixoVRStoryObject::StaticClass()))
292 return IPixoVRStoryObject::Execute_IsObjectActive(OverlapInfo.OverlapActor);
293 return false;
295 return OverlapInfo.OverlapActor->GetClass()->ImplementsInterface(UPixoVRStoryObject::StaticClass());
297 return OverlapInfo.OverlapActor->GetClass()->ImplementsInterface(UVRGripInterface::StaticClass());
298 default:
299 return false;
300 }
301 };
302
303 // Activation logic when hand approaches to interactable object hand animation changing and object is highlighting
305 {
306 if (HandHoldingObject == nullptr)
307 {
308 FOverlappingInfo OverlapInfo;
309 GetOverlappingActor(OverlapInfo);
310 if (OverlapInfo.OverlapActor)
311 {
312 if (OverlapedActor != OverlapInfo.OverlapActor)
313 {
315 IHandAnimationInterface::Execute_SetAnimationGripState(HandMesh->GetAnimInstance(), EPixoVRGripState::Open);
317 {
318 IPixoVRStoryObject::Execute_UpdateObjectHighlight(OverlapedActor, false);
319 }
320 }
321 if (IsObjectHasGripType(OverlapInfo, GrippableTypeChecker) && !InteractableObjectNearHand)
322 {
323 IHandAnimationInterface::Execute_SetAnimationGripState(HandMesh->GetAnimInstance(), EPixoVRGripState::CanGrab);
325 OverlapedActor = OverlapInfo.OverlapActor;
327 {
328 IPixoVRStoryObject::Execute_UpdateObjectHighlight(OverlapInfo.OverlapActor, true);
329 }
330 }
331 }
332 else
333 {
335 {
336 IHandAnimationInterface::Execute_SetAnimationGripState(HandMesh->GetAnimInstance(), EPixoVRGripState::Open);
339 {
340 IPixoVRStoryObject::Execute_UpdateObjectHighlight(OverlapedActor, false);
341 }
342 }
343 }
344 }
346 {
347 IPixoVRStoryObject::Execute_UpdateObjectHighlight(OverlapedActor, false);
348 OverlapedActor = nullptr;
349 }
350 }
351}
352
353void APixoVRHand::InitPixoVRHands(EControllerHand MotionSource, APixoVRCharacter* Character)
354{
355 OwningCharacter = Character;
356
357 HandMotionSource = MotionSource;
358 switch (MotionSource)
359 {
360 case EControllerHand::Left:
361 MotionController->SetTrackingMotionSource(FXRMotionControllerBase::LeftHandSourceId);
362 HandMesh->SetRelativeScale3D(FVector(1.0, 1.0, -1.0));
363 TouchComponent->PointerIndex = 0;
364 break;
365 case EControllerHand::Right:
366 MotionController->SetTrackingMotionSource(FXRMotionControllerBase::RightHandSourceId);
367 TouchComponent->PointerIndex = 1;
368 break;
369 default:
370 UE_LOG(LogTemp, Error, TEXT("Hand motion source is undefined!"));
371 break;
372 }
373
375 // Keep the controllers ticking after movement
376 /*MotionController->AddTickPrerequisiteComponent(OwningCharacter->GetCharacterMovement());
377 MotionController->OverrideSendTransform = &AVRBaseCharacter::Server_SendTransformLeftController;*/
378
379 if (HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
380 {
381 IHandAnimationInterface::Execute_SetHandActor(HandMesh->GetAnimInstance(), this);
382 }
383 else
384 UE_LOG(LogTemp, Error, TEXT("Animation blueprint does not implement PixoVRGripInterface"));
385}
386
387void APixoVRHand::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
388{
389 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
390
391 DOREPLIFETIME(APixoVRHand, HandHoldingObject);
392 DOREPLIFETIME(APixoVRHand, FingerData);
393}
394
396{
397 // If we hold already something on this hand, don't check for anything else.
398 if (HandHoldingObject != nullptr)
399 {
400 return;
401 }
402
403 TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
404 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldDynamic));
405 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_PhysicsBody));
406 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));
407 auto TraceComplex = false;
408 TArray<AActor*> ActorsToIgnore;
409 auto IgnoreSelf = true;
410 TArray<FHitResult> HitResults;
411
412 // TODO Because 4.22 has issues (returning always false) when Start and End vector are the same
413 // an offset is used.
414 bool Hit = UKismetSystemLibrary::SphereTraceMultiForObjects(GetWorld(),
415 GrabSphere->GetComponentLocation(),
416 GrabSphere->GetComponentLocation() + (GrabSphere->
417 GetForwardVector() * 0.01),
418 GrabSphere->GetUnscaledSphereRadius(),
419 ObjectTypes,
420 TraceComplex,
421 ActorsToIgnore,
422 EDrawDebugTrace::None,
423 HitResults,
424 IgnoreSelf);
425
426
427 if (Hit)
428 {
429 for (const auto& HitResult : HitResults)
430 {
431 // Does the actor support our grip interface?
432 if (HitResult.Actor->GetClass()->ImplementsInterface(UVRGripInterface::StaticClass()))
433 {
434 OverlappingInfo.OverlapActor = HitResult.Actor.Get();
435
436 if (HitResult.Component->GetClass()->ImplementsInterface(UVRGripInterface::StaticClass()))
437 {
438 OverlappingInfo.OverlapComponent = HitResult.Component.Get();
439 }
440
441 // Do we have a collision with a socket?
442 if (HitResult.BoneName != NAME_None)
443 {
444 OverlappingInfo.Socket = HitResult.BoneName;
445 }
446
447 if (OverlappingInfo.OverlapActor && !IVRGripInterface::Execute_DenyGripping(OverlappingInfo.OverlapActor,MotionController))
448 {
449 break;
450 }
451 }
452 }
453 }
454}
EGrippableTypeChecker
EGrippableTypeChecker is an enumeration that represents what type of objects we can grip.
Definition PixoVRHand.h:85
Pixo VR Character This class represents the main character in the Pixo VR game. It extends the AVRCha...
APixoVRHand * VRHandLeft
UPROPERTY(BlueprintReadOnly, Category = "Hands")
APixoVRHand * VRHandRight
UPROPERTY(BlueprintReadOnly, Category = "Hands")
virtual void GrabLeftReleased()
UFUNCTION(BlueprintCallable, Category = "Hands")
virtual void GrabRightReleased()
UFUNCTION(BlueprintCallable, Category = "Hands")
APixoVRHand is an actor class that represents a hand in the VR environment.
Definition PixoVRHand.h:99
void SetupFingerTracePoints()
Sets up the cache of relative points for finger tracing. This function should be called during initia...
float TraceFingerForObstacle(TArray< FVector > RelativePointsArray)
Traces the finger along the given array of relative points to check for obstacles.
TArray< FVector > ThumbPositionCache
Definition PixoVRHand.h:323
void UpdateFingerData()
Updates the finger data by tracing each finger for obstacles and storing the normalized obstacle dist...
UWidgetInteractionComponent * TouchComponent
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:172
bool TouchComponentCooldownActive
Definition PixoVRHand.h:339
void ManuallyPutActorToHand(AActor *ActorRef)
Manually puts an actor into the hand. Hand will try to grab this actor.
FFingerData FingerData
UPROPERTY(EditAnywhere, BlueprintReadWrite, Replicated, Category = "Animation")
Definition PixoVRHand.h:282
bool ChangeHandAnimationNearInteractableObject
UPROPERTY(EditDefaultsOnly, Category = "Animation")
Definition PixoVRHand.h:303
void DeactivateTouchCooldown()
Deactivates the touch cooldown of the hand.
bool InteractableObjectNearHand
Definition PixoVRHand.h:320
UStaticMeshComponent * LaserMesh
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:136
USkeletalMeshComponent * HandMesh
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:130
void GrabObject()
Grabs the object currently overlapped by grab sphere.
APixoVRCharacter * OwningCharacter
UPROPERTY(BlueprintReadWrite, Category = "Init")
Definition PixoVRHand.h:358
USplineComponent * RingSpline
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:160
bool IsObjectHighlightActive
Show highlight if hand near object that we can grab.
Definition PixoVRHand.h:319
USplineComponent * PinkySpline
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:166
TArray< FVector > GetRelativePointsArray(USplineComponent *FingerSpline, float Precision)
Retrieves an array of relative points along the finger spline.
TArray< FVector > MiddlePositionCache
Definition PixoVRHand.h:325
void InitPixoVRHands(EControllerHand MotionSource, APixoVRCharacter *Character)
UGripMotionControllerComponent * MotionController
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:118
virtual void BeginPlay() override
USphereComponent * GrabSphere
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:124
virtual void Tick(float DeltaTime) override
void ReleaseHeldObjectOnOtherHand(AActor *HeldActor)
Releases the held object on the other hand.
USplineComponent * MiddleSpline
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:154
USceneComponent * Root
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:112
void GetOverlappingActor(FOverlappingInfo &OverlappingInfo)
Gets the info of actor currently overlapping with the grab sphere.
EGrippableTypeChecker GrippableTypeChecker
Flag that indicated near which objects should we change animation.
Definition PixoVRHand.h:311
void ReleaseObject()
Releases the currently held object.
USplineComponent * ThumbSpline
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:142
TArray< FVector > PinkyPositionCache
Definition PixoVRHand.h:327
EControllerHand HandMotionSource
UPROPERTY(BlueprintReadWrite, Category = "Init", meta = (ExposeOnSpawn = "true"))
Definition PixoVRHand.h:352
USplineComponent * IndexSpline
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:148
TArray< FVector > IndexPositionCache
Definition PixoVRHand.h:324
UObject * HandHoldingObject
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
Definition PixoVRHand.h:228
AActor * OverlapedActor
Definition PixoVRHand.h:321
void OnTouchWidget(UWidgetComponent *WidgetComponent, UWidgetComponent *PreviousWidgetComponent)
Called when the hand touches a widget component.
void ToggleLaser(bool Visible)
Toggles the visibility of the laser.
USoundCue * LaserSound
UPROPERTY()
Definition PixoVRHand.h:242
TArray< FVector > RingPositionCache
Definition PixoVRHand.h:326
bool GripObjectByInterface(UObject *ObjectToGrip, const FTransform &WorldOffset, bool bWorldOffsetIsRelative=false, FName OptionalBoneToGripName=NAME_None, FName OptionalSnapToSocketName=NAME_None, bool bIsSlotGrip=false)
UFUNCTION(BlueprintCallable, Category = "GripMotionController")
bool bOffsetByHMD
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "GripMotionController|Advanced|Tracking")
bool DropObjectByInterface(UObject *ObjectToDrop=nullptr, uint8 GripIDToDrop=0, FVector OptionalAngularVelocity=FVector::ZeroVector, FVector OptionalLinearVelocity=FVector::ZeroVector)
UFUNCTION(BlueprintCallable, Category = "GripMotionController")
float Middle
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Definition PixoVRHand.h:62
float Pinky
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Definition PixoVRHand.h:74
float Index
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Definition PixoVRHand.h:56
float Ring
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Definition PixoVRHand.h:68
float Thumb
UPROPERTY(EditAnywhere, BlueprintReadWrite)
Definition PixoVRHand.h:50
FOverlappingInfo is a structure that holds information about overlapping actors and components.
Definition PixoVRHand.h:22
AActor * OverlapActor
Definition PixoVRHand.h:29
UPrimitiveComponent * OverlapComponent
Definition PixoVRHand.h:30