add "propagate_call" method to Node

It is possible to propagate a notification down the Node tree by
using `propagate_notification`, but there was no such method for
doing the same but with method calls.

This commit adds the `propagate_call` method, which calls a method
on a node and all child nodes. An optional paramter `parent_first`
determines whether the parent node gets called before or after the
children have been visited. It defaults to false, so the parent
gets called last.
This commit is contained in:
Karroffel 2017-08-19 15:17:06 +02:00
parent 5d85108f94
commit 390f7def39
3 changed files with 31 additions and 0 deletions

View file

@ -26549,6 +26549,17 @@
Notify the current node and all its children recursively by calling notification() in all of them. Notify the current node and all its children recursively by calling notification() in all of them.
</description> </description>
</method> </method>
<method name="propagate_call">
<argument index="0" name="method" type="String">
</argument>
<argument index="1" name="args" type="Array" default="[]">
</argument>
<argument index="2" name="parent_first" type="bool" default="false">
</argument>
<description>
Calls the method (if present) with the arguments given in "args" on this Node and recursively on all children. If the parent_first argument is true then the method will be called on the current [Node] first, then on all children. If it is false then the children will get called first.
</description>
</method>
<method name="queue_free"> <method name="queue_free">
<description> <description>
</description> </description>

View file

@ -1954,6 +1954,23 @@ void Node::propagate_notification(int p_notification) {
data.blocked--; data.blocked--;
} }
void Node::propagate_call(const StringName &p_method, const Array &p_args, const bool p_parent_first) {
data.blocked++;
if (p_parent_first && has_method(p_method))
callv(p_method, p_args);
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->propagate_call(p_method, p_args, p_parent_first);
}
if (!p_parent_first && has_method(p_method))
callv(p_method, p_args);
data.blocked--;
}
void Node::_propagate_replace_owner(Node *p_owner, Node *p_by_owner) { void Node::_propagate_replace_owner(Node *p_owner, Node *p_by_owner) {
if (get_owner() == p_owner) if (get_owner() == p_owner)
set_owner(p_by_owner); set_owner(p_by_owner);
@ -2761,6 +2778,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_filename", "filename"), &Node::set_filename); ClassDB::bind_method(D_METHOD("set_filename", "filename"), &Node::set_filename);
ClassDB::bind_method(D_METHOD("get_filename"), &Node::get_filename); ClassDB::bind_method(D_METHOD("get_filename"), &Node::get_filename);
ClassDB::bind_method(D_METHOD("propagate_notification", "what"), &Node::propagate_notification); ClassDB::bind_method(D_METHOD("propagate_notification", "what"), &Node::propagate_notification);
ClassDB::bind_method(D_METHOD("propagate_call", "method", "args", "parent_first"), &Node::propagate_call, DEFVAL(Array()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("set_fixed_process", "enable"), &Node::set_fixed_process); ClassDB::bind_method(D_METHOD("set_fixed_process", "enable"), &Node::set_fixed_process);
ClassDB::bind_method(D_METHOD("get_fixed_process_delta_time"), &Node::get_fixed_process_delta_time); ClassDB::bind_method(D_METHOD("get_fixed_process_delta_time"), &Node::get_fixed_process_delta_time);
ClassDB::bind_method(D_METHOD("is_fixed_processing"), &Node::is_fixed_processing); ClassDB::bind_method(D_METHOD("is_fixed_processing"), &Node::is_fixed_processing);

View file

@ -298,6 +298,8 @@ public:
void propagate_notification(int p_notification); void propagate_notification(int p_notification);
void propagate_call(const StringName &p_method, const Array &p_args = Array(), const bool p_parent_first = false);
/* PROCESSING */ /* PROCESSING */
void set_fixed_process(bool p_process); void set_fixed_process(bool p_process);
float get_fixed_process_delta_time() const; float get_fixed_process_delta_time() const;