Up to date
This page is up to date for Godot 4.2
.
If you still find outdated information, please open an issue.
Inspektor-Plugins¶
Das Inspektor-Dock ermöglicht es Ihnen, benutzerdefinierte Widgets zu erstellen, um Propertys über Plugins zu bearbeiten. Dies kann bei der Arbeit mit benutzerdefinierten Datentypen und Ressourcen von Vorteil sein, obwohl Sie die Funktion auch verwenden können, um die Inspektor-Widgets für Built-in-Typen zu ändern. Sie können benutzerdefinierte Steuerelemente für bestimmte Eigenschaften, ganze Objekte und sogar separate Controls in Verbindung mit bestimmten Datentypen erstellen.
Diese Anleitung erklärt, wie man die Klassen EditorInspectorPlugin und EditorProperty verwendet, um eine benutzerdefinierte Schnittstelle für Integer-Zahlen zu erstellen, die das Default-Verhalten durch einen Button ersetzt, die zufällige Werte zwischen 0 und 99 erzeugt.
Einrichten Ihres Plugins¶
Erstellen Sie ein neues leeres Plugin, um loszulegen.
Siehe auch
Siehe die Erstellen von Plugins-Anleitung, um Ihr neues Plugin einzurichten.
Nehmen wir an, Sie haben Ihren Plugin-Ordner my_inspector_plugin
genannt. Wenn dies der Fall ist, sollten Sie einen neuen Ordner addons/my_inspector_plugin
haben, der zwei Dateien enthält: plugin.cfg
und plugin.gd
.
Wie zuvor ist plugin.gd
ein Skript, das EditorPlugin erweitert, und Sie müssen neuen Code für seine Methoden _enter_tree
und _exit_tree
einführen. Um Ihr Inspektor-Plugin einzurichten, müssen Sie sein Skript laden, dann die Instanz erzeugen und hinzufügen, indem Sie add_inspector_plugin()
aufrufen. Wenn das Plugin deaktiviert ist, sollten Sie die hinzugefügte Instanz durch den Aufruf von remove_inspector_plugin()
entfernen.
Bemerkung
Hier laden Sie ein Skript und nicht eine gepackte Szene. Daher sollten Sie new()
anstelle von instance()
verwenden.
# 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
Interaktion mit dem Inspektor¶
Um mit dem Inspektor-Dock zu interagieren, muss Ihr Skript my_inspector_plugin.gd
die Klasse EditorInspectorPlugin erweitern. Diese Klasse bietet mehrere virtuelle Methoden, die beeinflussen, wie der Inspektor mit Propertys umgeht.
Um überhaupt einen Effekt zu haben, muss das Skript die Methode _can_handle()
implementieren. Diese Funktion wird für jedes bearbeitete Object aufgerufen und muss true
zurückgeben, wenn dieses Plugin das Objekt oder seine Propertys behandeln soll.
Bemerkung
Dies schließt jede Resource ein, die mit dem Objekt verbunden ist.
Sie können vier weitere Methoden implementieren, um dem Inspektor an bestimmten Positionen Controls hinzuzufügen. Die Methoden parse_begin()
und parse_end()
werden nur einmal am Anfang bzw. am Ende des Parsens für jedes Objekt aufgerufen. Sie können Controls am oberen oder unteren Rand des Inspektor-Layouts hinzufügen, indem sie add_custom_control()
aufrufen.
Wenn der Editor das Objekt analysiert, ruft er die Methoden parse_category()
und _parse_property()
auf. Dort können Sie, zusätzlich zu add_custom_control()
, sowohl add_property_editor()
als auch add_property_editor_for_multiple_properties()
aufrufen. Benutzen Sie diese letzten beiden Methoden, um speziell EditorProperty-basierte Controls hinzuzufügen.
# 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
Hinzufügen einer Schnittstelle zum Bearbeiten von Propertys¶
Die Klasse EditorProperty ist ein spezieller Typ von Control, der mit den bearbeiteten Objekten des Inspektor-Docks interagieren kann. Sie zeigt nichts an, kann aber alle anderen Nodes beherbergen, einschließlich komplexer Szenen.
Das Skript besteht aus drei wesentlichen Teilen, die EditorProperty erweitern:
Sie müssen die Methode
_init()
definieren, um die Struktur der Control-Nodes einzurichten.Sie sollten die Funktion
_update_property()
implementieren, um Änderungen an den Daten von außen zu behandeln.Irgendwann muss ein Signal ausgegeben werden, um den Inspektor darüber zu informieren, daß das Control die Property mit
emit_changed
geändert hat.
Sie können Ihr eigenes Widget auf zwei Arten darstellen. Verwenden Sie einfach die Default-Methode add_child()
, um es rechts vom Namen der Property anzuzeigen, oder verwenden Sie add_child()
gefolgt von set_bottom_editor()
, um es unterhalb des Namens zu positionieren.
# 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
Mit dem obigen Beispielcode sollten Sie in der Lage sein, ein benutzerdefiniertes Widget zu erstellen, um das Default-Control SpinBox für Integer-Zahlen durch einen Button zu ersetzen, der Zufallswerte generiert.