1use crate::{Vec2, Vec4, vec2};
2
3#[repr(C)]
5#[derive(Clone, Copy, Debug, Default, PartialEq)]
6pub struct Rect {
7 pub x: f32,
8 pub y: f32,
9 pub w: f32,
10 pub h: f32,
11}
12impl Rect {
13 pub const ZERO: Self = Self::new(0.0, 0.0, 0.0, 0.0);
14 pub const fn new(x: f32, y: f32, w: f32, h: f32) -> Self {
15 Self { x, y, w, h }
16 }
17 pub const fn point(self) -> Vec2 {
18 vec2(self.x, self.y)
19 }
20 pub const fn size(self) -> Vec2 {
21 vec2(self.w, self.h)
22 }
23 pub fn center(self) -> Vec2 {
24 self.point() + self.size() * 0.5
25 }
26 pub const fn left(self) -> f32 {
27 self.x
28 }
29 pub const fn right(self) -> f32 {
30 self.x + self.w
31 }
32 pub const fn top(self) -> f32 {
33 self.y
34 }
35 pub const fn bottom(self) -> f32 {
36 self.y + self.h
37 }
38 pub fn is_finite(self) -> bool {
39 [self.x, self.y, self.w, self.h]
40 .into_iter()
41 .all(f32::is_finite)
42 }
43 pub fn contains(self, p: Vec2) -> bool {
44 self.is_finite()
45 && self.w >= 0.0
46 && self.h >= 0.0
47 && p.x >= self.x
48 && p.x <= self.right()
49 && p.y >= self.y
50 && p.y <= self.bottom()
51 }
52 pub fn overlaps(self, other: &Self) -> bool {
54 self.w > 0.0
55 && self.h > 0.0
56 && other.w > 0.0
57 && other.h > 0.0
58 && self.x < other.right()
59 && self.right() > other.x
60 && self.y < other.bottom()
61 && self.bottom() > other.y
62 }
63 pub fn intersect(self, other: Self) -> Option<Self> {
64 if !self.overlaps(&other) {
65 return None;
66 }
67 let point = self.point().max(other.point());
68 let end = vec2(self.right(), self.bottom()).min(vec2(other.right(), other.bottom()));
69 Some(Self::new(
70 point.x,
71 point.y,
72 end.x - point.x,
73 end.y - point.y,
74 ))
75 }
76 pub fn combine_with(self, other: Self) -> Self {
77 let p = self.point().min(other.point());
78 let end = vec2(self.right(), self.bottom()).max(vec2(other.right(), other.bottom()));
79 Self::new(p.x, p.y, end.x - p.x, end.y - p.y)
80 }
81 pub fn move_to(&mut self, p: Vec2) {
82 self.x = p.x;
83 self.y = p.y;
84 }
85 pub fn offset(self, delta: Vec2) -> Self {
86 Self::new(self.x + delta.x, self.y + delta.y, self.w, self.h)
87 }
88 pub fn normalized(self) -> Self {
89 Self::new(
90 self.x.min(self.right()),
91 self.y.min(self.bottom()),
92 self.w.abs(),
93 self.h.abs(),
94 )
95 }
96}
97
98#[repr(C)]
100#[derive(Clone, Copy, Debug, Default, PartialEq)]
101pub struct Color {
102 pub r: f32,
103 pub g: f32,
104 pub b: f32,
105 pub a: f32,
106}
107impl Color {
108 pub const fn new(r: f32, g: f32, b: f32, a: f32) -> Self {
109 Self { r, g, b, a }
110 }
111 pub const fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
112 Self::new(
113 r as f32 / 255.0,
114 g as f32 / 255.0,
115 b as f32 / 255.0,
116 a as f32 / 255.0,
117 )
118 }
119 pub const fn from_hex(rgb: u32) -> Self {
121 Self::from_rgba((rgb >> 16) as u8, (rgb >> 8) as u8, rgb as u8, 255)
122 }
123 pub const fn to_vec(self) -> Vec4 {
124 Vec4::new(self.r, self.g, self.b, self.a)
125 }
126 pub const fn to_array(self) -> [f32; 4] {
127 [self.r, self.g, self.b, self.a]
128 }
129 pub fn to_rgba(self) -> [u8; 4] {
130 self.to_array()
131 .map(|c| (c.clamp(0.0, 1.0) * 255.0).round() as u8)
132 }
133 pub const fn with_alpha(self, alpha: f32) -> Self {
134 Self { a: alpha, ..self }
135 }
136 pub fn lerp(self, other: Self, t: f32) -> Self {
137 Self::from(self.to_vec().lerp(other.to_vec(), t))
138 }
139 pub fn premultiplied(self) -> Self {
140 Self::new(self.r * self.a, self.g * self.a, self.b * self.a, self.a)
141 }
142}
143impl From<Vec4> for Color {
144 fn from(v: Vec4) -> Self {
145 Self::new(v.x, v.y, v.z, v.w)
146 }
147}
148impl From<[f32; 4]> for Color {
149 fn from(v: [f32; 4]) -> Self {
150 Self::new(v[0], v[1], v[2], v[3])
151 }
152}
153impl From<Color> for [f32; 4] {
154 fn from(v: Color) -> Self {
155 v.to_array()
156 }
157}
158impl From<Color> for Vec4 {
159 fn from(v: Color) -> Self {
160 v.to_vec()
161 }
162}