use crate::core::Entity;
use crate::components::{Transform, Sprite};
use crate::runtime::Camera;
use super::super::resources::Vertex;
use super::transform::{CoordinateTransform, Transform2D};
pub struct SpriteRenderData {
pub vertices: [Vertex; 4],
pub indices: [u16; 6],
pub texture_path: String,
}
pub struct SpriteBatch {
sprites: Vec<SpriteRenderData>,
coord_transform: CoordinateTransform,
}
impl SpriteBatch {
pub fn new(screen_width: f32, screen_height: f32) -> Self {
Self {
sprites: Vec::new(),
coord_transform: CoordinateTransform::new(screen_width, screen_height),
}
}
pub fn begin_frame(&mut self) {
self.sprites.clear();
}
pub fn collect_sprites(&mut self, entities: &[Entity], camera: &Camera) {
for entity in entities {
if let (Some(transform), Some(sprite)) = (
entity.get_component::<Transform>(),
entity.get_component::<Sprite>()
) {
if sprite.is_visible() {
let view_position = camera.world_to_view(transform.position);
let mut view_transform = transform.clone();
view_transform.position = view_position;
let vertices = Transform2D::calculate_sprite_corners(
&view_transform,
sprite,
&self.coord_transform
);
let base_index = (self.sprites.len() * 4) as u16;
let indices = [
base_index, base_index + 1, base_index + 2,
base_index + 2, base_index + 3, base_index
];
let texture_path = sprite.texture_path.clone();
self.sprites.push(SpriteRenderData {
vertices,
indices,
texture_path,
});
}
}
}
}
pub fn sprites(&self) -> &[SpriteRenderData] {
&self.sprites
}
pub fn is_empty(&self) -> bool {
self.sprites.is_empty()
}
pub fn sprite_count(&self) -> usize {
self.sprites.len()
}
pub fn vertices(&self) -> Vec<Vertex> {
self.sprites
.iter()
.flat_map(|s| s.vertices.iter().copied())
.collect()
}
pub fn indices(&self) -> Vec<u16> {
self.sprites
.iter()
.flat_map(|s| s.indices.iter().copied())
.collect()
}
}