第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "Engine/CancellableAsyncAction.h"
#include "UObject/SoftObjectPtr.h"
#include "GUIS_AsyncAction_CreateWidget.generated.h"
class APlayerController;
class UGameInstance;
class UUserWidget;
class UWorld;
struct FFrame;
struct FStreamableHandle;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGUIS_CreateWidgetSignature, UUserWidget *, UserWidget);
/**
* Load the widget class asynchronously, the instance the widget after the loading completes, and return it on OnComplete.
*/
UCLASS(BlueprintType)
class GENERICUISYSTEM_API UGUIS_AsyncAction_CreateWidget : public UCancellableAsyncAction
{
GENERATED_UCLASS_BODY()
public:
virtual void Cancel() override;
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"))
static UGUIS_AsyncAction_CreateWidget *CreateWidgetAsync(UObject *WorldContextObject, TSoftClassPtr<UUserWidget> UserWidgetSoftClass, APlayerController *OwningPlayer,
bool bSuspendInputUntilComplete = true);
virtual void Activate() override;
public:
UPROPERTY(BlueprintAssignable)
FGUIS_CreateWidgetSignature OnComplete;
private:
void OnWidgetLoaded();
FName SuspendInputToken;
TWeakObjectPtr<APlayerController> OwningPlayer;
TWeakObjectPtr<UWorld> World;
TWeakObjectPtr<UGameInstance> GameInstance;
bool bSuspendInputUntilComplete;
TSoftClassPtr<UUserWidget> UserWidgetSoftClass;
TSharedPtr<FStreamableHandle> StreamingHandle;
};

View File

@@ -0,0 +1,59 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "Engine/CancellableAsyncAction.h"
#include "GameplayTagContainer.h"
#include "UObject/SoftObjectPtr.h"
#include "GUIS_AsyncAction_PushContentToUILayer.generated.h"
class UGUIS_GameUILayout;
class APlayerController;
class UCommonActivatableWidget;
class UObject;
struct FFrame;
struct FStreamableHandle;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPushContentToLayerForPlayerAsyncDelegate, UCommonActivatableWidget *, UserWidget);
/**
*
*/
UCLASS(BlueprintType)
class GENERICUISYSTEM_API UGUIS_AsyncAction_PushContentToUILayer : public UCancellableAsyncAction
{
GENERATED_UCLASS_BODY()
virtual void Cancel() override;
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"))
static UGUIS_AsyncAction_PushContentToUILayer* PushContentToUILayer(UGUIS_GameUILayout* UILayout,
UPARAM(meta = (AllowAbstract = false))
TSoftClassPtr<UCommonActivatableWidget> WidgetClass,
UPARAM(meta = (Categories = "UI.Layer,GUIS.Layer"))
FGameplayTag LayerName, bool bSuspendInputUntilComplete = true);
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WorldContextObject", BlueprintInternalUseOnly = "true"))
static UGUIS_AsyncAction_PushContentToUILayer* PushContentToUILayerForPlayer(APlayerController* PlayerController,
UPARAM(meta = (AllowAbstract = false))
TSoftClassPtr<UCommonActivatableWidget> WidgetClass,
UPARAM(meta = (Categories = "UI.Layer,GUIS.Layer"))
FGameplayTag LayerName, bool bSuspendInputUntilComplete = true);
virtual void Activate() override;
UPROPERTY(BlueprintAssignable)
FPushContentToLayerForPlayerAsyncDelegate BeforePush;
UPROPERTY(BlueprintAssignable)
FPushContentToLayerForPlayerAsyncDelegate AfterPush;
private:
FGameplayTag LayerName;
bool bSuspendInputUntilComplete = false;
TWeakObjectPtr<APlayerController> OwningPlayerPtr;
TWeakObjectPtr<UGUIS_GameUILayout> RootLayout;
TSoftClassPtr<UCommonActivatableWidget> WidgetClass;
TSharedPtr<FStreamableHandle> StreamingHandle;
};

View File

@@ -0,0 +1,60 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "GameplayTagContainer.h"
#include "Engine/CancellableAsyncAction.h"
#include "UI/Modal/GUIS_GameModal.h"
#include "UObject/ObjectPtr.h"
#include "GUIS_AsyncAction_ShowModel.generated.h"
enum class EGGF_DialogMessagingResult : uint8;
class FText;
class ULocalPlayer;
struct FFrame;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGUIS_ModalResultSignature, FGameplayTag, Result);
/**
* Allows easily triggering an async confirmation dialog in blueprints that you can then wait on the result.
*/
UCLASS()
class UGUIS_AsyncAction_ShowModel : public UCancellableAsyncAction
{
GENERATED_UCLASS_BODY()
public:
// UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (BlueprintInternalUseOnly = "true", WorldContext = "InWorldContextObject"))
// static UGUIS_AsyncAction_ShowModel* ShowModal(UObject* InWorldContextObject, FGameplayTag ModalTag, UGUIS_ModalDefinition* ModalDefinition);
/**
* 给定一个Modal定义然后显示该Modal。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta = (BlueprintInternalUseOnly = "true", WorldContext = "InWorldContextObject"))
static UGUIS_AsyncAction_ShowModel* ShowModal(UObject* InWorldContextObject, TSoftClassPtr<UGUIS_ModalDefinition> ModalDefinition);
virtual void Activate() override;
public:
UPROPERTY(BlueprintAssignable)
FGUIS_ModalResultSignature OnModalAction;
private:
void HandleModalAction(FGameplayTag ModalActionTag);
UPROPERTY(Transient)
TObjectPtr<UObject> WorldContextObject;
// UPROPERTY(Transient)
// TObjectPtr<ULocalPlayer> TargetLocalPlayer;
UPROPERTY(Transient)
TObjectPtr<APlayerController> TargetPlayerController;
UPROPERTY(Transient)
TSubclassOf<UGUIS_GameModalWidget> ModalWidgetClass;
UPROPERTY(Transient)
TObjectPtr<const UGUIS_ModalDefinition> ModalDefinition;
};

View File

@@ -0,0 +1,71 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "GUIS_UIAction.generated.h"
class UGUIS_ModalDefinition;
class UGUIS_UIAction;
/**
* Base ui action for single data.
*/
UCLASS(Blueprintable, EditInlineNew, CollapseCategories, DefaultToInstanced, Abstract, Const)
class GENERICUISYSTEM_API UGUIS_UIAction : public UObject
{
GENERATED_UCLASS_BODY()
virtual UWorld* GetWorld() const override;
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
bool IsCompatible(const UObject* Data) const;
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
bool CanInvoke(const UObject* Data, APlayerController* PlayerController) const;
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
void InvokeAction(const UObject* Data, APlayerController* PlayerController) const;
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS|UIAction")
FText GetActionName() const;
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS|UIAction")
FName GetActionID() const;
const FDataTableRowHandle& GetInputActionData() const { return InputActionData; }
bool GetShouldDisplayInActionBar() const { return bShouldDisplayInActionBar; }
bool GetRequiresConfirmation() const { return bRequiresConfirmation; }
TSoftClassPtr<UGUIS_ModalDefinition> GetConfirmationModalClass() const { return ConfirmationModalClass; };
protected:
UFUNCTION(BlueprintNativeEvent, Category = "UIAction", meta = (DisplayName = "Is Compatible"))
bool IsCompatibleInternal(const UObject* Data) const;
UFUNCTION(BlueprintNativeEvent, Category = "UIAction", meta = (DisplayName = "Can Invoke"))
bool CanInvokeInternal(const UObject* Data, APlayerController* PlayerController) const;
UFUNCTION(BlueprintNativeEvent, Category = "UIAction", meta = (DisplayName = "Invoke Action"))
void InvokeActionInternal(const UObject* Data, APlayerController* PlayerController) const;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UIAction")
FText DisplayName;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UIAction")
FName ActionID;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "UIAction", meta = (RowType = "/Script/CommonUI.CommonInputActionDataBase"))
FDataTableRowHandle InputActionData;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UIAction")
bool bShouldDisplayInActionBar{true};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UIAction")
bool bRequiresConfirmation{true};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="UIAction", meta=(EditCondition="bRequiresConfirmation"))
TSoftClassPtr<UGUIS_ModalDefinition> ConfirmationModalClass{nullptr};
};

View File

@@ -0,0 +1,34 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Engine/DataAsset.h"
#include "GUIS_UIActionFactory.generated.h"
class UGUIS_UIAction;
/**
* 提供一种通用的方式为UI对象选择合适的可用操作。
*/
UCLASS(BlueprintType, Const)
class GENERICUISYSTEM_API UGUIS_UIActionFactory : public UDataAsset
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
TArray<UGUIS_UIAction*> FindAvailableUIActionsForData(const UObject* Data) const;
protected:
/**
* A list of potential actions for incoming data.
* 针对传入数据的潜在可用ui操作。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GUIS", Instanced, meta=(TitleProperty="ActionId"))
TArray<TObjectPtr<UGUIS_UIAction>> PotentialActions;
#if WITH_EDITOR
virtual EDataValidationResult IsDataValid(FDataValidationContext& Context) const override;
#endif
};

View File

@@ -0,0 +1,78 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonUserWidget.h"
#include "GameplayTagContainer.h"
#include "GUIS_UIAction.h"
#include "GUIS_UIActionWidget.generated.h"
class UGUIS_AsyncAction_ShowModel;
class UGUIS_UIActionFactory;
/**
* A widget which can associate data with register ui action dynamically based on passed-in data.
* @attention There's no visual for this widget.
* 此Widget可以关联一个数据并为其自动注册可用的输入事件。
*/
UCLASS(ClassGroup = GUIS, meta=(Category="Generic UI System"), AutoExpandCategories=("GUIS"))
class GENERICUISYSTEM_API UGUIS_UIActionWidget : public UCommonUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
void SetAssociatedData(UObject* Data);
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
void RegisterActions();
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
virtual void RegisterActionsWithFactory(TSoftObjectPtr<UGUIS_UIActionFactory> InActionFactory);
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
virtual void UnregisterActions();
UFUNCTION(BlueprintCallable, Category="GUIS|UIAction")
virtual void CancelAction();
//~ Begin UWidget
#if WITH_EDITOR
virtual const FText GetPaletteCategory() override;
#endif
//~ End UWidget interface
protected:
UFUNCTION()
virtual void HandleUIAction(const UGUIS_UIAction* Action);
UFUNCTION()
virtual void HandleModalAction(FGameplayTag ActionTag);
UPROPERTY()
TWeakObjectPtr<UObject> AssociatedData;
/**
* A factory to get available ui actions for associated data.
* 该数据资产用于针对关联数据返回所有可用的ui操作。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="UIAction")
TObjectPtr<UGUIS_UIActionFactory> ActionFactory;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FGUIS_HandleUIActionSignature, const UGUIS_UIAction*, ActionReference);
UPROPERTY(BlueprintAssignable, Category="UIAction")
FGUIS_HandleUIActionSignature OnHandleUIAction;
private:
TArray<FUIActionBindingHandle> ActionBindings;
UPROPERTY()
TObjectPtr<const UGUIS_UIAction> CurrentAction{nullptr};
UPROPERTY()
TObjectPtr<UGUIS_AsyncAction_ShowModel> ModalTask{nullptr};
};

View File

@@ -0,0 +1,75 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "GUIS_DetailSectionsBuilder.generated.h"
class UGUIS_ListEntryDetailSection;
class UGUIS_ListEntry;
/**
* Base class for customizing how detail sections are gathered for an object.
* 自定义如何为对象收集细节部分的基类。
*/
UCLASS(Abstract, Blueprintable, meta = (Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_DetailSectionsBuilder : public UDataAsset
{
GENERATED_BODY()
public:
/**
* Gathers detail section classes for the specified data.
* 为指定数据收集细节部分类。
* @param Data The data object. 数据对象。
* @return Array of detail section classes. 细节部分类数组。
*/
UFUNCTION(Blueprintable, BlueprintNativeEvent)
TArray<TSoftClassPtr<UGUIS_ListEntryDetailSection>> GatherDetailSections(const UObject* Data);
virtual TArray<TSoftClassPtr<UGUIS_ListEntryDetailSection>> GatherDetailSections_Implementation(const UObject* Data);
};
/**
* Structure for mapping object classes to detail section classes.
* 将对象类映射到细节部分类的结构。
*/
USTRUCT()
struct GENERICUISYSTEM_API FGUIS_EntryDetailsClassSections
{
GENERATED_BODY()
/**
* Array of detail section classes for an object class.
* 对象类的细节部分类数组。
*/
UPROPERTY(EditAnywhere, Category="GUIS")
TArray<TSoftClassPtr<UGUIS_ListEntryDetailSection>> Sections;
};
/**
* Concrete class for mapping object classes to detail sections.
* 将对象类映射到细节部分的实体类。
*/
UCLASS(NotBlueprintable)
class GENERICUISYSTEM_API UGUIS_DetailSectionBuilder_Class : public UGUIS_DetailSectionsBuilder
{
GENERATED_BODY()
public:
/**
* Gathers detail section classes for the specified data.
* 为指定数据收集细节部分类。
* @param Data The data object. 数据对象。
* @return Array of detail section classes. 细节部分类数组。
*/
virtual TArray<TSoftClassPtr<UGUIS_ListEntryDetailSection>> GatherDetailSections_Implementation(const UObject* Data) override;
protected:
/**
* Mapping of object classes to their detail section configurations.
* 对象类到其细节部分配置的映射。
*/
UPROPERTY(EditDefaultsOnly, Category="GUIS", meta = (AllowAbstract))
TMap<TSubclassOf<UObject>, FGUIS_EntryDetailsClassSections> SectionsForClasses;
};

View File

@@ -0,0 +1,20 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/IUserObjectListEntry.h"
#include "UI/Foundation/GUIS_ButtonBase.h"
#include "GUIS_ListEntry.generated.h"
class UGUIS_UIAction;
/**
* List entry widget representing an item in a ListView or TileView.
* 表示ListView或TileView中项的列表入口小部件。
*/
UCLASS(Abstract, meta = (Category = "Generic UI", DisableNativeTick))
class GENERICUISYSTEM_API UGUIS_ListEntry : public UGUIS_ButtonBase, public IUserObjectListEntry
{
GENERATED_BODY()
};

View File

@@ -0,0 +1,41 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonUserWidget.h"
#include "GUIS_ListEntryDetailSection.generated.h"
/**
* Detail section widget for composing a detail view.
* 组成细节视图的细节部分小部件。
*/
UCLASS(Abstract, meta = (Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_ListEntryDetailSection : public UCommonUserWidget
{
GENERATED_BODY()
public:
/**
* Sets the object represented by this detail section.
* 设置此细节部分表示的对象。
* @param ListItemObject The object to display. 要显示的对象。
*/
void SetListItemObject(UObject* ListItemObject);
protected:
/**
* Called when the list item object is set.
* 列表项对象设置时调用。
* @param ListItemObject The object being set. 设置的对象。
*/
virtual void NativeOnListItemObjectSet(UObject* ListItemObject);
/**
* Blueprint event for when the list item object is set.
* 列表项对象设置时的蓝图事件。
* @param ListItemObject The object being set. 设置的对象。
*/
UFUNCTION(BlueprintImplementableEvent)
void OnListItemObjectSet(UObject* ListItemObject);
};

View File

@@ -0,0 +1,109 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonUserWidget.h"
#include "Blueprint/UserWidgetPool.h"
#include "GUIS_ListEntryDetailView.generated.h"
class UGUIS_DetailSectionsBuilder;
class UGUIS_ListEntryDetailSection;
class UVerticalBox;
class UGUIS_WidgetFactory;
struct FStreamableHandle;
/**
* Detail view containing multiple sections to represent an item (any UObject).
* 包含多个细节部分的视图用于展示一个项任意UObject类型
*/
UCLASS(Abstract, meta=(Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_ListEntryDetailView : public UCommonUserWidget
{
GENERATED_BODY()
public:
/**
* Constructor for the detail view widget.
* 细节视图小部件构造函数。
*/
UGUIS_ListEntryDetailView(const FObjectInitializer& ObjectInitializer);
/**
* Sets the object represented by this detail view as data.
* 设置此细节视图表示的对象作为数据。
* @param InListItemObject The object to display. 要显示的对象。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void SetListItemObject(UObject* InListItemObject);
/**
* Sets the associated detail sections builder.
* 设置关联的细节部分构建器。
* @param NewBuilder The detail sections builder. 细节部分构建器。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void SetSectionsBuilder(UGUIS_DetailSectionsBuilder* NewBuilder);
/**
* Releases Slate resources.
* 释放Slate资源。
* @param bReleaseChildren Whether to release child resources. 是否释放子资源。
*/
virtual void ReleaseSlateResources(bool bReleaseChildren) override;
protected:
/**
* Called when the widget is constructed.
* 小部件构造时调用。
*/
virtual void NativeConstruct() override;
/**
* Called when the widget is initialized.
* 小部件初始化时调用。
*/
virtual void NativeOnInitialized() override;
/**
* Creates a detail section extension for the specified data.
* 为指定数据创建细节部分扩展。
* @param InData The data object. 数据对象。
* @param SectionClass The section widget class. 部分小部件类。
*/
void CreateDetailsExtension(UObject* InData, TSubclassOf<UGUIS_ListEntryDetailSection> SectionClass);
/**
* Detail sections builder for displaying data based on widget specifications.
* 根据小部件规格显示数据的细节部分构建器。
*/
UPROPERTY(EditAnywhere, Category="GUIS", meta = (AllowAbstract = false))
TObjectPtr<UGUIS_DetailSectionsBuilder> SectionsBuilder;
/**
* Pool for managing extension widgets.
* 管理扩展小部件的池。
*/
UPROPERTY(Transient)
FUserWidgetPool ExtensionWidgetPool;
/**
* Current object represented by the detail view.
* 细节视图当前表示的对象。
*/
UPROPERTY(Transient)
TObjectPtr<UObject> CurrentListItemObject;
/**
* Handle for streaming assets.
* 流式加载资产的句柄。
*/
TSharedPtr<FStreamableHandle> StreamingHandle;
private:
/**
* Vertical box for detail sections.
* 细节部分的垂直框。
*/
UPROPERTY(BlueprintReadOnly, Category="GUIS", meta = (BindWidget, BlueprintProtected = true, AllowPrivateAccess = true))
TObjectPtr<UVerticalBox> Box_DetailSections;
};

View File

@@ -0,0 +1,61 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonListView.h"
#include "GUIS_ListView.generated.h"
class UGUIS_WidgetFactory;
/**
* Extended ListView allowing dynamic selection of entry widget class via data asset.
* 通过数据资产动态选择入口小部件类的扩展ListView。
*/
UCLASS(Blueprintable, meta = (Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_ListView : public UCommonListView
{
GENERATED_BODY()
public:
/**
* Constructor for the ListView widget.
* ListView小部件构造函数。
*/
UGUIS_ListView(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
#if WITH_EDITOR
/**
* Validates compiled defaults in the editor.
* 在编辑器中验证编译默认值。
* @param InCompileLog The widget compiler log. 小部件编译日志。
*/
virtual void ValidateCompiledDefaults(IWidgetCompilerLog& InCompileLog) const override;
#endif
/**
* Sets the entry widget factories for dynamic widget selection.
* 设置动态小部件选择的入口小部件工厂。
* @param NewFactories The array of widget factories. 小部件工厂数组。
*/
UFUNCTION(BlueprintCallable, Category = "ListEntries")
void SetEntryWidgetFactories(TArray<UGUIS_WidgetFactory*> NewFactories);
protected:
/**
* Generates an entry widget for the specified item.
* 为指定项生成入口小部件。
* @param Item The item to generate a widget for. 要生成小部件的项。
* @param DesiredEntryClass The desired entry widget class. 期望的入口小部件类。
* @param OwnerTable The owning table view. 所属表格视图。
* @return The generated widget. 生成的小部件。
*/
virtual UUserWidget& OnGenerateEntryWidgetInternal(UObject* Item, TSubclassOf<UUserWidget> DesiredEntryClass, const TSharedRef<STableViewBase>& OwnerTable) override;
/**
* Array of widget factories for dynamic entry widget selection.
* 动态入口小部件选择的小部件工厂数组。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ListEntries", meta = (IsBindableEvent = "True"))
TArray<TObjectPtr<UGUIS_WidgetFactory>> EntryWidgetFactories;
};

View File

@@ -0,0 +1,61 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonTileView.h"
#include "GUIS_TileView.generated.h"
class UGUIS_WidgetFactory;
/**
* Extended TileView allowing dynamic selection of entry widget class via data asset.
* 通过数据资产动态选择入口小部件类的扩展TileView。
*/
UCLASS(Blueprintable, meta = (Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_TileView : public UCommonTileView
{
GENERATED_BODY()
public:
/**
* Constructor for the TileView widget.
* TileView小部件构造函数。
*/
UGUIS_TileView(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
#if WITH_EDITOR
/**
* Validates compiled defaults in the editor.
* 在编辑器中验证编译默认值。
* @param InCompileLog The widget compiler log. 小部件编译日志。
*/
virtual void ValidateCompiledDefaults(IWidgetCompilerLog& InCompileLog) const override;
#endif
/**
* Sets the entry widget factories for dynamic widget selection.
* 设置动态小部件选择的入口小部件工厂。
* @param NewFactories The array of widget factories. 小部件工厂数组。
*/
UFUNCTION(BlueprintCallable, Category = "ListEntries")
void SetEntryWidgetFactories(TArray<UGUIS_WidgetFactory*> NewFactories);
protected:
/**
* Generates an entry widget for the specified item.
* 为指定项生成入口小部件。
* @param Item The item to generate a widget for. 要生成小部件的项。
* @param DesiredEntryClass The desired entry widget class. 期望的入口小部件类。
* @param OwnerTable The owning table view. 所属表格视图。
* @return The generated widget. 生成的小部件。
*/
virtual UUserWidget& OnGenerateEntryWidgetInternal(UObject* Item, TSubclassOf<UUserWidget> DesiredEntryClass, const TSharedRef<STableViewBase>& OwnerTable) override;
/**
* Array of widget factories for dynamic entry widget selection.
* 动态入口小部件选择的小部件工厂数组。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ListEntries", meta = (IsBindableEvent = "True"))
TArray<TObjectPtr<UGUIS_WidgetFactory>> EntryWidgetFactories;
};

View File

@@ -0,0 +1,63 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "GUIS_UserWidgetInterface.generated.h"
/**
* Interface for UserWidget functionality.
* 通用UserWidget功能的接口。
* @note Designed for UserWidgets (except UCommonActivatableWidget and its derivatives).
* @注意 专为UserWidget设计不包括UCommonActivatableWidget及其派生类
* @details Automatically called when used as an extension UI.
* @细节 用作扩展UI时自动调用。
*/
UINTERFACE()
class GENERICUISYSTEM_API UGUIS_UserWidgetInterface : public UInterface
{
GENERATED_BODY()
};
/**
* Implementation class for UserWidget interface.
* UserWidget接口的实现类。
*/
class GENERICUISYSTEM_API IGUIS_UserWidgetInterface
{
GENERATED_BODY()
public:
/**
* Retrieves the owning actor of the UserWidget.
* 获取UserWidget的所属演员。
* @return The logical owning actor. 逻辑所属演员。
* @note Tracks data for an actor in the game world.
* @注意 跟踪游戏世界中演员的数据。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="GUIS")
AActor* GetOwningActor();
/**
* Sets the owning actor of the UserWidget.
* 设置UserWidget的所属演员。
* @param NewOwningActor The new owning actor. 新的所属演员。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="GUIS")
void SetOwningActor(AActor* NewOwningActor);
/**
* Called when the UserWidget is activated.
* UserWidget激活时调用。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="GUIS")
void OnActivated();
/**
* Called when the UserWidget is deactivated.
* UserWidget禁用时调用。
*/
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category="GUIS")
void OnDeactivated();
};

View File

@@ -0,0 +1,57 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Engine/DataAsset.h"
#include "GUIS_WidgetFactory.generated.h"
class UUserWidget;
/**
* Base class for selecting appropriate widget classes for objects.
* 为对象选择合适小部件类的基类。
*/
UCLASS(Abstract, Blueprintable, BlueprintType, HideDropdown, Const)
class GENERICUISYSTEM_API UGUIS_WidgetFactory : public UDataAsset
{
GENERATED_BODY()
public:
/**
* Default constructor.
* 默认构造函数。
*/
UGUIS_WidgetFactory();
/**
* Finds the appropriate widget class for the given data.
* 为给定数据查找合适的小部件类。
* @param Data The data object. 数据对象。
* @return The widget class. 小部件类。
*/
UFUNCTION(BlueprintNativeEvent, Category="GUIS")
TSubclassOf<UUserWidget> FindWidgetClassForData(const UObject *Data) const;
protected:
/**
* Validates the data for the widget factory.
* 验证小部件工厂的数据。
* @param ValidationMessage The validation message (output). 验证消息(输出)。
* @return True if valid, false otherwise. 如果有效返回true否则返回false。
*/
UFUNCTION(BlueprintNativeEvent, Category="GUIS")
bool OnDataValidation(FText &ValidationMessage) const;
virtual bool OnDataValidation_Implementation(FText &ValidationMessage) const;
#if WITH_EDITOR
/**
* Validates data in the editor.
* 在编辑器中验证数据。
* @param Context The data validation context. 数据验证上下文。
* @return The validation result. 验证结果。
*/
virtual EDataValidationResult IsDataValid(FDataValidationContext &Context) const override;
#endif
};

View File

@@ -0,0 +1,65 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "CommonButtonBase.h"
#include "GUIS_ButtonBase.generated.h"
/**
* Base Button
* 基础按钮
*/
UCLASS(Abstract, BlueprintType, Blueprintable, meta=(Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_ButtonBase : public UCommonButtonBase
{
GENERATED_BODY()
public:
/**
* @param InText The override text to display on the button. 该Text会覆盖按钮上的文字。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void SetButtonText(const FText& InText);
protected:
// UUserWidget interface
virtual void NativePreConstruct() override;
// End of UUserWidget interface
// UCommonButtonBase interface
virtual void UpdateInputActionWidget() override;
virtual void OnInputMethodChanged(ECommonInputType CurrentInputType) override;
// End of UCommonButtonBase interface
void RefreshButtonText();
// 在PreConstruct,InputActionWidget更新以及ButtonText变化时会触发。
UFUNCTION(BlueprintImplementableEvent)
void OnUpdateButtonText(const FText& InText);
/**
* Will use the text from InputActionWidget if not checked.
* 在PreConstruct,InputActionWidget更新以及ButtonText变化时会触发。
*/
UFUNCTION(BlueprintImplementableEvent)
void OnUpdateButtonStyle();
/**
* Will use the text from InputActionWidget if not checked.
* 不勾选的情况下会使用来自InputActionWidget的显示文字。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Button", meta = (ExposeOnSpawn = true, InlineEditConditionToggle))
bool bOverride_ButtonText{true};
/**
* The text to display on the button.
* 按钮的显示文字。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Button", meta = (ExposeOnSpawn = true, EditCondition = "bOverride_ButtonText"))
FText ButtonText;
#if WITH_EDITOR
virtual const FText GetPaletteCategory() override;
#endif // WITH_EDITOR
};

View File

@@ -0,0 +1,20 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "GUIS_ButtonBase.h"
#include "GUIS_TabListWidgetBase.h"
#include "GUIS_TabButtonBase.generated.h"
class UCommonLazyImage;
/**
* Button used for switching between tabs.
* 用于切换选项卡的按钮。
*/
UCLASS(Abstract, Blueprintable, meta = (Category = "Generic UI", DisableNativeTick))
class GENERICUISYSTEM_API UGUIS_TabButtonBase : public UGUIS_ButtonBase, public IGUIS_TabButtonInterface
{
GENERATED_BODY()
};

View File

@@ -0,0 +1,55 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "Engine/DataAsset.h"
#include "Styling/SlateBrush.h"
#include "GUIS_TabDefinition.generated.h"
class UCommonActivatableWidget;
class UWidget;
class UCommonUserWidget;
class UCommonButtonBase;
/**
* Base Tab definition.
* @attention Deprecated as it's unstable.
* 基础选项卡定义。
* @注意 已经弃用
*/
UCLASS(Blueprintable, EditInlineNew, CollapseCategories, Const, DefaultToInstanced, Deprecated)
class GENERICUISYSTEM_API UDEPRECATED_GUIS_TabDefinition : public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FName TabId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FText TabText;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FSlateBrush IconBrush;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition", Transient)
bool bHidden;
/**
* A common button which implements GUIS_TabButtonInterface to received Label infomation.
* 指定用作Tab按钮的Widget类型该类型必须实现GUIS_TabButtonInterface以接收Label信息。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition", meta = (MustImplement = "/Script/GenericUISystem.GUIS_TabButtonInterface", AllowAbstract = "false"))
TSoftClassPtr<UCommonButtonBase> TabButtonType;
/**
* 该所呈现的Widget可选如果有指定那么需要调用
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
TSoftClassPtr<UCommonActivatableWidget> TabContentType;
UPROPERTY(Transient)
TObjectPtr<UWidget> CreatedTabContentWidget;
};

View File

@@ -0,0 +1,320 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonTabListWidgetBase.h"
#include "GUIS_TabListWidgetBase.generated.h"
class UDEPRECATED_GUIS_TabDefinition;
class UCommonButtonBase;
class UCommonUserWidget;
class UObject;
class UWidget;
struct FFrame;
/**
* Structure defining a tab descriptor.
* 定义选项卡描述的结构。
*/
USTRUCT(BlueprintType)
struct GENERICUISYSTEM_API FGUIS_TabDescriptor
{
GENERATED_BODY()
/**
* Default constructor.
* 默认构造函数。
*/
FGUIS_TabDescriptor();
/**
* Unique identifier for the tab.
* 选项卡的唯一标识符。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FName TabId;
/**
* Display text for the tab.
* 选项卡的显示文本。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FText TabText;
/**
* Icon brush for the tab.
* 选项卡的图标画刷。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
FSlateBrush IconBrush;
/**
* Whether the tab is hidden.
* 选项卡是否隐藏。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition", Transient)
bool bHidden{false};
/**
* Button type for the tab, must implement GUIS_TabButtonInterface.
* 选项卡的按钮类型必须实现GUIS_TabButtonInterface。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition", meta = (MustImplement = "/Script/GenericUISystem.GUIS_TabButtonInterface", AllowAbstract = "false"))
TSoftClassPtr<UCommonButtonBase> TabButtonType;
/**
* Content widget type for the tab (optional).
* 选项卡的内容小部件类型(可选)。
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Tab Definition")
TSoftClassPtr<UCommonUserWidget> TabContentType;
/**
* The created content widget for the tab.
* 选项卡的已创建内容小部件。
*/
UPROPERTY(Transient)
TObjectPtr<UWidget> CreatedTabContentWidget;
};
/**
* Interface for tab buttons.
* 选项卡按钮接口。
*/
UINTERFACE(BlueprintType)
class GENERICUISYSTEM_API UGUIS_TabButtonInterface : public UInterface
{
GENERATED_BODY()
};
/**
* Interface for tab buttons to receive and update tab label information.
* 选项卡按钮接收和更新标签信息的接口。
*/
class GENERICUISYSTEM_API IGUIS_TabButtonInterface
{
GENERATED_BODY()
public:
/**
* Sets the deprecated tab definition (no longer used).
* 设置已弃用的选项卡定义(不再使用)。
* @param TabDefinition The tab definition. 选项卡定义。
*/
UFUNCTION(BlueprintNativeEvent, Category = "Tab Button", meta=(DeprecatedFunction, DeprecationMessage="Use Set TabLabelInfo"))
void SetTabDefinition(const UDEPRECATED_GUIS_TabDefinition* TabDefinition);
/**
* Sets the tab label information.
* 设置选项卡标签信息。
* @param TabDescriptor The tab descriptor. 选项卡描述。
*/
UFUNCTION(BlueprintNativeEvent, Category = "Tab Button")
void SetTabLabelInfo(const FGUIS_TabDescriptor& TabDescriptor);
};
/**
* Tab list widget for managing and displaying tabs.
* 管理和显示选项卡的选项卡列表小部件。
* @note Can be linked to a switcher for dynamic tab switching.
* @注意 可关联到切换器以实现动态选项卡切换。
*/
UCLASS(Blueprintable, BlueprintType, Abstract, meta = (DisableNativeTick))
class GENERICUISYSTEM_API UGUIS_TabListWidgetBase : public UCommonTabListWidgetBase
{
GENERATED_BODY()
public:
/**
* Constructor for the tab list widget.
* 选项卡列表小部件构造函数。
*/
UGUIS_TabListWidgetBase();
/**
* Retrieves preregistered tab information by ID.
* 通过ID获取预注册的选项卡信息。
* @param TabNameId The tab ID. 选项卡ID。
* @param OutTabInfo The tab descriptor (output). 选项卡描述(输出)。
* @return True if found, false otherwise. 如果找到返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS|TabList")
bool GetPreregisteredTabInfo(const FName TabNameId, FGUIS_TabDescriptor& OutTabInfo);
/**
* Retrieves the index of a preregistered tab by ID.
* 通过ID获取预注册选项卡的索引。
* @param TabNameId The tab ID. 选项卡ID。
* @return The tab index. 选项卡索引。
*/
UFUNCTION(BlueprintCallable, Category = "GUIS|TabList")
int32 GetPreregisteredTabIndex(FName TabNameId) const;
/**
* Finds preregistered tab information by ID.
* 通过ID查找预注册的选项卡信息。
* @param TabNameId The tab ID. 选项卡ID。
* @param OutTabInfo The tab descriptor (output). 选项卡描述(输出)。
* @return True if found, false otherwise. 如果找到返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, Category = "GUIS|TabList", meta=(ExpandBoolAsExecs="ReturnValue"))
bool FindPreregisteredTabInfo(const FName TabNameId, FGUIS_TabDescriptor& OutTabInfo);
/**
* Toggles the hidden state of a tab (call before associating a switcher).
* 切换选项卡的隐藏状态(在关联切换器之前调用)。
* @param TabNameId The tab ID. 选项卡ID。
* @param bHidden Whether to hide the tab. 是否隐藏选项卡。
*/
UFUNCTION(BlueprintCallable, Category = "GUIS|TabList")
void SetTabHiddenState(FName TabNameId, bool bHidden);
/**
* Registers a dynamic tab.
* 注册动态选项卡。
* @param TabDescriptor The tab descriptor. 选项卡描述。
* @return True if successful, false otherwise. 如果成功返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, Category="GUIS|TabList")
bool RegisterDynamicTab(const FGUIS_TabDescriptor& TabDescriptor);
/**
* Checks if the first tab is active.
* 检查第一个选项卡是否激活。
* @return True if the first tab is active. 如果第一个选项卡激活返回true。
*/
UFUNCTION(BlueprintCallable, Category="GUIS|TabList")
bool IsFirstTabActive() const;
/**
* Checks if the last tab is active.
* 检查最后一个选项卡是否激活。
* @return True if the last tab is active. 如果最后一个选项卡激活返回true。
*/
UFUNCTION(BlueprintCallable, Category="GUIS|TabList")
bool IsLastTabActive() const;
/**
* Checks if a tab is visible.
* 检查选项卡是否可见。
* @param TabId The tab ID. 选项卡ID。
* @return True if the tab is visible. 如果选项卡可见返回true。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS|TabList")
bool IsTabVisible(FName TabId);
/**
* Retrieves the number of visible tabs.
* 获取可见选项卡的数量。
* @return The number of visible tabs. 可见选项卡数量。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS|TabList")
int32 GetVisibleTabCount();
/**
* Delegate for when a new tab is created.
* 新选项卡创建时的委托。
*/
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnTabContentCreated, FName, TabId, UCommonUserWidget *, TabWidget);
/**
* Native delegate for tab creation events.
* 选项卡创建事件的本地委托。
*/
DECLARE_EVENT_TwoParams(UGUIS_TabListWidgetBase, FOnTabContentCreatedNative, FName /* TabId */, UCommonUserWidget * /* TabWidget */);
/**
* Broadcasts when a new tab is created.
* 新选项卡创建时广播。
*/
UPROPERTY(BlueprintAssignable, Category="GUIS|TabList")
FOnTabContentCreated OnTabContentCreated;
/**
* Native event for tab creation.
* 选项卡创建的本地事件。
*/
FOnTabContentCreatedNative OnTabContentCreatedNative;
protected:
/**
* Called when the widget is initialized.
* 小部件初始化时调用。
*/
virtual void NativeOnInitialized() override;
/**
* Called when the widget is constructed.
* 小部件构造时调用。
*/
virtual void NativeConstruct() override;
/**
* Called when the widget is destructed.
* 小部件销毁时调用。
*/
virtual void NativeDestruct() override;
/**
* Called before the linked switcher changes.
* 关联切换器更改前调用。
*/
virtual void HandlePreLinkedSwitcherChanged() override;
/**
* Called after the linked switcher changes.
* 关联切换器更改后调用。
*/
virtual void HandlePostLinkedSwitcherChanged() override;
/**
* Handles tab creation.
* 处理选项卡创建。
* @param TabId The tab ID. 选项卡ID。
* @param TabButton The tab button. 选项卡按钮。
*/
virtual void HandleTabCreation_Implementation(FName TabId, UCommonButtonBase* TabButton) override;
/**
* Sets up the tabs.
* 设置选项卡。
*/
UFUNCTION(BlueprintCallable, Category="GUIS|TabList")
void SetupTabs();
/**
* Deprecated array of tab definitions.
* 已弃用的选项卡定义数组。
*/
UPROPERTY(Instanced, meta = (BlueprintProtected, TitleProperty = "TabId"))
TArray<TObjectPtr<UDEPRECATED_GUIS_TabDefinition>> TabDefinitions_DEPRECATED;
/**
* Array of preregistered tab descriptors.
* 预注册选项卡描述数组。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="TabList", meta=(TitleProperty="TabId"))
TArray<FGUIS_TabDescriptor> PreregisteredTabInfoArray;
/**
* Map of pending tab label information for runtime-registered tabs.
* 运行时注册选项卡的待处理标签信息映射。
*/
UPROPERTY()
TMap<FName, FGUIS_TabDescriptor> PendingTabLabelInfoMap;
#if WITH_EDITOR
/**
* Called after loading in the editor.
* 编辑器中加载后调用。
*/
virtual void PostLoad() override;
/**
* Validates compiled defaults in the editor.
* 在编辑器中验证编译默认值。
* @param CompileLog The widget compiler log. 小部件编译日志。
*/
virtual void ValidateCompiledDefaults(class IWidgetCompilerLog& CompileLog) const override;
#endif
};

View File

@@ -0,0 +1,97 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonActivatableWidget.h"
#include "GUIS_ActivatableWidget.generated.h"
struct FUIInputConfig;
/**
* Enum defining input modes for activatable widgets.
* 定义可激活小部件输入模式的枚举。
*/
UENUM()
enum class EGUIS_ActivatableWidgetInputMode : uint8
{
/**
* Default input mode.
* 默认输入模式。
*/
Default,
/**
* Allows both game and menu input.
* 允许游戏和菜单输入。
*/
GameAndMenu,
/**
* Game input only.
* 仅游戏输入。
*/
Game,
/**
* Menu input only.
* 仅菜单输入。
*/
Menu
};
/**
* Activatable widget that manages input configuration when activated.
* 可激活小部件,激活时管理输入配置。
*/
UCLASS(Abstract, Blueprintable)
class GENERICUISYSTEM_API UGUIS_ActivatableWidget : public UCommonActivatableWidget
{
GENERATED_BODY()
public:
/**
* Constructor for the activatable widget.
* 可激活小部件构造函数。
*/
UGUIS_ActivatableWidget(const FObjectInitializer& ObjectInitializer);
/**
* Sets whether the widget handles back navigation.
* 设置小部件是否处理后退导航。
* @param bNewState The new back handler state. 新的后退处理状态。
*/
UFUNCTION(BlueprintCallable, Category = "GUIS|ActivatableWidget")
void SetIsBackHandler(bool bNewState);
/**
* Retrieves the desired input configuration.
* 获取期望的输入配置。
* @return The input configuration. 输入配置。
*/
virtual TOptional<FUIInputConfig> GetDesiredInputConfig() const override;
#if WITH_EDITOR
/**
* Validates the compiled widget tree in the editor.
* 在编辑器中验证编译的小部件树。
* @param BlueprintWidgetTree The widget tree to validate. 要验证的小部件树。
* @param CompileLog The widget compiler log. 小部件编译日志。
*/
virtual void ValidateCompiledWidgetTree(const UWidgetTree& BlueprintWidgetTree, class IWidgetCompilerLog& CompileLog) const override;
#endif
protected:
/**
* Desired input mode when the widget is activated.
* 小部件激活时的期望输入模式。
*/
UPROPERTY(EditDefaultsOnly, Category="Input")
EGUIS_ActivatableWidgetInputMode InputConfig = EGUIS_ActivatableWidgetInputMode::Default;
/**
* Mouse capture behavior for game input.
* 游戏输入的鼠标捕获行为。
*/
UPROPERTY(EditDefaultsOnly, Category="Input")
EMouseCaptureMode GameMouseCaptureMode = EMouseCaptureMode::CapturePermanently;
};

View File

@@ -0,0 +1,19 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/Object.h"
#include "GUIS_GameUIContext.generated.h"
/**
* Base class for UI context data shared across multiple UI elements.
* 多个UI元素共享的UI上下文数据的基类。
* @details Allows subclassing to add custom data for UI interactions.
* @细节 允许子类化以添加用于UI交互的自定义数据。
*/
UCLASS(Abstract, Blueprintable, BlueprintType)
class GENERICUISYSTEM_API UGUIS_GameUIContext : public UObject
{
GENERATED_BODY()
};

View File

@@ -0,0 +1,191 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "Blueprint/IUserObjectListEntry.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "UObject/SoftObjectPtr.h"
#include "GUIS_GameUIFunctionLibrary.generated.h"
class UGUIS_GameUILayout;
enum class ECommonInputType : uint8;
template <typename T>
class TSubclassOf;
class APlayerController;
class UCommonActivatableWidget;
class ULocalPlayer;
class UObject;
class UUserWidget;
struct FFrame;
struct FGameplayTag;
/**
* Common functions for Game UI.
* 游戏UI的通用功能函数库。
*/
UCLASS()
class GENERICUISYSTEM_API UGUIS_GameUIFunctionLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UGUIS_GameUIFunctionLibrary()
{
}
/**
* Gets the input type of the owning player for the specified widget.
* 获取指定控件所属玩家的输入类型。
* @param WidgetContextObject The widget to query for input type. 要查询输入类型的控件。
* @return The input type of the owning player. 所属玩家的输入类型。
*/
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WidgetContextObject"))
static ECommonInputType GetOwningPlayerInputType(const UUserWidget* WidgetContextObject);
/**
* Checks if the owning player is using touch input.
* 检查所属玩家是否使用触摸输入。
* @param WidgetContextObject The widget to query for input type. 要查询输入类型的控件。
* @return True if the owning player is using touch input, false otherwise. 如果所属玩家使用触摸输入则返回true否则返回false。
*/
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WidgetContextObject"))
static bool IsOwningPlayerUsingTouch(const UUserWidget* WidgetContextObject);
/**
* Checks if the owning player is using a gamepad.
* 检查所属玩家是否使用游戏手柄。
* @param WidgetContextObject The widget to query for input type. 要查询输入类型的控件。
* @return True if the owning player is using a gamepad, false otherwise. 如果所属玩家使用游戏手柄则返回true否则返回false。
*/
UFUNCTION(BlueprintPure, BlueprintCosmetic, Category="GUIS", meta = (WorldContext = "WidgetContextObject"))
static bool IsOwningPlayerUsingGamepad(const UUserWidget* WidgetContextObject);
/**
* Pushes a widget to the specified UI layer for the given player.
* 将控件推送到指定玩家的UI层。
* @param PlayerController The player controller to associate with the UI layer. 与UI层关联的玩家控制器。
* @param LayerName The tag identifying the UI layer. 标识UI层的标签。
* @param WidgetClass The class of the widget to push. 要推送的控件类。
* @return The created widget instance. 创建的控件实例。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta=(DynamicOutputParam="ReturnValue", DeterminesOutputType="WidgetClass"))
static UCommonActivatableWidget* PushContentToUILayer_ForPlayer(const APlayerController* PlayerController, UPARAM(meta = (Categories = "UI.Layer,GUIS.Layer"))
FGameplayTag LayerName,
UPARAM(meta = (AllowAbstract = false))
TSubclassOf<UCommonActivatableWidget> WidgetClass);
/**
* Pops content from the specified UI layer for the given player.
* 从指定玩家的UI层中弹出内容。
* @param PlayerController The player controller associated with the UI layer. 与UI层关联的玩家控制器。
* @param LayerName The tag identifying the UI layer. 标识UI层的标签。
* @param RemainNum Number of widgets to remain in the layer (-1 means remove all.). 保留在层中的控件数量(-1表示不保留
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS")
static void PopContentFromUILayer_ForPlayer(const APlayerController* PlayerController, UPARAM(meta = (Categories = "UI.Layer,GUIS.Layer"))
FGameplayTag LayerName, int32 RemainNum = -1);
/**
* Removes a specific activatable widget from the UI layer.
* 从UI层中移除指定的可激活控件。
* @param ActivatableWidget The widget to remove. 要移除的控件。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta=(DefaultToSelf="ActivatableWidget"))
static void PopContentFromUILayer(UCommonActivatableWidget* ActivatableWidget);
/**
* Pops multiple activatable widgets from the UI layer.
* 从UI层中弹出多个可激活控件。
* @param ActivatableWidgets List of activatable widgets to pop. 要弹出的控件列表。
* @param bReverse If true, pops in reverse array order. 如果为true则按数组反向顺序弹出。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS", meta=(DefaultToSelf="ActivatableWidget"))
static void PopContentsFromUILayer(TArray<UCommonActivatableWidget*> ActivatableWidgets, bool bReverse = true);
/**
* Gets the local player associated with the given player controller.
* 获取与指定玩家控制器关联的本地玩家。
* @param PlayerController The player controller to query. 要查询的玩家控制器。
* @return The associated local player. 关联的本地玩家。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, BlueprintCosmetic, Category="GUIS")
static ULocalPlayer* GetLocalPlayerFromController(APlayerController* PlayerController);
/**
* Gets the game UI layout for the specified player.
* 获取指定玩家的游戏UI布局。
* @param PlayerController The player controller to query. 要查询的玩家控制器。
* @return The game UI layout for the player. 玩家的游戏UI布局。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS")
static UGUIS_GameUILayout* GetGameUILayoutForPlayer(const APlayerController* PlayerController);
/**
* Suspends input for the specified player with a reason.
* 暂停指定玩家的输入并提供原因。
* @param PlayerController The player controller to suspend input for. 要暂停输入的玩家控制器。
* @param SuspendReason The reason for suspending input. 暂停输入的原因。
* @return A token representing the suspension. 表示暂停的令牌。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS")
static FName SuspendInputForPlayer(APlayerController* PlayerController, FName SuspendReason);
/**
* Suspends input for the specified local player with a reason.
* 暂停指定本地玩家的输入并提供原因。
* @param LocalPlayer The local player to suspend input for. 要暂停输入的本地玩家。
* @param SuspendReason The reason for suspending input. 暂停输入的原因。
* @return A token representing the suspension. 表示暂停的令牌。
*/
static FName SuspendInputForPlayer(ULocalPlayer* LocalPlayer, FName SuspendReason);
/**
* Resumes input for the specified player using the suspension token.
* 使用暂停令牌恢复指定玩家的输入。
* @param PlayerController The player controller to resume input for. 要恢复输入的玩家控制器。
* @param SuspendToken The token from the suspension call. 暂停调用时返回的令牌。
*/
UFUNCTION(BlueprintCallable, BlueprintCosmetic, Category="GUIS")
static void ResumeInputForPlayer(APlayerController* PlayerController, FName SuspendToken);
/**
* Resumes input for the specified local player using the suspension token.
* 使用暂停令牌恢复指定本地玩家的输入。
* @param LocalPlayer The local player to resume input for. 要恢复输入的本地玩家。
* @param SuspendToken The token from the suspension call. 暂停调用时返回的令牌。
*/
static void ResumeInputForPlayer(ULocalPlayer* LocalPlayer, FName SuspendToken);
/**
* Returns the typed item in the owning list view that this entry is currently assigned to represent.
* 以指定类型的方式获取Entry要展示的Item。
* @param UserObjectListEntry The list entry to query (defaults to self). 要查询的列表条目(默认值为自身)。
* @param DesiredClass The type of ListItemObject. 列表项对象的类型。
* @return The typed item object. 类型化的列表项对象。
*/
UFUNCTION(BlueprintPure, Category="GUIS",
meta = (DeterminesOutputType = "DesiredClass", DynamicOutputParam = "ReturnValue", DefaultToSelf = UserObjectListEntry, DisplayName = "Get List item Object"))
static UObject* GetTypedListItem(TScriptInterface<IUserObjectListEntry> UserObjectListEntry, TSubclassOf<UObject> DesiredClass);
/**
* Safely returns the typed item in the owning list view that this entry is currently assigned to represent.
* 安全地以指定类型的方式获取Entry要展示的Item。
* @param UserObjectListEntry The list entry to query (defaults to self). 要查询的列表条目(默认值为自身)。
* @param DesiredClass The type of ListItemObject. 列表项对象的类型。
* @param OutItem The typed item object (output). 类型化的列表项对象(输出)。
* @return True if the item was successfully retrieved, false otherwise. 如果成功获取项则返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, Category="GUIS",
meta = (ExpandBoolAsExecs = "ReturnValue", DeterminesOutputType = "DesiredClass", DynamicOutputParam = "OutItemObject", DefaultToSelf = UserObjectListEntry, DisplayName =
"Get List item Object"))
static bool GetTypedListItemSafely(TScriptInterface<IUserObjectListEntry> UserObjectListEntry, TSubclassOf<UObject> DesiredClass, UObject*& OutItem);
private:
/**
* Tracks the number of active input suspensions.
* 跟踪当前活动的输入暂停数量。
*/
static int32 InputSuspensions;
};

View File

@@ -0,0 +1,213 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonActivatableWidget.h"
#include "Engine/AssetManager.h"
#include "Engine/StreamableManager.h"
#include "GameplayTagContainer.h"
#include "GUIS_GameUIFunctionLibrary.h"
#include "Widgets/CommonActivatableWidgetContainer.h" // IWYU pragma: keep
#include "GUIS_GameUILayout.generated.h"
class APlayerController;
class UClass;
class UCommonActivatableWidgetContainerBase;
class ULocalPlayer;
class UObject;
struct FFrame;
/**
* Enumeration for the state of an async UI widget layer load operation.
* 异步UI控件层加载操作状态的枚举。
*/
enum class EGUIS_AsyncWidgetLayerState : uint8
{
Canceled, // Operation was canceled. 操作被取消。
Initialize, // Widget is being initialized. 控件正在初始化。
AfterPush // Widget has been pushed to the layer. 控件已被推送到层。
};
/**
* Primary game UI layout for managing widget layers for a single player.
* 管理单个玩家控件层的游戏主UI布局。
* @details Handles the layout, pushing, and display of UI layers for a player in a split-screen game.
* @细节 处理分屏游戏中玩家的UI层布局、推送和显示。
*/
UCLASS(Abstract, meta = (DisableNativeTick))
class GENERICUISYSTEM_API UGUIS_GameUILayout : public UCommonUserWidget
{
GENERATED_BODY()
public:
/**
* Constructor for the game UI layout.
* 游戏UI布局的构造函数。
*/
UGUIS_GameUILayout(const FObjectInitializer &ObjectInitializer);
/**
* Sets the dormant state of the layout, limiting it to persistent actions.
* 设置布局的休眠状态,限制为持久动作。
* @param Dormant True to set the layout as dormant, false otherwise. 如果设置为休眠则为true否则为false。
*/
void SetIsDormant(bool Dormant);
/**
* Checks if the layout is in a dormant state.
* 检查布局是否处于休眠状态。
* @return True if the layout is dormant, false otherwise. 如果布局休眠则返回true否则返回false。
*/
bool IsDormant() const { return bIsDormant; }
public:
/**
* Asynchronously pushes a widget to a specified layer.
* 异步将控件推送到指定层。
* @param LayerName The tag of the layer to push to. 要推送到的层标签。
* @param bSuspendInputUntilComplete Whether to suspend input until loading is complete. 是否在加载完成前暂停输入。
* @param ActivatableWidgetClass The class of the widget to push. 要推送的控件类。
* @return A handle to the async streaming operation. 异步流操作的句柄。
*/
template <typename ActivatableWidgetT = UCommonActivatableWidget>
TSharedPtr<FStreamableHandle> PushWidgetToLayerStackAsync(FGameplayTag LayerName, bool bSuspendInputUntilComplete, TSoftClassPtr<UCommonActivatableWidget> ActivatableWidgetClass)
{
return PushWidgetToLayerStackAsync<ActivatableWidgetT>(LayerName, bSuspendInputUntilComplete, ActivatableWidgetClass, [](EGUIS_AsyncWidgetLayerState, ActivatableWidgetT *) {});
}
/**
* Asynchronously pushes a widget to a specified layer with a state callback.
* 使用状态回调异步将控件推送到指定层。
* @param LayerName The tag of the layer to push to. 要推送到的层标签。
* @param bSuspendInputUntilComplete Whether to suspend input until loading is complete. 是否在加载完成前暂停输入。
* @param ActivatableWidgetClass The class of the widget to push. 要推送的控件类。
* @param StateFunc Callback for handling widget state changes. 处理控件状态变化的回调。
* @return A handle to the async streaming operation. 异步流操作的句柄。
*/
template <typename ActivatableWidgetT = UCommonActivatableWidget>
TSharedPtr<FStreamableHandle> PushWidgetToLayerStackAsync(FGameplayTag LayerName, bool bSuspendInputUntilComplete, TSoftClassPtr<UCommonActivatableWidget> ActivatableWidgetClass,
TFunction<void(EGUIS_AsyncWidgetLayerState, ActivatableWidgetT *)> StateFunc)
{
static_assert(TIsDerivedFrom<ActivatableWidgetT, UCommonActivatableWidget>::IsDerived, "Only CommonActivatableWidgets can be used here");
static FName NAME_PushingWidgetToLayer("PushingWidgetToLayer");
const FName SuspendInputToken = bSuspendInputUntilComplete ? UGUIS_GameUIFunctionLibrary::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]()
{
UGUIS_GameUIFunctionLibrary::ResumeInputForPlayer(GetOwningPlayer(), SuspendInputToken);
ActivatableWidgetT *Widget = PushWidgetToLayerStack<ActivatableWidgetT>(
LayerName, ActivatableWidgetClass.Get(), [StateFunc](ActivatableWidgetT &WidgetToInit)
{ StateFunc(EGUIS_AsyncWidgetLayerState::Initialize, &WidgetToInit); });
StateFunc(EGUIS_AsyncWidgetLayerState::AfterPush, Widget);
}));
// Setup a cancel delegate to resume input if the operation is canceled.
StreamingHandle->BindCancelDelegate(FStreamableDelegate::CreateWeakLambda(this,
[this, StateFunc, SuspendInputToken]()
{
UGUIS_GameUIFunctionLibrary::ResumeInputForPlayer(GetOwningPlayer(), SuspendInputToken);
StateFunc(EGUIS_AsyncWidgetLayerState::Canceled, nullptr);
}));
return StreamingHandle;
}
/**
* Pushes a widget to a specified layer.
* 将控件推送到指定层。
* @param LayerName The tag of the layer to push to. 要推送到的层标签。
* @param ActivatableWidgetClass The class of the widget to push. 要推送的控件类。
* @return Pointer to the pushed widget, or nullptr if failed. 推送的控件指针失败时为nullptr。
*/
template <typename ActivatableWidgetT = UCommonActivatableWidget>
ActivatableWidgetT *PushWidgetToLayerStack(FGameplayTag LayerName, UClass *ActivatableWidgetClass)
{
return PushWidgetToLayerStack<ActivatableWidgetT>(LayerName, ActivatableWidgetClass, [](ActivatableWidgetT &) {});
}
/**
* Pushes a widget to a specified layer with initialization.
olduğuna * 将控件推送到指定层并进行初始化。
* @param LayerName The tag of the layer to push to. 要推送到的层标签。
* @param ActivatableWidgetClass The class of the widget to push. 要推送的控件类。
* @param InitInstanceFunc Function to initialize the widget instance. 初始化控件实例的函数。
* @return Pointer to the pushed widget, or nullptr if failed. 推送的控件指针失败时为nullptr。
*/
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;
}
/**
* Finds and removes a widget from any layer.
* 从任意层查找并移除控件。
* @param ActivatableWidget The widget to remove. 要移除的控件。
*/
void FindAndRemoveWidgetFromLayer(UCommonActivatableWidget *ActivatableWidget);
/**
* Retrieves the layer widget for a given layer tag.
* 获取给定层标签的层控件。
* @param LayerName The tag of the layer to retrieve. 要检索的层标签。
* @return Pointer to the layer widget, or nullptr if not found. 层控件指针未找到时为nullptr。
*/
UCommonActivatableWidgetContainerBase *GetLayerWidget(FGameplayTag LayerName);
protected:
/**
* Registers a layer for pushing widgets.
* 注册一个用于推送控件的层。
* @param LayerTag The tag identifying the layer. 标识层的标签。
* @param LayerWidget The widget container for the layer. 层的控件容器。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void RegisterLayer(UPARAM(meta = (Categories = "UI.Layer,GUIS.Layer")) FGameplayTag LayerTag, UCommonActivatableWidgetContainerBase *LayerWidget);
/**
* Called when the dormant state changes.
* 当休眠状态更改时调用。
*/
virtual void OnIsDormantChanged();
/**
* Handles widget stack transitioning events.
* 处理控件堆栈转换事件。
* @param Widget The widget container transitioning. 转换的控件容器。
* @param bIsTransitioning True if transitioning, false otherwise. 如果正在转换则为true否则为false。
*/
void OnWidgetStackTransitioning(UCommonActivatableWidgetContainerBase *Widget, bool bIsTransitioning);
private:
/**
* Indicates if the layout is dormant.
* 指示布局是否休眠。
*/
bool bIsDormant = false;
/**
* Tracks all suspended input tokens for async UI loading.
* 跟踪异步UI加载的所有暂停输入令牌。
*/
TArray<FName> SuspendInputTokens;
/**
* Registered layers for the primary layout.
* 主布局的注册层。
*/
UPROPERTY(Transient, meta = (Categories = "UI.Layer,GUIS.Layer"))
TMap<FGameplayTag, TObjectPtr<UCommonActivatableWidgetContainerBase>> Layers;
};

View File

@@ -0,0 +1,279 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "GUIS_GameUIStructLibrary.h"
#include "Engine/World.h"
#include "Engine/DataTable.h"
#include "GUIS_GameUIPolicy.generated.h"
class UCommonUserWidget;
class UGUIS_GameUIContext;
class ULocalPlayer;
class UGUIS_GameUISubsystem;
class UGUIS_GameUILayout;
/**
* Enumeration for local multiplayer UI interaction modes.
* 本地多人UI交互模式的枚举。
*/
UENUM()
enum class EGUIS_LocalMultiplayerInteractionMode : uint8
{
PrimaryOnly, // Fullscreen viewport for the primary player only. 仅为主玩家显示全屏视口。
SingleToggle, // Fullscreen viewport with player swapping control. 全屏视口,玩家可切换控制。
Simultaneous // Simultaneous viewports for all players. 为所有玩家同时显示视口。
};
/**
* Manages UI layouts for different local players.
* 为不同本地玩家管理UI布局。
* @details Controls the creation, addition, and removal of UI layouts and contexts.
* @细节 控制UI布局和上下文的创建、添加和移除。
*/
UCLASS(Abstract, Blueprintable, Within = GUIS_GameUISubsystem)
class GENERICUISYSTEM_API UGUIS_GameUIPolicy : public UObject
{
GENERATED_BODY()
public:
/**
* Retrieves the UI policy for the specified world context as a specific type.
* 获取指定世界上下文的UI策略转换为特定类型。
* @param WorldContextObject The object providing world context. 提供世界上下文的对象。
* @return The UI policy cast to the specified type. 转换为指定类型的UI策略。
*/
template <typename GameUIPolicyClass = UGUIS_GameUIPolicy>
static GameUIPolicyClass* GetGameUIPolicyAs(const UObject* WorldContextObject)
{
return Cast<GameUIPolicyClass>(GetGameUIPolicy(WorldContextObject));
}
/**
* Retrieves the UI policy for the specified world context.
* 获取指定世界上下文的UI策略。
* @param WorldContextObject The object providing world context. 提供世界上下文的对象。
* @return The UI policy. UI策略。
*/
static UGUIS_GameUIPolicy* GetGameUIPolicy(const UObject* WorldContextObject);
/**
* Retrieves the world associated with the UI policy.
* 获取与UI策略关联的世界。
* @return The associated world. 关联的世界。
*/
virtual UWorld* GetWorld() const override;
/**
* Retrieves the owning game UI subsystem.
* 获取所属的游戏UI子系统。
* @return The owning subsystem. 所属子系统。
*/
UGUIS_GameUISubsystem* GetOwningSubsystem() const;
/**
* Retrieves the root layout for a local player.
* 获取本地玩家的根布局。
* @param LocalPlayer The local player. 本地玩家。
* @return The root layout for the player. 玩家的根布局。
*/
UGUIS_GameUILayout* GetRootLayout(const ULocalPlayer* LocalPlayer) const;
/**
* Retrieves a UI context for a local player.
* 获取本地玩家的UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param ContextClass The class of the context to retrieve. 要检索的上下文类。
* @return The UI context, or nullptr if not found. UI上下文未找到时为nullptr。
*/
virtual UGUIS_GameUIContext* GetContext(const ULocalPlayer* LocalPlayer, TSubclassOf<UGUIS_GameUIContext> ContextClass);
/**
* Adds a UI context for a local player.
* 为本地玩家添加UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param NewContext The UI context to add. 要添加的UI上下文。
* @return True if the context was added, false otherwise. 如果上下文添加成功则返回true否则返回false。
*/
virtual bool AddContext(const ULocalPlayer* LocalPlayer, UGUIS_GameUIContext* NewContext);
/**
* Finds a UI context for a local player.
* 查找本地玩家的UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param ContextClass The class of the context to find. 要查找的上下文类。
* @return The found UI context, or nullptr if not found. 找到的UI上下文未找到时为nullptr。
*/
virtual UGUIS_GameUIContext* FindContext(const ULocalPlayer* LocalPlayer, TSubclassOf<UGUIS_GameUIContext> ContextClass);
/**
* Removes a UI context for a local player.
* 移除本地玩家的UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param ContextClass The class of the context to remove. 要移除的上下文类。
*/
virtual void RemoveContext(const ULocalPlayer* LocalPlayer, TSubclassOf<UGUIS_GameUIContext> ContextClass);
/**
* Adds a UI action binding for a local player.
* 为本地玩家添加UI动作绑定。
* @param LocalPlayer The local player. 本地玩家。
* @param Target The target widget for the action. 动作的目标控件。
* @param InputAction The input action to bind. 要绑定的输入动作。
* @param bShouldDisplayInActionBar Whether to display in the action bar. 是否在动作栏中显示。
* @param Callback Delegate called when the action is executed. 动作执行时调用的委托。
* @param BindingHandle The handle for the binding. 绑定的句柄。
*/
virtual void AddUIAction(const ULocalPlayer* LocalPlayer, UCommonUserWidget* Target, const FDataTableRowHandle& InputAction, bool bShouldDisplayInActionBar,
const FGUIS_UIActionExecutedDelegate& Callback,
FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Removes a UI action binding for a local player.
* 为本地玩家移除UI动作绑定。
* @param LocalPlayer The local player. 本地玩家。
* @param BindingHandle The handle of the binding to remove. 要移除的绑定句柄。
*/
virtual void RemoveUIAction(const ULocalPlayer* LocalPlayer, FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Gets the current multiplayer interaction mode.
* 获取当前的多人交互模式。
* @return The current interaction mode. 当前交互模式。
*/
EGUIS_LocalMultiplayerInteractionMode GetLocalMultiplayerInteractionMode() const { return LocalMultiplayerInteractionMode; }
/**
* Requests primary control for a specific layout.
* 为特定布局请求主要控制权。
* @param Layout The layout requesting primary control. 请求主要控制权的布局。
*/
void RequestPrimaryControl(UGUIS_GameUILayout* Layout);
protected:
/**
* Adds a layout to the viewport for a local player.
* 为本地玩家将布局添加到视口。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The layout to add. 要添加的布局。
*/
void AddLayoutToViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Removes a layout from the viewport for a local player.
* 为本地玩家从视口中移除布局。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The layout to remove. 要移除的布局。
*/
void RemoveLayoutFromViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Called when a root layout is added to the viewport.
* 当根布局添加到视口时调用。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The added layout. 添加的布局。
*/
virtual void OnRootLayoutAddedToViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Blueprint event for when a root layout is added to the viewport.
* 当根布局添加到视口时的蓝图事件。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The added layout. 添加的布局。
*/
UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnRootLayoutAddedToViewport"))
void BP_OnRootLayoutAddedToViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Called when a root layout is removed from the viewport.
* 当根布局从视口中移除时调用。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The removed layout. 移除的布局。
*/
virtual void OnRootLayoutRemovedFromViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Blueprint event for when a root layout is removed from the viewport.
* 当根布局从视口中移除时的蓝图事件。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The removed layout. 移除的布局。
*/
UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnRootLayoutRemovedFromViewport"))
void BP_OnRootLayoutRemovedFromViewport(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Called when a root layout is released.
* 当根布局被释放时调用。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The released layout. 释放的布局。
*/
virtual void OnRootLayoutReleased(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Blueprint event for when a root layout is released.
* 当根布局被释放时的蓝图事件。
* @param LocalPlayer The local player. 本地玩家。
* @param Layout The released layout. 释放的布局。
*/
UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "OnRootLayoutReleased"))
void BP_OnRootLayoutReleased(ULocalPlayer* LocalPlayer, UGUIS_GameUILayout* Layout);
/**
* Creates a layout widget for a local player.
* 为本地玩家创建布局控件。
* @param LocalPlayer The local player. 本地玩家。
*/
void CreateLayoutWidget(ULocalPlayer* LocalPlayer);
/**
* Retrieves the layout widget class for a local player.
* 获取本地玩家的布局控件类。
* @param LocalPlayer The local player. 本地玩家。
* @return The layout widget class. 布局控件类。
*/
TSubclassOf<UGUIS_GameUILayout> GetLayoutWidgetClass(ULocalPlayer* LocalPlayer);
private:
/**
* Current multiplayer interaction mode.
* 当前的多人交互模式。
*/
EGUIS_LocalMultiplayerInteractionMode LocalMultiplayerInteractionMode = EGUIS_LocalMultiplayerInteractionMode::PrimaryOnly;
/**
* The class used for the game UI layout.
* 用于游戏UI布局的类。
*/
UPROPERTY(EditAnywhere, Category="GUIS")
TSoftClassPtr<UGUIS_GameUILayout> LayoutClass;
/**
* Array of root viewport layout information.
* 根视口布局信息的数组。
*/
UPROPERTY(Transient)
TArray<FGUIS_RootViewportLayoutInfo> RootViewportLayouts;
/**
* Notifies when a player is added.
* 当玩家被添加时通知。
* @param LocalPlayer The added local player. 添加的本地玩家。
*/
void NotifyPlayerAdded(ULocalPlayer* LocalPlayer);
/**
* Notifies when a player is removed.
* 当玩家被移除时通知。
* @param LocalPlayer The removed local player. 移除的本地玩家。
*/
void NotifyPlayerRemoved(ULocalPlayer* LocalPlayer);
/**
* Notifies when a player is destroyed.
* 当玩家被销毁时通知。
* @param LocalPlayer The destroyed local player. 销毁的本地玩家。
*/
void NotifyPlayerDestroyed(ULocalPlayer* LocalPlayer);
friend class UGUIS_GameUISubsystem;
};

View File

@@ -0,0 +1,146 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Input/UIActionBindingHandle.h"
#include "UObject/Object.h"
#include "GUIS_GameUIStructLibrary.generated.h"
class UGUIS_GameUIContext;
class UGUIS_GameUILayout;
class ULocalPlayer;
/**
* Delegate for handling UI action execution.
* 处理UI动作执行的委托。
* @param ActionName The name of the executed action. 执行的动作名称。
*/
DECLARE_DYNAMIC_DELEGATE_OneParam(FGUIS_UIActionExecutedDelegate, FName, ActionName);
/**
* Struct for storing UI action binding information.
* 存储UI动作绑定信息的结构体。
*/
USTRUCT(BlueprintType)
struct FGUIS_UIActionBindingHandle
{
GENERATED_BODY()
/**
* Unique identifier for the binding.
* 绑定的唯一标识符。
*/
FName Id;
/**
* Handle for the UI action binding.
* UI动作绑定的句柄。
*/
FUIActionBindingHandle Handle;
};
/**
* Struct for storing UI context binding information.
* 存储UI上下文绑定信息的结构体。
*/
USTRUCT(BlueprintType)
struct FGUIS_UIContextBindingHandle
{
GENERATED_BODY()
FGUIS_UIContextBindingHandle()
{
};
/**
* Constructor for UI context binding handle.
* UI上下文绑定句柄的构造函数。
* @param InLocalPlayer The local player associated with the context. 与上下文关联的本地玩家。
* @param InContextClass The class of the context. 上下文的类。
*/
FGUIS_UIContextBindingHandle(ULocalPlayer* InLocalPlayer, UClass* InContextClass);
/**
* The local player associated with the context.
* 与上下文关联的本地玩家。
*/
UPROPERTY()
TObjectPtr<ULocalPlayer> LocalPlayer;
/**
* The class of the UI context.
* UI上下文的类。
*/
UPROPERTY()
UClass* ContextClass{nullptr};
};
/**
* Struct for storing root viewport layout information.
* 存储根视口布局信息的结构体。
*/
USTRUCT()
struct FGUIS_RootViewportLayoutInfo
{
GENERATED_BODY()
/**
* The local player associated with the layout.
* 与布局关联的本地玩家。
*/
UPROPERTY(Transient)
TObjectPtr<ULocalPlayer> LocalPlayer = nullptr;
/**
* The root layout widget.
* 根布局控件。
*/
UPROPERTY(Transient)
TObjectPtr<UGUIS_GameUILayout> RootLayout = nullptr;
/**
* Indicates if the layout is added to the viewport.
* 指示布局是否已添加到视口。
*/
UPROPERTY(Transient)
bool bAddedToViewport = false;
/**
* Array of UI contexts associated with the layout.
* 与布局关联的UI上下文数组。
*/
UPROPERTY(Transient)
TArray<TObjectPtr<UGUIS_GameUIContext>> Contexts;
/**
* Array of UI action binding handles.
* UI动作绑定句柄的数组。
*/
UPROPERTY(Transient)
TArray<FUIActionBindingHandle> BindingHandles;
FGUIS_RootViewportLayoutInfo()
{
}
/**
* Constructor for root viewport layout information.
* 根视口布局信息的构造函数。
* @param InLocalPlayer The local player. 本地玩家。
* @param InRootLayout The root layout widget. 根布局控件。
* @param bIsInViewport Whether the layout is in the viewport. 布局是否在视口中。
*/
FGUIS_RootViewportLayoutInfo(ULocalPlayer* InLocalPlayer, UGUIS_GameUILayout* InRootLayout, bool bIsInViewport)
: LocalPlayer(InLocalPlayer), RootLayout(InRootLayout), bAddedToViewport(bIsInViewport)
{
}
/**
* Equality operator to compare with a local player.
* 与本地玩家比较的相等运算符。
* @param OtherLocalPlayer The local player to compare with. 要比较的本地玩家。
* @return True if the local players match, false otherwise. 如果本地玩家匹配则返回true否则返回false。
*/
bool operator==(const ULocalPlayer* OtherLocalPlayer) const { return LocalPlayer == OtherLocalPlayer; }
};

View File

@@ -0,0 +1,223 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "Input/UIActionBindingHandle.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "GUIS_GameUIStructLibrary.h"
#include "UObject/SoftObjectPtr.h"
#include "GUIS_GameUISubsystem.generated.h"
class UCommonUserWidget;
class UGUIS_GameUIContext;
class FSubsystemCollectionBase;
class ULocalPlayer;
class UGUIS_GameUIPolicy;
class UObject;
/**
* Game UI subsystem for managing UI policies and player UI interactions.
* 管理UI策略和玩家UI交互的游戏UI子系统。
* @details Intended to be subclassed for game-specific UI functionality.
* @细节 旨在为特定游戏的UI功能进行子类化。
*/
UCLASS()
class GENERICUISYSTEM_API UGUIS_GameUISubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
UGUIS_GameUISubsystem()
{
}
/**
* Initializes the UI subsystem.
* 初始化UI子系统。
* @param Collection The subsystem collection base. 子系统集合基类。
*/
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
/**
* Deinitializes the UI subsystem.
* 取消初始化UI子系统。
*/
virtual void Deinitialize() override;
/**
* Determines if the subsystem should be created.
* 确定是否应创建子系统。
* @param Outer The outer object. 外部对象。
* @return True if the subsystem should be created, false otherwise. 如果应创建子系统则返回true否则返回false。
*/
virtual bool ShouldCreateSubsystem(UObject* Outer) const override;
/**
* Gets the current UI policy (const version).
* 获取当前UI策略常量版本
* @return The current UI policy. 当前UI策略。
*/
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS")
const UGUIS_GameUIPolicy* GetCurrentUIPolicy() const { return CurrentPolicy; }
/**
* Gets the current UI policy (non-const version).
* 获取当前UI策略非常量版本
* @return The current UI policy. 当前UI策略。
*/
UGUIS_GameUIPolicy* GetCurrentUIPolicy() { return CurrentPolicy; }
/**
* Adds a player to the UI subsystem.
* 将玩家添加到UI子系统。
* @param LocalPlayer The local player to add. 要添加的本地玩家。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
virtual void AddPlayer(ULocalPlayer* LocalPlayer);
/**
* Removes a player from the UI subsystem.
* 从UI子系统中移除玩家。
* @param LocalPlayer The local player to remove. 要移除的本地玩家。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
virtual void RemovePlayer(ULocalPlayer* LocalPlayer);
/**
* Notifies the subsystem when a player is added.
* 当玩家被添加时通知子系统。
* @param LocalPlayer The added local player. 添加的本地玩家。
*/
virtual void NotifyPlayerAdded(ULocalPlayer* LocalPlayer);
/**
* Notifies the subsystem when a player is removed.
* 当玩家被移除时通知子系统。
* @param LocalPlayer The removed local player. 移除的本地玩家。
*/
virtual void NotifyPlayerRemoved(ULocalPlayer* LocalPlayer);
/**
* Notifies the subsystem when a player is destroyed.
* 当玩家被销毁时通知子系统。
* @param LocalPlayer The destroyed local player. 销毁的本地玩家。
*/
virtual void NotifyPlayerDestroyed(ULocalPlayer* LocalPlayer);
/**
* Registers a UI action binding for a widget (deprecated).
* 为控件注册UI动作绑定已弃用
* @param Target The target widget. 目标控件。
* @param InputAction The input action to bind. 要绑定的输入动作。
* @param bShouldDisplayInActionBar Whether to display in the action bar. 是否在动作栏中显示。
* @param Callback Delegate called when the action is executed. 动作执行时调用的委托。
* @param BindingHandle The handle for the binding. 绑定的句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="Target", DeprecatedFunction, DeprecationMessage="Use RegisterUIActionBindingForPlayer"))
void RegisterUIActionBinding(UCommonUserWidget* Target, FDataTableRowHandle InputAction, bool bShouldDisplayInActionBar, const FGUIS_UIActionExecutedDelegate& Callback,
FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Unregisters a UI action binding (deprecated).
* 取消注册UI动作绑定已弃用
* @param BindingHandle The handle of the binding to unregister. 要取消注册的绑定句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DeprecatedFunction, DeprecationMessage="Use UnregisterUIActionBindingForPlayer"))
void UnregisterBinding(UPARAM(ref) FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Registers a UI action binding for a specific player.
* 为特定玩家注册UI动作绑定。
* @param LocalPlayer The local player. 本地玩家。
* @param Target The target widget. 目标控件。
* @param InputAction The input action to bind. 要绑定的输入动作。
* @param bShouldDisplayInActionBar Whether to display in the action bar. 是否在动作栏中显示。
* @param Callback Delegate called when the action is executed. 动作执行时调用的委托。
* @param BindingHandle The handle for the binding. 绑定的句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="Target"))
virtual void RegisterUIActionBindingForPlayer(ULocalPlayer* LocalPlayer, UCommonUserWidget* Target, FDataTableRowHandle InputAction, bool bShouldDisplayInActionBar,
const FGUIS_UIActionExecutedDelegate& Callback,
FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Unregisters a UI action binding for a specific player.
* 为特定玩家取消注册UI动作绑定。
* @param LocalPlayer The local player. 本地玩家。
* @param BindingHandle The handle of the binding to unregister. 要取消注册的绑定句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
virtual void UnregisterUIActionBindingForPlayer(ULocalPlayer* LocalPlayer, UPARAM(ref) FGUIS_UIActionBindingHandle& BindingHandle);
/**
* Registers a UI context for a specific player.
* 为特定玩家注册UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param Context The UI context to register. 要注册的UI上下文。
* @param BindingHandle The handle for the context binding. 上下文绑定的句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="LocalPlayer"))
void RegisterUIContextForPlayer(ULocalPlayer* LocalPlayer, UGUIS_GameUIContext* Context, FGUIS_UIContextBindingHandle& BindingHandle);
/**
* Registers a UI context for an actor.
* 为演员注册UI上下文。
* @param Actor The actor to associate with the context. 与上下文关联的演员。
* @param Context The UI context to register. 要注册的UI上下文。
* @param BindingHandle The handle for the context binding. 上下文绑定的句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="Actor"))
void RegisterUIContextForActor(AActor* Actor, UGUIS_GameUIContext* Context, FGUIS_UIContextBindingHandle& BindingHandle);
/**
* Finds a UI context for a specific player.
* 为特定玩家查找UI上下文。
* @param LocalPlayer The local player. 本地玩家。
* @param ContextClass The class of the context to find. 要查找的上下文类。
* @param OutContext The found UI context (output). 找到的UI上下文输出
* @return True if the context was found, false otherwise. 如果找到上下文则返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="LocalPlayer", DeterminesOutputType="ContextClass", DynamicOutputParam="OutContext", ExpandBoolAsExecs="ReturnValue"))
bool FindUIContextForPlayer(ULocalPlayer* LocalPlayer, TSubclassOf<UGUIS_GameUIContext> ContextClass, UGUIS_GameUIContext*& OutContext);
/**
* Finds a UI context from a binding handle.
* 通过绑定句柄查找UI上下文。
* @param BindingHandle The binding handle to query. 要查询的绑定句柄。
* @param ContextClass The class of the context to find. 要查找的上下文类。
* @param OutContext The found UI context (output). 找到的UI上下文输出
* @return True if the context was found, false otherwise. 如果找到上下文则返回true否则返回false。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="LocalPlayer", DeterminesOutputType="ContextClass", DynamicOutputParam="OutContext", ExpandBoolAsExecs="ReturnValue"))
bool FindUIContextFromHandle(UPARAM(ref) FGUIS_UIContextBindingHandle& BindingHandle, TSubclassOf<UGUIS_GameUIContext> ContextClass, UGUIS_GameUIContext*& OutContext);
/**
* Unregisters a UI context for a specific player.
* 为特定玩家取消注册UI上下文。
* @param BindingHandle The handle of the context binding to unregister. 要取消注册的上下文绑定句柄。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta=(DefaultToSelf="LocalPlayer"))
void UnregisterUIContextForPlayer(UPARAM(ref) FGUIS_UIContextBindingHandle& BindingHandle);
protected:
/**
* Switches to a specified UI policy.
* 切换到指定的UI策略。
* @param InPolicy The UI policy to switch to. 要切换到的UI策略。
*/
void SwitchToPolicy(UGUIS_GameUIPolicy* InPolicy);
private:
/**
* The current UI policy in use.
* 当前使用的UI策略。
*/
UPROPERTY(Transient)
TObjectPtr<UGUIS_GameUIPolicy> CurrentPolicy = nullptr;
/**
* Array of UI action binding handles.
* UI动作绑定句柄的数组。
*/
TArray<FUIActionBindingHandle> BindingHandles;
};

View File

@@ -0,0 +1,54 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "NativeGameplayTags.h"
/**
* Namespace for modal action gameplay tags.
* 模态动作游戏标签的命名空间。
*/
namespace GUIS_GameModalActionTags
{
/**
* Tag for "Ok" modal action.
* "确定"模态动作的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ok);
/**
* Tag for "Cancel" modal action.
* "取消"模态动作的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Cancel);
/**
* Tag for "Yes" modal action.
* "是"模态动作的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Yes);
/**
* Tag for "No" modal action.
* "否"模态动作的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(No);
/**
* Tag for unknown modal action.
* 未知模态动作的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Unknown);
}
/**
* Namespace for UI layer gameplay tags.
* UI层游戏标签的命名空间。
*/
namespace GUIS_GameUILayerTags
{
/**
* Tag for modal UI layer.
* 模态UI层的标签。
*/
GENERICUISYSTEM_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Modal);
}

View File

@@ -0,0 +1,74 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "UI/Mobile/GUIS_SimulatedInputWidget.h"
#include "GUIS_JoystickWidget.generated.h"
class UImage;
class UObject;
struct FGeometry;
struct FPointerEvent;
/**
* A UMG wrapper for the lyra virtual joystick.
*
* This will calculate a 2D vector clamped between -1 and 1
* to input as a key value to the player, simulating a gamepad analog stick.
*
* This is intended for use with and Enhanced Input player.
*/
UCLASS()
class GENERICUISYSTEM_API UGUIS_JoystickWidget : public UGUIS_SimulatedInputWidget
{
GENERATED_BODY()
public:
UGUIS_JoystickWidget(const FObjectInitializer& ObjectInitializer);
//~ Begin UUserWidget
virtual FReply NativeOnTouchStarted(const FGeometry& InGeometry, const FPointerEvent& InGestureEvent) override;
virtual FReply NativeOnTouchMoved(const FGeometry& InGeometry, const FPointerEvent& InGestureEvent) override;
virtual FReply NativeOnTouchEnded(const FGeometry& InGeometry, const FPointerEvent& InGestureEvent) override;
virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
//~ End UUserWidget interface
protected:
/**
* Calculate the delta position of the current touch from the origin.
*
* Input the associated gamepad key on the player
*
* Move the foreground joystick image in association with the given input to give the appearance that it
* is moving along with the player's finger
*/
void HandleTouchDelta(const FGeometry& InGeometry, const FPointerEvent& InGestureEvent);
/** Flush any player input that has been injected and disable the use of this analog stick. */
void StopInputSimulation();
/** How far can the inner image of the joystick be moved? */
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="GUIS")
float StickRange = 50.0f;
/** Image to be used as the background of the joystick */
UPROPERTY(BlueprintReadWrite, Category="GUIS", meta = (BindWidget))
TObjectPtr<UImage> JoystickBackground;
/** Image to be used as the foreground of the joystick */
UPROPERTY(BlueprintReadWrite, Category="GUIS", meta = (BindWidget))
TObjectPtr<UImage> JoystickForeground;
/** Should we negate the Y-axis value of the joystick? This is common for "movement" sticks */
UPROPERTY(BlueprintReadWrite, Category="GUIS", EditAnywhere)
bool bNegateYAxis = false;
/** The origin of the touch. Set on NativeOnTouchStarted */
UPROPERTY(Transient)
FVector2D TouchOrigin = FVector2D::ZeroVector;
UPROPERTY(Transient)
FVector2D StickVector = FVector2D::ZeroVector;
};

View File

@@ -0,0 +1,93 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonUserWidget.h"
#include "InputCoreTypes.h"
#include "CommonUserWidget.h"
#include "GUIS_SimulatedInputWidget.generated.h"
class UEnhancedInputLocalPlayerSubsystem;
class UInputAction;
class UCommonHardwareVisibilityBorder;
class UEnhancedPlayerInput;
/**
* A UMG widget with base functionality to inject input (keys or input actions)
* to the enhanced input subsystem.
*/
UCLASS()
class GENERICUISYSTEM_API UGUIS_SimulatedInputWidget : public UCommonUserWidget
{
GENERATED_BODY()
public:
UGUIS_SimulatedInputWidget(const FObjectInitializer& ObjectInitializer);
//~ Begin UWidget
#if WITH_EDITOR
virtual const FText GetPaletteCategory() override;
#endif
//~ End UWidget interface
//~ Begin UUserWidget
virtual void NativeConstruct() override;
virtual void NativeDestruct() override;
virtual FReply NativeOnTouchEnded(const FGeometry& InGeometry, const FPointerEvent& InGestureEvent) override;
//~ End UUserWidget interface
/** Get the enhanced input subsystem based on the owning local player of this widget. Will return null if there is no owning player */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS")
UEnhancedInputLocalPlayerSubsystem* GetEnhancedInputSubsystem() const;
/** Get the current player input from the current input subsystem */
UEnhancedPlayerInput* GetPlayerInput() const;
/** */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS")
const UInputAction* GetAssociatedAction() const { return AssociatedAction; }
/** Returns the current key that will be used to input any values. */
UFUNCTION(BlueprintCallable, BlueprintPure, Category="GUIS")
FKey GetSimulatedKey() const { return KeyToSimulate; }
/**
* Injects the given vector as an input to the current simulated key.
* This calls "InputKey" on the current player.
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void InputKeyValue(const FVector& Value);
/**
* Injects the given vector as an input to the current simulated key.
* This calls "InputKey" on the current player.
*/
UFUNCTION(BlueprintCallable, Category="GUIS")
void InputKeyValue2D(const FVector2D& Value);
UFUNCTION(BlueprintCallable, Category="GUIS")
void FlushSimulatedInput();
protected:
/** Set the KeyToSimulate based on a query from enhanced input about what keys are mapped to the associated action */
void QueryKeyToSimulate();
/** Called whenever control mappings change, so we have a chance to adapt our own keys */
UFUNCTION()
void OnControlMappingsRebuilt();
/** The common visibility border will allow you to specify UI for only specific platforms if desired */
UPROPERTY(BlueprintReadWrite, Category="GUIS", meta = (BindWidget))
TObjectPtr<UCommonHardwareVisibilityBorder> CommonVisibilityBorder = nullptr;
/** The associated input action that we should simulate input for */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="GUIS")
TObjectPtr<const UInputAction> AssociatedAction = nullptr;
/** The Key to simulate input for in the case where none are currently bound to the associated action */
UPROPERTY(BlueprintReadOnly, EditAnywhere, Category="GUIS")
FKey FallbackBindingKey = EKeys::Gamepad_Right2D;
/** The key that should be input via InputKey on the player input */
FKey KeyToSimulate;
};

View File

@@ -0,0 +1,129 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "CommonActivatableWidget.h"
#include "GameplayTagContainer.h"
#include "GUIS_GameModalTypes.h"
#include "GUIS_GameModal.generated.h"
class UCommonTextBlock;
class UDynamicEntryBox;
class UGUIS_GameModalWidget;
/**
* Definition for a modal dialog.
* 模态对话框的定义。
*/
UCLASS(Abstract, BlueprintType, Blueprintable, Const)
class GENERICUISYSTEM_API UGUIS_ModalDefinition : public UObject
{
GENERATED_BODY()
public:
/**
* Header text for the modal.
* 模态对话框的标题文本。
*/
UPROPERTY(EditAnywhere, Category="GUIS", BlueprintReadWrite)
FText Header;
/**
* Body text for the modal.
* 模态对话框的正文文本。
*/
UPROPERTY(EditAnywhere, Category="GUIS", BlueprintReadWrite)
FText Body;
/**
* Widget class used to represent the modal.
* 表示模态对话框的小部件类。
*/
UPROPERTY(EditAnywhere, Category="GUIS", BlueprintReadWrite)
TSoftClassPtr<UGUIS_GameModalWidget> ModalWidget;
/**
* Map of modal actions to their configurations.
* 模态动作及其配置的映射。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GUIS", meta = (ForceInlineRow, Categories = "GUIS.Modal.Action"))
TMap<FGameplayTag, FGUIS_GameModalAction> ModalActions;
};
/**
* Base widget for modal dialogs.
* 模态对话框的基础小部件。
* @note Must bind a DynamicEntryBox named "EntryBox_Buttons" for button registration.
* @注意 必须绑定一个名为"EntryBox_Buttons"的DynamicEntryBox以注册按钮。
*/
UCLASS(Abstract, meta = (Category = "Generic UI"))
class GENERICUISYSTEM_API UGUIS_GameModalWidget : public UCommonActivatableWidget
{
GENERATED_BODY()
public:
/**
* Constructor for the modal widget.
* 模态小部件构造函数。
*/
UGUIS_GameModalWidget();
/**
* Sets up the modal with the provided definition.
* 使用提供的定义设置模态对话框。
* @param ModalDefinition The modal definition. 模态定义。
* @param ModalActionCallback Callback for modal actions. 模态动作回调。
*/
virtual void SetupModal(const UGUIS_ModalDefinition* ModalDefinition, FGUIS_ModalActionResultSignature ModalActionCallback);
/**
* Closes the modal with the specified result.
* 以指定结果关闭模态对话框。
* @param ModalActionResult The modal action result. 模态动作结果。
*/
UFUNCTION(BlueprintCallable, Category="GUIS", meta = (Categories = "UI.Modal.Action,GUIS.Modal.Action"))
void CloseModal(FGameplayTag ModalActionResult);
/**
* Terminates the modal.
* 终止模态对话框。
*/
virtual void KillModal();
protected:
/**
* Event to apply modal definition data to UI elements.
* 将模态定义数据应用于UI元素的事件。
* @param ModalDefinition The modal definition. 模态定义。
*/
UFUNCTION(BlueprintImplementableEvent, Category="GUIS")
void OnSetupModal(const UGUIS_ModalDefinition* ModalDefinition);
/**
* Callback for modal action results.
* 模态动作结果的回调。
*/
FGUIS_ModalActionResultSignature OnModalActionCallback;
private:
/**
* Dynamic entry box for modal buttons.
* 模态按钮的动态入口框。
*/
UPROPERTY(Meta = (BindWidget))
TObjectPtr<UDynamicEntryBox> EntryBox_Buttons;
/**
* Text block for the modal header.
* 模态标题的文本块。
*/
UPROPERTY(Meta = (BindWidget))
TObjectPtr<UCommonTextBlock> Text_Header;
/**
* Text block for the modal body.
* 模态正文的文本块。
*/
UPROPERTY(Meta = (BindWidget))
TObjectPtr<UCommonTextBlock> Text_Body;
};

View File

@@ -0,0 +1,50 @@
// Copyright 2025 https://yuewu.dev/en All Rights Reserved.
#pragma once
#include "GameplayTagContainer.h"
#include "Subsystems/LocalPlayerSubsystem.h"
#include "Engine/DataTable.h"
#include "GUIS_GameModalTypes.generated.h"
class UGUIS_ButtonBase;
class FSubsystemCollectionBase;
class UGUIS_ModalDefinition;
class UObject;
/**
* Delegate for modal action results.
* 模态动作结果的委托。
*/
DECLARE_DELEGATE_OneParam(FGUIS_ModalActionResultSignature, FGameplayTag /* Result */);
/**
* Configuration for a modal action.
* 模态动作的配置。
*/
USTRUCT(BlueprintType)
struct GENERICUISYSTEM_API FGUIS_GameModalAction
{
GENERATED_BODY()
/**
* Display text for the modal action.
* 模态动作的显示文本。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GUIS")
FText DisplayText;
/**
* Button widget class for the modal action.
* 模态动作的按钮小部件类。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GUIS", NoClear)
TSoftClassPtr<UGUIS_ButtonBase> ButtonType;
/**
* Input action associated with the modal action.
* 模态动作关联的输入动作。
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="GUIS", meta = (RowType = "/Script/CommonUI.CommonInputActionDataBase"))
FDataTableRowHandle InputAction;
};