Skip to content

Commit af2b9be

Browse files
committed
Node3D and CanvasItem children change to LocalVector
1 parent 46c495c commit af2b9be

File tree

4 files changed

+91
-33
lines changed

4 files changed

+91
-33
lines changed

scene/3d/node_3d.cpp

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,15 @@ void Node3D::_propagate_transform_changed(Node3D *p_origin) {
108108
return;
109109
}
110110

111-
for (Node3D *&E : data.children) {
112-
if (E->data.top_level) {
113-
continue; //don't propagate to a top_level
111+
for (uint32_t n = 0; n < data.node3d_children.size(); n++) {
112+
Node3D *s = data.node3d_children[n];
113+
114+
// Don't propagate to a toplevel.
115+
if (!s->data.top_level) {
116+
s->_propagate_transform_changed(p_origin);
114117
}
115-
E->_propagate_transform_changed(p_origin);
116118
}
119+
117120
#ifdef TOOLS_ENABLED
118121
if ((!data.gizmos.is_empty() || data.notify_transform) && !data.ignore_notification && !xform_change.in_list()) {
119122
#else
@@ -148,9 +151,11 @@ void Node3D::_notification(int p_what) {
148151
}
149152

150153
if (data.parent) {
151-
data.C = data.parent->data.children.push_back(this);
152-
} else {
153-
data.C = nullptr;
154+
data.index_in_parent = data.parent->data.node3d_children.size();
155+
data.parent->data.node3d_children.push_back(this);
156+
} else if (data.index_in_parent != UINT32_MAX) {
157+
data.index_in_parent = UINT32_MAX;
158+
ERR_PRINT("Node3D ENTER_TREE detected without EXIT_TREE, recovering.");
154159
}
155160

156161
if (data.top_level && !Engine::get_singleton()->is_editor_hint()) {
@@ -202,11 +207,27 @@ void Node3D::_notification(int p_what) {
202207
if (xform_change.in_list()) {
203208
get_tree()->xform_change_list.remove(&xform_change);
204209
}
205-
if (data.C) {
206-
data.parent->data.children.erase(data.C);
210+
211+
if (data.parent) {
212+
if (data.index_in_parent != UINT32_MAX) {
213+
// Aliases
214+
uint32_t c = data.index_in_parent;
215+
LocalVector<Node3D *> &parent_children = data.parent->data.node3d_children;
216+
217+
parent_children.remove_at_unordered(c);
218+
219+
// After unordered remove, we need to inform the moved child
220+
// what their new id is in the parent children list.
221+
if (parent_children.size() > c) {
222+
parent_children[c]->data.index_in_parent = c;
223+
}
224+
} else {
225+
ERR_PRINT("Node3D index_in_parent unset at EXIT_TREE.");
226+
}
207227
}
228+
data.index_in_parent = UINT32_MAX;
229+
208230
data.parent = nullptr;
209-
data.C = nullptr;
210231
_update_visibility_parent(true);
211232
_disable_client_physics_interpolation();
212233
} break;
@@ -1063,11 +1084,12 @@ void Node3D::_propagate_visibility_changed() {
10631084
}
10641085
#endif
10651086

1066-
for (Node3D *c : data.children) {
1067-
if (!c || !c->data.visible) {
1068-
continue;
1087+
for (uint32_t n = 0; n < data.node3d_children.size(); n++) {
1088+
Node3D *s = data.node3d_children[n];
1089+
1090+
if (s->data.visible) {
1091+
s->_propagate_visibility_changed();
10691092
}
1070-
c->_propagate_visibility_changed();
10711093
}
10721094
}
10731095

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

1315-
for (Node3D *c : data.children) {
1337+
for (Node3D *c : data.node3d_children) {
13161338
c->_update_visibility_parent(false);
13171339
}
13181340
}

scene/3d/node_3d.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,12 @@ class Node3D : public Node {
153153
RID visibility_parent;
154154

155155
Node3D *parent = nullptr;
156-
List<Node3D *> children;
157-
List<Node3D *>::Element *C = nullptr;
156+
157+
// An unordered vector of `Spatial` children only.
158+
// This is a subset of the `Node::children`, purely
159+
// an optimization for faster traversal.
160+
LocalVector<Node3D *> node3d_children;
161+
uint32_t index_in_parent = UINT32_MAX;
158162

159163
ClientPhysicsInterpolationData *client_physics_interpolation_data = nullptr;
160164

scene/main/canvas_item.cpp

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,15 @@ void CanvasItem::_notification(int p_what) {
317317

318318
if (ci) {
319319
parent_visible_in_tree = ci->is_visible_in_tree();
320-
C = ci->children_items.push_back(this);
320+
321+
data.index_in_parent = ci->data.canvas_item_children.size();
322+
ci->data.canvas_item_children.push_back(this);
321323
} else {
324+
if (data.index_in_parent != UINT32_MAX) {
325+
data.index_in_parent = UINT32_MAX;
326+
ERR_PRINT("CanvasItem ENTER_TREE detected without EXIT_TREE, recovering.");
327+
}
328+
322329
CanvasLayer *cl = Object::cast_to<CanvasLayer>(parent);
323330

324331
if (cl) {
@@ -388,10 +395,27 @@ void CanvasItem::_notification(int p_what) {
388395
get_tree()->xform_change_list.remove(&xform_change);
389396
}
390397
_exit_canvas();
391-
if (C) {
392-
Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C);
393-
C = nullptr;
398+
399+
CanvasItem *parent = Object::cast_to<CanvasItem>(get_parent());
400+
if (parent) {
401+
if (data.index_in_parent != UINT32_MAX) {
402+
// Aliases
403+
uint32_t c = data.index_in_parent;
404+
LocalVector<CanvasItem *> &parent_children = parent->data.canvas_item_children;
405+
406+
parent_children.remove_at_unordered(c);
407+
408+
// After unordered remove, we need to inform the moved child
409+
// what their new id is in the parent children list.
410+
if (parent_children.size() > c) {
411+
parent_children[c]->data.index_in_parent = c;
412+
}
413+
} else {
414+
ERR_PRINT("CanvasItem index_in_parent unset at EXIT_TREE.");
415+
}
394416
}
417+
data.index_in_parent = UINT32_MAX;
418+
395419
if (window) {
396420
window->disconnect(SceneStringName(visibility_changed), callable_mp(this, &CanvasItem::_window_visibility_changed));
397421
window = nullptr;
@@ -1056,11 +1080,11 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) {
10561080
}
10571081
}
10581082

1059-
for (CanvasItem *ci : p_node->children_items) {
1060-
if (ci->top_level) {
1061-
continue;
1083+
for (uint32_t n = 0; n < p_node->data.canvas_item_children.size(); n++) {
1084+
CanvasItem *ci = p_node->data.canvas_item_children[n];
1085+
if (!ci->top_level) {
1086+
_notify_transform(ci);
10621087
}
1063-
_notify_transform(ci);
10641088
}
10651089
}
10661090

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

16131637
if (p_propagate) {
1614-
for (CanvasItem *E : children_items) {
1615-
if (!E->top_level && E->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
1616-
E->_update_texture_filter_changed(true);
1638+
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
1639+
CanvasItem *ci = data.canvas_item_children[n];
1640+
1641+
if (!ci->top_level && ci->texture_filter == TEXTURE_FILTER_PARENT_NODE) {
1642+
ci->_update_texture_filter_changed(true);
16171643
}
16181644
}
16191645
}
@@ -1665,9 +1691,10 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) {
16651691
_update_self_texture_repeat(texture_repeat_cache);
16661692

16671693
if (p_propagate) {
1668-
for (CanvasItem *E : children_items) {
1669-
if (!E->top_level && E->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
1670-
E->_update_texture_repeat_changed(true);
1694+
for (uint32_t n = 0; n < data.canvas_item_children.size(); n++) {
1695+
CanvasItem *ci = data.canvas_item_children[n];
1696+
if (!ci->top_level && ci->texture_repeat == TEXTURE_REPEAT_PARENT_NODE) {
1697+
ci->_update_texture_repeat_changed(true);
16711698
}
16721699
}
16731700
}

scene/main/canvas_item.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,13 @@ class CanvasItem : public Node {
8383
Color modulate = Color(1, 1, 1, 1);
8484
Color self_modulate = Color(1, 1, 1, 1);
8585

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

8994
int light_mask = 1;
9095
uint32_t visibility_layer = 1;

0 commit comments

Comments
 (0)