fix(ui): T-1140 overlay bar wraps instead of overflowing; strip dev ids from tooltips

Jeroen's first make atlas hands-on: 17 overlay chips in a single
HBoxContainer row ran off the right screen edge (positioning also
guessed the bar's width with a 520px fallback). The bar is now an
HFlowContainer with ALIGNMENT_END; the viewer gives it everything
right of the header (OVERLAY_BAR_HEADER_RESERVE) and rows wrap
right-aligned — verified via live capture, all 18 chips visible.

OVERLAY_DEFS tooltips leaked dev provenance into player-facing text —
ticket ids (#960, T-960, T-1046, T-1118, T-1119) and decision ids
(D-181, D-226, D-243) mean nothing in-game. Stripped to plain
language; the visibility-ladder semantics (public signal / observable
/ needs corporate contact / needs insider access) stay.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 08:59:08 +02:00
co-authored by Claude Fable 5
parent 9d2e9a4cf1
commit b56f6b0bc8
4 changed files with 49 additions and 18 deletions
@@ -1,4 +1,4 @@
extends HBoxContainer
extends HFlowContainer
## Overlay toggle bar for #835 AtlasViewer — nine MVP overlays plus two locked
## layers (#836, D-191 §7, D-181 signal visibility ladder).
@@ -11,6 +11,11 @@ extends HBoxContainer
## Layout: [ALWAYS-ON] [TOGGLEABLE] [LOCKED]. Each row in viewer.get_overlay_defs()
## produces exactly one button, so adding or retiring an overlay is a one-file
## change — the bar and marker renderer stay in lockstep (review #7).
##
## HFlowContainer, not HBoxContainer: the overlay count outgrew one row
## (17 chips at 42px min overflowed the right screen edge — Jeroen,
## companion feedback 2026-07-21). The viewer gives the bar a constrained
## width (everything right of the header) and rows wrap right-aligned.
const COLOR_PINNED: Color = Color("#c8d0e0")
const COLOR_ACTIVE: Color = Color("#f0d060")
@@ -23,7 +28,9 @@ var _buttons: Dictionary = {} # overlay_id -> Button
func _init(viewer_ref = null) -> void:
_viewer = viewer_ref
add_theme_constant_override("separation", 4)
alignment = FlowContainer.ALIGNMENT_END
add_theme_constant_override("h_separation", 4)
add_theme_constant_override("v_separation", 4)
func _ready() -> void:
+25 -16
View File
@@ -33,6 +33,9 @@ const ZOOM_STEP: float = 1.15
const PANEL_WIDTH: float = 320.0
const PANEL_MARGIN: float = 16.0
# Width reserved for the top-left header block (title + hint lines) that the
# wrapping overlay bar must not overlap.
const OVERLAY_BAR_HEADER_RESERVE: float = 360.0
# ── Colors ────────────────────────────────────────────────────────────────────
const COLOR_BG: Color = Color("#0d1117")
@@ -96,80 +99,80 @@ const OVERLAY_DEFS: Array = [
"id": "population_density",
"label": "POP",
"group": "toggle",
"tooltip": "Population density (D-181 public)."
"tooltip": "Population density (public signal)."
},
{
"id": "production_zones",
"label": "PRD",
"group": "toggle",
"tooltip": "Production zones (D-181 observable — requires presence)."
"tooltip": "Production zones (observable — requires presence)."
},
{
"id": "corp_presence",
"label": "CRP",
"group": "toggle",
"tooltip": "Corporate presence — Tier 1 only (D-181 observable)."
"tooltip": "Corporate presence — Tier 1 only (observable)."
},
{
"id": "stockpile_weeks",
"label": "STK",
"group": "locked",
"tooltip": "Stockpile weeks — LOCKED. Needs corporate contact (D-181 semi-private)."
"tooltip": "Stockpile weeks — LOCKED. Needs corporate contact."
},
{
"id": "production_vs_baseline",
"label": "BSL",
"group": "locked",
"tooltip": "Production vs baseline — LOCKED. Needs insider access (D-181 private)."
"tooltip": "Production vs baseline — LOCKED. Needs insider access."
},
{
"id": "gen_l1_rivers",
"label": "RVR",
"group": "toggle",
"tooltip": "Layer 1 — river network (generation overlay, #960)."
"tooltip": "River network (generation overlay)."
},
{
"id": "gen_l1_basins",
"label": "BAS",
"group": "toggle",
"tooltip": "Layer 1 — drainage basins (generation overlay, #960)."
"tooltip": "Drainage basins (generation overlay)."
},
{
"id": "gen_l1_attractors",
"label": "ATR",
"group": "toggle",
"tooltip": "Layer 1 — geographic attractors (generation overlay, #960)."
"tooltip": "Geographic attractors (generation overlay)."
},
{
"id": "gen_district",
"label": "MRPH",
"group": "toggle",
"tooltip": "District morphology zones (generation overlay, T-1046/D-226)."
"tooltip": "District morphology zones (generation overlay)."
},
{
"id": "gen_l2_roads",
"label": "RDS",
"group": "toggle",
"tooltip":
"Layer 2 — inter-settlement road/rail graph, colored by maintenance authority (generation overlay, T-960)."
"Inter-settlement road/rail graph, colored by maintenance authority (generation overlay)."
},
{
"id": "gen_l3_settlements",
"label": "STL",
"group": "toggle",
"tooltip": "Layer 3 — settlement placements, sized by population (generation overlay, T-960)."
"tooltip": "Settlement placements, sized by population (generation overlay)."
},
{
"id": "gen_region_grid",
"label": "TMP",
"group": "toggle",
"tooltip": "Region climate grid — mean temperature (generation overlay, T-1118/D-243)."
"tooltip": "Region climate — mean temperature (generation overlay)."
},
{
"id": "gen_l4_quarters",
"label": "QTR",
"group": "toggle",
"tooltip": "Layer 4 — quarter footprint, color=density shape=type (generation overlay, T-1119)."
"tooltip": "Quarter footprints — color is density, shape is district type (generation overlay)."
},
]
@@ -949,9 +952,15 @@ func _position_overlay_bar() -> void:
var sz: Vector2 = get_rect().size
if sz == Vector2.ZERO:
sz = Vector2(1280.0, 720.0)
# Top-right, leaving room for the header text
var bar_w: float = _overlay_bar.size.x if _overlay_bar.size.x > 0.0 else 520.0
_overlay_bar.position = Vector2(sz.x - bar_w - PANEL_MARGIN, PANEL_MARGIN)
# Top-right, constrained to everything right of the header. The bar is an
# HFlowContainer with ALIGNMENT_END: give it the available width and it
# wraps into as many right-aligned rows as the chip count needs (17 chips
# overflowed the screen edge as a single HBox row — companion feedback,
# 2026-07-21). Height is Control-clamped to the flow's minimum, so it
# grows per row on its own.
var avail_w: float = maxf(sz.x - OVERLAY_BAR_HEADER_RESERVE - PANEL_MARGIN * 2.0, 200.0)
_overlay_bar.position = Vector2(sz.x - avail_w - PANEL_MARGIN, PANEL_MARGIN)
_overlay_bar.size = Vector2(avail_w, 0.0)
# =============================================================================