1use anchor2d::{Anchor2D, HorizontalAnchor, VerticalAnchorContext, VerticalAnchorValue};
2use macroquad::prelude::*;
3use palette::Srgba;
4
5use crate::Renderer;
6
7fn srgba_to_color(srgba: Srgba) -> Color {
8 Color {
9 r: srgba.red,
10 g: srgba.green,
11 b: srgba.blue,
12 a: srgba.alpha,
13 }
14}
15
16#[derive(Debug, Default, Clone)]
17pub struct MacroquadRenderer {
18 font: Option<Font>,
19}
20
21impl MacroquadRenderer {
22 pub fn new(font: Option<Font>) -> Self {
23 Self { font }
24 }
25
26 pub fn get_font(&self) -> Option<&Font> {
27 self.font.as_ref()
28 }
29
30 pub fn set_font(&mut self, font: Option<Font>) {
31 self.font = font;
32 }
33}
34
35impl Renderer for MacroquadRenderer {
36 fn render_point(&mut self, position: ::glam::DVec2, color: Srgba) {
37 draw_rectangle(
38 position.x as f32,
39 position.y as f32,
40 1.0,
41 1.0,
42 srgba_to_color(color),
43 );
44 }
45
46 fn render_line(
47 &mut self,
48 start: ::glam::DVec2,
49 end: ::glam::DVec2,
50 thickness: f64,
51 color: Srgba,
52 ) {
53 draw_line(
54 start.x as f32,
55 start.y as f32,
56 end.x as f32,
57 end.y as f32,
58 thickness as f32,
59 srgba_to_color(color),
60 );
61 }
62
63 fn render_circle(&mut self, position: ::glam::DVec2, radius: f64, color: Srgba) {
64 draw_circle(
65 position.x as f32,
66 position.y as f32,
67 radius as f32,
68 srgba_to_color(color),
69 );
70 }
71
72 fn render_circle_lines(
73 &mut self,
74 position: ::glam::DVec2,
75 radius: f64,
76 thickness: f64,
77 color: Srgba,
78 ) {
79 draw_circle_lines(
80 position.x as f32,
81 position.y as f32,
82 radius as f32,
83 thickness as f32,
84 srgba_to_color(color),
85 );
86 }
87
88 fn render_arc(
89 &mut self,
90 position: ::glam::DVec2,
91 radius: f64,
92 rotation: f64,
93 arc: f64,
94 color: Srgba,
95 ) {
96 draw_arc(
98 position.x as f32,
99 position.y as f32,
100 64,
101 radius as f32,
102 rotation as f32,
103 1.0,
104 arc as f32,
105 srgba_to_color(color),
106 );
107 }
108
109 fn render_arc_lines(
110 &mut self,
111 position: ::glam::DVec2,
112 radius: f64,
113 rotation: f64,
114 arc: f64,
115 thickness: f64,
116 color: Srgba,
117 ) {
118 draw_arc(
119 position.x as f32,
120 position.y as f32,
121 64,
122 radius as f32,
123 rotation as f32,
124 thickness as f32,
125 arc as f32,
126 srgba_to_color(color),
127 );
128 }
129
130 fn render_text(
131 &mut self,
132 text: &str,
133 position: ::glam::DVec2,
134 anchor: Anchor2D,
135 size: f64,
136 color: Srgba,
137 ) {
138 let measurement = measure_text(text, self.font.as_ref(), size as u16, 1.0);
139
140 let x = match anchor.get_horizontal() {
141 HorizontalAnchor::Left => position.x,
142 HorizontalAnchor::Center => position.x - measurement.width as f64 / 2.0,
143 HorizontalAnchor::Right => position.x - measurement.width as f64,
144 };
145
146 let vertical_anchor = anchor.get_vertical();
147
148 let y = match (vertical_anchor.get_context(), vertical_anchor.get_value()) {
149 (VerticalAnchorContext::Graphics, VerticalAnchorValue::Bottom) => position.y,
150 (VerticalAnchorContext::Math, VerticalAnchorValue::Bottom) => {
151 position.y + measurement.offset_y as f64
152 }
153 (_, VerticalAnchorValue::Center) => position.y + measurement.offset_y as f64 / 2.0,
154 (VerticalAnchorContext::Graphics, VerticalAnchorValue::Top) => {
155 position.y + measurement.offset_y as f64
156 }
157 (VerticalAnchorContext::Math, VerticalAnchorValue::Top) => position.y,
158 };
159
160 draw_text_ex(
161 text,
162 x as f32,
163 y as f32,
164 TextParams {
165 font: self.font.as_ref(),
166 font_size: size as u16,
167 color: srgba_to_color(color),
168 ..TextParams::default()
169 },
170 );
171 }
172
173 fn render_text_outline(
174 &mut self,
175 text: &str,
176 position: ::glam::DVec2,
177 anchor: Anchor2D,
178 size: f64,
179 outline_thickness: f64,
180 color: Srgba,
181 outline_color: Srgba,
182 ) {
183 let measurement = measure_text(text, self.font.as_ref(), size as u16, 1.0);
184
185 let x = match anchor.get_horizontal() {
186 HorizontalAnchor::Left => position.x,
187 HorizontalAnchor::Center => position.x - measurement.width as f64 / 2.0,
188 HorizontalAnchor::Right => position.x - measurement.width as f64,
189 };
190
191 let vertical_anchor = anchor.get_vertical();
192
193 let y = match (vertical_anchor.get_context(), vertical_anchor.get_value()) {
194 (VerticalAnchorContext::Graphics, VerticalAnchorValue::Bottom) => position.y,
195 (VerticalAnchorContext::Math, VerticalAnchorValue::Bottom) => {
196 position.y + measurement.offset_y as f64
197 }
198 (_, VerticalAnchorValue::Center) => position.y + measurement.offset_y as f64 / 2.0,
199 (VerticalAnchorContext::Graphics, VerticalAnchorValue::Top) => {
200 position.y + measurement.offset_y as f64
201 }
202 (VerticalAnchorContext::Math, VerticalAnchorValue::Top) => position.y,
203 };
204
205 for i in -1..=1 {
206 for j in -1..=1 {
207 if i != 0 || j != 0 {
208 draw_text_ex(
209 text,
210 x as f32 - i as f32 * outline_thickness as f32,
211 y as f32 - j as f32 * outline_thickness as f32,
212 TextParams {
213 font: self.font.as_ref(),
214 font_size: size as u16,
215 color: srgba_to_color(outline_color),
216 ..TextParams::default()
217 },
218 );
219 }
220 }
221 }
222
223 draw_text_ex(
224 text,
225 x as f32,
226 y as f32,
227 TextParams {
228 font: self.font.as_ref(),
229 font_size: size as u16,
230 color: srgba_to_color(color),
231 ..TextParams::default()
232 },
233 );
234 }
235
236 fn render_rectangle(
237 &mut self,
238 position: ::glam::DVec2,
239 width: f64,
240 height: f64,
241 offset: ::glam::DVec2,
242 rotation: f64,
243 color: Srgba,
244 ) {
245 draw_rectangle_ex(
246 position.x as f32,
247 position.y as f32,
248 width as f32,
249 height as f32,
250 DrawRectangleParams {
251 offset: vec2(offset.x as f32, offset.y as f32),
252 rotation: rotation as f32,
253 color: srgba_to_color(color),
254 },
255 );
256 }
257
258 fn render_rectangle_lines(
259 &mut self,
260 position: ::glam::DVec2,
261 width: f64,
262 height: f64,
263 offset: ::glam::DVec2,
264 rotation: f64,
265 thickness: f64,
266 color: Srgba,
267 ) {
268 draw_rectangle_lines_ex(
269 position.x as f32,
270 position.y as f32,
271 width as f32,
272 height as f32,
273 thickness as f32,
274 DrawRectangleParams {
275 offset: vec2(offset.x as f32, offset.y as f32),
276 rotation: rotation as f32,
277 color: srgba_to_color(color),
278 },
279 );
280 }
281
282 fn render_equilateral_triangle(
283 &mut self,
284 position: ::glam::DVec2,
285 radius: f64,
286 rotation: f64,
287 color: Srgba,
288 ) {
289 draw_poly(
290 position.x as f32,
291 position.y as f32,
292 3,
293 radius as f32,
294 rotation.to_degrees() as f32,
295 srgba_to_color(color),
296 );
297 }
298
299 fn render_equilateral_triangle_lines(
300 &mut self,
301 position: ::glam::DVec2,
302 radius: f64,
303 rotation: f64,
304 thickness: f64,
305 color: Srgba,
306 ) {
307 draw_poly_lines(
308 position.x as f32,
309 position.y as f32,
310 3,
311 radius as f32,
312 rotation.to_degrees() as f32,
313 thickness as f32,
314 srgba_to_color(color),
315 );
316 }
317}