unity_asset_decode/sprite/
mod.rs1pub mod parser;
36pub mod processor;
37pub mod types;
38
39pub use parser::SpriteParser;
41pub use processor::{SpriteProcessor, SpriteStats};
42pub use types::{
43 Sprite,
45 SpriteAtlas,
46 SpriteBorder,
47 SpriteConfig,
49 SpriteInfo,
50 SpriteOffset,
51 SpritePivot,
52 SpriteRect,
53 SpriteRenderData,
54 SpriteResult,
55 SpriteSettings,
56};
57
58pub struct SpriteManager {
63 processor: SpriteProcessor,
64}
65
66impl SpriteManager {
67 pub fn new(version: crate::unity_version::UnityVersion) -> Self {
69 Self {
70 processor: SpriteProcessor::new(version),
71 }
72 }
73
74 pub fn with_config(version: crate::unity_version::UnityVersion, config: SpriteConfig) -> Self {
76 Self {
77 processor: SpriteProcessor::with_config(version, config),
78 }
79 }
80
81 pub fn process_sprite(
83 &self,
84 object: &crate::object::UnityObject,
85 ) -> crate::error::Result<SpriteResult> {
86 self.processor.parse_sprite(object)
87 }
88
89 pub fn process_sprite_with_texture(
91 &self,
92 sprite_object: &crate::object::UnityObject,
93 texture: &crate::texture::Texture2D,
94 ) -> crate::error::Result<SpriteResult> {
95 self.processor
96 .process_sprite_with_texture(sprite_object, texture)
97 }
98
99 pub fn process_sprite_atlas(
101 &self,
102 sprites: &[&crate::object::UnityObject],
103 ) -> crate::error::Result<SpriteAtlas> {
104 self.processor.process_sprite_atlas(sprites)
105 }
106
107 pub fn get_statistics(&self, sprites: &[&Sprite]) -> SpriteStats {
109 self.processor.get_sprite_stats(sprites)
110 }
111
112 pub fn validate_sprite(&self, sprite: &Sprite) -> crate::error::Result<()> {
114 self.processor.validate_sprite(sprite)
115 }
116
117 pub fn get_supported_features(&self) -> Vec<&'static str> {
119 self.processor.get_supported_features()
120 }
121
122 pub fn is_feature_supported(&self, feature: &str) -> bool {
124 self.processor.is_feature_supported(feature)
125 }
126
127 pub fn config(&self) -> &SpriteConfig {
129 self.processor.config()
130 }
131
132 pub fn set_config(&mut self, config: SpriteConfig) {
134 self.processor.set_config(config);
135 }
136
137 pub fn version(&self) -> &crate::unity_version::UnityVersion {
139 self.processor.version()
140 }
141
142 pub fn set_version(&mut self, version: crate::unity_version::UnityVersion) {
144 self.processor.set_version(version);
145 }
146}
147
148impl Default for SpriteManager {
149 fn default() -> Self {
150 Self::new(crate::unity_version::UnityVersion::default())
151 }
152}
153
154pub fn create_manager(version: crate::unity_version::UnityVersion) -> SpriteManager {
157 SpriteManager::new(version)
158}
159
160pub fn create_performance_manager(version: crate::unity_version::UnityVersion) -> SpriteManager {
162 let config = SpriteConfig {
163 extract_images: false,
164 process_atlas: false,
165 max_sprite_size: Some((1024, 1024)),
166 apply_transformations: false,
167 };
168 SpriteManager::with_config(version, config)
169}
170
171pub fn create_full_manager(version: crate::unity_version::UnityVersion) -> SpriteManager {
173 let config = SpriteConfig {
174 extract_images: true,
175 process_atlas: true,
176 max_sprite_size: None,
177 apply_transformations: true,
178 };
179 SpriteManager::with_config(version, config)
180}
181
182pub fn parse_sprite(
184 object: &crate::object::UnityObject,
185 version: &crate::unity_version::UnityVersion,
186) -> crate::error::Result<Sprite> {
187 let parser = SpriteParser::new(version.clone());
188 let result = parser.parse_from_unity_object(object)?;
189 Ok(result.sprite)
190}
191
192pub fn extract_sprite_image(
194 sprite: &Sprite,
195 texture: &crate::texture::Texture2D,
196 version: &crate::unity_version::UnityVersion,
197) -> crate::error::Result<Vec<u8>> {
198 let processor = SpriteProcessor::new(version.clone());
199 processor.extract_sprite_image(sprite, texture)
200}
201
202pub fn validate_sprite(sprite: &Sprite) -> crate::error::Result<()> {
204 let processor = SpriteProcessor::default();
205 processor.validate_sprite(sprite)
206}
207
208pub fn get_sprite_area(sprite: &Sprite) -> f32 {
210 sprite.get_area()
211}
212
213pub fn is_nine_slice_sprite(sprite: &Sprite) -> bool {
215 sprite.has_border()
216}
217
218pub fn is_atlas_sprite(sprite: &Sprite) -> bool {
220 sprite.is_atlas_sprite()
221}
222
223pub fn get_sprite_aspect_ratio(sprite: &Sprite) -> f32 {
225 sprite.get_aspect_ratio()
226}
227
228pub fn is_sprite_feature_supported(
230 version: &crate::unity_version::UnityVersion,
231 feature: &str,
232) -> bool {
233 match feature {
234 "basic_sprite" | "rect" | "pivot" => true,
235 "border" | "pixels_to_units" => version.major >= 5,
236 "polygon_sprites" | "sprite_atlas" => version.major >= 2017,
237 "sprite_mesh" | "sprite_physics" => version.major >= 2018,
238 _ => false,
239 }
240}
241
242pub fn get_recommended_config(version: &crate::unity_version::UnityVersion) -> SpriteConfig {
244 if version.major >= 2018 {
245 SpriteConfig {
247 extract_images: true,
248 process_atlas: true,
249 max_sprite_size: None,
250 apply_transformations: true,
251 }
252 } else if version.major >= 2017 {
253 SpriteConfig {
255 extract_images: true,
256 process_atlas: true,
257 max_sprite_size: Some((2048, 2048)),
258 apply_transformations: true,
259 }
260 } else if version.major >= 5 {
261 SpriteConfig {
263 extract_images: true,
264 process_atlas: false,
265 max_sprite_size: Some((1024, 1024)),
266 apply_transformations: false,
267 }
268 } else {
269 SpriteConfig {
271 extract_images: false,
272 process_atlas: false,
273 max_sprite_size: Some((512, 512)),
274 apply_transformations: false,
275 }
276 }
277}
278
279#[derive(Debug, Clone)]
281pub struct ProcessingOptions {
282 pub parallel_processing: bool,
283 pub cache_results: bool,
284 pub validate_sprites: bool,
285 pub generate_thumbnails: bool,
286}
287
288impl Default for ProcessingOptions {
289 fn default() -> Self {
290 Self {
291 parallel_processing: false,
292 cache_results: true,
293 validate_sprites: true,
294 generate_thumbnails: false,
295 }
296 }
297}
298
299#[cfg(test)]
300mod tests {
301 use super::*;
302
303 #[test]
304 fn test_manager_creation() {
305 let version = crate::unity_version::UnityVersion::default();
306 let manager = create_manager(version);
307 assert!(manager.get_supported_features().contains(&"basic_sprite"));
308 }
309
310 #[test]
311 fn test_performance_manager() {
312 let version = crate::unity_version::UnityVersion::default();
313 let manager = create_performance_manager(version);
314 assert!(!manager.config().extract_images);
315 assert!(!manager.config().process_atlas);
316 }
317
318 #[test]
319 fn test_full_manager() {
320 let version = crate::unity_version::UnityVersion::default();
321 let manager = create_full_manager(version);
322 assert!(manager.config().extract_images);
323 assert!(manager.config().process_atlas);
324 }
325
326 #[test]
327 fn test_feature_support() {
328 let version_2020 =
329 crate::unity_version::UnityVersion::parse_version("2020.3.12f1").unwrap();
330 assert!(is_sprite_feature_supported(&version_2020, "basic_sprite"));
331 assert!(is_sprite_feature_supported(
332 &version_2020,
333 "polygon_sprites"
334 ));
335 assert!(is_sprite_feature_supported(&version_2020, "sprite_mesh"));
336
337 let version_2017 =
338 crate::unity_version::UnityVersion::parse_version("2017.4.40f1").unwrap();
339 assert!(is_sprite_feature_supported(&version_2017, "sprite_atlas"));
340 assert!(!is_sprite_feature_supported(&version_2017, "sprite_mesh"));
341 }
342
343 #[test]
344 fn test_recommended_config() {
345 let version_2020 =
346 crate::unity_version::UnityVersion::parse_version("2020.3.12f1").unwrap();
347 let config = get_recommended_config(&version_2020);
348 assert!(config.extract_images);
349 assert!(config.process_atlas);
350 assert!(config.apply_transformations);
351
352 let version_5 = crate::unity_version::UnityVersion::parse_version("5.6.7f1").unwrap();
353 let config = get_recommended_config(&version_5);
354 assert!(config.extract_images);
355 assert!(!config.process_atlas);
356 }
357}