mirror of
https://github.com/bevyengine/bevy
synced 2025-01-08 19:29:04 +00:00
96b9d0a7e2
# Objective - Enables support for `Display::Block` - Enables support for `Overflow::Hidden` - Allows for cleaner integration with text, image and other content layout. - Unblocks https://github.com/bevyengine/bevy/pull/8104 - Unlocks the possibility of Bevy creating a custom layout tree over which Taffy operates. - Enables #8808 / #10193 to remove a Mutex around the font system. ## Todo - [x] ~Fix rendering of text/images to account for padding/border on nodes (should size/position to content box rather than border box)~ In order get this into a mergeable state this PR instead zeroes out padding/border when syncing leaf node styles into Taffy to preserve the existing behaviour. https://github.com/bevyengine/bevy/issues/6879 can be fixed in a followup PR. ## Solution - Update the version of Taffy - Update code to work with the new version Note: Taffy 0.4 has not yet been released. This PR is being created in advance of the release to ensure that there are no blockers to upgrading once the release occurs. --- ## Changelog - Bevy now supports the `Display::Block` and `Overflow::Hidden` styles.
111 lines
3.4 KiB
Rust
111 lines
3.4 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()
|
|
}
|
|
}
|
|
|
|
/// 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 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(
|
|
&self,
|
|
width: Option<f32>,
|
|
height: Option<f32>,
|
|
available_width: AvailableSpace,
|
|
available_height: AvailableSpace,
|
|
) -> Vec2 {
|
|
match self {
|
|
NodeMeasure::Fixed(fixed) => {
|
|
fixed.measure(width, height, available_width, available_height)
|
|
}
|
|
#[cfg(feature = "bevy_text")]
|
|
NodeMeasure::Text(text) => {
|
|
text.measure(width, height, available_width, available_height)
|
|
}
|
|
NodeMeasure::Image(image) => {
|
|
image.measure(width, height, available_width, available_height)
|
|
}
|
|
NodeMeasure::Custom(custom) => {
|
|
custom.measure(width, height, available_width, available_height)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 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(
|
|
&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, 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
|
|
}
|
|
}
|