Write component attribute table to .ecs file
parent
0360a875f2
commit
efa2c24487
|
@ -1,8 +1,8 @@
|
|||
use std::{error::Error, convert::TryInto, cmp::max};
|
||||
use std::{error::Error, convert::TryInto, cmp::max, num::ParseIntError};
|
||||
use image::GenericImageView;
|
||||
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};
|
||||
use super::{converter::{TiledTilemap, Layer, SystemPlane}, ecs::Component};
|
||||
|
||||
/**
|
||||
* Output the .bin and .pal file (using `tileset` tool to build it) containing each of the tiles
|
||||
|
@ -241,7 +241,7 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
|||
|
||||
// Assign this unique combination of components a type id
|
||||
// by inserting it into `types`
|
||||
types.insert( components );
|
||||
types.insert_if_absent( components );
|
||||
}
|
||||
|
||||
let largest_type_size: u16 = types.iter()
|
||||
|
@ -300,7 +300,84 @@ pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
|||
result.push( 0xFF );
|
||||
}
|
||||
|
||||
// TODO: Component Attribute Table
|
||||
// Component Attribute Table
|
||||
// Index all attribute values that do not parse to u16
|
||||
let mut attribute_value_ids: LinkedHashSet<String> = LinkedHashSet::new();
|
||||
for entity in &tilemap.ecs {
|
||||
for ( _, component ) in &entity.components {
|
||||
for ( _, attribute_value ) in &component.attributes {
|
||||
// Handling various types from Tiled Editor
|
||||
// * If it is "true" or "false", leave it alone. It will be articulated as 1 or 0.
|
||||
// * If it can be parsed as a u16, leave it alone.
|
||||
// * In all other cases, add to attribute_value_ids to create an index.
|
||||
if attribute_value != "true" && attribute_value != "false" {
|
||||
let try_as_u16: Result<u16, ParseIntError> = attribute_value.parse();
|
||||
if let Err( _ ) = try_as_u16 {
|
||||
attribute_value_ids.insert_if_absent( attribute_value.clone() );
|
||||
print_info( &format!( "Attribute Value ID {}: \"{}\"", attribute_value_ids.len() - 1, attribute_value ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the largest size of a combination of attributes (the component attribute union size)
|
||||
let largest_type_attributes_size = tilemap.ecs.iter()
|
||||
.map( | entity | {
|
||||
let mut total_attributes_for_entity = 0;
|
||||
|
||||
for ( _, component ) in &entity.components {
|
||||
total_attributes_for_entity += component.attributes.len()
|
||||
}
|
||||
|
||||
total_attributes_for_entity
|
||||
} )
|
||||
.reduce( | prev, current | max( prev, current ) )
|
||||
.ok_or( "internal error: no largest type attributes size" )? as u16;
|
||||
|
||||
// 2 bytes: Component Attribute Union Size
|
||||
result.extend( largest_type_attributes_size.to_be_bytes() );
|
||||
|
||||
// For (Object Table Size):
|
||||
for entity in &tilemap.ecs {
|
||||
// (Component Attribute Union Size) bytes: Component attribute settings
|
||||
// Sort components in this entity alphabetically, ascending
|
||||
let mut components: Vec<(&String, &Component)> = entity.components.iter().collect();
|
||||
components.sort_by( | a, b | a.0.partial_cmp( b.0 ).expect( "internal error: unsortable" ) );
|
||||
|
||||
let mut written_attributes = 0;
|
||||
for ( _, component ) in &components {
|
||||
// Sort attributes in each component alphabetically
|
||||
let mut attributes: Vec<(&String, &String)> = component.attributes.iter().collect();
|
||||
attributes.sort_by( | a, b | a.0.partial_cmp( b.0 ).expect( "internal error: unsortable" ) );
|
||||
|
||||
for ( _, attribute_value ) in attributes {
|
||||
written_attributes += 1;
|
||||
match attribute_value.as_str() {
|
||||
"true" => result.extend( ( 1 as u16 ).to_be_bytes() ),
|
||||
"false" => result.extend( ( 0 as u16 ).to_be_bytes() ),
|
||||
string => {
|
||||
let try_as_u16: Result<u16, ParseIntError> = string.parse();
|
||||
if let Ok( numeric ) = try_as_u16 {
|
||||
result.extend( numeric.to_be_bytes() );
|
||||
} else {
|
||||
let id: u16 = attribute_value_ids.iter()
|
||||
.position( | attribute_value | attribute_value == &string )
|
||||
.ok_or( "internal error: no type id" )? as u16;
|
||||
|
||||
result.extend( id.to_be_bytes() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the remainder of the union with 0xFF, if needed
|
||||
let remainder = largest_type_attributes_size - written_attributes;
|
||||
for _ in 0..remainder {
|
||||
result.extend( ( 0xFFFF as u16 ).to_be_bytes() );
|
||||
}
|
||||
}
|
||||
|
||||
// Output IDs to terminal
|
||||
let component_ids: Vec<String> = component_ids.into_iter().collect();
|
||||
|
|
Loading…
Reference in New Issue