Modify data structures to include palette data per tile
parent
f7b9216680
commit
ff08ee4e46
|
@ -67,7 +67,7 @@ pub fn run_command() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
Tools::Level { input_file, output_directory, console, tile_size } => {
|
Tools::Level { input_file, output_directory, console, tile_size } => {
|
||||||
let tiled_file = get_tiled_tilemap( &input_file )?;
|
let tiled_file = get_tiled_tilemap( &input_file )?;
|
||||||
print_info( &format!( "{:#?}", tiled_file ) );
|
//print_info( &format!( "{:#?}", tiled_file ) );
|
||||||
print_good( "file opened without errors" );
|
print_good( "file opened without errors" );
|
||||||
print_error( "unimplemented" );
|
print_error( "unimplemented" );
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,14 +10,13 @@ pub struct TiledTilemap {
|
||||||
pub layers: Vec<Layer>,
|
pub layers: Vec<Layer>,
|
||||||
ecs: Vec<ecs::Entity>,
|
ecs: Vec<ecs::Entity>,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub height: usize,
|
pub height: usize
|
||||||
pub tile_width: usize,
|
|
||||||
pub tile_height: usize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TiledTileset {
|
pub struct TiledTileset {
|
||||||
pub image: DynamicImage
|
pub image: DynamicImage,
|
||||||
|
pub palettes: Vec<Option<u8>>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -103,6 +102,42 @@ fn get_layer( layer: Node, map_width: usize, map_height: usize ) -> Result<Optio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_tiles( tileset: Node ) -> Result<TiledTileset, Box<dyn Error>> {
|
||||||
|
// Get the image for the tileset
|
||||||
|
let image = tileset.descendants().find( | node | node.tag_name() == "image".into() ).ok_or( "invalid file: no image object" )?;
|
||||||
|
let image = image::open( image.attribute( "source" ).ok_or( "invalid file: no source attribute on image" )? )?;
|
||||||
|
|
||||||
|
// Image must be a multiple of 8 (--system md)
|
||||||
|
if image.width() % 8 != 0 { return Err( "invalid file: tileset width not multiple of 8" )? }
|
||||||
|
if image.height() % 8 != 0 { return Err( "invalid file: tileset height not multiple of 8" )? }
|
||||||
|
|
||||||
|
let tile_count: usize = tileset.attribute( "tilecount" ).ok_or( "invalid file: no tilecount attribute on tileset" )?.parse()?;
|
||||||
|
let mut palettes: Vec<Option<u8>> = vec![ None; tile_count ];
|
||||||
|
|
||||||
|
let defined_tiles = tileset.descendants().filter( | node | node.tag_name() == "tile".into() );
|
||||||
|
for defined_tile in defined_tiles {
|
||||||
|
let tile_id: usize = defined_tile.attribute( "id" ).ok_or( "invalid file: id attribute not defined on a tile" )?.parse()?;
|
||||||
|
let properties = defined_tile.descendants().find( | node | node.tag_name() == "properties".into() ).ok_or( "invalid file: no properties descendant in tileset" )?;
|
||||||
|
let property = properties.descendants().find( | node | node.tag_name() == "property".into() && node.attribute( "reskit-palette" ).is_some() );
|
||||||
|
if let Some( property ) = property {
|
||||||
|
let property_type = property.attribute( "type" ).unwrap_or( "string" );
|
||||||
|
if property_type == "int" {
|
||||||
|
let palette_value: u8 = property.attribute( "value" ).ok_or( "invalid file: reskit-palette property has no value" )?.parse()?;
|
||||||
|
// --system md
|
||||||
|
if palette_value > 3 {
|
||||||
|
print_warning( &format!( "reskit-palette property on tile {} is not valid palette (0 to 3) - leaving palette unset, this is probably not what you want...", tile_id ) );
|
||||||
|
} else {
|
||||||
|
palettes[ tile_id ] = Some( palette_value );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_warning( &format!( "reskit-palette property on tile {} is not int type - leaving palette unset, this is probably not what you want...", tile_id ) )
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok( TiledTileset { image, palettes } )
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
|
pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
|
||||||
let file = read_to_string( path )?;
|
let file = read_to_string( path )?;
|
||||||
let document = roxmltree::Document::parse( &file )?;
|
let document = roxmltree::Document::parse( &file )?;
|
||||||
|
@ -135,6 +170,14 @@ pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
|
||||||
map.attribute( "tileheight" ).ok_or( "invalid file: no tileheight attribute" )?.parse()?
|
map.attribute( "tileheight" ).ok_or( "invalid file: no tileheight attribute" )?.parse()?
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// --system md is 8x8
|
||||||
|
if tile_width != 8 {
|
||||||
|
return Err( "invalid file: tile width is not 8 for --system md" )?
|
||||||
|
}
|
||||||
|
if tile_height != 8 {
|
||||||
|
return Err( "invalid file: tile height is not 8 for --system md" )?
|
||||||
|
}
|
||||||
|
|
||||||
// Build tileset (current version assumes one tileset per level)
|
// Build tileset (current version assumes one tileset per level)
|
||||||
let tileset = map.descendants().find( | node | node.tag_name() == "tileset".into() ).ok_or( "invalid file: no tileset" )?;
|
let tileset = map.descendants().find( | node | node.tag_name() == "tileset".into() ).ok_or( "invalid file: no tileset" )?;
|
||||||
let tileset_source_path = tileset.attribute( "source" ).ok_or( "invalid file: no tileset source" )?;
|
let tileset_source_path = tileset.attribute( "source" ).ok_or( "invalid file: no tileset source" )?;
|
||||||
|
@ -152,13 +195,7 @@ pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
|
||||||
return Err( "invalid file: referenced tilemap doesn't have same per-tile width and height of parent tilemap" )?
|
return Err( "invalid file: referenced tilemap doesn't have same per-tile width and height of parent tilemap" )?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the image for the tileset
|
let tileset = get_tiles( tileset )?;
|
||||||
let image = tileset.descendants().find( | node | node.tag_name() == "image".into() ).ok_or( "invalid file: no image object" )?;
|
|
||||||
let image = image::open( image.attribute( "source" ).ok_or( "invalid file: no source attribute on image" )? )?;
|
|
||||||
|
|
||||||
// Image must be a multiple of 8 (md system)
|
|
||||||
if image.width() % 8 != 0 { return Err( "invalid file: tileset width not multiple of 8" )? }
|
|
||||||
if image.height() % 8 != 0 { return Err( "invalid file: tileset height not multiple of 8" )? }
|
|
||||||
|
|
||||||
// Get the layers
|
// Get the layers
|
||||||
let layers: Vec<Layer> = map.descendants()
|
let layers: Vec<Layer> = map.descendants()
|
||||||
|
@ -184,13 +221,11 @@ pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
TiledTilemap {
|
TiledTilemap {
|
||||||
tileset: TiledTileset { image },
|
tileset,
|
||||||
layers,
|
layers,
|
||||||
ecs,
|
ecs,
|
||||||
width,
|
width,
|
||||||
height,
|
height
|
||||||
tile_width,
|
|
||||||
tile_height
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,13 +10,13 @@ pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
let mut palette: [u16; 16] = [ 0; 16 ];
|
let mut palette: [u16; 16] = [ 0; 16 ];
|
||||||
let mut all_tiles: Vec<u8> = Vec::new();
|
let mut all_tiles: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
for tile_y in 0..tilemap.tile_height {
|
for tile_y in 0..tilemap.height {
|
||||||
for tile_x in 0..tilemap.tile_width {
|
for tile_x in 0..tilemap.width {
|
||||||
let tile = tilemap.tileset.image.clone().crop(
|
let tile = tilemap.tileset.image.clone().crop(
|
||||||
tile_x as u32,
|
tile_x as u32,
|
||||||
tile_y as u32,
|
tile_y as u32,
|
||||||
tilemap.tile_width as u32,
|
8, // --system md
|
||||||
tilemap.tile_height as u32
|
8 // --system md
|
||||||
);
|
);
|
||||||
|
|
||||||
let tile_bin = image_to_tiles(
|
let tile_bin = image_to_tiles(
|
||||||
|
@ -52,8 +52,8 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>>
|
||||||
let layer_b: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneB, tiles: _ } ) );
|
let layer_b: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneB, tiles: _ } ) );
|
||||||
let layer_a: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneA, tiles: _ } ) );
|
let layer_a: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneA, tiles: _ } ) );
|
||||||
|
|
||||||
let md_height_per_tile = tilemap.tile_height / 8;
|
let md_height_per_tile = 1; // --system md
|
||||||
let md_width_per_tile = tilemap.tile_width / 8;
|
let md_width_per_tile = 1; // --system md
|
||||||
|
|
||||||
// Each entry in a `--system md` tilemap is 16 bits
|
// Each entry in a `--system md` tilemap is 16 bits
|
||||||
let mut nametable: Vec<u16> = vec![ 0; ( tilemap.width * md_width_per_tile ) * ( tilemap.height * md_height_per_tile ) ];
|
let mut nametable: Vec<u16> = vec![ 0; ( tilemap.width * md_width_per_tile ) * ( tilemap.height * md_height_per_tile ) ];
|
||||||
|
|
Loading…
Reference in New Issue