Documentation for the Unreal C++ Plugin
Loading...
Searching...
No Matches
BySpotTeleporter.cpp
Go to the documentation of this file.
1// Copyright(c) 2018 PixoVR, LLC. All Rights Reserved.
2
3
5
6#include "PixoVRCharacter.h"
8#include "Kismet/GameplayStatics.h"
9#include "Kismet/KismetMathLibrary.h"
10
12{
13 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderMeshFinder(TEXT("StaticMesh'/PixoCore/Meshes/BasicShapes/Cylinder.Cylinder'"));
14 UStaticMesh* CylinderMesh = CylinderMeshFinder.Object;
15
16 static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderRingMeshFinder(TEXT("StaticMesh'/PixoCore/Meshes/Controller/SM_FatCylinder.SM_FatCylinder'"));
17 UStaticMesh* CylinderRingMesh = CylinderRingMeshFinder.Object;
18
19 static ConstructorHelpers::FObjectFinder<UMaterial> TeleportCylinderMaterialFinder(TEXT("Material'/PixoCore/Materials/Controller/TeleportSpot/M_TeleportSpotPreviews.M_TeleportSpotPreviews'"));
20 UMaterial* CylinderMaterial = TeleportCylinderMaterialFinder.Object;
21
22 static ConstructorHelpers::FObjectFinder<UMaterial> ArcEndPointMaterialFinder(TEXT("Material'/PixoCore/Materials/Controller/TeleportSpot/M_TeleporterSpotMaterial.M_TeleporterSpotMaterial'"));
23 UMaterial* ArcEndPointMaterial = ArcEndPointMaterialFinder.Object;
24
25 TeleportersSpotCylinder = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TeleportersSpotCylinder"));
26 TeleportersSpotCylinder->SetupAttachment(RootComponent);
27 TeleportersSpotCylinder->SetWorldScale3D(FVector(0.75f, 0.75f, 1.0f));
28 TeleportersSpotCylinder->SetStaticMesh(CylinderMesh);
29 TeleportersSpotCylinder->SetMaterial(0, CylinderMaterial);
30 TeleportersSpotCylinder->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
31 TeleportersSpotCylinder->SetGenerateOverlapEvents(false);
32 TeleportersSpotCylinder->SetAbsolute(true, true, true);
33 TeleportersSpotCylinder->SetVisibility(false);
34
35 TeleportersSpotRing = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TeleportersSpotRing"));
37 TeleportersSpotRing->SetRelativeScale3D(FVector(0.5f, 0.5f, 0.15f));
38 TeleportersSpotRing->SetStaticMesh(CylinderRingMesh);
39 TeleportersSpotRing->SetMaterial(0, ArcEndPointMaterial);
40 TeleportersSpotRing->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
41 TeleportersSpotRing->SetGenerateOverlapEvents(false);
42 TeleportersSpotRing->SetVisibility(false);
43}
44
46{
47 Super::BeginPlay();
48
50 {
51 CylinderMaterialInstanceDynamic = UMaterialInstanceDynamic::Create(TeleportersSpotCylinder->GetMaterial(0), nullptr);
53 }
54
56 {
57 RingMaterialInstanceDynamic = UMaterialInstanceDynamic::Create(TeleportersSpotRing->GetMaterial(0), nullptr);
59 }
60
61 ActivateSpot(false);
62}
63
64void ATeleportersSpot::ActivateSpot(bool InActivate)
65{
67 {
68 bIsActive = InActivate;
69 if (InActivate)
70 {
71 CylinderMaterialInstanceDynamic->SetVectorParameterValue("Color", FLinearColor(ActiveColorOfSpot));
72 RingMaterialInstanceDynamic->SetVectorParameterValue("Color", FLinearColor(ActiveColorOfSpot));
73 }
74 else
75 {
76 CylinderMaterialInstanceDynamic->SetVectorParameterValue("Color", FLinearColor(NotActiveColorOfSpot));
77 RingMaterialInstanceDynamic->SetVectorParameterValue("Color", FLinearColor(NotActiveColorOfSpot));
78 }
79 }
80}
81
83{
84 return bIsActive;
85}
86
90
92{
93 Super::BeginPlay();
94
95 TArray<AActor*> FoundActors;
96 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATeleportersSpot::StaticClass(), FoundActors);
97 TeleportersSpots.Empty();
98 for (auto FoundActor : FoundActors)
99 {
100 TeleportersSpots.Add(Cast<ATeleportersSpot>(FoundActor));
101 }
102}
103
104void ABySpotTeleporter::ExecuteTeleportation(UVRBaseCharacterMovementComponent* InMovementComponent,
105 const FTransform& ActorTransform, const FVector& VRLocation, const FRotator& ActorRotation)
106{
107 // If we don't have a valid destination, don't execute teleportation.
109 {
110 return;
111 }
112
113 APixoVRCharacter* PixoVRCharacter = Cast<APixoVRCharacter>(GetOwner());
114 if (PixoVRCharacter)
115 {
116 if (PixoVRCharacter->bTeleportSoundsEnabled && PixoVRCharacter->TeleportSoundCue)
117 {
118 UGameplayStatics::PlaySound2D(this, PixoVRCharacter->TeleportSoundCue);
119 }
120 }
121
122 MovementComponent = InMovementComponent;
123
124 const FVector PivotPoint = VRLocation;
125 const FVector InvPivotPoint = UKismetMathLibrary::InverseTransformLocation(ActorTransform, PivotPoint);
126
127 ATeleportersSpot* LastValidTeleportersSpot = nullptr;
128 FVector LastValidTeleportLocation;
129 for (auto TeleportersSpot : TeleportersSpots)
130 {
131 if (TeleportersSpot->IsActive())
132 {
133 LastValidTeleportLocation = TeleportersSpot->TeleportersSpotCylinder->GetComponentLocation();
134 LastValidTeleportersSpot = TeleportersSpot;
135 }
136 }
137
138 // const FVector LastValidTeleportLocation = TeleportCylinder->GetComponentLocation();
139 const FVector TeleportToLocation = GetTeleportDestination(LastValidTeleportLocation);
140
141 UVRExpansionFunctionLibrary::RotateAroundPivot(FRotator::ZeroRotator, TeleportToLocation, ActorRotation, InvPivotPoint, TimedLocation, TimedRotation, true);
142
143 auto FadeInFinishedEvent = [this, LastValidTeleportersSpot, PixoVRCharacter]()
144 {
145 MovementComponent->PerformMoveAction_Teleport(TimedLocation, TimedRotation);
146 LastValidTeleportersSpot->OnCharacterTeleportedOnSpot.Broadcast(LastValidTeleportersSpot, PixoVRCharacter);
147 };
148
149 EventLogService::NewEvent<UFadeInAndFadeOutEvent>(nullptr, FadeInFinishedEvent, nullptr, FadeInDuration, 0.0f, FadeOutDuration);
150
152}
153
155{
156 if (AtListOneTeleportersActive() && InActivate)
157 {
158 return;
159 }
160
161 Super::ActivateTeleporter(InActivate);
162
163 for (auto TeleportersSpot : TeleportersSpots)
164 {
165 TeleportersSpot->TeleportersSpotCylinder->SetVisibility(InActivate);
166 TeleportersSpot->TeleportersSpotRing->SetVisibility(InActivate);
167 }
168}
169
171{
172 TArray<FVector> TracePoints;
173
174 // Is the location of the projectile falling onto the ground.
175 FVector TraceLocation;
176
177 bIsValidTeleportDestination = TraceTeleportDestination(TracePoints, TraceLocation);
178
180 {
181 UpdateArcSpline(TracePoints, true);
182 }
183
185}
186
187bool ABySpotTeleporter::TraceTeleportDestination(TArray<FVector>& TracePoints, FVector& TraceLocation)
188{
189 FVector StartPos(FVector::ZeroVector);
190 FVector LaunchVelocity (FVector::ZeroVector);
191
192 GetTeleportationTransform(StartPos, LaunchVelocity);
193 LaunchVelocity *= TeleportLaunchVelocity;
194
195 TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
196 ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECC_WorldStatic));
197
198 FPredictProjectilePathParams Params;
199 Params.bTraceWithCollision = true;
200 Params.bTraceComplex = false;
201 Params.DrawDebugType = EDrawDebugTrace::None;
202 Params.DrawDebugTime = 0.0f;
203 Params.SimFrequency = 30.0f;
204 Params.OverrideGravityZ = 0.0f;
205 Params.ObjectTypes = ObjectTypes;
206 Params.bTraceWithChannel = false;
207 Params.ProjectileRadius = 0.0f;
208 Params.StartLocation = StartPos;
209 Params.MaxSimTime = 2.0f;
210 Params.LaunchVelocity = LaunchVelocity;
211
212 FPredictProjectilePathResult PredictResult;
213 bool bHit = UGameplayStatics::PredictProjectilePath(this, Params, PredictResult);
214
215 if (!bHit)
216 {
217 return false;
218 }
219
220 FHitResult HitResult;
221 HitResult = PredictResult.HitResult;
222 TracePoints.Empty(PredictResult.PathData.Num());
223
224 for (const FPredictProjectilePathPointData& PathPoint : PredictResult.PathData)
225 {
226 TracePoints.Add(PathPoint.Location);
227 }
228
229 TraceLocation = HitResult.Location;
230
231 for (auto TeleportersSpot : TeleportersSpots)
232 {
233 FTransform CylinderTransform = TeleportersSpot->TeleportersSpotCylinder->GetComponentTransform();
234 FVector CylinderScale = CylinderTransform.GetScale3D();
235 FVector RingScale = TeleportersSpot->TeleportersSpotRing->GetComponentTransform().GetScale3D();
236
237 float CylinderRadius = TeleportersSpot->TeleportersSpotCylinder->Bounds.SphereRadius * CylinderScale.GetMax() + TeleportersSpot->BufferBoundsRadiusDetection;
238 float CylinderHalfHeight = TeleportersSpot->TeleportersSpotRing->Bounds.BoxExtent.Z * RingScale.Z + TeleportersSpot->BufferBoundsHeightDetection;
239
240 FVector LocationRelativeToComponent = CylinderTransform.InverseTransformPosition(TraceLocation);
241 if (TeleportersSpot->IsSpotHaveCubeShape)
242 {
243 if (FMath::Abs(LocationRelativeToComponent.X) <= TeleportersSpot->TeleportersSpotCylinder->Bounds.BoxExtent.X*SpotTeleporterExtendCoeficient &&
244 FMath::Abs(LocationRelativeToComponent.Y) <= TeleportersSpot->TeleportersSpotCylinder->Bounds.BoxExtent.Y*SpotTeleporterExtendCoeficient &&
245 FMath::Abs(LocationRelativeToComponent.Z) <= CylinderHalfHeight)
246 {
248 TeleportersSpot->ActivateSpot(true);
249 return true;
250 }
251 }
252 else //for sphere shapes
253 {
254 float DistanceToCenterXY = LocationRelativeToComponent.Size2D();
255
256 if (DistanceToCenterXY <= CylinderRadius && FMath::Abs(LocationRelativeToComponent.Z) <= CylinderHalfHeight)
257 {
259 TeleportersSpot->ActivateSpot(true);
260 return true;
261 }
262 }
263 }
264
266
267 return false;
268}
269
271{
272 for (auto TeleportersSpot : TeleportersSpots)
273 {
274 TeleportersSpot->ActivateSpot(false);
275 }
276}
277
279{
280 APixoVRCharacter* PixoVRCharacter = Cast<APixoVRCharacter>(UGameplayStatics::GetPlayerCharacter(GetWorld(), 0));
281 return PixoVRCharacter->TeleportControllerLeft->IsActivated() || PixoVRCharacter->TeleportControllerRight->IsActivated();
282}
virtual void ExecuteTeleportation(UVRBaseCharacterMovementComponent *InMovementComponent, const FTransform &ActorTransform, const FVector &VRLocation, const FRotator &ActorRotation) override
Execute the teleportation. It checks if there is a valid teleport destination before executing the te...
bool TraceTeleportDestination(TArray< FVector > &TracePoints, FVector &TraceLocation)
virtual void BeginPlay() override
virtual void TickTeleporter(float DeltaTime) override
Tick the Teleporter.
UVRBaseCharacterMovementComponent * MovementComponent
virtual void ActivateTeleporter(bool InActivate) override
Activate or deactivate the Teleporter.
TArray< ATeleportersSpot * > TeleportersSpots
UPROPERTY()
Pixo VR Character This class represents the main character in the Pixo VR game. It extends the AVRCha...
USoundCue * TeleportSoundCue
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "PixoVR", meta = (EditCondition = "bTeleportSo...
bool bTeleportSoundsEnabled
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "PixoVR")
ATeleporterBase * TeleportControllerRight
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
ATeleporterBase * TeleportControllerLeft
UPROPERTY(BlueprintReadOnly, Replicated, Category = "PixoVR")
float TeleportLaunchVelocity
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
bool bIsValidTeleportDestination
UPROPERTY(BlueprintReadOnly, Category = "PixoVR | Teleporter")
FRotator TimedRotation
virtual bool IsActivated()
Check if the teleporter is activated.
float FadeInDuration
UPROPERTY(EditAnywhere, Category = "PiUpdateMotionControllerRotationxoVR | Teleporter")
float FadeOutDuration
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
virtual void FVector GetTeleportDestination(const FVector &OriginalLocation)
Get the teleport destination.
void GetTeleportationTransform(FVector &Location, FVector &ForwardVector)
Get the teleportation transform which includes location and orientation.
virtual void UpdateArcEndpoint(const FVector &NewLocation, bool ValidLocationFound)
Update the endpoint of the arc spline.
virtual void UpdateArcSpline(TArray< FVector > &SplinePoints, bool ValidLocationFound)
Update the arc spline.
bool bDrawArcSpline
UPROPERTY(EditAnywhere, Category = "PixoVR | Teleporter")
UCLASS(BlueprintType)
UMaterialInstanceDynamic * RingMaterialInstanceDynamic
UPROPERTY()
FColor ActiveColorOfSpot
UPROPERTY(EditAnywhere, Category = "Spot | Color")
FColor NotActiveColorOfSpot
UPROPERTY(EditAnywhere, Category = "Spot | Color")
UMaterialInstanceDynamic * CylinderMaterialInstanceDynamic
UPROPERTY()
void ActivateSpot(bool InActivate)
Activate or deactivate the Teleporter.
virtual void BeginPlay() override
UStaticMeshComponent * TeleportersSpotRing
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Spot")
FOnCharacterTeleportedOnSpot OnCharacterTeleportedOnSpot
UPROPERTY(BlueprintAssignable, Category = "Spot | Delegates")
UStaticMeshComponent * TeleportersSpotCylinder
UPROPERTY(VisibleDefaultsOnly, BlueprintReadWrite, Category = "Spot")
static FUNCTION_NON_NULL_RETURN_START TEventType * NewEvent(APlayerController *Executor=nullptr) FUNCTION_NON_NULL_RETURN_END
Creates a new event of the specified type.