Skip to content

Runtime Resources: Improve runtime characters ability to have portraits #2589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func execute_tool(method:Callable) -> void:

tool_thread = Thread.new()
tool_progress_mutex = Mutex.new()
print(method)
tool_thread.start(method)

await tool_finished_signal
Expand All @@ -39,7 +38,7 @@ func execute_tool(method:Callable) -> void:
button.disabled = false


func _process(delta: float) -> void:
func _process(_delta: float) -> void:
if (tool_thread and tool_thread.is_alive()) or %ToolProgress.value < 1:
if tool_progress_mutex: tool_progress_mutex.lock()
%ToolProgress.value = tool_progress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ func get_next_search_position(navigate_up := false) -> Vector2i:
search_from_line = get_caret_line()
search_from_column = get_caret_column()

var flags := get_meta("current_search_flags", 0)
var flags: int = get_meta("current_search_flags", 0)
if navigate_up:
flags = flags | SEARCH_BACKWARDS
print()

pos = search(get_meta("current_search"), flags, search_from_line, search_from_column)
return pos

Expand Down
95 changes: 42 additions & 53 deletions addons/dialogic/Modules/Character/subsystem_portraits.gd
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ var default_portrait_scene: PackedScene = load(get_script().resource_path.get_ba
####################################################################################################

func clear_game_state(_clear_flag:=DialogicGameHandler.ClearFlags.FULL_CLEAR) -> void:
for character in dialogic.current_state_info.get('portraits', {}).keys():
remove_character(load(character))
for character_identifier in dialogic.current_state_info.get('portraits', {}).keys():
remove_character(DialogicResourceUtil.get_character_resource(character_identifier))
dialogic.current_state_info['portraits'] = {}


Expand Down Expand Up @@ -315,7 +315,7 @@ func _change_portrait_z_index(character_node: Node, z_index:int, update_zindex:=
## fully visible yet.
func get_character_portrait(character: DialogicCharacter) -> DialogicPortrait:
if is_character_joined(character):
var portrait_node: DialogicPortrait = dialogic.current_state_info['portraits'][character.resource_path].node.get_child(-1)
var portrait_node: DialogicPortrait = dialogic.current_state_info['portraits'][character.get_identifier()].node.get_child(-1)
return portrait_node

return null
Expand Down Expand Up @@ -411,14 +411,14 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S
if character_node == null:
return null

dialogic.current_state_info['portraits'][character.resource_path] = {'portrait':portrait, 'node':character_node, 'position_id':position_id, 'custom_mirror':mirrored}
dialogic.current_state_info['portraits'][character.get_identifier()] = {'portrait':portrait, 'node':character_node, 'position_id':position_id, 'custom_mirror':mirrored}

_change_portrait_mirror(character_node, mirrored)
_change_portrait_extradata(character_node, extra_data)
_change_portrait_z_index(character_node, z_index)

var info := {'character':character}
info.merge(dialogic.current_state_info['portraits'][character.resource_path])
info.merge(dialogic.current_state_info['portraits'][character.get_identifier()])
character_joined.emit(info)

if animation_name.is_empty():
Expand Down Expand Up @@ -452,30 +452,19 @@ func add_character(character: DialogicCharacter, container: DialogicNode_Portrai
printerr('[DialogicError] Cannot call add_portrait() with null character.')
return null

ResourceLoader.load_threaded_request(character.resource_path)
var character_node := _create_character_node(character, container)

var load_status = ResourceLoader.load_threaded_get_status(character.resource_path)
while load_status == ResourceLoader.THREAD_LOAD_IN_PROGRESS:
await get_tree().process_frame
load_status = ResourceLoader.load_threaded_get_status(character.resource_path)

if load_status == ResourceLoader.THREAD_LOAD_LOADED:
character = ResourceLoader.load_threaded_get(character.resource_path)
var character_node := _create_character_node(character, container)
if character_node == null:
printerr('[Dialogic] Failed to join character to position ', position_id, ". Could not find position container.")
return null

if character_node == null:
printerr('[Dialogic] Failed to join character to position ', position_id, ". Could not find position container.")
return null
dialogic.current_state_info['portraits'][character.get_identifier()] = {'portrait': portrait, 'node': character_node, 'position_id': position_id}

dialogic.current_state_info['portraits'][character.resource_path] = {'portrait': portrait, 'node': character_node, 'position_id': position_id}
_move_character(character_node, position_id)
await _change_portrait(character_node, portrait)

_move_character(character_node, position_id)
await _change_portrait(character_node, portrait)
return character_node

return character_node
else:
push_error('[Dialogic] Failed to load character "' + str(character.resource_path) + '".')
return null

## Changes the portrait of a character. Only works with joined characters.
func change_character_portrait(character: DialogicCharacter, portrait: String, fade_animation:="", fade_length := -1.0) -> void:
Expand All @@ -484,7 +473,7 @@ func change_character_portrait(character: DialogicCharacter, portrait: String, f

portrait = get_valid_portrait(character, portrait)

if dialogic.current_state_info.portraits[character.resource_path].portrait == portrait:
if dialogic.current_state_info.portraits[character.get_identifier()].portrait == portrait:
return

if fade_animation == "":
Expand All @@ -493,11 +482,11 @@ func change_character_portrait(character: DialogicCharacter, portrait: String, f

fade_animation = DialogicPortraitAnimationUtil.guess_animation(fade_animation, DialogicPortraitAnimationUtil.AnimationType.CROSSFADE)

var info := await _change_portrait(dialogic.current_state_info.portraits[character.resource_path].node, portrait, fade_animation, fade_length)
dialogic.current_state_info.portraits[character.resource_path].portrait = info.portrait
var info := await _change_portrait(dialogic.current_state_info.portraits[character.get_identifier()].node, portrait, fade_animation, fade_length)
dialogic.current_state_info.portraits[character.get_identifier()].portrait = info.portrait
_change_portrait_mirror(
dialogic.current_state_info.portraits[character.resource_path].node,
dialogic.current_state_info.portraits[character.resource_path].get('custom_mirror', false)
dialogic.current_state_info.portraits[character.get_identifier()].node,
dialogic.current_state_info.portraits[character.get_identifier()].get('custom_mirror', false)
)
character_portrait_changed.emit(info)

Expand All @@ -507,26 +496,26 @@ func change_character_mirror(character:DialogicCharacter, mirrored:= false, forc
if !is_character_joined(character):
return

_change_portrait_mirror(dialogic.current_state_info.portraits[character.resource_path].node, mirrored, force)
dialogic.current_state_info.portraits[character.resource_path]['custom_mirror'] = mirrored
_change_portrait_mirror(dialogic.current_state_info.portraits[character.get_identifier()].node, mirrored, force)
dialogic.current_state_info.portraits[character.get_identifier()]['custom_mirror'] = mirrored


## Changes the z_index of a character. Only works with joined characters
func change_character_z_index(character:DialogicCharacter, z_index:int, update_zindex:= true) -> void:
if !is_character_joined(character):
return

_change_portrait_z_index(dialogic.current_state_info.portraits[character.resource_path].node, z_index, update_zindex)
_change_portrait_z_index(dialogic.current_state_info.portraits[character.get_identifier()].node, z_index, update_zindex)
if update_zindex:
dialogic.current_state_info.portraits[character.resource_path]['z_index'] = z_index
dialogic.current_state_info.portraits[character.get_identifier()]['z_index'] = z_index


## Changes the extra data on the given character. Only works with joined characters
func change_character_extradata(character:DialogicCharacter, extra_data:="") -> void:
if !is_character_joined(character):
return
_change_portrait_extradata(dialogic.current_state_info.portraits[character.resource_path].node, extra_data)
dialogic.current_state_info.portraits[character.resource_path]['extra_data'] = extra_data
_change_portrait_extradata(dialogic.current_state_info.portraits[character.get_identifier()].node, extra_data)
dialogic.current_state_info.portraits[character.get_identifier()]['extra_data'] = extra_data


## Starts the given animation on the given character. Only works with joined characters
Expand All @@ -536,7 +525,7 @@ func animate_character(character: DialogicCharacter, animation_path: String, len

animation_path = DialogicPortraitAnimationUtil.guess_animation(animation_path)

var character_node: Node = dialogic.current_state_info.portraits[character.resource_path].node
var character_node: Node = dialogic.current_state_info.portraits[character.get_identifier()].node

return _animate_node(character_node, animation_path, length, repeats, is_reversed)

Expand All @@ -546,11 +535,11 @@ func move_character(character:DialogicCharacter, position_id:String, time:= 0.0,
if !is_character_joined(character):
return

if dialogic.current_state_info.portraits[character.resource_path].position_id == position_id:
if dialogic.current_state_info.portraits[character.get_identifier()].position_id == position_id:
return

_move_character(dialogic.current_state_info.portraits[character.resource_path].node, position_id, time, easing, trans)
dialogic.current_state_info.portraits[character.resource_path].position_id = position_id
_move_character(dialogic.current_state_info.portraits[character.get_identifier()].node, position_id, time, easing, trans)
dialogic.current_state_info.portraits[character.get_identifier()].position_id = position_id
character_moved.emit({'character':character, 'position_id':position_id, 'time':time})


Expand Down Expand Up @@ -592,8 +581,8 @@ func leave_all_characters(animation_name:="", animation_length:=0.0, animation_w
## Return `null` if the [param character] is not part of the scene.
func get_character_node(character: DialogicCharacter) -> Node:
if is_character_joined(character):
if is_instance_valid(dialogic.current_state_info['portraits'][character.resource_path].node):
return dialogic.current_state_info['portraits'][character.resource_path].node
if is_instance_valid(dialogic.current_state_info['portraits'][character.get_identifier()].node):
return dialogic.current_state_info['portraits'][character.get_identifier()].node
return null


Expand All @@ -609,12 +598,12 @@ func remove_character(character: DialogicCharacter) -> void:
character_node.queue_free()
character_left.emit({'character': character})

dialogic.current_state_info['portraits'].erase(character.resource_path)
dialogic.current_state_info['portraits'].erase(character.get_identifier())


## Returns true if the given character is currently joined.
func is_character_joined(character: DialogicCharacter) -> bool:
if character == null or not character.resource_path in dialogic.current_state_info['portraits']:
if character == null or not character.get_identifier() in dialogic.current_state_info['portraits']:
return false

return true
Expand All @@ -624,8 +613,8 @@ func is_character_joined(character: DialogicCharacter) -> bool:
func get_joined_characters() -> Array[DialogicCharacter]:
var chars: Array[DialogicCharacter] = []

for char_path: String in dialogic.current_state_info.get('portraits', {}).keys():
chars.append(load(char_path))
for char_identifier: String in dialogic.current_state_info.get('portraits', {}).keys():
chars.append(DialogicResourceUtil.get_character_resource(char_identifier))

return chars

Expand All @@ -635,7 +624,7 @@ func get_joined_characters() -> Array[DialogicCharacter]:
## Only joined is included (and false) for not joined characters
func get_character_info(character:DialogicCharacter) -> Dictionary:
if is_character_joined(character):
var info: Dictionary = dialogic.current_state_info['portraits'][character.resource_path]
var info: Dictionary = dialogic.current_state_info['portraits'][character.get_identifier()]
info['joined'] = true
return info
else:
Expand Down Expand Up @@ -672,18 +661,18 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
continue

if just_joined:
ResourceLoader.load_threaded_request(speaker.resource_path)
ResourceLoader.load_threaded_request(speaker.get_identifier())

var load_status = ResourceLoader.load_threaded_get_status(speaker.resource_path)
var load_status = ResourceLoader.load_threaded_get_status(speaker.get_identifier())
while load_status == ResourceLoader.THREAD_LOAD_IN_PROGRESS:
await get_tree().process_frame
load_status = ResourceLoader.load_threaded_get_status(speaker.resource_path)
load_status = ResourceLoader.load_threaded_get_status(speaker.get_identifier())

if load_status == ResourceLoader.THREAD_LOAD_LOADED:
speaker = ResourceLoader.load_threaded_get(speaker.resource_path)
speaker = ResourceLoader.load_threaded_get(speaker.get_identifier())
_create_character_node(speaker, container)
else:
push_error('[Dialogic] Failed to load speaker "' + str(speaker.resource_path) + '".')
push_error('[Dialogic] Failed to load speaker "' + str(speaker.get_identifier()) + '".')
continue

elif portrait.is_empty():
Expand Down Expand Up @@ -728,10 +717,10 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
var prev_speaker: DialogicCharacter = dialogic.Text.get_current_speaker()
if speaker != prev_speaker:
if is_character_joined(prev_speaker):
dialogic.current_state_info["portraits"][prev_speaker.resource_path].node.get_child(-1)._unhighlight()
dialogic.current_state_info["portraits"][prev_speaker.get_identifier()].node.get_child(-1)._unhighlight()

if is_character_joined(speaker):
dialogic.current_state_info["portraits"][speaker.resource_path].node.get_child(-1)._highlight()
dialogic.current_state_info["portraits"][speaker.get_identifier()].node.get_child(-1)._highlight()

#endregion

Expand Down
1 change: 0 additions & 1 deletion addons/dialogic/Modules/Style/DialogicStylesUtil.gd
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ static func get_fallback_style() -> DialogicStyle:


static func get_style_path(name_or_path:String) -> String:
print(style_directory)
if name_or_path.begins_with("res://"):
if not ResourceLoader.exists(name_or_path):
name_or_path = ""
Expand Down
2 changes: 1 addition & 1 deletion addons/dialogic/Modules/Text/event_text.gd
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func _execute() -> void:

var current_portrait: String = portrait
if portrait.is_empty():
portrait = dialogic.current_state_info["portraits"].get(character.resource_path, {}).get("portrait", "")
current_portrait = dialogic.current_state_info["portraits"].get(character.get_identifier(), {}).get("portrait", "")

var current_portrait_sound_mood: String = character.portraits.get(current_portrait, {}).get("sound_mood", "")
dialogic.Text.update_typing_sound_mood_from_character(character, current_portrait_sound_mood)
Expand Down
23 changes: 10 additions & 13 deletions addons/dialogic/Resources/character.gd
Original file line number Diff line number Diff line change
Expand Up @@ -139,21 +139,18 @@ func get_character_name() -> String:
else:
return "UnnamedCharacter"

#
### Sets the unique identifier-string of this resource.
### In editor (if the resource is already saved) the identifier will be stored.
### In game (if the resource is not stored) the resource will be temporarily registered.
#func set_identifier(new_identifier:String) -> bool:
#if resource_path and Engine.is_editor_hint():
#DialogicResourceUtil.change_unique_identifier(resource_path, new_identifier)
#return true
#if not resource_path and not Engine.is_editor_hint():
#DialogicResourceUtil.register_runtime_resource(self, new_identifier, "dch")
#return true
#return false


## Returns the info of the given portrait.
## Uses the default portrait if the given portrait doesn't exist.
func get_portrait_info(portrait_name:String) -> Dictionary:
return portraits.get(portrait_name, portraits.get(default_portrait, {}))


## Helper method intended for a simplified creation of portraits at runtime.
## For more complex needs, manually writing to the portraits dict is recommended.
func add_portrait(name:String, image:String, scene:= "") -> void:
portraits[name] = {
"scene": scene,
"export_overrides": {
"image": image}
}