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" />
This commit is contained in:
parent
68c19defb6
commit
dd2d84b342
@ -12,7 +12,7 @@ use bevy_ecs::{
|
||||
use bevy_input::{mouse::MouseButton, touch::Touches, ButtonInput};
|
||||
use bevy_math::{Rect, Vec2};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::ViewVisibility};
|
||||
use bevy_render::{camera::NormalizedRenderTarget, prelude::Camera, view::InheritedVisibility};
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_utils::HashMap;
|
||||
use bevy_window::{PrimaryWindow, Window};
|
||||
@ -28,9 +28,9 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
|
||||
///
|
||||
/// Updated in [`ui_focus_system`].
|
||||
///
|
||||
/// If a UI node has both [`Interaction`] and [`ViewVisibility`] components,
|
||||
/// If a UI node has both [`Interaction`] and [`InheritedVisibility`] components,
|
||||
/// [`Interaction`] will always be [`Interaction::None`]
|
||||
/// when [`ViewVisibility::get()`] is false.
|
||||
/// when [`InheritedVisibility::get()`] is false.
|
||||
/// This ensures that hidden UI nodes are not interactable,
|
||||
/// and do not end up stuck in an active state if hidden at the wrong time.
|
||||
///
|
||||
@ -140,13 +140,13 @@ pub struct NodeQuery {
|
||||
relative_cursor_position: Option<&'static mut RelativeCursorPosition>,
|
||||
focus_policy: Option<&'static FocusPolicy>,
|
||||
calculated_clip: Option<&'static CalculatedClip>,
|
||||
view_visibility: Option<&'static ViewVisibility>,
|
||||
inherited_visibility: Option<&'static InheritedVisibility>,
|
||||
target_camera: Option<&'static UiTargetCamera>,
|
||||
}
|
||||
|
||||
/// The system that sets Interaction for all UI elements based on the mouse cursor activity
|
||||
///
|
||||
/// Entities with a hidden [`ViewVisibility`] are always treated as released.
|
||||
/// Entities with a hidden [`InheritedVisibility`] are always treated as released.
|
||||
pub fn ui_focus_system(
|
||||
mut state: Local<State>,
|
||||
camera_query: Query<(Entity, &Camera)>,
|
||||
@ -227,9 +227,9 @@ pub fn ui_focus_system(
|
||||
return None;
|
||||
};
|
||||
|
||||
let view_visibility = node.view_visibility?;
|
||||
let inherited_visibility = node.inherited_visibility?;
|
||||
// Nodes that are not rendered should not be interactable
|
||||
if !view_visibility.get() {
|
||||
if !inherited_visibility.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
|
||||
|
||||
@ -50,7 +50,7 @@ pub struct NodeQuery {
|
||||
global_transform: &'static GlobalTransform,
|
||||
pickable: Option<&'static Pickable>,
|
||||
calculated_clip: Option<&'static CalculatedClip>,
|
||||
view_visibility: Option<&'static ViewVisibility>,
|
||||
inherited_visibility: Option<&'static InheritedVisibility>,
|
||||
target_camera: Option<&'static UiTargetCamera>,
|
||||
}
|
||||
|
||||
@ -124,8 +124,8 @@ pub fn ui_picking(
|
||||
|
||||
// Nodes that are not rendered should not be interactable
|
||||
if node
|
||||
.view_visibility
|
||||
.map(|view_visibility| view_visibility.get())
|
||||
.inherited_visibility
|
||||
.map(|inherited_visibility| inherited_visibility.get())
|
||||
!= Some(true)
|
||||
{
|
||||
continue;
|
||||
|
||||
@ -243,7 +243,7 @@ pub fn extract_shadows(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
&BoxShadow,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
@ -253,8 +253,7 @@ pub fn extract_shadows(
|
||||
) {
|
||||
let default_camera_entity = default_ui_camera.get();
|
||||
|
||||
for (entity, uinode, transform, view_visibility, box_shadow, clip, camera) in &box_shadow_query
|
||||
{
|
||||
for (entity, uinode, transform, visibility, box_shadow, clip, camera) in &box_shadow_query {
|
||||
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
|
||||
else {
|
||||
continue;
|
||||
@ -265,7 +264,7 @@ pub fn extract_shadows(
|
||||
};
|
||||
|
||||
// Skip if no visible shadows
|
||||
if !view_visibility.get() || box_shadow.is_empty() || uinode.is_empty() {
|
||||
if !visibility.get() || box_shadow.is_empty() || uinode.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ use bevy_math::Rect;
|
||||
use bevy_math::Vec2;
|
||||
use bevy_render::sync_world::RenderEntity;
|
||||
use bevy_render::sync_world::TemporaryRenderEntity;
|
||||
use bevy_render::view::ViewVisibility;
|
||||
use bevy_render::view::InheritedVisibility;
|
||||
use bevy_render::Extract;
|
||||
use bevy_sprite::BorderRect;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
@ -63,7 +63,7 @@ pub fn extract_debug_overlay(
|
||||
Query<(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
&GlobalTransform,
|
||||
Option<&UiTargetCamera>,
|
||||
|
||||
@ -42,7 +42,7 @@ use bevy_render::{
|
||||
render_phase::{PhaseItem, PhaseItemExtraIndex},
|
||||
sync_world::{RenderEntity, TemporaryRenderEntity},
|
||||
texture::GpuImage,
|
||||
view::ViewVisibility,
|
||||
view::InheritedVisibility,
|
||||
ExtractSchedule, Render,
|
||||
};
|
||||
use bevy_sprite::{BorderRect, SpriteAssetEvents};
|
||||
@ -285,7 +285,7 @@ pub fn extract_uinode_background_colors(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
&BackgroundColor,
|
||||
@ -294,7 +294,7 @@ pub fn extract_uinode_background_colors(
|
||||
mapping: Extract<Query<RenderEntity>>,
|
||||
) {
|
||||
let default_camera_entity = default_ui_camera.get();
|
||||
for (entity, uinode, transform, view_visibility, clip, camera, background_color) in
|
||||
for (entity, uinode, transform, inherited_visibility, clip, camera, background_color) in
|
||||
&uinode_query
|
||||
{
|
||||
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
|
||||
@ -307,7 +307,7 @@ pub fn extract_uinode_background_colors(
|
||||
};
|
||||
|
||||
// Skip invisible backgrounds
|
||||
if !view_visibility.get() || background_color.0.is_fully_transparent() {
|
||||
if !inherited_visibility.get() || background_color.0.is_fully_transparent() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ pub fn extract_uinode_images(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
&ImageNode,
|
||||
@ -357,7 +357,7 @@ pub fn extract_uinode_images(
|
||||
mapping: Extract<Query<RenderEntity>>,
|
||||
) {
|
||||
let default_camera_entity = default_ui_camera.get();
|
||||
for (entity, uinode, transform, view_visibility, clip, camera, image) in &uinode_query {
|
||||
for (entity, uinode, transform, inherited_visibility, clip, camera, image) in &uinode_query {
|
||||
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
|
||||
else {
|
||||
continue;
|
||||
@ -368,7 +368,7 @@ pub fn extract_uinode_images(
|
||||
};
|
||||
|
||||
// Skip invisible images
|
||||
if !view_visibility.get()
|
||||
if !inherited_visibility.get()
|
||||
|| image.color.is_fully_transparent()
|
||||
|| image.image.id() == TRANSPARENT_IMAGE_HANDLE.id()
|
||||
|| image.image_mode.uses_slices()
|
||||
@ -439,7 +439,7 @@ pub fn extract_uinode_borders(
|
||||
&Node,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
AnyOf<(&BorderColor, &Outline)>,
|
||||
@ -454,7 +454,7 @@ pub fn extract_uinode_borders(
|
||||
node,
|
||||
computed_node,
|
||||
global_transform,
|
||||
view_visibility,
|
||||
inherited_visibility,
|
||||
maybe_clip,
|
||||
maybe_camera,
|
||||
(maybe_border_color, maybe_outline),
|
||||
@ -472,7 +472,7 @@ pub fn extract_uinode_borders(
|
||||
};
|
||||
|
||||
// Skip invisible borders and removed nodes
|
||||
if !view_visibility.get() || node.display == Display::None {
|
||||
if !inherited_visibility.get() || node.display == Display::None {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -678,7 +678,7 @@ pub fn extract_text_sections(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
&ComputedTextBlock,
|
||||
@ -696,7 +696,7 @@ pub fn extract_text_sections(
|
||||
entity,
|
||||
uinode,
|
||||
global_transform,
|
||||
view_visibility,
|
||||
inherited_visibility,
|
||||
clip,
|
||||
camera,
|
||||
computed_block,
|
||||
@ -708,7 +708,7 @@ pub fn extract_text_sections(
|
||||
};
|
||||
|
||||
// Skip if not visible or if size is set to zero (e.g. when a parent is set to `Display::None`)
|
||||
if !view_visibility.get() || uinode.is_empty() {
|
||||
if !inherited_visibility.get() || uinode.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -369,7 +369,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&MaterialNode<M>,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
)>,
|
||||
@ -379,7 +379,9 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
|
||||
// If there is only one camera, we use it as default
|
||||
let default_single_camera = default_ui_camera.get();
|
||||
|
||||
for (entity, uinode, transform, handle, view_visibility, clip, camera) in uinode_query.iter() {
|
||||
for (entity, uinode, transform, handle, inherited_visibility, clip, camera) in
|
||||
uinode_query.iter()
|
||||
{
|
||||
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_single_camera)
|
||||
else {
|
||||
continue;
|
||||
@ -390,7 +392,7 @@ pub fn extract_ui_material_nodes<M: UiMaterial>(
|
||||
};
|
||||
|
||||
// skip invisible nodes
|
||||
if !view_visibility.get() {
|
||||
if !inherited_visibility.get() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -254,7 +254,7 @@ pub fn extract_ui_texture_slices(
|
||||
Entity,
|
||||
&ComputedNode,
|
||||
&GlobalTransform,
|
||||
&ViewVisibility,
|
||||
&InheritedVisibility,
|
||||
Option<&CalculatedClip>,
|
||||
Option<&UiTargetCamera>,
|
||||
&ImageNode,
|
||||
@ -264,7 +264,7 @@ pub fn extract_ui_texture_slices(
|
||||
) {
|
||||
let default_camera_entity = default_ui_camera.get();
|
||||
|
||||
for (entity, uinode, transform, view_visibility, clip, camera, image) in &slicers_query {
|
||||
for (entity, uinode, transform, inherited_visibility, clip, camera, image) in &slicers_query {
|
||||
let Some(camera_entity) = camera.map(UiTargetCamera::entity).or(default_camera_entity)
|
||||
else {
|
||||
continue;
|
||||
@ -291,7 +291,7 @@ pub fn extract_ui_texture_slices(
|
||||
};
|
||||
|
||||
// Skip invisible images
|
||||
if !view_visibility.get()
|
||||
if !inherited_visibility.get()
|
||||
|| image.color.is_fully_transparent()
|
||||
|| image.image.id() == TRANSPARENT_IMAGE_HANDLE.id()
|
||||
{
|
||||
|
||||
@ -6,7 +6,7 @@ use bevy_math::{vec4, Rect, Vec2, Vec4Swizzles};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::{Camera, RenderTarget},
|
||||
view::{self, Visibility, VisibilityClass},
|
||||
view::Visibility,
|
||||
};
|
||||
use bevy_sprite::BorderRect;
|
||||
use bevy_transform::components::Transform;
|
||||
@ -329,11 +329,9 @@ impl From<Vec2> for ScrollPosition {
|
||||
ScrollPosition,
|
||||
Transform,
|
||||
Visibility,
|
||||
VisibilityClass,
|
||||
ZIndex
|
||||
)]
|
||||
#[reflect(Component, Default, PartialEq, Debug)]
|
||||
#[component(on_add = view::add_visibility_class::<Node>)]
|
||||
#[cfg_attr(
|
||||
feature = "serialize",
|
||||
derive(serde::Serialize, serde::Deserialize),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user