- UZeusAOIComponent (Game/Network): componente de gameplay do player local com plus de debug. Overlays via DrawDebug* (esfera AOI real; spawn/cell/handoff placeholders) dirigidos pela UI via IZeusAOIDebugTarget + console vars. Estado persiste no componente entre aberturas do menu (IsOverlayEnabled). - AZeusCharacter: anexa o componente + abre/fecha o painel no F8 (UIOnly trava o jogo; Esc/F8 fecham); LoadClass lazy do painel no content do PLUGIN (/ZeusAdminTools/UI/WBP_AdminToolsAIO). - ZMMO.Build.cs: depende de ZeusAdminToolsRuntime. - UIProgressBar_Base: rename EaseOutCubic -> EaseOutCubicPB (fix unity-build). - ZMMO.uproject: remove entrada NwiroIntegrationKit. A UI e o C++ do plugin ZeusAdminTools vivem no repo Server (plugin autocontido). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
762 lines
23 KiB
C++
762 lines
23 KiB
C++
#include "UIProgressBar_Base.h"
|
|
|
|
#include "Components/Image.h"
|
|
#include "Components/OverlaySlot.h"
|
|
#include "Engine/DataTable.h"
|
|
#include "Engine/GameInstance.h"
|
|
#include "Materials/MaterialInstanceDynamic.h"
|
|
#include "Materials/MaterialInterface.h"
|
|
#include "Styling/SlateBrush.h"
|
|
#include "Styling/SlateTypes.h"
|
|
#include "UI/UIStyleRow.h"
|
|
#include "UI/UIStyleTokens.h"
|
|
#include "ZeusThemeSubsystem.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");
|
|
static const FName P_PrimaryColourBottom("PrimaryColourBottom");
|
|
static const FName P_SecondaryColour("SecondaryColour");
|
|
static const FName P_SecondaryColourBottom("SecondaryColourBottom");
|
|
static const FName P_EmptyColour("EmptyColour");
|
|
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");
|
|
|
|
// Edge material params
|
|
static const FName P_EdgeColour("EdgeColour");
|
|
static const FName P_EdgeWidth("EdgeWidth");
|
|
static const FName P_EdgeGlowWidth("EdgeGlowWidth");
|
|
static const FName P_EdgeGlowIntensity("EdgeGlowIntensity");
|
|
|
|
FORCEINLINE float EaseOutCubicPB(float Alpha)
|
|
{
|
|
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 UZeusThemeSubsystem* Theme = GI->GetSubsystem<UZeusThemeSubsystem>())
|
|
{
|
|
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()
|
|
{
|
|
Super::NativePreConstruct();
|
|
|
|
CurrentPrimaryLevel = InitialPrimaryLevel;
|
|
TargetPrimaryLevel = InitialPrimaryLevel;
|
|
PrimaryStart = InitialPrimaryLevel;
|
|
PrimaryElapsed = 0.f;
|
|
bAnimatingPrimary = false;
|
|
|
|
CurrentSecondaryLevel = InitialSecondaryLevel;
|
|
TargetSecondaryLevel = InitialSecondaryLevel;
|
|
SecondaryStart = InitialSecondaryLevel;
|
|
SecondaryElapsed = 0.f;
|
|
bAnimatingSecondary = false;
|
|
|
|
if (bUseTheme)
|
|
{
|
|
RefreshUIStyle();
|
|
}
|
|
else
|
|
{
|
|
ApplyBrushStyle();
|
|
EnsureMIDs();
|
|
ApplyMaterialOverrides();
|
|
}
|
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
|
}
|
|
|
|
void UUIProgressBar_Base::NativeConstruct()
|
|
{
|
|
Super::NativeConstruct();
|
|
|
|
if (!bThemeBound)
|
|
{
|
|
if (const UGameInstance* GI = GetGameInstance())
|
|
{
|
|
if (UZeusThemeSubsystem* Theme = GI->GetSubsystem<UZeusThemeSubsystem>())
|
|
{
|
|
Theme->OnThemeChanged.AddDynamic(this, &UUIProgressBar_Base::HandleThemeChanged);
|
|
bThemeBound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bUseTheme)
|
|
{
|
|
RefreshUIStyle();
|
|
}
|
|
else
|
|
{
|
|
ApplyBrushStyle();
|
|
EnsureMIDs();
|
|
ApplyMaterialOverrides();
|
|
}
|
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
|
}
|
|
|
|
void UUIProgressBar_Base::NativeDestruct()
|
|
{
|
|
if (bThemeBound)
|
|
{
|
|
if (const UGameInstance* GI = GetGameInstance())
|
|
{
|
|
if (UZeusThemeSubsystem* Theme = GI->GetSubsystem<UZeusThemeSubsystem>())
|
|
{
|
|
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)
|
|
{
|
|
Super::NativeTick(MyGeometry, InDeltaTime);
|
|
|
|
if (!bAnimatingPrimary && !bAnimatingSecondary)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (bAnimatingPrimary)
|
|
{
|
|
PrimaryElapsed += InDeltaTime;
|
|
const float Duration = FMath::Max(PrimaryAnimationSeconds, MinAnimSeconds);
|
|
const float Alpha = FMath::Clamp(PrimaryElapsed / Duration, 0.f, 1.f);
|
|
CurrentPrimaryLevel = FMath::Lerp(PrimaryStart, TargetPrimaryLevel, EaseOutCubicPB(Alpha));
|
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
|
if (Alpha >= 1.f)
|
|
{
|
|
CurrentPrimaryLevel = TargetPrimaryLevel;
|
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
|
bAnimatingPrimary = false;
|
|
}
|
|
}
|
|
|
|
if (bAnimatingSecondary)
|
|
{
|
|
SecondaryElapsed += InDeltaTime;
|
|
const float Duration = FMath::Max(SecondaryAnimationSeconds, MinAnimSeconds);
|
|
const float Alpha = FMath::Clamp(SecondaryElapsed / Duration, 0.f, 1.f);
|
|
CurrentSecondaryLevel = FMath::Lerp(SecondaryStart, TargetSecondaryLevel, EaseOutCubicPB(Alpha));
|
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
|
if (Alpha >= 1.f)
|
|
{
|
|
CurrentSecondaryLevel = TargetSecondaryLevel;
|
|
ApplySecondaryToMID(CurrentSecondaryLevel);
|
|
bAnimatingSecondary = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetTargetPrimaryLevel(float Primary01)
|
|
{
|
|
const float Clamped = FMath::Clamp(Primary01, 0.f, 1.f);
|
|
if (PrimaryAnimationSeconds <= MinAnimSeconds)
|
|
{
|
|
SetPrimaryLevelImmediate(Clamped);
|
|
return;
|
|
}
|
|
if (FMath::IsNearlyEqual(Clamped, CurrentPrimaryLevel, KINDA_SMALL_NUMBER) &&
|
|
FMath::IsNearlyEqual(Clamped, TargetPrimaryLevel, KINDA_SMALL_NUMBER))
|
|
{
|
|
return;
|
|
}
|
|
TargetPrimaryLevel = Clamped;
|
|
PrimaryStart = CurrentPrimaryLevel;
|
|
PrimaryElapsed = 0.f;
|
|
bAnimatingPrimary = true;
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetPrimaryLevelImmediate(float Primary01)
|
|
{
|
|
const float Clamped = FMath::Clamp(Primary01, 0.f, 1.f);
|
|
CurrentPrimaryLevel = Clamped;
|
|
TargetPrimaryLevel = Clamped;
|
|
PrimaryStart = Clamped;
|
|
PrimaryElapsed = 0.f;
|
|
bAnimatingPrimary = false;
|
|
ApplyPrimaryToMID(CurrentPrimaryLevel);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetTargetSecondaryLevel(float Sec01)
|
|
{
|
|
const float Clamped = FMath::Clamp(Sec01, 0.f, 1.f);
|
|
if (SecondaryAnimationSeconds <= MinAnimSeconds)
|
|
{
|
|
SetSecondaryLevelImmediate(Clamped);
|
|
return;
|
|
}
|
|
if (FMath::IsNearlyEqual(Clamped, CurrentSecondaryLevel, KINDA_SMALL_NUMBER) &&
|
|
FMath::IsNearlyEqual(Clamped, TargetSecondaryLevel, KINDA_SMALL_NUMBER))
|
|
{
|
|
return;
|
|
}
|
|
TargetSecondaryLevel = Clamped;
|
|
SecondaryStart = CurrentSecondaryLevel;
|
|
SecondaryElapsed = 0.f;
|
|
bAnimatingSecondary = true;
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetSecondaryLevelImmediate(float Sec01)
|
|
{
|
|
const float Clamped = FMath::Clamp(Sec01, 0.f, 1.f);
|
|
CurrentSecondaryLevel = Clamped;
|
|
TargetSecondaryLevel = Clamped;
|
|
SecondaryStart = Clamped;
|
|
SecondaryElapsed = 0.f;
|
|
bAnimatingSecondary = false;
|
|
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;
|
|
bOverridePrimaryColour = true;
|
|
if (FillMID) FillMID->SetVectorParameterValue(P_PrimaryColour, Color);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetPrimaryColourBottom(FLinearColor Color)
|
|
{
|
|
PrimaryColourBottom = Color;
|
|
bOverridePrimaryColourBottom = true;
|
|
if (FillMID) FillMID->SetVectorParameterValue(P_PrimaryColourBottom, Color);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetSecondaryColour(FLinearColor Color)
|
|
{
|
|
SecondaryColour = Color;
|
|
bOverrideSecondaryColour = true;
|
|
if (FillMID) FillMID->SetVectorParameterValue(P_SecondaryColour, Color);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetSecondaryColourBottom(FLinearColor Color)
|
|
{
|
|
SecondaryColourBottom = Color;
|
|
bOverrideSecondaryColourBottom = true;
|
|
if (FillMID) FillMID->SetVectorParameterValue(P_SecondaryColourBottom, Color);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetEmptyColour(FLinearColor Color)
|
|
{
|
|
EmptyColour = Color;
|
|
bOverrideEmptyColour = true;
|
|
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::SetEdgeVisible(bool bVisible)
|
|
{
|
|
bShowEdge = bVisible;
|
|
UpdateEdgeVisibility();
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetEdgeColour(FLinearColor Color)
|
|
{
|
|
EdgeColour = Color;
|
|
bOverrideEdgeColour = true;
|
|
if (EdgeMID) EdgeMID->SetVectorParameterValue(P_EdgeColour, Color);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetEdgeWidth(float Width01)
|
|
{
|
|
EdgeWidth = FMath::Clamp(Width01, 0.001f, 0.1f);
|
|
bOverrideEdgeWidth = true;
|
|
if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeWidth, EdgeWidth);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetEdgeGlowWidth(float GlowWidth01)
|
|
{
|
|
EdgeGlowWidth = FMath::Clamp(GlowWidth01, 0.f, 0.2f);
|
|
bOverrideEdgeGlowWidth = true;
|
|
if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeGlowWidth, EdgeGlowWidth);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetEdgeGlowIntensity(float Intensity01)
|
|
{
|
|
EdgeGlowIntensity = FMath::Clamp(Intensity01, 0.f, 1.f);
|
|
bOverrideEdgeGlowIntensity = true;
|
|
if (EdgeMID) EdgeMID->SetScalarParameterValue(P_EdgeGlowIntensity, EdgeGlowIntensity);
|
|
}
|
|
|
|
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;
|
|
bOverrideEnableGradient = true;
|
|
if (FillMID) FillMID->SetScalarParameterValue(P_EnableGradient, bEnabled ? 1.f : 0.f);
|
|
}
|
|
|
|
void UUIProgressBar_Base::SetGradientSplit(float Split01)
|
|
{
|
|
GradientSplit = FMath::Clamp(Split01, 0.f, 1.f);
|
|
bOverrideGradientSplit = true;
|
|
if (FillMID) FillMID->SetScalarParameterValue(P_GradientSplit, GradientSplit);
|
|
}
|
|
|
|
void UUIProgressBar_Base::ShowHealPreview(float TargetPct, FLinearColor PreviewColor)
|
|
{
|
|
SetSecondaryColour(PreviewColor);
|
|
SetTargetSecondaryLevel(TargetPct);
|
|
}
|
|
|
|
void UUIProgressBar_Base::ShowDamageLag(float OldPct, float NewPct, FLinearColor LagColor)
|
|
{
|
|
SetSecondaryColour(LagColor);
|
|
SetSecondaryLevelImmediate(OldPct);
|
|
SetPrimaryLevelImmediate(NewPct);
|
|
SetTargetSecondaryLevel(NewPct);
|
|
}
|
|
|
|
void UUIProgressBar_Base::ShowBuffer(float BufferPct, FLinearColor BufferColor)
|
|
{
|
|
SetSecondaryColour(BufferColor);
|
|
SetTargetSecondaryLevel(FMath::Clamp(CurrentPrimaryLevel + BufferPct, 0.f, 1.f));
|
|
}
|
|
|
|
void UUIProgressBar_Base::ClearSecondary()
|
|
{
|
|
SetTargetSecondaryLevel(0.f);
|
|
}
|
|
|
|
void UUIProgressBar_Base::EnsureMIDs()
|
|
{
|
|
if (FillImage && !FillMID)
|
|
{
|
|
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(FillImage->GetBrush().GetResourceObject()))
|
|
{
|
|
FillMID = UMaterialInstanceDynamic::Create(Mat, this);
|
|
FillImage->SetBrushFromMaterial(FillMID);
|
|
// SetBrushFromMaterial reseta DrawAs e OutlineSettings — re-aplica.
|
|
ApplyBrushStyle();
|
|
}
|
|
}
|
|
if (BackgroundImage && !BackgroundMID)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
if (EdgeImage && !EdgeMID)
|
|
{
|
|
if (UMaterialInterface* Mat = Cast<UMaterialInterface>(EdgeImage->GetBrush().GetResourceObject()))
|
|
{
|
|
EdgeMID = UMaterialInstanceDynamic::Create(Mat, this);
|
|
EdgeImage->SetBrushFromMaterial(EdgeMID);
|
|
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);
|
|
}
|
|
if (EdgeMID)
|
|
{
|
|
if (bOverrideEdgeColour) EdgeMID->SetVectorParameterValue(P_EdgeColour, EdgeColour);
|
|
if (bOverrideEdgeWidth) EdgeMID->SetScalarParameterValue(P_EdgeWidth, EdgeWidth);
|
|
if (bOverrideEdgeGlowWidth) EdgeMID->SetScalarParameterValue(P_EdgeGlowWidth, EdgeGlowWidth);
|
|
if (bOverrideEdgeGlowIntensity) EdgeMID->SetScalarParameterValue(P_EdgeGlowIntensity, EdgeGlowIntensity);
|
|
}
|
|
|
|
// Visibilidade dos widgets opcionais
|
|
if (TrackGridImage)
|
|
{
|
|
TrackGridImage->SetVisibility(bShowTrackGrid ? ESlateVisibility::HitTestInvisible : ESlateVisibility::Collapsed);
|
|
}
|
|
UpdateEdgeVisibility();
|
|
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(EdgeImage, /*bAllowBorder=*/false, 0.f);
|
|
Apply(ShimmerImage, /*bAllowBorder=*/false, InsetForShimmer);
|
|
|
|
if (ShimmerImage)
|
|
{
|
|
if (UOverlaySlot* OS = Cast<UOverlaySlot>(ShimmerImage->Slot))
|
|
{
|
|
OS->SetPadding(FMargin(InsetForShimmer));
|
|
}
|
|
}
|
|
}
|
|
|
|
void UUIProgressBar_Base::ApplyPrimaryToMID(float Value)
|
|
{
|
|
if (FillMID)
|
|
{
|
|
FillMID->SetScalarParameterValue(P_PrimaryLevel, Value);
|
|
}
|
|
// Edge acompanha o nível Primary (posição da linha = PrimaryLevel)
|
|
if (EdgeMID)
|
|
{
|
|
EdgeMID->SetScalarParameterValue(P_PrimaryLevel, Value);
|
|
}
|
|
UpdateEdgeVisibility();
|
|
}
|
|
|
|
void UUIProgressBar_Base::UpdateEdgeVisibility()
|
|
{
|
|
if (!EdgeImage)
|
|
{
|
|
return;
|
|
}
|
|
if (!bShowEdge)
|
|
{
|
|
EdgeImage->SetVisibility(ESlateVisibility::Collapsed);
|
|
return;
|
|
}
|
|
// Auto-hide quando Primary está nos extremos (0 ou 1) — Edge encostaria na borda.
|
|
const bool bAtExtreme = (CurrentPrimaryLevel <= 0.f) || (CurrentPrimaryLevel >= 1.f);
|
|
EdgeImage->SetVisibility(bAtExtreme ? ESlateVisibility::Collapsed : ESlateVisibility::HitTestInvisible);
|
|
}
|
|
|
|
void UUIProgressBar_Base::ApplySecondaryToMID(float Value)
|
|
{
|
|
if (FillMID)
|
|
{
|
|
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();
|
|
}
|