Skip to content
Snippets Groups Projects
pregen.rs 2.79 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::prelude::{Image, TextureAtlas};
Louis's avatar
Louis committed
use bevy::render::render_resource::TextureFormat;
use bevy::render::texture::TextureFormatPixelInfo;

use crate::{
	get_ldtk_tile_scale, Indexer, LdtkLayer, LdtkLevel, SuppliesImage, SuppliesTextureAtlas,
};
Louis's avatar
Louis committed

pub fn write_layer_to_texture(
	layer: &LdtkLayer,
	buffer: &mut Vec<u8>,
	format: &TextureFormat,
	image: &Image,
	atlas: &TextureAtlas,
) {
	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 Vec<u8>,
	format: &TextureFormat,
	image: &Image,
	atlas: &TextureAtlas,
) {
	for layer in level.layers() {
		write_layer_to_texture(layer, buffer, format, image, atlas);
	}
}

pub trait Rasterise {
	fn write_to_texture(
		&self,
		buffer: &mut Vec<u8>,
		format: &TextureFormat,
		images: &impl SuppliesImage,
		atlas: &impl SuppliesTextureAtlas,
	);
}

impl Rasterise for LdtkLevel {
	fn write_to_texture(
		&self,
		buffer: &mut Vec<u8>,
		format: &TextureFormat,
		images: &impl SuppliesImage,
		atlas: &impl SuppliesTextureAtlas,
	) {
		for layer in self.layers() {
			layer.write_to_texture(buffer, format, images, atlas);
		}
	}
}
impl Rasterise for LdtkLayer {
	fn write_to_texture(
		&self,
		buffer: &mut Vec<u8>,
		format: &TextureFormat,
		images: &impl SuppliesImage,
		atlas: &impl SuppliesTextureAtlas,
	) {
		if let Some(atlas) = self
			.infer_tileset_name()
			.and_then(|tn| atlas.get_atlas_handle(tn))
			.and_then(|hn| atlas.get_atlas(hn))
		{
			if let Some(image) = images.get_image(&atlas.texture) {
				write_layer_to_texture(self, buffer, format, image, atlas);
			}
		}
	}
}