Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 37 additions & 15 deletions scene/3d/node_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,15 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) {
return;
}

for (Node3D *&E : data.children) {
if (E->data.top_level) {
continue; //don't propagate to a top_level
for (uint32_t n = 0; n < data.node3d_children.size(); n++) {
Node3D *s = data.node3d_children[n];

// Don't propagate to a toplevel.
if (!s->data.top_level) {
s->_propagate_transform_changed(p_origin);
}
E->_propagate_transform_changed(p_origin);
}

#ifdef TOOLS_ENABLED
if ((!data.gizmos.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
#else
Expand Down Expand Up @@ -148,9 +151,11 @@ void Node3D::_notification(int p_what) {
}

if (data.parent) {
data.C = data.parent->data.children.push_back(this);
} else {
data.C = nullptr;
data.index_in_parent = data.parent->data.node3d_children.size();
data.parent->data.node3d_children.push_back(this);
} else if (data.index_in_parent != UINT32_MAX) {
data.index_in_parent = UINT32_MAX;
ERR_PRINT("Node3D ENTER_TREE detected without EXIT_TREE, recovering.");
}

if (data.top_level && !Engine::get_singleton()->is_editor_hint()) {
Expand Down Expand Up @@ -202,11 +207,27 @@ void Node3D::_notification(int p_what) {
if (xform_change.in_list()) {
get_tree()->xform_change_list.remove(&xform_change);
}
if (data.C) {
data.parent->data.children.erase(data.C);

if (data.parent) {
if (data.index_in_parent != UINT32_MAX) {
// Aliases
uint32_t c = data.index_in_parent;
LocalVector<Node3D *> &parent_children = data.parent->data.node3d_children;

parent_children.remove_at_unordered(c);

// After unordered remove, we need to inform the moved child
// what their new id is in the parent children list.
if (parent_children.size() > c) {
parent_children[c]->data.index_in_parent = c;
}
} else {
ERR_PRINT("Node3D index_in_parent unset at EXIT_TREE.");
}
}
data.index_in_parent = UINT32_MAX;

data.parent = nullptr;
data.C = nullptr;
_update_visibility_parent(true);
_disable_client_physics_interpolation();
} break;
Expand Down Expand Up @@ -1063,11 +1084,12 @@ void Node3D::_propagate_visibility_changed() {
}
#endif

for (Node3D *c : data.children) {
if (!c || !c->data.visible) {
continue;
for (uint32_t n = 0; n < data.node3d_children.size(); n++) {
Node3D *s = data.node3d_children[n];

if (s->data.visible) {
s->_propagate_visibility_changed();
}
c->_propagate_visibility_changed();
}
}

Expand Down Expand Up @@ -1312,7 +1334,7 @@ void Node3D::_update_visibility_parent(bool p_update_root) {
RS::get_singleton()->instance_set_visibility_parent(vi->get_instance(), data.visibility_parent);
}

for (Node3D *c : data.children) {
for (Node3D *c : data.node3d_children) {
c->_update_visibility_parent(false);
}
}
Expand Down
8 changes: 6 additions & 2 deletions scene/3d/node_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,12 @@ class Node3D : public Node {
RID visibility_parent;

Node3D *parent = nullptr;
List<Node3D *> children;
List<Node3D *>::Element *C = nullptr;

// An unordered vector of `Spatial` children only.
// This is a subset of the `Node::children`, purely
// an optimization for faster traversal.
LocalVector<Node3D *> node3d_children;
uint32_t index_in_parent = UINT32_MAX;

ClientPhysicsInterpolationData *client_physics_interpolation_data = nullptr;

Expand Down
55 changes: 41 additions & 14 deletions scene/main/canvas_item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,8 +317,15 @@ void CanvasItem::_notification(int p_what) {

if (ci) {
parent_visible_in_tree = ci->is_visible_in_tree();
C = ci->children_items.push_back(this);

data.index_in_parent = ci->data.canvas_item_children.size();
ci->data.canvas_item_children.push_back(this);
} else {
if (data.index_in_parent != UINT32_MAX) {
data.index_in_parent = UINT32_MAX;
ERR_PRINT("CanvasItem ENTER_TREE detected without EXIT_TREE, recovering.");
}

CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);

if (cl) {
Expand Down Expand Up @@ -388,10 +395,27 @@ void CanvasItem::_notification(int p_what) {
get_tree()->xform_change_list.remove(&xform_change);
}
_exit_canvas();
if (C) {
Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C);
C = nullptr;

CanvasItem *parent = Object::cast_to<CanvasItem>(get_parent());
if (parent) {
if (data.index_in_parent != UINT32_MAX) {
// Aliases
uint32_t c = data.index_in_parent;
LocalVector<CanvasItem *> &parent_children = parent->data.canvas_item_children;

parent_children.remove_at_unordered(c);

// After unordered remove, we need to inform the moved child
// what their new id is in the parent children list.
if (parent_children.size() > c) {
parent_children[c]->data.index_in_parent = c;
}
} else {
ERR_PRINT("CanvasItem index_in_parent unset at EXIT_TREE.");
}
}
data.index_in_parent = UINT32_MAX;

if (window) {
window->disconnect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
window = nullptr;
Expand Down Expand Up @@ -1056,11 +1080,11 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) {
}
}

for (CanvasItem *ci : p_node->children_items) {
if (ci->top_level) {
continue;
for (uint32_t n = 0; n < p_node->data.canvas_item_children.size(); n++) {
CanvasItem *ci = p_node->data.canvas_item_children[n];
if (!ci->top_level) {
_notify_transform(ci);
}
_notify_transform(ci);
}
}

Expand Down Expand Up @@ -1611,9 +1635,11 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) {
_update_self_texture_filter(texture_filter_cache);

if (p_propagate) {
for (CanvasItem *E : children_items) {
if (!E->top_level && E->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
E->_update_texture_filter_changed(true);
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
CanvasItem *ci = data.canvas_item_children[n];

if (!ci->top_level && ci->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
ci->_update_texture_filter_changed(true);
}
}
}
Expand Down Expand Up @@ -1665,9 +1691,10 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
_update_self_texture_repeat(texture_repeat_cache);

if (p_propagate) {
for (CanvasItem *E : children_items) {
if (!E->top_level && E->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
E->_update_texture_repeat_changed(true);
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
CanvasItem *ci = data.canvas_item_children[n];
if (!ci->top_level && ci->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
ci->_update_texture_repeat_changed(true);
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions scene/main/canvas_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,13 @@ class CanvasItem : public Node {
Color modulate = Color(1, 1, 1, 1);
Color self_modulate = Color(1, 1, 1, 1);

List<CanvasItem *> children_items;
List<CanvasItem *>::Element *C = nullptr;
struct Data {
// An unordered vector of `CanvasItem` children only.
// This is a subset of the `Node::children`, purely
// an optimization for faster traversal.
LocalVector<CanvasItem *> canvas_item_children;
uint32_t index_in_parent = UINT32_MAX;
} data;

int light_mask = 1;
uint32_t visibility_layer = 1;
Expand Down
Loading