From d676e50284ac5747e81bc15872eb69195905edb0 Mon Sep 17 00:00:00 2001 From: Duncan Brown Date: Thu, 1 Dec 2022 22:57:16 -0500 Subject: [PATCH] feat: adds additional options to dialog manager, including a left-click action option and a text skipping option --- .../game/scenes/dialogs/esc_dialog_manager.gd | 7 ++- .../game/scenes/dialogs/esc_dialog_player.gd | 9 +++- .../dialogs/state_machine/dialog_interrupt.gd | 6 +-- .../dialogs/state_machine/dialog_say.gd | 18 +++++++- .../state_machine/dialog_say_finish.gd | 30 ++++++++++++ .../esc_dialog_simple.gd | 8 +++- addons/escoria-dialog-simple/plugin.gd | 46 ++++++++++++++----- addons/escoria-dialog-simple/types/avatar.gd | 23 +++++++--- .../escoria-dialog-simple/types/floating.gd | 25 +++++++--- 9 files changed, 139 insertions(+), 33 deletions(-) create mode 100644 addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say_finish.gd diff --git a/addons/escoria-core/game/scenes/dialogs/esc_dialog_manager.gd b/addons/escoria-core/game/scenes/dialogs/esc_dialog_manager.gd index 10c4a2b1d..f47206339 100644 --- a/addons/escoria-core/game/scenes/dialogs/esc_dialog_manager.gd +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_manager.gd @@ -56,11 +56,16 @@ func choose(dialog_player: Node, dialog: ESCDialog): pass -# Trigger running the dialog faster +# Trigger running the dialogue faster func speedup(): pass +# Trigger an instant finish of the current dialog +func finish(): + pass + + # The say command has been interrupted, cancel the dialog display func interrupt(): pass diff --git a/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd b/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd index 42dcba6af..f3f114256 100644 --- a/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd +++ b/addons/escoria-core/game/scenes/dialogs/esc_dialog_player.gd @@ -42,6 +42,7 @@ func _create_states() -> void: "idle": DialogIdle.new(), "say": DialogSay.new(), "say_fast": DialogSayFast.new(), + "say_finish": DialogSayFinish.new(), "visible": DialogVisible.new(), "finish": DialogFinish.new(), "interrupt": DialogInterrupt.new(), @@ -70,11 +71,16 @@ func say(character: String, type: String, text: String) -> void: _change_state("say") -# Called when a dialog line is to be sped up. +# Called when a dialogue line is to be sped up. func speedup() -> void: _change_state("say_fast") +# Called when a dialogue line is to be finished immediately. +func finish() -> void: + _change_state("say_finish") + + # Display a list of choices # # #### Parameters @@ -96,5 +102,6 @@ func interrupt() -> void: func _on_dialog_manager_set(dialog_manager: ESCDialogManager) -> void: _dialog_manager = dialog_manager states_map["say_fast"].initialize(dialog_manager) + states_map["say_finish"].initialize(dialog_manager) states_map["visible"].initialize(dialog_manager) states_map["interrupt"].initialize(dialog_manager) diff --git a/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_interrupt.gd b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_interrupt.gd index cf0ae2d8e..4b05ba7c4 100644 --- a/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_interrupt.gd +++ b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_interrupt.gd @@ -13,10 +13,10 @@ func initialize(dialog_manager: ESCDialogManager) -> void: func enter(): escoria.logger.trace(self, "Dialog State Machine: Entered 'interrupt'.") - if not _dialog_manager.is_connected("say_finished", self, "_on_say_finished"): - _dialog_manager.connect("say_finished", self, "_on_say_finished", [], CONNECT_ONESHOT) - if _dialog_manager != null: + if not _dialog_manager.is_connected("say_finished", self, "_on_say_finished"): + _dialog_manager.connect("say_finished", self, "_on_say_finished", [], CONNECT_ONESHOT) + _dialog_manager.interrupt() diff --git a/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say.gd b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say.gd index b04524337..1a156c9fc 100644 --- a/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say.gd +++ b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say.gd @@ -44,13 +44,27 @@ func handle_input(_event): escoria.inputs_manager.INPUT_NONE and \ _dialog_manager != null: + var left_click_action = ESCProjectSettingsManager.get_setting(SimpleDialogPlugin.LEFT_CLICK_ACTION) + + _handle_left_click_action(left_click_action) + + +func _handle_left_click_action(left_click_action: String) -> void: + match left_click_action: + SimpleDialogPlugin.LEFT_CLICK_ACTION_SPEED_UP: if _dialog_manager.is_connected("say_visible", self, "_on_say_visible"): _dialog_manager.disconnect("say_visible", self, "_on_say_visible") escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_fast'") - emit_signal("finished", "say_fast") - get_tree().set_input_as_handled() + SimpleDialogPlugin.LEFT_CLICK_ACTION_INSTANT_FINISH: + if _dialog_manager.is_connected("say_visible", self, "_on_say_visible"): + _dialog_manager.disconnect("say_visible", self, "_on_say_visible") + + escoria.logger.trace(self, "Dialog State Machine: 'say' -> 'say_finish'") + emit_signal("finished", "say_finish") + + get_tree().set_input_as_handled() func enter(): diff --git a/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say_finish.gd b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say_finish.gd new file mode 100644 index 000000000..1f18d521f --- /dev/null +++ b/addons/escoria-core/game/scenes/dialogs/state_machine/dialog_say_finish.gd @@ -0,0 +1,30 @@ +extends State +class_name DialogSayFinish + + +# Reference to the currently playing dialog manager +var _dialog_manager: ESCDialogManager = null + + +func initialize(dialog_manager: ESCDialogManager) -> void: + _dialog_manager = dialog_manager + + +func enter(): + escoria.logger.trace(self, "Dialog State Machine: Entered 'say_finish'.") + + if escoria.inputs_manager.input_mode != \ + escoria.inputs_manager.INPUT_NONE and \ + _dialog_manager != null: + + if not _dialog_manager.is_connected("say_visible", self, "_on_say_visible"): + _dialog_manager.connect("say_visible", self, "_on_say_visible", [], CONNECT_ONESHOT) + + _dialog_manager.finish() + else: + escoria.logger.error(self, "Illegal state.") + + +func _on_say_visible() -> void: + escoria.logger.trace(self, "Dialog State Machine: 'say_finish' -> 'visible'") + emit_signal("finished", "visible") diff --git a/addons/escoria-dialog-simple/esc_dialog_simple.gd b/addons/escoria-dialog-simple/esc_dialog_simple.gd index 686e76512..b06b50fc5 100644 --- a/addons/escoria-dialog-simple/esc_dialog_simple.gd +++ b/addons/escoria-dialog-simple/esc_dialog_simple.gd @@ -90,12 +90,18 @@ func choose(dialog_player: Node, dialog: ESCDialog): emit_signal("option_chosen", option) -# Trigger running the dialog faster +# Trigger running the dialogue faster func speedup(): if _type_player != null: _type_player.speedup() +# Trigger an instant finish of the current dialog +func finish(): + if _type_player != null: + _type_player.finish() + + # The say command has been interrupted, cancel the dialog display func interrupt(): if _dialog_player.get_children().has(_type_player): diff --git a/addons/escoria-dialog-simple/plugin.gd b/addons/escoria-dialog-simple/plugin.gd index 9e47157b4..c5c90da00 100644 --- a/addons/escoria-dialog-simple/plugin.gd +++ b/addons/escoria-dialog-simple/plugin.gd @@ -1,6 +1,8 @@ # A simple dialog manager for Escoria tool extends EditorPlugin +class_name SimpleDialogPlugin + const MANAGER_CLASS="res://addons/escoria-dialog-simple/esc_dialog_simple.gd" const SETTINGS_ROOT="escoria/dialog_simple" @@ -8,9 +10,21 @@ const SETTINGS_ROOT="escoria/dialog_simple" const AVATARS_PATH = "%s/avatars_path" % SETTINGS_ROOT const TEXT_SPEED_PER_CHARACTER = "%s/text_speed_per_character" % SETTINGS_ROOT const FAST_TEXT_SPEED_PER_CHARACTER = "%s/fast_text_speed_per_character" % SETTINGS_ROOT -const MAX_TIME_TO_DISAPPEAR = "%s/max_time_to_disappear" % SETTINGS_ROOT -const SKIP_DIALOGS = "%s/skip_dialogs" % SETTINGS_ROOT const READING_SPEED_IN_WPM = "%s/reading_speed_in_wpm" % SETTINGS_ROOT +const CLEAR_TEXT_BY_CLICK_ONLY = "%s/clear_text_by_click_only" % SETTINGS_ROOT +const LEFT_CLICK_ACTION = "%s/left_click_action" % SETTINGS_ROOT + +const LEFT_CLICK_ACTION_SPEED_UP = "Speed up" +const LEFT_CLICK_ACTION_INSTANT_FINISH = "Instant finish" +const LEFT_CLICK_ACTION_NOTHING = "None" + + +var leftClickActions: Array = [ + LEFT_CLICK_ACTION_SPEED_UP, + LEFT_CLICK_ACTION_INSTANT_FINISH, + LEFT_CLICK_ACTION_NOTHING +] + # Override function to return the plugin name. func get_plugin_name(): @@ -36,12 +50,16 @@ func disable_plugin(): FAST_TEXT_SPEED_PER_CHARACTER ) + ESCProjectSettingsManager.remove_setting( + CLEAR_TEXT_BY_CLICK_ONLY + ) + ESCProjectSettingsManager.remove_setting( READING_SPEED_IN_WPM ) ESCProjectSettingsManager.remove_setting( - MAX_TIME_TO_DISAPPEAR + LEFT_CLICK_ACTION ) EscoriaPlugin.deregister_dialog_manager(MANAGER_CLASS) @@ -86,29 +104,33 @@ func enable_plugin(): ) ESCProjectSettingsManager.register_setting( - READING_SPEED_IN_WPM, - 200, + CLEAR_TEXT_BY_CLICK_ONLY, + false, { - "type": TYPE_INT + "type": TYPE_BOOL } ) ESCProjectSettingsManager.register_setting( - MAX_TIME_TO_DISAPPEAR, - 1.0, + READING_SPEED_IN_WPM, + 200, { "type": TYPE_INT } ) + var leftClickActionsString: String = ",".join(leftClickActions) + ESCProjectSettingsManager.register_setting( - SKIP_DIALOGS, - true, + LEFT_CLICK_ACTION, + "Speed up", { - "type": TYPE_BOOL + "type": TYPE_STRING, + "hint": PROPERTY_HINT_ENUM, + "hint_string": leftClickActionsString } ) - #escoria.settings_manager.custom_settings[SKIP_DIALOGS] = true + else: get_editor_interface().set_plugin_enabled( get_plugin_name(), diff --git a/addons/escoria-dialog-simple/types/avatar.gd b/addons/escoria-dialog-simple/types/avatar.gd index 5f0307349..6b116c465 100644 --- a/addons/escoria-dialog-simple/types/avatar.gd +++ b/addons/escoria-dialog-simple/types/avatar.gd @@ -44,13 +44,13 @@ onready var is_paused: bool = true # Build up the UI func _ready(): _text_speed_per_character = ProjectSettings.get_setting( - "escoria/dialog_simple/text_speed_per_character" + SimpleDialogPlugin.TEXT_SPEED_PER_CHARACTER ) _fast_text_speed_per_character = ProjectSettings.get_setting( - "escoria/dialog_simple/fast_text_speed_per_character" + SimpleDialogPlugin.FAST_TEXT_SPEED_PER_CHARACTER ) _reading_speed_in_wpm = ProjectSettings.get_setting( - "escoria/dialog_simple/reading_speed_in_wpm" + SimpleDialogPlugin.READING_SPEED_IN_WPM ) _word_regex.compile("\\S+") @@ -118,13 +118,24 @@ func speedup(): tween.start() +# Called by the dialog player when user wants to finish dialogue immediately. +func finish(): + tween.remove_all() + tween.interpolate_property(text_node, "percent_visible", + text_node.percent_visible, 1.0, 0.0) + tween.start() + + # The dialog line was printed, start the waiting time and then finish # the dialog func _on_dialog_line_typed(object, key): - var time_to_disappear: float = _calculate_time_to_disappear() text_node.visible_characters = -1 - $Timer.start(time_to_disappear) - $Timer.connect("timeout", self, "_on_dialog_finished") + + if not ESCProjectSettingsManager.get_setting(SimpleDialogPlugin.CLEAR_TEXT_BY_CLICK_ONLY): + var time_to_disappear: float = _calculate_time_to_disappear() + $Timer.start(time_to_disappear) + $Timer.connect("timeout", self, "_on_dialog_finished") + emit_signal("say_visible") diff --git a/addons/escoria-dialog-simple/types/floating.gd b/addons/escoria-dialog-simple/types/floating.gd index 857d74e83..60760080b 100644 --- a/addons/escoria-dialog-simple/types/floating.gd +++ b/addons/escoria-dialog-simple/types/floating.gd @@ -43,13 +43,13 @@ onready var is_paused: bool = true # Enable bbcode and catch the signal when a tween completed func _ready(): _text_speed_per_character = ProjectSettings.get_setting( - "escoria/dialog_simple/text_speed_per_character" + SimpleDialogPlugin.TEXT_SPEED_PER_CHARACTER ) _fast_text_speed_per_character = ProjectSettings.get_setting( - "escoria/dialog_simple/fast_text_speed_per_character" + SimpleDialogPlugin.FAST_TEXT_SPEED_PER_CHARACTER ) _reading_speed_in_wpm = ProjectSettings.get_setting( - "escoria/dialog_simple/reading_speed_in_wpm" + SimpleDialogPlugin.READING_SPEED_IN_WPM ) _word_regex.compile("\\S+") @@ -132,7 +132,7 @@ func say(character: String, line: String) : set_process(true) -# Called by the dialog player when user wants to finish dialog fast. +# Called by the dialog player when user wants to finish dialogue fast. func speedup(): if not _is_speeding_up: _is_speeding_up = true @@ -143,13 +143,24 @@ func speedup(): tween.start() +# Called by the dialog player when user wants to finish dialogue immediately. +func finish(): + tween.remove_all() + tween.interpolate_property(text_node, "percent_visible", + text_node.percent_visible, 1.0, 0.0) + tween.start() + + # The dialog line was printed, start the waiting time and then finish # the dialog func _on_dialog_line_typed(object, key): - var time_to_disappear: float = _calculate_time_to_disappear() text_node.visible_characters = -1 - $Timer.start(time_to_disappear) - $Timer.connect("timeout", self, "_on_dialog_finished") + + if not ESCProjectSettingsManager.get_setting(SimpleDialogPlugin.CLEAR_TEXT_BY_CLICK_ONLY): + var time_to_disappear: float = _calculate_time_to_disappear() + $Timer.start(time_to_disappear) + $Timer.connect("timeout", self, "_on_dialog_finished") + emit_signal("say_visible")