Skip to content

Commit

Permalink
Added tilemap CLI option, create directories before writing any files
Browse files Browse the repository at this point in the history
  • Loading branch information
peteward44 committed Dec 29, 2024
1 parent 37567e9 commit edabe05
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 10 deletions.
40 changes: 33 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,20 @@ fn operate() -> std::result::Result<(), failure::Error> {
.author("Pete Ward <[email protected]>")
.version(crate_version!())
.about("Builds texture atlas images with meta data output")
.arg(Arg::new("tilemap")
.long("tilemap")
.action(clap::ArgAction::SetTrue)
.help("Enables tilemap mode, automatically disables trimming, sets all input images to the size of the largest input image"))
.arg(Arg::new("rotation-disable")
.short('r')
.long("rotation-disable")
.action(clap::ArgAction::SetTrue)
.help("Disable sub image rotation"))
.arg(Arg::new("trim-disable")
.short('t')
.long("trim-disable")
.action(clap::ArgAction::SetTrue)
.help("Disable sub image trimming"))
.arg(Arg::new("fixed-size")
.short('f')
.long("fixed-size")
Expand Down Expand Up @@ -96,17 +105,30 @@ fn operate() -> std::result::Result<(), failure::Error> {
let input_name_root_dir = std::path::Path::new(matches.get_one::<String>("input-name-root-dir").unwrap());
let output_filename = std::path::Path::new(matches.get_one::<String>("image-output").unwrap());
let output_meta_filename = matches.get_one::<String>("meta-output").unwrap();
let allow_rotation = !matches.get_flag("rotation-disable");
let tilemap_mode = matches.get_flag("tilemap");
let allow_trimming = !tilemap_mode && !matches.get_flag("trim-disable");
let allow_rotation = !tilemap_mode && !matches.get_flag("rotation-disable");
let allow_grow = !matches.get_flag("fixed-size");

let mut packer = packer::Packer::new( output_width, output_height, allow_grow, allow_rotation, padding );

println!( "Calculating rects..." );
debug!( "Calculating rects..." );
let mut largest_w : i32 = 0;
let mut largest_h : i32 = 0;
let mut inputs: Vec<inputimage::InputImage> = vec!();
for filename in input_filenames.iter() {
let mut input = inputimage::InputImage::load( filename );
input.trim();
println!( "{{ w: {:?}, h: {:?} }}", input.vw, input.vh );
if allow_trimming
{
input.trim();
}
if input.w > largest_w {
largest_w = input.w;
}
if input.h > largest_h {
largest_h = input.h;
}
debug!( "{{ w: {:?}, h: {:?} }}", input.vw, input.vh );
inputs.push( input );
}

Expand All @@ -118,9 +140,13 @@ fn operate() -> std::result::Result<(), failure::Error> {
packer.add( input.vw, input.vh );
}

while !packer.pack() {
if !packer.grow() {
bail!( "Output size exceeded!" );
if tilemap_mode {
packer.pack_tilemap(largest_w, largest_h);
} else {
while !packer.pack() {
if !packer.grow() {
bail!( "Output size exceeded!" );
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/outputimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ impl OutputImage {
// image::save_buffer( filename, &self.data, self.w as u32, self.h as u32, image::RGBA(8))

{
let file = File::create( filename ).unwrap();
let parent_dir = filename.parent();
if parent_dir.is_some()
{
std::fs::create_dir_all(parent_dir.unwrap())?;
}
let file = File::create(filename).unwrap();
let ref mut w = BufWriter::new(file);

let mut encoder = png::Encoder::new(w, self.w as u32, self.h as u32); // Width is 2 pixels and height is 1.
Expand Down
16 changes: 15 additions & 1 deletion src/outputmeta.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use pathdiff::diff_paths;
use std::path::Path;
use std::env;
use tera::Tera;
use super::shapes;
use super::inputimage;
Expand Down Expand Up @@ -41,11 +42,19 @@ pub struct OutputMeta {
tera: Tera,
}

fn get_templates_directory() -> String {
let mut dir = env::current_exe().expect("Could not get templates directory");
dir.pop();
dir.push("templates");
dir.into_os_string().into_string().unwrap() + "/**/*"
}

impl OutputMeta {
pub fn new() -> OutputMeta {
let templates_directory = get_templates_directory();
OutputMeta {
subs: vec!(),
tera: Tera::new("templates/**/*").unwrap(),
tera: Tera::new(templates_directory.as_str()).unwrap(),
}
}

Expand Down Expand Up @@ -120,6 +129,11 @@ impl OutputMeta {
_ => self.tera.render(template, &context)?,
};

let parent_dir = filename.parent();
if parent_dir.is_some()
{
std::fs::create_dir_all(parent_dir.unwrap())?;
}
std::fs::write(filename, result.to_owned())?;
Ok(result)
}
Expand Down
39 changes: 38 additions & 1 deletion src/packer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,43 @@ impl Packer {
self.used_rects.push( shapes::Rect{ x: 0, y: 0, w: w, h: h } );
}

pub fn pack_tilemap(&mut self, tile_w: i32, tile_h: i32) {
let mut row_count: i32;
let column_count: i32;
{
let float_subimage_count = self.used_rects.len() as f32;
let subimage_count_sqrt = float_subimage_count.sqrt();
let tile_aspect_ratio: f32 = tile_h as f32 / tile_w as f32;
column_count = (subimage_count_sqrt * tile_aspect_ratio).ceil() as i32;
row_count = (float_subimage_count / column_count as f32) as i32;
if self.used_rects.len() % column_count as usize > 0 {
row_count += 1;
}
self.w = column_count * tile_w;
self.h = row_count * tile_h;

debug!("self.w={:?} self.h={:?} float_subimage_count={:?} tile_aspect_ratio={:?} row_count={:?} column_count={:?}", self.w, self.h, float_subimage_count, tile_aspect_ratio, row_count, column_count);
}
let mut tile_index = 0;
let mut new_results: Vec<PackResult> = vec!();
for used_rect in self.used_rects.iter() {
let tile_x = tile_index % column_count;
let tile_y = tile_index / column_count;
let x = tile_w * tile_x + ((tile_w - used_rect.w) / 2);
let y = tile_h * tile_y + ((tile_h - used_rect.h) / 2);
let packed_rect = PackResult
{
rect: shapes::Rect{
x, y, w: tile_w, h: tile_h,
},
rotated: false,
};
new_results.push(packed_rect);
tile_index += 1;
}
self.results = new_results;
}

pub fn pack( &mut self ) -> bool {
let mut new_results: Vec<PackResult> = vec!();
let mut free_rects: Vec<shapes::Rect> = vec!();
Expand Down Expand Up @@ -291,7 +328,7 @@ impl Packer {
mod test_packer {

fn assert_pack_result( result: &super::PackResult, x: i32, y: i32, w: i32, h: i32, rotated: bool, message: &str ) {
println!( "x={:?} y={:?} w={:?} h={:?}", result.rect.x, result.rect.y, result.rect.w, result.rect.h );
debug!( "x={:?} y={:?} w={:?} h={:?}", result.rect.x, result.rect.y, result.rect.w, result.rect.h );
assert_eq!( result.rect.x, x, "{} - x", message );
assert_eq!( result.rect.y, y, "{} - y", message );
assert_eq!( result.rect.w, w, "{} - w", message );
Expand Down

0 comments on commit edabe05

Please sign in to comment.