Merge pull request #107702 from lawnjelly/faster_children_iteration

[3.x] Fast child iteration in `Node`, `Spatial`, `CanvasItem`
This commit is contained in:
lawnjelly
2025-10-01 05:18:20 +01:00
committed by GitHub
5 changed files with 36 additions and 25 deletions

View File

@ -194,6 +194,15 @@ public:
return data[p_index];
}
_FORCE_INLINE_ const T &get_unchecked(U p_index) const {
DEV_ASSERT(p_index < count);
return data[p_index];
}
_FORCE_INLINE_ T &get_unchecked(U p_index) {
DEV_ASSERT(p_index < count);
return data[p_index];
}
void fill(T p_val) {
for (U i = 0; i < count; i++) {
data[i] = p_val;

View File

@ -1029,8 +1029,10 @@ void CanvasItem::_notify_transform(CanvasItem *p_node) {
}
}
CanvasItem **children = p_node->data.canvas_item_children.ptr();
for (uint32_t n = 0; n < p_node->data.canvas_item_children.size(); n++) {
CanvasItem *ci = p_node->data.canvas_item_children[n];
CanvasItem *ci = children[n];
if (!ci->toplevel) {
_notify_transform(ci);
}

View File

@ -104,10 +104,10 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) {
return; //already dirty
*/
data.children_lock++;
Spatial **children = data.spatial_children.ptr();
for (uint32_t n = 0; n < data.spatial_children.size(); n++) {
Spatial *s = data.spatial_children[n];
Spatial *s = children[n];
// Don't propagate to a toplevel.
if (!s->data.toplevel_active) {
@ -123,8 +123,6 @@ void Spatial::_propagate_transform_changed(Spatial *p_origin) {
get_tree()->xform_change_list.add(&xform_change);
}
data.dirty |= DIRTY_GLOBAL | DIRTY_GLOBAL_INTERPOLATED;
data.children_lock--;
}
void Spatial::notification_callback(int p_message_type) {
@ -872,7 +870,7 @@ void Spatial::_propagate_visibility_changed() {
#endif
for (uint32_t n = 0; n < data.spatial_children.size(); n++) {
Spatial *s = data.spatial_children[n];
Spatial *s = data.spatial_children.get_unchecked(n);
if (s->data.visible) {
s->_propagate_visibility_changed();
@ -901,7 +899,7 @@ void Spatial::_propagate_merging_allowed(bool p_merging_allowed) {
data.merging_allowed = p_merging_allowed;
for (uint32_t n = 0; n < data.spatial_children.size(); n++) {
Spatial *s = data.spatial_children[n];
Spatial *s = data.spatial_children.get_unchecked(n);
s->_propagate_merging_allowed(p_merging_allowed);
}
}
@ -1250,7 +1248,6 @@ Spatial::Spatial() :
_define_ancestry(AncestralClass::SPATIAL);
data.dirty = DIRTY_NONE;
data.children_lock = 0;
data.ignore_notification = false;
data.toplevel = false;

View File

@ -133,7 +133,6 @@ private:
bool merging_allowed : 1;
int children_lock;
Spatial *parent;
// An unordered vector of `Spatial` children only.

View File

@ -183,7 +183,7 @@ void Node::_propagate_ready() {
data.ready_notified = true;
data.blocked++;
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->_propagate_ready();
data.children.get_unchecked(i)->_propagate_ready();
}
data.blocked--;
@ -235,7 +235,7 @@ void Node::_propagate_physics_interpolation_reset_requested(bool p_requested) {
data.blocked++;
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->_propagate_physics_interpolation_reset_requested(p_requested);
data.children.get_unchecked(i)->_propagate_physics_interpolation_reset_requested(p_requested);
}
data.blocked--;
}
@ -281,8 +281,9 @@ void Node::_propagate_enter_tree() {
//block while adding children
for (int i = 0; i < data.children.size(); i++) {
if (!data.children[i]->is_inside_tree()) { // could have been added in enter_tree
data.children[i]->_propagate_enter_tree();
Node *child = data.children.get_unchecked(i);
if (!child->is_inside_tree()) { // could have been added in enter_tree
child->_propagate_enter_tree();
}
}
@ -429,7 +430,7 @@ void Node::move_child(Node *p_child, int p_pos) {
data.blocked++;
//new pos first
for (int i = motion_from; i <= motion_to; i++) {
data.children[i]->data.pos = i;
data.children.get_unchecked(i)->data.pos = i;
}
// notification second
move_child_notify(p_child);
@ -456,7 +457,7 @@ void Node::_propagate_groups_dirty() {
}
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->_propagate_groups_dirty();
data.children.get_unchecked(i)->_propagate_groups_dirty();
}
}
@ -563,9 +564,11 @@ void Node::_propagate_pause_owner(Node *p_owner) {
void Node::_propagate_pause_change_notification(int p_notification) {
notification(p_notification);
Node **children = data.children.ptr();
for (int i = 0; i < data.children.size(); i++) {
if (data.children[i]->data.pause_mode == PAUSE_MODE_INHERIT) {
data.children[i]->_propagate_pause_change_notification(p_notification);
if (children[i]->data.pause_mode == PAUSE_MODE_INHERIT) {
children[i]->_propagate_pause_change_notification(p_notification);
}
}
}
@ -575,7 +578,7 @@ void Node::set_network_master(int p_peer_id, bool p_recursive) {
if (p_recursive) {
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->set_network_master(p_peer_id, true);
data.children.get_unchecked(i)->set_network_master(p_peer_id, true);
}
}
}
@ -1400,7 +1403,8 @@ int Node::get_child_count() const {
Node *Node::get_child(int p_index) const {
ERR_FAIL_INDEX_V(p_index, data.children.size(), nullptr);
return data.children[p_index];
// Index already checked above, can use unsafe version here.
return data.children.get_unchecked(p_index);
}
Node *Node::_get_child_by_name(const StringName &p_name) const {
@ -1468,7 +1472,7 @@ Node *Node::get_node_or_null(const NodePath &p_path) const {
next = nullptr;
for (int j = 0; j < current->data.children.size(); j++) {
Node *child = current->data.children[j];
Node *child = current->data.children.get_unchecked(j);
if (child->data.name == name) {
next = child;
@ -1936,7 +1940,7 @@ void Node::_print_tree(const Node *p_node) {
void Node::_propagate_reverse_notification(int p_notification) {
data.blocked++;
for (int i = data.children.size() - 1; i >= 0; i--) {
data.children[i]->_propagate_reverse_notification(p_notification);
data.children.get_unchecked(i)->_propagate_reverse_notification(p_notification);
}
notification(p_notification, true);
@ -1953,7 +1957,7 @@ void Node::_propagate_deferred_notification(int p_notification, bool p_reverse)
}
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->_propagate_deferred_notification(p_notification, p_reverse);
data.children.get_unchecked(i)->_propagate_deferred_notification(p_notification, p_reverse);
}
if (p_reverse) {
@ -1968,7 +1972,7 @@ void Node::propagate_notification(int p_notification) {
notification(p_notification);
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->propagate_notification(p_notification);
data.children.get_unchecked(i)->propagate_notification(p_notification);
}
data.blocked--;
}
@ -1981,7 +1985,7 @@ void Node::propagate_call(const StringName &p_method, const Array &p_args, const
}
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->propagate_call(p_method, p_args, p_parent_first);
data.children.get_unchecked(i)->propagate_call(p_method, p_args, p_parent_first);
}
if (!p_parent_first && has_method(p_method)) {
@ -1998,7 +2002,7 @@ void Node::_propagate_replace_owner(Node *p_owner, Node *p_by_owner) {
data.blocked++;
for (int i = 0; i < data.children.size(); i++) {
data.children[i]->_propagate_replace_owner(p_owner, p_by_owner);
data.children.get_unchecked(i)->_propagate_replace_owner(p_owner, p_by_owner);
}
data.blocked--;
}