feat: ported escoria-ui-return-monkey-island-dialog-simple
This commit is contained in:
@@ -42,9 +42,8 @@ func show_chooser():
|
|||||||
_option_node.add_theme_color_override("font_color", color_normal)
|
_option_node.add_theme_color_override("font_color", color_normal)
|
||||||
_option_node.add_theme_color_override("font_color_hover", color_hover)
|
_option_node.add_theme_color_override("font_color_hover", color_hover)
|
||||||
_vbox.add_child(_option_node)
|
_vbox.add_child(_option_node)
|
||||||
_option_node.connect("pressed", self, "_on_answer_selected", [
|
|
||||||
option
|
_option_node.pressed.connect(_on_answer_selected.bind(option))
|
||||||
])
|
|
||||||
|
|
||||||
# If we've no options left, signify as much and start the timer with a
|
# If we've no options left, signify as much and start the timer with a
|
||||||
# very short interval so the appropriate signal can be fired. Note that
|
# very short interval so the appropriate signal can be fired. Note that
|
||||||
@@ -78,7 +77,7 @@ func hide_chooser():
|
|||||||
func _option_chosen(option: ESCDialogOption):
|
func _option_chosen(option: ESCDialogOption):
|
||||||
_remove_avatar()
|
_remove_avatar()
|
||||||
$TimerProgress.value = 0
|
$TimerProgress.value = 0
|
||||||
emit_signal("option_chosen", option)
|
option_chosen.emit(option)
|
||||||
|
|
||||||
|
|
||||||
# An option was chosen directly from the list
|
# An option was chosen directly from the list
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class_name SayLastDialogOptionCommand
|
|||||||
|
|
||||||
# Return the descriptor of the arguments of this command
|
# Return the descriptor of the arguments of this command
|
||||||
func configure() -> ESCCommandArgumentDescriptor:
|
func configure() -> ESCCommandArgumentDescriptor:
|
||||||
return ESCCommandArgumentDescriptor.new()
|
return ESCCommandArgumentDescriptor.new()
|
||||||
|
|
||||||
# Run the command
|
# Run the command
|
||||||
func run(_command_params: Array) -> int:
|
func run(_command_params: Array) -> int:
|
||||||
@@ -42,7 +42,8 @@ func run(_command_params: Array) -> int:
|
|||||||
escoria.dialog_player.say(
|
escoria.dialog_player.say(
|
||||||
speaking_character_global_id,
|
speaking_character_global_id,
|
||||||
"",
|
"",
|
||||||
text
|
text,
|
||||||
|
text # TODO (Eneko): should we pass real key?
|
||||||
)
|
)
|
||||||
await escoria.dialog_player.say_finished
|
await escoria.dialog_player.say_finished
|
||||||
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func run(command_params: Array) -> int:
|
|||||||
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
||||||
return ESCExecution.RC_CANCEL
|
return ESCExecution.RC_CANCEL
|
||||||
|
|
||||||
var text = param_list_id + "_" + String(rng.randi_range(0,param_lenght -1)) + ':" "'
|
var text = param_list_id + "_" + String.num_int64(rng.randi_range(0,param_lenght -1)) + ':" "'
|
||||||
|
|
||||||
var speaking_character_global_id = escoria.main.current_scene.player.global_id \
|
var speaking_character_global_id = escoria.main.current_scene.player.global_id \
|
||||||
if param_global_id.to_upper() == CURRENT_PLAYER_KEYWORD \
|
if param_global_id.to_upper() == CURRENT_PLAYER_KEYWORD \
|
||||||
@@ -103,7 +103,8 @@ func run(command_params: Array) -> int:
|
|||||||
escoria.dialog_player.say(
|
escoria.dialog_player.say(
|
||||||
speaking_character_global_id,
|
speaking_character_global_id,
|
||||||
"",
|
"",
|
||||||
text
|
text,
|
||||||
|
text # TODO (Eneko): should we pass real key?
|
||||||
)
|
)
|
||||||
await escoria.dialog_player.say_finished
|
await escoria.dialog_player.say_finished
|
||||||
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
||||||
@@ -123,4 +124,4 @@ func interrupt():
|
|||||||
escoria.logger.debug(
|
escoria.logger.debug(
|
||||||
self,
|
self,
|
||||||
"[%s] interrupt() function not implemented." % get_command_name()
|
"[%s] interrupt() function not implemented." % get_command_name()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -107,7 +107,8 @@ func run(command_params: Array) -> int:
|
|||||||
escoria.dialog_player.say(
|
escoria.dialog_player.say(
|
||||||
speaking_character_global_id,
|
speaking_character_global_id,
|
||||||
"",
|
"",
|
||||||
text
|
text,
|
||||||
|
text # TODO (Eneko): should we pass real key?
|
||||||
)
|
)
|
||||||
await escoria.dialog_player.say_finished
|
await escoria.dialog_player.say_finished
|
||||||
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
escoria.current_state = escoria.GAME_STATE.DEFAULT
|
||||||
@@ -137,4 +138,4 @@ func interrupt():
|
|||||||
escoria.logger.debug(
|
escoria.logger.debug(
|
||||||
self,
|
self,
|
||||||
"[%s] interrupt() function not implemented." % get_command_name()
|
"[%s] interrupt() function not implemented." % get_command_name()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ the node that inherits from this state machine interface
|
|||||||
If you don't the game will crash (on purpose, so you won't
|
If you don't the game will crash (on purpose, so you won't
|
||||||
forget to initialize the state machine)
|
forget to initialize the state machine)
|
||||||
"""
|
"""
|
||||||
@export var START_STATE: NodePath
|
@export var START_STATE: Node
|
||||||
var states_map = {}
|
var states_map = {}
|
||||||
|
|
||||||
var states_stack = [] # can also be used as a pushdown automaton
|
var states_stack = [] # can also be used as a pushdown automaton
|
||||||
@@ -27,7 +27,7 @@ var _active = false: set = set_active
|
|||||||
|
|
||||||
func initialize(start_state):
|
func initialize(start_state):
|
||||||
for child in get_children():
|
for child in get_children():
|
||||||
child.connect("finished", Callable(self, "_change_state"))
|
child.finished.connect(_change_state)
|
||||||
|
|
||||||
set_active(true)
|
set_active(true)
|
||||||
states_stack.push_front(start_state)
|
states_stack.push_front(start_state)
|
||||||
@@ -76,7 +76,7 @@ func _change_state(state_name):
|
|||||||
|
|
||||||
current_state = states_stack[0]
|
current_state = states_stack[0]
|
||||||
|
|
||||||
emit_signal("state_changed", current_state)
|
state_changed.emit(current_state)
|
||||||
|
|
||||||
#if state_name != "previous":
|
#if state_name != "previous":
|
||||||
current_state.enter()
|
current_state.enter()
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func _disable_plugin():
|
|||||||
|
|
||||||
|
|
||||||
# Add ourselves to the list of dialog managers
|
# Add ourselves to the list of dialog managers
|
||||||
func enable_plugin():
|
func _enable_plugin():
|
||||||
print("Enabling plugin Escoria Dialog Simple")
|
print("Enabling plugin Escoria Dialog Simple")
|
||||||
|
|
||||||
if EscoriaPlugin.register_dialog_manager(self, MANAGER_CLASS):
|
if EscoriaPlugin.register_dialog_manager(self, MANAGER_CLASS):
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ func _ready() -> void:
|
|||||||
escoria.connect("paused", Callable(self, "_on_paused"))
|
escoria.connect("paused", Callable(self, "_on_paused"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check whether a specific type is supported by the
|
# Check whether a specific type is supported by the
|
||||||
# dialog plugin
|
# dialog plugin
|
||||||
#
|
#
|
||||||
@@ -40,25 +39,6 @@ func has_type(type: String) -> bool:
|
|||||||
return true if type in ["floating"] else false
|
return true if type in ["floating"] else false
|
||||||
|
|
||||||
|
|
||||||
# Check whether a specific chooser type is supported by the
|
|
||||||
# dialog plugin
|
|
||||||
#
|
|
||||||
# #### Parameters
|
|
||||||
# - type: required chooser type
|
|
||||||
# *Returns* Whether the type is supported or not
|
|
||||||
func has_chooser_type(type: String) -> bool:
|
|
||||||
return true if type == "simple" else false
|
|
||||||
|
|
||||||
# Instructs the dialog manager to preserve the next dialog box used by a `say`
|
|
||||||
# command until a call to `disable_preserve_dialog_box` is made.
|
|
||||||
#
|
|
||||||
# This method should be idempotent, i.e. if called after the first time and
|
|
||||||
# prior to `disable_preserve_dialog_box` being called, the result should be the
|
|
||||||
# same.
|
|
||||||
func enable_preserve_dialog_box() -> void:
|
|
||||||
_should_preserve_dialog_box = true
|
|
||||||
|
|
||||||
|
|
||||||
# Instructs the dialog manager to no longer preserve the currently-preserved
|
# Instructs the dialog manager to no longer preserve the currently-preserved
|
||||||
# dialog box or to not preserve the next dialog box used by a `say` command
|
# dialog box or to not preserve the next dialog box used by a `say` command
|
||||||
# (this is the default state).
|
# (this is the default state).
|
||||||
@@ -74,36 +54,6 @@ func disable_preserve_dialog_box() -> void:
|
|||||||
_preserved_type_player_type = ""
|
_preserved_type_player_type = ""
|
||||||
_dialog_player.remove_child(_dialog_tip)
|
_dialog_player.remove_child(_dialog_tip)
|
||||||
|
|
||||||
# Output a text said by the item specified by the global id. Emit
|
|
||||||
# `say_finished` after finishing displaying the text.
|
|
||||||
#
|
|
||||||
# #### Parameters
|
|
||||||
# - dialog_player: Node of the dialog player in the UI
|
|
||||||
# - global_id: Global id of the item that is speaking
|
|
||||||
# - text: Text to say, optional prefixed by a translation key separated
|
|
||||||
# by a ":"
|
|
||||||
# - type: Type of dialog box to use
|
|
||||||
func say(dialog_player: Node, global_id: String, text: String, type: String):
|
|
||||||
_dialog_player = dialog_player
|
|
||||||
|
|
||||||
_initialize_say_states(global_id, text, type)
|
|
||||||
|
|
||||||
if _should_preserve_dialog_box:
|
|
||||||
# If the dialog box type doesn't match what's currently being reused (if anything),
|
|
||||||
# we want to remove the old one (if it exists) and then initialize and add the new dialog
|
|
||||||
# box type to the dialog player
|
|
||||||
if type != _preserved_type_player_type:
|
|
||||||
if _dialog_player.get_children().has(_type_player):
|
|
||||||
_dialog_player.remove_child(_type_player)
|
|
||||||
|
|
||||||
_init_type_player(type)
|
|
||||||
|
|
||||||
_preserved_type_player_type = type
|
|
||||||
else:
|
|
||||||
_init_type_player(type)
|
|
||||||
|
|
||||||
state_machine._change_state("say")
|
|
||||||
|
|
||||||
|
|
||||||
func do_say(global_id: String, text: String) -> void:
|
func do_say(global_id: String, text: String) -> void:
|
||||||
# Only add_child here in order to prevent _type_player from running its _process method
|
# Only add_child here in order to prevent _type_player from running its _process method
|
||||||
@@ -116,8 +66,6 @@ func do_say(global_id: String, text: String) -> void:
|
|||||||
_type_player.say(global_id, text)
|
_type_player.say(global_id, text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func _init_type_player(type: String) -> void:
|
func _init_type_player(type: String) -> void:
|
||||||
if type == "floating":
|
if type == "floating":
|
||||||
_type_player = preload(\
|
_type_player = preload(\
|
||||||
@@ -131,16 +79,8 @@ func _init_type_player(type: String) -> void:
|
|||||||
"res://addons/escoria-ui-return-monkey-island-dialog-simple/dialog_tip.tscn"\
|
"res://addons/escoria-ui-return-monkey-island-dialog-simple/dialog_tip.tscn"\
|
||||||
).instantiate()
|
).instantiate()
|
||||||
|
|
||||||
_type_player.connect("say_finished", Callable(self, "_on_say_finished"))
|
_type_player.say_finished.connect(_on_say_finished)
|
||||||
_type_player.connect("say_visible", Callable(self, "_on_say_visible"))
|
_type_player.say_visible.connect(_on_say_visible)
|
||||||
|
|
||||||
func _initialize_say_states(global_id: String, text: String, type: String) -> void:
|
|
||||||
state_machine.states_map["say"].initialize(self, global_id, text, type)
|
|
||||||
state_machine.states_map["finish"].initialize(_dialog_player)
|
|
||||||
state_machine.states_map["say_fast"].initialize(self)
|
|
||||||
state_machine.states_map["say_finish"].initialize(self)
|
|
||||||
state_machine.states_map["visible"].initialize(self)
|
|
||||||
state_machine.states_map["interrupt"].initialize(self)
|
|
||||||
|
|
||||||
|
|
||||||
func _on_say_finished():
|
func _on_say_finished():
|
||||||
@@ -150,11 +90,12 @@ func _on_say_finished():
|
|||||||
|
|
||||||
_is_saying = false
|
_is_saying = false
|
||||||
|
|
||||||
emit_signal("say_finished")
|
say_finished.emit()
|
||||||
|
|
||||||
|
|
||||||
func _on_say_visible():
|
func _on_say_visible():
|
||||||
emit_signal("say_visible")
|
say_visible.emit()
|
||||||
|
|
||||||
|
|
||||||
# Present an option chooser to the player and sends the signal
|
# Present an option chooser to the player and sends the signal
|
||||||
# `option_chosen` with the chosen dialog option
|
# `option_chosen` with the chosen dialog option
|
||||||
@@ -188,19 +129,7 @@ func do_choose(dialog_player: Node, dialog: ESCDialog, type: String = "simple"):
|
|||||||
if option is ESCDialogOption:
|
if option is ESCDialogOption:
|
||||||
escoria.globals_manager.set_global("ESC_DIALOG_CHOSEN_OPTION", option.option)
|
escoria.globals_manager.set_global("ESC_DIALOG_CHOSEN_OPTION", option.option)
|
||||||
# END MODIFIED FOR RETURN TO MONKEY UI
|
# END MODIFIED FOR RETURN TO MONKEY UI
|
||||||
emit_signal("option_chosen", option)
|
option_chosen.emit(option)
|
||||||
|
|
||||||
|
|
||||||
# Trigger running the dialogue faster
|
|
||||||
func speedup():
|
|
||||||
if is_instance_valid(_type_player):
|
|
||||||
_type_player.speedup()
|
|
||||||
|
|
||||||
|
|
||||||
# Trigger an instant finish of the current dialog
|
|
||||||
func finish():
|
|
||||||
if is_instance_valid(_type_player):
|
|
||||||
_type_player.finish()
|
|
||||||
|
|
||||||
|
|
||||||
# The say command has been interrupted, cancel the dialog display
|
# The say command has been interrupted, cancel the dialog display
|
||||||
@@ -215,21 +144,17 @@ func interrupt():
|
|||||||
_dialog_player.remove_child(_type_player)
|
_dialog_player.remove_child(_type_player)
|
||||||
remove_dialop_tip()
|
remove_dialop_tip()
|
||||||
|
|
||||||
emit_signal("say_finished")
|
say_finished.emit()
|
||||||
|
|
||||||
|
|
||||||
# To be called if voice audio has finished.
|
|
||||||
func voice_audio_finished():
|
|
||||||
if is_instance_valid(_type_player):
|
|
||||||
_type_player.voice_audio_finished()
|
|
||||||
|
|
||||||
|
|
||||||
func add_dialog_tip():
|
func add_dialog_tip():
|
||||||
if not _dialog_player.get_children().has(_dialog_tip):
|
if not _dialog_player.get_children().has(_dialog_tip):
|
||||||
_dialog_player.add_child(_dialog_tip)
|
_dialog_player.add_child(_dialog_tip)
|
||||||
|
|
||||||
|
|
||||||
func remove_dialop_tip():
|
func remove_dialop_tip():
|
||||||
_dialog_player.remove_child(_dialog_tip)
|
_dialog_player.remove_child(_dialog_tip)
|
||||||
|
|
||||||
|
|
||||||
func _on_paused():
|
func _on_paused():
|
||||||
remove_dialop_tip()
|
remove_dialop_tip()
|
||||||
|
|||||||
@@ -40,5 +40,5 @@ func update(_delta):
|
|||||||
|
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'choices' -> 'idle'")
|
escoria.logger.trace(self, "Dialog State Machine: 'choices' -> 'idle'")
|
||||||
|
|
||||||
emit_signal("finished", "idle")
|
finished.emit("idle")
|
||||||
_dialog_player.emit_signal("option_chosen", option)
|
_dialog_player.option_chosen.emit(option)
|
||||||
|
|||||||
@@ -17,5 +17,5 @@ func enter():
|
|||||||
|
|
||||||
func update(_delta):
|
func update(_delta):
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'finish' -> 'idle'")
|
escoria.logger.trace(self, "Dialog State Machine: 'finish' -> 'idle'")
|
||||||
emit_signal("finished", "idle")
|
finished.emit("idle")
|
||||||
_dialog_player.emit_signal("say_finished")
|
_dialog_player.say_finished.emit()
|
||||||
|
|||||||
@@ -13,13 +13,12 @@ func enter():
|
|||||||
escoria.logger.trace(self, "Dialog State Machine: Entered 'interrupt'.")
|
escoria.logger.trace(self, "Dialog State Machine: Entered 'interrupt'.")
|
||||||
|
|
||||||
if _dialog_manager != null:
|
if _dialog_manager != null:
|
||||||
if not _dialog_manager.is_connected("say_finished", Callable(self, "_on_say_finished")):
|
if not _dialog_manager.say_finished.is_connected(_on_say_finished):
|
||||||
_dialog_manager.connect("say_finished", Callable(self, "_on_say_finished"))
|
_dialog_manager.say_finished.connect(_on_say_finished)
|
||||||
|
|
||||||
_dialog_manager.interrupt()
|
_dialog_manager.interrupt()
|
||||||
|
|
||||||
|
|
||||||
func _on_say_finished() -> void:
|
func _on_say_finished() -> void:
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'interrupt' -> 'finish'")
|
escoria.logger.trace(self, "Dialog State Machine: 'interrupt' -> 'finish'")
|
||||||
emit_signal("finished", "finish")
|
finished.emit("finish")
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
extends "res://addons/escoria-ui-return-monkey-island-dialog-simple/patterns/state_machine/state.gd"
|
extends "res://addons/escoria-ui-return-monkey-island-dialog-simple/patterns/state_machine/state.gd"
|
||||||
|
|
||||||
|
|
||||||
# A regular expression that separates the translation key from the text
|
# Reference to the currently playing dialog manager
|
||||||
const KEYTEXT_REGEX = "^((?<key>[^:]+):)?\"(?<text>.+)\""
|
|
||||||
|
|
||||||
|
|
||||||
# Reference to the currently playing dialog manager
|
|
||||||
var _dialog_manager: ESCDialogManager = null
|
var _dialog_manager: ESCDialogManager = null
|
||||||
|
|
||||||
# Character that is talking
|
# Character that is talking
|
||||||
@@ -14,27 +10,28 @@ var _character: String
|
|||||||
# UI to use for the dialog
|
# UI to use for the dialog
|
||||||
var _type: String
|
var _type: String
|
||||||
|
|
||||||
|
# Translation key
|
||||||
|
var _key: String = ""
|
||||||
|
|
||||||
# Text to say
|
# Text to say
|
||||||
var _text: String
|
var _text: String
|
||||||
|
|
||||||
# Regular expression object for the separation of key and text
|
|
||||||
var _keytext_regex: RegEx = RegEx.new()
|
|
||||||
|
|
||||||
var _ready_to_say: bool
|
var _ready_to_say: bool
|
||||||
|
|
||||||
|
# flag for whether the dialog manager has started to "say" to ensure that it has
|
||||||
|
# prior to exiting this state as other states need this to happen to continue
|
||||||
|
# (other states rely on the setup that the dialog manager does)
|
||||||
|
var _say_started: bool
|
||||||
|
|
||||||
var _stop_talking_animation_on_option: String
|
var _stop_talking_animation_on_option: String
|
||||||
|
|
||||||
|
|
||||||
# Constructor
|
func initialize(dialog_manager: ESCDialogManager, character: String, text: String, type: String, key: String) -> void:
|
||||||
func _init() -> void:
|
|
||||||
_keytext_regex.compile(KEYTEXT_REGEX)
|
|
||||||
|
|
||||||
|
|
||||||
func initialize(dialog_manager: ESCDialogManager, character: String, text: String, type: String) -> void:
|
|
||||||
_dialog_manager = dialog_manager
|
_dialog_manager = dialog_manager
|
||||||
_character = character
|
_character = character
|
||||||
_text = text
|
_text = text
|
||||||
_type = type
|
_type = type
|
||||||
|
_key = key
|
||||||
_stop_talking_animation_on_option = \
|
_stop_talking_animation_on_option = \
|
||||||
ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.STOP_TALKING_ANIMATION_ON)
|
ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.STOP_TALKING_ANIMATION_ON)
|
||||||
|
|
||||||
@@ -53,17 +50,17 @@ func handle_input(_event):
|
|||||||
func _handle_left_click_action(left_click_action: String) -> void:
|
func _handle_left_click_action(left_click_action: String) -> void:
|
||||||
match left_click_action:
|
match left_click_action:
|
||||||
RTMISimpleDialogSettings.LEFT_CLICK_ACTION_SPEED_UP:
|
RTMISimpleDialogSettings.LEFT_CLICK_ACTION_SPEED_UP:
|
||||||
if _dialog_manager.is_connected("say_visible", Callable(self, "_on_say_visible")):
|
if _dialog_manager.say_visible.is_connected(_on_say_visible):
|
||||||
_dialog_manager.disconnect("say_visible", Callable(self, "_on_say_visible"))
|
_dialog_manager.say_visible.disconnect(_on_say_visible)
|
||||||
|
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_fast'")
|
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_fast'")
|
||||||
emit_signal("finished", "say_fast")
|
finished.emit("say_fast")
|
||||||
RTMISimpleDialogSettings.LEFT_CLICK_ACTION_INSTANT_FINISH:
|
RTMISimpleDialogSettings.LEFT_CLICK_ACTION_INSTANT_FINISH:
|
||||||
if _dialog_manager.is_connected("say_visible", Callable(self, "_on_say_visible")):
|
if _dialog_manager.say_visible.is_connected(_on_say_visible):
|
||||||
_dialog_manager.disconnect("say_visible", Callable(self, "_on_say_visible"))
|
_dialog_manager.say_visible.disconnect(_on_say_visible)
|
||||||
|
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_finish'")
|
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_finish'")
|
||||||
emit_signal("finished", "say_finish")
|
finished.emit("say_finish")
|
||||||
|
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
@@ -71,28 +68,18 @@ func _handle_left_click_action(left_click_action: String) -> void:
|
|||||||
func enter():
|
func enter():
|
||||||
escoria.logger.trace(self, "Dialog State Machine: Entered 'say'.")
|
escoria.logger.trace(self, "Dialog State Machine: Entered 'say'.")
|
||||||
|
|
||||||
if not _dialog_manager.is_connected("say_visible", Callable(self, "_on_say_visible")):
|
_say_started = false
|
||||||
_dialog_manager.connect("say_visible", Callable(self, "_on_say_visible"))
|
|
||||||
|
if not _dialog_manager.say_visible.is_connected(_on_say_visible):
|
||||||
|
_dialog_manager.say_visible.connect(_on_say_visible)
|
||||||
|
|
||||||
var matches = _keytext_regex.search(_text)
|
if _key and not _key.is_empty():
|
||||||
|
var _speech_resource = _get_voice_file(_key)
|
||||||
if not matches:
|
|
||||||
escoria.logger.error(
|
|
||||||
self,
|
|
||||||
"Unexpected text encountered: %s." % _text
|
|
||||||
)
|
|
||||||
|
|
||||||
var key = matches.get_string("key")
|
|
||||||
|
|
||||||
if matches.get_string("key") != "":
|
|
||||||
var _speech_resource = _get_voice_file(
|
|
||||||
matches.get_string("key")
|
|
||||||
)
|
|
||||||
|
|
||||||
if _speech_resource == "":
|
if _speech_resource == "":
|
||||||
escoria.logger.warn(
|
escoria.logger.warn(
|
||||||
self,
|
self,
|
||||||
"Unable to find voice file with key '%s'." % matches.get_string("key")
|
"Unable to find voice file with key '%s'." % _key
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
(
|
(
|
||||||
@@ -104,34 +91,38 @@ func enter():
|
|||||||
if not (
|
if not (
|
||||||
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
|
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
|
||||||
as ESCSpeechPlayer
|
as ESCSpeechPlayer
|
||||||
).stream.is_connected("finished", Callable(self, "_on_audio_finished")):
|
).stream.finished.is_connected(_on_audio_finished):
|
||||||
|
|
||||||
(
|
(
|
||||||
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
|
escoria.object_manager.get_object(escoria.object_manager.SPEECH).node\
|
||||||
as ESCSpeechPlayer
|
as ESCSpeechPlayer
|
||||||
).stream.connect("finished", Callable(self, "_on_audio_finished"))
|
).stream.finished.connect(_on_audio_finished)
|
||||||
|
|
||||||
var translated_text: String = tr(matches.get_string("key"))
|
var translated_text: String = tr(_key)
|
||||||
|
|
||||||
# Only update the text if the translated text was found; otherwise, raise
|
# Only update the text if the translated text was found; otherwise, raise
|
||||||
# a warning and use the original, untranslated text.
|
# a warning and use the original, untranslated text.
|
||||||
if translated_text == matches.get_string("key"):
|
if translated_text == _key:
|
||||||
escoria.logger.warn(
|
escoria.logger.warn(
|
||||||
self,
|
self,
|
||||||
"Unable to find position key '%s'. Using untranslated text." % matches.get_string("key")
|
"Unable to find translation key '%s'. Using untranslated text." % _key
|
||||||
)
|
)
|
||||||
_text = matches.get_string("text")
|
|
||||||
else:
|
else:
|
||||||
_text = translated_text
|
_text = translated_text
|
||||||
else:
|
|
||||||
_text = matches.get_string("text")
|
|
||||||
|
|
||||||
_ready_to_say = true
|
_ready_to_say = true
|
||||||
|
|
||||||
|
|
||||||
|
func exit() -> void:
|
||||||
|
if not _say_started:
|
||||||
|
_dialog_manager.do_say(_character, _text)
|
||||||
|
_say_started = true
|
||||||
|
|
||||||
|
|
||||||
func update(_delta):
|
func update(_delta):
|
||||||
if _ready_to_say:
|
if _ready_to_say:
|
||||||
_dialog_manager.do_say(_character, _text)
|
_dialog_manager.do_say(_character, _text)
|
||||||
|
_say_started = true
|
||||||
_ready_to_say = false
|
_ready_to_say = false
|
||||||
|
|
||||||
|
|
||||||
@@ -148,15 +139,15 @@ func _get_voice_file(key: String, start: String = "") -> String:
|
|||||||
start = ESCProjectSettingsManager.get_setting(
|
start = ESCProjectSettingsManager.get_setting(
|
||||||
ESCProjectSettingsManager.SPEECH_FOLDER
|
ESCProjectSettingsManager.SPEECH_FOLDER
|
||||||
)
|
)
|
||||||
var _dir = DirAccess.new()
|
var _dir = DirAccess.open(start)
|
||||||
if _dir.open(start) == OK:
|
if _dir != null:
|
||||||
_dir.list_dir_begin() # TODOConverter3To4 fill missing arguments https://github.com/godotengine/godot/pull/40547
|
_dir.list_dir_begin() # TODOConverter3To4 fill missing arguments https://github.com/godotengine/godot/pull/40547
|
||||||
var file_name = _dir.get_next()
|
var file_name = _dir.get_next()
|
||||||
while file_name != "":
|
while file_name != "":
|
||||||
if _dir.current_is_dir():
|
if _dir.current_is_dir():
|
||||||
var _voice_file = _get_voice_file(
|
var _voice_file = _get_voice_file(
|
||||||
key,
|
key,
|
||||||
start.plus_file(file_name)
|
start.path_join(file_name)
|
||||||
)
|
)
|
||||||
if _voice_file != "":
|
if _voice_file != "":
|
||||||
return _voice_file
|
return _voice_file
|
||||||
@@ -167,14 +158,14 @@ func _get_voice_file(key: String, start: String = "") -> String:
|
|||||||
ESCProjectSettingsManager.SPEECH_EXTENSION
|
ESCProjectSettingsManager.SPEECH_EXTENSION
|
||||||
)
|
)
|
||||||
]:
|
]:
|
||||||
return start.plus_file(file_name.trim_suffix(".import"))
|
return start.path_join(file_name.trim_suffix(".import"))
|
||||||
file_name = _dir.get_next()
|
file_name = _dir.get_next()
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
func _on_say_visible() -> void:
|
func _on_say_visible() -> void:
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'visible'")
|
escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'visible'")
|
||||||
emit_signal("finished", "visible")
|
finished.emit("visible")
|
||||||
|
|
||||||
|
|
||||||
func _on_audio_finished() -> void:
|
func _on_audio_finished() -> void:
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func enter():
|
|||||||
escoria.inputs_manager.INPUT_NONE and \
|
escoria.inputs_manager.INPUT_NONE and \
|
||||||
_dialog_manager != null:
|
_dialog_manager != null:
|
||||||
|
|
||||||
if not _dialog_manager.is_connected("say_visible", Callable(self, "_on_say_visible")):
|
if not _dialog_manager.say_visible.is_connected(_on_say_visible):
|
||||||
_dialog_manager.connect("say_visible", Callable(self, "_on_say_visible"))
|
_dialog_manager.say_visible.connect(_on_say_visible)
|
||||||
|
|
||||||
_dialog_manager.speedup()
|
_dialog_manager.speedup()
|
||||||
else:
|
else:
|
||||||
@@ -26,4 +26,4 @@ func enter():
|
|||||||
|
|
||||||
func _on_say_visible() -> void:
|
func _on_say_visible() -> void:
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'say_fast' -> 'visible'")
|
escoria.logger.trace(self, "Dialog State Machine: 'say_fast' -> 'visible'")
|
||||||
emit_signal("finished", "visible")
|
finished.emit("visible")
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ func enter():
|
|||||||
escoria.inputs_manager.INPUT_NONE and \
|
escoria.inputs_manager.INPUT_NONE and \
|
||||||
_dialog_manager != null:
|
_dialog_manager != null:
|
||||||
|
|
||||||
if not _dialog_manager.is_connected("say_visible", Callable(self, "_on_say_visible")):
|
if not _dialog_manager.say_visible.is_connected(_on_say_visible):
|
||||||
_dialog_manager.connect("say_visible", Callable(self, "_on_say_visible"))
|
_dialog_manager.say_visible.connect(_on_say_visible)
|
||||||
|
|
||||||
_dialog_manager.finish()
|
_dialog_manager.finish()
|
||||||
else:
|
else:
|
||||||
@@ -26,4 +26,4 @@ func enter():
|
|||||||
|
|
||||||
func _on_say_visible() -> void:
|
func _on_say_visible() -> void:
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'say_finish' -> 'visible'")
|
escoria.logger.trace(self, "Dialog State Machine: 'say_finish' -> 'visible'")
|
||||||
emit_signal("finished", "visible")
|
finished.emit("visible")
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ func initialize(dialog_manager: ESCDialogManager) -> void:
|
|||||||
func enter():
|
func enter():
|
||||||
escoria.logger.trace(self, "Dialog State Machine: Entered 'visible'.")
|
escoria.logger.trace(self, "Dialog State Machine: Entered 'visible'.")
|
||||||
|
|
||||||
if not _dialog_manager.is_connected("say_finished", Callable(self, "_on_say_finished")):
|
if not _dialog_manager.say_finished.is_connected(_on_say_finished):
|
||||||
_dialog_manager.connect("say_finished", Callable(self, "_on_say_finished"))
|
_dialog_manager.say_finished.connect(_on_say_finished)
|
||||||
|
|
||||||
|
|
||||||
func handle_input(_event):
|
func handle_input(_event):
|
||||||
@@ -21,14 +21,14 @@ func handle_input(_event):
|
|||||||
if escoria.inputs_manager.input_mode != \
|
if escoria.inputs_manager.input_mode != \
|
||||||
escoria.inputs_manager.INPUT_NONE:
|
escoria.inputs_manager.INPUT_NONE:
|
||||||
|
|
||||||
if _dialog_manager.is_connected("say_finished", Callable(self, "_on_say_finished")):
|
if _dialog_manager.say_finished.is_connected(_on_say_finished):
|
||||||
_dialog_manager.disconnect("say_finished", Callable(self, "_on_say_finished"))
|
_dialog_manager.say_finished.disconnect(_on_say_finished)
|
||||||
|
|
||||||
emit_signal("finished", "interrupt")
|
finished.emit("interrupt")
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
|
|
||||||
# Handles the end of a say function after it has emitted say_finished.
|
# Handles the end of a say function after it has emitted say_finished.
|
||||||
func _on_say_finished():
|
func _on_say_finished():
|
||||||
escoria.logger.trace(self, "Dialog State Machine: 'visible' -> 'finish'")
|
escoria.logger.trace(self, "Dialog State Machine: 'visible' -> 'finish'")
|
||||||
emit_signal("finished", "finish")
|
finished.emit("finish")
|
||||||
|
|||||||
@@ -37,13 +37,12 @@ var _current_line: String
|
|||||||
@onready var text_node = $Panel/MarginContainer/HSplitContainer/text
|
@onready var text_node = $Panel/MarginContainer/HSplitContainer/text
|
||||||
|
|
||||||
# The tween node for text animations
|
# The tween node for text animations
|
||||||
@onready var tween = $Panel/MarginContainer/HSplitContainer/text/Tween
|
@onready var tween: Tween3 = Tween3.new(self)
|
||||||
|
|
||||||
# Whether the dialog manager is paused
|
# Whether the dialog manager is paused
|
||||||
@onready var is_paused: bool = true
|
@onready var is_paused: bool = true
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Build up the UI
|
# Build up the UI
|
||||||
func _ready():
|
func _ready():
|
||||||
_text_time_per_character = ProjectSettings.get_setting(
|
_text_time_per_character = ProjectSettings.get_setting(
|
||||||
@@ -56,11 +55,11 @@ func _ready():
|
|||||||
"%s setting must be a non-negative number. Will use default value of %s." %
|
"%s setting must be a non-negative number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS,
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS,
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_text_time_per_character = RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
||||||
|
|
||||||
_fast_text_time_per_character = ProjectSettings.get_setting(
|
_fast_text_time_per_character = ProjectSettings.get_setting(
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST
|
||||||
@@ -72,11 +71,11 @@ func _ready():
|
|||||||
"%s setting must be a non-negative number. Will use default value of %s." %
|
"%s setting must be a non-negative number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST,
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST,
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_fast_text_time_per_character = RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
_fast_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
||||||
|
|
||||||
_reading_speed_in_wpm = ProjectSettings.get_setting(
|
_reading_speed_in_wpm = ProjectSettings.get_setting(
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM
|
RTMISimpleDialogSettings.READING_SPEED_IN_WPM
|
||||||
@@ -88,23 +87,21 @@ func _ready():
|
|||||||
"%s setting must be a positive number. Will use default value of %s." %
|
"%s setting must be a positive number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM,
|
RTMISimpleDialogSettings.READING_SPEED_IN_WPM,
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_reading_speed_in_wpm = RTMISimpleDialogSettings.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
_reading_speed_in_wpm = escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
||||||
|
|
||||||
_word_regex.compile("\\S+")
|
_word_regex.compile("\\S+")
|
||||||
|
|
||||||
text_node.bbcode_enabled = true
|
text_node.bbcode_enabled = true
|
||||||
tween.connect(
|
tween.finished.connect(_on_dialog_line_typed.bind("", ""))
|
||||||
"tween_completed",
|
|
||||||
self,
|
|
||||||
"_on_dialog_line_typed"
|
|
||||||
)
|
|
||||||
|
|
||||||
escoria.connect("paused", Callable(self, "_on_paused"))
|
escoria.paused.connect(_on_paused)
|
||||||
escoria.connect("resumed", Callable(self, "_on_resumed"))
|
escoria.resumed.connect(_on_resumed)
|
||||||
|
|
||||||
|
tree_exited.connect(_on_tree_exited)
|
||||||
|
|
||||||
|
|
||||||
# Switch the current character
|
# Switch the current character
|
||||||
@@ -145,13 +142,15 @@ func say(character: String, line: String):
|
|||||||
|
|
||||||
text_node.text = tr(line)
|
text_node.text = tr(line)
|
||||||
|
|
||||||
text_node.percent_visible = 0.0
|
text_node.visible_ratio = 0.0
|
||||||
var time_show_full_text = _text_time_per_character / 1000 * len(line)
|
var time_show_full_text = _text_time_per_character / 1000 * len(line)
|
||||||
|
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
tween.reset()
|
||||||
|
|
||||||
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
0.0, 1.0, time_show_full_text,
|
0.0, 1.0, time_show_full_text,
|
||||||
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
||||||
tween.start()
|
tween.play()
|
||||||
|
|
||||||
|
|
||||||
# Called by the dialog player when the
|
# Called by the dialog player when the
|
||||||
@@ -159,19 +158,19 @@ func speedup():
|
|||||||
if not _is_speeding_up:
|
if not _is_speeding_up:
|
||||||
_is_speeding_up = true
|
_is_speeding_up = true
|
||||||
var time_show_full_text = _fast_text_time_per_character / 1000 * len(_current_line)
|
var time_show_full_text = _fast_text_time_per_character / 1000 * len(_current_line)
|
||||||
tween.remove_all()
|
tween.reset()
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
text_node.percent_visible, 1.0, time_show_full_text,
|
text_node.visible_ratio, 1.0, time_show_full_text,
|
||||||
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
||||||
tween.start()
|
tween.play()
|
||||||
|
|
||||||
|
|
||||||
# Called by the dialog player when user wants to finish dialogue immediately.
|
# Called by the dialog player when user wants to finish dialogue immediately.
|
||||||
func finish():
|
func finish():
|
||||||
tween.remove_all()
|
tween.reset()
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
text_node.percent_visible, 1.0, 0.0)
|
text_node.visible_ratio, 1.0, 0.0)
|
||||||
tween.start()
|
tween.play()
|
||||||
|
|
||||||
|
|
||||||
# To be called if voice audio has finished.
|
# To be called if voice audio has finished.
|
||||||
@@ -191,10 +190,13 @@ func _on_dialog_line_typed(object, key):
|
|||||||
text_node.visible_characters = -1
|
text_node.visible_characters = -1
|
||||||
|
|
||||||
var time_to_disappear: float = _calculate_time_to_disappear()
|
var time_to_disappear: float = _calculate_time_to_disappear()
|
||||||
$Timer.start(time_to_disappear)
|
|
||||||
$Timer.connect("timeout", Callable(self, "_on_dialog_finished"))
|
|
||||||
|
|
||||||
emit_signal("say_visible")
|
if not $Timer.timeout.is_connected(_on_dialog_finished):
|
||||||
|
$Timer.timeout.connect(_on_dialog_finished)
|
||||||
|
|
||||||
|
$Timer.start(time_to_disappear)
|
||||||
|
|
||||||
|
say_visible.emit()
|
||||||
|
|
||||||
|
|
||||||
func _calculate_time_to_disappear() -> float:
|
func _calculate_time_to_disappear() -> float:
|
||||||
@@ -207,21 +209,31 @@ func _get_number_of_words() -> int:
|
|||||||
|
|
||||||
# Ending the dialog
|
# Ending the dialog
|
||||||
func _on_dialog_finished():
|
func _on_dialog_finished():
|
||||||
|
$Timer.stop()
|
||||||
|
|
||||||
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
|
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
|
||||||
if not ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY):
|
if not ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY):
|
||||||
emit_signal("say_finished")
|
say_finished.emit()
|
||||||
queue_free()
|
|
||||||
|
|
||||||
|
|
||||||
# Handler managing pause notification from Escoria
|
# Handler managing pause notification from Escoria
|
||||||
func _on_paused():
|
func _on_paused():
|
||||||
if tween.is_active():
|
if tween.is_running():
|
||||||
is_paused = true
|
is_paused = true
|
||||||
tween.stop_all()
|
tween.stop()
|
||||||
|
|
||||||
|
|
||||||
# Handler managing resume notification from Escoria
|
# Handler managing resume notification from Escoria
|
||||||
func _on_resumed():
|
func _on_resumed():
|
||||||
if not tween.is_active():
|
if not tween.is_running():
|
||||||
|
# We can't rely on "show()" to make an invisible popup reappear, as per the docs for
|
||||||
|
# CanvasItem. Instead, we need to use one of the popup_* methods.
|
||||||
|
if is_inside_tree():
|
||||||
|
popup_centered()
|
||||||
|
|
||||||
is_paused = false
|
is_paused = false
|
||||||
tween.resume_all()
|
tween.resume()
|
||||||
|
|
||||||
|
|
||||||
|
func _on_tree_exited():
|
||||||
|
queue_free()
|
||||||
|
|||||||
@@ -1,68 +1,46 @@
|
|||||||
[gd_scene load_steps=2 format=2]
|
[gd_scene load_steps=2 format=3 uid="uid://cp75ofyuetxux"]
|
||||||
|
|
||||||
[ext_resource path="res://addons/escoria-ui-return-monkey-island-dialog-simple/types/avatar.gd" type="Script" id=1]
|
[ext_resource type="Script" path="res://addons/escoria-ui-return-monkey-island-dialog-simple/types/avatar.gd" id="1"]
|
||||||
|
|
||||||
[node name="dialog_box" type="Popup"]
|
[node name="dialog_box" type="Popup"]
|
||||||
anchor_right = 1.0
|
size = Vector2i(510, 180)
|
||||||
anchor_bottom = 1.0
|
visible = true
|
||||||
offset_right = -782.0
|
script = ExtResource("1")
|
||||||
offset_bottom = -734.0
|
|
||||||
script = ExtResource( 1 )
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="Timer" type="Timer" parent="."]
|
[node name="Timer" type="Timer" parent="."]
|
||||||
|
|
||||||
[node name="Panel" type="Panel" parent="."]
|
[node name="Panel" type="Panel" parent="."]
|
||||||
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="MarginContainer" type="MarginContainer" parent="Panel"]
|
[node name="MarginContainer" type="MarginContainer" parent="Panel"]
|
||||||
|
layout_mode = 0
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
theme_override_constants/margin_right = 20
|
|
||||||
theme_override_constants/margin_top = 20
|
|
||||||
theme_override_constants/margin_left = 20
|
theme_override_constants/margin_left = 20
|
||||||
|
theme_override_constants/margin_top = 20
|
||||||
|
theme_override_constants/margin_right = 20
|
||||||
theme_override_constants/margin_bottom = 20
|
theme_override_constants/margin_bottom = 20
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="HSplitContainer" type="HSplitContainer" parent="Panel/MarginContainer"]
|
[node name="HSplitContainer" type="HSplitContainer" parent="Panel/MarginContainer"]
|
||||||
offset_left = 20.0
|
layout_mode = 2
|
||||||
offset_top = 20.0
|
|
||||||
offset_right = 478.0
|
|
||||||
offset_bottom = 146.0
|
|
||||||
theme_override_constants/separation = 35
|
theme_override_constants/separation = 35
|
||||||
dragger_visibility = 1
|
dragger_visibility = 1
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/MarginContainer/HSplitContainer"]
|
[node name="VBoxContainer" type="VBoxContainer" parent="Panel/MarginContainer/HSplitContainer"]
|
||||||
offset_right = 88.0
|
layout_mode = 2
|
||||||
offset_bottom = 126.0
|
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_stretch_ratio = 0.3
|
size_flags_stretch_ratio = 0.3
|
||||||
|
|
||||||
[node name="avatar" type="TextureRect" parent="Panel/MarginContainer/HSplitContainer/VBoxContainer"]
|
[node name="avatar" type="TextureRect" parent="Panel/MarginContainer/HSplitContainer/VBoxContainer"]
|
||||||
offset_right = 88.0
|
layout_mode = 2
|
||||||
offset_bottom = 108.0
|
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
expand = true
|
stretch_mode = 4
|
||||||
|
|
||||||
[node name="text" type="RichTextLabel" parent="Panel/MarginContainer/HSplitContainer"]
|
[node name="text" type="RichTextLabel" parent="Panel/MarginContainer/HSplitContainer"]
|
||||||
offset_left = 123.0
|
layout_mode = 2
|
||||||
offset_right = 458.0
|
|
||||||
offset_bottom = 126.0
|
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
bbcode_enabled = true
|
bbcode_enabled = true
|
||||||
text = "Here be some text"
|
text = "Here be some text"
|
||||||
text = "Here be some text"
|
|
||||||
__meta__ = {
|
|
||||||
"_edit_use_anchors_": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[node name="Tween" type="Tween" parent="Panel/MarginContainer/HSplitContainer/text"]
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ var _current_line: String
|
|||||||
|
|
||||||
|
|
||||||
# Tween node for text animation
|
# Tween node for text animation
|
||||||
@onready var tween: Tween = $Tween
|
@onready var tween: Tween3 = Tween3.new(self)
|
||||||
|
|
||||||
# The node showing the text
|
# The node showing the text
|
||||||
@onready var text_node: RichTextLabel = self
|
@onready var text_node: RichTextLabel = self
|
||||||
@@ -42,6 +42,7 @@ var _current_line: String
|
|||||||
# Whether the dialog manager is paused
|
# Whether the dialog manager is paused
|
||||||
@onready var is_paused: bool = true
|
@onready var is_paused: bool = true
|
||||||
|
|
||||||
|
var dialog_location_node = null
|
||||||
|
|
||||||
# Enable bbcode and catch the signal when a tween completed
|
# Enable bbcode and catch the signal when a tween completed
|
||||||
func _ready():
|
func _ready():
|
||||||
@@ -55,11 +56,11 @@ func _ready():
|
|||||||
"%s setting must be a non-negative number. Will use default value of %s." %
|
"%s setting must be a non-negative number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS,
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS,
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_text_time_per_character = RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_DEFAULT_VALUE
|
||||||
|
|
||||||
_fast_text_time_per_character = ProjectSettings.get_setting(
|
_fast_text_time_per_character = ProjectSettings.get_setting(
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST
|
||||||
@@ -71,11 +72,11 @@ func _ready():
|
|||||||
"%s setting must be a non-negative number. Will use default value of %s." %
|
"%s setting must be a non-negative number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST,
|
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST,
|
||||||
RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_fast_text_time_per_character = RTMISimpleDialogSettings.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
_fast_text_time_per_character = escoria.TEXT_TIME_PER_LETTER_MS_FAST_DEFAULT_VALUE
|
||||||
|
|
||||||
_reading_speed_in_wpm = ProjectSettings.get_setting(
|
_reading_speed_in_wpm = ProjectSettings.get_setting(
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM
|
RTMISimpleDialogSettings.READING_SPEED_IN_WPM
|
||||||
@@ -87,41 +88,36 @@ func _ready():
|
|||||||
"%s setting must be a positive number. Will use default value of %s." %
|
"%s setting must be a positive number. Will use default value of %s." %
|
||||||
[
|
[
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM,
|
RTMISimpleDialogSettings.READING_SPEED_IN_WPM,
|
||||||
RTMISimpleDialogSettings.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
_reading_speed_in_wpm = RTMISimpleDialogSettings.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
_reading_speed_in_wpm = escoria.READING_SPEED_IN_WPM_DEFAULT_VALUE
|
||||||
|
|
||||||
_word_regex.compile("\\S+")
|
_word_regex.compile("\\S+")
|
||||||
|
|
||||||
bbcode_enabled = true
|
bbcode_enabled = true
|
||||||
$Tween.connect("tween_completed", Callable(self, "_on_dialog_line_typed"))
|
|
||||||
|
tween.finished.connect(_on_dialog_line_typed.bind("", ""))
|
||||||
|
|
||||||
connect("tree_exiting", Callable(self, "_on_tree_exiting"))
|
tree_exiting.connect(_on_tree_exiting)
|
||||||
|
|
||||||
escoria.connect("paused", Callable(self, "_on_paused"))
|
escoria.paused.connect(_on_paused)
|
||||||
escoria.connect("resumed", Callable(self, "_on_resumed"))
|
escoria.resumed.connect(_on_resumed)
|
||||||
|
|
||||||
_current_line = ""
|
_current_line = ""
|
||||||
|
|
||||||
|
|
||||||
func _process(delta):
|
func _process(delta):
|
||||||
if _current_character.is_inside_tree() and \
|
if _current_character.is_inside_tree() and \
|
||||||
_current_character.has_node("dialog_position"):
|
is_instance_valid(dialog_location_node):
|
||||||
# Position the RichTextLabel on the character's dialog position, if any.
|
# Position the RichTextLabel on the character's dialog position, if any.
|
||||||
position = _current_character.get_node("dialog_position") \
|
position = dialog_location_node.get_global_transform_with_canvas().origin
|
||||||
super.get_global_transform_with_canvas().origin
|
|
||||||
position.x -= size.x / 2
|
position.x -= size.x / 2
|
||||||
|
|
||||||
if position.x < 0:
|
_account_for_margin_x()
|
||||||
position.x = 0
|
|
||||||
|
|
||||||
var screen_margin = position.x + size.x - \
|
_account_for_margin_y()
|
||||||
ProjectSettings.get("display/window/size/viewport_width")
|
|
||||||
|
|
||||||
if screen_margin > 0:
|
|
||||||
position.x -= screen_margin
|
|
||||||
|
|
||||||
|
|
||||||
# Make a character say something
|
# Make a character say something
|
||||||
@@ -139,41 +135,52 @@ func say(character: String, line: String) :
|
|||||||
# Position the RichTextLabel on the character's dialog position, if any.
|
# Position the RichTextLabel on the character's dialog position, if any.
|
||||||
_current_character = escoria.object_manager.get_object(character).node
|
_current_character = escoria.object_manager.get_object(character).node
|
||||||
|
|
||||||
|
var dialog_location_count:int = 0
|
||||||
|
|
||||||
|
for c in escoria.object_manager.get_object(character).node.get_children():
|
||||||
|
if c is Marker2D:
|
||||||
|
# Identify any Postion2D nodes
|
||||||
|
if c is ESCDialogLocation:
|
||||||
|
dialog_location_count += 1
|
||||||
|
dialog_location_node = c
|
||||||
|
|
||||||
|
if dialog_location_count > 1:
|
||||||
|
escoria.logger.warn(
|
||||||
|
self,
|
||||||
|
"Multiple ESCDialogLocation nodes found " +
|
||||||
|
"object %s. Last one will be used." % _current_character)
|
||||||
|
|
||||||
# Set text color to color set in the actor
|
# Set text color to color set in the actor
|
||||||
var text_color = _current_character.dialog_color
|
var text_color = _current_character.dialog_color
|
||||||
var text_color_html = text_color.to_html(false)
|
var text_color_html = text_color.to_html(false)
|
||||||
|
|
||||||
text_node.text = "[center][color=#" + text_color_html + "]" \
|
text_node.text = "[center][color=#" + text_color_html + "]" \
|
||||||
super.format([text_color_html]) + tr(line) + "[/color][center]"
|
.format([text_color_html]) + tr(line) + "[/color][center]"
|
||||||
|
|
||||||
if _current_character.is_inside_tree() and \
|
if _current_character.is_inside_tree() and \
|
||||||
_current_character.has_node("dialog_position"):
|
is_instance_valid(dialog_location_node):
|
||||||
position = _current_character.get_node(
|
position = dialog_location_node.get_global_transform_with_canvas().origin
|
||||||
"dialog_position"
|
|
||||||
).get_global_transform_with_canvas().origin
|
|
||||||
position.x -= size.x / 2
|
position.x -= size.x / 2
|
||||||
else:
|
else:
|
||||||
position.x = 0
|
position.x = 0
|
||||||
size.x = ProjectSettings.get_setting("display/window/size/viewport_width")
|
size.x = ProjectSettings.get_setting("display/window/size/viewport_width")
|
||||||
|
|
||||||
if position.x < 0:
|
_account_for_margin_x()
|
||||||
position.x = 0
|
|
||||||
|
|
||||||
var screen_margin = position.x + size.x - \
|
_account_for_margin_y()
|
||||||
ProjectSettings.get("display/window/size/viewport_width")
|
|
||||||
|
|
||||||
if screen_margin > 0:
|
|
||||||
position.x -= screen_margin
|
|
||||||
|
|
||||||
_current_character.start_talking()
|
_current_character.start_talking()
|
||||||
|
|
||||||
text_node.percent_visible = 0.0
|
text_node.visible_ratio = 0.0
|
||||||
var time_show_full_text = _text_time_per_character / 1000 * len(_current_line)
|
var time_show_full_text = _text_time_per_character / 1000 * len(_current_line)
|
||||||
|
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
tween.reset()
|
||||||
|
|
||||||
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
0.0, 1.0, time_show_full_text,
|
0.0, 1.0, time_show_full_text,
|
||||||
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
||||||
tween.start()
|
tween.play()
|
||||||
set_process(true)
|
set_process(true)
|
||||||
|
|
||||||
|
|
||||||
@@ -183,19 +190,21 @@ func speedup():
|
|||||||
_is_speeding_up = true
|
_is_speeding_up = true
|
||||||
var time_show_full_text = _fast_text_time_per_character / 1000 * len(_current_line)
|
var time_show_full_text = _fast_text_time_per_character / 1000 * len(_current_line)
|
||||||
|
|
||||||
tween.remove_all()
|
tween.reset()
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
|
||||||
text_node.percent_visible, 1.0, time_show_full_text,
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
|
text_node.visible_ratio, 1.0, time_show_full_text,
|
||||||
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
|
||||||
tween.start()
|
tween.play()
|
||||||
|
|
||||||
|
|
||||||
# Called by the dialog player when user wants to finish dialogue immediately.
|
# Called by the dialog player when user wants to finish dialogue immediately.
|
||||||
func finish():
|
func finish():
|
||||||
tween.remove_all()
|
tween.reset()
|
||||||
tween.interpolate_property(text_node, "percent_visible",
|
|
||||||
text_node.percent_visible, 1.0, 0.0)
|
tween.interpolate_property(text_node, "visible_ratio",
|
||||||
tween.start()
|
text_node.visible_ratio, 1.0, 0.0)
|
||||||
|
tween.play()
|
||||||
|
|
||||||
|
|
||||||
# To be called if voice audio has finished.
|
# To be called if voice audio has finished.
|
||||||
@@ -211,9 +220,9 @@ func _on_dialog_line_typed(object, key):
|
|||||||
|
|
||||||
var time_to_disappear: float = _calculate_time_to_disappear()
|
var time_to_disappear: float = _calculate_time_to_disappear()
|
||||||
$Timer.start(time_to_disappear)
|
$Timer.start(time_to_disappear)
|
||||||
$Timer.connect("timeout", Callable(self, "_on_dialog_finished"))
|
$Timer.timeout.connect(_on_dialog_finished)
|
||||||
|
|
||||||
emit_signal("say_visible")
|
say_visible.emit()
|
||||||
|
|
||||||
|
|
||||||
func _calculate_time_to_disappear() -> float:
|
func _calculate_time_to_disappear() -> float:
|
||||||
@@ -228,23 +237,23 @@ func _get_number_of_words() -> int:
|
|||||||
func _on_dialog_finished():
|
func _on_dialog_finished():
|
||||||
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
|
# Only trigger to clear the text if we aren't limiting the clearing trigger to a click.
|
||||||
if not ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY):
|
if not ESCProjectSettingsManager.get_setting(RTMISimpleDialogSettings.CLEAR_TEXT_BY_CLICK_ONLY):
|
||||||
emit_signal("say_finished")
|
say_finished.emit()
|
||||||
|
|
||||||
|
|
||||||
# Handler managing pause notification from Escoria
|
# Handler managing pause notification from Escoria
|
||||||
func _on_paused():
|
func _on_paused():
|
||||||
if tween.is_active():
|
if tween.is_running():
|
||||||
is_paused = true
|
is_paused = true
|
||||||
visible = false
|
visible = false
|
||||||
tween.stop_all()
|
tween.stop()
|
||||||
|
|
||||||
|
|
||||||
# Handler managing resume notification from Escoria
|
# Handler managing resume notification from Escoria
|
||||||
func _on_resumed():
|
func _on_resumed():
|
||||||
if not tween.is_active():
|
if not tween.is_running():
|
||||||
is_paused = false
|
is_paused = false
|
||||||
visible = true
|
visible = true
|
||||||
tween.resume_all()
|
tween.resume()
|
||||||
|
|
||||||
|
|
||||||
# Handler to deal with this node being removed
|
# Handler to deal with this node being removed
|
||||||
@@ -256,3 +265,25 @@ func _stop_character_talking():
|
|||||||
# Make the speaking item animation stop talking, if it is still alive
|
# Make the speaking item animation stop talking, if it is still alive
|
||||||
if is_instance_valid(_current_character) and _current_character != null:
|
if is_instance_valid(_current_character) and _current_character != null:
|
||||||
_current_character.stop_talking()
|
_current_character.stop_talking()
|
||||||
|
|
||||||
|
|
||||||
|
func _account_for_margin_x() -> void:
|
||||||
|
if position.x < 0:
|
||||||
|
position.x = 0
|
||||||
|
|
||||||
|
var screen_margin_x = position.x + size.x - \
|
||||||
|
ProjectSettings.get("display/window/size/viewport_width")
|
||||||
|
|
||||||
|
if screen_margin_x > 0:
|
||||||
|
position.x -= screen_margin_x
|
||||||
|
|
||||||
|
|
||||||
|
func _account_for_margin_y() -> void:
|
||||||
|
if position.y < 0:
|
||||||
|
position.y = 0
|
||||||
|
|
||||||
|
var screen_margin_y = position.y + size.y - \
|
||||||
|
ProjectSettings.get("display/window/size/viewport_height")
|
||||||
|
|
||||||
|
if screen_margin_y > 0:
|
||||||
|
position.y -= screen_margin_y
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
extends VBoxContainer
|
extends VBoxContainer
|
||||||
|
|
||||||
signal finished
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
pass # Replace with function body.
|
pass # Replace with function body.
|
||||||
|
|
||||||
func _process(_delta):
|
func _process(_delta):
|
||||||
var size = self.get_global_rect().size
|
var textSize = self.get_global_rect().size
|
||||||
if escoria.globals_manager.get_global("turno_credits_rolling"):
|
if escoria.globals_manager.get_global("turno_credits_rolling"):
|
||||||
self.set_position(self.get_position() + Vector2(0, -0.5))
|
self.set_position(self.get_position() + Vector2(0, -0.5))
|
||||||
if self.get_position().y < -20 - size.y:
|
if self.get_position().y < -20 - textSize.y:
|
||||||
escoria.globals_manager.set_global("turno_credits_rolling", false)
|
escoria.globals_manager.set_global("turno_credits_rolling", false)
|
||||||
emit_signal("finished")
|
emit_signal("finished")
|
||||||
|
|||||||
Reference in New Issue
Block a user