This commit is contained in:
2026-06-07 13:28:25 -07:00
parent 0df0b45163
commit 25b53cb062
25 changed files with 1573 additions and 125 deletions
@@ -0,0 +1,49 @@
---
id: DR-024
title: HUD reskinned with the Synty sci-fi-soldier kit via a build-safe HudTheme ScriptableObject (icons, fonts, panels, vignette, scheme-aware hints)
status: accepted
date: 2026-06-07
tags:
- decision
- hud
- ui-toolkit
- synty
- presentation
- juice
permalink: gamevault/07-sessions/decisions/dr-024-hud-synty-skin-theme
---
# DR-024 — HUD Synty skin + HudTheme (build-safe asset harvest into the code-built UITK HUD)
## Context
[[DR-021_HUD_UITK_BuildPalette]] put the HUD on UI Toolkit but flat-colour, system-font, text-only, and left open: per-buildable icons, a build-mode hint line, a conveyor-facing arrow. The imported **InterfaceSciFiSoldierHUD** + **InterfaceCore** packs ([[Synty_Asset_Inventory]]) are a complete on-theme HUD kit (status/map/inventory icons, HUD box/frame/bar/pip/gradient/glow sprites, 640 input-prompt glyphs, Orbitron + Exo 2.0 fonts). Operator: *"expansive, large pass … use everything you can, make it look good, good design principles."*
## Decision
1. **Curated, serialized `HudTheme` ScriptableObject is the build-safe asset bridge.** The Synty sprites/fonts live under `Assets/Synty/…`, NOT a `Resources/` folder, so a runtime name-string `Resources.Load("Synty/…")` would be stripped from the player build. Instead, `Assets/_Project/Resources/HudTheme.asset` holds ~31 **serialized** Sprite/Font references (the dependency walker pulls them into the build); it's loaded once, null-safe, via `HudTheme.Get()` (mirroring `MenuUi.LoadPanelSettings`). **Every consumer null-checks the theme AND each field and falls back to the flat-colour HUD** — a missing asset/ref never breaks or magenta-s the HUD, and EditMode stays green without the asset.
2. **Tint the white kit into the Aether palette; don't adopt the kit's stock colours.** `unityBackgroundImageTintColor` MULTIPLIES the (light-grey) Synty skins, so one panel sprite (`Box_Glass_01`) tinted per-cluster (panel-dark, warm-dark under siege) reads as a coherent system. Aether-cyan = friendly/charge/selection + structure icons; Blight-orange→red = threat/low-HP/siege; Ore-amber / Bio-green for resources. Orbitron-ExtraBold (SDF) for numerics + phase words; Exo 2.0 for labels/hints — applied through `MenuUi`'s shared factories so **menu/pause/settings re-font too**.
3. **Fonts = cached runtime SDF FontAssets.** `FontAsset.CreateFontAsset(Font)` + `FontDefinition.FromSDFFont` is the reliable runtime path (crisp at any scale, supports outlines). Built **once per font per session**, cached statically, and reset — together with the theme cache — on `[RuntimeInitializeOnLoadMethod(SubsystemRegistration)]` so a fast-enter-playmode session never references a destroyed atlas (matches the `VFXConfig`/`BuildPaletteState` static-reset rule). A tiny per-editor-session atlas leak is accepted.
4. **Let the art's authored 9-slice border drive slicing.** The Synty HUD frame/bar sprites ship borders (Box_Glass=25, Bar_Angled=80/0). Setting `unitySlice*` in code OVERRIDES them and logs a `"borders … overridden by style slices"` error per element. So `HudUi.Panel`/`Bar` assign the sprite + tint and set NO `unitySlice*` — the art border 9-slices correctly and the console stays clean. (Code slices are only needed for border-0 sprites — verified separately.)
5. **Layout follows HUD spatial convention; only data-backed elements are surfaced.** Persistent self-state hugs the corners (health bottom-left, resources top-left, threat top-right, build deck bottom-center); transient mission state is center-top (phase + countdown + CYCLE N + hex-pip goal). Conditional elements appear only when live (shield chip, threat panel hidden at zero/calm, control hints only in build mode) so the resting HUD is clean. No fake minimap/ammo/oxygen despite the kit shipping those sprites.
6. **Resolves the DR-021 opens.** Per-buildable icons (from `HudTheme.StructureIcon`, cost icon + affordability now keyed off `StructureCatalogEntry.CostResourceId` so it stays correct as the catalog grows); a **scheme-aware** build-mode control-hint bar (KBM vs gamepad glyphs via `AimPresentation.Scheme`, text keycaps where no glyph exists); and a **live conveyor-facing arrow** (rotated by `BuildPaletteState.Direction`) gated to conveyors. Low-health screen **vignette + hurt-flash** (`HudVisualMath`, pure + unit-tested) is the new unmissable damage signal.
## Consequences
- **No netcode / asmdef / ghost-hash change.** Pure client presentation: a new managed ScriptableObject + Resources asset + the rewritten observe-only `HudSystem` (client `PresentationSystemGroup`), `HudUi`/`MenuUi` factories, and `HudVisualMath`. `HudSystem` reads ECS read-only and mutates nothing; it adds `EntityManager.CompleteDependencyBeforeRO<T>()` for the components it reads, matching the sibling presentation systems.
- **Validated on 6.4.7** (real Server+Client): EditMode **214/214** (+6 `HudVisualMath`); 4 Play states screenshotted (base / build-mode / low-health / conveyor-facing); console clean. Screenshots: `HudSyntyPass_Base/BuildMode/LowHealth/ConveyorFacing.png`.
- New durable conventions folded into `CLAUDE.md` (build-safe HudTheme harvest; art-border-drives-slicing; verify Synty sprite import-mode).
## Open / deferred
- Conveyor-facing arrow's absolute compass mapping vs the world placement ghost (a 1-line `FacingDegrees` offset if the arrow art's default vector differs) — confirm in natural play.
- Narrow-window vitals↔palette overlap (resolution artifact; fine at 1920) — responsive layout deferred.
- Cooldown radial treatment; throughput-on-belt visuals (needs a replicated machine field — the [[DR-020_M7_Automation_Production_Chains]] open item).
- `HudTheme` icon picks are operator-tunable in the one asset (e.g. Wall uses the Armor glyph — no dedicated wall icon in the kit).
Builds on [[DR-021_HUD_UITK_BuildPalette]] (the UITK HUD + palette this skins) and [[DR-019_Frontend_Menu_Settings_Saves_Build]] (shared `MenuUi`/PanelSettings). Consumes [[Synty_Asset_Inventory]]'s "HUD polish" hook. Serves the co-op base-building + game-feel [[Pillars]].