1use bevy::{prelude::{Vec2, Resource}, reflect::Reflect};
2
3#[derive(Debug, Resource)]
7pub struct AoUIREM(pub f32);
8impl Default for AoUIREM {
9    fn default() -> Self {
10        Self(16.0)
11    }
12}
13
14#[derive(Debug, Clone, Copy, Default, Reflect)]
16#[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
17pub enum SetEM {
18    #[default]
19    None,
20    Pixels(f32),
21    Ems(f32),
22    Rems(f32),
23}
24
25#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
27#[cfg_attr(feature="serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum SizeUnit{
29    #[default]
30    Pixels,
32    Em,
34    Rem,
36    Percent,
38    MarginPx,
40    MarginEm,
42    MarginRem,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Default, Reflect)]
48pub struct Size2 {
49    x: SizeUnit,
50    y: SizeUnit,
51    raw: Vec2,
52}
53
54
55impl SizeUnit {
56
57    #[inline]
59    pub fn as_pixels(self, value: f32, parent: f32, em: f32, rem: f32) -> f32 {
60        match self {
61            SizeUnit::Pixels => value,
62            SizeUnit::Em => value * em,
63            SizeUnit::Rem => value * rem,
64            SizeUnit::Percent => value * parent,
65            SizeUnit::MarginPx => parent - value,
66            SizeUnit::MarginEm => parent - value * em,
67            SizeUnit::MarginRem => parent - value * rem,
68        }
69    }
70}
71
72impl Size2 {
73    pub const ZERO: Self = Self {
74        x: SizeUnit::Pixels,
75        y: SizeUnit::Pixels,
76        raw: Vec2::ZERO,
77    };
78
79
80    pub const INHERIT: Self = Self {
81        x: SizeUnit::Percent,
82        y: SizeUnit::Percent,
83        raw: Vec2::ONE,
84    };
85
86    pub const fn new(x: (SizeUnit, f32), y: (SizeUnit, f32)) -> Self{
88        Self {
89            x: x.0,
90            y: y.0,
91            raw: Vec2::new(x.1, y.1)
92        }
93    }
94
95    pub const fn pixels(x: f32, y: f32) -> Self{
97        Self {
98            x: SizeUnit::Pixels,
99            y: SizeUnit::Pixels,
100            raw: Vec2::new(x, y),
101        }
102    }
103
104    pub const fn em(x: f32, y: f32) -> Self{
106        Self {
107            x: SizeUnit::Em,
108            y: SizeUnit::Em,
109            raw: Vec2::new(x, y),
110        }
111    }
112
113    pub const fn rem(x: f32, y: f32) -> Self{
115        Self {
116            x: SizeUnit::Rem,
117            y: SizeUnit::Rem,
118            raw: Vec2::new(x, y),
119        }
120    }
121
122    pub const fn percent(x: f32, y: f32) -> Self{
124        Self {
125            x: SizeUnit::Percent,
126            y: SizeUnit::Percent,
127            raw: Vec2::new(x, y),
128        }
129    }
130
131    #[inline]
133    pub fn as_pixels(&self, parent: Vec2, em: f32, rem: f32) -> Vec2 {
134        Vec2::new(
135            self.x.as_pixels(self.raw.x, parent.x, em, rem),
136            self.y.as_pixels(self.raw.y, parent.y, em, rem),
137        )
138    }
139
140    pub fn units(&self) -> (SizeUnit, SizeUnit) {
142        (self.x, self.y)
143    }
144
145    pub fn get_pixels(&self) -> Option<Vec2> {
147        match (self.x, self.y) {
148            (SizeUnit::Pixels, SizeUnit::Pixels) => Some(self.raw),
149            _ => None,
150        }
151    }
152
153    pub fn raw(&self) -> Vec2 {
157        self.raw
158    }
159
160    #[doc(hidden)]
164    pub fn raw_mut(&mut self) -> &mut Vec2 {
165        &mut self.raw
166    }
167
168    pub fn edit_raw(&mut self, f: impl FnOnce(&mut Vec2)) {
172        f(&mut self.raw)
173    }
174}
175
176impl From<Vec2> for Size2 {
177    fn from(value: Vec2) -> Self {
178        Self { 
179            x: SizeUnit::Pixels, 
180            y: SizeUnit::Pixels,
181            raw: value
182        }
183    }
184}
185
186impl SetEM {
187    #[doc(hidden)]
188    pub fn raw_mut(&mut self) -> &mut f32 {
190        match self {
191            SetEM::None => panic!("Does not own a raw value."),
192            SetEM::Pixels(f) => f,
193            SetEM::Ems(f) => f,
194            SetEM::Rems(f) => f,
195        }
196    }
197}
198
199#[cfg(feature="serde")]
200const _:() = {
201    use serde::{Serialize, Deserialize};
202    impl Serialize for Size2 {
203        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
204            ((self.x, self.raw.x), (self.y, self.raw.y)).serialize(serializer)
205        }
206    }
207
208    impl<'de> Deserialize<'de> for Size2 {
209        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
210            let ((ux, x), (uy, y)) = <_>::deserialize(deserializer)?; 
211            Ok(Self { 
212                x: ux,
213                y: uy,
214                raw: Vec2::new(x, y)
215            })
216        }
217    }
218};