1use crate::{color::Color, get_context};
4
5use crate::quad_gl::{DrawMode, Vertex};
6use glam::{vec2, vec3, vec4, Mat4, Vec2};
7
8pub fn draw_triangle(v1: Vec2, v2: Vec2, v3: Vec2, color: Color) {
10 let context = get_context();
11
12 let vertices = [
13 Vertex::new(v1.x, v1.y, 0., 0., 0., color),
14 Vertex::new(v2.x, v2.y, 0., 0., 0., color),
15 Vertex::new(v3.x, v3.y, 0., 0., 0., color),
16 ];
17
18 let indices: [u16; 3] = [0, 1, 2];
19
20 context.gl.texture(None);
21 context.gl.draw_mode(DrawMode::Triangles);
22 context.gl.geometry(&vertices, &indices);
23}
24
25pub fn draw_triangle_lines(v1: Vec2, v2: Vec2, v3: Vec2, thickness: f32, color: Color) {
27 draw_line(v1.x, v1.y, v2.x, v2.y, thickness, color);
28 draw_line(v2.x, v2.y, v3.x, v3.y, thickness, color);
29 draw_line(v3.x, v3.y, v1.x, v1.y, thickness, color);
30}
31
32pub fn draw_rectangle(x: f32, y: f32, w: f32, h: f32, color: Color) {
35 let context = get_context();
36
37 #[rustfmt::skip]
38 let vertices = [
39 Vertex::new(x , y , 0., 0.0, 0.0, color),
40 Vertex::new(x + w, y , 0., 1.0, 0.0, color),
41 Vertex::new(x + w, y + h, 0., 1.0, 1.0, color),
42 Vertex::new(x , y + h, 0., 0.0, 1.0, color),
43 ];
44 let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
45
46 context.gl.texture(None);
47 context.gl.draw_mode(DrawMode::Triangles);
48 context.gl.geometry(&vertices, &indices);
49}
50
51pub fn draw_rectangle_lines(x: f32, y: f32, w: f32, h: f32, thickness: f32, color: Color) {
54 let context = get_context();
55 let t = thickness / 2.;
56
57 #[rustfmt::skip]
58 let vertices = [
59 Vertex::new(x , y , 0., 0.0, 1.0, color),
60 Vertex::new(x + w, y , 0., 1.0, 0.0, color),
61 Vertex::new(x + w, y + h, 0., 1.0, 1.0, color),
62 Vertex::new(x , y + h, 0., 0.0, 0.0, color),
63 Vertex::new(x + t , y + t , 0., 0.0, 0.0, color),
65 Vertex::new(x + w - t, y + t , 0., 0.0, 0.0, color),
66 Vertex::new(x + w - t, y + h - t, 0., 0.0, 0.0, color),
67 Vertex::new(x + t , y + h - t, 0., 0.0, 0.0, color),
68 ];
69 let indices: [u16; 24] = [
70 0, 1, 4, 1, 4, 5, 1, 5, 6, 1, 2, 6, 3, 7, 2, 2, 7, 6, 0, 4, 3, 3, 4, 7,
71 ];
72
73 context.gl.texture(None);
74 context.gl.draw_mode(DrawMode::Triangles);
75 context.gl.geometry(&vertices, &indices);
76}
77
78pub fn draw_rectangle_lines_ex(
79 x: f32,
80 y: f32,
81 w: f32,
82 h: f32,
83 thickness: f32,
84 params: DrawRectangleParams,
85) {
86 let context = get_context();
87 let tx = thickness / w;
88 let ty = thickness / h;
89
90 let transform_matrix = Mat4::from_translation(vec3(x, y, 0.0))
91 * Mat4::from_axis_angle(vec3(0.0, 0.0, 1.0), params.rotation)
92 * Mat4::from_scale(vec3(w, h, 1.0));
93
94 #[rustfmt::skip]
95 let v = [
96 transform_matrix * vec4( 0.0 - params.offset.x, 0.0 - params.offset.y, 0.0, 1.0),
97 transform_matrix * vec4( 0.0 - params.offset.x, 1.0 - params.offset.y, 0.0, 1.0),
98 transform_matrix * vec4( 1.0 - params.offset.x, 1.0 - params.offset.y, 0.0, 1.0),
99 transform_matrix * vec4( 1.0 - params.offset.x, 0.0 - params.offset.y, 0.0, 1.0),
100
101 transform_matrix * vec4( 0.0 - params.offset.x + tx, 0.0 - params.offset.y + ty, 0.0, 1.0),
102 transform_matrix * vec4( 0.0 - params.offset.x + tx, 1.0 - params.offset.y - ty, 0.0, 1.0),
103 transform_matrix * vec4( 1.0 - params.offset.x - tx, 1.0 - params.offset.y - ty, 0.0, 1.0),
104 transform_matrix * vec4( 1.0 - params.offset.x - tx, 0.0 - params.offset.y + ty, 0.0, 1.0),
105 ];
106
107 #[rustfmt::skip]
109 let vertices = [
110 Vertex::new(v[0].x, v[0].y, v[0].z, 0.0, 1.0, params.color),
111 Vertex::new(v[1].x, v[1].y, v[1].z, 1.0, 0.0, params.color),
112 Vertex::new(v[2].x, v[2].y, v[2].z, 1.0, 1.0, params.color),
113 Vertex::new(v[3].x, v[3].y, v[3].z, 1.0, 0.0, params.color),
114
115 Vertex::new(v[4].x, v[4].y, v[4].z, 0.0, 0.0, params.color),
116 Vertex::new(v[5].x, v[5].y, v[5].z, 0.0, 0.0, params.color),
117 Vertex::new(v[6].x, v[6].y, v[6].z, 0.0, 0.0, params.color),
118 Vertex::new(v[7].x, v[7].y, v[7].z, 0.0, 0.0, params.color),
119 ];
120 #[rustfmt::skip]
121 let indices: [u16; 24] = [
122 0, 4, 3,
123 4, 3, 7,
124 4, 0, 1,
125 4, 5, 1,
126 1, 5, 6,
127 1, 6, 2,
128 2, 3, 6,
129 3, 6, 7,
130 ];
131
132 context.gl.texture(None);
133 context.gl.draw_mode(DrawMode::Triangles);
134 context.gl.geometry(&vertices, &indices);
135}
136
137#[derive(Debug, Clone)]
138pub struct DrawRectangleParams {
139 pub offset: Vec2,
143
144 pub rotation: f32,
146
147 pub color: Color,
148}
149
150impl Default for DrawRectangleParams {
151 fn default() -> Self {
152 Self {
153 offset: vec2(0.0, 0.0),
154 rotation: 0.0,
155 color: Color::from_rgba(255, 255, 255, 255),
156 }
157 }
158}
159
160pub fn draw_rectangle_ex(x: f32, y: f32, w: f32, h: f32, params: DrawRectangleParams) {
163 let context = get_context();
164 let transform_matrix = Mat4::from_translation(vec3(x, y, 0.0))
165 * Mat4::from_axis_angle(vec3(0.0, 0.0, 1.0), params.rotation)
166 * Mat4::from_scale(vec3(w, h, 1.0));
167
168 #[rustfmt::skip]
169 let v = [
170 transform_matrix * vec4( 0.0 - params.offset.x, 0.0 - params.offset.y, 0.0, 1.0),
171 transform_matrix * vec4( 0.0 - params.offset.x, 1.0 - params.offset.y, 0.0, 1.0),
172 transform_matrix * vec4( 1.0 - params.offset.x, 1.0 - params.offset.y, 0.0, 1.0),
173 transform_matrix * vec4( 1.0 - params.offset.x, 0.0 - params.offset.y, 0.0, 1.0),
174 ];
175
176 #[rustfmt::skip]
177 let vertices = [
178 Vertex::new(v[0].x, v[0].y, v[0].z, 0.0, 0.0, params.color),
179 Vertex::new(v[1].x, v[1].y, v[1].z, 1.0, 0.0, params.color),
180 Vertex::new(v[2].x, v[2].y, v[2].z, 1.0, 1.0, params.color),
181 Vertex::new(v[3].x, v[3].y, v[3].z, 0.0, 1.0, params.color),
182 ];
183 let indices: [u16; 6] = [0, 1, 2, 0, 2, 3];
184
185 context.gl.texture(None);
186 context.gl.draw_mode(DrawMode::Triangles);
187 context.gl.geometry(&vertices, &indices);
188}
189
190pub fn draw_hexagon(
194 x: f32,
195 y: f32,
196 size: f32,
197 border: f32,
198 vertical: bool,
199 border_color: Color,
200 fill_color: Color,
201) {
202 let rotation = if vertical { 90. } else { 0. };
203 draw_poly(x, y, 6, size, rotation, fill_color);
204 if border > 0. {
205 draw_poly_lines(x, y, 6, size, rotation, border, border_color);
206 }
207}
208
209pub fn draw_poly(x: f32, y: f32, sides: u8, radius: f32, rotation: f32, color: Color) {
212 let context = get_context();
213
214 let mut vertices = Vec::<Vertex>::with_capacity(sides as usize + 2);
215 let mut indices = Vec::<u16>::with_capacity(sides as usize * 3);
216
217 let rot = rotation.to_radians();
218 vertices.push(Vertex::new(x, y, 0., 0., 0., color));
219 for i in 0..=sides {
220 let rx = (i as f32 / sides as f32 * std::f32::consts::PI * 2. + rot).cos();
221 let ry = (i as f32 / sides as f32 * std::f32::consts::PI * 2. + rot).sin();
222
223 let vertex = Vertex::new(x + radius * rx, y + radius * ry, 0., rx, ry, color);
224
225 vertices.push(vertex);
226
227 if i != sides {
228 indices.extend_from_slice(&[0, i as u16 + 1, i as u16 + 2]);
229 }
230 }
231
232 context.gl.texture(None);
233 context.gl.draw_mode(DrawMode::Triangles);
234 context.gl.geometry(&vertices, &indices);
235}
236
237pub fn draw_poly_lines(
240 x: f32,
241 y: f32,
242 sides: u8,
243 radius: f32,
244 rotation: f32,
245 thickness: f32,
246 color: Color,
247) {
248 draw_arc(x, y, sides, radius, rotation, thickness, 360.0, color);
249}
250
251pub fn draw_circle(x: f32, y: f32, r: f32, color: Color) {
256 draw_poly(x, y, 20, r, 0., color);
257}
258
259pub fn draw_circle_lines(x: f32, y: f32, r: f32, thickness: f32, color: Color) {
264 draw_poly_lines(x, y, 30, r, 0., thickness, color);
265}
266
267pub fn draw_ellipse(x: f32, y: f32, w: f32, h: f32, rotation: f32, color: Color) {
270 let sides = 20;
271 let context = get_context();
272
273 let mut vertices = Vec::<Vertex>::with_capacity(sides as usize + 2);
274 let mut indices = Vec::<u16>::with_capacity(sides as usize * 3);
275
276 let rot = rotation.to_radians();
277 let sr = rot.sin();
278 let cr = rot.cos();
279 vertices.push(Vertex::new(x, y, 0., 0., 0., color));
280 for i in 0..=sides {
281 let rx = (i as f32 / sides as f32 * std::f32::consts::PI * 2.).cos();
282 let ry = (i as f32 / sides as f32 * std::f32::consts::PI * 2.).sin();
283
284 let px = w * rx;
285 let py = h * ry;
286 let rotated_x = px * cr - py * sr;
287 let rotated_y = py * cr + px * sr;
288 let vertex = Vertex::new(x + rotated_x, y + rotated_y, 0., rx, ry, color);
289
290 vertices.push(vertex);
291
292 if i != sides {
293 indices.extend_from_slice(&[0, i as u16 + 1, i as u16 + 2]);
294 }
295 }
296
297 context.gl.texture(None);
298 context.gl.draw_mode(DrawMode::Triangles);
299 context.gl.geometry(&vertices, &indices);
300}
301
302pub fn draw_ellipse_lines(
305 x: f32,
306 y: f32,
307 w: f32,
308 h: f32,
309 rotation: f32,
310 thickness: f32,
311 color: Color,
312) {
313 let sides = 20;
314
315 let rot = rotation.to_radians();
316 let sr = rot.sin();
317 let cr = rot.cos();
318 for i in 0..sides {
319 let rx = (i as f32 / sides as f32 * std::f32::consts::PI * 2.).cos();
320 let ry = (i as f32 / sides as f32 * std::f32::consts::PI * 2.).sin();
321 let px = w * rx;
322 let py = h * ry;
323 let rotated_x = px * cr - py * sr;
324 let rotated_y = py * cr + px * sr;
325
326 let p0 = vec2(x + rotated_x, y + rotated_y);
327
328 let rx = ((i + 1) as f32 / sides as f32 * std::f32::consts::PI * 2.).cos();
329 let ry = ((i + 1) as f32 / sides as f32 * std::f32::consts::PI * 2.).sin();
330 let px = w * rx;
331 let py = h * ry;
332 let rotated_x = px * cr - py * sr;
333 let rotated_y = py * cr + px * sr;
334
335 let p1 = vec2(x + rotated_x, y + rotated_y);
336
337 draw_line(p0.x, p0.y, p1.x, p1.y, thickness, color);
338 }
339}
340
341pub fn draw_line(x1: f32, y1: f32, x2: f32, y2: f32, thickness: f32, color: Color) {
343 let context = get_context();
344 let dx = x2 - x1;
345 let dy = y2 - y1;
346
347 let nx = -dy;
350 let ny = dx;
351
352 let tlen = (nx * nx + ny * ny).sqrt() / (thickness * 0.5);
353 if tlen < f32::EPSILON {
354 return;
355 }
356 let tx = nx / tlen;
357 let ty = ny / tlen;
358
359 context.gl.texture(None);
360 context.gl.draw_mode(DrawMode::Triangles);
361 context.gl.geometry(
362 &[
363 Vertex::new(x1 + tx, y1 + ty, 0., 0., 0., color),
364 Vertex::new(x1 - tx, y1 - ty, 0., 0., 0., color),
365 Vertex::new(x2 + tx, y2 + ty, 0., 0., 0., color),
366 Vertex::new(x2 - tx, y2 - ty, 0., 0., 0., color),
367 ],
368 &[0, 1, 2, 2, 1, 3],
369 );
370}
371
372pub fn draw_arc(
375 x: f32,
376 y: f32,
377 sides: u8,
378 radius: f32,
379 rotation: f32,
380 thickness: f32,
381 arc: f32,
382 color: Color,
383) {
384 let rot = rotation.to_radians();
385 let part = arc.to_radians();
386
387 let sides = (sides as f32 * part / std::f32::consts::TAU)
388 .ceil()
389 .max(1.0);
390 let span = part / sides;
391 let sides = sides as usize;
392
393 let context = get_context();
394 context.gl.texture(None);
395 context.gl.draw_mode(DrawMode::Triangles);
396
397 let mut verticies = Vec::<Vertex>::with_capacity(sides * 2);
398 let mut indicies = Vec::<u16>::with_capacity(sides * 2);
399
400 for i in 0..sides {
401 let start_angle = i as f32 * span + rot;
402 let end_angle = start_angle + span;
403
404 indicies.extend([0, 1, 2, 2, 1, 3].map(|k| k + (verticies.len() as u16)));
405
406 for (angle, radius) in [
407 (start_angle, radius),
408 (start_angle, radius + thickness),
409 (end_angle, radius),
410 (end_angle, radius + thickness),
411 ] {
412 let point = Vec2::new(x, y) + radius * Vec2::from_angle(angle);
413 verticies.push(Vertex::new(point.x, point.y, 0., 0., 0., color));
414 }
415 }
416
417 context.gl.geometry(&verticies, &indicies);
418}