@tool @icon("res://addons/gd-dynamic-sound/icon.svg") class_name DynamicSoundPlayer2D ## 2D positional variant of [DynamicSoundPlayer]. ## ## Same playlist, intensity, fade, and pause behaviour — distance-attenuated ## from a 2D position relative to the listener. extends AudioStreamPlayer2D ## Songs to play in order. Mutated as songs finish: each finished song is ## popped, and re-appended at the back when [member Loop] is on. @export var Playlist : DynamicSoundPlaylist; ## Runtime mix between the three intensity layers. [code]0[/code] = least intense, [code]1[/code] = most intense. @export_range(0, 1) var Intensity : float = 0: set(value): Intensity = value; if _core: _core.apply_stream_volumes(volume_db); ## How the playlist loops when the current song ends. ## [code]Single[/code] keeps playing the same song; [code]All[/code] advances ## through the playlist and wraps from the last song back to the first. @export var LoopMode : DynamicSoundConstants.LoopMode = DynamicSoundConstants.LoopMode.All; ## How [method advance_to_next_song] and [method advance_to_track] transition between songs. ## Does not affect the natural end-of-song advance, which always uses the song's reverb tail. @export var SkipMode : DynamicSoundConstants.SkipMode = DynamicSoundConstants.SkipMode.UseReverbTail: set(value): SkipMode = value; notify_property_list_changed(); ## Crossfade duration in seconds when [member SkipMode] is [code]CrossFade[/code]. @export var CrossFadeDuration : float = 1.0; var _core : DynamicSoundPlayerCore; func _set(property: StringName, value: Variant) -> bool: if property == &"volume_db": if _core: _core.apply_stream_volumes(value); return false; return false; func _enter_tree() -> void: if not Engine.is_editor_hint(): return; if stream == null: stream = AudioStreamPolyphonic.new(); if bus == &"Master" and AudioServer.get_bus_index("Music") != -1: bus = "Music"; func _validate_property(property: Dictionary) -> void: if property.name == "CrossFadeDuration" and SkipMode != DynamicSoundConstants.SkipMode.CrossFade: property.usage &= ~PROPERTY_USAGE_EDITOR; func _ready() -> void: _core = DynamicSoundPlayerCore.new(self); _core.ready(); func _process(delta: float) -> void: if _core: _core.process(delta); ## Start (or resume) playlist playback. Useful when [code]autoplay[/code] is false. func play_playlist() -> void: if _core: _core.play_playlist(); ## Index of the song most recently started in the playlist. func get_current_song_index() -> int: return _core.get_current_song_index() if _core else 0; ## Skip to the next song (wraps to index 0). Smooth via the current song's reverb tail. func advance_to_next_song() -> void: if _core: _core.advance_to_next_song(); ## Jump to the song at [param index]. Smooth via the current song's reverb tail. func advance_to_track(index: int) -> void: if _core: _core.advance_to_track(index); ## Pause playback. Call [method resume] to continue. func pause() -> void: if _core: _core.pause(); ## Resume playback after a [method pause]. func resume() -> void: if _core: _core.resume(); ## True if a song is currently playing (and not paused). func is_song_playing() -> bool: return _core != null and _core.is_song_playing(); ## Start playback (if needed) and fade volume up from silent over [param duration] seconds. func fade_in(duration: float) -> void: if _core: _core.fade_in(duration); ## Fade volume to silent over [param duration] seconds, then stop playback. func fade_out(duration: float) -> void: if _core: _core.fade_out(duration);