use bevy::{asset::AssetLoader, prelude::*};
use serde::{Deserialize, Serialize};
use crate::prelude::*;
#[derive(Debug, Deserialize, Serialize)]
pub struct UVector2 {
pub x: u32,
pub y: u32,
}
impl From<UVector2> for UVec2 {
fn from(value: UVector2) -> Self {
Self::new(value.x, value.y)
}
}
#[derive(Debug, Deserialize, Serialize)]
pub enum AtlasLayoutDefinition {
Grid {
tile_size: UVector2,
columns: u32,
rows: u32,
padding: Option<UVector2>,
offset: Option<UVector2>,
},
}
impl From<AtlasLayoutDefinition> for TextureAtlasLayout {
fn from(value: AtlasLayoutDefinition) -> Self {
match value {
AtlasLayoutDefinition::Grid {
tile_size,
columns,
rows,
padding,
offset,
} => TextureAtlasLayout::from_grid(
tile_size.into(),
columns,
rows,
padding.map(|x| x.into()),
offset.map(|x| x.into()),
),
}
}
}
#[derive(Default)]
pub(crate) struct TextureAtlasLayoutLoader;
impl AssetLoader for TextureAtlasLayoutLoader {
type Asset = TextureAtlasLayout;
type Settings = ();
type Error = Error;
async fn load(
&self,
reader: &mut dyn bevy::asset::io::Reader,
_: &Self::Settings,
_: &mut bevy::asset::LoadContext<'_>,
) -> std::result::Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let def: AtlasLayoutDefinition = ron::de::from_bytes(&bytes)?;
Ok(def.into())
}
fn extensions(&self) -> &[&str] {
&["atlas_layout.ron"]
}
}
#[cfg(test)]
mod tests {
use super::*;
use bevy::asset::LoadState;
use std::time::Duration;
fn is_loading(load_state: LoadState) -> bool {
matches!(load_state, LoadState::Loading)
}
#[test]
fn test_atlas_layout_asset_loading() {
let mut app = App::new();
app.add_plugins((MinimalPlugins, AssetPlugin::default()));
app.init_asset::<TextureAtlasLayout>();
app.init_asset_loader::<TextureAtlasLayoutLoader>();
let handle: Handle<TextureAtlasLayout> = app
.world()
.resource::<AssetServer>()
.load("atlas_layout.ron");
app.update();
while is_loading(
app.world()
.resource::<AssetServer>()
.get_load_state(&handle)
.unwrap(),
) {
app.update();
std::thread::sleep(Duration::from_secs(1));
}
let texture_atlas = app
.world()
.resource::<Assets<TextureAtlasLayout>>()
.get(&handle)
.unwrap();
assert_eq!(texture_atlas.size, UVec2::new(192, 297));
assert_eq!(
texture_atlas.textures,
vec![
URect::new(0, 0, 96, 99),
URect::new(96, 0, 192, 99),
URect::new(0, 99, 96, 198),
URect::new(96, 99, 192, 198),
URect::new(0, 198, 96, 297),
URect::new(96, 198, 192, 297),
]
);
}
}