feat(ui): sistema de UI Style (tokens C++ por tema) + fontes Aurora Arcana

Camada de estilo data-driven do cliente ZMMO, portando o nucleo do projeto de referencia (Hyper) para C++ conforme ARQUITETURA.md (BP Struct proibido):

- Source/ZMMO/Data/UI: UIStyleTypes.h (enums EUI*), UIStyleTokens.h (tokens primitive/semantic/component), UIStyleRow.h (FUIStyle + FUIStyleRow). - ZMMOThemeSubsystem: GetActiveUIStyle() resolve DT_UI_Styles por ThemeId com fallback Default. - Fontes: 8 UFontFace Inline (Cinzel/Rajdhani) em Content/ZMMO/UI/Fonts + DT_UI_Styles preenchido. - ARQUITETURA.md: prefixo de widget UI_, classes base UUI*_Base (UCLASS Abstract) sem prefixo ZMMO. - Config/DefaultGame.ini: UIStyleTable apontando DT_UI_Styles. - Scripts/import_fonts.py (importador idempotente). Inclui tambem o scaffolding do modulo ZMMO ainda nao versionado (Source/ZMMO/Data, Game/UI, Content/ZMMO, uproject, Build.cs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-18 21:21:32 -03:00
parent 50471831a2
commit 1c06d69174
124 changed files with 2328 additions and 1 deletions

View File

@@ -0,0 +1,84 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "AbilityRow.generated.h"
class UTexture2D;
class UAnimMontage;
class UNiagaraSystem;
class USoundBase;
UENUM(BlueprintType)
enum class EAbilityCategory : uint8
{
Combat UMETA(DisplayName = "Combat"),
Buff UMETA(DisplayName = "Buff"),
Heal UMETA(DisplayName = "Heal"),
Movement UMETA(DisplayName = "Movement"),
Passive UMETA(DisplayName = "Passive")
};
UENUM(BlueprintType)
enum class EAbilityTarget : uint8
{
Self UMETA(DisplayName = "Self"),
Single UMETA(DisplayName = "Single Target"),
Area UMETA(DisplayName = "Area"),
Cone UMETA(DisplayName = "Cone"),
Line UMETA(DisplayName = "Line")
};
USTRUCT(BlueprintType)
struct ZMMO_API FAbilityRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability", meta = (MultiLine = true))
FText Description;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Ability")
EAbilityCategory Category = EAbilityCategory::Combat;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Targeting")
EAbilityTarget TargetMode = EAbilityTarget::Single;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Targeting")
float Range = 500.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Targeting", meta = (EditCondition = "TargetMode == EAbilityTarget::Area || TargetMode == EAbilityTarget::Cone"))
float Radius = 200.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cost")
int32 ManaCost = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Cost")
int32 StaminaCost = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Timing")
float CastTime = 0.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Timing")
float Cooldown = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Effect")
int32 BaseDamage = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Effect")
FName StatusEffectRow;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UTexture2D> Icon;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UAnimMontage> CastMontage;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UNiagaraSystem> CastVFX;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Audio")
TSoftObjectPtr<USoundBase> CastSound;
};

View File

@@ -0,0 +1,51 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "StatusEffectRow.generated.h"
class UTexture2D;
class UNiagaraSystem;
UENUM(BlueprintType)
enum class EStatusEffectKind : uint8
{
Buff UMETA(DisplayName = "Buff"),
Debuff UMETA(DisplayName = "Debuff"),
DoT UMETA(DisplayName = "Damage Over Time"),
HoT UMETA(DisplayName = "Heal Over Time"),
Crowd UMETA(DisplayName = "Crowd Control")
};
USTRUCT(BlueprintType)
struct ZMMO_API FStatusEffectRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status", meta = (MultiLine = true))
FText Description;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
EStatusEffectKind Kind = EStatusEffectKind::Buff;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
float Duration = 5.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
float TickInterval = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
int32 TickValue = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Status")
int32 MaxStacks = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UTexture2D> Icon;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UNiagaraSystem> AttachedVFX;
};

View File

@@ -0,0 +1,46 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "Items/ItemTypes.h"
#include "ItemRow.generated.h"
class AActor;
class UStaticMesh;
class UTexture2D;
USTRUCT(BlueprintType)
struct ZMMO_API FItemRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item", meta = (MultiLine = true))
FText Description;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
EItemType Type = EItemType::None;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
EItemRarity Rarity = EItemRarity::Common;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Equipment", meta = (EditCondition = "Type == EItemType::Weapon || Type == EItemType::Armor || Type == EItemType::Accessory"))
EEquipSlot EquipSlot = EEquipSlot::None;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
int32 MaxStack = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Item")
int32 BasePrice = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UTexture2D> Icon;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Visuals")
TSoftObjectPtr<UStaticMesh> WorldMesh;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Behavior")
TSoftClassPtr<AActor> BehaviorClass;
};

View File

@@ -0,0 +1,45 @@
#pragma once
#include "CoreMinimal.h"
#include "ItemTypes.generated.h"
UENUM(BlueprintType)
enum class EItemType : uint8
{
None UMETA(DisplayName = "None"),
Weapon UMETA(DisplayName = "Weapon"),
Armor UMETA(DisplayName = "Armor"),
Accessory UMETA(DisplayName = "Accessory"),
Consumable UMETA(DisplayName = "Consumable"),
Material UMETA(DisplayName = "Material"),
Quest UMETA(DisplayName = "Quest"),
Currency UMETA(DisplayName = "Currency")
};
UENUM(BlueprintType)
enum class EItemRarity : uint8
{
Common UMETA(DisplayName = "Common"),
Uncommon UMETA(DisplayName = "Uncommon"),
Rare UMETA(DisplayName = "Rare"),
Epic UMETA(DisplayName = "Epic"),
Legendary UMETA(DisplayName = "Legendary"),
Mythic UMETA(DisplayName = "Mythic")
};
UENUM(BlueprintType)
enum class EEquipSlot : uint8
{
None UMETA(DisplayName = "None"),
Head UMETA(DisplayName = "Head"),
Chest UMETA(DisplayName = "Chest"),
Legs UMETA(DisplayName = "Legs"),
Hands UMETA(DisplayName = "Hands"),
Feet UMETA(DisplayName = "Feet"),
MainHand UMETA(DisplayName = "Main Hand"),
OffHand UMETA(DisplayName = "Off Hand"),
TwoHand UMETA(DisplayName = "Two Hand"),
Ring UMETA(DisplayName = "Ring"),
Necklace UMETA(DisplayName = "Necklace"),
Cape UMETA(DisplayName = "Cape")
};

View File

@@ -0,0 +1,48 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "Mobs/MobTypes.h"
#include "Players/StatBlock.h"
#include "MobRow.generated.h"
class APawn;
USTRUCT(BlueprintType)
struct ZMMO_API FMobRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
TSoftClassPtr<APawn> BlueprintRef;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
EMobFamily Family = EMobFamily::Beast;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
EMobFaction Faction = EMobFaction::Hostile;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
EMobBehavior Behavior = EMobBehavior::Aggressive;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Mob")
int32 Level = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stats")
FStatBlock Stats;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Combat")
float AggroRadius = 800.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Combat")
float LeashRadius = 2000.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Rewards")
int32 ExperienceReward = 0;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Rewards")
FName DropTableRow;
};

View File

@@ -0,0 +1,35 @@
#pragma once
#include "CoreMinimal.h"
#include "MobTypes.generated.h"
UENUM(BlueprintType)
enum class EMobFaction : uint8
{
Neutral UMETA(DisplayName = "Neutral"),
Hostile UMETA(DisplayName = "Hostile"),
Friendly UMETA(DisplayName = "Friendly"),
Boss UMETA(DisplayName = "Boss")
};
UENUM(BlueprintType)
enum class EMobBehavior : uint8
{
Passive UMETA(DisplayName = "Passive"),
Defensive UMETA(DisplayName = "Defensive"),
Aggressive UMETA(DisplayName = "Aggressive"),
Patrol UMETA(DisplayName = "Patrol"),
Stationary UMETA(DisplayName = "Stationary")
};
UENUM(BlueprintType)
enum class EMobFamily : uint8
{
Beast UMETA(DisplayName = "Beast"),
Undead UMETA(DisplayName = "Undead"),
Humanoid UMETA(DisplayName = "Humanoid"),
Dragon UMETA(DisplayName = "Dragon"),
Elemental UMETA(DisplayName = "Elemental"),
Demon UMETA(DisplayName = "Demon"),
Construct UMETA(DisplayName = "Construct")
};

View File

@@ -0,0 +1,32 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "DialogRow.generated.h"
USTRUCT(BlueprintType)
struct ZMMO_API FDialogChoice
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog")
FText Text;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog")
FName NextNode;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog")
FName RequiredQuestState;
};
USTRUCT(BlueprintType)
struct ZMMO_API FDialogRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog", meta = (MultiLine = true))
FText SpeakerLine;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog")
TArray<FDialogChoice> Choices;
};

View File

@@ -0,0 +1,40 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "NPCRow.generated.h"
class APawn;
UENUM(BlueprintType)
enum class ENPCRole : uint8
{
Generic UMETA(DisplayName = "Generic"),
Vendor UMETA(DisplayName = "Vendor"),
Questgiver UMETA(DisplayName = "Questgiver"),
Trainer UMETA(DisplayName = "Trainer"),
Banker UMETA(DisplayName = "Banker"),
Innkeeper UMETA(DisplayName = "Innkeeper"),
Guard UMETA(DisplayName = "Guard")
};
USTRUCT(BlueprintType)
struct ZMMO_API FNPCRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "NPC")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "NPC")
TSoftClassPtr<APawn> BlueprintRef;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "NPC")
ENPCRole Role = ENPCRole::Generic;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Shop", meta = (EditCondition = "Role == ENPCRole::Vendor"))
TArray<FName> ShopInventory;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Dialog")
FName DialogRoot;
};

View File

@@ -0,0 +1,29 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "Players/StatBlock.h"
#include "ClassRow.generated.h"
class APawn;
USTRUCT(BlueprintType)
struct ZMMO_API FClassRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Class")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Class")
TSoftClassPtr<APawn> BlueprintRef;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stats")
FStatBlock BaseStats;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Stats")
FStatBlock LevelUpStats;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Class")
TArray<FName> StartingAbilities;
};

View File

@@ -0,0 +1,31 @@
#pragma once
#include "CoreMinimal.h"
#include "StatBlock.generated.h"
USTRUCT(BlueprintType)
struct ZMMO_API FStatBlock
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
int32 Health = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
int32 Mana = 50;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
int32 Stamina = 100;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
int32 Attack = 10;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
int32 Defense = 5;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
float MoveSpeed = 600.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
float AttackSpeed = 1.0f;
};

View File

@@ -0,0 +1,77 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "QuestRow.generated.h"
UENUM(BlueprintType)
enum class EQuestKind : uint8
{
Main UMETA(DisplayName = "Main"),
Side UMETA(DisplayName = "Side"),
Daily UMETA(DisplayName = "Daily"),
Repeatable UMETA(DisplayName = "Repeatable"),
Event UMETA(DisplayName = "Event")
};
UENUM(BlueprintType)
enum class EQuestObjectiveType : uint8
{
Kill UMETA(DisplayName = "Kill"),
Collect UMETA(DisplayName = "Collect"),
Talk UMETA(DisplayName = "Talk"),
Reach UMETA(DisplayName = "Reach Location"),
Use UMETA(DisplayName = "Use Item"),
Escort UMETA(DisplayName = "Escort")
};
USTRUCT(BlueprintType)
struct ZMMO_API FQuestObjective
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Objective")
EQuestObjectiveType Type = EQuestObjectiveType::Kill;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Objective")
FName TargetId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Objective")
int32 Required = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Objective")
FText Description;
};
USTRUCT(BlueprintType)
struct ZMMO_API FQuestRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest", meta = (MultiLine = true))
FText Description;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
EQuestKind Kind = EQuestKind::Side;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
int32 LevelRequirement = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
FName GiverNPC;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
FName TurnInNPC;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
TArray<FQuestObjective> Objectives;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
FName RewardRow;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Quest")
TArray<FName> Prerequisites;
};

View File

@@ -0,0 +1,29 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "ThemeCalendarRow.generated.h"
USTRUCT(BlueprintType)
struct ZMMO_API FThemeCalendarRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar")
FName ThemeId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar", meta = (ClampMin = "1", ClampMax = "12"))
int32 StartMonth = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar", meta = (ClampMin = "1", ClampMax = "31"))
int32 StartDay = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar", meta = (ClampMin = "1", ClampMax = "12"))
int32 EndMonth = 12;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar", meta = (ClampMin = "1", ClampMax = "31"))
int32 EndDay = 31;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Calendar", meta = (ToolTip = "Higher priority wins when ranges overlap."))
int32 Priority = 0;
};

View File

@@ -0,0 +1,29 @@
#pragma once
#include "CoreMinimal.h"
#include "ThemeKeys.generated.h"
UENUM(BlueprintType)
enum class EZMMOThemeKey : uint8
{
// HUD
HUD_Frame UMETA(DisplayName = "HUD - Frame"),
HUD_HotbarBackground UMETA(DisplayName = "HUD - Hotbar Background"),
HUD_HealthBar UMETA(DisplayName = "HUD - Health Bar"),
HUD_ManaBar UMETA(DisplayName = "HUD - Mana Bar"),
// Login / Character Select
Login_Background UMETA(DisplayName = "Login - Background"),
Login_Logo UMETA(DisplayName = "Login - Logo"),
Login_Music UMETA(DisplayName = "Login - Music"),
Login_AmbientVFX UMETA(DisplayName = "Login - Ambient VFX"),
CharSelect_Background UMETA(DisplayName = "Character Select - Background"),
// Inventory
Inventory_SlotEmpty UMETA(DisplayName = "Inventory - Empty Slot"),
Inventory_Background UMETA(DisplayName = "Inventory - Background"),
// Generic
MainMenu_Music UMETA(DisplayName = "Main Menu Music"),
LoadingScreen UMETA(DisplayName = "Loading Screen")
};

View File

@@ -0,0 +1,41 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "UObject/SoftObjectPtr.h"
#include "ThemeRow.generated.h"
class UObject;
class UTexture2D;
class USoundBase;
class UNiagaraSystem;
USTRUCT(BlueprintType)
struct ZMMO_API FThemeEntry
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
TSoftObjectPtr<UTexture2D> Texture;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
TSoftObjectPtr<USoundBase> Sound;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
TSoftObjectPtr<UNiagaraSystem> VFX;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
TSoftObjectPtr<UObject> Generic;
};
USTRUCT(BlueprintType)
struct ZMMO_API FThemeRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
FName ThemeId;
};

View File

@@ -0,0 +1,70 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "UIStyleTypes.h"
#include "UIStyleTokens.h"
#include "UIStyleRow.generated.h"
/**
* Struct raiz que agrega todos os tokens de estilo de um tema.
*
* Adicionar membros aqui (fase 2/3) é mudança aditiva e segura para a
* DataTable existente — mas, ao alterar este struct em produção, fazer
* backup de DT_UI_Styles (UHT invalida rows serializadas se a coluna não
* preservar valores). Ver ARQUITETURA.md / docs Epic sobre DataTable.
*/
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyle
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStylePalette Palette;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleSemantic Semantic;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleText Text;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleButton Button;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStylePanel Panel;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleBorders Borders;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleProgressBar ProgressBar;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyleTooltip Tooltip;
};
/**
* Linha de DT_UI_Styles. O Row Name é o ThemeId (ex.: "Default", "RPG"),
* espelhando DT_ThemeCalendar e ThemeRegistry — assim a camada de estilo
* é consumidora do ThemeId já resolvido pelo UZMMOThemeSubsystem.
*/
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FText DisplayName;
/** Validação tipada de design-time; runtime resolve por ThemeId/Row Name. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
EUITheme Theme = EUITheme::None;
/** Ponte para o ThemeId resolvido pelo UZMMOThemeSubsystem. */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FName ThemeId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style")
FUIStyle Style;
};

View File

@@ -0,0 +1,364 @@
#pragma once
#include "CoreMinimal.h"
#include "Fonts/SlateFontInfo.h"
#include "Layout/Margin.h"
#include "UIStyleTypes.h"
#include "UIStyleTokens.generated.h"
/**
* Tokens de estilo da UI organizados em 3 camadas (design tokens):
*
* 1. Primitive (FUIStylePalette) — paleta crua "Aurora Arcana".
* Espelha Tools/Templates/Zeus_Widget/shared/styles.css (:root).
* 2. Semantic (FUIStyleSemantic) — papéis (Accent, Surface, OnSurface...)
* que referenciam a primitive. Trocar de tema mexe sobretudo aqui.
* 3. Component (FUIStyle*) — por componente, consome a camada semantic.
*
* Defaults faithful ao tema padrão; tudo é sobrescrito por linha em
* DT_UI_Styles (FUIStyleRow). Cores em FColor(R,G,B[,A]) sRGB convertidas
* implicitamente para FLinearColor.
*/
// =====================================================================
// 1. Primitive — paleta Aurora Arcana
// =====================================================================
USTRUCT(BlueprintType)
struct ZMMO_API FUIStylePalette
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Bg0 = FLinearColor(FColor(7, 10, 18)); // --bg-0 #070A12
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Bg1 = FLinearColor(FColor(11, 16, 32)); // --bg-1 #0B1020
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Panel = FLinearColor(FColor(12, 18, 34, 235)); // --panel rgba(..,.92)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Panel2 = FLinearColor(FColor(17, 24, 42)); // --panel-2 #11182A
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Panel3 = FLinearColor(FColor(14, 20, 36)); // --panel-3 #0E1424
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Border = FLinearColor(FColor(58, 75, 120)); // --border #3A4B78
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor BorderSoft = FLinearColor(FColor(58, 75, 120, 140)); // --border-soft
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Gold = FLinearColor(FColor(201, 167, 90)); // --gold #C9A75A
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor GoldHi = FLinearColor(FColor(231, 200, 115)); // --gold-hi #E7C873
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Blue = FLinearColor(FColor(78, 163, 255)); // --blue #4EA3FF
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Violet = FLinearColor(FColor(123, 92, 255)); // --violet #7B5CFF
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Text = FLinearColor(FColor(244, 240, 230)); // --text #F4F0E6
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Text2 = FLinearColor(FColor(174, 182, 200)); // --text-2 #AEB6C8
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor TextDim = FLinearColor(FColor(105, 115, 138)); // --text-dim #69738A
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Danger = FLinearColor(FColor(217, 92, 92)); // --danger #D95C5C
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Online = FLinearColor(FColor(80, 216, 144)); // --online #50D890
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Palette")
FLinearColor Warn = FLinearColor(FColor(230, 180, 80)); // --warn #E6B450
};
// =====================================================================
// 2. Semantic — papéis (referenciam a primitive)
// =====================================================================
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleSemantic
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Accent = FLinearColor(FColor(201, 167, 90)); // Gold
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor AccentHover = FLinearColor(FColor(231, 200, 115)); // GoldHi
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Focus = FLinearColor(FColor(78, 163, 255)); // Blue
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Glow = FLinearColor(FColor(123, 92, 255)); // Violet
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor SurfaceBase = FLinearColor(FColor(7, 10, 18)); // Bg0
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Surface = FLinearColor(FColor(12, 18, 34, 235)); // Panel
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor SurfaceRaised = FLinearColor(FColor(17, 24, 42)); // Panel2
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor SurfaceSunken = FLinearColor(FColor(14, 20, 36)); // Panel3
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor OutlineStrong = FLinearColor(FColor(58, 75, 120)); // Border
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor OutlineSoft = FLinearColor(FColor(58, 75, 120, 140)); // BorderSoft
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor OnSurface = FLinearColor(FColor(244, 240, 230)); // Text
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor OnSurfaceMuted = FLinearColor(FColor(174, 182, 200)); // Text2
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor OnSurfaceDim = FLinearColor(FColor(105, 115, 138)); // TextDim
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Danger = FLinearColor(FColor(217, 92, 92)); // Danger
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Success = FLinearColor(FColor(80, 216, 144)); // Online
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Semantic")
FLinearColor Warning = FLinearColor(FColor(230, 180, 80)); // Warn
};
// =====================================================================
// 3. Component
// =====================================================================
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleText
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
FSlateFontInfo TitleFont; // Cinzel ExtraBold (display)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
FSlateFontInfo SectionFont; // Cinzel Bold (section title)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
FSlateFontInfo BodyFont; // Rajdhani Regular
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
FSlateFontInfo ButtonFont; // Rajdhani Bold
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
FSlateFontInfo LabelFont; // Rajdhani Bold (label/caps)
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
bool bLabelUppercase = true;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Text")
float TitleLetterSpacing = 0.f; // informativo (RichText/futuro)
};
/** Cores de uma variante de botão (primary/secondary/danger/ghost). */
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleButtonVariant
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BgNormal = FLinearColor::Transparent;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BgHover = FLinearColor::Transparent;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BgPressed = FLinearColor::Transparent;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BgDisabled = FLinearColor(0.f, 0.f, 0.f, 0.42f);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BorderNormal = FLinearColor::Transparent;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor BorderHover = FLinearColor::Transparent;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FLinearColor TextColor = FLinearColor::White;
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleButton
{
GENERATED_BODY()
// .btn-primary — dourado, texto quase preto
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FUIStyleButtonVariant Primary;
// .btn-secondary — painel sólido + borda
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FUIStyleButtonVariant Secondary;
// .btn-danger
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FUIStyleButtonVariant Danger;
// .btn-ghost — transparente + borda suave
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FUIStyleButtonVariant Ghost;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
FMargin Padding = FMargin(22.f, 12.f);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
float MinHeight = 48.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
float CornerRadius = 8.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
float BorderWidth = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
float HoverScale = 1.02f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
float PressedScale = 0.98f;
/** Tamanho por silhueta (Square/Rectangle/Topbar/Header). */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Button")
TMap<EUIButtonShape, FVector2D> ShapeSizes;
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStylePanel
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor Bg = FLinearColor(FColor(12, 18, 34, 235)); // Panel
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor BgRaised = FLinearColor(FColor(17, 24, 42)); // Panel2
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor BgSunken = FLinearColor(FColor(14, 20, 36)); // Panel3
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor BorderColor = FLinearColor(FColor(58, 75, 120));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor BorderSoftColor = FLinearColor(FColor(58, 75, 120, 140));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
float CornerRadius = 12.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
float CornerRadiusSmall = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
float BorderWidth = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FMargin Padding = FMargin(30.f);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FMargin PaddingSmall = FMargin(20.f);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor CardSelectedBorder = FLinearColor(FColor(201, 167, 90)); // Accent
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Panel")
FLinearColor CardSelectedBg = FLinearColor(FColor(24, 32, 58));
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleBorders
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
FLinearColor Color = FLinearColor(FColor(58, 75, 120));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
FLinearColor SoftColor = FLinearColor(FColor(58, 75, 120, 140));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
float Width = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
float Radius = 12.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
float RadiusSmall = 8.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
FLinearColor RuleColor = FLinearColor(FColor(201, 167, 90, 166)); // Gold ~.65
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
float RuleThickness = 2.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Borders")
float RuleSoftThickness = 1.f;
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleProgressBar
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
FLinearColor TrackColor = FLinearColor(FColor(14, 20, 36)); // Panel3
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
FLinearColor BorderColor = FLinearColor(FColor(58, 75, 120, 140));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
float Height = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
float CornerRadius = 6.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
float BorderWidth = 1.f;
/** Cor de preenchimento por tipo (Health/Mana/XP...). */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
TMap<EUIProgressBarType, FLinearColor> FillByType;
};
USTRUCT(BlueprintType)
struct ZMMO_API FUIStyleTooltip
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
FLinearColor Bg = FLinearColor(FColor(17, 24, 42)); // Panel2
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
FLinearColor BorderColor = FLinearColor(FColor(58, 75, 120));
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
float CornerRadius = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
float BorderWidth = 1.f;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
FMargin Padding = FMargin(18.f, 14.f);
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
FSlateFontInfo Font;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|Tooltip")
FLinearColor TextColor = FLinearColor(FColor(244, 240, 230)); // Text
};

View File

@@ -0,0 +1,74 @@
#pragma once
#include "CoreMinimal.h"
#include "UIStyleTypes.generated.h"
/**
* Enums do sistema de UI Style (tokens de tema visual).
*
* Espelha ThemeKeys.h: enums fortes, BlueprintType, primeiro valor None.
* O conceito de "tema ativo" continua sendo do UZMMOThemeSubsystem
* (resolvido por FName ThemeId). EUITheme é apenas validação tipada de
* design-time ao preencher DT_UI_Styles — não é a chave de runtime.
*/
UENUM(BlueprintType)
enum class EUITheme : uint8
{
None UMETA(DisplayName = "None"),
MMORPG UMETA(DisplayName = "MMORPG"),
Survival UMETA(DisplayName = "Survival"),
RPG UMETA(DisplayName = "RPG")
};
/** Forma/silhueta de um botão — usada pelo widget para escolher dimensões. */
UENUM(BlueprintType)
enum class EUIButtonShape : uint8
{
None UMETA(DisplayName = "None"),
Square UMETA(DisplayName = "Square"),
Rectangle UMETA(DisplayName = "Rectangle"),
Topbar UMETA(DisplayName = "Topbar"),
HeaderButton UMETA(DisplayName = "Header Button")
};
UENUM(BlueprintType)
enum class EUIPanelType : uint8
{
None UMETA(DisplayName = "None"),
Primary UMETA(DisplayName = "Primary"),
Secondary UMETA(DisplayName = "Secondary"),
Tertiary UMETA(DisplayName = "Tertiary"),
Card UMETA(DisplayName = "Card")
};
UENUM(BlueprintType)
enum class EUIProgressBarType : uint8
{
None UMETA(DisplayName = "None"),
Health UMETA(DisplayName = "Health"),
Mana UMETA(DisplayName = "Mana"),
Experience UMETA(DisplayName = "Experience"),
Cast UMETA(DisplayName = "Cast"),
Generic UMETA(DisplayName = "Generic")
};
UENUM(BlueprintType)
enum class EUIHeaderType : uint8
{
None UMETA(DisplayName = "None"),
Section UMETA(DisplayName = "Section"),
Panel UMETA(DisplayName = "Panel"),
SubPanel UMETA(DisplayName = "Sub Panel")
};
UENUM(BlueprintType)
enum class EUIIconType : uint8
{
None UMETA(DisplayName = "None"),
Inventory UMETA(DisplayName = "Inventory"),
Equipment UMETA(DisplayName = "Equipment"),
Skill UMETA(DisplayName = "Skill"),
Status UMETA(DisplayName = "Status"),
Currency UMETA(DisplayName = "Currency")
};

View File

@@ -0,0 +1,45 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataTable.h"
#include "Engine/World.h"
#include "ZoneRow.generated.h"
class USoundBase;
UENUM(BlueprintType)
enum class EZoneRules : uint8
{
Safe UMETA(DisplayName = "Safe"),
PvE UMETA(DisplayName = "PvE"),
PvP UMETA(DisplayName = "PvP"),
Dungeon UMETA(DisplayName = "Dungeon"),
Instance UMETA(DisplayName = "Instance")
};
USTRUCT(BlueprintType)
struct ZMMO_API FZoneRow : public FTableRowBase
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
TSoftObjectPtr<UWorld> Map;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
EZoneRules Rules = EZoneRules::PvE;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
int32 RecommendedLevelMin = 1;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
int32 RecommendedLevelMax = 10;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
TSoftObjectPtr<USoundBase> AmbientMusic;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Zone")
TSoftObjectPtr<USoundBase> AmbientSound;
};

View File

@@ -0,0 +1,11 @@
#include "ZMMOThemeDataAsset.h"
bool UZMMOThemeDataAsset::HasKey(EZMMOThemeKey Key) const
{
return Entries.Contains(Key);
}
const FThemeEntry* UZMMOThemeDataAsset::FindEntry(EZMMOThemeKey Key) const
{
return Entries.Find(Key);
}

View File

@@ -0,0 +1,26 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DataAsset.h"
#include "UI/ThemeKeys.h"
#include "UI/ThemeRow.h"
#include "ZMMOThemeDataAsset.generated.h"
UCLASS(BlueprintType)
class ZMMO_API UZMMOThemeDataAsset : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
FName ThemeId;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme")
FText DisplayName;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Theme", meta = (ToolTip = "Only fill the keys this theme overrides. Missing keys fall back to the Default theme."))
TMap<EZMMOThemeKey, FThemeEntry> Entries;
bool HasKey(EZMMOThemeKey Key) const;
const FThemeEntry* FindEntry(EZMMOThemeKey Key) const;
};

View File

@@ -0,0 +1,216 @@
#include "ZMMOThemeSubsystem.h"
#include "ZMMOThemeDataAsset.h"
#include "Engine/DataTable.h"
#include "Engine/Texture2D.h"
#include "Sound/SoundBase.h"
#include "NiagaraSystem.h"
#include "Misc/DateTime.h"
#include "UI/ThemeCalendarRow.h"
#include "UI/UIStyleRow.h"
namespace
{
/** Row Name da linha de estilo de fallback em DT_UI_Styles. */
const FName GUIStyleDefaultRow(TEXT("Default"));
}
void UZMMOThemeSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
DefaultTheme = DefaultThemeAsset.LoadSynchronous();
if (!DefaultTheme)
{
UE_LOG(LogTemp, Warning,
TEXT("[ZMMOThemeSubsystem] DefaultThemeAsset is not set. UI will have no theme."));
}
ResolveActiveTheme();
}
void UZMMOThemeSubsystem::Deinitialize()
{
ActiveTheme = nullptr;
DefaultTheme = nullptr;
Super::Deinitialize();
}
void UZMMOThemeSubsystem::ApplyServerTheme(FName ThemeId)
{
ServerThemeId = ThemeId;
ResolveActiveTheme();
}
void UZMMOThemeSubsystem::ForceTheme(FName ThemeId)
{
ForcedThemeId = ThemeId;
ResolveActiveTheme();
}
void UZMMOThemeSubsystem::ClearForcedTheme()
{
ForcedThemeId = NAME_None;
ResolveActiveTheme();
}
void UZMMOThemeSubsystem::ResolveActiveTheme()
{
FName Resolved = NAME_None;
if (!ForcedThemeId.IsNone())
{
Resolved = ForcedThemeId;
}
#if !UE_BUILD_SHIPPING
else if (!DevThemeOverride.IsNone())
{
Resolved = DevThemeOverride;
}
#endif
else if (!ServerThemeId.IsNone())
{
Resolved = ServerThemeId;
}
else
{
Resolved = ResolveByCalendar();
}
UZMMOThemeDataAsset* NewActive = !Resolved.IsNone() ? LoadThemeById(Resolved) : nullptr;
if (!NewActive)
{
NewActive = DefaultTheme;
Resolved = DefaultTheme ? DefaultTheme->ThemeId : NAME_None;
}
if (NewActive != ActiveTheme || Resolved != ActiveThemeId)
{
ActiveTheme = NewActive;
ActiveThemeId = Resolved;
ResolveActiveUIStyle(ActiveThemeId);
OnThemeChanged.Broadcast(ActiveThemeId);
}
}
void UZMMOThemeSubsystem::ResolveActiveUIStyle(FName ThemeId)
{
// Reset para os defaults do struct antes de aplicar a linha resolvida —
// assim um tema sem linha cai num estado coerente (paleta Aurora Arcana).
ActiveUIStyle = FUIStyle();
UDataTable* Table = UIStyleTable.LoadSynchronous();
if (!Table)
{
return;
}
const FUIStyleRow* Row = nullptr;
if (!ThemeId.IsNone())
{
Row = Table->FindRow<FUIStyleRow>(ThemeId, TEXT("UIStyle"));
}
if (!Row)
{
// Fallback: linha "Default" (mesma política dos assets, §5).
Row = Table->FindRow<FUIStyleRow>(GUIStyleDefaultRow, TEXT("UIStyle"));
}
if (Row)
{
ActiveUIStyle = Row->Style;
}
}
FName UZMMOThemeSubsystem::ResolveByCalendar() const
{
UDataTable* Table = CalendarTable.LoadSynchronous();
if (!Table)
{
return NAME_None;
}
const FDateTime Now = FDateTime::Now();
const int32 NowMonth = Now.GetMonth();
const int32 NowDay = Now.GetDay();
const int32 NowMD = NowMonth * 100 + NowDay;
FName Best = NAME_None;
int32 BestPriority = MIN_int32;
TArray<FName> RowNames = Table->GetRowNames();
for (const FName& RowName : RowNames)
{
const FThemeCalendarRow* Row = Table->FindRow<FThemeCalendarRow>(RowName, TEXT("ThemeCalendar"));
if (!Row || Row->ThemeId.IsNone())
{
continue;
}
const int32 StartMD = Row->StartMonth * 100 + Row->StartDay;
const int32 EndMD = Row->EndMonth * 100 + Row->EndDay;
const bool bInRange = (StartMD <= EndMD)
? (NowMD >= StartMD && NowMD <= EndMD)
: (NowMD >= StartMD || NowMD <= EndMD); // wraps across year (e.g. 12-15 -> 01-05)
if (bInRange && Row->Priority > BestPriority)
{
Best = Row->ThemeId;
BestPriority = Row->Priority;
}
}
return Best;
}
UZMMOThemeDataAsset* UZMMOThemeSubsystem::LoadThemeById(FName ThemeId) const
{
if (const TSoftObjectPtr<UZMMOThemeDataAsset>* Soft = ThemeRegistry.Find(ThemeId))
{
return Soft->LoadSynchronous();
}
return nullptr;
}
const FThemeEntry* UZMMOThemeSubsystem::FindEntryWithFallback(EZMMOThemeKey Key) const
{
if (ActiveTheme)
{
if (const FThemeEntry* Entry = ActiveTheme->FindEntry(Key))
{
return Entry;
}
}
if (DefaultTheme && DefaultTheme != ActiveTheme)
{
if (const FThemeEntry* Entry = DefaultTheme->FindEntry(Key))
{
return Entry;
}
}
return nullptr;
}
UTexture2D* UZMMOThemeSubsystem::GetTexture(EZMMOThemeKey Key) const
{
const FThemeEntry* Entry = FindEntryWithFallback(Key);
return Entry ? Entry->Texture.LoadSynchronous() : nullptr;
}
USoundBase* UZMMOThemeSubsystem::GetSound(EZMMOThemeKey Key) const
{
const FThemeEntry* Entry = FindEntryWithFallback(Key);
return Entry ? Entry->Sound.LoadSynchronous() : nullptr;
}
UNiagaraSystem* UZMMOThemeSubsystem::GetVFX(EZMMOThemeKey Key) const
{
const FThemeEntry* Entry = FindEntryWithFallback(Key);
return Entry ? Entry->VFX.LoadSynchronous() : nullptr;
}
UObject* UZMMOThemeSubsystem::GetGeneric(EZMMOThemeKey Key) const
{
const FThemeEntry* Entry = FindEntryWithFallback(Key);
return Entry ? Entry->Generic.LoadSynchronous() : nullptr;
}

View File

@@ -0,0 +1,124 @@
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "UI/ThemeKeys.h"
#include "UI/ThemeRow.h"
#include "UI/UIStyleRow.h"
#include "ZMMOThemeSubsystem.generated.h"
class UZMMOThemeDataAsset;
class UDataTable;
class UTexture2D;
class USoundBase;
class UNiagaraSystem;
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnZMMOThemeChanged, FName, NewThemeId);
/**
* Resolves which UI theme is active and answers asset lookups by EZMMOThemeKey.
*
* Resolution precedence (see ARQUITETURA.md §1.10):
* 1. Dev override (.ini DevThemeOverride) — ignored in Shipping builds.
* 2. Authoritative server theme (set via ApplyServerTheme).
* 3. Local calendar (DT_ThemeCalendar).
* 4. DA_Theme_Default.
*
* Widgets must never hold hard refs to theme textures/sounds. They consume the
* active theme through Get* methods on this subsystem.
*/
UCLASS(Config = Game)
class ZMMO_API UZMMOThemeSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
// USubsystem
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
/** Server-authoritative theme. Call from the ZeusNetwork ServerHello handler. */
UFUNCTION(BlueprintCallable, Category = "Theme")
void ApplyServerTheme(FName ThemeId);
/** Forces a specific theme regardless of precedence. Use only for debug UI. */
UFUNCTION(BlueprintCallable, Category = "Theme|Debug")
void ForceTheme(FName ThemeId);
/** Resets to the precedence-resolved theme. */
UFUNCTION(BlueprintCallable, Category = "Theme|Debug")
void ClearForcedTheme();
UFUNCTION(BlueprintPure, Category = "Theme")
FName GetActiveThemeId() const { return ActiveThemeId; }
UFUNCTION(BlueprintCallable, Category = "Theme")
UTexture2D* GetTexture(EZMMOThemeKey Key) const;
UFUNCTION(BlueprintCallable, Category = "Theme")
USoundBase* GetSound(EZMMOThemeKey Key) const;
UFUNCTION(BlueprintCallable, Category = "Theme")
UNiagaraSystem* GetVFX(EZMMOThemeKey Key) const;
UFUNCTION(BlueprintCallable, Category = "Theme")
UObject* GetGeneric(EZMMOThemeKey Key) const;
/**
* Tokens de estilo (cores/fontes/dimensões) do tema ativo, resolvidos de
* DT_UI_Styles pelo ThemeId. Faz fallback para a linha "Default" quando o
* tema ativo não tem linha própria — mesma política dos assets (§5).
*/
UFUNCTION(BlueprintPure, Category = "Theme|Style")
const FUIStyle& GetActiveUIStyle() const { return ActiveUIStyle; }
/** Fired whenever the active theme actually changes. */
UPROPERTY(BlueprintAssignable, Category = "Theme")
FOnZMMOThemeChanged OnThemeChanged;
protected:
/** Default theme. Must be filled with every key — it is the final fallback. */
UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
TSoftObjectPtr<UZMMOThemeDataAsset> DefaultThemeAsset;
/** Registry of seasonal/event themes keyed by ThemeId. */
UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
TMap<FName, TSoftObjectPtr<UZMMOThemeDataAsset>> ThemeRegistry;
/** Local calendar table (FThemeCalendarRow). Optional. */
UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
TSoftObjectPtr<UDataTable> CalendarTable;
/** Tabela de tokens de estilo (FUIStyleRow), keyed por ThemeId. */
UPROPERTY(Config, EditDefaultsOnly, Category = "Theme")
TSoftObjectPtr<UDataTable> UIStyleTable;
/** Dev-only override read from DefaultGame.ini. Empty in Shipping. */
UPROPERTY(Config, EditDefaultsOnly, Category = "Theme|Debug")
FName DevThemeOverride;
private:
void ResolveActiveTheme();
FName ResolveByCalendar() const;
UZMMOThemeDataAsset* LoadThemeById(FName ThemeId) const;
const FThemeEntry* FindEntryWithFallback(EZMMOThemeKey Key) const;
void ResolveActiveUIStyle(FName ThemeId);
UPROPERTY(Transient)
TObjectPtr<UZMMOThemeDataAsset> ActiveTheme;
UPROPERTY(Transient)
TObjectPtr<UZMMOThemeDataAsset> DefaultTheme;
UPROPERTY(Transient)
FName ActiveThemeId;
UPROPERTY(Transient)
FName ServerThemeId;
UPROPERTY(Transient)
FName ForcedThemeId;
UPROPERTY(Transient)
FUIStyle ActiveUIStyle;
};

View File

@@ -14,6 +14,7 @@ public class ZMMO : ModuleRules
"EnhancedInput",
"UMG",
"Slate",
"Niagara",
"ZeusNetwork"
});
@@ -27,7 +28,17 @@ public class ZMMO : ModuleRules
"ZMMO/Game/Entity",
"ZMMO/Game/Controller",
"ZMMO/Game/Modes",
"ZMMO/Game/Network"
"ZMMO/Game/Network",
"ZMMO/Game/UI",
"ZMMO/Data",
"ZMMO/Data/Items",
"ZMMO/Data/Mobs",
"ZMMO/Data/Players",
"ZMMO/Data/NPCs",
"ZMMO/Data/Abilities",
"ZMMO/Data/Quests",
"ZMMO/Data/UI",
"ZMMO/Data/World"
});
}
}