summaryrefslogtreecommitdiff
path: root/scene/main/node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main/node.cpp')
-rw-r--r--scene/main/node.cpp181
1 files changed, 113 insertions, 68 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 05409b7bfe..26c4e01d3f 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -5,8 +5,8 @@
/* GODOT ENGINE */
/* https://godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -41,10 +41,6 @@
#include "scene/scene_string_names.h"
#include "viewport.h"
-#ifdef TOOLS_ENABLED
-#include "editor/editor_settings.h"
-#endif
-
#include <stdint.h>
VARIANT_ENUM_CAST(Node::ProcessMode);
@@ -70,7 +66,9 @@ void Node::_notification(int p_notification) {
if (data.parent) {
data.process_owner = data.parent->data.process_owner;
} else {
- data.process_owner = nullptr;
+ ERR_PRINT("The root node can't be set to Inherit process mode, reverting to Pausable instead.");
+ data.process_mode = PROCESS_MODE_PAUSABLE;
+ data.process_owner = this;
}
} else {
data.process_owner = this;
@@ -112,11 +110,11 @@ void Node::_notification(int p_notification) {
memdelete(data.path_cache);
data.path_cache = nullptr;
}
- if (data.filename.length()) {
- get_multiplayer()->scene_enter_exit_notify(data.filename, this, false);
+ if (data.scene_file_path.length()) {
+ get_multiplayer()->scene_enter_exit_notify(data.scene_file_path, this, false);
}
} break;
- case NOTIFICATION_PATH_CHANGED: {
+ case NOTIFICATION_PATH_RENAMED: {
if (data.path_cache) {
memdelete(data.path_cache);
data.path_cache = nullptr;
@@ -144,9 +142,9 @@ void Node::_notification(int p_notification) {
GDVIRTUAL_CALL(_ready);
- if (data.filename.length()) {
+ if (data.scene_file_path.length()) {
ERR_FAIL_COND(!is_inside_tree());
- get_multiplayer()->scene_enter_exit_notify(data.filename, this, true);
+ get_multiplayer()->scene_enter_exit_notify(data.scene_file_path, this, true);
}
} break;
@@ -209,8 +207,8 @@ void Node::_propagate_enter_tree() {
data.inside_tree = true;
- for (Map<StringName, GroupData>::Element *E = data.grouped.front(); E; E = E->next()) {
- E->get().group = data.tree->add_to_group(E->key(), this);
+ for (KeyValue<StringName, GroupData> &E : data.grouped) {
+ E.value.group = data.tree->add_to_group(E.key, this);
}
notification(NOTIFICATION_ENTER_TREE);
@@ -233,7 +231,7 @@ void Node::_propagate_enter_tree() {
data.blocked--;
#ifdef DEBUG_ENABLED
- SceneDebugger::add_to_cache(data.filename, this);
+ SceneDebugger::add_to_cache(data.scene_file_path, this);
#endif
// enter groups
}
@@ -251,7 +249,7 @@ void Node::_propagate_exit_tree() {
//block while removing children
#ifdef DEBUG_ENABLED
- SceneDebugger::remove_from_cache(data.filename, this);
+ SceneDebugger::remove_from_cache(data.scene_file_path, this);
#endif
data.blocked++;
@@ -272,9 +270,9 @@ void Node::_propagate_exit_tree() {
// exit groups
- for (Map<StringName, GroupData>::Element *E = data.grouped.front(); E; E = E->next()) {
- data.tree->remove_from_group(E->key(), this);
- E->get().group = nullptr;
+ for (KeyValue<StringName, GroupData> &E : data.grouped) {
+ data.tree->remove_from_group(E.key, this);
+ E.value.group = nullptr;
}
data.viewport = nullptr;
@@ -334,7 +332,7 @@ void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) {
int motion_from = MIN(p_pos, p_child->data.pos);
int motion_to = MAX(p_pos, p_child->data.pos);
- data.children.remove(p_child->data.pos);
+ data.children.remove_at(p_child->data.pos);
data.children.insert(p_pos, p_child);
if (data.tree) {
@@ -351,9 +349,9 @@ void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) {
for (int i = motion_from; i <= motion_to; i++) {
data.children[i]->notification(NOTIFICATION_MOVED_IN_PARENT);
}
- for (const Map<StringName, GroupData>::Element *E = p_child->data.grouped.front(); E; E = E->next()) {
- if (E->get().group) {
- E->get().group->changed = true;
+ for (const KeyValue<StringName, GroupData> &E : p_child->data.grouped) {
+ if (E.value.group) {
+ E.value.group->changed = true;
}
}
@@ -436,18 +434,18 @@ void Node::set_process_mode(ProcessMode p_mode) {
bool prev_can_process = can_process();
bool prev_enabled = _is_enabled();
- data.process_mode = p_mode;
-
- if (data.process_mode == PROCESS_MODE_INHERIT) {
+ if (p_mode == PROCESS_MODE_INHERIT) {
if (data.parent) {
- data.process_owner = data.parent->data.owner;
+ data.process_owner = data.parent->data.process_owner;
} else {
- data.process_owner = nullptr;
+ ERR_FAIL_MSG("The root node can't be set to Inherit process mode.");
}
} else {
data.process_owner = this;
}
+ data.process_mode = p_mode;
+
bool next_can_process = can_process();
bool next_enabled = _is_enabled();
@@ -538,12 +536,13 @@ bool Node::is_multiplayer_authority() const {
/***** RPC CONFIG ********/
-uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc_mode, Multiplayer::TransferMode p_transfer_mode, int p_channel) {
+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);
}
@@ -554,6 +553,7 @@ uint16_t Node::rpc_config(const StringName &p_method, Multiplayer::RPCMode p_rpc
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);
}
@@ -702,6 +702,9 @@ bool Node::_can_process(bool p_paused) const {
process_mode = data.process_mode;
}
+ // The owner can't be set to inherit, must be a bug.
+ ERR_FAIL_COND_V(process_mode == PROCESS_MODE_INHERIT, false);
+
if (process_mode == PROCESS_MODE_DISABLED) {
return false;
} else if (process_mode == PROCESS_MODE_ALWAYS) {
@@ -889,14 +892,14 @@ void Node::_set_name_nocheck(const StringName &p_name) {
void Node::set_name(const String &p_name) {
String name = p_name.validate_node_name();
- ERR_FAIL_COND(name == "");
+ ERR_FAIL_COND(name.is_empty());
data.name = name;
if (data.parent) {
data.parent->_validate_child_name(this);
}
- propagate_notification(NOTIFICATION_PATH_CHANGED);
+ propagate_notification(NOTIFICATION_PATH_RENAMED);
if (is_inside_tree()) {
emit_signal(SNAME("renamed"));
@@ -905,17 +908,12 @@ void Node::set_name(const String &p_name) {
}
}
-static bool node_hrcr = false;
static SafeRefCount node_hrcr_count;
void Node::init_node_hrcr() {
node_hrcr_count.init(1);
}
-void Node::set_human_readable_collision_renaming(bool p_enabled) {
- node_hrcr = p_enabled;
-}
-
#ifdef TOOLS_ENABLED
String Node::validate_child_name(Node *p_child) {
StringName name = p_child->data.name;
@@ -927,9 +925,8 @@ String Node::validate_child_name(Node *p_child) {
void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
/* Make sure the name is unique */
- if (node_hrcr || p_force_human_readable) {
+ if (p_force_human_readable) {
//this approach to autoset node names is human readable but very slow
- //it's turned on while running in the editor
StringName name = p_child->data.name;
_generate_serial_child_name(p_child, name);
@@ -1211,7 +1208,7 @@ void Node::remove_child(Node *p_child) {
remove_child_notify(p_child);
p_child->notification(NOTIFICATION_UNPARENTED);
- data.children.remove(idx);
+ data.children.remove_at(idx);
//update pointer and size
child_count = data.children.size();
@@ -1673,10 +1670,10 @@ Array Node::_get_groups() const {
}
void Node::get_groups(List<GroupInfo> *p_groups) const {
- for (const Map<StringName, GroupData>::Element *E = data.grouped.front(); E; E = E->next()) {
+ for (const KeyValue<StringName, GroupData> &E : data.grouped) {
GroupInfo gi;
- gi.name = E->key();
- gi.persistent = E->get().persistent;
+ gi.name = E.key;
+ gi.persistent = E.value.persistent;
p_groups->push_back(gi);
}
}
@@ -1684,8 +1681,8 @@ void Node::get_groups(List<GroupInfo> *p_groups) const {
int Node::get_persistent_group_count() const {
int count = 0;
- for (const Map<StringName, GroupData>::Element *E = data.grouped.front(); E; E = E->next()) {
- if (E->get().persistent) {
+ for (const KeyValue<StringName, GroupData> &E : data.grouped) {
+ if (E.value.persistent) {
count += 1;
}
}
@@ -1841,12 +1838,12 @@ void Node::remove_and_skip() {
data.parent->remove_child(this);
}
-void Node::set_filename(const String &p_filename) {
- data.filename = p_filename;
+void Node::set_scene_file_path(const String &p_scene_file_path) {
+ data.scene_file_path = p_scene_file_path;
}
-String Node::get_filename() const {
- return data.filename;
+String Node::get_scene_file_path() const {
+ return data.scene_file_path;
}
void Node::set_editor_description(const String &p_editor_description) {
@@ -1896,6 +1893,56 @@ Node *Node::get_deepest_editable_node(Node *p_start_node) const {
return node;
}
+#ifdef TOOLS_ENABLED
+void Node::set_property_pinned(const String &p_property, bool p_pinned) {
+ bool current_pinned = false;
+ bool has_pinned = has_meta("_edit_pinned_properties_");
+ Array pinned;
+ String psa = get_property_store_alias(p_property);
+ if (has_pinned) {
+ pinned = get_meta("_edit_pinned_properties_");
+ current_pinned = pinned.has(psa);
+ }
+
+ if (current_pinned != p_pinned) {
+ if (p_pinned) {
+ pinned.append(psa);
+ if (!has_pinned) {
+ set_meta("_edit_pinned_properties_", pinned);
+ }
+ } else {
+ pinned.erase(psa);
+ if (pinned.is_empty()) {
+ remove_meta("_edit_pinned_properties_");
+ }
+ }
+ }
+}
+
+bool Node::is_property_pinned(const StringName &p_property) const {
+ if (!has_meta("_edit_pinned_properties_")) {
+ return false;
+ }
+ Array pinned = get_meta("_edit_pinned_properties_");
+ String psa = get_property_store_alias(p_property);
+ return pinned.has(psa);
+}
+
+StringName Node::get_property_store_alias(const StringName &p_property) const {
+ return p_property;
+}
+#endif
+
+void Node::get_storable_properties(Set<StringName> &r_storable_properties) const {
+ List<PropertyInfo> pi;
+ get_property_list(&pi);
+ for (List<PropertyInfo>::Element *E = pi.front(); E; E = E->next()) {
+ if ((E->get().usage & PROPERTY_USAGE_STORAGE)) {
+ r_storable_properties.insert(E->get().name);
+ }
+ }
+}
+
String Node::to_string() {
if (get_script_instance()) {
bool valid;
@@ -1943,8 +1990,8 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
nip->set_instance_path(ip->get_instance_path());
node = nip;
- } else if ((p_flags & DUPLICATE_USE_INSTANCING) && get_filename() != String()) {
- Ref<PackedScene> res = ResourceLoader::load(get_filename());
+ } else if ((p_flags & DUPLICATE_USE_INSTANCING) && !get_scene_file_path().is_empty()) {
+ Ref<PackedScene> res = ResourceLoader::load(get_scene_file_path());
ERR_FAIL_COND_V(res.is_null(), nullptr);
PackedScene::GenEditState ges = PackedScene::GEN_EDIT_STATE_DISABLED;
#ifdef TOOLS_ENABLED
@@ -1967,8 +2014,8 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
ERR_FAIL_COND_V(!node, nullptr);
}
- if (get_filename() != "") { //an instance
- node->set_filename(get_filename());
+ if (!get_scene_file_path().is_empty()) { //an instance
+ node->set_scene_file_path(get_scene_file_path());
node->data.editable_instance = data.editable_instance;
}
@@ -1999,7 +2046,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
node_tree.push_back(descendant);
- if (descendant->get_filename() != "" && instance_roots.has(descendant->get_owner())) {
+ if (!descendant->get_scene_file_path().is_empty() && instance_roots.has(descendant->get_owner())) {
instance_roots.push_back(descendant);
}
}
@@ -2308,7 +2355,7 @@ void Node::replace_by(Node *p_node, bool p_keep_groups) {
owned_by_owner[i]->set_owner(owner);
}
- p_node->set_filename(get_filename());
+ p_node->set_scene_file_path(get_scene_file_path());
}
void Node::_replace_connections_target(Node *p_new_target) {
@@ -2531,17 +2578,11 @@ NodePath Node::get_import_path() const {
}
static void _add_nodes_to_options(const Node *p_base, const Node *p_node, List<String> *r_options) {
-#ifdef TOOLS_ENABLED
- const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\"";
-#else
- const String quote_style = "\"";
-#endif
-
if (p_node != p_base && !p_node->get_owner()) {
return;
}
String n = p_base->get_path_to(p_node);
- r_options->push_back(n.quote(quote_style));
+ r_options->push_back(n.quote());
for (int i = 0; i < p_node->get_child_count(); i++) {
_add_nodes_to_options(p_base, p_node->get_child(i), r_options);
}
@@ -2688,8 +2729,8 @@ void Node::_bind_methods() {
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);
- ClassDB::bind_method(D_METHOD("get_filename"), &Node::get_filename);
+ ClassDB::bind_method(D_METHOD("set_scene_file_path", "scene_file_path"), &Node::set_scene_file_path);
+ ClassDB::bind_method(D_METHOD("get_scene_file_path"), &Node::get_scene_file_path);
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_physics_process", "enable"), &Node::set_physics_process);
@@ -2745,7 +2786,7 @@ void Node::_bind_methods() {
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(Multiplayer::TRANSFER_MODE_RELIABLE), DEFVAL(0));
+ 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("set_editor_description", "editor_description"), &Node::set_editor_description);
ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description);
@@ -2753,7 +2794,11 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("_set_import_path", "import_path"), &Node::set_import_path);
ClassDB::bind_method(D_METHOD("_get_import_path"), &Node::get_import_path);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
+#ifdef TOOLS_ENABLED
+ ClassDB::bind_method(D_METHOD("_set_property_pinned", "property", "pinned"), &Node::set_property_pinned);
+#endif
+
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "_import_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_import_path", "_get_import_path");
{
MethodInfo mi;
@@ -2784,7 +2829,7 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_INSTANCED);
BIND_CONSTANT(NOTIFICATION_DRAG_BEGIN);
BIND_CONSTANT(NOTIFICATION_DRAG_END);
- BIND_CONSTANT(NOTIFICATION_PATH_CHANGED);
+ BIND_CONSTANT(NOTIFICATION_PATH_RENAMED);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE);
@@ -2834,7 +2879,7 @@ void Node::_bind_methods() {
ADD_SIGNAL(MethodInfo("tree_exited"));
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_filename", "get_filename");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "scene_file_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_scene_file_path", "get_scene_file_path");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_owner", "get_owner");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "", "get_multiplayer");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_custom_multiplayer", "get_custom_multiplayer");
@@ -2844,7 +2889,7 @@ void Node::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "process_priority"), "set_process_priority", "get_process_priority");
ADD_GROUP("Editor Description", "editor_");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT), "set_editor_description", "get_editor_description");
GDVIRTUAL_BIND(_process, "delta");
GDVIRTUAL_BIND(_physics_process, "delta");