From c618d0876781ebfe65bedd8cde79105767e753f6 Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 18 Aug 2023 23:32:42 -0400 Subject: [PATCH 01/17] split ComputedVisiblity into two components --- crates/bevy_pbr/src/bundle.rs | 21 +- crates/bevy_pbr/src/light.rs | 64 ++-- crates/bevy_pbr/src/render/light.rs | 24 +- crates/bevy_pbr/src/render/mesh.rs | 12 +- crates/bevy_pbr/src/render/morph.rs | 8 +- crates/bevy_render/src/extract_component.rs | 8 +- crates/bevy_render/src/lib.rs | 4 +- crates/bevy_render/src/spatial_bundle.rs | 11 +- crates/bevy_render/src/view/mod.rs | 4 +- crates/bevy_render/src/view/visibility/mod.rs | 275 +++++++++--------- crates/bevy_scene/src/bundle.rs | 10 +- crates/bevy_sprite/src/bundle.rs | 12 +- crates/bevy_sprite/src/mesh2d/material.rs | 11 +- crates/bevy_sprite/src/mesh2d/mesh.rs | 8 +- crates/bevy_sprite/src/render/mod.rs | 18 +- crates/bevy_text/src/text2d.rs | 14 +- crates/bevy_ui/src/focus.rs | 8 +- crates/bevy_ui/src/node_bundles.rs | 37 ++- crates/bevy_ui/src/render/mod.rs | 36 ++- 19 files changed, 326 insertions(+), 259 deletions(-) diff --git a/crates/bevy_pbr/src/bundle.rs b/crates/bevy_pbr/src/bundle.rs index 0590dba4abdb6..e669a176fa0c0 100644 --- a/crates/bevy_pbr/src/bundle.rs +++ b/crates/bevy_pbr/src/bundle.rs @@ -8,7 +8,7 @@ use bevy_reflect::Reflect; use bevy_render::{ mesh::Mesh, primitives::{CascadesFrusta, CubemapFrusta, Frustum}, - view::{ComputedVisibility, Visibility, VisibleEntities}, + view::{Visibility, VisibleEntities, VisibleInHierarchy, VisibleInView}, }; use bevy_transform::components::{GlobalTransform, Transform}; use bevy_utils::HashMap; @@ -25,8 +25,10 @@ pub struct MaterialMeshBundle { pub global_transform: GlobalTransform, /// User indication of whether an entity is visible pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } impl Default for MaterialMeshBundle { @@ -37,7 +39,8 @@ impl Default for MaterialMeshBundle { transform: Default::default(), global_transform: Default::default(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), } } } @@ -85,8 +88,10 @@ pub struct PointLightBundle { pub global_transform: GlobalTransform, /// Enables or disables the light pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } /// A component bundle for spot light entities @@ -99,8 +104,10 @@ pub struct SpotLightBundle { pub global_transform: GlobalTransform, /// Enables or disables the light pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } /// A component bundle for [`DirectionalLight`] entities. @@ -115,6 +122,8 @@ pub struct DirectionalLightBundle { pub global_transform: GlobalTransform, /// Enables or disables the light pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hieararchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index 3e8c0d45177e6..da7426cc8206d 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -11,7 +11,7 @@ use bevy_render::{ primitives::{Aabb, CascadesFrusta, CubemapFrusta, Frustum, HalfSpace, Sphere}, render_resource::BufferBindingType, renderer::RenderDevice, - view::{ComputedVisibility, RenderLayers, VisibleEntities}, + view::{RenderLayers, VisibleEntities, VisibleInHierarchy, VisibleInView}, }; use bevy_transform::{components::GlobalTransform, prelude::Transform}; use bevy_utils::{tracing::warn, HashMap}; @@ -1178,8 +1178,8 @@ pub(crate) fn assign_lights_to_clusters( &mut Clusters, Option<&mut VisiblePointLights>, )>, - point_lights_query: Query<(Entity, &GlobalTransform, &PointLight, &ComputedVisibility)>, - spot_lights_query: Query<(Entity, &GlobalTransform, &SpotLight, &ComputedVisibility)>, + point_lights_query: Query<(Entity, &GlobalTransform, &PointLight, &VisibleInView)>, + spot_lights_query: Query<(Entity, &GlobalTransform, &SpotLight, &VisibleInView)>, mut lights: Local>, mut cluster_aabb_spheres: Local>>, mut max_point_lights_warning_emitted: Local, @@ -1196,7 +1196,7 @@ pub(crate) fn assign_lights_to_clusters( lights.extend( point_lights_query .iter() - .filter(|(.., visibility)| visibility.is_visible()) + .filter(|(.., visibility)| visibility.get()) .map( |(entity, transform, point_light, _visibility)| PointLightAssignmentData { entity, @@ -1210,7 +1210,7 @@ pub(crate) fn assign_lights_to_clusters( lights.extend( spot_lights_query .iter() - .filter(|(.., visibility)| visibility.is_visible()) + .filter(|(.., visibility)| visibility.get()) .map( |(entity, transform, spot_light, _visibility)| PointLightAssignmentData { entity, @@ -1797,7 +1797,7 @@ pub fn update_directional_light_frusta( ( &Cascades, &DirectionalLight, - &ComputedVisibility, + &VisibleInView, &mut CascadesFrusta, ), ( @@ -1810,7 +1810,7 @@ pub fn update_directional_light_frusta( // The frustum is used for culling meshes to the light for shadow mapping // so if shadow mapping is disabled for this light, then the frustum is // not needed. - if !directional_light.shadows_enabled || !visibility.is_visible() { + if !directional_light.shadows_enabled || !visibility.get() { continue; } @@ -1931,14 +1931,15 @@ pub fn check_light_mesh_visibility( &CascadesFrusta, &mut CascadesVisibleEntities, Option<&RenderLayers>, - &mut ComputedVisibility, + &mut VisibleInView, ), Without, >, mut visible_entity_query: Query< ( Entity, - &mut ComputedVisibility, + &VisibleInHierarchy, + &mut VisibleInView, Option<&RenderLayers>, Option<&Aabb>, Option<&GlobalTransform>, @@ -1963,13 +1964,8 @@ pub fn check_light_mesh_visibility( } // Directional lights - for ( - directional_light, - frusta, - mut visible_entities, - maybe_view_mask, - light_computed_visibility, - ) in &mut directional_lights + for (directional_light, frusta, mut visible_entities, maybe_view_mask, light_visible_in_view) in + &mut directional_lights { // Re-use already allocated entries where possible. let mut views_to_remove = Vec::new(); @@ -1995,16 +1991,22 @@ pub fn check_light_mesh_visibility( } // NOTE: If shadow mapping is disabled for the light then it must have no visible entities - if !directional_light.shadows_enabled || !light_computed_visibility.is_visible() { + if !directional_light.shadows_enabled || !light_visible_in_view.get() { continue; } let view_mask = maybe_view_mask.copied().unwrap_or_default(); - for (entity, mut computed_visibility, maybe_entity_mask, maybe_aabb, maybe_transform) in - &mut visible_entity_query + for ( + entity, + visible_in_hierarchy, + mut visible_in_view, + maybe_entity_mask, + maybe_aabb, + maybe_transform, + ) in &mut visible_entity_query { - if !computed_visibility.is_visible_in_hierarchy() { + if !visible_in_hierarchy.get() { continue; } @@ -2029,12 +2031,12 @@ pub fn check_light_mesh_visibility( continue; } - computed_visibility.set_visible_in_view(); + visible_in_view.set(); frustum_visible_entities.entities.push(entity); } } } else { - computed_visibility.set_visible_in_view(); + visible_in_view.set(); for view in frusta.frusta.keys() { let view_visible_entities = visible_entities .entities @@ -2081,13 +2083,14 @@ pub fn check_light_mesh_visibility( for ( entity, - mut computed_visibility, + visible_in_hierarchy, + mut visible_in_view, maybe_entity_mask, maybe_aabb, maybe_transform, ) in &mut visible_entity_query { - if !computed_visibility.is_visible_in_hierarchy() { + if !visible_in_hierarchy.get() { continue; } @@ -2109,12 +2112,12 @@ pub fn check_light_mesh_visibility( .zip(cubemap_visible_entities.iter_mut()) { if frustum.intersects_obb(aabb, &model_to_world, true, true) { - computed_visibility.set_visible_in_view(); + visible_in_view.set(); visible_entities.entities.push(entity); } } } else { - computed_visibility.set_visible_in_view(); + visible_in_view.set(); for visible_entities in cubemap_visible_entities.iter_mut() { visible_entities.entities.push(entity); } @@ -2145,13 +2148,14 @@ pub fn check_light_mesh_visibility( for ( entity, - mut computed_visibility, + visible_in_hierarchy, + mut visible_in_view, maybe_entity_mask, maybe_aabb, maybe_transform, ) in visible_entity_query.iter_mut() { - if !computed_visibility.is_visible_in_hierarchy() { + if !visible_in_hierarchy.get() { continue; } @@ -2169,11 +2173,11 @@ pub fn check_light_mesh_visibility( } if frustum.intersects_obb(aabb, &model_to_world, true, true) { - computed_visibility.set_visible_in_view(); + visible_in_view.set(); visible_entities.entities.push(entity); } } else { - computed_visibility.set_visible_in_view(); + visible_in_view.set(); visible_entities.entities.push(entity); } } diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 265a27e026f2d..bdb35ddf62cdb 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -22,7 +22,7 @@ use bevy_render::{ render_resource::*, renderer::{RenderContext, RenderDevice, RenderQueue}, texture::*, - view::{ComputedVisibility, ExtractedView, VisibleEntities}, + view::{ExtractedView, VisibleEntities, VisibleInView}, Extract, }; use bevy_transform::{components::GlobalTransform, prelude::Transform}; @@ -308,7 +308,7 @@ pub fn extract_lights( &PointLight, &CubemapVisibleEntities, &GlobalTransform, - &ComputedVisibility, + &VisibleInView, )>, >, spot_lights: Extract< @@ -316,7 +316,7 @@ pub fn extract_lights( &SpotLight, &VisibleEntities, &GlobalTransform, - &ComputedVisibility, + &VisibleInView, )>, >, directional_lights: Extract< @@ -328,7 +328,7 @@ pub fn extract_lights( &Cascades, &CascadeShadowConfig, &GlobalTransform, - &ComputedVisibility, + &VisibleInView, ), Without, >, @@ -355,10 +355,10 @@ pub fn extract_lights( let mut point_lights_values = Vec::with_capacity(*previous_point_lights_len); for entity in global_point_lights.iter().copied() { - if let Ok((point_light, cubemap_visible_entities, transform, visibility)) = + if let Ok((point_light, cubemap_visible_entities, transform, visible_in_view)) = point_lights.get(entity) { - if !visibility.is_visible() { + if !visible_in_view.get() { continue; } // TODO: This is very much not ideal. We should be able to re-use the vector memory. @@ -394,8 +394,10 @@ pub fn extract_lights( let mut spot_lights_values = Vec::with_capacity(*previous_spot_lights_len); for entity in global_point_lights.iter().copied() { - if let Ok((spot_light, visible_entities, transform, visibility)) = spot_lights.get(entity) { - if !visibility.is_visible() { + if let Ok((spot_light, visible_entities, transform, visible_in_view)) = + spot_lights.get(entity) + { + if !visible_in_view.get() { continue; } // TODO: This is very much not ideal. We should be able to re-use the vector memory. @@ -442,10 +444,10 @@ pub fn extract_lights( cascades, cascade_config, transform, - visibility, - ) in directional_lights.iter() + visible_in_view, + ) in &directional_lights { - if !visibility.is_visible() { + if !visible_in_view.get() { continue; } diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 46693e80978ac..55cda53b5446d 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -37,7 +37,7 @@ use bevy_render::{ BevyDefault, DefaultImageSampler, FallbackImageCubemap, FallbackImagesDepth, FallbackImagesMsaa, GpuImage, Image, ImageSampler, TextureFormatPixelInfo, }, - view::{ComputedVisibility, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms}, + view::{ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms, VisibleInView}, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; use bevy_transform::components::GlobalTransform; @@ -194,7 +194,7 @@ pub fn extract_meshes( meshes_query: Extract< Query<( Entity, - &ComputedVisibility, + &VisibleInView, &GlobalTransform, Option<&PreviousGlobalTransform>, &Handle, @@ -205,7 +205,7 @@ pub fn extract_meshes( ) { let mut caster_commands = Vec::with_capacity(*prev_caster_commands_len); let mut not_caster_commands = Vec::with_capacity(*prev_not_caster_commands_len); - let visible_meshes = meshes_query.iter().filter(|(_, vis, ..)| vis.is_visible()); + let visible_meshes = meshes_query.iter().filter(|(_, vis, ..)| vis.get()); for (entity, _, transform, previous_transform, handle, not_receiver, not_caster) in visible_meshes @@ -287,7 +287,7 @@ pub fn extract_skinned_meshes( mut commands: Commands, mut previous_len: Local, mut uniform: ResMut, - query: Extract>, + query: Extract>, inverse_bindposes: Extract>>, joint_query: Extract>, ) { @@ -295,8 +295,8 @@ pub fn extract_skinned_meshes( let mut values = Vec::with_capacity(*previous_len); let mut last_start = 0; - for (entity, computed_visibility, skin) in &query { - if !computed_visibility.is_visible() { + for (entity, visible_in_view, skin) in &query { + if !visible_in_view.get() { continue; } // PERF: This can be expensive, can we move this to prepare? diff --git a/crates/bevy_pbr/src/render/morph.rs b/crates/bevy_pbr/src/render/morph.rs index 43d2e2f585234..d25d797613245 100644 --- a/crates/bevy_pbr/src/render/morph.rs +++ b/crates/bevy_pbr/src/render/morph.rs @@ -5,7 +5,7 @@ use bevy_render::{ mesh::morph::{MeshMorphWeights, MAX_MORPH_WEIGHTS}, render_resource::{BufferUsages, BufferVec}, renderer::{RenderDevice, RenderQueue}, - view::ComputedVisibility, + view::VisibleInView, Extract, }; use bytemuck::Pod; @@ -72,14 +72,14 @@ pub fn extract_morphs( mut commands: Commands, mut previous_len: Local, mut uniform: ResMut, - query: Extract>, + query: Extract>, ) { uniform.buffer.clear(); let mut values = Vec::with_capacity(*previous_len); - for (entity, computed_visibility, morph_weights) in &query { - if !computed_visibility.is_visible() { + for (entity, visible_in_view, morph_weights) in &query { + if !visible_in_view.get() { continue; } let start = uniform.buffer.len(); diff --git a/crates/bevy_render/src/extract_component.rs b/crates/bevy_render/src/extract_component.rs index 606c8ccbe09ac..ac9c1af070253 100644 --- a/crates/bevy_render/src/extract_component.rs +++ b/crates/bevy_render/src/extract_component.rs @@ -1,7 +1,7 @@ use crate::{ render_resource::{encase::internal::WriteInto, DynamicUniformBuffer, ShaderType}, renderer::{RenderDevice, RenderQueue}, - view::ComputedVisibility, + view::VisibleInView, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; use bevy_app::{App, Plugin}; @@ -222,11 +222,11 @@ fn extract_components( fn extract_visible_components( mut commands: Commands, mut previous_len: Local, - query: Extract>, + query: Extract>, ) { let mut values = Vec::with_capacity(*previous_len); - for (entity, computed_visibility, query_item) in &query { - if computed_visibility.is_visible() { + for (entity, visible_in_view, query_item) in &query { + if visible_in_view.get() { if let Some(component) = C::extract_component(query_item) { values.push((entity, component)); } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index bab3e4b73cacd..e63d0170d353a 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -38,7 +38,7 @@ pub mod prelude { render_resource::Shader, spatial_bundle::SpatialBundle, texture::{Image, ImagePlugin}, - view::{ComputedVisibility, Msaa, Visibility, VisibilityBundle}, + view::{Msaa, Visibility, VisibilityBundle, VisibleInHierarchy, VisibleInView}, ExtractSchedule, }; } @@ -334,7 +334,7 @@ impl Plugin for RenderPlugin { } app.add_plugins(( - ValidParentCheckPlugin::::default(), + ValidParentCheckPlugin::::default(), WindowRenderPlugin, CameraPlugin, ViewPlugin, diff --git a/crates/bevy_render/src/spatial_bundle.rs b/crates/bevy_render/src/spatial_bundle.rs index b2d50da6097f6..0405e822b55e4 100644 --- a/crates/bevy_render/src/spatial_bundle.rs +++ b/crates/bevy_render/src/spatial_bundle.rs @@ -1,7 +1,7 @@ use bevy_ecs::prelude::Bundle; use bevy_transform::prelude::{GlobalTransform, Transform}; -use crate::view::{ComputedVisibility, Visibility}; +use crate::view::{Visibility, VisibleInHierarchy, VisibleInView}; /// A [`Bundle`] with the following [`Component`](bevy_ecs::component::Component)s: /// * [`Visibility`] and [`ComputedVisibility`], which describe the visibility of an entity @@ -17,8 +17,10 @@ use crate::view::{ComputedVisibility, Visibility}; pub struct SpatialBundle { /// The visibility of the entity. pub visibility: Visibility, - /// The computed visibility of the entity. - pub computed: ComputedVisibility, + /// The inherited visibility of the entity. + pub visible_in_hierarchy: VisibleInHierarchy, + /// The view visibility of the entity. + pub visible_in_view: VisibleInView, /// The transform of the entity. pub transform: Transform, /// The global transform of the entity. @@ -40,7 +42,8 @@ impl SpatialBundle { /// A visible [`SpatialBundle`], with no translation, rotation, and a scale of 1 on all axes. pub const INHERITED_IDENTITY: Self = SpatialBundle { visibility: Visibility::Inherited, - computed: ComputedVisibility::HIDDEN, + visible_in_hierarchy: VisibleInHierarchy::HIDDEN, + visible_in_view: VisibleInView::HIDDEN, transform: Transform::IDENTITY, global_transform: GlobalTransform::IDENTITY, }; diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index b2b773787c6e4..6c4fb0fd521d8 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -40,8 +40,8 @@ impl Plugin for ViewPlugin { fn build(&self, app: &mut App) { load_internal_asset!(app, VIEW_TYPE_HANDLE, "view.wgsl", Shader::from_wgsl); - app.register_type::() - .register_type::() + app.register_type::() + .register_type::() .register_type::() .register_type::() .register_type::() diff --git a/crates/bevy_render/src/view/visibility/mod.rs b/crates/bevy_render/src/view/visibility/mod.rs index 0e99f1cc09f78..5230c328fe89d 100644 --- a/crates/bevy_render/src/view/visibility/mod.rs +++ b/crates/bevy_render/src/view/visibility/mod.rs @@ -1,5 +1,6 @@ mod render_layers; +use bevy_derive::{Deref, DerefMut}; pub use render_layers::*; use bevy_app::{Plugin, PostUpdate}; @@ -60,81 +61,46 @@ impl std::cmp::PartialEq<&Visibility> for Visibility { } } -bitflags::bitflags! { - #[derive(Clone, Debug, Eq, PartialEq)] - pub(super) struct ComputedVisibilityFlags: u8 { - const VISIBLE_IN_VIEW = 1 << 0; - const VISIBLE_IN_HIERARCHY = 1 << 1; - } -} -bevy_reflect::impl_reflect_value!((in bevy_render::view) ComputedVisibilityFlags); +/// Whether or not an entity is visible in the hierarchy. +/// This will not be accurate until [`VisibilityPropagate`] runs in the [`PostUpdate`] schedule. +/// +/// If this is false, then [`VisibleInView`] should also be false. +/// +/// [`VisibilityPropagate`]: VisibilitySystems::VisibilityPropagate +#[derive(Component, Deref, DerefMut, Debug, Default, Clone, Copy, Reflect, PartialEq, Eq)] +pub struct VisibleInHierarchy(bool); -/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering -#[derive(Component, Clone, Reflect, Debug, Eq, PartialEq)] -#[reflect(Component, Default)] -pub struct ComputedVisibility { - flags: ComputedVisibilityFlags, -} +impl VisibleInHierarchy { + pub const HIDDEN: Self = Self(false); -impl Default for ComputedVisibility { - fn default() -> Self { - Self::HIDDEN + /// Returns `true` if the entity is visible in the hierarchy. + /// Otherwise, returns `false`. + pub fn get(self) -> bool { + self.0 } } -impl ComputedVisibility { - /// A [`ComputedVisibility`], set as invisible. - pub const HIDDEN: Self = ComputedVisibility { - flags: ComputedVisibilityFlags::empty(), - }; - - /// Whether this entity is visible to something this frame. This is true if and only if [`Self::is_visible_in_hierarchy`] and [`Self::is_visible_in_view`] - /// are true. This is the canonical method to call to determine if an entity should be drawn. - /// This value is updated in [`PostUpdate`] by the [`VisibilitySystems::CheckVisibility`] system set. - /// Reading it during [`Update`](bevy_app::Update) will yield the value from the previous frame. - #[inline] - pub fn is_visible(&self) -> bool { - self.flags.bits() == ComputedVisibilityFlags::all().bits() - } - - /// Whether this entity is visible in the entity hierarchy, which is determined by the [`Visibility`] component. - /// This takes into account "visibility inheritance". If any of this entity's ancestors (see [`Parent`]) are hidden, this entity - /// will be hidden as well. This value is updated in the [`VisibilitySystems::VisibilityPropagate`], which lives in the [`PostUpdate`] schedule. - #[inline] - pub fn is_visible_in_hierarchy(&self) -> bool { - self.flags - .contains(ComputedVisibilityFlags::VISIBLE_IN_HIERARCHY) - } +/// Algorithmically-computed indication or whether an entity is visible and should be extracted for rendering. +/// +/// This will be reset to `false` at the beginning of [`PostUpdate`], and then set to true by +/// [`CheckVisibility`] systems. Because of this, values of this type will be marked as changed on +/// nearly every frame, even when they do not change. +/// +/// [`VisibilitySystems::CheckVisibility`] +#[derive(Component, Deref, Debug, Default, Clone, Copy, Reflect, PartialEq, Eq)] +pub struct VisibleInView(bool); - /// Whether this entity is visible in _any_ view (Cameras, Lights, etc). Each entity type (and view type) should choose how to set this - /// value. For cameras and drawn entities, this will take into account [`RenderLayers`]. - /// - /// This value is reset to `false` every frame in [`VisibilitySystems::VisibilityPropagate`] during [`PostUpdate`]. - /// Each entity type then chooses how to set this field in the [`VisibilitySystems::CheckVisibility`] system set, in [`PostUpdate`]. - /// Meshes might use frustum culling to decide if they are visible in a view. - /// Other entities might just set this to `true` every frame. - #[inline] - pub fn is_visible_in_view(&self) -> bool { - self.flags - .contains(ComputedVisibilityFlags::VISIBLE_IN_VIEW) - } +impl VisibleInView { + pub const HIDDEN: Self = Self(false); - /// Sets `is_visible_in_view` to `true`. This is not reversible for a given frame, as it encodes whether or not this is visible in - /// _any_ view. This will be automatically reset to `false` every frame in [`VisibilitySystems::VisibilityPropagate`] and then set - /// to the proper value in [`VisibilitySystems::CheckVisibility`]. This should _only_ be set in systems with the [`VisibilitySystems::CheckVisibility`] - /// label. Don't call this unless you are defining a custom visibility system. For normal user-defined entity visibility, see [`Visibility`]. - #[inline] - pub fn set_visible_in_view(&mut self) { - self.flags.insert(ComputedVisibilityFlags::VISIBLE_IN_VIEW); + /// Returns `true` if the entity is visible in any view. + /// Otherwise, returns `false`. + pub fn get(self) -> bool { + self.0 } - #[inline] - fn reset(&mut self, visible_in_hierarchy: bool) { - self.flags = if visible_in_hierarchy { - ComputedVisibilityFlags::VISIBLE_IN_HIERARCHY - } else { - ComputedVisibilityFlags::empty() - }; + pub fn set(&mut self) { + self.0 = true; } } @@ -149,8 +115,10 @@ impl ComputedVisibility { pub struct VisibilityBundle { /// The visibility of the entity. pub visibility: Visibility, - /// The computed visibility of the entity. - pub computed: ComputedVisibility, + // The inherited visibility of the entity. + pub visible_in_hierarchy: VisibleInHierarchy, + // The computed visibility of the entity. + pub visible_in_view: VisibleInView, } /// Use this component to opt-out of built-in frustum culling for Mesh entities @@ -290,22 +258,38 @@ fn visibility_propagate_system( ( Option<&Children>, &Visibility, - &mut ComputedVisibility, + &mut VisibleInHierarchy, + &mut VisibleInView, Entity, ), Without, >, - mut visibility_query: Query<(&Visibility, &mut ComputedVisibility, &Parent)>, - children_query: Query<&Children, (With, With, With)>, + mut visibility_query: Query<( + &Visibility, + &mut VisibleInHierarchy, + &mut VisibleInView, + &Parent, + )>, + children_query: Query< + &Children, + ( + With, + With, + (With, With), + ), + >, ) { - for (children, visibility, mut computed_visibility, entity) in root_query.iter_mut() { + for (children, visibility, mut visible_in_hierarchy, mut visible_in_view, entity) in + root_query.iter_mut() + { + let is_visible = matches!(visibility, Visibility::Inherited | Visibility::Visible); + visible_in_hierarchy.set_if_neq(VisibleInHierarchy(is_visible)); // reset "view" visibility here ... if this entity should be drawn a future system should set this to true - computed_visibility - .reset(visibility == Visibility::Inherited || visibility == Visibility::Visible); + visible_in_view.set_if_neq(VisibleInView(false)); if let Some(children) = children { for child in children.iter() { let _ = propagate_recursive( - computed_visibility.is_visible_in_hierarchy(), + is_visible, &mut visibility_query, &children_query, *child, @@ -318,25 +302,38 @@ fn visibility_propagate_system( fn propagate_recursive( parent_visible: bool, - visibility_query: &mut Query<(&Visibility, &mut ComputedVisibility, &Parent)>, - children_query: &Query<&Children, (With, With, With)>, + visibility_query: &mut Query<( + &Visibility, + &mut VisibleInHierarchy, + &mut VisibleInView, + &Parent, + )>, + children_query: &Query< + &Children, + ( + With, + With, + (With, With), + ), + >, entity: Entity, expected_parent: Entity, // BLOCKED: https://github.com/rust-lang/rust/issues/31436 // We use a result here to use the `?` operator. Ideally we'd use a try block instead ) -> Result<(), ()> { let is_visible = { - let (visibility, mut computed_visibility, child_parent) = + let (visibility, mut visible_in_hierarchy, mut visible_in_view, child_parent) = visibility_query.get_mut(entity).map_err(drop)?; assert_eq!( child_parent.get(), expected_parent, "Malformed hierarchy. This probably means that your hierarchy has been improperly maintained, or contains a cycle" ); - let visible_in_hierarchy = (parent_visible && visibility == Visibility::Inherited) + let is_visible = (parent_visible && visibility == Visibility::Inherited) || visibility == Visibility::Visible; + visible_in_hierarchy.set_if_neq(VisibleInHierarchy(is_visible)); // reset "view" visibility here ... if this entity should be drawn a future system should set this to true - computed_visibility.reset(visible_in_hierarchy); - visible_in_hierarchy + visible_in_view.set_if_neq(VisibleInView(false)); + is_visible }; for child in children_query.get(entity).map_err(drop)?.iter() { @@ -355,14 +352,20 @@ pub fn check_visibility( mut view_query: Query<(&mut VisibleEntities, &Frustum, Option<&RenderLayers>), With>, mut visible_aabb_query: Query<( Entity, - &mut ComputedVisibility, + &VisibleInHierarchy, + &mut VisibleInView, Option<&RenderLayers>, &Aabb, &GlobalTransform, Option<&NoFrustumCulling>, )>, mut visible_no_aabb_query: Query< - (Entity, &mut ComputedVisibility, Option<&RenderLayers>), + ( + Entity, + &VisibleInHierarchy, + &mut VisibleInView, + Option<&RenderLayers>, + ), Without, >, ) { @@ -373,7 +376,8 @@ pub fn check_visibility( visible_aabb_query.par_iter_mut().for_each( |( entity, - mut computed_visibility, + visible_in_hierarchy, + mut visible_in_view, maybe_entity_mask, model_aabb, transform, @@ -381,7 +385,7 @@ pub fn check_visibility( )| { // skip computing visibility for entities that are configured to be hidden. is_visible_in_view has already been set to false // in visibility_propagate_system - if !computed_visibility.is_visible_in_hierarchy() { + if !visible_in_hierarchy.get() { return; } @@ -407,7 +411,7 @@ pub fn check_visibility( } } - computed_visibility.set_visible_in_view(); + visible_in_view.set(); let cell = thread_queues.get_or_default(); let mut queue = cell.take(); queue.push(entity); @@ -416,10 +420,10 @@ pub fn check_visibility( ); visible_no_aabb_query.par_iter_mut().for_each( - |(entity, mut computed_visibility, maybe_entity_mask)| { + |(entity, visible_in_hierarchy, mut visible_in_view, maybe_entity_mask)| { // skip computing visibility for entities that are configured to be hidden. is_visible_in_view has already been set to false // in visibility_propagate_system - if !computed_visibility.is_visible_in_hierarchy() { + if !visible_in_hierarchy.get() { return; } @@ -428,7 +432,7 @@ pub fn check_visibility( return; } - computed_visibility.set_visible_in_view(); + visible_in_view.set(); let cell = thread_queues.get_or_default(); let mut queue = cell.take(); queue.push(entity); @@ -458,24 +462,21 @@ mod test { let root1 = app .world - .spawn((Visibility::Hidden, ComputedVisibility::default())) - .id(); - let root1_child1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Hidden, + ..Default::default() + }) .id(); + let root1_child1 = app.world.spawn(VisibilityBundle::default()).id(); let root1_child2 = app .world - .spawn((Visibility::Hidden, ComputedVisibility::default())) - .id(); - let root1_child1_grandchild1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) - .id(); - let root1_child2_grandchild1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Hidden, + ..Default::default() + }) .id(); + let root1_child1_grandchild1 = app.world.spawn(VisibilityBundle::default()).id(); + let root1_child2_grandchild1 = app.world.spawn(VisibilityBundle::default()).id(); app.world .entity_mut(root1) @@ -487,26 +488,17 @@ mod test { .entity_mut(root1_child2) .push_children(&[root1_child2_grandchild1]); - let root2 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) - .id(); - let root2_child1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) - .id(); + let root2 = app.world.spawn(VisibilityBundle::default()).id(); + let root2_child1 = app.world.spawn(VisibilityBundle::default()).id(); let root2_child2 = app .world - .spawn((Visibility::Hidden, ComputedVisibility::default())) - .id(); - let root2_child1_grandchild1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) - .id(); - let root2_child2_grandchild1 = app - .world - .spawn((Visibility::default(), ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Hidden, + ..Default::default() + }) .id(); + let root2_child1_grandchild1 = app.world.spawn(VisibilityBundle::default()).id(); + let root2_child2_grandchild1 = app.world.spawn(VisibilityBundle::default()).id(); app.world .entity_mut(root2) @@ -523,9 +515,9 @@ mod test { let is_visible = |e: Entity| { app.world .entity(e) - .get::() + .get::() .unwrap() - .is_visible_in_hierarchy() + .get() }; assert!( !is_visible(root1), @@ -577,32 +569,53 @@ mod test { let root1 = app .world - .spawn((Visibility::Visible, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Visible, + ..Default::default() + }) .id(); let root1_child1 = app .world - .spawn((Visibility::Inherited, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Inherited, + ..Default::default() + }) .id(); let root1_child2 = app .world - .spawn((Visibility::Hidden, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Hidden, + ..Default::default() + }) .id(); let root1_child1_grandchild1 = app .world - .spawn((Visibility::Visible, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Visible, + ..Default::default() + }) .id(); let root1_child2_grandchild1 = app .world - .spawn((Visibility::Visible, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Visible, + ..Default::default() + }) .id(); let root2 = app .world - .spawn((Visibility::Inherited, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Inherited, + ..Default::default() + }) .id(); let root3 = app .world - .spawn((Visibility::Hidden, ComputedVisibility::default())) + .spawn(VisibilityBundle { + visibility: Visibility::Hidden, + ..Default::default() + }) .id(); app.world @@ -620,9 +633,9 @@ mod test { let is_visible = |e: Entity| { app.world .entity(e) - .get::() + .get::() .unwrap() - .is_visible_in_hierarchy() + .get() }; assert!( is_visible(root1), diff --git a/crates/bevy_scene/src/bundle.rs b/crates/bevy_scene/src/bundle.rs index 1e66e5729325a..428ed84b2f9e2 100644 --- a/crates/bevy_scene/src/bundle.rs +++ b/crates/bevy_scene/src/bundle.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ system::{Commands, Query}, }; #[cfg(feature = "bevy_render")] -use bevy_render::prelude::{ComputedVisibility, Visibility}; +use bevy_render::prelude::{Visibility, VisibleInHierarchy, VisibleInView}; use bevy_transform::components::{GlobalTransform, Transform}; use crate::{DynamicScene, InstanceId, Scene, SceneSpawner}; @@ -32,7 +32,9 @@ pub struct SceneBundle { #[cfg(feature = "bevy_render")] pub visibility: Visibility, #[cfg(feature = "bevy_render")] - pub computed_visibility: ComputedVisibility, + pub visible_in_hierarchy: VisibleInHierarchy, + #[cfg(feature = "bevy_render")] + pub visible_in_view: VisibleInView, } /// A component bundle for a [`DynamicScene`] root. @@ -49,7 +51,9 @@ pub struct DynamicSceneBundle { #[cfg(feature = "bevy_render")] pub visibility: Visibility, #[cfg(feature = "bevy_render")] - pub computed_visibility: ComputedVisibility, + pub visible_in_hierarchy: VisibleInHierarchy, + #[cfg(feature = "bevy_render")] + pub visible_in_view: VisibleInView, } /// System that will spawn scenes from [`SceneBundle`]. diff --git a/crates/bevy_sprite/src/bundle.rs b/crates/bevy_sprite/src/bundle.rs index 092e5a302bb8b..33dda29038c2d 100644 --- a/crates/bevy_sprite/src/bundle.rs +++ b/crates/bevy_sprite/src/bundle.rs @@ -6,7 +6,7 @@ use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render::{ texture::{Image, DEFAULT_IMAGE_HANDLE}, - view::{ComputedVisibility, Visibility}, + view::{Visibility, VisibleInHierarchy, VisibleInView}, }; use bevy_transform::components::{GlobalTransform, Transform}; @@ -18,8 +18,10 @@ pub struct SpriteBundle { pub texture: Handle, /// User indication of whether an entity is visible pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } impl Default for SpriteBundle { @@ -30,7 +32,8 @@ impl Default for SpriteBundle { global_transform: Default::default(), texture: DEFAULT_IMAGE_HANDLE.typed(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), } } } @@ -47,6 +50,7 @@ pub struct SpriteSheetBundle { pub global_transform: GlobalTransform, /// User indication of whether an entity is visible pub visibility: Visibility, + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, } diff --git a/crates/bevy_sprite/src/mesh2d/material.rs b/crates/bevy_sprite/src/mesh2d/material.rs index 2ba6765e720df..dc826d5907298 100644 --- a/crates/bevy_sprite/src/mesh2d/material.rs +++ b/crates/bevy_sprite/src/mesh2d/material.rs @@ -31,7 +31,7 @@ use bevy_render::{ }, renderer::RenderDevice, texture::FallbackImage, - view::{ComputedVisibility, ExtractedView, Msaa, Visibility, VisibleEntities}, + view::{ExtractedView, Msaa, Visibility, VisibleEntities, VisibleInHierarchy, VisibleInView}, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; use bevy_transform::components::{GlobalTransform, Transform}; @@ -583,8 +583,10 @@ pub struct MaterialMesh2dBundle { pub global_transform: GlobalTransform, /// User indication of whether an entity is visible pub visibility: Visibility, - /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + // Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, + // Indication of whether an entity is visible in any view. + pub visible_in_view: VisibleInView, } impl Default for MaterialMesh2dBundle { @@ -595,7 +597,8 @@ impl Default for MaterialMesh2dBundle { transform: Default::default(), global_transform: Default::default(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), } } } diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 3e6c4ce068bca..1899d9b0d9cac 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -20,7 +20,7 @@ use bevy_render::{ BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo, }, view::{ - ComputedVisibility, ExtractedView, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms, + ExtractedView, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms, VisibleInView, }, Extract, ExtractSchedule, Render, RenderApp, RenderSet, }; @@ -139,11 +139,11 @@ bitflags::bitflags! { pub fn extract_mesh2d( mut commands: Commands, mut previous_len: Local, - query: Extract>, + query: Extract>, ) { let mut values = Vec::with_capacity(*previous_len); - for (entity, computed_visibility, transform, handle) in &query { - if !computed_visibility.is_visible() { + for (entity, visible_in_view, transform, handle) in &query { + if !visible_in_view.get() { continue; } let transform = transform.compute_matrix(); diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index 8bce8ac998ba4..9b76c1a3154a3 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -28,8 +28,8 @@ use bevy_render::{ BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo, }, view::{ - ComputedVisibility, ExtractedView, Msaa, ViewTarget, ViewUniform, ViewUniformOffset, - ViewUniforms, VisibleEntities, + ExtractedView, Msaa, ViewTarget, ViewUniform, ViewUniformOffset, ViewUniforms, + VisibleEntities, VisibleInView, }, Extract, }; @@ -352,7 +352,7 @@ pub fn extract_sprites( sprite_query: Extract< Query<( Entity, - &ComputedVisibility, + &VisibleInView, &Sprite, &GlobalTransform, &Handle, @@ -361,7 +361,7 @@ pub fn extract_sprites( atlas_query: Extract< Query<( Entity, - &ComputedVisibility, + &VisibleInView, &TextureAtlasSprite, &GlobalTransform, &Handle, @@ -369,8 +369,8 @@ pub fn extract_sprites( >, ) { extracted_sprites.sprites.clear(); - for (entity, visibility, sprite, transform, handle) in sprite_query.iter() { - if !visibility.is_visible() { + for (entity, visible_in_view, sprite, transform, handle) in sprite_query.iter() { + if !visible_in_view.get() { continue; } // PERF: we don't check in this function that the `Image` asset is ready, since it should be in most cases and hashing the handle is expensive @@ -387,8 +387,10 @@ pub fn extract_sprites( anchor: sprite.anchor.as_vec(), }); } - for (entity, visibility, atlas_sprite, transform, texture_atlas_handle) in atlas_query.iter() { - if !visibility.is_visible() { + for (entity, visible_in_view, atlas_sprite, transform, texture_atlas_handle) in + atlas_query.iter() + { + if !visible_in_view.get() { continue; } if let Some(texture_atlas) = texture_atlases.get(texture_atlas_handle) { diff --git a/crates/bevy_text/src/text2d.rs b/crates/bevy_text/src/text2d.rs index a7c72c5d44f86..cc90b2dddc530 100644 --- a/crates/bevy_text/src/text2d.rs +++ b/crates/bevy_text/src/text2d.rs @@ -14,7 +14,7 @@ use bevy_reflect::Reflect; use bevy_render::{ prelude::Color, texture::Image, - view::{ComputedVisibility, Visibility}, + view::{Visibility, VisibleInHierarchy, VisibleInView}, Extract, }; use bevy_sprite::{Anchor, ExtractedSprite, ExtractedSprites, TextureAtlas}; @@ -70,8 +70,10 @@ pub struct Text2dBundle { pub global_transform: GlobalTransform, /// The visibility properties of the text. pub visibility: Visibility, - /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering. - pub computed_visibility: ComputedVisibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, + /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering + pub visible_in_view: VisibleInView, /// Contains the size of the text and its glyph's position and scale data. Generated via [`TextPipeline::queue_text`] pub text_layout_info: TextLayoutInfo, } @@ -83,7 +85,7 @@ pub fn extract_text2d_sprite( text2d_query: Extract< Query<( Entity, - &ComputedVisibility, + &VisibleInView, &Text, &TextLayoutInfo, &Anchor, @@ -98,10 +100,10 @@ pub fn extract_text2d_sprite( .unwrap_or(1.0); let scaling = GlobalTransform::from_scale(Vec3::splat(scale_factor.recip())); - for (entity, computed_visibility, text, text_layout_info, anchor, global_transform) in + for (entity, visible_in_view, text, text_layout_info, anchor, global_transform) in text2d_query.iter() { - if !computed_visibility.is_visible() { + if !visible_in_view.get() { continue; } diff --git a/crates/bevy_ui/src/focus.rs b/crates/bevy_ui/src/focus.rs index 7837d19ac0bfa..7d06ec0e12774 100644 --- a/crates/bevy_ui/src/focus.rs +++ b/crates/bevy_ui/src/focus.rs @@ -11,7 +11,7 @@ use bevy_ecs::{ use bevy_input::{mouse::MouseButton, touch::Touches, Input}; use bevy_math::Vec2; use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize}; -use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::ComputedVisibility}; +use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::VisibleInView}; use bevy_transform::components::GlobalTransform; use bevy_window::{PrimaryWindow, Window}; @@ -125,7 +125,7 @@ pub struct NodeQuery { relative_cursor_position: Option<&'static mut RelativeCursorPosition>, focus_policy: Option<&'static FocusPolicy>, calculated_clip: Option<&'static CalculatedClip>, - computed_visibility: Option<&'static ComputedVisibility>, + visible_in_view: Option<&'static VisibleInView>, } /// The system that sets Interaction for all UI elements based on the mouse cursor activity @@ -204,8 +204,8 @@ pub fn ui_focus_system( .filter_map(|entity| { if let Ok(node) = node_query.get_mut(*entity) { // Nodes that are not rendered should not be interactable - if let Some(computed_visibility) = node.computed_visibility { - if !computed_visibility.is_visible() { + if let Some(visible_in_view) = node.visible_in_view { + if !visible_in_view.get() { // Reset their interaction to None to avoid strange stuck state if let Some(mut interaction) = node.interaction { // We cannot simply set the interaction to None, as that will trigger change detection repeatedly diff --git a/crates/bevy_ui/src/node_bundles.rs b/crates/bevy_ui/src/node_bundles.rs index a8c82a4828893..5521ebb88a819 100644 --- a/crates/bevy_ui/src/node_bundles.rs +++ b/crates/bevy_ui/src/node_bundles.rs @@ -10,8 +10,8 @@ use crate::{ use bevy_asset::Handle; use bevy_ecs::bundle::Bundle; use bevy_render::{ - prelude::{Color, ComputedVisibility}, - view::Visibility, + prelude::Color, + view::{Visibility, VisibleInHierarchy, VisibleInView}, }; use bevy_sprite::TextureAtlas; #[cfg(feature = "bevy_text")] @@ -46,8 +46,10 @@ pub struct NodeBundle { pub global_transform: GlobalTransform, /// Describes the visibility properties of the node pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, } @@ -64,7 +66,8 @@ impl Default for NodeBundle { transform: Default::default(), global_transform: Default::default(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), z_index: Default::default(), } } @@ -107,8 +110,10 @@ pub struct ImageBundle { pub global_transform: GlobalTransform, /// Describes the visibility properties of the node pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, } @@ -152,8 +157,10 @@ pub struct AtlasImageBundle { pub global_transform: GlobalTransform, /// Describes the visibility properties of the node pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, } @@ -189,8 +196,10 @@ pub struct TextBundle { pub global_transform: GlobalTransform, /// Describes the visibility properties of the node pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, /// The background color that will fill the containing node @@ -205,16 +214,17 @@ impl Default for TextBundle { text_layout_info: Default::default(), text_flags: Default::default(), calculated_size: Default::default(), - // Transparent background - background_color: BackgroundColor(Color::NONE), node: Default::default(), style: Default::default(), focus_policy: Default::default(), transform: Default::default(), global_transform: Default::default(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), z_index: Default::default(), + // Transparent background + background_color: BackgroundColor(Color::NONE), } } } @@ -301,8 +311,10 @@ pub struct ButtonBundle { pub global_transform: GlobalTransform, /// Describes the visibility properties of the node pub visibility: Visibility, + /// Inherited visibility of an entity. + pub visible_in_hierarchy: VisibleInHierarchy, /// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering - pub computed_visibility: ComputedVisibility, + pub visible_in_view: VisibleInView, /// Indicates the depth at which the node should appear in the UI pub z_index: ZIndex, } @@ -321,7 +333,8 @@ impl Default for ButtonBundle { transform: Default::default(), global_transform: Default::default(), visibility: Default::default(), - computed_visibility: Default::default(), + visible_in_hierarchy: Default::default(), + visible_in_view: Default::default(), z_index: Default::default(), } } diff --git a/crates/bevy_ui/src/render/mod.rs b/crates/bevy_ui/src/render/mod.rs index 43753866dd4e0..0c2c0b0d5710c 100644 --- a/crates/bevy_ui/src/render/mod.rs +++ b/crates/bevy_ui/src/render/mod.rs @@ -3,6 +3,7 @@ mod render_pass; use bevy_core_pipeline::{core_2d::Camera2d, core_3d::Camera3d}; use bevy_hierarchy::Parent; +use bevy_render::view::VisibleInView; use bevy_render::{ExtractSchedule, Render}; use bevy_window::{PrimaryWindow, Window}; pub use pipeline::*; @@ -28,7 +29,7 @@ use bevy_render::{ render_resource::*, renderer::{RenderDevice, RenderQueue}, texture::Image, - view::{ComputedVisibility, ExtractedView, ViewUniforms}, + view::{ExtractedView, ViewUniforms}, Extract, RenderApp, RenderSet, }; use bevy_sprite::SpriteAssetEvents; @@ -180,7 +181,7 @@ pub fn extract_atlas_uinodes( &Node, &GlobalTransform, &BackgroundColor, - &ComputedVisibility, + &VisibleInView, Option<&CalculatedClip>, &Handle, &UiTextureAtlasImage, @@ -190,11 +191,18 @@ pub fn extract_atlas_uinodes( >, ) { for (stack_index, entity) in ui_stack.uinodes.iter().enumerate() { - if let Ok((uinode, transform, color, visibility, clip, texture_atlas_handle, atlas_image)) = - uinode_query.get(*entity) + if let Ok(( + uinode, + transform, + color, + visible_in_view, + clip, + texture_atlas_handle, + atlas_image, + )) = uinode_query.get(*entity) { // Skip invisible and completely transparent nodes - if !visibility.is_visible() || color.0.a() == 0.0 { + if !visible_in_view.get() || color.0.a() == 0.0 { continue; } @@ -270,7 +278,7 @@ pub fn extract_uinode_borders( &Style, &BorderColor, Option<&Parent>, - &ComputedVisibility, + &VisibleInView, Option<&CalculatedClip>, ), Without, @@ -289,11 +297,11 @@ pub fn extract_uinode_borders( / ui_scale.scale as f32; for (stack_index, entity) in ui_stack.uinodes.iter().enumerate() { - if let Ok((node, global_transform, style, border_color, parent, visibility, clip)) = + if let Ok((node, global_transform, style, border_color, parent, visible_in_view, clip)) = uinode_query.get(*entity) { // Skip invisible borders - if !visibility.is_visible() + if !visible_in_view.get() || border_color.0.a() == 0.0 || node.size().x <= 0. || node.size().y <= 0. @@ -387,7 +395,7 @@ pub fn extract_uinodes( &GlobalTransform, &BackgroundColor, Option<&UiImage>, - &ComputedVisibility, + &VisibleInView, Option<&CalculatedClip>, ), Without, @@ -395,11 +403,11 @@ pub fn extract_uinodes( >, ) { for (stack_index, entity) in ui_stack.uinodes.iter().enumerate() { - if let Ok((uinode, transform, color, maybe_image, visibility, clip)) = + if let Ok((uinode, transform, color, maybe_image, visible_in_view, clip)) = uinode_query.get(*entity) { // Skip invisible and completely transparent nodes - if !visibility.is_visible() || color.0.a() == 0.0 { + if !visible_in_view.get() || color.0.a() == 0.0 { continue; } @@ -517,7 +525,7 @@ pub fn extract_text_uinodes( &GlobalTransform, &Text, &TextLayoutInfo, - &ComputedVisibility, + &VisibleInView, Option<&CalculatedClip>, )>, >, @@ -532,11 +540,11 @@ pub fn extract_text_uinodes( let inverse_scale_factor = (scale_factor as f32).recip(); for (stack_index, entity) in ui_stack.uinodes.iter().enumerate() { - if let Ok((uinode, global_transform, text, text_layout_info, visibility, clip)) = + if let Ok((uinode, global_transform, text, text_layout_info, visible_in_view, clip)) = uinode_query.get(*entity) { // Skip if not visible or if size is set to zero (e.g. when a parent is set to `Display::None`) - if !visibility.is_visible() || uinode.size().x == 0. || uinode.size().y == 0. { + if !visible_in_view.get() || uinode.size().x == 0. || uinode.size().y == 0. { continue; } let transform = global_transform.compute_matrix() From e1ba867f880a79fb0da763a02ad1c701adcd0708 Mon Sep 17 00:00:00 2001 From: Joseph <21144246+JoJoJet@users.noreply.github.com> Date: Fri, 18 Aug 2023 23:59:33 -0400 Subject: [PATCH 02/17] update examples --- examples/2d/mesh2d_manual.rs | 6 +++--- examples/stress_tests/many_cubes.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/2d/mesh2d_manual.rs b/examples/2d/mesh2d_manual.rs index f2fb481388dfa..dc9473ff24cb9 100644 --- a/examples/2d/mesh2d_manual.rs +++ b/examples/2d/mesh2d_manual.rs @@ -296,11 +296,11 @@ pub fn extract_colored_mesh2d( mut previous_len: Local, // When extracting, you must use `Extract` to mark the `SystemParam`s // which should be taken from the main world. - query: Extract>>, + query: Extract>>, ) { let mut values = Vec::with_capacity(*previous_len); - for (entity, computed_visibility) in &query { - if !computed_visibility.is_visible() { + for (entity, visible_in_view) in &query { + if !visible_in_view.get() { continue; } values.push((entity, ColoredMesh2d)); diff --git a/examples/stress_tests/many_cubes.rs b/examples/stress_tests/many_cubes.rs index 20495b1ab7a61..89065d5f7f1cb 100644 --- a/examples/stress_tests/many_cubes.rs +++ b/examples/stress_tests/many_cubes.rs @@ -170,7 +170,7 @@ fn move_camera(time: Res