Compare commits

..

No commits in common. "62fcb599cc6c87c71745ce10dd5445fcca9af5d3" and "31832e8882c2bfce113d8690f10d490c124b63a1" have entirely different histories.

2 changed files with 26 additions and 50 deletions

View File

@ -1,5 +1,6 @@
use std::{error::Error, fs::read_to_string, path::Path, borrow::Cow};
use std::{error::Error, fs::read_to_string, path::Path, borrow::Cow, collections::HashMap};
use image::{DynamicImage, GenericImageView};
use regex::Regex;
use roxmltree::Node;
use crate::reskit::{utility::print_warning, cli::settings::TileOrder};
use super::ecs;
@ -9,6 +10,7 @@ pub struct TiledTilemap {
pub tileset: Vec<TiledTileset>,
pub layers: Vec<Layer>,
pub ecs: Vec<ecs::Entity>,
pub ecs_component_ids: HashMap<String, u8>,
pub width: usize,
pub height: usize
}
@ -252,8 +254,28 @@ pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
}
// Get the entity-component system
let mut ecs_component_ids = HashMap::new();
let object_group = map.descendants().find( | node | node.tag_name() == "objectgroup".into() );
let ecs = if let Some( object_group ) = object_group {
let object_group_properties = object_group.descendants().find( | node | node.tag_name() == "properties".into() );
if let Some( object_group_properties ) = object_group_properties {
let component_id_properties = object_group_properties.descendants()
.filter( | node | node.attribute( "name" ).unwrap_or( "" ).starts_with( "reskit-component-id" ) );
for property in component_id_properties {
let name_attribute = property.attribute( "name" ).ok_or( "internal error: no name attribute" )?;
let id: u8 = property.attribute( "value" ).ok_or( "internal error: no property value in object layer" )?.parse()?;
// Set up regex to remove individual parts
let regex = Regex::new( r#"reskit-component-id\[([a-z0-9_]+)\]"# )?;
let captures = regex.captures( name_attribute ).ok_or( "invalid file: invalid reskit-component-id key in object layer" )?;
let component_name = captures.get( 1 ).ok_or( "internal error: regex did not match properly" )?.as_str();
ecs_component_ids.insert( component_name.to_owned(), id );
}
}
// Add the "position" component by default
ecs_component_ids.insert( "position".to_owned(), ecs_component_ids.len() as u8 );
ecs::get_ecs( object_group )?
} else {
Vec::new()
@ -264,6 +286,7 @@ pub fn get_tiled_tilemap( path: &str ) -> Result<TiledTilemap, Box<dyn Error>> {
tileset,
layers,
ecs,
ecs_component_ids,
width,
height
}

View File

@ -1,6 +1,5 @@
use std::{error::Error, convert::TryInto, cmp::max, num::ParseIntError};
use image::GenericImageView;
use linked_hash_map::LinkedHashMap;
use linked_hash_set::LinkedHashSet;
use crate::reskit::{tileset::image_to_tiles, utility::{symbol_to_pascal, print_info}, cli::settings::TileOrder};
use super::{converter::{TiledTilemap, Layer, SystemPlane}, ecs::Component};
@ -227,8 +226,7 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
let mut result: Vec<u8> = Vec::new();
// Build a complete set of component IDs and types
let mut component_ids: LinkedHashSet<String> = LinkedHashSet::new();
// Build a complete set of types
let mut types: LinkedHashSet<LinkedHashSet<String>> = LinkedHashSet::new();
for entity in &tilemap.ecs {
// Get the list of components attached to this entity
@ -237,9 +235,6 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
components.sort();
let components: LinkedHashSet<String> = components.into_iter().collect();
// Assign an index to each unique component id by inserting it into `component_ids`
component_ids.extend( components.clone() );
// Assign this unique combination of components a type id
// by inserting it into `types`
types.insert_if_absent( components );
@ -264,7 +259,7 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
for component in ecs_type {
type_component_ids.push(
component_ids.iter().position( | value | component == value ).ok_or( "internal error: no component" )? as u8
*tilemap.ecs_component_ids.get( component ).ok_or( format!( "invalid file: undefined component symbol \"{}\"", component ) )?
);
}
@ -388,12 +383,6 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
}
}
// Output IDs to terminal
let component_ids: Vec<String> = component_ids.into_iter().collect();
for i in 0..component_ids.len() {
print_info( &format!( "Component ID {}: {}", i, component_ids[ i ] ) );
}
// Output type structures to terminal
let mut visited_types: LinkedHashSet<LinkedHashSet<String>> = LinkedHashSet::new();
for entity in &tilemap.ecs {
@ -437,7 +426,6 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn get_code( tilemap: &TiledTilemap, level_name: &str, path_prefix: &str ) -> Result<String, Box<dyn Error>> {
let version = env!( "CARGO_PKG_VERSION" );
let level_label = symbol_to_pascal( level_name );
let level_label_const_caps = level_label.to_uppercase();
let ( width, height ) = ( tilemap.width, tilemap.height );
let num_tiles = {
let mut total_tiles = 0;
@ -448,43 +436,9 @@ pub fn get_code( tilemap: &TiledTilemap, level_name: &str, path_prefix: &str ) -
total_tiles
};
// Output IDs for each type defined in the map
let mut component_ids: LinkedHashSet<String> = LinkedHashSet::new();
let mut attribute_ids: LinkedHashMap<String, LinkedHashSet<String>> = LinkedHashMap::new();
for entity in &tilemap.ecs {
let mut components: Vec<String> = entity.components.keys().map( | id | id.to_lowercase() ).collect();
components.sort();
let components: LinkedHashSet<String> = components.into_iter().collect();
component_ids.extend( components );
for ( component_name, component ) in &entity.components {
let mut attributes: Vec<String> = component.attributes.keys().map( | id | id.to_lowercase() ).collect();
attributes.sort();
let attribues: LinkedHashSet<String> = attributes.into_iter().collect();
attribute_ids.entry( component_name.to_owned() ).or_default().extend( attribues );
}
}
let component_ids: Vec<String> = component_ids.into_iter().collect();
let mut constants: String = String::new();
for i in 0..component_ids.len() {
let component_id = &component_ids[ i ];
constants += &format!( "{}_{} = {}\n", level_label_const_caps, component_id.to_uppercase(), i );
let attribute_ids: Vec<String> = attribute_ids[ component_id ].iter().map( | string | string.clone() ).collect();
for i in 0..attribute_ids.len() {
constants += &format!( "\t{}_{}_{} = {}\n", level_label_const_caps, component_id.to_uppercase(), attribute_ids[ i ].to_uppercase(), i );
}
}
let file = format!( r#"; Level definition file
; Generated by reskit v{version}
{constants}
{level_label}Tiles:
incbin '{path_prefix}{level_name}/tiles.bin'
@ -508,6 +462,5 @@ pub fn get_code( tilemap: &TiledTilemap, level_name: &str, path_prefix: &str ) -
dc.l {level_label}Collision
dc.l {level_label}Objects"# );
Ok( file )
}