4#include "Components/StaticMeshComponent.h"
5#include "Components/SplineComponent.h"
6#include "Components/WidgetInteractionComponent.h"
7#include "Kismet/GameplayStatics.h"
8#include "NavigationSystem.h"
13#include "Kismet/KismetMathLibrary.h"
15#define TELEPORT_DEBUG 0
20 : ArcSplineComponent(nullptr)
21 , ArcEndPoint(nullptr)
22 , TeleportCylinder(nullptr)
25 , ArcSplineMesh(nullptr)
26 , ArcSplineMaterial(nullptr)
27 , MotionController(nullptr)
28 , bIsTeleporterActive(false)
29 , bIsValidTeleportDestination(false)
30 , bDrawTeleportArrow(false)
31 , bDrawArcSpline(true)
32 , bDrawTeleportCylinder(true)
33 , TeleportRotation(FRotator::ZeroRotator)
34 , PadRotation(FRotator::ZeroRotator)
36 , TeleportLaunchVelocity(1200.0f)
37 , FadeInDuration(0.25f)
38 , FadeOutDuration(0.25f)
39 , TeleportFadeColor(FLinearColor::Black)
40 , NavigationSystem(nullptr)
42 PrimaryActorTick.bCanEverTick =
true;
43 PrimaryActorTick.bStartWithTickEnabled =
false;
46 SetReplicateMovement(
false);
47 bNetLoadOnClient =
false;
49 static ConstructorHelpers::FObjectFinder<UStaticMesh> ArcSplineMeshFinder(TEXT(
"StaticMesh'/PixoCore/Meshes/Controller/BeamMesh.BeamMesh'"));
52 static ConstructorHelpers::FObjectFinder<UMaterial> ArcSplineMaterialFinder(TEXT(
"Material'/PixoCore/Materials/Controller/SplineArcMaterial.SplineArcMaterial'"));
55 static ConstructorHelpers::FObjectFinder<UStaticMesh> ArcEndPointMeshFinder(TEXT(
"StaticMesh'/PixoCore/Meshes/BasicShapes/Sphere.Sphere'"));
56 UStaticMesh* ArcEndPointMesh = ArcEndPointMeshFinder.Object;
58 static ConstructorHelpers::FObjectFinder<UMaterial> ArcEndPointMaterialFinder(TEXT(
"Material'/PixoCore/Materials/Controller/ArcEndpointMaterial.ArcEndpointMaterial'"));
59 UMaterial* ArcEndPointMaterial = ArcEndPointMaterialFinder.Object;
61 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMeshFinder(TEXT(
"StaticMesh'/PixoCore/Meshes/BasicShapes/Cylinder.Cylinder'"));
62 UStaticMesh* CylinderMesh = CylinderMeshFinder.Object;
64 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderRingMeshFinder(TEXT(
"StaticMesh'/PixoCore/Meshes/Controller/SM_FatCylinder.SM_FatCylinder'"));
65 UStaticMesh* CylinderRingMesh = CylinderRingMeshFinder.Object;
67 static ConstructorHelpers::FObjectFinder<UMaterialInstance> TeleportCylinderMaterialFinder(TEXT(
"MaterialInstanceConstant'/PixoCore/Materials/Controller/TeleportCylinderPreviewMaterialInstance.TeleportCylinderPreviewMaterialInstance'"));
68 UMaterialInstance* CylinderMaterial = TeleportCylinderMaterialFinder.Object;
70 USceneComponent* SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT(
"TeleportSceneComponent"));
71 RootComponent = SceneComponent;
79 ArcEndPoint = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"ArcEndPoint"));
81 ArcEndPoint->SetWorldScale3D(FVector(0.08f, 0.08f, 0.08f));
85 ArcEndPoint->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
90 TeleportCylinder = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"TeleportCylinder"));
95 TeleportCylinder->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
100 Ring = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"Ring"));
102 Ring->SetRelativeScale3D(FVector(0.5f, 0.5f, 0.15f));
103 Ring->SetStaticMesh(CylinderRingMesh);
104 Ring->SetMaterial(0, ArcEndPointMaterial);
105 Ring->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
106 Ring->SetGenerateOverlapEvents(
false);
109 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderArrowMeshFinder(TEXT(
"StaticMesh'/PixoCore/Meshes/Controller/BeaconDirection.BeaconDirection'"));
110 UStaticMesh* CylinderArrowMesh = CylinderArrowMeshFinder.Object;
112 Arrow = CreateDefaultSubobject<UStaticMeshComponent>(TEXT(
"Arrow"));
113 Arrow->SetupAttachment(SceneComponent);
114 Arrow->SetStaticMesh(CylinderArrowMesh);
115 Arrow->SetMaterial(0, ArcEndPointMaterial);
116 Arrow->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
117 Arrow->SetGenerateOverlapEvents(
false);
118 Arrow->SetVisibility(
false,
true);
132 NavigationSystem = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld());
137 Super::Tick(DeltaTime);
154 TArray<FVector> TracePoints;
157 FVector TraceLocation;
160 FVector NavMeshLocation;
193 FVector DevicePosition = FVector::ZeroVector;
194 FRotator DeviceRotation = FRotator::ZeroRotator;
195 UHeadMountedDisplayFunctionLibrary::GetOrientationAndPosition(DeviceRotation, DevicePosition);
196 DevicePosition.Z = 0.0f;
197 FVector Correction = UKismetMathLibrary::GreaterGreater_VectorRotator(DevicePosition,
TeleportRotation);
199 FVector HMDPositionInWorldSpace = GetOwner()->GetActorLocation() - DevicePosition;
202 HMDPositionInWorldSpace.Z = 30.0f;
203 FVector OwnerActorLocation = GetOwner()->GetActorLocation();
204 OwnerActorLocation.Z += 10.0f;
205 UKismetSystemLibrary::DrawDebugLine(
this, OwnerActorLocation,
TeleportCylinder->GetComponentLocation(), FColor::Red, 0.0f, 2.0f);
206 UKismetSystemLibrary::DrawDebugLine(
this, OwnerActorLocation, HMDPositionInWorldSpace, FColor::Green, 0.0f, 2.0f);
252 SplineMeshComponent->DestroyComponent();
261 FVector StartPos(FVector::ZeroVector);
262 FVector LaunchVelocity (FVector::ZeroVector);
267 TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
268 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));
270 FPredictProjectilePathParams Params;
271 Params.bTraceWithCollision =
true;
272 Params.bTraceComplex =
false;
273 Params.DrawDebugType = EDrawDebugTrace::None;
274 Params.DrawDebugTime = 0.0f;
275 Params.SimFrequency = 30.0f;
276 Params.OverrideGravityZ = 0.0f;
277 Params.ObjectTypes = ObjectTypes;
278 Params.bTraceWithChannel =
false;
279 Params.ProjectileRadius = 0.0f;
280 Params.StartLocation = StartPos;
281 Params.MaxSimTime = 2.0f;
282 Params.LaunchVelocity = LaunchVelocity;
284 FPredictProjectilePathResult PredictResult;
285 bool bHit = UGameplayStatics::PredictProjectilePath(
this, Params, PredictResult);
287 FHitResult HitResult;
288 FVector LastTraceDestination;
290 HitResult = PredictResult.HitResult;
291 LastTraceDestination = PredictResult.LastTraceDestination.Location;
292 TracePoints.Empty(PredictResult.PathData.Num());
294 for (
const FPredictProjectilePathPointData& PathPoint : PredictResult.PathData)
296 TracePoints.Add(PathPoint.Location);
299 TraceLocation = HitResult.Location;
301 bool bProjectPointToNavigation =
false;
304 FVector QueryingExtent (500.0f, 500.0f, 500.0f);
305 FNavLocation NavLocation {};
307 bProjectPointToNavigation =
NavigationSystem->ProjectPointToNavigation(HitResult.Location, NavLocation, QueryingExtent);
308 NavMeshLocation = NavLocation.Location;
311 bProjectPointToNavigation = (NavMeshLocation != FVector(0.0f, 0.0f, 0.0f)) && (TraceLocation != NavMeshLocation);
313 return bHit & bProjectPointToNavigation;
318 Location = RootComponent->GetComponentLocation();
319 ForwardVector = RootComponent->GetForwardVector();
327 return OriginalLocation - Offset;
343 FVector A(Direction.X, Direction.Y, 0.0f);
352 FRotator CharacterRotation = GetOwner()->GetActorRotation();
353 CharacterRotation.Roll = 0.0f;
354 CharacterRotation.Pitch = 0.0f;
356 const FVector RotatedVector = CharacterRotation.RotateVector(A);
357 return RotatedVector.Rotation();
360 return FRotator::ZeroRotator;
365 Super::GetLifetimeReplicatedProps(OutLifetimeProps);
372 if(ValidLocationFound)
374 const auto Start = NavMeshLocation;
375 const auto End = Start + FVector(0.0f, 0.0f, -200.0f);
376 TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
377 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));
378 const auto TraceComplex =
false;
379 const TArray<AActor*> ActorsToIgnore;
380 const auto IgnoreSelf =
true;
381 FHitResult HitResult;
382 const float DrawTime = 5.0;
384 UKismetSystemLibrary::LineTraceSingleForObjects(
this,
390 EDrawDebugTrace::None,
397 FVector NewLocation = FVector::ZeroVector;
398 if(HitResult.bBlockingHit)
400 NewLocation = HitResult.ImpactPoint;
404 NewLocation = NavMeshLocation;
407 TeleportCylinder->SetWorldLocation(NewLocation,
false,
nullptr, ETeleportType::TeleportPhysics);
417 ArcEndPoint->SetVisibility(ValidLocationFound,
true);
418 ArcEndPoint->SetWorldLocation(NewLocation,
false,
nullptr, ETeleportType::TeleportPhysics);
425 if(ValidLocationFound)
427 for(
auto& SplinePoint : SplinePoints)
432 ArcSplineComponent->SetSplinePointType(SplinePoints.Num() - 1, ESplinePointType::CurveClamped,
true);
438 for(int32 Index = 0; Index <= NumberOfSplinesToAdd; Index++)
440 USplineMeshComponent* SplineMeshComponent = NewObject<USplineMeshComponent>(
this);
442 SplineMeshComponent->SetMobility(EComponentMobility::Movable);
443 SplineMeshComponent->SetStartPosition(FVector(0.0f, 0.0f, 0.0f),
true);
444 SplineMeshComponent->SetStartTangent(FVector(100.0f, 0.0f, 0.0f),
true);
445 SplineMeshComponent->SetEndPosition(FVector(100.0f, 0.0f, 0.0f),
true);
446 SplineMeshComponent->SetEndTangent(FVector(100.0f, 0.0f, 0.0f),
true);
447 SplineMeshComponent->SetSplineUpDir(FVector(0.0f, 0.0f, 1.0f),
true);
448 SplineMeshComponent->SetForwardAxis(ESplineMeshAxis::X,
true);
449 SplineMeshComponent->SetStartScale(FVector2D(4, 4));
450 SplineMeshComponent->SetEndScale(FVector2D(4, 4));
453 SplineMeshComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
454 SplineMeshComponent->SetGenerateOverlapEvents(
false);
456 FTransform Transform = FTransform(FRotator(0.0f, 0.0f, 0.0f), FVector(0.0f, 0.0f, 0.0f), FVector(1.0f, 1.0f, 1.0f));
457 SplineMeshComponent->SetRelativeTransform(Transform);
458 SplineMeshComponent->RegisterComponent();
471 SplineMeshComponent->SetVisibility(
true,
false);
473 const auto StartTangent =
ArcSplineComponent->GetTangentAtSplinePoint(Index, ESplineCoordinateSpace::Local);
474 const auto EndTangent =
ArcSplineComponent->GetTangentAtSplinePoint(Index + 1, ESplineCoordinateSpace::Local);
476 SplineMeshComponent->SetStartAndEnd(SplinePoints[Index], StartTangent, SplinePoints[Index + 1], EndTangent,
true);
481 SplineMeshComponent->SetVisibility(
false,
false);
491 SplineMeshComponent->SetVisibility(
false,
false);
497void APixoVRTeleporter::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
499 if(PropertyChangedEvent.Property !=
nullptr)
501 const FName PropertyName (PropertyChangedEvent.Property->GetFName());
508 Super::PostEditChangeProperty(PropertyChangedEvent);
522 const FVector PivotPoint = VRLocation;
523 const FVector InvPivotPoint = UKismetMathLibrary::InverseTransformLocation(ActorTransform, PivotPoint);
525 const FVector LastValidTeleportLocation =
TeleportCylinder->GetComponentLocation();
530 auto FadeInFinishedEvent = [
this]()
DEFINE_LOG_CATEGORY(LogPixoVRTeleporter)
Pixo VR Character This class represents the main character in the Pixo VR game. It extends the AVRCha...
Class for VR teleporter functionality. It allows teleportation using visual indicators.
void TickTeleporter(float DeltaTime)
Tick the Teleporter.
virtual void BeginPlay() override
float FadeInDuration
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
TArray< USplineMeshComponent * > SplineMeshComponents
UMaterial * ArcSplineMaterial
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR | Teleporter", Meta = (AllowPrivateAcc...
FRotator TeleportRotation
UPROPERTY(BlueprintReadOnly, Category = "PixoVR | Teleporter")
virtual void Tick(float DeltaTime) override
bool bIsTeleporterActive
UPROPERTY(BlueprintReadOnly, Category = "PixoVR | Teleporter")
virtual void Destroyed() override
bool bDrawTeleportCylinder
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
bool bDrawTeleportArrow
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
UStaticMeshComponent * ArcEndPoint
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
UStaticMeshComponent * Arrow
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
float TeleportLaunchVelocity
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
UStaticMeshComponent * TeleportCylinder
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
FRotator GetRotationFromInput(const FVector2D &Direction)
Calculate the FRotator from the pad of a controller.
UStaticMesh * ArcSplineMesh
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PixoVR | Teleporter", Meta = (AllowPrivateAcc...
UStaticMeshComponent * Ring
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
float FadeOutDuration
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
void GetTeleportationTransform(FVector &Location, FVector &ForwardVector)
Get the teleportation transform which includes location and orientation.
FRotator PadRotation
UPROPERTY(BlueprintReadOnly, Category = "PixoVR | Teleporter")
UGripMotionControllerComponent * MotionController
UPROPERTY(Replicated)
virtual void GetLifetimeReplicatedProps(TArray< FLifetimeProperty > &OutLifetimeProps) const override
UVRBaseCharacterMovementComponent * MovementComponent
void UpdateTeleportCylinder(const FVector &NewLocation, bool ValidLocationFound)
Update the teleport cylinder.
void ExecuteTeleportation(UVRBaseCharacterMovementComponent *MovementComponent, const FTransform &ActorTransform, const FVector &VRLocation, const FRotator &ActorRotation)
Execute the teleportation. It checks if there is a valid teleport destination before executing the te...
void UpdateArcSpline(TArray< FVector > &SplinePoints, bool ValidLocationFound)
Update the arc spline.
bool bIsValidTeleportDestination
UPROPERTY(BlueprintReadOnly, Category = "PixoVR | Teleporter")
FVector GetTeleportDestination(const FVector &OriginalLocation)
Get the teleport destination.
bool bDrawArcSpline
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
void ClearArc()
Clear the arc spline.
USplineComponent * ArcSplineComponent
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite)
void ActivateTeleporter(bool InActivate)
Activate or deactivate the Teleporter.
bool IsActivated()
Check if the teleporter is activated.
float ThumbDeadZone
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
bool TraceTeleportDestination(TArray< FVector > &TracePoints, FVector &TraceLocation, FVector &NavMeshLocation)
Traces the teleport destination using projectile path prediction and navigation system....
UNavigationSystemV1 * NavigationSystem
void SetMotionController(UGripMotionControllerComponent *InMotionController)
Set the motion controller that controls this Teleport.
void UpdateMotionControllerRotation(const FVector2D &Direction)
Update the motion controller rotation for pad rotation.
void UpdateArcEndpoint(const FVector &NewLocation, bool ValidLocationFound)
Update the endpoint of the arc spline.
FVector GetVRLocation() const
UFUNCTION(BlueprintPure, Category = "BaseVRCharacter|VRLocations")
UVRRootComponent * VRRootReference
UPROPERTY(Category = VRCharacter, VisibleAnywhere, Transient, BlueprintReadOnly, meta = (AllowPrivate...
UCLASS(Blueprintable, meta = (BlueprintSpawnableComponent), ClassGroup = MotionController)
void PerformMoveAction_Teleport(FVector TeleportLocation, FRotator TeleportRotation, EVRMoveActionVelocityRetention VelocityRetention=EVRMoveActionVelocityRetention::VRMOVEACTION_Velocity_None, bool bSkipEncroachmentCheck=false)
UFUNCTION(BlueprintCallable, Category = "VRMovement")
static void RotateAroundPivot(FRotator RotationDelta, FVector OriginalLocation, FRotator OriginalRotation, FVector PivotPoint, FVector &NewLocation, FRotator &NewRotation, bool bUseOriginalYawOnly=true)
UFUNCTION(BlueprintCallable, Category = "VRExpansionFunctions", meta = (bIgnoreSelf = "true",...
FTransform OffsetComponentToWorld