feat(ui): painel como o Hyper — texturas reais + Panels editável + fixes

- Realoca as 13 texturas de painel do Hyper p/ /Game/ZMMO/UI/CommonUI/Textures/Panels/ (remove as procedurais)
- DT_UI_Styles.PanelBackground com as 9 entradas fiéis ao Hyper Survival_Gold (DrawAs=Image, Margin 0, tint por chave); PanelOutline vazio como no Hyper
- FUIPanelBrushSet (espelha Struct_UI_Style_Panels): só os 2 mapas
- UUIPanel_Base expõe Panels EditAnywhere (Details como no Hyper), semeado do tema; modo-textura só SetBrush (sem padding/visibility inventados)
- Design-time carrega DT_UI_Styles direto (Designer pinta igual ao runtime)
- Fix: outline ausente usa NoDrawType (antes pintava centro branco com FSlateBrush default)
- Remove membro morto Content/UNamedSlot (Hyper não usa NamedSlot)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-19 02:03:09 -03:00
parent bc07c47557
commit 3889680469
22 changed files with 77 additions and 17 deletions

View File

@@ -292,6 +292,24 @@ struct ZMMO_API FUIStyleButton
TMap<EUIButtonShape, FVector2D> ShapeSizes;
};
/**
* Espelha 1:1 o Struct_UI_Style_Panels do Hyper: só os dois mapas de brush
* (fundo + contorno) indexados por EUIPanelTexture. É o que o UI_Panel_Master
* do Hyper expõe editável na instância (Details). EditAnywhere/ReadWrite para
* o designer ajustar brush por widget; o tema (DT) só faz seed/fallback.
*/
USTRUCT(BlueprintType)
struct ZMMO_API FUIPanelBrushSet
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Panel|Texture")
TMap<EUIPanelTexture, FSlateBrush> PanelBackground;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Panel|Texture")
TMap<EUIPanelTexture, FSlateBrush> PanelOutline;
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStylePanel
{

View File

@@ -3,8 +3,9 @@
#include "ZMMOThemeSubsystem.h"
#include "Engine/GameInstance.h"
#include "Components/Border.h"
#include "Components/NamedSlot.h"
#include "Styling/SlateBrush.h"
#include "Engine/DataTable.h"
#include "UI/UIStyleRow.h"
namespace
{
@@ -20,7 +21,25 @@ namespace
}
}
}
return Fallback; // design-time: defaults Aurora Arcana
// Design-time (sem GameInstance/subsystem): carrega o DT_UI_Styles
// direto e usa a row "Default", para o Designer pintar/mostrar os
// brushes igual ao runtime (caso contrário FUIStyle vem vazio).
static FUIStyle DesignStyle;
static bool bDesignLoaded = false;
if (!bDesignLoaded)
{
if (const UDataTable* DT = LoadObject<UDataTable>(nullptr,
TEXT("/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles")))
{
if (const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
FName(TEXT("Default")), TEXT("UIPanelDesign"), false))
{
DesignStyle = Row->Style;
bDesignLoaded = true;
}
}
}
return bDesignLoaded ? DesignStyle : Fallback;
}
}
@@ -35,23 +54,40 @@ void UUIPanel_Base::RefreshUIStyle()
const FUIStylePanel& P = AS.Panel;
// ---- Modo TEXTURA (padrão Hyper): brush por EUIPanelTexture ----
const FSlateBrush* BgTex = (PanelTexture != EUIPanelTexture::None)
? P.PanelBackground.Find(PanelTexture) : nullptr;
// Fiel ao UI_Panel_Master do Hyper: só faz SetBrush nos dois Borders
// (Find no mapa por chave). Sem padding/visibility — a arte da textura
// já traz a moldura; o conteúdo é injetado pelo WBP filho.
// Seed dos mapas da instância a partir do tema quando vazios — assim o
// Details mostra Panel Background/Outline preenchidos e editáveis (igual
// ao Hyper, cujo `Panels` é alimentado pelo estilo). Edições do designer
// têm prioridade; o tema (P) é fallback por chave.
if (Panels.PanelBackground.Num() == 0) { Panels.PanelBackground = P.PanelBackground; }
if (Panels.PanelOutline.Num() == 0) { Panels.PanelOutline = P.PanelOutline; }
const FSlateBrush* BgTex = nullptr;
if (PanelTexture != EUIPanelTexture::None)
{
BgTex = Panels.PanelBackground.Find(PanelTexture);
if (!BgTex) { BgTex = P.PanelBackground.Find(PanelTexture); }
}
if (BgTex)
{
Background->SetBrush(*BgTex);
Background->SetPadding(bUseSmallPadding ? P.PaddingSmall : P.Padding);
if (Outline)
{
if (const FSlateBrush* OlTex = P.PanelOutline.Find(PanelTexture))
// Hyper: Find sempre seguido de SetBrush. No Hyper a entrada de
// outline ausente é um brush TRANSPARENTE (alpha 0) — não some
// widget, só não desenha. Um FSlateBrush default desenha um
// retângulo BRANCO; o equivalente correto é DrawAs=NoDrawType.
const FSlateBrush* OlTex = Panels.PanelOutline.Find(PanelTexture);
if (!OlTex) { OlTex = P.PanelOutline.Find(PanelTexture); }
static const FSlateBrush NoDrawBrush = []
{
Outline->SetBrush(*OlTex);
Outline->SetVisibility(ESlateVisibility::HitTestInvisible);
}
else
{
Outline->SetVisibility(ESlateVisibility::Collapsed);
}
FSlateBrush B;
B.DrawAs = ESlateBrushDrawType::NoDrawType;
return B;
}();
Outline->SetBrush(OlTex ? *OlTex : NoDrawBrush);
}
BP_ApplyPanelStyle(P);
return;

View File

@@ -7,7 +7,6 @@
#include "UIPanel_Base.generated.h"
class UBorder;
class UNamedSlot;
/**
* Painel base do ZMMO — mesmo padrão do UUIButton_Base, mas container.
@@ -44,6 +43,16 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Panel")
EUIPanelTexture PanelTexture = EUIPanelTexture::None;
/**
* Mapas de brush por instância — espelha o `Panels` do UI_Panel_Master
* do Hyper (Details mostra Panel Background / Panel Outline editáveis).
* Tem prioridade. Se não houver brush p/ a chave aqui, cai no tema
* (DT_UI_Styles). Em NativePreConstruct é semeado a partir do tema
* quando vazio, então por padrão o tema manda — como no Hyper.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Panel")
FUIPanelBrushSet Panels;
/** Re-resolve os tokens do tema ativo e reaplica no Background. */
UFUNCTION(BlueprintCallable, Category = "UI Style")
void RefreshUIStyle();
@@ -66,9 +75,6 @@ protected:
UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UBorder> Outline;
UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UNamedSlot> Content;
private:
UFUNCTION()
void HandleThemeChanged(FName NewThemeId);