From e724a97480b4ccea90f208b3882492c71d34bf08 Mon Sep 17 00:00:00 2001 From: Jowan <42868150+Jowan-Spooner@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:22:16 +0200 Subject: [PATCH] UI/UX: Allow Inspector Field for timelines (#2371) This now shows a proper selection tool for timelines (a dynamic field like in the timelines) when doing `@export var tml: DialogicTimeline` --- .../Events/Fields/field_options_dynamic.gd | 5 +- .../Editor/Inspector/inspector_plugin.gd | 15 ++++ .../Inspector/timeline_inspector_field.gd | 82 +++++++++++++++++++ addons/dialogic/plugin.gd | 7 +- 4 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 addons/dialogic/Editor/Inspector/inspector_plugin.gd create mode 100644 addons/dialogic/Editor/Inspector/timeline_inspector_field.gd diff --git a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd index 7ca7391f7..16a315f14 100644 --- a/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd +++ b/addons/dialogic/Editor/Events/Fields/field_options_dynamic.gd @@ -76,7 +76,10 @@ func _autofocus() -> void: ################################################################################ func _ready() -> void: - %Focus.add_theme_stylebox_override('panel', get_theme_stylebox('focus', 'DialogicEventEdit')) + var focus := get_theme_stylebox("focus", "LineEdit") + if has_theme_stylebox("focus", "DialogicEventEdit"): + focus = get_theme_stylebox('focus', 'DialogicEventEdit') + %Focus.add_theme_stylebox_override('panel', focus) %Search.text_changed.connect(_on_Search_text_changed) %Search.text_submitted.connect(_on_Search_text_entered) diff --git a/addons/dialogic/Editor/Inspector/inspector_plugin.gd b/addons/dialogic/Editor/Inspector/inspector_plugin.gd new file mode 100644 index 000000000..0a40bc388 --- /dev/null +++ b/addons/dialogic/Editor/Inspector/inspector_plugin.gd @@ -0,0 +1,15 @@ +@tool +extends EditorInspectorPlugin + + +func _can_handle(object: Object) -> bool: + return true + + +func _parse_property(object: Object, type: Variant.Type, name: String, hint_type: PropertyHint, hint_string: String, usage_flags: int, wide: bool) -> bool: + if type == TYPE_OBJECT and hint_type == PROPERTY_HINT_RESOURCE_TYPE: + if hint_string == "DialogicTimeline": + var editor: EditorProperty = load("res://addons/dialogic/Editor/Inspector/timeline_inspector_field.gd").new() + add_property_editor(name, editor) + return true + return false diff --git a/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd new file mode 100644 index 000000000..6e617fead --- /dev/null +++ b/addons/dialogic/Editor/Inspector/timeline_inspector_field.gd @@ -0,0 +1,82 @@ +@tool +extends EditorProperty + +var field: Control = null +var button: Button = null +# An internal value of the property. +var current_value: DialogicTimeline = null +# A guard against internal changes when the property is updated. +var updating = false + + +func _init() -> void: + var hbox := HBoxContainer.new() + add_child(hbox) + + field = load("res://addons/dialogic/Editor/Events/Fields/field_options_dynamic.tscn").instantiate() + hbox.add_child(field) + field.placeholder_text = "No Timeline" + field.size_flags_horizontal = Control.SIZE_EXPAND_FILL + field.size_flags_vertical = Control.SIZE_SHRINK_CENTER + field.mode = field.Modes.IDENTIFIER + field.fit_text_length = false + field.valid_file_drop_extension = ".dtl" + field.value_changed.connect(_on_field_value_changed) + field.get_suggestions_func = get_timeline_suggestions + + button = Button.new() + hbox.add_child(button) + button.hide() + button.pressed.connect(_on_button_pressed, CONNECT_DEFERRED) + + +func _on_field_value_changed(property:String, value:Variant) -> void: + # Ignore the signal if the property is currently being updated. + if updating: + return + + var new_value: DialogicTimeline = null + if value: + new_value = DialogicResourceUtil.get_timeline_resource(value) + + if current_value != new_value: + current_value = new_value + if current_value: + button.show() + else: + button.hide() + emit_changed(get_edited_property(), current_value) + + +func _update_property() -> void: + field.resource_icon = get_theme_icon("TripleBar", "EditorIcons") + button.icon = get_theme_icon("ExternalLink", "EditorIcons") + + # Read the current value from the property. + var new_value = get_edited_object()[get_edited_property()] + if (new_value == current_value): + return + + # Update the control with the new value. + updating = true + current_value = new_value + if current_value: + field.set_value(DialogicResourceUtil.get_unique_identifier(current_value.resource_path)) + button.show() + else: + button.hide() + field.set_value("") + updating = false + + +func get_timeline_suggestions(filter:String) -> Dictionary: + var suggestions := {} + var timeline_directory := DialogicResourceUtil.get_timeline_directory() + for identifier in timeline_directory.keys(): + suggestions[identifier] = {'value': identifier, 'tooltip':timeline_directory[identifier], 'editor_icon': ["TripleBar", "EditorIcons"]} + return suggestions + + +func _on_button_pressed() -> void: + if current_value: + EditorInterface.edit_resource(current_value) diff --git a/addons/dialogic/plugin.gd b/addons/dialogic/plugin.gd index 4b7549eab..cb0089acb 100644 --- a/addons/dialogic/plugin.gd +++ b/addons/dialogic/plugin.gd @@ -9,7 +9,7 @@ const PLUGIN_ICON_PATH := "res://addons/dialogic/Editor/Images/plugin-icon.svg" ## References used by various other scripts to quickly reference these things var editor_view: Control # the root of the dialogic editor - +var inspector_plugin: EditorInspectorPlugin = null ## Initialization func _init() -> void: @@ -36,6 +36,9 @@ func _enter_tree() -> void: get_editor_interface().get_editor_main_screen().add_child(editor_view) _make_visible(false) + inspector_plugin = load("res://addons/dialogic/Editor/Inspector/inspector_plugin.gd").new() + add_inspector_plugin(inspector_plugin) + # Auto-update the singleton path for alpha users # TODO remove at some point during beta or later if not "Core" in ProjectSettings.get_setting("autoload/"+PLUGIN_NAME, ""): @@ -48,6 +51,8 @@ func _exit_tree() -> void: remove_control_from_bottom_panel(editor_view) editor_view.queue_free() + if inspector_plugin: + remove_inspector_plugin(inspector_plugin) #endregion