emath/
rect_transform.rs

1use crate::{pos2, remap, remap_clamp, Pos2, Rect, Vec2};
2
3/// Linearly transforms positions from one [`Rect`] to another.
4///
5/// [`RectTransform`] stores the rectangles, and therefore supports clamping and culling.
6#[repr(C)]
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
9#[cfg_attr(feature = "bytemuck", derive(bytemuck::Pod, bytemuck::Zeroable))]
10pub struct RectTransform {
11    from: Rect,
12    to: Rect,
13}
14
15impl RectTransform {
16    pub fn identity(from_and_to: Rect) -> Self {
17        Self::from_to(from_and_to, from_and_to)
18    }
19
20    pub fn from_to(from: Rect, to: Rect) -> Self {
21        Self { from, to }
22    }
23
24    pub fn from(&self) -> &Rect {
25        &self.from
26    }
27
28    pub fn to(&self) -> &Rect {
29        &self.to
30    }
31
32    /// The scale factors.
33    pub fn scale(&self) -> Vec2 {
34        self.to.size() / self.from.size()
35    }
36
37    pub fn inverse(&self) -> Self {
38        Self::from_to(self.to, self.from)
39    }
40
41    /// Transforms the given coordinate in the `from` space to the `to` space.
42    pub fn transform_pos(&self, pos: Pos2) -> Pos2 {
43        pos2(
44            remap(pos.x, self.from.x_range(), self.to.x_range()),
45            remap(pos.y, self.from.y_range(), self.to.y_range()),
46        )
47    }
48
49    /// Transforms the given rectangle in the `in`-space to a rectangle in the `out`-space.
50    pub fn transform_rect(&self, rect: Rect) -> Rect {
51        Rect {
52            min: self.transform_pos(rect.min),
53            max: self.transform_pos(rect.max),
54        }
55    }
56
57    /// Transforms the given coordinate in the `from` space to the `to` space,
58    /// clamping if necessary.
59    pub fn transform_pos_clamped(&self, pos: Pos2) -> Pos2 {
60        pos2(
61            remap_clamp(pos.x, self.from.x_range(), self.to.x_range()),
62            remap_clamp(pos.y, self.from.y_range(), self.to.y_range()),
63        )
64    }
65}
66
67/// Transforms the position.
68impl std::ops::Mul<Pos2> for RectTransform {
69    type Output = Pos2;
70
71    fn mul(self, pos: Pos2) -> Pos2 {
72        self.transform_pos(pos)
73    }
74}
75
76/// Transforms the position.
77impl std::ops::Mul<Pos2> for &RectTransform {
78    type Output = Pos2;
79
80    fn mul(self, pos: Pos2) -> Pos2 {
81        self.transform_pos(pos)
82    }
83}