Skip to content

Commit 9c97189

Browse files
committed
Pre-calculate is_visible_in_tree()
1 parent b94cd9b commit 9c97189

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

scene/3d/spatial.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ void Spatial::_notification(int p_what) {
157157
} else {
158158
data.C = nullptr;
159159
}
160+
_update_visible_in_tree();
160161

161162
if (data.toplevel && !Engine::get_singleton()->is_editor_hint()) {
162163
if (data.parent) {
@@ -216,6 +217,8 @@ void Spatial::_notification(int p_what) {
216217
data.parent = nullptr;
217218
data.C = nullptr;
218219
data.toplevel_active = false;
220+
221+
_update_visible_in_tree();
219222
_disable_client_physics_interpolation();
220223
} break;
221224
case NOTIFICATION_ENTER_WORLD: {
@@ -732,6 +735,36 @@ Ref<World> Spatial::get_world() const {
732735
return data.viewport->find_world();
733736
}
734737

738+
void Spatial::_update_visible_in_tree() {
739+
Spatial *parent = get_parent_spatial();
740+
741+
bool propagate_visible = parent ? parent->data.visible_in_tree : true;
742+
743+
// Only propagate visible when entering tree if we are visible.
744+
propagate_visible &= is_visible();
745+
746+
_propagate_visible_in_tree(this, propagate_visible);
747+
}
748+
749+
void Spatial::_propagate_visible_in_tree(Spatial *p_node, bool p_visible_in_tree) {
750+
// If any node is invisible, the propagation changes to invisible below.
751+
p_visible_in_tree &= p_node->is_visible();
752+
753+
// No change.
754+
if (p_node->data.visible_in_tree == p_visible_in_tree) {
755+
return;
756+
}
757+
758+
p_node->data.visible_in_tree = p_visible_in_tree;
759+
760+
for (int32_t n = 0; n < p_node->get_child_count(); n++) {
761+
Spatial *s = Object::cast_to<Spatial>(p_node->get_child(n));
762+
if (s) {
763+
_propagate_visible_in_tree(s, p_visible_in_tree);
764+
}
765+
}
766+
}
767+
735768
void Spatial::_propagate_visibility_changed() {
736769
notification(NOTIFICATION_VISIBILITY_CHANGED);
737770
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
@@ -791,6 +824,10 @@ void Spatial::show() {
791824
return;
792825
}
793826

827+
bool parent_visible = get_parent_spatial() ? get_parent_spatial()->data.visible_in_tree : true;
828+
if (parent_visible) {
829+
_propagate_visible_in_tree(this, true);
830+
}
794831
_propagate_visibility_changed();
795832
}
796833

@@ -805,10 +842,14 @@ void Spatial::hide() {
805842
return;
806843
}
807844

845+
bool parent_visible = get_parent_spatial() ? get_parent_spatial()->data.visible_in_tree : true;
846+
if (parent_visible) {
847+
_propagate_visible_in_tree(this, false);
848+
}
808849
_propagate_visibility_changed();
809850
}
810851

811-
bool Spatial::is_visible_in_tree() const {
852+
bool Spatial::_is_visible_in_tree_reference() const {
812853
const Spatial *s = this;
813854

814855
while (s) {
@@ -1121,6 +1162,7 @@ Spatial::Spatial() :
11211162
data.viewport = nullptr;
11221163
data.inside_world = false;
11231164
data.visible = true;
1165+
data.visible_in_tree = true;
11241166
data.disable_scale = false;
11251167
data.vi_visible = true;
11261168
data.merging_allowed = true;

scene/3d/spatial.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class Spatial : public Node {
121121
bool notify_transform : 1;
122122

123123
bool visible : 1;
124+
bool visible_in_tree : 1;
124125
bool disable_scale : 1;
125126

126127
// Scene tree interpolation
@@ -155,6 +156,9 @@ class Spatial : public Node {
155156
void _notify_dirty();
156157
void _propagate_transform_changed(Spatial *p_origin);
157158

159+
void _update_visible_in_tree();
160+
bool _is_visible_in_tree_reference() const;
161+
void _propagate_visible_in_tree(Spatial *p_node, bool p_visible_in_tree);
158162
void _propagate_visibility_changed();
159163
void _propagate_merging_allowed(bool p_merging_allowed);
160164

@@ -293,7 +297,15 @@ class Spatial : public Node {
293297
bool is_visible() const;
294298
void show();
295299
void hide();
296-
bool is_visible_in_tree() const;
300+
bool is_visible_in_tree() const {
301+
#if DEV_ENABLED
302+
// As this is newly introduced, regression test the old method against the new in DEV builds.
303+
// If no regressions, this can be removed after a beta.
304+
bool visible = _is_visible_in_tree_reference();
305+
ERR_FAIL_COND_V_MSG(data.visible_in_tree != visible, visible, "is_visible_in_tree regression detected, recovering.");
306+
#endif
307+
return data.visible_in_tree;
308+
}
297309

298310
void force_update_transform();
299311

0 commit comments

Comments
 (0)