75 percent done ECS exporter
parent
bd6136903d
commit
0360a875f2
|
@ -1,6 +1,6 @@
|
|||
use std::{error::Error, fs::File, io::Write, path::Path};
|
||||
use clap::Parser;
|
||||
use crate::reskit::{tileset, soundtrack::{formats::dmf::DmfModule, engines::echo::engine::{EchoFormat, EchoArtifact}}, utility::{print_good, print_error, print_info}, level::{converter::get_tiled_tilemap, system::{get_tiles, get_code, get_tilemap, get_collision_map}}};
|
||||
use crate::reskit::{tileset, soundtrack::{formats::dmf::DmfModule, engines::echo::engine::{EchoFormat, EchoArtifact}}, utility::{print_good, print_error, print_info}, level::{converter::get_tiled_tilemap, system::{get_tiles, get_code, get_tilemap, get_collision_map, get_ecs}}};
|
||||
use super::settings::{Args, Tools, TileOutputFormat, TileOrder};
|
||||
|
||||
pub fn run_command() -> Result<(), Box<dyn Error>> {
|
||||
|
@ -87,6 +87,10 @@ pub fn run_command() -> Result<(), Box<dyn Error>> {
|
|||
nametables_bin.write_all( &get_collision_map( &tiled_file )? )?;
|
||||
print_good( "exported collision.lvc" );
|
||||
|
||||
let mut nametables_bin = File::create( format!( "{}objects.ecs", output_directory ) )?;
|
||||
nametables_bin.write_all( &get_ecs( &tiled_file )? )?;
|
||||
print_good( "exported objects.ecs" );
|
||||
|
||||
let mut code_asm = File::create( format!( "{}level.asm", output_directory ) )?;
|
||||
code_asm.write_all( &get_code( &tiled_file, "testlevel", "levels/" )?.as_bytes() )?;
|
||||
print_good( "exported level.asm" );
|
||||
|
|
|
@ -8,7 +8,7 @@ use super::ecs;
|
|||
pub struct TiledTilemap {
|
||||
pub tileset: Vec<TiledTileset>,
|
||||
pub layers: Vec<Layer>,
|
||||
ecs: Vec<ecs::Entity>,
|
||||
pub ecs: Vec<ecs::Entity>,
|
||||
pub width: usize,
|
||||
pub height: usize
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::{error::Error, convert::TryInto};
|
||||
use std::{error::Error, convert::TryInto, cmp::max};
|
||||
use image::GenericImageView;
|
||||
use crate::reskit::{tileset::image_to_tiles, utility::symbol_to_pascal, cli::settings::TileOrder};
|
||||
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};
|
||||
|
||||
/**
|
||||
|
@ -215,6 +216,101 @@ pub fn get_collision_map( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Er
|
|||
Ok( result )
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity-component system defined. If none is defined return an empty vec.
|
||||
*/
|
||||
pub fn get_ecs( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
if tilemap.ecs.is_empty() {
|
||||
return Ok( vec![] )
|
||||
}
|
||||
|
||||
let mut result: Vec<u8> = Vec::new();
|
||||
|
||||
// Build a complete set of component IDs and types
|
||||
let mut component_ids: LinkedHashSet<String> = LinkedHashSet::new();
|
||||
let mut types: LinkedHashSet<LinkedHashSet<String>> = LinkedHashSet::new();
|
||||
for entity in &tilemap.ecs {
|
||||
// Get the list of components attached to this entity
|
||||
// Sort alphabetically as order matters in LinkedHashSets
|
||||
let mut components: Vec<String> = entity.components.keys().map( | id | id.to_lowercase() ).collect();
|
||||
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( components );
|
||||
}
|
||||
|
||||
let largest_type_size: u16 = types.iter()
|
||||
.map( | components | components.len() as u16 )
|
||||
.reduce( | prev, current | max( prev, current ) )
|
||||
.ok_or( "internal error: type is empty" )?;
|
||||
|
||||
// Type Table
|
||||
// 2 bytes: Number of Types
|
||||
result.extend( ( types.len() as u16 ).to_be_bytes() );
|
||||
|
||||
// 2 bytes: Type Definition Union Size
|
||||
result.extend( largest_type_size.to_be_bytes() );
|
||||
|
||||
// For (Number of Types):
|
||||
for ecs_type in &types {
|
||||
// (Type Definition Union Size) bytes: List of Component IDs
|
||||
let mut type_component_ids: Vec<u8> = vec![];
|
||||
|
||||
for component in ecs_type {
|
||||
type_component_ids.push(
|
||||
component_ids.iter().position( | value | component == value ).ok_or( "internal error: no component" )? as u8
|
||||
);
|
||||
}
|
||||
|
||||
// Fill the remainder of the union with 0xFF, if needed
|
||||
let remainder = largest_type_size as usize - type_component_ids.len();
|
||||
for _ in 0..remainder {
|
||||
type_component_ids.push( 0xFF );
|
||||
}
|
||||
|
||||
result.extend( type_component_ids );
|
||||
}
|
||||
|
||||
// Object Table
|
||||
// 2 bytes: Object Table Size
|
||||
result.extend( ( 512 as u16 ).to_be_bytes() );
|
||||
|
||||
// For (Object Table Size)
|
||||
for entity in &tilemap.ecs {
|
||||
// Do the thing again
|
||||
let mut components: Vec<String> = entity.components.keys().map( | id | id.to_lowercase() ).collect();
|
||||
components.sort();
|
||||
let components: LinkedHashSet<String> = components.into_iter().collect();
|
||||
|
||||
// What type id is this?
|
||||
let type_id: u8 = types.iter().position( | ecs_type | ecs_type == &components ).ok_or( "internal error: no type id" )? as u8;
|
||||
|
||||
// Output type id
|
||||
result.push( type_id );
|
||||
}
|
||||
|
||||
// Fill the remainder of the sparse Object Array with 0xFF, if needed
|
||||
let remainder = 512 - tilemap.ecs.len();
|
||||
for _ in 0..remainder {
|
||||
result.push( 0xFF );
|
||||
}
|
||||
|
||||
// TODO: Component Attribute Table
|
||||
|
||||
// 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 ] ) );
|
||||
}
|
||||
|
||||
Ok( result )
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a helper .asm or .c file that ties all the level components together
|
||||
*/
|
||||
|
@ -246,12 +342,16 @@ pub fn get_code( tilemap: &TiledTilemap, level_name: &str, path_prefix: &str ) -
|
|||
{level_label}Collision:
|
||||
incbin '{path_prefix}{level_name}/collision.lvc'
|
||||
|
||||
{level_label}Objects:
|
||||
incbin '{path_prefix}{level_name}/objects.ecs'
|
||||
|
||||
{level_label}:
|
||||
dc.w {width}, {height}, {num_tiles}
|
||||
dc.l {level_label}Tiles
|
||||
dc.l {level_label}Palettes
|
||||
dc.l {level_label}Nametables
|
||||
dc.l {level_label}Collision"# );
|
||||
dc.l {level_label}Collision
|
||||
dc.l {level_label}Objects"# );
|
||||
|
||||
Ok( file )
|
||||
}
|
Loading…
Reference in New Issue