1use crate::{
2 context::DrawContext,
3 sprite::SpriteTexture,
4 utils::{TextureRef, Vertex},
5};
6use spitfire_glow::{
7 graphics::{Graphics, Surface},
8 renderer::{GlowTextureFiltering, GlowTextureFormat},
9};
10use std::borrow::Cow;
11
12pub struct Canvas {
13 surface: Surface,
14}
15
16impl Canvas {
17 pub fn simple(
18 width: u32,
19 height: u32,
20 format: GlowTextureFormat,
21 graphics: &Graphics<Vertex>,
22 ) -> Result<Self, String> {
23 Ok(Self {
24 surface: graphics.surface(vec![graphics
25 .texture(width, height, 1, format, None)?
26 .into()])?,
27 })
28 }
29
30 pub fn from_surface(surface: Surface) -> Self {
31 Self { surface }
32 }
33
34 pub fn from_screen(
35 texture_formats: Vec<GlowTextureFormat>,
36 graphics: &Graphics<Vertex>,
37 ) -> Result<Self, String> {
38 let width = graphics.main_camera.screen_size.x as _;
39 let height = graphics.main_camera.screen_size.y as _;
40 Ok(Self {
41 surface: graphics.surface(
42 texture_formats
43 .into_iter()
44 .filter_map(|format| {
45 graphics
46 .texture(width, height, 1, format, None)
47 .ok()
48 .map(|texture| texture.into())
49 })
50 .collect(),
51 )?,
52 })
53 }
54
55 pub fn color(mut self, color: [f32; 4]) -> Self {
56 self.surface.set_color(color);
57 self
58 }
59
60 pub fn match_to_screen(&mut self, graphics: &Graphics<Vertex>) -> Result<(), String> {
61 let width = graphics.main_camera.screen_size.x as _;
62 let height = graphics.main_camera.screen_size.y as _;
63 if self.surface.width() != width || self.surface.height() != height {
64 self.surface = graphics.surface(
65 self.surface
66 .attachments()
67 .iter()
68 .filter_map(|attachment| {
69 graphics
70 .texture(width, height, 1, attachment.texture.format(), None)
71 .ok()
72 .map(|texture| texture.into())
73 })
74 .collect(),
75 )?;
76 }
77 Ok(())
78 }
79
80 pub fn activate(
81 &self,
82 context: &mut DrawContext,
83 graphics: &mut Graphics<Vertex>,
84 clear: bool,
85 ) {
86 context.end_frame();
87 let _ = graphics.draw();
88 let _ = graphics.push_surface(self.surface.clone());
89 let _ = graphics.prepare_frame(clear);
90 context.begin_frame(graphics);
91 }
92
93 pub fn deactivate(context: &mut DrawContext, graphics: &mut Graphics<Vertex>) {
94 context.end_frame();
95 let _ = graphics.draw();
96 let _ = graphics.pop_surface();
97 let _ = graphics.prepare_frame(false);
98 context.begin_frame(graphics);
99 }
100
101 pub fn with<R>(
102 &self,
103 context: &mut DrawContext,
104 graphics: &mut Graphics<Vertex>,
105 clear: bool,
106 mut f: impl FnMut(&mut DrawContext, &mut Graphics<Vertex>) -> R,
107 ) -> R {
108 self.activate(context, graphics, clear);
109 let result = f(context, graphics);
110 Self::deactivate(context, graphics);
111 result
112 }
113
114 pub fn surface(&self) -> &Surface {
115 &self.surface
116 }
117
118 pub fn surface_mut(&mut self) -> &mut Surface {
119 &mut self.surface
120 }
121
122 pub fn sprite_texture(
123 &self,
124 index: usize,
125 sampler: Cow<'static, str>,
126 filtering: GlowTextureFiltering,
127 ) -> Option<SpriteTexture> {
128 Some(SpriteTexture {
129 sampler,
130 texture: TextureRef::object(self.surface.attachments().get(index)?.texture.clone()),
131 filtering,
132 })
133 }
134}