Opt-out for UI clipping (#19826)

# Objective

Opt-out for UI clipping, for motivation see issue #19821

## Solution

New zst component `OverrideClip`. A UI node entity with this component
will ignore any inherited clipping rect, so it will never get clipped
regardless of the `Overflow` settings of its ancestors.

#### Why use a marker component and not add a new variant to `Overflow`
instead?
A separate marker component allows users to set both `Overflow` and
`OverrideClip` on the same node.

## Testing

Run the `overflow` example with the `OverrideClip` component added to
the `ImagNode`s and you will see that clipping is disabled.
This commit is contained in:
ickshonpe 2025-06-27 18:17:09 +01:00 committed by GitHub
parent a0b90cd618
commit 45a379cf2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 4 deletions

View File

@ -2246,6 +2246,11 @@ pub struct CalculatedClip {
pub clip: Rect,
}
/// UI node entities with this component will ignore any clipping rect they inherit,
/// the node will not be clipped regardless of its ancestors' `Overflow` setting.
#[derive(Component)]
pub struct OverrideClip;
/// Indicates that this [`Node`] entity's front-to-back ordering is not controlled solely
/// by its location in the UI hierarchy. A node with a higher z-index will appear on top
/// of sibling nodes with a lower z-index.

View File

@ -3,8 +3,8 @@
use crate::{
experimental::{UiChildren, UiRootNodes},
ui_transform::UiGlobalTransform,
CalculatedClip, ComputedNodeTarget, DefaultUiCamera, Display, Node, OverflowAxis, UiScale,
UiTargetCamera,
CalculatedClip, ComputedNodeTarget, DefaultUiCamera, Display, Node, OverflowAxis, OverrideClip,
UiScale, UiTargetCamera,
};
use super::ComputedNode;
@ -12,7 +12,7 @@ use bevy_ecs::{
change_detection::DetectChangesMut,
entity::Entity,
hierarchy::ChildOf,
query::{Changed, With},
query::{Changed, Has, With},
system::{Commands, Query, Res},
};
use bevy_math::{Rect, UVec2};
@ -28,6 +28,7 @@ pub fn update_clipping_system(
&ComputedNode,
&UiGlobalTransform,
Option<&mut CalculatedClip>,
Has<OverrideClip>,
)>,
ui_children: UiChildren,
) {
@ -50,15 +51,22 @@ fn update_clipping(
&ComputedNode,
&UiGlobalTransform,
Option<&mut CalculatedClip>,
Has<OverrideClip>,
)>,
entity: Entity,
mut maybe_inherited_clip: Option<Rect>,
) {
let Ok((node, computed_node, transform, maybe_calculated_clip)) = node_query.get_mut(entity)
let Ok((node, computed_node, transform, maybe_calculated_clip, has_override_clip)) =
node_query.get_mut(entity)
else {
return;
};
// If the UI node entity has an `OverrideClip` component, discard any inherited clip rect
if has_override_clip {
maybe_inherited_clip = None;
}
// If `display` is None, clip the entire node and all its descendants by replacing the inherited clip with a default rect (which is empty)
if node.display == Display::None {
maybe_inherited_clip = Some(Rect::default());