111 lines
2.8 KiB
GDScript
111 lines
2.8 KiB
GDScript
'''音效播放管理器
|
|
可以通過預設的音效表和對應Node的Signal播放對應的音效
|
|
'''
|
|
|
|
class_name ReedSFXManager extends Node
|
|
|
|
|
|
@export var bindings: Array[SFXSignalBinding] = []
|
|
@export var enable_debug: bool = true
|
|
|
|
func _ready() -> void:
|
|
_bind_all()
|
|
|
|
func _bind_all() -> void:
|
|
_dbg_fmt("binding count=%d manager=%s", [bindings.size(), get_path()])
|
|
|
|
for binding in bindings:
|
|
_dbg_fmt(
|
|
"try bind: target_node=%s signal=%s",
|
|
[binding.target_node, binding.signal_name]
|
|
)
|
|
|
|
if not has_node(binding.target_node):
|
|
push_warning(
|
|
"[SFX] target node not found: %s (manager=%s)"
|
|
% [binding.target_node, get_path()]
|
|
)
|
|
continue
|
|
|
|
var target := get_node(binding.target_node)
|
|
_dbg_fmt("target resolved: %s path=%s", [target, target.get_path()])
|
|
|
|
if not target.has_signal(binding.signal_name):
|
|
push_warning(
|
|
"[SFX] signal not found: %s on %s"
|
|
% [binding.signal_name, target.get_path()]
|
|
)
|
|
continue
|
|
|
|
var cb := func(ctx = null):
|
|
_dbg_fmt(
|
|
"callback fired: binding=%s ctx=%s",
|
|
[binding, ctx]
|
|
)
|
|
_on_sfx_signal(binding, ctx)
|
|
|
|
if target.is_connected(binding.signal_name, cb):
|
|
_dbg_fmt("already connected: %s", [binding.signal_name])
|
|
else:
|
|
var err := target.connect(binding.signal_name, cb)
|
|
_dbg_fmt("connect result=%d (OK=0)", [err])
|
|
|
|
func _on_sfx_signal(binding: SFXSignalBinding, args: Variant) -> void:
|
|
if enable_debug and binding.debug_print:
|
|
print_debug(binding.get_debug_message())
|
|
|
|
match binding.spawn_space:
|
|
SFXSignalBinding.SpawnSpace.GLOBAL:
|
|
_play_global(binding)
|
|
|
|
SFXSignalBinding.SpawnSpace.WORLD_POSITION:
|
|
if args is Dictionary and args.has("world_pos"):
|
|
_play_at_position(binding, args["world_pos"])
|
|
|
|
func _dbg(msg: String) -> void:
|
|
if not enable_debug:
|
|
return
|
|
print("[SFX]", msg)
|
|
|
|
func _dbg_fmt(fmt: String, args: Array = []) -> void:
|
|
if not enable_debug:
|
|
return
|
|
print("[SFX]", fmt % args)
|
|
|
|
# -----------------------------
|
|
# 播放逻辑
|
|
# -----------------------------
|
|
|
|
func _play_global(binding: SFXSignalBinding) -> void:
|
|
var target := get_node(binding.target_node)
|
|
if not binding.audio_stream:
|
|
return
|
|
|
|
var player := _create_player(binding)
|
|
add_child(player)
|
|
|
|
player.global_position = target.global_position + binding.offset
|
|
if binding.autoplay:
|
|
player.play()
|
|
|
|
|
|
func _play_at_position(binding: SFXSignalBinding, pos: Vector2) -> void:
|
|
if not binding.audio_stream:
|
|
return
|
|
|
|
|
|
var player := _create_player(binding)
|
|
add_child(player)
|
|
|
|
player.global_position = pos + binding.offset
|
|
if binding.autoplay:
|
|
player.play()
|
|
|
|
func _create_player(binding: SFXSignalBinding) -> AudioStreamPlayer2D:
|
|
var player := AudioStreamPlayer2D.new()
|
|
player.stream = binding.audio_stream
|
|
player.volume_db = binding.volume_db
|
|
player.pitch_scale = binding.pitch_scale
|
|
player.finished.connect(player.queue_free)
|
|
return player
|