auto-gen spritesheets

This commit is contained in:
Evan Pratten 2022-03-21 09:10:02 -04:00
parent 023eb14983
commit aa340d5806
26 changed files with 132 additions and 3 deletions

View File

@ -3,6 +3,7 @@ members = ["./game/game_logic", "./game/desktop_wrapper"]
exclude = [
"./third_party/raylib-rs/raylib",
"./third_party/raylib-rs/raylib-sys",
"./automation/anim_stitcher"
]
[profile.release]

View File

@ -0,0 +1,17 @@
[package]
name = "anim_stitcher"
publish = false
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.126", features = ["derive"] }
serde_json = "1.0.64"
build-helper = { version = "0.1.1", optional = true }
image = { version = "0.24.1", optional = true }
regex = { version = "1.5.5", optional = true }
[features]
default = []
generator = ["build-helper", "image", "regex"]

View File

@ -0,0 +1,66 @@
use std::path::{Path, PathBuf};
use image::{GenericImage, ImageResult};
use regex::Regex;
const SPRITE_TYPE_RE: &str = r"^([a-z]+)_";
fn sprite_name_to_output_dir(sprite_name: &str) -> PathBuf {
// Determine the sprite type
let sprite_type: String = Regex::new(SPRITE_TYPE_RE)
.unwrap()
.captures(sprite_name)
.unwrap()
.get(1)
.unwrap()
.as_str()
.to_string()
.into();
// Build the output directory
Path::new("../dist/gen/anm/")
.join(sprite_type)
.join(sprite_name)
}
pub fn stitch_sprites(sprite_name: &str, ordered_image_files: Vec<PathBuf>) -> ImageResult<()> {
build_helper::warning!(
"Generating sprite `{}` from {} images",
sprite_name,
ordered_image_files.len()
);
// Collect all images into a vec of actual image data
let mut images = Vec::new();
for image_file in ordered_image_files {
let image_data = image::open(image_file.as_path()).unwrap();
images.push(image_data);
}
// Calculate the final width and height of the sprite
let img_width_out: u32 = images.iter().map(|im| im.width()).sum();
let img_height_out: u32 = images.iter().map(|im| im.height()).max().unwrap_or(0);
// Initialize an image buffer with the appropriate size.
let mut imgbuf = image::ImageBuffer::new(img_width_out, img_height_out);
let mut accumulated_width = 0;
// Copy each input image at the correct location in the output image.
for img in images {
imgbuf.copy_from(&img, accumulated_width, 0).unwrap();
accumulated_width += img.width();
}
// Get the output directory
let output_dir = sprite_name_to_output_dir(sprite_name);
// Create the output directory if it doesn't exist
if !output_dir.exists() {
std::fs::create_dir_all(output_dir.as_path()).unwrap();
}
// Write the output image to disk.
imgbuf.save(output_dir.join(format!("{}.png", sprite_name)))?;
Ok(())
}

View File

@ -0,0 +1,3 @@
#[cfg(feature = "generator")]
pub mod generator;

View File

@ -0,0 +1,9 @@
# The Auto-Stitch directory
This is a bit of a *magic* directory. Anything put in here will automatically be turned into a spritesheet at compile time.
## File organization
In this directory, framesets are expected to be stored in subdirectories. The names of these are important as they will translate into the names of the spritesheets.
For example, if you put a set of frames in `auto_stitch/chr_testFox`, you will get a spritesheet generated to `dist/gen/anm/chr/chr_testFox.png`.

View File

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 119 KiB

View File

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

1
game/dist/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/gen/*

View File

@ -3,20 +3,26 @@ name = "game_logic"
publish = false
version = "0.1.0"
edition = "2021"
build = "build.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
raylib = { version = "3.7", path = "../../third_party/raylib-rs/raylib" }
sad_machine = { version = "1.0", path = "../../third_party/sm" }
tokio = { version = "1.17.0", featurs = ["fs"] }
tokio = { version = "1.17.0", features = ["fs"] }
log = "0.4.14"
profiling = "1.0.5"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
directories = "4.0.1"
chrono = { verison = "0.4.19", features = ["serde"] }
chrono = { version = "0.4.19", features = ["serde"] }
discord-sdk = "0.3.0"
rust-embed = { version = "6.2.0", features = ["compression"] }
thiserror = "1.0.30"
# nalgebra = { version = "0.30.1", features = ["serde"] }
approx = "0.5.1"
approx = "0.5.1"
[build-dependencies.anim_stitcher]
version = "*"
features = ["generator"]
path = "../../automation/anim_stitcher"

26
game/game_logic/build.rs Normal file
View File

@ -0,0 +1,26 @@
//! This script contains code that generates more code.
//!
//! The idea being that we can have assets auto-pack and optimize themselves at build time.
fn main() {
// We want to re-build if the assets change
println!("cargo:rerun-if-changed=../auto_stitch");
// Search for all direct children of the auto_stitch directory
for entry in std::fs::read_dir("../auto_stitch").unwrap() {
let entry = entry.unwrap();
let path = entry.path();
// Get all children of the current entry
if let Ok(children) = std::fs::read_dir(&path) {
let children_paths = children.map(|e| e.unwrap().path()).collect::<Vec<_>>();
// Process into a sprite
anim_stitcher::generator::stitch_sprites(
path.file_name().unwrap().to_str().unwrap(),
children_paths,
)
.unwrap();
}
}
}