Agrarsense
Spectator.cpp
Go to the documentation of this file.
1// Copyright (c) 2023 FrostBit Software Lab at the Lapland University of Applied Sciences
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
6#include "Spectator.h"
7#include "GameFramework/FloatingPawnMovement.h"
8#include "GameFramework/PlayerController.h"
9#include "Components/SceneComponent.h"
10#include "NiagaraFunctionLibrary.h"
11#include "NiagaraSystem.h"
12
14
16{
17 Super::BeginPlay();
18
19 // Load and setup rain/snow fall niagara system for this spectator
20 UNiagaraSystem* NiagaraSystem = LoadObject<UNiagaraSystem>(nullptr, TEXT("/Game/Agrarsense/Particles/WaterAndSnow/NS_Particles.NS_Particles"));
21 if (NiagaraSystem)
22 {
23 NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(NiagaraSystem, this->GetRootComponent(),
24 FName("NiagaraEmitterSocketName"),
25 FVector(0.0, 0.0, 150.0f), FRotator::ZeroRotator, EAttachLocation::KeepRelativeOffset, true);
26
27 ASensor::HideComponentForAllCameras(Cast<UPrimitiveComponent>(NiagaraComponent));
28 }
29
30 // Disable niagara component
32}
33
34void ASpectator::EndPlay(const EEndPlayReason::Type EndPlayReason)
35{
36 Super::EndPlay(EndPlayReason);
37
39 {
40 NiagaraComponent->UnregisterComponent();
41 NiagaraComponent->DestroyComponent();
42 NiagaraComponent = nullptr;
43 }
44
45 Target.Reset();
46}
47
48void ASpectator::TeleportSpectator(const FTransform& Transform)
49{
50 if (!IsPlayerControlled())
51 {
52 return;
53 }
54
55 // Detach from any Actor and enable inputs.
57
58 FVector TargetLocation = Transform.GetLocation();
59 FVector Direction = GetActorLocation() - TargetLocation;
60 Direction.Normalize();
61
62 // 20 units away from the target so we are not top if it..
63 FVector NewLocation = TargetLocation + Direction * 20.0f;
64
65 FRotator NewRotation = (TargetLocation - NewLocation).ToOrientationRotator();
66
67 SetActorLocationAndRotation(NewLocation, NewRotation);
68
69 // Set the player controller rotation to match the incoming Transform angle,
70 // This actually sets the camera angle.
71 APlayerController* PlayerController = Cast<APlayerController>(GetController());
72 if (PlayerController)
73 {
74 PlayerController->SetControlRotation(Transform.Rotator());
75 }
76}
77
78void ASpectator::TeleportToActorLocation(const AActor* Actor)
79{
80 if (Actor)
81 {
82 FTransform Transform = Actor->GetActorTransform();
84 }
85}
86
87void ASpectator::FollowActor(AActor* Actor, bool DisableInputs, const float DistanceToActor, const float HeightOffset)
88{
89 Target = Actor;
90
91 if (!Target.IsValid())
92 {
93 return;
94 }
95
96 // Detach from any previous target
97 DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
98
99 // Set the offset to position the spectator slightly above and behind the actor
100 FVector Offset = FVector(0.0f, 0.0f, HeightOffset);
101
102 FVector TargetActorLocation = Actor->GetActorLocation();
103
104 FVector DirectionToActor = TargetActorLocation - GetActorLocation();
105 DirectionToActor.Normalize();
106
107 // Face the camera slightly down toward the actor
108 APlayerController* PlayerController = Cast<APlayerController>(GetController());
109 if (PlayerController)
110 {
111 if (DisableInputs)
112 {
113 DisableInput(PlayerController);
114 }
115 FRotator NewRotation = DirectionToActor.ToOrientationRotator();
116 PlayerController->SetControlRotation(NewRotation);
117 }
118
119 // Calculate the new location to be closer behind the actor
120 FVector NewLocation = TargetActorLocation + DirectionToActor * -DistanceToActor + Offset;
121
122 // Attach to the new target actor's root component with the offset
123 USceneComponent* Root = Actor->GetRootComponent();
124 if (Root)
125 {
126 AttachToComponent(Root, FAttachmentTransformRules::KeepRelativeTransform);
127 SetActorLocation(NewLocation);
128 }
129
130 OnFollowTargetChanged.Broadcast(true, Target.Get());
131}
132
133void ASpectator::TeleportToActorFollowLocation(AActor* Actor, const float DistanceToActor, const float HeightOffset)
134{
135 if (!IsValid(Actor))
136 {
137 return;
138 }
139
140 // Set the offset to position the spectator slightly above and behind the actor
141 FVector Offset = FVector(0.0f, 0.0f, HeightOffset);
142
143 FVector TargetActorLocation = Actor->GetActorLocation();
144
145 FVector DirectionToActor = TargetActorLocation - GetActorLocation();
146 DirectionToActor.Normalize();
147
148 // Face the camera slightly down toward the actor
149 APlayerController* PlayerController = Cast<APlayerController>(GetController());
150 if (PlayerController)
151 {
152 FRotator NewRotation = DirectionToActor.ToOrientationRotator();
153 PlayerController->SetControlRotation(NewRotation);
154 }
155
156 // Calculate the new location to be closer behind the actor
157 FVector NewLocation = TargetActorLocation + DirectionToActor * -DistanceToActor + Offset;
158
159 SetActorLocation(NewLocation);
160
161}
162
164{
165 // Detach from any previous target
166 DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
167
168 Target.Reset();
169
170 if (EnableInputs)
171 {
172 APlayerController* PlayerController = Cast<APlayerController>(GetController());
173
174 if (PlayerController)
175 {
176 EnableInput(PlayerController);
177 }
178 }
179
180 OnFollowTargetChanged.Broadcast(false, Target.Get());
181}
182
184{
186 {
187 NiagaraComponent->SetVisibility(Visible);
188 }
189}
190
191void ASpectator::SetMaxSpeed(float MaxSpeed)
192{
193 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
194 if (FloatingMovement)
195 {
196 FloatingMovement->MaxSpeed = MaxSpeed;
197 }
198}
199
201{
202 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
203 if (FloatingMovement)
204 {
205 return FloatingMovement->MaxSpeed;
206 }
207
208 // Else return default value of 1500.0f (set in BP_spectator blueprint)
209 return 1500.0f;
210}
211
213{
214 return Cast<UFloatingPawnMovement>(GetMovementComponent());
215}
216
217
219{
220
221 if (!IsPlayerControlled())
222 {
223 return;
224 }
225
226 FTransform Transform = TeleportLocation.TeleportLocationTransform;
227
228 // Detach from any Actor and enable inputs.
230
231 SetActorLocationAndRotation(Transform.GetLocation(), Transform.GetRotation().Rotator());
232
233 // Set the player controller rotation to match the incoming Transform angle,
234 // This actually sets the camera angle.
235 APlayerController* PlayerController = Cast<APlayerController>(GetController());
236 if (PlayerController)
237 {
238 PlayerController->SetControlRotation(Transform.Rotator());
239 }
240}
static void HideComponentForAllCameras(UPrimitiveComponent *PrimitiveComponent)
Definition: Sensor.cpp:255
void SetMaxSpeed(float MaxSpeed=1500.0f)
Definition: Spectator.cpp:191
void TeleportToActorFollowLocation(AActor *Actor, const float DistanceToActor=1500.0f, const float HeightOffset=500.0f)
Definition: Spectator.cpp:133
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Definition: Spectator.cpp:34
float GetMaxSpeed()
Definition: Spectator.cpp:200
void StopFollowingAnyActor(bool EnableInputs=true)
Definition: Spectator.cpp:163
FFollowTargetChanged OnFollowTargetChanged
Definition: Spectator.h:131
void FollowActor(AActor *Actor, bool DisableInputs=true, const float DistanceToActor=150.0f, const float HeightOffset=10.0f)
Definition: Spectator.cpp:87
void TeleportToActorLocation(const AActor *Actor)
Definition: Spectator.cpp:78
TWeakObjectPtr< AActor > Target
Definition: Spectator.h:144
UNiagaraComponent * NiagaraComponent
Definition: Spectator.h:140
UFloatingPawnMovement * GetFloatingPawnMovement()
Definition: Spectator.cpp:212
void SetNiagaraComponentVisibility(bool Visible)
Definition: Spectator.cpp:183
virtual void BeginPlay() override
Definition: Spectator.cpp:15
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:48
void TeleportToLevelTeleportLocation(FLevelTeleportLocation TeleportLocation)
Definition: Spectator.cpp:218