diff --git a/Tests/Unit/guess_special_resource_test.gd b/Tests/Unit/guess_special_resource_test.gd index 14c7574eb..41749c7d0 100644 --- a/Tests/Unit/guess_special_resource_test.gd +++ b/Tests/Unit/guess_special_resource_test.gd @@ -4,9 +4,9 @@ extends GdUnitTestSuite ## as space-delimited prefix. func test_fade_in_animation_paths() -> void: const TYPE := "PortraitAnimation" - var fade_in_1 := DialogicResourceUtil.guess_special_resource(TYPE, "fade in", "") - var fade_in_2 := DialogicResourceUtil.guess_special_resource(TYPE, "fade in out", "") - var fade_in_3 := DialogicResourceUtil.guess_special_resource(TYPE, "fade out", "") + var fade_in_1: String = DialogicResourceUtil.guess_special_resource(TYPE, "fade in").get('path', "") + var fade_in_2: String = DialogicResourceUtil.guess_special_resource(TYPE, "fade cross").get('path', "") + var fade_in_3: String = DialogicResourceUtil.guess_special_resource(TYPE, "fade out").get('path', "") var is_any_fade_in_empty := fade_in_1.is_empty() or fade_in_2.is_empty() or fade_in_3.is_empty() assert(is_any_fade_in_empty == false, "Fade In/Out animations are empty.") @@ -18,22 +18,22 @@ func test_fade_in_animation_paths() -> void: ## Test if invalid animation paths will return empty strings. func test_invalid_animation_path() -> void: const TYPE := "PortraitAnimation" - var invalid_animation_1 := DialogicResourceUtil.guess_special_resource(TYPE, "fade i", "") + var invalid_animation_1: String = DialogicResourceUtil.guess_special_resource(TYPE, "fade i").get('path', "") assert(invalid_animation_1.is_empty() == true, "Invalid animation 1's path is not empty.") - var invalid_animation_2 := DialogicResourceUtil.guess_special_resource(TYPE, "fade", "") + var invalid_animation_2: String = DialogicResourceUtil.guess_special_resource(TYPE, "fade").get('path', "") assert(invalid_animation_2.is_empty() == true, "Invalid animation 2's path is not empty.") ## Test if invalid types will return empty strings. func test_invalid_type_path() -> void: const INVALID_TYPE := "Portait Animation" - var invalid_animation := DialogicResourceUtil.guess_special_resource(INVALID_TYPE, "fade in", "") + var invalid_animation: String = DialogicResourceUtil.guess_special_resource(INVALID_TYPE, "fade in").get('path', "") assert(invalid_animation.is_empty() == true, "Invalid animation 1's path is not empty.") const VALID_TYPE := "PortraitAnimation" - var valid_animation_path := DialogicResourceUtil.guess_special_resource(VALID_TYPE, "fade in", "") + var valid_animation_path: String = DialogicResourceUtil.guess_special_resource(VALID_TYPE, "fade in").get('path', "") assert(valid_animation_path.is_empty() == false, "Valids animation's path is empty.") assert(not invalid_animation == valid_animation_path, "Valid and invalid animation paths are equal.") diff --git a/addons/dialogic/Core/DialogicResourceUtil.gd b/addons/dialogic/Core/DialogicResourceUtil.gd index cac50ee47..d8e978fa0 100644 --- a/addons/dialogic/Core/DialogicResourceUtil.gd +++ b/addons/dialogic/Core/DialogicResourceUtil.gd @@ -4,7 +4,7 @@ class_name DialogicResourceUtil static var label_cache := {} static var event_cache: Array[DialogicEvent] = [] -static var special_resources : Array[Dictionary] = [] +static var special_resources := {} static func update() -> void: @@ -173,43 +173,75 @@ static func update_event_cache() -> Array: ################################################################################ static func update_special_resources() -> void: - special_resources = [] + special_resources.clear() for indexer in DialogicUtil.get_indexers(): - special_resources.append_array(indexer._get_special_resources()) + var additions := indexer._get_special_resources() + for resource_type in additions: + if not resource_type in special_resources: + special_resources[resource_type] = {} + special_resources[resource_type].merge(additions[resource_type]) -static func list_special_resources_of_type(type:String) -> Array: +static func list_special_resources(type:String, filter := {}) -> Dictionary: if special_resources.is_empty(): update_special_resources() - return special_resources.filter(func(x:Dictionary): return type == x.get('type','')).map(func(x:Dictionary): return x.get('path', '')) - - -static func guess_special_resource(type: String, name: String, default := "") -> String: + if type in special_resources: + if filter.is_empty(): + return special_resources[type] + else: + var results := {} + for i in special_resources[type]: + if match_resource_filter(special_resources[type][i], filter): + results[i] = special_resources[type][i] + return results + return {} + + +static func match_resource_filter(dict:Dictionary, filter:Dictionary) -> bool: + for i in filter: + if not i in dict: + return false + if typeof(filter[i]) == TYPE_ARRAY: + if not dict[i] in filter[i]: + return false + else: + if not dict[i] == filter[i]: + return false + return true + + +static func guess_special_resource(type: String, string: String, default := {}, filter := {}, ignores:PackedStringArray=[]) -> Dictionary: if special_resources.is_empty(): update_special_resources() - - if name.begins_with('res://'): - return name - - for path: String in list_special_resources_of_type(type): - var pretty_path := DialogicUtil.pretty_name(path).to_lower() - var pretty_name := name.to_lower() - - if pretty_path == pretty_name: - return path - - elif pretty_name.ends_with(" in"): - pretty_name = pretty_name + " out" - - if pretty_path == pretty_name: - return path - - elif pretty_name.ends_with(" out"): - pretty_name = pretty_name.replace("out", "in out") - - if pretty_path == pretty_name: - return path - + var resources := list_special_resources(type, filter) + if resources.is_empty(): + printerr("[Dialogic] No ", type, "s found, but attempted to use one.") + return default + + string = string.to_lower() + + if string.begins_with('res://'): + for i in resources.values(): + if i.path == string: + return i + printerr("[Dialogic] Unable to find ", type, " at path '", string, "'.") + return default + + if string in resources: + return resources[string] + + if not ignores.is_empty(): + var regex := RegEx.create_from_string(r" ?\b(" + "|".join(ignores) + r")\b") + for name in resources: + if regex.sub(name, "") == string: + return resources[name] + + ## As a last effort check against the unfiltered list + if string in special_resources[type]: + push_warning("[Dialogic] Using ", type, " '", string,"' when not supposed to.") + return special_resources[type][string] + + printerr("[Dialogic] Unable to identify ", type, " based on string '", string, "'.") return default #endregion diff --git a/addons/dialogic/Core/DialogicUtil.gd b/addons/dialogic/Core/DialogicUtil.gd index 85148cb8c..51931b62b 100644 --- a/addons/dialogic/Core/DialogicUtil.gd +++ b/addons/dialogic/Core/DialogicUtil.gd @@ -111,39 +111,6 @@ static func get_indexers(include_custom := true, force_reload := false) -> Array return indexers -enum AnimationType {ALL, IN, OUT, ACTION} - - - -static func get_portrait_animation_scripts(type := AnimationType.ALL) -> Array: - var animations := DialogicResourceUtil.list_special_resources_of_type("PortraitAnimation") - const CROSS_ANIMATION := "_in_out" - const OUT_ANIMATION := "_out" - const IN_ANIMATION := "_in" - - return animations.filter( - func(script: String) -> bool: - match (type): - AnimationType.ALL: - return true - - AnimationType.IN: - return IN_ANIMATION in script or CROSS_ANIMATION in script - - AnimationType.OUT: - return OUT_ANIMATION in script or CROSS_ANIMATION in script - - # All animations that are not IN or OUT. - # Extra check for CROSS animations to prevent parsing parts - # of the name as an IN or OUT animation. - AnimationType.ACTION: - #return CROSS_ANIMATION in script or not (IN_ANIMATION in script or OUT_ANIMATION in script) - return not IN_ANIMATION in script and not OUT_ANIMATION in script - - _: - return false - ) - ## Turns a [param file_path] from `some_file.png` to `Some File`. static func pretty_name(file_path: String) -> String: @@ -153,7 +120,6 @@ static func pretty_name(file_path: String) -> String: return _name - #endregion @@ -633,16 +599,3 @@ static func get_portrait_position_suggestions(search_text := "") -> Dictionary: return suggestions - -static func get_portrait_animation_suggestions(_search_text := "", empty_text := "Default", action := AnimationType.ALL) -> Dictionary: - var suggestions := {} - - suggestions[empty_text] = {'value':"", 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} - - for anim in DialogicUtil.get_portrait_animation_scripts(action): - suggestions[DialogicUtil.pretty_name(anim)] = { - 'value' : DialogicUtil.pretty_name(anim), - 'editor_icon' : ["Animation", "EditorIcons"] - } - - return suggestions diff --git a/addons/dialogic/Core/index_class.gd b/addons/dialogic/Core/index_class.gd index 25e276fc0..979f93035 100644 --- a/addons/dialogic/Core/index_class.gd +++ b/addons/dialogic/Core/index_class.gd @@ -59,8 +59,8 @@ func _get_text_modifiers() -> Array[Dictionary]: ## These can later be retrieved with DialogicResourceUtil. ## Each dictionary should contain (at least "type" and "path"). ## E.g. {"type":"Animation", "path": "res://..."} -func _get_special_resources() -> Array[Dictionary]: - return [] +func _get_special_resources() -> Dictionary: + return {} #region HELPERS @@ -70,12 +70,26 @@ func list_dir(subdir:='') -> Array: return Array(DirAccess.get_files_at(this_folder.path_join(subdir))).map(func(file):return this_folder.path_join(subdir).path_join(file)) -func list_special_resources(subdir:='', type:='', extension:="") -> Array[Dictionary]: - var array := [] +func list_special_resources(subdir:='', extension:="") -> Dictionary: + var dict := {} for i in list_dir(subdir): if extension.is_empty() or i.ends_with(extension): - array.append({'type':type, 'path':i}) - return Array(array, TYPE_DICTIONARY, "", null) + dict[DialogicUtil.pretty_name(i).to_lower()] = {"path":i} + return dict + + +func list_animations(subdir := "") -> Dictionary: + var full_animation_list := {} + for path in list_dir(subdir): + if not path.ends_with(".gd"): + continue + var anim_object: DialogicAnimation = load(path).new() + var versions := anim_object._get_named_variations() + for version_name in versions: + full_animation_list[version_name] = versions[version_name] + full_animation_list[version_name]["path"] = path + anim_object.queue_free() + return full_animation_list #endregion diff --git a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd index 400b9a7a3..697e807d5 100644 --- a/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd +++ b/addons/dialogic/Editor/TimelineEditor/TextEditor/CodeCompletionHelper.gd @@ -15,6 +15,8 @@ var completion_word_regex := RegEx.new() var completion_shortcode_getter_regex := RegEx.new() # To find the parameter name of the current if typing a value var completion_shortcode_param_getter_regex := RegEx.new() +# To find the value of a paramater that is being typed +var completion_shortcode_value_regex := RegEx.new() # Stores references to all shortcode events for parameter and value suggestions var shortcode_events := {} @@ -26,6 +28,7 @@ func _ready() -> void: completion_word_regex.compile("(?(\\W)|^)(?\\w*)\\x{FFFF}") completion_shortcode_getter_regex.compile("\\[(?\\w*)") completion_shortcode_param_getter_regex.compile("(?\\w*)\\W*=\\s*\"?(\\w|\\s)*"+String.chr(0xFFFF)) + completion_shortcode_value_regex.compile(r'(\[|\s)[^\[\s=]*="(?[^"$]*)'+String.chr(0xFFFF)) text_syntax_highlighter.mode = text_syntax_highlighter.Modes.TEXT_EVENT_ONLY @@ -42,6 +45,11 @@ func get_code_completion_word(text:CodeEdit) -> String: var result := completion_word_regex.search(get_code_completion_line(text)) return result.get_string('word') if result else "" +# Helper that gets the currently typed parameter +func get_code_completion_parameter_value(text:CodeEdit) -> String: + var result := completion_shortcode_value_regex.search(get_code_completion_line(text)) + return result.get_string('value') if result else "" + # Helper that gets the symbol before the current word func get_code_completion_prev_symbol(text:CodeEdit) -> String: @@ -98,8 +106,8 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG # word in option ## Note on VALUE key - # The value key is used to store a potential closing letter for the completion. - # The completion will check if the letter is already present and add it otherwise. + # The value key is used to store a potential closing string for the completion. + # The completion will check if the string is already present and add it otherwise. # Shortcode event suggestions if mode == Modes.FULL_HIGHLIGHTING and syntax_highlighter.line_is_shortcode_event(text.get_caret_line()): @@ -134,7 +142,7 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG text.add_code_completion_option(CodeEdit.KIND_MEMBER, param, param+'="' , shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3), text.get_theme_icon("MemberProperty", "EditorIcons")) # suggest values - elif symbol == '=' or symbol == '"' or get_code_completion_prev_symbol(text) == '"': + elif symbol == '=' or symbol == '"': var current_parameter_gex := completion_shortcode_param_getter_regex.search(line) if !current_parameter_gex: text.update_code_completion_options(false) @@ -148,7 +156,7 @@ func request_code_completion(force:bool, text:CodeEdit, mode:=Modes.FULL_HIGHLIG if typeof(shortcode_events[code].get_shortcode_parameters()[current_parameter].default) == TYPE_BOOL: suggest_bool(text, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3)) elif len(word) > 0: - text.add_code_completion_option(CodeEdit.KIND_MEMBER, word, word, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3), text.get_theme_icon("GuiScrollArrowRight", "EditorIcons"), '" ') + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, word, word, shortcode_events[code].event_color.lerp(syntax_highlighter.normal_color, 0.3), text.get_theme_icon("GuiScrollArrowRight", "EditorIcons"), '" ') text.update_code_completion_options(true) return @@ -218,16 +226,16 @@ func suggest_variables(text:CodeEdit): # Helper that adds true and false as options func suggest_bool(text:CodeEdit, color:Color): - text.add_code_completion_option(CodeEdit.KIND_MEMBER, 'true', 'true', color, text.get_theme_icon("GuiChecked", "EditorIcons"), '" ') - text.add_code_completion_option(CodeEdit.KIND_MEMBER, 'false', 'false', color, text.get_theme_icon("GuiUnchecked", "EditorIcons"), '" ') + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, 'true', 'true', color, text.get_theme_icon("GuiChecked", "EditorIcons"), '" ') + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, 'false', 'false', color, text.get_theme_icon("GuiUnchecked", "EditorIcons"), '" ') func suggest_custom_suggestions(suggestions:Dictionary, text:CodeEdit, color:Color) -> void: for key in suggestions.keys(): if suggestions[key].has('text_alt'): - text.add_code_completion_option(CodeEdit.KIND_MEMBER, key, suggestions[key].text_alt[0], color, suggestions[key].get('icon', null), '" ') + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, key, suggestions[key].text_alt[0], color, suggestions[key].get('icon', null), '" ') else: - text.add_code_completion_option(CodeEdit.KIND_MEMBER, key, str(suggestions[key].value), color, suggestions[key].get('icon', null), '" ') + text.add_code_completion_option(CodeEdit.KIND_VARIABLE, key, str(suggestions[key].value), color, suggestions[key].get('icon', null), '" ') # Filters the list of all possible options, depending on what was typed @@ -242,6 +250,10 @@ func filter_code_completion_candidates(candidates:Array, text:CodeEdit) -> Array elif candidate.kind == text.KIND_MEMBER: if current_word.is_empty() or current_word.to_lower() in candidate.insert_text.to_lower(): valid_candidates.append(candidate) + elif candidate.kind == text.KIND_VARIABLE: + var current_param_value := get_code_completion_parameter_value(text) + if current_param_value.is_empty() or current_param_value.to_lower() in candidate.insert_text.to_lower(): + valid_candidates.append(candidate) elif candidate.kind == text.KIND_CONSTANT: if current_word.is_empty() or candidate.insert_text.begins_with(current_word): valid_candidates.append(candidate) @@ -255,17 +267,23 @@ func filter_code_completion_candidates(candidates:Array, text:CodeEdit) -> Array # Inserts the selected item func confirm_code_completion(replace:bool, text:CodeEdit) -> void: # Note: I decided to ALWAYS use replace mode, as dialogic is supposed to be beginner friendly - var word := get_code_completion_word(text) + var code_completion := text.get_code_completion_option(text.get_code_completion_selected_index()) + + var word := get_code_completion_word(text) + if code_completion.kind == CodeEdit.KIND_VARIABLE: + word = get_code_completion_parameter_value(text) + text.remove_text(text.get_caret_line(), text.get_caret_column()-len(word), text.get_caret_line(), text.get_caret_column()) text.set_caret_column(text.get_caret_column()-len(word)) - text.insert_text_at_caret(code_completion.insert_text)# + text.insert_text_at_caret(code_completion.insert_text) + if code_completion.has('default_value') and typeof(code_completion['default_value']) == TYPE_STRING: - var next_letter := text.get_line(text.get_caret_line()).substr(text.get_caret_column(), 1) - if next_letter != code_completion['default_value']: - text.insert_text_at_caret(code_completion['default_value']) - else: + var next_letter := text.get_line(text.get_caret_line()).substr(text.get_caret_column(), len(code_completion['default_value'])) + if next_letter == code_completion['default_value'] or next_letter[0] == code_completion['default_value'][0]: text.set_caret_column(text.get_caret_column()+1) + else: + text.insert_text_at_caret(code_completion['default_value']) #endregion diff --git a/addons/dialogic/Modules/Background/event_background.gd b/addons/dialogic/Modules/Background/event_background.gd index 28fe72c4e..ca1a3a56b 100644 --- a/addons/dialogic/Modules/Background/event_background.gd +++ b/addons/dialogic/Modules/Background/event_background.gd @@ -147,7 +147,7 @@ func build_event_editor() -> void: func get_transition_suggestions(_filter:String="") -> Dictionary: - var transitions := DialogicResourceUtil.list_special_resources_of_type("BackgroundTransition") + var transitions := DialogicResourceUtil.list_special_resources("BackgroundTransition") var suggestions := {} for i in transitions: suggestions[DialogicUtil.pretty_name(i)] = {'value': DialogicUtil.pretty_name(i), 'editor_icon': ["PopupMenu", "EditorIcons"]} diff --git a/addons/dialogic/Modules/Background/index.gd b/addons/dialogic/Modules/Background/index.gd index e25806421..d40f03020 100644 --- a/addons/dialogic/Modules/Background/index.gd +++ b/addons/dialogic/Modules/Background/index.gd @@ -9,5 +9,5 @@ func _get_subsystems() -> Array: return [{'name':'Backgrounds', 'script':this_folder.path_join('subsystem_backgrounds.gd')}] -func _get_special_resources() -> Array[Dictionary]: - return list_special_resources("Transitions/Defaults", "BackgroundTransition", ".gd") +func _get_special_resources() -> Dictionary: + return {&"BackgroundTransition":list_special_resources("Transitions/Defaults", ".gd")} diff --git a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd index 5312334e9..9a07bee56 100644 --- a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd +++ b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd @@ -99,7 +99,7 @@ func update_background(scene := "", argument := "", fade_time := 0.0, transition else: new_viewport = null - var trans_script: Script = load(DialogicResourceUtil.guess_special_resource("BackgroundTransition", transition_path, default_transition)) + var trans_script: Script = load(DialogicResourceUtil.guess_special_resource("BackgroundTransition", transition_path, {"path":default_transition}).path) var trans_node := Node.new() trans_node.set_script(trans_script) trans_node = (trans_node as DialogicBackgroundTransition) diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd b/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd index f0c8b6849..a2469778e 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/bounce.gd @@ -9,3 +9,9 @@ func animate() -> void: tween.tween_property(node, 'position:y', orig_pos.y, time*0.6).set_trans(Tween.TRANS_BOUNCE) tween.parallel().tween_property(node, 'scale:y', orig_scale.y, time*0.6).set_trans(Tween.TRANS_BOUNCE) tween.finished.connect(emit_signal.bind('finished_once')) + + +func _get_named_variations() -> Dictionary: + return { + "bounce": {"type": AnimationType.ACTION}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd index 0f487bf33..d5484d901 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/bounce_in_out.gd @@ -30,3 +30,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "bounce in": {"reversed": false, "type": AnimationType.IN}, + "bounce out": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd index 92c80137f..719ca1b85 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_down_in_out.gd @@ -36,3 +36,9 @@ func animate() -> void: await tween.finished finished_once.emit() + +func _get_named_variations() -> Dictionary: + return { + "fade in down": {"reversed": false, "type": AnimationType.IN}, + "fade out up": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd index 006526d6a..e432ecd43 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_in_out.gd @@ -24,3 +24,11 @@ func animate() -> void: await tween.finished finished_once.emit() + +func _get_named_variations() -> Dictionary: + return { + "fade in": {"reversed": false, "type": AnimationType.IN}, + "fade out": {"reversed": true, "type": AnimationType.OUT}, + "fade cross": {"type": AnimationType.CROSSFADE}, + } + diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd index 6f23292a3..269c91971 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/fade_up_in_out.gd @@ -34,4 +34,11 @@ func animate() -> void: tween.tween_property(node, modulation_alpha, end_modulation, time) await tween.finished - finished_once.emit() \ No newline at end of file + finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "fade in up": {"reversed": false, "type": AnimationType.IN}, + "fade out down": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd b/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd index e3a982dce..36e8eab83 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/heartbeat.gd @@ -5,3 +5,9 @@ func animate() -> void: tween.tween_property(node, 'scale', Vector2(1,1)*1.2, time*0.5).set_trans(Tween.TRANS_ELASTIC).set_ease(Tween.EASE_OUT) tween.tween_property(node, 'scale', Vector2(1,1), time*0.5).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT) tween.finished.connect(emit_signal.bind('finished_once')) + + +func _get_named_variations() -> Dictionary: + return { + "heartbeat": {"type": AnimationType.ACTION}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd index b6ec6e482..3044c69fd 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/instant_in_out.gd @@ -3,3 +3,10 @@ extends DialogicAnimation func animate() -> void: await node.get_tree().process_frame finished.emit() + + +func _get_named_variations() -> Dictionary: + return { + "instant in": {"reversed": false, "type": AnimationType.IN}, + "instant out": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd index 9648809e0..de445fc95 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/shake_x.gd @@ -13,3 +13,8 @@ func animate() -> void: tween.tween_method(bound_multitween, Vector2(), Vector2(-1,0)*strength, time*0.1) tween.tween_method(bound_multitween, Vector2(), Vector2(1, 0)*strength, time*0.2) tween.finished.connect(emit_signal.bind('finished_once')) + +func _get_named_variations() -> Dictionary: + return { + "shake x": {"type": AnimationType.ACTION}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd b/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd index 0107ed8a2..2b6ee2043 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/shake_y.gd @@ -15,3 +15,8 @@ func animate() -> void: tween.tween_property(node, 'position:y', orig_pos.y, time*0.2) tween.finished.connect(emit_signal.bind('finished_once')) + +func _get_named_variations() -> Dictionary: + return { + "shake y": {"type": AnimationType.ACTION}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd index d76746f83..281846e99 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_down_in_out.gd @@ -17,3 +17,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "slide in down": {"reversed": false, "type": AnimationType.IN}, + "slide out up": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd index 766707209..b26768888 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_left_in_out.gd @@ -17,3 +17,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "slide in left": {"reversed": false, "type": AnimationType.IN}, + "slide out right": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd index 3568a2069..828fecbad 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_right_in_out.gd @@ -18,3 +18,10 @@ func animate() -> void: tween.tween_property(node, 'position:x', end_position_x, time) tween.finished.connect(emit_signal.bind('finished_once')) + + +func _get_named_variations() -> Dictionary: + return { + "slide in right": {"reversed": false, "type": AnimationType.IN}, + "slide out left": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd index d0928b01e..c1fe73eaf 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/slide_up_in.gd @@ -16,3 +16,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "slide in up": {"reversed": false, "type": AnimationType.IN}, + "slide out down": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd b/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd index bc38560f6..93ce8ca65 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/tada.gd @@ -17,3 +17,8 @@ func animate() -> void: tween.parallel().tween_property(node, 'rotation', 0.0, time*0.3) tween.finished.connect(emit_signal.bind('finished_once')) + +func _get_named_variations() -> Dictionary: + return { + "tada": {"type": AnimationType.ACTION}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd index 95dd52f2e..2595c2887 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_center_in_out.gd @@ -27,3 +27,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "zoom center in": {"reversed": false, "type": AnimationType.IN}, + "zoom center out": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd index 5d7a9507f..21cc3382d 100644 --- a/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd +++ b/addons/dialogic/Modules/Character/DefaultAnimations/zoom_in_out.gd @@ -26,3 +26,10 @@ func animate() -> void: await tween.finished finished_once.emit() + + +func _get_named_variations() -> Dictionary: + return { + "zoom in": {"reversed": false, "type": AnimationType.IN}, + "zoom out": {"reversed": true, "type": AnimationType.OUT}, + } diff --git a/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd b/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd new file mode 100644 index 000000000..66908e330 --- /dev/null +++ b/addons/dialogic/Modules/Character/DialogicPortraitAnimationsUtil.gd @@ -0,0 +1,47 @@ +@tool +class_name DialogicPortraitAnimationUtil + +enum AnimationType {ALL=-1, IN=1, OUT=2, ACTION=3, CROSSFADE=4} + + +static func guess_animation(string:String, type := AnimationType.ALL) -> String: + var default := {} + var filter := {} + var ignores := [] + match type: + AnimationType.ALL: + pass + AnimationType.IN: + filter = {"type":AnimationType.IN} + ignores = ["in"] + AnimationType.OUT: + filter = {"type":AnimationType.OUT} + ignores = ["out"] + AnimationType.ACTION: + filter = {"type":AnimationType.ACTION} + AnimationType.CROSSFADE: + filter = {"type":AnimationType.CROSSFADE} + ignores = ["cross"] + return DialogicResourceUtil.guess_special_resource(&"PortraitAnimation", string, default, filter, ignores).get("path", "") + + +static func get_portrait_animations_filtered(type := AnimationType.ALL) -> Dictionary: + var filter := {"type":type} + if type == AnimationType.ALL: + filter["type"] = [AnimationType.IN, AnimationType.OUT, AnimationType.ACTION] + return DialogicResourceUtil.list_special_resources("PortraitAnimation", filter) + + +static func get_suggestions(_search_text := "", current_value:= "", empty_text := "Default", action := AnimationType.ALL) -> Dictionary: + var suggestions := {} + + if empty_text and current_value: + suggestions[empty_text] = {'value':"", 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} + + for anim_name in get_portrait_animations_filtered(action): + suggestions[DialogicUtil.pretty_name(anim_name)] = { + 'value' : DialogicUtil.pretty_name(anim_name), + 'editor_icon' : ["Animation", "EditorIcons"] + } + + return suggestions diff --git a/addons/dialogic/Modules/Character/class_dialogic_animation.gd b/addons/dialogic/Modules/Character/class_dialogic_animation.gd index 713ba43bf..7b9c11d6e 100644 --- a/addons/dialogic/Modules/Character/class_dialogic_animation.gd +++ b/addons/dialogic/Modules/Character/class_dialogic_animation.gd @@ -3,6 +3,8 @@ extends Node ## Class that can be used to animate portraits. Can be extended to create animations. +enum AnimationType {IN=1, OUT=2, ACTION=3, CROSSFADE=4} + signal finished_once signal finished @@ -58,6 +60,10 @@ func resume() -> void: node.process_mode = Node.PROCESS_MODE_INHERIT +func _get_named_variations() -> Dictionary: + return {} + + ## If the animation wants to change the modulation, this method ## will return the property to change. ## diff --git a/addons/dialogic/Modules/Character/event_character.gd b/addons/dialogic/Modules/Character/event_character.gd index 68af5731d..92a6e7015 100644 --- a/addons/dialogic/Modules/Character/event_character.gd +++ b/addons/dialogic/Modules/Character/event_character.gd @@ -450,13 +450,19 @@ func get_position_suggestions(search_text:String='') -> Dictionary: func get_animation_suggestions(search_text:String='') -> Dictionary: - var empty_text := "Default" - if action == Actions.UPDATE: - empty_text = "None" - return DialogicUtil.get_portrait_animation_suggestions(search_text, empty_text, action+1) + var DPAU := DialogicPortraitAnimationUtil + match action: + Actions.JOIN: + return DPAU.get_suggestions(search_text, animation_name, "Default", DPAU.AnimationType.IN) + Actions.LEAVE: + return DPAU.get_suggestions(search_text, animation_name, "Default", DPAU.AnimationType.OUT) + Actions.UPDATE: + return DPAU.get_suggestions(search_text, animation_name, "None", DPAU.AnimationType.ACTION) + return {} + func get_fade_suggestions(search_text:String='') -> Dictionary: - return DialogicUtil.get_portrait_animation_suggestions(search_text, "Default", 1) + return DialogicPortraitAnimationUtil.get_suggestions(search_text, fade_animation, "Default", DialogicPortraitAnimationUtil.AnimationType.CROSSFADE) ####################### CODE COMPLETION ######################################## @@ -477,41 +483,49 @@ func _get_code_completion(CodeCompletionHelper:Node, TextNode:TextEdit, line:Str for position in get_position_suggestions(): TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, position, position+' ', TextNode.syntax_highlighter.normal_color) - if '[' in line_until_caret and (symbol == "[" or symbol == " "): - suggest_parameter("animation", line, TextNode) - - if "animation=" in line: - for param in ["length", "wait"]: - suggest_parameter(param, line, TextNode) - if line.begins_with('update'): - suggest_parameter("repeat", line, TextNode) - if line.begins_with("update"): - for param in ["time", "trans", "ease"]: - suggest_parameter(param, line, TextNode) - if not line.begins_with('leave'): - for param in ["mirrored", "z_index", "extra_data"]: - suggest_parameter(param, line, TextNode) - - if line_until_caret.ends_with('animation="'): - var animations := [] - - if line.begins_with('join'): - animations = DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.IN) - - if line.begins_with('update'): - animations = DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.ACTION) - - if line.begins_with('leave'): - animations = DialogicUtil.get_portrait_animation_scripts(DialogicUtil.AnimationType.OUT) - - for script: String in animations: - TextNode.add_code_completion_option(CodeEdit.KIND_MEMBER, DialogicUtil.pretty_name(script), DialogicUtil.pretty_name(script)+'" ', TextNode.syntax_highlighter.normal_color) - elif line_until_caret.ends_with('wait="') or line_until_caret.ends_with('mirrored="'): - CodeCompletionHelper.suggest_bool(TextNode, TextNode.syntax_highlighter.normal_color) - elif line_until_caret.ends_with('trans="'): - CodeCompletionHelper.suggest_custom_suggestions(list_to_suggestions(trans_options), TextNode, TextNode.syntax_highlighter.normal_color) - elif line_until_caret.ends_with('ease="'): - CodeCompletionHelper.suggest_custom_suggestions(list_to_suggestions(ease_options), TextNode, TextNode.syntax_highlighter.normal_color) + # Shortcode Part + if '[' in line_until_caret: + # Suggest Parameters + if symbol == '[' or symbol == ' ' and line_until_caret.count('"')%2 == 0:# and (symbol == "[" or (symbol == " " and line_until_caret.rfind('="') < line_until_caret.rfind('"')-1)): + suggest_parameter("animation", line, TextNode) + + if "animation=" in line: + for param in ["length", "wait"]: + suggest_parameter(param, line, TextNode) + if line.begins_with('update'): + suggest_parameter("repeat", line, TextNode) + if line.begins_with("update"): + for param in ["time", "trans", "ease"]: + suggest_parameter(param, line, TextNode) + if not line.begins_with('leave'): + for param in ["mirrored", "z_index", "extra_data"]: + suggest_parameter(param, line, TextNode) + + # Suggest Values + else: + var current_param: RegExMatch = CodeCompletionHelper.completion_shortcode_param_getter_regex.search(line) + if not current_param: + return + + match current_param.get_string("param"): + "animation": + var animations := {} + if line.begins_with('join'): + animations = DialogicPortraitAnimationUtil.get_portrait_animations_filtered(DialogicPortraitAnimationUtil.AnimationType.IN) + elif line.begins_with('update'): + animations = DialogicPortraitAnimationUtil.get_portrait_animations_filtered(DialogicPortraitAnimationUtil.AnimationType.ACTION) + elif line.begins_with('leave'): + animations = DialogicPortraitAnimationUtil.get_portrait_animations_filtered(DialogicPortraitAnimationUtil.AnimationType.OUT) + + for script: String in animations: + TextNode.add_code_completion_option(CodeEdit.KIND_VARIABLE, DialogicUtil.pretty_name(script), DialogicUtil.pretty_name(script), TextNode.syntax_highlighter.normal_color, null, '" ') + + "wait", "mirrored": + CodeCompletionHelper.suggest_bool(TextNode, TextNode.syntax_highlighter.normal_color) + "trans": + CodeCompletionHelper.suggest_custom_suggestions(list_to_suggestions(trans_options), TextNode, TextNode.syntax_highlighter.normal_color) + "ease": + CodeCompletionHelper.suggest_custom_suggestions(list_to_suggestions(ease_options), TextNode, TextNode.syntax_highlighter.normal_color) func suggest_parameter(parameter:String, line:String, TextNode:TextEdit) -> void: diff --git a/addons/dialogic/Modules/Character/index.gd b/addons/dialogic/Modules/Character/index.gd index ff4bd3a01..8705e3b86 100644 --- a/addons/dialogic/Modules/Character/index.gd +++ b/addons/dialogic/Modules/Character/index.gd @@ -16,5 +16,5 @@ func _get_text_effects() -> Array[Dictionary]: return [{'command':'portrait', 'subsystem':'Portraits', 'method':'text_effect_portrait', 'arg':true}] -func _get_special_resources() -> Array[Dictionary]: - return list_special_resources('DefaultAnimations', &'PortraitAnimation') +func _get_special_resources() -> Dictionary: + return {&'PortraitAnimation': list_animations("DefaultAnimations")} diff --git a/addons/dialogic/Modules/Character/settings_portraits.gd b/addons/dialogic/Modules/Character/settings_portraits.gd index 2e4b206bc..097cdf10e 100644 --- a/addons/dialogic/Modules/Character/settings_portraits.gd +++ b/addons/dialogic/Modules/Character/settings_portraits.gd @@ -87,23 +87,15 @@ func save_setting(value:Variant, settings_key:String) -> void: func get_join_animation_suggestions(search_text:String) -> Dictionary: - var suggestions := {} - for anim in list_animations(): - if '_in' in anim.get_file(): - suggestions[DialogicUtil.pretty_name(anim)] = {'value':anim, 'icon':get_theme_icon('Animation', 'EditorIcons')} - return suggestions + return DialogicPortraitAnimationUtil.get_suggestions(search_text, %JoinDefault.current_value, "", DialogicPortraitAnimationUtil.AnimationType.IN) func get_leave_animation_suggestions(search_text:String) -> Dictionary: - var suggestions := {} - for anim in list_animations(): - if '_out' in anim.get_file(): - suggestions[DialogicUtil.pretty_name(anim)] = {'value':anim, 'icon':get_theme_icon('Animation', 'EditorIcons')} - return suggestions + return DialogicPortraitAnimationUtil.get_suggestions(search_text, %LeaveDefault.current_value, "", DialogicPortraitAnimationUtil.AnimationType.OUT) + + +func get_crossfade_animation_suggestions(search_text:String) -> Dictionary: + return DialogicPortraitAnimationUtil.get_suggestions(search_text, %CrossFadeDefault.current_value, "", DialogicPortraitAnimationUtil.AnimationType.CROSSFADE) -func list_animations() -> Array: - var list := DialogicUtil.listdir(get_script().resource_path.get_base_dir().path_join('DefaultAnimations'), true, false, true) - list.append_array(DialogicUtil.listdir(ProjectSettings.get_setting('dialogic/animations/custom_folder', 'res://addons/dialogic_additions/Animations'), true, false, true)) - return list diff --git a/addons/dialogic/Modules/Character/subsystem_containers.gd b/addons/dialogic/Modules/Character/subsystem_containers.gd index fb13ea1bb..a129d52ae 100644 --- a/addons/dialogic/Modules/Character/subsystem_containers.gd +++ b/addons/dialogic/Modules/Character/subsystem_containers.gd @@ -45,11 +45,11 @@ func add_container(position_id: String, position := "", size := "") -> DialogicN if example_position: var new_position := DialogicNode_PortraitContainer.new() example_position.get_parent().add_child(new_position) + new_position.name = "Portrait_"+position_id.validate_node_name() new_position.size = str_to_vector(size) copy_container_setup(example_position, new_position) new_position.container_ids = [position_id] new_position.position = str_to_vector(position)-new_position._get_origin_position() - new_position.name = "Portrait_"+position_id.validate_node_name() position_changed.emit({&'change':'added', &'container_node':new_position, &'position_id':position_id}) return new_position return null diff --git a/addons/dialogic/Modules/Character/subsystem_portraits.gd b/addons/dialogic/Modules/Character/subsystem_portraits.gd index 05034e565..b7377be89 100644 --- a/addons/dialogic/Modules/Character/subsystem_portraits.gd +++ b/addons/dialogic/Modules/Character/subsystem_portraits.gd @@ -254,6 +254,8 @@ func _animate_node(node: Node, animation_path: String, length: float, repeats := ## Moves the given portrait to the given container. func _move_character(character_node: Node2D, transform:="", time := 0.0, easing:= Tween.EASE_IN_OUT, trans:= Tween.TRANS_SINE) -> void: var tween := character_node.create_tween().set_ease(easing).set_trans(trans).set_parallel() + if time == 0: + tween = null var container: DialogicNode_PortraitContainer = character_node.get_parent() dialogic.PortraitContainers.move_container(container, transform, tween, time) @@ -395,7 +397,7 @@ func join_character(character:DialogicCharacter, portrait:String, position_id:S animation_length = _get_join_default_length() animation_wait = ProjectSettings.get_setting('dialogic/animations/join_default_wait', true) - animation_name = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_name, "") + animation_name = DialogicPortraitAnimationUtil.guess_animation(animation_name, DialogicPortraitAnimationUtil.AnimationType.IN) if animation_name and animation_length > 0: var anim: DialogicAnimation = _animate_node(character_node, animation_name, animation_length) @@ -450,7 +452,7 @@ func change_character_portrait(character: DialogicCharacter, portrait: String, f fade_animation = ProjectSettings.get_setting('dialogic/animations/cross_fade_default', "Fade In Out") fade_length = ProjectSettings.get_setting('dialogic/animations/cross_fade_default_length', 0.5) - fade_animation = DialogicResourceUtil.guess_special_resource("PortraitAnimation", fade_animation, fade_animation) + 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) dialogic.current_state_info.portraits[character.resource_path].portrait = info.portrait @@ -493,10 +495,9 @@ func animate_character(character: DialogicCharacter, animation_path: String, len if not is_character_joined(character): return null - animation_path = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_path, "") + animation_path = DialogicPortraitAnimationUtil.guess_animation(animation_path) var character_node: Node = dialogic.current_state_info.portraits[character.resource_path].node - #var portrait_node: Node = character_node.get_child(-1) return _animate_node(character_node, animation_path, length, repeats, is_reversed) @@ -524,7 +525,7 @@ func leave_character(character: DialogicCharacter, animation_name:= "", animatio animation_length = _get_leave_default_length() animation_wait = ProjectSettings.get_setting('dialogic/animations/leave_default_wait', true) - animation_name = DialogicResourceUtil.guess_special_resource("PortraitAnimation", animation_name, "") + animation_name = DialogicPortraitAnimationUtil.guess_animation(animation_name, DialogicPortraitAnimationUtil.AnimationType.OUT) if not animation_name.is_empty(): var character_node := get_character_node(character) @@ -564,6 +565,7 @@ func remove_character(character: DialogicCharacter) -> void: if is_instance_valid(character_node) and character_node is Node: var container := character_node.get_parent() + container.get_parent().remove_child(container) container.queue_free() character_node.queue_free() character_left.emit({'character': character}) @@ -610,12 +612,6 @@ func get_character_info(character:DialogicCharacter) -> Dictionary: #endregion -#region Positions -#################################################################################################### - -#endregion - - #region SPEAKER PORTRAIT CONTAINERS #################################################################################################### @@ -626,7 +622,7 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: for character_node: Node in container.get_children(): if not character_node.get_meta('character') == speaker: var leave_animation: String = ProjectSettings.get_setting('dialogic/animations/leave_default', "Fade Up Out") - leave_animation = DialogicResourceUtil.guess_special_resource("PortraitAnimation", leave_animation, "") + leave_animation = DialogicPortraitAnimationUtil.guess_animation(leave_animation, DialogicPortraitAnimationUtil.AnimationType.OUT) var leave_animation_length := _get_leave_default_length() if leave_animation and leave_animation_length: @@ -652,7 +648,7 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: var fade_animation: String = ProjectSettings.get_setting('dialogic/animations/cross_fade_default', "Fade In Out") var fade_length: float = ProjectSettings.get_setting('dialogic/animations/cross_fade_default_length', 0.5) - fade_animation = DialogicResourceUtil.guess_special_resource("PortraitAnimation", fade_animation, fade_animation) + fade_animation = DialogicPortraitAnimationUtil.guess_animation(fade_animation, DialogicPortraitAnimationUtil.AnimationType.CROSSFADE) if container.portrait_prefix+portrait in speaker.portraits: portrait = container.portrait_prefix+portrait @@ -665,7 +661,7 @@ func change_speaker(speaker: DialogicCharacter = null, portrait := "") -> void: if just_joined: var join_animation: String = ProjectSettings.get_setting('dialogic/animations/join_default', "Fade Up In") - join_animation = DialogicResourceUtil.guess_special_resource("PortraitAnimation", join_animation, "") + join_animation = DialogicPortraitAnimationUtil.guess_animation(join_animation, DialogicPortraitAnimationUtil.AnimationType.IN) var join_animation_length := _get_join_default_length() if join_animation and join_animation_length: diff --git a/addons/dialogic/Modules/Clear/event_clear.gd b/addons/dialogic/Modules/Clear/event_clear.gd index c675cda3a..f7ea8302d 100644 --- a/addons/dialogic/Modules/Clear/event_clear.gd +++ b/addons/dialogic/Modules/Clear/event_clear.gd @@ -34,7 +34,7 @@ func _execute() -> void: if clear_portraits and dialogic.has_subsystem('Portraits') and len(dialogic.Portraits.get_joined_characters()) != 0: if final_time == 0: - dialogic.Portraits.leave_all_characters(DialogicResourceUtil.guess_special_resource("PortraitAnimation", 'Instant In Or Out'), final_time, step_by_step) + dialogic.Portraits.leave_all_characters(DialogicResourceUtil.guess_special_resource("PortraitAnimation", 'Instant In Or Out').path, final_time, step_by_step) else: dialogic.Portraits.leave_all_characters("", final_time, step_by_step) if step_by_step: await dialogic.get_tree().create_timer(final_time).timeout