Use attribute menu design backplate

This commit is contained in:
2026-04-26 21:51:08 +08:00
parent 8a29b6eeb7
commit 6b19fe2d81
12 changed files with 76 additions and 39 deletions

View File

@@ -98,8 +98,8 @@ void UPHYAttributeGroupWidget::BuildNativeWidgetTree()
} }
UBorder* RootBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("RootBorder")); UBorder* RootBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("RootBorder"));
RootBorder->SetBrush(MakeAttributeGroupBrush(AttributeGroupPaperTexturePath, FVector2D(500.0f, 260.0f), FLinearColor(0.99f, 0.97f, 0.89f, 0.76f), ESlateBrushDrawType::Box, FMargin(0.045f))); RootBorder->SetBrushColor(FLinearColor::Transparent);
RootBorder->SetPadding(FMargin(14.0f, 10.0f)); RootBorder->SetPadding(FMargin(14.0f, 8.0f));
WidgetTree->RootWidget = RootBorder; WidgetTree->RootWidget = RootBorder;
UVerticalBox* RootBox = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("RootBox")); UVerticalBox* RootBox = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("RootBox"));

View File

@@ -41,6 +41,7 @@ namespace
{ {
constexpr float AttributeDesignWidth = 1693.0f; constexpr float AttributeDesignWidth = 1693.0f;
constexpr float AttributeDesignHeight = 942.0f; constexpr float AttributeDesignHeight = 942.0f;
const TCHAR* const AttributeBackplateTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_AttributeBackplate.T_PHY_UI_AttributeBackplate");
const TCHAR* const AttributePaperTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.T_PHY_UI_PaperPanel"); const TCHAR* const AttributePaperTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.T_PHY_UI_PaperPanel");
const TCHAR* const AttributeJadeTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.T_PHY_UI_JadePanel"); const TCHAR* const AttributeJadeTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.T_PHY_UI_JadePanel");
const TCHAR* const AttributeCinnabarTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.T_PHY_UI_CinnabarTab"); const TCHAR* const AttributeCinnabarTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.T_PHY_UI_CinnabarTab");
@@ -60,6 +61,14 @@ namespace
return Brush; return Brush;
} }
FSlateBrush MakeAttributeTransparentBrush()
{
FSlateBrush Brush;
Brush.DrawAs = ESlateBrushDrawType::NoDrawType;
Brush.TintColor = FSlateColor(FLinearColor::Transparent);
return Brush;
}
void AddAttributeMenuCanvasChild(UCanvasPanel* CanvasPanel, UWidget* ChildWidget, const FVector2D Position, const FVector2D Size, const int32 ZOrder = 0) void AddAttributeMenuCanvasChild(UCanvasPanel* CanvasPanel, UWidget* ChildWidget, const FVector2D Position, const FVector2D Size, const int32 ZOrder = 0)
{ {
if (!CanvasPanel || !ChildWidget) if (!CanvasPanel || !ChildWidget)
@@ -88,16 +97,15 @@ namespace
UButton* CreateAttributeNavButton(UWidgetTree* WidgetTree, const FName WidgetName, const FText Label, const bool bActive) UButton* CreateAttributeNavButton(UWidgetTree* WidgetTree, const FName WidgetName, const FText Label, const bool bActive)
{ {
UButton* Button = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), WidgetName); UButton* Button = WidgetTree->ConstructWidget<UButton>(UButton::StaticClass(), WidgetName);
const FLinearColor NormalTint = bActive ? FLinearColor(1.0f, 0.95f, 0.82f, 0.98f) : FLinearColor(0.95f, 0.91f, 0.80f, 0.30f);
const FLinearColor HoverTint = bActive ? FLinearColor(1.0f, 0.98f, 0.88f, 1.0f) : FLinearColor(0.40f, 0.58f, 0.50f, 0.42f);
FButtonStyle ButtonStyle; FButtonStyle ButtonStyle;
ButtonStyle.SetNormal(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(180.0f, 72.0f), NormalTint)); const FSlateBrush TransparentBrush = MakeAttributeTransparentBrush();
ButtonStyle.SetHovered(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(180.0f, 72.0f), HoverTint)); ButtonStyle.SetNormal(TransparentBrush);
ButtonStyle.SetPressed(MakeAttributeMenuBrush(AttributeCinnabarTexturePath, FVector2D(180.0f, 72.0f), FLinearColor(0.72f, 0.25f, 0.14f, 0.95f))); ButtonStyle.SetHovered(TransparentBrush);
ButtonStyle.SetPressed(TransparentBrush);
Button->SetStyle(ButtonStyle); Button->SetStyle(ButtonStyle);
UTextBlock* ButtonText = CreateAttributeMenuText(WidgetTree, NAME_None, Label, 24, bActive ? FLinearColor(0.04f, 0.44f, 0.38f, 1.0f) : FLinearColor(0.30f, 0.28f, 0.22f, 1.0f)); UTextBlock* ButtonText = CreateAttributeMenuText(WidgetTree, NAME_None, Label, 25, bActive ? FLinearColor(0.04f, 0.72f, 0.66f, 1.0f) : FLinearColor(0.34f, 0.32f, 0.26f, 0.62f));
Button->SetContent(ButtonText); Button->SetContent(ButtonText);
return Button; return Button;
} }
@@ -301,11 +309,11 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree()
DesignSizeBox->AddChild(DesignCanvas); DesignSizeBox->AddChild(DesignCanvas);
UBorder* BackgroundPanel = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("BackgroundPanel")); UBorder* BackgroundPanel = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("BackgroundPanel"));
BackgroundPanel->SetBrush(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(AttributeDesignWidth, AttributeDesignHeight), FLinearColor(0.96f, 0.93f, 0.84f, 1.0f), ESlateBrushDrawType::Box, FMargin(0.035f))); BackgroundPanel->SetBrush(MakeAttributeMenuBrush(AttributeBackplateTexturePath, FVector2D(AttributeDesignWidth, AttributeDesignHeight), FLinearColor::White, ESlateBrushDrawType::Image, FMargin(0.0f)));
AddAttributeMenuCanvasChild(DesignCanvas, BackgroundPanel, FVector2D(0.0f, 0.0f), FVector2D(AttributeDesignWidth, AttributeDesignHeight), 0); AddAttributeMenuCanvasChild(DesignCanvas, BackgroundPanel, FVector2D(0.0f, 0.0f), FVector2D(AttributeDesignWidth, AttributeDesignHeight), 0);
UBorder* TitlePlaque = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("TitlePlaque")); UBorder* TitlePlaque = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("TitlePlaque"));
TitlePlaque->SetBrush(MakeAttributeMenuBrush(AttributeJadeTexturePath, FVector2D(390.0f, 88.0f), FLinearColor(0.18f, 0.34f, 0.30f, 0.98f))); TitlePlaque->SetBrushColor(FLinearColor::Transparent);
TitlePlaque->SetPadding(FMargin(78.0f, 0.0f, 0.0f, 4.0f)); TitlePlaque->SetPadding(FMargin(78.0f, 0.0f, 0.0f, 4.0f));
AddAttributeMenuCanvasChild(DesignCanvas, TitlePlaque, FVector2D(0.0f, 7.0f), FVector2D(402.0f, 88.0f), 3); AddAttributeMenuCanvasChild(DesignCanvas, TitlePlaque, FVector2D(0.0f, 7.0f), FVector2D(402.0f, 88.0f), 3);
@@ -322,17 +330,18 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree()
AddAttributeMenuCanvasChild(DesignCanvas, BagNavButton, FVector2D(1188.0f, 11.0f), FVector2D(155.0f, 70.0f), 3); AddAttributeMenuCanvasChild(DesignCanvas, BagNavButton, FVector2D(1188.0f, 11.0f), FVector2D(155.0f, 70.0f), 3);
UBorder* HeaderRule = CreateAttributeMenuLine(WidgetTree, TEXT("HeaderRule")); UBorder* HeaderRule = CreateAttributeMenuLine(WidgetTree, TEXT("HeaderRule"));
AddAttributeMenuCanvasChild(DesignCanvas, HeaderRule, FVector2D(392.0f, 85.0f), FVector2D(1245.0f, 18.0f), 2); HeaderRule->SetBrushColor(FLinearColor::Transparent);
AddAttributeMenuCanvasChild(DesignCanvas, HeaderRule, FVector2D(392.0f, 85.0f), FVector2D(1245.0f, 18.0f), 1);
SummaryWidget = WidgetTree->ConstructWidget<UPHYAttributeSummaryWidget>(UPHYAttributeSummaryWidget::StaticClass(), TEXT("SummaryWidget")); SummaryWidget = WidgetTree->ConstructWidget<UPHYAttributeSummaryWidget>(UPHYAttributeSummaryWidget::StaticClass(), TEXT("SummaryWidget"));
UBorder* SummaryPanel = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("SummaryPanel")); UBorder* SummaryPanel = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("SummaryPanel"));
SummaryPanel->SetBrush(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(462.0f, 710.0f), FLinearColor(0.98f, 0.96f, 0.88f, 0.96f), ESlateBrushDrawType::Box, FMargin(0.085f))); SummaryPanel->SetBrushColor(FLinearColor::Transparent);
SummaryPanel->SetPadding(FMargin(27.0f, 24.0f, 27.0f, 22.0f)); SummaryPanel->SetPadding(FMargin(27.0f, 24.0f, 27.0f, 22.0f));
SummaryPanel->SetContent(SummaryWidget); SummaryPanel->SetContent(SummaryWidget);
AddAttributeMenuCanvasChild(DesignCanvas, SummaryPanel, FVector2D(35.0f, 103.0f), FVector2D(462.0f, 710.0f), 2); AddAttributeMenuCanvasChild(DesignCanvas, SummaryPanel, FVector2D(35.0f, 103.0f), FVector2D(462.0f, 710.0f), 2);
UBorder* PageBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("PageBorder")); UBorder* PageBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("PageBorder"));
PageBorder->SetBrush(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(1120.0f, 735.0f), FLinearColor(0.98f, 0.96f, 0.88f, 0.92f), ESlateBrushDrawType::Box, FMargin(0.055f))); PageBorder->SetBrushColor(FLinearColor::Transparent);
PageBorder->SetPadding(FMargin(28.0f, 22.0f, 28.0f, 24.0f)); PageBorder->SetPadding(FMargin(28.0f, 22.0f, 28.0f, 24.0f));
AddAttributeMenuCanvasChild(DesignCanvas, PageBorder, FVector2D(515.0f, 103.0f), FVector2D(1120.0f, 735.0f), 2); AddAttributeMenuCanvasChild(DesignCanvas, PageBorder, FVector2D(515.0f, 103.0f), FVector2D(1120.0f, 735.0f), 2);

View File

@@ -5,9 +5,12 @@
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributePageWidget) #include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributePageWidget)
#include "Blueprint/WidgetTree.h" #include "Blueprint/WidgetTree.h"
#include "Components/Border.h"
#include "Components/ScrollBox.h" #include "Components/ScrollBox.h"
#include "Components/ScrollBoxSlot.h" #include "Components/ScrollBoxSlot.h"
#include "Components/TextBlock.h" #include "Components/TextBlock.h"
#include "Components/UniformGridPanel.h"
#include "Components/UniformGridSlot.h"
#include "Components/VerticalBox.h" #include "Components/VerticalBox.h"
#include "Components/VerticalBoxSlot.h" #include "Components/VerticalBoxSlot.h"
#include "Fonts/SlateFontInfo.h" #include "Fonts/SlateFontInfo.h"
@@ -40,9 +43,10 @@ void UPHYAttributePageWidget::SetPageTitle(FText InPageTitle)
void UPHYAttributePageWidget::ClearGroups() void UPHYAttributePageWidget::ClearGroups()
{ {
if (GroupsBox) GroupCount = 0;
if (GroupsGrid)
{ {
GroupsBox->ClearChildren(); GroupsGrid->ClearChildren();
} }
} }
@@ -50,16 +54,22 @@ UPHYAttributeGroupWidget* UPHYAttributePageWidget::AddGroup(FText GroupTitle)
{ {
BuildNativeWidgetTree(); BuildNativeWidgetTree();
if (!GroupsBox || !WidgetTree) if (!GroupsGrid || !WidgetTree)
{ {
return nullptr; return nullptr;
} }
UPHYAttributeGroupWidget* GroupWidget = WidgetTree->ConstructWidget<UPHYAttributeGroupWidget>(UPHYAttributeGroupWidget::StaticClass()); UPHYAttributeGroupWidget* GroupWidget = WidgetTree->ConstructWidget<UPHYAttributeGroupWidget>(UPHYAttributeGroupWidget::StaticClass());
GroupWidget->SetGroupTitle(MoveTemp(GroupTitle)); GroupWidget->SetGroupTitle(MoveTemp(GroupTitle));
if (UVerticalBoxSlot* GroupSlot = GroupsBox->AddChildToVerticalBox(GroupWidget)) UBorder* GroupPadding = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass());
GroupPadding->SetBrushColor(FLinearColor(1.0f, 1.0f, 1.0f, 0.0f));
GroupPadding->SetPadding(FMargin(0.0f, 0.0f, 14.0f, 14.0f));
GroupPadding->SetContent(GroupWidget);
const int32 GroupIndex = GroupCount++;
if (UUniformGridSlot* GroupSlot = GroupsGrid->AddChildToUniformGrid(GroupPadding, GroupIndex / 2, GroupIndex % 2))
{ {
GroupSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 12.0f)); GroupSlot->SetHorizontalAlignment(HAlign_Fill);
GroupSlot->SetVerticalAlignment(VAlign_Top);
} }
return GroupWidget; return GroupWidget;
} }
@@ -71,7 +81,7 @@ void UPHYAttributePageWidget::BuildNativeWidgetTree()
WidgetTree = NewObject<UWidgetTree>(this, TEXT("WidgetTree"), RF_Transient); WidgetTree = NewObject<UWidgetTree>(this, TEXT("WidgetTree"), RF_Transient);
} }
if (WidgetTree->RootWidget && TitleText && GroupsScrollBox && GroupsBox) if (WidgetTree->RootWidget && TitleText && GroupsScrollBox && GroupsGrid)
{ {
return; return;
} }
@@ -80,11 +90,12 @@ void UPHYAttributePageWidget::BuildNativeWidgetTree()
WidgetTree->RootWidget = RootBox; WidgetTree->RootWidget = RootBox;
TitleText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("TitleText")); TitleText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("TitleText"));
TitleText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 22)); TitleText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 12));
TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.42f, 0.18f, 0.08f, 1.0f))); TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.42f, 0.18f, 0.08f, 0.0f)));
TitleText->SetVisibility(ESlateVisibility::Collapsed);
if (UVerticalBoxSlot* TitleSlot = RootBox->AddChildToVerticalBox(TitleText)) if (UVerticalBoxSlot* TitleSlot = RootBox->AddChildToVerticalBox(TitleText))
{ {
TitleSlot->SetPadding(FMargin(2.0f, 0.0f, 0.0f, 12.0f)); TitleSlot->SetPadding(FMargin(0.0f));
} }
GroupsScrollBox = WidgetTree->ConstructWidget<UScrollBox>(UScrollBox::StaticClass(), TEXT("GroupsScrollBox")); GroupsScrollBox = WidgetTree->ConstructWidget<UScrollBox>(UScrollBox::StaticClass(), TEXT("GroupsScrollBox"));
@@ -93,8 +104,8 @@ void UPHYAttributePageWidget::BuildNativeWidgetTree()
ScrollSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); ScrollSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
} }
GroupsBox = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("GroupsBox")); GroupsGrid = WidgetTree->ConstructWidget<UUniformGridPanel>(UUniformGridPanel::StaticClass(), TEXT("GroupsGrid"));
if (UScrollBoxSlot* GroupsSlot = Cast<UScrollBoxSlot>(GroupsScrollBox->AddChild(GroupsBox))) if (UScrollBoxSlot* GroupsSlot = Cast<UScrollBoxSlot>(GroupsScrollBox->AddChild(GroupsGrid)))
{ {
GroupsSlot->SetPadding(FMargin(0.0f)); GroupsSlot->SetPadding(FMargin(0.0f));
} }

View File

@@ -34,7 +34,7 @@ namespace
Brush.DrawAs = ESlateBrushDrawType::Box; Brush.DrawAs = ESlateBrushDrawType::Box;
Brush.Margin = FMargin(0.08f); Brush.Margin = FMargin(0.08f);
Brush.ImageSize = FVector2D(512.0f, 64.0f); Brush.ImageSize = FVector2D(512.0f, 64.0f);
Brush.TintColor = FSlateColor(FLinearColor(1.0f, 1.0f, 1.0f, 0.88f)); Brush.TintColor = FSlateColor(FLinearColor(1.0f, 0.98f, 0.90f, 0.24f));
if (UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, AttributeResourceRowTexturePath)) if (UTexture2D* Texture = LoadObject<UTexture2D>(nullptr, AttributeResourceRowTexturePath))
{ {
Brush.SetResourceObject(Texture); Brush.SetResourceObject(Texture);

View File

@@ -75,8 +75,8 @@ void UPHYAttributeRowWidget::BuildNativeWidgetTree()
} }
RowBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("RowBorder")); RowBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("RowBorder"));
RowBorder->SetBrush(MakeAttributeRowBrush(AttributeRowTexturePath, FVector2D(512.0f, 64.0f), FLinearColor(1.0f, 0.98f, 0.90f, 0.78f))); RowBorder->SetBrush(MakeAttributeRowBrush(AttributeRowTexturePath, FVector2D(512.0f, 64.0f), FLinearColor(1.0f, 0.98f, 0.90f, 0.42f)));
RowBorder->SetPadding(FMargin(11.0f, 5.0f)); RowBorder->SetPadding(FMargin(9.0f, 3.0f));
WidgetTree->RootWidget = RowBorder; WidgetTree->RootWidget = RowBorder;
RowBox = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass(), TEXT("RowBox")); RowBox = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass(), TEXT("RowBox"));

View File

@@ -38,6 +38,16 @@ namespace
} }
return Brush; return Brush;
} }
FText MakeAttributeSummaryDisplayName(const FText& SourceName)
{
FString NameString = SourceName.IsEmpty() ? FString(TEXT("修行者")) : SourceName.ToString();
if (NameString.Len() > 10)
{
NameString = NameString.Left(10) + TEXT("...");
}
return FText::FromString(NameString);
}
} }
UPHYAttributeSummaryWidget::UPHYAttributeSummaryWidget(const FObjectInitializer& ObjectInitializer) UPHYAttributeSummaryWidget::UPHYAttributeSummaryWidget(const FObjectInitializer& ObjectInitializer)
@@ -147,8 +157,8 @@ void UPHYAttributeSummaryWidget::BuildNativeWidgetTree()
} }
UBorder* PortraitBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("PortraitBorder")); UBorder* PortraitBorder = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("PortraitBorder"));
PortraitBorder->SetBrush(MakeAttributeSummaryBrush(AttributeSummaryPortraitTexturePath, FVector2D(380.0f, 438.0f), FLinearColor(0.97f, 0.98f, 0.94f, 0.96f), ESlateBrushDrawType::Box, FMargin(0.075f))); PortraitBorder->SetBrush(MakeAttributeSummaryBrush(AttributeSummaryPortraitTexturePath, FVector2D(380.0f, 438.0f), FLinearColor(1.0f, 1.0f, 1.0f, 0.98f), ESlateBrushDrawType::Image, FMargin(0.0f)));
PortraitBorder->SetPadding(FMargin(10.0f)); PortraitBorder->SetPadding(FMargin(0.0f));
PortraitSizeBox->AddChild(PortraitBorder); PortraitSizeBox->AddChild(PortraitBorder);
ResourceBox = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("ResourceBox")); ResourceBox = WidgetTree->ConstructWidget<UVerticalBox>(UVerticalBox::StaticClass(), TEXT("ResourceBox"));
@@ -168,7 +178,7 @@ void UPHYAttributeSummaryWidget::UpdateSummaryWidgets()
{ {
if (PlayerNameText) if (PlayerNameText)
{ {
PlayerNameText->SetText(PlayerName.IsEmpty() ? FText::FromString(TEXT("修行者")) : PlayerName); PlayerNameText->SetText(MakeAttributeSummaryDisplayName(PlayerName));
} }
if (LevelText) if (LevelText)
{ {

View File

@@ -9,6 +9,7 @@
class UPHYAttributeGroupWidget; class UPHYAttributeGroupWidget;
class UScrollBox; class UScrollBox;
class UTextBlock; class UTextBlock;
class UUniformGridPanel;
class UVerticalBox; class UVerticalBox;
/** /**
@@ -64,5 +65,8 @@ protected:
/** @brief 分组容器。 */ /** @brief 分组容器。 */
UPROPERTY(Transient) UPROPERTY(Transient)
TObjectPtr<UVerticalBox> GroupsBox; TObjectPtr<UUniformGridPanel> GroupsGrid;
/** @brief 当前分页分组数量,用于双列排版。 */
int32 GroupCount = 0;
}; };