srs2dge_core/packer/texture/
mod.rs

1use super::{
2    packer2d::Packer,
3    rect::{PositionedRect, Rect},
4};
5use crate::{target::Target, texture::Texture};
6use image::RgbaImage;
7use rapid_qoi::{Colors, Qoi};
8use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
9use std::ops::Deref;
10use wgpu::TextureUsages;
11
12//
13
14pub use map::*;
15
16//
17
18mod map;
19
20//
21
22const USAGE: u32 = TextureUsages::TEXTURE_BINDING.bits()
23    | TextureUsages::COPY_SRC.bits()
24    | TextureUsages::COPY_DST.bits();
25
26//
27
28#[derive(Debug, Clone)]
29pub struct TextureAtlasBuilder {
30    packer: Packer,
31
32    // side length limit
33    limit: u16,
34}
35
36#[derive(Debug)]
37pub struct TextureAtlas {
38    texture: Texture<USAGE>,
39}
40
41#[derive(Debug, Clone)]
42pub struct TextureAtlasFile {
43    image: RgbaImage,
44}
45
46//
47
48pub trait Reference<T> {
49    fn reference(&self) -> &'_ T;
50}
51
52//
53
54impl<T> Reference<T> for T {
55    fn reference(&self) -> &'_ T {
56        self
57    }
58}
59
60impl<T> Reference<T> for &T {
61    fn reference(&self) -> &'_ T {
62        *self
63    }
64}
65
66impl Default for TextureAtlasBuilder {
67    fn default() -> Self {
68        Self {
69            packer: Default::default(),
70            limit: u16::MAX,
71        }
72    }
73}
74
75impl TextureAtlasBuilder {
76    pub fn new() -> Self {
77        Self::default()
78    }
79
80    /* pub fn new_sized(width: u32, height: u32) -> Self {
81        Self {
82            packer: Packer::new(Rect { width, height }),
83            ..Default::default()
84        }
85    } */
86
87    /// side length limit
88    pub fn with_limit(mut self, limit: u16) -> Self {
89        self.limit = limit;
90        self
91    }
92
93    pub fn push(&mut self, rect: Rect) -> Option<PositionedRect> {
94        self.packer.push_until(rect, self.limit)
95    }
96
97    pub fn build<I, R>(self, target: &Target, iter: I) -> TextureAtlas
98    where
99        R: Reference<RgbaImage>,
100        I: IntoIterator<Item = (R, PositionedRect)>,
101    {
102        let dim = self.packer.area();
103
104        // combine all images into one
105        let mut combined = RgbaImage::new(dim.width, dim.height);
106        for (image, pos) in iter {
107            for (xo, yo, pixel) in image.reference().enumerate_pixels() {
108                combined.put_pixel(pos.x + xo, pos.y + yo, *pixel);
109            }
110        }
111
112        let texture = Texture::new_rgba_with(target, &combined);
113
114        TextureAtlas { texture }
115    }
116}
117
118impl TextureAtlas {
119    pub async fn convert(&self, target: &Target) -> TextureAtlasFile {
120        let image = self.texture.read(target).await.into_rgba8();
121        TextureAtlasFile { image }
122    }
123}
124
125impl Deref for TextureAtlas {
126    type Target = Texture<USAGE>;
127
128    fn deref(&self) -> &Self::Target {
129        &self.texture
130    }
131}
132
133impl TextureAtlasFile {
134    pub fn convert(&self, target: &Target) -> TextureAtlas {
135        let texture = Texture::new_rgba_with(target, &self.image);
136        TextureAtlas { texture }
137    }
138}
139
140impl Serialize for TextureAtlasFile {
141    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
142    where
143        S: Serializer,
144    {
145        let qoi = Qoi {
146            width: self.image.width(),
147            height: self.image.height(),
148            colors: Colors::Rgba,
149        };
150
151        let image = qoi
152            .encode_alloc(self.image.as_raw())
153            .map_err(serde::ser::Error::custom)?;
154
155        serializer.serialize_bytes(&image)
156    }
157}
158
159impl<'de> Deserialize<'de> for TextureAtlasFile {
160    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
161    where
162        D: Deserializer<'de>,
163    {
164        let image = deserializer.deserialize_byte_buf(V)?;
165
166        struct V;
167
168        impl<'de> Visitor<'de> for V {
169            type Value = Vec<u8>;
170
171            fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
172                write!(f, "byte array")
173            }
174
175            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
176            where
177                E: serde::de::Error,
178            {
179                Ok(v.to_owned())
180            }
181
182            fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
183            where
184                E: serde::de::Error,
185            {
186                Ok(v)
187            }
188        }
189
190        let (qoi, image) = Qoi::decode_alloc(&image).map_err(serde::de::Error::custom)?;
191
192        Ok(Self {
193            image: RgbaImage::from_raw(qoi.width, qoi.height, image).unwrap(),
194        })
195    }
196}