diff options
Diffstat (limited to 'scene/main/node.cpp')
-rw-r--r-- | scene/main/node.cpp | 193 |
1 files changed, 69 insertions, 124 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp index b4701637a4..a2b0f1a825 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -33,12 +33,12 @@ #include "core/config/project_settings.h" #include "core/core_string_names.h" #include "core/io/resource_loader.h" -#include "core/multiplayer/multiplayer_api.h" #include "core/object/message_queue.h" #include "core/string/print_string.h" #include "instance_placeholder.h" #include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" +#include "scene/main/multiplayer_api.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" #include "viewport.h" @@ -328,12 +328,21 @@ void Node::move_child(Node *p_child, int p_pos) { // We need to check whether node is internal and move it only in the relevant node range. if (p_child->_is_internal_front()) { + if (p_pos < 0) { + p_pos += data.internal_children_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()) { + if (p_pos < 0) { + p_pos += data.internal_children_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 { + if (p_pos < 0) { + p_pos += get_child_count(false); + } 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); } @@ -389,21 +398,6 @@ void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) { data.blocked--; } -void Node::raise() { - if (!data.parent) { - return; - } - - // 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::_propagate_groups_dirty() { for (const KeyValue<StringName, GroupData> &E : data.grouped) { if (E.value.group) { @@ -582,35 +576,30 @@ bool Node::is_multiplayer_authority() const { /***** RPC CONFIG ********/ -uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, bool p_call_local, 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) { - Multiplayer::RPCConfig &nd = data.rpc_methods.write[i]; - nd.rpc_mode = p_rpc_mode; - nd.transfer_mode = p_transfer_mode; - nd.call_local = p_call_local; - nd.channel = p_channel; - return i | (1 << 15); - } +void Node::rpc_config(const StringName &p_method, const Variant &p_config) { + if (data.rpc_config.get_type() != Variant::DICTIONARY) { + data.rpc_config = Dictionary(); + } + Dictionary node_config = data.rpc_config; + if (p_config.get_type() == Variant::NIL) { + node_config.erase(p_method); + } else { + ERR_FAIL_COND(p_config.get_type() != Variant::DICTIONARY); + node_config[p_method] = p_config; } - // New method - Multiplayer::RPCConfig nd; - nd.name = p_method; - nd.rpc_mode = p_rpc_mode; - nd.transfer_mode = p_transfer_mode; - nd.channel = p_channel; - nd.call_local = p_call_local; - data.rpc_methods.push_back(nd); - return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15); +} + +const Variant Node::get_node_rpc_config() const { + return data.rpc_config; } /***** RPC FUNCTIONS ********/ -void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Error Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 1) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 1; - return; + return ERR_INVALID_PARAMETER; } Variant::Type type = p_args[0]->get_type(); @@ -618,28 +607,28 @@ void Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::STRING_NAME; - return; + return ERR_INVALID_PARAMETER; } StringName method = (*p_args[0]).operator StringName(); - rpcp(0, method, &p_args[1], p_argcount - 1); - + Error err = rpcp(0, method, &p_args[1], p_argcount - 1); r_error.error = Callable::CallError::CALL_OK; + return err; } -void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { +Error Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { if (p_argcount < 2) { r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; r_error.argument = 2; - return; + return ERR_INVALID_PARAMETER; } if (p_args[0]->get_type() != Variant::INT) { r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 0; r_error.expected = Variant::INT; - return; + return ERR_INVALID_PARAMETER; } Variant::Type type = p_args[1]->get_type(); @@ -647,20 +636,20 @@ void Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallEr r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; r_error.argument = 1; r_error.expected = Variant::STRING_NAME; - return; + return ERR_INVALID_PARAMETER; } int peer_id = *p_args[0]; StringName method = (*p_args[1]).operator StringName(); - rpcp(peer_id, method, &p_args[2], p_argcount - 2); - + Error err = rpcp(peer_id, method, &p_args[2], p_argcount - 2); r_error.error = Callable::CallError::CALL_OK; + return err; } -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, p_method, p_arg, p_argcount); +Error Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { + ERR_FAIL_COND_V(!is_inside_tree(), ERR_UNCONFIGURED); + return get_multiplayer()->rpcp(this, p_peer_id, p_method, p_arg, p_argcount); } Ref<MultiplayerAPI> Node::get_multiplayer() const { @@ -670,10 +659,6 @@ Ref<MultiplayerAPI> Node::get_multiplayer() const { return get_tree()->get_multiplayer(get_path()); } -Vector<Multiplayer::RPCConfig> Node::get_node_rpc_methods() const { - return data.rpc_methods; -} - //////////// end of rpc bool Node::can_process_notification(int p_what) const { @@ -957,6 +942,18 @@ String Node::validate_child_name(Node *p_child) { } #endif +String Node::adjust_name_casing(const String &p_name) { + switch (GLOBAL_GET("editor/node_naming/name_casing").operator int()) { + case NAME_CASING_PASCAL_CASE: + return p_name.to_pascal_case(); + case NAME_CASING_CAMEL_CASE: + return p_name.to_camel_case(); + case NAME_CASING_SNAKE_CASE: + return p_name.to_snake_case(); + } + return p_name; +} + void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { /* Make sure the name is unique */ @@ -1030,19 +1027,8 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co //no name and a new name is needed, create one. name = p_child->get_class(); - // Adjust casing according to project setting. The current type name is expected to be in PascalCase. - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - break; - case NAME_CASING_CAMEL_CASE: { - String n = name; - n[0] = n.to_lower()[0]; - name = n; - } break; - case NAME_CASING_SNAKE_CASE: - name = String(name).camelcase_to_underscore(true); - break; - } + // Adjust casing according to project setting. + name = adjust_name_casing(name); } //quickly test if proposed name exists @@ -1139,7 +1125,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, InternalMode p_internal) { +void Node::add_child(Node *p_child, bool p_force_readable_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 @@ -1148,7 +1134,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name, InternalMode p_i #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_child_name(p_child, p_legible_unique_name); + _validate_child_name(p_child, p_force_readable_name); _add_child_nocheck(p_child, p_child->data.name); if (p_internal == INTERNAL_MODE_FRONT) { @@ -1162,7 +1148,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name, InternalMode p_i } } -void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) { +void Node::add_sibling(Node *p_sibling, bool p_force_readable_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! @@ -1175,7 +1161,7 @@ void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) { internal = INTERNAL_MODE_BACK; } - data.parent->add_child(p_sibling, p_legible_unique_name, internal); + data.parent->add_child(p_sibling, p_force_readable_name, internal); data.parent->_move_child(p_sibling, get_index() + 1); } @@ -1787,8 +1773,8 @@ void Node::remove_from_group(const StringName &p_identifier) { data.grouped.remove(E); } -Array Node::_get_groups() const { - Array groups; +TypedArray<StringName> Node::_get_groups() const { + TypedArray<StringName> groups; List<GroupInfo> gi; get_groups(&gi); for (const GroupInfo &E : gi) { @@ -1930,43 +1916,6 @@ Ref<Tween> Node::create_tween() { return tween; } -void Node::remove_and_skip() { - ERR_FAIL_COND(!data.parent); - - Node *new_owner = get_owner(); - - List<Node *> children; - - while (true) { - bool clear = true; - for (int i = 0; i < data.children.size(); i++) { - Node *c_node = data.children[i]; - if (!c_node->get_owner()) { - continue; - } - - remove_child(c_node); - c_node->_propagate_replace_owner(this, nullptr); - children.push_back(c_node); - clear = false; - break; - } - - if (clear) { - break; - } - } - - while (!children.is_empty()) { - Node *c_node = children.front()->get(); - data.parent->add_child(c_node); - c_node->_propagate_replace_owner(nullptr, new_owner); - children.pop_front(); - } - - data.parent->remove_child(this); -} - void Node::set_scene_file_path(const String &p_scene_file_path) { data.scene_file_path = p_scene_file_path; } @@ -2404,7 +2353,7 @@ void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { if (copy && copytarget) { const Callable copy_callable = Callable(copytarget, E.callable.get_method()); if (!copy->is_connected(E.signal.get_name(), copy_callable)) { - copy->connect(E.signal.get_name(), copy_callable, E.binds, E.flags); + copy->connect(E.signal.get_name(), copy_callable, E.flags); } } } @@ -2490,7 +2439,7 @@ void Node::_replace_connections_target(Node *p_new_target) { c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method())); bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method()); ERR_CONTINUE_MSG(!valid, vformat("Attempt to connect signal '%s.%s' to nonexistent method '%s.%s'.", c.signal.get_object()->get_class(), c.signal.get_name(), c.callable.get_object()->get_class(), c.callable.get_method())); - c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.binds, c.flags); + c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.flags); } } } @@ -2691,21 +2640,19 @@ void Node::clear_internal_tree_resource_paths() { } } -TypedArray<String> Node::get_configuration_warnings() const { - TypedArray<String> ret; +PackedStringArray Node::get_configuration_warnings() const { + PackedStringArray ret; Vector<String> warnings; if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) { - for (int i = 0; i < warnings.size(); i++) { - ret.push_back(warnings[i]); - } + ret.append_array(warnings); } return ret; } String Node::get_configuration_warnings_as_string() const { - TypedArray<String> warnings = get_configuration_warnings(); + PackedStringArray warnings = get_configuration_warnings(); String all_warnings = String(); for (int i = 0; i < warnings.size(); i++) { if (i > 0) { @@ -2713,7 +2660,7 @@ String Node::get_configuration_warnings_as_string() const { } // Format as a bullet point list to make multiple warnings easier to distinguish // from each other. - all_warnings += String::utf8("• ") + String(warnings[i]); + all_warnings += String::utf8("• ") + warnings[i]; } return all_warnings; } @@ -2795,11 +2742,11 @@ void Node::_bind_methods() { GLOBAL_DEF("editor/node_naming/name_casing", NAME_CASING_PASCAL_CASE); ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_casing", PropertyInfo(Variant::INT, "editor/node_naming/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case")); - ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "legible_unique_name"), &Node::add_sibling, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_sibling", "sibling", "force_readable_name"), &Node::add_sibling, DEFVAL(false)); 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", "internal"), &Node::add_child, DEFVAL(false), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("add_child", "node", "force_readable_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", "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)); @@ -2824,10 +2771,8 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_in_group", "group"), &Node::is_in_group); ClassDB::bind_method(D_METHOD("move_child", "child_node", "to_position"), &Node::move_child); ClassDB::bind_method(D_METHOD("get_groups"), &Node::_get_groups); - ClassDB::bind_method(D_METHOD("raise"), &Node::raise); 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", "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); @@ -2888,7 +2833,7 @@ void Node::_bind_methods() { 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("rpc_config", "method", "rpc_mode", "call_local", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(false), DEFVAL(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("rpc_config", "method", "config"), &Node::rpc_config); 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); @@ -2931,7 +2876,7 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_PROCESS); BIND_CONSTANT(NOTIFICATION_PARENTED); BIND_CONSTANT(NOTIFICATION_UNPARENTED); - BIND_CONSTANT(NOTIFICATION_INSTANCED); + BIND_CONSTANT(NOTIFICATION_SCENE_INSTANTIATED); BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN); BIND_CONSTANT(NOTIFICATION_DRAG_END); BIND_CONSTANT(NOTIFICATION_PATH_RENAMED); |