wcanvas/
ctx.rs

1//! Module defining the manipulation of graphics contexts.
2
3use std::collections::BTreeMap;
4
5use crate::{brush::Brush, canvas::ShaderData, geo::Rect, tex::Texture};
6
7/// Represents a graphics context.
8pub struct GraphicsContext<'a> {
9    pub(crate) render_pass: wgpu::RenderPass<'a>,
10    pub(crate) shader_data: ShaderData,
11    pub(crate) viewport: Rect,
12    pub(crate) bind_group_table: &'a BTreeMap<u64, wgpu::BindGroup>,
13}
14
15impl<'a> GraphicsContext<'a> {
16    /// Set the brush to use for future draw calls.
17    pub fn set_brush(&mut self, brush: &Brush) {
18        self.shader_data.brush = brush.to_shader_data();
19    }
20
21    /// Set the texture to use for future draw calls.
22    pub fn set_texture(&mut self, texture: &Texture, rect: &Rect) {
23        self.shader_data.tex_pos[0] = rect.pos.x as f32 / texture.size.width as f32;
24        self.shader_data.tex_pos[1] = rect.pos.y as f32 / texture.size.height as f32;
25
26        self.shader_data.tex_size[0] = rect.size.width as f32 / texture.size.width as f32;
27        self.shader_data.tex_size[1] = rect.size.height as f32 / texture.size.height as f32;
28
29        self.render_pass.set_bind_group(
30            0,
31            self.bind_group_table
32                .get(&texture.bind_group_index)
33                .unwrap(),
34            &[],
35        );
36    }
37
38    /// Fill in a rectangle with the current brush.
39    pub fn fill_rect(&mut self, rect: &Rect) {
40        let fwidth = self.viewport.size.width as f32;
41        let fheight = self.viewport.size.height as f32;
42
43        let converted_y = self.viewport.size.height as i32 - rect.pos.y - rect.size.height as i32;
44
45        self.shader_data.pos[0] = (2.0 * rect.pos.x as f32 / fwidth) - 1.0;
46        self.shader_data.pos[1] = (2.0 * converted_y as f32 / fheight) - 1.0;
47
48        self.shader_data.size[0] = 2.0 * rect.size.width as f32 / fwidth;
49        self.shader_data.size[1] = 2.0 * rect.size.height as f32 / fheight;
50
51        self.render_pass.set_push_constants(
52            wgpu::ShaderStages::VERTEX,
53            0,
54            self.shader_data.as_bytes(),
55        );
56        self.render_pass.draw(0..6, 0..1);
57    }
58}