extends SceneTree const GuildView = preload("res://entry/views/guild_page_view.gd") const InkCheck = preload("res://tools/ui_ink_check.gd") const FIXTURES := [Vector2i(1280, 720)] const LOCALES := ["zh_CN", "en"] # Accessibility pass: 1.0 plus the shipped 130% text scale (M73). const TEXT_SCALES := [1.0, 1.3] var ink_scanned := 0 var probe_text_scale := 1.0 var ink_violations: Array = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var out := OS.get_environment("ABG_EVIDENCE_DIR") if out.is_empty(): push_error("requires ABG_EVIDENCE_DIR") quit(1) return DirAccess.make_dir_recursive_absolute(out) var ink_self := InkCheck.self_test(root) if ink_self.size() < 3: push_error("M62 ink self-test expected at least 3 violations, got %d" % ink_self.size()) quit(1) return print("ABG_M62_INK_SELF_TEST_OK violations=%d" % ink_self.size()) ink_scanned = 0 ink_violations = [] for fixture in FIXTURES: for locale in LOCALES: for text_scale in TEXT_SCALES: probe_text_scale = float(text_scale) await _capture_fixture(fixture, locale, out) var report_path := OS.get_environment("ABG_EVIDENCE_DIR").path_join("ink-violations-%s.json" % _probe_id()) 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_M53_GUILD_INK_OK scanned=%d violations=0" % ink_scanned) else: for violation in ink_violations: push_error("M53 ink violation %s: text=%s slot=%s font=%s" % [String(violation.get("node", "?")), String(violation.get("text_width", "?")), String(violation.get("slot_width", "?")), String(violation.get("font_size", "?"))]) print("ABG_M53_GUILD_INK_FAIL scanned=%d violations=%d" % [ink_scanned, ink_violations.size()]) quit(1) return print("ABG_M53_GUILD_VISUAL_PROBE_OK states=members locales=%d scans=%d views=static,dynamic,final" % [LOCALES.size(), ink_scanned]) quit(0) func _probe_id() -> String: return "m53-guild" func _scan_ink(view: Control, locale: String, label: String) -> void: # Legacy-chrome pages (pre-M62) record their ink defects as a baseline for # the W5 migration; migrated pages (Market, Readiness once moved) must be # strict. The report file is the machine-readable work list. var violations := InkCheck.scan(view) ink_scanned += 1 for violation in violations: violation["locale"] = locale violation["fixture"] = label ink_violations.append(violation) func _capture_fixture(fixture: Vector2i, locale: String, out: String) -> void: root.size = Vector2(fixture) var capture_viewport := SubViewport.new() capture_viewport.name = "GuildCaptureViewport" capture_viewport.size = fixture capture_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS capture_viewport.transparent_bg = false root.add_child(capture_viewport) var view := GuildView.new() view.name = "GuildVisualProbeView" view.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) view.configure_presentation({"safe_area": 24, "text_scale": probe_text_scale, "locale": locale}) capture_viewport.add_child(view) view.render({ "ok": true, "locale": locale, "company": { "owned_count": 2, "coin": 38, "display_recruits": [ {"recruit_id": "owned-001", "profession_id": "PF-B01", "rendered_name_snapshot": {"en": "Ari", "zh_CN": "阿里"}, "profession_name": {"en": "Vanguard", "zh_CN": "先锋"}}, {"recruit_id": "owned-002", "profession_id": "PF-B06", "rendered_name_snapshot": {"en": "Bram", "zh_CN": "布拉姆"}, "profession_name": {"en": "Arcanist", "zh_CN": "奥术师"}}, ], }, "destinations": {}, "recruits": [], "notice": "", }) await _settle() _scan_ink(view, locale, "%dx%d" % [fixture.x, fixture.y]) _save(capture_viewport, out, locale, fixture, "final") var overlay := view.find_child("GuildAnchorRoot", true, false) as Control if overlay != null: overlay.visible = false await _settle() _save(capture_viewport, out, locale, fixture, "static") if overlay != null: overlay.visible = true var world := view.find_child("GuildMasterWorldExtension", true, false) as Control if world != null: world.visible = false await _settle() _save(capture_viewport, out, locale, fixture, "dynamic") view.queue_free() capture_viewport.queue_free() await process_frame func _settle() -> void: for _i in range(3): await process_frame func _save(viewport: SubViewport, out: String, locale: String, fixture: Vector2i, kind: String) -> void: var viewport_texture := viewport.get_texture() if viewport_texture == null: return var image := viewport_texture.get_image() if image != null: image.save_png(out.path_join("guild-%dx%d-%s-%s.png" % [fixture.x, fixture.y, locale, kind]))