From 3c07f0680c22a89acecc7ca7e3325cb1b0288c64 Mon Sep 17 00:00:00 2001 From: autocommit Date: Thu, 4 Jun 2026 21:36:41 -0700 Subject: [PATCH] refactor(ui): tokenize world-map HUD + minimap colors (p2-74 cluster 3b) Route inline Color() in the world-map HUD banners and minimap onto ThemeAssets design tokens. Visual-only (Rail 3), no logic change: - world_map_hud: patrol banner box -> background.panel/accent.science + label accent.science; rally picker box -> background.panel/accent.sage + title accent.science; notification toast box -> background.panel/accent.gold + label text.primary - minimap: const FOG_COLOR/UNEXPLORED_COLOR/PING_RING_COLOR -> _ready()-populated vars from fog.explored/fog.unexplored/accent.ping; border stylebox border -> border.panel; backdrop fill -> background.deepest Minimap TERRAIN_COLORS biome palette stays hardcoded with an explicit comment: it is game-content color (no UI token applies) and a deliberately distinct muted minimap rendering, not a terrain.json mirror (the arrays diverge). Re-sourcing it is a Rail-2 data follow-up, out of scope for this visual-only token pass. DataLoader RGB conversion, env-var viewport color, transparent structural fills, and the neutral gray default left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/game/engine/scenes/hud/minimap.gd | 31 +++++++++++++++------ src/game/engine/scenes/hud/world_map_hud.gd | 18 ++++++------ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/game/engine/scenes/hud/minimap.gd b/src/game/engine/scenes/hud/minimap.gd index 53a86398..914a05c0 100644 --- a/src/game/engine/scenes/hud/minimap.gd +++ b/src/game/engine/scenes/hud/minimap.gd @@ -9,7 +9,12 @@ const CityScript: GDScript = preload("res://engine/src/entities/city.gd") const UnitScript: GDScript = preload("res://engine/src/entities/unit.gd") const PlayerScript: GDScript = preload("res://engine/src/entities/player.gd") -## Terrain colors indexed by terrain_id — keep in sync with terrain.json +## Minimap terrain palette indexed by terrain_id. These are game-content +## colors (no UI design token applies) and are a deliberately distinct, +## muted minimap rendering — NOT a mirror of terrain.json's `color` arrays +## (those diverge by 10-70/channel; only `coast` coincides). p2-74 leaves +## this hardcoded; routing it through a data source is a Rail-2 follow-up +## (logic change, out of scope for the visual-only token pass). const TERRAIN_COLORS: Dictionary = { "ocean": Color(0.12, 0.24, 0.55), "coast": Color(0.31, 0.71, 0.86), @@ -28,8 +33,6 @@ const TERRAIN_COLORS: Dictionary = { "volcano": Color(0.55, 0.16, 0.12), } const DEFAULT_TERRAIN_COLOR: Color = Color(0.3, 0.3, 0.3) -const FOG_COLOR: Color = Color(0.0, 0.0, 0.0, 0.70) -const UNEXPLORED_COLOR: Color = Color(0.0, 0.0, 0.0, 0.90) const CITY_DOT_RADIUS: float = 4.0 const UNIT_DOT_RADIUS: float = 3.0 const OWNER_TINT_ALPHA: float = 0.38 @@ -39,7 +42,6 @@ const OWNER_TILE_SIZE: Vector2 = Vector2(3.0, 3.0) ## `_ping_remaining` ticks down each overlay redraw frame so the pulse ## fades naturally without a dedicated tween. const PING_DURATION_SEC: float = 1.6 -const PING_RING_COLOR: Color = Color(1.0, 0.92, 0.45, 1.0) const PING_RING_BASE_RADIUS: float = 4.0 const PING_RING_GROWTH: float = 8.0 const PING_RING_WIDTH: float = 2.0 @@ -53,6 +55,14 @@ var _camera: Camera2D = null var _ping_axial: Vector2i = Vector2i(-9999, -9999) var _ping_started_at: float = -1.0 +## Token-sourced colors, populated in _ready() (ThemeAssets.color isn't +## const-eval safe). fog/ping map to dedicated design tokens; the minimap +## backdrop uses the deepest background token. +var _fog_color: Color = Color(0.0, 0.0, 0.0, 0.70) +var _unexplored_color: Color = Color(0.0, 0.0, 0.0, 0.90) +var _ping_ring_color: Color = Color(1.0, 0.92, 0.45, 1.0) +var _backdrop_color: Color = Color(0.04, 0.04, 0.06) + @onready var _map_rect: TextureRect = %MapRect @onready var _overlay_rect: Control = %OverlayRect @@ -62,11 +72,16 @@ func _ready() -> void: _overlay_rect.draw.connect(_draw_overlay) gui_input.connect(_on_gui_input) + _fog_color = ThemeAssets.color("fog.explored") + _unexplored_color = ThemeAssets.color("fog.unexplored") + _ping_ring_color = ThemeAssets.color("accent.ping") + _backdrop_color = ThemeAssets.color("background.deepest") + var border_panel: Panel = get_node_or_null("Border") as Panel if border_panel != null: var style: StyleBoxFlat = StyleBoxFlat.new() style.bg_color = Color(0.0, 0.0, 0.0, 0.0) - style.border_color = Color(0.75, 0.65, 0.35, 0.95) + style.border_color = ThemeAssets.color("border.panel") style.set_border_width_all(2) style.set_corner_radius_all(2) border_panel.add_theme_stylebox_override("panel", style) @@ -141,7 +156,7 @@ func _rebuild_terrain() -> void: var img_w: int = maxi(1, roundi(mm_size.x)) var img_h: int = maxi(1, roundi(mm_size.y)) _cached_image = Image.create(img_w, img_h, false, Image.FORMAT_RGB8) - _cached_image.fill(Color(0.04, 0.04, 0.06)) + _cached_image.fill(_backdrop_color) for py: int in img_h: for px: int in img_w: @@ -204,7 +219,7 @@ func _draw_ping() -> void: return var t: float = clampf(elapsed / PING_DURATION_SEC, 0.0, 1.0) var radius: float = PING_RING_BASE_RADIUS + PING_RING_GROWTH * t - var color: Color = PING_RING_COLOR + var color: Color = _ping_ring_color color.a = 1.0 - t var pixel_pos: Vector2 = _world_to_mini( HexUtilsScript.axial_to_pixel(_ping_axial) + Vector2( @@ -224,7 +239,7 @@ func _draw_fog(game_map: RefCounted, player_index: int) -> void: HexUtilsScript.HEX_WIDTH * 0.5, HexUtilsScript.HEX_HEIGHT * 0.5 ) ) - var fog_col: Color = FOG_COLOR if vis == 1 else UNEXPLORED_COLOR + var fog_col: Color = _fog_color if vis == 1 else _unexplored_color _overlay_rect.draw_rect( Rect2(pixel_pos - Vector2(1.0, 1.0), Vector2(3.0, 3.0)), fog_col ) diff --git a/src/game/engine/scenes/hud/world_map_hud.gd b/src/game/engine/scenes/hud/world_map_hud.gd index 2bd69821..bfb547f6 100644 --- a/src/game/engine/scenes/hud/world_map_hud.gd +++ b/src/game/engine/scenes/hud/world_map_hud.gd @@ -213,8 +213,8 @@ func _build_patrol_banner() -> void: _patrol_banner.offset_bottom = 162.0 _patrol_banner.visible = false var style: StyleBoxFlat = StyleBoxFlat.new() - style.bg_color = Color(0.05, 0.08, 0.14, 0.94) - style.border_color = Color(0.3, 0.55, 0.9, 0.9) + style.bg_color = ThemeAssets.color("background.panel") + style.border_color = ThemeAssets.color("accent.science") style.set_border_width_all(2) style.set_corner_radius_all(4) style.content_margin_left = 12.0 @@ -226,7 +226,7 @@ func _build_patrol_banner() -> void: _patrol_banner_label = Label.new() _patrol_banner_label.name = "PatrolBannerLabel" _patrol_banner_label.add_theme_font_size_override("font_size", 15) - _patrol_banner_label.add_theme_color_override("font_color", Color(0.75, 0.88, 1.0)) + _patrol_banner_label.add_theme_color_override("font_color", ThemeAssets.color("accent.science")) _patrol_banner_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER _patrol_banner_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART _patrol_banner.add_child(_patrol_banner_label) @@ -245,8 +245,8 @@ func _build_rally_command_picker() -> void: _rally_command_picker.offset_bottom = 48.0 _rally_command_picker.visible = false var style: StyleBoxFlat = StyleBoxFlat.new() - style.bg_color = Color(0.05, 0.08, 0.14, 0.96) - style.border_color = Color(0.55, 0.75, 0.35, 0.9) + style.bg_color = ThemeAssets.color("background.panel") + style.border_color = ThemeAssets.color("accent.sage") style.set_border_width_all(2) style.set_corner_radius_all(4) style.content_margin_left = 14.0 @@ -263,7 +263,7 @@ func _build_rally_command_picker() -> void: var title: Label = Label.new() title.text = ThemeVocabulary.lookup("rally_command_pick_title") title.add_theme_font_size_override("font_size", 13) - title.add_theme_color_override("font_color", Color(0.75, 0.88, 1.0)) + title.add_theme_color_override("font_color", ThemeAssets.color("accent.science")) title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER vbox.add_child(title) @@ -360,8 +360,8 @@ func show_notification(text: String) -> void: panel.mouse_filter = Control.MOUSE_FILTER_IGNORE var style: StyleBoxFlat = StyleBoxFlat.new() - style.bg_color = Color(0.08, 0.06, 0.04, 0.92) - style.border_color = Color(0.85, 0.7, 0.3, 0.85) + style.bg_color = ThemeAssets.color("background.panel") + style.border_color = ThemeAssets.color("accent.gold") style.set_border_width_all(2) style.set_corner_radius_all(4) style.content_margin_left = 12.0 @@ -373,7 +373,7 @@ func show_notification(text: String) -> void: var label: Label = Label.new() label.text = text label.add_theme_font_size_override("font_size", 14) - label.add_theme_color_override("font_color", Color(1.0, 0.94, 0.78)) + label.add_theme_color_override("font_color", ThemeAssets.color("text.primary")) label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART panel.add_child(label)