1use std::{cell::RefCell, collections::HashMap};
4use super::RenderPass;
5
6use crate::{
7 font::{Font, FontManager}, math::{Color, Point2, RectF, Vector2, Vector3, Vertex}, utils::ArcRef
8};
9
10use super::{
11 super::{
12 GPUInner,
13 texture::{
14 atlas::TextureAtlas,
15 Texture,
16 TextureBuilder,
17 TextureUsage,
18 TextureSampler,
19 TextureFormat
20 },
21 shader::{GraphicsShader, GraphicsShaderBuilder},
22 },
23};
24
25#[derive(Clone, Debug)]
26pub(crate) struct DrawingGlobalState {
27 pub texture: Texture,
28 pub shader: GraphicsShader,
29 pub font_manager: FontManager,
30 pub font_textures: HashMap<String, Texture>,
31}
32
33impl DrawingGlobalState {
34 pub fn new(gpu_inner: &ArcRef<GPUInner>) -> Option<Self> {
35 let default_texture = TextureBuilder::new(ArcRef::clone(gpu_inner))
36 .set_raw_image(&[255u8, 255, 255, 255], Point2::new(1, 1), TextureFormat::Bgra8Unorm)
37 .set_usage(TextureUsage::Sampler)
38 .build()
39 .ok()?;
40
41 let default_shader = GraphicsShaderBuilder::new(ArcRef::clone(gpu_inner))
42 .set_source(include_str!("./resources/drawing_shader.wgsl"))
43 .build()
44 .ok()?;
45
46 let font_manager = FontManager::new();
47
48 Some(Self {
49 texture: default_texture,
50 shader: default_shader,
51 font_manager,
52 font_textures: HashMap::new(),
53 })
54 }
55}
56
57pub(crate) struct DrawingContextInner {
58 pass: RenderPass,
59 drawing_global_state: ArcRef<DrawingGlobalState>,
60
61 vertices: Vec<Vertex>,
62 indices: Vec<u16>,
63
64 texture: Option<(Texture, TextureSampler)>,
65 texture_uv: Option<RectF>,
66 texture_atlas_uv: Option<RectF>,
67 shader: Option<GraphicsShader>,
68 scissor: Option<RectF>,
69 viewport: Option<RectF>,
70 rotation: f32,
71 current_queue: Option<DrawingQueue>,
72 queue: Vec<DrawingQueue>,
73
74 current_font: Option<Font>,
75 current_font_texture: Option<Texture>,
76}
77
78impl DrawingContextInner {
79 pub fn get_absolute_uv(&self) -> RectF {
80 fn remap_uv(rect1: RectF, rect2: RectF) -> RectF {
81 RectF {
82 x: rect2.x + (rect2.w - rect2.x) * rect1.x,
83 y: rect2.y + (rect2.h - rect2.y) * rect1.y,
84 w: rect2.x + (rect2.w - rect2.x) * rect1.w,
85 h: rect2.y + (rect2.h - rect2.y) * rect1.h,
86 }
87 }
88
89 fn resolve_uv(uv1: Option<RectF>, uv2: Option<RectF>) -> RectF {
90 match (uv1, uv2) {
91 (Some(r1), Some(r2)) => remap_uv(r1, r2),
92 (Some(r1), None) => r1,
93 (None, Some(r2)) => r2,
94 (None, None) => RectF::new(0.0, 0.0, 1.0, 1.0),
95 }
96 }
97
98 resolve_uv(self.texture_uv.clone(), self.texture_atlas_uv.clone())
99 }
100
101 pub fn push_geometry(
102 &mut self,
103 vertices: &[Vertex],
104 indices: &[u16],
105 has_image: bool,
106 ) {
107 if vertices.is_empty() || indices.is_empty() {
108 return;
109 }
110
111 let base_index = self.vertices.len() as u16;
112 let indices: Vec<u16> = indices.iter().map(|i| i + base_index).collect();
113 self.push_queue(indices.len() as u32, has_image);
114
115 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
116 {
117 for vertex in vertices {
118 if vertex.position.z != 0.0 {
119 panic!("DrawingContext only supports 2D rendering with z = 0.0");
120 }
121
122 if vertex.texcoord.x < 0.0
123 || vertex.texcoord.y < 0.0
124 || vertex.texcoord.x > 1.0
125 || vertex.texcoord.y > 1.0
126 {
127 panic!("Texture coordinates must be in the range [0, 1]");
128 }
129 }
130 }
131
132 if self.rotation < 0.0 {
133 self.rotation += 360.0;
134 }
135
136 if self.rotation > 0.0 {
137 let mut l = Vector3::new(f32::MAX, f32::MAX, 0.0);
138 let mut r = Vector3::new(f32::MIN, f32::MIN, 0.0);
139
140 for vertex in vertices {
141 l = l.min(&vertex.position);
142 r = r.max(&vertex.position);
143 }
144
145 let center = (l + r) * 0.5;
146 let angle = self.rotation.to_radians();
147
148 let cos_angle = angle.cos();
149 let sin_angle = angle.sin();
150
151 let mut vertices = vertices.to_vec();
152 for vertex in vertices.iter_mut() {
153 vertex.position -= center;
154
155 let x = vertex.position.x * cos_angle - vertex.position.y * sin_angle;
156 let y = vertex.position.x * sin_angle + vertex.position.y * cos_angle;
157
158 vertex.position.x = x + center.x;
159 vertex.position.y = y + center.y;
160 }
161
162 self.vertices.extend_from_slice(&vertices);
163 } else {
164 self.vertices.extend_from_slice(vertices);
165 }
166
167 self.indices.extend_from_slice(&indices);
168 }
169
170 pub fn push_queue(
171 &mut self,
172 count: u32,
173 has_image: bool,
174 ) {
175 let mut push_new_queue = false;
176
177 if self.current_queue.is_some() {
178 let ref_queue = self.current_queue.as_ref().unwrap();
179
180 let current_texture = if has_image { &self.texture } else { &None };
182
183 let texture_changed = match (&ref_queue.texture, current_texture) {
184 (None, None) => false,
185 (Some(_), None) | (None, Some(_)) => true,
186 (
187 Some((old_texture, old_sampler)),
188 Some((new_texture, new_sampler)),
189 ) => {
190 old_texture != new_texture
191 || old_sampler != new_sampler
192 }
193 };
194
195 if texture_changed {
196 push_new_queue = true;
197 }
198
199 let blend_states_changed = {
200 let renderpass_inner = self.pass.inner.borrow();
201 let ref_queue_blend_states = &ref_queue.blend_states;
202
203 if renderpass_inner.render_targets.len() != ref_queue_blend_states.len() {
204 panic!("Render targets count mismatch: expected {}, got {}", renderpass_inner.render_targets.len(), ref_queue_blend_states.len());
205 } else {
206 renderpass_inner.render_targets.iter().enumerate().any(|(i, render_target)| {
207 let (state, color_write) = &ref_queue_blend_states[i];
208 render_target.blend != *state || render_target.write_mask != *color_write
209 })
210 }
211 };
212
213 if blend_states_changed {
214 push_new_queue = true;
215 }
216
217 if ref_queue.scissors != self.scissor {
219 push_new_queue = true;
220 }
221
222 if ref_queue.viewport != self.viewport {
224 push_new_queue = true;
225 }
226
227 if ref_queue.shader != self.shader {
229 push_new_queue = true;
230 }
231 } else {
232 push_new_queue = true;
233 }
234
235 if push_new_queue {
237 if let Some(queue) = self.current_queue.take() {
238 self.queue.push(queue);
239 }
240
241 let blend_state = {
242 let renderpass_inner = self.pass.inner.borrow();
243 renderpass_inner.render_targets.iter()
244 .map(|rt| (rt.blend.clone(), rt.write_mask))
245 .collect::<Vec<_>>()
246 };
247
248 self.current_queue = Some(DrawingQueue {
249 texture: self.texture.clone(),
250 shader: None,
251 scissors: self.scissor.clone(),
252 viewport: self.viewport.clone(),
253 start_index: self.indices.len() as u32,
254 start_vertex: 0, count,
256 blend_states: blend_state,
257 });
258 } else {
259 let queue = self.current_queue.as_mut().unwrap();
260 queue.count += count;
261 }
262 }
263
264 pub fn load_font(&mut self, font_path: &str, range: Option<&[(u32, u32)]>, size: f32) {
265 let mut state = self.drawing_global_state.borrow_mut();
266 if let Ok(font) = state.font_manager.load_font(font_path, range, size) {
267 if !state.font_textures.contains_key(font_path) {
268 let texture = font.create_texture_inner(&self.pass.graphics)
269 .expect("Failed to create font texture");
270
271 state.font_textures.insert(font_path.to_string(), texture);
272 }
273
274 self.current_font = Some(font);
275 self.current_font_texture = state.font_textures.get(font_path).cloned();
276 } else {
277 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
278 {
279 crate::dbg_log!("Failed to load font: {}", font_path);
280 }
281 }
282 }
283
284 pub fn set_font(&mut self, font: &Font) {
285 let name = {
286 let font_inner = font.inner.borrow();
287 font_inner.info.path.clone().into_os_string().into_string()
288 .ok()
289 };
290
291 if name.is_none() {
292 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
293 {
294 crate::dbg_log!("Font path is None, cannot set font");
295 }
296 return;
297 }
298
299 let name = name.unwrap();
300
301 let mut state = self.drawing_global_state.borrow_mut();
302 if !state.font_textures.contains_key(&name) {
303 let texture = font.create_texture_inner(&self.pass.graphics)
304 .expect("Failed to create font texture");
305
306 state.font_textures.insert(name.to_string(), texture);
307 }
308
309 self.current_font = Some(font.clone());
310 self.current_font_texture = state.font_textures.get(&name).cloned();
311 }
312}
313
314pub(crate) struct DrawingQueue {
315 pub texture: Option<(Texture, TextureSampler)>,
316 pub shader: Option<GraphicsShader>,
317
318 pub scissors: Option<RectF>,
319 pub viewport: Option<RectF>,
320
321 pub start_index: u32,
322 pub start_vertex: u32,
323 pub count: u32,
324
325 pub blend_states: Vec<(Option<wgpu::BlendState>, Option<wgpu::ColorWrites>)>,
326}
327
328#[derive(Clone, Debug)]
332pub struct DrawingContext {
333 pub(crate) inner: ArcRef<DrawingContextInner>,
334
335 pub(crate) vertex_cache: Vec<Vertex>,
336 pub(crate) index_cache: Vec<u16>,
337}
338
339impl DrawingContext {
340 pub(crate) fn new(pass: RenderPass) -> Option<Self> {
341 if pass.graphics.borrow().drawing_state.is_none() {
342 let state = DrawingGlobalState::new(&pass.graphics)?;
343
344 let mut gpu_inner = pass.graphics.borrow_mut();
345 gpu_inner.drawing_state = Some(ArcRef::new(state));
346 }
347
348 let drawing_state = ArcRef::clone(
349 &pass.graphics.borrow().drawing_state.as_ref().unwrap()
350 );
351
352 let inner = DrawingContextInner {
353 pass: pass,
354 drawing_global_state: drawing_state,
355
356 vertices: Vec::new(),
357 indices: Vec::new(),
358 rotation: 0.0,
359 texture: None,
360 texture_uv: None,
361 texture_atlas_uv: None,
362 shader: None,
363 scissor: None,
364 viewport: None,
365 current_queue: None,
366 queue: Vec::new(),
367
368 current_font: None,
369 current_font_texture: None,
370 };
371
372 Some(DrawingContext {
373 inner: ArcRef::new(inner),
374
375 vertex_cache: Vec::new(),
376 index_cache: Vec::new(),
377 })
378 }
379
380 fn construct_line(a: Vector2, b: Vector2, thickness: f32) -> Option<([Vector2; 4], [u16; 6])> {
381 let dir = b - a;
382 let len = dir.length();
383 if len == 0.0 {
384 return None;
385 }
386
387 let dir = dir / len;
388 let perp = Vector2::new(-dir.y, dir.x) * (thickness * 0.5);
389
390 let vertices = [a + perp, b + perp, b - perp, a - perp];
391
392 let indices = [0, 1, 2, 0, 2, 3];
393
394 Some((vertices, indices))
395 }
396
397 #[allow(dead_code)]
398 fn construct_quad(pos: Vector2, size: Vector2) -> ([Vector2; 4], [u16; 6]) {
399 let vertices = [
400 Vector2::new(pos.x, pos.y),
401 Vector2::new(pos.x + size.x, pos.y),
402 Vector2::new(pos.x + size.x, pos.y + size.y),
403 Vector2::new(pos.x, pos.y + size.y),
404 ];
405
406 let indices = [0, 1, 2, 0, 2, 3];
407
408 (vertices, indices)
409 }
410
411 pub fn load_font(&mut self, font_path: &str, range: Option<&[(u32, u32)]>, size: f32) {
413 let mut inner = self.inner.borrow_mut();
414 inner.load_font(font_path, range, size);
415 }
416
417 pub fn set_font(&mut self, font: &Font) {
419 let mut inner = self.inner.borrow_mut();
420 inner.set_font(font);
421 }
422
423 pub fn get_font(&self) -> Font {
425 let mut inner = self.inner.borrow_mut();
426 if inner.current_font.is_none() {
427 inner.load_font("Arial", None, 16.0);
428 }
429
430 inner.current_font.clone().unwrap_or_else(|| {
431 panic!("Fatal: No font loaded, this shouldn't happen as default Font is loaded on demand.");
432 })
433 }
434
435 pub fn draw_text(&mut self, text: &str, pos: Vector2, color: Color) {
437 let mut inner = self.inner.borrow_mut();
438 if inner.current_font.is_none() {
439 inner.load_font("Arial", None, 16.0);
440 }
441
442 vec_clear(&mut self.vertex_cache);
443 vec_clear(&mut self.index_cache);
444
445 let font = inner.current_font.as_ref().unwrap();
446 let texture_size = font.texture_size();
447 let line_height = font.line_height();
448 let ascender = font.ascender();
449 let space_width = font.space_width();
450
451 let mut pen_y = 0.0;
453 let mut min_y = f32::MAX;
454 for c in text.chars() {
455 let codepoint = c as u32;
456 if codepoint == 0 {
457 continue;
458 }
459
460 if codepoint == '\n' as u32 {
461 pen_y += line_height;
462 continue;
463 }
464
465 if let Ok(glyph) = font.get_glyph(codepoint) {
466 min_y = f32::min(min_y, pen_y + ascender - (glyph.bearing_y + glyph.height));
467 }
468 }
469
470 let mut pen = pos;
471 for c in text.chars() {
472 let codepoint = c as u32;
473 if codepoint == 0 {
474 continue;
475 }
476
477 if codepoint == '\n' as u32 {
478 pen.x = pos.x;
479 pen.y += line_height;
480 continue;
481 }
482
483 if codepoint == ' ' as u32 {
484 pen.x += space_width;
485 continue;
486 }
487
488 if let Ok(glyph) = font.get_glyph(codepoint) {
489 let x0 = pen.x + glyph.bearing_x;
490 let y0 = pen.y + ascender - (glyph.bearing_y + glyph.height) - min_y;
491 let x1 = x0 + glyph.width;
492 let y1 = y0 + glyph.height;
493
494 let uv_x0 = glyph.atlas_start_offset.x as f32 / texture_size.x as f32;
495 let uv_y0 = glyph.atlas_start_offset.y as f32 / texture_size.y as f32;
496 let uv_x1 = (glyph.atlas_start_offset.x + glyph.width) as f32 / texture_size.x as f32;
497 let uv_y1 = (glyph.atlas_start_offset.y + glyph.height) as f32 / texture_size.y as f32;
498
499 let vertices = [
500 Vertex::new(Vector3::new(x0, y0, 0.0), color, Vector2::new(uv_x0, uv_y0)),
501 Vertex::new(Vector3::new(x1, y0, 0.0), color, Vector2::new(uv_x1, uv_y0)),
502 Vertex::new(Vector3::new(x1, y1, 0.0), color, Vector2::new(uv_x1, uv_y1)),
503 Vertex::new(Vector3::new(x0, y1, 0.0), color, Vector2::new(uv_x0, uv_y1)),
504 ];
505
506 let base_index = self.vertex_cache.len() as u16;
507 let indices = [
508 base_index + 0,
509 base_index + 1,
510 base_index + 2,
511 base_index + 0,
512 base_index + 2,
513 base_index + 3,
514 ];
515
516 self.vertex_cache.extend_from_slice(&vertices);
517 self.index_cache.extend_from_slice(&indices);
518
519 pen.x += glyph.advance_x;
520 }
521 }
522
523 if self.index_cache.is_empty() {
524 return;
525 }
526
527 let all_vertices = &self.vertex_cache;
528 let all_indices = &self.index_cache;
529
530 let current_texture = inner.texture.clone();
531 let font_texture = inner.current_font_texture.clone();
532 inner.texture = Some((
533 font_texture.unwrap(),
534 TextureSampler::DEFAULT,
535 ));
536
537 inner.push_geometry(&all_vertices, &all_indices, true);
538
539 inner.texture = current_texture;
540 }
541
542 pub fn draw_rect(&mut self, pos: Vector2, size: Vector2, thickness: f32, color: Color) {
544 let corners = [
545 pos,
546 pos + Vector2::new(size.x, 0.0),
547 pos + size,
548 pos + Vector2::new(0.0, size.y),
549 ];
550
551 let all_vertices = &mut self.vertex_cache;
552 let all_indices = &mut self.index_cache;
553 let mut index_offset = 0u16;
554
555 vec_clear(all_vertices);
556 vec_clear(all_indices);
557
558 for i in 0..4 {
559 let a = corners[i];
560 let b = corners[(i + 1) % 4];
561 let line = Self::construct_line(a, b, thickness);
562 if line.is_none() {
563 continue;
564 }
565
566 let (vertices, mut indices) = line.unwrap();
567 let vertices = vertices
568 .iter()
569 .map(|v| {
570 Vertex::new(
571 Vector3::new(v.x, v.y, 0.0),
572 color,
573 Vector2::ZERO,
574 )
575 })
576 .collect::<Vec<_>>();
577
578 indices.iter_mut().for_each(|idx| *idx += index_offset);
579 index_offset += vertices.len() as u16;
580
581 all_vertices.extend(vertices);
582 all_indices.extend(indices);
583 }
584
585 self.inner.borrow_mut()
586 .push_geometry(&all_vertices, &all_indices, false);
587 }
588
589 pub fn draw_line(&mut self, a: Vector2, b: Vector2, thickness: f32, color: Color) {
591 let line = Self::construct_line(a, b, thickness);
592 if line.is_none() {
593 return;
594 }
595
596 let (vertices, indices) = line.unwrap();
597 let vertices = vertices
598 .iter()
599 .map(|v| {
600 Vertex::new(
601 Vector3::new(v.x, v.y, 0.0),
602 color,
603 Vector2::ZERO,
604 )
605 })
606 .collect::<Vec<_>>();
607
608 self.inner.borrow_mut()
609 .push_geometry(&vertices, &indices, false);
610 }
611
612 pub fn draw_rect_filled(&mut self, pos: Vector2, size: Vector2, color: Color) {
614 let vertices = [
615 Vertex::new(
616 Vector3::new(pos.x, pos.y, 0.0),
617 color,
618 Vector2::ZERO,
619 ),
620 Vertex::new(
621 Vector3::new(pos.x + size.x, pos.y, 0.0),
622 color,
623 Vector2::ZERO,
624 ),
625 Vertex::new(
626 Vector3::new(pos.x + size.x, pos.y + size.y, 0.0),
627 color,
628 Vector2::ZERO,
629 ),
630 Vertex::new(
631 Vector3::new(pos.x, pos.y + size.y, 0.0),
632 color,
633 Vector2::ZERO,
634 ),
635 ];
636
637 let indices = [0, 1, 2, 0, 2, 3];
638
639 self.inner.borrow_mut()
640 .push_geometry(&vertices, &indices, false);
641 }
642
643 pub fn draw_rect_filled_colors(
645 &mut self,
646 pos: Vector2,
647 size: Vector2,
648 color_tl: Color,
649 color_tr: Color,
650 color_br: Color,
651 color_bl: Color,
652 ) {
653 let vertices = [
654 Vertex::new(
655 Vector3::new(pos.x, pos.y, 0.0),
656 color_tl.into_srgb(),
657 Vector2::ZERO,
658 ),
659 Vertex::new(
660 Vector3::new(pos.x + size.x, pos.y, 0.0),
661 color_tr.into_srgb(),
662 Vector2::ZERO,
663 ),
664 Vertex::new(
665 Vector3::new(pos.x + size.x, pos.y + size.y, 0.0),
666 color_br.into_srgb(),
667 Vector2::ZERO,
668 ),
669 Vertex::new(
670 Vector3::new(pos.x, pos.y + size.y, 0.0),
671 color_bl.into_srgb(),
672 Vector2::ZERO,
673 ),
674 ];
675
676 let indices = [
677 0, 1, 2, 0, 2, 3, ];
680
681 self.inner.borrow_mut()
682 .push_geometry(&vertices, &indices, false);
683 }
684
685 pub fn draw_triangle(
687 &mut self,
688 a: Vector2,
689 b: Vector2,
690 c: Vector2,
691 thickness: f32,
692 color: Color,
693 ) {
694 let points = [
695 Vector2::new(a.x, a.y),
696 Vector2::new(b.x, b.y),
697 Vector2::new(c.x, c.y),
698 ];
699
700 let all_vertices = &mut self.vertex_cache;
701 let all_indices = &mut self.index_cache;
702
703 vec_clear(all_vertices);
704 vec_clear(all_indices);
705
706 let mut index_offset = 0u16;
707 for i in 0..3 {
708 let a = points[i];
709 let b = points[(i + 1) % 3];
710
711 let line = Self::construct_line(a, b, thickness);
712 if line.is_none() {
713 continue;
714 }
715
716 let (vertices, mut indices) = line.unwrap();
717 let vertices = vertices
718 .iter()
719 .map(|v| Vertex::new(Vector3::new(v.x, v.y, 0.0), color, Vector2::ZERO))
720 .collect::<Vec<_>>();
721
722 indices.iter_mut().for_each(|idx| *idx += index_offset);
723 index_offset += vertices.len() as u16;
724
725 all_vertices.extend(vertices);
726 all_indices.extend(indices);
727 }
728
729 if all_indices.is_empty() {
730 return;
731 }
732
733 self.inner.borrow_mut()
734 .push_geometry(&all_vertices, &all_indices, false);
735 }
736
737 pub fn draw_triangle_filled(&mut self, a: Vector2, b: Vector2, c: Vector2, color: Color) {
739 let vertices = [
740 Vertex::new(Vector3::new(a.x, a.y, 0.0), color, Vector2::ZERO),
741 Vertex::new(Vector3::new(b.x, b.y, 0.0), color, Vector2::ZERO),
742 Vertex::new(Vector3::new(c.x, c.y, 0.0), color, Vector2::ZERO),
743 ];
744
745 let indices = [0, 1, 2];
746
747 self.inner.borrow_mut()
748 .push_geometry(&vertices, &indices, false);
749 }
750
751 pub fn draw_triangle_filled_colors(
752 &mut self,
753 a: Vector2,
754 b: Vector2,
755 c: Vector2,
756 color_a: Color,
757 color_b: Color,
758 color_c: Color,
759 ) {
760 let vertices = [
761 Vertex::new(Vector3::new(a.x, a.y, 0.0), color_a, Vector2::ZERO),
762 Vertex::new(Vector3::new(b.x, b.y, 0.0), color_b, Vector2::ZERO),
763 Vertex::new(Vector3::new(c.x, c.y, 0.0), color_c, Vector2::ZERO),
764 ];
765
766 let indices = [0, 1, 2];
767
768 self.inner.borrow_mut()
769 .push_geometry(&vertices, &indices, false);
770 }
771
772 pub fn draw_circle(
774 &mut self,
775 center: Vector2,
776 radius: f32,
777 segments: u32,
778 thickness: f32,
779 color: Color,
780 ) {
781 if segments < 3 {
782 return;
783 }
784
785 let angle_step = std::f32::consts::PI * 2.0 / segments as f32;
786
787 let mut vertices = Vec::with_capacity(segments as usize * 2);
788 let mut indices = Vec::with_capacity(segments as usize * 6);
789
790 for i in 0..segments {
791 let angle_a = i as f32 * angle_step;
792 let angle_b = (i + 1) as f32 * angle_step;
793
794 let a = Vector2::new(
795 center.x + radius * angle_a.cos(),
796 center.y + radius * angle_a.sin(),
797 );
798 let b = Vector2::new(
799 center.x + radius * angle_b.cos(),
800 center.y + radius * angle_b.sin(),
801 );
802
803 let line = Self::construct_line(a, b, thickness);
804 if line.is_none() {
805 continue;
806 }
807
808 let (line_vertices, line_indices) = line.unwrap();
809
810 let base_index = vertices.len() as u16;
811 let line_vertices: Vec<Vertex> = line_vertices
812 .iter()
813 .map(|v| Vertex::new(Vector3::new(v.x, v.y, 0.0), color, Vector2::ZERO))
814 .collect();
815
816 vertices.extend(line_vertices);
817 indices.extend(line_indices.into_iter().map(|i| i + base_index));
818 }
819
820 if indices.is_empty() {
821 return;
822 }
823
824 self.inner.borrow_mut()
825 .push_geometry(&vertices, &indices, false);
826 }
827
828 pub fn draw_circle_filled(
829 &mut self,
830 center: Vector2,
831 radius: f32,
832 segments: u32,
833 color: Color,
834 ) {
835 if segments < 3 {
836 return;
837 }
838
839 let angle_step = std::f32::consts::PI * 2.0 / segments as f32;
840 let vertices = &mut self.vertex_cache;
841 let indices = &mut self.index_cache;
842
843 vec_clear(vertices);
844 vec_clear(indices);
845
846 vertices.push(Vertex::new(
847 Vector3::new(center.x, center.y, 0.0),
848 color,
849 Vector2::ZERO,
850 ));
851
852 for i in 0..segments {
853 let angle = angle_step * i as f32;
854 let x = center.x + radius * angle.cos();
855 let y = center.y + radius * angle.sin();
856
857 vertices.push(Vertex::new(Vector3::new(x, y, 0.0), color, Vector2::ZERO));
858 indices.push(i as u16 + 1);
859 }
860
861 triangle_fan_to_list_indices_ref(&mut *indices);
862
863 if indices.is_empty() {
864 return;
865 }
866
867 self.inner.borrow_mut()
868 .push_geometry(&vertices, &indices, false);
869 }
870
871 pub fn draw_rect_image(&mut self, pos: Vector2, size: Vector2, color: Color) {
872 let mut inner = self.inner.borrow_mut();
873 let uv: RectF = inner.get_absolute_uv();
874
875 let vertices = [
876 Vertex::new(
877 Vector3::new(pos.x, pos.y, 0.0),
878 color,
879 Vector2::new(uv.x, uv.y),
880 ),
881 Vertex::new(
882 Vector3::new(pos.x + size.x, pos.y, 0.0),
883 color,
884 Vector2::new(uv.w, uv.y),
885 ),
886 Vertex::new(
887 Vector3::new(pos.x + size.x, pos.y + size.y, 0.0),
888 color,
889 Vector2::new(uv.w, uv.h),
890 ),
891 Vertex::new(
892 Vector3::new(pos.x, pos.y + size.y, 0.0),
893 color,
894 Vector2::new(uv.x, uv.h),
895 ),
896 ];
897
898 let indices = [0, 1, 2, 0, 2, 3];
899 inner.push_geometry(&vertices, &indices, true);
900 }
901
902 pub fn draw_rect_image_colors(
903 &mut self,
904 pos: Vector2,
905 size: Vector2,
906 color_tl: Color,
907 color_tr: Color,
908 color_br: Color,
909 color_bl: Color,
910 ) {
911 let mut inner = self.inner.borrow_mut();
912 let uv = inner.get_absolute_uv();
913
914 let vertices = [
915 Vertex::new(
916 Vector3::new(pos.x, pos.y, 0.0),
917 color_tl,
918 Vector2::new(uv.x, uv.y),
919 ),
920 Vertex::new(
921 Vector3::new(pos.x + size.x, pos.y, 0.0),
922 color_tr,
923 Vector2::new(uv.w, uv.y),
924 ),
925 Vertex::new(
926 Vector3::new(pos.x + size.x, pos.y + size.y, 0.0),
927 color_br,
928 Vector2::new(uv.w, uv.h),
929 ),
930 Vertex::new(
931 Vector3::new(pos.x, pos.y + size.y, 0.0),
932 color_bl,
933 Vector2::new(uv.x, uv.h),
934 ),
935 ];
936
937 let indices = [0, 1, 2, 0, 2, 3];
938 inner.push_geometry(&vertices, &indices, true);
939 }
940
941 pub fn draw_triangle_image(&mut self, a: Vector2, b: Vector2, c: Vector2, color: Color) {
942 let mut inner = self.inner.borrow_mut();
943 let uv = inner.get_absolute_uv();
944
945 let vertices = [
946 Vertex::new(Vector3::new(a.x, a.y, 0.0), color, Vector2::new(uv.x, uv.y)),
947 Vertex::new(Vector3::new(b.x, b.y, 0.0), color, Vector2::new(uv.w, uv.y)),
948 Vertex::new(
949 Vector3::new(c.x, c.y, 0.0),
950 color,
951 Vector2::new(uv.w * 0.5, uv.h),
952 ),
953 ];
954
955 let indices = [0, 1, 2];
956 inner.push_geometry(&vertices, &indices, true);
957 }
958
959 pub fn draw_triangle_image_colors(
960 &mut self,
961 a: Vector2,
962 b: Vector2,
963 c: Vector2,
964 color_a: Color,
965 color_b: Color,
966 color_c: Color,
967 ) {
968 let mut inner = self.inner.borrow_mut();
969 let uv = inner.get_absolute_uv();
970
971 let vertices = [
972 Vertex::new(Vector3::new(a.x, a.y, 0.0), color_a, Vector2::new(uv.x, uv.y)),
973 Vertex::new(Vector3::new(b.x, b.y, 0.0), color_b, Vector2::new(uv.w, uv.y)),
974 Vertex::new(Vector3::new(c.x, c.y, 0.0), color_c, Vector2::new(uv.w * 0.5, uv.h)),
975 ];
976
977 let indices = [0, 1, 2];
978 inner.push_geometry(&vertices, &indices, true);
979 }
980
981 pub fn draw_circle_image(&mut self, center: Vector2, radius: f32, segments: u32, color: Color) {
982 if segments < 3 {
983 return;
984 }
985
986 let mut inner = self.inner.borrow_mut();
987 let uv = inner.get_absolute_uv();
988
989 let angle_step = std::f32::consts::PI * 2.0 / segments as f32;
990 let mut vertices = Vec::with_capacity(segments as usize);
991 let mut indices = Vec::with_capacity(segments as usize * 3);
992
993 for i in 0..segments {
994 let angle = angle_step * i as f32;
995 let x = center.x + radius * angle.cos();
996 let y = center.y + radius * angle.sin();
997
998 let u = uv.x + (uv.w - uv.x) * (angle.cos() * 0.5 + 0.5);
999 let v = uv.y + (uv.h - uv.y) * (angle.sin() * 0.5 + 0.5);
1000
1001 vertices.push(Vertex::new(
1002 Vector3::new(x, y, 0.0),
1003 color,
1004 Vector2::new(u, v),
1005 ));
1006
1007 indices.push(i as u16);
1008 }
1009
1010 triangle_fan_to_list_indices_ref(&mut indices);
1011
1012 if indices.is_empty() {
1013 return;
1014 }
1015
1016 inner.push_geometry(&vertices, &indices, true);
1017 }
1018
1019 pub fn set_rotation(&mut self, rotation: f32) {
1020 let mut inner = self.inner.borrow_mut();
1021 inner.rotation = rotation;
1022 }
1023
1024 pub fn get_rotation(&self) -> f32 {
1025 self.inner.borrow().rotation
1026 }
1027
1028 pub fn set_scissor(&mut self, scissor: RectF) {
1029 let mut inner = self.inner.borrow_mut();
1030 inner.scissor = Some(scissor);
1031 }
1032
1033 pub fn set_viewport(&mut self, viewport: RectF) {
1034 let mut inner = self.inner.borrow_mut();
1035 inner.viewport = Some(viewport);
1036 }
1037
1038 pub fn set_texture(&mut self, texture: Option<&Texture>) {
1039 self.set_texture_ex(texture, None);
1040 }
1041
1042 pub fn set_texture_ex(
1043 &mut self,
1044 texture: Option<&Texture>,
1045 sampler: Option<TextureSampler>,
1046 ) {
1047 let mut inner = self.inner.borrow_mut();
1048
1049 match texture {
1050 Some(texture) => {
1051 let texture_ref = texture.inner.borrow();
1052
1053 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
1054 if !texture_ref.usages.contains(TextureUsage::Sampler) {
1055 panic!("Texture must be created with TextureUsage::Sampler");
1056 }
1057
1058 let default_sampler = TextureSampler::DEFAULT;
1059 let sampler = sampler.unwrap_or(default_sampler);
1060
1061 inner.texture = Some((texture.clone(), sampler));
1062 }
1063 None => {
1064 inner.texture = None;
1065 }
1066 }
1067 }
1068
1069 pub fn set_texture_uv(&mut self, texture_uv: Option<RectF>) {
1070 let mut inner = self.inner.borrow_mut();
1071
1072 match texture_uv {
1073 Some(uv) => {
1074 inner.texture_uv = Some(uv);
1075 }
1076 None => {
1077 inner.texture_uv = None;
1078 }
1079 }
1080 }
1081
1082 pub fn set_texture_atlas(&mut self, atlas: Option<(&TextureAtlas, &str)>) {
1083 self.set_texture_atlas_ex(atlas);
1084 }
1085
1086 pub fn set_texture_atlas_ex(
1087 &mut self,
1088 atlas: Option<(&TextureAtlas, &str)>,
1089 ) {
1090 match atlas {
1091 Some((atlas, id)) => {
1092 let tex_coord = atlas.get_id(id);
1093
1094 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
1095 if tex_coord.is_none() {
1096 panic!("Texture atlas does not contain the specified id: {}", id);
1097 }
1098
1099 let (tex_coord, _) = tex_coord.unwrap();
1100 let texture = atlas.get_texture();
1101
1102 let mut inner = self.inner.borrow_mut();
1103
1104 let default_sampler = TextureSampler::DEFAULT;
1105 inner.texture_atlas_uv = Some(tex_coord);
1106 inner.texture = Some((
1107 texture.clone(),
1108 default_sampler,
1109 ));
1110 }
1111 None => {
1112 self.inner.borrow_mut().texture_atlas_uv = None;
1113 return;
1114 }
1115 };
1116 }
1117
1118 pub fn set_shader(&mut self, shader: Option<&GraphicsShader>) {
1119 let mut inner = self.inner.borrow_mut();
1120
1121 match shader {
1122 Some(shader) => {
1123 let shader_ref = shader.inner.borrow();
1124
1125 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
1126 {
1127 let mut fullfiled = false;
1128 for binding in shader_ref.reflection.iter() {
1129 use super::super::shader::types::{ShaderReflect, ShaderBindingType};
1130
1131 let bindings = match binding {
1132 ShaderReflect::Fragment { bindings, .. } => bindings,
1133 ShaderReflect::VertexFragment { bindings, .. } => bindings,
1134 _ => continue,
1135 };
1136
1137 if bindings.iter().any(|b| {
1138 b.group == 0
1139 && b.binding == 0
1140 && matches!(b.ty, ShaderBindingType::Texture(_))
1141 }) && bindings.iter().any(|b| {
1142 b.group == 0
1143 && b.binding == 1
1144 && matches!(b.ty, ShaderBindingType::Sampler(_))
1145 }) {
1146 fullfiled = true;
1147 break;
1148 }
1149 }
1150
1151 if !fullfiled {
1152 panic!(
1153 "Required shader bindings where group 0, binding 0 for texture or group 0, binding 1 are missing for sampler"
1154 );
1155 }
1156 }
1157
1158 inner.shader = Some(shader.clone());
1159 }
1160 None => {
1161 inner.shader = None;
1162 }
1163 }
1164 }
1165
1166 pub(crate) fn end(&mut self) {
1167 let mut inner = self.inner.borrow_mut();
1168
1169 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
1170 if inner.vertices.is_empty() {
1171 crate::dbg_log!(
1172 "DrawingContext::end: No vertices to draw, did you forget to call a drawing function?"
1173 );
1174
1175 return;
1176 }
1177
1178 if let Some(queue) = inner.current_queue.take() {
1179 inner.queue.push(queue);
1180 }
1181
1182 let mut queues = inner.queue.drain(..).collect::<Vec<_>>();
1183 let mut vertices = inner.vertices.drain(..).collect::<Vec<_>>();
1184 let indices = inner.indices.drain(..).collect::<Vec<_>>();
1185
1186 {
1187 let graphics_inner = inner.pass.graphics.borrow();
1188 let drawing = graphics_inner.drawing_state.as_ref().unwrap().borrow();
1189
1190 let swapchain_size = {
1191 let renderpass_inner = inner.pass.inner.borrow_mut();
1192
1193 Vector2::new(
1194 renderpass_inner.surface_size.x as f32,
1195 renderpass_inner.surface_size.y as f32,
1196 )
1197 };
1198
1199 for vertex in vertices.iter_mut() {
1200 vertex.position.x = vertex.position.x / swapchain_size.x * 2.0 - 1.0;
1201 vertex.position.y = 1.0 - (vertex.position.y / swapchain_size.y * 2.0);
1202 }
1203
1204 for queue in queues.iter_mut() {
1205 if queue.texture.is_none() {
1206 let default_texture = drawing
1207 .texture
1208 .clone();
1209
1210 let sampler = TextureSampler::DEFAULT;
1211 queue.texture = Some((default_texture, sampler));
1212 }
1213
1214 if queue.shader.is_none() {
1215 let default_shader = drawing
1216 .shader
1217 .clone();
1218
1219 queue.shader = Some(default_shader);
1220 }
1221 }
1222 };
1223
1224 let (vertex_buffer, index_buffer) = {
1225 let mut graphics_inner = inner.pass.graphics.borrow_mut();
1226
1227 let vertex_buffer = graphics_inner
1228 .create_staging_buffer(bytemuck::cast_slice(&vertices), wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST);
1229
1230 let index_buffer = graphics_inner
1231 .create_staging_buffer(bytemuck::cast_slice(&indices), wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST);
1232
1233 (vertex_buffer, index_buffer)
1234 };
1235
1236 for queue in queues {
1237 let pass = &mut inner.pass;
1238
1239 if let Some(mut pass_inner) = pass.inner.try_borrow_mut() {
1240 for (i, blend_state) in queue.blend_states.iter().enumerate() {
1241 if i >= pass_inner.render_targets.len() {
1242 #[cfg(any(debug_assertions, feature = "enable-release-validation"))]
1243 {
1244 crate::dbg_log!("DrawingContext::end: Blend state index {} out of bounds for render_targets", i);
1245 }
1246 continue;
1247 }
1248
1249 let attachment = &mut pass_inner.render_targets[i];
1250 attachment.blend = blend_state.0.clone();
1251 attachment.write_mask = blend_state.1.clone();
1252 }
1253 }
1254
1255 pass.set_scissor(queue.scissors);
1256 pass.set_viewport(queue.viewport, 0.0, 1.0);
1257
1258 let (texture, sampler) = queue.texture.as_ref().unwrap();
1259
1260 pass.set_shader(queue.shader.as_ref());
1261 pass
1262 .set_gpu_buffer_wgpu(Some(vertex_buffer.clone()), Some(index_buffer.clone()));
1263
1264 pass.set_attachment_texture(0, 0, Some(&texture));
1265 pass.set_attachment_sampler(0, 1, Some(sampler));
1266
1267 pass
1268 .draw_indexed(queue.start_index..(queue.start_index + queue.count), queue.start_vertex as i32, 1);
1269 }
1270 }
1271}
1272
1273impl Drop for DrawingContext {
1274 fn drop(&mut self) {
1275 if std::thread::panicking() {
1276 return;
1277 }
1278
1279 self.end();
1280 }
1281}
1282
1283thread_local! {
1285 static INDICES_VEC: RefCell<Vec<u16>> = RefCell::new(Vec::new());
1286}
1287
1288fn triangle_fan_to_list_indices_ref(param: &mut Vec<u16>) {
1291 if param.len() < 3 {
1292 return;
1293 }
1294
1295 INDICES_VEC.with(|vec| {
1296 let mut vec = vec.borrow_mut();
1297
1298 vec_clear(&mut vec);
1299 vec.resize((param.len() - 2) * 3, 0);
1300
1301 for i in 1..(param.len() - 1) {
1302 vec[(i - 1) * 3] = param[0];
1303 vec[(i - 1) * 3 + 1] = param[i];
1304 vec[(i - 1) * 3 + 2] = param[i + 1];
1305 }
1306
1307 vec_clear(param);
1308 param.extend_from_slice(&vec);
1309 });
1310}
1311
1312fn vec_clear<T>(vec: &mut Vec<T>) {
1314 unsafe {
1317 assert!(
1318 std::mem::needs_drop::<T>() == false,
1319 "Cannot clear vector of type that needs drop"
1320 );
1321
1322 vec.set_len(0);
1323 }
1324}