fix(client): address PR #62 review — input guard, public API, geometry cache
- constants.gd: clamp format_game_time input to 0..1439 (Hoshe #2) - interaction_list.gd: add public hide_list() wrapper (Hoshe #3, Tyre #1) - main.gd: call hide_list() instead of private _hide() - time_display.gd: cache font geometry in update_from_state(), use boolean _has_data flag instead of string guard (Tyre #2) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
+34
-19
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user