Les greffons de l'inspecteur

Le dock de l'inspecteur vous permet de créer des widgets personnalisés pour modifier les propriétés par le biais de plugins. Cela peut être utile lorsque vous travaillez avec des types de données et des ressources personnalisés, bien que vous puissiez utiliser cette fonctionnalité pour modifier les widgets de l'inspecteur pour les types intégrés. Vous pouvez concevoir des contrôles personnalisés pour des propriétés spécifiques, des objets entiers, et même des contrôles séparés associés à des types de données particuliers.

Ce guide explique comment utiliser les classes EditorInspectorPlugin et EditorProperty pour créer une interface personnalisée pour les entiers, en remplaçant le comportement par défaut par un bouton qui génère des valeurs aléatoires entre 0 et 99.

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

Le comportement par défaut à gauche et le résultat final à droite.

Configuration de votre plugin

Créez un greffon vide pour démarrer.

Voir aussi

Consultez le guide Création de plugins pour configurer votre nouveau plugin.

Supposons que vous ayez appelé votre dossier de plugins my_inspector_plugin. Si c'est le cas, vous devriez vous retrouver avec un nouveau dossier addons/my_inspector_plugin qui contient deux fichiers : plugin.cfg et plugin.gd.

Comme précédemment, plugin.gd est un script étendant EditorPlugin et vous devez introduire du nouveau code pour ses méthodes _enter_tree et _exit_tree. Pour configurer votre plugin d'inspecteur, vous devez charger son script, puis créer et ajouter l'instance en appelant add_inspector_plugin(). Si le plugin est désactivé, vous devez supprimer l'instance que vous avez ajoutée en appelant remove_inspector_plugin().

Note

Ici, vous chargez un script et non une scène packagée. C'est pourquoi vous devez utiliser new() au lieu de instance().

# plugin.gd
tool
extends EditorPlugin

var plugin


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


func _exit_tree():
    remove_inspector_plugin(plugin)

Interagir avec l'inspecteur

Pour interagir avec le dock de l'inspecteur, votre script MyInspectorPlugin.gd doit étendre la classe EditorInspectorPlugin. Cette classe fournit plusieurs méthodes virtuelles qui affectent la façon dont l'inspecteur gère les propriétés.

Pour avoir un quelconque effet, le script doit implémenter la méthode can_handle(). Cette fonction est appelée pour chaque Object édité et doit retourner true si ce plugin doit gérer l'objet ou ses propriétés.

Note

Cela inclus tous les Resource attachés à un objet.

Vous pouvez implémenter quatre autres méthodes pour ajouter des contrôles à l'inspecteur à des positions spécifiques. Les méthodes parse_begin() et parse_end() ne sont appelées qu'une seule fois, respectivement au début et à la fin de l'analyse de chaque objet. Ils peuvent ajouter des contrôles en haut ou en bas de la disposition de l'inspecteur en appelant add_custom_control().

Lorsque l'éditeur analyse l'objet, il appelle les méthodes parse_category() et parse_property(). Là, en plus de addd_custom_control(), vous pouvez appeler à la fois addd_property_editor() et addd_property_editor_for_multiple_properties(). Utilisez ces deux dernières méthodes pour ajouter spécifiquement des contrôles basés sur class_EditorProperty`.

# MyInspectorPlugin.gd
extends EditorInspectorPlugin

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


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


func parse_property(object, type, path, hint, hint_text, usage):
    # 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(path, RandomIntEditor.new())
        # Inform the editor to remove the default property editor for
        # this property type.
        return true
    else:
        return false

Ajouter une interface pour modifier les propriétés

La classe EditorProperty est un type spécial de Control qui peut interagir avec les objets édités du dock de l'inspecteur. Elle n'affiche rien mais peut accueillir n'importe quel autre nœud de contrôle, y compris des scènes complexes.

Il y a principalement trois parties dans un script héritant de EditorProperty :

  1. Vous devez définir la méthode _init() pour mettre en place la structure des nœuds de contrôle.

  2. Vous devez implémenter la fonction update_property() pour gérer les modifications des données depuis l'extérieur.

  3. Un signal doit être émis à un moment donné pour informer l'inspecteur que le contrôle a modifié la propriété en utilisant emit_changed.

Vous pouvez afficher votre widget personnalisé de deux façons. Utilisez simplement la méthode par défaut add_child() pour l'afficher à droite du nom de la propriété, et utilisez add_child() suivi de set_bottom_editor() pour le positionner sous le nom.

# RandomIntEditor.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.connect("pressed", self, "_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)

En utilisant le code d'exemple ci-dessus, vous devriez être en mesure de créer un widget personnalisé qui remplace le contrôle par défaut SpinBox pour les nombres entiers par un Button qui génère des valeurs aléatoires.