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.

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)
// Plugin.cs
#if TOOLS
using Godot;
[Tool]
public class Plugin : EditorPlugin
{
private MyInspectorPlugin _plugin;
public override void _EnterTree()
{
_plugin = new MyInspectorPlugin();
AddInspectorPlugin(_plugin);
}
public override void _ExitTree()
{
RemoveInspectorPlugin(_plugin);
}
}
#endif
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
// MyInspectorPlugin.cs
#if TOOLS
using Godot;
[Tool]
public class MyInspectorPlugin : EditorInspectorPlugin
{
public override bool CanHandle(Object @object)
{
// We support all objects in this example.
return true;
}
public override bool ParseProperty(Object @object, int type, string path, int hint, string hintText, int usage)
{
// We handle properties of type integer.
if (type == (int)Variant.Type.Int)
{
// Create an instance of the custom property editor and register
// it to a specific property path.
AddPropertyEditor(path, new RandomIntEditor());
// Inform the editor to remove the default property editor for
// this property type.
return true;
}
return false;
}
}
#endif
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 :
Vous devez définir la méthode
_init()
pour mettre en place la structure des nœuds de contrôle.Vous devez implémenter la fonction
update_property()
pour gérer les modifications des données depuis l'extérieur.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)
// RandomIntEditor.cs
#if TOOLS
using Godot;
[Tool]
public class RandomIntEditor : EditorProperty
{
// The main control for editing the property.
private Button _propertyControl = new Button();
// An internal value of the property.
private int _currentValue = 0;
// A guard against internal changes when the property is updated.
private bool _updating = false;
public RandomIntEditor()
{
// Add the control as a direct child of EditorProperty node.
AddChild(_propertyControl);
// Make sure the control is able to retain the focus.
AddFocusable(_propertyControl);
// Setup the initial state and connect to the signal to track changes.
RefreshControlText();
_propertyControl.Connect("pressed", this, nameof(OnButtonPressed));
}
private void OnButtonPressed()
{
// Ignore the signal if the property is currently being updated.
if (_updating)
{
return;
}
// Generate a new random integer between 0 and 99.
_currentValue = (int)GD.Randi() % 100;
RefreshControlText();
EmitChanged(GetEditedProperty(), _currentValue);
}
public override void UpdateProperty()
{
// Read the current value from the property.
var newValue = (int)GetEditedObject().Get(GetEditedProperty());
if (newValue == _currentValue)
{
return;
}
// Update the control with the new value.
_updating = true;
_currentValue = newValue;
RefreshControlText();
_updating = false;
}
private void RefreshControlText()
{
_propertyControl.Text = $"Value: {_currentValue}";
}
}
#endif
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.