Skip to content

Commit f216b65

Browse files
authored
Add support for waiting for input (#955)
1 parent ad31581 commit f216b65

15 files changed

+190
-64
lines changed

addons/dialogue_manager/DialogueManager.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -432,12 +432,6 @@ public string? Time
432432
get => time;
433433
}
434434

435-
private Dictionary pauses = new Dictionary();
436-
public Dictionary Pauses
437-
{
438-
get => pauses;
439-
}
440-
441435
private Dictionary speeds = new Dictionary();
442436
public Dictionary Speeds
443437
{
@@ -476,7 +470,6 @@ public DialogueLine(RefCounted data)
476470
character = (string)data.Get("character");
477471
text = (string)data.Get("text");
478472
translation_key = (string)data.Get("translation_key");
479-
pauses = (Dictionary)data.Get("pauses");
480473
speeds = (Dictionary)data.Get("speeds");
481474
inline_mutations = (Array<Godot.Collections.Array>)data.Get("inline_mutations");
482475
time = (string)data.Get("time");

addons/dialogue_manager/compiler/compiler.gd

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ static func extract_translatable_string(text: String) -> String:
4444
return line.text
4545

4646

47+
## Extract a mutation from a string.
48+
static func extract_mutation(text: String) -> Dictionary:
49+
var compilation: DMCompilation = DMCompilation.new()
50+
return compilation.extract_mutation(text)
51+
52+
4753
## Get the known titles in a dialogue script.
4854
static func get_titles_in_text(text: String, path: String) -> Dictionary:
4955
var compilation: DMCompilation = DMCompilation.new()

addons/dialogue_manager/compiler/resolved_line_data.gd

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ class_name DMResolvedLineData extends RefCounted
33

44
## The line's text
55
var text: String = ""
6-
## A map of pauses against where they are found in the text.
7-
var pauses: Dictionary = {}
86
## A map of speed changes against where they are found in the text.
97
var speeds: Dictionary = {}
108
## A list of any mutations to run and where they are found in the text.
@@ -15,7 +13,6 @@ var time: String = ""
1513

1614
func _init(line: String) -> void:
1715
text = line
18-
pauses = {}
1916
speeds = {}
2017
mutations = []
2118
time = ""
@@ -64,8 +61,7 @@ func _init(line: String) -> void:
6461
var raw_args = bbcode.raw_args
6562
var args = {}
6663
if code in ["$>", "$>>", "do", "do!", "set"]:
67-
var compilation: DMCompilation = DMCompilation.new()
68-
args["value"] = compilation.extract_mutation("%s %s" % [code, raw_args])
64+
args["value"] = DMCompiler.extract_mutation("%s %s" % [code, raw_args])
6965
else:
7066
# Could be something like:
7167
# "=1.0"
@@ -79,10 +75,8 @@ func _init(line: String) -> void:
7975

8076
match code:
8177
"wait":
82-
if pauses.has(index):
83-
pauses[index] += args.get("value").to_float()
84-
else:
85-
pauses[index] = args.get("value").to_float()
78+
var wait: Dictionary = DMCompiler.extract_mutation("do wait(%s)" % [args.get("value", "null")])
79+
mutations.append([index, wait])
8680
"speed":
8781
speeds[index] = args.get("value").to_float()
8882
"/speed":

addons/dialogue_manager/components/code_edit_syntax_highlighter.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func _get_line_syntax_highlighting(line: int) -> Dictionary:
130130
if tag.begins_with("if"):
131131
colors[index + bbcode.start + 1] = { color = theme.conditions_color }
132132
else:
133-
colors[index + bbcode.start + 1] = { color = theme.mutations_color }
133+
colors[index + bbcode.start + 1] = { color = theme.mutations_line_color }
134134
var expression: Array = expression_parser.tokenise(code, DMConstants.TYPE_MUTATION, bbcode.start + bbcode.code.length())
135135
if expression.size() == 0 or expression[0].type == DMConstants.TYPE_ERROR:
136136
colors[index + bbcode.start + tag.length() + 1] = { color = theme.critical_color }

addons/dialogue_manager/dialogue_label.gd

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ class_name DialogueLabel extends RichTextLabel
99
## Emitted for each letter typed out.
1010
signal spoke(letter: String, letter_index: int, speed: float)
1111

12-
## Emitted when typing paused for a `[wait]`
13-
signal paused_typing(duration: float)
14-
1512
## Emitted when the player skips the typing of dialogue.
1613
signal skipped_typing()
1714

@@ -21,6 +18,9 @@ signal started_typing()
2118
## Emitted when typing finishes.
2219
signal finished_typing()
2320

21+
## [Deprecated] No longer emitted.
22+
signal paused_typing(duration: float)
23+
2424

2525
## The action to press to skip typing.
2626
@export var skip_action: StringName = &"ui_cancel"
@@ -57,12 +57,13 @@ var dialogue_line:
5757
## Whether the label is currently typing itself out.
5858
var is_typing: bool = false:
5959
set(value):
60-
var is_finished: bool = is_typing != value and value == false
61-
is_typing = value
60+
var is_finished: bool = _is_typing != value and value == false and visible_characters == get_total_character_count()
61+
_is_typing = value
6262
if is_finished:
6363
finished_typing.emit()
6464
get:
65-
return is_typing
65+
return _is_typing and not _is_awaiting_mutation
66+
var _is_typing: bool = false
6667

6768
var _last_wait_index: int = -1
6869
var _last_mutation_index: int = -1
@@ -71,7 +72,7 @@ var _is_awaiting_mutation: bool = false
7172

7273

7374
func _process(delta: float) -> void:
74-
if self.is_typing:
75+
if _is_typing:
7576
# Type out text
7677
if visible_ratio < 1:
7778
# See if we are waiting
@@ -83,7 +84,7 @@ func _process(delta: float) -> void:
8384
else:
8485
# Make sure any mutations at the end of the line get run
8586
_mutate_inline_mutations(get_total_character_count())
86-
self.is_typing = false
87+
is_typing = false
8788

8889

8990
## Sets the label's text from the current dialogue line. Override if you want
@@ -102,25 +103,25 @@ func type_out() -> void:
102103
_last_mutation_index = -1
103104
_already_mutated_indices.clear()
104105

105-
self.is_typing = true
106+
is_typing = true
106107
started_typing.emit()
107108

108109
# Allow typing listeners a chance to connect
109110
await get_tree().process_frame
110111

111112
if get_total_character_count() == 0:
112-
self.is_typing = false
113+
is_typing = false
113114
elif seconds_per_step == 0:
114115
_mutate_remaining_mutations()
115116
visible_characters = get_total_character_count()
116-
self.is_typing = false
117+
is_typing = false
117118

118119

119120
## Stop typing out the text and jump right to the end
120121
func skip_typing() -> void:
121122
_mutate_remaining_mutations()
122123
visible_characters = get_total_character_count()
123-
self.is_typing = false
124+
is_typing = false
124125
skipped_typing.emit()
125126

126127

@@ -136,17 +137,11 @@ func _type_next(delta: float, seconds_needed: float) -> void:
136137
_mutate_inline_mutations(visible_characters)
137138
if _is_awaiting_mutation: return
138139

139-
var additional_waiting_seconds: float = _get_pause(visible_characters)
140-
141140
# Pause on characters like "."
142-
if _should_auto_pause():
143-
additional_waiting_seconds += seconds_per_pause_step
144-
145-
# Pause at literal [wait] directives
146-
if _last_wait_index != visible_characters and additional_waiting_seconds > 0:
141+
var waiting_seconds: float = seconds_per_pause_step if _should_auto_pause() else 0
142+
if _last_wait_index != visible_characters and waiting_seconds > 0:
147143
_last_wait_index = visible_characters
148-
_waiting_seconds += additional_waiting_seconds
149-
paused_typing.emit(_get_pause(visible_characters))
144+
_waiting_seconds += waiting_seconds
150145
else:
151146
visible_characters += 1
152147
if visible_characters <= get_total_character_count():
@@ -159,11 +154,6 @@ func _type_next(delta: float, seconds_needed: float) -> void:
159154
_type_next(delta, seconds_needed)
160155

161156

162-
# Get the pause for the current typing position if there is one
163-
func _get_pause(at_index: int) -> float:
164-
return dialogue_line.pauses.get(at_index, 0)
165-
166-
167157
# Get the speed for the current typing position
168158
func _get_speed(at_index: int) -> float:
169159
var speed: float = 1

addons/dialogue_manager/dialogue_line.gd

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ var text_replacements: Array[Dictionary] = []
2626
## The key to use for translating this line.
2727
var translation_key: String = ""
2828

29-
## A map for when and for how long to pause while typing out the dialogue text.
30-
var pauses: Dictionary = {}
31-
3229
## A map for speed changes when typing out the dialogue text.
3330
var speeds: Dictionary = {}
3431

@@ -71,7 +68,6 @@ func _init(data: Dictionary = {}) -> void:
7168
text = data.text
7269
text_replacements = data.get("text_replacements", [] as Array[Dictionary])
7370
translation_key = data.get("translation_key", data.text)
74-
pauses = data.get("pauses", {})
7571
speeds = data.get("speeds", {})
7672
inline_mutations = data.get("inline_mutations", [] as Array[Array])
7773
time = data.get("time", "")

addons/dialogue_manager/dialogue_manager.gd

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ signal bridge_get_line_completed(line: DialogueLine)
3737
## Used internally
3838
signal bridge_dialogue_started(resource: DialogueResource)
3939

40-
## Used inernally
40+
## Used internally
4141
signal bridge_mutated()
4242

4343

@@ -363,7 +363,7 @@ func get_resolved_line_data(data: Dictionary, extra_game_states: Array = []) ->
363363
resolved_text = resolved_text.substr(0, r.start) + r.body + resolved_text.substr(r.end, 9999)
364364
# Move any other markers now that the text has changed
365365
var offset: int = r.end - r.start - r.body.length()
366-
for key in [&"pauses", &"speeds", &"time"]:
366+
for key in [&"speeds", &"time"]:
367367
if markers.get(key) == null: continue
368368
var marker = markers.get(key)
369369
var next_marker: Dictionary = {}
@@ -610,7 +610,6 @@ func create_dialogue_line(data: Dictionary, extra_game_states: Array) -> Dialogu
610610
text = resolved_data.text,
611611
text_replacements = data.get(&"text_replacements", [] as Array[Dictionary]),
612612
translation_key = data.get(&"translation_key", data.text),
613-
pauses = resolved_data.pauses,
614613
speeds = resolved_data.speeds,
615614
inline_mutations = resolved_data.mutations,
616615
time = resolved_data.time,
@@ -746,7 +745,11 @@ func _mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation:
746745
match expression[0].function:
747746
&"wait", &"Wait":
748747
mutated.emit(mutation.merged({ is_inline = is_inline_mutation }))
749-
await Engine.get_main_loop().create_timer(float(args[0])).timeout
748+
if [TYPE_FLOAT, TYPE_INT].has(typeof(args[0])):
749+
await Engine.get_main_loop().create_timer(float(args[0])).timeout
750+
else:
751+
var actions: PackedStringArray = PackedStringArray(args[0] if typeof(args[0]) == TYPE_ARRAY else [args[0]])
752+
await _wait_for(actions)
750753
return
751754

752755
&"debug", &"Debug":
@@ -768,6 +771,14 @@ func _mutate(mutation: Dictionary, extra_game_states: Array, is_inline_mutation:
768771
await Engine.get_main_loop().process_frame
769772

770773

774+
# Wait for a given action
775+
func _wait_for(actions: PackedStringArray) -> void:
776+
var waiter = DMWaiter.new(actions)
777+
add_child(waiter)
778+
await waiter.waited
779+
waiter.queue_free()
780+
781+
771782
# Check if a mutation contains an assignment token.
772783
func _mutation_contains_assignment(mutation: Array) -> bool:
773784
for token in mutation:

addons/dialogue_manager/example_balloon/example_balloon.gd

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ var mutation_cooldown: Timer = Timer.new()
5151
## The menu of responses
5252
@onready var responses_menu: DialogueResponsesMenu = %ResponsesMenu
5353

54+
## Indicator to show that player can progress dialogue.
55+
@onready var progress: Polygon2D = %Progress
56+
5457

5558
func _ready() -> void:
5659
balloon.hide()
@@ -64,6 +67,10 @@ func _ready() -> void:
6467
add_child(mutation_cooldown)
6568

6669

70+
func _process(delta: float) -> void:
71+
progress.visible = not dialogue_label.is_typing and dialogue_line.responses.size() == 0
72+
73+
6774
func _unhandled_input(_event: InputEvent) -> void:
6875
# Only the balloon is allowed to handle input while it's showing
6976
get_viewport().set_input_as_handled()
@@ -91,6 +98,7 @@ func start(dialogue_resource: DialogueResource, title: String, extra_game_states
9198
func apply_dialogue_line() -> void:
9299
mutation_cooldown.stop()
93100

101+
progress.hide()
94102
is_waiting_for_input = false
95103
balloon.focus_mode = Control.FOCUS_ALL
96104
balloon.grab_focus()
@@ -142,9 +150,10 @@ func _on_mutation_cooldown_timeout() -> void:
142150

143151

144152
func _on_mutated(_mutation: Dictionary) -> void:
145-
is_waiting_for_input = false
146-
will_hide_balloon = true
147-
mutation_cooldown.start(0.1)
153+
if not _mutation.is_inline:
154+
is_waiting_for_input = false
155+
will_hide_balloon = true
156+
mutation_cooldown.start(0.1)
148157

149158

150159
func _on_balloon_gui_input(event: InputEvent) -> void:

0 commit comments

Comments
 (0)