spitfire-draw 0.36.14

Drawing helper module for Spitfire toolset
Documentation
use crate::{
    context::DrawContext,
    sprite::SpriteTexture,
    utils::{TextureRef, Vertex},
};
use spitfire_glow::{
    graphics::{Graphics, Surface},
    renderer::{GlowTextureFiltering, GlowTextureFormat},
};
use std::borrow::Cow;

pub struct Canvas {
    surface: Surface,
}

impl Canvas {
    pub fn simple(
        width: u32,
        height: u32,
        format: GlowTextureFormat,
        graphics: &Graphics<Vertex>,
    ) -> Result<Self, String> {
        Ok(Self {
            surface: graphics.surface(vec![
                graphics.texture(width, height, 1, format, None)?.into(),
            ])?,
        })
    }

    pub fn from_surface(surface: Surface) -> Self {
        Self { surface }
    }

    pub fn from_screen(
        texture_formats: Vec<GlowTextureFormat>,
        graphics: &Graphics<Vertex>,
    ) -> Result<Self, String> {
        let width = graphics.state.main_camera.screen_size.x as _;
        let height = graphics.state.main_camera.screen_size.y as _;
        Ok(Self {
            surface: graphics.surface(
                texture_formats
                    .into_iter()
                    .filter_map(|format| {
                        graphics
                            .texture(width, height, 1, format, None)
                            .ok()
                            .map(|texture| texture.into())
                    })
                    .collect(),
            )?,
        })
    }

    pub fn color(mut self, color: [f32; 4]) -> Self {
        self.surface.set_color(color);
        self
    }

    pub fn match_to_screen(&mut self, graphics: &Graphics<Vertex>) -> Result<(), String> {
        let width = graphics.state.main_camera.screen_size.x as _;
        let height = graphics.state.main_camera.screen_size.y as _;
        self.match_to_size(graphics, width, height)
    }

    pub fn match_to_size(
        &mut self,
        graphics: &Graphics<Vertex>,
        width: u32,
        height: u32,
    ) -> Result<(), String> {
        if self.surface.width() != width || self.surface.height() != height {
            self.surface = graphics.surface(
                self.surface
                    .attachments()
                    .iter()
                    .filter_map(|attachment| {
                        graphics
                            .texture(width, height, 1, attachment.texture.format(), None)
                            .ok()
                            .map(|texture| texture.into())
                    })
                    .collect(),
            )?;
        }
        Ok(())
    }

    pub fn activate(
        &self,
        context: &mut DrawContext,
        graphics: &mut Graphics<Vertex>,
        clear: bool,
    ) {
        context.end_frame();
        let _ = graphics.draw();
        let _ = graphics.push_surface(self.surface.clone());
        let _ = graphics.prepare_frame(clear);
        context.begin_frame(graphics);
    }

    pub fn deactivate(context: &mut DrawContext, graphics: &mut Graphics<Vertex>) {
        context.end_frame();
        let _ = graphics.draw();
        let _ = graphics.pop_surface();
        let _ = graphics.prepare_frame(false);
        context.begin_frame(graphics);
    }

    pub fn with<R>(
        &self,
        context: &mut DrawContext,
        graphics: &mut Graphics<Vertex>,
        clear: bool,
        mut f: impl FnMut(&mut DrawContext, &mut Graphics<Vertex>) -> R,
    ) -> R {
        self.activate(context, graphics, clear);
        let result = f(context, graphics);
        Self::deactivate(context, graphics);
        result
    }

    pub fn surface(&self) -> &Surface {
        &self.surface
    }

    pub fn surface_mut(&mut self) -> &mut Surface {
        &mut self.surface
    }

    pub fn sprite_texture(
        &self,
        index: usize,
        sampler: Cow<'static, str>,
        filtering: GlowTextureFiltering,
    ) -> Option<SpriteTexture> {
        Some(SpriteTexture {
            sampler,
            texture: TextureRef::object(self.surface.attachments().get(index)?.texture.clone()),
            filtering,
        })
    }
}