use bevy::prelude::{Image, TextureAtlas}; use bevy::render::render_resource::TextureFormat; use bevy::render::texture::TextureFormatPixelInfo; use bevy::sprite::TextureAtlasLayout; use crate::{ get_ldtk_tile_scale, Indexer, LdtkLayer, LdtkLevel, SuppliesImage, SuppliesTextureAtlas, }; pub fn write_layer_to_texture( layer: &LdtkLayer, buffer: &mut [u8], format: &TextureFormat, image: &Image, atlas: &TextureAtlasLayout, ) { if !layer.has_tiles() { return; } let tile_size = get_ldtk_tile_scale(); let layer_indexer = Indexer::new( layer.indexer().width() * tile_size as i64, layer.indexer().height() * tile_size as i64, ); let texture_indexer = Indexer::new(image.size().x, image.size().y); layer.for_each_tile(|x, y, tile| { let part = match atlas.textures.get(tile.tile.t as usize) { Some(rect) => rect, None => return, }; let real_x = x * tile_size as i64; let real_y = y * tile_size as i64; for relative_x in 0..part.width() as usize { for relative_y in 0..part.height() as usize { let tile_image_x = part.min.x as usize + relative_x; let tile_image_y = part.min.y as usize + relative_y; let tile_index = texture_indexer.index(tile_image_x, tile_image_y); let output_x = real_x as usize + relative_x; let output_y = real_y as usize + relative_y; let output_index = layer_indexer.index(output_x, output_y); if let Some(target_pixel) = image.data.chunks_exact(format.pixel_size()).nth(tile_index) { if let Some(map_px) = buffer .chunks_exact_mut(format.pixel_size()) .nth(output_index) { if target_pixel.iter().any(|p| p != &0) { map_px.copy_from_slice(target_pixel); } } }; } } }); } pub fn write_map_to_texture( level: &LdtkLevel, buffer: &mut [u8], format: &TextureFormat, image: &Image, atlas: &TextureAtlasLayout, ) { for layer in level.layers() { write_layer_to_texture(layer, buffer, format, image, atlas); } } pub trait Rasterise { fn write_to_texture( &self, buffer: &mut [u8], format: &TextureFormat, images: &impl SuppliesImage, atlas: &impl SuppliesTextureAtlas, ); } impl Rasterise for LdtkLevel { fn write_to_texture( &self, buffer: &mut [u8], format: &TextureFormat, images: &impl SuppliesImage, atlas: &impl SuppliesTextureAtlas, ) { for layer in self.layers() { layer.write_to_texture(buffer, format, images, atlas); } } } impl LdtkLevel { pub fn write_filtered_to_texture( &self, buffer: &mut [u8], format: &TextureFormat, images: &impl SuppliesImage, atlas: &impl SuppliesTextureAtlas, predicate: impl Fn(&LdtkLayer) -> bool, ) { for layer in self.layers() { if predicate(layer) { layer.write_to_texture(buffer, format, images, atlas); } } } } impl Rasterise for LdtkLayer { fn write_to_texture( &self, buffer: &mut [u8], format: &TextureFormat, images: &impl SuppliesImage, atlas: &impl SuppliesTextureAtlas, ) { if let Some(tileset_name) = self.infer_tileset_name() { let maybe_atlas = atlas .get_atlas_handle(&tileset_name) .and_then(|hn| atlas.get_atlas(hn)); let maybe_image = images .get_image_handle(&tileset_name) .and_then(|hn| images.get_image(hn)); if let Some((atlas, image)) = maybe_atlas.zip(maybe_image) { write_layer_to_texture(self, buffer, format, image, atlas); } } } }