mirror of
https://github.com/bevyengine/bevy
synced 2025-01-08 19:29:04 +00:00
cd497152bb
# Objective - `bevy_ui` does not build without the `bevy_text` feature due to improper feature gating. - Specifically, `MeasureArgs<'a>` had an unused lifetime `'a` without `bevy_text` enabled. This is because it stores a reference to a `cosmic_text::FontSystem`. - This was caught by `flag-frenzy` in [this run](https://github.com/TheBevyFlock/flag-frenzy/actions/runs/10024258523/job/27706132250). ## Solution - Add a `PhantomData` to `MeasureArgs<'a>` in order to maintain its lifetime argument. - I also named it `font_system`, after the feature-gated argument that actually needs a lifetime, for usability. Please comment if you have a better solution! - Move some unused imports to be behind the `bevy_text` feature gate. ## Testing ```bash # Fails on main. cargo check -p bevy_ui --no-default-features # Succeeds on main. cargo check -p bevy_ui --no-default-features -F bevy_text ``` --- ## Migration Guide **This is not a breaking change for users migrating from 0.14, since `MeasureArgs` did not exist then.** When the `bevy_text` feature is disabled for `bevy_ui`, the type of the `MeasureArgs::font_system` field is now a `PhantomData` instead of being removed entirely. This is in order to keep the lifetime parameter, even though it is unused without text being enabled.
97 lines
3.3 KiB
Rust
97 lines
3.3 KiB
Rust
use bevy_ecs::prelude::Component;
|
|
use bevy_ecs::reflect::ReflectComponent;
|
|
use bevy_math::Vec2;
|
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
|
use std::fmt::Formatter;
|
|
pub use taffy::style::AvailableSpace;
|
|
|
|
use crate::widget::ImageMeasure;
|
|
|
|
#[cfg(feature = "bevy_text")]
|
|
use crate::widget::TextMeasure;
|
|
|
|
impl std::fmt::Debug for ContentSize {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("ContentSize").finish()
|
|
}
|
|
}
|
|
|
|
pub struct MeasureArgs<'a> {
|
|
pub width: Option<f32>,
|
|
pub height: Option<f32>,
|
|
pub available_width: AvailableSpace,
|
|
pub available_height: AvailableSpace,
|
|
#[cfg(feature = "bevy_text")]
|
|
pub font_system: &'a mut bevy_text::cosmic_text::FontSystem,
|
|
// When `bevy_text` is disabled, use `PhantomData` in order to keep lifetime in type signature.
|
|
#[cfg(not(feature = "bevy_text"))]
|
|
pub font_system: std::marker::PhantomData<&'a mut ()>,
|
|
}
|
|
|
|
/// 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(&mut self, measure_args: MeasureArgs<'_>, style: &taffy::Style) -> Vec2;
|
|
}
|
|
|
|
/// A type to serve as Taffy's node context (which allows the content size of leaf nodes to be computed)
|
|
///
|
|
/// It has specific variants for common built-in types to avoid making them opaque and needing to box them
|
|
/// by wrapping them in a closure and a Custom variant that allows arbitrary measurement closures if required.
|
|
pub enum NodeMeasure {
|
|
Fixed(FixedMeasure),
|
|
#[cfg(feature = "bevy_text")]
|
|
Text(TextMeasure),
|
|
Image(ImageMeasure),
|
|
Custom(Box<dyn Measure>),
|
|
}
|
|
|
|
impl Measure for NodeMeasure {
|
|
fn measure(&mut self, measure_args: MeasureArgs, style: &taffy::Style) -> Vec2 {
|
|
match self {
|
|
NodeMeasure::Fixed(fixed) => fixed.measure(measure_args, style),
|
|
#[cfg(feature = "bevy_text")]
|
|
NodeMeasure::Text(text) => text.measure(measure_args, style),
|
|
NodeMeasure::Image(image) => image.measure(measure_args, style),
|
|
NodeMeasure::Custom(custom) => custom.measure(measure_args, style),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A `FixedMeasure` is a `Measure` that ignores all constraints and
|
|
/// always returns the same size.
|
|
#[derive(Default, Clone)]
|
|
pub struct FixedMeasure {
|
|
pub size: Vec2,
|
|
}
|
|
|
|
impl Measure for FixedMeasure {
|
|
fn measure(&mut self, _: MeasureArgs, _: &taffy::Style) -> Vec2 {
|
|
self.size
|
|
}
|
|
}
|
|
|
|
/// A node with a `ContentSize` component is a node where its size
|
|
/// is based on its content.
|
|
#[derive(Component, Reflect, Default)]
|
|
#[reflect(Component, Default)]
|
|
pub struct ContentSize {
|
|
/// The `Measure` used to compute the intrinsic size
|
|
#[reflect(ignore)]
|
|
pub(crate) measure: Option<NodeMeasure>,
|
|
}
|
|
|
|
impl ContentSize {
|
|
/// Set a `Measure` for the UI node entity with this component
|
|
pub fn set(&mut self, measure: NodeMeasure) {
|
|
self.measure = Some(measure);
|
|
}
|
|
|
|
/// Creates a `ContentSize` with a `Measure` that always returns given `size` argument, regardless of the UI layout's constraints.
|
|
pub fn fixed_size(size: Vec2) -> ContentSize {
|
|
let mut content_size = Self::default();
|
|
content_size.set(NodeMeasure::Fixed(FixedMeasure { size }));
|
|
content_size
|
|
}
|
|
}
|