use crate::{
experimental::{UiChildren, UiRootNodes},
ui_transform::UiGlobalTransform,
CalculatedClip, ComputedNode, Display, FixedNode, Node, OverrideClip,
};
use bevy_ecs::{
entity::Entity,
query::Has,
system::{Commands, Query},
};
pub fn update_clipping_system(
mut commands: Commands,
root_nodes: UiRootNodes,
mut node_query: Query<(
&Node,
&ComputedNode,
&UiGlobalTransform,
Option<&mut CalculatedClip>,
Has<OverrideClip>,
Has<FixedNode>,
)>,
ui_children: UiChildren,
) {
for root_node in root_nodes.iter() {
update_clipping(
&mut commands,
&ui_children,
&mut node_query,
root_node,
None,
);
}
}
fn update_clipping(
commands: &mut Commands,
ui_children: &UiChildren,
node_query: &mut Query<(
&Node,
&ComputedNode,
&UiGlobalTransform,
Option<&mut CalculatedClip>,
Has<OverrideClip>,
Has<FixedNode>,
)>,
entity: Entity,
mut maybe_inherited_clip: Option<CalculatedClip>,
) {
let Ok((
node,
computed_node,
transform,
maybe_calculated_clip,
has_override_clip,
has_fixed_node,
)) = node_query.get_mut(entity)
else {
return;
};
if has_override_clip || has_fixed_node {
maybe_inherited_clip = None;
}
if node.display == Display::None {
maybe_inherited_clip = Some(CalculatedClip::FullyClipped);
}
if let Some(mut calculated_clip) = maybe_calculated_clip {
if let Some(inherited_clip) = maybe_inherited_clip.as_ref() {
if *calculated_clip != *inherited_clip {
*calculated_clip = inherited_clip.clone();
}
} else {
commands.entity(entity).remove::<CalculatedClip>();
}
} else if let Some(inherited_clip) = maybe_inherited_clip.as_ref() {
commands.entity(entity).try_insert(inherited_clip.clone());
}
let children_clip = if maybe_inherited_clip
.as_ref()
.is_some_and(CalculatedClip::is_fully_clipped)
|| node.overflow.is_visible()
{
maybe_inherited_clip
} else if let Some(clip_from_world) = transform.try_inverse() {
let mut clip = maybe_inherited_clip.unwrap_or_default();
clip.push_rect(
computed_node.resolve_clip_rect(node.overflow, node.overflow_clip_margin),
clip_from_world,
);
Some(clip)
} else {
Some(CalculatedClip::FullyClipped)
};
for child in ui_children.iter_ui_children(entity) {
update_clipping(
commands,
ui_children,
node_query,
child,
children_clip.clone(),
);
}
}