extends SceneTree const Controller = preload("res://campaign/fg2_graybox_controller.gd") const Fixture = preload("res://campaign/fg2_fixture.gd") const VIEWPORT := Vector2i(844, 390) const EMULATION_SETTING := "input_devices/pointing/emulate_mouse_from_touch" var failures: Array[String] = [] var experience var parsed_touches := 0 var parsed_drags := 0 func _initialize() -> void: call_deferred("run_test") func run_test() -> void: var original_emulation := bool(ProjectSettings.get_setting(EMULATION_SETTING, true)) ProjectSettings.set_setting(EMULATION_SETTING, false) root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND root.content_scale_size = VIEWPORT root.size = VIEWPORT experience = Controller.new() experience.battle_auto_advance = false experience.size = Vector2(VIEWPORT) experience.configure_entry(Fixture.canonical_market_state()) root.add_child(experience) await settle(8) var routes: Array = experience.view.routes var steady_id := String(routes[0].offer_id) var adapt_id := String(routes[1].offer_id) var peril_id := String(routes[2].offer_id) await tap("FG2Route_%s" % adapt_id) expect(experience.selected_route_id == adapt_id, "raw touch selects one route exactly once") await release_outside("FG2Route_%s" % peril_id) expect(experience.selected_route_id == adapt_id, "outside release cannot activate another route") await canceled_touch("FG2Route_%s" % peril_id) expect(experience.selected_route_id == adapt_id, "canceled touch cannot activate another route") var order: Array = Array(experience.adapter.market.state.current_run.deployed_recruit_ids).duplicate() await drag("FG2CompanyTarget_%s" % String(order[-1]), "FG2CompanyTarget_%s" % String(order[0])) expect(Array(experience.adapter.market.state.current_run.deployed_recruit_ids) != order, "raw drag reorders without becoming a button tap") await tap("FG2Route_%s" % steady_id) await tap("FG2DepartButton") expect(experience.screen == Controller.SCREEN_BATTLE, "raw touch commits the selected route") expect(experience.raw_button_activation_count == 3, "three valid releases activate exactly three buttons") expect(experience.input_touch_count == parsed_touches and experience.input_drag_count == parsed_drags, "all commands use parsed ScreenTouch/ScreenDrag") expect(experience.fallback_input_count == 0 and experience.direct_command_count == 0, "Web touch owns no fallback or direct path") ProjectSettings.set_setting(EMULATION_SETTING, original_emulation) experience.queue_free() await settle(60) if failures.is_empty(): print("ABG_FG2_WEB_TOUCH_OK emulate_mouse=false touch=%d drag=%d exact_once=3 outside=true canceled=true route=true reorder=true battle=true fallback=0 direct=0" % [parsed_touches, parsed_drags]) quit(0) else: for failure in failures: push_error(failure) quit(1) func tap(node_name: String) -> void: var control := experience.find_child(node_name, true, false) as Control expect(control != null, "%s exists" % node_name) if control == null: return var point := root.get_final_transform() * control.get_global_rect().get_center() await touch(point, point, false) func release_outside(node_name: String) -> void: var control := experience.find_child(node_name, true, false) as Control expect(control != null, "%s exists for outside release" % node_name) if control == null: return var point := root.get_final_transform() * control.get_global_rect().get_center() await touch(point, Vector2(4, VIEWPORT.y - 4), false) func canceled_touch(node_name: String) -> void: var control := experience.find_child(node_name, true, false) as Control expect(control != null, "%s exists for cancel" % node_name) if control == null: return var point := root.get_final_transform() * control.get_global_rect().get_center() await touch(point, point, true) func touch(press_point: Vector2, release_point: Vector2, canceled: bool) -> void: var down := InputEventScreenTouch.new() down.index = 0 down.position = press_point down.pressed = true Input.parse_input_event(down) parsed_touches += 1 await process_frame var up := InputEventScreenTouch.new() up.index = 0 up.position = release_point up.pressed = false up.canceled = canceled Input.parse_input_event(up) await settle(4) func drag(source_name: String, target_name: String) -> void: var source := experience.find_child(source_name, true, false) as Control var target := experience.find_child(target_name, true, false) as Control expect(source != null and target != null, "drag targets exist") if source == null or target == null: return var start := root.get_final_transform() * source.get_global_rect().get_center() var finish := root.get_final_transform() * target.get_global_rect().get_center() var down := InputEventScreenTouch.new() down.index = 1 down.position = start down.pressed = true Input.parse_input_event(down) parsed_touches += 1 await process_frame var motion := InputEventScreenDrag.new() motion.index = 1 motion.position = finish motion.relative = finish - start Input.parse_input_event(motion) parsed_drags += 1 await process_frame var up := InputEventScreenTouch.new() up.index = 1 up.position = finish up.pressed = false Input.parse_input_event(up) await settle(4) func settle(frames: int) -> void: for _index in range(frames): await process_frame func expect(condition: bool, message: String) -> void: if not condition: failures.append("FG-2 Web touch: %s" % message)