1use crate::*;
2
3pub mod prelude {
5 pub use super::{
7 Align,
8 Scaling,
9 };
10}
11
12#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
17pub struct Rectangle2D {
18 pub pos : Vec2,
19 pub size: Vec2,
20}
21impl Rectangle2D {
22 pub fn lerp(self, rhs: Self, lerp: f32) -> Self {
23 Rectangle2D {
24 pos: self.pos.lerp(rhs.pos, lerp),
25 size: self.size.lerp(rhs.size, lerp),
26 }
27 }
28}
29impl Rectangle2D {
30 pub const EMPTY: Rectangle2D = Rectangle2D { pos : Vec2::ZERO, size: Vec2::ZERO };
32 pub const fn new() -> Self {
34 Rectangle2D::EMPTY
35 }
36 pub fn with_pos(mut self, pos: impl Into<Vec2>) -> Self {
38 self.pos = pos.into();
39 self
40 }
41 pub fn with_x(mut self, width: f32) -> Self {
43 self.pos.x = width;
44 self
45 }
46 pub fn with_y(mut self, height: f32) -> Self {
48 self.pos.y = height;
49 self
50 }
51 pub fn with_size(mut self, size: impl Into<Vec2>) -> Self {
53 self.size = size.into();
54 self
55 }
56 pub fn with_width(mut self, width: f32) -> Self {
58 self.size.x = width;
59 self
60 }
61 pub fn with_height(mut self, height: f32) -> Self {
63 self.size.y = height;
64 self
65 }
66}
67
68#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
78pub struct Align (pub f32);
79impl Align {
80 pub const START: Align = Align(-1.0);
81 pub const LEFT: Align = Align(-1.0);
82 pub const CENTER: Align = Align(0.0);
83 pub const MIDDLE: Align = Align(0.0);
84 pub const END: Align = Align(1.0);
85 pub const RIGHT: Align = Align(1.0);
86}
87impl From<f32> for Align {
88 fn from(val: f32) -> Self {
89 Align(val)
90 }
91}
92
93
94#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
104pub enum Scaling {
105 HorFill,
107 VerFill,
109 #[default] Fit,
111 Fill,
113}
114
115
116#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
121pub enum UiLayoutType {
122 Boundary(UiLayoutTypeBoundary),
123 Window(UiLayoutTypeWindow),
124 Solid(UiLayoutTypeSolid),
125}
126impl UiLayoutType {
127 pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
129 match self {
130 UiLayoutType::Boundary(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
131 UiLayoutType::Window(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
132 UiLayoutType::Solid(layout) => layout.compute(parent, absolute_scale, viewport_size, font_size),
133 }
134 }
135}
136impl From<UiLayoutTypeBoundary> for UiLayoutType {
137 fn from(value: UiLayoutTypeBoundary) -> Self {
138 UiLayoutType::Boundary(value)
139 }
140}
141impl From<UiLayoutTypeWindow> for UiLayoutType {
142 fn from(value: UiLayoutTypeWindow) -> Self {
143 UiLayoutType::Window(value)
144 }
145}
146impl From<UiLayoutTypeSolid> for UiLayoutType {
147 fn from(value: UiLayoutTypeSolid) -> Self {
148 UiLayoutType::Solid(value)
149 }
150}
151
152
153#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
155pub struct UiLayoutTypeBoundary {
156 pub pos1: UiValue<Vec2>,
158 pub pos2: UiValue<Vec2>,
160}
161impl UiLayoutTypeBoundary {
162 pub const fn new() -> Self {
164 Self {
165 pos1: UiValue::new(),
166 pos2: UiValue::new(),
167 }
168 }
169 pub fn pos1(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
171 self.pos1 = pos.into();
172 self
173 }
174 pub fn pos2(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
176 self.pos2 = pos.into();
177 self
178 }
179 pub fn x1(mut self, x: impl Into<UiValue<f32>>) -> Self {
181 self.pos1.set_x(x);
182 self
183 }
184 pub fn y1(mut self, y: impl Into<UiValue<f32>>) -> Self {
186 self.pos1.set_y(y);
187 self
188 }
189 pub fn x2(mut self, x: impl Into<UiValue<f32>>) -> Self {
191 self.pos2.set_x(x);
192 self
193 }
194 pub fn y2(mut self, y: impl Into<UiValue<f32>>) -> Self {
196 self.pos2.set_y(y);
197 self
198 }
199 pub fn set_pos1(&mut self, pos: impl Into<UiValue<Vec2>>) {
201 self.pos1 = pos.into();
202 }
203 pub fn set_pos2(&mut self, pos: impl Into<UiValue<Vec2>>) {
205 self.pos2 = pos.into();
206 }
207 pub fn set_x1(&mut self, x: impl Into<UiValue<f32>>) {
209 self.pos1.set_x(x);
210 }
211 pub fn set_y1(&mut self, y: impl Into<UiValue<f32>>) {
213 self.pos1.set_y(y);
214 }
215 pub fn set_x2(&mut self, x: impl Into<UiValue<f32>>) {
217 self.pos2.set_x(x);
218 }
219 pub fn set_y2(&mut self, y: impl Into<UiValue<f32>>) {
221 self.pos2.set_y(y);
222 }
223 pub fn pack(self) -> UiLayout {
225 UiLayout::from(self)
226 }
227 pub fn wrap(self) -> UiLayoutType {
229 UiLayoutType::from(self)
230 }
231 pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
233 let pos1 = self.pos1.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
234 let pos2 = self.pos2.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
235 let size = pos2 - pos1;
236 Rectangle2D {
237 pos: -parent.size / 2.0 + pos1 + size/2.0,
238 size,
239 }
240 }
241}
242
243#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
245pub struct UiLayoutTypeWindow {
246 pub pos : UiValue<Vec2>,
248 pub anchor: Anchor,
250 pub size: UiValue<Vec2>,
252}
253impl UiLayoutTypeWindow {
254 pub const fn new() -> Self {
256 Self {
257 pos: UiValue::new(),
258 anchor: Anchor::TOP_LEFT,
259 size: UiValue::new(),
260 }
261 }
262 pub fn full(self) -> Self {
264 self.size(Rl(100.0))
265 }
266 pub fn pos(mut self, pos: impl Into<UiValue<Vec2>>) -> Self {
268 self.pos = pos.into();
269 self
270 }
271 pub fn x(mut self, x: impl Into<UiValue<f32>>) -> Self {
273 self.pos.set_x(x);
274 self
275 }
276 pub fn y(mut self, y: impl Into<UiValue<f32>>) -> Self {
278 self.pos.set_y(y);
279 self
280 }
281 pub fn size(mut self, size: impl Into<UiValue<Vec2>>) -> Self {
283 self.size = size.into();
284 self
285 }
286 pub fn width(mut self, width: impl Into<UiValue<f32>>) -> Self {
288 self.size.set_x(width);
289 self
290 }
291 pub fn height(mut self, height: impl Into<UiValue<f32>>) -> Self {
293 self.size.set_y(height);
294 self
295 }
296 pub fn anchor(mut self, anchor: impl Into<Anchor>) -> Self {
298 self.anchor = anchor.into();
299 self
300 }
301 pub fn set_pos(&mut self, pos: impl Into<UiValue<Vec2>>){
303 self.pos = pos.into();
304 }
305 pub fn set_x(&mut self, x: impl Into<UiValue<f32>>){
307 self.pos.set_x(x);
308 }
309 pub fn set_y(&mut self, y: impl Into<UiValue<f32>>){
311 self.pos.set_y(y);
312 }
313 pub fn set_size(&mut self, size: impl Into<UiValue<Vec2>>){
315 self.size = size.into();
316 }
317 pub fn set_width(&mut self, width: impl Into<UiValue<f32>>){
319 self.size.set_x(width);
320 }
321 pub fn set_height(&mut self, height: impl Into<UiValue<f32>>){
323 self.size.set_y(height);
324 }
325 pub fn set_anchor(&mut self, anchor: impl Into<Anchor>){
327 self.anchor = anchor.into();
328 }
329 pub fn pack(self) -> UiLayout {
331 UiLayout::from(self)
332 }
333 pub fn wrap(self) -> UiLayoutType {
335 UiLayoutType::from(self)
336 }
337 pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
339 let pos = self.pos.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
340 let size = self.size.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
341 let mut anchor = self.anchor.as_vec();
342 anchor.y *= -1.0;
343 Rectangle2D {
344 pos: -parent.size / 2.0 + pos - size * (anchor),
345 size,
346 }
347 }
348}
349
350#[derive(Debug, Default, Clone, Copy, PartialEq, Reflect)]
352pub struct UiLayoutTypeSolid {
353 pub size: UiValue<Vec2>,
355 pub align_x: Align,
357 pub align_y: Align,
359 pub scaling: Scaling,
361}
362impl UiLayoutTypeSolid {
363 pub fn new() -> Self {
365 Self {
366 size: Ab(Vec2::ONE).into(),
367 align_x: Align::CENTER,
368 align_y: Align::CENTER,
369 scaling: Scaling::Fit,
370 }
371 }
372 pub fn size(mut self, size: impl Into<UiValue<Vec2>>) -> Self {
374 self.size = size.into();
375 self
376 }
377 pub fn width(mut self, width: impl Into<UiValue<f32>>) -> Self {
379 self.size.set_x(width);
380 self
381 }
382 pub fn height(mut self, height: impl Into<UiValue<f32>>) -> Self {
384 self.size.set_y(height);
385 self
386 }
387 pub fn align_x(mut self, align: impl Into<Align>) -> Self {
389 self.align_x = align.into();
390 self
391 }
392 pub fn align_y(mut self, align: impl Into<Align>) -> Self {
394 self.align_y = align.into();
395 self
396 }
397 pub fn scaling(mut self, scaling: Scaling) -> Self {
399 self.scaling = scaling;
400 self
401 }
402 pub fn set_size(&mut self, size: impl Into<UiValue<Vec2>>) {
404 self.size = size.into();
405 }
406 pub fn set_width(&mut self, width: impl Into<UiValue<f32>>) {
408 self.size.set_x(width);
409 }
410 pub fn set_height(&mut self, height: impl Into<UiValue<f32>>) {
412 self.size.set_y(height);
413 }
414 pub fn set_align_x(&mut self, align: impl Into<Align>) {
416 self.align_x = align.into();
417 }
418 pub fn set_align_y(&mut self, align: impl Into<Align>) {
420 self.align_y = align.into();
421 }
422 pub fn set_scaling(&mut self, scaling: Scaling) {
424 self.scaling = scaling;
425 }
426 pub fn pack(self) -> UiLayout {
428 UiLayout::from(self)
429 }
430 pub fn wrap(self) -> UiLayoutType {
432 UiLayoutType::from(self)
433 }
434 pub(crate) fn compute(&self, parent: &Rectangle2D, absolute_scale: f32, viewport_size: Vec2, font_size: f32) -> Rectangle2D {
436
437 let size = self.size.evaluate(Vec2::splat(absolute_scale), parent.size, viewport_size, Vec2::splat(font_size));
438
439 let scale = match self.scaling {
440 Scaling::HorFill => parent.size.x / size.x,
441 Scaling::VerFill => parent.size.y / size.y,
442 Scaling::Fit => f32::min(parent.size.x / size.x, parent.size.y / size.y),
443 Scaling::Fill => f32::max(parent.size.x / size.x, parent.size.y / size.y),
444 };
445
446 let center_point = parent.size / 2.0;
447
448 let computed_width = size.x * scale;
449 let computed_height = size.y * scale;
450 let computed_point = Vec2::new(center_point.x - computed_width / 2.0, center_point.y - computed_height / 2.0);
451
452 Rectangle2D {
453 pos: Vec2::new(
454 computed_point.x * self.align_x.0,
455 computed_point.y * self.align_y.0,
456 ),
457 size: (computed_width, computed_height).into(),
458 }
459 }
460}