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
16
18{
19 Super::BeginPlay();
20
21 // Load and setup rain/snow fall niagara system for this spectator
22 UNiagaraSystem* NiagaraSystem = LoadObject<UNiagaraSystem>(nullptr, TEXT("/Game/Agrarsense/Particles/WaterAndSnow/NS_Particles.NS_Particles"));
23 if (NiagaraSystem)
24 {
25 NiagaraComponent = UNiagaraFunctionLibrary::SpawnSystemAttached(NiagaraSystem, this->GetRootComponent(),
26 FName("NiagaraEmitterSocketName"),
27 FVector(0.0, 0.0, 150.0f), FRotator::ZeroRotator, EAttachLocation::KeepRelativeOffset, true);
28
29 ASensor::HideComponentForAllCameras(Cast<UPrimitiveComponent>(NiagaraComponent));
30 }
31
32 // Disable niagara component
34
35 // Create OverlapSensor
36 FSensorSpawnParameters SpawnParams;
37 SpawnParams.Transform = GetActorTransform();
38 SpawnParams.SensorIdentifier = "spectator/overlap";
39 SpawnParams.SensorName = "overlap";
40 SpawnParams.SimulateSensor = true;
41 SpawnParams.Parent = this;
42
43 FVector RelativePosition = FVector(0.0f, 0.0f, 0.0f);
44 float OverlapBoundsSize = 15.0f;
45
46 FOverlapSensorParameters SensorParams;
47 SensorParams.OwningActor = this;
48 SensorParams.Size = FVector(OverlapBoundsSize, OverlapBoundsSize, OverlapBoundsSize);
49 SensorParams.RelativePosition = RelativePosition;
50 SensorParams.AllChannels = true;
51
52 OverlapSensor = USensorFactory::SpawnOverlapSensor(SpawnParams, SensorParams);
53}
54
55void ASpectator::EndPlay(const EEndPlayReason::Type EndPlayReason)
56{
57 Super::EndPlay(EndPlayReason);
58
60 {
61 NiagaraComponent->UnregisterComponent();
62 NiagaraComponent->DestroyComponent();
63 NiagaraComponent = nullptr;
64 }
65
66 if (OverlapSensor)
67 {
68 OverlapSensor->Destroy();
69 OverlapSensor = nullptr;
70 }
71
72 Target.Reset();
73}
74
75void ASpectator::TeleportSpectator(const FTransform& Transform)
76{
77 if (!IsPlayerControlled())
78 {
79 return;
80 }
81
82 // Detach from any Actor and enable inputs.
84
85 FVector TargetLocation = Transform.GetLocation();
86 FVector Direction = GetActorLocation() - TargetLocation;
87 Direction.Normalize();
88
89 // 20 units away from the target so we are not top if it..
90 FVector NewLocation = TargetLocation + Direction * 20.0f;
91
92 FRotator NewRotation = (TargetLocation - NewLocation).ToOrientationRotator();
93
94 SetActorLocationAndRotation(NewLocation, NewRotation);
95
96 // Set the player controller rotation to match the incoming Transform angle,
97 // This actually sets the camera angle.
98 APlayerController* PlayerController = Cast<APlayerController>(GetController());
99 if (PlayerController)
100 {
101 PlayerController->SetControlRotation(Transform.Rotator());
102 }
103}
104
105void ASpectator::TeleportToActorLocation(const AActor* Actor)
106{
107 if (Actor)
108 {
109 FTransform Transform = Actor->GetActorTransform();
111 }
112}
113
114void ASpectator::FollowActor(AActor* Actor, bool DisableInputs, const float DistanceToActor, const float HeightOffset)
115{
116 Target = Actor;
117
118 if (!Target.IsValid())
119 {
120 return;
121 }
122
123 // Detach from any previous target
124 DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
125
126 // Set the offset to position the spectator slightly above and behind the actor
127 FVector Offset = FVector(0.0f, 0.0f, HeightOffset);
128
129 FVector TargetActorLocation = Actor->GetActorLocation();
130
131 FVector DirectionToActor = TargetActorLocation - GetActorLocation();
132 DirectionToActor.Normalize();
133
134 // Face the camera slightly down toward the actor
135 APlayerController* PlayerController = Cast<APlayerController>(GetController());
136 if (PlayerController)
137 {
138 if (DisableInputs)
139 {
140 DisableInput(PlayerController);
141 }
142 FRotator NewRotation = DirectionToActor.ToOrientationRotator();
143 PlayerController->SetControlRotation(NewRotation);
144 }
145
146 // Calculate the new location to be closer behind the actor
147 FVector NewLocation = TargetActorLocation + DirectionToActor * -DistanceToActor + Offset;
148
149 // Attach to the new target actor's root component with the offset
150 USceneComponent* Root = Actor->GetRootComponent();
151 if (Root)
152 {
153 AttachToComponent(Root, FAttachmentTransformRules::KeepRelativeTransform);
154 SetActorLocation(NewLocation);
155 }
156
157 OnFollowTargetChanged.Broadcast(true, Target.Get());
158}
159
160void ASpectator::TeleportToFollowLocation(FVector TargetLocation, const float DistanceToLocation, const float HeightOffset)
161{
162 // Set the offset to position the spectator slightly above and behind the actor
163 FVector Offset = FVector(0.0f, 0.0f, HeightOffset);
164
165 FVector DirectionToActor = TargetLocation - GetActorLocation();
166 DirectionToActor.Normalize();
167
168 // Face the camera slightly down toward the actor
169 APlayerController* PlayerController = Cast<APlayerController>(GetController());
170 if (PlayerController)
171 {
172 FRotator NewRotation = DirectionToActor.ToOrientationRotator();
173 PlayerController->SetControlRotation(NewRotation);
174 }
175
176 // Calculate the new location to be closer behind the actor
177 FVector NewLocation = TargetLocation + DirectionToActor * -DistanceToLocation + Offset;
178
179 SetActorLocation(NewLocation);
180}
181
182void ASpectator::TeleportToActorFollowLocation(AActor* Actor, const float DistanceToActor, const float HeightOffset)
183{
184 if (!IsValid(Actor))
185 {
186 return;
187 }
188
189 FVector TargetLocation = Actor->GetActorLocation();
190
191 TeleportToFollowLocation(TargetLocation, DistanceToActor, HeightOffset);
192}
193
195{
196 // Detach from any previous target
197 DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
198
199 Target.Reset();
200
201 if (EnableInputs)
202 {
203 APlayerController* PlayerController = Cast<APlayerController>(GetController());
204
205 if (PlayerController)
206 {
207 EnableInput(PlayerController);
208 }
209 }
210
211 OnFollowTargetChanged.Broadcast(false, Target.Get());
212}
213
215{
217 {
218 NiagaraComponent->SetVisibility(Visible);
219 }
220}
221
222void ASpectator::SetMaxSpeed(float MaxSpeed)
223{
224 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
225 if (FloatingMovement)
226 {
227 FloatingMovement->MaxSpeed = MaxSpeed;
228 }
229}
230
232{
233 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
234 if (FloatingMovement)
235 {
236 return FloatingMovement->MaxSpeed;
237 }
238
239 // Else return default value of 1500.0f (set in BP_spectator blueprint)
240 return 1500.0f;
241}
242
244{
245 return Cast<UFloatingPawnMovement>(GetMovementComponent());
246}
247
248
250{
251
252 if (!IsPlayerControlled())
253 {
254 return;
255 }
256
257 FTransform Transform = TeleportLocation.TeleportLocationTransform;
258
259 // Detach from any Actor and enable inputs.
261
262 SetActorLocationAndRotation(Transform.GetLocation(), Transform.GetRotation().Rotator());
263
264 // Set the player controller rotation to match the incoming Transform angle,
265 // This actually sets the camera angle.
266 APlayerController* PlayerController = Cast<APlayerController>(GetController());
267 if (PlayerController)
268 {
269 PlayerController->SetControlRotation(Transform.Rotator());
270 }
271}
static void HideComponentForAllCameras(UPrimitiveComponent *PrimitiveComponent)
Definition: Sensor.cpp:315
void SetMaxSpeed(float MaxSpeed=1500.0f)
Definition: Spectator.cpp:222
AOverlapSensor * OverlapSensor
Definition: Spectator.h:158
void TeleportToActorFollowLocation(AActor *Actor, const float DistanceToActor=1500.0f, const float HeightOffset=500.0f)
Definition: Spectator.cpp:182
void TeleportToFollowLocation(FVector TargetLocation, const float DistanceToLocation, const float HeightOffset)
Definition: Spectator.cpp:160
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Definition: Spectator.cpp:55
float GetMaxSpeed()
Definition: Spectator.cpp:231
void StopFollowingAnyActor(bool EnableInputs=true)
Definition: Spectator.cpp:194
FFollowTargetChanged OnFollowTargetChanged
Definition: Spectator.h:146
void FollowActor(AActor *Actor, bool DisableInputs=true, const float DistanceToActor=150.0f, const float HeightOffset=10.0f)
Definition: Spectator.cpp:114
void TeleportToActorLocation(const AActor *Actor)
Definition: Spectator.cpp:105
TWeakObjectPtr< AActor > Target
Definition: Spectator.h:162
UNiagaraComponent * NiagaraComponent
Definition: Spectator.h:155
UFloatingPawnMovement * GetFloatingPawnMovement()
Definition: Spectator.cpp:243
void SetNiagaraComponentVisibility(bool Visible)
Definition: Spectator.cpp:214
virtual void BeginPlay() override
Definition: Spectator.cpp:17
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:75
void TeleportToLevelTeleportLocation(FLevelTeleportLocation TeleportLocation)
Definition: Spectator.cpp:249
static AOverlapSensor * SpawnOverlapSensor(const FSensorSpawnParameters SpawnParameters, FOverlapSensorParameters SensorParameters)