summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--[-rwxr-xr-x]scene/main/node.cpp109
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/scene_tree.cpp24
-rw-r--r--scene/main/scene_tree.h7
-rw-r--r--scene/main/viewport.cpp37
-rw-r--r--scene/main/viewport.h2
6 files changed, 120 insertions, 61 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 01e11962ff..cae368aeca 100755..100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -1198,7 +1198,7 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) {
unique = false;
} else {
//check if exists
- Node **childs = data.children.ptr();
+ Node **childs = data.children.ptrw();
int cc = data.children.size();
for (int i = 0; i < cc; i++) {
@@ -2104,37 +2104,65 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const
ERR_FAIL_COND_V(!node, NULL);
}
- List<PropertyInfo> plist;
-
- get_property_list(&plist);
+ if (get_filename() != "") { //an instance
+ node->set_filename(get_filename());
+ }
StringName script_property_name = CoreStringNames::get_singleton()->_script;
- if (p_flags & DUPLICATE_SCRIPTS) {
- bool is_valid = false;
- Variant script = get(script_property_name, &is_valid);
- if (is_valid) {
- node->set(script_property_name, script);
+ List<const Node *> node_tree;
+ node_tree.push_front(this);
+
+ if (instanced) {
+ // Since nodes in the instanced hierarchy won't be duplicated explicitly, we need to make an inventory
+ // of all the nodes in the tree of the instanced scene in order to transfer the values of the properties
+
+ for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
+ for (int i = 0; i < N->get()->get_child_count(); ++i) {
+
+ // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later
+ if (N->get()->get_child(i)->data.owner != this)
+ continue;
+
+ node_tree.push_back(N->get()->get_child(i));
+ }
}
}
- for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
+ for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) {
- if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
- continue;
- String name = E->get().name;
- if (name == script_property_name)
- continue;
+ Node *current_node = node->get_node(get_path_to(N->get()));
+ ERR_CONTINUE(!current_node);
- Variant value = get(name);
- // Duplicate dictionaries and arrays, mainly needed for __meta__
- if (value.get_type() == Variant::DICTIONARY) {
- value = Dictionary(value).copy();
- } else if (value.get_type() == Variant::ARRAY) {
- value = Array(value).duplicate();
+ if (p_flags & DUPLICATE_SCRIPTS) {
+ bool is_valid = false;
+ Variant script = N->get()->get(script_property_name, &is_valid);
+ if (is_valid) {
+ current_node->set(script_property_name, script);
+ }
}
- node->set(name, value);
+ List<PropertyInfo> plist;
+ N->get()->get_property_list(&plist);
+
+ for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
+
+ if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
+ continue;
+ String name = E->get().name;
+ if (name == script_property_name)
+ continue;
+
+ Variant value = N->get()->get(name);
+ // Duplicate dictionaries and arrays, mainly needed for __meta__
+ if (value.get_type() == Variant::DICTIONARY) {
+ value = Dictionary(value).copy();
+ } else if (value.get_type() == Variant::ARRAY) {
+ value = Array(value).duplicate();
+ }
+
+ current_node->set(name, value);
+ }
}
node->set_name(get_name());
@@ -2502,24 +2530,19 @@ bool Node::has_node_and_resource(const NodePath &p_path) const {
return false;
Node *node = get_node(p_path);
- if (p_path.get_subname_count()) {
+ bool result = false;
- RES r;
- for (int j = 0; j < p_path.get_subname_count(); j++) {
- r = j == 0 ? node->get(p_path.get_subname(j)) : r->get(p_path.get_subname(j));
- if (r.is_null())
- return false;
- }
- }
+ node->get_indexed(p_path.get_subnames(), &result);
- return true;
+ return result;
}
Array Node::_get_node_and_resource(const NodePath &p_path) {
Node *node;
RES res;
- node = get_node_and_resource(p_path, res);
+ Vector<StringName> leftover_path;
+ node = get_node_and_resource(p_path, res, leftover_path);
Array result;
if (node)
@@ -2532,21 +2555,35 @@ Array Node::_get_node_and_resource(const NodePath &p_path) {
else
result.push_back(Variant());
+ result.push_back(NodePath(Vector<StringName>(), leftover_path, false));
+
return result;
}
-Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res) const {
+Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property) const {
Node *node = get_node(p_path);
r_res = RES();
+ r_leftover_subpath = Vector<StringName>();
if (!node)
return NULL;
if (p_path.get_subname_count()) {
- for (int j = 0; j < p_path.get_subname_count(); j++) {
- r_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j));
- ERR_FAIL_COND_V(r_res.is_null(), node);
+ int j = 0;
+ // If not p_last_is_property, we shouldn't consider the last one as part of the resource
+ for (; j < p_path.get_subname_count() - p_last_is_property; j++) {
+ RES new_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j));
+
+ if (new_res.is_null()) {
+ break;
+ }
+
+ r_res = new_res;
+ }
+ for (; j < p_path.get_subname_count(); j++) {
+ // Put the rest of the subpath in the leftover path
+ r_leftover_subpath.push_back(p_path.get_subname(j));
}
}
diff --git a/scene/main/node.h b/scene/main/node.h
index bd0b18c87a..2b71b71c8d 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -245,7 +245,7 @@ public:
Node *get_node(const NodePath &p_path) const;
Node *find_node(const String &p_mask, bool p_recursive = true, bool p_owned = true) const;
bool has_node_and_resource(const NodePath &p_path) const;
- Node *get_node_and_resource(const NodePath &p_path, RES &r_res) const;
+ Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const;
Node *get_parent() const;
_FORCE_INLINE_ SceneTree *get_tree() const {
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index d4be683a2b..deb40800bc 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -127,7 +127,7 @@ void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) {
group_map.erase(E);
}
-void SceneTree::_flush_transform_notifications() {
+void SceneTree::flush_transform_notifications() {
SelfList<Node> *n = xform_change_list.first();
while (n) {
@@ -418,12 +418,12 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) {
if (!input_handled) {
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check
- input_handled = true;
_flush_ugc();
+ // input_handled = true; - no reason to set this as handled
root_lock--;
//MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
} else {
- input_handled = true;
+ // input_handled = true; - no reason to set this as handled
root_lock--;
}
@@ -448,7 +448,7 @@ bool SceneTree::iteration(float p_time) {
current_frame++;
- _flush_transform_notifications();
+ flush_transform_notifications();
MainLoop::iteration(p_time);
physics_process_time = p_time;
@@ -459,7 +459,7 @@ bool SceneTree::iteration(float p_time) {
_notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications();
+ flush_transform_notifications();
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
root_lock--;
@@ -487,7 +487,7 @@ bool SceneTree::idle(float p_time) {
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications();
+ flush_transform_notifications();
_notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
_notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
@@ -503,7 +503,7 @@ bool SceneTree::idle(float p_time) {
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
- _flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
+ flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds");
root_lock--;
@@ -794,6 +794,7 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
Vector3(0, 0, 1)
};
+ /* clang-format off */
int diamond_faces[8 * 3] = {
0, 2, 4,
0, 3, 4,
@@ -804,6 +805,7 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() {
1, 2, 5,
1, 3, 5,
};
+ /* clang-format on */
PoolVector<int> indices;
for (int i = 0; i < 8 * 3; i++)
@@ -1001,7 +1003,7 @@ Array SceneTree::_get_nodes_in_group(const StringName &p_group) {
ret.resize(nc);
- Node **ptr = E->get().nodes.ptr();
+ Node **ptr = E->get().nodes.ptrw();
for (int i = 0; i < nc; i++) {
ret[i] = ptr[i];
@@ -1024,7 +1026,7 @@ void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_li
int nc = E->get().nodes.size();
if (nc == 0)
return;
- Node **ptr = E->get().nodes.ptr();
+ Node **ptr = E->get().nodes.ptrw();
for (int i = 0; i < nc; i++) {
p_list->push_back(ptr[i]);
@@ -1997,9 +1999,9 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int
Variant::CallError ce;
- node->call(name, argp.ptr(), argc, ce);
+ node->call(name, (const Variant **)argp.ptr(), argc, ce);
if (ce.error != Variant::CallError::CALL_OK) {
- String error = Variant::get_call_error_text(node, name, argp.ptr(), argc, ce);
+ String error = Variant::get_call_error_text(node, name, (const Variant **)argp.ptr(), argc, ce);
error = "RPC - " + error;
ERR_PRINTS(error);
}
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index bc3efdc42f..244fc8da62 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -157,7 +157,6 @@ private:
Map<UGCall, Vector<Variant> > unique_group_calls;
bool ugc_locked;
void _flush_ugc();
- void _flush_transform_notifications();
_FORCE_INLINE_ void _update_group_order(Group &g);
void _update_listener();
@@ -344,6 +343,8 @@ public:
void notify_group(const StringName &p_group, int p_notification);
void set_group(const StringName &p_group, const String &p_name, const Variant &p_value);
+ void flush_transform_notifications();
+
virtual void input_text(const String &p_text);
virtual void input_event(const Ref<InputEvent> &p_event);
virtual void init();
@@ -419,8 +420,8 @@ public:
void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink = 1);
-//void change_scene(const String& p_path);
-//Node *get_loaded_scene();
+ //void change_scene(const String& p_path);
+ //Node *get_loaded_scene();
#ifdef TOOLS_ENABLED
void set_edited_scene_root(Node *p_node);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 1f539041fd..4635de81e8 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -69,6 +69,8 @@ void ViewportTexture::setup_local_to_scene() {
ERR_FAIL_COND(!vp);
vp->viewport_textures.insert(this);
+
+ VS::get_singleton()->texture_set_proxy(proxy, vp->texture_rid);
}
void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) {
@@ -105,8 +107,8 @@ Size2 ViewportTexture::get_size() const {
}
RID ViewportTexture::get_rid() const {
- ERR_FAIL_COND_V(!vp, RID());
- return vp->texture_rid;
+ //ERR_FAIL_COND_V(!vp, RID());
+ return proxy;
}
bool ViewportTexture::has_alpha() const {
@@ -147,6 +149,7 @@ ViewportTexture::ViewportTexture() {
vp = NULL;
set_local_to_scene(true);
+ proxy = VS::get_singleton()->texture_create();
}
ViewportTexture::~ViewportTexture() {
@@ -154,6 +157,8 @@ ViewportTexture::~ViewportTexture() {
if (vp) {
vp->viewport_textures.erase(this);
}
+
+ VS::get_singleton()->free(proxy);
}
/////////////////////////////////////
@@ -539,7 +544,7 @@ void Viewport::_notification(int p_what) {
Vector2 point = get_canvas_transform().affine_inverse().xform(pos);
Physics2DDirectSpaceState::ShapeResult res[64];
- int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true);
+ int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true);
for (int i = 0; i < rc; i++) {
if (res[i].collider_id && res[i].collider) {
@@ -622,7 +627,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true);
+ bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true);
ObjectID new_collider = 0;
if (col) {
@@ -658,7 +663,7 @@ void Viewport::_notification(int p_what) {
PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
if (space) {
- bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true);
+ bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true);
ObjectID new_collider = 0;
if (col) {
CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
@@ -931,6 +936,9 @@ void Viewport::_camera_remove(Camera *p_camera) {
cameras.erase(p_camera);
if (camera == p_camera) {
+ if (camera && find_world().is_valid()) {
+ camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
+ }
camera = NULL;
}
}
@@ -1261,12 +1269,9 @@ Transform2D Viewport::_get_input_pre_xform() const {
Vector2 Viewport::_get_window_offset() const {
- /*
- if (parent_control) {
- return (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin();
+ if (get_parent() && get_parent()->has_method("get_global_position")) {
+ return get_parent()->call("get_global_position");
}
- */
-
return Vector2();
}
@@ -1641,6 +1646,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
} else {
+ bool is_handled = false;
+
_gui_sort_modal_stack();
while (!gui.modal_stack.empty()) {
@@ -1658,11 +1665,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
top->notification(Control::NOTIFICATION_MODAL_CLOSE);
top->_modal_stack_remove();
top->hide();
+
+ if (!top->pass_on_modal_close_click()) {
+ is_handled = true;
+ }
} else {
break;
}
}
+ if (is_handled) {
+ get_tree()->set_input_as_handled();
+ return;
+ }
+
//Matrix32 parent_xform;
/*
@@ -2813,6 +2829,7 @@ Viewport::Viewport() {
default_texture.instance();
default_texture->vp = const_cast<Viewport *>(this);
viewport_textures.insert(default_texture.ptr());
+ VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid);
//internal_listener = SpatialSoundServer::get_singleton()->listener_create();
audio_listener = false;
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 6bbd4b26b5..0835e3f69a 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -59,6 +59,8 @@ class ViewportTexture : public Texture {
friend class Viewport;
Viewport *vp;
+ RID proxy;
+
protected:
static void _bind_methods();