Skip to content

Commit 7262af4

Browse files
Events: Simplify logic for branching / end branches (#2559)
* Fix an issue with End Branch events - fixes #2558 * Attempt at a big logic overhaul for branches Trying to get rid of all the code that loops over the timeline with a bunch of "ignore"-levels, because it was always a mess. This seems slightly better. Needs a bunch of testing first though.
1 parent b8624d2 commit 7262af4

File tree

6 files changed

+82
-74
lines changed

6 files changed

+82
-74
lines changed

addons/dialogic/Editor/TimelineEditor/VisualEditor/timeline_editor_visual.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func create_end_branch_event(at_index:int, parent_node:Node) -> Node:
418418
end_branch_event.gui_input.connect(_on_event_block_gui_input.bind(end_branch_event))
419419
parent_node.end_node = end_branch_event
420420
end_branch_event.parent_node = parent_node
421-
end_branch_event.add_end_control(parent_node.resource.get_end_branch_control())
421+
end_branch_event.add_end_control(parent_node.resource._get_end_branch_control())
422422
%Timeline.add_child(end_branch_event)
423423
%Timeline.move_child(end_branch_event, at_index)
424424
return end_branch_event

addons/dialogic/Modules/Choice/event_choice.gd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ func _execute() -> void:
3737
dialogic.Choices.show_current_question(false)
3838
dialogic.current_state = dialogic.States.AWAITING_CHOICE
3939

40+
41+
func _is_branch_starter() -> bool:
42+
return dialogic.Choices.is_question(dialogic.current_timeline_events.find(self))
43+
4044
#endregion
4145

4246

@@ -53,7 +57,7 @@ func _init() -> void:
5357

5458

5559
# return a control node that should show on the END BRANCH node
56-
func get_end_branch_control() -> Control:
60+
func _get_end_branch_control() -> Control:
5761
return load(get_script().resource_path.get_base_dir().path_join('ui_choice_end.tscn')).instantiate()
5862
#endregion
5963

addons/dialogic/Modules/Choice/subsystem_choices.gd

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -244,28 +244,22 @@ func _on_choice_selected(choice_info := {}) -> void:
244244
dialogic.handle_event(choice_info.event_index + 1)
245245

246246

247-
248247
## Returns the indexes of the choice events related to the current question.
249248
func get_current_choice_indexes() -> Array:
250249
var choices := []
251-
var evt_idx := dialogic.current_event_idx
252-
var ignore := 0
250+
var index := dialogic.current_event_idx-1
253251
while true:
254-
if evt_idx >= len(dialogic.current_timeline_events):
252+
index += 1
253+
if index >= len(dialogic.current_timeline_events):
255254
break
256-
if dialogic.current_timeline_events[evt_idx] is DialogicChoiceEvent:
257-
if ignore == 0:
258-
choices.append(evt_idx)
259-
ignore += 1
260-
elif dialogic.current_timeline_events[evt_idx].can_contain_events:
261-
ignore += 1
255+
256+
var event: DialogicEvent = dialogic.current_timeline_events[index]
257+
if event is DialogicChoiceEvent:
258+
choices.append(index)
259+
index = event.get_end_branch_index()
262260
else:
263-
if ignore == 0:
264-
break
261+
break
265262

266-
if dialogic.current_timeline_events[evt_idx] is DialogicEndBranchEvent:
267-
ignore -= 1
268-
evt_idx += 1
269263
return choices
270264

271265

@@ -281,20 +275,27 @@ func _on_dialogic_action() -> void:
281275
#region HELPERS
282276
####################################################################################################
283277

278+
## Returns `true` if the given index is a text event before a question or the first choice event of a question.
284279
func is_question(index:int) -> bool:
285-
if dialogic.current_timeline_events[index] is DialogicTextEvent:
280+
var event: DialogicEvent = dialogic.current_timeline_events[index]
281+
if event is DialogicTextEvent:
286282
if len(dialogic.current_timeline_events)-1 != index:
287-
if dialogic.current_timeline_events[index+1] is DialogicChoiceEvent:
283+
var next_event: DialogicEvent = dialogic.current_timeline_events[index+1]
284+
if next_event is DialogicChoiceEvent:
288285
return true
289286

290-
if dialogic.current_timeline_events[index] is DialogicChoiceEvent:
291-
if index != 0 and dialogic.current_timeline_events[index-1] is DialogicEndBranchEvent:
292-
if dialogic.current_timeline_events[dialogic.current_timeline_events[index-1].find_opening_index(index-1)] is DialogicChoiceEvent:
293-
return false
294-
else:
295-
return true
287+
if event is DialogicChoiceEvent:
288+
if index == 0:
289+
return true
290+
var prev_event: DialogicEvent = dialogic.current_timeline_events[index-1]
291+
if not prev_event is DialogicEndBranchEvent:
292+
return true
293+
var prev_event_opener: DialogicEvent = dialogic.current_timeline_events[prev_event.get_opening_index()]
294+
if prev_event_opener is DialogicChoiceEvent:
295+
return false
296296
else:
297297
return true
298+
298299
return false
299300

300301
#endregion

addons/dialogic/Modules/Condition/event_condition.gd

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ extends DialogicEvent
77
enum ConditionTypes {IF, ELIF, ELSE}
88

99
### Settings
10-
## condition type (see [ConditionTypes]). Defaults to if.
10+
11+
## Condition type (see [ConditionTypes]). Defaults to if.
1112
var condition_type := ConditionTypes.IF
1213
## The condition as a string. Will be executed as an Expression.
1314
var condition := ""
@@ -26,24 +27,12 @@ func _execute() -> void:
2627

2728
var result: bool = dialogic.Expressions.execute_condition(condition)
2829
if not result:
29-
var idx: int = dialogic.current_event_idx
30-
var ignore := 1
31-
while true:
32-
idx += 1
33-
if not dialogic.current_timeline.get_event(idx) or ignore == 0:
34-
break
35-
elif dialogic.current_timeline.get_event(idx).can_contain_events:
36-
ignore += 1
37-
elif dialogic.current_timeline.get_event(idx) is DialogicEndBranchEvent:
38-
ignore -= 1
39-
40-
dialogic.current_event_idx = idx-1
30+
dialogic.current_event_idx = get_end_branch_index()
31+
4132
finish()
4233

4334

44-
## only called if the previous event was an end-branch event
45-
## return true if this event should be executed if the previous event was an end-branch event
46-
func should_execute_this_branch() -> bool:
35+
func _is_branch_starter() -> bool:
4736
return condition_type == ConditionTypes.IF
4837

4938

@@ -60,7 +49,7 @@ func _init() -> void:
6049

6150

6251
# return a control node that should show on the END BRANCH node
63-
func get_end_branch_control() -> Control:
52+
func _get_end_branch_control() -> Control:
6453
return load(get_script().resource_path.get_base_dir().path_join('ui_condition_end.tscn')).instantiate()
6554

6655
################################################################################

addons/dialogic/Modules/Core/event_end_branch.gd

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,42 @@ func _execute() -> void:
1414
finish()
1515

1616

17+
## Returns the index of the first event that
18+
## - is on the same "indentation"
19+
## - is not a branching event (unless it is a branch starter)
1720
func find_next_index() -> int:
1821
var idx: int = dialogic.current_event_idx
19-
20-
var ignore: int = 1
2122
while true:
2223
idx += 1
2324
var event: DialogicEvent = dialogic.current_timeline.get_event(idx)
2425
if not event:
2526
return idx
26-
if event is DialogicEndBranchEvent:
27-
if ignore > 1:
28-
ignore -= 1
29-
elif event.can_contain_events and not event.should_execute_this_branch():
30-
ignore += 1
31-
elif ignore <= 1:
32-
return idx
3327

34-
return idx
28+
if event.can_contain_events:
29+
if event._is_branch_starter():
30+
break
31+
else:
32+
idx = event.get_end_branch_index()
33+
break
34+
else:
35+
break
3536

37+
return idx
3638

37-
func find_opening_index(at_index:int) -> int:
38-
var idx: int = at_index
3939

40-
var ignore: int = 1
40+
func get_opening_index() -> int:
41+
var index: int = dialogic.current_timeline_events.find(self)
4142
while true:
42-
idx -= 1
43-
var event: DialogicEvent = dialogic.current_timeline.get_event(idx)
44-
if not event:
45-
return idx
43+
index -= 1
44+
if index < 0:
45+
break
46+
var event: DialogicEvent = dialogic.current_timeline_events[index]
4647
if event is DialogicEndBranchEvent:
47-
ignore += 1
48+
index = event.get_opening_index()
4849
elif event.can_contain_events:
49-
ignore -= 1
50-
if ignore == 0:
51-
return idx
50+
return index
51+
return 0
5252

53-
return idx
5453
#endregion
5554

5655
#region INITIALIZE

addons/dialogic/Resources/event.gd

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,38 @@ func _execute() -> void:
146146
#endregion
147147

148148

149-
#region OVERRIDABLES
149+
#region BRANCHING EVENTS
150150
################################################################################
151+
## All of this section should only be in use if [member can_contain_events] is `true`.
151152

152-
## to be overridden by sub-classes
153-
## only called if can_contain_events is true.
154-
## return a control node that should show on the END BRANCH node
155-
func get_end_branch_control() -> Control:
153+
154+
## To be overridden. Only called if [member can_contain_events] is `true`.
155+
## Return a control node that should show on the END BRANCH node.
156+
func _get_end_branch_control() -> Control:
156157
return null
157158

158159

159-
## to be overridden by sub-classes
160-
## only called if can_contain_events is true and the previous event was an end-branch event
161-
## return true if this event should be executed if the previous event was an end-branch event
162-
## basically only important for the Condition event but who knows. Some day someone might need this.
163-
func should_execute_this_branch() -> bool:
160+
## To be overridden. Return `true` if this event should be executed even if a previous branch has been executed.
161+
## E.g. IF events returns true, but ELIF and ELSE do not. The first choice of a question does this, while the others don't.
162+
func _is_branch_starter() -> bool:
164163
return false
165164

165+
166+
## Returns the index of the end branch event of this event (Only use if can_contain_events is true).
167+
func get_end_branch_index() -> int:
168+
var idx: int = dialogic.current_timeline_events.find(self)
169+
while true:
170+
idx += 1
171+
var event: DialogicEvent = dialogic.current_timeline.get_event(idx)
172+
if not event:
173+
break
174+
if event.can_contain_events:
175+
idx = event.get_end_branch_index()
176+
if event is DialogicEndBranchEvent:
177+
break
178+
return idx
179+
180+
166181
#endregion
167182

168183

0 commit comments

Comments
 (0)