└── addons └── sound_manager ├── LICENSE ├── SoundManager.cs ├── abstract_audio_player_pool.gd ├── ambient_sounds.gd ├── music.gd ├── plugin.cfg ├── plugin.gd ├── sound_effects.gd └── sound_manager.gd /addons/sound_manager/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-present Nathan Hoad 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /addons/sound_manager/SoundManager.cs: -------------------------------------------------------------------------------- 1 | using Godot; 2 | using Godot.Collections; 3 | 4 | namespace NathanHoad 5 | { 6 | public partial class SoundManager : Node 7 | { 8 | private static Node instance; 9 | public static Node Instance 10 | { 11 | get 12 | { 13 | if (instance == null) 14 | { 15 | instance = (Node)Engine.GetSingleton("SoundManager"); 16 | } 17 | return instance; 18 | } 19 | } 20 | 21 | 22 | public static ProcessModeEnum SoundProcessMode 23 | { 24 | get => ((Node)Instance.Get("sound_effects")).ProcessMode; 25 | set 26 | { 27 | ((Node)Instance.Get("sound_effects")).ProcessMode = value; 28 | } 29 | } 30 | 31 | public static ProcessModeEnum UISoundProcessMode 32 | { 33 | get => ((Node)Instance.Get("ui_sound_effects")).ProcessMode; 34 | set 35 | { 36 | ((Node)Instance.Get("ui_sound_effects")).ProcessMode = value; 37 | } 38 | } 39 | 40 | public static ProcessModeEnum AmbientSoundProcessMode 41 | { 42 | get => ((Node)Instance.Get("ambient_sounds")).ProcessMode; 43 | set 44 | { 45 | ((Node)Instance.Get("ambient_sounds")).ProcessMode = value; 46 | } 47 | } 48 | 49 | public static ProcessModeEnum MusicProcessMode 50 | { 51 | get => ((Node)Instance.Get("music")).ProcessMode; 52 | set 53 | { 54 | ((Node)Instance.Get("music")).ProcessMode = value; 55 | } 56 | } 57 | 58 | 59 | #region Sounds 60 | 61 | public static float GetSoundVolume() 62 | { 63 | return (float)Instance.Call("get_sound_volume"); 64 | } 65 | 66 | 67 | public static float GetUISoundVolume() 68 | { 69 | return (float)Instance.Call("get_ui_sound_volume"); 70 | } 71 | 72 | 73 | public static void SetSoundVolume(float volume) 74 | { 75 | Instance.Call("set_sound_volume", volume); 76 | } 77 | 78 | 79 | public static AudioStreamPlayer PlaySound(AudioStream resource, string overrideBus = "") 80 | { 81 | return (AudioStreamPlayer)Instance.Call("play_sound", resource, overrideBus); 82 | } 83 | 84 | 85 | public static AudioStreamPlayer PlaySoundWithPitch(AudioStream resource, float pitch, string overrideBus = "") 86 | { 87 | return (AudioStreamPlayer)Instance.Call("play_sound_with_pitch", resource, pitch, overrideBus); 88 | } 89 | 90 | 91 | public static void StopSound(AudioStream resource) 92 | { 93 | Instance.Call("stop_sound", resource); 94 | } 95 | 96 | 97 | public static AudioStreamPlayer PlayUISound(AudioStream resource, string overrideBus = "") 98 | { 99 | return (AudioStreamPlayer)Instance.Call("play_ui_sound", resource, overrideBus); 100 | } 101 | 102 | 103 | public static AudioStreamPlayer PlayUISoundWithPitch(AudioStream resource, float pitch, string overrideBus = "") 104 | { 105 | return (AudioStreamPlayer)Instance.Call("play_ui_sound_with_pitch", resource, pitch, overrideBus); 106 | } 107 | 108 | 109 | public static void StopUISound(AudioStream resource) 110 | { 111 | Instance.Call("stop_ui_sound", resource); 112 | } 113 | 114 | 115 | public static void SetDefaultSoundBus(string bus) 116 | { 117 | Instance.Call("set_default_sound_bus", bus); 118 | } 119 | 120 | 121 | public static void SetDefaultUISoundBus(string bus) 122 | { 123 | Instance.Call("set_default_ui_sound_bus", bus); 124 | } 125 | 126 | #endregion 127 | 128 | 129 | #region Ambient sounds 130 | 131 | public static AudioStreamPlayer PlayAmbientSound(AudioStream resource, float fadeInDuration, string overrideBus = "") 132 | { 133 | return (AudioStreamPlayer)Instance.Call("play_ambient_sound", resource, fadeInDuration); 134 | } 135 | 136 | 137 | public static void StopAmbientSound(AudioStream resource, float fadeOutDuration) 138 | { 139 | Instance.Call("stop_ambient_sound", resource, fadeOutDuration); 140 | } 141 | 142 | 143 | public static void StopAllAmbientSounds(float fadeOutDuration) 144 | { 145 | Instance.Call("stop_all_ambient_sounds", fadeOutDuration); 146 | } 147 | 148 | 149 | public static void SetDefaultAmbientSoundBus(string bus) 150 | { 151 | Instance.Call("set_default_ambient_sound_bus", bus); 152 | } 153 | 154 | #endregion 155 | 156 | 157 | #region Music 158 | 159 | public static float GetMusicVolume() 160 | { 161 | return (float)Instance.Call("get_music_volume"); 162 | } 163 | 164 | 165 | public static void SetMusicVolume(float volume) 166 | { 167 | Instance.Call("set_music_volume", volume); 168 | } 169 | 170 | 171 | public static AudioStreamPlayer PlayMusic(AudioStream resource, float crossFadeDuration = 0.0f, string overrideBus = "") 172 | { 173 | return (AudioStreamPlayer)Instance.Call("play_music", resource, crossFadeDuration, overrideBus); 174 | } 175 | 176 | 177 | public static AudioStreamPlayer PlayMusicFromPosition(AudioStream resource, float position, float crossFadeDuration = 0.0f, string overrideBus = "") 178 | { 179 | return (AudioStreamPlayer)Instance.Call("play_music_from_position", resource, position, crossFadeDuration, overrideBus); 180 | } 181 | 182 | 183 | public static AudioStreamPlayer PlayMusicAtVolume(AudioStream resource, float volume, float crossFadeDuration = 0.0f, string overrideBus = "") 184 | { 185 | return (AudioStreamPlayer)Instance.Call("play_music_at_volume", resource, volume, crossFadeDuration, overrideBus); 186 | } 187 | 188 | public static AudioStreamPlayer PlayMusicFromPositionAtVolume(AudioStream resource, float position, float volume, float crossFadeDuration = 0.0f, string overrideBus = "") 189 | { 190 | return (AudioStreamPlayer)Instance.Call("play_music_from_position_at_volume", resource, position, volume, crossFadeDuration, overrideBus); 191 | } 192 | 193 | 194 | public static Array GetMusicTrackHistory() 195 | { 196 | return (Array)Instance.Call("get_music_track_history"); 197 | } 198 | 199 | 200 | public static string GetLastPlayedMusicTrack() 201 | { 202 | return (string)Instance.Call("get_last_played_music_track"); 203 | } 204 | 205 | 206 | public static bool IsMusicPlaying(AudioStream resource = null) 207 | { 208 | return (bool)Instance.Call("is_music_playing", resource); 209 | } 210 | 211 | 212 | public static bool IsMusicTrackPlaying(string resource_path) 213 | { 214 | return (bool)Instance.Call("is_music_track_playing", resource_path); 215 | } 216 | 217 | 218 | public static Array GetCurrentlyPlayingMusic() 219 | { 220 | return (Array)Instance.Call("get_currently_playing_music"); 221 | } 222 | 223 | 224 | public static Array GetCurrentlyPlayingTracks() 225 | { 226 | return (Array)Instance.Call("get_currently_playing_tracks"); 227 | } 228 | 229 | 230 | public static void PauseMusic(AudioStream resource = null) 231 | { 232 | Instance.Call("pause_music", resource); 233 | } 234 | 235 | 236 | public static void ResumeMusic(AudioStream resource = null) 237 | { 238 | Instance.Call("resume_music", resource); 239 | } 240 | 241 | 242 | public static void StopMusic(float fadeOutDuration = 0.0f) 243 | { 244 | Instance.Call("stop_music", fadeOutDuration); 245 | } 246 | 247 | 248 | public static void SetDefaultMusicBus(string bus) 249 | { 250 | Instance.Call("set_default_music_bus", bus); 251 | } 252 | 253 | #endregion 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /addons/sound_manager/abstract_audio_player_pool.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | @export var default_busses := [] 5 | @export var default_pool_size := 8 6 | 7 | 8 | var available_players: Array[AudioStreamPlayer] = [] 9 | var busy_players: Array[AudioStreamPlayer] = [] 10 | var bus: String = "Master" 11 | 12 | var _tweens: Dictionary = {} 13 | 14 | 15 | func _init(possible_busses: PackedStringArray = default_busses, pool_size: int = default_pool_size) -> void: 16 | bus = get_possible_bus(possible_busses) 17 | 18 | for i in pool_size: 19 | increase_pool() 20 | 21 | func get_possible_bus(possible_busses: PackedStringArray) -> String: 22 | for possible_bus in possible_busses: 23 | var cases: PackedStringArray = [ 24 | possible_bus, 25 | possible_bus.to_lower(), 26 | possible_bus.to_camel_case(), 27 | possible_bus.to_pascal_case(), 28 | possible_bus.to_snake_case() 29 | ] 30 | for case in cases: 31 | if AudioServer.get_bus_index(case) > -1: 32 | return case 33 | return "Master" 34 | 35 | 36 | func prepare(resource: AudioStream, override_bus: String = "") -> AudioStreamPlayer: 37 | var player: AudioStreamPlayer 38 | 39 | if resource is AudioStreamRandomizer: 40 | player = get_player_with_resource(resource) 41 | 42 | if player == null: 43 | player = get_available_player() 44 | 45 | player.stream = resource 46 | player.bus = override_bus if override_bus != "" else bus 47 | player.volume_db = linear_to_db(1.0) 48 | player.pitch_scale = 1 49 | return player 50 | 51 | 52 | func get_available_player() -> AudioStreamPlayer: 53 | if available_players.size() == 0: 54 | increase_pool() 55 | var player = available_players.pop_front() 56 | busy_players.append(player) 57 | return player 58 | 59 | 60 | func get_player_with_resource(resource: AudioStream) -> AudioStreamPlayer: 61 | for player in busy_players + available_players: 62 | if player.stream == resource: 63 | return player 64 | return null 65 | 66 | 67 | func get_busy_player_with_resource(resource: AudioStream) -> AudioStreamPlayer: 68 | for player in busy_players: 69 | if player.stream.resource_path == resource.resource_path: 70 | return player 71 | return null 72 | 73 | 74 | func mark_player_as_available(player: AudioStreamPlayer) -> void: 75 | if busy_players.has(player): 76 | busy_players.erase(player) 77 | 78 | if available_players.size() >= default_pool_size: 79 | available_players.erase(player) 80 | player.queue_free() 81 | elif not available_players.has(player): 82 | available_players.append(player) 83 | 84 | 85 | func increase_pool() -> void: 86 | # See if we can reclaim a rogue busy player 87 | for player in busy_players: 88 | if not player.playing: 89 | mark_player_as_available(player) 90 | return 91 | 92 | # Otherwise, add a new player 93 | var player := AudioStreamPlayer.new() 94 | add_child(player) 95 | available_players.append(player) 96 | player.bus = bus 97 | player.finished.connect(_on_player_finished.bind(player)) 98 | 99 | 100 | func fade_volume(player: AudioStreamPlayer, from_volume: float, to_volume: float, duration: float) -> AudioStreamPlayer: 101 | # Remove any tweens that might already be on this player 102 | _remove_tween(player) 103 | 104 | # Start a new tween 105 | var tween: Tween = get_tree().create_tween().bind_node(self) 106 | 107 | player.volume_db = from_volume 108 | if from_volume > to_volume: 109 | # Fade out 110 | tween.tween_property(player, "volume_db", to_volume, duration).set_trans(Tween.TRANS_CIRC).set_ease(Tween.EASE_IN) 111 | else: 112 | # Fade in 113 | tween.tween_property(player, "volume_db", to_volume, duration).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) 114 | 115 | _tweens[player] = tween 116 | tween.finished.connect(_on_fade_completed.bind(player, tween, from_volume, to_volume, duration)) 117 | 118 | return player 119 | 120 | 121 | #region Helpers 122 | 123 | 124 | func _remove_tween(player: AudioStreamPlayer) -> void: 125 | if _tweens.has(player): 126 | var fade: Tween = _tweens.get(player) 127 | fade.kill() 128 | _tweens.erase(player) 129 | 130 | 131 | #endregion 132 | 133 | #region Signals 134 | 135 | 136 | func _on_player_finished(player: AudioStreamPlayer) -> void: 137 | mark_player_as_available(player) 138 | 139 | 140 | func _on_fade_completed(player: AudioStreamPlayer, tween: Tween, from_volume: float, to_volume: float, duration: float): 141 | _remove_tween(player) 142 | 143 | # If we just faded out then our player is now available 144 | if to_volume <= -79.0: 145 | player.stop() 146 | mark_player_as_available(player) 147 | 148 | 149 | #endregion 150 | -------------------------------------------------------------------------------- /addons/sound_manager/ambient_sounds.gd: -------------------------------------------------------------------------------- 1 | extends "./abstract_audio_player_pool.gd" 2 | 3 | 4 | func play(resource: AudioStream, fade_in_duration: float, override_bus: String = "") -> AudioStreamPlayer: 5 | var player = get_busy_player_with_resource(resource) 6 | 7 | # If it's already playing then don't play it again 8 | if is_instance_valid(player): return player 9 | 10 | player = prepare(resource, override_bus) 11 | fade_volume(player, -80.0, 0.0, fade_in_duration) 12 | player.call_deferred("play") 13 | return player 14 | 15 | 16 | func stop(resource: AudioStream, fade_out_duration: float = 0.0) -> void: 17 | if fade_out_duration <= 0.0: 18 | fade_out_duration = 0.01 19 | 20 | for player in busy_players: 21 | if player.stream == resource: 22 | fade_volume(player, player.volume_db, -80, fade_out_duration) 23 | 24 | 25 | func stop_all(fade_out_duration: float = 0.0) -> void: 26 | if fade_out_duration <= 0.0: 27 | fade_out_duration = 0.01 28 | 29 | for player in busy_players: 30 | fade_volume(player, player.volume_db, -80, fade_out_duration) 31 | -------------------------------------------------------------------------------- /addons/sound_manager/music.gd: -------------------------------------------------------------------------------- 1 | extends "./abstract_audio_player_pool.gd" 2 | 3 | 4 | var track_history: PackedStringArray = [] 5 | 6 | 7 | func play(resource: AudioStream, position: float = 0.0, volume: float = 0.0, crossfade_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 8 | stop(crossfade_duration * 2) 9 | 10 | var player = get_busy_player_with_resource(resource) 11 | 12 | # If the player already exists then just make sure the volume is right (it might have just been fading in or out) 13 | if player != null: 14 | fade_volume(player, player.volume_db, volume, crossfade_duration) 15 | return player 16 | 17 | # Otherwise we need to prep another player and handle its introduction 18 | player = prepare(resource, override_bus) 19 | fade_volume(player, -80.0, volume, crossfade_duration) 20 | 21 | # Remember this track name 22 | track_history.insert(0, resource.resource_path) 23 | if track_history.size() > 50: 24 | track_history.remove_at(50) 25 | 26 | player.call_deferred("play", position) 27 | return player 28 | 29 | 30 | func is_playing(resource: AudioStream) -> bool: 31 | if resource != null: 32 | return get_busy_player_with_resource(resource) != null 33 | else: 34 | return busy_players.size() > 0 35 | 36 | 37 | func stop(fade_out_duration: float = 0.0) -> void: 38 | for player in busy_players: 39 | if fade_out_duration <= 0.0: 40 | fade_out_duration = 0.01 41 | fade_volume(player, player.volume_db, -80, fade_out_duration) 42 | 43 | 44 | func pause(resource: AudioStream = null) -> void: 45 | if resource != null: 46 | var player = get_busy_player_with_resource(resource) 47 | if is_instance_valid(player): 48 | player.stream_paused = true 49 | else: 50 | for player in busy_players: 51 | player.stream_paused = true 52 | 53 | 54 | func resume(resource: AudioStream = null) -> void: 55 | if resource != null: 56 | var player = get_busy_player_with_resource(resource) 57 | if is_instance_valid(player): 58 | player.stream_paused = false 59 | else: 60 | for player in busy_players: 61 | player.stream_paused = false 62 | 63 | 64 | func is_track_playing(resource_path: String) -> bool: 65 | for player in busy_players: 66 | if player.stream.resource_path == resource_path: 67 | return true 68 | return false 69 | 70 | 71 | func get_currently_playing() -> Array[AudioStream]: 72 | var tracks: Array[AudioStream] = [] 73 | for player in busy_players: 74 | tracks.append(player.stream) 75 | return tracks 76 | 77 | 78 | func get_currently_playing_tracks() -> PackedStringArray: 79 | var tracks: PackedStringArray = [] 80 | for player in busy_players: 81 | tracks.append(player.stream.resource_path) 82 | return tracks 83 | -------------------------------------------------------------------------------- /addons/sound_manager/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="SoundManager" 4 | description="Manage your sounds and music" 5 | author="Nathan Hoad" 6 | version="2.6.2" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/sound_manager/plugin.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | 4 | 5 | func _enter_tree(): 6 | add_autoload_singleton("SoundManager", get_plugin_path() + "/sound_manager.gd") 7 | 8 | 9 | func _exit_tree(): 10 | remove_autoload_singleton("SoundManager") 11 | 12 | 13 | func get_plugin_path() -> String: 14 | return get_script().resource_path.get_base_dir() 15 | -------------------------------------------------------------------------------- /addons/sound_manager/sound_effects.gd: -------------------------------------------------------------------------------- 1 | extends "./abstract_audio_player_pool.gd" 2 | 3 | 4 | func play(resource: AudioStream, override_bus: String = "") -> AudioStreamPlayer: 5 | var player = prepare(resource, override_bus) 6 | player.call_deferred("play") 7 | return player 8 | 9 | 10 | func stop(resource: AudioStream) -> void: 11 | for player in busy_players: 12 | if player.stream == resource: 13 | player.call_deferred("stop") 14 | -------------------------------------------------------------------------------- /addons/sound_manager/sound_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | const SoundEffectsPlayer = preload("./sound_effects.gd") 5 | const AmbientSoundsPlayer = preload("./ambient_sounds.gd") 6 | const MusicPlayer = preload("./music.gd") 7 | 8 | var sound_effects: SoundEffectsPlayer = SoundEffectsPlayer.new(["Sounds", "SFX"], 8) 9 | var ui_sound_effects: SoundEffectsPlayer = SoundEffectsPlayer.new(["UI", "Interface", "Sounds", "SFX"], 8) 10 | var ambient_sounds: AmbientSoundsPlayer = AmbientSoundsPlayer.new(["Sounds", "SFX"], 1) 11 | var music: MusicPlayer = MusicPlayer.new(["Music"], 2) 12 | 13 | var sound_process_mode: ProcessMode: 14 | set(value): 15 | sound_effects.process_mode = value 16 | get: 17 | return sound_effects.process_mode 18 | 19 | var ui_sound_process_mode: ProcessMode: 20 | set(value): 21 | ui_sound_effects.process_mode = value 22 | get: 23 | return ui_sound_effects.process_mode 24 | 25 | 26 | var ambient_sound_process_mode: ProcessMode: 27 | set(value): 28 | ambient_sounds.process_mode = value 29 | get: 30 | return ambient_sounds.process_mode 31 | 32 | 33 | var music_process_mode: ProcessMode: 34 | set(value): 35 | music.process_mode = value 36 | get: 37 | return music.process_mode 38 | 39 | 40 | func _init() -> void: 41 | Engine.register_singleton("SoundManager", self) 42 | 43 | add_child(sound_effects) 44 | add_child(ui_sound_effects) 45 | add_child(ambient_sounds) 46 | add_child(music) 47 | 48 | self.sound_process_mode = PROCESS_MODE_PAUSABLE 49 | self.ui_sound_process_mode = PROCESS_MODE_ALWAYS 50 | self.ambient_sound_process_mode = PROCESS_MODE_ALWAYS 51 | self.music_process_mode = PROCESS_MODE_ALWAYS 52 | 53 | 54 | #region Sounds 55 | 56 | 57 | func get_sound_volume() -> float: 58 | return db_to_linear(AudioServer.get_bus_volume_db(AudioServer.get_bus_index(sound_effects.bus))) 59 | 60 | 61 | func set_sound_volume(volume_between_0_and_1: float) -> void: 62 | _show_shared_bus_warning() 63 | AudioServer.set_bus_volume_db(AudioServer.get_bus_index(sound_effects.bus), linear_to_db(volume_between_0_and_1)) 64 | 65 | 66 | func play_sound(resource: AudioStream, override_bus: String = "") -> AudioStreamPlayer: 67 | return sound_effects.play(resource, override_bus) 68 | 69 | 70 | func play_sound_with_pitch(resource: AudioStream, pitch: float = 1.0, override_bus: String = "") -> AudioStreamPlayer: 71 | var player = sound_effects.play(resource, override_bus) 72 | player.pitch_scale = pitch 73 | return player 74 | 75 | 76 | func stop_sound(resource: AudioStream) -> void: 77 | return sound_effects.stop(resource) 78 | 79 | 80 | func set_default_sound_bus(bus: String) -> void: 81 | sound_effects.bus = bus 82 | 83 | 84 | #endregion 85 | 86 | #region UI sounds 87 | 88 | 89 | func get_ui_sound_volume() -> float: 90 | return db_to_linear(AudioServer.get_bus_volume_db(AudioServer.get_bus_index(ui_sound_effects.bus))) 91 | 92 | 93 | func set_ui_sound_volume(volume_between_0_and_1: float) -> void: 94 | _show_shared_bus_warning() 95 | AudioServer.set_bus_volume_db(AudioServer.get_bus_index(ui_sound_effects.bus), linear_to_db(volume_between_0_and_1)) 96 | 97 | 98 | func play_ui_sound(resource: AudioStream, override_bus: String = "") -> AudioStreamPlayer: 99 | return ui_sound_effects.play(resource, override_bus) 100 | 101 | 102 | func play_ui_sound_with_pitch(resource: AudioStream, pitch: float = 1.0, override_bus: String = "") -> AudioStreamPlayer: 103 | var player = ui_sound_effects.play(resource, override_bus) 104 | player.pitch_scale = pitch 105 | return player 106 | 107 | 108 | func stop_ui_sound(resource: AudioStream) -> void: 109 | return ui_sound_effects.stop(resource) 110 | 111 | 112 | func set_default_ui_sound_bus(bus: String) -> void: 113 | ui_sound_effects.bus = bus 114 | 115 | 116 | #endregion 117 | 118 | #region Ambient sound 119 | 120 | 121 | func get_ambient_sound_volume() -> float: 122 | return db_to_linear(AudioServer.get_bus_volume_db(AudioServer.get_bus_index(ambient_sounds.bus))) 123 | 124 | 125 | func set_ambient_sound_volume(volume_between_0_and_1: float) -> void: 126 | _show_shared_bus_warning() 127 | AudioServer.set_bus_volume_db(AudioServer.get_bus_index(ambient_sounds.bus), linear_to_db(volume_between_0_and_1)) 128 | 129 | 130 | func play_ambient_sound(resource: AudioStream, fade_in_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 131 | return ambient_sounds.play(resource, fade_in_duration, override_bus) 132 | 133 | 134 | func stop_ambient_sound(resource: AudioStream, fade_out_duration: float = 0.0) -> void: 135 | ambient_sounds.stop(resource, fade_out_duration) 136 | 137 | 138 | func stop_all_ambient_sounds(fade_out_duration: float = 0.0) -> void: 139 | ambient_sounds.stop_all(fade_out_duration) 140 | 141 | 142 | func set_default_ambient_sound_bus(bus: String) -> void: 143 | ambient_sounds.bus = bus 144 | 145 | 146 | #endregion 147 | 148 | #region Music 149 | 150 | func get_music_volume() -> float: 151 | return db_to_linear(AudioServer.get_bus_volume_db(AudioServer.get_bus_index(music.bus))) 152 | 153 | 154 | func set_music_volume(volume_between_0_and_1: float) -> void: 155 | _show_shared_bus_warning() 156 | AudioServer.set_bus_volume_db(AudioServer.get_bus_index(music.bus), linear_to_db(volume_between_0_and_1)) 157 | 158 | 159 | func play_music(resource: AudioStream, crossfade_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 160 | return music.play(resource, 0.0, 0.0, crossfade_duration, override_bus) 161 | 162 | 163 | func play_music_from_position(resource: AudioStream, position: float = 0.0, crossfade_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 164 | return music.play(resource, position, 0.0, crossfade_duration, override_bus) 165 | 166 | 167 | func play_music_at_volume(resource: AudioStream, volume: float = 0.0, crossfade_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 168 | return music.play(resource, 0.0, volume, crossfade_duration, override_bus) 169 | 170 | 171 | func play_music_from_position_at_volume(resource: AudioStream, position: float = 0.0, volume: float = 0.0, crossfade_duration: float = 0.0, override_bus: String = "") -> AudioStreamPlayer: 172 | return music.play(resource, position, volume, crossfade_duration, override_bus) 173 | 174 | 175 | func get_music_track_history() -> Array: 176 | return music.track_history 177 | 178 | 179 | func get_last_played_music_track() -> String: 180 | return music.track_history[0] 181 | 182 | 183 | func is_music_playing(resource: AudioStream = null) -> bool: 184 | return music.is_playing(resource) 185 | 186 | 187 | func is_music_track_playing(resource_path: String) -> bool: 188 | return music.is_track_playing(resource_path) 189 | 190 | 191 | func get_currently_playing_music() -> Array: 192 | return music.get_currently_playing() 193 | 194 | 195 | func get_currently_playing_music_tracks() -> Array: 196 | return music.get_currently_playing_tracks() 197 | 198 | 199 | func pause_music(resource: AudioStream = null) -> void: 200 | music.pause(resource) 201 | 202 | 203 | func resume_music(resource: AudioStream = null) -> void: 204 | music.resume(resource) 205 | 206 | 207 | func stop_music(fade_out_duration: float = 0.0) -> void: 208 | music.stop(fade_out_duration) 209 | 210 | 211 | func set_default_music_bus(bus: String) -> void: 212 | music.bus = bus 213 | 214 | 215 | #endregion 216 | 217 | #region helpers 218 | 219 | 220 | func _show_shared_bus_warning() -> void: 221 | if "Master" in [music.bus, sound_effects.bus, ui_sound_effects.bus, ambient_sounds.bus]: 222 | push_warning("Using the Master sound bus directly isn't recommended.") 223 | if music.bus == sound_effects.bus or music.bus == ui_sound_effects.bus: 224 | push_warning("Both music and sounds are using the same bus: %s" % music.bus) 225 | 226 | 227 | #endregion 228 | --------------------------------------------------------------------------------