diff --git a/Content/ZMMO/UI/Shared/UI_ProgressBar_Master.uasset b/Content/ZMMO/UI/Shared/UI_ProgressBar_Master.uasset index 40cc97a..548e522 100644 Binary files a/Content/ZMMO/UI/Shared/UI_ProgressBar_Master.uasset and b/Content/ZMMO/UI/Shared/UI_ProgressBar_Master.uasset differ diff --git a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar.uasset b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar.uasset index a24dffe..85676b1 100644 Binary files a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar.uasset and b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar.uasset differ diff --git a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_BG.uasset b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_BG.uasset new file mode 100644 index 0000000..b38c14d Binary files /dev/null and b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_BG.uasset differ diff --git a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_HP.uasset b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_HP.uasset index 902fd3b..1b30666 100644 Binary files a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_HP.uasset and b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_HP.uasset differ diff --git a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_Shimmer.uasset b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_Shimmer.uasset new file mode 100644 index 0000000..533f5e9 Binary files /dev/null and b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_Shimmer.uasset differ diff --git a/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_TrackGrid.uasset b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_TrackGrid.uasset new file mode 100644 index 0000000..62596e7 Binary files /dev/null and b/Content/ZMMO/UI/Themes/Default/Progressbar/UI_M_ProgressBar_TrackGrid.uasset differ diff --git a/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.cpp b/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.cpp index 4120258..ac53323 100644 --- a/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.cpp +++ b/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.cpp @@ -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(FillImage->GetBrush().GetResourceObject())) + { + FillMID = UMaterialInstanceDynamic::Create(Mat, this); + FillImage->SetBrushFromMaterial(FillMID); + // SetBrushFromMaterial reseta DrawAs e OutlineSettings — re-aplica. + ApplyBrushStyle(); + } } - UMaterialInterface* Mat = Cast(FillImage->GetBrush().GetResourceObject()); - if (!Mat) + if (BackgroundImage && !BackgroundMID) { - return; + if (UMaterialInterface* Mat = Cast(BackgroundImage->GetBrush().GetResourceObject())) + { + BackgroundMID = UMaterialInstanceDynamic::Create(Mat, this); + BackgroundImage->SetBrushFromMaterial(BackgroundMID); + ApplyBrushStyle(); + } + } + if (TrackGridImage && !TrackGridMID) + { + if (UMaterialInterface* Mat = Cast(TrackGridImage->GetBrush().GetResourceObject())) + { + TrackGridMID = UMaterialInstanceDynamic::Create(Mat, this); + TrackGridImage->SetBrushFromMaterial(TrackGridMID); + ApplyBrushStyle(); + } + } + if (ShimmerImage && !ShimmerMID) + { + if (UMaterialInterface* Mat = Cast(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(ShimmerImage->Slot)) + { + OS->SetPadding(FMargin(InsetForShimmer)); + } } - FillMID = UMaterialInstanceDynamic::Create(Mat, this); - FillImage->SetBrushFromMaterial(FillMID); } void UUIProgressBar_Base::ApplyPrimaryToMID(float Value) diff --git a/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.h b/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.h index aebd7b1..6a3495b 100644 --- a/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.h +++ b/Source/ZMMO/Game/UI/Widgets/UIProgressBar_Base.h @@ -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 FillImage; + UPROPERTY(meta = (BindWidgetOptional)) + TObjectPtr BackgroundImage; + + UPROPERTY(meta = (BindWidgetOptional)) + TObjectPtr TrackGridImage; + + UPROPERTY(meta = (BindWidgetOptional)) + TObjectPtr ShimmerImage; + private: UPROPERTY(Transient) TObjectPtr FillMID; - void EnsureMID(); + UPROPERTY(Transient) + TObjectPtr BackgroundMID; + + UPROPERTY(Transient) + TObjectPtr TrackGridMID; + + UPROPERTY(Transient) + TObjectPtr 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;