From 879e66f01464c096947d1da7744ed3bda1160677 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:05:55 +0100 Subject: [PATCH 01/17] Add `Tween` Event. --- addons/dialogic/Modules/Tween/event_tween.gd | 632 +++++++++++++++++++ addons/dialogic/Modules/Tween/index.gd | 6 + 2 files changed, 638 insertions(+) create mode 100644 addons/dialogic/Modules/Tween/event_tween.gd create mode 100644 addons/dialogic/Modules/Tween/index.gd diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd new file mode 100644 index 000000000..2c4c682fc --- /dev/null +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -0,0 +1,632 @@ +@tool +extends DialogicEvent +class_name DialogicTweenEvent + +enum TweenTarget { + PORTRAIT, + BACKGROUND, +} + +const TIME_DEFAULT := 0.0 +const IS_RELATIVE_DEFAULT := false +const AWAIT_DEFAULT := false +const PARALLEL_DEFAULT := false +const EASE_DEFAULT := Tween.EASE_IN +const TRANSITION_DEFAULT := Tween.TRANS_LINEAR + + +var _property := "" : + set(value): + + if value.contains(":"): + var split_property := value.split(":") + _property = split_property[0] + _sub_property = split_property[1] + else: + _property = value + _sub_property = "" + + var variable_value: Variant = ColorRect.new().get(_property) + var variant_type: Variant.Type = typeof(variable_value) as Variant.Type + + var new_value_type := variant_to_value_type(variant_type) + _value_type = new_value_type + +var _sub_property := "" +var _target := TweenTarget.BACKGROUND +var _time: float = TIME_DEFAULT +var _is_relative: bool = IS_RELATIVE_DEFAULT +var _await: bool = AWAIT_DEFAULT +var _parallel := PARALLEL_DEFAULT +var _ease := EASE_DEFAULT +var _transition := TRANSITION_DEFAULT +var _value_type: ValueType = ValueType.NUMBER +var _value: Variant = null : + set(value): + _value = value + print(value) + +func _execute() -> void: + var target_node: Node = null + + match _target: + TweenTarget.PORTRAIT: + target_node = null + + TweenTarget.BACKGROUND: + target_node = dialogic.Backgrounds.get_current_background_node() + + var tween := dialogic.create_tween() + tween.set_ease(_ease) + tween.set_trans(_transition) + + if _parallel: + tween.set_parallel(true) + + var full_property_path := _property + + if not _sub_property.is_empty(): + full_property_path += ":" + _sub_property + + + var tweener := tween.tween_property(target_node, full_property_path, _value, _time) + + if _is_relative: + tweener.as_relative() + + if _await: + await tweener.finished + + finish() + + +#region INITIALIZE +################################################################################ +# Set fixed settings of this event +func _init() -> void: + event_name = "Tween" + set_default_color("Color2") + event_category = "Visuals" + event_sorting_index = 3 + + + +#endregion + +#region SAVING/LOADING +################################################################################ + +func to_text() -> String: + var result_string := "[tween " + + match _target: + TweenTarget.PORTRAIT: result_string += "portrait " + TweenTarget.BACKGROUND: result_string += "background " + + + if not _property.is_empty(): + result_string += " property=\"" + _property + + if not _sub_property.is_empty(): + result_string += ":" + _sub_property + + result_string += "\"" + + if not _value == null: + result_string += " value=\"" + str(_value) + "\"" + + + if not _time == TIME_DEFAULT: + result_string += " time=\"" + str(_time) + "\"" + + if not _is_relative == IS_RELATIVE_DEFAULT: + result_string += " is_relative=\"" + str(_is_relative) + "\"" + + if not _await == AWAIT_DEFAULT: + result_string += " await=\"" + str(_await) + "\"" + + if not _ease == EASE_DEFAULT: + result_string += " ease=\"" + _tween_ease_to_text(_ease) + "\"" + + if not _transition == TRANSITION_DEFAULT: + result_string += " transition=\"" + _transition_to_text(_transition) + "\"" + + + + return result_string + "]" + + +func _transition_to_text(transition_kind: int) -> String: + match transition_kind: + Tween.TRANS_LINEAR: + return "Linear" + + Tween.TRANS_SINE: + return "Sine" + + Tween.TRANS_QUINT: + return "Quint" + + Tween.TRANS_QUART: + return "Quart" + + Tween.TRANS_QUAD: + return "Quad" + + Tween.TRANS_EXPO: + return "Expo" + + Tween.TRANS_ELASTIC: + return "Elastic" + + Tween.TRANS_CUBIC: + return "Cubic" + + Tween.TRANS_CIRC: + return "Circ" + + Tween.TRANS_BOUNCE: + return "Bounce" + + Tween.TRANS_BACK: + return "Back" + + Tween.TRANS_SPRING: + return "Spring" + + return "Linear" + + +func _text_to_transition(transition_text: String) -> int: + var transition_lowercase := transition_text.to_lower().trim_prefix("trans").strip_edges() + + match transition_lowercase: + "linear": + return Tween.TRANS_LINEAR + + "sine": + return Tween.TRANS_SINE + + "quint": + return Tween.TRANS_QUINT + + "quart": + return Tween.TRANS_QUART + + "quad": + return Tween.TRANS_QUAD + + "expo": + return Tween.TRANS_EXPO + + "elastic": + return Tween.TRANS_ELASTIC + + "cubic": + return Tween.TRANS_CUBIC + + "circ": + return Tween.TRANS_CIRC + + "bounce": + return Tween.TRANS_BOUNCE + + "back": + return Tween.TRANS_BACK + + "spring": + return Tween.TRANS_SPRING + + return Tween.TRANS_LINEAR + + +## The [param ease_kind] is an integer representing the ease approach +## the [class Tween] will use. +func _tween_ease_to_text(ease_kind: int) -> String: + match ease_kind: + Tween.EASE_IN: + return "Ease In" + + Tween.EASE_OUT: + return "Ease Out" + + Tween.EASE_IN_OUT: + return "Ease In Out" + + Tween.EASE_OUT_IN: + return "Ease Out In" + + return "Ease In" + + +func _text_to_tween_ease(ease_text: String) -> int: + var ease_lowercase := ease_text.to_lower() + + match ease_lowercase: + "ease in": + return Tween.EASE_IN + + "ease out": + return Tween.EASE_OUT + + "ease in out": + return Tween.EASE_IN_OUT + + "ease out in": + return Tween.EASE_OUT_IN + + return Tween.EASE_IN + + +func from_text(string: String) -> void: + var regex_str := r'(\w+)\s*=\s*"([^"]*)"|(\w+)' + var regex := RegEx.new() + regex.compile(regex_str) + + for regex_match in regex.search_all(string): + + var key := regex_match.get_string(1) + + if key.is_empty(): + key = regex_match.get_string(0) + + var value := regex_match.get_string(2) + + match key: + "portrait": + _target = TweenTarget.PORTRAIT + + "background": + _target = TweenTarget.BACKGROUND + + "property": + _property = value + + "time": + _time = float(value) + + "is_relative": + _is_relative = true + + "await": + _await = true + + "value": + _value = string_to_value_type(value) + + "ease": + _ease = _text_to_tween_ease(value) as Tween.EaseType + + "transition": + _transition = _text_to_transition(value) as Tween.TransitionType + + + +func string_to_value_type(value: String) -> Variant: + if value.is_valid_int(): + return value.to_int() + + if value.is_valid_float(): + return value.to_float() + + if value.begins_with("("): + var values := value.replace("(", "").replace(")", "").split(",") + var x_value := values[0].strip_edges().to_float() + var y_value := values[1].strip_edges().to_float() + return Vector2(x_value, y_value) + + return null + + + +func get_shortcode() -> String: + return "tween" + + +func get_shortcode_parameters() -> Dictionary: + return { + #param_name : property_info + "property" : {"property": "_property", "default": _property}, + "value" : {"property": "_value", "default": _value}, + "target" : {"property": "_target", "default": _target}, + "time" : {"property": "_time", "default": _time}, + "is_relative" : {"property": "_is_relative", "default": _is_relative}, + "await" : {"property": "_await", "default": _await}, + "sub_property" : {"property": "_sub_property", "default": _sub_property}, + "ease" : {"property": "_ease", "default": _ease}, + } + + +# You can alternatively overwrite these 3 functions: to_text(), from_text(), is_valid_event() +#endregion + + +func get_all_properties(search_string: String) -> Dictionary: + const VALID_TYPE := [TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I] + const IGNORE_WORDS := ["process_"] + + var color_rect := ColorRect.new() + var suggestions := {} + var fallback_icon := ["Variant", "EditorIcons"] + + for property_info: Dictionary in color_rect.get_property_list(): + var property_name: String = property_info.get("name") + + if not search_string.is_empty() and not property_name.contains(search_string): + continue + + var ignore_property: bool = false + for ignore_term: String in IGNORE_WORDS: + + if property_name.begins_with(ignore_term): + ignore_property = true + break + + if ignore_property: + continue + + var property_type: Variant.Type = property_info.get("type") + + if not VALID_TYPE.has(property_type): + continue + + var icon: Variant = fallback_icon + + match property_type: + Variant.Type.TYPE_INT: + icon = ["Number", "EditorIcons"] + Variant.Type.TYPE_FLOAT: + icon = ["Float", "EditorIcons"] + Variant.Type.TYPE_STRING: + icon = ["String", "EditorIcons"] + _: + icon = ["Variant", "EditorIcons"] + + + suggestions[property_name] = { + "label": "[b]"+ property_name + "[/b]", + "value": property_name, + "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") + } + + + return suggestions + + +#region EDITOR REPRESENTATION +################################################################################ + +func build_event_editor() -> void: + #var background_node := DialogicUtil.autoload().get_tree().get_first_node_in_group("dialogic_background_holders").get_child(0) + + add_header_edit("_target", ValueType.FIXED_OPTIONS, { + "left_text": "Tween ", + "options": [ + { + "label": "Portrait", + "value": TweenTarget.PORTRAIT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Background", + "value": TweenTarget.BACKGROUND, + "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") + }, + ] + }) + + + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + {"placeholder" : "", + "mode" : 1, + "suggestions_func" : get_all_properties, + #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus" : false, + "left_text": " property " + }) + + + add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { + #"left_text": "Point:", + "autofocus" : false, + "placeholder" : "All", + "mode" : 1, + "options": [ + { + "label": "All", + "value": "", + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "x", + "value": "x", + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "y", + "value": "y", + "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") + }, + ] + }, + "_value_type == ValueType.VECTOR2" + ) + + + + #region VALUE FIELDS + add_header_edit("_value", ValueType.NUMBER, + { + "left_text": " to ", + "mode": 1, + }, + "not _property.is_empty() and _value_type == ValueType.NUMBER" + ) + + add_header_edit("_value", ValueType.VECTOR2, + { + "left_text": " to ", + "mode": 1, + }, + "not _property.is_empty() && _value_type == ValueType.VECTOR2 && _sub_property.is_empty()" + ) + + add_header_edit("_value", ValueType.NUMBER, + { + "left_text": " to ", + "mode": 1, + }, + "not _property.is_empty() && _value_type == ValueType.VECTOR2 && not _sub_property.is_empty()" + ) + #endregion + + + + add_header_edit("_time", ValueType.NUMBER, + { + "left_text":" over ", + "right_text": " seconds. ", + "only_positive": true, + } + ) + + + add_header_edit("_is_relative", ValueType.BOOL, + {"left_text":"Relative:"}, "_time > 0.0" + ) + + add_header_edit("_await", ValueType.BOOL, + {"left_text": "Await:"}, "_time > 0.0" + ) + + # Body Optioms + add_body_edit("_ease", ValueType.FIXED_OPTIONS, { + "left_text": "Ease:", + "autofocus" : false, + "mode" : 2, + "placeholder": "Ease In", + "options": [ + { + "label": "Ease In", + "value": Tween.EASE_IN, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out", + "value": Tween.EASE_OUT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease In Out", + "value": Tween.EASE_IN_OUT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out In", + "value": Tween.EASE_OUT_IN, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + }, + "_time > 0.0" + ) + + + add_body_edit("_transition", ValueType.FIXED_OPTIONS, { + "left_text": "Transition:", + "autofocus" : false, + "mode" : 1, + "placeholder": "Linear", + "options": [ + { + "label": "Linear", + "value": Tween.TRANS_LINEAR, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Sine", + "value": Tween.TRANS_SINE, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quint", + "value": Tween.TRANS_QUINT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quart", + "value": Tween.TRANS_QUART, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quad", + "value": Tween.TRANS_QUAD, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Expo", + "value": Tween.TRANS_EXPO, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Elastic", + "value": Tween.TRANS_ELASTIC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out In", + "value": Tween.TRANS_CUBIC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Circ", + "value": Tween.TRANS_CIRC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Bounce", + "value": Tween.TRANS_BOUNCE, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Back", + "value": Tween.TRANS_BACK, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Spring", + "value": Tween.TRANS_SPRING, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + }, + "_time > 0.0" + ) + +func variant_to_value_type(value: Variant.Type) -> ValueType: + match value: + Variant.Type.TYPE_STRING: + return ValueType.SINGLELINE_TEXT + + Variant.Type.TYPE_INT: + return ValueType.NUMBER + + Variant.Type.TYPE_FLOAT: + return ValueType.NUMBER + + Variant.Type.TYPE_VECTOR2: + return ValueType.VECTOR2 + + Variant.Type.TYPE_VECTOR2I: + return ValueType.VECTOR2 + + Variant.Type.TYPE_RECT2: + return ValueType.VECTOR2 + + Variant.Type.TYPE_RECT2I: + return ValueType.VECTOR2 + + _: + return ValueType.CUSTOM + +#endregion diff --git a/addons/dialogic/Modules/Tween/index.gd b/addons/dialogic/Modules/Tween/index.gd new file mode 100644 index 000000000..4ed2b8bb5 --- /dev/null +++ b/addons/dialogic/Modules/Tween/index.gd @@ -0,0 +1,6 @@ +@tool +extends DialogicIndexer + +func _get_events() -> Array: + return [this_folder.path_join('event_tween.gd')] + From 1a03996f6b6d5b06cf8fd1b54fab0d482ac18d37 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:06:36 +0100 Subject: [PATCH 02/17] Add method to get current background. --- .../Modules/Background/subsystem_backgrounds.gd | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd index 5312334e9..6b9fcac45 100644 --- a/addons/dialogic/Modules/Background/subsystem_backgrounds.gd +++ b/addons/dialogic/Modules/Background/subsystem_backgrounds.gd @@ -176,6 +176,22 @@ func add_background_node(scene:PackedScene, parent:DialogicNode_BackgroundHolder return v_con +## Returns the current background node. +func get_current_background_node() -> Node: + var background_holder: DialogicNode_BackgroundHolder = null + + if dialogic.has_subsystem("Styles"): + background_holder = dialogic.Styles.get_first_node_in_layout("dialogic_background_holders") + else: + background_holder = get_tree().get_first_node_in_group("dialogic_background_holders") + + var current_viewport: Node = background_holder.get_meta("current_viewport") + var current_background_node: Node = current_viewport.get_meta("node") + + return current_background_node + + + ## Whether a background is set. func has_background() -> bool: return !dialogic.current_state_info.get('background_scene', '').is_empty() or !dialogic.current_state_info.get('background_argument','').is_empty() From 5f9d387da49c4e72f9eca42b06b2a01861c57f4f Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:06:51 +0100 Subject: [PATCH 03/17] Add static typing. --- addons/dialogic/Resources/event.gd | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/addons/dialogic/Resources/event.gd b/addons/dialogic/Resources/event.gd index 02ed9f0ef..bf0e102f4 100644 --- a/addons/dialogic/Resources/event.gd +++ b/addons/dialogic/Resources/event.gd @@ -115,7 +115,7 @@ func _to_string() -> String: ################################################################################ ## Executes the event behaviour. In subclasses [_execute] (not this one) should be overriden! -func execute(_dialogic_game_handler) -> void: +func execute(_dialogic_game_handler: DialogicGameHandler) -> void: event_started.emit(self) dialogic = _dialogic_game_handler call_deferred("_execute") @@ -228,7 +228,7 @@ func _load_from_string(string:String) -> void: ## Assigns the custom defaults -func _load_custom_defaults(): +func _load_custom_defaults() -> void: for default_prop in DialogicUtil.get_custom_event_defaults(event_name): if default_prop in self: set(default_prop, DialogicUtil.get_custom_event_defaults(event_name)[default_prop]) @@ -263,24 +263,33 @@ func to_text() -> String: var result_string: String = "["+self.get_shortcode() var params: Dictionary = get_shortcode_parameters() var custom_defaults: Dictionary = DialogicUtil.get_custom_event_defaults(event_name) - for parameter in params.keys(): + + for parameter: String in params.keys(): + if (typeof(get(params[parameter].property)) != typeof(custom_defaults.get(params[parameter].property, params[parameter].default))) or \ (get(params[parameter].property) != custom_defaults.get(params[parameter].property, params[parameter].default)): + if typeof(get(params[parameter].property)) == TYPE_OBJECT: result_string += " "+parameter+'="'+str(get(params[parameter].property).resource_path)+'"' + elif typeof(get(params[parameter].property)) == TYPE_STRING: result_string += " "+parameter+'="'+get(params[parameter].property).replace('=', "\\=")+'"' # if this is an enum with values provided, try to use a text alternative elif typeof(get(params[parameter].property)) == TYPE_INT and params[parameter].has('suggestions'): + for option in params[parameter].suggestions.call().values(): + if option.value == get(params[parameter].property): + if option.has('text_alt'): result_string += " "+parameter+'="'+option.text_alt[0]+'"' else: result_string += " "+parameter+'="'+var_to_str(option.value).replace('=', "\\=")+'"' break + elif typeof(get(params[parameter].property)) == TYPE_DICTIONARY: result_string += " "+parameter+'="'+ JSON.stringify(get(params[parameter].property)).replace('=', "\\=")+'"' + else: result_string += " "+parameter+'="'+var_to_str(get(params[parameter].property)).replace('=', "\\=")+'"' result_string += "]" @@ -292,7 +301,8 @@ func to_text() -> String: func from_text(string:String) -> void: var data: Dictionary = parse_shortcode_parameters(string) var params: Dictionary = get_shortcode_parameters() - for parameter in params.keys(): + + for parameter: String in params.keys(): if not parameter in data: continue From 4f63721d337c45a789f0b9d29a071480e87f53a3 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:07:40 +0100 Subject: [PATCH 04/17] Add value setting and step support to Vector2 event fields. --- .../Editor/Events/Fields/field_vector2.gd | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd b/addons/dialogic/Editor/Events/Fields/field_vector2.gd index 040abf079..f15388bd0 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd @@ -2,11 +2,21 @@ extends DialogicVisualEditorFieldVector ## Event block field for a Vector2. +@export var step: float = 0.1 +@export var enforce_step: bool = true + var current_value := Vector2() +func _ready() -> void: + if enforce_step: + $X.step = step + $Y.step = step + + func _set_value(value: Variant) -> void: current_value = value + value_changed.emit(property_name, value) super(value) @@ -14,6 +24,19 @@ func get_value() -> Vector2: return current_value +func _load_display_info(info: Dictionary) -> void: + for option in info.keys(): + match option: + #'min': min = info[option] + #'max': max = info[option] + #'prefix': update_prefix(info[option]) + #'suffix': update_suffix(info[option]) + 'step': + enforce_step = true + step = info[option] + #'hide_step_button': %Spin.hide() + + func _on_sub_value_changed(sub_component: String, value: float) -> void: match sub_component: 'X': current_value.x = value From 48a6d00df8e0068a551f8de3ea89742fea44337b Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:08:11 +0100 Subject: [PATCH 05/17] Fix placeholder support for fixed event fields. --- .../Editor/Events/Fields/field_options_fixed.gd | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd index 0b379f50e..f88866eda 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd +++ b/addons/dialogic/Editor/Events/Fields/field_options_fixed.gd @@ -3,6 +3,9 @@ extends DialogicVisualEditorField ## Event block field for constant options. For varying options use ComplexPicker. + +@export var placeholder_text := "Placeholder Text" + var options : Array = [] ## if true, only the symbol will be displayed. In the dropdown text will be visible. @@ -18,6 +21,7 @@ var current_value: Variant = -1 func _ready() -> void: add_theme_color_override("font_disabled_color", get_theme_color("font_color", "MenuButton")) self.about_to_popup.connect(insert_options) + self.text = placeholder_text call("get_popup").index_pressed.connect(index_pressed) @@ -25,15 +29,23 @@ func _load_display_info(info:Dictionary) -> void: options = info.get('options', []) self.disabled = info.get('disabled', false) symbol_only = info.get('symbol_only', false) + placeholder_text = info.get('placeholder', 'Select Resource') + + +func _set_value(value: Variant) -> void: + if value == null: + self.text = placeholder_text -func _set_value(value:Variant) -> void: for option in options: if option['value'] == value: + if typeof(option.get('icon')) == TYPE_ARRAY: option.icon = callv('get_theme_icon', option.get('icon')) + if !symbol_only: self.text = option['label'] + self.icon = option.get('icon', null) current_value = value From 0be30ff01287ff64a4179e95ab8d465bb89ead52 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 26 Mar 2024 17:09:02 +0100 Subject: [PATCH 06/17] Turn number event fields value ranges off by default. --- .../Editor/Events/Fields/field_number.gd | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/addons/dialogic/Editor/Events/Fields/field_number.gd b/addons/dialogic/Editor/Events/Fields/field_number.gd index 967bdf645..ff3527d9d 100644 --- a/addons/dialogic/Editor/Events/Fields/field_number.gd +++ b/addons/dialogic/Editor/Events/Fields/field_number.gd @@ -7,8 +7,10 @@ extends DialogicVisualEditorField @export var allow_string : bool = false @export var step: float = 0.1 @export var enforce_step: bool = true -@export var min: float = 0 -@export var max: float= 999 +@export var limit_value: bool = false +@export var min: float = 0.0 +@export var max: float = 999.0 +@export var only_positive: bool = false @export var value = 0.0 @export var prefix: String = "" @export var suffix: String = "" @@ -33,11 +35,13 @@ func _load_display_info(info: Dictionary) -> void: use_float_mode(info.get('step', 0.1)) 1: #INT use_int_mode(info.get('step', 1)) - 2: #DECIBLE: + 2: #DECIBEL: use_decibel_mode(info.get('step', step)) - for option in info.keys(): + + for option: String in info.keys(): match option: + 'limit_value': limit_value = info[option] 'min': min = info[option] 'max': max = info[option] 'prefix': update_prefix(info[option]) @@ -53,7 +57,7 @@ func _set_value(new_value: Variant) -> void: %Value.tooltip_text = tooltip_text -func _autofocus(): +func _autofocus() -> void: %Value.grab_focus() @@ -73,7 +77,7 @@ func use_int_mode(value_step: float = 1) -> void: enforce_step = true -func use_decibel_mode(value_step: float = step) -> void: +func use_decibel_mode(_value_step: float = step) -> void: max = 6 update_suffix("dB") min = -80 @@ -158,19 +162,36 @@ func _on_decrement_button_down(button: NodePath) -> void: func _on_value_text_submitted(new_text: String, no_signal:= false) -> void: if new_text.is_valid_float(): - var temp: float = min(max(new_text.to_float(), min), max) + var final_value := new_text.to_float() + + if limit_value: + final_value = min(max(final_value, min), max) + + elif only_positive: + final_value = max(0, final_value) + if !enforce_step: - value = temp + value = final_value else: - value = snapped(temp, step) + value = snapped(final_value, step) + elif allow_string: value = new_text + %Value.text = str(value).pad_decimals(len(str(float(step)-floorf(step)))-2) + if not no_signal: value_changed.emit(property_name, value) - # Visually disable Up or Down arrow when limit is reached to better indicate a limit has been hit - %Spin/Decrement.disabled = value <= min - %Spin/Increment.disabled = value >= max + + if limit_value: + # Visually disable Up or Down arrow when limit is reached to better + ## indicate a limit has been hit. + %Spin/Decrement.disabled = value <= min + %Spin/Increment.disabled = value >= max + + else: + %Spin/Decrement.disabled = false + %Spin/Increment.disabled = false # If prefix or suffix was clicked, select the actual value box instead and move the caret to the closest side. From ddd1b51fcc2856237dca2e2cf3ee00987db0d5ac Mon Sep 17 00:00:00 2001 From: Cake Date: Thu, 28 Mar 2024 09:50:48 +0100 Subject: [PATCH 07/17] Add conversion support for handling various number and vector types. --- addons/dialogic/Core/DialogicUtil.gd | 24 +++++++++++++++++++ .../Editor/Events/Fields/field_vector2.gd | 17 ++++++++++++- .../Editor/Events/Fields/field_vector3.gd | 15 ++++++++++++ .../Editor/Events/Fields/field_vector4.gd | 16 +++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/addons/dialogic/Core/DialogicUtil.gd b/addons/dialogic/Core/DialogicUtil.gd index 1f9466a43..7dcbe3650 100644 --- a/addons/dialogic/Core/DialogicUtil.gd +++ b/addons/dialogic/Core/DialogicUtil.gd @@ -504,6 +504,30 @@ static func logical_convert(value:Variant) -> Variant: return value +static func vector2_to_vector3(vector: Vector2) -> Vector3: + return Vector3(vector.x, vector.y, 0) + + +static func vector3_to_vector2(vector: Vector3) -> Vector2: + return Vector2(vector.x, vector.y) + + +static func vector4_to_vector2(vector: Vector4) -> Vector2: + return Vector2(vector.x, vector.y) + + +static func vector2_to_vector4(vector: Vector2) -> Vector4: + return Vector4(vector.x, vector.y, 0, 0) + + +static func vector3_to_vector4(vector:Vector3) -> Vector4: + return Vector4(vector.x, vector.y, vector.z, 0) + + +static func vector4_to_vector3(vector: Vector4) -> Vector3: + return Vector3(vector.x, vector.y, vector.z) + + ## Takes [param source] and builds a dictionary of keys only. ## The values are `null`. static func str_to_hash_set(source: String) -> Dictionary: diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd b/addons/dialogic/Editor/Events/Fields/field_vector2.gd index f15388bd0..c6c4def6e 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd @@ -15,7 +15,22 @@ func _ready() -> void: func _set_value(value: Variant) -> void: + + if value is float or value is int: + var number := value as float + value = Vector2(number, number) + + elif value is Vector4: + value = DialogicUtil.vector4_to_vector2(value as Vector4) + + elif value is Vector3: + value = DialogicUtil.vector3_to_vector2(value as Vector3) + + elif not value is Vector2: + value = Vector2() + current_value = value + value_changed.emit(property_name, value) super(value) @@ -25,7 +40,7 @@ func get_value() -> Vector2: func _load_display_info(info: Dictionary) -> void: - for option in info.keys(): + for option: String in info.keys(): match option: #'min': min = info[option] #'max': max = info[option] diff --git a/addons/dialogic/Editor/Events/Fields/field_vector3.gd b/addons/dialogic/Editor/Events/Fields/field_vector3.gd index c5b9f6dee..116241fc2 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector3.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector3.gd @@ -6,7 +6,22 @@ var current_value := Vector3() func _set_value(value: Variant) -> void: + if value is float or value is int: + var number: float = value.as_float() + value = Vector3(number, number, number) + + elif value is Vector2: + value = DialogicUtil.vector2_to_vector3(value as Vector2) + + elif value is Vector4: + value = DialogicUtil.vector4_to_vector3(value as Vector4) + + elif not value.is_valid_vector3(): + value = Vector3() + current_value = value + + value_changed.emit(property_name, value) super(value) diff --git a/addons/dialogic/Editor/Events/Fields/field_vector4.gd b/addons/dialogic/Editor/Events/Fields/field_vector4.gd index 3259ce379..f384ea591 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector4.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector4.gd @@ -6,7 +6,23 @@ var current_value := Vector4() func _set_value(value: Variant) -> void: + + if value is float or value is int: + var number: float = value.as_float() + value = Vector4(number, number, number, number) + + elif value is Vector2: + value = DialogicUtil.vector2_to_vector4(value as Vector2) + + elif value is Vector3: + value = DialogicUtil.vector3_to_vector4(value as Vector3) + + elif not value is Vector4: + value = Vector4() + current_value = value + + value_changed.emit(property_name, value) super(value) From 758e579a6a106a8632606b1f514cc6161fb6c83a Mon Sep 17 00:00:00 2001 From: Cake Date: Thu, 28 Mar 2024 10:34:34 +0100 Subject: [PATCH 08/17] Add step precision support for all vector event field types. --- .../Editor/Events/Fields/field_vector2.gd | 11 +++++----- .../Editor/Events/Fields/field_vector3.gd | 20 ++++++++++++++++++ .../Editor/Events/Fields/field_vector4.gd | 21 +++++++++++++++++++ .../Editor/Events/Fields/field_vector_base.gd | 2 +- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd b/addons/dialogic/Editor/Events/Fields/field_vector2.gd index c6c4def6e..e37f83803 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd @@ -8,13 +8,8 @@ extends DialogicVisualEditorFieldVector var current_value := Vector2() -func _ready() -> void: - if enforce_step: - $X.step = step - $Y.step = step - - func _set_value(value: Variant) -> void: + print("Setting value to: ", value) if value is float or value is int: var number := value as float @@ -51,6 +46,10 @@ func _load_display_info(info: Dictionary) -> void: step = info[option] #'hide_step_button': %Spin.hide() + if enforce_step: + $X.step = step + $Y.step = step + func _on_sub_value_changed(sub_component: String, value: float) -> void: match sub_component: diff --git a/addons/dialogic/Editor/Events/Fields/field_vector3.gd b/addons/dialogic/Editor/Events/Fields/field_vector3.gd index 116241fc2..43101656d 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector3.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector3.gd @@ -4,6 +4,8 @@ extends DialogicVisualEditorFieldVector var current_value := Vector3() +@export var step: float = 0.1 +@export var enforce_step: bool = true func _set_value(value: Variant) -> void: if value is float or value is int: @@ -37,6 +39,24 @@ func _on_sub_value_changed(sub_component: String, value: float) -> void: _on_value_changed(current_value) +func _load_display_info(info: Dictionary) -> void: + for option: String in info.keys(): + match option: + #'min': min = info[option] + #'max': max = info[option] + #'prefix': update_prefix(info[option]) + #'suffix': update_suffix(info[option]) + 'step': + enforce_step = true + step = info[option] + #'hide_step_button': %Spin.hide() + + if enforce_step: + $X.step = step + $Y.step = step + $Z.step = step + + func _update_sub_component_text(value: Variant) -> void: $X._on_value_text_submitted(str(value.x), true) $Y._on_value_text_submitted(str(value.y), true) diff --git a/addons/dialogic/Editor/Events/Fields/field_vector4.gd b/addons/dialogic/Editor/Events/Fields/field_vector4.gd index f384ea591..8d2259b9b 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector4.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector4.gd @@ -4,6 +4,8 @@ extends DialogicVisualEditorFieldVector var current_value := Vector4() +@export var step: float = 0.1 +@export var enforce_step: bool = true func _set_value(value: Variant) -> void: @@ -30,6 +32,25 @@ func get_value() -> Vector4: return current_value +func _load_display_info(info: Dictionary) -> void: + for option: String in info.keys(): + match option: + #'min': min = info[option] + #'max': max = info[option] + #'prefix': update_prefix(info[option]) + #'suffix': update_suffix(info[option]) + 'step': + enforce_step = true + step = info[option] + #'hide_step_button': %Spin.hide() + + if enforce_step: + $X.step = step + $Y.step = step + $Z.step = step + $W.step = step + + func _on_sub_value_changed(sub_component: String, value: float) -> void: match sub_component: 'X': current_value.x = value diff --git a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd index 5d5d9e95d..02d3d6981 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector_base.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector_base.gd @@ -4,7 +4,7 @@ extends DialogicVisualEditorField func _ready() -> void: - for child in get_children(): + for child: Node in get_children(): child.tooltip_text = tooltip_text child.property_name = child.name #to identify the name of the changed sub-component child.value_changed.connect(_on_sub_value_changed) From acc3f3343e32cbe40c46d7186c9708ecc29d54ab Mon Sep 17 00:00:00 2001 From: Cake Date: Thu, 28 Mar 2024 10:36:59 +0100 Subject: [PATCH 09/17] Remove `print`s. --- addons/dialogic/Editor/Events/Fields/field_vector2.gd | 1 - 1 file changed, 1 deletion(-) diff --git a/addons/dialogic/Editor/Events/Fields/field_vector2.gd b/addons/dialogic/Editor/Events/Fields/field_vector2.gd index e37f83803..4862ae0f8 100644 --- a/addons/dialogic/Editor/Events/Fields/field_vector2.gd +++ b/addons/dialogic/Editor/Events/Fields/field_vector2.gd @@ -9,7 +9,6 @@ var current_value := Vector2() func _set_value(value: Variant) -> void: - print("Setting value to: ", value) if value is float or value is int: var number := value as float From 268780a28777f88d1824e81d5ddc229a83f569c0 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 2 Apr 2024 17:19:35 +0200 Subject: [PATCH 10/17] Add Node Path Support to the Tween Event. --- addons/dialogic/Modules/Tween/event_tween.gd | 104 +++++++++++++++---- 1 file changed, 86 insertions(+), 18 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 2c4c682fc..56a4d64f8 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -5,6 +5,7 @@ class_name DialogicTweenEvent enum TweenTarget { PORTRAIT, BACKGROUND, + NODE_PATH, } const TIME_DEFAULT := 0.0 @@ -26,14 +27,21 @@ var _property := "" : _property = value _sub_property = "" - var variable_value: Variant = ColorRect.new().get(_property) - var variant_type: Variant.Type = typeof(variable_value) as Variant.Type + var variant_type: Variant.Type = Variant.Type.TYPE_NIL + + if _target == TweenTarget.BACKGROUND: + var variable_value: Variant = ColorRect.new().get(_property) + variant_type = typeof(variable_value) as Variant.Type + + elif _target == TweenTarget.NODE_PATH: + variant_type = typeof(_value) as Variant.Type var new_value_type := variant_to_value_type(variant_type) _value_type = new_value_type var _sub_property := "" var _target := TweenTarget.BACKGROUND +var _node_path := "" var _time: float = TIME_DEFAULT var _is_relative: bool = IS_RELATIVE_DEFAULT var _await: bool = AWAIT_DEFAULT @@ -44,7 +52,9 @@ var _value_type: ValueType = ValueType.NUMBER var _value: Variant = null : set(value): _value = value - print(value) +var _revert_value := false +var _revert_after := 0.0 +var _revert_time := 0.0 func _execute() -> void: var target_node: Node = null @@ -56,6 +66,14 @@ func _execute() -> void: TweenTarget.BACKGROUND: target_node = dialogic.Backgrounds.get_current_background_node() + TweenTarget.NODE_PATH: + target_node = dialogic.get_tree().get_root().get_node(_node_path) + + if target_node == null: + printerr("[Dialogic] Node path '" + _node_path + "' not found, aborting Tween Event.") + finish() + return + var tween := dialogic.create_tween() tween.set_ease(_ease) tween.set_trans(_transition) @@ -102,7 +120,10 @@ func to_text() -> String: match _target: TweenTarget.PORTRAIT: result_string += "portrait " TweenTarget.BACKGROUND: result_string += "background " + TweenTarget.NODE_PATH: result_string += "unique " + if not _node_path.is_empty(): + result_string += " path=\"" + _node_path + "\"" if not _property.is_empty(): result_string += " property=\"" + _property @@ -115,7 +136,6 @@ func to_text() -> String: if not _value == null: result_string += " value=\"" + str(_value) + "\"" - if not _time == TIME_DEFAULT: result_string += " time=\"" + str(_time) + "\"" @@ -279,6 +299,12 @@ func from_text(string: String) -> void: "background": _target = TweenTarget.BACKGROUND + "unique": + _target = TweenTarget.NODE_PATH + + "path": + _node_path = value + "property": _property = value @@ -315,6 +341,15 @@ func string_to_value_type(value: String) -> Variant: var y_value := values[1].strip_edges().to_float() return Vector2(x_value, y_value) + if value == "true": + return true + + elif value == "false": + return false + + if value.begins_with('"') and value.ends_with('"'): + return value.strip_edges() + return null @@ -327,6 +362,7 @@ func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info "property" : {"property": "_property", "default": _property}, + "path" : {"property": "_node_path", "default": _node_path}, "value" : {"property": "_value", "default": _value}, "target" : {"property": "_target", "default": _target}, "time" : {"property": "_time", "default": _time}, @@ -412,18 +448,43 @@ func build_event_editor() -> void: "value": TweenTarget.BACKGROUND, "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") }, + { + "label": "Node Path", + "value": TweenTarget.NODE_PATH, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, ] }) + add_header_edit("_node_path", ValueType.SINGLELINE_TEXT, + { + "left_text": " of ", + "mode": 1, + }, + "_target == TweenTarget.NODE_PATH" + ) + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, - {"placeholder" : "", - "mode" : 1, - "suggestions_func" : get_all_properties, - #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), - "autofocus" : false, - "left_text": " property " - }) + { + "placeholder" : "", + "mode" : 1, + "suggestions_func" : get_all_properties, + #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus" : false, + "left_text": " property ", + }, + "_target == TweenTarget.BACKGROUND" + ) + + + add_header_edit("_property", ValueType.SINGLELINE_TEXT, + { + "left_text": " property ", + "mode": 1, + }, + "_target == TweenTarget.NODE_PATH" + ) add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { @@ -453,14 +514,13 @@ func build_event_editor() -> void: ) - #region VALUE FIELDS add_header_edit("_value", ValueType.NUMBER, { "left_text": " to ", "mode": 1, }, - "not _property.is_empty() and _value_type == ValueType.NUMBER" + "not _property.is_empty() and _value_type == ValueType.NUMBER and not _target == TweenTarget.NODE_PATH" ) add_header_edit("_value", ValueType.VECTOR2, @@ -468,7 +528,7 @@ func build_event_editor() -> void: "left_text": " to ", "mode": 1, }, - "not _property.is_empty() && _value_type == ValueType.VECTOR2 && _sub_property.is_empty()" + "not _property.is_empty() && _value_type == ValueType.VECTOR2 && _sub_property.is_empty() and not _target == TweenTarget.NODE_PATH" ) add_header_edit("_value", ValueType.NUMBER, @@ -476,11 +536,19 @@ func build_event_editor() -> void: "left_text": " to ", "mode": 1, }, - "not _property.is_empty() && _value_type == ValueType.VECTOR2 && not _sub_property.is_empty()" + "not _property.is_empty() && _value_type == ValueType.VECTOR2 && not _sub_property.is_empty() and not _target == TweenTarget.NODE_PATH" ) - #endregion + add_header_edit("_value", ValueType.SINGLELINE_TEXT, + { + "left_text": " to ", + "mode": 1, + }, + "_target == TweenTarget.NODE_PATH" + ) + #endregion + add_header_edit("_time", ValueType.NUMBER, { @@ -490,7 +558,6 @@ func build_event_editor() -> void: } ) - add_header_edit("_is_relative", ValueType.BOOL, {"left_text":"Relative:"}, "_time > 0.0" ) @@ -499,7 +566,7 @@ func build_event_editor() -> void: {"left_text": "Await:"}, "_time > 0.0" ) - # Body Optioms + # Body Options add_body_edit("_ease", ValueType.FIXED_OPTIONS, { "left_text": "Ease:", "autofocus" : false, @@ -603,6 +670,7 @@ func build_event_editor() -> void: "_time > 0.0" ) + func variant_to_value_type(value: Variant.Type) -> ValueType: match value: Variant.Type.TYPE_STRING: From 065ef0a20948ea834262c5fb60d98f9d676e1eb3 Mon Sep 17 00:00:00 2001 From: Cake Date: Tue, 2 Apr 2024 23:23:35 +0200 Subject: [PATCH 11/17] Add Portrait Support to the Tween Event. --- addons/dialogic/Modules/Tween/event_tween.gd | 133 ++++++++++++++++++- 1 file changed, 130 insertions(+), 3 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 56a4d64f8..11bfb7d2e 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -33,12 +33,35 @@ var _property := "" : var variable_value: Variant = ColorRect.new().get(_property) variant_type = typeof(variable_value) as Variant.Type + elif _target == TweenTarget.PORTRAIT: + var variable_value: Variant = DialogicCharacter.new().get(_property) + variant_type = typeof(variable_value) as Variant.Type + elif _target == TweenTarget.NODE_PATH: variant_type = typeof(_value) as Variant.Type var new_value_type := variant_to_value_type(variant_type) + print(new_value_type) _value_type = new_value_type + +## The character that will join/leave/update. +var character : DialogicCharacter = null +## Used to set the character resource from the unique name identifier and vice versa +var _character_identifier: String: + get: + if character: + var identifier := DialogicResourceUtil.get_unique_identifier(character.resource_path) + + if not identifier.is_empty(): + return identifier + + return _character_identifier + + set(value): + _character_identifier = value + character = DialogicResourceUtil.get_character_resource(value) + var _sub_property := "" var _target := TweenTarget.BACKGROUND var _node_path := "" @@ -61,7 +84,12 @@ func _execute() -> void: match _target: TweenTarget.PORTRAIT: - target_node = null + if character == null or not dialogic.Portraits.is_character_joined(character): + printerr("[Dialogic] Character '" + _character_identifier + "' not part of the scene, aborting Tween Event.") + finish() + return + + target_node = dialogic.current_state_info.portraits[character.resource_path].node.get_child(-1) TweenTarget.BACKGROUND: target_node = dialogic.Backgrounds.get_current_background_node() @@ -120,11 +148,14 @@ func to_text() -> String: match _target: TweenTarget.PORTRAIT: result_string += "portrait " TweenTarget.BACKGROUND: result_string += "background " - TweenTarget.NODE_PATH: result_string += "unique " + TweenTarget.NODE_PATH: result_string += "path " if not _node_path.is_empty(): result_string += " path=\"" + _node_path + "\"" + if not _character_identifier.is_empty(): + result_string += " character=\"" + _character_identifier + "\"" + if not _property.is_empty(): result_string += " property=\"" + _property @@ -299,9 +330,12 @@ func from_text(string: String) -> void: "background": _target = TweenTarget.BACKGROUND - "unique": + "path": _target = TweenTarget.NODE_PATH + "character": + _character_identifier = value + "path": _node_path = value @@ -362,6 +396,7 @@ func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info "property" : {"property": "_property", "default": _property}, + "character" : {"property": "_character", "default": _character_identifier}, "path" : {"property": "_node_path", "default": _node_path}, "value" : {"property": "_value", "default": _value}, "target" : {"property": "_target", "default": _target}, @@ -377,6 +412,61 @@ func get_shortcode_parameters() -> Dictionary: #endregion + + + +func get_all_character_properties(search_string: String) -> Dictionary: + const VALID_TYPE := [TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I] + const IGNORE_WORDS := ["process_"] + + var color_rect := DialogicCharacter.new() + var suggestions := {} + var fallback_icon := ["Variant", "EditorIcons"] + + for property_info: Dictionary in color_rect.get_property_list(): + var property_name: String = property_info.get("name") + + if not search_string.is_empty() and not property_name.contains(search_string): + continue + + var ignore_property: bool = false + for ignore_term: String in IGNORE_WORDS: + + if property_name.begins_with(ignore_term): + ignore_property = true + break + + if ignore_property: + continue + + var property_type: Variant.Type = property_info.get("type") + + if not VALID_TYPE.has(property_type): + continue + + var icon: Variant = fallback_icon + + match property_type: + Variant.Type.TYPE_INT: + icon = ["Number", "EditorIcons"] + Variant.Type.TYPE_FLOAT: + icon = ["Float", "EditorIcons"] + Variant.Type.TYPE_STRING: + icon = ["String", "EditorIcons"] + _: + icon = ["Variant", "EditorIcons"] + + + suggestions[property_name] = { + "label": "[b]"+ property_name + "[/b]", + "value": property_name, + "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") + } + + + return suggestions + + func get_all_properties(search_string: String) -> Dictionary: const VALID_TYPE := [TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I] const IGNORE_WORDS := ["process_"] @@ -429,6 +519,21 @@ func get_all_properties(search_string: String) -> Dictionary: return suggestions +func get_character_suggestions(search_text: String) -> Dictionary: + var suggestions := {} + #override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work + + var icon = load("res://addons/dialogic/Editor/Images/Resources/character.svg") + + suggestions['(No one)'] = {'value':'', 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} + var character_directory = DialogicResourceUtil.get_character_directory() + + for resource in character_directory.keys(): + suggestions[resource] = {'value': resource, 'tooltip': character_directory[resource], 'icon': icon.duplicate()} + return suggestions + + + #region EDITOR REPRESENTATION ################################################################################ @@ -464,6 +569,17 @@ func build_event_editor() -> void: "_target == TweenTarget.NODE_PATH" ) + add_header_edit('_character_identifier', ValueType.DYNAMIC_OPTIONS, + {'placeholder' : 'Character', + 'file_extension' : '.dch', + 'mode' : 2, + 'suggestions_func' : get_character_suggestions, + 'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + 'autofocus' : false, + }, + "_target == TweenTarget.PORTRAIT" + ) + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, { @@ -477,6 +593,17 @@ func build_event_editor() -> void: "_target == TweenTarget.BACKGROUND" ) + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + { + "placeholder" : "", + "mode" : 1, + "suggestions_func" : get_all_character_properties, + #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus" : false, + "left_text": " property ", + }, + "_target == TweenTarget.PORTRAIT" + ) add_header_edit("_property", ValueType.SINGLELINE_TEXT, { From 7d20cb71fefd040a947843c9b930e9bc7a0f858d Mon Sep 17 00:00:00 2001 From: Cake Date: Wed, 3 Apr 2024 06:26:59 +0200 Subject: [PATCH 12/17] Add error checks. --- addons/dialogic/Modules/Tween/event_tween.gd | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 11bfb7d2e..e0fe6b033 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -115,8 +115,18 @@ func _execute() -> void: full_property_path += ":" + _sub_property + if target_node == null: + printerr("[Dialogic] Tween Event failed to find target node, aborting.") + finish() + return + var tweener := tween.tween_property(target_node, full_property_path, _value, _time) + if tweener == null: + printerr("[Dialogic] Tween Event failed to create Tween, aborting.") + finish() + return + if _is_relative: tweener.as_relative() From 860f93544e58b8722b4591cf1cd6d4d7fec3a78b Mon Sep 17 00:00:00 2001 From: Cake Date: Wed, 3 Apr 2024 06:55:06 +0200 Subject: [PATCH 13/17] Refactor the code. --- addons/dialogic/Modules/Tween/event_tween.gd | 241 +++++++++++-------- 1 file changed, 145 insertions(+), 96 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index e0fe6b033..5d4a2ff28 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -529,129 +529,79 @@ func get_all_properties(search_string: String) -> Dictionary: return suggestions + func get_character_suggestions(search_text: String) -> Dictionary: var suggestions := {} #override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work - var icon = load("res://addons/dialogic/Editor/Images/Resources/character.svg") + var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg") suggestions['(No one)'] = {'value':'', 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} - var character_directory = DialogicResourceUtil.get_character_directory() + var character_directory := DialogicResourceUtil.get_character_directory() - for resource in character_directory.keys(): + for resource: String in character_directory.keys(): suggestions[resource] = {'value': resource, 'tooltip': character_directory[resource], 'icon': icon.duplicate()} return suggestions - -#region EDITOR REPRESENTATION -################################################################################ - -func build_event_editor() -> void: - #var background_node := DialogicUtil.autoload().get_tree().get_first_node_in_group("dialogic_background_holders").get_child(0) - - add_header_edit("_target", ValueType.FIXED_OPTIONS, { - "left_text": "Tween ", - "options": [ - { - "label": "Portrait", - "value": TweenTarget.PORTRAIT, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Background", - "value": TweenTarget.BACKGROUND, - "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") - }, - { - "label": "Node Path", - "value": TweenTarget.NODE_PATH, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - ] - }) - - add_header_edit("_node_path", ValueType.SINGLELINE_TEXT, +# Add a sub property field for all supported vector types. +func _add_sub_property_fields() -> void: + var options := [ { - "left_text": " of ", - "mode": 1, + "label": "All", + "value": "", }, - "_target == TweenTarget.NODE_PATH" - ) - - add_header_edit('_character_identifier', ValueType.DYNAMIC_OPTIONS, - {'placeholder' : 'Character', - 'file_extension' : '.dch', - 'mode' : 2, - 'suggestions_func' : get_character_suggestions, - 'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), - 'autofocus' : false, + { + "label": "X", + "value": "x", }, - "_target == TweenTarget.PORTRAIT" - ) - + { + "label": "Y", + "value": "y", + }, + { + "label": "Z", + "value": "z", + }, + { + "label": "W", + "value": "w", + }, + ] - add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { - "placeholder" : "", - "mode" : 1, - "suggestions_func" : get_all_properties, - #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), "autofocus" : false, - "left_text": " property ", + "placeholder" : "All", + "mode" : 1, + "options": options.slice(0, 2) }, - "_target == TweenTarget.BACKGROUND" + "_value_type == ValueType.VECTOR2" ) - add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { - "placeholder" : "", - "mode" : 1, - "suggestions_func" : get_all_character_properties, - #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), "autofocus" : false, - "left_text": " property ", + "placeholder" : "All", + "mode" : 1, + "options": options.slice(0, 3), }, - "_target == TweenTarget.PORTRAIT" + "_value_type == ValueType.VECTOR3" ) - add_header_edit("_property", ValueType.SINGLELINE_TEXT, + add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { - "left_text": " property ", - "mode": 1, + "autofocus" : false, + "placeholder" : "All", + "mode" : 1, + "options": options.slice(0, 4), }, - "_target == TweenTarget.NODE_PATH" - ) - - - add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, { - #"left_text": "Point:", - "autofocus" : false, - "placeholder" : "All", - "mode" : 1, - "options": [ - { - "label": "All", - "value": "", - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "x", - "value": "x", - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "y", - "value": "y", - "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") - }, - ] - }, - "_value_type == ValueType.VECTOR2" + "_value_type == ValueType.VECTOR4" ) - #region VALUE FIELDS +## Adds all possible fields to set the target value the tween shall reach. +func _add_value_fields() -> void: add_header_edit("_value", ValueType.NUMBER, { "left_text": " to ", @@ -684,9 +634,46 @@ func build_event_editor() -> void: }, "_target == TweenTarget.NODE_PATH" ) - #endregion +## Adds all possible fields to set the property the tween shall act on. +func _add_property_fields() -> void: + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + { + "placeholder" : "", + "mode" : 1, + "suggestions_func" : get_all_properties, + #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus" : false, + "left_text": " property ", + }, + "_target == TweenTarget.BACKGROUND" + ) + + add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + { + "placeholder" : "", + "mode" : 1, + "suggestions_func" : get_all_character_properties, + #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus" : false, + "left_text": " property ", + }, + "_target == TweenTarget.PORTRAIT" + ) + + add_header_edit("_property", ValueType.SINGLELINE_TEXT, + { + "left_text": " property ", + "mode": 1, + }, + "_target == TweenTarget.NODE_PATH" + ) + + +## Adds fields that may appear if time is not zero. +## Also adds the time field. +func _add_time_properties() -> void: add_header_edit("_time", ValueType.NUMBER, { "left_text":" over ", @@ -804,11 +791,73 @@ func build_event_editor() -> void: }, ] }, - "_time > 0.0" + "_time > 0.0" + ) + + +## Adds all possible fields for the target of the tween. +## This helps to find the node to tween. +func _add_target_fields() -> void: + add_header_edit("_target", ValueType.FIXED_OPTIONS, { + "left_text": "Tween ", + "options": [ + { + "label": "Portrait", + "value": TweenTarget.PORTRAIT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Background", + "value": TweenTarget.BACKGROUND, + "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") + }, + { + "label": "Node Path", + "value": TweenTarget.NODE_PATH, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + }) + + add_header_edit("_node_path", ValueType.SINGLELINE_TEXT, + { + "left_text": " of ", + "mode": 1, + }, + "_target == TweenTarget.NODE_PATH" ) + add_header_edit('_character_identifier', ValueType.DYNAMIC_OPTIONS, + {'placeholder' : 'Character', + 'file_extension' : '.dch', + 'mode' : 2, + 'suggestions_func' : get_character_suggestions, + 'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + 'autofocus' : false, + }, + "_target == TweenTarget.PORTRAIT" + ) + + + +#region EDITOR REPRESENTATION +################################################################################ + +func build_event_editor() -> void: + # Decides what node to tween. + _add_target_fields() + # Decides what property to tween. + _add_property_fields() + # Decides what, if any, sub-property to target. + _add_sub_property_fields() + # Decides what value to tween to. + _add_value_fields() + # Extra values if time is not zero. + _add_time_properties() + + -func variant_to_value_type(value: Variant.Type) -> ValueType: +static func variant_to_value_type(value: Variant.Type) -> ValueType: match value: Variant.Type.TYPE_STRING: return ValueType.SINGLELINE_TEXT From 062866372cb118c7d31f9bfcf476dc57845ffe84 Mon Sep 17 00:00:00 2001 From: Cake Date: Wed, 3 Apr 2024 06:56:25 +0200 Subject: [PATCH 14/17] Format code. --- addons/dialogic/Modules/Tween/event_tween.gd | 488 ++++++++++--------- 1 file changed, 260 insertions(+), 228 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 5d4a2ff28..53fcda4e9 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -15,10 +15,8 @@ const PARALLEL_DEFAULT := false const EASE_DEFAULT := Tween.EASE_IN const TRANSITION_DEFAULT := Tween.TRANS_LINEAR - -var _property := "" : +var _property := "": set(value): - if value.contains(":"): var split_property := value.split(":") _property = split_property[0] @@ -30,11 +28,11 @@ var _property := "" : var variant_type: Variant.Type = Variant.Type.TYPE_NIL if _target == TweenTarget.BACKGROUND: - var variable_value: Variant = ColorRect.new().get(_property) + var variable_value: Variant = ColorRect.new().get(_property) variant_type = typeof(variable_value) as Variant.Type elif _target == TweenTarget.PORTRAIT: - var variable_value: Variant = DialogicCharacter.new().get(_property) + var variable_value: Variant = DialogicCharacter.new().get(_property) variant_type = typeof(variable_value) as Variant.Type elif _target == TweenTarget.NODE_PATH: @@ -44,9 +42,8 @@ var _property := "" : print(new_value_type) _value_type = new_value_type - ## The character that will join/leave/update. -var character : DialogicCharacter = null +var character: DialogicCharacter = null ## Used to set the character resource from the unique name identifier and vice versa var _character_identifier: String: get: @@ -72,24 +69,33 @@ var _parallel := PARALLEL_DEFAULT var _ease := EASE_DEFAULT var _transition := TRANSITION_DEFAULT var _value_type: ValueType = ValueType.NUMBER -var _value: Variant = null : +var _value: Variant = null: set(value): _value = value var _revert_value := false var _revert_after := 0.0 var _revert_time := 0.0 + func _execute() -> void: var target_node: Node = null match _target: TweenTarget.PORTRAIT: if character == null or not dialogic.Portraits.is_character_joined(character): - printerr("[Dialogic] Character '" + _character_identifier + "' not part of the scene, aborting Tween Event.") + printerr( + ( + "[Dialogic] Character '" + + _character_identifier + + "' not part of the scene, aborting Tween Event." + ) + ) finish() return - target_node = dialogic.current_state_info.portraits[character.resource_path].node.get_child(-1) + target_node = ( + dialogic.current_state_info.portraits[character.resource_path].node.get_child(-1) + ) TweenTarget.BACKGROUND: target_node = dialogic.Backgrounds.get_current_background_node() @@ -98,7 +104,9 @@ func _execute() -> void: target_node = dialogic.get_tree().get_root().get_node(_node_path) if target_node == null: - printerr("[Dialogic] Node path '" + _node_path + "' not found, aborting Tween Event.") + printerr( + "[Dialogic] Node path '" + _node_path + "' not found, aborting Tween Event." + ) finish() return @@ -114,7 +122,6 @@ func _execute() -> void: if not _sub_property.is_empty(): full_property_path += ":" + _sub_property - if target_node == null: printerr("[Dialogic] Tween Event failed to find target node, aborting.") finish() @@ -146,53 +153,54 @@ func _init() -> void: event_sorting_index = 3 - #endregion #region SAVING/LOADING ################################################################################ + func to_text() -> String: var result_string := "[tween " match _target: - TweenTarget.PORTRAIT: result_string += "portrait " - TweenTarget.BACKGROUND: result_string += "background " - TweenTarget.NODE_PATH: result_string += "path " + TweenTarget.PORTRAIT: + result_string += "portrait " + TweenTarget.BACKGROUND: + result_string += "background " + TweenTarget.NODE_PATH: + result_string += "path " if not _node_path.is_empty(): - result_string += " path=\"" + _node_path + "\"" + result_string += ' path="' + _node_path + '"' if not _character_identifier.is_empty(): - result_string += " character=\"" + _character_identifier + "\"" + result_string += ' character="' + _character_identifier + '"' if not _property.is_empty(): - result_string += " property=\"" + _property + result_string += ' property="' + _property if not _sub_property.is_empty(): result_string += ":" + _sub_property - result_string += "\"" + result_string += '"' if not _value == null: - result_string += " value=\"" + str(_value) + "\"" + result_string += ' value="' + str(_value) + '"' if not _time == TIME_DEFAULT: - result_string += " time=\"" + str(_time) + "\"" + result_string += ' time="' + str(_time) + '"' if not _is_relative == IS_RELATIVE_DEFAULT: - result_string += " is_relative=\"" + str(_is_relative) + "\"" + result_string += ' is_relative="' + str(_is_relative) + '"' if not _await == AWAIT_DEFAULT: - result_string += " await=\"" + str(_await) + "\"" + result_string += ' await="' + str(_await) + '"' if not _ease == EASE_DEFAULT: - result_string += " ease=\"" + _tween_ease_to_text(_ease) + "\"" + result_string += ' ease="' + _tween_ease_to_text(_ease) + '"' if not _transition == TRANSITION_DEFAULT: - result_string += " transition=\"" + _transition_to_text(_transition) + "\"" - - + result_string += ' transition="' + _transition_to_text(_transition) + '"' return result_string + "]" @@ -325,7 +333,6 @@ func from_text(string: String) -> void: regex.compile(regex_str) for regex_match in regex.search_all(string): - var key := regex_match.get_string(1) if key.is_empty(): @@ -371,7 +378,6 @@ func from_text(string: String) -> void: _transition = _text_to_transition(value) as Tween.TransitionType - func string_to_value_type(value: String) -> Variant: if value.is_valid_int(): return value.to_int() @@ -397,7 +403,6 @@ func string_to_value_type(value: String) -> Variant: return null - func get_shortcode() -> String: return "tween" @@ -405,16 +410,16 @@ func get_shortcode() -> String: func get_shortcode_parameters() -> Dictionary: return { #param_name : property_info - "property" : {"property": "_property", "default": _property}, - "character" : {"property": "_character", "default": _character_identifier}, - "path" : {"property": "_node_path", "default": _node_path}, - "value" : {"property": "_value", "default": _value}, - "target" : {"property": "_target", "default": _target}, - "time" : {"property": "_time", "default": _time}, - "is_relative" : {"property": "_is_relative", "default": _is_relative}, - "await" : {"property": "_await", "default": _await}, - "sub_property" : {"property": "_sub_property", "default": _sub_property}, - "ease" : {"property": "_ease", "default": _ease}, + "property": {"property": "_property", "default": _property}, + "character": {"property": "_character", "default": _character_identifier}, + "path": {"property": "_node_path", "default": _node_path}, + "value": {"property": "_value", "default": _value}, + "target": {"property": "_target", "default": _target}, + "time": {"property": "_time", "default": _time}, + "is_relative": {"property": "_is_relative", "default": _is_relative}, + "await": {"property": "_await", "default": _await}, + "sub_property": {"property": "_sub_property", "default": _sub_property}, + "ease": {"property": "_ease", "default": _ease}, } @@ -422,11 +427,10 @@ func get_shortcode_parameters() -> Dictionary: #endregion - - - func get_all_character_properties(search_string: String) -> Dictionary: - const VALID_TYPE := [TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I] + const VALID_TYPE := [ + TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I + ] const IGNORE_WORDS := ["process_"] var color_rect := DialogicCharacter.new() @@ -441,7 +445,6 @@ func get_all_character_properties(search_string: String) -> Dictionary: var ignore_property: bool = false for ignore_term: String in IGNORE_WORDS: - if property_name.begins_with(ignore_term): ignore_property = true break @@ -466,19 +469,19 @@ func get_all_character_properties(search_string: String) -> Dictionary: _: icon = ["Variant", "EditorIcons"] - suggestions[property_name] = { - "label": "[b]"+ property_name + "[/b]", + "label": "[b]" + property_name + "[/b]", "value": property_name, "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") } - return suggestions func get_all_properties(search_string: String) -> Dictionary: - const VALID_TYPE := [TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I] + const VALID_TYPE := [ + TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I + ] const IGNORE_WORDS := ["process_"] var color_rect := ColorRect.new() @@ -493,7 +496,6 @@ func get_all_properties(search_string: String) -> Dictionary: var ignore_property: bool = false for ignore_term: String in IGNORE_WORDS: - if property_name.begins_with(ignore_term): ignore_property = true break @@ -518,29 +520,28 @@ func get_all_properties(search_string: String) -> Dictionary: _: icon = ["Variant", "EditorIcons"] - suggestions[property_name] = { - "label": "[b]"+ property_name + "[/b]", + "label": "[b]" + property_name + "[/b]", "value": property_name, "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") } - return suggestions - func get_character_suggestions(search_text: String) -> Dictionary: var suggestions := {} #override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg") - suggestions['(No one)'] = {'value':'', 'editor_icon':["GuiRadioUnchecked", "EditorIcons"]} + suggestions["(No one)"] = {"value": "", "editor_icon": ["GuiRadioUnchecked", "EditorIcons"]} var character_directory := DialogicResourceUtil.get_character_directory() for resource: String in character_directory.keys(): - suggestions[resource] = {'value': resource, 'tooltip': character_directory[resource], 'icon': icon.duplicate()} + suggestions[resource] = { + "value": resource, "tooltip": character_directory[resource], "icon": icon.duplicate() + } return suggestions @@ -569,31 +570,32 @@ func _add_sub_property_fields() -> void: }, ] - add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, - { - "autofocus" : false, - "placeholder" : "All", - "mode" : 1, - "options": options.slice(0, 2) - }, + add_header_edit( + "_sub_property", + ValueType.FIXED_OPTIONS, + {"autofocus": false, "placeholder": "All", "mode": 1, "options": options.slice(0, 2)}, "_value_type == ValueType.VECTOR2" ) - add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, + add_header_edit( + "_sub_property", + ValueType.FIXED_OPTIONS, { - "autofocus" : false, - "placeholder" : "All", - "mode" : 1, + "autofocus": false, + "placeholder": "All", + "mode": 1, "options": options.slice(0, 3), }, "_value_type == ValueType.VECTOR3" ) - add_header_edit("_sub_property", ValueType.FIXED_OPTIONS, + add_header_edit( + "_sub_property", + ValueType.FIXED_OPTIONS, { - "autofocus" : false, - "placeholder" : "All", - "mode" : 1, + "autofocus": false, + "placeholder": "All", + "mode": 1, "options": options.slice(0, 4), }, "_value_type == ValueType.VECTOR4" @@ -602,7 +604,9 @@ func _add_sub_property_fields() -> void: ## Adds all possible fields to set the target value the tween shall reach. func _add_value_fields() -> void: - add_header_edit("_value", ValueType.NUMBER, + add_header_edit( + "_value", + ValueType.NUMBER, { "left_text": " to ", "mode": 1, @@ -610,7 +614,9 @@ func _add_value_fields() -> void: "not _property.is_empty() and _value_type == ValueType.NUMBER and not _target == TweenTarget.NODE_PATH" ) - add_header_edit("_value", ValueType.VECTOR2, + add_header_edit( + "_value", + ValueType.VECTOR2, { "left_text": " to ", "mode": 1, @@ -618,7 +624,9 @@ func _add_value_fields() -> void: "not _property.is_empty() && _value_type == ValueType.VECTOR2 && _sub_property.is_empty() and not _target == TweenTarget.NODE_PATH" ) - add_header_edit("_value", ValueType.NUMBER, + add_header_edit( + "_value", + ValueType.NUMBER, { "left_text": " to ", "mode": 1, @@ -626,8 +634,9 @@ func _add_value_fields() -> void: "not _property.is_empty() && _value_type == ValueType.VECTOR2 && not _sub_property.is_empty() and not _target == TweenTarget.NODE_PATH" ) - - add_header_edit("_value", ValueType.SINGLELINE_TEXT, + add_header_edit( + "_value", + ValueType.SINGLELINE_TEXT, { "left_text": " to ", "mode": 1, @@ -638,31 +647,37 @@ func _add_value_fields() -> void: ## Adds all possible fields to set the property the tween shall act on. func _add_property_fields() -> void: - add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + add_header_edit( + "_property", + ValueType.DYNAMIC_OPTIONS, { - "placeholder" : "", - "mode" : 1, - "suggestions_func" : get_all_properties, + "placeholder": "", + "mode": 1, + "suggestions_func": get_all_properties, #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), - "autofocus" : false, - "left_text": " property ", + "autofocus": false, + "left_text": " property ", }, "_target == TweenTarget.BACKGROUND" ) - add_header_edit("_property", ValueType.DYNAMIC_OPTIONS, + add_header_edit( + "_property", + ValueType.DYNAMIC_OPTIONS, { - "placeholder" : "", - "mode" : 1, - "suggestions_func" : get_all_character_properties, + "placeholder": "", + "mode": 1, + "suggestions_func": get_all_character_properties, #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), - "autofocus" : false, - "left_text": " property ", + "autofocus": false, + "left_text": " property ", }, "_target == TweenTarget.PORTRAIT" ) - add_header_edit("_property", ValueType.SINGLELINE_TEXT, + add_header_edit( + "_property", + ValueType.SINGLELINE_TEXT, { "left_text": " property ", "mode": 1, @@ -674,123 +689,128 @@ func _add_property_fields() -> void: ## Adds fields that may appear if time is not zero. ## Also adds the time field. func _add_time_properties() -> void: - add_header_edit("_time", ValueType.NUMBER, + add_header_edit( + "_time", + ValueType.NUMBER, { - "left_text":" over ", + "left_text": " over ", "right_text": " seconds. ", "only_positive": true, } - ) - - add_header_edit("_is_relative", ValueType.BOOL, - {"left_text":"Relative:"}, "_time > 0.0" ) - add_header_edit("_await", ValueType.BOOL, - {"left_text": "Await:"}, "_time > 0.0" - ) + add_header_edit("_is_relative", ValueType.BOOL, {"left_text": "Relative:"}, "_time > 0.0") + + add_header_edit("_await", ValueType.BOOL, {"left_text": "Await:"}, "_time > 0.0") # Body Options - add_body_edit("_ease", ValueType.FIXED_OPTIONS, { - "left_text": "Ease:", - "autofocus" : false, - "mode" : 2, - "placeholder": "Ease In", - "options": [ - { - "label": "Ease In", - "value": Tween.EASE_IN, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Ease Out", - "value": Tween.EASE_OUT, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Ease In Out", - "value": Tween.EASE_IN_OUT, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Ease Out In", - "value": Tween.EASE_OUT_IN, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - ] - }, - "_time > 0.0" + add_body_edit( + "_ease", + ValueType.FIXED_OPTIONS, + { + "left_text": "Ease:", + "autofocus": false, + "mode": 2, + "placeholder": "Ease In", + "options": + [ + { + "label": "Ease In", + "value": Tween.EASE_IN, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out", + "value": Tween.EASE_OUT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease In Out", + "value": Tween.EASE_IN_OUT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out In", + "value": Tween.EASE_OUT_IN, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + }, + "_time > 0.0" ) - - add_body_edit("_transition", ValueType.FIXED_OPTIONS, { - "left_text": "Transition:", - "autofocus" : false, - "mode" : 1, - "placeholder": "Linear", - "options": [ - { - "label": "Linear", - "value": Tween.TRANS_LINEAR, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Sine", - "value": Tween.TRANS_SINE, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Quint", - "value": Tween.TRANS_QUINT, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Quart", - "value": Tween.TRANS_QUART, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Quad", - "value": Tween.TRANS_QUAD, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Expo", - "value": Tween.TRANS_EXPO, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Elastic", - "value": Tween.TRANS_ELASTIC, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Ease Out In", - "value": Tween.TRANS_CUBIC, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Circ", - "value": Tween.TRANS_CIRC, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Bounce", - "value": Tween.TRANS_BOUNCE, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Back", - "value": Tween.TRANS_BACK, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Spring", - "value": Tween.TRANS_SPRING, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - ] - }, + add_body_edit( + "_transition", + ValueType.FIXED_OPTIONS, + { + "left_text": "Transition:", + "autofocus": false, + "mode": 1, + "placeholder": "Linear", + "options": + [ + { + "label": "Linear", + "value": Tween.TRANS_LINEAR, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Sine", + "value": Tween.TRANS_SINE, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quint", + "value": Tween.TRANS_QUINT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quart", + "value": Tween.TRANS_QUART, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Quad", + "value": Tween.TRANS_QUAD, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Expo", + "value": Tween.TRANS_EXPO, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Elastic", + "value": Tween.TRANS_ELASTIC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Ease Out In", + "value": Tween.TRANS_CUBIC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Circ", + "value": Tween.TRANS_CIRC, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Bounce", + "value": Tween.TRANS_BOUNCE, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Back", + "value": Tween.TRANS_BACK, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Spring", + "value": Tween.TRANS_SPRING, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + }, "_time > 0.0" ) @@ -798,28 +818,38 @@ func _add_time_properties() -> void: ## Adds all possible fields for the target of the tween. ## This helps to find the node to tween. func _add_target_fields() -> void: - add_header_edit("_target", ValueType.FIXED_OPTIONS, { - "left_text": "Tween ", - "options": [ - { - "label": "Portrait", - "value": TweenTarget.PORTRAIT, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - { - "label": "Background", - "value": TweenTarget.BACKGROUND, - "icon": load("res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg") - }, - { - "label": "Node Path", - "value": TweenTarget.NODE_PATH, - "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") - }, - ] - }) - - add_header_edit("_node_path", ValueType.SINGLELINE_TEXT, + add_header_edit( + "_target", + ValueType.FIXED_OPTIONS, + { + "left_text": "Tween ", + "options": + [ + { + "label": "Portrait", + "value": TweenTarget.PORTRAIT, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + { + "label": "Background", + "value": TweenTarget.BACKGROUND, + "icon": + load( + "res://addons/dialogic/Modules/DefaultLayoutParts/Layer_FullBackground/background_layer_icon.svg" + ) + }, + { + "label": "Node Path", + "value": TweenTarget.NODE_PATH, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg") + }, + ] + } + ) + + add_header_edit( + "_node_path", + ValueType.SINGLELINE_TEXT, { "left_text": " of ", "mode": 1, @@ -827,22 +857,25 @@ func _add_target_fields() -> void: "_target == TweenTarget.NODE_PATH" ) - add_header_edit('_character_identifier', ValueType.DYNAMIC_OPTIONS, - {'placeholder' : 'Character', - 'file_extension' : '.dch', - 'mode' : 2, - 'suggestions_func' : get_character_suggestions, - 'icon' : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), - 'autofocus' : false, + add_header_edit( + "_character_identifier", + ValueType.DYNAMIC_OPTIONS, + { + "placeholder": "Character", + "file_extension": ".dch", + "mode": 2, + "suggestions_func": get_character_suggestions, + "icon": load("res://addons/dialogic/Editor/Images/Resources/character.svg"), + "autofocus": false, }, "_target == TweenTarget.PORTRAIT" ) - #region EDITOR REPRESENTATION ################################################################################ + func build_event_editor() -> void: # Decides what node to tween. _add_target_fields() @@ -856,7 +889,6 @@ func build_event_editor() -> void: _add_time_properties() - static func variant_to_value_type(value: Variant.Type) -> ValueType: match value: Variant.Type.TYPE_STRING: From 98b6c35ee67f2fbb911dc36e34592d668a7ff3e7 Mon Sep 17 00:00:00 2001 From: Cake Date: Wed, 3 Apr 2024 07:17:38 +0200 Subject: [PATCH 15/17] Refactor into Utility region. --- addons/dialogic/Modules/Tween/event_tween.gd | 452 +++++++++---------- 1 file changed, 215 insertions(+), 237 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 53fcda4e9..431eebbf6 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -15,6 +15,9 @@ const PARALLEL_DEFAULT := false const EASE_DEFAULT := Tween.EASE_IN const TRANSITION_DEFAULT := Tween.TRANS_LINEAR +const _REGEX_STRING := r'(\w+)\s*=\s*"([^"]*)"|(\w+)' +static var _REGEX_TEXT_TO_VISUAL := RegEx.create_from_string(_REGEX_STRING) + var _property := "": set(value): if value.contains(":"): @@ -205,90 +208,6 @@ func to_text() -> String: return result_string + "]" -func _transition_to_text(transition_kind: int) -> String: - match transition_kind: - Tween.TRANS_LINEAR: - return "Linear" - - Tween.TRANS_SINE: - return "Sine" - - Tween.TRANS_QUINT: - return "Quint" - - Tween.TRANS_QUART: - return "Quart" - - Tween.TRANS_QUAD: - return "Quad" - - Tween.TRANS_EXPO: - return "Expo" - - Tween.TRANS_ELASTIC: - return "Elastic" - - Tween.TRANS_CUBIC: - return "Cubic" - - Tween.TRANS_CIRC: - return "Circ" - - Tween.TRANS_BOUNCE: - return "Bounce" - - Tween.TRANS_BACK: - return "Back" - - Tween.TRANS_SPRING: - return "Spring" - - return "Linear" - - -func _text_to_transition(transition_text: String) -> int: - var transition_lowercase := transition_text.to_lower().trim_prefix("trans").strip_edges() - - match transition_lowercase: - "linear": - return Tween.TRANS_LINEAR - - "sine": - return Tween.TRANS_SINE - - "quint": - return Tween.TRANS_QUINT - - "quart": - return Tween.TRANS_QUART - - "quad": - return Tween.TRANS_QUAD - - "expo": - return Tween.TRANS_EXPO - - "elastic": - return Tween.TRANS_ELASTIC - - "cubic": - return Tween.TRANS_CUBIC - - "circ": - return Tween.TRANS_CIRC - - "bounce": - return Tween.TRANS_BOUNCE - - "back": - return Tween.TRANS_BACK - - "spring": - return Tween.TRANS_SPRING - - return Tween.TRANS_LINEAR - - ## The [param ease_kind] is an integer representing the ease approach ## the [class Tween] will use. func _tween_ease_to_text(ease_kind: int) -> String: @@ -328,11 +247,7 @@ func _text_to_tween_ease(ease_text: String) -> int: func from_text(string: String) -> void: - var regex_str := r'(\w+)\s*=\s*"([^"]*)"|(\w+)' - var regex := RegEx.new() - regex.compile(regex_str) - - for regex_match in regex.search_all(string): + for regex_match in _REGEX_TEXT_TO_VISUAL.search_all(string): var key := regex_match.get_string(1) if key.is_empty(): @@ -378,38 +293,12 @@ func from_text(string: String) -> void: _transition = _text_to_transition(value) as Tween.TransitionType -func string_to_value_type(value: String) -> Variant: - if value.is_valid_int(): - return value.to_int() - - if value.is_valid_float(): - return value.to_float() - - if value.begins_with("("): - var values := value.replace("(", "").replace(")", "").split(",") - var x_value := values[0].strip_edges().to_float() - var y_value := values[1].strip_edges().to_float() - return Vector2(x_value, y_value) - - if value == "true": - return true - - elif value == "false": - return false - - if value.begins_with('"') and value.ends_with('"'): - return value.strip_edges() - - return null - - func get_shortcode() -> String: return "tween" func get_shortcode_parameters() -> Dictionary: return { - #param_name : property_info "property": {"property": "_property", "default": _property}, "character": {"property": "_character", "default": _character_identifier}, "path": {"property": "_node_path", "default": _node_path}, @@ -423,126 +312,12 @@ func get_shortcode_parameters() -> Dictionary: } -# You can alternatively overwrite these 3 functions: to_text(), from_text(), is_valid_event() -#endregion - - -func get_all_character_properties(search_string: String) -> Dictionary: - const VALID_TYPE := [ - TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I - ] - const IGNORE_WORDS := ["process_"] - - var color_rect := DialogicCharacter.new() - var suggestions := {} - var fallback_icon := ["Variant", "EditorIcons"] +func _get_all_character_properties(search_string: String) -> Dictionary: + return _get_all_properties(search_string, TweenTarget.PORTRAIT) - for property_info: Dictionary in color_rect.get_property_list(): - var property_name: String = property_info.get("name") - if not search_string.is_empty() and not property_name.contains(search_string): - continue - - var ignore_property: bool = false - for ignore_term: String in IGNORE_WORDS: - if property_name.begins_with(ignore_term): - ignore_property = true - break - - if ignore_property: - continue - - var property_type: Variant.Type = property_info.get("type") - - if not VALID_TYPE.has(property_type): - continue - - var icon: Variant = fallback_icon - - match property_type: - Variant.Type.TYPE_INT: - icon = ["Number", "EditorIcons"] - Variant.Type.TYPE_FLOAT: - icon = ["Float", "EditorIcons"] - Variant.Type.TYPE_STRING: - icon = ["String", "EditorIcons"] - _: - icon = ["Variant", "EditorIcons"] - - suggestions[property_name] = { - "label": "[b]" + property_name + "[/b]", - "value": property_name, - "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") - } - - return suggestions - - -func get_all_properties(search_string: String) -> Dictionary: - const VALID_TYPE := [ - TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I - ] - const IGNORE_WORDS := ["process_"] - - var color_rect := ColorRect.new() - var suggestions := {} - var fallback_icon := ["Variant", "EditorIcons"] - - for property_info: Dictionary in color_rect.get_property_list(): - var property_name: String = property_info.get("name") - - if not search_string.is_empty() and not property_name.contains(search_string): - continue - - var ignore_property: bool = false - for ignore_term: String in IGNORE_WORDS: - if property_name.begins_with(ignore_term): - ignore_property = true - break - - if ignore_property: - continue - - var property_type: Variant.Type = property_info.get("type") - - if not VALID_TYPE.has(property_type): - continue - - var icon: Variant = fallback_icon - - match property_type: - Variant.Type.TYPE_INT: - icon = ["Number", "EditorIcons"] - Variant.Type.TYPE_FLOAT: - icon = ["Float", "EditorIcons"] - Variant.Type.TYPE_STRING: - icon = ["String", "EditorIcons"] - _: - icon = ["Variant", "EditorIcons"] - - suggestions[property_name] = { - "label": "[b]" + property_name + "[/b]", - "value": property_name, - "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") - } - - return suggestions - - -func get_character_suggestions(search_text: String) -> Dictionary: - var suggestions := {} - #override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work - - var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg") - - suggestions["(No one)"] = {"value": "", "editor_icon": ["GuiRadioUnchecked", "EditorIcons"]} - var character_directory := DialogicResourceUtil.get_character_directory() - - for resource: String in character_directory.keys(): - suggestions[resource] = { - "value": resource, "tooltip": character_directory[resource], "icon": icon.duplicate() - } - return suggestions +func _get_all_background_properties(search_string: String) -> Dictionary: + return _get_all_properties(search_string, TweenTarget.BACKGROUND) # Add a sub property field for all supported vector types. @@ -653,7 +428,7 @@ func _add_property_fields() -> void: { "placeholder": "", "mode": 1, - "suggestions_func": get_all_properties, + "suggestions_func": _get_all_background_properties, #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), "autofocus": false, "left_text": " property ", @@ -667,7 +442,7 @@ func _add_property_fields() -> void: { "placeholder": "", "mode": 1, - "suggestions_func": get_all_character_properties, + "suggestions_func": _get_all_character_properties, #"icon" : load("res://addons/dialogic/Editor/Images/Resources/character.svg"), "autofocus": false, "left_text": " property ", @@ -873,7 +648,6 @@ func _add_target_fields() -> void: #region EDITOR REPRESENTATION -################################################################################ func build_event_editor() -> void: @@ -889,7 +663,111 @@ func build_event_editor() -> void: _add_time_properties() -static func variant_to_value_type(value: Variant.Type) -> ValueType: +#endregion + + +#region UTILITY +func get_character_suggestions(_search_text: String) -> Dictionary: + var suggestions := {} + #override the previous _character_directory with the meta, specifically for searching otherwise new nodes wont work + + var icon := load("res://addons/dialogic/Editor/Images/Resources/character.svg") + + suggestions["(No one)"] = {"value": "", "editor_icon": ["GuiRadioUnchecked", "EditorIcons"]} + var character_directory := DialogicResourceUtil.get_character_directory() + + for resource: String in character_directory.keys(): + suggestions[resource] = { + "value": resource, "tooltip": character_directory[resource], "icon": icon.duplicate() + } + return suggestions + + +func _transition_to_text(transition_kind: int) -> String: + match transition_kind: + Tween.TRANS_LINEAR: + return "Linear" + + Tween.TRANS_SINE: + return "Sine" + + Tween.TRANS_QUINT: + return "Quint" + + Tween.TRANS_QUART: + return "Quart" + + Tween.TRANS_QUAD: + return "Quad" + + Tween.TRANS_EXPO: + return "Expo" + + Tween.TRANS_ELASTIC: + return "Elastic" + + Tween.TRANS_CUBIC: + return "Cubic" + + Tween.TRANS_CIRC: + return "Circ" + + Tween.TRANS_BOUNCE: + return "Bounce" + + Tween.TRANS_BACK: + return "Back" + + Tween.TRANS_SPRING: + return "Spring" + + return "Linear" + + +func _text_to_transition(transition_text: String) -> int: + var transition_lowercase := transition_text.to_lower().trim_prefix("trans").strip_edges() + + match transition_lowercase: + "linear": + return Tween.TRANS_LINEAR + + "sine": + return Tween.TRANS_SINE + + "quint": + return Tween.TRANS_QUINT + + "quart": + return Tween.TRANS_QUART + + "quad": + return Tween.TRANS_QUAD + + "expo": + return Tween.TRANS_EXPO + + "elastic": + return Tween.TRANS_ELASTIC + + "cubic": + return Tween.TRANS_CUBIC + + "circ": + return Tween.TRANS_CIRC + + "bounce": + return Tween.TRANS_BOUNCE + + "back": + return Tween.TRANS_BACK + + "spring": + return Tween.TRANS_SPRING + + return Tween.TRANS_LINEAR + + +func variant_to_value_type(value: Variant.Type) -> ValueType: match value: Variant.Type.TYPE_STRING: return ValueType.SINGLELINE_TEXT @@ -915,4 +793,104 @@ static func variant_to_value_type(value: Variant.Type) -> ValueType: _: return ValueType.CUSTOM + +## Fetches all properties of a common type for the [param target] type. +func _get_all_properties(search_string: String, target: TweenTarget) -> Dictionary: + const VALID_TYPE := [ + TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_VECTOR2, TYPE_VECTOR2I, TYPE_RECT2, TYPE_RECT2I + ] + const IGNORE_WORDS := ["process_"] + + var property_target: Variant = null + + match target: + TweenTarget.PORTRAIT: + property_target = DialogicCharacter.new() + TweenTarget.BACKGROUND: + property_target = ColorRect.new() + TweenTarget.NODE_PATH: + property_target = Node.new() + + var suggestions := {} + var fallback_icon := ["Variant", "EditorIcons"] + + for property_info: Dictionary in property_target.get_property_list(): + var property_name: String = property_info.get("name") + + if not search_string.is_empty() and not property_name.contains(search_string): + continue + + var ignore_property: bool = false + for ignore_term: String in IGNORE_WORDS: + if property_name.begins_with(ignore_term): + ignore_property = true + break + + if ignore_property: + continue + + var property_type: Variant.Type = property_info.get("type") + + if not VALID_TYPE.has(property_type): + continue + + var icon: Variant = fallback_icon + + match property_type: + Variant.Type.TYPE_INT: + icon = ["Number", "EditorIcons"] + Variant.Type.TYPE_FLOAT: + icon = ["Float", "EditorIcons"] + Variant.Type.TYPE_STRING: + icon = ["String", "EditorIcons"] + _: + icon = ["Variant", "EditorIcons"] + + suggestions[property_name] = { + "label": "[b]" + property_name + "[/b]", + "value": property_name, + "icon": load("res://addons/dialogic/Editor/Images/Pieces/variable.svg") + } + + return suggestions + + +## Tries to transform a `String` to a valid primitive type. +## +## This can be used to convert from Timeline Text Mode back to Visual Mode. +## It allows the user to type in values in Text Mode and make them work. +func string_to_value_type(value: String) -> Variant: + if value.is_valid_int(): + return value.to_int() + + if value.is_valid_float(): + return value.to_float() + + if value.begins_with("("): + var values := value.replace("(", "").replace(")", "").split(",", 4) + var x_value := values[0].strip_edges().to_float() + var y_value := values[1].strip_edges().to_float() + + if values.size() == 3: + var z_value := values[2].strip_edges().to_float() + return Vector3(x_value, y_value, z_value) + + elif values.size() == 4: + var z_value := values[2].strip_edges().to_float() + var w_value := values[3].strip_edges().to_float() + return Vector4(x_value, y_value, z_value, w_value) + + return Vector2(x_value, y_value) + + if value == "true": + return true + + elif value == "false": + return false + + if value.begins_with('"') and value.ends_with('"'): + return value.strip_edges() + + return null + #endregion From 2748f5c5dfe0df21be6e04f3fbf7843fc774e73f Mon Sep 17 00:00:00 2001 From: Cake Date: Mon, 30 Sep 2024 12:27:34 +0200 Subject: [PATCH 16/17] Fix matching `path` twice. --- addons/dialogic/Modules/Tween/event_tween.gd | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index 431eebbf6..c40310321 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -264,13 +264,11 @@ func from_text(string: String) -> void: "path": _target = TweenTarget.NODE_PATH + _node_path = value "character": _character_identifier = value - "path": - _node_path = value - "property": _property = value From 4abdf713da9369e2ce01a0cd0cf84893c91d237b Mon Sep 17 00:00:00 2001 From: Cake Date: Mon, 30 Sep 2024 12:32:47 +0200 Subject: [PATCH 17/17] Add Information when failing to tween Value. --- addons/dialogic/Modules/Tween/event_tween.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/dialogic/Modules/Tween/event_tween.gd b/addons/dialogic/Modules/Tween/event_tween.gd index c40310321..247473e5f 100644 --- a/addons/dialogic/Modules/Tween/event_tween.gd +++ b/addons/dialogic/Modules/Tween/event_tween.gd @@ -133,7 +133,7 @@ func _execute() -> void: var tweener := tween.tween_property(target_node, full_property_path, _value, _time) if tweener == null: - printerr("[Dialogic] Tween Event failed to create Tween, aborting.") + printerr("[Dialogic] Tween Event failed to create Tween, aborting. Check if property " + full_property_path + " matches type of the value " + _value) finish() return