use crate::prelude::*;
pub fn sprite_plugin(_session: &mut Session) {
Sprite::register_schema();
AtlasSprite::register_schema();
}
#[derive(Clone, HasSchema, Debug)]
#[schema(opaque, no_default)]
#[type_data(asset_loader(["png", "jpg", "jpeg"], ImageAssetLoader))]
pub enum Image {
Data(image::DynamicImage),
External(u32),
}
struct ImageAssetLoader;
impl AssetLoader for ImageAssetLoader {
fn load(
&self,
_ctx: AssetLoadCtx,
bytes: &[u8],
) -> futures::future::Boxed<anyhow::Result<SchemaBox>> {
let bytes = bytes.to_vec();
Box::pin(async move {
Ok(SchemaBox::new(Image::Data(image::load_from_memory(
&bytes,
)?)))
})
}
}
#[derive(Clone, HasSchema, Debug, Default)]
#[repr(C)]
#[type_data(metadata_asset("atlas"))]
pub struct Atlas {
pub image: Handle<Image>,
pub tile_size: Vec2,
pub rows: u32,
pub columns: u32,
pub padding: Vec2,
pub offset: Vec2,
pub tile_collision: SMap<String, AtlasCollisionTile>,
}
impl Atlas {
pub fn tile_pos(&self, idx: u32) -> Vec2 {
let row = idx / self.columns;
let col = idx % self.columns;
uvec2(col, row).as_vec2() * self.tile_size
}
pub fn size(&self) -> Vec2 {
uvec2(self.columns, self.rows).as_vec2() * self.tile_size
}
}
#[derive(Copy, Clone, HasSchema, Debug, Default)]
#[repr(C)]
pub struct AtlasCollisionTile {
pub min: Vec2,
pub max: Vec2,
}
impl AtlasCollisionTile {
pub fn clamped_values(&self) -> AtlasCollisionTile {
let zero = Vec2::ZERO;
let one = Vec2::new(1.0, 1.0);
AtlasCollisionTile {
min: self.min.clamp(zero, one),
max: self.max.clamp(zero, one),
}
}
pub fn has_area(&self) -> bool {
let extent = self.max - self.min;
extent.x > 0.0 && extent.y > 0.0
}
}
#[derive(Clone, HasSchema, Debug, Default)]
#[repr(C)]
pub struct Sprite {
pub color: Color,
pub image: Handle<Image>,
pub flip_x: bool,
pub flip_y: bool,
}
#[derive(Debug, Default, Clone, HasSchema)]
#[repr(C)]
pub struct AtlasSprite {
pub color: Color,
pub index: u32,
pub atlas: Handle<Atlas>,
pub flip_x: bool,
pub flip_y: bool,
}
impl AtlasSprite {
pub fn new(atlas: Handle<Atlas>) -> Self {
Self {
atlas,
color: Color::WHITE,
..default()
}
}
}