Fixes for a few minor borders and outlines bugs (#16071)

# Objective

1. Nodes with `Display::None` set are removed from the layout and have
no position or size. Outlines should not be drawn for a node with
`Display::None` set.
2. The outline and border colors are checked for transparency together.
If only one of the two is transparent, both will get queued.
3. The `node.is_empty()` check is insufficient to check if a border is
present since a non-zero sized node can have a zero width border.

## Solution

1. Add a check to `extract_uinode_borders` and ignore the node if
`Display::None` is set.
2. Filter the border and outline optional components by
`is_fully_transparent`.
3.  Check if all the border widths are zero instead.

## Testing

I added dark cyan outlines around the left and right sections in the
`display_and_visibility` example. If you run the example and set the
outermost node to `Display::None` on the right, then you'll see the that
the outline on the left disappears.
This commit is contained in:
ickshonpe 2024-10-23 21:41:42 +01:00 committed by GitHub
parent 7577895d0c
commit c9a3f34f5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 21 deletions

View File

@ -5,8 +5,8 @@ mod ui_material_pipeline;
pub mod ui_texture_slice_pipeline; pub mod ui_texture_slice_pipeline;
use crate::{ use crate::{
BackgroundColor, BorderColor, CalculatedClip, ComputedNode, DefaultUiCamera, Outline, BackgroundColor, BorderColor, CalculatedClip, ComputedNode, DefaultUiCamera, Display, Node,
ResolvedBorderRadius, TargetCamera, UiAntiAlias, UiBoxShadowSamples, UiImage, UiScale, Outline, ResolvedBorderRadius, TargetCamera, UiAntiAlias, UiBoxShadowSamples, UiImage, UiScale,
}; };
use bevy_app::prelude::*; use bevy_app::prelude::*;
use bevy_asset::{load_internal_asset, AssetEvent, AssetId, Assets, Handle}; use bevy_asset::{load_internal_asset, AssetEvent, AssetId, Assets, Handle};
@ -399,6 +399,7 @@ pub fn extract_uinode_borders(
uinode_query: Extract< uinode_query: Extract<
Query<( Query<(
Entity, Entity,
&Node,
&ComputedNode, &ComputedNode,
&GlobalTransform, &GlobalTransform,
&ViewVisibility, &ViewVisibility,
@ -415,7 +416,8 @@ pub fn extract_uinode_borders(
for ( for (
entity, entity,
uinode, node,
computed_node,
global_transform, global_transform,
view_visibility, view_visibility,
maybe_clip, maybe_clip,
@ -435,24 +437,22 @@ pub fn extract_uinode_borders(
continue; continue;
}; };
// Skip invisible borders // Skip invisible borders and removed nodes
if !view_visibility.get() if !view_visibility.get() || node.display == Display::None {
|| maybe_border_color.is_some_and(|border_color| border_color.0.is_fully_transparent())
&& maybe_outline.is_some_and(|outline| outline.color.is_fully_transparent())
{
continue; continue;
} }
// don't extract border if no border or the node is zero-sized (a zero sized node can still have an outline). // Don't extract borders with zero width along all edges
if !uinode.is_empty() && uinode.border() != BorderRect::ZERO { if computed_node.border() != BorderRect::ZERO {
if let Some(border_color) = maybe_border_color { if let Some(border_color) = maybe_border_color.filter(|bc| !bc.0.is_fully_transparent())
{
extracted_uinodes.uinodes.insert( extracted_uinodes.uinodes.insert(
commands.spawn(TemporaryRenderEntity).id(), commands.spawn(TemporaryRenderEntity).id(),
ExtractedUiNode { ExtractedUiNode {
stack_index: uinode.stack_index, stack_index: computed_node.stack_index,
color: border_color.0.into(), color: border_color.0.into(),
rect: Rect { rect: Rect {
max: uinode.size(), max: computed_node.size(),
..Default::default() ..Default::default()
}, },
image, image,
@ -463,8 +463,8 @@ pub fn extract_uinode_borders(
transform: global_transform.compute_matrix(), transform: global_transform.compute_matrix(),
flip_x: false, flip_x: false,
flip_y: false, flip_y: false,
border: uinode.border(), border: computed_node.border(),
border_radius: uinode.border_radius(), border_radius: computed_node.border_radius(),
node_type: NodeType::Border, node_type: NodeType::Border,
}, },
main_entity: entity.into(), main_entity: entity.into(),
@ -473,15 +473,20 @@ pub fn extract_uinode_borders(
} }
} }
if let Some(outline) = maybe_outline { if computed_node.outline_width() <= 0. {
let outline_size = uinode.outlined_node_size(); continue;
}
if let Some(outline) = maybe_outline.filter(|outline| !outline.color.is_fully_transparent())
{
let outline_size = computed_node.outlined_node_size();
let parent_clip = let parent_clip =
maybe_parent.and_then(|parent| parent_clip_query.get(parent.get()).ok()); maybe_parent.and_then(|parent| parent_clip_query.get(parent.get()).ok());
extracted_uinodes.uinodes.insert( extracted_uinodes.uinodes.insert(
commands.spawn(TemporaryRenderEntity).id(), commands.spawn(TemporaryRenderEntity).id(),
ExtractedUiNode { ExtractedUiNode {
stack_index: uinode.stack_index, stack_index: computed_node.stack_index,
color: outline.color.into(), color: outline.color.into(),
rect: Rect { rect: Rect {
max: outline_size, max: outline_size,
@ -495,8 +500,8 @@ pub fn extract_uinode_borders(
atlas_scaling: None, atlas_scaling: None,
flip_x: false, flip_x: false,
flip_y: false, flip_y: false,
border: BorderRect::square(uinode.outline_width()), border: BorderRect::square(computed_node.outline_width()),
border_radius: uinode.outline_radius(), border_radius: computed_node.outline_radius(),
node_type: NodeType::Border, node_type: NodeType::Border,
}, },
main_entity: entity.into(), main_entity: entity.into(),

View File

@ -1,7 +1,7 @@
//! Demonstrates how Display and Visibility work in the UI. //! Demonstrates how Display and Visibility work in the UI.
use bevy::{ use bevy::{
color::palettes::css::{DARK_GRAY, YELLOW}, color::palettes::css::{DARK_CYAN, DARK_GRAY, YELLOW},
prelude::*, prelude::*,
winit::WinitSettings, winit::WinitSettings,
}; };
@ -187,6 +187,11 @@ fn spawn_left_panel(builder: &mut ChildBuilder, palette: &[Color; 4]) -> Vec<Ent
..default() ..default()
}, },
BackgroundColor(palette[0]), BackgroundColor(palette[0]),
Outline {
width: Val::Px(4.),
color: DARK_CYAN.into(),
offset: Val::Px(10.),
},
)) ))
.with_children(|parent| { .with_children(|parent| {
parent.spawn(Node { parent.spawn(Node {
@ -289,6 +294,11 @@ fn spawn_right_panel(
..default() ..default()
}, },
BackgroundColor(palette[0]), BackgroundColor(palette[0]),
Outline {
width: Val::Px(4.),
color: DARK_CYAN.into(),
offset: Val::Px(10.),
},
)) ))
.with_children(|parent| { .with_children(|parent| {
spawn_buttons(parent, target_ids.pop().unwrap()); spawn_buttons(parent, target_ids.pop().unwrap());