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 {
data.C = nullptr;
}
_update_visible_in_tree();
if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) {
if (data.parent) {
@ -217,6 +218,8 @@ void Spatial::_notification(int p_what) {
data.parent = nullptr;
data.C = nullptr;
data.toplevel_active = false;
_update_visible_in_tree();
_disable_client_physics_interpolation();
} break;
case NOTIFICATION_ENTER_WORLD: {
@ -818,6 +821,36 @@ Ref<World> Spatial::get_world() const {
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() {
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
@ -877,6 +910,10 @@ void Spatial::show() {
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();
}
@ -891,10 +928,14 @@ void Spatial::hide() {
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();
}
bool Spatial::is_visible_in_tree() const {
bool Spatial::_is_visible_in_tree_reference() const {
const Spatial *s = this;
while (s) {
@ -1207,6 +1248,7 @@ Spatial::Spatial() :
data.viewport = nullptr;
data.inside_world = false;
data.visible = true;
data.visible_in_tree = true;
data.disable_scale = false;
data.vi_visible = true;
data.merging_allowed = true;

View File

@ -121,6 +121,7 @@ private:
bool notify_transform : 1;
bool visible : 1;
bool visible_in_tree : 1;
bool disable_scale : 1;
// Scene tree interpolation
@ -155,6 +156,9 @@ private:
void _notify_dirty();
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_merging_allowed(bool p_merging_allowed);
@ -293,7 +297,15 @@ public:
bool is_visible() const;
void show();
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();