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