summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2024-09-06 11:10:58 +0200
committerRémi Verschelde <rverschelde@gmail.com>2024-09-06 11:10:58 +0200
commit58b3481eaf0bf43ebe2777d48b3bff719ce78833 (patch)
treeebca6799e41cfa925a85ee37e79a1b8cfa194e68
parentf2b76b97c0e00d90a6d3c1539148b639c10d3fc7 (diff)
parentbe5068d44b17a7a55382825e3df139410506d37f (diff)
downloadredot-engine-58b3481eaf0bf43ebe2777d48b3bff719ce78833.tar.gz
Merge pull request #89649 from dalexeev/core-bind-and-doc-iter-virtual-methods
Core: Bind and document iterator API virtual methods
-rw-r--r--core/object/object.cpp70
-rw-r--r--doc/classes/Object.xml49
2 files changed, 100 insertions, 19 deletions
diff --git a/core/object/object.cpp b/core/object/object.cpp
index 4be1dc4b34..d6b7d7a7fe 100644
--- a/core/object/object.cpp
+++ b/core/object/object.cpp
@@ -1724,33 +1724,65 @@ void Object::_bind_methods() {
#define BIND_OBJ_CORE_METHOD(m_method) \
::ClassDB::add_virtual_method(get_class_static(), m_method, true, Vector<String>(), true);
- MethodInfo notification_mi("_notification", PropertyInfo(Variant::INT, "what"));
- notification_mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32);
- BIND_OBJ_CORE_METHOD(notification_mi);
- BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_set", PropertyInfo(Variant::STRING_NAME, "property"), PropertyInfo(Variant::NIL, "value")));
+ BIND_OBJ_CORE_METHOD(MethodInfo("_init"));
+
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::STRING, "_to_string"));
+
+ {
+ MethodInfo mi("_notification");
+ mi.arguments.push_back(PropertyInfo(Variant::INT, "what"));
+ mi.arguments_metadata.push_back(GodotTypeInfo::Metadata::METADATA_INT_IS_INT32);
+ BIND_OBJ_CORE_METHOD(mi);
+ }
+
+ {
+ MethodInfo mi("_set");
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
+ mi.arguments.push_back(PropertyInfo(Variant::NIL, "value", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
+ mi.return_val.type = Variant::BOOL;
+ BIND_OBJ_CORE_METHOD(mi);
+ }
+
#ifdef TOOLS_ENABLED
- MethodInfo miget("_get", PropertyInfo(Variant::STRING_NAME, "property"));
- miget.return_val.name = "Variant";
- miget.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_OBJ_CORE_METHOD(miget);
+ {
+ MethodInfo mi("_get");
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_OBJ_CORE_METHOD(mi);
+ }
- MethodInfo plget("_get_property_list");
- plget.return_val.type = Variant::ARRAY;
- plget.return_val.hint = PROPERTY_HINT_ARRAY_TYPE;
- plget.return_val.hint_string = "Dictionary";
- BIND_OBJ_CORE_METHOD(plget);
+ {
+ MethodInfo mi("_get_property_list");
+ mi.return_val.type = Variant::ARRAY;
+ mi.return_val.hint = PROPERTY_HINT_ARRAY_TYPE;
+ mi.return_val.hint_string = "Dictionary";
+ BIND_OBJ_CORE_METHOD(mi);
+ }
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::NIL, "_validate_property", PropertyInfo(Variant::DICTIONARY, "property")));
BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_property_can_revert", PropertyInfo(Variant::STRING_NAME, "property")));
- MethodInfo mipgr("_property_get_revert", PropertyInfo(Variant::STRING_NAME, "property"));
- mipgr.return_val.name = "Variant";
- mipgr.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
- BIND_OBJ_CORE_METHOD(mipgr);
+ {
+ MethodInfo mi("_property_get_revert");
+ mi.arguments.push_back(PropertyInfo(Variant::STRING_NAME, "property"));
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_OBJ_CORE_METHOD(mi);
+ }
+
+ // These are actually `Variant` methods, but that doesn't matter since scripts can't inherit built-in types.
+
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_iter_init", PropertyInfo(Variant::ARRAY, "iter")));
+
+ BIND_OBJ_CORE_METHOD(MethodInfo(Variant::BOOL, "_iter_next", PropertyInfo(Variant::ARRAY, "iter")));
+
+ {
+ MethodInfo mi("_iter_get");
+ mi.arguments.push_back(PropertyInfo(Variant::NIL, "iter", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NIL_IS_VARIANT));
+ mi.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
+ BIND_OBJ_CORE_METHOD(mi);
+ }
#endif
- BIND_OBJ_CORE_METHOD(MethodInfo("_init"));
- BIND_OBJ_CORE_METHOD(MethodInfo(Variant::STRING, "_to_string"));
BIND_CONSTANT(NOTIFICATION_POSTINITIALIZE);
BIND_CONSTANT(NOTIFICATION_PREDELETE);
diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml
index 0cfa3a5d4a..a331c05e47 100644
--- a/doc/classes/Object.xml
+++ b/doc/classes/Object.xml
@@ -192,6 +192,55 @@
[b]Note:[/b] If [method _init] is defined with [i]required[/i] parameters, the Object with script may only be created directly. If any other means (such as [method PackedScene.instantiate] or [method Node.duplicate]) are used, the script's initialization will fail.
</description>
</method>
+ <method name="_iter_get" qualifiers="virtual">
+ <return type="Variant" />
+ <param index="0" name="iter" type="Variant" />
+ <description>
+ Returns the current iterable value. [param iter] stores the iteration state, but unlike [method _iter_init] and [method _iter_next] the state is supposed to be read-only, so there is no [Array] wrapper.
+ </description>
+ </method>
+ <method name="_iter_init" qualifiers="virtual">
+ <return type="bool" />
+ <param index="0" name="iter" type="Array" />
+ <description>
+ Initializes the iterator. [param iter] stores the iteration state. Since GDScript does not support passing arguments by reference, a single-element array is used as a wrapper. Returns [code]true[/code] so long as the iterator has not reached the end.
+ Example:
+ [codeblock]
+ class MyRange:
+ var _from
+ var _to
+
+ func _init(from, to):
+ assert(from &lt;= to)
+ _from = from
+ _to = to
+
+ func _iter_init(iter):
+ iter[0] = _from
+ return iter[0] &lt; _to
+
+ func _iter_next(iter):
+ iter[0] += 1
+ return iter[0] &lt; _to
+
+ func _iter_get(iter):
+ return iter
+
+ func _ready():
+ var my_range = MyRange.new(2, 5)
+ for x in my_range:
+ print(x) # Prints 2, 3, 4.
+ [/codeblock]
+ [b]Note:[/b] Alternatively, you can ignore [param iter] and use the object's state instead, see [url=$DOCS_URL/tutorials/scripting/gdscript/gdscript_advanced.html#custom-iterators]online docs[/url] for an example. Note that in this case you will not be able to reuse the same iterator instance in nested loops. Also, make sure you reset the iterator state in this method if you want to reuse the same instance multiple times.
+ </description>
+ </method>
+ <method name="_iter_next" qualifiers="virtual">
+ <return type="bool" />
+ <param index="0" name="iter" type="Array" />
+ <description>
+ Moves the iterator to the next iteration. [param iter] stores the iteration state. Since GDScript does not support passing arguments by reference, a single-element array is used as a wrapper. Returns [code]true[/code] so long as the iterator has not reached the end.
+ </description>
+ </method>
<method name="_notification" qualifiers="virtual">
<return type="void" />
<param index="0" name="what" type="int" />