use valo_dl::Image;
use valo_geometry::{Matrix, Rect};
#[derive(Clone)]
pub(super) struct Snapshot {
pub view: wgpu::TextureView,
pub placement: Placement,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub(super) struct Placement {
pub size: [u32; 2],
pub transform: Matrix,
pub placed: bool,
}
impl Snapshot {
pub fn of_image(image: &Image, dst: &Rect, transform: &Matrix) -> Self {
let [width, height] = image.size().map(|size| size as f32);
Self {
view: image.view().clone(),
placement: Placement {
size: image.size(),
transform: transform
.then(&Matrix::translation(dst.x, dst.y))
.then(&Matrix::scale(dst.width / width, dst.height / height)),
placed: false,
},
}
}
pub fn placed_where_drawn(mut self, placed: bool) -> Self {
self.placement.placed = placed;
self
}
}
impl Placement {
pub fn coverage(&self) -> Rect {
let texels = Rect::new(0.0, 0.0, self.size[0] as f32, self.size[1] as f32);
self.transform.map_rect(&texels)
}
pub fn texel_rect(&self, region: &Rect) -> Rect {
self.texel_transform().map_rect(region)
}
pub fn texel_transform(&self) -> Matrix {
self.transform
.invert()
.expect("a snapshot's transform is invertible")
}
pub fn uv_mapping(&self) -> [f32; 4] {
let [a, b, c, d, tx, ty] = self.transform.to_affine();
debug_assert!(b == 0.0 && c == 0.0, "uv mapping of a turned snapshot");
let (w, h) = (self.size[0] as f32, self.size[1] as f32);
[1.0 / (a * w), 1.0 / (d * h), -tx / (a * w), -ty / (d * h)]
}
pub fn region_uv_mapping(&self, region: &Rect) -> [f32; 4] {
let [x, y, z, w] = self.uv_mapping();
[x, y, region.x * x + z, region.y * y + w]
}
}