Skip to content

Commit

Permalink
Implement proper timeline ending logic (#2536)
Browse files Browse the repository at this point in the history
* Adjust clear event to only await music fade if music is playing

* Implement dialog ending timeline

This timeline (by default just a [clear] event) plays when dialog ends (or end_timeline() is called).

* Make sure instant clear event is actually instant
  • Loading branch information
Jowan-Spooner authored Feb 16, 2025
1 parent 5d96384 commit 742fd28
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 19 deletions.
36 changes: 23 additions & 13 deletions addons/dialogic/Core/DialogicGameHandler.gd
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ var paused := false:

dialogic_resumed.emit()

## A timeline that will be played when dialog ends.
## By default this timeline only contains a clear event.
var dialog_ending_timeline: DialogicTimeline

## Emitted when [member paused] changes to `true`.
signal dialogic_paused
## Emitted when [member paused] changes to `false`.
Expand Down Expand Up @@ -158,6 +162,9 @@ func _ready() -> void:

clear()

dialog_ending_timeline = DialogicTimeline.new()
dialog_ending_timeline.from_text("[clear]")


#region TIMELINE & EVENT HANDLING
################################################################################
Expand Down Expand Up @@ -242,9 +249,22 @@ func preload_timeline(timeline_resource:Variant) -> Variant:


## Clears and stops the current timeline.
func end_timeline() -> void:
## If [param skip_ending] is `true`, the dialog_ending_timeline is not getting played
func end_timeline(skip_ending := false) -> void:
if not skip_ending and dialog_ending_timeline and current_timeline != dialog_ending_timeline:
start(dialog_ending_timeline)
return

await clear(ClearFlags.TIMELINE_INFO_ONLY)
_on_timeline_ended()

if Styles.has_active_layout_node() and Styles.get_layout_node().is_inside_tree():
match ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0):
0:
Styles.get_layout_node().get_parent().remove_child(Styles.get_layout_node())
Styles.get_layout_node().queue_free()
1:
Styles.get_layout_node().hide()

timeline_ended.emit()


Expand Down Expand Up @@ -368,7 +388,7 @@ func load_full_state(state_info:Dictionary) -> void:
if current_state_info.get('current_timeline', null):
start_timeline(current_state_info.current_timeline, current_state_info.get('current_event_idx', 0))
else:
end_timeline.call_deferred()
end_timeline.call_deferred(true)
#endregion


Expand Down Expand Up @@ -413,16 +433,6 @@ func add_subsystem(subsystem_name:String, script_path:String) -> DialogicSubsyst
#region HELPERS
################################################################################

## This handles the `Layout End Behaviour` setting that can be changed in the Dialogic settings.
func _on_timeline_ended() -> void:
if self.Styles.has_active_layout_node() and self.Styles.get_layout_node().is_inside_tree():
match ProjectSettings.get_setting('dialogic/layout/end_behaviour', 0):
0:
self.Styles.get_layout_node().get_parent().remove_child(self.Styles.get_layout_node())
self.Styles.get_layout_node().queue_free()
1:
@warning_ignore("unsafe_method_access")
self.Styles.get_layout_node().hide()


func print_debug_moment() -> void:
Expand Down
10 changes: 9 additions & 1 deletion addons/dialogic/Modules/Audio/subsystem_audio.gd
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func update_audio(channel_name:= "", path := "", settings_overrides := {}) -> vo
current_audio_channels[channel_name] = new_player


## Returns true if any audio is playing on the given [param channel_name].
## Returns `true` if any audio is playing on the given [param channel_name].
func is_channel_playing(channel_name: String) -> bool:
return (current_audio_channels.has(channel_name)
and is_instance_valid(current_audio_channels[channel_name])
Expand Down Expand Up @@ -226,6 +226,14 @@ func is_channel_playing_file(file_path: String, channel_name: String) -> bool:
and current_audio_channels[channel_name].stream.resource_path == file_path)


## Returns `true` if any channel is playing.
func is_any_channel_playing() -> bool:
for channel in current_audio_channels:
if is_channel_playing(channel):
return true
return false


func _on_audio_finished(player: AudioStreamPlayer, channel_name: String, path: String) -> void:
if current_audio_channels.has(channel_name) and current_audio_channels[channel_name] == player:
current_audio_channels.erase(channel_name)
Expand Down
9 changes: 5 additions & 4 deletions addons/dialogic/Modules/Clear/event_clear.gd
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ func _execute() -> void:
var time_per_event: float = dialogic.Inputs.auto_skip.time_per_event
final_time = min(time, time_per_event)

if clear_textbox and dialogic.has_subsystem("Text"):
if clear_textbox and dialogic.has_subsystem("Text") and dialogic.Text.is_textbox_visible():
dialogic.Text.update_dialog_text('')
dialogic.Text.hide_textbox()
dialogic.Text.hide_textbox(final_time == 0)
dialogic.current_state = dialogic.States.IDLE
if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout

Expand All @@ -44,9 +44,10 @@ func _execute() -> void:
if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout

if clear_music and dialogic.has_subsystem('Audio'):
dialogic.Audio.stop_all_channels(final_time)
dialogic.Audio.stop_all_one_shot_sounds()
if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout
if dialogic.Audio.is_any_channel_playing():
dialogic.Audio.stop_all_channels(final_time)
if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout

if clear_style and dialogic.has_subsystem('Styles'):
dialogic.Styles.change_style()
Expand Down
2 changes: 1 addition & 1 deletion addons/dialogic/Modules/Jump/event_return.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extends DialogicEvent
################################################################################

func _execute() -> void:
if !dialogic.Jump.is_jump_stack_empty():
if not dialogic.Jump.is_jump_stack_empty():
dialogic.Jump.resume_from_last_jump()
else:
dialogic.end_timeline()
Expand Down

0 comments on commit 742fd28

Please sign in to comment.