Skip to content
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

Added a multithreading loading #2522

Merged
merged 2 commits into from
Jan 23, 2025
Merged
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
120 changes: 86 additions & 34 deletions addons/dialogic/Modules/Character/subsystem_portraits.gd
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,22 @@ func load_game_state(_load_flag:=LoadFlags.FULL_LOAD) -> void:
var character_info: Dictionary = portraits_info[character_path]
var character: DialogicCharacter = load(character_path)
var container := dialogic.PortraitContainers.load_position_container(character.get_character_name())
add_character(character, container, character_info.portrait, character_info.position_id)
change_character_mirror(character, character_info.get('custom_mirror', false))
change_character_z_index(character, character_info.get('z_index', 0))
change_character_extradata(character, character_info.get('extra_data', ""))

ResourceLoader.load_threaded_request(character_path)

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

if load_status == ResourceLoader.THREAD_LOAD_LOADED:
character = ResourceLoader.load_threaded_get(character_path)
add_character(character, container, character_info.portrait, character_info.position_id)
change_character_mirror(character, character_info.get('custom_mirror', false))
change_character_z_index(character, character_info.get('z_index', 0))
change_character_extradata(character, character_info.get('extra_data', ""))
else:
push_error('[Dialogic] Failed to load character "' + str(character_path) + '".')

# Load Speaker Portrait
var speaker: Variant = dialogic.current_state_info.get('speaker', "")
Expand Down Expand Up @@ -117,19 +129,29 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:=
if (not previous_portrait == null and
previous_portrait.get_meta('scene', '') == scene_path and
# Also check if the scene supports changing to the given portrait.
previous_portrait.has_method('_should_do_portrait_update') and
previous_portrait._should_do_portrait_update(character, portrait)):
portrait_node = previous_portrait
info['same_scene'] = true

else:

if ResourceLoader.exists(scene_path):
var packed_scene: PackedScene = load(scene_path)
ResourceLoader.load_threaded_request(scene_path)

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

if packed_scene:
portrait_node = packed_scene.instantiate()
if load_status == ResourceLoader.THREAD_LOAD_LOADED:
var packed_scene: PackedScene = ResourceLoader.load_threaded_get(scene_path)
if packed_scene:
portrait_node = packed_scene.instantiate()
else:
push_error('[Dialogic] Portrait node "' + str(scene_path) + '" for character [' + character.display_name + '] could not be loaded. Your portrait might not show up on the screen. Confirm the path is correct.')
else:
push_error('[Dialogic] Portrait node "' + str(scene_path) + '" for character [' + character.display_name + '] could not be loaded. Your portrait might not show up on the screen. Confirm the path is correct.')
push_error('[Dialogic] Failed to load portrait node "' + str(scene_path) + '" for character [' + character.display_name + '].')

if !portrait_node:
portrait_node = default_portrait_scene.instantiate()
Expand All @@ -156,7 +178,8 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:=
if not fade_animation.is_empty() and fade_length > 0:
var fade_out := _animate_node(previous_portrait, fade_animation, fade_length, 1, true)
var _fade_in := _animate_node(portrait_node, fade_animation, fade_length, 1, false)
fade_out.finished.connect(previous_portrait.queue_free)
await fade_out.finished
previous_portrait.queue_free()
else:
previous_portrait.queue_free()

Expand All @@ -167,20 +190,26 @@ func _change_portrait(character_node: Node2D, portrait: String, fade_animation:=
## Unless @force is false, this will take into consideration the character mirror,
## portrait mirror and portrait position mirror settings.
func _change_portrait_mirror(character_node: Node2D, mirrored := false, force := false) -> void:
var latest_portrait := character_node.get_child(-1)
var latest_portrait := character_node.get_child(-1) if character_node.get_child_count() > 0 else null

if latest_portrait.has_method('_set_mirror'):
if latest_portrait and latest_portrait.has_method("_set_mirror"):
var character: DialogicCharacter = character_node.get_meta('character')
var current_portrait_info := character.get_portrait_info(character_node.get_meta('portrait'))
latest_portrait._set_mirror(force or (mirrored != character.mirror != character_node.get_parent().mirrored != current_portrait_info.get('mirror', false)))


func _change_portrait_extradata(character_node: Node2D, extra_data := "") -> void:
var latest_portrait := character_node.get_child(-1)
if not is_instance_valid(character_node):
push_error("[Dialogic] Invalid character node provided.")
return

if latest_portrait.has_method('_set_extra_data'):
latest_portrait._set_extra_data(extra_data)
if character_node.get_child_count() > 0:
var latest_portrait := character_node.get_child(-1)

if latest_portrait and latest_portrait.has_method("_set_extra_data"):
latest_portrait._set_extra_data(extra_data)
else:
push_warning("[Dialogic] No portrait found for character node: " + character_node.name)

func _update_character_transform(character_node:Node, time := 0.0) -> void:
for child in character_node.get_children():
Expand Down Expand Up @@ -379,7 +408,7 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S
return

var container := dialogic.PortraitContainers.add_container(character.get_character_name())
var character_node := add_character(character, container, portrait, position_id)
var character_node := await add_character(character, container, portrait, position_id)
if character_node == null:
return null

Expand Down Expand Up @@ -410,9 +439,9 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S
return character_node


func add_character(character:DialogicCharacter, container: DialogicNode_PortraitContainer, portrait:String, position_id:String) -> Node:
func add_character(character: DialogicCharacter, container: DialogicNode_PortraitContainer, portrait: String, position_id: String) -> Node:
if is_character_joined(character):
printerr('[DialogicError] Cannot add a already joined character. If this is intended call _create_character_node manually.')
printerr('[DialogicError] Cannot add an already joined character. If this is intended, call _create_character_node manually.')
return null

portrait = get_valid_portrait(character, portrait)
Expand All @@ -423,21 +452,31 @@ func add_character(character:DialogicCharacter, container: DialogicNode_Portrait
if not character:
printerr('[DialogicError] Cannot call add_portrait() with null character.')
return null

ResourceLoader.load_threaded_request(character.resource_path)

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)

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 load_status == ResourceLoader.THREAD_LOAD_LOADED:
character = ResourceLoader.load_threaded_get(character.resource_path)
var character_node := _create_character_node(character, container)

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

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

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

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:="DEFAULT", fade_length := -1.0) -> void:
Expand All @@ -455,7 +494,7 @@ func change_character_portrait(character: DialogicCharacter, portrait: String, f

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

var info := _change_portrait(dialogic.current_state_info.portraits[character.resource_path].node, portrait, fade_animation, fade_length)
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
_change_portrait_mirror(
dialogic.current_state_info.portraits[character.resource_path].node,
Expand Down Expand Up @@ -629,7 +668,8 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:

if leave_animation and leave_animation_length:
var animate_out := _animate_node(character_node, leave_animation, leave_animation_length, 1, true)
animate_out.finished.connect(character_node.queue_free)
await animate_out.finished
character_node.queue_free()
else:
character_node.get_parent().remove_child(character_node)
character_node.queue_free()
Expand All @@ -640,7 +680,19 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
continue

if just_joined:
_create_character_node(speaker, container)
ResourceLoader.load_threaded_request(speaker.resource_path)

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

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

elif portrait.is_empty():
continue
Expand All @@ -655,10 +707,10 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:

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

if container.portrait_prefix+portrait in speaker.portraits:
portrait = container.portrait_prefix+portrait
if container.portrait_prefix + portrait in speaker.portraits:
portrait = container.portrait_prefix + portrait

_change_portrait(character_node, portrait, fade_animation, fade_length)
await _change_portrait(character_node, portrait, fade_animation, fade_length)

# if the character has no portraits _change_portrait won't actually add a child node
if character_node.get_child_count() == 0:
Expand All @@ -677,7 +729,7 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void:
var join_animation_length := _get_join_default_length()

if join_animation and join_animation_length:
_animate_node(character_node, join_animation, join_animation_length)
await _animate_node(character_node, join_animation, join_animation_length).finished

_change_portrait_mirror(character_node)

Expand Down
Loading