#pragma once #include "CoreMinimal.h" #include "Engine/HitResult.h" #include "GameFramework/PlayerController.h" #include "UObject/ObjectKey.h" #include "PlayerControllerBase.generated.h" class UlxRootCanvasPanel; class UWidget; UCLASS(BlueprintType, Blueprintable) class INTEGRATION_API AlxPlayerControllerBase : public APlayerController { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static void SetLookAt(const UObject *Context, const FHitResult &HitResult); UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static const FHitResult &GetLookAt(const UObject *Context); UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static const AActor *GetLookAtActor(const UObject *Context); UFUNCTION(BlueprintPure, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static FVector2D GetLookAtPixel(const UObject *Context); UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Look-At Detection") static void SetLookAtChanged(const UObject *Context); // Blueprint events UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") void CalculateLookAt(); UFUNCTION(BlueprintImplementableEvent, Category = "Luprex|Look-At Detection") void LookAtChanged(); // Called by GameMode each tick. void UpdateLookAt(); // Called by GameMode each tick. GCs dead requests and will // eventually reconcile focus, pointer, and capture state. void UpdateInputMode(); virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; private: FDelegateHandle FocusChangingHandle; void HandleFocusChanging( const struct FFocusEvent &FocusEvent, const class FWeakWidgetPath &OldPath, const TSharedPtr &OldFocusedWidget, const class FWidgetPath &NewPath, const TSharedPtr &NewFocusedWidget); public: virtual void BuildInputStack(TArray& InputStack) override; // Read UUserWidget::InputComponent via reflection. The field is // protected and has no public accessor; this reaches through the // FProperty so we always see the current value without caching it. static class UInputComponent* GetWidgetInputComponent(class UUserWidget *Widget); // Restore focus back to the window that is in front, if it wants focus. UFUNCTION(BlueprintCallable, meta = (WorldContext = "Context"), Category = "Luprex|Root Canvas") static void RestoreFocusToFrontWidget(const UObject *Context); // Add a widget to the root canvas at ZOrder 0 with default slot flags. UFUNCTION(BlueprintCallable, Category = "Luprex|Root Canvas", meta = (DefaultToSelf = "Widget", HideSelfPin = "true")) static void AddWidgetToRoot(class UUserWidget *Widget); // Get the player controller, cast to AlxPlayerControllerBase. static AlxPlayerControllerBase *FromContext(const UObject *Context); UPROPERTY() FHitResult CurrentLookAt; // The last widget whose focus request was granted. TObjectKey LastWidgetGrantedFocus; // The single top-level UUserWidget added to the viewport. All // top-level UI widgets are children of RootCanvas inside it. UPROPERTY() UUserWidget *RootWidget = nullptr; // The root canvas panel inside RootWidget. Children of this // canvas are the top-level widgets; their slots carry both // layout and input-mode configuration. UPROPERTY() UlxRootCanvasPanel *RootCanvas = nullptr; // The viewport client uses this to notify us that the user // clicked on a focusable widget. void ClickToFocus(TSharedRef Widget); private: TWeakPtr ClickToFocusTarget; public: bool MustCallLookAtChanged = false; };