Fix the double leaf node updates in flex_node_system (#8264)
# Objective If a UI node has a changed `CalculatedSize` component and either the UI does a full update or the node also has a changed `Style` component, the node's corresponding Taffy node will be updated twice by `flex_node_system`. ## Solution Add a `Without<Calculated>` query filter so that the two changed node queries in `flex_node_system` are mutually exclusive and move the `CalculatedSize` node updater into the else block of the full-update if conditional.
This commit is contained in:
parent
e900bd9e12
commit
0cf3000ee0
@ -5,7 +5,7 @@ use bevy_ecs::{
|
|||||||
change_detection::DetectChanges,
|
change_detection::DetectChanges,
|
||||||
entity::Entity,
|
entity::Entity,
|
||||||
event::EventReader,
|
event::EventReader,
|
||||||
query::{Changed, ReadOnlyWorldQuery, With, Without},
|
query::{Changed, Or, With, Without},
|
||||||
removal_detection::RemovedComponents,
|
removal_detection::RemovedComponents,
|
||||||
system::{Query, Res, ResMut, Resource},
|
system::{Query, Res, ResMut, Resource},
|
||||||
};
|
};
|
||||||
@ -244,11 +244,14 @@ pub fn ui_layout_system(
|
|||||||
mut resize_events: EventReader<bevy_window::WindowResized>,
|
mut resize_events: EventReader<bevy_window::WindowResized>,
|
||||||
mut ui_surface: ResMut<UiSurface>,
|
mut ui_surface: ResMut<UiSurface>,
|
||||||
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
|
root_node_query: Query<Entity, (With<Node>, Without<Parent>)>,
|
||||||
node_query: Query<(Entity, &Style, Option<&CalculatedSize>), (With<Node>, Changed<Style>)>,
|
|
||||||
full_node_query: Query<(Entity, &Style, Option<&CalculatedSize>), With<Node>>,
|
full_node_query: Query<(Entity, &Style, Option<&CalculatedSize>), With<Node>>,
|
||||||
|
changed_style_query: Query<
|
||||||
|
(Entity, &Style),
|
||||||
|
(With<Node>, Without<CalculatedSize>, Changed<Style>),
|
||||||
|
>,
|
||||||
changed_size_query: Query<
|
changed_size_query: Query<
|
||||||
(Entity, &Style, &CalculatedSize),
|
(Entity, &Style, &CalculatedSize),
|
||||||
(With<Node>, Changed<CalculatedSize>),
|
(With<Node>, Or<(Changed<CalculatedSize>, Changed<Style>)>),
|
||||||
>,
|
>,
|
||||||
children_query: Query<(Entity, &Children), (With<Node>, Changed<Children>)>,
|
children_query: Query<(Entity, &Children), (With<Node>, Changed<Children>)>,
|
||||||
mut removed_children: RemovedComponents<Children>,
|
mut removed_children: RemovedComponents<Children>,
|
||||||
@ -282,34 +285,28 @@ pub fn ui_layout_system(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let scale_factor = logical_to_physical_factor * ui_scale.scale;
|
let scale_factor = logical_to_physical_factor * ui_scale.scale;
|
||||||
|
let layout_context = LayoutContext::new(scale_factor, physical_size);
|
||||||
let viewport_values = LayoutContext::new(scale_factor, physical_size);
|
|
||||||
|
|
||||||
fn update_changed<F: ReadOnlyWorldQuery>(
|
|
||||||
ui_surface: &mut UiSurface,
|
|
||||||
viewport_values: &LayoutContext,
|
|
||||||
query: Query<(Entity, &Style, Option<&CalculatedSize>), F>,
|
|
||||||
) {
|
|
||||||
// update changed nodes
|
|
||||||
for (entity, style, calculated_size) in &query {
|
|
||||||
// TODO: remove node from old hierarchy if its root has changed
|
|
||||||
if let Some(calculated_size) = calculated_size {
|
|
||||||
ui_surface.upsert_leaf(entity, style, calculated_size, viewport_values);
|
|
||||||
} else {
|
|
||||||
ui_surface.upsert_node(entity, style, viewport_values);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !scale_factor_events.is_empty() || ui_scale.is_changed() || resized {
|
if !scale_factor_events.is_empty() || ui_scale.is_changed() || resized {
|
||||||
scale_factor_events.clear();
|
scale_factor_events.clear();
|
||||||
update_changed(&mut ui_surface, &viewport_values, full_node_query);
|
// update all nodes
|
||||||
|
for (entity, style, calculated_size) in &full_node_query {
|
||||||
|
if let Some(calculated_size) = calculated_size {
|
||||||
|
ui_surface.upsert_leaf(entity, style, calculated_size, &layout_context);
|
||||||
|
} else {
|
||||||
|
ui_surface.upsert_node(entity, style, &layout_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
update_changed(&mut ui_surface, &viewport_values, node_query);
|
// update changed nodes without a calculated size
|
||||||
}
|
for (entity, style) in changed_style_query.iter() {
|
||||||
|
ui_surface.upsert_node(entity, style, &layout_context);
|
||||||
|
}
|
||||||
|
|
||||||
for (entity, style, calculated_size) in &changed_size_query {
|
// update changed nodes with a calculated size
|
||||||
ui_surface.upsert_leaf(entity, style, calculated_size, &viewport_values);
|
for (entity, style, calculated_size) in changed_size_query.iter() {
|
||||||
|
ui_surface.upsert_leaf(entity, style, calculated_size, &layout_context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up removed nodes
|
// clean up removed nodes
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user