Objekt Klasse

Siehe auch

Diese Seite beschreibt die C++ - Implementierung von Objekten in Godot. Suchen Sie nach der Objektklassenreferenz? Have a look here.

Allgemeine Definition

Object ist die Basisklasse für fast alles. Die meisten Klassen in Godot erben direkt oder indirekt davon. Objekte bieten Reflexions- und bearbeitbare Eigenschaften, und für deren Deklaration muss ein einziges Makro wie dieses verwendet werden.

class CustomObject : public Object {

    GDCLASS(CustomObject, Object); // this is required to inherit
};

Dadurch erhalten Objekte viele Funktionen, wie zum Beispiel

obj = memnew(CustomObject);
print_line("Object class: ", obj->get_class()); // print object class

obj2 = Object::cast_to<OtherClass>(obj); // converting between classes, this also works without RTTI enabled.

Referenzen:

Ein Objekt registrieren

ClassDB ist eine statische Klasse, welche die gesamte Liste der von Object geerbten registrierten Klassen sowie dynamische Bindungen an alle Methodeneigenschaften und Ganzzahlkonstanten enthält.

Klassen werden registriert durch Aufruf:

ClassDB::register_class<MyCustomClass>()

Durch die Registrierung kann die Klasse durch Skripte, Code instanziiert oder beim Deserialisieren erneut erstellt werden.

Die Registrierung als virtuell ist die gleiche, aber sie kann nicht instanziert werden.

ClassDB::register_virtual_class<MyCustomClass>()

Von Objekten abgeleitete Klassen können die statische Funktion static void _bind_methods() überschreiben. Wenn eine Klasse registriert ist, wird diese statische Funktion aufgerufen, um alle Objektmethoden, Eigenschaften, Konstanten usw. zu registrieren. Sie wird nur einmal aufgerufen. Wenn eine von Object abgeleitete Klasse instanziiert, aber nicht registriert wurde, wird sie automatisch als virtuell registriert.

In _bind_methods gibt es ein paar Dinge, die getan werden können. Das Registrieren von Funktionen ist eine:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomMethod);

Standardwerte für Argumente können in umgekehrter Reihenfolge übergeben werden:

ClassDB::bind_method(D_METHOD("methodname", "arg1name", "arg2name"), &MyCustomType::method, DEFVAL(-1)); // default value for arg2name

D_METHOD ist ein Makro, das "Methodenname" zur Steigerung der Effizienz in einen StringName konvertiert. Argumentnamen werden zur Selbstbeobachtung verwendet, aber beim Kompilieren bei der Veröffentlichung werden sie vom Makro ignoriert, sodass die Zeichenfolgen nicht verwendet und nicht optimiert werden.

Weitere Beispiele finden Sie unter _bind_methods von Control oder Objekt.

Wenn nur Module und Funktionen hinzugefügt werden, von denen nicht erwartet wird, dass sie so gründlich dokumentiert werden, kann das Makro D_METHOD() ignoriert und eine Zeichenfolge, die den Namen übergibt, kann der Kürze halber übergeben werden.

Referenzen:

Konstanten

Klassen haben oft Aufzählungen wie:

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

Damit diese beim Binden an Methoden funktionieren, muss die Aufzählung als in int konvertierbar deklariert werden. Dazu wird ein Makro bereitgestellt:

VARIANT_ENUM_CAST(MyClass::SomeMode); // now functions that take SomeMode can be bound.

Die Konstanten können auch innerhalb von _bind_methods gebunden werden, indem Sie Folgendes verwenden:

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

Eigenschaften (set/get)

Objekte exportieren Eigenschaften, Eigenschaften sind für Folgendes nützlich:

  • Serialisierung und Deserialisierung des Objekts.

  • Erstellen einer Liste editierbarer Werte für die vom Objekt abgeleitete Klasse.

Eigenschaften werden normalerweise durch die Klasse PropertyInfo() definiert. Normalerweise konstruiert als:

PropertyInfo(type, name, hint, hint_string, usage_flags)

Zum Beispiel:

PropertyInfo(Variant::INT, "amount", PROPERTY_HINT_RANGE, "0,49,1", PROPERTY_USAGE_EDITOR)

Dies ist eine Ganzzahl-Eigenschaft mit dem Namen "amount". Der Hinweis ist ein Bereich. Der Bereich reicht von 0 bis 49 in Schritten von 1 (Ganzzahlen). Es kann nur für den Editor verwendet werden (Wert visuell bearbeiten), wird jedoch nicht serialisiert.

ein weiteres Beispiel:

PropertyInfo(Variant::STRING, "modes", PROPERTY_HINT_ENUM, "Enabled,Disabled,Turbo")

Dies ist eine Zeichenfolgeeigenschaft, die eine beliebige Zeichenfolge annehmen kann, der Editor jedoch nur die definierten Hinweiszeichen zulässt. Da keine Verwendungsflags angegeben wurden, sind die Standardflags PROPERTY_USAGE_STORAGE und PROPERTY_USAGE_EDITOR.

In object.h sind viele Hinweise und Verwendungsflags verfügbar. Überprüfen Sie sie.

Eigenschaften können auch wie C# -Eigenschaften funktionieren und über das Index mithilfe der Indizierung aufgerufen werden. Von dieser Verwendung wird jedoch im Allgemeinen abgeraten, da die Verwendung von Funktionen aus Gründen der Lesbarkeit bevorzugt wird. Viele Eigenschaften sind auch an Kategorien gebunden, z. B. "Animation/Frame", die eine Indizierung nur mit dem Operator [] unmöglich machen.

Aus _bind_methods() können Eigenschaften erstellt und gebunden werden, solange set/get-Funktionen vorhanden sind. Beispiel:

ADD_PROPERTY(PropertyInfo(Variant::INT, "amount"), "set_amount", "get_amount")

Dadurch wird die Eigenschaft mit Hilfe des Setters und des Getters erstellt.

Bindung von Eigenschaften mit _set/_get/_get_property_list

Ein zusätzliches Verfahren zum Erstellen von Eigenschaften besteht, wenn mehr Flexibilität gewünscht wird (d.H. Hinzufügen oder Entfernen von Eigenschaften im Kontext).

Die folgenden Funktionen können in einer von Object abgeleiteten Klasse überschrieben werden. Sie sind NICHT virtuell. Machen Sie sie NICHT virtuell. Sie werden bei jeder Überschreibung aufgerufen und die vorherigen Funktionen werden nicht ungültig gemacht (mehrstufiger Aufruf).

protected:
     void _get_property_list(List<PropertyInfo> *r_props) const;      // return list of properties
     bool _get(const StringName &p_property, Variant &r_value) const; // return true if property was found
     bool _set(const StringName &p_property, const Variant &p_value); // return true if property was found

Dies ist auch etwas weniger effizient, da p_property mit den gewünschten Namen in serieller Reihenfolge verglichen werden muss.

dynamisches Casting

Godot bietet zum Beispiel dynamisches Casting zwischen von Objekten abgeleiteten Klassen:

void somefunc(Object *some_obj) {

     Button *button = Object::cast_to<Button>(some_obj);
}

Wenn die Umwandlung fehlschlägt, wird NULL zurückgegeben. Dieses System verwendet RTTI, funktioniert aber auch einwandfrei (wenn auch etwas langsamer), wenn RTTI deaktiviert ist. Dies ist nützlich auf Plattformen, auf denen eine kleine Binärgröße ideal ist, z. B. HTML5 oder Konsolen (mit geringem Speicher).

Signale

Für Objekte kann eine Reihe von Signalen definiert werden (ähnlich wie bei Delegierten in anderen Sprachen). Die Verbindung zu ihnen ist ziemlich einfach:

obj->connect(<signal>, target_instance, target_method)
// for example:
obj->connect("enter_tree", this, "_node_entered_tree")

Die Methode _node_entered_tree muss bei der Klasse mit ClassDB::bind_method registriert werden (siehe oben).

Das Hinzufügen von Signalen zu einer Klasse erfolgt in _bind_methods, z.B. mit dem Makro ADD_SIGNAL:

ADD_SIGNAL(MethodInfo("been_killed"))

Referenzen

Referenz erbt von Object und enthält einen Referenzzähler. Es ist die Basis für referenzgezählte Objekttypen. Die Deklaration muss mit dem Ref<> Template erfolgen. Zum Beispiel:

class MyReference: public Reference {
    GDCLASS(MyReference, Reference);
};

Ref<MyReference> myref(memnew(MyReference));

myref wird als Referenz gezählt. Es wird freigegeben, wenn keine Ref<> Templates mehr darauf verweisen.

Referenzen:

Ressourcen:

Resource erbt von Reference, sodass alle Ressourcen als Referenz gezählt werden. Ressourcen können optional einen Pfad enthalten, der auf eine Datei auf der Festplatte verweist. Dies kann mit resource.set_path(path) eingestellt werden. Dies wird normalerweise vom Ressourcenlader durchgeführt. Keine zwei verschiedenen Ressourcen können denselben Pfad haben. Wenn Sie dies versuchen, wird ein Fehler angezeigt.

Ressourcen ohne Pfad sind ebenfalls in Ordnung.

Referenzen:

Ressourcen laden

Ressourcen können mit der ResourceLoader-API wie folgt geladen werden:

Ref<Resource> res = ResourceLoader::load("res://someresource.res")

Wenn zuvor ein Verweis auf diese Ressource geladen wurde und sich im Speicher befindet, gibt der Ressourcenlader diesen Verweis zurück. Dies bedeutet, dass nur eine Ressource gleichzeitig aus einer Datei geladen werden kann, auf die auf der Festplatte verwiesen wird.

  • resourceinteractiveloader (TODO)

Ressourcen speichern

Das Speichern einer Ressource kann mit der RessourcenSpeicher-API erfolgen:

ResourceSaver::save("res://someresource.res", instance)

Instance will be saved. Sub resources that have a path to a file will be saved as a reference to that resource. Sub resources without a path will be bundled with the saved resource and assigned sub-IDs, like res://someresource.res::1. This also helps to cache them when loaded.