175 lines
6.5 KiB
GDScript
175 lines
6.5 KiB
GDScript
extends SceneTree
|
|
|
|
## M63 entry-page visual probe (W5/DEV-1R). It captures the migrated entry
|
|
## states at the shipped fixtures with the runtime content, the chrome-only
|
|
## static view and the content-only dynamic view on a neutral field, and it
|
|
## runs the shared ink checker on every build. Boot is strict from M63-A; the
|
|
## later entry pages join this probe as they migrate.
|
|
|
|
const EntryShell = preload("res://entry/entry_shell.gd")
|
|
const SettingsStore = preload("res://entry/settings_store.gd")
|
|
const InkCheck = preload("res://tools/ui_ink_check.gd")
|
|
|
|
const SIZES := [Vector2i(760, 360), Vector2i(844, 390), Vector2i(1280, 720)]
|
|
const LOCALES := ["zh_CN", "en"]
|
|
const STATES := ["running", "error"]
|
|
|
|
var output_root := ""
|
|
var ink_scanned := 0
|
|
var ink_violations: Array = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("_run")
|
|
|
|
|
|
func _run() -> void:
|
|
output_root = OS.get_environment("ABG_EVIDENCE_DIR")
|
|
if output_root.is_empty():
|
|
push_error("M63 entry probe requires the owned test-attempt runner")
|
|
quit(1)
|
|
return
|
|
DirAccess.make_dir_recursive_absolute(output_root)
|
|
var self_test := InkCheck.self_test(root)
|
|
if self_test.size() < 3:
|
|
push_error("M63 ink self-test expected at least 3 violations, got %d" % self_test.size())
|
|
quit(1)
|
|
return
|
|
print("ABG_M63_INK_SELF_TEST_OK violations=%d" % self_test.size())
|
|
for size in SIZES:
|
|
for locale in LOCALES:
|
|
for state in STATES:
|
|
await _capture_boot(size, locale, state)
|
|
await _capture_setup(size, locale)
|
|
var report_path := output_root.path_join("ink-violations-m63-entry.json")
|
|
var file := FileAccess.open(report_path, FileAccess.WRITE)
|
|
if file != null:
|
|
file.store_string(JSON.stringify(ink_violations, " "))
|
|
file.close()
|
|
if ink_violations.is_empty():
|
|
print("ABG_M63_ENTRY_INK_OK scanned=%d violations=0" % ink_scanned)
|
|
else:
|
|
for violation in ink_violations:
|
|
push_error("M63 ink violation %s %s: %s" % [violation.node, violation.kind, violation.detail])
|
|
print("ABG_M63_ENTRY_INK_FAIL scanned=%d violations=%d" % [ink_scanned, ink_violations.size()])
|
|
quit(1)
|
|
return
|
|
print("ABG_M63_ENTRY_VISUAL_PROBE_OK sizes=3 locales=2 pages=boot,setup states=running,error views=static,dynamic,final")
|
|
quit(0)
|
|
|
|
|
|
func _capture_boot(size: Vector2i, locale: String, state: String) -> void:
|
|
var viewport := SubViewport.new()
|
|
viewport.size = size
|
|
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
|
root.add_child(viewport)
|
|
var shell := EntryShell.new()
|
|
shell.auto_start = false
|
|
viewport.add_child(shell)
|
|
await _frames(3)
|
|
shell.settings = SettingsStore.new().defaults()
|
|
shell.settings.locale = locale
|
|
shell.settings.text_scale = 1.0
|
|
shell.boot_snapshot = (
|
|
{"state": "error", "completed": 2, "total": 4, "step": "preferences", "code": "SETTINGS_FILE_INVALID"}
|
|
if state == "error"
|
|
else {"state": "running", "completed": 2, "total": 4, "step": "preferences", "code": ""}
|
|
)
|
|
shell._render_boot_state()
|
|
await _frames(4)
|
|
_scan_ink(shell, locale, "%dx%d-%s" % [size.x, size.y, state])
|
|
await _save(viewport, "boot-%dx%d-%s-%s" % [size.x, size.y, locale, state], "final")
|
|
# static: chrome only, runtime copy hidden.
|
|
for node_name in ["BootIdentity", "BootStatus", "BootDetail", "BootProgressValue", "BootDiagnostics"]:
|
|
var control := shell.find_child(node_name, true, false) as CanvasItem
|
|
if control != null:
|
|
control.visible = false
|
|
await _frames(2)
|
|
await _save(viewport, "boot-%dx%d-%s-%s" % [size.x, size.y, locale, state], "static")
|
|
for node_name in ["BootIdentity", "BootStatus", "BootDetail", "BootProgressValue", "BootDiagnostics"]:
|
|
var control := shell.find_child(node_name, true, false) as CanvasItem
|
|
if control != null:
|
|
control.visible = true
|
|
# dynamic: content only on a neutral field (world hidden).
|
|
var world := shell.find_child("BootWorld", true, false) as CanvasItem
|
|
var shade := shell.find_child("BootWorldShade", true, false) as CanvasItem
|
|
if world != null:
|
|
world.visible = false
|
|
if shade != null:
|
|
shade.visible = false
|
|
var neutral := ColorRect.new()
|
|
neutral.name = "M63NeutralField"
|
|
neutral.color = Color("#5b6165")
|
|
neutral.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
|
neutral.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
|
shell.add_child(neutral)
|
|
shell.move_child(neutral, 0)
|
|
await _frames(2)
|
|
await _save(viewport, "boot-%dx%d-%s-%s" % [size.x, size.y, locale, state], "dynamic")
|
|
viewport.queue_free()
|
|
await process_frame
|
|
|
|
|
|
func _capture_setup(size: Vector2i, locale: String) -> void:
|
|
var viewport := SubViewport.new()
|
|
viewport.size = size
|
|
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
|
root.add_child(viewport)
|
|
var shell := EntryShell.new()
|
|
shell.auto_start = false
|
|
viewport.add_child(shell)
|
|
await _frames(3)
|
|
shell.settings = SettingsStore.new().defaults()
|
|
shell.settings.locale = locale
|
|
shell.settings.text_scale = 1.0
|
|
shell.size = Vector2(size)
|
|
shell.show_first_launch()
|
|
await _frames(5)
|
|
# The shell lays out on resize; drive it once for the offscreen capture.
|
|
shell._layout_first_launch()
|
|
shell._refresh_first_launch_labels()
|
|
await _frames(3)
|
|
_scan_ink(shell, locale, "setup-%dx%d" % [size.x, size.y])
|
|
await _save(viewport, "setup-%dx%d-%s" % [size.x, size.y, locale], "final")
|
|
for node_name in ["FirstLaunchHeading", "FirstLaunchSubheading", "FirstLaunchPreviewHeading", "SetupPreviewTitle", "SetupPreviewDetail"]:
|
|
var control := shell.find_child(node_name, true, false) as CanvasItem
|
|
if control != null:
|
|
control.visible = false
|
|
for row_name in ["SetupLanguage", "SetupSafeArea", "SetupTextScale", "SetupReducedMotion", "SetupReducedFlashes", "SetupCaptions"]:
|
|
var row := shell.find_child(row_name, true, false) as Control
|
|
if row != null:
|
|
var label := row.get_node_or_null("RowLabel") as CanvasItem
|
|
var value := row.get_node_or_null("ValuePlate") as CanvasItem
|
|
if label != null:
|
|
label.visible = false
|
|
if value != null:
|
|
value.visible = false
|
|
await _frames(2)
|
|
await _save(viewport, "setup-%dx%d-%s" % [size.x, size.y, locale], "static")
|
|
viewport.queue_free()
|
|
await process_frame
|
|
|
|
|
|
func _scan_ink(view: Control, locale: String, label: String) -> void:
|
|
var violations := InkCheck.scan(view)
|
|
ink_scanned += 1
|
|
for violation in violations:
|
|
violation["locale"] = locale
|
|
violation["fixture"] = label
|
|
ink_violations.append(violation)
|
|
|
|
|
|
func _save(viewport: SubViewport, stem: String, mode: String) -> void:
|
|
await RenderingServer.frame_post_draw
|
|
var texture := viewport.get_texture()
|
|
if texture == null:
|
|
return
|
|
var image := texture.get_image()
|
|
if image != null and not image.is_empty():
|
|
image.save_png(output_root.path_join("%s-%s.png" % [stem, mode]))
|
|
|
|
|
|
func _frames(count: int) -> void:
|
|
for _index in count:
|
|
await process_frame
|