搬了lyra的hudlayout
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/CancellableAsyncAction.h"
|
||||
#include "UObject/SoftObjectPtr.h"
|
||||
|
||||
#include "AsyncAction_CreateWidgetAsync.generated.h"
|
||||
|
||||
class APlayerController;
|
||||
class UGameInstance;
|
||||
class UUserWidget;
|
||||
class UWorld;
|
||||
struct FFrame;
|
||||
struct FStreamableHandle;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCreateWidgetAsyncDelegate, UUserWidget*, UserWidget);
|
||||
|
||||
/**
|
||||
* Load the widget class asynchronously, the instance the widget after the loading completes, and return it on OnComplete.
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class COMMONGAME_API UAsyncAction_CreateWidgetAsync : public UCancellableAsyncAction
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
virtual void Cancel() override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta=(WorldContext = "WorldContextObject", BlueprintInternalUseOnly="true"))
|
||||
static UAsyncAction_CreateWidgetAsync* CreateWidgetAsync(UObject* WorldContextObject, TSoftClassPtr<UUserWidget> UserWidgetSoftClass, APlayerController* OwningPlayer, bool bSuspendInputUntilComplete = true);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FCreateWidgetAsyncDelegate OnComplete;
|
||||
|
||||
private:
|
||||
|
||||
void OnWidgetLoaded();
|
||||
|
||||
FName SuspendInputToken;
|
||||
TWeakObjectPtr<APlayerController> OwningPlayer;
|
||||
TWeakObjectPtr<UWorld> World;
|
||||
TWeakObjectPtr<UGameInstance> GameInstance;
|
||||
bool bSuspendInputUntilComplete;
|
||||
TSoftClassPtr<UUserWidget> UserWidgetSoftClass;
|
||||
TSharedPtr<FStreamableHandle> StreamingHandle;
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/CancellableAsyncAction.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "UObject/SoftObjectPtr.h"
|
||||
|
||||
#include "AsyncAction_PushContentToLayerForPlayer.generated.h"
|
||||
|
||||
class APlayerController;
|
||||
class UCommonActivatableWidget;
|
||||
class UObject;
|
||||
struct FFrame;
|
||||
struct FStreamableHandle;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPushContentToLayerForPlayerAsyncDelegate, UCommonActivatableWidget*, UserWidget);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(BlueprintType)
|
||||
class COMMONGAME_API UAsyncAction_PushContentToLayerForPlayer : public UCancellableAsyncAction
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
virtual void Cancel() override;
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta=(WorldContext = "WorldContextObject", BlueprintInternalUseOnly="true"))
|
||||
static UAsyncAction_PushContentToLayerForPlayer* PushContentToLayerForPlayer(APlayerController* OwningPlayer, UPARAM(meta = (AllowAbstract=false)) TSoftClassPtr<UCommonActivatableWidget> WidgetClass, UPARAM(meta = (Categories = "UI.Layer")) FGameplayTag LayerName, bool bSuspendInputUntilComplete = true);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
public:
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FPushContentToLayerForPlayerAsyncDelegate BeforePush;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FPushContentToLayerForPlayerAsyncDelegate AfterPush;
|
||||
|
||||
private:
|
||||
|
||||
FGameplayTag LayerName;
|
||||
bool bSuspendInputUntilComplete = false;
|
||||
TWeakObjectPtr<APlayerController> OwningPlayerPtr;
|
||||
TSoftClassPtr<UCommonActivatableWidget> WidgetClass;
|
||||
|
||||
TSharedPtr<FStreamableHandle> StreamingHandle;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Kismet/BlueprintAsyncActionBase.h"
|
||||
|
||||
#include "UObject/ObjectPtr.h"
|
||||
#include "AsyncAction_ShowConfirmation.generated.h"
|
||||
|
||||
enum class ECommonMessagingResult : uint8;
|
||||
|
||||
class FText;
|
||||
class UCommonGameDialogDescriptor;
|
||||
class ULocalPlayer;
|
||||
struct FFrame;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCommonMessagingResultMCDelegate, ECommonMessagingResult, Result);
|
||||
|
||||
/**
|
||||
* Allows easily triggering an async confirmation dialog in blueprints that you can then wait on the result.
|
||||
*/
|
||||
UCLASS()
|
||||
class UAsyncAction_ShowConfirmation : public UBlueprintAsyncActionBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta = (BlueprintInternalUseOnly = "true", WorldContext = "InWorldContextObject"))
|
||||
static UAsyncAction_ShowConfirmation* ShowConfirmationYesNo(
|
||||
UObject* InWorldContextObject, FText Title, FText Message
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta = (BlueprintInternalUseOnly = "true", WorldContext = "InWorldContextObject"))
|
||||
static UAsyncAction_ShowConfirmation* ShowConfirmationOkCancel(
|
||||
UObject* InWorldContextObject, FText Title, FText Message
|
||||
);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, meta = (BlueprintInternalUseOnly = "true", WorldContext = "InWorldContextObject"))
|
||||
static UAsyncAction_ShowConfirmation* ShowConfirmationCustom(
|
||||
UObject* InWorldContextObject, UCommonGameDialogDescriptor* Descriptor
|
||||
);
|
||||
|
||||
virtual void Activate() override;
|
||||
|
||||
public:
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FCommonMessagingResultMCDelegate OnResult;
|
||||
|
||||
private:
|
||||
void HandleConfirmationResult(ECommonMessagingResult ConfirmationResult);
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UObject> WorldContextObject;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<ULocalPlayer> TargetLocalPlayer;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UCommonGameDialogDescriptor> Descriptor;
|
||||
};
|
||||
72
Plugins/CommonGame/Source/Public/CommonGameInstance.h
Normal file
72
Plugins/CommonGame/Source/Public/CommonGameInstance.h
Normal file
@@ -0,0 +1,72 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/GameInstance.h"
|
||||
|
||||
#include "CommonGameInstance.generated.h"
|
||||
|
||||
enum class ECommonUserAvailability : uint8;
|
||||
enum class ECommonUserPrivilege : uint8;
|
||||
|
||||
class FText;
|
||||
class UCommonUserInfo;
|
||||
class UCommonSession_SearchResult;
|
||||
struct FOnlineResultInformation;
|
||||
class ULocalPlayer;
|
||||
class USocialManager;
|
||||
class UObject;
|
||||
struct FFrame;
|
||||
struct FGameplayTag;
|
||||
|
||||
UCLASS(Abstract, Config = Game)
|
||||
class COMMONGAME_API UCommonGameInstance : public UGameInstance
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonGameInstance(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
/** Handles errors/warnings from CommonUser, can be overridden per game */
|
||||
UFUNCTION()
|
||||
virtual void HandleSystemMessage(FGameplayTag MessageType, FText Title, FText Message);
|
||||
|
||||
UFUNCTION()
|
||||
virtual void HandlePrivilegeChanged(const UCommonUserInfo* UserInfo, ECommonUserPrivilege Privilege, ECommonUserAvailability OldAvailability, ECommonUserAvailability NewAvailability);
|
||||
|
||||
/** Call to reset user and session state, usually because a player has been disconnected */
|
||||
virtual void ResetUserAndSessionState();
|
||||
|
||||
/**
|
||||
* Requested Session Flow
|
||||
* Something requests the user to join a specific session (for example, a platform overlay via OnUserRequestedSession).
|
||||
* This request is handled in SetRequestedSession.
|
||||
* Check if we can join the requested session immediately (CanJoinRequestedSession). If we can, join the requested session (JoinRequestedSession)
|
||||
* If not, cache the requested session and instruct the game to get into a state where the session can be joined (ResetGameAndJoinRequestedSession)
|
||||
*/
|
||||
/** Handles user accepting a session invite from an external source (for example, a platform overlay). Intended to be overridden per game. */
|
||||
virtual void OnUserRequestedSession(const FPlatformUserId& PlatformUserId, UCommonSession_SearchResult* InRequestedSession, const FOnlineResultInformation& RequestedSessionResult);
|
||||
|
||||
/** Get the requested session */
|
||||
UCommonSession_SearchResult* GetRequestedSession() const { return RequestedSession; }
|
||||
/** Set (or clear) the requested session. When this is set, the requested session flow begins. */
|
||||
virtual void SetRequestedSession(UCommonSession_SearchResult* InRequestedSession);
|
||||
/** Checks if the requested session can be joined. Can be overridden per game. */
|
||||
virtual bool CanJoinRequestedSession() const;
|
||||
/** Join the requested session */
|
||||
virtual void JoinRequestedSession();
|
||||
/** Get the game into a state to join the requested session */
|
||||
virtual void ResetGameAndJoinRequestedSession();
|
||||
|
||||
virtual int32 AddLocalPlayer(ULocalPlayer* NewPlayer, FPlatformUserId UserId) override;
|
||||
virtual bool RemoveLocalPlayer(ULocalPlayer* ExistingPlayer) override;
|
||||
virtual void Init() override;
|
||||
virtual void ReturnToMainMenu() override;
|
||||
|
||||
private:
|
||||
/** This is the primary player*/
|
||||
TWeakObjectPtr<ULocalPlayer> PrimaryPlayer;
|
||||
/** Session the player has requested to join */
|
||||
UPROPERTY()
|
||||
TObjectPtr<UCommonSession_SearchResult> RequestedSession;
|
||||
};
|
||||
51
Plugins/CommonGame/Source/Public/CommonLocalPlayer.h
Normal file
51
Plugins/CommonGame/Source/Public/CommonLocalPlayer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/LocalPlayer.h"
|
||||
|
||||
#include "CommonLocalPlayer.generated.h"
|
||||
|
||||
class APawn;
|
||||
class APlayerController;
|
||||
class APlayerState;
|
||||
class FViewport;
|
||||
class UObject;
|
||||
class UPrimaryGameLayout;
|
||||
struct FSceneViewProjectionData;
|
||||
|
||||
UCLASS(config=Engine, transient)
|
||||
class COMMONGAME_API UCommonLocalPlayer : public ULocalPlayer
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonLocalPlayer();
|
||||
|
||||
/** Called when the local player is assigned a player controller */
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FPlayerControllerSetDelegate, UCommonLocalPlayer* LocalPlayer, APlayerController* PlayerController);
|
||||
FPlayerControllerSetDelegate OnPlayerControllerSet;
|
||||
|
||||
/** Called when the local player is assigned a player state */
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FPlayerStateSetDelegate, UCommonLocalPlayer* LocalPlayer, APlayerState* PlayerState);
|
||||
FPlayerStateSetDelegate OnPlayerStateSet;
|
||||
|
||||
/** Called when the local player is assigned a player pawn */
|
||||
DECLARE_MULTICAST_DELEGATE_TwoParams(FPlayerPawnSetDelegate, UCommonLocalPlayer* LocalPlayer, APawn* Pawn);
|
||||
FPlayerPawnSetDelegate OnPlayerPawnSet;
|
||||
|
||||
FDelegateHandle CallAndRegister_OnPlayerControllerSet(FPlayerControllerSetDelegate::FDelegate Delegate);
|
||||
FDelegateHandle CallAndRegister_OnPlayerStateSet(FPlayerStateSetDelegate::FDelegate Delegate);
|
||||
FDelegateHandle CallAndRegister_OnPlayerPawnSet(FPlayerPawnSetDelegate::FDelegate Delegate);
|
||||
|
||||
public:
|
||||
virtual bool GetProjectionData(FViewport* Viewport, FSceneViewProjectionData& ProjectionData, int32 StereoViewIndex) const override;
|
||||
|
||||
bool IsPlayerViewEnabled() const { return bIsPlayerViewEnabled; }
|
||||
void SetIsPlayerViewEnabled(bool bInIsPlayerViewEnabled) { bIsPlayerViewEnabled = bInIsPlayerViewEnabled; }
|
||||
|
||||
UPrimaryGameLayout* GetRootUILayout() const;
|
||||
|
||||
private:
|
||||
bool bIsPlayerViewEnabled = true;
|
||||
};
|
||||
27
Plugins/CommonGame/Source/Public/CommonPlayerController.h
Normal file
27
Plugins/CommonGame/Source/Public/CommonPlayerController.h
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ModularPlayerController.h"
|
||||
|
||||
#include "CommonPlayerController.generated.h"
|
||||
|
||||
class APawn;
|
||||
class UObject;
|
||||
|
||||
UCLASS(config=Game)
|
||||
class COMMONGAME_API ACommonPlayerController : public AModularPlayerController
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
ACommonPlayerController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
||||
|
||||
virtual void ReceivedPlayer() override;
|
||||
virtual void SetPawn(APawn* InPawn) override;
|
||||
virtual void OnPossess(class APawn* APawn) override;
|
||||
virtual void OnUnPossess() override;
|
||||
|
||||
protected:
|
||||
virtual void OnRep_PlayerState() override;
|
||||
};
|
||||
228
Plugins/CommonGame/Source/Public/CommonPlayerInputKey.h
Normal file
228
Plugins/CommonGame/Source/Public/CommonPlayerInputKey.h
Normal file
@@ -0,0 +1,228 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommonUserWidget.h"
|
||||
#include "Fonts/SlateFontInfo.h"
|
||||
|
||||
#include "CommonPlayerInputKey.generated.h"
|
||||
|
||||
enum class ECommonInputType : uint8;
|
||||
|
||||
class APlayerController;
|
||||
class FPaintArgs;
|
||||
class FSlateRect;
|
||||
class FSlateWindowElementList;
|
||||
class FWidgetStyle;
|
||||
class UCommonLocalPlayer;
|
||||
class UMaterialInstanceDynamic;
|
||||
class UObject;
|
||||
struct FFrame;
|
||||
struct FGeometry;
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class ECommonKeybindForcedHoldStatus : uint8
|
||||
{
|
||||
NoForcedHold,
|
||||
ForcedHold,
|
||||
NeverShowHold
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FMeasuredText
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
FText GetText() const { return CachedText; }
|
||||
void SetText(const FText& InText);
|
||||
|
||||
FVector2D GetTextSize() const { return CachedTextSize; }
|
||||
FVector2D UpdateTextSize(const FSlateFontInfo &InFontInfo, float FontScale = 1.0f) const;
|
||||
|
||||
private:
|
||||
|
||||
FText CachedText;
|
||||
mutable FVector2D CachedTextSize;
|
||||
mutable bool bTextDirty = true;
|
||||
};
|
||||
|
||||
UCLASS(Abstract, BlueprintType, Blueprintable, meta = (DisableNativeTick))
|
||||
class COMMONGAME_API UCommonPlayerInputKey : public UCommonUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonPlayerInputKey(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
/** Update the key and associated display based on our current Boundaction */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void UpdateKeybindWidget();
|
||||
|
||||
/** Set the bound key for our keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetBoundKey(FKey NewBoundAction);
|
||||
|
||||
/** Set the bound action for our keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetBoundAction(FName NewBoundAction);
|
||||
|
||||
/** Force this keybind to be a hold keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget", meta=(DeprecatedFunction, DeprecationMessage = "Use SetForcedHoldKeybindStatus instead"))
|
||||
void SetForcedHoldKeybind(bool InForcedHoldKeybind);
|
||||
|
||||
/** Force this keybind to be a hold keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetForcedHoldKeybindStatus(ECommonKeybindForcedHoldStatus InForcedHoldKeybindStatus);
|
||||
|
||||
/** Force this keybind to be a hold keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetShowProgressCountDown(bool bShow);
|
||||
|
||||
/** Set the axis scale value for this keybind */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetAxisScale(const float NewValue) { AxisScale = NewValue; }
|
||||
|
||||
/** Set the preset name override value for this keybind. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
void SetPresetNameOverride(const FName NewValue) { PresetNameOverride = NewValue; }
|
||||
|
||||
/** Our current BoundAction */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Keybind Widget")
|
||||
FName BoundAction;
|
||||
|
||||
/** Scale to read when using an axis Mapping */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Keybind Widget")
|
||||
float AxisScale;
|
||||
|
||||
/** Key this widget is bound to set directly in blueprint. Used when we want to reference a specific key instead of an action. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Keybind Widget")
|
||||
FKey BoundKeyFallback;
|
||||
|
||||
/** Allows us to set the input type explicitly for the keybind widget. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Keybind Widget")
|
||||
ECommonInputType InputTypeOverride;
|
||||
|
||||
/** Allows us to set the preset name explicitly for the keybind widget. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Keybind Widget")
|
||||
FName PresetNameOverride;
|
||||
|
||||
/** Setting that can show this keybind as a hold or never show it as a hold (even if it is) */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Keybind Widget")
|
||||
ECommonKeybindForcedHoldStatus ForcedHoldKeybindStatus;
|
||||
|
||||
/** Called through a delegate when we start hold progress */
|
||||
UFUNCTION()
|
||||
void StartHoldProgress(FName HoldActionName, float HoldDuration);
|
||||
|
||||
/** Called through a delegate when we stop hold progress */
|
||||
UFUNCTION()
|
||||
void StopHoldProgress(FName HoldActionName, bool bCompletedSuccessfully);
|
||||
|
||||
/** Get whether this keybind is a hold action. */
|
||||
UFUNCTION(BlueprintCallable, Category = "Keybind Widget")
|
||||
bool IsHoldKeybind() const { return bIsHoldKeybind; }
|
||||
|
||||
UFUNCTION()
|
||||
bool IsBoundKeyValid() const { return BoundKey.IsValid(); }
|
||||
|
||||
protected:
|
||||
virtual void NativePreConstruct() override;
|
||||
virtual void NativeConstruct() override;
|
||||
virtual int32 NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry, const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId, const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const override;
|
||||
void RecalculateDesiredSize();
|
||||
|
||||
/** Overridden to destroy our MID */
|
||||
virtual void NativeDestruct() override;
|
||||
|
||||
/** Whether or not this keybind widget is currently set to be a hold keybind */
|
||||
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Keybind Widget", meta=(ScriptName = "IsHoldKeybindValue"))
|
||||
bool bIsHoldKeybind;
|
||||
|
||||
/** */
|
||||
UPROPERTY(Transient)
|
||||
bool bShowKeybindBorder;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FVector2D FrameSize;
|
||||
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Keybind Widget")
|
||||
bool bShowTimeCountDown;
|
||||
|
||||
/** Derived Key this widget is bound to */
|
||||
UPROPERTY(BlueprintReadOnly, Category = "Keybind Widget")
|
||||
FKey BoundKey;
|
||||
|
||||
/** Material for showing Progress */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Keybind Widget")
|
||||
FSlateBrush HoldProgressBrush;
|
||||
|
||||
/** The key bind text border. */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Keybind Widget")
|
||||
FSlateBrush KeyBindTextBorder;
|
||||
|
||||
/** Should this keybinding widget display information that it is currently unbound? */
|
||||
UPROPERTY(EditAnywhere, Category = "Keybind Widget")
|
||||
bool bShowUnboundStatus = false;
|
||||
|
||||
/** The font to apply at each size */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Font")
|
||||
FSlateFontInfo KeyBindTextFont;
|
||||
|
||||
/** The font to apply at each size */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Font")
|
||||
FSlateFontInfo CountdownTextFont;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FMeasuredText CountdownText;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FMeasuredText KeybindText;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FMargin KeybindTextPadding;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FVector2D KeybindFrameMinimumSize;
|
||||
|
||||
/** The material parameter name for hold percentage in the HoldKeybindImage */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Keybind Widget")
|
||||
FName PercentageMaterialParameterName;
|
||||
|
||||
/** MID for the progress percentage */
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UMaterialInstanceDynamic> ProgressPercentageMID;
|
||||
|
||||
virtual void NativeOnInitialized() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Synchronizes the hold progress to whatever is currently set in the
|
||||
* owning player controller.
|
||||
*/
|
||||
void SyncHoldProgress();
|
||||
|
||||
/** Called for updating the HoldKeybindImage during a hold keybind */
|
||||
void UpdateHoldProgress();
|
||||
|
||||
/** Called when we want to set up this keybind widget as a hold keybind */
|
||||
void SetupHoldKeybind();
|
||||
|
||||
void ShowHoldBackPlate();
|
||||
|
||||
void HandlePlayerControllerSet(UCommonLocalPlayer* LocalPlayer, APlayerController* PlayerController);
|
||||
|
||||
/** Time when we started using a hold keybind */
|
||||
float HoldKeybindStartTime = 0;
|
||||
|
||||
/** How long, in seconds, we will be doing a hold keybind */
|
||||
float HoldKeybindDuration = 0;
|
||||
|
||||
bool bDrawProgress = false;
|
||||
bool bDrawBrushForKey = false;
|
||||
bool bDrawCountdownText = false;
|
||||
bool bWaitingForPlayerController = false;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
FSlateBrush CachedKeyBrush;
|
||||
};
|
||||
62
Plugins/CommonGame/Source/Public/CommonUIExtensions.h
Normal file
62
Plugins/CommonGame/Source/Public/CommonUIExtensions.h
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Kismet/BlueprintFunctionLibrary.h"
|
||||
#include "UObject/SoftObjectPtr.h"
|
||||
|
||||
#include "CommonUIExtensions.generated.h"
|
||||
|
||||
enum class ECommonInputType : uint8;
|
||||
template <typename T> class TSubclassOf;
|
||||
|
||||
class APlayerController;
|
||||
class UCommonActivatableWidget;
|
||||
class ULocalPlayer;
|
||||
class UObject;
|
||||
class UUserWidget;
|
||||
struct FFrame;
|
||||
struct FGameplayTag;
|
||||
|
||||
UCLASS()
|
||||
class COMMONGAME_API UCommonUIExtensions : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonUIExtensions() { }
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category = "Global UI Extensions", meta = (WorldContext = "WidgetContextObject"))
|
||||
static ECommonInputType GetOwningPlayerInputType(const UUserWidget* WidgetContextObject);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category = "Global UI Extensions", meta = (WorldContext = "WidgetContextObject"))
|
||||
static bool IsOwningPlayerUsingTouch(const UUserWidget* WidgetContextObject);
|
||||
|
||||
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category = "Global UI Extensions", meta = (WorldContext = "WidgetContextObject"))
|
||||
static bool IsOwningPlayerUsingGamepad(const UUserWidget* WidgetContextObject);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static UCommonActivatableWidget* PushContentToLayer_ForPlayer(const ULocalPlayer* LocalPlayer, UPARAM(meta = (Categories = "UI.Layer")) FGameplayTag LayerName, UPARAM(meta = (AllowAbstract = false)) TSubclassOf<UCommonActivatableWidget> WidgetClass);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static void PushStreamedContentToLayer_ForPlayer(const ULocalPlayer* LocalPlayer, UPARAM(meta = (Categories = "UI.Layer")) FGameplayTag LayerName, UPARAM(meta = (AllowAbstract = false)) TSoftClassPtr<UCommonActivatableWidget> WidgetClass);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static void PopContentFromLayer(UCommonActivatableWidget* ActivatableWidget);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static ULocalPlayer* GetLocalPlayerFromController(APlayerController* PlayerController);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static FName SuspendInputForPlayer(APlayerController* PlayerController, FName SuspendReason);
|
||||
|
||||
static FName SuspendInputForPlayer(ULocalPlayer* LocalPlayer, FName SuspendReason);
|
||||
|
||||
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category = "Global UI Extensions")
|
||||
static void ResumeInputForPlayer(APlayerController* PlayerController, FName SuspendToken);
|
||||
|
||||
static void ResumeInputForPlayer(ULocalPlayer* LocalPlayer, FName SuspendToken);
|
||||
|
||||
private:
|
||||
static int32 InputSuspensions;
|
||||
};
|
||||
50
Plugins/CommonGame/Source/Public/GameUIManagerSubsystem.h
Normal file
50
Plugins/CommonGame/Source/Public/GameUIManagerSubsystem.h
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Subsystems/GameInstanceSubsystem.h"
|
||||
#include "UObject/SoftObjectPtr.h"
|
||||
|
||||
#include "GameUIManagerSubsystem.generated.h"
|
||||
|
||||
class FSubsystemCollectionBase;
|
||||
class UCommonLocalPlayer;
|
||||
class UGameUIPolicy;
|
||||
class UObject;
|
||||
|
||||
/**
|
||||
* This manager is intended to be replaced by whatever your game needs to
|
||||
* actually create, so this class is abstract to prevent it from being created.
|
||||
*
|
||||
* If you just need the basic functionality you will start by sublcassing this
|
||||
* subsystem in your own game.
|
||||
*/
|
||||
UCLASS(Abstract, config = Game)
|
||||
class COMMONGAME_API UGameUIManagerSubsystem : public UGameInstanceSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGameUIManagerSubsystem() { }
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
|
||||
|
||||
const UGameUIPolicy* GetCurrentUIPolicy() const { return CurrentPolicy; }
|
||||
UGameUIPolicy* GetCurrentUIPolicy() { return CurrentPolicy; }
|
||||
|
||||
virtual void NotifyPlayerAdded(UCommonLocalPlayer* LocalPlayer);
|
||||
virtual void NotifyPlayerRemoved(UCommonLocalPlayer* LocalPlayer);
|
||||
virtual void NotifyPlayerDestroyed(UCommonLocalPlayer* LocalPlayer);
|
||||
|
||||
protected:
|
||||
void SwitchToPolicy(UGameUIPolicy* InPolicy);
|
||||
|
||||
private:
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UGameUIPolicy> CurrentPolicy = nullptr;
|
||||
|
||||
UPROPERTY(config, EditAnywhere)
|
||||
TSoftClassPtr<UGameUIPolicy> DefaultUIPolicyClass;
|
||||
};
|
||||
103
Plugins/CommonGame/Source/Public/GameUIPolicy.h
Normal file
103
Plugins/CommonGame/Source/Public/GameUIPolicy.h
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Engine/World.h"
|
||||
|
||||
#include "GameUIPolicy.generated.h"
|
||||
|
||||
class UCommonLocalPlayer;
|
||||
class UGameUIManagerSubsystem;
|
||||
class ULocalPlayer;
|
||||
class UPrimaryGameLayout;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UENUM()
|
||||
enum class ELocalMultiplayerInteractionMode : uint8
|
||||
{
|
||||
// Fullscreen viewport for the primary player only, regardless of the other player's existence
|
||||
PrimaryOnly,
|
||||
|
||||
// Fullscreen viewport for one player, but players can swap control over who's is displayed and who's is dormant
|
||||
SingleToggle,
|
||||
|
||||
// Viewports displayed simultaneously for both players
|
||||
Simultaneous
|
||||
};
|
||||
|
||||
USTRUCT()
|
||||
struct FRootViewportLayoutInfo
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<ULocalPlayer> LocalPlayer = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UPrimaryGameLayout> RootLayout = nullptr;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
bool bAddedToViewport = false;
|
||||
|
||||
FRootViewportLayoutInfo() {}
|
||||
FRootViewportLayoutInfo(ULocalPlayer* InLocalPlayer, UPrimaryGameLayout* InRootLayout, bool bIsInViewport)
|
||||
: LocalPlayer(InLocalPlayer)
|
||||
, RootLayout(InRootLayout)
|
||||
, bAddedToViewport(bIsInViewport)
|
||||
{}
|
||||
|
||||
bool operator==(const ULocalPlayer* OtherLocalPlayer) const { return LocalPlayer == OtherLocalPlayer; }
|
||||
};
|
||||
|
||||
UCLASS(Abstract, Blueprintable, Within = GameUIManagerSubsystem)
|
||||
class COMMONGAME_API UGameUIPolicy : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
template <typename GameUIPolicyClass = UGameUIPolicy>
|
||||
static GameUIPolicyClass* GetGameUIPolicyAs(const UObject* WorldContextObject)
|
||||
{
|
||||
return Cast<GameUIPolicyClass>(GetGameUIPolicy(WorldContextObject));
|
||||
}
|
||||
|
||||
static UGameUIPolicy* GetGameUIPolicy(const UObject* WorldContextObject);
|
||||
|
||||
public:
|
||||
virtual UWorld* GetWorld() const override;
|
||||
UGameUIManagerSubsystem* GetOwningUIManager() const;
|
||||
UPrimaryGameLayout* GetRootLayout(const UCommonLocalPlayer* LocalPlayer) const;
|
||||
|
||||
ELocalMultiplayerInteractionMode GetLocalMultiplayerInteractionMode() const { return LocalMultiplayerInteractionMode; }
|
||||
|
||||
void RequestPrimaryControl(UPrimaryGameLayout* Layout);
|
||||
|
||||
protected:
|
||||
void AddLayoutToViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout);
|
||||
void RemoveLayoutFromViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout);
|
||||
|
||||
virtual void OnRootLayoutAddedToViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout);
|
||||
virtual void OnRootLayoutRemovedFromViewport(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout);
|
||||
virtual void OnRootLayoutReleased(UCommonLocalPlayer* LocalPlayer, UPrimaryGameLayout* Layout);
|
||||
|
||||
void CreateLayoutWidget(UCommonLocalPlayer* LocalPlayer);
|
||||
TSubclassOf<UPrimaryGameLayout> GetLayoutWidgetClass(UCommonLocalPlayer* LocalPlayer);
|
||||
|
||||
private:
|
||||
ELocalMultiplayerInteractionMode LocalMultiplayerInteractionMode = ELocalMultiplayerInteractionMode::PrimaryOnly;
|
||||
|
||||
UPROPERTY(EditAnywhere)
|
||||
TSoftClassPtr<UPrimaryGameLayout> LayoutClass;
|
||||
|
||||
UPROPERTY(Transient)
|
||||
TArray<FRootViewportLayoutInfo> RootViewportLayouts;
|
||||
|
||||
private:
|
||||
void NotifyPlayerAdded(UCommonLocalPlayer* LocalPlayer);
|
||||
void NotifyPlayerRemoved(UCommonLocalPlayer* LocalPlayer);
|
||||
void NotifyPlayerDestroyed(UCommonLocalPlayer* LocalPlayer);
|
||||
|
||||
friend class UGameUIManagerSubsystem;
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommonActivatableWidget.h"
|
||||
#include "CommonMessagingSubsystem.h"
|
||||
|
||||
#include "CommonGameDialog.generated.h"
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FConfirmationDialogAction
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/** Required: The dialog option to provide. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
ECommonMessagingResult Result = ECommonMessagingResult::Unknown;
|
||||
|
||||
/** Optional: Display Text to use instead of the action name associated with the result. */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText OptionalDisplayText;
|
||||
|
||||
bool operator==(const FConfirmationDialogAction& Other) const
|
||||
{
|
||||
return Result == Other.Result &&
|
||||
OptionalDisplayText.EqualTo(Other.OptionalDisplayText);
|
||||
}
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class COMMONGAME_API UCommonGameDialogDescriptor : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static UCommonGameDialogDescriptor* CreateConfirmationOk(const FText& Header, const FText& Body);
|
||||
static UCommonGameDialogDescriptor* CreateConfirmationOkCancel(const FText& Header, const FText& Body);
|
||||
static UCommonGameDialogDescriptor* CreateConfirmationYesNo(const FText& Header, const FText& Body);
|
||||
static UCommonGameDialogDescriptor* CreateConfirmationYesNoCancel(const FText& Header, const FText& Body);
|
||||
|
||||
public:
|
||||
/** The header of the message to display */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText Header;
|
||||
|
||||
/** The body of the message to display */
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
FText Body;
|
||||
|
||||
/** The confirm button's input action to use. */
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
TArray<FConfirmationDialogAction> ButtonActions;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(Abstract)
|
||||
class COMMONGAME_API UCommonGameDialog : public UCommonActivatableWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonGameDialog();
|
||||
|
||||
virtual void SetupDialog(UCommonGameDialogDescriptor* Descriptor, FCommonMessagingResultDelegate ResultCallback);
|
||||
|
||||
virtual void KillDialog();
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Subsystems/LocalPlayerSubsystem.h"
|
||||
|
||||
#include "CommonMessagingSubsystem.generated.h"
|
||||
|
||||
class FSubsystemCollectionBase;
|
||||
class UCommonGameDialogDescriptor;
|
||||
class UObject;
|
||||
|
||||
/** Possible results from a dialog */
|
||||
UENUM(BlueprintType)
|
||||
enum class ECommonMessagingResult : uint8
|
||||
{
|
||||
/** The "yes" button was pressed */
|
||||
Confirmed,
|
||||
/** The "no" button was pressed */
|
||||
Declined,
|
||||
/** The "ignore/cancel" button was pressed */
|
||||
Cancelled,
|
||||
/** The dialog was explicitly killed (no user input) */
|
||||
Killed,
|
||||
Unknown UMETA(Hidden)
|
||||
};
|
||||
|
||||
DECLARE_DELEGATE_OneParam(FCommonMessagingResultDelegate, ECommonMessagingResult /* Result */);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
UCLASS(config = Game)
|
||||
class COMMONGAME_API UCommonMessagingSubsystem : public ULocalPlayerSubsystem
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UCommonMessagingSubsystem() { }
|
||||
|
||||
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
|
||||
virtual void Deinitialize() override;
|
||||
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
|
||||
|
||||
virtual void ShowConfirmation(UCommonGameDialogDescriptor* DialogDescriptor, FCommonMessagingResultDelegate ResultCallback = FCommonMessagingResultDelegate());
|
||||
virtual void ShowError(UCommonGameDialogDescriptor* DialogDescriptor, FCommonMessagingResultDelegate ResultCallback = FCommonMessagingResultDelegate());
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
137
Plugins/CommonGame/Source/Public/PrimaryGameLayout.h
Normal file
137
Plugins/CommonGame/Source/Public/PrimaryGameLayout.h
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CommonActivatableWidget.h"
|
||||
#include "CommonUIExtensions.h"
|
||||
#include "Engine/AssetManager.h"
|
||||
#include "Engine/StreamableManager.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "Widgets/CommonActivatableWidgetContainer.h" // IWYU pragma: keep
|
||||
|
||||
#include "PrimaryGameLayout.generated.h"
|
||||
|
||||
class APlayerController;
|
||||
class UClass;
|
||||
class UCommonActivatableWidgetContainerBase;
|
||||
class ULocalPlayer;
|
||||
class UObject;
|
||||
struct FFrame;
|
||||
|
||||
/**
|
||||
* The state of an async load operation for the UI.
|
||||
*/
|
||||
enum class EAsyncWidgetLayerState : uint8
|
||||
{
|
||||
Canceled,
|
||||
Initialize,
|
||||
AfterPush
|
||||
};
|
||||
|
||||
/**
|
||||
* The primary game UI layout of your game. This widget class represents how to layout, push and display all layers
|
||||
* of the UI for a single player. Each player in a split-screen game will receive their own primary game layout.
|
||||
*/
|
||||
UCLASS(Abstract, meta = (DisableNativeTick))
|
||||
class COMMONGAME_API UPrimaryGameLayout : public UCommonUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
static UPrimaryGameLayout* GetPrimaryGameLayoutForPrimaryPlayer(const UObject* WorldContextObject);
|
||||
static UPrimaryGameLayout* GetPrimaryGameLayout(APlayerController* PlayerController);
|
||||
static UPrimaryGameLayout* GetPrimaryGameLayout(ULocalPlayer* LocalPlayer);
|
||||
|
||||
public:
|
||||
UPrimaryGameLayout(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
/** A dormant root layout is collapsed and responds only to persistent actions registered by the owning player */
|
||||
void SetIsDormant(bool Dormant);
|
||||
bool IsDormant() const { return bIsDormant; }
|
||||
|
||||
public:
|
||||
template <typename ActivatableWidgetT = UCommonActivatableWidget>
|
||||
TSharedPtr<FStreamableHandle> PushWidgetToLayerStackAsync(FGameplayTag LayerName, bool bSuspendInputUntilComplete, TSoftClassPtr<UCommonActivatableWidget> ActivatableWidgetClass)
|
||||
{
|
||||
return PushWidgetToLayerStackAsync<ActivatableWidgetT>(LayerName, bSuspendInputUntilComplete, ActivatableWidgetClass, [](EAsyncWidgetLayerState, ActivatableWidgetT*) {});
|
||||
}
|
||||
|
||||
template <typename ActivatableWidgetT = UCommonActivatableWidget>
|
||||
TSharedPtr<FStreamableHandle> PushWidgetToLayerStackAsync(FGameplayTag LayerName, bool bSuspendInputUntilComplete, TSoftClassPtr<UCommonActivatableWidget> ActivatableWidgetClass, TFunction<void(EAsyncWidgetLayerState, ActivatableWidgetT*)> StateFunc)
|
||||
{
|
||||
static_assert(TIsDerivedFrom<ActivatableWidgetT, UCommonActivatableWidget>::IsDerived, "Only CommonActivatableWidgets can be used here");
|
||||
|
||||
static FName NAME_PushingWidgetToLayer("PushingWidgetToLayer");
|
||||
const FName SuspendInputToken = bSuspendInputUntilComplete ? UCommonUIExtensions::SuspendInputForPlayer(GetOwningPlayer(), NAME_PushingWidgetToLayer) : NAME_None;
|
||||
|
||||
FStreamableManager& StreamableManager = UAssetManager::Get().GetStreamableManager();
|
||||
TSharedPtr<FStreamableHandle> StreamingHandle = StreamableManager.RequestAsyncLoad(ActivatableWidgetClass.ToSoftObjectPath(), FStreamableDelegate::CreateWeakLambda(this,
|
||||
[this, LayerName, ActivatableWidgetClass, StateFunc, SuspendInputToken]()
|
||||
{
|
||||
UCommonUIExtensions::ResumeInputForPlayer(GetOwningPlayer(), SuspendInputToken);
|
||||
|
||||
ActivatableWidgetT* Widget = PushWidgetToLayerStack<ActivatableWidgetT>(LayerName, ActivatableWidgetClass.Get(), [StateFunc](ActivatableWidgetT& WidgetToInit) {
|
||||
StateFunc(EAsyncWidgetLayerState::Initialize, &WidgetToInit);
|
||||
});
|
||||
|
||||
StateFunc(EAsyncWidgetLayerState::AfterPush, Widget);
|
||||
})
|
||||
);
|
||||
|
||||
// Setup a cancel delegate so that we can resume input if this handler is canceled.
|
||||
StreamingHandle->BindCancelDelegate(FStreamableDelegate::CreateWeakLambda(this,
|
||||
[this, StateFunc, SuspendInputToken]()
|
||||
{
|
||||
UCommonUIExtensions::ResumeInputForPlayer(GetOwningPlayer(), SuspendInputToken);
|
||||
StateFunc(EAsyncWidgetLayerState::Canceled, nullptr);
|
||||
})
|
||||
);
|
||||
|
||||
return StreamingHandle;
|
||||
}
|
||||
|
||||
template <typename ActivatableWidgetT = UCommonActivatableWidget>
|
||||
ActivatableWidgetT* PushWidgetToLayerStack(FGameplayTag LayerName, UClass* ActivatableWidgetClass)
|
||||
{
|
||||
return PushWidgetToLayerStack<ActivatableWidgetT>(LayerName, ActivatableWidgetClass, [](ActivatableWidgetT&) {});
|
||||
}
|
||||
|
||||
template <typename ActivatableWidgetT = UCommonActivatableWidget>
|
||||
ActivatableWidgetT* PushWidgetToLayerStack(FGameplayTag LayerName, UClass* ActivatableWidgetClass, TFunctionRef<void(ActivatableWidgetT&)> InitInstanceFunc)
|
||||
{
|
||||
static_assert(TIsDerivedFrom<ActivatableWidgetT, UCommonActivatableWidget>::IsDerived, "Only CommonActivatableWidgets can be used here");
|
||||
|
||||
if (UCommonActivatableWidgetContainerBase* Layer = GetLayerWidget(LayerName))
|
||||
{
|
||||
return Layer->AddWidget<ActivatableWidgetT>(ActivatableWidgetClass, InitInstanceFunc);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Find the widget if it exists on any of the layers and remove it from the layer.
|
||||
void FindAndRemoveWidgetFromLayer(UCommonActivatableWidget* ActivatableWidget);
|
||||
|
||||
// Get the layer widget for the given layer tag.
|
||||
UCommonActivatableWidgetContainerBase* GetLayerWidget(FGameplayTag LayerName);
|
||||
|
||||
protected:
|
||||
/** Register a layer that widgets can be pushed onto. */
|
||||
UFUNCTION(BlueprintCallable, Category="Layer")
|
||||
void RegisterLayer(UPARAM(meta = (Categories = "UI.Layer")) FGameplayTag LayerTag, UCommonActivatableWidgetContainerBase* LayerWidget);
|
||||
|
||||
virtual void OnIsDormantChanged();
|
||||
|
||||
void OnWidgetStackTransitioning(UCommonActivatableWidgetContainerBase* Widget, bool bIsTransitioning);
|
||||
|
||||
private:
|
||||
bool bIsDormant = false;
|
||||
|
||||
// Lets us keep track of all suspended input tokens so that multiple async UIs can be loading and we correctly suspend
|
||||
// for the duration of all of them.
|
||||
TArray<FName> SuspendInputTokens;
|
||||
|
||||
// The registered layers for the primary layout.
|
||||
UPROPERTY(Transient, meta = (Categories = "UI.Layer"))
|
||||
TMap<FGameplayTag, TObjectPtr<UCommonActivatableWidgetContainerBase>> Layers;
|
||||
};
|
||||
Reference in New Issue
Block a user