40250 classic: increment 50 (Phase 1 W3) — §8.3 in-game help window
Implement the in-game Help window as a 1:1 migration of uihelp.py's HelpWindow (single-page: ENABLE_HELP_MULTIPAGE = 0 -> LoadDialogSinglePage). - project/ui/help_ui.gd (new): loads the real helpwindow.py uiscript via UiScript -> UiBuild; _relabel() resolves the <HELP_*>/<CLOSE> placeholders (produced when UiManager has no locale callback) from the project Locale table (en) with verbatim English fallbacks, covering the original script's two duplicate help_02 rows (right/middle camera). open/close/toggle/is_open; close_button -> close; ESC handled by the UiManager window stack. - project/ui/system_menu_ui.gd: help_button changed from the placeholder toast to close() + open_help(); adds const HelpUI, an injectable help_ui member, _ensure_help() (lazy build, reuses the menu's ui/client/assets_root), open_help(), toggle_help(); setup() gains an optional 6th arg (old 5-arg callers unaffected). - project/game_scene.gd: single elif in _unhandled_input — KEY_H without ctrl/meta -> system_menu_ui.toggle_help() (Ctrl+H stays free for /user_horse_ride). - project/help_ui_test.gd (new): headless SceneTree test — helpwindow.py load, 19 verbatim help rows + taskbar labels bound and non-placeholder, close_button text, rows() helper, close/open/toggle, ESC stack top, SystemMenuUI.open_help() lazy build. Tests: help_ui_test, system_menu_ui_test, gamescene_test, ui_test all PASS (plus system_option_ui_test, char_status_ui_test). No build/ in this worktree so C++ ctest not run (no C++ change). Real-server and visual (.sub textures) not verified. Docs: CLIENT-GAP.md W3 row + increment 50 bullet; CLIENT-GAP-FIX.md §8.3 status/改动/测试/验收 + C.5 batch record. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014yvAPqPivoY7vmBbzgqK4W
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
f32064c74a
commit
d7711ba5f0
@@ -0,0 +1,115 @@
|
||||
# help_ui_test —— §8.3 帮助窗 headless 自检(真 `helpwindow.py` uiscript + 假 client)。
|
||||
# godot --headless --path project --script help_ui_test.gd
|
||||
# 校验:helpwindow.py 装载、19 条帮助行 + 任务栏标签逐字绑定(对齐
|
||||
# `locale/locale/en/locale_interface.txt` 的 `HELP_*`)、close_button、open/close/toggle、
|
||||
# 以及 SystemMenuUI.open_help() 懒建并打开本窗。缺 uiscript 资产时优雅跳过。
|
||||
extends SceneTree
|
||||
|
||||
const UiManager = preload("res://ui/ui_manager.gd")
|
||||
const HelpUI = preload("res://ui/help_ui.gd")
|
||||
const SystemMenuUI = preload("res://ui/system_menu_ui.gd")
|
||||
|
||||
class FakeClient extends Node:
|
||||
func say(_type: int, _text: String) -> bool:
|
||||
return true
|
||||
|
||||
var _fail := 0
|
||||
func _ck(c: bool, m: String) -> void:
|
||||
if not c:
|
||||
_fail += 1
|
||||
printerr("FAIL: " + m)
|
||||
|
||||
func _init() -> void:
|
||||
_run()
|
||||
if _fail == 0:
|
||||
print("PASS: help_ui_test (helpwindow.py + HELP_* rows + close/open/toggle + SystemMenu.open_help)")
|
||||
quit(0)
|
||||
else:
|
||||
printerr("%d check(s) failed" % _fail)
|
||||
quit(1)
|
||||
|
||||
func _txt(hw: Node, nm: String) -> String:
|
||||
var n: Control = hw._node(nm)
|
||||
return String(n.text) if n and ("text" in n) else "<missing:%s>" % nm
|
||||
|
||||
func _run() -> void:
|
||||
var assets := AssetRoot.path()
|
||||
if not FileAccess.file_exists(assets.path_join("uiscript/uiscript/helpwindow.py")):
|
||||
print(" (skip: no helpwindow.py — assets checkout missing)")
|
||||
return
|
||||
|
||||
var ui: CanvasLayer = UiManager.new()
|
||||
get_root().add_child(ui)
|
||||
ui._ready()
|
||||
var fc := FakeClient.new()
|
||||
get_root().add_child(fc)
|
||||
|
||||
var hw: Node = HelpUI.new()
|
||||
get_root().add_child(hw)
|
||||
hw.setup(ui, fc, assets)
|
||||
hw.open()
|
||||
_ck(hw.is_open(), "help window opened")
|
||||
if not hw.is_open():
|
||||
return
|
||||
|
||||
# --- 19 条浮动帮助行都绑定且非占位 ---
|
||||
var bound := 0
|
||||
for i in range(1, 20):
|
||||
var nm := "help_%02d" % i
|
||||
var s := _txt(hw, nm)
|
||||
_ck(not s.begins_with("<missing"), "%s node exists" % nm)
|
||||
_ck(s.strip_edges() != "", "%s non-empty" % nm)
|
||||
_ck(not (s.begins_with("<") and s.ends_with(">")), "%s not a <KEY> placeholder (got %s)" % [nm, s])
|
||||
if not s.strip_edges().is_empty() and not (s.begins_with("<") and s.ends_with(">")):
|
||||
bound += 1
|
||||
_ck(bound == 19, "all 19 help rows bound (got %d)" % bound)
|
||||
|
||||
# --- 逐字对照 locale/locale/en/locale_interface.txt ---
|
||||
_ck(_txt(hw, "help_01") == "Panel: W, A, S, D or arrow keys",
|
||||
"help_01 = HELP_MOVE_KEY (got %s)" % _txt(hw, "help_01"))
|
||||
_ck(_txt(hw, "help_06") == "Attack: left mouse button or space bar",
|
||||
"help_06 = HELP_ATTACK_KEY (got %s)" % _txt(hw, "help_06"))
|
||||
_ck(_txt(hw, "help_02") == "Camera View: middle or right mouse button",
|
||||
"help_02 = HELP_CONTROL_CAMERA_BY_MIDDLEBUTTON (2nd dup wins) (got %s)" % _txt(hw, "help_02"))
|
||||
_ck(_txt(hw, "help_19") == "Display help: H",
|
||||
"help_19 = HELP_HELP (got %s)" % _txt(hw, "help_19"))
|
||||
|
||||
# --- 任务栏贴纸标签 ---
|
||||
_ck(_txt(hw, "taskbar_help_02") == "Hit Points (HP)",
|
||||
"taskbar_help_02 = HELP_HP (got %s)" % _txt(hw, "taskbar_help_02"))
|
||||
_ck(_txt(hw, "taskbar_help_08b") == "(Character Window, Inventory Window,",
|
||||
"taskbar_help_08b = HELP_CHARACTER_BUTTON1 (got %s)" % _txt(hw, "taskbar_help_08b"))
|
||||
|
||||
# --- close_button ---
|
||||
var close_btn: Control = hw._node("close_button")
|
||||
_ck(close_btn is BaseButton, "close_button is a button")
|
||||
_ck(_txt(hw, "close_button") == "Close", "close_button text = Close (got %s)" % _txt(hw, "close_button"))
|
||||
|
||||
# --- rows() 便捷器 ---
|
||||
var rows: Array = hw.rows()
|
||||
_ck(rows.size() == 19, "rows() returns 19 entries (got %d)" % rows.size())
|
||||
var all_nonempty := true
|
||||
for r in rows:
|
||||
if String(r).strip_edges().is_empty():
|
||||
all_nonempty = false
|
||||
_ck(all_nonempty, "rows() all non-empty")
|
||||
|
||||
# --- close_button 关窗 ---
|
||||
close_btn.pressed.emit()
|
||||
_ck(not hw.is_open(), "close_button closes help window")
|
||||
|
||||
# --- open / toggle / ESC 栈 ---
|
||||
hw.toggle()
|
||||
_ck(hw.is_open(), "toggle() re-opens help window")
|
||||
_ck(ui.top() == hw._win.get("root"), "help window is top of UiManager stack (ESC closes it)")
|
||||
hw.toggle()
|
||||
_ck(not hw.is_open(), "toggle() closes help window")
|
||||
|
||||
# --- SystemMenuUI.open_help() 懒建并打开 ---
|
||||
var sm: Node = SystemMenuUI.new()
|
||||
get_root().add_child(sm)
|
||||
sm.setup(ui, fc, assets)
|
||||
sm.open_help()
|
||||
_ck(is_instance_valid(sm.help_ui), "SystemMenuUI.open_help() lazily builds help_ui")
|
||||
_ck(sm.help_ui.is_open(), "SystemMenuUI.open_help() opens the help window")
|
||||
sm.help_ui.close()
|
||||
Reference in New Issue
Block a user