diff --git a/addons/capri_tools/global_music_selector.gd b/addons/capri_tools/global_music_selector.gd new file mode 100644 index 0000000..53d9f8f --- /dev/null +++ b/addons/capri_tools/global_music_selector.gd @@ -0,0 +1,46 @@ +extends EditorProperty + + +var _dropdown_button := Button.new() + +var _popup_menu := PopupMenu.new() + + +func _init() -> void: + _dropdown_button.pressed.connect(_show_popup) + _dropdown_button.icon = EditorInterface.get_editor_theme().get_icon("AudioStreamWAV", "EditorIcons") + + _popup_menu.index_pressed.connect(_on_song_selected) + + add_child(_dropdown_button) + add_child(_popup_menu) + add_focusable(_dropdown_button) + + +func _update_property() -> void: + var new_value: StringName = get_edited_object()[get_edited_property()] + _dropdown_button.text = new_value.capitalize() + + +func _show_popup() -> void: + var songs = Music.songs.keys() + + _popup_menu.clear() + for sound: StringName in songs: + _popup_menu.add_icon_item( + EditorInterface.get_editor_theme().get_icon("AudioStreamWAV", "EditorIcons"), + sound.capitalize() + ) + + var button_rect = _dropdown_button.get_global_rect() + _popup_menu.reset_size() + var popup_pos = button_rect.position + Vector2(DisplayServer.window_get_position()) + _popup_menu.position = popup_pos + _popup_menu.min_size.x = button_rect.size.x + _popup_menu.popup() + + +func _on_song_selected(index: int) -> void: + var sound = Music.songs.keys()[index] + _dropdown_button.grab_focus() + emit_changed(get_edited_property(), sound) diff --git a/addons/capri_tools/global_music_selector.gd.uid b/addons/capri_tools/global_music_selector.gd.uid new file mode 100644 index 0000000..817031e --- /dev/null +++ b/addons/capri_tools/global_music_selector.gd.uid @@ -0,0 +1 @@ +uid://uc6u3ls6jx3y diff --git a/addons/capri_tools/global_sound_selector_plugin.gd b/addons/capri_tools/global_sound_selector_plugin.gd index d963c34..4f0e5bc 100644 --- a/addons/capri_tools/global_sound_selector_plugin.gd +++ b/addons/capri_tools/global_sound_selector_plugin.gd @@ -2,6 +2,7 @@ extends EditorInspectorPlugin const GlobalSoundSelector = preload("global_sound_selector.gd") +const GlobalMusicSelector = preload("global_music_selector.gd") func _can_handle(object: Object) -> bool: @@ -9,8 +10,11 @@ func _can_handle(object: Object) -> bool: func _parse_property(object: Object, type: Variant.Type, name: String, hint_type: PropertyHint, hint_string: String, usage_flags: int, wide: bool) -> bool: - if type == TYPE_STRING_NAME and hint_string == "global_sound": - add_property_editor(name, GlobalSoundSelector.new()) - return true - else: - return false + if type == TYPE_STRING_NAME: + if hint_string == "global_sound": + add_property_editor(name, GlobalSoundSelector.new()) + return true + if hint_string == "global_music": + add_property_editor(name, GlobalMusicSelector.new()) + return true + return false diff --git a/assets/music/bug_music.ogg b/assets/music/bug_music.ogg new file mode 100644 index 0000000..f36408e Binary files /dev/null and b/assets/music/bug_music.ogg differ diff --git a/assets/music/bug_music.ogg.import b/assets/music/bug_music.ogg.import new file mode 100644 index 0000000..d2bb39b --- /dev/null +++ b/assets/music/bug_music.ogg.import @@ -0,0 +1,19 @@ +[remap] + +importer="oggvorbisstr" +type="AudioStreamOggVorbis" +uid="uid://dmctaba7v1rgu" +path="res://.godot/imported/bug_music.ogg-4e14ca93037a40f8bd3b8d23ee565dcc.oggvorbisstr" + +[deps] + +source_file="res://assets/music/bug_music.ogg" +dest_files=["res://.godot/imported/bug_music.ogg-4e14ca93037a40f8bd3b8d23ee565dcc.oggvorbisstr"] + +[params] + +loop=true +loop_offset=28.0 +bpm=0.0 +beat_count=0 +bar_beats=4 diff --git a/autoloads/global_sounds.tscn b/autoloads/global_sounds.tscn index 8a1de4a..f848e22 100644 --- a/autoloads/global_sounds.tscn +++ b/autoloads/global_sounds.tscn @@ -14,7 +14,6 @@ sounds = { [node name="SoggyAmbience" type="AudioStreamPlayer" parent="."] stream = ExtResource("2_3njyb") volume_db = -10.0 -autoplay = true bus = &"Background Sound" [node name="WinSound" type="AudioStreamPlayer" parent="."] diff --git a/autoloads/music.gd b/autoloads/music.gd new file mode 100644 index 0000000..2a2e7e3 --- /dev/null +++ b/autoloads/music.gd @@ -0,0 +1,53 @@ +@tool +extends Node + + +@export_dir var songs_dir: String +@export_tool_button("Update Songs") var _update_songs_action = _update_songs +@export var songs: Dictionary[StringName, AudioStream] + +@export var player_a: AudioStreamPlayer +@export var player_b: AudioStreamPlayer + + +@onready var _active_player: AudioStreamPlayer = player_a +@onready var _tween: Tween = null + + +func play_song(id: StringName, crossfade_time: float = 0.0, restart: bool = false) -> void: + var new_stream = songs.get(id) as AudioStream + if new_stream: + if not restart and _active_player.stream == new_stream: + return + var new_player = player_b if _active_player == player_a else player_a + new_player.stream = new_stream + new_player.play() + + if crossfade_time > 0.0: + new_player.volume_linear = 0.0 + if _tween: + _tween.kill() + _tween = create_tween().set_parallel() + _tween.tween_property(new_player, ^"volume_linear", 1.0, crossfade_time) + _tween.tween_property(_active_player, ^"volume_linear", 0.0, crossfade_time) + _tween.chain().tween_callback(_active_player.stop) + else: + new_player.volume_linear = 1.0 + _active_player.stop() + + _active_player = new_player + + +func _update_songs() -> void: + songs.clear() + var dir = DirAccess.open(songs_dir) + if dir: + dir.list_dir_begin() + var file = dir.get_next() + while file != "": + if not dir.current_is_dir() and not file.ends_with(".import"): + var stream := load(songs_dir + "/" + file) as AudioStream + if stream: + songs[file.get_basename()] = stream + file = dir.get_next() + notify_property_list_changed() diff --git a/autoloads/music.gd.uid b/autoloads/music.gd.uid new file mode 100644 index 0000000..9bbeb91 --- /dev/null +++ b/autoloads/music.gd.uid @@ -0,0 +1 @@ +uid://dgi1v18r8dx4q diff --git a/autoloads/music.tscn b/autoloads/music.tscn new file mode 100644 index 0000000..7a7902e --- /dev/null +++ b/autoloads/music.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://cxrhw5ic2vunh"] + +[ext_resource type="Script" uid="uid://dgi1v18r8dx4q" path="res://autoloads/music.gd" id="1_16wm1"] +[ext_resource type="AudioStream" uid="uid://dmctaba7v1rgu" path="res://assets/music/bug_music.ogg" id="2_kl0u4"] + +[node name="Music" type="Node" node_paths=PackedStringArray("player_a", "player_b")] +script = ExtResource("1_16wm1") +songs_dir = "res://assets/music" +songs = Dictionary[StringName, AudioStream]({ +&"bug_music": ExtResource("2_kl0u4") +}) +player_a = NodePath("MusicPlayerA") +player_b = NodePath("MusicPlayerB") + +[node name="MusicPlayerA" type="AudioStreamPlayer" parent="."] +bus = &"Music" + +[node name="MusicPlayerB" type="AudioStreamPlayer" parent="."] +bus = &"Music" diff --git a/autoloads/scene_manager.tscn b/autoloads/scene_manager.tscn index 4ac64e0..4e9a340 100644 --- a/autoloads/scene_manager.tscn +++ b/autoloads/scene_manager.tscn @@ -1,8 +1,6 @@ -[gd_scene load_steps=4 format=3 uid="uid://ckgsfhfpg00ys"] +[gd_scene load_steps=2 format=3 uid="uid://ckgsfhfpg00ys"] [ext_resource type="Script" uid="uid://crlo6ow7fo6ca" path="res://autoloads/scene_manager.gd" id="1_1hxm1"] -[ext_resource type="AudioStream" uid="uid://sci5aqar0oyx" path="res://assets/audio/bgs/amb_sog.wav" id="2_dr7pa"] -[ext_resource type="AudioStream" uid="uid://flc817bekeh6" path="res://assets/audio/sfx/level_win.ogg" id="3_8ri5f"] [node name="SceneManager" type="Node" node_paths=PackedStringArray("viewport", "viewport_holder")] script = ExtResource("1_1hxm1") @@ -49,14 +47,3 @@ handle_input_locally = false canvas_item_default_texture_filter = 0 size = Vector2i(288, 216) render_target_update_mode = 4 - -[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] -stream = ExtResource("2_dr7pa") -volume_db = -10.0 -autoplay = true -bus = &"Background Sound" - -[node name="WinSound" type="AudioStreamPlayer" parent="."] -stream = ExtResource("3_8ri5f") -volume_db = -6.558 -bus = &"Sound Effects" diff --git a/default_bus_layout.tres b/default_bus_layout.tres index c20f634..86cc9b8 100644 --- a/default_bus_layout.tres +++ b/default_bus_layout.tres @@ -10,23 +10,29 @@ spread = 0.3 wet = 0.1 [resource] -bus/1/name = &"Capri" +bus/1/name = &"Music" bus/1/solo = false bus/1/mute = false bus/1/bypass_fx = false bus/1/volume_db = 0.0 bus/1/send = &"Master" -bus/1/effect/0/effect = SubResource("AudioEffectReverb_rn7sq") -bus/1/effect/0/enabled = true -bus/2/name = &"Background Sound" +bus/2/name = &"Capri" bus/2/solo = false bus/2/mute = false bus/2/bypass_fx = false bus/2/volume_db = 0.0 bus/2/send = &"Master" -bus/3/name = &"Sound Effects" +bus/2/effect/0/effect = SubResource("AudioEffectReverb_rn7sq") +bus/2/effect/0/enabled = true +bus/3/name = &"Background Sound" bus/3/solo = false bus/3/mute = false bus/3/bypass_fx = false bus/3/volume_db = 0.0 bus/3/send = &"Master" +bus/4/name = &"Sound Effects" +bus/4/solo = false +bus/4/mute = false +bus/4/bypass_fx = false +bus/4/volume_db = 0.0 +bus/4/send = &"Master" diff --git a/maps/descent/tutorial.tscn b/maps/descent/tutorial.tscn index 844ed7e..039b2dd 100644 --- a/maps/descent/tutorial.tscn +++ b/maps/descent/tutorial.tscn @@ -21,6 +21,7 @@ shader_parameter/fps = 15.0 script = ExtResource("1_8bygc") title = "Obligatory Tutorial Level" id = "tutorial" +music = &"bug_music" [node name="Sprite2D" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_sf5kh") diff --git a/maps/level_z.tscn b/maps/level_z.tscn index ce6a651..bc4d050 100644 --- a/maps/level_z.tscn +++ b/maps/level_z.tscn @@ -13,6 +13,7 @@ script = ExtResource("1_hcs1r") title = "Test Level Z" id = "z-level" order = 2 +music = &"bug_music" [node name="Background" type="Sprite2D" parent="."] modulate = Color(0.996924, 0.421436, 0, 1) diff --git a/objects/enemies/lashy/blast_star.tscn b/objects/enemies/lashy/blast_star.tscn index 2732ff6..60b2b16 100644 --- a/objects/enemies/lashy/blast_star.tscn +++ b/objects/enemies/lashy/blast_star.tscn @@ -2,6 +2,33 @@ [ext_resource type="Texture2D" uid="uid://350f21o7jrwq" path="res://assets/textures/effects/star.png" id="1_1xc4y"] +[sub_resource type="Animation" id="Animation_6qf6s"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("Sprite2D:scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector2(1, 1)] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath("Sprite2D:rotation") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [0.0] +} + [sub_resource type="Animation" id="Animation_1xc4y"] resource_name = "blast" length = 0.3 @@ -45,33 +72,6 @@ tracks/2/keys = { }] } -[sub_resource type="Animation" id="Animation_6qf6s"] -length = 0.001 -tracks/0/type = "value" -tracks/0/imported = false -tracks/0/enabled = true -tracks/0/path = NodePath("Sprite2D:scale") -tracks/0/interp = 1 -tracks/0/loop_wrap = true -tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [Vector2(1, 1)] -} -tracks/1/type = "value" -tracks/1/imported = false -tracks/1/enabled = true -tracks/1/path = NodePath("Sprite2D:rotation") -tracks/1/interp = 1 -tracks/1/loop_wrap = true -tracks/1/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), -"update": 0, -"values": [0.0] -} - [sub_resource type="AnimationLibrary" id="AnimationLibrary_kd46a"] _data = { &"RESET": SubResource("Animation_6qf6s"), diff --git a/project.godot b/project.godot index 93a1a87..c556d90 100644 --- a/project.godot +++ b/project.godot @@ -20,6 +20,7 @@ config/icon="res://icon.svg" SceneManager="*res://autoloads/scene_manager.tscn" Levels="*res://autoloads/levels.tscn" GlobalSounds="*res://autoloads/global_sounds.tscn" +Music="*res://autoloads/music.tscn" [display] diff --git a/scripts/level/level.gd b/scripts/level/level.gd index e4f6bf7..f3df270 100644 --- a/scripts/level/level.gd +++ b/scripts/level/level.gd @@ -5,3 +5,8 @@ extends Node2D @export var title: String @export var id: String @export_range(0,1,1,"or_greater") var order: int +@export_custom(0, "global_music") var music: StringName + + +func _ready() -> void: + Music.play_song(music)