Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
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.
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/my_inspector_plugin.gd").new()
add_inspector_plugin(plugin)
func _exit_tree():
remove_inspector_plugin(plugin)
// Plugin.cs
#if TOOLS
using Godot;
[Tool]
public partial 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¶
To interact with the inspector dock, your my_inspector_plugin.gd
script must
extend the EditorInspectorPlugin class. This class provides several
virtual methods that affect how the inspector handles properties.
To have any effect at all, the script must implement the _can_handle()
method. This function is called for each edited Object and must
return true
if this plugin should handle the object or its properties.
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()
.
As the editor parses the object, it calls the parse_category()
and
_parse_property()
methods. There, in addition to add_custom_control()
,
you can call both add_property_editor()
and
add_property_editor_for_multiple_properties()
. Use these last two methods to
specifically add EditorProperty-based controls.
# 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
// MyInspectorPlugin.cs
#if TOOLS
using Godot;
public partial class MyInspectorPlugin : EditorInspectorPlugin
{
public override bool _CanHandle(GodotObject @object)
{
// We support all objects in this example.
return true;
}
public override bool _ParseProperty(GodotObject @object, Variant.Type type,
string name, PropertyHint hintType, string hintString,
PropertyUsageFlags usageFlags, bool wide)
{
// We handle properties of type integer.
if (type == Variant.Type.Int)
{
// Create an instance of the custom property editor and register
// it to a specific property path.
AddPropertyEditor(name, 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.You should implement the
_update_property()
to handle changes to the data from the outside.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.
# 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)
// RandomIntEditor.cs
#if TOOLS
using Godot;
public partial 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.Pressed += 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.