UniversalBars plugin: PEAK-style universal UMG bars
Procedural M_UI_UniversalBar material (SDF rounded-rect, fill/delayed/shield/ penalty-zones/stripes/segments/flash/pulse), 6 preset instances, animated UUniversalBarWidget + UUniversalHUDWidget + global UUniversalBarsSubsystem API, UUniversalBarsTheme DataAsset, and a ready WBP_HUD_InGame with zone-tracking status chips. See README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
157
Source/UniversalBars/Public/UniversalBarWidget.h
Normal file
157
Source/UniversalBars/Public/UniversalBarWidget.h
Normal file
@ -0,0 +1,157 @@
|
||||
// Copyright IHY. Universal Bars plugin.
|
||||
// One animated UMG bar driven by M_UI_UniversalBar. Handles a single logical
|
||||
// value (HP, stamina, durability, ...) plus optional data-driven penalty zones
|
||||
// for combined PEAK-style capacity bars (hunger / weight / cold eating into max).
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Blueprint/UserWidget.h"
|
||||
#include "UniversalBarWidget.generated.h"
|
||||
|
||||
class UImage;
|
||||
class UMaterialInstanceDynamic;
|
||||
|
||||
// A penalty / reserve zone consuming capacity from the right end of the bar.
|
||||
USTRUCT(BlueprintType)
|
||||
struct FBarZone
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Zone")
|
||||
FName Id = NAME_None;
|
||||
|
||||
// Target width as a fraction of the full track (0..1).
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Zone", meta=(ClampMin="0", ClampMax="1"))
|
||||
float Width = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Zone")
|
||||
FLinearColor Color = FLinearColor(0.9f, 0.6f, 0.2f, 1.f);
|
||||
|
||||
// Animated width that eases toward Width at runtime (not authored).
|
||||
float DisplayWidth = 0.f;
|
||||
};
|
||||
|
||||
UCLASS()
|
||||
class UNIVERSALBARS_API UUniversalBarWidget : public UUserWidget
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UUniversalBarWidget(const FObjectInitializer& ObjectInitializer);
|
||||
|
||||
// Name this "BarImage" in the WBP; assign an MI_UI_Bar_* (or the master) to its Brush.
|
||||
UPROPERTY(meta=(BindWidget))
|
||||
TObjectPtr<UImage> BarImage = nullptr;
|
||||
|
||||
// ---- animation tuning ----
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float FillRiseSpeed = 7.f; // how fast the bright fill grows on increase/heal
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float DelayedFallSpeed = 4.f; // how fast the damage-lag tail drains on decrease
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float DelayedDelay = 0.25f; // pause before the tail starts draining (sec)
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float FlashSpeed = 6.f; // flash decay rate
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float ZoneInterpSpeed = 8.f; // penalty-zone width easing
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
float LowThreshold = 0.25f; // below this, low-value pulse turns on
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Anim")
|
||||
bool bAutoFlashOnChange = true; // SetFillPercent auto-plays damage/heal flash
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Colors")
|
||||
FLinearColor DamageFlashColor = FLinearColor(1.f, 0.12f, 0.12f, 1.f);
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Colors")
|
||||
FLinearColor HealFlashColor = FLinearColor(0.6f, 1.f, 0.6f, 1.f);
|
||||
|
||||
// ---- data-driven penalty zones (combined / PEAK mode) ----
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Bar|Zones")
|
||||
TArray<FBarZone> PenaltyZones;
|
||||
|
||||
// ===== public API =====
|
||||
// Animated set of the bar's main value (0..1). Decrease => instant drop + lag
|
||||
// tail (+ damage flash). Increase => smooth rise (+ heal flash).
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetFillPercent(float NewValue, bool bAnimate = true);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetShieldPercent(float NewValue);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void PlayDamageFlash();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void PlayHealFlash();
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void PlayFlash(FLinearColor Color);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetBarColors(FLinearColor Fill, FLinearColor Empty, FLinearColor Border, FLinearColor Delayed);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetSegmentCount(int32 Count);
|
||||
|
||||
// ---- penalty zone management (animated) ----
|
||||
UFUNCTION(BlueprintCallable, Category="Bar|Zones")
|
||||
void SetPenaltyZone(FName Id, float Width, FLinearColor Color);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar|Zones")
|
||||
void SetPenaltyZoneWidth(FName Id, float Width);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar|Zones")
|
||||
void RemovePenaltyZone(FName Id);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar|Zones")
|
||||
void ClearPenaltyZones();
|
||||
|
||||
// Generic escape hatches.
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetScalar(FName Param, float Value);
|
||||
|
||||
UFUNCTION(BlueprintCallable, Category="Bar")
|
||||
void SetVector(FName Param, FLinearColor Value);
|
||||
|
||||
UFUNCTION(BlueprintPure, Category="Bar")
|
||||
float GetFillPercent() const { return TargetFill; }
|
||||
|
||||
// ---- zone layout in bar-U space (0..1), using current animated widths ----
|
||||
// Right edge of the usable region (1 - sum of penalty display widths).
|
||||
UFUNCTION(BlueprintPure, Category="Bar|Zones")
|
||||
float GetUsableEnd() const;
|
||||
|
||||
// U-coordinate of a penalty zone's centre; -1 if the zone is absent.
|
||||
UFUNCTION(BlueprintPure, Category="Bar|Zones")
|
||||
float GetZoneCenter(FName Id) const;
|
||||
|
||||
protected:
|
||||
virtual void NativeConstruct() override;
|
||||
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||
|
||||
UMaterialInstanceDynamic* EnsureMID();
|
||||
void PushZones(bool bImmediate);
|
||||
|
||||
private:
|
||||
UPROPERTY(Transient)
|
||||
TObjectPtr<UMaterialInstanceDynamic> BarMID = nullptr;
|
||||
|
||||
float TargetFill = 1.f;
|
||||
float DisplayFill = 1.f;
|
||||
float DelayedFill = 1.f;
|
||||
float DelayTimer = 0.f;
|
||||
|
||||
float FlashAmount = 0.f;
|
||||
bool bFlashing = false;
|
||||
FLinearColor PendingFlashColor = FLinearColor::Red;
|
||||
|
||||
float PulseAmount = 0.f;
|
||||
|
||||
static constexpr int32 MaxMaterialZones = 4;
|
||||
};
|
||||
Reference in New Issue
Block a user