mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-05 22:09:56 +03:00
Revamping of the docs organisation for a more coherent TOC
Only the pages were moved so far and some empty ones created,
the up-to-date toctrees come in the next commit.
(cherry picked from commit b408bdb918)
This commit is contained in:
committed by
Rémi Verschelde
parent
6a730cb057
commit
5e05011eae
310
development/cpp/object_class.rst
Normal file
310
development/cpp/object_class.rst
Normal file
@@ -0,0 +1,310 @@
|
||||
.. _doc_object_class:
|
||||
|
||||
Object class
|
||||
============
|
||||
|
||||
General definition
|
||||
------------------
|
||||
|
||||
:ref:`Object <class_object>` is the base class for almost everything. Most classes in Godot
|
||||
inherit directly or indirectly from it. Objects provide reflection and
|
||||
editable properties, and declaring them is a matter of using a single
|
||||
macro like this.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
class CustomObject : public Object {
|
||||
|
||||
OBJ_TYPE(CustomObject,Object); // this is required to inherit
|
||||
};
|
||||
|
||||
This makes Objects gain a lot of functionality, like for example
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
obj = memnew(CustomObject);
|
||||
print_line("Object Type: ",obj->get_type()); //print object type
|
||||
|
||||
obj2 = obj->cast_to<OtherType>(); // converting between types, this also works without RTTI enabled.
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/object.h <https://github.com/godotengine/godot/blob/master/core/object.h>`__
|
||||
|
||||
Registering an Object
|
||||
---------------------
|
||||
|
||||
ObjectTypeDB is a static class that holds the entire list of registered
|
||||
classes that inherit from Object, as well as dynamic bindings to all
|
||||
their methods properties and integer constants.
|
||||
|
||||
Classes are registered by calling:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ObjectTypeDB::register_type<MyCustomType>()
|
||||
|
||||
Registering it will allow the type to be instanced by scripts, code, or
|
||||
creating them again when deserializing.
|
||||
|
||||
Registering as virtual is the same but it can't be instanced.
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ObjectTypeDB::register_virtual_type<MyCustomType>()
|
||||
|
||||
Object-derived classes can override the static function
|
||||
``static void _bind_methods()``. When one class is registered, this
|
||||
static function is called to register all the object methods,
|
||||
properties, constants, etc. It's only called once. If an Object derived
|
||||
class is instanced but has not been registered, it will be registered as
|
||||
virtual automatically.
|
||||
|
||||
Inside ``_bind_methods``, there are a couple of things that can be done.
|
||||
Registering functions is one:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ObjectTypeDB::register_method(_MD("methodname","arg1name","arg2name"),&MyCustomMethod);
|
||||
|
||||
Default values for arguments can be passed in reverse order:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ObjectTypeDB::register_method(_MD("methodname","arg1name","arg2name"),&MyCustomType::method,DEFVAL(-1)); //default value for arg2name
|
||||
|
||||
``_MD`` is a macro that converts "methodname" to a StringName for more
|
||||
efficiency. Argument names are used for introspection, but when
|
||||
compiling on release, the macro ignores them, so the strings are unused
|
||||
and optimized away.
|
||||
|
||||
Check ``_bind_methods`` of Control or Object for more examples.
|
||||
|
||||
If just adding modules and functionality that is not expected to be
|
||||
documented as thoroughly, the ``_MD()`` macro can safely be ignored and a
|
||||
string passing the name can be passed for brevity.
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/object_type_db.h <https://github.com/godotengine/godot/blob/master/core/object_type_db.h>`__
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
Classes often have enums such as:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
enum SomeMode {
|
||||
MODE_FIRST,
|
||||
MODE_SECOND
|
||||
};
|
||||
|
||||
For these to work when binding to methods, the enum must be declared
|
||||
convertible to int, for this a macro is provided:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
VARIANT_ENUM_CAST( MyClass::SomeMode ); // now functions that take SomeMode can be bound.
|
||||
|
||||
The constants can also be bound inside ``_bind_methods``, by using:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
BIND_CONSTANT( MODE_FIRST );
|
||||
BIND_CONSTANT( MODE_SECOND );
|
||||
|
||||
Properties (set/get)
|
||||
--------------------
|
||||
|
||||
Objects export properties, properties are useful for the following:
|
||||
|
||||
- Serializing and deserializing the object.
|
||||
- Creating a list of editable values for the Object derived class.
|
||||
|
||||
Properties are usually defined by the PropertyInfo() class. Usually
|
||||
constructed as:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
PropertyInfo(type,name,hint,hint_string,usage_flags)
|
||||
|
||||
For example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
PropertyInfo(Variant::INT,"amount",PROPERTY_HINT_RANGE,"0,49,1",PROPERTY_USAGE_EDITOR)
|
||||
|
||||
This is an integer property, named "amount", hint is a range, range goes
|
||||
from 0 to 49 in steps of 1 (integers). It is only usable for the editor
|
||||
(edit value visually) but won't be serialized.
|
||||
|
||||
Another example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
PropertyInfo(Variant::STRING,"modes",PROPERTY_HINT_ENUM,"Enabled,Disabled,Turbo")
|
||||
|
||||
This is a string property, can take any string but the editor will only
|
||||
allow the defined hint ones. Since no usage flags were specified, the
|
||||
default ones are PROPERTY_USAGE_STORAGE and PROPERTY_USAGE_EDITOR.
|
||||
|
||||
There are plenty of hints and usage flags available in object.h, give them a
|
||||
check.
|
||||
|
||||
Properties can also work like C# properties and be accessed from script
|
||||
using indexing, but this usage is generally discouraged, as using
|
||||
functions is preferred for legibility. Many properties are also bound
|
||||
with categories, such as "animation/frame" which also make indexing
|
||||
impossible unless using operator [].
|
||||
|
||||
From ``_bind_methods()``, properties can be created and bound as long as
|
||||
set/get functions exist. Example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"amount"), _SCS("set_amount"), _SCS("get_amount") )
|
||||
|
||||
This creates the property using the setter and the getter. ``_SCS`` is a
|
||||
macro that creates a StringName efficiently.
|
||||
|
||||
Binding properties using ``_set``/``_get``/``_get_property_list``
|
||||
-----------------------------------------------------------------
|
||||
|
||||
An additional method of creating properties exists when more flexibility
|
||||
is desired (i.e. adding or removing properties on context).
|
||||
|
||||
The following functions can be overridden in an Object derived class,
|
||||
they are NOT virtual, DO NOT make them virtual, they are called for
|
||||
every override and the previous ones are not invalidated (multilevel
|
||||
call).
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
void _get_property_info(List<PropertyInfo> *r_props); //return list of properties
|
||||
bool _get(const StringName& p_property, Variany& r_value) const; //return true if property was found
|
||||
bool _set(const StringName& p_property, const Variany& p_value); //return true if property was found
|
||||
|
||||
This is also a little less efficient since ``p_property`` must be
|
||||
compared against the desired names in serial order.
|
||||
|
||||
Dynamic casting
|
||||
---------------
|
||||
|
||||
Godot provides dynamic casting between Object-derived classes, for
|
||||
example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
void somefunc(Object *some_obj) {
|
||||
|
||||
Button *button = some_obj->cast_to<Button>();
|
||||
}
|
||||
|
||||
If cast fails, NULL is returned. This system uses RTTI, but it also
|
||||
works fine (although a bit slower) when RTTI is disabled. This is useful
|
||||
on platforms where a very small binary size is ideal, such as HTML5 or
|
||||
consoles (with low memory footprint).
|
||||
|
||||
Signals
|
||||
-------
|
||||
|
||||
Objects can have a set of signals defined (similar to Delegates in other
|
||||
languages). Connecting to them is rather easy:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
obj->connect(<signal>,target_instance,target_method)
|
||||
//for example
|
||||
obj->connect("enter_tree",this,"_node_entered_tree")
|
||||
|
||||
The method ``_node_entered_tree`` must be registered to the class using
|
||||
``ObjectTypeDB::register_method`` (explained before).
|
||||
|
||||
Adding signals to a class is done in ``_bind_methods``, using the
|
||||
``ADD_SIGNAL`` macro, for example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
ADD_SIGNAL( MethodInfo("been_killed") )
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
:ref:`Reference <class_reference>` inherits from Object and holds a
|
||||
reference count. It is the base for reference counted object types.
|
||||
Declaring them must be done using Ref<> template. For example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
class MyReference: public Reference {
|
||||
OBJ_TYPE( MyReference,Reference );
|
||||
};
|
||||
|
||||
Ref<MyReference> myref = memnew( MyReference );
|
||||
|
||||
``myref`` is reference counted. It will be freed when no more Ref<>
|
||||
templates point to it.
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/reference.h <https://github.com/godotengine/godot/blob/master/core/reference.h>`__
|
||||
|
||||
Resources:
|
||||
----------
|
||||
|
||||
:ref:`Resource <class_resource>` inherits from Reference, so all resources
|
||||
are reference counted. Resources can optionally contain a path, which
|
||||
reference a file on disk. This can be set with ``resource.set_path(path)``.
|
||||
This is normally done by the resource loader though. No two different
|
||||
resources can have the same path, attempt to do so will result in an error.
|
||||
|
||||
Resources without a path are fine too.
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/resource.h <https://github.com/godotengine/godot/blob/master/core/resource.h>`__
|
||||
|
||||
Resource loading
|
||||
----------------
|
||||
|
||||
Resources can be loaded with the ResourceLoader API, like this:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
Ref<Resource> res = ResourceLoader::load("res://someresource.res")
|
||||
|
||||
If a reference to that resource has been loaded previously and is in
|
||||
memory, the resource loader will return that reference. This means that
|
||||
there can be only one resource loaded from a file referenced on disk at
|
||||
the same time.
|
||||
|
||||
- resourceinteractiveloader (TODO)
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/io/resource_loader.h <https://github.com/godotengine/godot/blob/master/core/io/resource_loader.h>`__
|
||||
|
||||
Resource saving
|
||||
---------------
|
||||
|
||||
Saving a resource can be done with the resource saver API:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
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.
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
- `core/io/resource_saver.h <https://github.com/godotengine/godot/blob/master/core/io/resource_saver.h>`__
|
||||
Reference in New Issue
Block a user