Indent every script with tabs, like the Godot editor does
This commit is contained in:
1 parent
8c1987807c
commit
bad4b3ad8b
35 files changed
+1653
-1653
No files matched your search
+153
-153
@@ -9,131 +9,131 @@ extends RefCounted
|
||||
## them a node lives in.
|
||||
|
||||
const SOUNDTRACKS: Array[String] = [
|
||||
"Chrono Trigger", "Final Fantasy VI", "Secret of Mana", "Terranigma",
|
||||
"Earthbound", "Super Metroid", "The Legend of Zelda: A Link to the Past",
|
||||
"Donkey Kong Country 2", "Lufia II", "Illusion of Gaia",
|
||||
"Chrono Trigger", "Final Fantasy VI", "Secret of Mana", "Terranigma",
|
||||
"Earthbound", "Super Metroid", "The Legend of Zelda: A Link to the Past",
|
||||
"Donkey Kong Country 2", "Lufia II", "Illusion of Gaia",
|
||||
]
|
||||
const SONG_INFO: Dictionary = {
|
||||
"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time",
|
||||
"SongNo": 0, "Soundtrack": "Chrono Trigger", "Song": "Corridors of Time",
|
||||
}
|
||||
const SYNC_PROGRESS: Dictionary = {"progress": 40, "time_spent": "00:00:02"}
|
||||
const SYNC_RESULT: Dictionary = {
|
||||
"soundtracks_added": ["Terranigma", "Lufia II"],
|
||||
"soundtracks_re_added": [],
|
||||
"soundtracks_changed_title": {"FF6": "Final Fantasy VI"},
|
||||
"soundtracks_changed_content": ["Chrono Trigger"],
|
||||
"soundtracks_removed": ["Old Soundtrack"],
|
||||
"catched_errors": [],
|
||||
"total_time": "00:00:03",
|
||||
"soundtracks_added": ["Terranigma", "Lufia II"],
|
||||
"soundtracks_re_added": [],
|
||||
"soundtracks_changed_title": {"FF6": "Final Fantasy VI"},
|
||||
"soundtracks_changed_content": ["Chrono Trigger"],
|
||||
"soundtracks_removed": ["Old Soundtrack"],
|
||||
"catched_errors": [],
|
||||
"total_time": "00:00:03",
|
||||
}
|
||||
|
||||
## Popups in the order the tour opens them.
|
||||
const POPUPS: Array[String] = [
|
||||
"Search", "SyncWindow", "SettingsWindow", "QRWindow", "NewCharacterSelect",
|
||||
"ShortcutsWindow", "AboutWindow", "WinnerWindow", "Log", "StatisticsPopupPanel",
|
||||
"Search", "SyncWindow", "SettingsWindow", "QRWindow", "NewCharacterSelect",
|
||||
"ShortcutsWindow", "AboutWindow", "WinnerWindow", "Log", "StatisticsPopupPanel",
|
||||
]
|
||||
|
||||
var _main: Control
|
||||
|
||||
|
||||
func _init(main: Control) -> void:
|
||||
_main = main
|
||||
_main = main
|
||||
|
||||
|
||||
## Returns a fake server that answers every request the main window makes on the tour.
|
||||
## Call [method FakeHttpTransport.install] before the main window is created.
|
||||
static func make_server() -> FakeHttpTransport:
|
||||
var server: FakeHttpTransport = FakeHttpTransport.new()
|
||||
var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3")
|
||||
server.respond_json("/music/all", SOUNDTRACKS)
|
||||
server.respond_json("/music/all/order", SOUNDTRACKS)
|
||||
server.respond_json("/music/list", [])
|
||||
server.respond_json("/characters", [])
|
||||
server.respond_bytes("/music/rand", mp3)
|
||||
server.respond_bytes("/music/addQue", PackedByteArray())
|
||||
server.respond_json("/music/info", SONG_INFO)
|
||||
server.respond_bytes("/music/reset", PackedByteArray())
|
||||
server.respond_bytes("/music/played?song=0", PackedByteArray())
|
||||
server.respond_bytes("/sync", PackedByteArray())
|
||||
server.respond_json("/sync/progress", SYNC_PROGRESS)
|
||||
return server
|
||||
var server: FakeHttpTransport = FakeHttpTransport.new()
|
||||
var mp3: PackedByteArray = FileAccess.get_file_as_bytes("res://tests/data/short.mp3")
|
||||
server.respond_json("/music/all", SOUNDTRACKS)
|
||||
server.respond_json("/music/all/order", SOUNDTRACKS)
|
||||
server.respond_json("/music/list", [])
|
||||
server.respond_json("/characters", [])
|
||||
server.respond_bytes("/music/rand", mp3)
|
||||
server.respond_bytes("/music/addQue", PackedByteArray())
|
||||
server.respond_json("/music/info", SONG_INFO)
|
||||
server.respond_bytes("/music/reset", PackedByteArray())
|
||||
server.respond_bytes("/music/played?song=0", PackedByteArray())
|
||||
server.respond_bytes("/sync", PackedByteArray())
|
||||
server.respond_json("/sync/progress", SYNC_PROGRESS)
|
||||
return server
|
||||
|
||||
|
||||
## Puts Settings and Playlist in the state the tour expects. Call it before the main
|
||||
## window is created.
|
||||
static func prepare_autoloads() -> void:
|
||||
Playlist.reset_playlist()
|
||||
Playlist.first_song_played = false
|
||||
Playlist.is_song_downloading = false
|
||||
Settings.player_array.clear()
|
||||
Settings.edit_players = false
|
||||
Settings.currently_syncing = false
|
||||
Settings.character_select_open = false
|
||||
Settings.add_to_stats = true
|
||||
Settings.hide_next_track = true
|
||||
Settings.use_low_played_mode = false
|
||||
Settings.winning_score = 20
|
||||
# The inspiration list scrolls by itself, which would make every picture different
|
||||
Settings.inspiration_list_speed = 0
|
||||
Playlist.reset_playlist()
|
||||
Playlist.first_song_played = false
|
||||
Playlist.is_song_downloading = false
|
||||
Settings.player_array.clear()
|
||||
Settings.edit_players = false
|
||||
Settings.currently_syncing = false
|
||||
Settings.character_select_open = false
|
||||
Settings.add_to_stats = true
|
||||
Settings.hide_next_track = true
|
||||
Settings.use_low_played_mode = false
|
||||
Settings.winning_score = 20
|
||||
# The inspiration list scrolls by itself, which would make every picture different
|
||||
Settings.inspiration_list_speed = 0
|
||||
|
||||
|
||||
## Runs the tour. [param on_state] is called (and awaited) with the name of each state
|
||||
## and the popup that is open in it, or [code]null[/code] when no popup is open.
|
||||
func run(on_state: Callable) -> void:
|
||||
# The debug build lowers the winning score on startup; keep it out of reach
|
||||
Settings.winning_score = 20
|
||||
await _settle()
|
||||
await on_state.call("startup", null)
|
||||
# The debug build lowers the winning score on startup; keep it out of reach
|
||||
Settings.winning_score = 20
|
||||
await _settle()
|
||||
await on_state.call("startup", null)
|
||||
|
||||
_call("add_players")
|
||||
await _settle()
|
||||
await on_state.call("add_player_row", null)
|
||||
_call("add_players")
|
||||
await _settle()
|
||||
await on_state.call("add_player_row", null)
|
||||
|
||||
_add_player("Crono")
|
||||
_add_player("Marle")
|
||||
_call("add_players")
|
||||
await _settle()
|
||||
await on_state.call("players_added", null)
|
||||
_add_player("Crono")
|
||||
_add_player("Marle")
|
||||
_call("add_players")
|
||||
await _settle()
|
||||
await on_state.call("players_added", null)
|
||||
|
||||
_call("play_next_song")
|
||||
await _settle()
|
||||
_freeze_music_player()
|
||||
_player_row(0).add_point()
|
||||
_player_row(0).add_point()
|
||||
_player_row(1).add_point()
|
||||
_call("show_answer_pressed")
|
||||
await _settle()
|
||||
_freeze_music_player()
|
||||
_fix_log_times()
|
||||
await _settle()
|
||||
await on_state.call("playing", null)
|
||||
_call("play_next_song")
|
||||
await _settle()
|
||||
_freeze_music_player()
|
||||
_player_row(0).add_point()
|
||||
_player_row(0).add_point()
|
||||
_player_row(1).add_point()
|
||||
_call("show_answer_pressed")
|
||||
await _settle()
|
||||
_freeze_music_player()
|
||||
_fix_log_times()
|
||||
await _settle()
|
||||
await on_state.call("playing", null)
|
||||
|
||||
for popup_name: String in POPUPS:
|
||||
var popup: Node = await _open_popup(popup_name)
|
||||
await _settle()
|
||||
await on_state.call("popup_" + popup_name, popup)
|
||||
_close_popup(popup)
|
||||
await _settle()
|
||||
for popup_name: String in POPUPS:
|
||||
var popup: Node = await _open_popup(popup_name)
|
||||
await _settle()
|
||||
await on_state.call("popup_" + popup_name, popup)
|
||||
_close_popup(popup)
|
||||
await _settle()
|
||||
|
||||
var sync_window: PopupWindow = _node("SyncWindow")
|
||||
Settings.currently_syncing = false
|
||||
sync_window.has_synced = false
|
||||
sync_window.start_sync()
|
||||
sync_window.sync_timer.stop()
|
||||
sync_window._on_sync_timeout()
|
||||
await _settle()
|
||||
await on_state.call("sync_in_progress", sync_window)
|
||||
sync_window.close()
|
||||
await _settle()
|
||||
await on_state.call("sync_buttons_locked", null)
|
||||
var sync_window: PopupWindow = _node("SyncWindow")
|
||||
Settings.currently_syncing = false
|
||||
sync_window.has_synced = false
|
||||
sync_window.start_sync()
|
||||
sync_window.sync_timer.stop()
|
||||
sync_window._on_sync_timeout()
|
||||
await _settle()
|
||||
await on_state.call("sync_in_progress", sync_window)
|
||||
sync_window.close()
|
||||
await _settle()
|
||||
await on_state.call("sync_buttons_locked", null)
|
||||
|
||||
_server().respond_json("/sync/progress", SYNC_RESULT)
|
||||
sync_window._on_sync_timeout()
|
||||
sync_window.open()
|
||||
await _settle()
|
||||
await on_state.call("sync_result", sync_window)
|
||||
sync_window.close()
|
||||
await _settle()
|
||||
_server().respond_json("/sync/progress", SYNC_RESULT)
|
||||
sync_window._on_sync_timeout()
|
||||
sync_window.open()
|
||||
await _settle()
|
||||
await on_state.call("sync_result", sync_window)
|
||||
sync_window.close()
|
||||
await _settle()
|
||||
|
||||
|
||||
## Returns where every Control and Window in [param subtree] is on screen, keyed by its
|
||||
@@ -141,109 +141,109 @@ func run(on_state: Callable) -> void:
|
||||
## Nodes added at runtime without a name are keyed by their index, e.g. [code]#2[/code],
|
||||
## so the keys are the same on every run.
|
||||
static func dump_layout(main: Node, subtree: Node) -> Dictionary:
|
||||
var layout: Dictionary = {}
|
||||
var path: String = String(main.get_path_to(subtree))
|
||||
_dump_node(subtree, path, layout)
|
||||
return layout
|
||||
var layout: Dictionary = {}
|
||||
var path: String = String(main.get_path_to(subtree))
|
||||
_dump_node(subtree, path, layout)
|
||||
return layout
|
||||
|
||||
|
||||
static func _dump_node(node: Node, path: String, layout: Dictionary) -> void:
|
||||
if node is Control:
|
||||
var rect: Rect2 = (node as Control).get_global_rect()
|
||||
layout[path] = {"rect": _round_rect(rect), "visible": node.is_visible_in_tree()}
|
||||
elif node is Window:
|
||||
var window: Window = node
|
||||
layout[path] = {
|
||||
"rect": _round_rect(Rect2(window.position, window.size)),
|
||||
"visible": window.visible,
|
||||
}
|
||||
for child: Node in node.get_children():
|
||||
var key: String = "#%d" % child.get_index() if "@" in child.name \
|
||||
else String(child.name)
|
||||
_dump_node(child, key if path == "." else path + "/" + key, layout)
|
||||
if node is Control:
|
||||
var rect: Rect2 = (node as Control).get_global_rect()
|
||||
layout[path] = {"rect": _round_rect(rect), "visible": node.is_visible_in_tree()}
|
||||
elif node is Window:
|
||||
var window: Window = node
|
||||
layout[path] = {
|
||||
"rect": _round_rect(Rect2(window.position, window.size)),
|
||||
"visible": window.visible,
|
||||
}
|
||||
for child: Node in node.get_children():
|
||||
var key: String = "#%d" % child.get_index() if "@" in child.name \
|
||||
else String(child.name)
|
||||
_dump_node(child, key if path == "." else path + "/" + key, layout)
|
||||
|
||||
|
||||
static func _round_rect(rect: Rect2) -> Array[float]:
|
||||
return [snappedf(rect.position.x, 0.01), snappedf(rect.position.y, 0.01),
|
||||
snappedf(rect.size.x, 0.01), snappedf(rect.size.y, 0.01)]
|
||||
return [snappedf(rect.position.x, 0.01), snappedf(rect.position.y, 0.01),
|
||||
snappedf(rect.size.x, 0.01), snappedf(rect.size.y, 0.01)]
|
||||
|
||||
|
||||
## Finds a node of the main window by [param node_name], whether it is a direct child
|
||||
## of the main window or of its Quiz or TopBar scene.
|
||||
func _node(node_name: String) -> Node:
|
||||
for parent: Node in [_main, _main.get_node_or_null("Quiz"),
|
||||
_main.get_node_or_null("TopBar")]:
|
||||
if parent != null && parent.has_node(node_name):
|
||||
return parent.get_node(node_name)
|
||||
push_error("UiTour: no node named " + node_name)
|
||||
return null
|
||||
for parent: Node in [_main, _main.get_node_or_null("Quiz"),
|
||||
_main.get_node_or_null("TopBar")]:
|
||||
if parent != null && parent.has_node(node_name):
|
||||
return parent.get_node(node_name)
|
||||
push_error("UiTour: no node named " + node_name)
|
||||
return null
|
||||
|
||||
|
||||
## Calls [param method] on the players panel, the quiz or the main window, whichever
|
||||
## has it first.
|
||||
func _call(method: String, args: Array = []) -> Variant:
|
||||
for path: String in ["Quiz/PlayersPanel", "Quiz"]:
|
||||
var target: Node = _main.get_node_or_null(path)
|
||||
if target != null && target.has_method(method):
|
||||
return target.callv(method, args)
|
||||
return _main.callv(method, args)
|
||||
for path: String in ["Quiz/PlayersPanel", "Quiz"]:
|
||||
var target: Node = _main.get_node_or_null(path)
|
||||
if target != null && target.has_method(method):
|
||||
return target.callv(method, args)
|
||||
return _main.callv(method, args)
|
||||
|
||||
|
||||
func _server() -> FakeHttpTransport:
|
||||
return MusicServerClient.transport
|
||||
return MusicServerClient.transport
|
||||
|
||||
|
||||
func _settle() -> void:
|
||||
for i: int in 4:
|
||||
await _main.get_tree().process_frame
|
||||
for i: int in 4:
|
||||
await _main.get_tree().process_frame
|
||||
|
||||
|
||||
func _add_player(player_name: String) -> void:
|
||||
(_node("PlayersPanel").get_node("VBoxContainer/AddPlayerContainer/PlayerNameField") \
|
||||
as TextEdit).text = player_name
|
||||
_call("add_player")
|
||||
(_node("PlayersPanel").get_node("VBoxContainer/AddPlayerContainer/PlayerNameField") \
|
||||
as TextEdit).text = player_name
|
||||
_call("add_player")
|
||||
|
||||
|
||||
func _player_row(index: int) -> Player:
|
||||
return _node("PlayersPanel").get_node(
|
||||
"VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_child(index)
|
||||
return _node("PlayersPanel").get_node(
|
||||
"VBoxContainer/ScrollContainer/PlayersListVBoxContainer").get_child(index)
|
||||
|
||||
|
||||
## Stops the song so the time and progress bar look the same on every run.
|
||||
func _freeze_music_player() -> void:
|
||||
var music_player: MusicPlayer = _node("MusicPlayer")
|
||||
music_player.audio_player.stop()
|
||||
music_player.sound_player.stop()
|
||||
music_player.progress_slider.value = 0
|
||||
music_player.music_time_label.text = "00:00 / 00:01"
|
||||
var music_player: MusicPlayer = _node("MusicPlayer")
|
||||
music_player.audio_player.stop()
|
||||
music_player.sound_player.stop()
|
||||
music_player.progress_slider.value = 0
|
||||
music_player.music_time_label.text = "00:00 / 00:01"
|
||||
|
||||
|
||||
## The log starts each row with the time of day; use a fixed time instead.
|
||||
func _fix_log_times() -> void:
|
||||
var log_window: PopupWindow = _node("Log")
|
||||
for row: Label in log_window.log_box.get_children():
|
||||
row.text = "12:00:00 " + row.text.substr(9)
|
||||
var log_window: PopupWindow = _node("Log")
|
||||
for row: Label in log_window.log_box.get_children():
|
||||
row.text = "12:00:00 " + row.text.substr(9)
|
||||
|
||||
|
||||
func _open_popup(popup_name: String) -> Node:
|
||||
var popup: Node = _node(popup_name)
|
||||
match popup_name:
|
||||
"SyncWindow":
|
||||
# Opening the window starts a sync; show the empty window instead
|
||||
popup.open()
|
||||
"NewCharacterSelect":
|
||||
popup.show_grid("Crono")
|
||||
"WinnerWindow":
|
||||
popup.show_winner(Settings.player_array[0])
|
||||
"StatisticsPopupPanel":
|
||||
_call("get_statistics")
|
||||
_:
|
||||
popup.open()
|
||||
return popup
|
||||
var popup: Node = _node(popup_name)
|
||||
match popup_name:
|
||||
"SyncWindow":
|
||||
# Opening the window starts a sync; show the empty window instead
|
||||
popup.open()
|
||||
"NewCharacterSelect":
|
||||
popup.show_grid("Crono")
|
||||
"WinnerWindow":
|
||||
popup.show_winner(Settings.player_array[0])
|
||||
"StatisticsPopupPanel":
|
||||
_call("get_statistics")
|
||||
_:
|
||||
popup.open()
|
||||
return popup
|
||||
|
||||
|
||||
func _close_popup(popup: Node) -> void:
|
||||
if popup is PopupWindow:
|
||||
popup.close()
|
||||
else:
|
||||
popup.visible = false
|
||||
if popup is PopupWindow:
|
||||
popup.close()
|
||||
else:
|
||||
popup.visible = false
|
||||
Reference in new issue
Block a user