Merge pull request #107324 from lawnjelly/is_vis_in_tree

[3.x] Pre-calculate `is_visible_in_tree()`
This commit is contained in:
lawnjelly 2025-06-12 15:23:59 +01:00 committed by GitHub
commit 67265bacd5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 56 additions and 2 deletions

View File

@ -158,6 +158,7 @@ void Spatial::_notification(int p_what) {
} else { } else {
data.C = nullptr; data.C = nullptr;
} }
_update_visible_in_tree();
if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) { if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) {
if (data.parent) { if (data.parent) {
@ -217,6 +218,8 @@ void Spatial::_notification(int p_what) {
data.parent = nullptr; data.parent = nullptr;
data.C = nullptr; data.C = nullptr;
data.toplevel_active = false; data.toplevel_active = false;
_update_visible_in_tree();
_disable_client_physics_interpolation(); _disable_client_physics_interpolation();
} break; } break;
case NOTIFICATION_ENTER_WORLD: { case NOTIFICATION_ENTER_WORLD: {
@ -818,6 +821,36 @@ Ref<World> Spatial::get_world() const {
return data.viewport->find_world(); return data.viewport->find_world();
} }
void Spatial::_update_visible_in_tree() {
Spatial *parent = get_parent_spatial();
bool propagate_visible = parent ? parent->data.visible_in_tree : true;
// Only propagate visible when entering tree if we are visible.
propagate_visible &= is_visible();
_propagate_visible_in_tree(propagate_visible);
}
void Spatial::_propagate_visible_in_tree(bool p_visible_in_tree) {
// If any node is invisible, the propagation changes to invisible below.
p_visible_in_tree &= is_visible();
// No change.
if (data.visible_in_tree == p_visible_in_tree) {
return;
}
data.visible_in_tree = p_visible_in_tree;
for (int32_t n = 0; n < get_child_count(); n++) {
Spatial *s = Object::cast_to<Spatial>(get_child(n));
if (s) {
s->_propagate_visible_in_tree(p_visible_in_tree);
}
}
}
void Spatial::_propagate_visibility_changed() { void Spatial::_propagate_visibility_changed() {
notification(NOTIFICATION_VISIBILITY_CHANGED); notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed); emit_signal(SceneStringNames::get_singleton()->visibility_changed);
@ -877,6 +910,10 @@ void Spatial::show() {
return; return;
} }
bool parent_visible = get_parent_spatial() ? get_parent_spatial()->data.visible_in_tree : true;
if (parent_visible) {
_propagate_visible_in_tree(true);
}
_propagate_visibility_changed(); _propagate_visibility_changed();
} }
@ -891,10 +928,14 @@ void Spatial::hide() {
return; return;
} }
bool parent_visible = get_parent_spatial() ? get_parent_spatial()->data.visible_in_tree : true;
if (parent_visible) {
_propagate_visible_in_tree(false);
}
_propagate_visibility_changed(); _propagate_visibility_changed();
} }
bool Spatial::is_visible_in_tree() const { bool Spatial::_is_visible_in_tree_reference() const {
const Spatial *s = this; const Spatial *s = this;
while (s) { while (s) {
@ -1207,6 +1248,7 @@ Spatial::Spatial() :
data.viewport = nullptr; data.viewport = nullptr;
data.inside_world = false; data.inside_world = false;
data.visible = true; data.visible = true;
data.visible_in_tree = true;
data.disable_scale = false; data.disable_scale = false;
data.vi_visible = true; data.vi_visible = true;
data.merging_allowed = true; data.merging_allowed = true;

View File

@ -121,6 +121,7 @@ private:
bool notify_transform : 1; bool notify_transform : 1;
bool visible : 1; bool visible : 1;
bool visible_in_tree : 1;
bool disable_scale : 1; bool disable_scale : 1;
// Scene tree interpolation // Scene tree interpolation
@ -155,6 +156,9 @@ private:
void _notify_dirty(); void _notify_dirty();
void _propagate_transform_changed(Spatial *p_origin); void _propagate_transform_changed(Spatial *p_origin);
void _update_visible_in_tree();
bool _is_visible_in_tree_reference() const;
void _propagate_visible_in_tree(bool p_visible_in_tree);
void _propagate_visibility_changed(); void _propagate_visibility_changed();
void _propagate_merging_allowed(bool p_merging_allowed); void _propagate_merging_allowed(bool p_merging_allowed);
@ -293,7 +297,15 @@ public:
bool is_visible() const; bool is_visible() const;
void show(); void show();
void hide(); void hide();
bool is_visible_in_tree() const; bool is_visible_in_tree() const {
#if DEV_ENABLED
// As this is newly introduced, regression test the old method against the new in DEV builds.
// If no regressions, this can be removed after a beta.
bool visible = _is_visible_in_tree_reference();
ERR_FAIL_COND_V_MSG(data.visible_in_tree != visible, visible, "is_visible_in_tree regression detected, recovering.");
#endif
return data.visible_in_tree;
}
void force_update_transform(); void force_update_transform();