maxgame/addons/popochiu/engine/audio_manager/audio_cue.gd
2025-07-17 01:49:18 -04:00

179 lines
6.6 KiB
GDScript

@tool
class_name PopochiuAudioCue
extends Resource
## Used to play audio files with extra properties.
##
## You can set the pitch (with random values), volume, and audio bus, as well as specify whether
## it loops, and whether it is 2D positioned.
## The audio file to play.
@export var audio: AudioStream
## Whether the audio file will loop when played.
@export var loop := false : set = set_loop
## Whether this audio cue uses a 2D position.
@export var is_2d := false
## Whether the audio can be played simultaneously with other instances of itself. Especially useful
## for audio cues set in a loop (where [member loop] is [code]true[/code]).
@export var can_play_simultaneous := true
## The pitch value (in semitones) to use when playing the audio file.
@export var pitch := 0.0
## The volume to use when playing the audio file.
@export var volume := 0.0
## The range of values to use for randomly changing the pitch of the audio file when played.
@export var rnd_pitch := Vector2.ZERO
## The range of values to use to randomly changing the volume of the audio file when played.
@export var rnd_volume := Vector2.ZERO
## Maximum distance from which the audio file is still hearable. This only works if [member is_2d]
## is [code]true[/code].
@export var max_distance := 2000
## The audio bus in which the audio file will be played.
@export var bus := "Master"
#region Public #####################################################################################
## Plays this audio cue with a fade that lasts [param duration] seconds. If [param wait_to_end] is
## set to [code]true[/code], the function will wait for the audio to finish. You can specify the
## starting volume with [param from] and the target volume with [param to], as well as the
## [param position_2d] of the [AudioStreamPlayer] or [AudioStreamPlayer2D] that will play the audio
## file.
func fade(
duration := 1.0, wait_to_end := false, from := -80.0, to := INF, position_2d := Vector2.ZERO
) -> void:
if wait_to_end:
await PopochiuUtils.e.am.play_fade_cue(resource_name, duration, from, to, position_2d, true)
else:
PopochiuUtils.e.am.play_fade_cue(resource_name, duration, from, to, position_2d)
## Plays this audio cue with a fade that lasts [param duration] seconds. If [param wait_to_end] is
## set to [code]true[/code], the function will wait for the audio to finish. You can specify the
## starting volume with [param from] and the target volume with [param to], as well as the
## [param position_2d] of the [AudioStreamPlayer] or [AudioStreamPlayer2D] that will play the audio
## file.[br][br]
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
func queue_fade(
duration := 1.0, wait_to_end := false, from := -80.0, to := INF, position_2d := Vector2.ZERO
) -> Callable:
return func ():
if wait_to_end:
await fade(duration, wait_to_end, from, to, position_2d)
else:
fade(duration, wait_to_end, from, to, position_2d)
await PopochiuUtils.e.get_tree().process_frame
## Stops the audio cue, with an optional fade effect lasting [param fade_duration] seconds.
func stop(fade_duration := 0.0) -> void:
PopochiuUtils.e.am.stop(resource_name, fade_duration)
## Stops the audio cue, with an optional fade effect lasting [param fade_duration] seconds.[br][br]
## [i]This method is intended to be used inside a [method Popochiu.queue] of instructions.[/i]
func queue_stop(fade_duration := 0.0) -> Callable:
return func ():
stop(fade_duration)
await PopochiuUtils.e.get_tree().process_frame
## Changes the [member AudioStreamPlayer.pitch_scale] of the [AudioStreamPlayer] playing the audio
## file associated with this audio cue to [param pitch]. If the audio was played with a 2D position,
## then [member AudioStreamPlayer2D.pitch_scale] will be affected.
func change_stream_pitch(pitch := 0.0) -> void:
PopochiuUtils.e.am.change_cue_pitch(resource_name, pitch)
## Changes the [member AudioStreamPlayer.volume_db] of the [AudioStreamPlayer] playing the audio
## file associated with this audio cue to [param volume]. If the audio was played with a 2D
## position, then [member AudioStreamPlayer2D.volume_db] will be affected.
func change_stream_volume(volume := 0.0) -> void:
PopochiuUtils.e.am.change_cue_volume(resource_name, volume)
## Returns the value of [member AudioStreamPlayer.pitch_scale] to be applied to the
## [AudioStreamPlayer] playing the audio file associated with this audio cue. If the audio was
## played with a 2D position, then [member AudioStreamPlayer2D.volume_db] will be affected.
func get_pitch_scale() -> float:
var p := PopochiuUtils.a.semitone_to_pitch(pitch)
if rnd_pitch != Vector2.ZERO:
p = _get_rnd_pitch()
return p
## Returns the playback position of this audio cue.
func get_cue_playback_position() -> float:
return PopochiuUtils.e.am.get_cue_playback_position(resource_name)
## Maps [param values] to the properties of this audio cue. This is used by TabAudio when changing
## the script of the audio cue to one of the types: [AudioCueSound] or [AudioCueMusic].
func set_values(values: Dictionary) -> void:
resource_name = values.resource_name
audio = values.audio
loop = values.loop
is_2d = values.is_2d
pitch = values.pitch
volume = values.volume
rnd_pitch = values.rnd_pitch
rnd_volume = values.rnd_volume
max_distance = values.max_distance
bus = values.bus
## Returns the properties of this audio cue as a [Dictionary]. This is used by TabAudio when
## changing the script of the audio cue to one of the types: [AudioCueSound] or [AudioCueMusic].
func get_values() -> Dictionary:
return {
resource_name = resource_name,
audio = audio,
loop = loop,
is_2d = is_2d,
pitch = pitch,
volume = volume,
rnd_pitch = rnd_pitch,
rnd_volume = rnd_volume,
max_distance = max_distance,
bus = bus
}
## Returns [code]true[/code] if playing.
func is_playing() -> bool:
return PopochiuUtils.a.is_playing_cue(resource_name)
#endregion
#region SetGet #####################################################################################
func set_loop(value: bool) -> void:
loop = value
if not audio: return
match audio.get_class():
'AudioStreamOggVorbis', 'AudioStreamMP3':
audio.loop = value
'AudioStreamWAV':
(audio as AudioStreamWAV).loop_mode = (
AudioStreamWAV.LOOP_FORWARD if value else AudioStreamWAV.LOOP_DISABLED
)
notify_property_list_changed()
#endregion
#region Private ####################################################################################
func _get_rnd_pitch() -> float:
randomize()
return PopochiuUtils.a.semitone_to_pitch(pitch + randf_range(rnd_pitch.x, rnd_pitch.y))
func _get_rnd_volume() -> float:
randomize()
return volume + randf_range(rnd_volume.x, rnd_volume.y)
#endregion