Initial commit
This commit is contained in:
commit
7becdd23b6
989 changed files with 28526 additions and 0 deletions
17
addons/resonate/music_manager/music_bank.gd
Normal file
17
addons/resonate/music_manager/music_bank.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class_name MusicBank
|
||||
extends Node
|
||||
## A container used to store & group music tracks in your scene.
|
||||
|
||||
|
||||
## This bank's unique identifier.
|
||||
@export var label: String
|
||||
|
||||
## The bus to use for all tracks played from this bank.[br][br]
|
||||
## [b]Note:[/b] this will override the bus set in your project settings (Audio/Manager/Music/Bank)
|
||||
@export var bus: String
|
||||
|
||||
## The underlying process mode for all tracks played from this bank.
|
||||
@export var mode: Node.ProcessMode
|
||||
|
||||
## The collection of tracks associated with this bank.
|
||||
@export var tracks: Array[MusicTrackResource]
|
||||
15
addons/resonate/music_manager/music_bank.svg
Normal file
15
addons/resonate/music_manager/music_bank.svg
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16">
|
||||
<g clip-path="url(#a)">
|
||||
<path fill="url(#b)" d="M14 0H2a2 2 0 0 0-2 2v12c0 1.1.9 2 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2Zm-1.14 10.29a1.81 1.81 0 0 1-1.82 1.79c-1 0-1.82-.82-1.82-1.82a1.83 1.83 0 0 1 2.12-1.79V4.59L6.73 5.92v6.38a2.2 2.2 0 1 1-1.85-2.17V4.15c0-.37.24-.69.59-.79l6.34-1.83a.82.82 0 0 1 1.05.79v7.97Z"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="b" x1="2.9" x2="13.1" y1="16.83" y2="-.83" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#9F9"/>
|
||||
<stop offset=".5" stop-color="#E6D767"/>
|
||||
<stop offset="1" stop-color="#EA6C5E"/>
|
||||
</linearGradient>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M0 0h16v16H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 758 B |
37
addons/resonate/music_manager/music_bank.svg.import
Normal file
37
addons/resonate/music_manager/music_bank.svg.import
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bxfmecl088q55"
|
||||
path="res://.godot/imported/music_bank.svg-4038ad3a11ca952c7a39bede8a3b962e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/resonate/music_manager/music_bank.svg"
|
||||
dest_files=["res://.godot/imported/music_bank.svg-4038ad3a11ca952c7a39bede8a3b962e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
368
addons/resonate/music_manager/music_manager.gd
Normal file
368
addons/resonate/music_manager/music_manager.gd
Normal file
|
|
@ -0,0 +1,368 @@
|
|||
extends Node
|
||||
## The MusicManager is responsible for all music in your game.
|
||||
##
|
||||
## It manages the playback of music tracks, which are constructed with one or more
|
||||
## stems. Each stem can be independently enabled or disabled, allowing for more dynamic
|
||||
## playback. Music tracks can also be crossfaded when switching from one to another.
|
||||
##
|
||||
## @tutorial(View example scenes): https://github.com/hugemenace/resonate/tree/main/examples
|
||||
|
||||
|
||||
const ResonateSettings = preload("../shared/resonate_settings.gd")
|
||||
var _settings = ResonateSettings.new()
|
||||
|
||||
## Emitted only once when the MusicManager has finished setting up and
|
||||
## is ready to play music tracks and enable and disable stems.
|
||||
signal loaded
|
||||
|
||||
## Emitted every time the MusicManager detects that a MusicBank has
|
||||
## been added or removed from the scene tree.
|
||||
signal banks_updated
|
||||
|
||||
## Emitted whenever [signal MusicManager.loaded] or
|
||||
## [signal MusicManager.pools_updated] is emitted.
|
||||
signal updated
|
||||
|
||||
## Whether the MusicManager has completed setup and is ready to
|
||||
## play music tracks and enable and disable stems.
|
||||
var has_loaded: bool = false
|
||||
|
||||
var _music_table: Dictionary = {}
|
||||
var _music_table_hash: int
|
||||
var _music_streams: Array[StemmedMusicStreamPlayer] = []
|
||||
var _volume: float
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Lifecycle methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
func _init():
|
||||
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_auto_add_music()
|
||||
|
||||
var scene_root = get_tree().root.get_tree()
|
||||
scene_root.node_added.connect(_on_scene_node_added)
|
||||
scene_root.node_removed.connect(_on_scene_node_removed)
|
||||
|
||||
|
||||
func _process(_p_delta) -> void:
|
||||
if _music_table_hash != _music_table.hash():
|
||||
_music_table_hash = _music_table.hash()
|
||||
banks_updated.emit()
|
||||
updated.emit()
|
||||
|
||||
if has_loaded:
|
||||
return
|
||||
|
||||
has_loaded = true
|
||||
loaded.emit()
|
||||
updated.emit()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
## Play a music track from a SoundBank, and optionally fade-in
|
||||
## or crossfade over the provided [b]p_crossfade_time[/b].
|
||||
func play(p_bank_label: String, p_track_name: String, p_crossfade_time: float = 5.0) -> bool:
|
||||
if not has_loaded:
|
||||
push_error("Resonate - The music track [%s] on bank [%s] can't be played as the MusicManager has not loaded yet. Use the [loaded] signal/event to determine when it is ready." % [p_track_name, p_bank_label])
|
||||
return false
|
||||
|
||||
if not _music_table.has(p_bank_label):
|
||||
push_error("Resonate - Tried to play the music track [%s] from an unknown bank [%s]." % [p_track_name, p_bank_label])
|
||||
return false
|
||||
|
||||
if not _music_table[p_bank_label]["tracks"].has(p_track_name):
|
||||
push_error("Resonate - Tried to play an unknown music track [%s] from the bank [%s]." % [p_track_name, p_bank_label])
|
||||
return false
|
||||
|
||||
var bank = _music_table[p_bank_label] as Dictionary
|
||||
var track = bank["tracks"][p_track_name] as Dictionary
|
||||
var stems = track["stems"] as Array
|
||||
|
||||
if stems.size() == 0:
|
||||
push_error("Resonate - The music track [%s] on bank [%s] has no stems, you'll need to add one at minimum." % [p_track_name, p_bank_label])
|
||||
return false
|
||||
|
||||
for stem in stems:
|
||||
if stem.stream == null:
|
||||
push_error("Resonate - The stem [%s] on the music track [%s] on bank [%s] does not have an audio stream, you'll need to add one." % [stem.name, p_track_name, p_bank_label])
|
||||
return false
|
||||
|
||||
if not ResonateUtils.is_stream_looped(stem.stream):
|
||||
push_warning("Resonate - The stem [%s] on the music track [%s] on bank [%s] is not set to loop, which will cause it to work incorrectly." % [stem.name, p_track_name, p_bank_label])
|
||||
|
||||
var bus = _get_bus(bank.bus, track.bus)
|
||||
var player = StemmedMusicStreamPlayer.create(p_bank_label, p_track_name, bus, bank.mode, _volume)
|
||||
|
||||
if _music_streams.size() > 0:
|
||||
for stream in _music_streams:
|
||||
stream.stop_stems(p_crossfade_time)
|
||||
|
||||
_music_streams.append(player)
|
||||
|
||||
add_child(player)
|
||||
|
||||
player.start_stems(stems, p_crossfade_time)
|
||||
player.stopped.connect(_on_player_stopped.bind(player))
|
||||
|
||||
return true
|
||||
|
||||
|
||||
## Check whether the MusicManager is playing from a specific bank, or any track
|
||||
## with the given name, or more specifically a certain track from a certain bank.
|
||||
func is_playing(p_bank_label: String = "", p_track_name: String = "") -> bool:
|
||||
if not has_loaded:
|
||||
return false
|
||||
|
||||
if _music_streams.size() == 0:
|
||||
return false
|
||||
|
||||
var current_player = _get_current_player()
|
||||
var is_playing = not current_player.is_stopping
|
||||
var bank_label = current_player.bank_label
|
||||
var track_name = current_player.track_name
|
||||
|
||||
if p_bank_label == "" and p_track_name == "":
|
||||
return is_playing
|
||||
|
||||
if p_bank_label != "" and p_track_name == "":
|
||||
return bank_label == p_bank_label and is_playing
|
||||
|
||||
if p_bank_label == "" and p_track_name != "":
|
||||
return track_name == p_track_name and is_playing
|
||||
|
||||
return bank_label == p_bank_label and track_name == p_track_name and is_playing
|
||||
|
||||
|
||||
## Stop the playback of all music.
|
||||
func stop(p_fade_time: float = 5.0) -> void:
|
||||
if not _is_playing_music():
|
||||
push_warning("Resonate - Cannot stop the music track as there is no music currently playing.")
|
||||
return
|
||||
|
||||
var current_player = _get_current_player()
|
||||
|
||||
current_player.stop_stems(p_fade_time)
|
||||
|
||||
|
||||
## Check whether the MusicManager should skip playing a new track. It will return true if the
|
||||
## MusicManager has not loaded yet, or if the flag you provide is not [b]false[/b] or [b]null[/b].
|
||||
func should_skip_playing(p_flag) -> bool:
|
||||
return not has_loaded or (p_flag != false and p_flag != null)
|
||||
|
||||
|
||||
## Set the volume of the current music track (if playing) and all future tracks to be played.
|
||||
func set_volume(p_volume: float) -> void:
|
||||
_volume = p_volume
|
||||
|
||||
if not _is_playing_music():
|
||||
return
|
||||
|
||||
var current_player = _get_current_player()
|
||||
|
||||
current_player.set_volume(_volume)
|
||||
|
||||
|
||||
## Enable the specified stem on the currently playing music track.
|
||||
func enable_stem(p_name: String, p_fade_time: float = 2.0) -> void:
|
||||
_set_stem(p_name, true, p_fade_time)
|
||||
|
||||
|
||||
## Disable the specified stem on the currently playing music track.
|
||||
func disable_stem(p_name: String, p_fade_time: float = 2.0) -> void:
|
||||
_set_stem(p_name, false, p_fade_time)
|
||||
|
||||
|
||||
## Set the volume for the specified stem on the currently playing music track.
|
||||
func set_stem_volume(p_name: String, p_volume: float) -> void:
|
||||
if not _is_playing_music():
|
||||
push_warning("Resonate - Cannot set the volume of stem [%s] as there is no music currently playing." % p_name)
|
||||
return
|
||||
|
||||
var current_player = _get_current_player()
|
||||
|
||||
current_player.set_stem_volume(p_name, p_volume)
|
||||
|
||||
|
||||
## Get the underlying details of the provided stem for the currently playing music track.
|
||||
func get_stem_details(p_name: String) -> Variant:
|
||||
if not _is_playing_music():
|
||||
push_warning("Resonate - Cannot get the details for stem [%s] as there is no music currently playing." % p_name)
|
||||
return
|
||||
|
||||
var current_player = _get_current_player()
|
||||
|
||||
return current_player.get_stem_details(p_name)
|
||||
|
||||
|
||||
## Will automatically stop the provided music track when the provided
|
||||
## [b]p_base[/b] is removed from the scene tree.
|
||||
func stop_on_exit(p_base: Node, p_bank_label: String, p_track_name: String, p_fade_time: float = 5.0) -> void:
|
||||
p_base.tree_exiting.connect(_on_music_player_exiting.bind(p_bank_label, p_track_name, p_fade_time))
|
||||
|
||||
|
||||
## Will automatically stop the provided music track when the provided
|
||||
## [b]p_base[/b] is removed from the scene tree.[br][br]
|
||||
## [b]Note:[/b] This method has been deprecated, please use [method MusicManager.stop_on_exit] instead.
|
||||
## @deprecated
|
||||
func auto_stop(p_base: Node, p_bank_label: String, p_track_name: String, p_fade_time: float = 5.0) -> void:
|
||||
push_warning("Resonate - auto_stop has been deprecated, please use stop_on_exit instead.")
|
||||
stop_on_exit(p_base, p_bank_label, p_track_name, p_fade_time)
|
||||
|
||||
|
||||
## Manually add a new SoundBank into the music track cache.
|
||||
func add_bank(p_bank: MusicBank) -> void:
|
||||
_add_bank(p_bank)
|
||||
|
||||
|
||||
## Remove the provided bank from the music track cache.
|
||||
func remove_bank(p_bank_label: String) -> void:
|
||||
if not _music_table.has(p_bank_label):
|
||||
return
|
||||
|
||||
_music_table.erase(p_bank_label)
|
||||
|
||||
|
||||
## Clear all banks from the music track cache.
|
||||
func clear_banks() -> void:
|
||||
_music_table.clear()
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
func _on_scene_node_added(p_node: Node) -> void:
|
||||
if not p_node is MusicBank:
|
||||
return
|
||||
|
||||
_add_bank(p_node)
|
||||
|
||||
|
||||
func _on_scene_node_removed(p_node: Node) -> void:
|
||||
if not p_node is MusicBank:
|
||||
return
|
||||
|
||||
_remove_bank(p_node)
|
||||
|
||||
|
||||
func _auto_add_music() -> void:
|
||||
var music_banks = ResonateUtils.find_all_nodes(self, "MusicBank")
|
||||
|
||||
for music_bank in music_banks:
|
||||
_add_bank(music_bank)
|
||||
|
||||
_music_table_hash = _music_table.hash()
|
||||
|
||||
|
||||
func _add_bank(p_bank: MusicBank) -> void:
|
||||
if _music_table.has(p_bank.label):
|
||||
_music_table[p_bank.label]["ref_count"] = \
|
||||
_music_table[p_bank.label]["ref_count"] + 1
|
||||
|
||||
return
|
||||
|
||||
_music_table[p_bank.label] = {
|
||||
"name": p_bank.label,
|
||||
"bus": p_bank.bus,
|
||||
"mode": p_bank.mode,
|
||||
"tracks": _create_tracks(p_bank.tracks),
|
||||
"ref_count": 1,
|
||||
}
|
||||
|
||||
|
||||
func _remove_bank(p_bank: MusicBank) -> void:
|
||||
if not _music_table.has(p_bank.label):
|
||||
return
|
||||
|
||||
if _music_table[p_bank.label]["ref_count"] == 1:
|
||||
_music_table.erase(p_bank.label)
|
||||
return
|
||||
|
||||
_music_table[p_bank.label]["ref_count"] = \
|
||||
_music_table[p_bank.label]["ref_count"] - 1
|
||||
|
||||
|
||||
func _create_tracks(p_tracks: Array[MusicTrackResource]) -> Dictionary:
|
||||
var tracks = {}
|
||||
|
||||
for track in p_tracks:
|
||||
tracks[track.name] = {
|
||||
"name": track.name,
|
||||
"bus": track.bus,
|
||||
"stems": _create_stems(track.stems),
|
||||
}
|
||||
|
||||
return tracks
|
||||
|
||||
|
||||
func _create_stems(p_stems: Array[MusicStemResource]) -> Array:
|
||||
var stems = []
|
||||
|
||||
for stem in p_stems:
|
||||
stems.append({
|
||||
"name": stem.name,
|
||||
"enabled": stem.enabled,
|
||||
"volume": stem.volume,
|
||||
"stream": stem.stream,
|
||||
})
|
||||
|
||||
return stems
|
||||
|
||||
|
||||
func _get_bus(p_bank_bus: String, p_track_bus: String) -> String:
|
||||
if p_track_bus != null and p_track_bus != "":
|
||||
return p_track_bus
|
||||
|
||||
if p_bank_bus != null and p_bank_bus != "":
|
||||
return p_bank_bus
|
||||
|
||||
return ProjectSettings.get_setting(
|
||||
_settings.MUSIC_BANK_BUS_SETTING_NAME,
|
||||
_settings.MUSIC_BANK_BUS_SETTING_DEFAULT)
|
||||
|
||||
|
||||
func _is_playing_music() -> bool:
|
||||
return _music_streams.size() > 0
|
||||
|
||||
|
||||
func _get_current_player() -> StemmedMusicStreamPlayer:
|
||||
if _music_streams.size() == 0:
|
||||
return null
|
||||
|
||||
return _music_streams.back() as StemmedMusicStreamPlayer
|
||||
|
||||
|
||||
func _set_stem(p_name: String, p_enabled: bool, p_fade_time: float) -> void:
|
||||
if not _is_playing_music():
|
||||
push_warning("Resonate - Cannot toggle the stem [%s] as there is no music currently playing." % p_name)
|
||||
return
|
||||
|
||||
var current_player = _get_current_player()
|
||||
|
||||
current_player.toggle_stem(p_name, p_enabled, p_fade_time)
|
||||
|
||||
|
||||
func _on_music_player_exiting(p_bank_label: String, p_track_name: String, p_fade_time: float) -> void:
|
||||
if not is_playing(p_bank_label, p_track_name):
|
||||
return
|
||||
|
||||
stop(p_fade_time)
|
||||
|
||||
|
||||
func _on_player_stopped(p_player: StemmedMusicStreamPlayer) -> void:
|
||||
if not _is_playing_music():
|
||||
return
|
||||
|
||||
_music_streams.erase(p_player)
|
||||
remove_child(p_player)
|
||||
16
addons/resonate/music_manager/music_stem_resource.gd
Normal file
16
addons/resonate/music_manager/music_stem_resource.gd
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
class_name MusicStemResource
|
||||
extends Resource
|
||||
## A container used to store the details of one particular music track's stem.
|
||||
|
||||
|
||||
## This stem's unique identifier within the scope of the track it belongs to.
|
||||
@export var name: String = ""
|
||||
|
||||
## Whether this stem will start playing automatically when the track starts.
|
||||
@export var enabled: bool = false
|
||||
|
||||
## The volume of the stem.
|
||||
@export_range(-80.0, 6.0, 0.1, "suffix:dB") var volume: float = 0.0
|
||||
|
||||
## The audio stream associated with this stem.
|
||||
@export var stream: AudioStream
|
||||
14
addons/resonate/music_manager/music_track_resource.gd
Normal file
14
addons/resonate/music_manager/music_track_resource.gd
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
class_name MusicTrackResource
|
||||
extends Resource
|
||||
## A container used to store the details of a music track and all of its corresponding stems.
|
||||
|
||||
|
||||
## This track's unique identifier within the scope of the bank it belongs to.
|
||||
@export var name: String = ""
|
||||
|
||||
## The bus to use for this particular track.[br][br]
|
||||
## [b]Note:[/b] this will override the bus set on the bank, or in your project settings (Audio/Manager/Music/Bank)
|
||||
@export var bus: String = ""
|
||||
|
||||
## The collection of stems that make up this track.
|
||||
@export var stems: Array[MusicStemResource]
|
||||
189
addons/resonate/music_manager/stemmed_music_stream_player.gd
Normal file
189
addons/resonate/music_manager/stemmed_music_stream_player.gd
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
class_name StemmedMusicStreamPlayer
|
||||
extends AudioStreamPlayer
|
||||
## An extended AudioStreamPlayer capable of managing and playing a
|
||||
## collection of stems that make up a music track.
|
||||
|
||||
|
||||
## Emitted when this player has completely stopped playing a track.
|
||||
signal stopped
|
||||
|
||||
## True when this player is in the process of shutting down and stopping a track.
|
||||
var is_stopping: bool
|
||||
|
||||
## The label of the bank that this player's track came from.
|
||||
var bank_label: String
|
||||
|
||||
## The name of the track associated with this player.
|
||||
var track_name: String
|
||||
|
||||
const _DISABLED_VOLUME: float = -80
|
||||
const _START_TRANS: Tween.TransitionType = Tween.TRANS_QUART
|
||||
const _START_EASE: Tween.EaseType = Tween.EASE_OUT
|
||||
const _STOP_TRANS: Tween.TransitionType = Tween.TRANS_QUART
|
||||
const _STOP_EASE: Tween.EaseType = Tween.EASE_IN
|
||||
|
||||
var _fade_tween: Tween
|
||||
var _stems: Dictionary
|
||||
var _max_volume: float
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Public methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
## Create a new player associated with a given bank and track.
|
||||
static func create(p_bank_label: String, p_track_name: String, p_bus: String, p_mode: Node.ProcessMode, p_max_volume: float) -> StemmedMusicStreamPlayer:
|
||||
var player = StemmedMusicStreamPlayer.new()
|
||||
var stream = AudioStreamPolyphonic.new()
|
||||
|
||||
player.bank_label = p_bank_label
|
||||
player.track_name = p_track_name
|
||||
player.stream = stream
|
||||
player.process_mode = p_mode
|
||||
player.bus = p_bus
|
||||
player.volume_db = _DISABLED_VOLUME
|
||||
player._max_volume = p_max_volume
|
||||
player.is_stopping = false
|
||||
|
||||
return player
|
||||
|
||||
|
||||
## Start the collection of stems associated with the track on this player.
|
||||
## This is what fundamentally starts the music track.[br][br]
|
||||
## [b]Note:[/b] this should only be called once.
|
||||
func start_stems(p_stems: Array, p_crossfade_time: float) -> void:
|
||||
if playing:
|
||||
return
|
||||
|
||||
stream.polyphony = p_stems.size()
|
||||
max_polyphony = p_stems.size()
|
||||
|
||||
play()
|
||||
|
||||
var playback = get_stream_playback() as AudioStreamPlaybackPolyphonic
|
||||
|
||||
for stem in p_stems:
|
||||
var stream_id = playback.play_stream(stem.stream)
|
||||
var max_volume = stem.volume
|
||||
var volume = max_volume if stem.enabled else _DISABLED_VOLUME
|
||||
|
||||
playback.set_stream_volume(stream_id, volume)
|
||||
|
||||
_stems[stem.name] = {
|
||||
"name": stem.name,
|
||||
"enabled": stem.enabled,
|
||||
"stream_id": stream_id,
|
||||
"volume": volume,
|
||||
"max_volume": max_volume,
|
||||
"tween": null,
|
||||
}
|
||||
|
||||
_fade_tween = create_tween()
|
||||
_fade_tween \
|
||||
.tween_property(self, "volume_db", _max_volume, p_crossfade_time) \
|
||||
.set_trans(_START_TRANS) \
|
||||
.set_ease(_START_EASE)
|
||||
|
||||
|
||||
## Toggle (enable or disable) the specified stem associated with the track on this player.
|
||||
func toggle_stem(p_name: String, p_enabled: bool, p_fade_time: float) -> void:
|
||||
if not _stems.has(p_name):
|
||||
push_warning("Resonate - Cannot toggle the stem [%s] on music track [%s] from bank [%s] as it does not exist." % [p_name, track_name, bank_label])
|
||||
return
|
||||
|
||||
var playback = get_stream_playback() as AudioStreamPlaybackPolyphonic
|
||||
var stem = _stems[p_name]
|
||||
var old_tween = stem.tween as Tween
|
||||
var new_tween = create_tween()
|
||||
var target_volume = stem.max_volume if p_enabled else _DISABLED_VOLUME
|
||||
|
||||
if old_tween != null:
|
||||
old_tween.kill()
|
||||
|
||||
_stems[p_name]["tween"] = new_tween
|
||||
_stems[p_name]["enabled"] = p_enabled
|
||||
|
||||
var transition = _START_TRANS if p_enabled else _STOP_TRANS
|
||||
var easing = _START_EASE if p_enabled else _STOP_EASE
|
||||
|
||||
new_tween \
|
||||
.tween_method(_tween_stem_volume.bind(p_name), stem.volume, target_volume, p_fade_time) \
|
||||
.set_trans(transition) \
|
||||
.set_ease(easing)
|
||||
|
||||
|
||||
## Set the volume of this player.[br][br]
|
||||
## [b]Note:[/b] if called when the player is still fading in or out, it will
|
||||
## immediately cancel the fade and set the volume at specified level.
|
||||
func set_volume(p_volume: float) -> void:
|
||||
if _fade_tween != null and _fade_tween.is_running():
|
||||
_fade_tween.kill()
|
||||
|
||||
_max_volume = p_volume
|
||||
volume_db = p_volume
|
||||
|
||||
|
||||
## Set the volume of a specific stem associated with this track.[br][br]
|
||||
## [b]Note:[/b] if called when the stem is still fading in or out, it will
|
||||
## immediately cancel the fade and set the volume at specified level.
|
||||
func set_stem_volume(p_name: String, p_volume: float) -> void:
|
||||
var playback = get_stream_playback() as AudioStreamPlaybackPolyphonic
|
||||
var stem = _stems[p_name]
|
||||
|
||||
if stem["tween"] != null and stem["tween"].is_running():
|
||||
stem["tween"].kill()
|
||||
|
||||
playback.set_stream_volume(stem.stream_id, p_volume)
|
||||
|
||||
_stems[p_name]["volume"] = p_volume
|
||||
_stems[p_name]["max_volume"] = p_volume
|
||||
|
||||
|
||||
## This will stop all stems associated with this player, causing it to shut-down and stop.
|
||||
func stop_stems(p_fade_time: float) -> void:
|
||||
if is_stopping:
|
||||
return
|
||||
|
||||
is_stopping = true
|
||||
|
||||
var tween = create_tween()
|
||||
tween \
|
||||
.tween_property(self, "volume_db", _DISABLED_VOLUME, p_fade_time) \
|
||||
.set_trans(_STOP_TRANS) \
|
||||
.set_ease(_STOP_EASE)
|
||||
|
||||
tween.finished.connect(_on_stop_stems_tween_finished)
|
||||
|
||||
|
||||
## Get the underlying details of the provided stem for the currently playing music track.
|
||||
func get_stem_details(p_name: String) -> Variant:
|
||||
if not _stems.has(p_name):
|
||||
push_warning("Resonate - Cannot get the details for stem [%s] on music track [%s] from bank [%s] as it does not exist." % [p_name, track_name, bank_label])
|
||||
return null
|
||||
|
||||
var stem = _stems[p_name]
|
||||
|
||||
return {
|
||||
"name": stem.name,
|
||||
"enabled": stem.enabled,
|
||||
"volume": stem.volume,
|
||||
}
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Private methods
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
|
||||
func _tween_stem_volume(p_target_volume: float, p_name: String) -> void:
|
||||
var playback = get_stream_playback() as AudioStreamPlaybackPolyphonic
|
||||
var stem = _stems[p_name]
|
||||
|
||||
playback.set_stream_volume(stem.stream_id, p_target_volume)
|
||||
|
||||
_stems[p_name]["volume"] = p_target_volume
|
||||
|
||||
|
||||
func _on_stop_stems_tween_finished() -> void:
|
||||
stopped.emit()
|
||||
Loading…
Add table
Add a link
Reference in a new issue