extends SceneTree var failures: Array[String] = [] func _init() -> void: _run.call_deferred() func _run() -> void: await process_frame _check_resources_load() await _check_runner_upcoming_and_triggered_once() await _check_event_bus_mirroring() _finish() func _check_resources_load() -> void: _expect(load("res://resources/chart_event.gd") != null, "ChartEvent script should load") _expect(load("res://resources/chart_track.gd") != null, "ChartTrack script should load") _expect(load("res://resources/beat_chart.gd") != null, "BeatChart script should load") _expect(load("res://scenes/chart/chart_runner.gd") != null, "ChartRunner script should load") func _make_event(beat: int, event_type: StringName, target_id := &"", lead_beats := 1.0): var event_script: Script = load("res://resources/chart_event.gd") var event: Resource = event_script.new() event.set("beat_index", beat) event.set("event_type", event_type) event.set("target_id", target_id) event.set("lead_beats", lead_beats) return event func _make_chart() -> Resource: var chart_script: Script = load("res://resources/beat_chart.gd") var track_script: Script = load("res://resources/chart_track.gd") var chart: Resource = chart_script.new() var track: Resource = track_script.new() chart.set("chart_id", &"test_chart") track.set("track_id", &"enemy") track.set("track_type", &"enemy") track.set("events", [ _make_event(2, &"enemy_prepare_attack", &"test_enemy", 1.0), _make_event(3, &"enemy_attack_active", &"test_enemy", 1.0), ]) chart.set("tracks", [track]) return chart func _make_runner(chart: Resource) -> Node: var runner_script: Script = load("res://scenes/chart/chart_runner.gd") var runner: Node = runner_script.new() runner.set("beat_time_override", 0.5) runner.call("set_chart", chart) root.add_child(runner) return runner func _check_runner_upcoming_and_triggered_once() -> void: var runner := _make_runner(_make_chart()) var upcoming: Array[StringName] = [] var triggered: Array[StringName] = [] runner.connect("chart_event_upcoming", func(event: Resource, _time_to_event: float) -> void: upcoming.append(StringName(str(event.get("event_type")))) ) runner.connect("chart_event_triggered", func(event: Resource) -> void: triggered.append(StringName(str(event.get("event_type")))) ) runner.call("update_for_song_time", 0.49) _expect(upcoming == [&"enemy_prepare_attack"], "Prepare upcoming should fire at lead window") _expect(triggered.is_empty(), "No event should trigger before event time") runner.call("update_for_song_time", 1.0) runner.call("update_for_song_time", 1.1) _expect(triggered == [&"enemy_prepare_attack"], "Prepare triggered should fire once") runner.call("update_for_song_time", 1.49) runner.call("update_for_song_time", 1.50) runner.call("update_for_song_time", 1.80) _expect(upcoming.count(&"enemy_attack_active") == 1, "Attack upcoming should fire once") _expect(triggered.count(&"enemy_attack_active") == 1, "Attack triggered should fire once") runner.queue_free() await process_frame func _check_event_bus_mirroring() -> void: var bus_script: Script = load("res://autoload/event_bus.gd") var bus := root.get_node_or_null("EventBus") var owns_bus := false if bus == null: bus = bus_script.new() bus.name = "EventBus" root.add_child(bus) owns_bus = true var mirrored_upcoming: Array[Resource] = [] var mirrored_triggered: Array[Resource] = [] bus.connect("chart_event_upcoming", func(_event: Resource, _time_to_event: float) -> void: mirrored_upcoming.append(_event) ) bus.connect("chart_event_triggered", func(_event: Resource) -> void: mirrored_triggered.append(_event) ) var runner := _make_runner(_make_chart()) runner.call("update_for_song_time", 0.49) runner.call("update_for_song_time", 1.0) _expect(mirrored_upcoming.size() == 2, "ChartRunner should mirror upcoming events to EventBus") _expect(mirrored_triggered.size() == 1, "ChartRunner should mirror triggered events to EventBus") runner.queue_free() if owns_bus: bus.queue_free() await process_frame func _expect(condition: bool, label: String) -> void: if not condition: failures.append(label) func _finish() -> void: if failures.is_empty(): print("PASS chart layer") quit(0) else: for failure: String in failures: push_error(failure) quit(1)