Files
mtgodot-poc/project/system_option_ui_test.gd

132 lines
5.4 KiB
GDScript

# system_option_ui_test —— P11 系统设置窗 headless 自检(真 uiscript + 假 audio/cam/env)。
# godot --headless --path project --script system_option_ui_test.gd
# 校验 systemoptiondialog.py 装载、音量 / 镜头 / 雾控件绑定(对照 uisystemoption.py)、
# 持久化到 user://system_option.cfg。缺 uiscript 资产时优雅跳过。
extends SceneTree
const SystemOptionUI = preload("res://ui/system_option_ui.gd")
class FakeAudio extends Node:
var master_bgm := 0.6
var master_sfx := 0.9
var _bgm := [null, null]
var _bgm_cur := 0
class FakeCam extends Node:
var max_dist := 20.0
var dist := 18.0
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: system_option_ui_test (layout + volume/camera/fog bind + cfg persist)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)
func _cfg_path() -> String:
return ProjectSettings.globalize_path(SystemOptionUI.config_path())
func _run() -> void:
var assets := AssetRoot.path()
if not FileAccess.file_exists(assets.path_join("uiscript/uiscript/systemoptiondialog.py")):
print(" (skip: no systemoptiondialog.py — assets checkout missing)")
return
# 干净起步
if FileAccess.file_exists(_cfg_path()):
DirAccess.remove_absolute(_cfg_path())
var UiManager = load("res://ui/ui_manager.gd")
var ui: CanvasLayer = UiManager.new()
get_root().add_child(ui)
ui._ready()
var au := FakeAudio.new()
var cam := FakeCam.new()
get_root().add_child(au)
get_root().add_child(cam)
var env := Environment.new()
var so: Node = SystemOptionUI.new()
get_root().add_child(so)
so.setup(ui, assets, au, func(): return cam, func(): return env)
so.open()
_ck(so.is_open(), "system-option window opened")
if not so.is_open():
return
# --- 音量 sliderbar → snd.SetMusicVolume / SetSoundVolume ---
var mv: Control = so._node("music_volume_controller")
var sv: Control = so._node("sound_volume_controller")
_ck(mv is Range and sv is Range, "volume controllers are Range sliders")
_ck(is_equal_approx(mv.min_value, 0.0) and is_equal_approx(mv.max_value, 1.0),
"music slider range set to 0..1")
_ck(mv.value_changed.is_connected(so._on_music_volume), "music slider wired to _on_music_volume")
_ck(sv.value_changed.is_connected(so._on_sound_volume), "sound slider wired to _on_sound_volume")
so._on_music_volume(0.30) # = 拖动 music_volume_controller
_ck(is_equal_approx(au.master_bgm, 0.30), "music slider -> audio.master_bgm (got %s)" % au.master_bgm)
so._on_sound_volume(0.75)
_ck(is_equal_approx(au.master_sfx, 0.75), "sound slider -> audio.master_sfx (got %s)" % au.master_sfx)
# --- 镜头 근/원 radio → max_dist ---
(so._node("camera_short") as BaseButton).pressed.emit()
_ck(so.camera_mode == 0, "camera_short -> mode 0")
_ck(is_equal_approx(cam.max_dist, SystemOptionUI.CAMERA_MAX[0]), "camera short -> cam.max_dist=%s" % cam.max_dist)
_ck(cam.dist <= cam.max_dist, "camera dist clamped to new max")
(so._node("camera_long") as BaseButton).pressed.emit()
_ck(so.camera_mode == 1 and is_equal_approx(cam.max_dist, SystemOptionUI.CAMERA_MAX[1]), "camera_long -> mode 1 / far max")
# 라디오 배타성
_ck(not (so._node("camera_short") as BaseButton).button_pressed, "camera_short unset after camera_long")
# --- 안개 0/1/2 radio → Environment.fog_density ---
(so._node("fog_level0") as BaseButton).pressed.emit()
_ck(so.fog_level == 0 and env.fog_enabled
and is_equal_approx(env.fog_density, SystemOptionUI.FOG_DENSITY[0]),
"fog_level0 (dense) -> env.fog_density=%s" % env.fog_density)
(so._node("fog_level2") as BaseButton).pressed.emit()
_ck(so.fog_level == 2 and is_equal_approx(env.fog_density, SystemOptionUI.FOG_DENSITY[2]),
"fog_level2 (light) -> env.fog_density=%s" % env.fog_density)
# --- 持久화: user://system_option.cfg ---
_ck(FileAccess.file_exists(_cfg_path()), "cfg written")
var cfg := ConfigFile.new()
cfg.load(_cfg_path())
_ck(is_equal_approx(float(cfg.get_value("audio", "music_volume", -1.0)), 0.30), "cfg music_volume persisted")
_ck(int(cfg.get_value("video", "fog_level", -1)) == 2, "cfg fog_level persisted")
_ck(int(cfg.get_value("video", "camera_mode", -1)) == 1, "cfg camera_mode persisted")
so.close()
_ck(not so.is_open(), "system-option window closed")
# 移动端专用横屏设置页:滑杆与单选项不依赖 PC 固定坐标小控件。
ui.set_mobile_mode(true)
so.set_mobile_mode(true)
so.open()
_ck(so.is_open() and so._mobile_root.size == Vector2(680, 340),
"mobile system-option window uses landscape base size")
_ck(so._mobile_root.find_children("*", "HSlider", true, false).size() == 2,
"mobile system-option exposes music and sound sliders")
so.close()
# --- 두 번째 인스턴스가 cfg 를 읽어 즉시 적용 ---
var au2 := FakeAudio.new()
var cam2 := FakeCam.new()
get_root().add_child(au2)
get_root().add_child(cam2)
var env2 := Environment.new()
var so2: Node = SystemOptionUI.new()
get_root().add_child(so2)
so2.setup(ui, assets, au2, func(): return cam2, func(): return env2)
_ck(is_equal_approx(au2.master_bgm, 0.30), "reload: cfg music_volume applied on setup")
_ck(is_equal_approx(cam2.max_dist, SystemOptionUI.CAMERA_MAX[1]), "reload: cfg camera_mode applied")
_ck(is_equal_approx(env2.fog_density, SystemOptionUI.FOG_DENSITY[2]), "reload: cfg fog_level applied")
if FileAccess.file_exists(_cfg_path()):
DirAccess.remove_absolute(_cfg_path())