1pub const GUI_ROUNDING: f32 = 1.0 / 32.0;
19
20pub trait GuiRounding {
24 fn round_ui(self) -> Self;
32
33 fn floor_ui(self) -> Self;
35
36 fn round_to_pixels(self, pixels_per_point: f32) -> Self;
44
45 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self;
54}
55
56impl GuiRounding for f32 {
57 #[inline]
58 fn round_ui(self) -> Self {
59 (self / GUI_ROUNDING).round() * GUI_ROUNDING
60 }
61
62 #[inline]
63 fn floor_ui(self) -> Self {
64 (self / GUI_ROUNDING).floor() * GUI_ROUNDING
65 }
66
67 #[inline]
68 fn round_to_pixels(self, pixels_per_point: f32) -> Self {
69 (self * pixels_per_point).round() / pixels_per_point
70 }
71
72 #[inline]
73 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
74 ((self * pixels_per_point - 0.5).round() + 0.5) / pixels_per_point
75 }
76}
77
78impl GuiRounding for f64 {
79 #[inline]
80 fn round_ui(self) -> Self {
81 (self / GUI_ROUNDING as Self).round() * GUI_ROUNDING as Self
82 }
83
84 #[inline]
85 fn floor_ui(self) -> Self {
86 (self / GUI_ROUNDING as Self).floor() * GUI_ROUNDING as Self
87 }
88
89 #[inline]
90 fn round_to_pixels(self, pixels_per_point: f32) -> Self {
91 (self * pixels_per_point as Self).round() / pixels_per_point as Self
92 }
93
94 #[inline]
95 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
96 ((self * pixels_per_point as Self - 0.5).round() + 0.5) / pixels_per_point as Self
97 }
98}
99
100impl GuiRounding for crate::Vec2 {
101 #[inline]
102 fn round_ui(self) -> Self {
103 Self::new(self.x.round_ui(), self.y.round_ui())
104 }
105
106 #[inline]
107 fn floor_ui(self) -> Self {
108 Self::new(self.x.floor_ui(), self.y.floor_ui())
109 }
110
111 #[inline]
112 fn round_to_pixels(self, pixels_per_point: f32) -> Self {
113 Self::new(
114 self.x.round_to_pixels(pixels_per_point),
115 self.y.round_to_pixels(pixels_per_point),
116 )
117 }
118
119 #[inline]
121 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
122 Self::new(
123 self.x.round_to_pixel_center(pixels_per_point),
124 self.y.round_to_pixel_center(pixels_per_point),
125 )
126 }
127}
128
129impl GuiRounding for crate::Pos2 {
130 #[inline]
131 fn round_ui(self) -> Self {
132 Self::new(self.x.round_ui(), self.y.round_ui())
133 }
134
135 #[inline]
136 fn floor_ui(self) -> Self {
137 Self::new(self.x.floor_ui(), self.y.floor_ui())
138 }
139
140 #[inline]
141 fn round_to_pixels(self, pixels_per_point: f32) -> Self {
142 Self::new(
143 self.x.round_to_pixels(pixels_per_point),
144 self.y.round_to_pixels(pixels_per_point),
145 )
146 }
147
148 #[inline]
149 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
150 Self::new(
151 self.x.round_to_pixel_center(pixels_per_point),
152 self.y.round_to_pixel_center(pixels_per_point),
153 )
154 }
155}
156
157impl GuiRounding for crate::Rect {
158 #[inline]
161 fn round_ui(self) -> Self {
162 Self::from_min_max(self.min.round_ui(), self.max.round_ui())
163 }
164
165 #[inline]
168 fn floor_ui(self) -> Self {
169 Self::from_min_max(self.min.floor_ui(), self.max.floor_ui())
170 }
171
172 #[inline]
175 fn round_to_pixels(self, pixels_per_point: f32) -> Self {
176 Self::from_min_max(
177 self.min.round_to_pixels(pixels_per_point),
178 self.max.round_to_pixels(pixels_per_point),
179 )
180 }
181
182 #[inline]
185 fn round_to_pixel_center(self, pixels_per_point: f32) -> Self {
186 Self::from_min_max(
187 self.min.round_to_pixel_center(pixels_per_point),
188 self.max.round_to_pixel_center(pixels_per_point),
189 )
190 }
191}
192
193#[test]
194fn test_gui_rounding() {
195 assert_eq!(0.0_f32.round_ui(), 0.0);
196 assert_eq!((GUI_ROUNDING * 1.11).round_ui(), GUI_ROUNDING);
197 assert_eq!((-GUI_ROUNDING * 1.11).round_ui(), -GUI_ROUNDING);
198 assert_eq!(f32::NEG_INFINITY.round_ui(), f32::NEG_INFINITY);
199 assert_eq!(f32::INFINITY.round_ui(), f32::INFINITY);
200
201 assert_eq!(0.17_f32.round_to_pixel_center(2.0), 0.25);
202}