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: int = maxi(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