Optimize ui_layout_system (#14064)
# Objective - Currently bevy's ui layout system could takes a long time. ## Solution - cache `default_ui_camera `entity to avoid repetitive lookup ## Performance cargo run --release --example many_buttons --features bevy/trace_tracy 
This commit is contained in:
parent
330911f1bf
commit
db19d2ee47
@ -104,10 +104,9 @@ pub fn ui_layout_system(
|
|||||||
root_nodes: Vec<Entity>,
|
root_nodes: Vec<Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let default_camera = default_ui_camera.get();
|
||||||
let camera_with_default = |target_camera: Option<&TargetCamera>| {
|
let camera_with_default = |target_camera: Option<&TargetCamera>| {
|
||||||
target_camera
|
target_camera.map(TargetCamera::entity).or(default_camera)
|
||||||
.map(TargetCamera::entity)
|
|
||||||
.or(default_ui_camera.get())
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let resized_windows: HashSet<Entity> = resize_events.read().map(|event| event.window).collect();
|
let resized_windows: HashSet<Entity> = resize_events.read().map(|event| event.window).collect();
|
||||||
@ -130,7 +129,7 @@ pub fn ui_layout_system(
|
|||||||
|
|
||||||
// Precalculate the layout info for each camera, so we have fast access to it for each node
|
// Precalculate the layout info for each camera, so we have fast access to it for each node
|
||||||
let mut camera_layout_info: HashMap<Entity, CameraLayoutInfo> = HashMap::new();
|
let mut camera_layout_info: HashMap<Entity, CameraLayoutInfo> = HashMap::new();
|
||||||
for (entity, target_camera) in &root_node_query {
|
root_node_query.iter().for_each(|(entity,target_camera)|{
|
||||||
match camera_with_default(target_camera) {
|
match camera_with_default(target_camera) {
|
||||||
Some(camera_entity) => {
|
Some(camera_entity) => {
|
||||||
let Ok((_, camera)) = cameras.get(camera_entity) else {
|
let Ok((_, camera)) = cameras.get(camera_entity) else {
|
||||||
@ -138,7 +137,7 @@ pub fn ui_layout_system(
|
|||||||
"TargetCamera (of root UI node {entity:?}) is pointing to a camera {:?} which doesn't exist",
|
"TargetCamera (of root UI node {entity:?}) is pointing to a camera {:?} which doesn't exist",
|
||||||
camera_entity
|
camera_entity
|
||||||
);
|
);
|
||||||
continue;
|
return;
|
||||||
};
|
};
|
||||||
let layout_info = camera_layout_info
|
let layout_info = camera_layout_info
|
||||||
.entry(camera_entity)
|
.entry(camera_entity)
|
||||||
@ -155,10 +154,10 @@ pub fn ui_layout_system(
|
|||||||
entity
|
entity
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
});
|
||||||
|
|
||||||
// When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node.
|
// When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node.
|
||||||
for entity in removed_components.removed_content_sizes.read() {
|
for entity in removed_components.removed_content_sizes.read() {
|
||||||
@ -166,30 +165,32 @@ pub fn ui_layout_system(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sync Style and ContentSize to Taffy for all nodes
|
// Sync Style and ContentSize to Taffy for all nodes
|
||||||
for (entity, style, content_size, target_camera) in style_query.iter_mut() {
|
style_query
|
||||||
if let Some(camera) =
|
.iter_mut()
|
||||||
camera_with_default(target_camera).and_then(|c| camera_layout_info.get(&c))
|
.for_each(|(entity, style, content_size, target_camera)| {
|
||||||
{
|
if let Some(camera) =
|
||||||
if camera.resized
|
camera_with_default(target_camera).and_then(|c| camera_layout_info.get(&c))
|
||||||
|| !scale_factor_events.is_empty()
|
|
||||||
|| ui_scale.is_changed()
|
|
||||||
|| style.is_changed()
|
|
||||||
|| content_size
|
|
||||||
.as_ref()
|
|
||||||
.map(|c| c.measure.is_some())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
{
|
||||||
let layout_context = LayoutContext::new(
|
if camera.resized
|
||||||
camera.scale_factor,
|
|| !scale_factor_events.is_empty()
|
||||||
[camera.size.x as f32, camera.size.y as f32].into(),
|
|| ui_scale.is_changed()
|
||||||
);
|
|| style.is_changed()
|
||||||
let measure = content_size.and_then(|mut c| c.measure.take());
|
|| content_size
|
||||||
ui_surface.upsert_node(&layout_context, entity, &style, measure);
|
.as_ref()
|
||||||
|
.map(|c| c.measure.is_some())
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
let layout_context = LayoutContext::new(
|
||||||
|
camera.scale_factor,
|
||||||
|
[camera.size.x as f32, camera.size.y as f32].into(),
|
||||||
|
);
|
||||||
|
let measure = content_size.and_then(|mut c| c.measure.take());
|
||||||
|
ui_surface.upsert_node(&layout_context, entity, &style, measure);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ui_surface.upsert_node(&LayoutContext::DEFAULT, entity, &Style::default(), None);
|
||||||
}
|
}
|
||||||
} else {
|
});
|
||||||
ui_surface.upsert_node(&LayoutContext::DEFAULT, entity, &Style::default(), None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scale_factor_events.clear();
|
scale_factor_events.clear();
|
||||||
|
|
||||||
// clean up removed cameras
|
// clean up removed cameras
|
||||||
@ -210,11 +211,11 @@ pub fn ui_layout_system(
|
|||||||
for entity in removed_components.removed_children.read() {
|
for entity in removed_components.removed_children.read() {
|
||||||
ui_surface.try_remove_children(entity);
|
ui_surface.try_remove_children(entity);
|
||||||
}
|
}
|
||||||
for (entity, children) in &children_query {
|
children_query.iter().for_each(|(entity, children)| {
|
||||||
if children.is_changed() {
|
if children.is_changed() {
|
||||||
ui_surface.update_children(entity, &children);
|
ui_surface.update_children(entity, &children);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
#[cfg(feature = "bevy_text")]
|
#[cfg(feature = "bevy_text")]
|
||||||
let font_system = text_pipeline.font_system_mut();
|
let font_system = text_pipeline.font_system_mut();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user