Initial project sync
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
extends SceneTree
|
||||
|
||||
var failures: Array[String] = []
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
_run.call_deferred()
|
||||
|
||||
|
||||
func _run() -> void:
|
||||
# 节奏标记/连击动画基线按 easy 判定窗取值;显式钉住,不依赖残留的 settings.cfg。
|
||||
var settings := root.get_node_or_null("GameSettings")
|
||||
if settings != null:
|
||||
settings.call("set_difficulty", &"easy")
|
||||
var scene: PackedScene = load("res://scenes/ui/main_ui.tscn")
|
||||
if scene == null:
|
||||
push_error("Could not load main_ui.tscn")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
var ui := scene.instantiate()
|
||||
root.add_child(ui)
|
||||
await process_frame
|
||||
|
||||
var track := ui.get_node_or_null("RhythmTrack") as Control
|
||||
if track == null:
|
||||
failures.append("Missing RhythmTrack")
|
||||
_finish(ui)
|
||||
return
|
||||
|
||||
_expect_node(track, "LeftMover", "RhythmTrack should keep the animated left mover")
|
||||
_expect_node(track, "RightMover", "RhythmTrack should keep the animated right mover")
|
||||
_expect_node(track, "CenterFlash", "RhythmTrack should keep the center beat flash")
|
||||
|
||||
var bus := _event_bus()
|
||||
bus.emit_signal("beat_ticked", 1)
|
||||
await process_frame
|
||||
var center_flash := track.get_node_or_null("CenterFlash") as CanvasItem
|
||||
if center_flash != null:
|
||||
# Beat ticks now pulse the flash at BEAT_TICK_FLASH_PEAK (0.35) so full
|
||||
# brightness stays reserved for judged hits; assert visibility, not peak.
|
||||
_expect_bool(center_flash.modulate.a > 0.2, true, "CenterFlash should become visible on beat")
|
||||
|
||||
var marker_container := track.get_node_or_null("ChartMarkerContainer") as Control
|
||||
if marker_container == null:
|
||||
failures.append("RhythmTrack should include ChartMarkerContainer")
|
||||
else:
|
||||
# 谱面预告标记已被有意停用(rhythm_track._on_chart_event_upcoming 为空操作);
|
||||
# 钉住"不再生成标记"的现行为,防止无声复活。
|
||||
var event_script: Script = load("res://resources/chart_event.gd")
|
||||
var event: Resource = event_script.new()
|
||||
event.set("event_type", &"enemy_action")
|
||||
event.set("action_id", &"enemy_slash")
|
||||
bus.emit_signal("chart_event_upcoming", event, 0.5)
|
||||
await process_frame
|
||||
_expect_bool(marker_container.get_child_count() == 0, true, "Chart upcoming events must not spawn markers (feature deliberately disabled)")
|
||||
|
||||
bus.emit_signal("judgement_made", &"perfect", 0.0, 12)
|
||||
await process_frame
|
||||
var label := track.get_node_or_null("JudgementLabel") as Label
|
||||
if label != null:
|
||||
_expect_bool(label.scale.x > 1.0, true, "JudgementLabel should pulse on judgement")
|
||||
_expect_bool(label.modulate.is_equal_approx(Color("00f2ff")), true, "JudgementLabel should use judgement color")
|
||||
|
||||
var combo_window := ui.get_node_or_null("ComboWindow") as Control
|
||||
if combo_window == null:
|
||||
failures.append("Missing ComboWindow")
|
||||
else:
|
||||
bus.emit_signal("combo_updated", [&"A"])
|
||||
await process_frame
|
||||
# 改版后 child(0) 是外框 SlotFrame,真正脉冲的是命名槽位面板 Slot1。
|
||||
var first_slot := combo_window.get_node_or_null("Slot1") as Control
|
||||
if first_slot == null:
|
||||
failures.append("ComboWindow should expose the Slot1 panel")
|
||||
else:
|
||||
_expect_bool(first_slot.scale.x > 1.0, true, "Combo slot should pulse when filled")
|
||||
bus.emit_signal("combo_cleared", &"full")
|
||||
await process_frame
|
||||
_expect_bool(first_slot.scale.x > 1.0, true, "Combo slots should flash when cleared")
|
||||
|
||||
var charge_bar := ui.get_node_or_null("StatusBars/ChargeBar") as ProgressBar
|
||||
if charge_bar == null:
|
||||
failures.append("Missing ChargeBar")
|
||||
else:
|
||||
bus.emit_signal("player_charge_changed", 1.1, 1.1, true, true)
|
||||
await create_timer(0.05).timeout
|
||||
var first_alpha := charge_bar.modulate.a
|
||||
await create_timer(0.05).timeout
|
||||
var second_alpha := charge_bar.modulate.a
|
||||
_expect_bool(not is_equal_approx(first_alpha, second_alpha), true, "ChargeBar should flash while ready")
|
||||
|
||||
_finish(ui)
|
||||
|
||||
|
||||
func _event_bus() -> Node:
|
||||
var bus := root.get_node_or_null("EventBus")
|
||||
if bus == null:
|
||||
bus = load("res://autoload/event_bus.gd").new()
|
||||
bus.name = "EventBus"
|
||||
root.add_child(bus)
|
||||
return bus
|
||||
|
||||
|
||||
func _expect_node(node: Node, path: String, label: String) -> void:
|
||||
if node.get_node_or_null(path) == null:
|
||||
failures.append(label)
|
||||
|
||||
|
||||
func _expect_bool(actual: bool, expected: bool, label: String) -> void:
|
||||
if actual != expected:
|
||||
failures.append("%s: expected %s, got %s" % [label, expected, actual])
|
||||
|
||||
|
||||
func _finish(ui: Node) -> void:
|
||||
ui.free()
|
||||
if failures.is_empty():
|
||||
print("PASS ui animation regression")
|
||||
quit(0)
|
||||
else:
|
||||
for failure: String in failures:
|
||||
push_error(failure)
|
||||
quit(1)
|
||||
Reference in New Issue
Block a user