1 @icon("node_dialog_text_icon.svg")
2 class_name DialogicNode_DialogText
5 ## Dialogic node that can reveal text at a given (changeable speed).
7 signal started_revealing_text()
8 signal continued_revealing_text(new_character : String)
9 signal finished_revealing_text()
10 enum Alignment {LEFT, CENTER, RIGHT}
12 @export var enabled := true
13 @export var alignment := Alignment.LEFT
14 @export var textbox_root: Node = self
16 @export var hide_when_empty := false
17 @export var start_hidden := true
19 var revealing := false
20 var base_visible_characters := 0
22 # The used speed per revealed character.
23 # May be overwritten when syncing reveal speed to voice.
24 var active_speed: float = 0.01
26 var speed_counter: float = 0
28 func _set(property: StringName, what: Variant) -> bool:
29 if property == 'text' and typeof(what) == TYPE_STRING:
34 textbox_root.visible = !what.is_empty()
40 func _ready() -> void:
42 add_to_group('dialogic_dialog_text')
43 meta_hover_ended.connect(_on_meta_hover_ended)
44 meta_hover_started.connect(_on_meta_hover_started)
45 meta_clicked.connect(_on_meta_clicked)
46 gui_input.connect(on_gui_input)
48 if textbox_root == null:
56 # this is called by the DialogicGameHandler to set text
58 func reveal_text(_text: String, keep_previous:=false) -> void:
65 base_visible_characters = 0
67 if alignment == Alignment.CENTER:
68 text = '[center]'+text
69 elif alignment == Alignment.RIGHT:
71 visible_characters = 0
74 base_visible_characters = len(text)
75 visible_characters = len(get_parsed_text())
78 # If Auto-Skip is enabled and we append the text (keep_previous),
79 # we can skip revealing the text and just show it all at once.
80 if DialogicUtil.autoload().Inputs.auto_skip.enabled:
81 visible_characters = 1
86 started_revealing_text.emit()
89 func set_speed(delay_per_character:float) -> void:
90 if DialogicUtil.autoload().Text.is_text_voice_synced() and DialogicUtil.autoload().Voice.is_running():
91 var total_characters := get_total_character_count() as float
92 var remaining_time: float = DialogicUtil.autoload().Voice.get_remaining_time()
93 var synced_speed := remaining_time / total_characters
94 active_speed = synced_speed
97 active_speed = delay_per_character
100 ## Reveals one additional character.
101 func continue_reveal() -> void:
102 if visible_characters <= get_total_character_count():
105 var current_index := visible_characters - base_visible_characters
106 await DialogicUtil.autoload().Text.execute_effects(current_index, self, false)
108 if visible_characters == -1:
112 visible_characters += 1
114 if visible_characters > -1 and visible_characters <= len(get_parsed_text()):
115 continued_revealing_text.emit(get_parsed_text()[visible_characters-1])
118 # if the text finished organically, add a small input block
119 # this prevents accidental skipping when you expected the text to be longer
120 DialogicUtil.autoload().Inputs.block_input(ProjectSettings.get_setting('dialogic/text/advance_delay', 0.1))
123 ## Reveals the entire text instantly.
124 func finish_text() -> void:
126 DialogicUtil.autoload().Text.execute_effects(-1, self, true)
128 DialogicUtil.autoload().current_state = DialogicGameHandler.States.IDLE
130 finished_revealing_text.emit()
133 ## Checks if the next character in the text can be revealed.
134 func _process(delta: float) -> void:
135 if !revealing or DialogicUtil.autoload().paused:
138 speed_counter += delta
140 while speed_counter > active_speed and revealing and !DialogicUtil.autoload().paused:
141 speed_counter -= active_speed
146 func _on_meta_hover_started(_meta:Variant) -> void:
147 DialogicUtil.autoload().Inputs.action_was_consumed = true
149 func _on_meta_hover_ended(_meta:Variant) -> void:
150 DialogicUtil.autoload().Inputs.action_was_consumed = false
152 func _on_meta_clicked(_meta:Variant) -> void:
153 DialogicUtil.autoload().Inputs.action_was_consumed = true
156 ## Handle mouse input
157 func on_gui_input(event:InputEvent) -> void:
158 DialogicUtil.autoload().Inputs.handle_node_gui_input(event)