Skip to content

Commit 56d2dc0

Browse files
Portraits: Improving/fixing issues with Speaker signal and Highlight methods (#2543)
- fixes several issues reported on the discord server This code is defenitely breaking some compatibilty, because the speaker is now stored as an identifier and not as a resource_path in the current_state (breaks compat with old saves and maybe with some custom code of people). This is necessary to allow the speaker_update method to work with runtime-characters. Could also break stuff because the order of operations in the text event has slightly been changed. Also removed the unnecessary get_current_character method from the Portraits subsystem, as it just did the same as the Text systems method, and speaker is mostly a text concept anyways. Fixed a dumb mistake in the dialogic_identifiable_resource
1 parent 7262af4 commit 56d2dc0

File tree

6 files changed

+96
-83
lines changed

6 files changed

+96
-83
lines changed

Tests/Unit/subsystem_text_test.gd

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
extends GdUnitTestSuite
22

3-
const VALID_SPEAKER_PATH := "res://Tests/Resources/unit_test_character.dch"
3+
const VALID_SPEAKER_PATH := "unit_test_character"
4+
5+
6+
func test_build_character_directory() -> void:
7+
DialogicResourceUtil.update()
8+
49

510
## We ensure that missing a speaker will return null.
611
func test_missing_current_speaker() -> void:
@@ -24,4 +29,4 @@ func test_set_valid_current_speaker() -> void:
2429
var current_speaker := DialogicUtil.autoload().Text.get_current_speaker()
2530

2631
assert(not current_speaker == null, "Valid speaker must be valid, but is invalid.")
27-
assert(current_speaker.get_path() == VALID_SPEAKER_PATH, "Valid speaker path is not set correctly.")
32+
assert(current_speaker.get_identifier() == VALID_SPEAKER_PATH, "Valid speaker path is not set correctly.")

addons/dialogic/Core/DialogicGameHandler.gd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ signal dialogic_paused
8080
signal dialogic_resumed
8181

8282

83-
## Emitted when the timeline ends.
84-
## This can be a timeline ending or [method end_timeline] being called.
85-
signal timeline_ended
8683
## Emitted when a timeline starts by calling either [method start]
8784
## or [method start_timeline].
8885
signal timeline_started
86+
## Emitted when the timeline ends.
87+
## This can be a timeline ending or [method end_timeline] being called.
88+
signal timeline_ended
8989
## Emitted when an event starts being executed.
9090
## The event may not have finished executing yet.
9191
signal event_handled(resource: DialogicEvent)

addons/dialogic/Modules/Character/subsystem_portraits.gd

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void:
5353
push_error('[Dialogic] Failed to load character "' + str(character_path) + '".')
5454

5555
# Load Speaker Portrait
56-
var speaker: Variant = dialogic.current_state_info.get('speaker', "")
56+
var speaker: Variant = dialogic.current_state_info.get("speaker", "")
5757
if speaker:
58-
dialogic.current_state_info['speaker'] = ""
59-
change_speaker(load(speaker))
60-
dialogic.current_state_info['speaker'] = speaker
58+
dialogic.current_state_info["speaker"] = ""
59+
change_speaker(DialogicResourceUtil.get_character_resource(speaker))
60+
dialogic.current_state_info["speaker"] = speaker
6161

6262

6363
func pause() -> void:
@@ -613,13 +613,6 @@ func remove_character(character: DialogicCharacter) -> void:
613613
dialogic.current_state_info['portraits'].erase(character.resource_path)
614614

615615

616-
func get_current_character() -> DialogicCharacter:
617-
if dialogic.current_state_info.get('speaker', null):
618-
return load(dialogic.current_state_info.speaker)
619-
return null
620-
621-
622-
623616
## Returns true if the given character is currently joined.
624617
func is_character_joined(character: DialogicCharacter) -> bool:
625618
if character == null or not character.resource_path in dialogic.current_state_info['portraits']:
@@ -733,16 +726,13 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
733726

734727
_change_portrait_mirror(character_node)
735728

736-
if speaker:
737-
if speaker.resource_path != dialogic.current_state_info['speaker']:
738-
if dialogic.current_state_info['speaker'] and is_character_joined(load(dialogic.current_state_info['speaker'])):
739-
dialogic.current_state_info['portraits'][dialogic.current_state_info['speaker']].node.get_child(-1)._unhighlight()
740-
741-
if speaker and is_character_joined(speaker):
742-
dialogic.current_state_info['portraits'][speaker.resource_path].node.get_child(-1)._highlight()
743-
744-
elif dialogic.current_state_info['speaker'] and is_character_joined(load(dialogic.current_state_info['speaker'])):
745-
dialogic.current_state_info['portraits'][dialogic.current_state_info['speaker']].node.get_child(-1)._unhighlight()
729+
var prev_speaker: DialogicCharacter = dialogic.Text.get_current_speaker()
730+
if speaker != prev_speaker:
731+
if is_character_joined(prev_speaker):
732+
dialogic.current_state_info["portraits"][prev_speaker.resource_path].node.get_child(-1)._unhighlight()
733+
734+
if is_character_joined(speaker):
735+
dialogic.current_state_info["portraits"][speaker.resource_path].node.get_child(-1)._highlight()
746736

747737
#endregion
748738

@@ -753,14 +743,15 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
753743
## Called from the [portrait=something] text effect.
754744
func text_effect_portrait(_text_node:Control, _skipped:bool, argument:String) -> void:
755745
if argument:
756-
if dialogic.current_state_info.get('speaker', null):
757-
change_character_portrait(load(dialogic.current_state_info.speaker), argument)
758-
change_speaker(load(dialogic.current_state_info.speaker), argument)
746+
var current_speaker := dialogic.Text.get_current_speaker()
747+
if current_speaker:
748+
change_character_portrait(current_speaker, argument)
749+
change_speaker(current_speaker, argument)
759750

760751

761752
## Called from the [extra_data=something] text effect.
762753
func text_effect_extradata(_text_node:Control, _skipped:bool, argument:String) -> void:
763754
if argument:
764-
if dialogic.current_state_info.get('speaker', null):
765-
change_character_extradata(load(dialogic.current_state_info.speaker), argument)
755+
if dialogic.Text.get_current_speaker():
756+
change_character_extradata(dialogic.Text.get_current_speaker(), argument)
766757
#endregion

addons/dialogic/Modules/Text/event_text.gd

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -51,45 +51,60 @@ func _clear_state() -> void:
5151
dialogic.current_state_info.erase('text_sub_idx')
5252
_disconnect_signals()
5353

54+
5455
func _execute() -> void:
5556
if text.is_empty():
5657
finish()
5758
return
58-
59-
if (not character or character.custom_info.get('style', '').is_empty()) and dialogic.has_subsystem('Styles'):
60-
# if previous characters had a custom style change back to base style
61-
if dialogic.current_state_info.get('base_style') != dialogic.current_state_info.get('style'):
62-
dialogic.Styles.change_style(dialogic.current_state_info.get('base_style', 'Default'))
63-
await dialogic.get_tree().process_frame
64-
65-
var character_name_text := dialogic.Text.get_character_name_parsed(character)
66-
if character:
67-
dialogic.current_state_info['speaker'] = character.resource_path
68-
if dialogic.has_subsystem('Styles') and character.custom_info.get('style', null):
69-
dialogic.Styles.change_style(character.custom_info.style, false)
70-
await dialogic.get_tree().process_frame
71-
72-
73-
if portrait and dialogic.has_subsystem('Portraits') and dialogic.Portraits.is_character_joined(character):
74-
dialogic.Portraits.change_character_portrait(character, portrait)
75-
dialogic.Portraits.change_speaker(character, portrait)
76-
var check_portrait: String = portrait if !portrait.is_empty() else dialogic.current_state_info['portraits'].get(character.resource_path, {}).get('portrait', '')
77-
78-
if check_portrait and character.portraits.get(check_portrait, {}).get('sound_mood', '') in character.custom_info.get('sound_moods', {}):
79-
dialogic.Text.update_typing_sound_mood(character.custom_info.get('sound_moods', {}).get(character.portraits[check_portrait].get('sound_mood', {}), {}))
80-
elif !character.custom_info.get('sound_mood_default', '').is_empty():
81-
dialogic.Text.update_typing_sound_mood(character.custom_info.get('sound_moods', {}).get(character.custom_info.get('sound_mood_default'), {}))
59+
60+
61+
## Change Portrait and Active Speaker
62+
if dialogic.has_subsystem("Portraits"):
63+
if character:
64+
65+
dialogic.Portraits.change_speaker(character, portrait)
66+
67+
if portrait and dialogic.Portraits.is_character_joined(character):
68+
dialogic.Portraits.change_character_portrait(character, portrait)
69+
8270
else:
83-
dialogic.Text.update_typing_sound_mood()
84-
71+
dialogic.Portraits.change_speaker(null)
72+
73+
## Change and Type Sound Mood
74+
if character:
8575
dialogic.Text.update_name_label(character)
76+
77+
var current_portrait: String = portrait
78+
if portrait.is_empty():
79+
portrait = dialogic.current_state_info["portraits"].get(character.resource_path, {}).get("portrait", "")
80+
81+
var current_portrait_sound_mood: String = character.portraits.get(current_portrait, {}).get("sound_mood", "")
82+
dialogic.Text.update_typing_sound_mood_from_character(character, current_portrait_sound_mood)
83+
8684
else:
87-
dialogic.Portraits.change_speaker(null)
8885
dialogic.Text.update_name_label(null)
8986
dialogic.Text.update_typing_sound_mood()
87+
88+
89+
## Handle style changes
90+
if dialogic.has_subsystem("Styles"):
91+
var current_base_style: String = dialogic.current_state_info.get("base_style")
92+
var current_style: String = dialogic.current_state_info.get("style", "")
93+
var character_style: String = "" if not character else character.custom_info.get("style", "")
94+
95+
## Change back to base style, if another characters style is currently used
96+
if (not character or character_style.is_empty()) and (current_base_style != current_style):
97+
dialogic.Styles.change_style(dialogic.current_state_info.get("base_style", "Default"))
98+
await dialogic.get_tree().process_frame
99+
100+
## Change to the characters style if this character has one
101+
elif character and not character_style.is_empty():
102+
dialogic.Styles.change_style(current_style, false)
103+
await dialogic.get_tree().process_frame
90104

91105
_connect_signals()
92106

107+
var character_name_text := dialogic.Text.get_character_name_parsed(character)
93108
var final_text: String = get_property_translated('text')
94109
if ProjectSettings.get_setting('dialogic/text/split_at_new_lines', false):
95110
match ProjectSettings.get_setting('dialogic/text/split_at_new_lines_as', 0):

addons/dialogic/Modules/Text/subsystem_text.gd

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,10 @@ var _autopauses := {}
7474
####################################################################################################
7575

7676
func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
77-
update_dialog_text('', true)
77+
update_dialog_text("", true)
7878
update_name_label(null)
79-
dialogic.current_state_info['speaker'] = ""
80-
dialogic.current_state_info['text'] = ''
79+
dialogic.current_state_info["speaker"] = ""
80+
dialogic.current_state_info["text"] = ""
8181

8282
set_text_reveal_skippable(ProjectSettings.get_setting('dialogic/text/initial_text_reveal_skippable', true))
8383

@@ -90,9 +90,7 @@ func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) ->
9090
func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void:
9191
update_textbox(dialogic.current_state_info.get('text', ''), true)
9292
update_dialog_text(dialogic.current_state_info.get('text', ''), true)
93-
var character: DialogicCharacter = null
94-
if dialogic.current_state_info.get('speaker', ""):
95-
character = load(dialogic.current_state_info.get('speaker', ""))
93+
var character: DialogicCharacter = get_current_speaker()
9694

9795
if character:
9896
update_name_label(character)
@@ -190,18 +188,18 @@ func update_dialog_text(text: String, instant := false, additional := false) ->
190188

191189

192190
func _on_dialog_text_finished() -> void:
193-
text_finished.emit({'text':dialogic.current_state_info['text'], 'character':dialogic.current_state_info['speaker']})
191+
text_finished.emit({"text":dialogic.current_state_info["text"], "character":dialogic.current_state_info["speaker"]})
194192

195193

196194
## Updates the visible name on all name labels nodes.
197195
## If a name changes, the [signal speaker_updated] signal is emitted.
198196
func update_name_label(character:DialogicCharacter):
199-
var character_path := character.resource_path if character else ""
200-
var current_character_path: String = dialogic.current_state_info.get("speaker", "")
197+
var character_id := character.get_identifier() if character else ""
198+
var current_character_id: String = dialogic.current_state_info.get("speaker", "")
201199

202-
if character_path != current_character_path:
203-
dialogic.current_state_info['speaker'] = character_path
200+
if character_id != current_character_id:
204201
speaker_updated.emit(character)
202+
dialogic.current_state_info["speaker"] = character_id
205203

206204
var name_label_text := get_character_name_parsed(character)
207205

@@ -214,8 +212,19 @@ func update_name_label(character:DialogicCharacter):
214212
name_label.self_modulate = Color(1,1,1,1)
215213

216214

215+
func update_typing_sound_mood_from_character(character:DialogicCharacter, mood:String) -> void:
216+
if character.custom_info.get("sound_moods", {}).is_empty():
217+
update_typing_sound_mood()
218+
elif mood in character.custom_info.get("sound_moods", {}):
219+
update_typing_sound_mood(character.custom_info.get("sound_moods", {})[mood])
220+
else:
221+
var default_mood := character.custom_info.get("sound_mood_default")
222+
update_typing_sound_mood(character.custom_info.get("sound_moods", {}).get(default_mood, {}))
223+
224+
225+
217226
func update_typing_sound_mood(mood:Dictionary = {}) -> void:
218-
for typing_sound in get_tree().get_nodes_in_group('dialogic_type_sounds'):
227+
for typing_sound in get_tree().get_nodes_in_group("dialogic_type_sounds"):
219228
typing_sound.load_overwrite(mood)
220229

221230

@@ -447,19 +456,12 @@ func get_character_name_parsed(character:DialogicCharacter) -> String:
447456
## Returns the [class DialogicCharacter] of the current speaker.
448457
## If there is no current speaker or the speaker is not found, returns null.
449458
func get_current_speaker() -> DialogicCharacter:
450-
var speaker_path: String = dialogic.current_state_info.get("speaker", "")
459+
var speaker_id: String = dialogic.current_state_info.get("speaker", "")
451460

452-
if speaker_path.is_empty():
461+
if speaker_id.is_empty():
453462
return null
454463

455-
var speaker_resource := load(speaker_path)
456-
457-
if speaker_resource == null:
458-
return null
459-
460-
var speaker_character := speaker_resource as DialogicCharacter
461-
462-
return speaker_character
464+
return DialogicResourceUtil.get_character_resource(speaker_id)
463465

464466

465467
func _update_user_speed(_user_speed:float) -> void:
@@ -596,9 +598,9 @@ func effect_signal(_text_node:Control, _skipped:bool, argument:String) -> void:
596598

597599
func effect_mood(_text_node:Control, _skipped:bool, argument:String) -> void:
598600
if argument.is_empty(): return
599-
if dialogic.current_state_info.get('speaker', ""):
601+
if get_current_speaker():
600602
update_typing_sound_mood(
601-
load(dialogic.current_state_info.speaker).custom_info.get('sound_moods', {}).get(argument, {}))
603+
get_current_speaker().custom_info.get('sound_moods', {}).get(argument, {}))
602604

603605

604606
var modifier_select_regex := RegEx.create_from_string(r"(?<!\\)\<[^\>]+(\/[^\>]*)\>")

addons/dialogic/Resources/dialogic_identifiable_resource.gd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func _to_string() -> String:
1818
func get_identifier() -> String:
1919
if resource_path:
2020
return DialogicResourceUtil.get_unique_identifier_by_path(resource_path)
21-
if Engine.is_editor_hint():
21+
if not Engine.is_editor_hint():
2222
return DialogicResourceUtil.get_runtime_unique_identifier(self, _get_extension())
2323
return ""
2424

0 commit comments

Comments
 (0)