diff --git a/client/scripts/constants.gd b/client/scripts/constants.gd index 0afcb9106..31d4efa68 100644 --- a/client/scripts/constants.gd +++ b/client/scripts/constants.gd @@ -98,9 +98,8 @@ const DIALOGUE_MAX_WIDTH: int = 1200 # D-031: Format game-minutes (0..1439) as station local time string "HH:MM". static func format_game_time(time_of_day: int) -> String: - var hours: int = time_of_day / 60 - var minutes: int = time_of_day % 60 - return "%02d:%02d" % [hours, minutes] + var clamped: int = clampi(time_of_day, 0, 1439) + return "%02d:%02d" % [clamped / 60, clamped % 60] # Default camera zoom — used as fallback when get_camera_2d() returns null const CAMERA_DEFAULT_ZOOM: Vector2 = Vector2(2.0, 2.0) diff --git a/client/scripts/main.gd b/client/scripts/main.gd index a681daabf..9c68ba529 100644 --- a/client/scripts/main.gd +++ b/client/scripts/main.gd @@ -105,7 +105,7 @@ func _process(delta: float) -> void: if interaction_list and interaction_list.has_method("update_from_state"): if dialogue_box and dialogue_box.is_dialogue_active(): if interaction_list.is_showing(): - interaction_list._hide() + interaction_list.hide_list() else: interaction_list.update_from_state() diff --git a/client/ui/interaction_list.gd b/client/ui/interaction_list.gd index 298c4c63f..d44fd7c68 100644 --- a/client/ui/interaction_list.gd +++ b/client/ui/interaction_list.gd @@ -204,6 +204,10 @@ func get_visible_verb_count() -> int: return _verb_items.size() +func hide_list() -> void: + _hide() + + func is_showing() -> bool: return _showing diff --git a/client/ui/time_display.gd b/client/ui/time_display.gd index bcf11a8ce..bf1fe44ee 100644 --- a/client/ui/time_display.gd +++ b/client/ui/time_display.gd @@ -24,8 +24,18 @@ const PHASE_COLORS := { var _time_str: String = "--:--" var _phase_str: String = "" var _day_str: String = "" +var _day_text: String = "" var _phase_color: Color = Constants.IMPLANT_TEXT_DIM var _last_signature: String = "" +var _has_data: bool = false + +# Cached geometry — recomputed in update_from_state(), used in _draw() +var _time_size: Vector2 = Vector2.ZERO +var _phase_size: Vector2 = Vector2.ZERO +var _day_size: Vector2 = Vector2.ZERO +var _meta_h: float = 0.0 +var _box_w: float = 0.0 +var _box_h: float = 0.0 func _ready() -> void: @@ -46,37 +56,42 @@ func update_from_state() -> void: _time_str = Constants.format_game_time(tod) _phase_str = phase _day_str = "D%d" % (day + 1) + _day_text = " " + _day_str _phase_color = PHASE_COLORS.get(phase, Constants.IMPLANT_TEXT_DIM) + _has_data = true + _cache_geometry() queue_redraw() -func _draw() -> void: - if _time_str == "--:--": - return +func _cache_geometry() -> void: var font := ThemeDB.fallback_font + _time_size = font.get_string_size(_time_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_TIME) + _phase_size = font.get_string_size(_phase_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META) + _day_size = font.get_string_size(_day_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META) + _meta_h = font.get_string_size("A", HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META).y + var meta_w := _phase_size.x + _day_size.x + var content_w := max(_time_size.x, meta_w) + _box_w = content_w + PADDING.x * 2 + _box_h = PADDING.y * 2 + _time_size.y + 3 + _meta_h - # Measure - var time_size := font.get_string_size(_time_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_TIME) - var phase_size := font.get_string_size(_phase_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META) - var day_text := " " + _day_str - var day_size := font.get_string_size(day_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META) - var meta_w := phase_size.x + day_size.x - var content_w := max(time_size.x, meta_w) - var box_w := content_w + PADDING.x * 2 - var meta_h := font.get_string_size("A", HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META).y - var box_h := PADDING.y * 2 + time_size.y + 3 + meta_h + +func _draw() -> void: + if not _has_data: + return # Background - draw_rect(Rect2(Vector2.ZERO, Vector2(box_w, box_h)), BG_COLOR) - draw_rect(Rect2(Vector2.ZERO, Vector2(box_w, box_h)), BORDER_COLOR, false, 1.0) + draw_rect(Rect2(Vector2.ZERO, Vector2(_box_w, _box_h)), BG_COLOR) + draw_rect(Rect2(Vector2.ZERO, Vector2(_box_w, _box_h)), BORDER_COLOR, false, 1.0) + + var font := ThemeDB.fallback_font # HH:MM (primary, full brightness) - draw_string(font, Vector2(PADDING.x, PADDING.y + time_size.y), + draw_string(font, Vector2(PADDING.x, PADDING.y + _time_size.y), _time_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_TIME, Constants.IMPLANT_TEXT_COLOR) # Phase + day number (secondary, dimmed + phase-tinted) - var meta_y := PADDING.y + time_size.y + 3 + meta_h + var meta_y := PADDING.y + _time_size.y + 3 + _meta_h draw_string(font, Vector2(PADDING.x, meta_y), _phase_str, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META, _phase_color) - draw_string(font, Vector2(PADDING.x + phase_size.x, meta_y), - day_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META, Constants.IMPLANT_TEXT_DIM) + draw_string(font, Vector2(PADDING.x + _phase_size.x, meta_y), + _day_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE_META, Constants.IMPLANT_TEXT_DIM)