Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ui/src/measurement.rs
6598 views
1
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
2
use bevy_math::Vec2;
3
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
4
use bevy_text::CosmicFontSystem;
5
use core::fmt::Formatter;
6
pub use taffy::style::AvailableSpace;
7
8
use crate::widget::ImageMeasure;
9
10
use crate::widget::TextMeasure;
11
12
impl core::fmt::Debug for ContentSize {
13
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
14
f.debug_struct("ContentSize").finish()
15
}
16
}
17
18
pub struct MeasureArgs<'a> {
19
pub width: Option<f32>,
20
pub height: Option<f32>,
21
pub available_width: AvailableSpace,
22
pub available_height: AvailableSpace,
23
pub font_system: &'a mut CosmicFontSystem,
24
pub buffer: Option<&'a mut bevy_text::ComputedTextBlock>,
25
}
26
27
/// A `Measure` is used to compute the size of a ui node
28
/// when the size of that node is based on its content.
29
pub trait Measure: Send + Sync + 'static {
30
/// Calculate the size of the node given the constraints.
31
fn measure(&mut self, measure_args: MeasureArgs<'_>, style: &taffy::Style) -> Vec2;
32
}
33
34
/// A type to serve as Taffy's node context (which allows the content size of leaf nodes to be computed)
35
///
36
/// It has specific variants for common built-in types to avoid making them opaque and needing to box them
37
/// by wrapping them in a closure and a Custom variant that allows arbitrary measurement closures if required.
38
pub enum NodeMeasure {
39
Fixed(FixedMeasure),
40
41
Text(TextMeasure),
42
Image(ImageMeasure),
43
Custom(Box<dyn Measure>),
44
}
45
46
impl Measure for NodeMeasure {
47
fn measure(&mut self, measure_args: MeasureArgs, style: &taffy::Style) -> Vec2 {
48
match self {
49
NodeMeasure::Fixed(fixed) => fixed.measure(measure_args, style),
50
51
NodeMeasure::Text(text) => text.measure(measure_args, style),
52
NodeMeasure::Image(image) => image.measure(measure_args, style),
53
NodeMeasure::Custom(custom) => custom.measure(measure_args, style),
54
}
55
}
56
}
57
58
/// A `FixedMeasure` is a `Measure` that ignores all constraints and
59
/// always returns the same size.
60
#[derive(Default, Clone)]
61
pub struct FixedMeasure {
62
pub size: Vec2,
63
}
64
65
impl Measure for FixedMeasure {
66
fn measure(&mut self, _: MeasureArgs, _: &taffy::Style) -> Vec2 {
67
self.size
68
}
69
}
70
71
/// A node with a `ContentSize` component is a node where its size
72
/// is based on its content.
73
#[derive(Component, Reflect, Default)]
74
#[reflect(Component, Default)]
75
pub struct ContentSize {
76
/// The `Measure` used to compute the intrinsic size
77
#[reflect(ignore)]
78
pub(crate) measure: Option<NodeMeasure>,
79
}
80
81
impl ContentSize {
82
/// Set a `Measure` for the UI node entity with this component
83
pub fn set(&mut self, measure: NodeMeasure) {
84
self.measure = Some(measure);
85
}
86
87
/// Creates a `ContentSize` with a `Measure` that always returns given `size` argument, regardless of the UI layout's constraints.
88
pub fn fixed_size(size: Vec2) -> ContentSize {
89
let mut content_size = Self::default();
90
content_size.set(NodeMeasure::Fixed(FixedMeasure { size }));
91
content_size
92
}
93
}
94
95