Files
Bonchellon 41a0cdef36 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>
2026-06-23 19:04:50 +03:00

232 lines
8.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Universal Bars
PEAK-style universal UMG bars for Unreal Engine 5.7 — one procedural material
drives every kind of stat bar (health, stamina, hunger, thirst, oxygen, cold,
shield, injury, boss HP, item durability, progress), with a global subsystem
API and animated damage / heal / low-value feedback.
Everything is **procedural** — no bar textures required. White rounded border,
soft corners, dark translucent backdrop, bright flat fill: clean cartoon
survival HUD.
---
## 1. Install / enable
The plugin lives at `Plugins/UniversalBars/`. It is a project plugin and is
enabled by default. After pulling, regenerate project files and build the
editor target once (it adds the `UniversalBars` runtime module). Content mounts
under `/UniversalBars/`.
> New C++ classes (a new module) cannot be hot-loaded by Live Coding — do a full
> editor build the first time.
---
## 2. What's inside
```
/UniversalBars/
Materials/
M_UI_UniversalBar master material (Domain=UI, Translucent, procedural SDF)
MI_UI_Bar_Health solo green bar
MI_UI_Bar_Stamina solo yellow-green bar
MI_UI_Bar_Injury striped "broken HP" bar
MI_UI_Bar_Shield blue bar + shield overlay
MI_UI_Bar_Boss segmented boss bar
MI_UI_Bar_PeakCombined HP + hunger + weight in ONE bar (PEAK capacity)
Components/
WBP_UniversalBar one reusable bar (parent: UUniversalBarWidget)
WBP_BarHealth combined-capacity variant
WBP_BarStamina stamina variant
WBP_HUD_InGame ready HUD: health + stamina + status chips
Theme/ put DA_UniversalBars_* theme assets here
C++ (module UniversalBars):
UUniversalBarWidget one animated bar
UUniversalHUDWidget HUD container with high-level stat setters
UUniversalBarsSubsystem global access point (UWorldSubsystem)
UUniversalBarsTheme palette / geometry / chip-colour DataAsset
```
---
## 3. Quick start
### Blueprint — easiest path (global API, no widget reference)
1. On `BeginPlay` (player controller / HUD), call
`Universal Bars Subsystem → Create HUD` with `HUD Class = WBP_HUD_InGame`.
2. From **anywhere** in BP:
```
Get World Subsystem (UniversalBarsSubsystem)
→ Set Health (0.62) // 0..1, animates + flashes automatically
→ Set Stamina (0.8)
→ Set Hunger (0.16) // penalty zone eats into max HP (combined bar)
→ Set Weight (0.12)
→ Damage Health (0.2) // red flash + instant drop + lag tail
→ Heal Health (0.25) // green flash + smooth rise
```
Direction is detected for you: a decrease plays the damage animation, an
increase plays the heal animation.
### C++
```cpp
#include "UniversalBarsSubsystem.h"
if (UUniversalBarsSubsystem* Bars = UUniversalBarsSubsystem::Get(this))
{
Bars->SetHealth(0.62f);
Bars->SetHunger(0.16f);
Bars->DamageHealth(0.2f);
}
```
### Driving a single bar directly
Place a `WBP_UniversalBar` (or a preset variant) anywhere and call:
```cpp
UUniversalBarWidget* Bar = ...;
Bar->SetFillPercent(0.5f); // animated
Bar->SetShieldPercent(0.25f);
Bar->SetSegmentCount(10); // boss segments
Bar->SetPenaltyZone("Hunger", 0.16f, FLinearColor(0.9f,0.6f,0.2f,1)); // animated zone
Bar->PlayDamageFlash(); // manual flash
```
---
## 4. Animation model (same as the HTML prototype)
| Change | Bright fill | Lag tail | Flash |
|---|---|---|---|
| **Decrease / damage** | snaps down instantly | holds `DelayedDelay`s, then drains at `DelayedFallSpeed` | red (`DamageFlashColor`) |
| **Increase / heal** | eases up at `FillRiseSpeed` | jumps to target (lighter "incoming" band) | green (`HealFlashColor`) |
| **value < `LowThreshold`** | — | — | border pulses (low-value warning) |
| **penalty zone change** | — | zone width eases at `ZoneInterpSpeed` | — |
All tuning fields live on `UUniversalBarWidget` (Bar|Anim category). Set
`bAutoFlashOnChange=false` to drive flashes manually.
Under the hood the material exposes `FillPercent`, `DelayedFillPercent`,
`FlashAmount`, `LowHPPulseAmount` — the widget tweens these every tick via a
Dynamic Material Instance.
---
## 5. Combined "capacity" bar (PEAK)
One bar = current value (bright) + depleted-but-recoverable zone (dark) +
striped penalty zones eating max from the right:
- `MaxFillPercent` — right edge of the usable region (`1 - sum(penalties)`).
- `PenaltyCount` + `PenaltyEnd1..4` + `PenaltyColor1..4` — up to 4 striped zones.
You never set these by hand — `SetHunger / SetWeight / SetCold` (HUD) or
`SetPenaltyZone(Id, Width, Color)` (bar) manage them and animate the widths.
Set a penalty to `0` to retract its zone.
`PenaltyCount = 0` → the same material is a plain solo bar.
---
## 6. Material parameter reference
**Scalars:** `FillPercent`, `DelayedFillPercent`, `ShieldPercent`,
`MaxFillPercent`, `PenaltyCount`, `PenaltyEnd1..4`, `BarOpacity`,
`BackgroundOpacity`, `CornerRadius`, `BorderSize`, `InnerPadding`,
`EdgeSoftness`, `BarAspect`, `FlashAmount`, `LowHPPulseAmount`, `PulseSpeed`,
`StripeAmount`, `StripeScale`, `StripeSpeed`, `SegmentCount`,
`SegmentDividerSize`, `SegmentDividerOpacity`, `UseVerticalFill`, `InvertFill`,
`NoiseAmount`, `TimeOffset`.
**Vectors:** `FillColor`, `DelayedFillColor`, `ShieldColor`, `BackgroundColor`,
`BorderColor`, `EmptyColor`, `FlashColor`, `StripeColorA`, `StripeColorB`,
`PenaltyColor1..4`.
`BarAspect` must roughly match the on-screen width/height ratio so the rounded
corners stay circular (default 8 ≈ a 600×75 bar).
---
## 7. Theme
`UUniversalBarsTheme` (DataAsset) centralises palette + geometry + chip colours.
Create one under `/UniversalBars/Theme/` (right-click → Miscellaneous → Data
Asset → Universal Bars Theme), then assign it to `WBP_HUD_InGame`'s `Theme`
property. `UUniversalHUDWidget::ApplyTheme()` runs on construct and retints both
bars and all chips. Per-preset look still lives in the `MI_UI_Bar_*` instances;
the theme is the HUD-level override.
---
## 8. Presets (recommended values)
| Preset | Fill | Notes |
|---|---|---|
| Health | `(0.30,0.85,0.20)` | white border, low-HP pulse, damage lag |
| Stamina | `(0.85,0.95,0.30)` | thinner, no pulse |
| Injury | `(0.75,0.20,0.20)` + `StripeAmount=1` | striped "broken" HP |
| Shield | `(0.30,0.70,1.0)` + `ShieldPercent` | blue + overlay |
| Boss | `(0.85,0.15,0.15)` + `SegmentCount=10` | wide, segmented, less rounded |
| PeakCombined | green + Hunger/Weight penalties | one-bar HP+hunger+weight |
Keep `BorderColor` pure white and `BorderSize` 0.060.10 for the toy/cartoon
look; `CornerRadius` 0.50.7 for horizontal bars.
---
## 9. Demo / study mode (WBP_HUD_InGame)
`WBP_HUD_InGame` ships with **Demo Mode ON** (`UUniversalHUDWidget::bDemoMode`).
While on, the HUD's `NativeTick` runs a 10-step cycle every `DemoStepInterval`
(1.6 s) so you can watch every animation live in PIE:
```
0 DamageHealth(0.25) red flash + instant drop + lag tail
1 SetStamina(0.30) stamina drop
2 HealHealth(0.20) green flash + smooth rise
3 SetHunger(0.18) amber zone eases in from the right
4 SetWeight(0.14) red zone eases in
5 SetStamina(0.95) stamina refill
6 HealHealth(0.30)
7 SetHunger(0.0) hunger zone retracts
8 SetWeight(0.0) weight zone retracts
9 DamageHealth(0.45) big hit -> low-HP border pulse
```
To watch: add the HUD (`Subsystem → Create HUD`, or just drop it in any widget /
PIE) and press Play. The cycle restarts each time the widget constructs.
**Turn it off for shipping:** open `WBP_HUD_InGame` → Class Defaults → uncheck
**Demo Mode**, or call `SetDemoMode(false)`. Read `DemoStepNow()` in
`UniversalHUDWidget.cpp` to see exactly which API call drives each animation.
## 9b. Status chips (PEAK markers)
In `WBP_HUD_InGame` the chips live in a `CanvasPanel` (`ChipCanvas`) **overlaid on
the health bar**, not in a row below it. Each tick `UUniversalHUDWidget::PositionChips()`
slides them to sit just above the centre of their zone, using
`UUniversalBarWidget::GetUsableEnd()` / `GetZoneCenter("Hunger"|"Weight"|"Cold")`:
- `ChipHeart` → the usable-HP / penalty boundary
- `ChipHunger` → centre of the hunger zone (hidden until `SetHunger > 0`)
- `ChipWeight` → centre of the weight zone
- `ChipCold` → centre of the cold zone
So when hunger/weight grow or shrink, the chips ride along with the zone edges.
Add your own marker by placing an `Image` in `ChipCanvas` and binding it (or extend
`PositionChips`). Swap the placeholder tints for real icon textures.
## 10. Notes / limits
- The bar is a UI-domain material — it only renders inside UMG/Slate (not on
meshes). Verify visuals in the UMG designer or content-browser thumbnail.
- Up to 4 penalty zones are drawn by the material in a single draw call; the
widget warns if you push more.
- `SetFillPercent` clamps to 0..1. Feed it `CurrentHP / MaxHP`, etc.