From 23f2ed11eb1279d5591d18ec27c236f992f45cea Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 27 Dec 2024 20:35:28 +0100 Subject: [PATCH] Updated how players and song list works Made many changes with caching, how players works, added sound effects and animations any many more things --- MainWindow.gd | 383 +++++++++++++++++++----------------- MainWindow.tscn | 60 +++--- MusicPlayer.gd | 72 ++++--- MusicPlayer.tscn | 8 + Player.gd | 134 ++++--------- PlayerObject.gd | 43 +++- Settings.gd | 54 +++-- SettingsWindow.gd | 3 + SongObject.gd | 39 +++- default_theme.tres | 6 + export_presets.cfg | 2 +- song_list_object.gd | 50 +++++ song_list_object.tscn | 65 ++++++ sounds/itemequip.wav | Bin 0 -> 6342 bytes sounds/itemequip.wav.import | 24 +++ sounds/itemopen.wav | Bin 0 -> 29604 bytes sounds/itemopen.wav.import | 24 +++ style_box_flat.tres | 4 + 18 files changed, 612 insertions(+), 359 deletions(-) create mode 100644 default_theme.tres create mode 100644 song_list_object.gd create mode 100644 song_list_object.tscn create mode 100644 sounds/itemequip.wav create mode 100644 sounds/itemequip.wav.import create mode 100644 sounds/itemopen.wav create mode 100644 sounds/itemopen.wav.import create mode 100644 style_box_flat.tres diff --git a/MainWindow.gd b/MainWindow.gd index e063342..37f53a5 100644 --- a/MainWindow.gd +++ b/MainWindow.gd @@ -91,7 +91,7 @@ var music_list_scroll: ScrollContainer = $MusicListPanel/ScrollContainer var music_list: VBoxContainer = $MusicListPanel/ScrollContainer/MusicList @onready -var players: VBoxContainer = $Players/VBoxContainer +var player_container: VBoxContainer = $Players/VBoxContainer @onready var character_select: Control = $CharacterSelect @@ -120,6 +120,9 @@ var winner_popup: PopupPanel = $WinnerPopupPanel @onready var winner_label: Label = $WinnerPopupPanel/WinnerLabel +@onready +var winner_picture: TextureRect = $WinnerPopupPanel/WinnerPicture + @onready var auto_repeat_song_button: CheckButton = $RepeatSongCheckButton @@ -127,27 +130,26 @@ var auto_repeat_song_button: CheckButton = $RepeatSongCheckButton var music_player_container: PanelContainer = $MusicPlayer var player := preload("res://Player.tscn") +var song_list_object := preload("res://song_list_object.tscn") var songs: Array= [] var games: Array = [] -var song_list: Array = [] -var next_label: Label var current_player: Node # Called when the node enters the scene tree for the first time. func _ready() -> void: var is_debug: bool = OS.has_feature("debug") - - #var is_mac := OS.has_feature("macos") + var is_mac: bool = OS.has_feature("macos") if is_debug: print("is_debug") ##Settings.default_path = "http://localhost:8080" ##Settings.selected_server = 3 - Settings.default_path = "http://localhost:8080" - Settings.selected_server = 3 - #if is_mac: - # print("is_mac") - next_button.pressed.connect(next_track) + Settings.default_path = "http://localhost:8080" + Settings.selected_server = 3 + Settings.winning_score = 5 + if is_mac: + print("is_mac") + next_button.pressed.connect(fetch_song.bind(false)) show_answer_button.pressed.connect(show_answer_pressed) search_button.pressed.connect(show_search) sync_button.pressed.connect(sync_games) @@ -160,8 +162,8 @@ func _ready() -> void: character_select.connect("character_selected", _on_character_selected) new_player_name_field.connect("enter_key_pressed", add_player) - music_player_container.connect("add_to_queue", _on_add_to_queue) - music_player_container.connect("show_answer", show_answer_pressed) + music_player_container.connect("play_next_song", fetch_song.bind(false)) + music_player_container.connect("update_song_list", update_song_list) add_players_button.pressed.connect(add_players) add_player_button.pressed.connect(add_player) @@ -169,7 +171,8 @@ func _ready() -> void: auto_repeat_song_button.pressed.connect(repeat_song) get_suggestion_list() - fetch_full_music_list_at_start() + fetch_song_list_at_start() + fetch_song(true) func _input(event: InputEvent) -> void: if event is InputEventKey and event.pressed: @@ -199,21 +202,127 @@ func _input(event: InputEvent) -> void: func repeat_song() -> void: Settings.auto_repeat_song = !Settings.auto_repeat_song -func next_track() -> void: - next_button.disabled = true - music_player_container.pause() - music_player_container.fetch_next_song() +func show_answer_pressed() -> void: + print("show_answer_pressed") + print("show_answer_pressed song_object: ", Settings.song_object_array[Settings.latest_played_song]._to_string()) + Settings.song_object_array[Settings.latest_played_song].is_answered = true + update_song_list() + +func fetch_song_list_at_start() -> void: + print("fetch_song_list_at_start") + var fetch_song_list_at_start_done: Callable = func fetch_songs_at_start_done(data) -> void: + Settings.song_object_array = [] + if data == null: + Settings.latest_played_song = Settings.song_object_array.size() + update_song_list() + return + if typeof(data) == TYPE_ARRAY: + for d in data: + var new_song_object: SongObject = SongObject.new() + new_song_object.song_number = d.SongNo + new_song_object.game_title = d.Game + new_song_object.song_title = d.Song + new_song_object.is_answered = true + new_song_object.has_played = true + Settings.song_object_array.append(new_song_object) + else: + print("Unexpected data") + Settings.latest_played_song = Settings.song_object_array.size() + update_song_list() + Settings.make_request2("/music/list", fetch_song_list_at_start_done, true) + +#not first "/music/addPlayed" +#"/music/rand" +#"/music/addQue" +#"/music/info" +func fetch_song(first_time: bool) -> void: + print("fetch_song") + if !first_time: + if Settings.song_object_array[Settings.latest_played_song].has_played && !Settings.song_object_array[Settings.latest_played_song].is_answered: + Settings.song_object_array[Settings.latest_played_song].is_answered = true + Settings.latest_played_song = Settings.song_object_array.size() - 1 + music_player_container.play_song_object(Settings.latest_played_song) + if Settings.add_to_stats : + print("add to stats") + Settings.make_request3("/music/addPlayed") + + next_button.disabled = true + + var url: String = "" + if Settings.use_low_played_mode: + url = "/music/rand/low" + else: + url = "/music/rand" + var new_song_object: SongObject = SongObject.new() + var fetch_song_done: Callable = func fetch_song_done(body: PackedByteArray) -> void: + print("fetch_song_done") + var sound: AudioStream = AudioStreamMP3.new() + sound.data = body + new_song_object.song = sound + + var added_to_que_done: Callable = func added_to_que_done() -> void: + print("added_to_que_done") + var fetch_song_info_done: Callable = func fetch_song_info_done(data_received: Dictionary) -> void: + print("fetch_song_info_done") + new_song_object.song_number = data_received.SongNo + new_song_object.game_title = data_received.Game + new_song_object.song_title = data_received.Song + + print("new_song_object: ", new_song_object.to_string()) + Settings.song_object_array.append(new_song_object) + next_button.disabled = false + Settings.make_request2("/music/info", fetch_song_info_done, true) + + Settings.make_request2("/music/addQue", added_to_que_done, false) + + Settings.make_request2(url, fetch_song_done, true) + +func update_song_list() -> void: + print("update_song_list") + if Settings.currently_playing_song >= 0: + game_label.text = Settings.song_object_array[Settings.currently_playing_song].get_game_title() + song_label.text = Settings.song_object_array[Settings.currently_playing_song].get_song_title() + Settings.delete_children(music_list) + for s: SongObject in Settings.song_object_array: + if !s.has_played: + return + var new_song_list_object: SongListObject = song_list_object.instantiate() + new_song_list_object.song_object = s + new_song_list_object.gui_input.connect(song_object_clicked.bind(s.song_number)) + music_list.add_child(new_song_list_object) + +func song_object_clicked(event: InputEvent, song_no: int) -> void: + if (event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT): + print("Clicked Song Object: ", Settings.song_object_array[song_no].to_string()) + if Settings.song_object_array[song_no].song == null: + print("has no song, need to download") + var song_downloaded: Callable = func song_downloaded(body: PackedByteArray) -> void: + var sound: AudioStream = AudioStreamMP3.new() + sound.data = body + Settings.song_object_array[song_no].song = sound + music_player_container.play_song_object(song_no) + + Settings.make_request2("/music?song=" + str(song_no), song_downloaded, true) + else: + print("song already downloaded") + music_player_container.play_song_object(song_no) func reset_playlist() -> void: print("reset_playlist") - Settings.make_request2("/music/reset", fetch_full_music_list_at_start, false) + var playlist_reset_done: Callable = func playlist_reset_done() -> void: + Settings.currently_playing_song = -1 + Settings.latest_played_song = 0 + Settings.song_object_array.clear() + fetch_song_list_at_start() + fetch_song(true) + + Settings.make_request2("/music/reset", playlist_reset_done, false) func reset_points() -> void: print("reset_points") - var players_to_reset: Array = players.get_children() - for player_to_reset: Node in players_to_reset: - if player_to_reset.has_method("reset_points"): - player_to_reset.reset_points() + for player_objects: PlayerObject in Settings.player_array: + player_objects.reset_points() + load_players() func show_about() -> void: print("show_about") @@ -232,13 +341,6 @@ func get_statistics() -> void: statistic_popup.visible = true statistic_label.text = "Total amount of games in the playlist: " + str(games.size()) -func _on_add_to_queue() -> void: - print("_on_add_to_queue") - next_button.disabled = false - Settings.make_request2("/music/addQue", fetched, false) - game_label.text = "????????" - song_label.text = "??????" - func sync_games() -> void: print("sync_games") sync_button.disabled = true @@ -249,14 +351,24 @@ func sync_games() -> void: reset_playlist() get_suggestion_list() search_view.get_list_of_games() + + var new_games_synced: Callable = func new_games_synced(synced) -> void: + sync_button.disabled = false + sync_popup.visible = true + print("games_synced") + print("synced: ", synced) + reset_playlist() + get_suggestion_list() + search_view.get_list_of_games() + if Settings.quick_sync == true: - Settings.make_request2("/sync/quick", games_synced, false) + Settings.make_request2("/sync/new", new_games_synced, true) else: - Settings.make_request2("/sync", games_synced, false) + Settings.make_request2("/sync/quick", games_synced, false) func get_suggestion_list() -> void: print("get_suggestion_list") - var populate_list: Callable = func(array) -> void: + var populate_list: Callable = func populate_list(array) -> void: if typeof(array) == TYPE_ARRAY: games = [] games.append_array(array) @@ -274,162 +386,73 @@ func get_suggestion_list() -> void: func add_players() -> void: print("add_players") + Settings.edit_players = !Settings.edit_players add_player_container.visible = !add_player_container.visible new_player_name_field.grab_focus() func add_player() -> void: print("add_player") - var new_player: Node = player.instantiate() - new_player.player_name = new_player_name_field.text - new_player.player_score = new_player_name_field.text + ": 0" - new_player.id = Settings.get_next_player_id() + var new_player_object: PlayerObject = PlayerObject.new(new_player_name_field.text, Settings.player_array.size()) new_player_name_field.text = "" - players.add_child(new_player) - new_player.connect("change_character_clicked", _on_player_change_character_clicked.bind(new_player)) - new_player.connect("first_point_triggerd", music_player_container._on_point_triggered.bind("first")) - new_player.connect("match_point_triggerd", music_player_container._on_point_triggered.bind("match")) - new_player.connect("winner_triggerd", _on_player_won.bind(new_player.player_name)) - new_player.connect("player_removed", _on_player_removed.bind(new_player)) + Settings.player_array.append(new_player_object) + new_player_object.connect("first_point_triggerd", music_player_container._on_point_triggered.bind("first")) + new_player_object.connect("match_point_triggerd", music_player_container._on_point_triggered.bind("match")) + new_player_object.connect("winner_triggerd", _on_player_won.bind(new_player_object.id)) + new_player_object.connect("point_given_sound", _on_make_point_given_sound) + new_player_object.connect("player_point_given", _on_point_given.bind(new_player_object.id)) + new_player_object.connect("player_point_taken", _on_point_taken.bind(new_player_object.id)) + load_players() -func _on_player_won(player_name: String) -> void: +func load_players() -> void: + print("load_players") + Settings.delete_player_children(player_container) + var counter: int = 0 + for player_object: PlayerObject in Settings.player_array: + print(player_object.player_name) + + var new_player: Player = player.instantiate() + new_player.id = counter + + new_player.connect("change_character_clicked", _on_player_change_character_clicked.bind(new_player)) + new_player.connect("player_removed", _on_player_removed.bind(counter)) + + player_container.add_child(new_player) + counter += 1 + +func _on_point_given(player_given_point: int) -> void: + print("_on_point_given") + if Settings.currently_playing_song >= 0: + Settings.song_object_array[Settings.currently_playing_song].add_point(player_given_point) + update_song_list() + +func _on_make_point_given_sound() -> void: + music_player_container.play_sound_effect(preload("res://sounds/itemopen.wav")) + +func _on_point_taken(player_taken_point: int) -> void: + print("_on_point_taken") + music_player_container.play_sound_effect(preload("res://sounds/itemequip.wav")) + if Settings.currently_playing_song >= 0: + Settings.song_object_array[Settings.currently_playing_song].remove_point(player_taken_point) + update_song_list() + +func _on_player_won(winning_player_id: int) -> void: print("_on_player_won") winner_popup.visible = true - winner_label.text = player_name + " won!!" + winner_label.text = Settings.player_array[winning_player_id].player_name + " won!!" + winner_picture.custom_minimum_size = Vector2(80, 40) + winner_picture.ignore_texture_size = true + winner_picture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT + winner_picture.texture = Settings.player_array[winning_player_id].character music_player_container.play_sound(preload("res://sounds/winning.mp3")) -func show_search() -> void: - print("show_search") - if search_view.visible == false: - search_view.visible = true - else: - search_view.visible = false - -func show_answer_pressed() -> void: - print("show_answer_pressed") - var show_fetched: Callable = func(data_received: Dictionary) -> void: - print("show_fetched data_received: ", data_received) - game_label.text = data_received.Game - song_label.text = data_received.Song - var format_string: String = "%d. %s - %s" - var actual_string: String = format_string % [(data_received.SongNo+1), data_received.Game, data_received.Song] - if next_label == null: - next_label = Label.new() - next_label.set_texture_filter(TextureFilter.TEXTURE_FILTER_NEAREST) - next_label.add_theme_font_size_override("font_size", 20) - next_label.text = actual_string - Settings.make_request2("/music/info", show_fetched, true) - -func fetch_full_music_list_at_start() -> void: - print("fetch_full_music_list_at_start") - var show_music_list_at_start: Callable = func(data) -> void: - if data == null: - song_list = [] - Settings.delete_children(music_list) - return - if typeof(data) == TYPE_ARRAY: - song_list = [] - song_list.append_array(data) - print("song_list", song_list) - for song: Dictionary in song_list: - var music_list_label: Label = Label.new() - music_list_label.set_texture_filter(TextureFilter.TEXTURE_FILTER_NEAREST) - music_list_label.add_theme_font_size_override("font_size", 20) - music_list_label.autowrap_mode = TextServer.AUTOWRAP_WORD - var format_string: String = "%d. %s - %s" - var actual_string: String = format_string % [(song.SongNo+1), song.Game, song.Song] - music_list_label.text = actual_string - music_list_label.mouse_filter = Control.MOUSE_FILTER_PASS - music_list_label.gui_input.connect(song_clicked.bind(music_list_label, song.SongNo)) - music_list.add_child(music_list_label) - else: - print("Unexpected data") - Settings.make_request2("/music/list", show_music_list_at_start, true) +func _on_player_removed(player_to_remove: int) -> void: + print("_on_player_removed ", player_to_remove) + Settings.player_array.remove_at(player_to_remove) + load_players() -func fetch_full_music_list(event: InputEvent, song_no: int) -> void: - print("fetch_full_music_list") - if (event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT): - var show_music_list: Callable = func(data_received) -> void: - if typeof(data_received) == TYPE_ARRAY: - song_list = [] - song_list.append_array(data_received) - Settings.delete_children(music_list) - for song: Dictionary in song_list: - var music_label: Label= Label.new() - music_label.set_texture_filter(TextureFilter.TEXTURE_FILTER_NEAREST) - music_label.add_theme_font_size_override("font_size", 20) - music_label.autowrap_mode = TextServer.AUTOWRAP_WORD - game_label.text = song.Game - song_label.text = song.Song - var format_string: String = "%d. %s - %s" - var actual_string: String = format_string % [(song.SongNo+1), song.Game, song.Song] - music_label.text = actual_string - music_label.mouse_filter = Control.MOUSE_FILTER_PASS - music_label.gui_input.connect(song_clicked.bind(music_label, song.SongNo)) - print(str(music_list.get_child_count()) + " | " + str(song_list.size() - 1)) - if music_list.get_child_count() == song_list.size() - 1: - music_label.add_theme_color_override("font_color", Color(1, 0.5, 0)) - music_list.add_child(music_label) - else: - print("Unexpected data") - Settings.make_request2("/music/list", show_music_list, true) - Settings.make_request2("/music?song=" + str(song_no), music_player_container.play_song, true) - Settings.make_request2("/music/info", show_answer, true) - -func show_answer(answer: Dictionary) -> void: - print("show_answer1: ", answer) - game_label.text = answer.Game - song_label.text = answer.Song - -func fetched() -> void: - print("fetched") - var show_fetched_list: Callable = func(data_received) -> void: - if typeof(data_received) == TYPE_ARRAY: - song_list = [] - song_list.append_array(data_received) - Settings.delete_children(music_list) - song_list.remove_at(song_list.size() - 1) - for song: Dictionary in song_list: - var fetched_song_label: Label = Label.new() - fetched_song_label.set_texture_filter(TextureFilter.TEXTURE_FILTER_NEAREST) - fetched_song_label.add_theme_font_size_override("font_size", 20) - fetched_song_label.autowrap_mode = TextServer.AUTOWRAP_WORD - var format_string: String = "%d. %s - %s" - var actual_string: String = format_string % [(song.SongNo+1), song.Game, song.Song] - fetched_song_label.text = actual_string - fetched_song_label.mouse_filter = Control.MOUSE_FILTER_PASS - fetched_song_label.gui_input.connect(song_clicked.bind(fetched_song_label, song.SongNo)) - music_list.add_child(fetched_song_label) - - songs = music_list.get_children() - for song: Label in songs: - song.remove_theme_color_override("font_color") - next_label = Label.new() - next_label.set_texture_filter(TextureFilter.TEXTURE_FILTER_NEAREST) - next_label.add_theme_font_size_override("font_size", 20) - next_label.add_theme_color_override("font_color", Color(1, 0.5, 0)) - next_label.text = "??? - ???" - next_label.mouse_filter = Control.MOUSE_FILTER_PASS - next_label.gui_input.connect(fetch_full_music_list.bind(songs.size())) - music_list.add_child(next_label) - else: - print("Unexpected data") - Settings.make_request2("/music/list", show_fetched_list, true) - -func song_clicked(event: InputEvent, clicked_song_label: Label, song_no: int) -> void: - print("song_clicked") - if (event is InputEventMouseButton && event.pressed && event.button_index == MOUSE_BUTTON_LEFT): - print("Song Clicked: " + str(song_no)) - songs = music_list.get_children() - for song: Label in songs: - song.remove_theme_color_override("font_color") - clicked_song_label.add_theme_color_override("font_color", Color(1, 0.5, 0)) - Settings.make_request2("/music?song=" + str(song_no), music_player_container.play_song, true) - Settings.make_request2("/music/info", show_answer, true) - -func _on_player_removed(new_player: Node) -> void: - print("_on_player_removed") - Settings.player_removed() - players.remove_child(new_player) + for song_list_object: SongObject in Settings.song_object_array: + Settings.song_object_array[song_list_object.song_number].players_given_point.remove_at(Settings.song_object_array[song_list_object.song_number].players_given_point.find(player_to_remove)) + update_song_list() func _on_player_change_character_clicked(new_player: Node) -> void: print("_on_player_change_character_clicked") @@ -441,6 +464,14 @@ func _on_character_selected(file_name: String) -> void: character_select.visible = false current_player._on_control_character_selected_clicked(file_name) +func show_search() -> void: + print("show_search") + if search_view.visible == false: + search_view.visible = true + else: + search_view.visible = false + + ###Local var local_path: String = '/Users/sebastian/ResilioSync/Sorterat_test/Metal Gear Solid 4 - Guns of the Patriots/2-16 Metal Gear Saga.mp3' diff --git a/MainWindow.tscn b/MainWindow.tscn index bca8396..182a06d 100644 --- a/MainWindow.tscn +++ b/MainWindow.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=25 format=3 uid="uid://xwq863o6uvsu"] +[gd_scene load_steps=26 format=3 uid="uid://xwq863o6uvsu"] [ext_resource type="Script" path="res://MainWindow.gd" id="1_eu0t5"] [ext_resource type="PackedScene" uid="uid://b16on0oscg1bv" path="res://CharacterSelect.tscn" id="2_76kf4"] @@ -9,6 +9,7 @@ [ext_resource type="Script" path="res://PlayerNameField.gd" id="7_qsdfy"] [ext_resource type="Theme" uid="uid://rxexo3ur85as" path="res://LightGrayTheme.tres" id="7_wxbv6"] [ext_resource type="PackedScene" uid="uid://bxydgil1yifps" path="res://SearchWindow.tscn" id="9_5ijvr"] +[ext_resource type="Texture2D" uid="uid://r4as0nmtoa7p" path="res://noCharacter.png" id="11_1qef0"] [ext_resource type="PackedScene" uid="uid://dldpeo5y3l5hq" path="res://SettingsWindow.tscn" id="11_k62u5"] [sub_resource type="LabelSettings" id="LabelSettings_ychxr"] @@ -103,6 +104,26 @@ file_mode = 2 access = 2 show_hidden_files = true +[node name="MusicListPanel" type="PanelContainer" parent="."] +layout_mode = 0 +offset_left = 64.0 +offset_top = 384.0 +offset_right = 1152.0 +offset_bottom = 896.0 +theme = ExtResource("7_wxbv6") + +[node name="ScrollContainer" type="ScrollContainer" parent="MusicListPanel"] +layout_mode = 2 +follow_focus = true +script = ExtResource("7_dj026") + +[node name="MusicList" type="VBoxContainer" parent="MusicListPanel/ScrollContainer"] +texture_filter = 1 +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +theme_override_constants/separation = 10 + [node name="ScrollContainer" type="ScrollContainer" parent="."] texture_filter = 1 layout_mode = 0 @@ -297,25 +318,6 @@ action_mode = 0 shortcut = SubResource("Shortcut_d6fml") text = "Randomize new track" -[node name="MusicListPanel" type="PanelContainer" parent="."] -layout_mode = 0 -offset_left = 64.0 -offset_top = 384.0 -offset_right = 1152.0 -offset_bottom = 896.0 -theme = ExtResource("7_wxbv6") - -[node name="ScrollContainer" type="ScrollContainer" parent="MusicListPanel"] -layout_mode = 2 -follow_focus = true -script = ExtResource("7_dj026") - -[node name="MusicList" type="VBoxContainer" parent="MusicListPanel/ScrollContainer"] -texture_filter = 1 -layout_mode = 2 -size_flags_horizontal = 3 -size_flags_vertical = 3 - [node name="SearchButton" type="Button" parent="."] texture_filter = 1 layout_mode = 0 @@ -408,7 +410,7 @@ vertical_alignment = 1 [node name="AboutPopupPanel" type="PopupPanel" parent="."] initial_position = 2 -size = Vector2i(848, 272) +size = Vector2i(848, 710) [node name="VBoxContainer" type="VBoxContainer" parent="AboutPopupPanel"] offset_left = 4.0 @@ -479,17 +481,27 @@ offset_bottom = 354.0 [node name="WinnerPopupPanel" type="PopupPanel" parent="."] initial_position = 2 -size = Vector2i(350, 100) +size = Vector2i(600, 350) + +[node name="WinnerPicture" type="TextureRect" parent="WinnerPopupPanel"] +offset_left = 4.0 +offset_top = 4.0 +offset_right = 596.0 +offset_bottom = 346.0 +texture = ExtResource("11_1qef0") +expand_mode = 2 +stretch_mode = 4 [node name="WinnerLabel" type="Label" parent="WinnerPopupPanel"] texture_filter = 1 offset_left = 4.0 offset_top = 4.0 -offset_right = 346.0 -offset_bottom = 96.0 +offset_right = 596.0 +offset_bottom = 346.0 text = "Sansan won!!" label_settings = SubResource("LabelSettings_hr75l") horizontal_alignment = 1 +vertical_alignment = 2 [node name="RepeatSongCheckButton" type="CheckButton" parent="."] layout_mode = 0 diff --git a/MusicPlayer.gd b/MusicPlayer.gd index cbdd39d..f2ac383 100644 --- a/MusicPlayer.gd +++ b/MusicPlayer.gd @@ -13,6 +13,12 @@ var restart_button: TextureButton = $MusicPlayerContainer/RestartTextureButton @onready var audio_player: AudioStreamPlayer = $AudioStreamPlayer +@onready +var sound_player: AudioStreamPlayer = $AudioSoundPlayer + +@onready +var sound_effect_player: AudioStreamPlayer = $AudioSoundEffectPlayer + @onready var progress_slider: HSlider = $MusicPlayerContainer/MusicPlayerSlider @@ -35,10 +41,8 @@ var playback_position: float var stream: AudioStream var song_finished: bool = false -signal fetched -signal winner(player_name: String) -signal add_to_queue -signal show_answer +signal update_song_list +signal play_next_song # Called when the node enters the scene tree for the first time. func _ready() -> void: @@ -98,7 +102,7 @@ func _on_finished() -> void: play_button.texture_normal = play_icon song_finished = true if !Settings.stop_after_current: - fetch_next_song() + play_next_song.emit() if Settings.auto_repeat_song: restart() @@ -133,59 +137,53 @@ func _on_point_triggered(point: String) -> void: elif point == "match": play_sound(preload("res://sounds/sound0.mp3")) +func play_sound_effect(sound_effect_name: AudioStream) -> void: + sound_effect_player.stream = sound_effect_name + sound_effect_player.play() + func play_sound(sound_name: AudioStream) -> void: - audio_player.stream = sound_name - audio_player.play() - song_finished = false - play_button.texture_normal = pause_icon - stream = audio_player.stream - progress_slider.max_value = round(stream.get_length()) - progress_slider.tick_count = round(stream.get_length() / 60) + sound_player.stream = sound_name + audio_player.stop() + sound_player.play() + song_finished = true + play_button.texture_normal = play_icon + progress_slider.value = 0 + if stream != null: + music_time_label.text = format_text(progress_slider.value, stream.get_length()) func play_song(body: PackedByteArray) -> void: var sound: AudioStream = AudioStreamMP3.new() sound.data = body audio_player.stream = sound audio_player.play() + sound_player.stop() song_finished = false play_button.texture_normal = pause_icon stream = audio_player.stream progress_slider.max_value = round(stream.get_length()) - progress_slider.tick_count = round(stream.get_length() / 60) + progress_slider.tick_count = round(stream.get_length() / 60) -func song_fetched(body: PackedByteArray) -> void: +func play_song_object(song_object_no: int) -> void: + print("play_song_object") if audio_player.is_playing(): audio_player.stop() - await get_tree().create_timer(1.0).timeout - print("song_fetched") - var sound: AudioStream = AudioStreamMP3.new() - sound.data = body - print("play given song") - audio_player.stream = sound + await get_tree().create_timer(0.5).timeout + audio_player.stream = Settings.song_object_array[song_object_no].song + sound_player.stop() audio_player.play() song_finished = false play_button.texture_normal = pause_icon stream = audio_player.stream progress_slider.max_value = round(stream.get_length()) progress_slider.tick_count = round(stream.get_length() / 60) - add_to_queue.emit() - if Settings.add_to_stats: - print("add to stats") - Settings.make_request3("/music/addPlayed") + Settings.currently_playing_song = song_object_no + Settings.unset_is_playing() if !Settings.hide_next_track: - show_answer.emit() - -func fetch_next_song() -> void: - #if audio_player.is_playing(): - # audio_player.stop() - # await get_tree().create_timer(1.0).timeout - print("fetch_next_song") - var url: String = "" - if Settings.use_low_played_mode: - url = "/music/rand/low" - else: - url = "/music/rand" - Settings.make_request2(url, song_fetched, true) + print("Show answer now!!") + Settings.song_object_array[song_object_no].is_answered = true + Settings.song_object_array[song_object_no].has_played = true + Settings.song_object_array[song_object_no].is_playing = true + update_song_list.emit() func get_sound_test_song() -> void: Settings.make_request2("/music/soundTest", play_song, true) diff --git a/MusicPlayer.tscn b/MusicPlayer.tscn index 1e389d8..938dd47 100644 --- a/MusicPlayer.tscn +++ b/MusicPlayer.tscn @@ -45,6 +45,14 @@ script = ExtResource("1_t24ra") stream = ExtResource("2_xti80") bus = &"music" +[node name="AudioSoundPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource("2_xti80") +bus = &"music" + +[node name="AudioSoundEffectPlayer" type="AudioStreamPlayer" parent="."] +stream = ExtResource("2_xti80") +bus = &"music" + [node name="MusicPlayerContainer" type="HBoxContainer" parent="."] layout_mode = 2 size_flags_vertical = 4 diff --git a/Player.gd b/Player.gd index f61a729..2d20b37 100644 --- a/Player.gd +++ b/Player.gd @@ -5,10 +5,10 @@ extends Control var player_name_field := $HBoxContainer/Name @onready -var add := $HBoxContainer/AddPoint +var add_button := $HBoxContainer/AddPoint @onready -var minus := $HBoxContainer/RemovePoint +var minus_button := $HBoxContainer/RemovePoint @onready var character := $HBoxContainer/Character @@ -17,119 +17,55 @@ var character := $HBoxContainer/Character var remove_player := $HBoxContainer/RemovePlayer signal change_character_clicked -signal first_point_triggerd -signal match_point_triggerd -signal winner_triggerd signal player_removed -@export -var player_name: String - -@export -var player_score: String - @export var id: int -var is_first_point: bool = true - # Called when the node enters the scene tree for the first time. func _ready() -> void: - add.pressed.connect(add_point) - minus.pressed.connect(minus_point) + add_button.pressed.connect(add_point) + add_button.set_shortcut(create_button_shortcut(id, false)) + minus_button.pressed.connect(minus_point) + minus_button.set_shortcut(create_button_shortcut(id, true)) character.pressed.connect(change_character) - remove_player.pressed.connect(func(): player_removed.emit()) - player_name_field.text = player_score + remove_player.pressed.connect(func() -> void: player_removed.emit()) + update_score() + set_player_character() -func _input(event: InputEvent) -> void: - if event is InputEventKey and event.pressed: - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_1: - check_player(1, false) - elif event.alt_pressed && event.keycode == KEY_1: - check_player(1, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_2: - check_player(2, false) - elif event.alt_pressed && event.keycode == KEY_2: - check_player(2, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_3: - check_player(3, false) - elif event.alt_pressed && event.keycode == KEY_3: - check_player(3, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_4: - check_player(4, false) - elif event.alt_pressed && event.keycode == KEY_4: - check_player(4, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_5: - check_player(5, false) - elif event.alt_pressed && event.keycode == KEY_5: - check_player(5, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_6: - check_player(6, false) - elif event.alt_pressed && event.keycode == KEY_6: - check_player(6, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_7: - check_player(7, false) - elif event.alt_pressed && event.keycode == KEY_7: - check_player(7, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_8: - check_player(8, false) - elif event.alt_pressed && event.keycode == KEY_8: - check_player(8, true) - if event.alt_pressed && event.ctrl_pressed && event.keycode == KEY_9: - check_player(9, false) - elif event.alt_pressed && event.keycode == KEY_9: - check_player(9, true) +func _process(delta: float) -> void: + remove_player.visible = Settings.edit_players -func check_player(pressed: int, add: bool): - if (id == pressed): - print("Player " + str(id) + " pressed") - if add: - add_point() - else: - minus_point() +func create_button_shortcut(scancode : int, ctrl_pressed: bool) -> Shortcut: + var button_shortcut: Shortcut = Shortcut.new() + var button_event : InputEventKey = InputEventKey.new() + button_event.keycode = scancode + 49 + button_event.alt_pressed = true + button_event.ctrl_pressed = ctrl_pressed + button_shortcut.events.append(button_event) + return button_shortcut -func add_point(): - if is_first_point: - is_first_point = false - first_point_triggerd.emit() +func add_point() -> void: + Settings.player_array[id].add_point() + update_score() - var new_value := get_point() + 1 - set_point(new_value) - - if new_value == Settings.winning_score - 1: - match_point_triggerd.emit() - - if new_value == Settings.winning_score: - winner_triggerd.emit() - -func minus_point(): - var new_value := get_point() - 1 - set_point(new_value) - - if new_value == 0: - is_first_point = true - -func reset_points(): - var new_value := 0 - set_point(new_value) - is_first_point = true - -func change_character(): +func minus_point() -> void: + Settings.player_array[id].minus_point() + update_score() + +func change_character() -> void: change_character_clicked.emit() -func _on_control_character_selected_clicked(file_name: String): +func _on_control_character_selected_clicked(file_name: String) -> void: print("Back in player list with: " + file_name) - - var texture = load("res://characters/" + file_name) + Settings.player_array[id].character = load("res://characters/" + file_name) + set_player_character() + +func set_player_character() -> void: character.custom_minimum_size = Vector2(80, 40) character.ignore_texture_size = true character.stretch_mode = TextureButton.STRETCH_KEEP_ASPECT - character.texture_normal = texture + character.texture_normal = Settings.player_array[id].character -func get_point() -> int: - var arr = player_name_field.text.split(":") - return arr[1].to_int() - -func set_point(new_point: int): - var arr = player_name_field.text.split(":") - player_name_field.text = arr[0] + ": " + str(new_point) +func update_score() -> void: + player_name_field.text = str(Settings.player_array[id].id) + " " + Settings.player_array[id].player_name + ": " + str(Settings.player_array[id].player_score) diff --git a/PlayerObject.gd b/PlayerObject.gd index 403ab15..1996a0d 100644 --- a/PlayerObject.gd +++ b/PlayerObject.gd @@ -1,5 +1,12 @@ extends Node +class_name PlayerObject +signal first_point_triggerd +signal match_point_triggerd +signal winner_triggerd +signal point_given_sound +signal player_point_given +signal player_point_taken @export var id: int @@ -8,6 +15,38 @@ var id: int var player_name: String @export -var player_score: String +var player_score: int -var character: Texture +var is_first_point: bool = true + +var character: Texture = load("res://noCharacter.png") + +func _init(new_name: String, new_id: int): + player_name = new_name + id = new_id + player_score = 0 + +func add_point() -> void: + if player_score < Settings.winning_score: + player_score += 1 + player_point_given.emit() + if player_score == 1 && is_first_point: + is_first_point = false + first_point_triggerd.emit() + elif player_score == Settings.winning_score - 1: + match_point_triggerd.emit() + elif player_score == Settings.winning_score: + winner_triggerd.emit() + else: + point_given_sound.emit() + +func minus_point() -> void: + if player_score > 0: + player_score -= 1 + player_point_taken.emit() + if player_score == 0: + is_first_point = true + +func reset_points() -> void: + player_score = 0 + is_first_point = true diff --git a/Settings.gd b/Settings.gd index 1f79b85..d84d344 100644 --- a/Settings.gd +++ b/Settings.gd @@ -17,11 +17,16 @@ var fullscreen: bool = false var quick_sync: bool = true var play_local: bool = false -var number_of_players: int = 0 +var player_array: Array[PlayerObject] +var song_object_array: Array[SongObject] = [] +var latest_played_song: int = 0 +var currently_playing_song: int = -1 +var edit_players: bool = false -var version: String = "0.9.0-Beta" +var version: String = "1.5.0" var whats_new: String = "Changelog: +1.5.0: Made big changes to players and the song list and how the local song list works 0.9.0-Beta: Fixed settings and updated the player view 0.8.0-Beta: Fixed reset buttons and some other small things 0.7.8-Beta: Added shortcuts. Added dialog for winner. Started cleaning code. @@ -41,26 +46,20 @@ Alt + Z = Reset Alt + X = Play/Pause Alt + C = Next Song Alt + V = Show Answer -Alt + Enter = Fullscreen" - -#play = X -#nästa = c -#visa svar = v -#lägga till poäng? 1, 2, 3, 4, 5, 6 - -func get_next_player_id() -> int: - number_of_players += 1 - return number_of_players - -func player_removed() -> void: - number_of_players -= 1 +Alt + Enter = Fullscreen +Alt + UP = Volume up +Alt + DOWN = Volume down +Alt + LEFT = Jump back in song +Alt + Ctrl = Restart song +Alt + RIGHT = Jump forward in song +Alt + 1, 2, 3, 4, 5, 6 = Give player point +Alt + Ctrl + 1, 2, 3, 4, 5, 6 = Take point from player" func make_request2(address: String, func_name: Callable, expect_data: bool) -> void: - print("func_name: ", func_name.get_method()) - print("get_object: ", func_name.get_object()) var error_handling: Callable = func(_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: print("request done to address: ", default_path + address) if response_code == 200: + print("func_name: ", func_name.get_method()) if !expect_data: func_name.call() else: @@ -68,14 +67,14 @@ func make_request2(address: String, func_name: Callable, expect_data: bool) -> v var error: int = json.parse(body.get_string_from_utf8()) if error == OK: var data_received = json.get_data() - #print("data_received: ", data_received) - print("data_received type: ", typeof(data_received)) + print("data_received type: ", type_string(typeof(data_received))) if typeof(data_received) == TYPE_ARRAY: func_name.call(data_received) elif func_name != null: func_name.call(data_received) else: print("song_received") + print("data_received type: ", type_string(typeof(body))) func_name.call(body) var http_request: HTTPRequest = HTTPRequest.new() @@ -90,6 +89,7 @@ func make_request2(address: String, func_name: Callable, expect_data: bool) -> v func make_request3(address: String) -> void: var error_handling: Callable = func(_result: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void: + print("request done to address: ", default_path + address) if response_code != 200: print("Error: " + str(response_code)) @@ -105,3 +105,19 @@ func delete_children(node: Node) -> void: for n: Node in node.get_children(): node.remove_child(n) n.queue_free() + +func delete_player_children(node: Node) -> void: + for n: Node in node.get_children(): + print(n) + print(n.name) + if n.name == "HBoxContainer": + pass + elif n.name == "AddPlayerContainer": + pass + else: + node.remove_child(n) + n.queue_free() + +func unset_is_playing() -> void: + for song_object: SongObject in song_object_array: + song_object.is_playing = false diff --git a/SettingsWindow.gd b/SettingsWindow.gd index ceda87e..145122c 100644 --- a/SettingsWindow.gd +++ b/SettingsWindow.gd @@ -50,6 +50,9 @@ func _ready(): hide_next_track_button.button_pressed = Settings.hide_next_track add_to_database_button.button_pressed = Settings.add_to_stats low_played_button.button_pressed = Settings.use_low_played_mode + score_label.text = str(Settings.winning_score) + fullscreen_button.button_pressed = Settings.fullscreen + quick_sync_button.button_pressed = Settings.quick_sync select_server_button.select(Settings.selected_server) select_server_button.item_selected.connect(select_server) diff --git a/SongObject.gd b/SongObject.gd index 4d5d480..a4a756c 100644 --- a/SongObject.gd +++ b/SongObject.gd @@ -1,12 +1,14 @@ extends Node +class_name SongObject + var song_number: int var song_title: String var game_title: String -var players_given_point: Array[String] +var players_given_point: Array[int] = [] var is_answered: bool = false @@ -15,3 +17,38 @@ var has_played: bool = false var is_playing: bool = false var song: AudioStream + +func get_game_title() -> String: + if is_answered: + return game_title + else: + return "????????" + +func get_song_title() -> String: + if is_answered: + return song_title + else: + return "??????" + +func get_song_info() -> String: + if is_answered: + var format_string: String = "%d. %s - %s" + return format_string % [(song_number + 1), game_title, song_title] + else: + return "??? - ???" + +func add_point(id: int) -> void: + print("add_point") + if !players_given_point.has(id): + players_given_point.append(id) + players_given_point.sort() + +func remove_point(id: int) -> void: + print("remove_point") + if players_given_point.has(id): + players_given_point.remove_at(players_given_point.find(id)) + players_given_point.sort() + +func _to_string() -> String: + var format_string: String = "song_number: %d | game_title: %s | song_title: %s | is_answered: %s | has_played: %s | is_playing: %s" + return format_string % [(song_number), game_title, song_title, is_answered, has_played, is_playing] diff --git a/default_theme.tres b/default_theme.tres new file mode 100644 index 0000000..8f931a5 --- /dev/null +++ b/default_theme.tres @@ -0,0 +1,6 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://8bllart6xn1f"] + +[ext_resource type="StyleBox" uid="uid://bsv6yb0yir04l" path="res://style_box_flat.tres" id="1_uierc"] + +[resource] +PanelContainer/styles/panel = ExtResource("1_uierc") diff --git a/export_presets.cfg b/export_presets.cfg index 7d8516c..00eacf2 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -9,7 +9,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../../ResilioSync/Sorterat/MusicPlayer_1.3.0.exe" +export_path="../../ResilioSync/Sorterat/MusicPlayer_1.5.0.exe" encryption_include_filters="" encryption_exclude_filters="" encrypt_pck=false diff --git a/song_list_object.gd b/song_list_object.gd new file mode 100644 index 0000000..1a6690d --- /dev/null +++ b/song_list_object.gd @@ -0,0 +1,50 @@ +class_name SongListObject +extends PanelContainer + +@onready +var song_list_label: Label = $HBoxContainer/SongListLabel + +@onready +var song_list_players: HBoxContainer = $HBoxContainer/SongListPlayers + +var song_object: SongObject + +#Color(0.18, 0.18, 0.18) +#Color(0.302, 0.302, 0.302) +#Color(0.259, 0.259, 0.259) + +# Called when the node enters the scene tree for the first time. +func _ready() -> void: + #if song_object != null && song_object.song_number % 2 == 0: + # var new_stylebox_normal = self.get_theme_stylebox("panel").duplicate() + # new_stylebox_normal.bg_color = Color(0.18, 0.18, 0.18) + # self.add_theme_stylebox_override("panel", new_stylebox_normal) + # song_list_label.add_theme_stylebox_override("normal", new_stylebox_normal) + #else: + # var new_stylebox_normal = self.get_theme_stylebox("panel").duplicate() + # new_stylebox_normal.bg_color = Color(0.18, 0.18, 0.18) + # self.add_theme_stylebox_override("panel", new_stylebox_normal) + # song_list_label.add_theme_stylebox_override("normal", new_stylebox_normal) + set_label() + update_players() + +func set_label() -> void: + if song_object != null: + var size_to_change: int = song_object.players_given_point.size() * 50 + song_list_label.custom_minimum_size = Vector2(1000 - size_to_change, 28) + if song_object.is_playing: + song_list_label.add_theme_color_override("font_color", Color(1, 0.5, 0)) + song_list_label.text = song_object.get_song_info() + +func update_players() -> void: + Settings.delete_children(song_list_players) + if song_object != null: + for player_id: int in song_object.players_given_point: + for player: PlayerObject in Settings.player_array: + if player.id == player_id: + var texture: TextureRect = TextureRect.new() + texture.texture = player.character + texture.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + texture.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED + texture.custom_minimum_size = Vector2(50, 25) + song_list_players.add_child(texture) diff --git a/song_list_object.tscn b/song_list_object.tscn new file mode 100644 index 0000000..074970f --- /dev/null +++ b/song_list_object.tscn @@ -0,0 +1,65 @@ +[gd_scene load_steps=5 format=3 uid="uid://1jbtmhbqolqe"] + +[ext_resource type="Texture2D" uid="uid://c8r7ykphss4c2" path="res://characters/Link.png" id="1_ll28s"] +[ext_resource type="Script" path="res://song_list_object.gd" id="1_lspki"] +[ext_resource type="Theme" uid="uid://8bllart6xn1f" path="res://default_theme.tres" id="1_x7fq8"] +[ext_resource type="StyleBox" uid="uid://bsv6yb0yir04l" path="res://style_box_flat.tres" id="3_5h84f"] + +[node name="SongListObject" type="PanelContainer"] +custom_minimum_size = Vector2(1000, 0) +offset_right = 1088.0 +offset_bottom = 59.0 +theme = ExtResource("1_x7fq8") +script = ExtResource("1_lspki") + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 +size_flags_vertical = 0 + +[node name="SongListLabel" type="Label" parent="HBoxContainer"] +texture_filter = 2 +custom_minimum_size = Vector2(865, 28) +layout_mode = 2 +size_flags_horizontal = 3 +mouse_filter = 1 +theme = ExtResource("1_x7fq8") +theme_override_font_sizes/font_size = 20 +theme_override_styles/normal = ExtResource("3_5h84f") +text = "Final Fantasy Dissidia 012 Duodecim (Sista Fantasin Meningsskiljaktigheter 012 Tolv) - 'Crystal Cave -arrange-'' from FINAL FANTASY III" +autowrap_mode = 2 + +[node name="Panel" type="Panel" parent="HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 0 + +[node name="SongListPlayers" type="HBoxContainer" parent="HBoxContainer"] +layout_mode = 2 +size_flags_vertical = 0 + +[node name="TextureRect" type="TextureRect" parent="HBoxContainer/SongListPlayers"] +custom_minimum_size = Vector2(50, 25) +layout_mode = 2 +texture = ExtResource("1_ll28s") +expand_mode = 1 +stretch_mode = 5 + +[node name="TextureRect2" type="TextureRect" parent="HBoxContainer/SongListPlayers"] +custom_minimum_size = Vector2(50, 25) +layout_mode = 2 +texture = ExtResource("1_ll28s") +expand_mode = 1 +stretch_mode = 6 + +[node name="TextureRect3" type="TextureRect" parent="HBoxContainer/SongListPlayers"] +custom_minimum_size = Vector2(50, 25) +layout_mode = 2 +texture = ExtResource("1_ll28s") +expand_mode = 1 + +[node name="TextureRect4" type="TextureRect" parent="HBoxContainer/SongListPlayers"] +custom_minimum_size = Vector2(50, 25) +layout_mode = 2 +texture = ExtResource("1_ll28s") +expand_mode = 1 +stretch_mode = 6 diff --git a/sounds/itemequip.wav b/sounds/itemequip.wav new file mode 100644 index 0000000000000000000000000000000000000000..c404be27f790a26787abf4d94d1cefe629d0ac24 GIT binary patch literal 6342 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 literal 0 HcmV?d00001 diff --git a/sounds/itemequip.wav.import b/sounds/itemequip.wav.import new file mode 100644 index 0000000..60332c4 --- /dev/null +++ b/sounds/itemequip.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://bxec8tc8fbni" +path="res://.godot/imported/itemequip.wav-7374990029ccea3349119e7625a59c28.sample" + +[deps] + +source_file="res://sounds/itemequip.wav" +dest_files=["res://.godot/imported/itemequip.wav-7374990029ccea3349119e7625a59c28.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/sounds/itemopen.wav b/sounds/itemopen.wav new file mode 100644 index 0000000000000000000000000000000000000000..ef69fb7ec0efd643c85e3f0e9b02c1f1625239a6 GIT binary patch literal 29604 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

l?G}r6M=8ul1pJT@6lRC&Z9z1 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 GfBp?NLrRzc literal 0 HcmV?d00001 diff --git a/sounds/itemopen.wav.import b/sounds/itemopen.wav.import new file mode 100644 index 0000000..9fa3bf8 --- /dev/null +++ b/sounds/itemopen.wav.import @@ -0,0 +1,24 @@ +[remap] + +importer="wav" +type="AudioStreamWAV" +uid="uid://csg6u2h41dm4t" +path="res://.godot/imported/itemopen.wav-f6c0fafd05bb02980988f5de7142987f.sample" + +[deps] + +source_file="res://sounds/itemopen.wav" +dest_files=["res://.godot/imported/itemopen.wav-f6c0fafd05bb02980988f5de7142987f.sample"] + +[params] + +force/8_bit=false +force/mono=false +force/max_rate=false +force/max_rate_hz=44100 +edit/trim=false +edit/normalize=false +edit/loop_mode=0 +edit/loop_begin=0 +edit/loop_end=-1 +compress/mode=0 diff --git a/style_box_flat.tres b/style_box_flat.tres new file mode 100644 index 0000000..7aecf29 --- /dev/null +++ b/style_box_flat.tres @@ -0,0 +1,4 @@ +[gd_resource type="StyleBoxFlat" format=3 uid="uid://bsv6yb0yir04l"] + +[resource] +bg_color = Color(0.180392, 0.180392, 0.180392, 1)