feat(ui): F3 debug overlay — real-time game state display (#511)
Toggle with F3. Shows tick, fps, position, facing, stance, zone, entity/tile counts, interaction/recognition counts, dialogue status, stationary ticks, insert state, time/tick_rate, mode, gauntlet. Two-column layout, click-through, hidden by default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,11 @@ bug_report={
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194343,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
debug_overlay={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194334,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
]
|
||||
}
|
||||
teleport_hub={
|
||||
"deadzone": 0.5,
|
||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194317,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
extends Control
|
||||
# #511: F3 debug overlay — real-time game state display for dev use.
|
||||
|
||||
const HEADER_COLOR := Color("#e8c547")
|
||||
const LABEL_COLOR := Color("#8890a0")
|
||||
const VALUE_COLOR := Color("#c8d0e0")
|
||||
const BG_COLOR := Color(0.08, 0.08, 0.12, 0.85)
|
||||
const FONT_SIZE := 12
|
||||
const LINE_HEIGHT := 16
|
||||
const PADDING := Vector2(10, 8)
|
||||
const COL_GAP := 16 # gap between left and right columns
|
||||
|
||||
var _cached_font: Font = null
|
||||
|
||||
func _ready() -> void:
|
||||
visible = false
|
||||
_cached_font = ThemeDB.fallback_font
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("debug_overlay"):
|
||||
visible = not visible
|
||||
if visible:
|
||||
queue_redraw()
|
||||
|
||||
func update_from_state() -> void:
|
||||
if not visible:
|
||||
return
|
||||
queue_redraw()
|
||||
|
||||
func _draw() -> void:
|
||||
if not visible:
|
||||
return
|
||||
var font: Font = _cached_font if _cached_font else ThemeDB.fallback_font
|
||||
|
||||
# Build lines as [label, value, label, value] pairs (two columns)
|
||||
var left_lines: Array = []
|
||||
var right_lines: Array = []
|
||||
|
||||
left_lines.append(["tick", str(GameState.current_tick)])
|
||||
right_lines.append(["fps", str(Engine.get_frames_per_second())])
|
||||
|
||||
var pos := GameState.player_position
|
||||
left_lines.append(["pos", "(%d, %d)" % [int(pos.x), int(pos.y)]])
|
||||
right_lines.append(["facing", GameState.player_facing])
|
||||
|
||||
left_lines.append(["stance", GameState.player_stance])
|
||||
right_lines.append(["zone", GameState.current_zone_id if GameState.current_zone_id != "" else "-"])
|
||||
|
||||
left_lines.append(["entities", str(GameState.visible_entities.size())])
|
||||
right_lines.append(["tiles", str(GameState.visible_tiles.size())])
|
||||
|
||||
left_lines.append(["interactions", str(GameState.nearby_interactions.size())])
|
||||
right_lines.append(["recognitions", str(GameState.pending_recognitions.size())])
|
||||
|
||||
var mono_status := "active" if GameState.current_monologue != null else "idle"
|
||||
var dlg_status := "active" if GameState.dialogue_active else "idle"
|
||||
left_lines.append(["monologue", mono_status])
|
||||
right_lines.append(["dialogue", dlg_status])
|
||||
|
||||
left_lines.append(["stationary", str(GameState.stationary_ticks)])
|
||||
right_lines.append(["insert", "ON" if GameState.insert_active else "OFF"])
|
||||
|
||||
var gt := GameState.game_time
|
||||
var time_str := "%s d%s" % [gt.get("day_phase", "-"), str(gt.get("day", "-"))] if gt.size() > 0 else "-"
|
||||
var rate_str: String = gt.get("tick_rate", "-") if gt.size() > 0 else "-"
|
||||
left_lines.append(["time", time_str])
|
||||
right_lines.append(["tick_rate", rate_str])
|
||||
|
||||
var mode_str := "test" if SimBridge.test_mode else "live"
|
||||
var gauntlet_str := "ON" if GameState.gauntlet_mode else "OFF"
|
||||
left_lines.append(["mode", mode_str])
|
||||
right_lines.append(["gauntlet", gauntlet_str])
|
||||
|
||||
# Measure column widths
|
||||
var left_label_w: float = 0.0
|
||||
var left_value_w: float = 0.0
|
||||
var right_label_w: float = 0.0
|
||||
var right_value_w: float = 0.0
|
||||
|
||||
for line in left_lines:
|
||||
left_label_w = max(left_label_w, font.get_string_size(line[0] + ": ", HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE).x)
|
||||
left_value_w = max(left_value_w, font.get_string_size(line[1], HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE).x)
|
||||
for line in right_lines:
|
||||
right_label_w = max(right_label_w, font.get_string_size(line[0] + ": ", HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE).x)
|
||||
right_value_w = max(right_value_w, font.get_string_size(line[1], HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE).x)
|
||||
|
||||
var header_text := "F3 DEBUG"
|
||||
var header_w := font.get_string_size(header_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE + 1).x
|
||||
var content_w := left_label_w + left_value_w + COL_GAP + right_label_w + right_value_w
|
||||
var box_w: float = max(header_w, content_w) + PADDING.x * 2
|
||||
var line_count := max(left_lines.size(), right_lines.size())
|
||||
var box_h: float = PADDING.y * 2 + LINE_HEIGHT + LINE_HEIGHT * line_count # header + data lines
|
||||
|
||||
# Background
|
||||
draw_rect(Rect2(Vector2.ZERO, Vector2(box_w, box_h)), BG_COLOR)
|
||||
|
||||
# Header
|
||||
var y: float = PADDING.y + FONT_SIZE
|
||||
draw_string(font, Vector2(PADDING.x, y), header_text, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE + 1, HEADER_COLOR)
|
||||
y += LINE_HEIGHT
|
||||
|
||||
# Data lines (two columns)
|
||||
var right_x: float = PADDING.x + left_label_w + left_value_w + COL_GAP
|
||||
for i in range(line_count):
|
||||
if i < left_lines.size():
|
||||
var lbl: String = left_lines[i][0] + ": "
|
||||
var val: String = left_lines[i][1]
|
||||
draw_string(font, Vector2(PADDING.x, y), lbl, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE, LABEL_COLOR)
|
||||
draw_string(font, Vector2(PADDING.x + left_label_w, y), val, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE, VALUE_COLOR)
|
||||
if i < right_lines.size():
|
||||
var lbl: String = right_lines[i][0] + ": "
|
||||
var val: String = right_lines[i][1]
|
||||
draw_string(font, Vector2(right_x, y), lbl, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE, LABEL_COLOR)
|
||||
draw_string(font, Vector2(right_x + right_label_w, y), val, HORIZONTAL_ALIGNMENT_LEFT, -1, FONT_SIZE, VALUE_COLOR)
|
||||
y += LINE_HEIGHT
|
||||
Reference in New Issue
Block a user