Files
integration/Source/Integration/PlayerControllerBase.cpp

170 lines
4.5 KiB
C++
Raw Normal View History

#include "PlayerControllerBase.h"
#include "Common.h"
#include "Tangible.h"
#include "TangibleManager.h"
#include "Components/InputComponent.h"
#include "Engine/LevelScriptActor.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
AlxPlayerControllerBase *AlxPlayerControllerBase::FromContext(const UObject *Context)
{
APlayerController *PC = Context->GetWorld()->GetFirstPlayerController();
AlxPlayerControllerBase *Result = Cast<AlxPlayerControllerBase>(PC);
if (Result == nullptr)
{
UE_LOG(LogLuprexIntegration, Fatal, TEXT("Not currently using a Luprex Player Controller."));
}
return Result;
}
const FHitResult &AlxPlayerControllerBase::GetLookAt(const UObject *Context)
{
return FromContext(Context)->CurrentLookAt;
}
const AActor *AlxPlayerControllerBase::GetLookAtActor(const UObject *Context)
{
return FromContext(Context)->CurrentLookAt.GetActor();
}
void AlxPlayerControllerBase::SetLookAt(const UObject *Context, const FHitResult &HitResult)
{
AlxPlayerControllerBase *PC = FromContext(Context);
if (PC->CurrentLookAt.HitObjectHandle != HitResult.HitObjectHandle)
{
PC->MustCallLookAtChanged = true;
}
PC->CurrentLookAt = HitResult;
}
void AlxPlayerControllerBase::SetLookAtChanged(const UObject *Context)
{
AlxPlayerControllerBase *PC = FromContext(Context);
PC->MustCallLookAtChanged = true;
}
FVector2D AlxPlayerControllerBase::GetLookAtPixel(const UObject *Context)
{
AlxPlayerControllerBase *PC = FromContext(Context);
FVector2D ScreenPosition;
if (!UGameplayStatics::ProjectWorldToScreen(PC, PC->CurrentLookAt.Location, ScreenPosition, false))
{
return FVector2D();
}
return ScreenPosition;
}
void AlxPlayerControllerBase::PushInputComponent(UInputComponent* InInputComponent)
{
if (InInputComponent)
{
CurrentInputStack.RemoveSingle(InInputComponent);
CurrentInputStack.Add(InInputComponent);
}
}
bool AlxPlayerControllerBase::PopInputComponent(UInputComponent* InInputComponent)
{
if (InInputComponent)
{
if (CurrentInputStack.RemoveSingle(InInputComponent) > 0)
{
InInputComponent->ClearBindingValues();
return true;
}
}
return false;
}
void AlxPlayerControllerBase::BuildInputStack(TArray<UInputComponent*>& InputStack)
{
// Controlled pawn gets last dibs on the input stack
APawn* ControlledPawn = GetPawnOrSpectator();
if (ControlledPawn)
{
if (ControlledPawn->InputEnabled())
{
// Get the explicit input component that is created upon Pawn possession. This one gets last dibs.
if (ControlledPawn->InputComponent)
{
InputStack.Push(ControlledPawn->InputComponent);
}
// See if there is another InputComponent that was added to the Pawn's components array (possibly by script).
for (UActorComponent* ActorComponent : ControlledPawn->GetComponents())
{
UInputComponent* PawnInputComponent = Cast<UInputComponent>(ActorComponent);
if (PawnInputComponent && PawnInputComponent != ControlledPawn->InputComponent)
{
InputStack.Push(PawnInputComponent);
}
}
}
}
// LevelScriptActors are put on the stack next
for (ULevel* Level : GetWorld()->GetLevels())
{
ALevelScriptActor* ScriptActor = Level->GetLevelScriptActor();
if (ScriptActor)
{
if (ScriptActor->InputEnabled() && ScriptActor->InputComponent)
{
InputStack.Push(ScriptActor->InputComponent);
}
}
}
if (InputEnabled())
{
InputStack.Push(InputComponent);
}
// Sort the components first by bBlockInput, then by
// priority. We don't touch the original array, because
// we want to preserve information about which component
// was pushed last.
TArray<UInputComponent*, TInlineAllocator<20>> Pushed;
for (int32 Idx = 0; Idx < CurrentInputStack.Num(); ++Idx)
{
UInputComponent* IC = CurrentInputStack[Idx].Get();
if (IsValid(IC))
{
Pushed.Add(IC);
}
else
{
CurrentInputStack.RemoveAt(Idx--);
}
}
Pushed.StableSort([](const UInputComponent& A, const UInputComponent& B)
{
if (A.bBlockInput != B.bBlockInput) return !A.bBlockInput;
return A.Priority < B.Priority;
});
InputStack.Append(Pushed);
}
void AlxPlayerControllerBase::UpdateLookAt()
{
UlxTangibleManager *TM = GetGameInstance()->GetSubsystem<UlxTangibleManager>();
if (TM == nullptr) return;
UlxTangible *Possessed = TM->GetPossessedTangible();
if (Possessed == nullptr) return;
APawn *Pawn = GetPawn();
if (Pawn == nullptr) return;
2026-03-12 19:12:37 -04:00
if (Possessed->GetActor() != Cast<AActor>(Pawn)) return;
if (PlayerCameraManager == nullptr) return;
CalculateLookAt();
if (MustCallLookAtChanged)
{
MustCallLookAtChanged = false;
LookAtChanged();
}
}