MagicNStuff/game/src/core/dialog/dialog_player.gd

92 lines
2.5 KiB
GDScript

class_name DialogPlayer
extends Node
signal dialog_finished(dialog_key: StringName)
static var active_dialog_playbacks: Array[DialogEntryPlayback] = []
@export_node_path("AudioStreamPlayer", "AudioStreamPlayer2D", "AudioStreamPlayer3D")
var audio_player: NodePath: set = set_audio_player
@export var dialogs: Dictionary[StringName, DialogEntry] = {}
var _audio_player: Node
var _current_dialog_key: StringName
var _current_dialog_playback: DialogEntryPlayback
func _ready() -> void:
set_process(false)
set_audio_player(audio_player)
func _process(_delta: float) -> void:
if is_instance_valid(_audio_player) and is_instance_valid(_current_dialog_playback):
_current_dialog_playback.playback_position = _audio_player.get_playback_position()
func set_audio_player(audio_player_path: NodePath) -> void:
if is_instance_valid(_audio_player):
_audio_player.finished.disconnect(_on_dialog_finished)
audio_player = audio_player_path
_audio_player = get_node_or_null(audio_player)
if not is_instance_valid(_audio_player):
set_process(false)
return
if (
not _audio_player.has_method(&"play")
or not _audio_player.has_method(&"get_playback_position")
or not &"playing" in _audio_player
or not _audio_player.has_signal(&"finished")
):
_audio_player = null
push_error("audio_player is not a valid player.")
return
set_process(_audio_player.playing)
if not _audio_player.finished.is_connected(_on_dialog_finished):
_audio_player.finished.connect(_on_dialog_finished)
func play(entry_key: StringName, from_position: float = 0.0) -> void:
var dialog_entry: DialogEntry = dialogs.get(entry_key)
if is_instance_valid(dialog_entry):
stop_dialog()
_audio_player.stream = dialog_entry.get_voiceline_stream()
_current_dialog_key = entry_key
_current_dialog_playback = DialogEntryPlayback.new(dialog_entry)
active_dialog_playbacks.append(_current_dialog_playback)
_audio_player.play(from_position)
set_process(true)
func get_current_dialog_entry() -> DialogEntry:
return dialogs.get(_current_dialog_key)
func get_playback_position() -> float:
return _audio_player.get_playback_position() if is_instance_valid(_audio_player) else 0.0
func stop_dialog() -> void:
active_dialog_playbacks.erase(_current_dialog_playback)
_current_dialog_key = &""
_current_dialog_playback = null
_audio_player.stream = null
func _on_dialog_finished() -> void:
var entry: DialogEntry = dialogs.get(_current_dialog_key)
stop_dialog()
set_process(false)
dialog_finished.emit(entry)