134 lines
3.3 KiB
GDScript
134 lines
3.3 KiB
GDScript
@tool
|
|
class_name Sfx extends AudioStreamPlayer
|
|
|
|
@export_enum("交互与效果音", "BGM", "场景背景音") var mode := "交互与效果音":
|
|
set(value):
|
|
mode = value
|
|
notify_property_list_changed()
|
|
# 默认 stream 会变成 default 值
|
|
@export var audio_dict: Dictionary[String, AudioStream]
|
|
|
|
# 当前播放状态注册;节点销毁前卸载
|
|
# TODO BGM 过程抑制场景音效;场景音效随玩家运动呼吸 (结合 Sfx2D)
|
|
# 感应玩家移动:装饰音
|
|
var default_db := 0.0
|
|
|
|
# 只有 场景背景音 生效
|
|
var scene_loop := true
|
|
var scene_autostart := true
|
|
var scene_sense_player_mov := false
|
|
|
|
|
|
func _ready() -> void:
|
|
bus = &"game_sfx"
|
|
default_db = volume_db
|
|
if Engine.is_editor_hint():
|
|
audio_dict.erase("default")
|
|
return
|
|
if stream:
|
|
audio_dict["default"] = stream
|
|
finished.connect(_on_finished)
|
|
|
|
|
|
func switch_stream(stream_name: String, play_next:= false, easing_duration := 1.0):
|
|
if not audio_dict.has(stream_name):
|
|
printerr("Audio stream not found in audio_dict: ", stream_name)
|
|
return
|
|
if easing_duration > 0:
|
|
easing_kill(easing_duration).tween_callback(func():
|
|
stream = audio_dict[stream_name]
|
|
if play_next:
|
|
play()
|
|
)
|
|
else:
|
|
stream = audio_dict[stream_name]
|
|
if play_next:
|
|
play()
|
|
|
|
|
|
func _on_finished() -> void:
|
|
if mode == "场景背景音" and scene_loop:
|
|
play()
|
|
|
|
|
|
func resart(ease_duration := 1.0):
|
|
easing_kill(ease_duration).tween_callback(play)
|
|
|
|
|
|
# queue free 导致 sfx 无法播放,使用全局声源
|
|
func global_play() -> void:
|
|
if stream:
|
|
AudioManager.play_sfx(stream)
|
|
|
|
|
|
# 注意:会导致 volume db 变化
|
|
func easing_kill(duration: float = 2.0) -> Tween:
|
|
# stop with easing
|
|
var tween = create_tween()
|
|
if playing:
|
|
tween.tween_property(self, "volume_db", -80.0, duration)
|
|
tween.tween_callback(stop)
|
|
# set volume_db back to default
|
|
tween.tween_callback(func(): volume_db = default_db)
|
|
return tween
|
|
|
|
|
|
func _get_property_list() -> Array[Dictionary]:
|
|
if mode != "场景背景音":
|
|
return []
|
|
# # 只有 场景背景音 生效
|
|
# var scene_loop := true
|
|
# var scene_autostart := true
|
|
# var scene_sense_player_mov := false
|
|
return [
|
|
{
|
|
"name": "场景背景音配置项",
|
|
"type": TYPE_NIL,
|
|
"usage": PROPERTY_USAGE_GROUP,
|
|
},
|
|
{"name": "自动开始", "type": TYPE_BOOL},
|
|
{"name": "循环播放", "type": TYPE_BOOL},
|
|
{"name": "感应玩家操作", "type": TYPE_BOOL}
|
|
]
|
|
|
|
|
|
func _property_can_revert(property: StringName) -> bool:
|
|
return property == "自动开始" or property == "循环播放" or property == "感应玩家操作"
|
|
|
|
|
|
func _property_get_revert(property: StringName) -> Variant:
|
|
if property == "自动开始" or property == "循环播放":
|
|
return true
|
|
elif property == "感应玩家操作":
|
|
return false
|
|
return null
|
|
|
|
|
|
func _set(property: StringName, value: Variant) -> bool:
|
|
if mode != "场景背景音":
|
|
return false
|
|
if property == "自动开始":
|
|
if value != null:
|
|
autoplay = value
|
|
scene_autostart = value
|
|
return true
|
|
elif property == "循环播放":
|
|
scene_loop = value
|
|
return true
|
|
elif property == "感应玩家操作":
|
|
scene_sense_player_mov = value
|
|
return true
|
|
return false
|
|
|
|
|
|
func _get(property: StringName) -> Variant:
|
|
if mode != "场景背景音":
|
|
return null
|
|
if property == "自动开始":
|
|
return scene_autostart
|
|
elif property == "循环播放":
|
|
return scene_loop
|
|
elif property == "感应玩家操作":
|
|
return scene_sense_player_mov
|
|
return null
|