1use crate::Val;
2use bevy_derive::Deref;
3use bevy_ecs::component::Component;
4use bevy_ecs::prelude::ReflectComponent;
5use bevy_math::Affine2;
6use bevy_math::Mat2;
7use bevy_math::Rot2;
8use bevy_math::Vec2;
9use bevy_reflect::prelude::*;
10use core::ops::Mul;
11
12#[derive(Debug, PartialEq, Clone, Copy, Reflect)]
14#[reflect(Default, PartialEq, Debug, Clone)]
15#[cfg_attr(
16 feature = "serialize",
17 derive(serde::Serialize, serde::Deserialize),
18 reflect(Serialize, Deserialize)
19)]
20pub struct Val2 {
21 pub x: Val,
25 pub y: Val,
29}
30
31impl Val2 {
32 pub const ZERO: Self = Self {
33 x: Val::ZERO,
34 y: Val::ZERO,
35 };
36
37 pub const fn px(x: f32, y: f32) -> Self {
39 Self {
40 x: Val::Px(x),
41 y: Val::Px(y),
42 }
43 }
44
45 pub const fn percent(x: f32, y: f32) -> Self {
47 Self {
48 x: Val::Percent(x),
49 y: Val::Percent(y),
50 }
51 }
52
53 pub const fn new(x: Val, y: Val) -> Self {
55 Self { x, y }
56 }
57
58 pub fn resolve(&self, scale_factor: f32, base_size: Vec2, viewport_size: Vec2) -> Vec2 {
63 Vec2::new(
64 self.x
65 .resolve(scale_factor, base_size.x, viewport_size)
66 .unwrap_or(0.),
67 self.y
68 .resolve(scale_factor, base_size.y, viewport_size)
69 .unwrap_or(0.),
70 )
71 }
72}
73
74impl Default for Val2 {
75 fn default() -> Self {
76 Self::ZERO
77 }
78}
79
80#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect)]
84#[reflect(Component, Default, PartialEq, Debug, Clone)]
85#[cfg_attr(
86 feature = "serialize",
87 derive(serde::Serialize, serde::Deserialize),
88 reflect(Serialize, Deserialize)
89)]
90#[require(UiGlobalTransform)]
91pub struct UiTransform {
92 pub translation: Val2,
94 pub scale: Vec2,
96 pub rotation: Rot2,
98}
99
100impl UiTransform {
101 pub const IDENTITY: Self = Self {
102 translation: Val2::ZERO,
103 scale: Vec2::ONE,
104 rotation: Rot2::IDENTITY,
105 };
106
107 pub const fn from_rotation(rotation: Rot2) -> Self {
109 Self {
110 rotation,
111 ..Self::IDENTITY
112 }
113 }
114
115 pub const fn from_translation(translation: Val2) -> Self {
117 Self {
118 translation,
119 ..Self::IDENTITY
120 }
121 }
122
123 pub const fn from_scale(scale: Vec2) -> Self {
125 Self {
126 scale,
127 ..Self::IDENTITY
128 }
129 }
130
131 pub fn compute_affine(&self, scale_factor: f32, base_size: Vec2, target_size: Vec2) -> Affine2 {
134 Affine2::from_mat2_translation(
135 Mat2::from(self.rotation) * Mat2::from_diagonal(self.scale),
136 self.translation
137 .resolve(scale_factor, base_size, target_size),
138 )
139 }
140}
141
142impl Default for UiTransform {
143 fn default() -> Self {
144 Self::IDENTITY
145 }
146}
147
148#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect, Deref)]
153#[reflect(Component, Default, PartialEq, Debug, Clone)]
154#[cfg_attr(
155 feature = "serialize",
156 derive(serde::Serialize, serde::Deserialize),
157 reflect(Serialize, Deserialize)
158)]
159pub struct UiGlobalTransform(Affine2);
160
161impl Default for UiGlobalTransform {
162 fn default() -> Self {
163 Self(Affine2::IDENTITY)
164 }
165}
166
167impl UiGlobalTransform {
168 #[inline]
171 pub fn try_inverse(&self) -> Option<Affine2> {
172 (self.matrix2.determinant() != 0.).then_some(self.inverse())
173 }
174
175 #[inline]
177 pub fn from_translation(translation: Vec2) -> Self {
178 Self(Affine2::from_translation(translation))
179 }
180
181 #[inline]
183 pub fn from_xy(x: f32, y: f32) -> Self {
184 Self::from_translation(Vec2::new(x, y))
185 }
186
187 #[inline]
189 pub fn from_rotation(rotation: Rot2) -> Self {
190 Self(Affine2::from_mat2(rotation.into()))
191 }
192
193 #[inline]
195 pub fn from_scale(scale: Vec2) -> Self {
196 Self(Affine2::from_scale(scale))
197 }
198
199 #[inline]
202 pub fn to_scale_angle_translation(&self) -> (Vec2, f32, Vec2) {
203 self.0.to_scale_angle_translation()
204 }
205
206 #[inline]
208 pub fn affine(&self) -> Affine2 {
209 self.0
210 }
211}
212
213impl From<Affine2> for UiGlobalTransform {
214 fn from(value: Affine2) -> Self {
215 Self(value)
216 }
217}
218
219impl From<UiGlobalTransform> for Affine2 {
220 fn from(value: UiGlobalTransform) -> Self {
221 value.0
222 }
223}
224
225impl From<&UiGlobalTransform> for Affine2 {
226 fn from(value: &UiGlobalTransform) -> Self {
227 value.0
228 }
229}
230
231impl Mul for UiGlobalTransform {
232 type Output = Self;
233
234 #[inline]
235 fn mul(self, value: Self) -> Self::Output {
236 Self(self.0 * value.0)
237 }
238}
239
240impl Mul<Affine2> for UiGlobalTransform {
241 type Output = Affine2;
242
243 #[inline]
244 fn mul(self, affine2: Affine2) -> Self::Output {
245 self.0 * affine2
246 }
247}
248
249impl Mul<UiGlobalTransform> for Affine2 {
250 type Output = Affine2;
251
252 #[inline]
253 fn mul(self, transform: UiGlobalTransform) -> Self::Output {
254 self * transform.0
255 }
256}
257
258impl Mul<Vec2> for UiGlobalTransform {
259 type Output = Vec2;
260
261 #[inline]
262 fn mul(self, value: Vec2) -> Vec2 {
263 self.transform_point2(value)
264 }
265}