First work on dialogic, resized guild, and started implementing portraits.
This commit is contained in:
82
addons/dialogic/Modules/Voice/event_voice.gd
Normal file
82
addons/dialogic/Modules/Voice/event_voice.gd
Normal file
@@ -0,0 +1,82 @@
|
||||
@tool
|
||||
class_name DialogicVoiceEvent
|
||||
extends DialogicEvent
|
||||
|
||||
## Event that allows to set the sound file to use for the next text event.
|
||||
|
||||
|
||||
### Settings
|
||||
|
||||
## The path to the sound file.
|
||||
var file_path := "":
|
||||
set(value):
|
||||
if file_path != value:
|
||||
file_path = value
|
||||
ui_update_needed.emit()
|
||||
## The volume the sound will be played at.
|
||||
var volume: float = 0
|
||||
## The audio bus to play the sound on.
|
||||
var audio_bus := "Master"
|
||||
|
||||
|
||||
################################################################################
|
||||
## EXECUTE
|
||||
################################################################################
|
||||
|
||||
func _execute() -> void:
|
||||
# If Auto-Skip is enabled, we may not want to play voice audio.
|
||||
# Instant Auto-Skip will always skip voice audio.
|
||||
if (dialogic.Inputs.auto_skip.enabled
|
||||
and dialogic.Inputs.auto_skip.skip_voice):
|
||||
finish()
|
||||
return
|
||||
|
||||
dialogic.Voice.set_file(file_path)
|
||||
dialogic.Voice.set_volume(volume)
|
||||
dialogic.Voice.set_bus(audio_bus)
|
||||
finish()
|
||||
# the rest is executed by a text event
|
||||
|
||||
|
||||
################################################################################
|
||||
## INITIALIZE
|
||||
################################################################################
|
||||
|
||||
func _init() -> void:
|
||||
event_name = "Voice"
|
||||
set_default_color('Color7')
|
||||
event_category = "Audio"
|
||||
event_sorting_index = 5
|
||||
|
||||
|
||||
################################################################################
|
||||
## SAVING/LOADING
|
||||
################################################################################
|
||||
|
||||
func get_shortcode() -> String:
|
||||
return "voice"
|
||||
|
||||
|
||||
func get_shortcode_parameters() -> Dictionary:
|
||||
return {
|
||||
#param_name : property_info
|
||||
"path" : {"property": "file_path", "default": ""},
|
||||
"volume" : {"property": "volume", "default": 0},
|
||||
"bus" : {"property": "audio_bus", "default": "Master"}
|
||||
}
|
||||
|
||||
|
||||
################################################################################
|
||||
## EDITOR REPRESENTATION
|
||||
################################################################################
|
||||
|
||||
func build_event_editor() -> void:
|
||||
add_header_edit('file_path', ValueType.FILE, {
|
||||
'left_text' : 'Set',
|
||||
'right_text' : 'as the next voice audio',
|
||||
'file_filter' : "*.mp3, *.ogg, *.wav",
|
||||
'placeholder' : "Select file",
|
||||
'editor_icon' : ["AudioStreamPlayer", "EditorIcons"]})
|
||||
add_header_edit('file_path', ValueType.AUDIO_PREVIEW)
|
||||
add_body_edit('volume', ValueType.NUMBER, {'left_text':'Volume:', 'mode':2}, '!file_path.is_empty()')
|
||||
add_body_edit('audio_bus', ValueType.SINGLELINE_TEXT, {'left_text':'Audio Bus:'}, '!file_path.is_empty()')
|
||||
1
addons/dialogic/Modules/Voice/event_voice.gd.uid
Normal file
1
addons/dialogic/Modules/Voice/event_voice.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cjunb4s52mxyr
|
||||
BIN
addons/dialogic/Modules/Voice/icon.png
Normal file
BIN
addons/dialogic/Modules/Voice/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
40
addons/dialogic/Modules/Voice/icon.png.import
Normal file
40
addons/dialogic/Modules/Voice/icon.png.import
Normal file
@@ -0,0 +1,40 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://vkvdtrxe5lxu"
|
||||
path="res://.godot/imported/icon.png-85989da147a1404ecd08c88eac72cda1.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/dialogic/Modules/Voice/icon.png"
|
||||
dest_files=["res://.godot/imported/icon.png-85989da147a1404ecd08c88eac72cda1.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
10
addons/dialogic/Modules/Voice/index.gd
Normal file
10
addons/dialogic/Modules/Voice/index.gd
Normal file
@@ -0,0 +1,10 @@
|
||||
@tool
|
||||
extends DialogicIndexer
|
||||
|
||||
|
||||
func _get_events() -> Array:
|
||||
return [this_folder.path_join('event_voice.gd')]
|
||||
|
||||
|
||||
func _get_subsystems() -> Array:
|
||||
return [{'name':'Voice', 'script':this_folder.path_join('subsystem_voice.gd')}]
|
||||
1
addons/dialogic/Modules/Voice/index.gd.uid
Normal file
1
addons/dialogic/Modules/Voice/index.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://b5ubg2ytulgue
|
||||
137
addons/dialogic/Modules/Voice/subsystem_voice.gd
Normal file
137
addons/dialogic/Modules/Voice/subsystem_voice.gd
Normal file
@@ -0,0 +1,137 @@
|
||||
extends DialogicSubsystem
|
||||
## Subsystem that manages setting voice lines for text events.
|
||||
##
|
||||
## It's recommended to use the [class DialogicVoiceEvent] to set the voice lines
|
||||
## for text events and not start playing them directly.
|
||||
|
||||
|
||||
## Emitted whenever a new voice line starts playing.
|
||||
## The [param info] contains the following keys and values:
|
||||
## [br]
|
||||
## Key | Value Type | Value [br]
|
||||
## -------- | ------------- | ----- [br]
|
||||
## `file` | [type String] | The path to file played. [br]
|
||||
signal voiceline_started(info: Dictionary)
|
||||
|
||||
|
||||
## Emitted whenever a voice line finished playing.
|
||||
## The [param info] contains the following keys and values:
|
||||
## [br]
|
||||
## Key | Value Type | Value [br]
|
||||
## ---------------- | ------------- | ----- [br]
|
||||
## `file` | [type String] | The path to file played. [br]
|
||||
## `remaining_time` | [type float] | The remaining time of the voiceline. [br]
|
||||
signal voiceline_finished(info: Dictionary)
|
||||
|
||||
|
||||
## Emitted whenever a voice line gets interrupted and does not finish playing.
|
||||
## The [param info] contains the following keys and values:
|
||||
## [br]
|
||||
## Key | Value Type | Value [br]
|
||||
## ---------------- | ------------- | ----- [br]
|
||||
## `file` | [type String] | The path to file played. [br]
|
||||
## `remaining_time` | [type float] | The remaining time of the voiceline. [br]
|
||||
signal voiceline_stopped(info: Dictionary)
|
||||
|
||||
|
||||
## The current audio file being played.
|
||||
var current_audio_file: String
|
||||
|
||||
## The audio player for the voiceline.
|
||||
var voice_player := AudioStreamPlayer.new()
|
||||
|
||||
#region STATE
|
||||
####################################################################################################
|
||||
|
||||
## Stops the current voice from playing.
|
||||
func pause() -> void:
|
||||
voice_player.stream_paused = true
|
||||
|
||||
|
||||
## Resumes a paused voice.
|
||||
func resume() -> void:
|
||||
voice_player.stream_paused = false
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region MAIN METHODS
|
||||
####################################################################################################
|
||||
|
||||
func _ready() -> void:
|
||||
add_child(voice_player)
|
||||
voice_player.finished.connect(_on_voice_finished)
|
||||
|
||||
|
||||
## Whether the current event is a text event and has a voice
|
||||
## event before it.
|
||||
func is_voiced(index: int) -> bool:
|
||||
if index > 0 and dialogic.current_timeline_events[index] is DialogicTextEvent:
|
||||
if dialogic.current_timeline_events[index-1] is DialogicVoiceEvent:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
|
||||
## Plays the voice line. This will be invoked by Dialogic.
|
||||
## Requires [method set_file] to be called before or nothing plays.
|
||||
func play_voice() -> void:
|
||||
voice_player.play()
|
||||
voiceline_started.emit({'file': current_audio_file})
|
||||
|
||||
|
||||
## Set a voice file [param path] to be played, then invoke [method play_voice].
|
||||
##
|
||||
## This method does not check if [param path] is a valid file.
|
||||
func set_file(path: String) -> void:
|
||||
if current_audio_file == path:
|
||||
return
|
||||
|
||||
current_audio_file = path
|
||||
var audio: AudioStream = load(path)
|
||||
voice_player.stream = audio
|
||||
|
||||
|
||||
## Set the volume to a [param value] in decibels.
|
||||
func set_volume(value: float) -> void:
|
||||
voice_player.volume_db = value
|
||||
|
||||
|
||||
## Set the voice player's bus to a [param bus_name].
|
||||
func set_bus(bus_name: String) -> void:
|
||||
voice_player.bus = bus_name
|
||||
|
||||
|
||||
## Stops the current voice line from playing.
|
||||
func stop_audio() -> void:
|
||||
if voice_player.playing:
|
||||
voiceline_stopped.emit({'file':current_audio_file, 'remaining_time':get_remaining_time()})
|
||||
|
||||
voice_player.stop()
|
||||
|
||||
|
||||
## Called when the voice line finishes playing.
|
||||
## Connected to [signal finished] on [member voice_player]
|
||||
func _on_voice_finished() -> void:
|
||||
voiceline_finished.emit({'file':current_audio_file, 'remaining_time':get_remaining_time()})
|
||||
|
||||
|
||||
## Returns the remaining time of the current voice line in seconds.
|
||||
##
|
||||
## If there is no voice line playing, returns `0`.
|
||||
func get_remaining_time() -> float:
|
||||
if not voice_player or not voice_player.playing:
|
||||
return 0.0
|
||||
|
||||
var stream_length := voice_player.stream.get_length()
|
||||
var playback_position := voice_player.get_playback_position()
|
||||
var remaining_seconds := stream_length - playback_position
|
||||
|
||||
return remaining_seconds
|
||||
|
||||
|
||||
## Whether there is still positive time remaining for the current voiceline.
|
||||
func is_running() -> bool:
|
||||
return get_remaining_time() > 0.0
|
||||
|
||||
#endregion
|
||||
1
addons/dialogic/Modules/Voice/subsystem_voice.gd.uid
Normal file
1
addons/dialogic/Modules/Voice/subsystem_voice.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://ba0mhh8rtbq3i
|
||||
Reference in New Issue
Block a user