Skip to content

Commit dd2d84b

Browse files
authored
Remove ViewVisibility from UI nodes (#17405)
# Objective The UI can only target a single view and doesn't support `RenderLayers`, so there doesn't seem to be any need for UI nodes to require `ViewVisibility` and `VisibilityClass`. Fixes #17400 ## Solution Remove the `ViewVisibility` and `VisibilityClass` component requires from `Node` and change the visibility queries to only query for `InheritedVisibility`. ## Testing ```cargo run --example many_buttons --release --features "trace_tracy"``` Yellow is this PR, red is main. `bevy_render::view::visibility::reset_view_visibility` <img width="531" alt="reset-view" src="https://github.com/user-attachments/assets/a44b215d-96bf-43ec-8669-31530ff98eae" /> `bevy_render::view::visibility::check_visibility` <img width="445" alt="view_visibility" src="https://github.com/user-attachments/assets/fa111757-da91-434d-88e4-80bdfa29374f" />
1 parent 68c19de commit dd2d84b

8 files changed

+37
-38
lines changed

crates/bevy_ui/src/focus.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use bevy_ecs::{
1212
use bevy_input::{mouse::MouseButton, touch::Touches, ButtonInput};
1313
use bevy_math::{Rect, Vec2};
1414
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
15-
use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::ViewVisibility};
15+
use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::InheritedVisibility};
1616
use bevy_transform::components::GlobalTransform;
1717
use bevy_utils::HashMap;
1818
use bevy_window::{PrimaryWindow, Window};
@@ -28,9 +28,9 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
2828
///
2929
/// Updated in [`ui_focus_system`].
3030
///
31-
/// If a UI node has both [`Interaction`] and [`ViewVisibility`] components,
31+
/// If a UI node has both [`Interaction`] and [`InheritedVisibility`] components,
3232
/// [`Interaction`] will always be [`Interaction::None`]
33-
/// when [`ViewVisibility::get()`] is false.
33+
/// when [`InheritedVisibility::get()`] is false.
3434
/// This ensures that hidden UI nodes are not interactable,
3535
/// and do not end up stuck in an active state if hidden at the wrong time.
3636
///
@@ -140,13 +140,13 @@ pub struct NodeQuery {
140140
relative_cursor_position: Option<&'static mut RelativeCursorPosition>,
141141
focus_policy: Option<&'static FocusPolicy>,
142142
calculated_clip: Option<&'static CalculatedClip>,
143-
view_visibility: Option<&'static ViewVisibility>,
143+
inherited_visibility: Option<&'static InheritedVisibility>,
144144
target_camera: Option<&'static UiTargetCamera>,
145145
}
146146

147147
/// The system that sets Interaction for all UI elements based on the mouse cursor activity
148148
///
149-
/// Entities with a hidden [`ViewVisibility`] are always treated as released.
149+
/// Entities with a hidden [`InheritedVisibility`] are always treated as released.
150150
pub fn ui_focus_system(
151151
mut state: Local<State>,
152152
camera_query: Query<(Entity, &Camera)>,
@@ -227,9 +227,9 @@ pub fn ui_focus_system(
227227
return None;
228228
};
229229

230-
let view_visibility = node.view_visibility?;
230+
let inherited_visibility = node.inherited_visibility?;
231231
// Nodes that are not rendered should not be interactable
232-
if !view_visibility.get() {
232+
if !inherited_visibility.get() {
233233
// Reset their interaction to None to avoid strange stuck state
234234
if let Some(mut interaction) = node.interaction {
235235
// We cannot simply set the interaction to None, as that will trigger change detection repeatedly

crates/bevy_ui/src/picking_backend.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub struct NodeQuery {
5050
global_transform: &'static GlobalTransform,
5151
pickable: Option<&'static Pickable>,
5252
calculated_clip: Option<&'static CalculatedClip>,
53-
view_visibility: Option<&'static ViewVisibility>,
53+
inherited_visibility: Option<&'static InheritedVisibility>,
5454
target_camera: Option<&'static UiTargetCamera>,
5555
}
5656

@@ -124,8 +124,8 @@ pub fn ui_picking(
124124

125125
// Nodes that are not rendered should not be interactable
126126
if node
127-
.view_visibility
128-
.map(|view_visibility| view_visibility.get())
127+
.inherited_visibility
128+
.map(|inherited_visibility| inherited_visibility.get())
129129
!= Some(true)
130130
{
131131
continue;

crates/bevy_ui/src/render/box_shadow.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ pub fn extract_shadows(
243243
Entity,
244244
&ComputedNode,
245245
&GlobalTransform,
246-
&ViewVisibility,
246+
&InheritedVisibility,
247247
&BoxShadow,
248248
Option<&CalculatedClip>,
249249
Option<&UiTargetCamera>,
@@ -253,8 +253,7 @@ pub fn extract_shadows(
253253
) {
254254
let default_camera_entity = default_ui_camera.get();
255255

256-
for (entity, uinode, transform, view_visibility, box_shadow, clip, camera) in &box_shadow_query
257-
{
256+
for (entity, uinode, transform, visibility, box_shadow, clip, camera) in &box_shadow_query {
258257
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
259258
else {
260259
continue;
@@ -265,7 +264,7 @@ pub fn extract_shadows(
265264
};
266265

267266
// Skip if no visible shadows
268-
if !view_visibility.get() || box_shadow.is_empty() || uinode.is_empty() {
267+
if !visibility.get() || box_shadow.is_empty() || uinode.is_empty() {
269268
continue;
270269
}
271270

crates/bevy_ui/src/render/debug_overlay.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use bevy_math::Rect;
1414
use bevy_math::Vec2;
1515
use bevy_render::sync_world::RenderEntity;
1616
use bevy_render::sync_world::TemporaryRenderEntity;
17-
use bevy_render::view::ViewVisibility;
17+
use bevy_render::view::InheritedVisibility;
1818
use bevy_render::Extract;
1919
use bevy_sprite::BorderRect;
2020
use bevy_transform::components::GlobalTransform;
@@ -63,7 +63,7 @@ pub fn extract_debug_overlay(
6363
Query<(
6464
Entity,
6565
&ComputedNode,
66-
&ViewVisibility,
66+
&InheritedVisibility,
6767
Option<&CalculatedClip>,
6868
&GlobalTransform,
6969
Option<&UiTargetCamera>,

crates/bevy_ui/src/render/mod.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use bevy_render::{
4242
render_phase::{PhaseItem, PhaseItemExtraIndex},
4343
sync_world::{RenderEntity, TemporaryRenderEntity},
4444
texture::GpuImage,
45-
view::ViewVisibility,
45+
view::InheritedVisibility,
4646
ExtractSchedule, Render,
4747
};
4848
use bevy_sprite::{BorderRect, SpriteAssetEvents};
@@ -285,7 +285,7 @@ pub fn extract_uinode_background_colors(
285285
Entity,
286286
&ComputedNode,
287287
&GlobalTransform,
288-
&ViewVisibility,
288+
&InheritedVisibility,
289289
Option<&CalculatedClip>,
290290
Option<&UiTargetCamera>,
291291
&BackgroundColor,
@@ -294,7 +294,7 @@ pub fn extract_uinode_background_colors(
294294
mapping: Extract<Query<RenderEntity>>,
295295
) {
296296
let default_camera_entity = default_ui_camera.get();
297-
for (entity, uinode, transform, view_visibility, clip, camera, background_color) in
297+
for (entity, uinode, transform, inherited_visibility, clip, camera, background_color) in
298298
&uinode_query
299299
{
300300
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
@@ -307,7 +307,7 @@ pub fn extract_uinode_background_colors(
307307
};
308308

309309
// Skip invisible backgrounds
310-
if !view_visibility.get() || background_color.0.is_fully_transparent() {
310+
if !inherited_visibility.get() || background_color.0.is_fully_transparent() {
311311
continue;
312312
}
313313

@@ -348,7 +348,7 @@ pub fn extract_uinode_images(
348348
Entity,
349349
&ComputedNode,
350350
&GlobalTransform,
351-
&ViewVisibility,
351+
&InheritedVisibility,
352352
Option<&CalculatedClip>,
353353
Option<&UiTargetCamera>,
354354
&ImageNode,
@@ -357,7 +357,7 @@ pub fn extract_uinode_images(
357357
mapping: Extract<Query<RenderEntity>>,
358358
) {
359359
let default_camera_entity = default_ui_camera.get();
360-
for (entity, uinode, transform, view_visibility, clip, camera, image) in &uinode_query {
360+
for (entity, uinode, transform, inherited_visibility, clip, camera, image) in &uinode_query {
361361
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
362362
else {
363363
continue;
@@ -368,7 +368,7 @@ pub fn extract_uinode_images(
368368
};
369369

370370
// Skip invisible images
371-
if !view_visibility.get()
371+
if !inherited_visibility.get()
372372
|| image.color.is_fully_transparent()
373373
|| image.image.id() == TRANSPARENT_IMAGE_HANDLE.id()
374374
|| image.image_mode.uses_slices()
@@ -439,7 +439,7 @@ pub fn extract_uinode_borders(
439439
&Node,
440440
&ComputedNode,
441441
&GlobalTransform,
442-
&ViewVisibility,
442+
&InheritedVisibility,
443443
Option<&CalculatedClip>,
444444
Option<&UiTargetCamera>,
445445
AnyOf<(&BorderColor, &Outline)>,
@@ -454,7 +454,7 @@ pub fn extract_uinode_borders(
454454
node,
455455
computed_node,
456456
global_transform,
457-
view_visibility,
457+
inherited_visibility,
458458
maybe_clip,
459459
maybe_camera,
460460
(maybe_border_color, maybe_outline),
@@ -472,7 +472,7 @@ pub fn extract_uinode_borders(
472472
};
473473

474474
// Skip invisible borders and removed nodes
475-
if !view_visibility.get() || node.display == Display::None {
475+
if !inherited_visibility.get() || node.display == Display::None {
476476
continue;
477477
}
478478

@@ -678,7 +678,7 @@ pub fn extract_text_sections(
678678
Entity,
679679
&ComputedNode,
680680
&GlobalTransform,
681-
&ViewVisibility,
681+
&InheritedVisibility,
682682
Option<&CalculatedClip>,
683683
Option<&UiTargetCamera>,
684684
&ComputedTextBlock,
@@ -696,7 +696,7 @@ pub fn extract_text_sections(
696696
entity,
697697
uinode,
698698
global_transform,
699-
view_visibility,
699+
inherited_visibility,
700700
clip,
701701
camera,
702702
computed_block,
@@ -708,7 +708,7 @@ pub fn extract_text_sections(
708708
};
709709

710710
// Skip if not visible or if size is set to zero (e.g. when a parent is set to `Display::None`)
711-
if !view_visibility.get() || uinode.is_empty() {
711+
if !inherited_visibility.get() || uinode.is_empty() {
712712
continue;
713713
}
714714

crates/bevy_ui/src/render/ui_material_pipeline.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
369369
&ComputedNode,
370370
&GlobalTransform,
371371
&MaterialNode<M>,
372-
&ViewVisibility,
372+
&InheritedVisibility,
373373
Option<&CalculatedClip>,
374374
Option<&UiTargetCamera>,
375375
)>,
@@ -379,7 +379,9 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
379379
// If there is only one camera, we use it as default
380380
let default_single_camera = default_ui_camera.get();
381381

382-
for (entity, uinode, transform, handle, view_visibility, clip, camera) in uinode_query.iter() {
382+
for (entity, uinode, transform, handle, inherited_visibility, clip, camera) in
383+
uinode_query.iter()
384+
{
383385
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_single_camera)
384386
else {
385387
continue;
@@ -390,7 +392,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
390392
};
391393

392394
// skip invisible nodes
393-
if !view_visibility.get() {
395+
if !inherited_visibility.get() {
394396
continue;
395397
}
396398

crates/bevy_ui/src/render/ui_texture_slice_pipeline.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub fn extract_ui_texture_slices(
254254
Entity,
255255
&ComputedNode,
256256
&GlobalTransform,
257-
&ViewVisibility,
257+
&InheritedVisibility,
258258
Option<&CalculatedClip>,
259259
Option<&UiTargetCamera>,
260260
&ImageNode,
@@ -264,7 +264,7 @@ pub fn extract_ui_texture_slices(
264264
) {
265265
let default_camera_entity = default_ui_camera.get();
266266

267-
for (entity, uinode, transform, view_visibility, clip, camera, image) in &slicers_query {
267+
for (entity, uinode, transform, inherited_visibility, clip, camera, image) in &slicers_query {
268268
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
269269
else {
270270
continue;
@@ -291,7 +291,7 @@ pub fn extract_ui_texture_slices(
291291
};
292292

293293
// Skip invisible images
294-
if !view_visibility.get()
294+
if !inherited_visibility.get()
295295
|| image.color.is_fully_transparent()
296296
|| image.image.id() == TRANSPARENT_IMAGE_HANDLE.id()
297297
{

crates/bevy_ui/src/ui_node.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bevy_math::{vec4, Rect, Vec2, Vec4Swizzles};
66
use bevy_reflect::prelude::*;
77
use bevy_render::{
88
camera::{Camera, RenderTarget},
9-
view::{self, Visibility, VisibilityClass},
9+
view::Visibility,
1010
};
1111
use bevy_sprite::BorderRect;
1212
use bevy_transform::components::Transform;
@@ -329,11 +329,9 @@ impl From<Vec2> for ScrollPosition {
329329
ScrollPosition,
330330
Transform,
331331
Visibility,
332-
VisibilityClass,
333332
ZIndex
334333
)]
335334
#[reflect(Component, Default, PartialEq, Debug)]
336-
#[component(on_add = view::add_visibility_class::<Node>)]
337335
#[cfg_attr(
338336
feature = "serialize",
339337
derive(serde::Serialize, serde::Deserialize),

0 commit comments

Comments
 (0)