Documentation for the Unreal C++ Plugin
Loading...
Searching...
No Matches
PixoVRCharacter.cpp
Go to the documentation of this file.
1// Copyright(c) Pixo Group. All Rights Reserved.
2
3#include "PixoVRCharacter.h"
12#include "Components/BillboardComponent.h"
13#include "GameFramework/GameModeBase.h"
14#include "Grippables/GrippableActor.h"
19#include "Kismet/GameplayStatics.h"
21
22DEFINE_LOG_CATEGORY(LogPixoVRCharacter);
23
25 : DefaultPlayerHeight(165)
26 , bLaserBeamActive(false)
27 , LeftTeleporterSocket(NAME_None)
28 , RightTeleporterSocket(NAME_None)
29 , TeleportControllerLeft(nullptr)
30 , TeleportControllerRight(nullptr)
31 , LeftLaserBeamSocket(NAME_None)
32 , RightLaserBeamSocket(NAME_None)
33 , LaserControllerLeft(nullptr)
34 , LaserControllerRight(nullptr)
35 , bLeftLaserBeamIsActiveOnStart(false)
36 , bRightLaserBeamIsActiveOnStart(false)
37 , WristMenuLoc(nullptr)
38 , ProgressBarClass(APixoVRCircleProgress::StaticClass())
39 , WristMenuSocket(FName("WristMenuSocket"))
40 , WristMenu(nullptr)
41 , MirroredWristMenuScale(FVector(1, -1, -1))
42 , ToolSocket("ToolSocket")
43 , BaseTurnRate(45.0f)
44 , BaseLookUpRate(45.0f)
45 , bDisableToolsInputBindings(false)
46 , Head(nullptr)
47 , Body(nullptr)
48{
49 PrimaryActorTick.bCanEverTick = true;
50
51 bReplicates = true;
52 SetReplicateMovement(true);
53 bNetLoadOnClient = true;
54
55 static ConstructorHelpers::FObjectFinder<UStaticMesh> HeadMeshFinder(
56 TEXT("StaticMesh'/PixoCore/Meshes/SM_PlayerHead.SM_PlayerHead'"));
57 UStaticMesh* HeadMesh = HeadMeshFinder.Object;
58
59 static ConstructorHelpers::FObjectFinder<UMaterialInstance> HeadMeshMaterialFinder(
60 TEXT("MaterialInstanceConstant'/PixoCore/Materials/MI_PlayerHead.MI_PlayerHead'"));
61 UMaterialInstance* HeadMeshMaterial = HeadMeshMaterialFinder.Object;
62
63 static ConstructorHelpers::FObjectFinder<UStaticMesh> BodyMeshFinder(
64 TEXT("StaticMesh'/PixoCore/Meshes/BasicShapes/Cylinder.Cylinder'"));
65 UStaticMesh* BodyMesh = BodyMeshFinder.Object;
66
67 static ConstructorHelpers::FObjectFinder<UMaterial> BodyMeshMaterialFinder(
68 TEXT("Material'/PixoCore/Materials/Body/BasicShapeMaterialTrans.BasicShapeMaterialTrans'"));
69 UMaterial* BodyMeshMaterial = BodyMeshMaterialFinder.Object;
70
71 TeleportControllerClass = APixoVRTeleporter::StaticClass();
72 LaserControllerClass = APixoVRLaser::StaticClass();
73 WristMenuClass = APixoVRWristMenu::StaticClass();
74
75 Head = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("HeadMesh"));
76 Head->SetStaticMesh(HeadMesh);
77 Head->SetMaterial(0, HeadMeshMaterial);
78 Head->SetRelativeLocation(FVector(0.0f, 0.0f, -15.0f));
79 Head->SetRelativeRotation(FRotator(0.0f, -90.0f, 0.0f));
80 Head->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
81 Head->SetupAttachment(VRReplicatedCamera);
82
83 Body = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BodyMesh"));
84 Body->SetStaticMesh(BodyMesh);
85 Body->SetMaterial(0, BodyMeshMaterial);
86 Body->SetRelativeLocation(FVector(-8.0f, 0.0f, -160.0f));
87 Body->SetRelativeScale3D(FVector(0.5f, 0.5f, 0.1f));
88 Body->SetCollisionProfileName(UCollisionProfile::CustomCollisionProfileName);
89 Body->SetCollisionEnabled(ECollisionEnabled::QueryOnly);
90 Body->SetCollisionObjectType(ECollisionChannel::ECC_Pawn);
91 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldStatic, ECollisionResponse::ECR_Overlap);
92 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldDynamic, ECollisionResponse::ECR_Overlap);
93 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap);
94 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_PhysicsBody, ECollisionResponse::ECR_Overlap);
95 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_Vehicle, ECollisionResponse::ECR_Overlap);
96 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_Destructible, ECollisionResponse::ECR_Overlap);
97 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Overlap);
98 Body->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Overlap);
99 Body->SetupAttachment(ParentRelativeAttachment);
100
101 bUseControllerRotationPitch = true;
102 bUseControllerRotationYaw = true;
103 bUseControllerRotationRoll = false;
104
105 VRReplicatedCamera->bUsePawnControlRotation = false;
106 VRReplicatedCamera->bLockToHmd = true;
107 VRReplicatedCamera->bAutoSetLockToHmd = true;
108 VRReplicatedCamera->SetRelativeLocation(FVector(0.0f, 0.0f, DefaultPlayerHeight));
109
110 WristMenuLoc = CreateDefaultSubobject<UBillboardComponent>(TEXT("Wrist Menu PC Location"));
111 WristMenuLoc->SetRelativeScale3D(FVector(.25f, .25f, .25f));
112 WristMenuLoc->SetRelativeLocation(FVector(50.0f, 2.0f, .0f));
113 WristMenuLoc->SetupAttachment(VRReplicatedCamera);
114
115 InputAdapter = NewObject<UPixoVRInputAdapter>();
116 LongHoldComponent = CreateDefaultSubobject<UPixoVRLongHoldComponent>(TEXT("LongHoldComponent"));
117
118 FadeSphere = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FadeSphere"));
119 FadeSphere->SetupAttachment(VRReplicatedCamera);
120 static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereMeshAsset(
121 TEXT("StaticMesh'/Engine/BasicShapes/Sphere.Sphere'"));
122 FadeSphere->SetStaticMesh(SphereMeshAsset.Object);
123 static ConstructorHelpers::FObjectFinder<UMaterial> FadeSphereMaterialAsset(
124 TEXT("Material'/PixoCore/Materials/Controller/M_FadeMaterial.M_FadeMaterial'"));
125 FadeSphere->SetMaterial(0, FadeSphereMaterialAsset.Object);
126 FadeSphere->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
127 FadeSphere->SetCollisionEnabled(ECollisionEnabled::NoCollision);
128
129 //Causes crashes on PICO
130 //UBlueprintGeneratedClass* DefaultVRHandClass = Cast<UBlueprintGeneratedClass>(StaticLoadClass(UObject::StaticClass(), nullptr,TEXT("/PixoCore/Blueprints/Hands/BP_PixoVRHand.BP_PixoVRHand_C")));
131 //VRHandClass = DefaultVRHandClass;
132}
133
134
136{
137 Super::BeginPlay();
138
139 OnDestroyed.AddDynamic(this, &APixoVRCharacter::PlayerDestroyed);
140
141 if (GetLocalRole() == ROLE_Authority && GetWorld()->GetAuthGameMode()->GetClass()->ImplementsInterface(UPixoCoreInterface::StaticClass()))
142 {
143 HintManager = Cast<UHintManager>(IPixoCoreInterface::Execute_GetManagerRef(GetWorld()->GetAuthGameMode(), UHintManager::StaticClass()));
144 }
145
146 // We will spawn here only on the clients. The server will spawn the tools when this character gets possessed by a new controller.
147 if(!HasAuthority())
148 {
149 SpawnTeleporter(EControllerHand::Left, true);
150 SpawnTeleporter(EControllerHand::Right, true);
151 }
152
153 const auto DeviceName = UHeadMountedDisplayFunctionLibrary::GetHMDDeviceName();
154
155 UE_LOG(LogPixoVRCharacter, Log, TEXT("PixoVRCharacter::BeginPlay DeviceName = %s"), *DeviceName.ToString());
156
157 if (DeviceName == "SteamVR") // VIVE
158 {
159 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Floor);
160 }
161 else if (DeviceName == "OculusHMD") // Oculus
162 {
163 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Eye);
164 VRProxyComponent->AddLocalOffset(FVector(0.0f, 0.0f, DefaultPlayerHeight));
165 }
166 else if (DeviceName == "WaveVR") // FOCUS PLUS
167 {
168 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Floor);
169 }
170 else if (DeviceName == "PICOXRHMD") // PICO NEO
171 {
172 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Floor);
173 }
174 else if (DeviceName.ToString().Contains("Monado"))
175 {
176 FBPVRControllerProfile ControllerProfile;
177 UVRGlobalSettings::GetControllerProfile("VRX", ControllerProfile);
178 UVRGlobalSettings::LoadControllerProfile(ControllerProfile, true);
179
180 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Floor);
181 VRProxyComponent->AddLocalOffset(FVector(0.0f, 0.0f, 15.f));
182 }
183 else // Windows
184 {
185// default to quest setup, unless compiling on windows
186// this is for unknown headsets like the VRX
187#if PLATFORM_WINDOWS
188 // default to windows
189 ActivateFPSMode(true);
190#else
191 // ...or default to oculus
192 UHeadMountedDisplayFunctionLibrary::SetTrackingOrigin(EHMDTrackingOrigin::Floor);
193 // VRProxyComponent->AddLocalOffset(FVector(0.0f, 0.0f, DefaultPlayerHeight));
194#endif
195 }
196}
197
198void APixoVRCharacter::Tick(float DeltaTime)
199{
200 Super::Tick(DeltaTime);
201
203 {
205 }
206
208 {
210 }
211
212 if(GetLocalRole() == ROLE_Authority)
213 {
214 // Do Wrist Menu related stuff.
215 if(WristMenu)
216 {
218 {
219 FVector2D PadPosition = FVector2D::ZeroVector;
220 FVector2D Tmp;
221 if (CurrentWristMenuHand == EControllerHand::Left)
222 {
224 }
225 else
226 {
228 }
229 PadPosition = Tmp;
230 WristMenu->UpdateTrackpadPosition(PadPosition);
231 }
232 }
233 }
234}
235
236void APixoVRCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
237{
238 Super::SetupPlayerInputComponent(PlayerInputComponent);
239
240 if (InputsTable)
241 {
243 }
244 else
245 {
246 UE_LOG(LogPixoVRCharacter, Warning, TEXT("PixoVRCharacter::InputsTable not set!"));
247 }
248
249 PlayerInputComponent->BindAxis("MoveForward", this, &APixoVRCharacter::MoveForward);
250 PlayerInputComponent->BindAxis("MoveRight", this, &APixoVRCharacter::MoveRight);
251 PlayerInputComponent->BindAxis("Turn", this, &APixoVRCharacter::TurnAtRate);
252 PlayerInputComponent->BindAxis("LookUp", this, &APixoVRCharacter::LookUpAtRate);
253
254 PlayerInputComponent->BindAction("TeleportLeft", IE_Pressed, this, &APixoVRCharacter::HandleTeleportLeftPressed);
255 PlayerInputComponent->BindAction("TeleportLeft", IE_Released, this, &APixoVRCharacter::HandleTeleportLeftReleased);
256 PlayerInputComponent->BindAction("TeleportRight", IE_Pressed, this, &APixoVRCharacter::HandleTeleportRightPressed);
257 PlayerInputComponent->BindAction("TeleportRight", IE_Released, this, &APixoVRCharacter::HandleTeleportRightReleased);
258
259 PlayerInputComponent->BindAxis("TeleportLeftByAxis", this, &APixoVRCharacter::HandleTeleportLeftByAxis);
260 PlayerInputComponent->BindAxis("TeleportRightByAxis", this, &APixoVRCharacter::HandleTeleportRightByAxis);
261
262 PlayerInputComponent->BindAxis("MotionControllerThumbLeft_Y", this, &APixoVRCharacter::HandleTeleportLeftUp);
263 PlayerInputComponent->BindAxis("MotionControllerThumbLeft_X", this, &APixoVRCharacter::HandleTeleportLeftRight);
264 PlayerInputComponent->BindAxis("MotionControllerThumbRight_Y", this, &APixoVRCharacter::HandleTeleportRightUp);
265 PlayerInputComponent->BindAxis("MotionControllerThumbRight_X", this, &APixoVRCharacter::HandleTeleportRightRight);
266
267 PlayerInputComponent->BindAction("LaserBeamLeft", IE_Pressed, this, &APixoVRCharacter::HandleLaserBeamLeftPressed);
268 PlayerInputComponent->BindAction("LaserBeamRight", IE_Pressed, this, &APixoVRCharacter::HandleLaserBeamRightPressed);
269
270 PlayerInputComponent->BindAction("LaserSelectUILeft", IE_Pressed, this, &APixoVRCharacter::HandleLaserSelectLeft);
271 PlayerInputComponent->BindAction("LaserSelectUILeft", IE_Released, this, &APixoVRCharacter::HandleLaserReleaseLeft);
272 PlayerInputComponent->BindAction("LaserSelectUIRight", IE_Pressed, this, &APixoVRCharacter::HandleLaserSelectRight);
273 PlayerInputComponent->BindAction("LaserSelectUIRight", IE_Released, this, &APixoVRCharacter::HandleLaserReleaseRight);
274
275 PlayerInputComponent->BindAction("PCToggleWristMenu", IE_Pressed, this, &APixoVRCharacter::HandleActivateWristMenuPressedLeft);
276 PlayerInputComponent->BindAction("ActivateWristMenu", IE_Pressed, this, &APixoVRCharacter::HandleActivateWristMenuPressed);
277 PlayerInputComponent->BindAction("SelectWristMenuItemLeft", IE_Pressed, this, &APixoVRCharacter::HandleSelectWristMenuItemPressedLeft);
278 PlayerInputComponent->BindAction("SelectWristMenuItemRight", IE_Pressed, this, &APixoVRCharacter::HandleSelectWristMenuItemPressedRight);
279 PlayerInputComponent->BindAction("DoubleTapWristMenu", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuDoubleTap);
280
281 PlayerInputComponent->BindAction("SelectWristMenuItem1", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem1Pressed);
282 PlayerInputComponent->BindAction("SelectWristMenuItem2", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem2Pressed);
283 PlayerInputComponent->BindAction("SelectWristMenuItem3", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem3Pressed);
284 PlayerInputComponent->BindAction("SelectWristMenuItem4", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem4Pressed);
285 PlayerInputComponent->BindAction("SelectWristMenuItem5", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem5Pressed);
286 PlayerInputComponent->BindAction("SelectWristMenuItem6", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem6Pressed);
287 PlayerInputComponent->BindAction("SelectWristMenuItem7", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem7Pressed);
288 PlayerInputComponent->BindAction("SelectWristMenuItem8", IE_Pressed, this, &APixoVRCharacter::HandleWristMenuItem8Pressed);
289
290 PlayerInputComponent->BindAction("GrabLeft", IE_Pressed, this, &APixoVRCharacter::GrabLeftPressed);
291 PlayerInputComponent->BindAction("GrabLeft", IE_Released, this, &APixoVRCharacter::GrabLeftReleased);
292 PlayerInputComponent->BindAction("GrabRight", IE_Pressed, this, &APixoVRCharacter::GrabRightPressed);
293 PlayerInputComponent->BindAction("GrabRight", IE_Released, this, &APixoVRCharacter::GrabRightReleased);
294
295 PlayerInputComponent->BindAction("HintActivated", IE_Pressed, this, &APixoVRCharacter::ActivateHint);
296
297 PlayerInputComponent->BindAction("TurnVRLeft", IE_Pressed, this, &APixoVRCharacter::TurnVRLeft);
298 PlayerInputComponent->BindAction("TurnVRRight", IE_Pressed, this, &APixoVRCharacter::TurnVRRight);
299 PlayerInputComponent->BindAxis("TurnVRByAxis", this, &APixoVRCharacter::TurnVRByAxis);
300}
301
302void APixoVRCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
303{
304 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
305
306 DOREPLIFETIME(APixoVRCharacter, bIsOverWidgetUse);
309 DOREPLIFETIME(APixoVRCharacter, bActivateLeftLaser);
311 DOREPLIFETIME(APixoVRCharacter, WristMenu);
312 DOREPLIFETIME(APixoVRCharacter, bTeleporterEnabled);
316 DOREPLIFETIME(APixoVRCharacter, ProgressBar);
317}
318
319void APixoVRCharacter::PossessedBy(AController* NewController)
320{
321 Super::PossessedBy(NewController);
322
323 // Spawn hands
324 const FAttachmentTransformRules HandTransformRule = FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false);
325 FActorSpawnParameters ActorSpawnParameters = {};
326 ActorSpawnParameters.Owner = this;
327 ActorSpawnParameters.Instigator = this;
328
329 VRHandLeft = GetWorld()->SpawnActor<APixoVRHand>(VRHandClass, ActorSpawnParameters);
330 VRHandLeft->InitPixoVRHands(EControllerHand::Left, this);
331 VRHandLeft->AttachToComponent(VRProxyComponent, HandTransformRule);
332 VRHandLeft->MotionController->AddTickPrerequisiteComponent(GetCharacterMovement());
333 VRHandLeft->MotionController->OverrideSendTransform = &AVRBaseCharacter::Server_SendTransformLeftController;
334
335 VRHandRight = GetWorld()->SpawnActor<APixoVRHand>(VRHandClass, ActorSpawnParameters);
336 VRHandRight->InitPixoVRHands(EControllerHand::Right, this);
337 VRHandRight->AttachToComponent(VRProxyComponent, HandTransformRule);
338 VRHandRight->MotionController->AddTickPrerequisiteComponent(GetCharacterMovement());
339 VRHandRight->MotionController->OverrideSendTransform = &AVRBaseCharacter::Server_SendTransformRightController;
340
341 // We will spawn the tools on the server when the character gets possessed by a new controller.
342 SpawnTeleporter(EControllerHand::Left, true);
343 SpawnTeleporter(EControllerHand::Right, true);
344
345 SpawnLaserBeam(EControllerHand::Left, bLeftLaserBeamIsActiveOnStart);
346 SpawnLaserBeam(EControllerHand::Right, bRightLaserBeamIsActiveOnStart);
347
350}
351
353{
354 if(!CanTeleport())
355 {
356 return;
357 }
358
359 ActivateTeleporter(EControllerHand::Left, true);
360}
361
363{
365 {
366 return;
367 }
368
369 ExecuteTeleportation(EControllerHand::Left);
370}
371
373{
374 if(!CanTeleport())
375 {
376 return;
377 }
378
379 ActivateTeleporter(EControllerHand::Right, true);
380}
381
383{
385 {
386 return;
387 }
388
389 ExecuteTeleportation(EControllerHand::Right);
390}
391
393{
394 static bool IsLeftTeleportActivatedByFunc = false;
395
396 if (CurrentAxisValue > 0.f && !TeleportControllerLeft->IsActivated())
397 {
398 if(!CanTeleport())
399 {
400 return;
401 }
402
403 IsLeftTeleportActivatedByFunc = true;
404 ActivateTeleporter(EControllerHand::Left, true);
405 }
406 else if (CurrentAxisValue <= 0.f && IsLeftTeleportActivatedByFunc)
407 {
408 IsLeftTeleportActivatedByFunc = false;
409
411 {
412 return;
413 }
414
415 ExecuteTeleportation(EControllerHand::Left);
416 }
417}
418
420{
421 static bool IsRightTeleportActivatedByFunc = false;
422
423 if (CurrentAxisValue > 0.f && !TeleportControllerRight->IsActivated())
424 {
425 if(!CanTeleport())
426 {
427 return;
428 }
429
430 IsRightTeleportActivatedByFunc = true;
431 ActivateTeleporter(EControllerHand::Right, true);
432 }
433 else if (CurrentAxisValue <= 0.f && IsRightTeleportActivatedByFunc)
434 {
435 IsRightTeleportActivatedByFunc = false;
436
438 {
439 return;
440 }
441
442 ExecuteTeleportation(EControllerHand::Right);
443 }
444}
445
447{
448 return !((WristMenu && WristMenu->IsActivated()) || bTeleporterEnabled == false);
449}
450
452{
453 ATeleporterBase* TeleportController = nullptr;
454
455 switch(Hand)
456 {
457 case EControllerHand::Left: TeleportController = TeleportControllerLeft; break;
458 case EControllerHand::Right: TeleportController = TeleportControllerRight; break;
459 }
460
461 // Either no TeleportController class was specified, means the user didn't want to use
462 // a Teleporter at all, or we received a wrong Hand enum which should not happen.
463 if(!TeleportController) return;
464
465 // Execute the teleportation.
466 TeleportController->ExecuteTeleportation(VRMovementReference, GetActorTransform(), GetVRLocation(), GetActorRotation());
467 // Disable the Teleporter.
468 ActivateTeleporter(Hand, false);
469}
470
471void APixoVRCharacter::ActivateTeleporter(EControllerHand Hand, bool InActivate)
472{
473 OnTeleportationActivated().Broadcast(Hand, InActivate);
474
475 switch(Hand)
476 {
477 case EControllerHand::Left:
478 {
480 {
482 }
483 }
484 break;
485 case EControllerHand::Right:
486 {
488 {
490 }
491 }
492 break;
493 default:
494 break;
495 }
496
497 NotifyActivateTeleporter(Hand, InActivate);
498}
499
500void APixoVRCharacter::SpawnTeleporter(EControllerHand Hand, bool InActivate)
501{
502 const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, EAttachmentRule::KeepWorld, false);
503 FActorSpawnParameters ActorSpawnParameters = {};
504 ActorSpawnParameters.Owner = this;
505 ActorSpawnParameters.Instigator = this;
506
507 switch (Hand)
508 {
509 case EControllerHand::Left:
510 {
512 {
513 TeleportControllerLeft = GetWorld()->SpawnActor<ATeleporterBase>(TeleportControllerClass, ActorSpawnParameters);
514 TeleportControllerLeft->SetMotionController(LeftMotionController);
515
517 {
518 if (VRHandLeft->HandMesh)
519 {
520 TeleportControllerLeft->AttachToComponent(VRHandLeft->HandMesh, AttachmentTransformRules, LeftTeleporterSocket);
521 }
522 }
523 }
524 }
525 break;
526 case EControllerHand::Right:
527 {
529 {
530 TeleportControllerRight = GetWorld()->SpawnActor<ATeleporterBase>(TeleportControllerClass, ActorSpawnParameters);
531 TeleportControllerRight->SetMotionController(RightMotionController);
532
534 {
535 if (VRHandLeft->HandMesh)
536 {
537 TeleportControllerRight->AttachToComponent(VRHandRight->HandMesh, AttachmentTransformRules, RightTeleporterSocket);
538 }
539 }
540 }
541 }
542 break;
543 default: break;
544 }
545}
546
547void APixoVRCharacter::SpawnNewTeleporterClass(TSubclassOf<ATeleporterBase> TeleporterClass)
548{
549 TeleportControllerClass = TeleporterClass;
550
551 TeleportControllerLeft->Destroy();
552 TeleportControllerRight->Destroy();
553
554 SpawnTeleporter(EControllerHand::Left, true);
555 SpawnTeleporter(EControllerHand::Right, true);
556}
557
558void APixoVRCharacter::MulticastActivateTeleporter_Implementation(EControllerHand Hand, bool InActivate)
559{
560 if(!IsLocallyControlled())
561 {
562 OnTeleportationActivated().Broadcast(Hand, InActivate);
563 switch (Hand)
564 {
565 case EControllerHand::Left:
566 {
568 {
570 }
571 }
572 break;
573 case EControllerHand::Right:
574 {
576 {
578 }
579 }
580 break;
581 default:
582 break;
583 }
584 }
585}
586
587void APixoVRCharacter::NotifyActivateTeleporter_Implementation(EControllerHand Hand, bool InActivate)
588{
589 MulticastActivateTeleporter(Hand, InActivate);
590}
591
592bool APixoVRCharacter::NotifyActivateTeleporter_Validate(EControllerHand Hand, bool InActivate)
593{
594 return true;
595}
596
598{
599 // Are we going to use the Laser-beam at all?
601 {
602 // No, just don't do anything.
603 return;
604 }
605
607 {
608 return;
609 }
610
612 {
613 bLaserBeamActive = true;
614 ActivateLaserBeam(EControllerHand::Right, false);
615
616 if (VRHandRight->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
617 {
618 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandRight->HandMesh->GetAnimInstance(), EPixoVRGripState::Open);
619 }
620 }
621 else
622 {
624 }
625
626 ActivateLaserBeam(EControllerHand::Left, bLaserBeamActive);
627
628 if (VRHandLeft->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
629 {
631 {
632 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandLeft->HandMesh->GetAnimInstance(), EPixoVRGripState::HoldLaserPointer);
633 }
634 else
635 {
636 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandLeft->HandMesh->GetAnimInstance(), EPixoVRGripState::Open);
637 }
638 }
639}
640
642{
643 // Are we going to use the Laser-beam at all?
645 {
646 // No, just don't do anything.
647 return;
648 }
649
651 {
652 return;
653 }
654
656 {
657 bLaserBeamActive = true;
658 ActivateLaserBeam(EControllerHand::Left, false);
659
660 if (VRHandLeft->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
661 {
662 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandLeft->HandMesh->GetAnimInstance(),
664 }
665 }
666 else
667 {
669 }
670
671 ActivateLaserBeam(EControllerHand::Right, bLaserBeamActive);
672
673 if (VRHandRight->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
674 {
676 {
677 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandRight->HandMesh->GetAnimInstance(), EPixoVRGripState::HoldLaserPointer);
678 }
679 else
680 {
681 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandRight->HandMesh->GetAnimInstance(), EPixoVRGripState::Open);
682 }
683 }
684}
685
686void APixoVRCharacter::IsLaserActivated(bool& IsActivated, EControllerHand& Hand)
687{
688 IsActivated = bLaserBeamActive;
689 Hand = bActivateLeftLaser ? EControllerHand::Left : EControllerHand::Right;
690}
691
692void APixoVRCharacter::IsOverWidgetUse_Implementation(EControllerHand Hand, bool InPressed)
693{
694 PerformIsOverWidgetUse(Hand, InPressed);
695}
696
697void APixoVRCharacter::PerformIsOverWidgetUse_Implementation(EControllerHand Hand, bool InPressed)
698{
699 bIsOverWidgetUse = false;
700
701 switch(Hand)
702 {
703 case EControllerHand::Left:
704 {
706 {
708 }
709 }
710 break;
711 case EControllerHand::Right:
712 {
714 {
716 }
717 }
718 break;
719 default: break;
720 }
721}
722
723bool APixoVRCharacter::IsOverWidgetUse_Validate(EControllerHand Hand, bool InPressed)
724{
725 return true;
726}
727
728void APixoVRCharacter::SpawnLaserBeam(EControllerHand Hand, bool InActivate)
729{
730 const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, true);
731 FActorSpawnParameters ActorSpawnParameters = {};
732 ActorSpawnParameters.Owner = this;
733 ActorSpawnParameters.Instigator = this;
734
735 switch(Hand)
736 {
737 case EControllerHand::Left:
738 {
740 {
741 LaserControllerLeft = GetWorld()->SpawnActor<APixoVRLaser>(LaserControllerClass, ActorSpawnParameters);
742 LaserControllerLeft->SetHandType(EControllerHand::Left, IsLocallyControlled());
743 LaserControllerLeft->AttachToComponent(VRHandLeft->HandMesh, AttachmentTransformRules, LeftLaserBeamSocket);
744 LaserControllerLeft->WidgetInteraction->PointerIndex = 0;
745
746 if(InActivate)
747 {
749 }
750 }
751 }
752 break;
753 case EControllerHand::Right:
754 {
756 {
757 LaserControllerRight = GetWorld()->SpawnActor<APixoVRLaser>(LaserControllerClass, ActorSpawnParameters);
758 LaserControllerRight->SetHandType(EControllerHand::Right, IsLocallyControlled());
759 LaserControllerRight->AttachToComponent(VRHandRight->HandMesh, AttachmentTransformRules, RightLaserBeamSocket);
760 LaserControllerRight->WidgetInteraction->PointerIndex = 1;
761
762 if(InActivate)
763 {
765 }
766 }
767 }
768 break;
769 default: break;
770 }
771}
772
774{
776 {
777 IsOverWidgetUse(EControllerHand::Left, true);
778
779 HandleLaserSelectEvent(EControllerHand::Left, true);
780 }
781}
782
784{
786 {
787 IsOverWidgetUse(EControllerHand::Left, false);
788
789 HandleLaserSelectEvent(EControllerHand::Left, false);
790 }
791}
792
794{
796 {
797 IsOverWidgetUse(EControllerHand::Right, true);
798
799 HandleLaserSelectEvent(EControllerHand::Right, true);
800 }
801}
802
804{
806 {
807 IsOverWidgetUse(EControllerHand::Right, false);
808
809 HandleLaserSelectEvent(EControllerHand::Right, false);
810 }
811}
812
813void APixoVRCharacter::HandleLaserSelectEvent_Implementation(EControllerHand Hand, bool Pressed)
814{
815 MultiHandleLaserSelectEvent(Hand, Pressed);
816}
817
818void APixoVRCharacter::MultiHandleLaserSelectEvent_Implementation(EControllerHand Hand, bool Pressed)
819{
820 HandleLaserSelect(Hand, Pressed);
821}
822
823void APixoVRCharacter::HandleLaserSelect(EControllerHand Hand, bool Pressed)
824{
825 switch (Hand)
826 {
827 case EControllerHand::Left:
828 {
830 }
831 break;
832 case EControllerHand::Right:
833 {
835 }
836 break;
837 default:
838 break;
839 }
840}
841
842void APixoVRCharacter::ActivateLaserBeam_Implementation(EControllerHand Hand, bool InActivate)
843{
844 switch (Hand)
845 {
846 case EControllerHand::Left:
847 {
848 VRHandLeft->ToggleLaser(InActivate);
849
850 bActivateLeftLaser = InActivate;
852 }
853 break;
854 case EControllerHand::Right:
855 {
856 VRHandRight->ToggleLaser(InActivate);
857
858 bActivateRightLaser = InActivate;
860 }
861 break;
862 default:
863 break;
864 }
865
867}
868
869bool APixoVRCharacter::ActivateLaserBeam_Validate(EControllerHand Hand, bool InActivate)
870{
871 return true;
872}
873
874void APixoVRCharacter::ActivateFPSMode_Implementation(bool Enable)
875{
876 bFPSMode = Enable;
877
878 if(bFPSMode)
879 {
880 VRHandLeft->AttachToComponent(VRReplicatedCamera, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false));
881 VRHandLeft->SetActorRelativeLocation(FVector(62.0f, -28.0f, -15.0f));
882
883 VRHandRight->AttachToComponent(VRReplicatedCamera, FAttachmentTransformRules(EAttachmentRule::SnapToTarget, false));
884 VRHandRight->SetActorRelativeLocation(FVector(62.0f, 31.0f, -15.0f));
885
886 bUseControllerRotationPitch = false;
887
888 const auto MovementComponent = Cast<UVRCharacterMovementComponent>(GetMovementComponent());
889 MovementComponent->bUseClientControlRotation = true;
890 MovementComponent->bAllowMovementMerging = true;
891
892 VRReplicatedCamera->bUsePawnControlRotation = true;
893 VRReplicatedCamera->bLockToHmd = false;
894 VRReplicatedCamera->bAutoSetLockToHmd = false;
895 }
896}
897
898void APixoVRCharacter::TurnVRByAxis(float CurrentAxisValue)
899{
900 static float PreviousAxisValue = 0.f;
901
902 if (CurrentAxisValue != 0.f)
903 {
904 if (CurrentAxisValue > 0.f && PreviousAxisValue <= 0.f)
905 TurnVRRight();
906 else if (CurrentAxisValue < 0.f && PreviousAxisValue >= 0.f)
907 TurnVRLeft();
908 }
909
910 PreviousAxisValue = CurrentAxisValue;
911}
912
914{
916 {
917 return;
918 }
919
920 AddActorWorldRotationVR(FRotator(0.0f, -DeflectionAngle, 0.0f));
922}
923
925{
927 {
928 return;
929 }
930
931 AddActorWorldRotationVR(FRotator(0.0f, DeflectionAngle, 0.0f));
933}
934
936{
937 AddMovementInput(GetVRForwardVector(), Value);
938}
939
941{
942 AddMovementInput(GetVRRightVector(), Value);
943}
944
946{
947 AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
948}
949
951{
952 AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
953}
954
956{
957 OnHandGrabAction.Broadcast(true, true);
958
960 IPixoVRStoryObject::Execute_CouldBeGrabbedWithTwoHands(VRHandLeft->HandHoldingObject))
961 {
962 if (IPixoVRStoryObject::Execute_IsObjectHeldWithTwoHands(VRHandLeft->HandHoldingObject))
963 IPixoVRStoryObject::Execute_ReleaseTwoHands(VRHandLeft->HandHoldingObject, VRHandRight->MotionController);
964 else
965 IPixoVRStoryObject::Execute_GrabWithTwoHands(VRHandLeft->HandHoldingObject, VRHandRight->MotionController);
966 return;
967 }
968
969 if (HoldToolRight)
970 {
972 IPixoVRStoryObject::Execute_ReleaseItemByPress(VRHandRight->HandHoldingObject))
973 {
975 }
976
977 return;
978 }
979
981
983 {
984 bLaserBeamActive = false;
985 ActivateLaserBeam(EControllerHand::Right, false);
986 }
988 {
989 return;
990 }
991
992 if (VRHandRight->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
993 {
995
996 if (VRHandRight->HandHoldingObject != nullptr)
997 {
998 if (VRHandRight->HandHoldingObject->GetClass()->ImplementsInterface(UGripResponseAnimationInterface::StaticClass()))
999 {
1000 if (IGripResponseAnimationInterface::Execute_IsUsingCustomGripAnimation(VRHandRight->HandHoldingObject))
1001 {
1002 GripAnimation = IGripResponseAnimationInterface::Execute_GetObjectGripAnimation(VRHandRight->HandHoldingObject);
1003 }
1004 else
1005 {
1006 GripAnimation = EPixoVRGripState::AdvanceGrab;
1007 }
1008 }
1009 else
1010 {
1011 GripAnimation = EPixoVRGripState::AdvanceGrab;
1012 }
1013 }
1014 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandRight->HandMesh->GetAnimInstance(), GripAnimation);
1015 }
1016}
1017
1019{
1020 OnHandGrabAction.Broadcast(true, false);
1021
1023 IPixoVRStoryObject::Execute_CouldBeGrabbedWithTwoHands(VRHandRight->HandHoldingObject))
1024 {
1025 if (IPixoVRStoryObject::Execute_IsObjectHeldWithTwoHands(VRHandRight->HandHoldingObject))
1026 IPixoVRStoryObject::Execute_ReleaseTwoHands(VRHandRight->HandHoldingObject, VRHandLeft->MotionController);
1027 else
1028 IPixoVRStoryObject::Execute_GrabWithTwoHands(VRHandRight->HandHoldingObject, VRHandLeft->MotionController);
1029 return;
1030 }
1031
1032 if (HoldToolLeft)
1033 {
1035 && IPixoVRStoryObject::Execute_ReleaseItemByPress(VRHandLeft->HandHoldingObject))
1036 {
1038 }
1039
1040 return;
1041 }
1042
1044
1046 {
1047 bLaserBeamActive = false;
1048 ActivateLaserBeam(EControllerHand::Left, false);
1049 }
1051 {
1052 return;
1053 }
1054
1055 if (VRHandLeft->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
1056 {
1058
1059 if (VRHandLeft->HandHoldingObject != nullptr)
1060 {
1061 if (VRHandLeft->HandHoldingObject->GetClass()->ImplementsInterface(UGripResponseAnimationInterface::StaticClass()))
1062 {
1063 if (IGripResponseAnimationInterface::Execute_IsUsingCustomGripAnimation(VRHandLeft->HandHoldingObject))
1064 {
1065 GripAnimation = IGripResponseAnimationInterface::Execute_GetObjectGripAnimation(VRHandLeft->HandHoldingObject);
1066 }
1067 else
1068 {
1069 GripAnimation = EPixoVRGripState::AdvanceGrab;
1070 }
1071 }
1072 else
1073 {
1074 GripAnimation = EPixoVRGripState::AdvanceGrab;
1075 }
1076 }
1077 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandLeft->HandMesh->GetAnimInstance(), GripAnimation);
1078 }
1079}
1080
1082{
1084 {
1085 if (VRHandRight->HandHoldingObject->Implements<UPixoVRStoryObject>() &&
1086 IPixoVRStoryObject::Execute_DenyDropping(VRHandRight->HandHoldingObject))
1087 {
1088 return;
1089 }
1090 if (VRHandRight->HandHoldingObject->Implements<UPixoVRStoryObject>() &&
1091 IPixoVRStoryObject::Execute_HoldItemByClick(VRHandRight->HandHoldingObject) &&
1093 {
1094 HoldToolRight = true;
1095 return;
1096 }
1097 }
1098
1100 {
1101 return;
1102 }
1103
1104 if (HoldToolRight)
1105 {
1106 HoldToolRight = false;
1107 }
1108
1110
1111 if (VRHandRight->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(
1112 UHandAnimationInterface::StaticClass()))
1113 {
1114 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandRight->HandMesh->GetAnimInstance(),
1116 }
1117}
1118
1120{
1122 {
1124 && IPixoVRStoryObject::Execute_DenyDropping(VRHandLeft->HandHoldingObject))
1125 {
1126 return;
1127 }
1129 && IPixoVRStoryObject::Execute_HoldItemByClick(VRHandLeft->HandHoldingObject) && !HoldToolLeft)
1130 {
1131 HoldToolLeft = true;
1132 return;
1133 }
1134 }
1135
1137 {
1138 return;
1139 }
1140
1141 if (HoldToolLeft)
1142 {
1143 HoldToolLeft = false;
1144 }
1145
1147
1148 if(VRHandLeft->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
1149 {
1150 IHandAnimationInterface::Execute_SetAnimationGripState(VRHandLeft->HandMesh->GetAnimInstance(),EPixoVRGripState::Open);
1151 }
1152}
1153
1155{
1156 OnHandGrabAction.Broadcast(false, true);
1157
1159 && IPixoVRStoryObject::Execute_ReleaseItemByPress(VRHandRight->HandHoldingObject))
1160 {
1161 if (!HoldToolRight)
1162 {
1163 HoldToolRight = true;
1164 }
1165 }
1166 else
1167 {
1169 }
1170}
1171
1173{
1174 OnHandGrabAction.Broadcast(false, false);
1175
1177 && IPixoVRStoryObject::Execute_ReleaseItemByPress(VRHandLeft->HandHoldingObject))
1178 {
1179 if (!HoldToolLeft)
1180 {
1181 HoldToolLeft = true;
1182 }
1183 }
1184 else
1185 {
1187 }
1188
1189}
1190
1191AActor* APixoVRCharacter::SpawnActorInHand(TSubclassOf<AActor> ActorClass, bool RightHand)
1192{
1193 APixoVRHand* HandRef = RightHand ? VRHandRight : VRHandLeft;
1194 if (HandRef->HandHoldingObject)
1195 {
1196 UE_LOG(LogTemp, Error, TEXT("APixoVRCharacter - Can't spawn object in the hand"));
1197 return nullptr;
1198 }
1199
1200 AActor* SpawnedActor = GetWorld()->SpawnActor(ActorClass);
1201 APixoVRLaser* LaserRef = RightHand ? LaserControllerRight : LaserControllerLeft;
1202 EControllerHand ActiveHand = RightHand ? EControllerHand::Right : EControllerHand::Left;
1203
1204 HandRef->ManuallyPutActorToHand(SpawnedActor);
1205
1206 if(LaserRef->bIsLaserBeamActive)
1207 {
1208 bLaserBeamActive = false;
1209 ActivateLaserBeam(ActiveHand, false);
1210 }
1211
1212 if (SpawnedActor->Implements<UPixoVRStoryObject>() && IPixoVRStoryObject::Execute_HoldItemByClick(SpawnedActor) && !(RightHand ? HoldToolRight : HoldToolRight))
1213 {
1214 if (RightHand)
1215 HoldToolRight = true;
1216 else
1217 HoldToolLeft = true;
1218 }
1219
1220 auto ChangeAnimation = [=]()
1221 {
1222 if (HandRef->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
1223 {
1225
1226 if (SpawnedActor != nullptr)
1227 {
1228 if (SpawnedActor->GetClass()->ImplementsInterface(UGripResponseAnimationInterface::StaticClass()))
1229 {
1230 if (IGripResponseAnimationInterface::Execute_IsUsingCustomGripAnimation(SpawnedActor))
1231 {
1232 GripAnimation = IGripResponseAnimationInterface::Execute_GetObjectGripAnimation(SpawnedActor);
1233 }
1234 else
1235 {
1236 GripAnimation = EPixoVRGripState::AdvanceGrab;
1237 }
1238 }
1239 else
1240 {
1241 GripAnimation = EPixoVRGripState::AdvanceGrab;
1242 }
1243 }
1244 IHandAnimationInterface::Execute_SetAnimationGripState(HandRef->HandMesh->GetAnimInstance(), GripAnimation);
1245 }
1246 };
1247 FTimerDelegate TimerDelegate;
1248 TimerDelegate.BindLambda(ChangeAnimation);
1249 GetWorldTimerManager().SetTimerForNextTick(TimerDelegate);
1250 return SpawnedActor;
1251}
1252
1254{
1256 {
1258 }
1260 {
1262 }
1263}
1264
1266{
1267 APixoVRHand* HandToReset = RightHand ? VRHandRight : VRHandLeft;
1268 RightHand ? HoldToolRight = false : HoldToolLeft = false;
1269
1270 if (HandToReset->HandHoldingObject)
1271 HandToReset->ReleaseObject();
1272
1273 if(HandToReset->HandMesh->GetAnimInstance()->GetClass()->ImplementsInterface(UHandAnimationInterface::StaticClass()))
1274 IHandAnimationInterface::Execute_SetAnimationGripState(HandToReset->HandMesh->GetAnimInstance(),EPixoVRGripState::Open);
1275}
1276
1277void APixoVRCharacter::ShowTool(EControllerHand Hand, AActor* Tool)
1278{
1279 const FAttachmentTransformRules AttachmentTransformRules(EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, true);
1280
1281 switch(Hand)
1282 {
1283 case EControllerHand::Left:
1284 Tool->SetActorLocation(VRHandLeft->HandMesh->GetSocketLocation(ToolSocket));
1286 break;
1287 case EControllerHand::Right:
1288 Tool->SetActorLocation(VRHandRight->HandMesh->GetSocketLocation(ToolSocket));
1290 break;
1291 }
1292}
1293
1295{
1296 if (HintManager)
1297 {
1298 HintManager->HintActivated(false);
1299 }
1300 else
1301 UE_LOG(LogTemp, Error, TEXT("HintManager isn't initialized"));
1302}
1303
1305{
1306 if (HintManager)
1307 {
1309 }
1310 else
1311 UE_LOG(LogTemp, Error, TEXT("HintManager isn't initialized"));
1312}
1313
1315{
1317 {
1318 LaserControllerRight->Destroy();
1319 }
1320
1322 {
1323 LaserControllerLeft->Destroy();
1324 }
1325
1326 if (WristMenu)
1327 {
1328 WristMenu->Destroy();
1329 }
1330
1332 {
1334 }
1335
1337 {
1339 }
1340}
1341
1342void APixoVRCharacter::HandleTeleportRightRight_Implementation(float Value)
1343{
1345}
1346
1347bool APixoVRCharacter::HandleTeleportRightRight_Validate(float Value)
1348{
1349 return true;
1350}
1351
1352void APixoVRCharacter::HandleTeleportRightUp_Implementation(float Value)
1353{
1355}
1356
1357bool APixoVRCharacter::HandleTeleportRightUp_Validate(float Value)
1358{
1359 return true;
1360}
1361
1362void APixoVRCharacter::HandleTeleportLeftRight_Implementation(float Value)
1363{
1365}
1366
1367bool APixoVRCharacter::HandleTeleportLeftRight_Validate(float Value)
1368{
1369 return true;
1370}
1371
1372void APixoVRCharacter::HandleTeleportLeftUp_Implementation(float Value)
1373{
1375}
1376
1377bool APixoVRCharacter::HandleTeleportLeftUp_Validate(float Value)
1378{
1379 return true;
1380}
1381
1383{
1384 ActivateWristMenu(EControllerHand::Left);
1385}
1386
1388{
1389 ActivateWristMenu(EControllerHand::Right);
1390}
1391
1393{
1394 if (LastPressedKey == InputKey)
1395 {
1397 }
1398 else
1399 {
1400 LastPressedKey = InputKey;
1401 }
1402}
1403
1404void APixoVRCharacter::SpawnProgressBar_Implementation()
1405{
1406 const FAttachmentTransformRules ProgressBarAttachmentTransformRules(EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, true);
1407 FActorSpawnParameters ActorSpawnParameters = {};
1408
1409 ActorSpawnParameters.Owner = this;
1410 ActorSpawnParameters.Instigator = this;
1411
1412 if (ProgressBar)
1413 {
1414 ProgressBar = GetWorld()->SpawnActor<APixoVRCircleProgress>(ProgressBarClass, ActorSpawnParameters);
1415 ProgressBar->AttachToComponent(VRHandLeft->HandMesh, ProgressBarAttachmentTransformRules, WristMenuSocket);
1416 }
1417}
1418
1419bool APixoVRCharacter::SpawnProgressBar_Validate()
1420{
1421 return true;
1422}
1423
1424void APixoVRCharacter::SpawnWristMenu_Implementation()
1425{
1426 if(WristMenuClass)
1427 {
1428 const FAttachmentTransformRules WristMenuAttachmentTransformRules(EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, true);
1429
1430 FActorSpawnParameters ActorSpawnParameters = {};
1431 ActorSpawnParameters.Owner = this;
1432 ActorSpawnParameters.Instigator = this;
1433
1434 WristMenu = GetWorld()->SpawnActor<APixoVRWristMenu>(WristMenuClass, ActorSpawnParameters);
1435 WristMenu->AttachToComponent(VRHandLeft->HandMesh, WristMenuAttachmentTransformRules, WristMenuSocket);
1436 }
1437}
1438
1439bool APixoVRCharacter::SpawnWristMenu_Validate()
1440{
1441 return true;
1442}
1443
1444void APixoVRCharacter::ActivateProgressBar_Implementation(EControllerHand Hand, bool InActivate)
1445{
1446 const auto CurrentHand = Hand == EControllerHand::Left ? VRHandLeft->HandMesh : VRHandRight->HandMesh;
1447
1448 const FAttachmentTransformRules ProgressBarAttachment(EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, EAttachmentRule::KeepRelative, true);
1449
1450 if (ProgressBar)
1451 {
1452 ProgressBar->AttachToComponent(CurrentHand, ProgressBarAttachment, WristMenuSocket);
1453 ProgressBar->SetActorScale3D(Hand == EControllerHand::Left ? FVector(1) : MirroredWristMenuScale);
1455 }
1456}
1457
1458bool APixoVRCharacter::ActivateProgressBar_Validate(EControllerHand Hand, bool InActivate)
1459{
1460 return true;
1461}
1462
1463void APixoVRCharacter::ActivateWristMenu_Implementation(EControllerHand Hand)
1464{
1465 if (!WristMenu)
1466 {
1467 return;
1468 }
1469
1470 ActivateProgressBar(Hand, false);
1471 LastPressedKey = "None";
1472
1473 const auto CurrentHand = Hand == EControllerHand::Left ? VRHandLeft->HandMesh : VRHandRight->HandMesh;
1474
1475 const FAttachmentTransformRules WristMenuAttachmentTransformRules(EAttachmentRule::KeepRelative,
1476 EAttachmentRule::KeepRelative,
1477 EAttachmentRule::KeepRelative, true);
1478
1479 const auto PlatformName = UGameplayStatics::GetPlatformName();
1480
1481 if (PlatformName == "Windows" || PlatformName == "Mac" || PlatformName == "Linux")
1482 {
1483 WristMenu->AttachToComponent(WristMenuLoc, WristMenuAttachmentTransformRules);
1485 }
1486 else
1487 {
1488 WristMenu->AttachToComponent(CurrentHand, WristMenuAttachmentTransformRules, WristMenuSocket);
1489 }
1490
1491 // Mirror wrist if it is for right hand, as left hand was default before.
1492 if (Hand == EControllerHand::Left)
1493 {
1494 WristMenu->SetActorScale3D(FVector(1));
1495 }
1496 else
1497 {
1498 WristMenu->SetActorScale3D(MirroredWristMenuScale);
1499 }
1500
1501 if (WristMenu->IsActivated())
1502 {
1503 if (CurrentWristMenuHand == Hand)
1504 {
1506 }
1507 }
1508 else
1509 {
1511 }
1512
1513 CurrentWristMenuHand = Hand;
1514
1515 OnWristMenuActivated.Broadcast(Hand);
1516}
1517
1518bool APixoVRCharacter::ActivateWristMenu_Validate(EControllerHand Hand)
1519{
1520 return true;
1521}
1522
1524{
1525 ActivateWristMenu(EControllerHand::Left);
1526}
1527
1541
1542void APixoVRCharacter::SelectWristMenu(EControllerHand Hand)
1543{
1544 if(Hand == CurrentWristMenuHand)
1545 {
1547 }
1548}
1549
1551{
1552 if (EControllerHand::Left == CurrentWristMenuHand)
1553 {
1555 }
1556}
1557
1559{
1560 if (EControllerHand::Right == CurrentWristMenuHand)
1561 {
1563 }
1564}
1565
1570
1575
1580
1585
1590
1595
1600
EPixoVRGripState
Enumeration for different grip states for hand animation in PixoVR.
DEFINE_LOG_CATEGORY(LogPixoVRCharacter)
Pixo VR Character This class represents the main character in the Pixo VR game. It extends the AVRCha...
FName LeftTeleporterSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
APixoVRCircleProgress * ProgressBar
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR", meta = (AllowPrivateAccess = "true"))
bool bActivateRightLaser
UPROPERTY(BlueprintReadOnly, Replicated)
bool bIsOverWidgetUse
UPROPERTY(Replicated)
float DefaultPlayerHeight
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category = "PixoVR")
bool bActivateLeftLaser
UPROPERTY(BlueprintReadOnly, Replicated)
bool bLeftLaserBeamIsActiveOnStart
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "PixoVR")
void HandleLaserSelectEvent(EControllerHand Hand, bool Pressed)
UFUNCTION(Server, Reliable)
virtual void HandleWristMenuItem3Pressed()
virtual bool CanTeleport() const
EControllerHand CurrentWristMenuHand
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Replicated, Category= "PixoVR")
virtual void HandleWristMenuItem1Pressed()
void DeactivateHint()
UFUNCTION(BlueprintCallable, Category = "Hint")
void PlayerDestroyed(AActor *Act)
UFUNCTION()
void ActivateHint()
UFUNCTION(BlueprintCallable, Category = "Hint")
FVector2D LastTeleportLeftDirectionVector
void HandleSelectWristMenuItemPressed()
UFUNCTION(BlueprintCallable)
void ExecuteTeleportation(EControllerHand Hand)
UFUNCTION()
FOnCameraRotatedByController OnCameraRotatedByController
UPROPERTY(BlueprintAssignable, Category = "Hands")
virtual void GrabLeftPressed()
UFUNCTION(BlueprintCallable, Category = "Hands")
TSubclassOf< APixoVRCircleProgress > ProgressBarClass
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
APixoVRLaser * LaserControllerRight
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
virtual void TurnVRByAxis(float Value)
void HandleTeleportLeftRight(float Value)
UFUNCTION(Server, Unreliable, WithValidation)
void IsOverWidgetUse(EControllerHand Hand, bool InPressed)
UFUNCTION(Server, Reliable, WithValidation)
virtual void GrabRightPressed()
UFUNCTION(BlueprintCallable, Category = "Hands")
FName LeftLaserBeamSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
APixoVRHand * VRHandLeft
UPROPERTY(BlueprintReadOnly, Category = "Hands")
virtual void BeginPlay() override
void ActivateWristMenu(EControllerHand Hand)
Activate/Deactivate the Wrist Menu.
void HandleHandAnimationLaser(EControllerHand Hand)
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category ="PixoVR")
TSubclassOf< ATeleporterBase > TeleportControllerClass
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
virtual void PossessedBy(AController *NewController) override
TSubclassOf< APixoVRWristMenu > WristMenuClass
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
TSubclassOf< APixoVRLaser > LaserControllerClass
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
UDataTable * InputsTable
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite, Category="PixoVR")
void SpawnLaserBeam(EControllerHand Hand, bool InActivate)
UFUNCTION()
void HandleTeleportRightReleased()
UFUNCTION(BlueprintCallable)
void PerformIsOverWidgetUse(EControllerHand Hand, bool InPressed)
UFUNCTION(Client, Reliable)
void ResetHand(bool RightHand)
Reset hand animation to Open state and drop any object holding.
virtual void HandleWristMenuItem8Pressed()
void TurnAtRate(float Rate)
FName RightLaserBeamSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
UHintManager * HintManager
UPROPERTY(BlueprintReadOnly)
FName RightTeleporterSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
bool bTeleporterEnabled
Allows for disabling of Teleporter via BP.
virtual void TurnVRRight()
void HandleTeleportLeftPressed()
UFUNCTION(BlueprintCallable)
FVector MirroredWristMenuScale
virtual void HandleSelectWristMenuItemPressedLeft()
void HandleLaserSelect(EControllerHand Hand, bool Pressed)
UFUNCTION()
void LookUpAtRate(float Rate)
UStaticMeshComponent * Body
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "PixoVR", meta = (AllowPrivateAccess = "tru...
void ActivateTeleporter(EControllerHand Hand, bool InActivate)
Activate/Deactivate the Teleporter.
void HandleActivateWristMenuPressedRight()
UFUNCTION(BlueprintCallable)
virtual void HandleWristMenuDoubleTap(FKey InputKey)
bool bRightLaserBeamIsActiveOnStart
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "PixoVR")
void HandleTeleportLeftUp(float Value)
UFUNCTION(Server, Unreliable, WithValidation)
FVector2D LastTeleportRightDirectionVector
void MoveRight(float Value)
UPixoVRLongHoldComponent * LongHoldComponent
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "PixoVR", meta = (AllowPrivateAccess = "tru...
void IsLaserActivated(bool &IsActivated, EControllerHand &Hand)
UStaticMeshComponent * Head
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "PixoVR", meta = (AllowPrivateAccess = "tru...
void ActivateProgressBar(EControllerHand Hand, bool InActivate)
UFUNCTION(BlueprintCallable, Server, Reliable, WithValidation, Category = "PixoVR")
APixoVRHand * VRHandRight
UPROPERTY(BlueprintReadOnly, Category = "Hands")
void HandleTeleportLeftByAxis(float CurrentAxisValue)
UFUNCTION(BlueprintCallable)
void HandleActivateWristMenuPressedLeft()
UFUNCTION(BlueprintCallable)
APixoVRWristMenu * WristMenu
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR", meta = (AllowPrivateAccess = "true"))
void MultiHandleLaserSelectEvent(EControllerHand Hand, bool Pressed)
UFUNCTION(NetMulticast, Reliable)
APixoVRLaser * LaserControllerLeft
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
void SpawnTeleporter(EControllerHand Hand, bool InActivate)
UFUNCTION()
void MulticastActivateTeleporter(EControllerHand Hand, bool InActivate)
UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "PixoVR")
virtual void HandleWristMenuItem6Pressed()
virtual void SetupPlayerInputComponent(UInputComponent *PlayerInputComponent) override
void ActivateLaserBeam(EControllerHand Hand, bool InActivate)
Activate/Deactivate the Laser-beam.
FOnTeleportationActivated & OnTeleportationActivated()
USceneComponent * WristMenuLoc
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "PixoVR")
void HandleLaserBeamLeftPressed()
UFUNCTION(BlueprintCallable)
bool bLaserBeamActive
UPROPERTY(BlueprintReadWrite, Category = "PixoVR")
float DeflectionAngle
The angle by which we rotate the player.
UStaticMeshComponent * FadeSphere
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Fade")
virtual void HandleWristMenuItem5Pressed()
void HandleTeleportRightRight(float Value)
UFUNCTION(Server, Unreliable, WithValidation)
void HandleActivateWristMenuPressed()
UFUNCTION(BlueprintCallable)
bool bRotationByControllerEnabled
UPROPERTY(EditAnywhere, Replicated, BlueprintReadWrite, Category = "PixoVR")
virtual void HandleSelectWristMenuItemPressedRight()
void MoveForward(float Value)
UPixoVRInputAdapter * InputAdapter
UPROPERTY()
AActor * SpawnActorInHand(TSubclassOf< AActor > ActorClass, bool RightHand)
UFUNCTION(BlueprintCallable, Category = "Hands")
void ActivateFPSMode(bool Enable)
For Windows.
virtual void Tick(float DeltaTime) override
ATeleporterBase * TeleportControllerRight
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
ATeleporterBase * TeleportControllerLeft
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
TSubclassOf< APixoVRHand > VRHandClass
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Hands")
void SelectWristMenu(EControllerHand Hand)
UFUNCTION(BlueprintCallable)
void ShowTool(EControllerHand Hand, AActor *Tool)
UFUNCTION(BlueprintCallable)
void SpawnNewTeleporterClass(TSubclassOf< ATeleporterBase > TeleporterClass)
UFUNCTION(BlueprintCallable, Category = "PixoVR")
void HandleTeleportLeftReleased()
UFUNCTION(BlueprintCallable)
void HandleTeleportRightUp(float Value)
UFUNCTION(Server, Unreliable, WithValidation)
FName ToolSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
FName WristMenuSocket
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR")
FOnHandGrabAction OnHandGrabAction
UPROPERTY(BlueprintAssignable, Category = "Hands")
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > &OutLifetimeProps) const override
void HandleTeleportRightPressed()
UFUNCTION(BlueprintCallable)
virtual void GrabLeftReleased()
UFUNCTION(BlueprintCallable, Category = "Hands")
virtual void TurnVRLeft()
FOnWristMenuActivated OnWristMenuActivated
UPROPERTY(BlueprintAssignable)
void HandleTeleportRightByAxis(float CurrentAxisValue)
UFUNCTION(BlueprintCallable)
void NotifyActivateTeleporter(EControllerHand Hand, bool InActivate)
UFUNCTION(BlueprintCallable, Server, Reliable, WithValidation, Category = "PixoVR")
void ResetHandHoldingObject()
UFUNCTION(BlueprintCallable, Category = "Hands")
virtual void GrabRightReleased()
UFUNCTION(BlueprintCallable, Category = "Hands")
void HandleLaserBeamRightPressed()
UFUNCTION(BlueprintCallable)
virtual void HandleWristMenuItem2Pressed()
void SpawnWristMenu()
UFUNCTION(Server, Reliable, WithValidation)
virtual void HandleWristMenuItem7Pressed()
void SpawnProgressBar()
UFUNCTION(Server, Reliable, WithValidation)
virtual void HandleWristMenuItem4Pressed()
Class representing a circular progress indicator in PixoVR. The circle progress can be updated to dis...
void SetCircleProgressEnabled(bool bIsEnabled)
Sets the enabled state of the circle progress.
APixoVRHand is an actor class that represents a hand in the VR environment.
Definition PixoVRHand.h:99
void ManuallyPutActorToHand(AActor *ActorRef)
Manually puts an actor into the hand. Hand will try to grab this actor.
USkeletalMeshComponent * HandMesh
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:130
void GrabObject()
Grabs the object currently overlapped by grab sphere.
void InitPixoVRHands(EControllerHand MotionSource, APixoVRCharacter *Character)
UGripMotionControllerComponent * MotionController
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Components")
Definition PixoVRHand.h:118
void ReleaseObject()
Releases the currently held object.
UObject * HandHoldingObject
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
Definition PixoVRHand.h:250
void ToggleLaser(bool Visible)
Toggles the visibility of the laser.
Class for VR laser interaction. It can interact with widget buttons or actors derived from IPixoVRInt...
Definition PixoVRLaser.h:23
bool IsOverWidgetUse(bool InPressed)
Check if the laser is over a widget and simulate button press.
void TriggerSelect(bool State)
Call this method when the user wants to select the hovered object.
void SetHandType(EControllerHand HandType, bool InIsLocal)
Set the hand type describing which hand is holding it.
UWidgetInteractionComponent * WidgetInteraction
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
void ActivateLaserBeam(bool InActivate)
Activate or deactivate the laser beam.
bool bIsLaserBeamActive
UPROPERTY(BlueprintReadOnly, Transient, ReplicatedUsing=OnRep_LaserBeamActive, Category = "PixoVR | L...
A actor class representing the PixoVR wrist menu. The wrist menu allows users to interact with menu i...
bool bAlignToPlayerHead
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR | Wrist Menu")
EWristMenuItemCategory SelectMenuItem()
Signal that the user has performed a select action on the wrist menu.
bool IsActivated()
Check if the wrist menu is activated.
void ActivateWristMenu(bool InActivate)
Activate or deactivate the wrist menu.
void CalculateRotationByItemIndex(const int32 WristMenuItemIndex)
Calculate the rotation of the pointer arrow based on the item index.
void UpdateTrackpadPosition(const FVector2D &position)
Update the position of the trackpad. You need to call this method when the user moves his fingers (th...
UCLASS(Abstract)
virtual void ActivateTeleporter(bool InActivate)
Activate or deactivate the Teleporter.
virtual void ExecuteTeleportation(UVRBaseCharacterMovementComponent *MovementComponent, const FTransform &ActorTransform, const FVector &VRLocation, const FRotator &ActorRotation) PURE_VIRTUAL(
Execute the teleportation. It checks if there is a valid teleport destination before executing the te...
virtual bool IsActivated()
Check if the teleporter is activated.
virtual void SetMotionController(UGripMotionControllerComponent *InMotionController)
Set the motion controller that controls this Teleport.
virtual void UpdateMotionControllerRotation(const FVector2D &Direction)
Update the motion controller rotation for pad rotation.
void HintActivated(bool Activate)
This function is called when a hint is activated or deactivated. Broadcasts UHintActivatedEvent and O...
void ResolveMappings(const UDataTable *MappingsTable)
UINTERFACE(MinimalAPI)