srs2dge_core/packer/texture/
mod.rs1use 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
12pub use map::*;
15
16mod map;
19
20const USAGE: u32 = TextureUsages::TEXTURE_BINDING.bits()
23 | TextureUsages::COPY_SRC.bits()
24 | TextureUsages::COPY_DST.bits();
25
26#[derive(Debug, Clone)]
29pub struct TextureAtlasBuilder {
30 packer: Packer,
31
32 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
46pub trait Reference<T> {
49 fn reference(&self) -> &'_ T;
50}
51
52impl<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 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 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}