From 8a29b6eeb7eae507172d9c2e0b85ac77c6132901 Mon Sep 17 00:00:00 2001 From: cit110 <840418418@qq.com> Date: Sun, 26 Apr 2026 21:29:17 +0800 Subject: [PATCH] Improve attribute menu visual style --- .../Textures/T_PHY_UI_CinnabarTab.uasset | 3 + .../Textures/T_PHY_UI_GoldRule.uasset | 3 + .../Textures/T_PHY_UI_JadePanel.uasset | 3 + .../Textures/T_PHY_UI_PaperPanel.uasset | 3 + .../Textures/T_PHY_UI_PortraitFrame.uasset | 3 + .../Textures/T_PHY_UI_RowStrip.uasset | 3 + .../Private/UI/PHYAttributeGroupWidget.cpp | 39 ++- .../PHY/Private/UI/PHYAttributeMenuWidget.cpp | 260 ++++++++++++++---- .../UI/PHYAttributeOverviewPageWidget.cpp | 7 +- .../UI/PHYAttributeResourceBarWidget.cpp | 61 +++- .../PHY/Private/UI/PHYAttributeRowWidget.cpp | 53 +++- .../Private/UI/PHYAttributeSummaryWidget.cpp | 96 +++++-- Source/PHY/Public/UI/PHYAttributeMenuWidget.h | 13 + Source/PHY/Public/UI/PHYAttributeRowWidget.h | 5 + 14 files changed, 438 insertions(+), 114 deletions(-) create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.uasset create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.uasset create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.uasset create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.uasset create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_PortraitFrame.uasset create mode 100644 Content/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.uasset diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.uasset new file mode 100644 index 0000000..4bbb5ee --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:860f59a61b6e462f5fefb161d959adc496bc04fec6b92daa7c2016d014e9ea2d +size 61917 diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.uasset new file mode 100644 index 0000000..d6866de --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c7fb6d42554088755838fbe0ec2f8ad077d96fb5a82e6431d65ba66f0441499f +size 6355 diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.uasset new file mode 100644 index 0000000..8a35e8b --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c2468a0b74ad5580913aac30379887b7b683eee62821536846eb2dd92c7a631 +size 338779 diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.uasset new file mode 100644 index 0000000..e606501 --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edd62461ce723ab4af51cb73d43d408e15fdfe4db3a1ae5723306eb96699555e +size 1194864 diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PortraitFrame.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PortraitFrame.uasset new file mode 100644 index 0000000..b31a519 --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_PortraitFrame.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd743d1c73ccdb2e40fd8083b1fcc810aab89e6c53cb989a98e41c2aa628f919 +size 85437 diff --git a/Content/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.uasset b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.uasset new file mode 100644 index 0000000..fc80a1c --- /dev/null +++ b/Content/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.uasset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1bf7b3fc64a5d3bbc66d1387fc88fd701084d03d02650374773b839e74ed8d79 +size 11058 diff --git a/Source/PHY/Private/UI/PHYAttributeGroupWidget.cpp b/Source/PHY/Private/UI/PHYAttributeGroupWidget.cpp index 25f4bce..a34debc 100644 --- a/Source/PHY/Private/UI/PHYAttributeGroupWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeGroupWidget.cpp @@ -9,11 +9,33 @@ #include "Components/TextBlock.h" #include "Components/VerticalBox.h" #include "Components/VerticalBoxSlot.h" +#include "Engine/Texture2D.h" #include "Fonts/SlateFontInfo.h" #include "Styling/CoreStyle.h" +#include "Styling/SlateBrush.h" #include "UI/PHYAttributeRowWidget.h" #include "Widgets/SWidget.h" +namespace +{ + const TCHAR* const AttributeGroupPaperTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_PaperPanel.T_PHY_UI_PaperPanel"); + const TCHAR* const AttributeGroupGoldRuleTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.T_PHY_UI_GoldRule"); + + FSlateBrush MakeAttributeGroupBrush(const TCHAR* TexturePath, const FVector2D ImageSize, const FLinearColor Tint, const ESlateBrushDrawType::Type DrawAs = ESlateBrushDrawType::Box, const FMargin Margin = FMargin(0.08f)) + { + FSlateBrush Brush; + Brush.DrawAs = DrawAs; + Brush.Margin = Margin; + Brush.ImageSize = ImageSize; + Brush.TintColor = FSlateColor(Tint); + if (UTexture2D* Texture = LoadObject(nullptr, TexturePath)) + { + Brush.SetResourceObject(Texture); + } + return Brush; + } +} + UPHYAttributeGroupWidget::UPHYAttributeGroupWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { @@ -58,7 +80,7 @@ UPHYAttributeRowWidget* UPHYAttributeGroupWidget::AddRow(FText Label, FText Valu RowWidget->SetRow(MoveTemp(Label), MoveTemp(Value), bCanUpgrade); if (UVerticalBoxSlot* RowSlot = RowsBox->AddChildToVerticalBox(RowWidget)) { - RowSlot->SetPadding(FMargin(0.0f, 1.0f)); + RowSlot->SetPadding(FMargin(0.0f, 2.0f)); } return RowWidget; } @@ -76,7 +98,7 @@ void UPHYAttributeGroupWidget::BuildNativeWidgetTree() } UBorder* RootBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RootBorder")); - RootBorder->SetBrushColor(FLinearColor(0.98f, 0.94f, 0.84f, 0.58f)); + RootBorder->SetBrush(MakeAttributeGroupBrush(AttributeGroupPaperTexturePath, FVector2D(500.0f, 260.0f), FLinearColor(0.99f, 0.97f, 0.89f, 0.76f), ESlateBrushDrawType::Box, FMargin(0.045f))); RootBorder->SetPadding(FMargin(14.0f, 10.0f)); WidgetTree->RootWidget = RootBorder; @@ -84,11 +106,18 @@ void UPHYAttributeGroupWidget::BuildNativeWidgetTree() RootBorder->SetContent(RootBox); TitleText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("TitleText")); - TitleText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 17)); - TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.56f, 0.18f, 0.10f, 1.0f))); + TitleText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 19)); + TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.48f, 0.27f, 0.11f, 1.0f))); if (UVerticalBoxSlot* TitleSlot = RootBox->AddChildToVerticalBox(TitleText)) { - TitleSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 6.0f)); + TitleSlot->SetPadding(FMargin(2.0f, 0.0f, 0.0f, 2.0f)); + } + + UBorder* HeaderRule = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("HeaderRule")); + HeaderRule->SetBrush(MakeAttributeGroupBrush(AttributeGroupGoldRuleTexturePath, FVector2D(512.0f, 24.0f), FLinearColor(0.87f, 0.69f, 0.34f, 0.72f), ESlateBrushDrawType::Image, FMargin(0.0f))); + if (UVerticalBoxSlot* RuleSlot = RootBox->AddChildToVerticalBox(HeaderRule)) + { + RuleSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 8.0f)); } RowsBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("RowsBox")); diff --git a/Source/PHY/Private/UI/PHYAttributeMenuWidget.cpp b/Source/PHY/Private/UI/PHYAttributeMenuWidget.cpp index 1d2e610..9c43833 100644 --- a/Source/PHY/Private/UI/PHYAttributeMenuWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeMenuWidget.cpp @@ -11,18 +11,26 @@ #include "Blueprint/WidgetTree.h" #include "Components/Border.h" #include "Components/Button.h" +#include "Components/CanvasPanel.h" +#include "Components/CanvasPanelSlot.h" #include "Components/HorizontalBox.h" #include "Components/HorizontalBoxSlot.h" #include "Components/SafeZone.h" +#include "Components/ScaleBox.h" #include "Components/SizeBox.h" +#include "Components/Spacer.h" #include "Components/TextBlock.h" #include "Components/VerticalBox.h" #include "Components/VerticalBoxSlot.h" #include "Components/WidgetSwitcher.h" +#include "Engine/Texture2D.h" #include "Fonts/SlateFontInfo.h" #include "GameFramework/PlayerController.h" #include "Player/PHYPlayerState.h" #include "Styling/CoreStyle.h" +#include "Styling/SlateBrush.h" +#include "Styling/SlateTypes.h" +#include "UI/PHYAttributeResourceBarWidget.h" #include "UI/PHYAttributeOverviewPageWidget.h" #include "UI/PHYAttributeSummaryWidget.h" #include "UI/PHYCombatDerivedAttributePageWidget.h" @@ -31,6 +39,93 @@ namespace { + constexpr float AttributeDesignWidth = 1693.0f; + constexpr float AttributeDesignHeight = 942.0f; + 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 AttributeCinnabarTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.T_PHY_UI_CinnabarTab"); + const TCHAR* const AttributeGoldRuleTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_GoldRule.T_PHY_UI_GoldRule"); + + FSlateBrush MakeAttributeMenuBrush(const TCHAR* TexturePath, const FVector2D ImageSize, const FLinearColor Tint, const ESlateBrushDrawType::Type DrawAs = ESlateBrushDrawType::Box, const FMargin Margin = FMargin(0.08f)) + { + FSlateBrush Brush; + Brush.DrawAs = DrawAs; + Brush.Margin = Margin; + Brush.ImageSize = ImageSize; + Brush.TintColor = FSlateColor(Tint); + if (UTexture2D* Texture = LoadObject(nullptr, TexturePath)) + { + Brush.SetResourceObject(Texture); + } + return Brush; + } + + void AddAttributeMenuCanvasChild(UCanvasPanel* CanvasPanel, UWidget* ChildWidget, const FVector2D Position, const FVector2D Size, const int32 ZOrder = 0) + { + if (!CanvasPanel || !ChildWidget) + { + return; + } + + if (UCanvasPanelSlot* CanvasSlot = CanvasPanel->AddChildToCanvas(ChildWidget)) + { + CanvasSlot->SetAutoSize(false); + CanvasSlot->SetPosition(Position); + CanvasSlot->SetSize(Size); + CanvasSlot->SetZOrder(ZOrder); + } + } + + UTextBlock* CreateAttributeMenuText(UWidgetTree* WidgetTree, const FName WidgetName, const FText Text, const int32 FontSize, const FLinearColor Color) + { + UTextBlock* TextBlock = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), WidgetName); + TextBlock->SetText(Text); + TextBlock->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), FontSize)); + TextBlock->SetColorAndOpacity(FSlateColor(Color)); + return TextBlock; + } + + UButton* CreateAttributeNavButton(UWidgetTree* WidgetTree, const FName WidgetName, const FText Label, const bool bActive) + { + UButton* Button = WidgetTree->ConstructWidget(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; + ButtonStyle.SetNormal(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(180.0f, 72.0f), NormalTint)); + ButtonStyle.SetHovered(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(180.0f, 72.0f), HoverTint)); + ButtonStyle.SetPressed(MakeAttributeMenuBrush(AttributeCinnabarTexturePath, FVector2D(180.0f, 72.0f), FLinearColor(0.72f, 0.25f, 0.14f, 0.95f))); + 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)); + Button->SetContent(ButtonText); + return Button; + } + + void ApplyAttributeSubTabStyle(UButton* Button, const bool bActive) + { + if (!Button) + { + return; + } + + FButtonStyle ButtonStyle; + const FLinearColor NormalTint = bActive ? FLinearColor(0.16f, 0.46f, 0.39f, 0.92f) : FLinearColor(0.90f, 0.83f, 0.66f, 0.76f); + const FLinearColor HoverTint = bActive ? FLinearColor(0.19f, 0.54f, 0.46f, 0.95f) : FLinearColor(0.96f, 0.89f, 0.72f, 0.90f); + ButtonStyle.SetNormal(MakeAttributeMenuBrush(bActive ? AttributeJadeTexturePath : AttributePaperTexturePath, FVector2D(210.0f, 54.0f), NormalTint)); + ButtonStyle.SetHovered(MakeAttributeMenuBrush(bActive ? AttributeJadeTexturePath : AttributePaperTexturePath, FVector2D(210.0f, 54.0f), HoverTint)); + ButtonStyle.SetPressed(MakeAttributeMenuBrush(AttributeCinnabarTexturePath, FVector2D(210.0f, 54.0f), FLinearColor(0.72f, 0.24f, 0.14f, 0.92f))); + Button->SetStyle(ButtonStyle); + Button->SetBackgroundColor(FLinearColor::White); + } + + UBorder* CreateAttributeMenuLine(UWidgetTree* WidgetTree, const FName WidgetName) + { + UBorder* Line = WidgetTree->ConstructWidget(UBorder::StaticClass(), WidgetName); + Line->SetBrush(MakeAttributeMenuBrush(AttributeGoldRuleTexturePath, FVector2D(512.0f, 24.0f), FLinearColor(1.0f, 0.86f, 0.44f, 0.80f), ESlateBrushDrawType::Image, FMargin(0.0f))); + return Line; + } + TArray MakeTrackedAttributes() { return { @@ -180,7 +275,7 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree() WidgetTree = NewObject(this, TEXT("WidgetTree"), RF_Transient); } - if (WidgetTree->RootWidget && SummaryWidget && PageSwitcher && OverviewPage && CombatPage && ElementPage) + if (WidgetTree->RootWidget && SummaryWidget && PageSwitcher && OverviewPage && CombatPage && ElementPage && HeaderHealthBar && HeaderManaBar && HeaderStaminaBar) { return; } @@ -188,60 +283,107 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree() USafeZone* RootSafeZone = WidgetTree->ConstructWidget(USafeZone::StaticClass(), TEXT("RootSafeZone")); WidgetTree->RootWidget = RootSafeZone; - UBorder* RootBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RootBorder")); - RootBorder->SetBrushColor(FLinearColor(0.83f, 0.78f, 0.64f, 0.94f)); - RootBorder->SetPadding(FMargin(28.0f)); - RootSafeZone->SetContent(RootBorder); + UBorder* RootWash = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RootWash")); + RootWash->SetBrushColor(FLinearColor(0.08f, 0.10f, 0.09f, 0.96f)); + RootSafeZone->SetContent(RootWash); - UHorizontalBox* MainBox = WidgetTree->ConstructWidget(UHorizontalBox::StaticClass(), TEXT("MainBox")); - RootBorder->SetContent(MainBox); + UScaleBox* DesignScaleBox = WidgetTree->ConstructWidget(UScaleBox::StaticClass(), TEXT("DesignScaleBox")); + DesignScaleBox->SetStretch(EStretch::ScaleToFit); + DesignScaleBox->SetStretchDirection(EStretchDirection::Both); + RootWash->SetContent(DesignScaleBox); + + USizeBox* DesignSizeBox = WidgetTree->ConstructWidget(USizeBox::StaticClass(), TEXT("DesignSizeBox")); + DesignSizeBox->SetWidthOverride(AttributeDesignWidth); + DesignSizeBox->SetHeightOverride(AttributeDesignHeight); + DesignScaleBox->AddChild(DesignSizeBox); + + UCanvasPanel* DesignCanvas = WidgetTree->ConstructWidget(UCanvasPanel::StaticClass(), TEXT("DesignCanvas")); + DesignSizeBox->AddChild(DesignCanvas); + + UBorder* BackgroundPanel = WidgetTree->ConstructWidget(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))); + AddAttributeMenuCanvasChild(DesignCanvas, BackgroundPanel, FVector2D(0.0f, 0.0f), FVector2D(AttributeDesignWidth, AttributeDesignHeight), 0); + + UBorder* TitlePlaque = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("TitlePlaque")); + TitlePlaque->SetBrush(MakeAttributeMenuBrush(AttributeJadeTexturePath, FVector2D(390.0f, 88.0f), FLinearColor(0.18f, 0.34f, 0.30f, 0.98f))); + 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); + + UTextBlock* TitleText = CreateAttributeMenuText(WidgetTree, TEXT("TitleText"), FText::FromString(TEXT("角色属性")), 31, FLinearColor(0.99f, 0.88f, 0.61f, 1.0f)); + TitlePlaque->SetContent(TitleText); + + UButton* AttributeNavButton = CreateAttributeNavButton(WidgetTree, TEXT("AttributeNavButton"), FText::FromString(TEXT("属性")), true); + AddAttributeMenuCanvasChild(DesignCanvas, AttributeNavButton, FVector2D(552.0f, 9.0f), FVector2D(170.0f, 74.0f), 3); + UButton* EquipNavButton = CreateAttributeNavButton(WidgetTree, TEXT("EquipNavButton"), FText::FromString(TEXT("装备")), false); + AddAttributeMenuCanvasChild(DesignCanvas, EquipNavButton, FVector2D(764.0f, 11.0f), FVector2D(155.0f, 70.0f), 3); + UButton* SkillNavButton = CreateAttributeNavButton(WidgetTree, TEXT("SkillNavButton"), FText::FromString(TEXT("技能")), false); + AddAttributeMenuCanvasChild(DesignCanvas, SkillNavButton, FVector2D(978.0f, 11.0f), FVector2D(155.0f, 70.0f), 3); + UButton* BagNavButton = CreateAttributeNavButton(WidgetTree, TEXT("BagNavButton"), FText::FromString(TEXT("背包")), false); + AddAttributeMenuCanvasChild(DesignCanvas, BagNavButton, FVector2D(1188.0f, 11.0f), FVector2D(155.0f, 70.0f), 3); + + UBorder* HeaderRule = CreateAttributeMenuLine(WidgetTree, TEXT("HeaderRule")); + AddAttributeMenuCanvasChild(DesignCanvas, HeaderRule, FVector2D(392.0f, 85.0f), FVector2D(1245.0f, 18.0f), 2); SummaryWidget = WidgetTree->ConstructWidget(UPHYAttributeSummaryWidget::StaticClass(), TEXT("SummaryWidget")); - USizeBox* SummarySizeBox = WidgetTree->ConstructWidget(USizeBox::StaticClass(), TEXT("SummarySizeBox")); - SummarySizeBox->SetWidthOverride(360.0f); - SummarySizeBox->AddChild(SummaryWidget); - if (UHorizontalBoxSlot* SummarySlot = MainBox->AddChildToHorizontalBox(SummarySizeBox)) - { - SummarySlot->SetSize(FSlateChildSize(ESlateSizeRule::Automatic)); - SummarySlot->SetPadding(FMargin(0.0f, 0.0f, 18.0f, 0.0f)); - } + UBorder* SummaryPanel = WidgetTree->ConstructWidget(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->SetPadding(FMargin(27.0f, 24.0f, 27.0f, 22.0f)); + SummaryPanel->SetContent(SummaryWidget); + AddAttributeMenuCanvasChild(DesignCanvas, SummaryPanel, FVector2D(35.0f, 103.0f), FVector2D(462.0f, 710.0f), 2); UBorder* PageBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("PageBorder")); - PageBorder->SetBrushColor(FLinearColor(0.96f, 0.92f, 0.82f, 0.72f)); - PageBorder->SetPadding(FMargin(22.0f)); - if (UHorizontalBoxSlot* PageSlot = MainBox->AddChildToHorizontalBox(PageBorder)) - { - PageSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); - } + PageBorder->SetBrush(MakeAttributeMenuBrush(AttributePaperTexturePath, FVector2D(1120.0f, 735.0f), FLinearColor(0.98f, 0.96f, 0.88f, 0.92f), ESlateBrushDrawType::Box, FMargin(0.055f))); + 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); UVerticalBox* PageBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("PageBox")); PageBorder->SetContent(PageBox); - UTextBlock* HeaderText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("HeaderText")); - HeaderText->SetText(FText::FromString(TEXT("角色属性"))); - HeaderText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 28)); - HeaderText->SetColorAndOpacity(FSlateColor(FLinearColor(0.35f, 0.13f, 0.06f, 1.0f))); - PageBox->AddChildToVerticalBox(HeaderText); + UTextBlock* ResourceTitleText = CreateAttributeMenuText(WidgetTree, TEXT("ResourceTitleText"), FText::FromString(TEXT("战斗资源")), 22, FLinearColor(0.39f, 0.22f, 0.10f, 1.0f)); + PageBox->AddChildToVerticalBox(ResourceTitleText); + + UBorder* ResourceRule = CreateAttributeMenuLine(WidgetTree, TEXT("ResourceRule")); + if (UVerticalBoxSlot* ResourceRuleSlot = PageBox->AddChildToVerticalBox(ResourceRule)) + { + ResourceRuleSlot->SetPadding(FMargin(0.0f, 4.0f, 0.0f, 8.0f)); + } + + HeaderHealthBar = WidgetTree->ConstructWidget(UPHYAttributeResourceBarWidget::StaticClass(), TEXT("HeaderHealthBar")); + HeaderManaBar = WidgetTree->ConstructWidget(UPHYAttributeResourceBarWidget::StaticClass(), TEXT("HeaderManaBar")); + HeaderStaminaBar = WidgetTree->ConstructWidget(UPHYAttributeResourceBarWidget::StaticClass(), TEXT("HeaderStaminaBar")); + + if (UVerticalBoxSlot* HealthSlot = PageBox->AddChildToVerticalBox(HeaderHealthBar)) + { + HealthSlot->SetPadding(FMargin(4.0f, 0.0f, 0.0f, 2.0f)); + } + if (UVerticalBoxSlot* ManaSlot = PageBox->AddChildToVerticalBox(HeaderManaBar)) + { + ManaSlot->SetPadding(FMargin(4.0f, 0.0f, 0.0f, 2.0f)); + } + if (UVerticalBoxSlot* StaminaSlot = PageBox->AddChildToVerticalBox(HeaderStaminaBar)) + { + StaminaSlot->SetPadding(FMargin(4.0f, 0.0f, 0.0f, 12.0f)); + } UHorizontalBox* TabBox = WidgetTree->ConstructWidget(UHorizontalBox::StaticClass(), TEXT("TabBox")); if (UVerticalBoxSlot* TabSlot = PageBox->AddChildToVerticalBox(TabBox)) { - TabSlot->SetPadding(FMargin(0.0f, 12.0f, 0.0f, 16.0f)); + TabSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 14.0f)); } - OverviewTabButton = CreateTabButton(TEXT("OverviewTabButton"), FText::FromString(TEXT("总览"))); + OverviewTabButton = CreateTabButton(TEXT("OverviewTabButton"), FText::FromString(TEXT("核心属性"))); CombatTabButton = CreateTabButton(TEXT("CombatTabButton"), FText::FromString(TEXT("战斗衍生"))); ElementTabButton = CreateTabButton(TEXT("ElementTabButton"), FText::FromString(TEXT("元素衍生"))); - TabBox->AddChildToHorizontalBox(OverviewTabButton); + if (UHorizontalBoxSlot* OverviewTabSlot = TabBox->AddChildToHorizontalBox(OverviewTabButton)) + { + OverviewTabSlot->SetPadding(FMargin(0.0f, 0.0f, 10.0f, 0.0f)); + } if (UHorizontalBoxSlot* CombatTabSlot = TabBox->AddChildToHorizontalBox(CombatTabButton)) { - CombatTabSlot->SetPadding(FMargin(8.0f, 0.0f, 0.0f, 0.0f)); - } - if (UHorizontalBoxSlot* ElementTabSlot = TabBox->AddChildToHorizontalBox(ElementTabButton)) - { - ElementTabSlot->SetPadding(FMargin(8.0f, 0.0f, 0.0f, 0.0f)); + CombatTabSlot->SetPadding(FMargin(0.0f, 0.0f, 10.0f, 0.0f)); } + TabBox->AddChildToHorizontalBox(ElementTabButton); PageSwitcher = WidgetTree->ConstructWidget(UWidgetSwitcher::StaticClass(), TEXT("PageSwitcher")); if (UVerticalBoxSlot* SwitcherSlot = PageBox->AddChildToVerticalBox(PageSwitcher)) @@ -260,6 +402,13 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree() CombatTabButton->OnClicked.AddUniqueDynamic(this, &UPHYAttributeMenuWidget::HandleCombatTabClicked); ElementTabButton->OnClicked.AddUniqueDynamic(this, &UPHYAttributeMenuWidget::HandleElementTabClicked); + UButton* ConfirmButton = CreateAttributeNavButton(WidgetTree, TEXT("ConfirmButton"), FText::FromString(TEXT("确认")), true); + AddAttributeMenuCanvasChild(DesignCanvas, ConfirmButton, FVector2D(484.0f, 865.0f), FVector2D(255.0f, 58.0f), 3); + UButton* BackButton = CreateAttributeNavButton(WidgetTree, TEXT("BackButton"), FText::FromString(TEXT("返回")), false); + AddAttributeMenuCanvasChild(DesignCanvas, BackButton, FVector2D(774.0f, 865.0f), FVector2D(210.0f, 58.0f), 3); + UButton* ResetButton = CreateAttributeNavButton(WidgetTree, TEXT("ResetButton"), FText::FromString(TEXT("重置加点")), false); + AddAttributeMenuCanvasChild(DesignCanvas, ResetButton, FVector2D(1014.0f, 865.0f), FVector2D(260.0f, 58.0f), 3); + SetActivePage(ActivePageIndex); RefreshAttributePages(); } @@ -267,12 +416,12 @@ void UPHYAttributeMenuWidget::BuildNativeWidgetTree() UButton* UPHYAttributeMenuWidget::CreateTabButton(const FName ButtonName, const FText Label) { UButton* TabButton = WidgetTree->ConstructWidget(UButton::StaticClass(), ButtonName); - TabButton->SetBackgroundColor(FLinearColor(0.25f, 0.48f, 0.42f, 0.78f)); + ApplyAttributeSubTabStyle(TabButton, false); UTextBlock* TabText = WidgetTree->ConstructWidget(UTextBlock::StaticClass()); TabText->SetText(Label); - TabText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16)); - TabText->SetColorAndOpacity(FSlateColor(FLinearColor(0.98f, 0.94f, 0.84f, 1.0f))); + TabText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 18)); + TabText->SetColorAndOpacity(FSlateColor(FLinearColor(0.30f, 0.23f, 0.15f, 1.0f))); TabButton->SetContent(TabText); return TabButton; } @@ -289,21 +438,9 @@ void UPHYAttributeMenuWidget::SetActivePage(const int32 NewPageIndex) void UPHYAttributeMenuWidget::UpdateTabVisuals() { - const FLinearColor ActiveColor(0.68f, 0.21f, 0.12f, 0.92f); - const FLinearColor InactiveColor(0.25f, 0.48f, 0.42f, 0.78f); - - if (OverviewTabButton) - { - OverviewTabButton->SetBackgroundColor(ActivePageIndex == 0 ? ActiveColor : InactiveColor); - } - if (CombatTabButton) - { - CombatTabButton->SetBackgroundColor(ActivePageIndex == 1 ? ActiveColor : InactiveColor); - } - if (ElementTabButton) - { - ElementTabButton->SetBackgroundColor(ActivePageIndex == 2 ? ActiveColor : InactiveColor); - } + ApplyAttributeSubTabStyle(OverviewTabButton, ActivePageIndex == 0); + ApplyAttributeSubTabStyle(CombatTabButton, ActivePageIndex == 1); + ApplyAttributeSubTabStyle(ElementTabButton, ActivePageIndex == 2); } void UPHYAttributeMenuWidget::BindToPlayerState(APHYPlayerState* NewPlayerState) @@ -391,6 +528,25 @@ void UPHYAttributeMenuWidget::RefreshAttributePages() GetAttributeValue(UPHYCombatAttributeSet::GetMaxStaminaAttribute())); } + const float Health = GetAttributeValue(UPHYCombatAttributeSet::GetHealthAttribute()); + const float MaxHealth = GetAttributeValue(UPHYCombatAttributeSet::GetMaxHealthAttribute()); + const float Mana = GetAttributeValue(UPHYCombatAttributeSet::GetManaAttribute()); + const float MaxMana = GetAttributeValue(UPHYCombatAttributeSet::GetMaxManaAttribute()); + const float Stamina = GetAttributeValue(UPHYCombatAttributeSet::GetStaminaAttribute()); + const float MaxStamina = GetAttributeValue(UPHYCombatAttributeSet::GetMaxStaminaAttribute()); + if (HeaderHealthBar) + { + HeaderHealthBar->SetResource(FText::FromString(TEXT("生命值 (HP)")), Health, MaxHealth, FLinearColor(0.78f, 0.18f, 0.14f, 1.0f)); + } + if (HeaderManaBar) + { + HeaderManaBar->SetResource(FText::FromString(TEXT("法力值 (MP)")), Mana, MaxMana, FLinearColor(0.12f, 0.45f, 0.88f, 1.0f)); + } + if (HeaderStaminaBar) + { + HeaderStaminaBar->SetResource(FText::FromString(TEXT("耐力值 (ST)")), Stamina, MaxStamina, FLinearColor(0.12f, 0.67f, 0.58f, 1.0f)); + } + UAbilitySystemComponent* AbilitySystemComponent = BoundAbilitySystemComponent.Get(); if (OverviewPage) { diff --git a/Source/PHY/Private/UI/PHYAttributeOverviewPageWidget.cpp b/Source/PHY/Private/UI/PHYAttributeOverviewPageWidget.cpp index 3947d37..17e2ced 100644 --- a/Source/PHY/Private/UI/PHYAttributeOverviewPageWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeOverviewPageWidget.cpp @@ -37,7 +37,7 @@ namespace void UPHYAttributeOverviewPageWidget::RefreshAttributes(UAbilitySystemComponent* AbilitySystemComponent) { - SetPageTitle(FText::FromString(TEXT("属性总览"))); + SetPageTitle(FText::FromString(TEXT("核心属性"))); ClearGroups(); UPHYAttributeGroupWidget* CoreGroup = AddGroup(FText::FromString(TEXT("核心属性"))); @@ -47,9 +47,4 @@ void UPHYAttributeOverviewPageWidget::RefreshAttributes(UAbilitySystemComponent* AddOverviewAttributeRow(CoreGroup, TEXT("智力"), MakeOverviewNumberText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCoreAttributeSet::GetIntelligenceAttribute())), true); AddOverviewAttributeRow(CoreGroup, TEXT("精神"), MakeOverviewNumberText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCoreAttributeSet::GetSpiritAttribute())), true); AddOverviewAttributeRow(CoreGroup, TEXT("感知"), MakeOverviewNumberText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCoreAttributeSet::GetPerceptionAttribute())), true); - - UPHYAttributeGroupWidget* ResourceGroup = AddGroup(FText::FromString(TEXT("战斗资源"))); - AddOverviewAttributeRow(ResourceGroup, TEXT("生命值"), MakeOverviewPairText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetHealthAttribute()), GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxHealthAttribute()))); - AddOverviewAttributeRow(ResourceGroup, TEXT("法力值"), MakeOverviewPairText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetManaAttribute()), GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxManaAttribute()))); - AddOverviewAttributeRow(ResourceGroup, TEXT("耐力值"), MakeOverviewPairText(GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetStaminaAttribute()), GetOverviewAttributeValue(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxStaminaAttribute()))); } diff --git a/Source/PHY/Private/UI/PHYAttributeResourceBarWidget.cpp b/Source/PHY/Private/UI/PHYAttributeResourceBarWidget.cpp index 3fc1590..d5c760b 100644 --- a/Source/PHY/Private/UI/PHYAttributeResourceBarWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeResourceBarWidget.cpp @@ -5,22 +5,42 @@ #include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributeResourceBarWidget) #include "Blueprint/WidgetTree.h" +#include "Components/Border.h" #include "Components/HorizontalBox.h" #include "Components/HorizontalBoxSlot.h" #include "Components/ProgressBar.h" +#include "Components/SizeBox.h" #include "Components/TextBlock.h" #include "Components/VerticalBox.h" #include "Components/VerticalBoxSlot.h" +#include "Engine/Texture2D.h" #include "Fonts/SlateFontInfo.h" #include "Styling/CoreStyle.h" +#include "Styling/SlateBrush.h" #include "Widgets/SWidget.h" namespace { + const TCHAR* const AttributeResourceRowTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.T_PHY_UI_RowStrip"); + float MakePercent(const float CurrentValue, const float MaxValue) { return MaxValue > UE_SMALL_NUMBER ? FMath::Clamp(CurrentValue / MaxValue, 0.0f, 1.0f) : 0.0f; } + + FSlateBrush MakeAttributeResourceBrush() + { + FSlateBrush Brush; + Brush.DrawAs = ESlateBrushDrawType::Box; + Brush.Margin = FMargin(0.08f); + Brush.ImageSize = FVector2D(512.0f, 64.0f); + Brush.TintColor = FSlateColor(FLinearColor(1.0f, 1.0f, 1.0f, 0.88f)); + if (UTexture2D* Texture = LoadObject(nullptr, AttributeResourceRowTexturePath)) + { + Brush.SetResourceObject(Texture); + } + return Brush; + } } UPHYAttributeResourceBarWidget::UPHYAttributeResourceBarWidget(const FObjectInitializer& ObjectInitializer) @@ -61,32 +81,43 @@ void UPHYAttributeResourceBarWidget::BuildNativeWidgetTree() return; } - UVerticalBox* RootBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("RootBox")); - WidgetTree->RootWidget = RootBox; + UBorder* RootBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RootBorder")); + RootBorder->SetBrush(MakeAttributeResourceBrush()); + RootBorder->SetPadding(FMargin(10.0f, 5.0f)); + WidgetTree->RootWidget = RootBorder; UHorizontalBox* HeaderBox = WidgetTree->ConstructWidget(UHorizontalBox::StaticClass(), TEXT("HeaderBox")); - if (UVerticalBoxSlot* HeaderSlot = RootBox->AddChildToVerticalBox(HeaderBox)) - { - HeaderSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 2.0f)); - } + RootBorder->SetContent(HeaderBox); LabelText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("LabelText")); - LabelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 14)); - LabelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.30f, 0.26f, 0.20f, 1.0f))); + LabelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16)); + LabelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.34f, 0.27f, 0.17f, 1.0f))); if (UHorizontalBoxSlot* LabelSlot = HeaderBox->AddChildToHorizontalBox(LabelText)) { - LabelSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); + LabelSlot->SetSize(FSlateChildSize(ESlateSizeRule::Automatic)); + LabelSlot->SetPadding(FMargin(0.0f, 0.0f, 18.0f, 0.0f)); + LabelSlot->SetVerticalAlignment(VAlign_Center); } + USizeBox* BarSizeBox = WidgetTree->ConstructWidget(USizeBox::StaticClass(), TEXT("BarSizeBox")); + BarSizeBox->SetHeightOverride(13.0f); + if (UHorizontalBoxSlot* BarOuterSlot = HeaderBox->AddChildToHorizontalBox(BarSizeBox)) + { + BarOuterSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); + BarOuterSlot->SetPadding(FMargin(0.0f, 2.0f, 18.0f, 0.0f)); + BarOuterSlot->SetVerticalAlignment(VAlign_Center); + } + + ResourceBar = WidgetTree->ConstructWidget(UProgressBar::StaticClass(), TEXT("ResourceBar")); + BarSizeBox->AddChild(ResourceBar); + ValueText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("ValueText")); ValueText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 14)); - ValueText->SetColorAndOpacity(FSlateColor(FLinearColor(0.10f, 0.26f, 0.23f, 1.0f))); - HeaderBox->AddChildToHorizontalBox(ValueText); - - ResourceBar = WidgetTree->ConstructWidget(UProgressBar::StaticClass(), TEXT("ResourceBar")); - if (UVerticalBoxSlot* BarSlot = RootBox->AddChildToVerticalBox(ResourceBar)) + ValueText->SetColorAndOpacity(FSlateColor(FLinearColor(0.23f, 0.20f, 0.16f, 1.0f))); + if (UHorizontalBoxSlot* ValueSlot = HeaderBox->AddChildToHorizontalBox(ValueText)) { - BarSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 7.0f)); + ValueSlot->SetSize(FSlateChildSize(ESlateSizeRule::Automatic)); + ValueSlot->SetVerticalAlignment(VAlign_Center); } UpdateResourceWidgets(); diff --git a/Source/PHY/Private/UI/PHYAttributeRowWidget.cpp b/Source/PHY/Private/UI/PHYAttributeRowWidget.cpp index 1118076..23baa5f 100644 --- a/Source/PHY/Private/UI/PHYAttributeRowWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeRowWidget.cpp @@ -5,14 +5,38 @@ #include UE_INLINE_GENERATED_CPP_BY_NAME(PHYAttributeRowWidget) #include "Blueprint/WidgetTree.h" +#include "Components/Border.h" #include "Components/Button.h" #include "Components/HorizontalBox.h" #include "Components/HorizontalBoxSlot.h" #include "Components/TextBlock.h" +#include "Engine/Texture2D.h" #include "Fonts/SlateFontInfo.h" #include "Styling/CoreStyle.h" +#include "Styling/SlateBrush.h" +#include "Styling/SlateTypes.h" #include "Widgets/SWidget.h" +namespace +{ + const TCHAR* const AttributeRowTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_RowStrip.T_PHY_UI_RowStrip"); + const TCHAR* const AttributeRowCinnabarTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_CinnabarTab.T_PHY_UI_CinnabarTab"); + + FSlateBrush MakeAttributeRowBrush(const TCHAR* TexturePath, const FVector2D ImageSize, const FLinearColor Tint, const ESlateBrushDrawType::Type DrawAs = ESlateBrushDrawType::Box, const FMargin Margin = FMargin(0.08f)) + { + FSlateBrush Brush; + Brush.DrawAs = DrawAs; + Brush.Margin = Margin; + Brush.ImageSize = ImageSize; + Brush.TintColor = FSlateColor(Tint); + if (UTexture2D* Texture = LoadObject(nullptr, TexturePath)) + { + Brush.SetResourceObject(Texture); + } + return Brush; + } +} + UPHYAttributeRowWidget::UPHYAttributeRowWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { @@ -45,39 +69,48 @@ void UPHYAttributeRowWidget::BuildNativeWidgetTree() WidgetTree = NewObject(this, TEXT("WidgetTree"), RF_Transient); } - if (WidgetTree->RootWidget && RowBox && LabelText && ValueText && UpgradeButton && UpgradeText) + if (WidgetTree->RootWidget && RowBorder && RowBox && LabelText && ValueText && UpgradeButton && UpgradeText) { return; } + RowBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RowBorder")); + RowBorder->SetBrush(MakeAttributeRowBrush(AttributeRowTexturePath, FVector2D(512.0f, 64.0f), FLinearColor(1.0f, 0.98f, 0.90f, 0.78f))); + RowBorder->SetPadding(FMargin(11.0f, 5.0f)); + WidgetTree->RootWidget = RowBorder; + RowBox = WidgetTree->ConstructWidget(UHorizontalBox::StaticClass(), TEXT("RowBox")); - WidgetTree->RootWidget = RowBox; + RowBorder->SetContent(RowBox); LabelText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("LabelText")); - LabelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 15)); - LabelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.28f, 0.25f, 0.20f, 1.0f))); + LabelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16)); + LabelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.31f, 0.25f, 0.16f, 1.0f))); if (UHorizontalBoxSlot* LabelSlot = RowBox->AddChildToHorizontalBox(LabelText)) { LabelSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); - LabelSlot->SetPadding(FMargin(0.0f, 4.0f, 10.0f, 4.0f)); + LabelSlot->SetPadding(FMargin(0.0f, 3.0f, 10.0f, 3.0f)); LabelSlot->SetVerticalAlignment(VAlign_Center); } ValueText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("ValueText")); - ValueText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 15)); - ValueText->SetColorAndOpacity(FSlateColor(FLinearColor(0.08f, 0.24f, 0.22f, 1.0f))); + ValueText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16)); + ValueText->SetColorAndOpacity(FSlateColor(FLinearColor(0.08f, 0.36f, 0.28f, 1.0f))); if (UHorizontalBoxSlot* ValueSlot = RowBox->AddChildToHorizontalBox(ValueText)) { ValueSlot->SetSize(FSlateChildSize(ESlateSizeRule::Automatic)); - ValueSlot->SetPadding(FMargin(0.0f, 4.0f, 8.0f, 4.0f)); + ValueSlot->SetPadding(FMargin(0.0f, 3.0f, 12.0f, 3.0f)); ValueSlot->SetVerticalAlignment(VAlign_Center); } UpgradeButton = WidgetTree->ConstructWidget(UButton::StaticClass(), TEXT("UpgradeButton")); - UpgradeButton->SetBackgroundColor(FLinearColor(0.67f, 0.16f, 0.10f, 0.85f)); + FButtonStyle UpgradeButtonStyle; + UpgradeButtonStyle.SetNormal(MakeAttributeRowBrush(AttributeRowCinnabarTexturePath, FVector2D(34.0f, 34.0f), FLinearColor(0.20f, 0.35f, 0.31f, 0.96f))); + UpgradeButtonStyle.SetHovered(MakeAttributeRowBrush(AttributeRowCinnabarTexturePath, FVector2D(34.0f, 34.0f), FLinearColor(0.27f, 0.48f, 0.42f, 1.0f))); + UpgradeButtonStyle.SetPressed(MakeAttributeRowBrush(AttributeRowCinnabarTexturePath, FVector2D(34.0f, 34.0f), FLinearColor(0.74f, 0.24f, 0.13f, 1.0f))); + UpgradeButton->SetStyle(UpgradeButtonStyle); UpgradeText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("UpgradeText")); UpgradeText->SetText(FText::FromString(TEXT("+"))); - UpgradeText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 14)); + UpgradeText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 20)); UpgradeText->SetColorAndOpacity(FSlateColor(FLinearColor(0.98f, 0.92f, 0.78f, 1.0f))); UpgradeButton->SetContent(UpgradeText); if (UHorizontalBoxSlot* UpgradeSlot = RowBox->AddChildToHorizontalBox(UpgradeButton)) diff --git a/Source/PHY/Private/UI/PHYAttributeSummaryWidget.cpp b/Source/PHY/Private/UI/PHYAttributeSummaryWidget.cpp index 89e47d1..8a99afd 100644 --- a/Source/PHY/Private/UI/PHYAttributeSummaryWidget.cpp +++ b/Source/PHY/Private/UI/PHYAttributeSummaryWidget.cpp @@ -6,15 +6,40 @@ #include "Blueprint/WidgetTree.h" #include "Components/Border.h" +#include "Components/HorizontalBox.h" +#include "Components/HorizontalBoxSlot.h" +#include "Components/SizeBox.h" #include "Components/Spacer.h" #include "Components/TextBlock.h" #include "Components/VerticalBox.h" #include "Components/VerticalBoxSlot.h" +#include "Engine/Texture2D.h" #include "Fonts/SlateFontInfo.h" #include "Styling/CoreStyle.h" +#include "Styling/SlateBrush.h" #include "UI/PHYAttributeResourceBarWidget.h" #include "Widgets/SWidget.h" +namespace +{ + const TCHAR* const AttributeSummaryJadeTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_JadePanel.T_PHY_UI_JadePanel"); + const TCHAR* const AttributeSummaryPortraitTexturePath = TEXT("/Game/AGame/UI/Attributes/Textures/T_PHY_UI_PortraitFrame.T_PHY_UI_PortraitFrame"); + + FSlateBrush MakeAttributeSummaryBrush(const TCHAR* TexturePath, const FVector2D ImageSize, const FLinearColor Tint, const ESlateBrushDrawType::Type DrawAs = ESlateBrushDrawType::Box, const FMargin Margin = FMargin(0.08f)) + { + FSlateBrush Brush; + Brush.DrawAs = DrawAs; + Brush.Margin = Margin; + Brush.ImageSize = ImageSize; + Brush.TintColor = FSlateColor(Tint); + if (UTexture2D* Texture = LoadObject(nullptr, TexturePath)) + { + Brush.SetResourceObject(Texture); + } + return Brush; + } +} + UPHYAttributeSummaryWidget::UPHYAttributeSummaryWidget(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { @@ -60,50 +85,72 @@ void UPHYAttributeSummaryWidget::BuildNativeWidgetTree() WidgetTree = NewObject(this, TEXT("WidgetTree"), RF_Transient); } - if (WidgetTree->RootWidget && PlayerNameText && LevelText && CombatPowerText && ExperienceBar && HealthBar && ManaBar && StaminaBar) + if (WidgetTree->RootWidget && PlayerNameText && LevelText && CombatPowerText && ExperienceBar && ResourceBox) { return; } UBorder* RootBorder = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("RootBorder")); - RootBorder->SetBrushColor(FLinearColor(0.92f, 0.86f, 0.70f, 0.55f)); - RootBorder->SetPadding(FMargin(18.0f)); + RootBorder->SetBrushColor(FLinearColor(1.0f, 1.0f, 1.0f, 0.0f)); + RootBorder->SetPadding(FMargin(0.0f)); WidgetTree->RootWidget = RootBorder; UVerticalBox* RootBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("RootBox")); RootBorder->SetContent(RootBox); - PlayerNameText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("PlayerNameText")); - PlayerNameText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 24)); - PlayerNameText->SetColorAndOpacity(FSlateColor(FLinearColor(0.28f, 0.16f, 0.08f, 1.0f))); - RootBox->AddChildToVerticalBox(PlayerNameText); + UHorizontalBox* HeaderBox = WidgetTree->ConstructWidget(UHorizontalBox::StaticClass(), TEXT("HeaderBox")); + if (UVerticalBoxSlot* HeaderSlot = RootBox->AddChildToVerticalBox(HeaderBox)) + { + HeaderSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 14.0f)); + } + + UBorder* LevelSeal = WidgetTree->ConstructWidget(UBorder::StaticClass(), TEXT("LevelSeal")); + LevelSeal->SetBrush(MakeAttributeSummaryBrush(AttributeSummaryJadeTexturePath, FVector2D(92.0f, 92.0f), FLinearColor(0.18f, 0.33f, 0.30f, 0.96f))); + LevelSeal->SetPadding(FMargin(10.0f)); + if (UHorizontalBoxSlot* SealSlot = HeaderBox->AddChildToHorizontalBox(LevelSeal)) + { + SealSlot->SetSize(FSlateChildSize(ESlateSizeRule::Automatic)); + SealSlot->SetPadding(FMargin(0.0f, 0.0f, 18.0f, 0.0f)); + SealSlot->SetVerticalAlignment(VAlign_Center); + } LevelText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("LevelText")); - LevelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 17)); - LevelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.14f, 0.34f, 0.30f, 1.0f))); - if (UVerticalBoxSlot* LevelSlot = RootBox->AddChildToVerticalBox(LevelText)) + LevelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 31)); + LevelText->SetColorAndOpacity(FSlateColor(FLinearColor(1.0f, 0.86f, 0.55f, 1.0f))); + LevelSeal->SetContent(LevelText); + + UVerticalBox* HeaderTextBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("HeaderTextBox")); + if (UHorizontalBoxSlot* HeaderTextSlot = HeaderBox->AddChildToHorizontalBox(HeaderTextBox)) { - LevelSlot->SetPadding(FMargin(0.0f, 8.0f, 0.0f, 0.0f)); + HeaderTextSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill)); + HeaderTextSlot->SetVerticalAlignment(VAlign_Center); } + PlayerNameText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("PlayerNameText")); + PlayerNameText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 24)); + PlayerNameText->SetColorAndOpacity(FSlateColor(FLinearColor(0.26f, 0.20f, 0.12f, 1.0f))); + HeaderTextBox->AddChildToVerticalBox(PlayerNameText); + CombatPowerText = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("CombatPowerText")); CombatPowerText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 17)); - CombatPowerText->SetColorAndOpacity(FSlateColor(FLinearColor(0.60f, 0.34f, 0.08f, 1.0f))); - if (UVerticalBoxSlot* PowerSlot = RootBox->AddChildToVerticalBox(CombatPowerText)) + CombatPowerText->SetColorAndOpacity(FSlateColor(FLinearColor(0.60f, 0.36f, 0.11f, 1.0f))); + if (UVerticalBoxSlot* PowerSlot = HeaderTextBox->AddChildToVerticalBox(CombatPowerText)) { - PowerSlot->SetPadding(FMargin(0.0f, 4.0f, 0.0f, 14.0f)); + PowerSlot->SetPadding(FMargin(0.0f, 8.0f, 0.0f, 0.0f)); } - UTextBlock* PortraitPlaceholder = WidgetTree->ConstructWidget(UTextBlock::StaticClass(), TEXT("PortraitPlaceholder")); - PortraitPlaceholder->SetText(FText::FromString(TEXT("云纹角色剪影"))); - PortraitPlaceholder->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 20)); - PortraitPlaceholder->SetColorAndOpacity(FSlateColor(FLinearColor(0.38f, 0.45f, 0.38f, 0.85f))); - if (UVerticalBoxSlot* PortraitSlot = RootBox->AddChildToVerticalBox(PortraitPlaceholder)) + USizeBox* PortraitSizeBox = WidgetTree->ConstructWidget(USizeBox::StaticClass(), TEXT("PortraitSizeBox")); + PortraitSizeBox->SetHeightOverride(438.0f); + if (UVerticalBoxSlot* PortraitSlot = RootBox->AddChildToVerticalBox(PortraitSizeBox)) { - PortraitSlot->SetPadding(FMargin(0.0f, 22.0f, 0.0f, 24.0f)); - PortraitSlot->SetHorizontalAlignment(HAlign_Center); + PortraitSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 18.0f)); } + UBorder* PortraitBorder = WidgetTree->ConstructWidget(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->SetPadding(FMargin(10.0f)); + PortraitSizeBox->AddChild(PortraitBorder); + ResourceBox = WidgetTree->ConstructWidget(UVerticalBox::StaticClass(), TEXT("ResourceBox")); RootBox->AddChildToVerticalBox(ResourceBox); @@ -113,9 +160,6 @@ void UPHYAttributeSummaryWidget::BuildNativeWidgetTree() StaminaBar = WidgetTree->ConstructWidget(UPHYAttributeResourceBarWidget::StaticClass(), TEXT("StaminaBar")); ResourceBox->AddChildToVerticalBox(ExperienceBar); - ResourceBox->AddChildToVerticalBox(HealthBar); - ResourceBox->AddChildToVerticalBox(ManaBar); - ResourceBox->AddChildToVerticalBox(StaminaBar); UpdateSummaryWidgets(); } @@ -128,11 +172,11 @@ void UPHYAttributeSummaryWidget::UpdateSummaryWidgets() } if (LevelText) { - LevelText->SetText(FText::FromString(FString::Printf(TEXT("等级 %d"), Level))); + LevelText->SetText(FText::FromString(FString::Printf(TEXT("%d"), Level))); } if (CombatPowerText) { - CombatPowerText->SetText(FText::FromString(FString::Printf(TEXT("战力 %d"), CombatPower))); + CombatPowerText->SetText(FText::FromString(FString::Printf(TEXT("战斗评分\n%d"), CombatPower))); } if (ExperienceBar) { diff --git a/Source/PHY/Public/UI/PHYAttributeMenuWidget.h b/Source/PHY/Public/UI/PHYAttributeMenuWidget.h index 080a5e9..f44a43d 100644 --- a/Source/PHY/Public/UI/PHYAttributeMenuWidget.h +++ b/Source/PHY/Public/UI/PHYAttributeMenuWidget.h @@ -12,6 +12,7 @@ class APlayerController; class APHYPlayerState; class UAbilitySystemComponent; class UButton; +class UPHYAttributeResourceBarWidget; class UHorizontalBox; class UPHYAttributeOverviewPageWidget; class UPHYCombatDerivedAttributePageWidget; @@ -138,6 +139,18 @@ protected: UPROPERTY(Transient) TObjectPtr PageSwitcher; + /** @brief 设计稿右侧顶部生命资源条。 */ + UPROPERTY(Transient) + TObjectPtr HeaderHealthBar; + + /** @brief 设计稿右侧顶部法力资源条。 */ + UPROPERTY(Transient) + TObjectPtr HeaderManaBar; + + /** @brief 设计稿右侧顶部耐力资源条。 */ + UPROPERTY(Transient) + TObjectPtr HeaderStaminaBar; + /** @brief 总览分页。 */ UPROPERTY(Transient) TObjectPtr OverviewPage; diff --git a/Source/PHY/Public/UI/PHYAttributeRowWidget.h b/Source/PHY/Public/UI/PHYAttributeRowWidget.h index 75fa885..7952f3a 100644 --- a/Source/PHY/Public/UI/PHYAttributeRowWidget.h +++ b/Source/PHY/Public/UI/PHYAttributeRowWidget.h @@ -7,6 +7,7 @@ #include "PHYAttributeRowWidget.generated.h" class UButton; +class UBorder; class UHorizontalBox; class UTextBlock; @@ -55,6 +56,10 @@ protected: /** @brief 行根容器。 */ UPROPERTY(Transient) + TObjectPtr RowBorder; + + /** @brief 行水平容器。 */ + UPROPERTY(Transient) TObjectPtr RowBox; /** @brief 属性名称文本。 */