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:
parent
7577895d0c
commit
c9a3f34f5d
@ -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(),
|
||||||
|
@ -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());
|
||||||
|
Loading…
Reference in New Issue
Block a user