ServerSelect (Fase 1): - UIServerSelectScreen_Base: subscribe OnRawMessage + C_WORLD_LIST_REQUEST - WBP_ServerCard instanciado dinamicamente em GridPanel CardContainer (2 cols) - UIServerCard_Base: SetFromEntry + OnCardPressed delegate + UI_Button_Master - Push real-time S_WORLD_STATUS_UPDATE (opcode 2062) atualiza card in-place - FZMMOWorldEntry struct, EZMMOWorldState enum no wire (offline/online/maint) - Sem hardcap de slots — cards usam toda largura via ColumnFill weights Lobby/CharSelect (Fase 1.5): - UIUserLobbyScreen_Base + WBP_UserLobby (WidgetSwitcher: lista + create) - C_CHAR_LIST_REQUEST filtrado por SelectedWorldId do FlowSubsystem - UICharCard_Base + WBP_CharCard com Select/Delete + Accept/Cancel quando delete agendado; Text_DeleteCountdown atualiza em tempo real (timer 1s) - UICharacterCreatePage_Base + WBP_CharacterCreate (Name + ComboBox class) - Handlers S_CHAR_SELECT_OK (handoff parse), CHAR_CREATE_OK/REJECT, CHAR_DELETE_ACK/ACCEPT_ACK/CANCEL_ACK (refresh lista) Auxiliares + fixes: - ARQUITETURA_SERVER_SELECT.md + ARQUITETURA_CHARACTER_MODEL.md - UIFrontEndFlowSubsystem: SelectedWorldId state + transicao Lobby - DA_FrontEndScreenSet: Lobby -> WBP_UserLobby_C - UICheckBox_Base + UICommonText_Base (componentes auxiliares) - BSB_Button_Transparent.Disabled DrawAs=IMAGE -> NoDraw (fix bg branco) - WBP_ServerCard layout: HBox para chips Region/Ping/Status, SizeBox 10x10 no Dot verde (anti-overflow); SelfHitTestInvisible em containers (hover)
139 lines
4.4 KiB
C++
139 lines
4.4 KiB
C++
#include "UICommonText_Base.h"
|
|
|
|
#include "ZMMOThemeSubsystem.h"
|
|
#include "Engine/GameInstance.h"
|
|
#include "Engine/DataTable.h"
|
|
#include "Styling/CoreStyle.h"
|
|
#include "UI/UIStyleRow.h"
|
|
|
|
namespace
|
|
{
|
|
const TCHAR* GStylesDT = TEXT("/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles");
|
|
|
|
// Retorna POR VALOR (cópia fresca): nunca persiste ponteiro de FontObject
|
|
// num static não-rastreado por GC (causa AV ao hashear a fonte no preview).
|
|
FUIStyle ResolveTextStyle(const UWidget* Widget, const FUIStyle& Fallback)
|
|
{
|
|
if (Widget)
|
|
{
|
|
if (const UGameInstance* GI = Widget->GetGameInstance())
|
|
{
|
|
if (const UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
|
|
{
|
|
return Theme->GetActiveUIStyle();
|
|
}
|
|
}
|
|
}
|
|
// Design-time relê o DT a cada chamada. Local (não-static): a fonte
|
|
// fica viva apenas durante o RefreshUIStyle (o UObject UFont é mantido
|
|
// pelo DataTable carregado — sem ponteiro pendurado entre frames).
|
|
FUIStyle DesignStyle;
|
|
bool bHas = false;
|
|
if (const UDataTable* DT = LoadObject<UDataTable>(nullptr, GStylesDT))
|
|
{
|
|
if (const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
|
|
FName(TEXT("Default")), TEXT("UITextDesign"), false))
|
|
{
|
|
DesignStyle = Row->Style;
|
|
bHas = true;
|
|
}
|
|
}
|
|
return bHas ? DesignStyle : Fallback;
|
|
}
|
|
|
|
// Fallback: categorias clássicas a partir de FUIStyle.Text (já configurado
|
|
// com as FF_ fonts no DT) enquanto o mapa TextRoles não for preenchido.
|
|
bool LegacyRole(const FUIStyle& AS, FName Role, FSlateFontInfo& OutFont,
|
|
FLinearColor& OutColor, bool& bOutUpper)
|
|
{
|
|
const FUIStyleText& T = AS.Text;
|
|
const FUIStylePalette& P = AS.Palette;
|
|
const FString R = Role.ToString();
|
|
bOutUpper = false;
|
|
if (R.Equals(TEXT("Title"), ESearchCase::IgnoreCase)) { OutFont = T.TitleFont; OutColor = P.Text; return true; }
|
|
if (R.Equals(TEXT("Section"), ESearchCase::IgnoreCase)) { OutFont = T.SectionFont; OutColor = P.Text; return true; }
|
|
if (R.Equals(TEXT("Button"), ESearchCase::IgnoreCase)) { OutFont = T.ButtonFont; OutColor = P.Text; return true; }
|
|
if (R.Equals(TEXT("Label"), ESearchCase::IgnoreCase)) { OutFont = T.LabelFont; OutColor = P.Text2; bOutUpper = T.bLabelUppercase; return true; }
|
|
if (R.Equals(TEXT("Dim"), ESearchCase::IgnoreCase)) { OutFont = T.BodyFont; OutColor = P.TextDim; return true; }
|
|
if (R.Equals(TEXT("Body"), ESearchCase::IgnoreCase)) { OutFont = T.BodyFont; OutColor = P.Text; return true; }
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void UUICommonText_Base::RefreshUIStyle()
|
|
{
|
|
const FUIStyle Fallback;
|
|
const FUIStyle AS = ResolveTextStyle(this, Fallback);
|
|
|
|
FSlateFontInfo RoleFont;
|
|
FLinearColor RoleColor = AS.Palette.Text;
|
|
bool bUpper = false;
|
|
|
|
// 1) Mapa data-driven (autor define no DT_UI_Styles).
|
|
if (const FUITextStyle* E = AS.TextRoles.Find(TextRole))
|
|
{
|
|
RoleFont = E->Font;
|
|
RoleColor = E->Color;
|
|
bUpper = E->bUppercase;
|
|
}
|
|
// 2) Fallback p/ categorias clássicas de FUIStyle.Text.
|
|
else if (!LegacyRole(AS, TextRole, RoleFont, RoleColor, bUpper))
|
|
{
|
|
RoleFont = AS.Text.BodyFont;
|
|
RoleColor = AS.Palette.Text;
|
|
}
|
|
|
|
// Nunca deixa sem fonte (evita o "A BASIC LATIN" gigante/quebrado).
|
|
if (RoleFont.FontObject == nullptr && RoleFont.CompositeFont == nullptr)
|
|
{
|
|
RoleFont = FCoreStyle::GetDefaultFontStyle("Regular", 14);
|
|
}
|
|
|
|
SetFont(RoleFont);
|
|
SetColorAndOpacity(FSlateColor(RoleColor));
|
|
|
|
if (bUpper)
|
|
{
|
|
const FText Cur = GetText();
|
|
if (!Cur.IsEmpty())
|
|
{
|
|
SetText(FText::FromString(Cur.ToString().ToUpper()));
|
|
}
|
|
}
|
|
}
|
|
|
|
TArray<FString> UUICommonText_Base::GetTextRoleOptions() const
|
|
{
|
|
return GetThemeTextRoleOptions();
|
|
}
|
|
|
|
TArray<FString> UUICommonText_Base::GetThemeTextRoleOptions()
|
|
{
|
|
TArray<FString> Options;
|
|
// Categorias clássicas sempre disponíveis (fallback garantido).
|
|
for (const TCHAR* N : { TEXT("Title"), TEXT("Section"), TEXT("Body"),
|
|
TEXT("Button"), TEXT("Label"), TEXT("Dim") })
|
|
{
|
|
Options.Add(N);
|
|
}
|
|
// + chaves definidas pelo autor no DT_UI_Styles (data-driven).
|
|
if (const UDataTable* DT = LoadObject<UDataTable>(nullptr, GStylesDT))
|
|
{
|
|
if (const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
|
|
FName(TEXT("Default")), TEXT("UITextRoleOptions"), false))
|
|
{
|
|
for (const TPair<FName, FUITextStyle>& Pair : Row->Style.TextRoles)
|
|
{
|
|
Options.AddUnique(Pair.Key.ToString());
|
|
}
|
|
}
|
|
}
|
|
return Options;
|
|
}
|
|
|
|
void UUICommonText_Base::SynchronizeProperties()
|
|
{
|
|
Super::SynchronizeProperties();
|
|
RefreshUIStyle();
|
|
}
|