Classe Object

Voir aussi

This page describes the C++ implementation of objects in Godot. Looking for the Object class reference? Have a look here.

Définition générale

Object est la classe de base pour presque tout. La plupart des classes de Godot en héritent directement ou indirectement. Les Objects fournissent des propriétés de réflexion et d'édition, et les déclarer est une question d'utilisation d'une seule macro comme celle-ci.

class CustomObject : public Object {

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

Cela permet aux Objects d'acquérir de nombreuses fonctionnalités, comme par exemple

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.

Références :

Déclarer un Object

ClassDB est une classe statique qui contient la liste complète des classes déclarées qui héritent d'Object, ainsi que des liens dynamiques vers toutes les propriétés de leurs méthodes et constantes entières.

Les classes sont déclarées en appelant :

ClassDB::register_class<MyCustomClass>()

La déclarer permettra à la classe d'être instanciée par des scripts, du code, ou de les recréer lors de la désérialisation.

Déclarer comme virtuelle est la même chose, mais elle ne peut pas être instancié.

ClassDB::register_virtual_class<MyCustomClass>()

Les classes dérivées d'Object peuvent surcharger la fonction statique static void _bind_methods(). Lorsqu'une classe est déclarée, cette fonction statique est appelée pour déclarer toutes les méthodes, propriétés, constantes, etc. de l'Object. Elle n'est appelée qu'une seule fois. Si une classe dérivée d'un Object est instanciée mais n'a pas été déclarée, elle sera automatiquement déclarée comme virtuelle.

A l'intérieur de bind_methods, il y a deux ou trois choses qui peuvent être faites. La déclaration des fonctions en est une :

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

Les valeurs par défaut des arguments peuvent être transmises dans l'ordre inverse :

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

D_METHOD est une macro qui convertit le "methodname" en un StringName pour plus d'efficacité. Les noms d'arguments sont utilisés pour l'introspection, mais lors de la compilation de version release, la macro les ignore, de sorte que les chaînes de caractères(string) sont inutilisées et optimisées(optimized away).

Consultez _bind_methods de Control ou Object pour plus d'exemples.

Si l'on se contente d'ajouter des modules et des fonctionnalités qui ne sont pas censés être documentés de manière aussi complète, la macro D_METHOD() peut être ignorée sans risque et une chaîne de caractère passant le nom peut être passée pour plus de brièveté.

Références :

Constantes

Les classes ont souvent des énumérations telles que :

enum SomeMode {
   MODE_FIRST,
   MODE_SECOND
};

Pour qu'elles fonctionnent lorsqu'elles sont liées à des méthodes, l'énumération doit être déclarée convertible en int, pour cela une macro est fournie :

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

Les constantes peuvent également être liées à l'intérieur de bind_methods, en utilisant :

BIND_CONSTANT(MODE_FIRST);
BIND_CONSTANT(MODE_SECOND);

Propriétés (set/get)

Les objets exportent des propriétés, les propriétés sont utiles pour :

  • Sérialiser et dé-sérialiser l’objet.
  • Création d'une liste de valeurs modifiables pour la classe dérivée de l'objet.

Les propriétés sont généralement définies par la classe PropertyInfo(). Généralement construites sous la forme :

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

Par exemple :

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

Il s'agit d'une propriété entière, nommée "amount", l'indice est une plage, la plage va de 0 à 49 par pas de 1 (entiers). Elle n'est utilisable que dans l'éditeur (pour éditer visuellement sa valeur) mais elle ne sera pas sérialisée.

Un autre exemple :

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

Il s'agit d'une propriété de type chaîne de caractère(string), qui peut prendre n'importe quelle chaîne de caractère mais l'éditeur n'autorisera que ceux définis avec un indice. Comme aucun drapeau d'utilisation n'a été spécifié, les drapeaus par défaut sont PROPERTY_USAGE_STORAGE et PROPERTY_USAGE_EDITOR.

Il existe de nombreux conseils et indicateurs d'utilisation disponibles dans object.h, vérifiez-les.

Les propriétés peuvent également fonctionner comme des propriétés C # et être accessibles à partir d'un script en, utilisant une indexation, mais cette utilisation est généralement déconseillée, car l'utilisation de fonctions est à privilégier pour la lisibilité. De nombreuses propriétés sont également liées à des catégories, telles que "animation/frame" qui rendent également l'indexation impossible à moins d'utiliser l'opérateur [].

A partir de _bind_methods(), les propriétés peuvent être créées et liées tant que les fonctions set/get existent. Exemple :

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

Cela crée la propriété en utilisant le setter et le getter.

Liaison (Binding) des propriétés à l'aide de _set/_get/_get_property_list

Il existe une méthode de création de propriétés supplémentaire lorsque plus de flexibilité est souhaitée (par exemple, l'ajout ou la suppression de propriétés dans un contexte donné).

Les fonctions suivantes peuvent être surchargée dans une classe dérivée, elles ne sont PAS virtuelles, NE LES RENDEZ PAS virtuelles, elles sont appelées à chaque surcharge et les précédentes ne sont pas invalidées (appel à plusieurs niveaux).

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

C'est aussi un peu moins efficace car p_property doit être comparé aux noms souhaités dans l'ordre de la série.

Casting dynamique

Godot fournit un casting dynamique entre les classes dérivées d’objets, par exemple :

void somefunc(Object *some_obj) {

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

En cas d'échec du casting, NULL est renvoyé. Ce système utilise RTTI, mais il fonctionne aussi bien (bien qu'un peu plus lentement) lorsque RTTI est désactivé. Cela est utile sur les plateformes où un binaire de petite taille est idéal, comme pour du HTML5 ou les consoles (avec une empreinte mémoire faible).

Signaux

Les objets peuvent avoir un ensemble de signaux définis (semblable aux délégations(Delegates) dans d'autres langues). Se connecter est assez simple :

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

La méthode _node_entered_tree doit être enregistrée dans la classe en utilisant ClassDB::register_method (comme expliqué précédemment).

L'ajout des signaux à la classe se fait dans _bind_methods, en utilisant la macro ADD_SIGNAL , pour exemple :

ADD_SIGNAL(MethodInfo("been_killed"))

References

Reference hérite de Object et contient un compteur de références. Il constitue la base pour les types d'objets dont les références sont comptées. Leur déclaration doit être faite en utilisant le modèle Ref<>. Par exemple :

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

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

myref est comptée par référence. Elle sera libéré lorsque plus aucun Template de type Ref <> ne l'utilisera.

Références :

Ressources :

Resource hérite de Reference, donc toutes les références aux ressources sont comptées. Les ressources peuvent facultativement contenir un chemin d'accès, qui fait référence à un fichier sur le disque. Ceci peut être défini avec resource.set_path(path). Cependant, c'est généralement le chargeur de ressources qui s'en charge. Deux ressources différentes ne peuvent pas avoir le même chemin, tenter de le faire entraînera une erreur.

Une ressource sans chemin est également correcte.

Références :

Chargement des ressources

Les ressources peuvent être chargées en utilisant l'API ResourceLoader, comme ceci :

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

Si une référence à cette ressource a déjà été chargée précédemment et existe en mémoire, le chargeur de ressources retournera cette référence. Cela signifie qu'il ne peut y avoir qu'une seule ressource chargée par fichier référencé sur le disque à la fois.

  • resourceinteractiveloader (à faire / TODO)

Enregistrement de ressources

L'enregistrement d'une ressource peut être effectué avec l'API de sauvegarde de ressources :

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

L'instance sera sauvegardée. Les sous-ressources qui ont un chemin à un fichier seront sauvegardées en tant que référence à cette ressource. Les sous-ressources sans chemin seront regroupées avec la ressource sauvegardée et se verront attribuer des sous-identifiants, comme "res://someresource.res::1". Cela permet également de les mettre en cache lorsqu'elles sont chargées.