use crate::resource::vertex_index::VertexIndex;
use crate::resource::GpuMesh2d;
use glamx::Vec2;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct SpriteSheet {
pub columns: u32,
pub rows: u32,
}
impl SpriteSheet {
pub fn new(columns: u32, rows: u32) -> Self {
assert!(
columns > 0 && rows > 0,
"sprite sheet needs a non-empty grid"
);
SpriteSheet { columns, rows }
}
pub fn len(&self) -> u32 {
self.columns * self.rows
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn frame_uv(&self, index: u32) -> (Vec2, Vec2) {
let index = index % self.len();
let col = index % self.columns;
let row = index / self.columns;
let cell = Vec2::new(1.0 / self.columns as f32, 1.0 / self.rows as f32);
let min = Vec2::new(col as f32, row as f32) * cell;
(min, min + cell)
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Border {
pub left: f32,
pub right: f32,
pub top: f32,
pub bottom: f32,
}
impl Border {
pub fn uniform(inset: f32) -> Self {
Border {
left: inset,
right: inset,
top: inset,
bottom: inset,
}
}
pub fn symmetric(horizontal: f32, vertical: f32) -> Self {
Border {
left: horizontal,
right: horizontal,
top: vertical,
bottom: vertical,
}
}
}
pub(crate) fn nine_slice_mesh(size: Vec2, world: Border, uv: Border) -> GpuMesh2d {
let hx = size.x * 0.5;
let hy = size.y * 0.5;
let xs = [-hx, -hx + world.left, hx - world.right, hx];
let ys = [hy, hy - world.top, -hy + world.bottom, -hy];
let us = [0.0, uv.left, 1.0 - uv.right, 1.0];
let vs = [0.0, uv.top, 1.0 - uv.bottom, 1.0];
let mut coords = Vec::with_capacity(16);
let mut uvs = Vec::with_capacity(16);
for j in 0..4 {
for i in 0..4 {
coords.push(Vec2::new(xs[i], ys[j]));
uvs.push(Vec2::new(us[i], vs[j]));
}
}
let mut faces = Vec::with_capacity(18);
for j in 0..3u32 {
for i in 0..3u32 {
let tl = (j * 4 + i) as VertexIndex;
let tr = tl + 1;
let bl = tl + 4;
let br = bl + 1;
faces.push([tl, bl, br]);
faces.push([tl, br, tr]);
}
}
GpuMesh2d::new(coords, faces, Some(uvs), false)
}