Select Git revision
PointOfInterestManager.cpp
PointOfInterestManager.cpp 4.72 KiB
#include "PointOfInterestManager.h"
#include "PointOfInterest.h"
#include "Kismet/GameplayStatics.h"
#include "Logging/StructuredLog.h"
DEFINE_LOG_CATEGORY(POIManagerLog);
APointOfInterestManager::APointOfInterestManager()
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
PrimaryActorTick.SetTickFunctionEnable(true);
POIs = TArray<APointOfInterest*>();
SplineComponent = CreateDefaultSubobject<USplineComponent>("SplineComponent");
SplineComponent->SetupAttachment(RootComponent.Get());
}
void APointOfInterestManager::TickActor(float DeltaTime, enum ELevelTick TickType, FActorTickFunction& ThisTickFunction)
{
SplineComponent->Duration = SplineComponent->GetSplineLength() / CameraSpeed;
if (IsRidingCamera)
{
ProgressCameraRide();
}
}
void APointOfInterestManager::AddPointOfInterest()
{
APointOfInterest* POI = static_cast<APointOfInterest*>(GetWorld()->SpawnActor(APointOfInterest::StaticClass()));
POI->GetRootComponent()->TransformUpdated.AddLambda([this](USceneComponent*, EUpdateTransformFlags, ETeleportType)
{
UpdateSpline();
});
POIs.Add(POI);
UpdateSpline();
}
void APointOfInterestManager::VisitNextPointOfInterest()
{
if (CurrentPOIIndex >= GetPointOfInterestCount() - 1)
{
CurrentPOIIndex = 0;
}
else
{
++CurrentPOIIndex;
}
VisitPointOfInterest(POIs[CurrentPOIIndex]);
}
void APointOfInterestManager::VisitPreviousPointOfInterest()
{
if (CurrentPOIIndex <= 0)
{
CurrentPOIIndex = GetPointOfInterestCount() - 1;
}
else
{
--CurrentPOIIndex;
}
VisitPointOfInterest(POIs[CurrentPOIIndex]);
}
void APointOfInterestManager::VisitPointOfInterestByIndex(int index)
{
VisitPointOfInterest(POIs[index]);
}
void APointOfInterestManager::VisitPointOfInterest(APointOfInterest* POI) const
{
APawn* Pawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if (!Pawn)
{
UE_LOGFMT(POIManagerLog, Warning, "Attempted to move player pawn but no pawn found to move.");
return;
}
FVector Location = POI->GetActorLocation();
FRotator Rotation = POI->GetActorRotation();
Rotation.Pitch = 0;
Rotation.Roll = 0;
Pawn->Controller->SetControlRotation(Rotation);
Pawn->SetActorLocationAndRotation(Location, Rotation);
}
int APointOfInterestManager::GetPointOfInterestCount()
{
return POIs.Num();
}
void APointOfInterestManager::StartCameraRide()
{
CameraRideStart = UGameplayStatics::GetTimeSeconds(this);
CameraRideEnd = CameraRideStart + SplineComponent->Duration;
IsRidingCamera = true;
}
void APointOfInterestManager::StopCameraRide()
{
CameraRideEnded();
}
void APointOfInterestManager::UpdateSpline()
{
for (int i = 0; i < GetPointOfInterestCount(); ++i)
{
if (POIs[i] == nullptr)
{
POIs.RemoveAt(i);
SplineComponent->RemoveSplinePoint(i);
--i;
}
else if (!POIs[i]->GetRootComponent()->TransformUpdated.IsBound())
{
POIs[i]->GetRootComponent()->TransformUpdated.AddLambda(
[this](USceneComponent*, EUpdateTransformFlags, ETeleportType)
{
UpdateSpline();
});
}
}
int POIsNum = GetPointOfInterestCount();
int SplinePointsNum = SplineComponent->GetNumberOfSplinePoints();
if (POIsNum > SplinePointsNum)
{
for (int i = SplinePointsNum; i < POIsNum; ++i)
{
SplineComponent->AddSplinePointAtIndex(FVector::Zero(), i, ESplineCoordinateSpace::World);
}
}
else if (POIsNum < SplinePointsNum)
{
for (int i = SplinePointsNum - 1; i >= POIsNum; --i)
{
SplineComponent->RemoveSplinePoint(i);
}
}
for (int i = 0; i < GetPointOfInterestCount(); ++i)
{
APointOfInterest* POI = POIs[i];
FVector POIPosition = POI->GetActorLocation();
FRotator POIRotation = POI->GetActorRotation();
SplineComponent->SetLocationAtSplinePoint(i, POIPosition, ESplineCoordinateSpace::World);
SplineComponent->SetRotationAtSplinePoint(i, POIRotation, ESplineCoordinateSpace::World);
}
}
void APointOfInterestManager::ProgressCameraRide()
{
double Current = UGameplayStatics::GetTimeSeconds(this);
float SecondsSinceStart = Current - CameraRideStart;
UE_LOGFMT(POIManagerLog, VeryVerbose, "");
APawn* Pawn = UGameplayStatics::GetPlayerPawn(GetWorld(), 0);
if (!Pawn)
{
UE_LOGFMT(POIManagerLog, Warning, "Attempted to move player pawn but no pawn found to move.");
return;
}
if (Current < CameraRideEnd)
{
FVector Location = SplineComponent->GetLocationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
FRotator Rotation = SplineComponent->GetRotationAtTime(SecondsSinceStart, ESplineCoordinateSpace::World);
Rotation.Pitch = 0;
Rotation.Roll = 0;
Pawn->Controller->SetControlRotation(Rotation);
Pawn->SetActorLocationAndRotation(Location, Rotation);
}
else
{
CameraRideEnded();
}
}
void APointOfInterestManager::CameraRideEnded()
{
IsRidingCamera = false;
VisitPointOfInterestByIndex(GetPointOfInterestCount() - 1);
}