183 lines
5.0 KiB
C++
183 lines
5.0 KiB
C++
#include "PlayerControllerBase.h"
|
|
#include "Common.h"
|
|
#include "Tangible.h"
|
|
#include "TangibleManager.h"
|
|
#include "Kismet/GameplayStatics.h"
|
|
#include "Engine/GameInstance.h"
|
|
#include "Engine/GameViewportClient.h"
|
|
#include "Framework/Application/SlateApplication.h"
|
|
#include "Widgets/SViewport.h"
|
|
#include "Slate/SObjectWidget.h"
|
|
|
|
FString AlxPlayerControllerBase::GetUserWidgetName(SWidget *W)
|
|
{
|
|
while (W)
|
|
{
|
|
if (W->GetType() == FName("SObjectWidget"))
|
|
{
|
|
UUserWidget *UW = static_cast<SObjectWidget*>(W)->GetWidgetObject();
|
|
if (UW) return UW->GetClass()->GetName();
|
|
}
|
|
W = W->GetParentWidget().Get();
|
|
}
|
|
return TEXT("Unknown Widget");
|
|
}
|
|
|
|
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::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
HotkeyInputComponent = NewObject<UInputComponent>(this);
|
|
HotkeyInputComponent->bBlockInput = false;
|
|
PushInputComponent(HotkeyInputComponent);
|
|
}
|
|
|
|
void AlxPlayerControllerBase::UpdateEventDispatch()
|
|
{
|
|
EventRequests.GarbageCollect();
|
|
|
|
// If we're in GameOnly mode, check that focus is still on the viewport.
|
|
if (CurrentInputMode == InputMode::GameOnly)
|
|
{
|
|
UGameViewportClient *GVC = GetWorld() ? GetWorld()->GetGameViewport() : nullptr;
|
|
if (GVC)
|
|
{
|
|
TSharedPtr<SViewport> ViewportWidget = GVC->GetGameViewportWidget();
|
|
if (ViewportWidget.IsValid())
|
|
{
|
|
TSharedPtr<SWidget> Focused = FSlateApplication::Get().GetKeyboardFocusedWidget();
|
|
if (Focused.Get() != ViewportWidget.Get())
|
|
{
|
|
UE_LOG(LogLuprexIntegration, Error, TEXT("In GameOnly mode, keyboard focus must stay on viewport, but was stolen by: %s. Restoring."), *GetUserWidgetName(Focused.Get()));
|
|
EventRequests.SetDirty();
|
|
}
|
|
if (!ViewportWidget->HasMouseCapture())
|
|
{
|
|
UE_LOG(LogLuprexIntegration, Error, TEXT("In GameOnly mode, viewport must have mouse capture, but lost it. Restoring."));
|
|
EventRequests.SetDirty();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!EventRequests.IsDirty()) return;
|
|
EventRequests.ClearDirty();
|
|
|
|
CurrentInputMode = EventRequests.GetRequestedMode();
|
|
const TArray<FlxEventRequest> &Requests = EventRequests.GetRequests();
|
|
|
|
if (CurrentInputMode == InputMode::UIOnly)
|
|
{
|
|
SetInputMode(FInputModeUIOnly().SetWidgetToFocus(Requests[0].Widget->GetCachedWidget()));
|
|
}
|
|
else
|
|
{
|
|
SetInputMode(FInputModeGameOnly());
|
|
|
|
HotkeyInputComponent->KeyBindings.Empty();
|
|
TSet<FKey> BoundKeys;
|
|
for (const FlxEventRequest &Req : Requests)
|
|
{
|
|
for (const FKey &Key : Req.Hotkeys)
|
|
{
|
|
if (!BoundKeys.Contains(Key))
|
|
{
|
|
BoundKeys.Add(Key);
|
|
HotkeyInputComponent->BindKey(Key, IE_Pressed, this, &AlxPlayerControllerBase::ForwardKeyEvent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void AlxPlayerControllerBase::ForwardKeyEvent(FKey Key)
|
|
{
|
|
// TODO: implement
|
|
}
|
|
|
|
|
|
void AlxPlayerControllerBase::RequestEvents(const FlxEventRequest &Request)
|
|
{
|
|
if (!FlxEventRequests::SanityCheck(Request)) return;
|
|
AlxPlayerControllerBase *PC = FromContext(Request.Widget);
|
|
PC->EventRequests.Request(Request);
|
|
}
|
|
|
|
void AlxPlayerControllerBase::UnRequestEvents(UUserWidget *Widget)
|
|
{
|
|
if (Widget == nullptr)
|
|
{
|
|
UE_LOG(LogLuprexIntegration, Error, TEXT("UnRequestEvents called with null widget."));
|
|
return;
|
|
}
|
|
AlxPlayerControllerBase *PC = FromContext(Widget);
|
|
PC->EventRequests.Remove(Widget);
|
|
}
|
|
|
|
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;
|
|
if (Possessed->GetActor() != Cast<AActor>(Pawn)) return;
|
|
if (PlayerCameraManager == nullptr) return;
|
|
|
|
CalculateLookAt();
|
|
|
|
if (MustCallLookAtChanged)
|
|
{
|
|
MustCallLookAtChanged = false;
|
|
LookAtChanged();
|
|
}
|
|
}
|