From e99c2b1b7c8e4492700f1e6169a716557387fccc Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Sun, 10 Sep 2023 22:48:23 +0100 Subject: [PATCH 1/3] `ContentSize` If you remove a `ContentSize` component from a Bevy UI entity and then immediately replace it `ui_layout_system` will remove the measure func from the internal Taffy layout tree but no new measure func will be generated to replace it since it's the widget systems that are responsible for creating their respective measure funcs not `ui_layout_system`. The widget systems only perform updates on changes to their content, and don't check `ContentSize` for changes. This means that until the content is changed in some way, no content will be displayed by the node. This commit fixes this by performing `ui_layout_system`'s `ContentSize` removal detection and resolution first, before measure func updates and in the widget systems generating a new `Measure` when a `ContentSize` component is added to a widget entity. --- crates/bevy_ui/src/layout/mod.rs | 10 +++++----- crates/bevy_ui/src/widget/image.rs | 5 +++-- crates/bevy_ui/src/widget/text.rs | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 4ed138c1f3681..9efb245bc0696 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -274,6 +274,11 @@ pub fn ui_layout_system( } } + // When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node. + for entity in removed_content_sizes.iter() { + ui_surface.try_remove_measure(entity); + } + for (entity, mut content_size) in measure_query.iter_mut() { if let Some(measure_func) = content_size.measure_func.take() { ui_surface.update_measure(entity, measure_func); @@ -283,11 +288,6 @@ pub fn ui_layout_system( // clean up removed nodes ui_surface.remove_entities(removed_nodes.iter()); - // When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node. - for entity in removed_content_sizes.iter() { - ui_surface.try_remove_measure(entity); - } - // update window children (for now assuming all Nodes live in the primary window) ui_surface.set_window_children(primary_window_entity, root_node_query.iter()); diff --git a/crates/bevy_ui/src/widget/image.rs b/crates/bevy_ui/src/widget/image.rs index 022c174adf462..adeded8d36246 100644 --- a/crates/bevy_ui/src/widget/image.rs +++ b/crates/bevy_ui/src/widget/image.rs @@ -3,6 +3,7 @@ use crate::{ }; use bevy_asset::{Assets, Handle}; +use bevy_ecs::change_detection::DetectChanges; use bevy_ecs::query::Without; use bevy_ecs::{ prelude::Component, @@ -96,7 +97,7 @@ pub fn update_image_content_size_system( texture.texture_descriptor.size.height as f32, ); // Update only if size or scale factor has changed to avoid needless layout calculations - if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor { + if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor || content_size.is_added() { image_size.size = size; content_size.set(ImageMeasure { // multiply the image size by the scale factor to get the physical size @@ -135,7 +136,7 @@ pub fn update_atlas_content_size_system( if let Some(atlas) = atlases.get(atlas) { let size = atlas.textures[atlas_image.index].size(); // Update only if size or scale factor has changed to avoid needless layout calculations - if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor { + if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor || content_size.is_added() { image_size.size = size; content_size.set(ImageMeasure { // multiply the image size by the scale factor to get the physical size diff --git a/crates/bevy_ui/src/widget/text.rs b/crates/bevy_ui/src/widget/text.rs index ff042093c5dfa..fa3f272d4559b 100644 --- a/crates/bevy_ui/src/widget/text.rs +++ b/crates/bevy_ui/src/widget/text.rs @@ -128,7 +128,7 @@ pub fn measure_text_system( if *last_scale_factor == scale_factor { // scale factor unchanged, only create new measure funcs for modified text for (text, content_size, text_flags) in text_query.iter_mut() { - if text.is_changed() || text_flags.needs_new_measure_func { + if text.is_changed() || text_flags.needs_new_measure_func || content_size.is_added() { create_text_measure(&fonts, scale_factor, text, content_size, text_flags); } } From be79532421369e1bea6d49b33228cc8a7fef55b6 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Sun, 10 Sep 2023 23:16:41 +0100 Subject: [PATCH 2/3] cargo fmt --all --- crates/bevy_ui/src/widget/image.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/bevy_ui/src/widget/image.rs b/crates/bevy_ui/src/widget/image.rs index adeded8d36246..f7a54c0da6f42 100644 --- a/crates/bevy_ui/src/widget/image.rs +++ b/crates/bevy_ui/src/widget/image.rs @@ -97,7 +97,10 @@ pub fn update_image_content_size_system( texture.texture_descriptor.size.height as f32, ); // Update only if size or scale factor has changed to avoid needless layout calculations - if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor || content_size.is_added() { + if size != image_size.size + || combined_scale_factor != *previous_combined_scale_factor + || content_size.is_added() + { image_size.size = size; content_size.set(ImageMeasure { // multiply the image size by the scale factor to get the physical size @@ -136,7 +139,10 @@ pub fn update_atlas_content_size_system( if let Some(atlas) = atlases.get(atlas) { let size = atlas.textures[atlas_image.index].size(); // Update only if size or scale factor has changed to avoid needless layout calculations - if size != image_size.size || combined_scale_factor != *previous_combined_scale_factor || content_size.is_added() { + if size != image_size.size + || combined_scale_factor != *previous_combined_scale_factor + || content_size.is_added() + { image_size.size = size; content_size.set(ImageMeasure { // multiply the image size by the scale factor to get the physical size From 2a52bb6ac2c6c08b8c82769c5ff5d856d38e58d8 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Mon, 18 Sep 2023 08:57:34 +0100 Subject: [PATCH 3/3] Replaced use of deprecated method --- crates/bevy_ui/src/layout/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ui/src/layout/mod.rs b/crates/bevy_ui/src/layout/mod.rs index 40cdc0ccaa64b..80cd0c9f86092 100644 --- a/crates/bevy_ui/src/layout/mod.rs +++ b/crates/bevy_ui/src/layout/mod.rs @@ -275,7 +275,7 @@ pub fn ui_layout_system( } // When a `ContentSize` component is removed from an entity, we need to remove the measure from the corresponding taffy node. - for entity in removed_content_sizes.iter() { + for entity in removed_content_sizes.read() { ui_surface.try_remove_measure(entity); }