
# Objective fixes #8516 * Give `CalculatedSize` a more specific and intuitive name. * `MeasureFunc`s should only be updated when their `CalculatedSize` is modified by the systems managing their content. For example, suppose that you have a UI displaying an image using an `ImageNode`. When the window is resized, the node's `MeasureFunc` will be updated even though the dimensions of the texture contained by the node are unchanged. * Fix the `CalculatedSize` API so that it no longer requires the extra boxing and the `dyn_clone` method. ## Solution * Rename `CalculatedSize` to `ContentSize` * Only update `MeasureFunc`s on `CalculatedSize` changes. * Remove the `dyn_clone` method from `Measure` and move the `Measure` from the `ContentSize` component rather than cloning it. * Change the measure_func field of `ContentSize` to type `Option<taffy::node::MeasureFunc>`. Add a `set` method that wraps the given measure appropriately. --- ## Changelog * Renamed `CalculatedSize` to `ContentSize`. * Replaced `upsert_leaf` with a function `update_measure` that only updates the node's `MeasureFunc`. * `MeasureFunc`s are only updated when the `ContentSize` changes and not when the layout changes. * Scale factor is no longer applied to the size values passed to the `MeasureFunc`. * Remove the `ContentSize` scaling in `text_system`. * The `dyn_clone` method has been removed from the `Measure` trait. * `Measure`s are moved from the `ContentSize` component instead of cloning them. * Added `set` method to `ContentSize` that replaces the `new` function. ## Migration Guide * `CalculatedSize` has been renamed to `ContentSize`. * The `upsert_leaf` function has been removed from `UiSurface` and replaced with `update_measure` which updates the `MeasureFunc` without node insertion. * The `dyn_clone` method has been removed from the `Measure` trait. * The new function of `CalculatedSize` has been replaced with the method `set`.
83 lines
2.3 KiB
Rust
83 lines
2.3 KiB
Rust
use bevy_ecs::prelude::Component;
|
|
use bevy_ecs::reflect::ReflectComponent;
|
|
use bevy_math::Vec2;
|
|
use bevy_reflect::Reflect;
|
|
use std::fmt::Formatter;
|
|
pub use taffy::style::AvailableSpace;
|
|
|
|
impl std::fmt::Debug for ContentSize {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("ContentSize").finish()
|
|
}
|
|
}
|
|
|
|
/// A `Measure` is used to compute the size of a ui node
|
|
/// when the size of that node is based on its content.
|
|
pub trait Measure: Send + Sync + 'static {
|
|
/// Calculate the size of the node given the constraints.
|
|
fn measure(
|
|
&self,
|
|
width: Option<f32>,
|
|
height: Option<f32>,
|
|
available_width: AvailableSpace,
|
|
available_height: AvailableSpace,
|
|
) -> Vec2;
|
|
}
|
|
|
|
/// A `FixedMeasure` is a `Measure` that ignores all constraints and
|
|
/// always returns the same size.
|
|
#[derive(Default, Clone)]
|
|
pub struct FixedMeasure {
|
|
size: Vec2,
|
|
}
|
|
|
|
impl Measure for FixedMeasure {
|
|
fn measure(
|
|
&self,
|
|
_: Option<f32>,
|
|
_: Option<f32>,
|
|
_: AvailableSpace,
|
|
_: AvailableSpace,
|
|
) -> Vec2 {
|
|
self.size
|
|
}
|
|
}
|
|
|
|
/// A node with a `ContentSize` component is a node where its size
|
|
/// is based on its content.
|
|
#[derive(Component, Reflect)]
|
|
#[reflect(Component)]
|
|
pub struct ContentSize {
|
|
/// The `Measure` used to compute the intrinsic size
|
|
#[reflect(ignore)]
|
|
pub(crate) measure_func: Option<taffy::node::MeasureFunc>,
|
|
}
|
|
|
|
impl ContentSize {
|
|
/// Set a `Measure` for this function
|
|
pub fn set(&mut self, measure: impl Measure) {
|
|
let measure_func =
|
|
move |size: taffy::prelude::Size<Option<f32>>,
|
|
available: taffy::prelude::Size<AvailableSpace>| {
|
|
let size =
|
|
measure.measure(size.width, size.height, available.width, available.height);
|
|
taffy::prelude::Size {
|
|
width: size.x,
|
|
height: size.y,
|
|
}
|
|
};
|
|
self.measure_func = Some(taffy::node::MeasureFunc::Boxed(Box::new(measure_func)));
|
|
}
|
|
}
|
|
|
|
#[allow(clippy::derivable_impls)]
|
|
impl Default for ContentSize {
|
|
fn default() -> Self {
|
|
Self {
|
|
measure_func: Some(taffy::node::MeasureFunc::Raw(|_, _| {
|
|
taffy::prelude::Size::ZERO
|
|
})),
|
|
}
|
|
}
|
|
}
|