diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/node.cpp | 202 | ||||
-rw-r--r-- | scene/main/node.h | 36 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 2 | ||||
-rw-r--r-- | scene/main/window.cpp | 2 |
4 files changed, 167 insertions, 75 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp index cafa4fa2d2..05409b7bfe 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -48,6 +48,7 @@ #include <stdint.h> VARIANT_ENUM_CAST(Node::ProcessMode); +VARIANT_ENUM_CAST(Node::InternalMode); int Node::orphan_node_count = 0; @@ -122,28 +123,27 @@ void Node::_notification(int p_notification) { } } break; case NOTIFICATION_READY: { - if (get_script_instance()) { - if (GDVIRTUAL_IS_OVERRIDDEN(_input)) { - set_process_input(true); - } - - if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) { - set_process_unhandled_input(true); - } + if (GDVIRTUAL_IS_OVERRIDDEN(_input)) { + set_process_input(true); + } - if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_key_input)) { - set_process_unhandled_key_input(true); - } + if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) { + set_process_unhandled_input(true); + } - if (GDVIRTUAL_IS_OVERRIDDEN(_process)) { - set_process(true); - } - if (GDVIRTUAL_IS_OVERRIDDEN(_physics_process)) { - set_physics_process(true); - } + if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_key_input)) { + set_process_unhandled_key_input(true); + } - GDVIRTUAL_CALL(_ready); + if (GDVIRTUAL_IS_OVERRIDDEN(_process)) { + set_process(true); } + if (GDVIRTUAL_IS_OVERRIDDEN(_physics_process)) { + set_physics_process(true); + } + + GDVIRTUAL_CALL(_ready); + if (data.filename.length()) { ERR_FAIL_COND(!is_inside_tree()); get_multiplayer()->scene_enter_exit_notify(data.filename, this, true); @@ -291,14 +291,40 @@ void Node::_propagate_exit_tree() { void Node::move_child(Node *p_child, int p_pos) { ERR_FAIL_NULL(p_child); - ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, vformat("Invalid new child position: %d.", p_pos)); ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node."); + + // We need to check whether node is internal and move it only in the relevant node range. + if (p_child->_is_internal_front()) { + ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_front, vformat("Invalid new child position: %d. Child is internal.", p_pos)); + _move_child(p_child, p_pos); + } else if (p_child->_is_internal_back()) { + ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_back, vformat("Invalid new child position: %d. Child is internal.", p_pos)); + _move_child(p_child, data.children.size() - data.internal_children_back + p_pos); + } else { + ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1 - data.internal_children_front - data.internal_children_back, vformat("Invalid new child position: %d.", p_pos)); + _move_child(p_child, p_pos + data.internal_children_front); + } +} + +void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) { ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup)."); // Specifying one place beyond the end // means the same as moving to the last position - if (p_pos == data.children.size()) { - p_pos--; + if (!p_ignore_end) { // p_ignore_end is a little hack to make back internal children work properly. + if (p_child->_is_internal_front()) { + if (p_pos == data.internal_children_front) { + p_pos--; + } + } else if (p_child->_is_internal_back()) { + if (p_pos == data.children.size()) { + p_pos--; + } + } else { + if (p_pos == data.children.size() - data.internal_children_back) { + p_pos--; + } + } } if (p_child->data.pos == p_pos) { @@ -339,7 +365,14 @@ void Node::raise() { return; } - data.parent->move_child(this, data.parent->data.children.size() - 1); + // Internal children move within a different index range. + if (_is_internal_front()) { + data.parent->move_child(this, data.parent->data.internal_children_front - 1); + } else if (_is_internal_back()) { + data.parent->move_child(this, data.parent->data.internal_children_back - 1); + } else { + data.parent->move_child(this, data.parent->get_child_count(false) - 1); + } } void Node::add_child_notify(Node *p_child) { @@ -483,32 +516,32 @@ void Node::_propagate_process_owner(Node *p_owner, int p_pause_notification, int } } -void Node::set_network_master(int p_peer_id, bool p_recursive) { - data.network_master = p_peer_id; +void Node::set_multiplayer_authority(int p_peer_id, bool p_recursive) { + data.multiplayer_authority = p_peer_id; if (p_recursive) { for (int i = 0; i < data.children.size(); i++) { - data.children[i]->set_network_master(p_peer_id, true); + data.children[i]->set_multiplayer_authority(p_peer_id, true); } } } -int Node::get_network_master() const { - return data.network_master; +int Node::get_multiplayer_authority() const { + return data.multiplayer_authority; } -bool Node::is_network_master() const { +bool Node::is_multiplayer_authority() const { ERR_FAIL_COND_V(!is_inside_tree(), false); - return get_multiplayer()->get_network_unique_id() == data.network_master; + return get_multiplayer()->get_unique_id() == data.multiplayer_authority; } /***** RPC CONFIG ********/ -uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel) { +uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, Multiplayer::TransferMode p_transfer_mode, int p_channel) { for (int i = 0; i < data.rpc_methods.size(); i++) { if (data.rpc_methods[i].name == p_method) { - MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i]; + Multiplayer::RPCConfig &nd = data.rpc_methods.write[i]; nd.rpc_mode = p_rpc_mode; nd.transfer_mode = p_transfer_mode; nd.channel = p_channel; @@ -516,7 +549,7 @@ uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_ } } // New method - MultiplayerAPI::RPCConfig nd; + Multiplayer::RPCConfig nd; nd.name = p_method; nd.rpc_mode = p_rpc_mode; nd.transfer_mode = p_transfer_mode; @@ -609,7 +642,7 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { ERR_FAIL_COND(!is_inside_tree()); - get_multiplayer()->rpcp(this, p_peer_id, true, p_method, p_arg, p_argcount); + get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount); } Ref<MultiplayerAPI> Node::get_multiplayer() const { @@ -630,7 +663,7 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { multiplayer = p_multiplayer; } -Vector<MultiplayerAPI::RPCConfig> Node::get_node_rpc_methods() const { +Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { return data.rpc_methods; } @@ -1058,6 +1091,10 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) { p_child->data.pos = data.children.size(); data.children.push_back(p_child); p_child->data.parent = this; + + if (data.internal_children_back > 0) { + _move_child(p_child, data.children.size() - data.internal_children_back - 1); + } p_child->notification(NOTIFICATION_PARENTED); if (data.tree) { @@ -1070,7 +1107,7 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) { add_child_notify(p_child); } -void Node::add_child(Node *p_child, bool p_legible_unique_name) { +void Node::add_child(Node *p_child, bool p_legible_unique_name, InternalMode p_internal) { ERR_FAIL_NULL(p_child); ERR_FAIL_COND_MSG(p_child == this, vformat("Can't add child '%s' to itself.", p_child->get_name())); // adding to itself! ERR_FAIL_COND_MSG(p_child->data.parent, vformat("Can't add child '%s' to '%s', already has a parent '%s'.", p_child->get_name(), get_name(), p_child->data.parent->get_name())); //Fail if node has a parent @@ -1079,19 +1116,35 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) { #endif ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead."); - /* Validate name */ _validate_child_name(p_child, p_legible_unique_name); - _add_child_nocheck(p_child, p_child->data.name); + + if (p_internal == INTERNAL_MODE_FRONT) { + _move_child(p_child, data.internal_children_front); + data.internal_children_front++; + } else if (p_internal == INTERNAL_MODE_BACK) { + if (data.internal_children_back > 0) { + _move_child(p_child, data.children.size() - 1, true); + } + data.internal_children_back++; + } } void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) { ERR_FAIL_NULL(p_sibling); + ERR_FAIL_NULL(data.parent); ERR_FAIL_COND_MSG(p_sibling == this, vformat("Can't add sibling '%s' to itself.", p_sibling->get_name())); // adding to itself! ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_sibling() failed. Consider using call_deferred(\"add_sibling\", sibling) instead."); - get_parent()->add_child(p_sibling, p_legible_unique_name); - get_parent()->move_child(p_sibling, this->get_index() + 1); + InternalMode internal = INTERNAL_MODE_DISABLED; + if (_is_internal_front()) { // The sibling will have the same internal status. + internal = INTERNAL_MODE_FRONT; + } else if (_is_internal_back()) { + internal = INTERNAL_MODE_BACK; + } + + data.parent->add_child(p_sibling, p_legible_unique_name, internal); + data.parent->_move_child(p_sibling, get_index() + 1); } void Node::_propagate_validate_owner() { @@ -1145,7 +1198,12 @@ void Node::remove_child(Node *p_child) { ERR_FAIL_COND_MSG(idx == -1, vformat("Cannot remove child node '%s' as it is not a child of this node.", p_child->get_name())); //ERR_FAIL_COND( p_child->data.blocked > 0 ); - //if (data.scene) { does not matter + // If internal child, update the counter. + if (p_child->_is_internal_front()) { + data.internal_children_front--; + } else if (p_child->_is_internal_back()) { + data.internal_children_back--; + } p_child->_set_tree(nullptr); //} @@ -1175,17 +1233,29 @@ void Node::remove_child(Node *p_child) { } } -int Node::get_child_count() const { - return data.children.size(); +int Node::get_child_count(bool p_include_internal) const { + if (p_include_internal) { + return data.children.size(); + } else { + return data.children.size() - data.internal_children_front - data.internal_children_back; + } } -Node *Node::get_child(int p_index) const { - if (p_index < 0) { - p_index += data.children.size(); +Node *Node::get_child(int p_index, bool p_include_internal) const { + if (p_include_internal) { + if (p_index < 0) { + p_index += data.children.size(); + } + ERR_FAIL_INDEX_V(p_index, data.children.size(), nullptr); + return data.children[p_index]; + } else { + if (p_index < 0) { + p_index += data.children.size() - data.internal_children_front - data.internal_children_back; + } + ERR_FAIL_INDEX_V(p_index, data.children.size() - data.internal_children_front - data.internal_children_back, nullptr); + p_index += data.internal_children_front; + return data.children[p_index]; } - ERR_FAIL_INDEX_V(p_index, data.children.size(), nullptr); - - return data.children[p_index]; } Node *Node::_get_child_by_name(const StringName &p_name) const { @@ -1717,7 +1787,13 @@ void Node::_propagate_replace_owner(Node *p_owner, Node *p_by_owner) { data.blocked--; } -int Node::get_index() const { +int Node::get_index(bool p_include_internal) const { + // p_include_internal = false doesn't make sense if the node is internal. + ERR_FAIL_COND_V_MSG(!p_include_internal && (_is_internal_front() || _is_internal_back()), -1, "Node is internal. Can't get index with 'include_internal' being false."); + + if (data.parent && !p_include_internal) { + return data.pos - data.parent->data.internal_children_front; + } return data.pos; } @@ -2429,12 +2505,12 @@ void Node::queue_delete() { } } -TypedArray<Node> Node::_get_children() const { +TypedArray<Node> Node::_get_children(bool p_include_internal) const { TypedArray<Node> arr; - int cc = get_child_count(); + int cc = get_child_count(p_include_internal); arr.resize(cc); for (int i = 0; i < cc; i++) { - arr[i] = get_child(i); + arr[i] = get_child(i, p_include_internal); } return arr; @@ -2581,11 +2657,11 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name); ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name); - ClassDB::bind_method(D_METHOD("add_child", "node", "legible_unique_name"), &Node::add_child, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_child", "node", "legible_unique_name", "internal"), &Node::add_child, DEFVAL(false), DEFVAL(0)); ClassDB::bind_method(D_METHOD("remove_child", "node"), &Node::remove_child); - ClassDB::bind_method(D_METHOD("get_child_count"), &Node::get_child_count); - ClassDB::bind_method(D_METHOD("get_children"), &Node::_get_children); - ClassDB::bind_method(D_METHOD("get_child", "idx"), &Node::get_child); + ClassDB::bind_method(D_METHOD("get_child_count", "include_internal"), &Node::get_child_count, DEFVAL(false)); // Note that the default value bound for include_internal is false, while the method is declared with true. This is because internal nodes are irrelevant for GDSCript. + ClassDB::bind_method(D_METHOD("get_children", "include_internal"), &Node::_get_children, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("get_child", "idx", "include_internal"), &Node::get_child, DEFVAL(false)); ClassDB::bind_method(D_METHOD("has_node", "path"), &Node::has_node); ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node); ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null); @@ -2609,7 +2685,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("set_owner", "owner"), &Node::set_owner); ClassDB::bind_method(D_METHOD("get_owner"), &Node::get_owner); ClassDB::bind_method(D_METHOD("remove_and_skip"), &Node::remove_and_skip); - ClassDB::bind_method(D_METHOD("get_index"), &Node::get_index); + ClassDB::bind_method(D_METHOD("get_index", "include_internal"), &Node::get_index, DEFVAL(false)); ClassDB::bind_method(D_METHOD("print_tree"), &Node::print_tree); ClassDB::bind_method(D_METHOD("print_tree_pretty"), &Node::print_tree_pretty); ClassDB::bind_method(D_METHOD("set_filename", "filename"), &Node::set_filename); @@ -2661,15 +2737,15 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready); - ClassDB::bind_method(D_METHOD("set_network_master", "id", "recursive"), &Node::set_network_master, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("get_network_master"), &Node::get_network_master); + ClassDB::bind_method(D_METHOD("set_multiplayer_authority", "id", "recursive"), &Node::set_multiplayer_authority, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("get_multiplayer_authority"), &Node::get_multiplayer_authority); - ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master); + ClassDB::bind_method(D_METHOD("is_multiplayer_authority"), &Node::is_multiplayer_authority); ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer); ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer); - ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(MultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description); @@ -2747,6 +2823,10 @@ void Node::_bind_methods() { BIND_ENUM_CONSTANT(DUPLICATE_SCRIPTS); BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANCING); + BIND_ENUM_CONSTANT(INTERNAL_MODE_DISABLED); + BIND_ENUM_CONSTANT(INTERNAL_MODE_FRONT); + BIND_ENUM_CONSTANT(INTERNAL_MODE_BACK); + ADD_SIGNAL(MethodInfo("ready")); ADD_SIGNAL(MethodInfo("renamed")); ADD_SIGNAL(MethodInfo("tree_entered")); diff --git a/scene/main/node.h b/scene/main/node.h index a07accba2f..198501eeac 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -73,6 +73,12 @@ public: NAME_CASING_SNAKE_CASE }; + enum InternalMode { + INTERNAL_MODE_DISABLED, + INTERNAL_MODE_FRONT, + INTERNAL_MODE_BACK, + }; + struct Comparator { bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); } }; @@ -97,6 +103,8 @@ private: Node *parent = nullptr; Node *owner = nullptr; Vector<Node *> children; + int internal_children_front = 0; + int internal_children_back = 0; int pos = -1; int depth = -1; int blocked = 0; // Safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed. @@ -119,8 +127,8 @@ private: ProcessMode process_mode = PROCESS_MODE_INHERIT; Node *process_owner = nullptr; - int network_master = 1; // Server by default. - Vector<MultiplayerAPI::RPCConfig> rpc_methods; + int multiplayer_authority = 1; // Server by default. + Vector<Multiplayer::RPCConfig> rpc_methods; // Variables used to properly sort the node when processing, ignored otherwise. // TODO: Should move all the stuff below to bits. @@ -172,12 +180,15 @@ private: void _duplicate_signals(const Node *p_original, Node *p_copy) const; Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = nullptr) const; - TypedArray<Node> _get_children() const; + TypedArray<Node> _get_children(bool p_include_internal = true) const; Array _get_groups() const; Variant _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); Variant _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); + _FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; } + _FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; } + friend class SceneTree; void _set_tree(SceneTree *p_tree); @@ -284,12 +295,12 @@ public: StringName get_name() const; void set_name(const String &p_name); - void add_child(Node *p_child, bool p_legible_unique_name = false); + void add_child(Node *p_child, bool p_legible_unique_name = false, InternalMode p_internal = INTERNAL_MODE_DISABLED); void add_sibling(Node *p_sibling, bool p_legible_unique_name = false); void remove_child(Node *p_child); - int get_child_count() const; - Node *get_child(int p_index) const; + int get_child_count(bool p_include_internal = true) const; + Node *get_child(int p_index, bool p_include_internal = true) const; bool has_node(const NodePath &p_path) const; Node *get_node(const NodePath &p_path) const; Node *get_node_or_null(const NodePath &p_path) const; @@ -327,6 +338,7 @@ public: int get_persistent_group_count() const; void move_child(Node *p_child, int p_pos); + void _move_child(Node *p_child, int p_pos, bool p_ignore_end = false); void raise(); void set_owner(Node *p_owner); @@ -334,7 +346,7 @@ public: void get_owned_by(Node *p_by, List<Node *> *p_owned); void remove_and_skip(); - int get_index() const; + int get_index(bool p_include_internal = true) const; Ref<Tween> create_tween(); @@ -450,12 +462,12 @@ public: bool is_displayed_folded() const; /* NETWORK */ - void set_network_master(int p_peer_id, bool p_recursive = true); - int get_network_master() const; - bool is_network_master() const; + void set_multiplayer_authority(int p_peer_id, bool p_recursive = true); + int get_multiplayer_authority() const; + bool is_multiplayer_authority() const; - uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC - Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const; + uint16_t rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, Multiplayer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC + Vector<Multiplayer::RPCConfig> get_node_rpc_methods() const; void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index b1b94ae910..19331c1906 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -31,7 +31,7 @@ #ifndef SCENE_TREE_H #define SCENE_TREE_H -#include "core/io/multiplayer_api.h" +#include "core/multiplayer/multiplayer_api.h" #include "core/os/main_loop.h" #include "core/os/thread_safe.h" #include "core/templates/self_list.h" diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 1fcfce2ea9..ca5a3915d0 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1497,7 +1497,7 @@ void Window::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,Fullscreen"), "set_mode", "get_mode"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen"), "set_current_screen", "get_current_screen"); ADD_GROUP("Flags", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible"); |