feat(ui/progressbar): BG + TrackGrid + Shimmer com RoundedBox nativo do Slate

Substitui o SDF de cantos arredondados no material por DrawAs=RoundedBox
nativo do Slate (OutlineSettings.CornerRadii em pixel space, qualidade
perfeita independente do aspect ratio).

Adiciona 3 materiais separados pra layers de efeito:
- UI_M_ProgressBar_BG: fundo solido (1 param BackgroundColour)
- UI_M_ProgressBar_TrackGrid: linhas verticais a cada N divisoes
  (GridColour, GridDivisions, GridLineThickness)
- UI_M_ProgressBar_Shimmer: faixa de luz animada (Time node) deslizando
  E->D em loop (ShimmerColour, ShimmerWidth, ShimmerSpeed, ShimmerSoftness)

WBP UI_ProgressBar_Master ganha 3 UImage irmaos do FillImage no Overlay
(z-order: BG -> TrackGrid -> Fill -> Shimmer), todos com BindWidgetOptional.

C++ UUIProgressBar_Base:
- Enum EUIProgressBarStyle (Box/Rounded) controla DrawAs dos 4 brushes
- CornerRadius em pixels (0..100), aplicado via OutlineSettings.CornerRadii
- bShowBorder + BorderColour + BorderWidth pra outline so no BG
- bShowTrackGrid / bShowShimmer toggles (visibility do widget)
- ShimmerImage com inset = BorderWidth (slot padding + corner reduzido)
  pra nao sobrepor o outline do BG quando passa pelas extremidades
- UPROPERTYs override pra cada cor/param de cada material com
  InlineEditConditionToggle, setters runtime que persistem o flag

Inclui MI exemplo UI_M_ProgressBar_HP atualizada.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 21:26:50 -03:00
parent 5d44647170
commit 8843ac3d1c
8 changed files with 450 additions and 41 deletions

View File

@@ -1,14 +1,17 @@
#include "UIProgressBar_Base.h"
#include "Components/Image.h"
#include "Components/OverlaySlot.h"
#include "Materials/MaterialInstanceDynamic.h"
#include "Materials/MaterialInterface.h"
#include "Styling/SlateBrush.h"
#include "Styling/SlateTypes.h"
namespace
{
constexpr float MinAnimSeconds = 0.001f;
// Fill material params
static const FName P_PrimaryLevel("PrimaryLevel");
static const FName P_SecondaryLevel("SecondaryLevel");
static const FName P_PrimaryColour("PrimaryColour");
@@ -19,6 +22,20 @@ namespace
static const FName P_EnableGradient("EnableGradient");
static const FName P_GradientSplit("GradientSplit");
// BG material params
static const FName P_BackgroundColour("BackgroundColour");
// TrackGrid material params
static const FName P_GridColour("GridColour");
static const FName P_GridDivisions("GridDivisions");
static const FName P_GridLineThickness("GridLineThickness");
// Shimmer material params
static const FName P_ShimmerColour("ShimmerColour");
static const FName P_ShimmerWidth("ShimmerWidth");
static const FName P_ShimmerSpeed("ShimmerSpeed");
static const FName P_ShimmerSoftness("ShimmerSoftness");
FORCEINLINE float EaseOutCubic(float Alpha)
{
return 1.f - FMath::Pow(1.f - Alpha, 3.f);
@@ -41,8 +58,9 @@ void UUIProgressBar_Base::NativePreConstruct()
SecondaryElapsed = 0.f;
bAnimatingSecondary = false;
EnsureMID();
ApplyOverridesToMID();
ApplyBrushStyle();
EnsureMIDs();
ApplyMaterialOverrides();
ApplyPrimaryToMID(CurrentPrimaryLevel);
ApplySecondaryToMID(CurrentSecondaryLevel);
}
@@ -51,8 +69,9 @@ void UUIProgressBar_Base::NativeConstruct()
{
Super::NativeConstruct();
EnsureMID();
ApplyOverridesToMID();
ApplyBrushStyle();
EnsureMIDs();
ApplyMaterialOverrides();
ApplyPrimaryToMID(CurrentPrimaryLevel);
ApplySecondaryToMID(CurrentSecondaryLevel);
}
@@ -157,6 +176,37 @@ void UUIProgressBar_Base::SetSecondaryLevelImmediate(float Sec01)
ApplySecondaryToMID(CurrentSecondaryLevel);
}
void UUIProgressBar_Base::SetDrawStyle(EUIProgressBarStyle InStyle)
{
DrawStyle = InStyle;
ApplyBrushStyle();
}
void UUIProgressBar_Base::SetCornerRadius(float RadiusPixels)
{
CornerRadius = FMath::Clamp(RadiusPixels, 0.f, 100.f);
ApplyBrushStyle();
}
void UUIProgressBar_Base::SetBorderVisible(bool bVisible)
{
bShowBorder = bVisible;
ApplyBrushStyle();
}
void UUIProgressBar_Base::SetBorderColour(FLinearColor Color)
{
BorderColour = Color;
bShowBorder = true;
ApplyBrushStyle();
}
void UUIProgressBar_Base::SetBorderWidth(float WidthPixels)
{
BorderWidth = FMath::Clamp(WidthPixels, 0.f, 10.f);
ApplyBrushStyle();
}
void UUIProgressBar_Base::SetPrimaryColour(FLinearColor Color)
{
PrimaryColour = Color;
@@ -192,6 +242,80 @@ void UUIProgressBar_Base::SetEmptyColour(FLinearColor Color)
if (FillMID) FillMID->SetVectorParameterValue(P_EmptyColour, Color);
}
void UUIProgressBar_Base::SetBackgroundColour(FLinearColor Color)
{
BackgroundColour = Color;
bOverrideBackgroundColour = true;
if (BackgroundMID) BackgroundMID->SetVectorParameterValue(P_BackgroundColour, Color);
}
void UUIProgressBar_Base::SetTrackGridVisible(bool bVisible)
{
bShowTrackGrid = bVisible;
if (TrackGridImage)
{
TrackGridImage->SetVisibility(bVisible ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
}
}
void UUIProgressBar_Base::SetGridColour(FLinearColor Color)
{
GridColour = Color;
bOverrideGridColour = true;
if (TrackGridMID) TrackGridMID->SetVectorParameterValue(P_GridColour, Color);
}
void UUIProgressBar_Base::SetGridDivisions(float Divisions)
{
GridDivisions = FMath::Clamp(Divisions, 2.f, 50.f);
bOverrideGridDivisions = true;
if (TrackGridMID) TrackGridMID->SetScalarParameterValue(P_GridDivisions, GridDivisions);
}
void UUIProgressBar_Base::SetGridLineThickness(float Thickness)
{
GridLineThickness = FMath::Clamp(Thickness, 0.001f, 0.2f);
bOverrideGridLineThickness = true;
if (TrackGridMID) TrackGridMID->SetScalarParameterValue(P_GridLineThickness, GridLineThickness);
}
void UUIProgressBar_Base::SetShimmerVisible(bool bVisible)
{
bShowShimmer = bVisible;
if (ShimmerImage)
{
ShimmerImage->SetVisibility(bVisible ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
}
}
void UUIProgressBar_Base::SetShimmerColour(FLinearColor Color)
{
ShimmerColour = Color;
bOverrideShimmerColour = true;
if (ShimmerMID) ShimmerMID->SetVectorParameterValue(P_ShimmerColour, Color);
}
void UUIProgressBar_Base::SetShimmerWidth(float Width01)
{
ShimmerWidth = FMath::Clamp(Width01, 0.05f, 1.f);
bOverrideShimmerWidth = true;
if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerWidth, ShimmerWidth);
}
void UUIProgressBar_Base::SetShimmerSpeed(float Speed)
{
ShimmerSpeed = FMath::Clamp(Speed, 0.01f, 5.f);
bOverrideShimmerSpeed = true;
if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerSpeed, ShimmerSpeed);
}
void UUIProgressBar_Base::SetShimmerSoftness(float Softness)
{
ShimmerSoftness = FMath::Clamp(Softness, 0.5f, 8.f);
bOverrideShimmerSoftness = true;
if (ShimmerMID) ShimmerMID->SetScalarParameterValue(P_ShimmerSoftness, ShimmerSoftness);
}
void UUIProgressBar_Base::SetGradientEnabled(bool bEnabled)
{
bEnableGradient = bEnabled;
@@ -206,21 +330,6 @@ void UUIProgressBar_Base::SetGradientSplit(float Split01)
if (FillMID) FillMID->SetScalarParameterValue(P_GradientSplit, GradientSplit);
}
void UUIProgressBar_Base::ApplyOverridesToMID()
{
if (!FillMID)
{
return;
}
if (bOverridePrimaryColour) FillMID->SetVectorParameterValue(P_PrimaryColour, PrimaryColour);
if (bOverridePrimaryColourBottom) FillMID->SetVectorParameterValue(P_PrimaryColourBottom, PrimaryColourBottom);
if (bOverrideSecondaryColour) FillMID->SetVectorParameterValue(P_SecondaryColour, SecondaryColour);
if (bOverrideSecondaryColourBottom) FillMID->SetVectorParameterValue(P_SecondaryColourBottom, SecondaryColourBottom);
if (bOverrideEmptyColour) FillMID->SetVectorParameterValue(P_EmptyColour, EmptyColour);
if (bOverrideEnableGradient) FillMID->SetScalarParameterValue(P_EnableGradient, bEnableGradient ? 1.f : 0.f);
if (bOverrideGradientSplit) FillMID->SetScalarParameterValue(P_GradientSplit, GradientSplit);
}
void UUIProgressBar_Base::ShowHealPreview(float TargetPct, FLinearColor PreviewColor)
{
SetSecondaryColour(PreviewColor);
@@ -246,19 +355,138 @@ void UUIProgressBar_Base::ClearSecondary()
SetTargetSecondaryLevel(0.f);
}
void UUIProgressBar_Base::EnsureMID()
void UUIProgressBar_Base::EnsureMIDs()
{
if (FillMID || !FillImage)
if (FillImage && !FillMID)
{
return;
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(FillImage->GetBrush().GetResourceObject()))
{
FillMID = UMaterialInstanceDynamic::Create(Mat, this);
FillImage->SetBrushFromMaterial(FillMID);
// SetBrushFromMaterial reseta DrawAs e OutlineSettings — re-aplica.
ApplyBrushStyle();
}
}
UMaterialInterface* Mat = Cast<UMaterialInterface>(FillImage->GetBrush().GetResourceObject());
if (!Mat)
if (BackgroundImage && !BackgroundMID)
{
return;
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(BackgroundImage->GetBrush().GetResourceObject()))
{
BackgroundMID = UMaterialInstanceDynamic::Create(Mat, this);
BackgroundImage->SetBrushFromMaterial(BackgroundMID);
ApplyBrushStyle();
}
}
if (TrackGridImage && !TrackGridMID)
{
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(TrackGridImage->GetBrush().GetResourceObject()))
{
TrackGridMID = UMaterialInstanceDynamic::Create(Mat, this);
TrackGridImage->SetBrushFromMaterial(TrackGridMID);
ApplyBrushStyle();
}
}
if (ShimmerImage && !ShimmerMID)
{
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(ShimmerImage->GetBrush().GetResourceObject()))
{
ShimmerMID = UMaterialInstanceDynamic::Create(Mat, this);
ShimmerImage->SetBrushFromMaterial(ShimmerMID);
ApplyBrushStyle();
}
}
}
void UUIProgressBar_Base::ApplyMaterialOverrides()
{
if (FillMID)
{
if (bOverridePrimaryColour) FillMID->SetVectorParameterValue(P_PrimaryColour, PrimaryColour);
if (bOverridePrimaryColourBottom) FillMID->SetVectorParameterValue(P_PrimaryColourBottom, PrimaryColourBottom);
if (bOverrideSecondaryColour) FillMID->SetVectorParameterValue(P_SecondaryColour, SecondaryColour);
if (bOverrideSecondaryColourBottom) FillMID->SetVectorParameterValue(P_SecondaryColourBottom, SecondaryColourBottom);
if (bOverrideEmptyColour) FillMID->SetVectorParameterValue(P_EmptyColour, EmptyColour);
if (bOverrideEnableGradient) FillMID->SetScalarParameterValue(P_EnableGradient, bEnableGradient ? 1.f : 0.f);
if (bOverrideGradientSplit) FillMID->SetScalarParameterValue(P_GradientSplit, GradientSplit);
}
if (BackgroundMID)
{
if (bOverrideBackgroundColour) BackgroundMID->SetVectorParameterValue(P_BackgroundColour, BackgroundColour);
}
if (TrackGridMID)
{
if (bOverrideGridColour) TrackGridMID->SetVectorParameterValue(P_GridColour, GridColour);
if (bOverrideGridDivisions) TrackGridMID->SetScalarParameterValue(P_GridDivisions, GridDivisions);
if (bOverrideGridLineThickness) TrackGridMID->SetScalarParameterValue(P_GridLineThickness, GridLineThickness);
}
if (ShimmerMID)
{
if (bOverrideShimmerColour) ShimmerMID->SetVectorParameterValue(P_ShimmerColour, ShimmerColour);
if (bOverrideShimmerWidth) ShimmerMID->SetScalarParameterValue(P_ShimmerWidth, ShimmerWidth);
if (bOverrideShimmerSpeed) ShimmerMID->SetScalarParameterValue(P_ShimmerSpeed, ShimmerSpeed);
if (bOverrideShimmerSoftness) ShimmerMID->SetScalarParameterValue(P_ShimmerSoftness, ShimmerSoftness);
}
// Visibilidade do TrackGrid + Shimmer acompanham os toggles
if (TrackGridImage)
{
TrackGridImage->SetVisibility(bShowTrackGrid ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
}
if (ShimmerImage)
{
ShimmerImage->SetVisibility(bShowShimmer ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
}
}
void UUIProgressBar_Base::ApplyBrushStyle()
{
const float InsetForShimmer = bShowBorder ? FMath::Max(BorderWidth, 0.f) : 0.f;
auto Apply = [this](UImage* Img, bool bAllowBorder, float RadiusInset)
{
if (!Img)
{
return;
}
FSlateBrush B = Img->GetBrush();
B.DrawAs = (DrawStyle == EUIProgressBarStyle::Rounded)
? ESlateBrushDrawType::RoundedBox
: ESlateBrushDrawType::Image;
FSlateBrushOutlineSettings Outline = B.OutlineSettings;
const float R = FMath::Max(CornerRadius - RadiusInset, 0.f);
Outline.CornerRadii = FVector4(R, R, R, R);
Outline.RoundingType = ESlateBrushRoundingType::FixedRadius;
if (bAllowBorder && bShowBorder)
{
Outline.Color = FSlateColor(BorderColour);
Outline.Width = FMath::Max(BorderWidth, 0.f);
}
else
{
Outline.Color = FSlateColor(FLinearColor::Transparent);
Outline.Width = 0.f;
}
B.OutlineSettings = Outline;
Img->SetBrush(B);
};
// Borda só no BG. Shimmer ganha inset = BorderWidth (padding no slot + corner reduzido)
// pra não passar por cima do outline do BG. Demais widgets sem inset.
Apply(BackgroundImage, /*bAllowBorder=*/true, 0.f);
Apply(TrackGridImage, /*bAllowBorder=*/false, 0.f);
Apply(FillImage, /*bAllowBorder=*/false, 0.f);
Apply(ShimmerImage, /*bAllowBorder=*/false, InsetForShimmer);
if (ShimmerImage)
{
if (UOverlaySlot* OS = Cast<UOverlaySlot>(ShimmerImage->Slot))
{
OS->SetPadding(FMargin(InsetForShimmer));
}
}
FillMID = UMaterialInstanceDynamic::Create(Mat, this);
FillImage->SetBrushFromMaterial(FillMID);
}
void UUIProgressBar_Base::ApplyPrimaryToMID(float Value)

View File

@@ -7,18 +7,25 @@
class UImage;
class UMaterialInstanceDynamic;
/** 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 com material custom
* (UI_M_ProgressBar) e expõe API com dois níveis:
* Primary (preenchimento atual) + Secondary (preview / damage lag / buffer).
* ProgressBar do ZMMO. Wrappa um UImage (FillImage) + UImage de background
* (BackgroundImage) com material custom. O arredondamento dos cantos usa
* o RoundedBox nativo do Slate (Brush.DrawAs + OutlineSettings.CornerRadii)
* pra ficar pixel-perfect e independente do aspect ratio.
*
* Modelo assimétrico: SecondaryLevel só aparece visualmente se for MAIOR
* que PrimaryLevel — representa heal preview, damage trail, buffer
* empilhado em cima da barra principal.
*
* Cores: por padrão vêm da Material Instance atribuída ao FillImage.
* Cada cor tem um toggle de override (InlineEditConditionToggle) que,
* quando ligado, sobrescreve o valor da MI via MID em PreConstruct.
* Modelo assimetrico de niveis: SecondaryLevel so aparece visualmente se
* for MAIOR que PrimaryLevel — representa heal preview, damage trail,
* buffer empilhado em cima da barra principal.
*/
UCLASS(Abstract, Blueprintable)
class ZMMO_API UUIProgressBar_Base : public UCommonUserWidget
@@ -46,7 +53,36 @@ public:
meta = (ClampMin = "0", ClampMax = "5"))
float SecondaryAnimationSeconds = 0.8f;
// === Color overrides (sobrescrevem a MI) ===
// === Draw Style ===
/** Box=DrawAs Image (sem corner), Rounded=DrawAs RoundedBox (cantos arredondados). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Style")
EUIProgressBarStyle DrawStyle = EUIProgressBarStyle::Box;
/**
* Raio dos cantos em PIXELS. Aplicado quando DrawStyle = Rounded.
* Se RoundingType = HalfHeightRadius (default do Slate), o Slate clampeia
* automaticamente em metade da altura — ou seja, valor maior que isso vira pill.
*/
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Style",
meta = (ClampMin = "0", ClampMax = "100"))
float CornerRadius = 8.f;
/** Cor do outline em volta do Background (Slate OutlineSettings.Color). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Style",
meta = (InlineEditConditionToggle))
bool bShowBorder = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Style",
meta = (EditCondition = "bShowBorder"))
FLinearColor BorderColour = FLinearColor(0.f, 0.f, 0.f, 0.8f);
/** Espessura do outline em pixels. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Style",
meta = (EditCondition = "bShowBorder", ClampMin = "0", ClampMax = "10"))
float BorderWidth = 1.f;
// === Color overrides (Fill material) ===
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Colors",
meta = (InlineEditConditionToggle))
@@ -88,6 +124,85 @@ public:
meta = (EditCondition = "bOverrideEmptyColour"))
FLinearColor EmptyColour = FLinearColor(0.f, 0.f, 0.f, 0.6f);
// === Background override ===
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Background",
meta = (InlineEditConditionToggle))
bool bOverrideBackgroundColour = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Background",
meta = (EditCondition = "bOverrideBackgroundColour"))
FLinearColor BackgroundColour = FLinearColor(0.f, 0.f, 0.f, 0.6f);
// === Track Grid (efeito de listras verticais sobre o BG) ===
/** Liga/desliga a renderização do TrackGridImage. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid")
bool bShowTrackGrid = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (InlineEditConditionToggle))
bool bOverrideGridColour = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (EditCondition = "bOverrideGridColour"))
FLinearColor GridColour = FLinearColor(1.f, 1.f, 1.f, 0.05f);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (InlineEditConditionToggle))
bool bOverrideGridDivisions = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (EditCondition = "bOverrideGridDivisions", ClampMin = "2", ClampMax = "50"))
float GridDivisions = 10.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (InlineEditConditionToggle))
bool bOverrideGridLineThickness = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|TrackGrid",
meta = (EditCondition = "bOverrideGridLineThickness", ClampMin = "0.001", ClampMax = "0.2"))
float GridLineThickness = 0.02f;
// === Shimmer (faixa de luz animada por cima do Fill) ===
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer")
bool bShowShimmer = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (InlineEditConditionToggle))
bool bOverrideShimmerColour = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (EditCondition = "bOverrideShimmerColour"))
FLinearColor ShimmerColour = FLinearColor(1.f, 0.94f, 0.78f, 0.35f);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (InlineEditConditionToggle))
bool bOverrideShimmerWidth = false;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (EditCondition = "bOverrideShimmerWidth", ClampMin = "0.05", ClampMax = "1.0"))
float ShimmerWidth = 0.2f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (InlineEditConditionToggle))
bool bOverrideShimmerSpeed = false;
/** Ciclos por segundo. 0.4545 = ciclo de 2.2s (default CSS). */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (EditCondition = "bOverrideShimmerSpeed", ClampMin = "0.01", ClampMax = "5.0"))
float ShimmerSpeed = 0.4545f;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (InlineEditConditionToggle))
bool bOverrideShimmerSoftness = false;
/** Expoente da bell curve. Maior = pico mais fino. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Shimmer",
meta = (EditCondition = "bOverrideShimmerSoftness", ClampMin = "0.5", ClampMax = "8.0"))
float ShimmerSoftness = 2.f;
// === Gradient overrides ===
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ProgressBar|Gradient",
@@ -128,7 +243,24 @@ public:
UFUNCTION(BlueprintPure, Category = "ProgressBar")
float GetCurrentSecondaryLevel() const { return CurrentSecondaryLevel; }
// === Runtime color/gradient setters (também marcam o override pra evitar reset no próximo PreConstruct) ===
// === Style API ===
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Style")
void SetDrawStyle(EUIProgressBarStyle InStyle);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Style")
void SetCornerRadius(float RadiusPixels);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Style")
void SetBorderVisible(bool bVisible);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Style")
void SetBorderColour(FLinearColor Color);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Style")
void SetBorderWidth(float WidthPixels);
// === Color setters (Fill MID) ===
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Colors")
void SetPrimaryColour(FLinearColor Color);
@@ -145,6 +277,36 @@ public:
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Colors")
void SetEmptyColour(FLinearColor Color);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Background")
void SetBackgroundColour(FLinearColor Color);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|TrackGrid")
void SetTrackGridVisible(bool bVisible);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|TrackGrid")
void SetGridColour(FLinearColor Color);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|TrackGrid")
void SetGridDivisions(float Divisions);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|TrackGrid")
void SetGridLineThickness(float Thickness);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Shimmer")
void SetShimmerVisible(bool bVisible);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Shimmer")
void SetShimmerColour(FLinearColor Color);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Shimmer")
void SetShimmerWidth(float Width01);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Shimmer")
void SetShimmerSpeed(float Speed);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Shimmer")
void SetShimmerSoftness(float Softness);
UFUNCTION(BlueprintCallable, Category = "ProgressBar|Gradient")
void SetGradientEnabled(bool bEnabled);
@@ -173,14 +335,33 @@ protected:
UPROPERTY(meta = (BindWidget))
TObjectPtr<UImage> FillImage;
UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UImage> BackgroundImage;
UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UImage> TrackGridImage;
UPROPERTY(meta = (BindWidgetOptional))
TObjectPtr<UImage> ShimmerImage;
private:
UPROPERTY(Transient)
TObjectPtr<UMaterialInstanceDynamic> FillMID;
void EnsureMID();
UPROPERTY(Transient)
TObjectPtr<UMaterialInstanceDynamic> BackgroundMID;
UPROPERTY(Transient)
TObjectPtr<UMaterialInstanceDynamic> TrackGridMID;
UPROPERTY(Transient)
TObjectPtr<UMaterialInstanceDynamic> ShimmerMID;
void EnsureMIDs();
void ApplyPrimaryToMID(float Value);
void ApplySecondaryToMID(float Value);
void ApplyOverridesToMID();
void ApplyMaterialOverrides();
void ApplyBrushStyle();
float CurrentPrimaryLevel = 1.f;
float TargetPrimaryLevel = 1.f;