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::TeleportToFollowLocation(FVector TargetLocation, const float DistanceToLocation, const float HeightOffset)
134{
135 // Set the offset to position the spectator slightly above and behind the actor
136 FVector Offset = FVector(0.0f, 0.0f, HeightOffset);
137
138 FVector DirectionToActor = TargetLocation - GetActorLocation();
139 DirectionToActor.Normalize();
140
141 // Face the camera slightly down toward the actor
142 APlayerController* PlayerController = Cast<APlayerController>(GetController());
143 if (PlayerController)
144 {
145 FRotator NewRotation = DirectionToActor.ToOrientationRotator();
146 PlayerController->SetControlRotation(NewRotation);
147 }
148
149 // Calculate the new location to be closer behind the actor
150 FVector NewLocation = TargetLocation + DirectionToActor * -DistanceToLocation + Offset;
151
152 SetActorLocation(NewLocation);
153}
154
155void ASpectator::TeleportToActorFollowLocation(AActor* Actor, const float DistanceToActor, const float HeightOffset)
156{
157 if (!IsValid(Actor))
158 {
159 return;
160 }
161
162 FVector TargetLocation = Actor->GetActorLocation();
163
164 TeleportToFollowLocation(TargetLocation, DistanceToActor, HeightOffset);
165}
166
168{
169 // Detach from any previous target
170 DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
171
172 Target.Reset();
173
174 if (EnableInputs)
175 {
176 APlayerController* PlayerController = Cast<APlayerController>(GetController());
177
178 if (PlayerController)
179 {
180 EnableInput(PlayerController);
181 }
182 }
183
184 OnFollowTargetChanged.Broadcast(false, Target.Get());
185}
186
188{
190 {
191 NiagaraComponent->SetVisibility(Visible);
192 }
193}
194
195void ASpectator::SetMaxSpeed(float MaxSpeed)
196{
197 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
198 if (FloatingMovement)
199 {
200 FloatingMovement->MaxSpeed = MaxSpeed;
201 }
202}
203
205{
206 UFloatingPawnMovement* FloatingMovement = GetFloatingPawnMovement();
207 if (FloatingMovement)
208 {
209 return FloatingMovement->MaxSpeed;
210 }
211
212 // Else return default value of 1500.0f (set in BP_spectator blueprint)
213 return 1500.0f;
214}
215
217{
218 return Cast<UFloatingPawnMovement>(GetMovementComponent());
219}
220
221
223{
224
225 if (!IsPlayerControlled())
226 {
227 return;
228 }
229
230 FTransform Transform = TeleportLocation.TeleportLocationTransform;
231
232 // Detach from any Actor and enable inputs.
234
235 SetActorLocationAndRotation(Transform.GetLocation(), Transform.GetRotation().Rotator());
236
237 // Set the player controller rotation to match the incoming Transform angle,
238 // This actually sets the camera angle.
239 APlayerController* PlayerController = Cast<APlayerController>(GetController());
240 if (PlayerController)
241 {
242 PlayerController->SetControlRotation(Transform.Rotator());
243 }
244}
static void HideComponentForAllCameras(UPrimitiveComponent *PrimitiveComponent)
Definition: Sensor.cpp:278
void SetMaxSpeed(float MaxSpeed=1500.0f)
Definition: Spectator.cpp:195
void TeleportToActorFollowLocation(AActor *Actor, const float DistanceToActor=1500.0f, const float HeightOffset=500.0f)
Definition: Spectator.cpp:155
void TeleportToFollowLocation(FVector TargetLocation, const float DistanceToLocation, const float HeightOffset)
Definition: Spectator.cpp:133
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
Definition: Spectator.cpp:34
float GetMaxSpeed()
Definition: Spectator.cpp:204
void StopFollowingAnyActor(bool EnableInputs=true)
Definition: Spectator.cpp:167
FFollowTargetChanged OnFollowTargetChanged
Definition: Spectator.h:138
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:151
UNiagaraComponent * NiagaraComponent
Definition: Spectator.h:147
UFloatingPawnMovement * GetFloatingPawnMovement()
Definition: Spectator.cpp:216
void SetNiagaraComponentVisibility(bool Visible)
Definition: Spectator.cpp:187
virtual void BeginPlay() override
Definition: Spectator.cpp:15
void TeleportSpectator(const FTransform &Transform)
Definition: Spectator.cpp:48
void TeleportToLevelTeleportLocation(FLevelTeleportLocation TeleportLocation)
Definition: Spectator.cpp:222