Плагины инспектора

Панель инспектора позволяет создавать пользовательские виджеты для редактирования свойств с помощью плагинов. Это может быть полезно при работе с пользовательскими типами данных и ресурсами, хотя вы также можете использовать эту функцию для изменения виджетов инспектора для встроенных типов. Вы можете создавать пользовательские элементы управления для конкретных свойств, целых объектов и даже отдельные элементы управления, связанные с определёнными типами данных.

В этом руководстве объясняется, как использовать классы EditorInspectorPlugin и EditorProperty для создания пользовательского интерфейса для целых чисел, заменяя поведение по умолчанию кнопкой, которая генерирует случайные значения от 0 до 99.

../../../_images/inspector_plugin_example.png

Поведение по умолчанию слева и конечный результат справа.

Настройка вашего плагина

Чтобы начать, создайте новый пустой плагин.

См. также

Инструкции по настройке нового плагина см. в руководстве Создание плагинов.

Предположим, вы назвали папку плагина my_inspector_plugin. В этом случае у вас должна появиться новая папка addons/my_inspector_plugin, содержащая два файла: plugin.cfg и plugin.gd.

Как и прежде, plugin.gd — это скрипт, расширяющий EditorPlugin, и вам необходимо добавить новый код для его методов _enter_tree и _exit_tree. Чтобы настроить плагин-инспектор, необходимо загрузить его скрипт, а затем создать и добавить экземпляр, вызвав add_inspector_plugin(). Если плагин отключён, необходимо удалить добавленный экземпляр, вызвав remove_inspector_plugin().

Примечание

Здесь вы загружаете скрипт, а не упакованную сцену. Поэтому следует использовать new() вместо instantiate().

# plugin.gd
@tool
extends EditorPlugin

var plugin


func _enter_tree():
    plugin = preload("res://addons/my_inspector_plugin/my_inspector_plugin.gd").new()
    add_inspector_plugin(plugin)


func _exit_tree():
    remove_inspector_plugin(plugin)

Взаимодействие с инспектором

Для взаимодействия с панелью инспектора ваш скрипт my_inspector_plugin.gd должен расширять класс EditorInspectorPlugin. Этот класс предоставляет несколько виртуальных методов, влияющих на обработку свойств инспектором.

Чтобы скрипт хоть как-то действовал, он должен реализовывать метод _can_handle(). Эта функция вызывается для каждого отредактированного объекта Object и должна возвращать true, если плагин должен обрабатывать объект или его свойства.

Примечание

Это включает в себя любой Resource, прикрепленный к объекту.

Вы можете реализовать четыре других метода для добавления элементов управления в инспектор в определённых позициях. Методы _parse_begin() и _parse_end() вызываются только один раз в начале и в конце разбора каждого объекта соответственно. Они позволяют добавлять элементы управления в верхнюю или нижнюю часть макета инспектора, вызывая add_custom_control().

При разборе объекта редактор вызывает методы _parse_category() и _parse_property(). Помимо add_custom_control(), здесь можно вызывать add_property_editor() и add_property_editor_for_multiple_properties(). Используйте эти два последних метода для добавления элементов управления на основе EditorProperty.

# my_inspector_plugin.gd
extends EditorInspectorPlugin

var RandomIntEditor = preload("res://addons/my_inspector_plugin/random_int_editor.gd")


func _can_handle(object):
    # We support all objects in this example.
    return true


func _parse_property(object, type, name, hint_type, hint_string, usage_flags, wide):
    # We handle properties of type integer.
    if type == TYPE_INT:
        # Create an instance of the custom property editor and register
        # it to a specific property path.
        add_property_editor(name, RandomIntEditor.new())
        # Inform the editor to remove the default property editor for
        # this property type.
        return true
    else:
        return false

Добавление интерфейса для редактирования свойств

Класс EditorProperty — это особый тип Control, который может взаимодействовать с редактируемыми объектами в доке инспектора. Он ничего не отображает, но может содержать любые другие элементы управления, включая сложные сцены.

Скрипт, расширяющий EditorProperty, состоит из трех основных частей:

  1. Для настройки структуры узлов управления необходимо определить метод _init().

  2. Вам следует реализовать _update_property() для обработки изменений данных извне.

  3. В какой-то момент должен быть выдан сигнал, информирующий инспектора о том, что элемент управления изменил свойство с помощью emit_changed.

Вы можете отобразить свой виджет двумя способами. Используйте только метод add_child() по умолчанию, чтобы отобразить его справа от имени свойства, и используйте add_child(), а затем set_bottom_editor(), чтобы разместить его под именем.

# random_int_editor.gd
extends EditorProperty


# The main control for editing the property.
var property_control = Button.new()
# An internal value of the property.
var current_value = 0
# A guard against internal changes when the property is updated.
var updating = false


func _init():
    # Add the control as a direct child of EditorProperty node.
    add_child(property_control)
    # Make sure the control is able to retain the focus.
    add_focusable(property_control)
    # Setup the initial state and connect to the signal to track changes.
    refresh_control_text()
    property_control.pressed.connect(_on_button_pressed)


func _on_button_pressed():
    # Ignore the signal if the property is currently being updated.
    if (updating):
        return

    # Generate a new random integer between 0 and 99.
    current_value = randi() % 100
    refresh_control_text()
    emit_changed(get_edited_property(), current_value)


func _update_property():
    # 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
    refresh_control_text()
    updating = false

func refresh_control_text():
    property_control.text = "Value: " + str(current_value)

Используя приведенный выше пример кода, вы сможете создать пользовательский виджет, который заменит элемент управления по умолчанию SpinBox для целых чисел на Button, который генерирует случайные значения.