1 extends DialogicSubsystem
2 ## Subsystem that manages setting voice lines for text events.
4 ## It's recommended to use the [class DialogicVoiceEvent] to set the voice lines
5 ## for text events and not start playing them directly.
8 ## Emitted whenever a new voice line starts playing.
9 ## The [param info] contains the following keys and values:
11 ## Key | Value Type | Value [br]
12 ## -------- | ------------- | ----- [br]
13 ## `file` | [type String] | The path to file played. [br]
14 signal voiceline_started(info: Dictionary)
17 ## Emitted whenever a voice line finished playing.
18 ## The [param info] contains the following keys and values:
20 ## Key | Value Type | Value [br]
21 ## ---------------- | ------------- | ----- [br]
22 ## `file` | [type String] | The path to file played. [br]
23 ## `remaining_time` | [type float] | The remaining time of the voiceline. [br]
24 signal voiceline_finished(info: Dictionary)
27 ## Emitted whenever a voice line gets interrupted and does not finish playing.
28 ## The [param info] contains the following keys and values:
30 ## Key | Value Type | Value [br]
31 ## ---------------- | ------------- | ----- [br]
32 ## `file` | [type String] | The path to file played. [br]
33 ## `remaining_time` | [type float] | The remaining time of the voiceline. [br]
34 signal voiceline_stopped(info: Dictionary)
37 ## The current audio file being played.
38 var current_audio_file: String
40 ## The audio player for the voiceline.
41 var voice_player := AudioStreamPlayer.new()
44 ####################################################################################################
46 ## Stops the current voice from playing.
48 voice_player.stream_paused = true
51 ## Resumes a paused voice.
52 func resume() -> void:
53 voice_player.stream_paused = false
59 ####################################################################################################
61 func _ready() -> void:
62 add_child(voice_player)
63 voice_player.finished.connect(_on_voice_finished)
66 ## Whether the current event is a text event and has a voice
68 func is_voiced(index: int) -> bool:
69 if index > 0 and dialogic.current_timeline_events[index] is DialogicTextEvent:
70 if dialogic.current_timeline_events[index-1] is DialogicVoiceEvent:
76 ## Plays the voice line. This will be invoked by Dialogic.
77 ## Requires [method set_file] to be called before or nothing plays.
78 func play_voice() -> void:
80 voiceline_started.emit({'file': current_audio_file})
83 ## Set a voice file [param path] to be played, then invoke [method play_voice].
85 ## This method does not check if [param path] is a valid file.
86 func set_file(path: String) -> void:
87 if current_audio_file == path:
90 current_audio_file = path
91 var audio: AudioStream = load(path)
92 voice_player.stream = audio
95 ## Set the volume to a [param value] in decibels.
96 func set_volume(value: float) -> void:
97 voice_player.volume_db = value
100 ## Set the voice player's bus to a [param bus_name].
101 func set_bus(bus_name: String) -> void:
102 voice_player.bus = bus_name
105 ## Stops the current voice line from playing.
106 func stop_audio() -> void:
107 if voice_player.playing:
108 voiceline_stopped.emit({'file':current_audio_file, 'remaining_time':get_remaining_time()})
113 ## Called when the voice line finishes playing.
114 ## Connected to [signal finished] on [member voice_player]
115 func _on_voice_finished() -> void:
116 voiceline_finished.emit({'file':current_audio_file, 'remaining_time':get_remaining_time()})
119 ## Returns the remaining time of the current voice line in seconds.
121 ## If there is no voice line playing, returns `0`.
122 func get_remaining_time() -> float:
123 if not voice_player or not voice_player.playing:
126 var stream_length := voice_player.stream.get_length()
127 var playback_position := voice_player.get_playback_position()
128 var remaining_seconds := stream_length - playback_position
130 return remaining_seconds
133 ## Whether there is still positive time remaining for the current voiceline.
134 func is_running() -> bool:
135 return get_remaining_time() > 0.0