Compare commits
2 Commits
88eb20eefa
...
e1fca1ae8d
| Author | SHA1 | Date | |
|---|---|---|---|
| e1fca1ae8d | |||
| c9492a3910 |
Binary file not shown.
Binary file not shown.
BIN
Content/ZMMO/UI/HUD/WBP_PlayerVitalsPanel.uasset
Normal file
BIN
Content/ZMMO/UI/HUD/WBP_PlayerVitalsPanel.uasset
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -374,29 +374,78 @@ struct ZMMO_API FUIStyleBorders
|
|||||||
float RuleSoftThickness = 1.f;
|
float RuleSoftThickness = 1.f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Variante completa de ProgressBar: materiais por layer (Fill/BG/Track/Edge/Shimmer)
|
||||||
|
* + parametros visuais (DrawStyle, CornerRadius, Border) + toggles de efeito.
|
||||||
|
*
|
||||||
|
* Material nulo = nao sobrescreve o brush do WBP (usa o que esta atribuido la).
|
||||||
|
* Aplicada pelo UUIProgressBar_Base quando bUseTheme=true via Variant FName.
|
||||||
|
*/
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct ZMMO_API FUIStyleProgressBarVariant
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
// ---- Materiais (opcionais; nullptr = mantem brush do WBP) ----
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Materials")
|
||||||
|
TObjectPtr<UMaterialInterface> FillMaterial;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Materials")
|
||||||
|
TObjectPtr<UMaterialInterface> BackgroundMaterial;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Materials")
|
||||||
|
TObjectPtr<UMaterialInterface> TrackGridMaterial;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Materials")
|
||||||
|
TObjectPtr<UMaterialInterface> EdgeMaterial;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Materials")
|
||||||
|
TObjectPtr<UMaterialInterface> ShimmerMaterial;
|
||||||
|
|
||||||
|
// ---- Style (forma + bordas) ----
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Style")
|
||||||
|
EUIProgressBarStyle DrawStyle = EUIProgressBarStyle::Rounded;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Style",
|
||||||
|
meta = (ClampMin = "0", ClampMax = "100"))
|
||||||
|
float CornerRadius = 8.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Style")
|
||||||
|
bool bShowBorder = false;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Style")
|
||||||
|
FLinearColor BorderColour = FLinearColor(0.f, 0.f, 0.f, 0.8f);
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Style",
|
||||||
|
meta = (ClampMin = "0", ClampMax = "10"))
|
||||||
|
float BorderWidth = 1.f;
|
||||||
|
|
||||||
|
// ---- Toggles de efeito ----
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Effects")
|
||||||
|
bool bShowTrackGrid = false;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Effects")
|
||||||
|
bool bShowEdge = false;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar|Effects")
|
||||||
|
bool bShowShimmer = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProgressBar — padrao multi-map Hyper-style. Variantes (HP/MP/XP/Cast/...) sao
|
||||||
|
* editadas direto no DT_UI_Styles; cada UUIProgressBar_Base referencia uma key
|
||||||
|
* FName (dropdown via meta=GetOptions resolve esse mapa em runtime+editor).
|
||||||
|
*/
|
||||||
USTRUCT(BlueprintType)
|
USTRUCT(BlueprintType)
|
||||||
struct ZMMO_API FUIStyleProgressBar
|
struct ZMMO_API FUIStyleProgressBar
|
||||||
{
|
{
|
||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "UI Style|ProgressBar")
|
||||||
FLinearColor TrackColor = FLinearColor(FColor(14, 20, 36)); // Panel3
|
TMap<FName, FUIStyleProgressBarVariant> Variants;
|
||||||
|
|
||||||
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)
|
USTRUCT(BlueprintType)
|
||||||
|
|||||||
@@ -81,6 +81,16 @@ enum class EUIProgressBarType : uint8
|
|||||||
Generic UMETA(DisplayName = "Generic")
|
Generic UMETA(DisplayName = "Generic")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Preset que controla Brush.DrawAs em todos os UImages da ProgressBar. */
|
||||||
|
UENUM(BlueprintType)
|
||||||
|
enum class EUIProgressBarStyle : uint8
|
||||||
|
{
|
||||||
|
/** DrawAs=Image. Sem mascara nos cantos. */
|
||||||
|
Box UMETA(DisplayName = "Box"),
|
||||||
|
/** DrawAs=RoundedBox. Cantos arredondados via Slate nativo (pixel-perfect). */
|
||||||
|
Rounded UMETA(DisplayName = "Rounded"),
|
||||||
|
};
|
||||||
|
|
||||||
UENUM(BlueprintType)
|
UENUM(BlueprintType)
|
||||||
enum class EUIHeaderType : uint8
|
enum class EUIHeaderType : uint8
|
||||||
{
|
{
|
||||||
|
|||||||
96
Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp
Normal file
96
Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.cpp
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include "ZMMOHudPlayerVitalsWidget.h"
|
||||||
|
|
||||||
|
#include "Components/TextBlock.h"
|
||||||
|
#include "UI/Widgets/UIProgressBar_Base.h"
|
||||||
|
#include "Internationalization/Text.h"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
/** Formata int com separador de milhar do locale (ex.: 9840 -> "9,840"). */
|
||||||
|
FText FormatNumber(int64 Value)
|
||||||
|
{
|
||||||
|
return FText::AsNumber(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SafeRatio(int32 Current, int32 Max)
|
||||||
|
{
|
||||||
|
return Max > 0 ? FMath::Clamp(static_cast<float>(Current) / static_cast<float>(Max), 0.f, 1.f) : 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOHudPlayerVitalsWidget::ApplySnapshot(const FZMMOAttributesSnapshot& Snapshot)
|
||||||
|
{
|
||||||
|
LastSnapshot = Snapshot;
|
||||||
|
|
||||||
|
// HP / SP (pool efetivo — % real)
|
||||||
|
ApplyHpSp(Snapshot.Hp, Snapshot.MaxHp, Snapshot.Sp, Snapshot.MaxSp);
|
||||||
|
|
||||||
|
// Level
|
||||||
|
if (LvlText)
|
||||||
|
{
|
||||||
|
LvlText->SetText(FText::FromString(FString::Printf(TEXT("LVL %d"), Snapshot.BaseLevel)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// BASE / JOB EXP — sem "exp-to-next" no snapshot. Readout mostra valor
|
||||||
|
// absoluto acumulado; as barras ficam pra quando a curva de exp existir.
|
||||||
|
if (ExpReadout)
|
||||||
|
{
|
||||||
|
ExpReadout->SetText(FormatNumber(Snapshot.BaseExp));
|
||||||
|
}
|
||||||
|
if (JobReadout)
|
||||||
|
{
|
||||||
|
JobReadout->SetText(FormatNumber(Snapshot.JobExp));
|
||||||
|
}
|
||||||
|
|
||||||
|
OnSnapshotApplied(Snapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOHudPlayerVitalsWidget::ApplyHpSp(int32 Hp, int32 MaxHp, int32 Sp, int32 MaxSp)
|
||||||
|
{
|
||||||
|
LastSnapshot.Hp = Hp;
|
||||||
|
LastSnapshot.MaxHp = MaxHp;
|
||||||
|
LastSnapshot.Sp = Sp;
|
||||||
|
LastSnapshot.MaxSp = MaxSp;
|
||||||
|
|
||||||
|
if (HpBar)
|
||||||
|
{
|
||||||
|
HpBar->SetTargetPrimaryLevel(SafeRatio(Hp, MaxHp));
|
||||||
|
}
|
||||||
|
if (SpBar)
|
||||||
|
{
|
||||||
|
SpBar->SetTargetPrimaryLevel(SafeRatio(Sp, MaxSp));
|
||||||
|
}
|
||||||
|
if (HpReadout)
|
||||||
|
{
|
||||||
|
HpReadout->SetText(FText::Format(
|
||||||
|
NSLOCTEXT("ZMMOHud", "HpSpReadout", "{0}/{1}"),
|
||||||
|
FormatNumber(Hp), FormatNumber(MaxHp)));
|
||||||
|
}
|
||||||
|
if (SpReadout)
|
||||||
|
{
|
||||||
|
SpReadout->SetText(FText::Format(
|
||||||
|
NSLOCTEXT("ZMMOHud", "HpSpReadout", "{0}/{1}"),
|
||||||
|
FormatNumber(Sp), FormatNumber(MaxSp)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOHudPlayerVitalsWidget::SetCharName(const FString& InName)
|
||||||
|
{
|
||||||
|
if (NameText)
|
||||||
|
{
|
||||||
|
NameText->SetText(FText::FromString(InName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOHudPlayerVitalsWidget::SetClassName(const FString& InClassName)
|
||||||
|
{
|
||||||
|
if (ClassText)
|
||||||
|
{
|
||||||
|
ClassText->SetText(FText::FromString(InClassName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UZMMOHudPlayerVitalsWidget::OnSnapshotApplied_Implementation(const FZMMOAttributesSnapshot& /*Snapshot*/)
|
||||||
|
{
|
||||||
|
// Default vazio — skin do WBP estende se quiser (low-HP flash, etc.).
|
||||||
|
}
|
||||||
92
Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.h
Normal file
92
Source/ZMMO/Game/UI/InGame/ZMMOHudPlayerVitalsWidget.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CommonUserWidget.h"
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "ZMMOAttributeTypes.h"
|
||||||
|
#include "ZMMOHudPlayerVitalsWidget.generated.h"
|
||||||
|
|
||||||
|
class UUIProgressBar_Base;
|
||||||
|
class UTextBlock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sub-widget do HUD: painel de vitais do player (portrait + nome/job/level +
|
||||||
|
* barras HP/SP/BASE EXP/JOB EXP). Sem auto-bind no AttributeComponent — o
|
||||||
|
* parent (UZMMOHudWidget) propaga snapshots via ApplySnapshot/ApplyHpSp.
|
||||||
|
*
|
||||||
|
* Barras são UUIProgressBar_Base (material custom Primary/Secondary). HP/SP
|
||||||
|
* têm pool efetivo no snapshot → % real. BASE/JOB EXP só têm exp acumulado
|
||||||
|
* (sem "exp-to-next") — barras de EXP ficam pra quando a curva existir;
|
||||||
|
* por ora o readout mostra o valor absoluto.
|
||||||
|
*
|
||||||
|
* WBP filho (WBP_PlayerVitalsPanel) deve ter widgets com EXATAMENTE estes
|
||||||
|
* nomes: HpBar, SpBar (obrigatórios); ExpBar, JobBar, NameText, ClassText,
|
||||||
|
* LvlText, HpReadout, SpReadout, ExpReadout, JobReadout (opcionais).
|
||||||
|
*/
|
||||||
|
UCLASS(Abstract, Blueprintable, BlueprintType)
|
||||||
|
class ZMMO_API UZMMOHudPlayerVitalsWidget : public UCommonUserWidget
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Atualiza todos os campos a partir do snapshot. Chamado pelo UZMMOHudWidget. */
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
|
||||||
|
void ApplySnapshot(const FZMMOAttributesSnapshot& Snapshot);
|
||||||
|
|
||||||
|
/** Atualiza apenas HP/SP (otimização do tick — sem mexer em level/exp). */
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
|
||||||
|
void ApplyHpSp(int32 Hp, int32 MaxHp, int32 Sp, int32 MaxSp);
|
||||||
|
|
||||||
|
/** Nome do char — vem do PlayerState (não está no snapshot). */
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
|
||||||
|
void SetCharName(const FString& InName);
|
||||||
|
|
||||||
|
/** Nome do job/classe — vem do JobsDatabase via ClassId (não é string no snapshot). */
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "Zeus|HUD")
|
||||||
|
void SetClassName(const FString& InClassName);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Hook BP pra skin reagir (cores low-HP, animações, etc.). */
|
||||||
|
UFUNCTION(BlueprintNativeEvent, Category = "Zeus|HUD")
|
||||||
|
void OnSnapshotApplied(const FZMMOAttributesSnapshot& Snapshot);
|
||||||
|
virtual void OnSnapshotApplied_Implementation(const FZMMOAttributesSnapshot& Snapshot);
|
||||||
|
|
||||||
|
// === BindWidget — barras (HP/SP obrigatórias) ===
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidget), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UUIProgressBar_Base> HpBar;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidget), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UUIProgressBar_Base> SpBar;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UUIProgressBar_Base> ExpBar;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UUIProgressBar_Base> JobBar;
|
||||||
|
|
||||||
|
// === BindWidget — textos (todos opcionais) ===
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> NameText;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> ClassText;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> LvlText;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> HpReadout;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> SpReadout;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> ExpReadout;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
TObjectPtr<UTextBlock> JobReadout;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Último snapshot recebido (cache pra ApplyHpSp manter MaxHp/MaxSp). */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
FZMMOAttributesSnapshot LastSnapshot;
|
||||||
|
};
|
||||||
@@ -10,6 +10,9 @@
|
|||||||
#include "ZMMO.h"
|
#include "ZMMO.h"
|
||||||
#include "ZMMOAttributeComponent.h"
|
#include "ZMMOAttributeComponent.h"
|
||||||
#include "ZMMOHudHpSpWidget.h"
|
#include "ZMMOHudHpSpWidget.h"
|
||||||
|
#include "ZMMOHudPlayerVitalsWidget.h"
|
||||||
|
#include "ZMMOJobsLibrary.h"
|
||||||
|
#include "ZMMOPlayerState.h"
|
||||||
|
|
||||||
UZMMOHudWidget::UZMMOHudWidget(const FObjectInitializer& ObjectInitializer)
|
UZMMOHudWidget::UZMMOHudWidget(const FObjectInitializer& ObjectInitializer)
|
||||||
: Super(ObjectInitializer)
|
: Super(ObjectInitializer)
|
||||||
@@ -98,12 +101,28 @@ void UZMMOHudWidget::UnbindFromComponent()
|
|||||||
|
|
||||||
void UZMMOHudWidget::HandleAttributesChanged(const FZMMOAttributesSnapshot& Snapshot)
|
void UZMMOHudWidget::HandleAttributesChanged(const FZMMOAttributesSnapshot& Snapshot)
|
||||||
{
|
{
|
||||||
// Propaga snapshot aos sub-widgets que ja existem. Em V1 so' HpSpBar.
|
// Propaga snapshot aos sub-widgets que ja existem.
|
||||||
if (HpSpBar)
|
if (HpSpBar)
|
||||||
{
|
{
|
||||||
HpSpBar->ApplySnapshot(Snapshot);
|
HpSpBar->ApplySnapshot(Snapshot);
|
||||||
}
|
}
|
||||||
// Futuros: PlayerInfo->ApplySnapshot, Buffs->RefreshIcons, etc.
|
if (PlayerVitals)
|
||||||
|
{
|
||||||
|
PlayerVitals->ApplySnapshot(Snapshot);
|
||||||
|
|
||||||
|
// Identidade: nome vem do PlayerState (não está no snapshot); job vem
|
||||||
|
// do JobsSubsystem resolvendo ClassId -> display name.
|
||||||
|
if (UZMMOAttributeComponent* Comp = BoundComponent.Get())
|
||||||
|
{
|
||||||
|
if (const AZMMOPlayerState* PS = Cast<AZMMOPlayerState>(Comp->GetOwner()))
|
||||||
|
{
|
||||||
|
PlayerVitals->SetCharName(PS->CharName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PlayerVitals->SetClassName(
|
||||||
|
UZMMOJobsLibrary::GetJobDisplayName(this, Snapshot.ClassId).ToString());
|
||||||
|
}
|
||||||
|
// Futuros: Buffs->RefreshIcons, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
void UZMMOHudWidget::HandleHpSpChanged(int32 Hp, int32 Sp)
|
void UZMMOHudWidget::HandleHpSpChanged(int32 Hp, int32 Sp)
|
||||||
@@ -115,6 +134,10 @@ void UZMMOHudWidget::HandleHpSpChanged(int32 Hp, int32 Sp)
|
|||||||
{
|
{
|
||||||
HpSpBar->ApplyHpSp(Hp, Snap.MaxHp, Sp, Snap.MaxSp);
|
HpSpBar->ApplyHpSp(Hp, Snap.MaxHp, Sp, Snap.MaxSp);
|
||||||
}
|
}
|
||||||
|
if (PlayerVitals)
|
||||||
|
{
|
||||||
|
PlayerVitals->ApplyHpSp(Hp, Snap.MaxHp, Sp, Snap.MaxSp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ class UTextBlock;
|
|||||||
class UWidget;
|
class UWidget;
|
||||||
class UZMMOAttributeComponent;
|
class UZMMOAttributeComponent;
|
||||||
class UZMMOHudHpSpWidget;
|
class UZMMOHudHpSpWidget;
|
||||||
|
class UZMMOHudPlayerVitalsWidget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root da HUD de gameplay. UCommonActivatableWidget pushed pelo
|
* Root da HUD de gameplay. UCommonActivatableWidget pushed pelo
|
||||||
@@ -74,6 +75,12 @@ protected:
|
|||||||
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
UZMMOHudHpSpWidget* HpSpBar = nullptr;
|
UZMMOHudHpSpWidget* HpSpBar = nullptr;
|
||||||
|
|
||||||
|
/// Painel de vitais novo (portrait + nome/job/level + HP/SP/EXP/JOB bars).
|
||||||
|
/// Substitui o HpSpBar legado. BindWidgetOptional — coexiste durante a
|
||||||
|
/// migração; o WBP_HUD pode ter um ou outro.
|
||||||
|
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional), Category = "Zeus|HUD")
|
||||||
|
UZMMOHudPlayerVitalsWidget* PlayerVitals = nullptr;
|
||||||
|
|
||||||
/// Container do toast "LEVEL UP!" (Fase 3). Hidden por default; em
|
/// Container do toast "LEVEL UP!" (Fase 3). Hidden por default; em
|
||||||
/// `HandleLevelUp` vira visivel por `LevelUpToastDurationSec` segundos
|
/// `HandleLevelUp` vira visivel por `LevelUpToastDurationSec` segundos
|
||||||
/// (ver `Show/HideLevelUpToast`). WBP_HUD coloca um Border + Image + TextBlock
|
/// (ver `Show/HideLevelUpToast`). WBP_HUD coloca um Border + Image + TextBlock
|
||||||
|
|||||||
@@ -2,10 +2,15 @@
|
|||||||
|
|
||||||
#include "Components/Image.h"
|
#include "Components/Image.h"
|
||||||
#include "Components/OverlaySlot.h"
|
#include "Components/OverlaySlot.h"
|
||||||
|
#include "Engine/DataTable.h"
|
||||||
|
#include "Engine/GameInstance.h"
|
||||||
#include "Materials/MaterialInstanceDynamic.h"
|
#include "Materials/MaterialInstanceDynamic.h"
|
||||||
#include "Materials/MaterialInterface.h"
|
#include "Materials/MaterialInterface.h"
|
||||||
#include "Styling/SlateBrush.h"
|
#include "Styling/SlateBrush.h"
|
||||||
#include "Styling/SlateTypes.h"
|
#include "Styling/SlateTypes.h"
|
||||||
|
#include "UI/UIStyleRow.h"
|
||||||
|
#include "UI/UIStyleTokens.h"
|
||||||
|
#include "ZMMOThemeSubsystem.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -46,6 +51,50 @@ namespace
|
|||||||
{
|
{
|
||||||
return 1.f - FMath::Pow(1.f - Alpha, 3.f);
|
return 1.f - FMath::Pow(1.f - Alpha, 3.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolve a FUIStyle ativa — runtime via ThemeSubsystem, design-time via DT direto. */
|
||||||
|
FUIStyle ResolveProgressBarStyle(const UUserWidget* Widget)
|
||||||
|
{
|
||||||
|
if (Widget)
|
||||||
|
{
|
||||||
|
if (const UGameInstance* GI = Widget->GetGameInstance())
|
||||||
|
{
|
||||||
|
if (const UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
|
||||||
|
{
|
||||||
|
return Theme->GetActiveUIStyle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Design-time fallback: lê DT_UI_Styles row "Default" direto do disk.
|
||||||
|
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("UIProgressBarDesign"), false))
|
||||||
|
{
|
||||||
|
return Row->Style;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FUIStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FString> CollectVariantOptions()
|
||||||
|
{
|
||||||
|
TArray<FString> Options;
|
||||||
|
Options.Add(FString()); // entrada vazia = sem theme
|
||||||
|
const UDataTable* DT = LoadObject<UDataTable>(nullptr,
|
||||||
|
TEXT("/Game/ZMMO/Data/UI/DT_UI_Styles.DT_UI_Styles"));
|
||||||
|
if (!DT) return Options;
|
||||||
|
const FUIStyleRow* Row = DT->FindRow<FUIStyleRow>(
|
||||||
|
FName(TEXT("Default")), TEXT("UIProgressBarGetOptions"), false);
|
||||||
|
if (!Row) return Options;
|
||||||
|
for (const TPair<FName, FUIStyleProgressBarVariant>& Pair : Row->Style.ProgressBar.Variants)
|
||||||
|
{
|
||||||
|
Options.Add(Pair.Key.ToString());
|
||||||
|
}
|
||||||
|
Options.Sort();
|
||||||
|
return Options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UUIProgressBar_Base::NativePreConstruct()
|
void UUIProgressBar_Base::NativePreConstruct()
|
||||||
@@ -64,9 +113,16 @@ void UUIProgressBar_Base::NativePreConstruct()
|
|||||||
SecondaryElapsed = 0.f;
|
SecondaryElapsed = 0.f;
|
||||||
bAnimatingSecondary = false;
|
bAnimatingSecondary = false;
|
||||||
|
|
||||||
ApplyBrushStyle();
|
if (bUseTheme)
|
||||||
EnsureMIDs();
|
{
|
||||||
ApplyMaterialOverrides();
|
RefreshUIStyle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyBrushStyle();
|
||||||
|
EnsureMIDs();
|
||||||
|
ApplyMaterialOverrides();
|
||||||
|
}
|
||||||
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
||||||
ApplySecondaryToMID(CurrentSecondaryLevel);
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
||||||
}
|
}
|
||||||
@@ -75,13 +131,56 @@ void UUIProgressBar_Base::NativeConstruct()
|
|||||||
{
|
{
|
||||||
Super::NativeConstruct();
|
Super::NativeConstruct();
|
||||||
|
|
||||||
ApplyBrushStyle();
|
if (!bThemeBound)
|
||||||
EnsureMIDs();
|
{
|
||||||
ApplyMaterialOverrides();
|
if (const UGameInstance* GI = GetGameInstance())
|
||||||
|
{
|
||||||
|
if (UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
|
||||||
|
{
|
||||||
|
Theme->OnThemeChanged.AddDynamic(this, &UUIProgressBar_Base::HandleThemeChanged);
|
||||||
|
bThemeBound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bUseTheme)
|
||||||
|
{
|
||||||
|
RefreshUIStyle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyBrushStyle();
|
||||||
|
EnsureMIDs();
|
||||||
|
ApplyMaterialOverrides();
|
||||||
|
}
|
||||||
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
||||||
ApplySecondaryToMID(CurrentSecondaryLevel);
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UUIProgressBar_Base::NativeDestruct()
|
||||||
|
{
|
||||||
|
if (bThemeBound)
|
||||||
|
{
|
||||||
|
if (const UGameInstance* GI = GetGameInstance())
|
||||||
|
{
|
||||||
|
if (UZMMOThemeSubsystem* Theme = GI->GetSubsystem<UZMMOThemeSubsystem>())
|
||||||
|
{
|
||||||
|
Theme->OnThemeChanged.RemoveDynamic(this, &UUIProgressBar_Base::HandleThemeChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bThemeBound = false;
|
||||||
|
}
|
||||||
|
Super::NativeDestruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UUIProgressBar_Base::HandleThemeChanged(FName /*NewThemeId*/)
|
||||||
|
{
|
||||||
|
if (bUseTheme)
|
||||||
|
{
|
||||||
|
RefreshUIStyle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UUIProgressBar_Base::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
void UUIProgressBar_Base::NativeTick(const FGeometry& MyGeometry, float InDeltaTime)
|
||||||
{
|
{
|
||||||
Super::NativeTick(MyGeometry, InDeltaTime);
|
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||||
@@ -584,3 +683,79 @@ void UUIProgressBar_Base::ApplySecondaryToMID(float Value)
|
|||||||
FillMID->SetScalarParameterValue(P_SecondaryLevel, Value);
|
FillMID->SetScalarParameterValue(P_SecondaryLevel, Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// =====================================================================
|
||||||
|
// Theme integration (bUseTheme + Variant)
|
||||||
|
// =====================================================================
|
||||||
|
|
||||||
|
void UUIProgressBar_Base::RefreshUIStyle()
|
||||||
|
{
|
||||||
|
if (!bUseTheme || Variant.IsNone())
|
||||||
|
{
|
||||||
|
// Fallback: comportamento manual.
|
||||||
|
ApplyBrushStyle();
|
||||||
|
EnsureMIDs();
|
||||||
|
ApplyMaterialOverrides();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const FUIStyle ActiveStyle = ResolveProgressBarStyle(this);
|
||||||
|
const FUIStyleProgressBarVariant* V = ActiveStyle.ProgressBar.Variants.Find(Variant);
|
||||||
|
if (!V)
|
||||||
|
{
|
||||||
|
// Variante não existe no DT — fallback manual.
|
||||||
|
ApplyBrushStyle();
|
||||||
|
EnsureMIDs();
|
||||||
|
ApplyMaterialOverrides();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ApplyThemeVariant(*V);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UUIProgressBar_Base::ApplyThemeVariant(const FUIStyleProgressBarVariant& V)
|
||||||
|
{
|
||||||
|
// Style — copia pros campos do widget e re-aplica brush.
|
||||||
|
DrawStyle = V.DrawStyle;
|
||||||
|
CornerRadius = V.CornerRadius;
|
||||||
|
bShowBorder = V.bShowBorder;
|
||||||
|
BorderColour = V.BorderColour;
|
||||||
|
BorderWidth = V.BorderWidth;
|
||||||
|
|
||||||
|
// Toggles de efeito
|
||||||
|
bShowTrackGrid = V.bShowTrackGrid;
|
||||||
|
bShowEdge = V.bShowEdge;
|
||||||
|
bShowShimmer = V.bShowShimmer;
|
||||||
|
|
||||||
|
// Troca materiais nos brushes quando definidos. Reseta MIDs cacheados pra
|
||||||
|
// que EnsureMIDs() pegue o material novo na próxima chamada.
|
||||||
|
auto AssignMaterial = [](UImage* Img, UMaterialInterface* Mat)
|
||||||
|
{
|
||||||
|
if (!Img || !Mat) return;
|
||||||
|
FSlateBrush B = Img->GetBrush();
|
||||||
|
if (B.GetResourceObject() != Mat)
|
||||||
|
{
|
||||||
|
B.SetResourceObject(Mat);
|
||||||
|
B.DrawAs = ESlateBrushDrawType::Image; // reset; ApplyBrushStyle re-aplica
|
||||||
|
Img->SetBrush(B);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (V.FillMaterial) { AssignMaterial(FillImage, V.FillMaterial); FillMID = nullptr; }
|
||||||
|
if (V.BackgroundMaterial) { AssignMaterial(BackgroundImage, V.BackgroundMaterial); BackgroundMID = nullptr; }
|
||||||
|
if (V.TrackGridMaterial) { AssignMaterial(TrackGridImage, V.TrackGridMaterial); TrackGridMID = nullptr; }
|
||||||
|
if (V.EdgeMaterial) { AssignMaterial(EdgeImage, V.EdgeMaterial); EdgeMID = nullptr; }
|
||||||
|
if (V.ShimmerMaterial) { AssignMaterial(ShimmerImage, V.ShimmerMaterial); ShimmerMID = nullptr; }
|
||||||
|
|
||||||
|
ApplyBrushStyle();
|
||||||
|
EnsureMIDs();
|
||||||
|
// Quando vem do tema, ignora os bOverride* individuais — variante já é a
|
||||||
|
// fonte da verdade. Cores são definidas pela MI atribuída ao brush.
|
||||||
|
|
||||||
|
// Aplica visibility dos toggles
|
||||||
|
if (TrackGridImage) TrackGridImage->SetVisibility(bShowTrackGrid ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
|
||||||
|
if (ShimmerImage) ShimmerImage->SetVisibility(bShowShimmer ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
|
||||||
|
UpdateEdgeVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FString> UUIProgressBar_Base::GetProgressBarVariantOptions() const
|
||||||
|
{
|
||||||
|
return CollectVariantOptions();
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,20 +2,12 @@
|
|||||||
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
#include "CommonUserWidget.h"
|
#include "CommonUserWidget.h"
|
||||||
|
#include "UI/UIStyleTypes.h"
|
||||||
#include "UIProgressBar_Base.generated.h"
|
#include "UIProgressBar_Base.generated.h"
|
||||||
|
|
||||||
class UImage;
|
class UImage;
|
||||||
class UMaterialInstanceDynamic;
|
class UMaterialInstanceDynamic;
|
||||||
|
struct FUIStyleProgressBarVariant;
|
||||||
/** Preset que controla Brush.DrawAs (Image=Box, RoundedBox=Rounded) em ambos os widgets. */
|
|
||||||
UENUM(BlueprintType)
|
|
||||||
enum class EUIProgressBarStyle : uint8
|
|
||||||
{
|
|
||||||
/** DrawAs=Image. Sem mascara nos cantos. */
|
|
||||||
Box UMETA(DisplayName = "Box"),
|
|
||||||
/** DrawAs=RoundedBox. Cantos arredondados via Slate nativo (pixel-perfect). */
|
|
||||||
Rounded UMETA(DisplayName = "Rounded"),
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ProgressBar do ZMMO. Wrappa um UImage (FillImage) + UImage de background
|
* ProgressBar do ZMMO. Wrappa um UImage (FillImage) + UImage de background
|
||||||
@@ -33,6 +25,35 @@ class ZMMO_API UUIProgressBar_Base : public UCommonUserWidget
|
|||||||
GENERATED_BODY()
|
GENERATED_BODY()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// === Theme (DT_UI_Styles integration) ===
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true = le toda a config visual (materiais + style + toggles) do
|
||||||
|
* DT_UI_Styles (FUIStyleProgressBar.Variants[Variant]). Tema
|
||||||
|
* centralizado, ignora as UPROPERTYs override individuais abaixo.
|
||||||
|
* false = ignora a DT, usa apenas as UPROPERTYs/toggles do widget.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Theme")
|
||||||
|
bool bUseTheme = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chave da variante (HP/MP/XP/Cast/...). Dropdown popula via
|
||||||
|
* meta=GetOptions lendo DT_UI_Styles.Default.ProgressBar.Variants. Vazio
|
||||||
|
* = sem theme aplicado (igual bUseTheme=false).
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Theme",
|
||||||
|
meta = (EditCondition = "bUseTheme", EditConditionHides,
|
||||||
|
GetOptions = "GetProgressBarVariantOptions"))
|
||||||
|
FName Variant;
|
||||||
|
|
||||||
|
/** Re-resolve a variante atual e reaplica nos widgets. */
|
||||||
|
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Theme")
|
||||||
|
void RefreshUIStyle();
|
||||||
|
|
||||||
|
/** Populador do dropdown (meta=GetOptions) das variantes. */
|
||||||
|
UFUNCTION()
|
||||||
|
TArray<FString> GetProgressBarVariantOptions() const;
|
||||||
|
|
||||||
// === Levels ===
|
// === Levels ===
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar",
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar",
|
||||||
@@ -384,6 +405,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void NativePreConstruct() override;
|
virtual void NativePreConstruct() override;
|
||||||
virtual void NativeConstruct() override;
|
virtual void NativeConstruct() override;
|
||||||
|
virtual void NativeDestruct() override;
|
||||||
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||||
|
|
||||||
UPROPERTY(meta = (BindWidget))
|
UPROPERTY(meta = (BindWidget))
|
||||||
@@ -423,6 +445,12 @@ private:
|
|||||||
void ApplyMaterialOverrides();
|
void ApplyMaterialOverrides();
|
||||||
void ApplyBrushStyle();
|
void ApplyBrushStyle();
|
||||||
void UpdateEdgeVisibility();
|
void UpdateEdgeVisibility();
|
||||||
|
void ApplyThemeVariant(const FUIStyleProgressBarVariant& Variant);
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleThemeChanged(FName NewThemeId);
|
||||||
|
|
||||||
|
bool bThemeBound = false;
|
||||||
|
|
||||||
float CurrentPrimaryLevel = 1.f;
|
float CurrentPrimaryLevel = 1.f;
|
||||||
float TargetPrimaryLevel = 1.f;
|
float TargetPrimaryLevel = 1.f;
|
||||||
|
|||||||
Reference in New Issue
Block a user