diff --git a/common/audio_manager/assets/morceaux/menu/main_menu.ogg.import b/common/audio_manager/assets/morceaux/menu/main_menu.ogg.import index dea4db2..6fae5f7 100644 --- a/common/audio_manager/assets/morceaux/menu/main_menu.ogg.import +++ b/common/audio_manager/assets/morceaux/menu/main_menu.ogg.import @@ -13,7 +13,7 @@ dest_files=["res://.godot/imported/main_menu.ogg-45c6ef59eabdc081ad36ff5114035b6 [params] loop=true -loop_offset=0 -bpm=0 +loop_offset=0.0 +bpm=0.0 beat_count=0 bar_beats=4 diff --git a/common/audio_manager/assets/morceaux/niveau/forest_phase_1.ogg.import b/common/audio_manager/assets/morceaux/niveau/forest_phase_1.ogg.import index 05eeb2d..55da31a 100644 --- a/common/audio_manager/assets/morceaux/niveau/forest_phase_1.ogg.import +++ b/common/audio_manager/assets/morceaux/niveau/forest_phase_1.ogg.import @@ -13,7 +13,7 @@ dest_files=["res://.godot/imported/forest_phase_1.ogg-6fd2e255642e47e98a5560b5a2 [params] loop=true -loop_offset=0 -bpm=0 +loop_offset=0.0 +bpm=0.0 beat_count=0 bar_beats=4 diff --git a/common/audio_manager/assets/morceaux/niveau/forest_phase_2.ogg.import b/common/audio_manager/assets/morceaux/niveau/forest_phase_2.ogg.import index 7f2ea6b..aa8b02d 100644 --- a/common/audio_manager/assets/morceaux/niveau/forest_phase_2.ogg.import +++ b/common/audio_manager/assets/morceaux/niveau/forest_phase_2.ogg.import @@ -13,7 +13,7 @@ dest_files=["res://.godot/imported/forest_phase_2.ogg-1497e4a80f7f2adb0670888710 [params] loop=true -loop_offset=0 -bpm=0 +loop_offset=0.0 +bpm=0.0 beat_count=0 bar_beats=4 diff --git a/common/audio_manager/assets/morceaux/niveau/forest_waiting.ogg.import b/common/audio_manager/assets/morceaux/niveau/forest_waiting.ogg.import index b49d3c2..b644b90 100644 --- a/common/audio_manager/assets/morceaux/niveau/forest_waiting.ogg.import +++ b/common/audio_manager/assets/morceaux/niveau/forest_waiting.ogg.import @@ -13,7 +13,7 @@ dest_files=["res://.godot/imported/forest_waiting.ogg-b3b1041d32126973edfe0a5259 [params] loop=true -loop_offset=0 -bpm=0 +loop_offset=0.0 +bpm=0.0 beat_count=0 bar_beats=4 diff --git a/common/audio_manager/audio_manager.tscn b/common/audio_manager/audio_manager.tscn index eba92d5..43e83c9 100644 --- a/common/audio_manager/audio_manager.tscn +++ b/common/audio_manager/audio_manager.tscn @@ -46,15 +46,6 @@ stream_0 = ExtResource("2_tuvql") stream_1 = ExtResource("3_7uv4r") stream_2 = ExtResource("4_tuvql") -[sub_resource type="AudioStreamPlaylist" id="AudioStreamPlaylist_ajci6"] -stream_count = 6 -stream_0 = ExtResource("5_ajci6") -stream_1 = ExtResource("4_2fduo") -stream_2 = ExtResource("11_ngi21") -stream_3 = ExtResource("9_am7i4") -stream_4 = ExtResource("10_tq535") -stream_5 = ExtResource("12_xmumj") - [sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_kfbah"] [sub_resource type="AudioStreamRandomizer" id="AudioStreamRandomizer_1w04j"] @@ -93,31 +84,53 @@ stream_7/stream = ExtResource("36_4sa2t") process_mode = 3 script = ExtResource("1_0tvca") -[node name="Ambiance" type="Node" parent="." unique_id=1989991562] +[node name="Ambiances" type="Node" parent="." unique_id=1989991562] unique_name_in_owner = true -[node name="Exterior" type="AudioStreamPlayer" parent="Ambiance" unique_id=1405716780] +[node name="Exterior" type="AudioStreamPlayer" parent="Ambiances" unique_id=1405716780] unique_name_in_owner = true stream = SubResource("AudioStreamPlaylist_8204s") -[node name="Astra" type="AudioStreamPlayer" parent="Ambiance" unique_id=1244577212] +[node name="Astra" type="AudioStreamPlayer" parent="Ambiances" unique_id=1244577212] unique_name_in_owner = true stream = ExtResource("5_8204s") -[node name="Demeter" type="AudioStreamPlayer" parent="Ambiance" unique_id=351918026] +[node name="Demeter" type="AudioStreamPlayer" parent="Ambiances" unique_id=351918026] unique_name_in_owner = true stream = ExtResource("6_8204s") -[node name="Borea" type="AudioStreamPlayer" parent="Ambiance" unique_id=1857904648] +[node name="Borea" type="AudioStreamPlayer" parent="Ambiances" unique_id=1857904648] unique_name_in_owner = true stream = ExtResource("7_spekb") [node name="Musics" type="Node" parent="." unique_id=1450527710] unique_name_in_owner = true -[node name="Region" type="AudioStreamPlayer" parent="Musics" unique_id=1029114070] +[node name="RegionForestPhase1" type="AudioStreamPlayer" parent="Musics" unique_id=1029114070] unique_name_in_owner = true -stream = SubResource("AudioStreamPlaylist_ajci6") +stream = ExtResource("9_am7i4") + +[node name="RegionForestPhase2" type="AudioStreamPlayer" parent="Musics" unique_id=417543634] +unique_name_in_owner = true +stream = ExtResource("10_tq535") + +[node name="RegionMinePhase1" type="AudioStreamPlayer" parent="Musics" unique_id=152032267] +unique_name_in_owner = true +stream = ExtResource("5_ajci6") + +[node name="RegionMinePhase2" type="AudioStreamPlayer" parent="Musics" unique_id=348001141] +unique_name_in_owner = true +stream = ExtResource("4_2fduo") + +[node name="RegionForestLoop" type="AudioStreamPlayer" parent="Musics" unique_id=482654512] +unique_name_in_owner = true +stream = ExtResource("12_xmumj") +bus = &"Music" + +[node name="RegionMineLoop" type="AudioStreamPlayer" parent="Musics" unique_id=814165127] +unique_name_in_owner = true +stream = ExtResource("11_ngi21") +bus = &"Music" [node name="Title" type="AudioStreamPlayer" parent="Musics" unique_id=2105759422] unique_name_in_owner = true diff --git a/common/audio_manager/scripts/audio_manager.gd b/common/audio_manager/scripts/audio_manager.gd index b187937..f293843 100644 --- a/common/audio_manager/scripts/audio_manager.gd +++ b/common/audio_manager/scripts/audio_manager.gd @@ -1,19 +1,207 @@ extends Node +class_name AudioManagerInstance const MIN_VOLUME = -60. const MAX_VOLUME = 24. const DEFAULT_FADE_TIME : float = 0.5 +const REGION_FIRST_PHASE = [ + "RegionForestPhase1", + "RegionForestPhase2", + "RegionMinePhase1", + "RegionMinePhase2" +] + +const REGION_LOOP_PHASE = [ + "RegionForestLoop", + "RegionForestLoop", + "RegionMineLoop", + "RegionMineLoop" +] + @onready var settings : SettingsData = GameInfo.settings_data -var music_action : AudioAction -var ambiance_action : AudioAction -var playing_music : AudioStreamPlayer = null -var playing_ambiance : AudioStreamPlayer = null +var music_actions : Array[AudioAction] +var ambiance_actions : Array[AudioAction] +var playing_musics : Array[String] = [] +var playing_ambiances : Array[String] = [] var default_volumes := {} +# ----------------- Partie Fonctionnelle ---------------- + +# Fonction s'exécutant à chaque changement de scène +func _on_change_scene(scene : Scene): + stop_all_ambiances() + + match scene.scene_id: + "TITLE": + play_music_alone("Title", false, 0.0) + "INTRO": + stop_all_musics() + "REGION": + play_ambiance("Exterior") + var region_level = GameInfo.game_data.current_region_data.region_level + var first_phase = REGION_FIRST_PHASE[region_level % len(REGION_FIRST_PHASE)] + var loop_phase = REGION_LOOP_PHASE[region_level % len(REGION_LOOP_PHASE)] + print(first_phase) + play_music_alone(first_phase) + queue_music(loop_phase, first_phase) + "COCKPIT": + play_music_alone("Ship", true) + "ASTRA": + stop_all_musics() + play_ambiance_alone("Astra") + "GARAGE": + stop_all_musics() + "BOREA": + stop_all_musics() + play_ambiance_alone("Borea") + +# Fonction s'exécutant à chaque début de timeline +func _on_timeline_started(): + var timeline_name = Dialogic.current_timeline.resource_path.split("/")[-1].trim_suffix(".dtl") + change_ambiances_volume(-10) + + match timeline_name: + "demeter_astra_failed": + play_ambiance("Demeter") + "demeter_ship_presentation": + play_ambiance("Demeter") + "demeter_intro": + play_ambiance("Demeter") + "demeter_post_tutorial": + play_ambiance("Demeter") + "failure": + play_ambiance("Demeter") + +# Fonction s'exécutant à chaque fin de timeline +func _on_timeline_ended(): + if SceneManager.actual_scene: + change_ambiances_volume() + _on_change_scene(SceneManager.actual_scene) + +# Joue la musique définie par player_name, arrête toute les autres musiques immédiatement +# - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer +# - from_random_time : joue depuis un temps aléatoire (true) ou non (false) +# - fade_time : durée du fondu d'arrivée +func play_music_alone( + player_name : String = "", + from_random_time := false, + fade_time := DEFAULT_FADE_TIME +): + stop_all_musics() + play_music(player_name,from_random_time,fade_time) + +# Joue la musique définie par player_name +# - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer +# - from_random_time : joue depuis un temps aléatoire (true) ou non (false) +# - fade_time : durée du fondu d'arrivée +func play_music( + player_name : String = "", + from_random_time := false, + fade_time := DEFAULT_FADE_TIME +): + music_actions.append(AudioLaunch.new( + player_name, + from_random_time, + fade_time + )) + +# Joue la musique définie par player_name juste après la fin de la musique after_player_name, stoppe cette dernière à ce moment +# - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer +# - after_player_name : Nom de la Node dans la scène Godot à attendre, puis à stopper +# - from_random_time : joue depuis un temps aléatoire (true) ou non (false) +# - fade_time : durée du fondu d'arrivée +func queue_music( + player_name : String, + after_player_name : String, + from_random_time := false, + fade_time := DEFAULT_FADE_TIME +): + var player : AudioStreamPlayer = get_player_from_node(after_player_name, %Musics) + if player: + await player.finished + music_actions.append(AudioStop.new(after_player_name)) + music_actions.append(AudioLaunch.new( + player_name, + from_random_time, + fade_time + )) + +# Stoppe la musique définie par player_name +# - player_name : Nom de la Node dans la scène Godot sous la node Musics à jouer +# - fade_time : durée du fondu de départ +func stop_music(player_name : String, fade := DEFAULT_FADE_TIME): + music_actions.append(AudioStop.new(player_name, fade)) + +# Stoppe toutes les musiques +# - fade_time : durée du fondu de départ +func stop_all_musics(fade := DEFAULT_FADE_TIME): + music_actions.append(AudioStopAll.new(fade)) + +# Joue l'ambiance définie par player_name, arrête toute les autres musiques immédiatement +# - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer +# - from_random_time : joue depuis un temps aléatoire (true) ou non (false) +# - fade_time : durée du fondu d'arrivée +func play_ambiance_alone( + player_name : String = "", + from_random_time := false, + fade_time := DEFAULT_FADE_TIME +): + stop_all_ambiances() + play_ambiance(player_name,from_random_time,fade_time) + +# Joue l'ambiance définie par player_name +# - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer +# - from_random_time : joue depuis un temps aléatoire (true) ou non (false) +# - fade_time : durée du fondu d'arrivée +func play_ambiance( + player_name : String = "", + from_random_time := false, + fade_time := DEFAULT_FADE_TIME +): + ambiance_actions.append(AudioLaunch.new( + player_name, + from_random_time, + fade_time + )) + +# Stoppe l'ambiance définie par player_name +# - player_name : Nom de la Node dans la scène Godot sous la node Ambiances à jouer +# - fade_time : durée du fondu de départ +func stop_ambiance(player_name : String, fade := DEFAULT_FADE_TIME): + ambiance_actions.append(AudioStop.new(player_name, fade)) + +# Stoppe toutes les ambiances +# - fade_time : durée du fondu de départ +func stop_all_ambiances(fade := DEFAULT_FADE_TIME): + ambiance_actions.append(AudioStopAll.new(fade)) + +# Change le volume de toutes les ambiances qui jouent +# - db_change : changement du volume en décibel, mettre à 0 pour reset le volume +# - fade_time : durée du fondu de départ +func change_ambiances_volume(db_change := 0., fade := DEFAULT_FADE_TIME): + ambiance_actions.append( + AudioChangeVolumeAll.new( + db_change, + fade + ) + ) + +# Joue un +# - player_name : Nom de la Node dans la scène Godot à jouer +func play_sfx(sfx_name : String): + var player := %Sfx.find_child(sfx_name) as AudioStreamPlayer + if player: + player.play() + else: + printerr("Sfx %s not found" % sfx_name) + + +# ----------------- Partie Technique (pas touche Nils ;D) ---------------- + func _ready(): for player in get_all_players(): player.stop() @@ -28,113 +216,36 @@ func _ready(): Dialogic.timeline_ended.connect(_on_timeline_ended) func _process(_d): - if music_action: - playing_music = process_audio_action( - music_action, - %Musics, - playing_music - ) - music_action = null + if len(music_actions) > 0: + playing_musics = process_audio_actions_for_node(music_actions, %Musics, playing_musics) + music_actions = [] - if ambiance_action: - playing_ambiance = process_audio_action( - ambiance_action, - %Ambiance, - playing_ambiance + if len(ambiance_actions) > 0: + playing_ambiances = process_audio_actions_for_node(ambiance_actions, %Ambiances, playing_ambiances) + ambiance_actions = [] + +func process_audio_actions_for_node( + audio_actions : Array[AudioAction], + parent_node : Node, + current_players: Array[String] +): + var players : Array[String] = current_players.duplicate() + for audio_action in audio_actions: + players = audio_action.process( + self, + parent_node, + players ) - ambiance_action = null + return players -func process_audio_action( - audio_action : AudioAction, - player_search_node: Node, - current_player: AudioStreamPlayer = null -) -> AudioStreamPlayer: - if audio_action is AudioLaunch: - return process_audio_launch(audio_action, player_search_node, current_player) - elif audio_action is AudioStop and current_player and current_player.playing: - stop_player(current_player) - - return null -func process_audio_launch( - audio_launch : AudioLaunch, - player_search_node: Node, - current_player: AudioStreamPlayer = null, -) -> AudioStreamPlayer: - var player = player_search_node.find_child(audio_launch.player_name) +func get_player_from_node(player_name : String, parent_node : Node) -> AudioStreamPlayer: + var player = parent_node.find_child(player_name) if not player: - printerr("Player %s not found in category %s" % [audio_launch.player_name, player_search_node.name]) + printerr("Player %s not found in category %s" % [player_name, parent_node.name]) return null - if current_player and current_player.playing and current_player.name == audio_launch.player_name: - return current_player - elif current_player: - stop_player(current_player) - - start_player(player, audio_launch.from_random_time, audio_launch.fade_time) return player -func _on_change_scene(scene : Scene): - stop_ambiance() - - match scene.scene_id: - "TITLE": - play_music("Title", false, 0.0) - "INTRO": - stop_music() - "REGION": - play_music("Region", true) - play_ambiance("Exterior") - "COCKPIT": - play_music("Ship") - "ASTRA": - stop_music() - play_ambiance("Astra") - "GARAGE": - stop_music() - "BOREA": - stop_music() - play_ambiance("Borea") - -func _on_timeline_started(): - var timeline_name = Dialogic.current_timeline.resource_path.split("/")[-1].trim_suffix(".dtl") - stop_ambiance() - - match timeline_name: - "demeter_astra_failed": - play_ambiance("Demeter") - "demeter_ship_presentation": - play_ambiance("Demeter") - "demeter_intro": - play_ambiance("Demeter") - "demeter_post_tutorial": - play_ambiance("Demeter") - "failure": - play_ambiance("Demeter") - -func _on_timeline_ended(): - if SceneManager.actual_scene: - _on_change_scene(SceneManager.actual_scene) - -func play_music(player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME): - music_action = AudioLaunch.new( - player_name, - from_random_time, - fade_time - ) - -func stop_music(): - music_action = AudioStop.new() - -func play_ambiance(player_name : String = "", from_random_time := false, fade_time := DEFAULT_FADE_TIME): - ambiance_action = AudioLaunch.new( - player_name, - from_random_time, - fade_time - ) - -func stop_ambiance(): - ambiance_action = AudioStop.new() - func fetch_default_volumes(): var all_players := get_all_players() @@ -147,7 +258,7 @@ func setup_players_bus(): player.bus = (AudioServer.get_bus_name(SettingsData.MUSIC_BUS_ID)) elif player.get_parent() == %Sfx: player.bus = (AudioServer.get_bus_name(SettingsData.SFX_BUS_ID)) - elif player.get_parent() == %Ambiance: + elif player.get_parent() == %Ambiances: player.bus = (AudioServer.get_bus_name(SettingsData.AMBIANCE_BUS_ID)) func get_volume(player : AudioStreamPlayer) -> float: @@ -156,12 +267,12 @@ func get_volume(player : AudioStreamPlayer) -> float: func get_all_players() -> Array[AudioStreamPlayer]: var players : Array[AudioStreamPlayer] = [] players.append_array(get_players_from_node(%Musics)) - players.append_array(get_players_from_node(%Ambiance)) + players.append_array(get_players_from_node(%Ambiances)) players.append_array(get_players_from_node(%Sfx)) return players -func get_players_from_node(node : Node) -> Array[AudioStreamPlayer]: +static func get_players_from_node(node : Node) -> Array[AudioStreamPlayer]: var streams : Array[AudioStreamPlayer] = [] for c in node.get_children(): @@ -196,31 +307,108 @@ func stop_player(player : AudioStreamPlayer, fade_time = DEFAULT_FADE_TIME): func reset_volume(player : AudioStreamPlayer): player.volume_db = get_volume(player) -func play_sfx(sfx_name : String): - print(sfx_name) - var player := %Sfx.find_child(sfx_name) as AudioStreamPlayer - if player: - player.play() - else: - printerr("Sfx %s not found" % sfx_name) +@abstract class AudioAction: -class AudioAction: - pass + @abstract func process( + manager: AudioManagerInstance, + parent_node : Node, + current_players : Array[String] + ) -> Array[String] class AudioLaunch extends AudioAction: var player_name : String var from_random_time : bool var fade_time : float + var alone : bool func _init( _player_name : String, _from_random_time := false, _fade_time := DEFAULT_FADE_TIME, + _alone := true, ): player_name = _player_name from_random_time = _from_random_time fade_time = _fade_time + func process( + manager: AudioManagerInstance, + parent_node : Node, + current_players : Array[String] + ) -> Array[String]: + print("%s Launching %s" % [parent_node.name, player_name]) + var player = manager.get_player_from_node(player_name,parent_node) + if player and not player in current_players: + manager.start_player(player, from_random_time, fade_time) + current_players.append(player_name) + return current_players class AudioStop extends AudioAction: - pass + var player_name : String + var fade_time : float + + func _init( + _player_name : String, + _fade_time := DEFAULT_FADE_TIME, + ): + player_name = _player_name + fade_time = fade_time + + func process( + manager: AudioManagerInstance, + parent_node : Node, + current_players : Array[String] + ) -> Array[String]: + print("%s Stopping %s" % [parent_node.name, player_name]) + var player = manager.get_player_from_node(player_name,parent_node) + if player and player in current_players: + manager.stop_player(player, fade_time) + current_players.erase(player_name) + return current_players + +class AudioStopAll extends AudioAction: + var fade_time : float + + func _init( + _fade_time := DEFAULT_FADE_TIME, + ): + fade_time = fade_time + + func process( + manager: AudioManagerInstance, + parent_node : Node, + current_players : Array[String] + ) -> Array[String]: + print("%s Stopping All" % parent_node.name) + for player_name in current_players: + var player := manager.get_player_from_node(player_name,parent_node) + if player: + manager.stop_player(player, fade_time) + return [] + +class AudioChangeVolumeAll extends AudioAction: + var db_change : float + var fade_time : float + + func _init( + _db_change := 1.0, + _fade_time := DEFAULT_FADE_TIME, + ): + db_change = _db_change + fade_time = fade_time + + func process( + manager: AudioManagerInstance, + parent_node : Node, + current_players : Array[String] + ) -> Array[String]: + print("%d Change volume all" % parent_node.name) + for player_name in current_players: + var player := manager.get_player_from_node(player_name,parent_node) + if player: + manager.set_volume( + player, + manager.get_volume(player) + db_change, + fade_time + ) + return current_players