diff --git a/src/reskit/cli/evaluator.rs b/src/reskit/cli/evaluator.rs index 2d1a854..66d6654 100644 --- a/src/reskit/cli/evaluator.rs +++ b/src/reskit/cli/evaluator.rs @@ -67,7 +67,7 @@ pub fn run_command() -> Result<(), Box> { } Tools::Level { input_file, output_directory, console, tile_size } => { 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_error( "unimplemented" ); } diff --git a/src/reskit/level/converter.rs b/src/reskit/level/converter.rs index 30a34ea..b7e2809 100644 --- a/src/reskit/level/converter.rs +++ b/src/reskit/level/converter.rs @@ -10,14 +10,13 @@ pub struct TiledTilemap { pub layers: Vec, ecs: Vec, pub width: usize, - pub height: usize, - pub tile_width: usize, - pub tile_height: usize + pub height: usize } #[derive(Debug)] pub struct TiledTileset { - pub image: DynamicImage + pub image: DynamicImage, + pub palettes: Vec> } #[derive(Debug)] @@ -103,6 +102,42 @@ fn get_layer( layer: Node, map_width: usize, map_height: usize ) -> Result Result> { + // 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> = 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> { let file = read_to_string( path )?; let document = roxmltree::Document::parse( &file )?; @@ -135,6 +170,14 @@ pub fn get_tiled_tilemap( path: &str ) -> Result> { 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) 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" )?; @@ -152,13 +195,7 @@ pub fn get_tiled_tilemap( path: &str ) -> Result> { 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 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" )? } + let tileset = get_tiles( tileset )?; // Get the layers let layers: Vec = map.descendants() @@ -184,13 +221,11 @@ pub fn get_tiled_tilemap( path: &str ) -> Result> { Ok( TiledTilemap { - tileset: TiledTileset { image }, + tileset, layers, ecs, width, - height, - tile_width, - tile_height + height } ) } else { diff --git a/src/reskit/level/system.rs b/src/reskit/level/system.rs index 8ae8ad0..2023dbc 100644 --- a/src/reskit/level/system.rs +++ b/src/reskit/level/system.rs @@ -10,13 +10,13 @@ pub fn get_tiles( tilemap: &TiledTilemap ) -> Result, Box> { let mut palette: [u16; 16] = [ 0; 16 ]; let mut all_tiles: Vec = Vec::new(); - for tile_y in 0..tilemap.tile_height { - for tile_x in 0..tilemap.tile_width { + for tile_y in 0..tilemap.height { + for tile_x in 0..tilemap.width { let tile = tilemap.tileset.image.clone().crop( tile_x as u32, tile_y as u32, - tilemap.tile_width as u32, - tilemap.tile_height as u32 + 8, // --system md + 8 // --system md ); let tile_bin = image_to_tiles( @@ -52,8 +52,8 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result, Box> 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 md_height_per_tile = tilemap.tile_height / 8; - let md_width_per_tile = tilemap.tile_width / 8; + let md_height_per_tile = 1; // --system md + let md_width_per_tile = 1; // --system md // Each entry in a `--system md` tilemap is 16 bits let mut nametable: Vec = vec![ 0; ( tilemap.width * md_width_per_tile ) * ( tilemap.height * md_height_per_tile ) ];