mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
load aseprite files directly with asefile
This commit is contained in:
parent
e67f1ff45f
commit
84e6af5d2f
78
agb-image-converter/Cargo.lock
generated
78
agb-image-converter/Cargo.lock
generated
|
@ -18,15 +18,29 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
|||
name = "agb_image_converter"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"asefile",
|
||||
"image",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asefile"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d5f7de918fd4cb18249819fc4bd27f6a5dbfbc9dcb271727f27dacf17ce880"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"flate2",
|
||||
"image",
|
||||
"log",
|
||||
"nohash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -81,6 +95,18 @@ dependencies = [
|
|||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.24.1"
|
||||
|
@ -97,10 +123,19 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
name = "libc"
|
||||
version = "0.2.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
|
@ -111,6 +146,22 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nohash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0f889fb66f7acdf83442c35775764b51fed3c606ab9cee51500dbde2cf528ca"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -161,7 +212,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"crc32fast",
|
||||
"deflate",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -182,12 +233,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
|
@ -208,17 +253,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.86"
|
||||
|
|
|
@ -16,4 +16,4 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
syn = "1.0.86"
|
||||
proc-macro2 = "1.0.36"
|
||||
quote = "1.0.15"
|
||||
serde_json = "1.0"
|
||||
asefile = "0.3.2"
|
||||
|
|
|
@ -1,102 +1,23 @@
|
|||
use std::{
|
||||
fs::File,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
str,
|
||||
};
|
||||
use std::path::Path;
|
||||
|
||||
use asefile::{AsepriteFile, Tag};
|
||||
use image::DynamicImage;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Aseprite {
|
||||
pub frames: Vec<Frame>,
|
||||
pub meta: Meta,
|
||||
pub fn generate_from_file(filename: &Path) -> (Vec<DynamicImage>, Vec<Tag>) {
|
||||
let ase = AsepriteFile::read_file(filename).expect("Aseprite file should exist");
|
||||
|
||||
let mut images = Vec::new();
|
||||
let mut tags = Vec::new();
|
||||
|
||||
for frame in 0..ase.num_frames() {
|
||||
let image = ase.frame(frame).image();
|
||||
|
||||
images.push(DynamicImage::ImageRgba8(image))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Meta {
|
||||
pub app: String,
|
||||
pub version: String,
|
||||
pub image: String,
|
||||
pub format: String,
|
||||
pub size: Size,
|
||||
pub scale: String,
|
||||
#[serde(rename = "frameTags")]
|
||||
pub frame_tags: Vec<FrameTag>,
|
||||
for tag in 0..ase.num_tags() {
|
||||
tags.push(ase.tag(tag).clone())
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Size {
|
||||
pub w: u32,
|
||||
pub h: u32,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Copy)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum Direction {
|
||||
Forward,
|
||||
Backward,
|
||||
Pingpong,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct FrameTag {
|
||||
pub name: String,
|
||||
pub from: u32,
|
||||
pub to: u32,
|
||||
pub direction: Direction,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct Frame {
|
||||
pub frame: Frame2,
|
||||
pub trimmed: bool,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct Frame2 {
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub w: u32,
|
||||
pub h: u32,
|
||||
}
|
||||
|
||||
pub fn generate_from_file(filename: &Path) -> (Aseprite, DynamicImage) {
|
||||
let out_dir = std::env::var("OUT_DIR").expect("Expected OUT_DIR");
|
||||
|
||||
let output_filename = Path::new(&out_dir).join(filename.file_name().unwrap());
|
||||
|
||||
let image_output = output_filename.with_extension("png");
|
||||
let json_output = output_filename.with_extension("json");
|
||||
|
||||
let command = Command::new("aseprite")
|
||||
.args([
|
||||
&PathBuf::from("-b"),
|
||||
&PathBuf::from(filename),
|
||||
&"--sheet".into(),
|
||||
&image_output,
|
||||
&"--format".into(),
|
||||
&"json-array".into(),
|
||||
&"--data".into(),
|
||||
&json_output,
|
||||
&"--list-tags".into(),
|
||||
])
|
||||
.output()
|
||||
.expect("Could not run aseprite");
|
||||
assert!(
|
||||
command.status.success(),
|
||||
"Aseprite did not complete successfully : {}",
|
||||
str::from_utf8(&*command.stdout).unwrap_or("Output contains invalid string")
|
||||
);
|
||||
|
||||
let json: Aseprite = serde_json::from_reader(
|
||||
File::open(&json_output).expect("The json output from aseprite could not be openned"),
|
||||
)
|
||||
.expect("The output from aseprite could not be decoded");
|
||||
|
||||
(
|
||||
json,
|
||||
image::open(image_output).expect("Image should be readable"),
|
||||
)
|
||||
(images, tags)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ mod image_loader;
|
|||
mod palette16;
|
||||
mod rust_generator;
|
||||
|
||||
use image::GenericImageView;
|
||||
use image_loader::Image;
|
||||
|
||||
use colour::Colour;
|
||||
|
@ -93,7 +94,6 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
|
|||
|
||||
let mut optimiser = palette16::Palette16Optimiser::new();
|
||||
let mut images = Vec::new();
|
||||
let mut frames = Vec::new();
|
||||
let mut tags = Vec::new();
|
||||
|
||||
let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir");
|
||||
|
@ -105,24 +105,18 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
|
|||
.collect();
|
||||
|
||||
for filename in filenames.iter() {
|
||||
let (json, image) = aseprite::generate_from_file(filename);
|
||||
let tile_size = json.frames[0].frame.w;
|
||||
let (frames, tag) = aseprite::generate_from_file(filename);
|
||||
|
||||
for frame in json.frames.iter() {
|
||||
assert!(frame.frame.w == tile_size);
|
||||
assert!(
|
||||
frame.frame.w == frame.frame.h
|
||||
&& frame.frame.w.is_power_of_two()
|
||||
&& frame.frame.w <= 32
|
||||
);
|
||||
}
|
||||
tags.push((tag, images.len()));
|
||||
|
||||
let image = Image::load_from_dyn_image(image);
|
||||
for frame in frames {
|
||||
let width = frame.width();
|
||||
assert!(width == frame.height() && width.is_power_of_two() && width <= 32);
|
||||
|
||||
add_to_optimiser(&mut optimiser, &image, tile_size as usize);
|
||||
let image = Image::load_from_dyn_image(frame);
|
||||
add_to_optimiser(&mut optimiser, &image, width as usize);
|
||||
images.push(image);
|
||||
frames.push(json.frames.clone());
|
||||
tags.push(json.meta.frame_tags.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let optimised_results = optimiser.optimise_palettes(None);
|
||||
|
@ -138,17 +132,16 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
|
|||
});
|
||||
|
||||
let mut pre = 0;
|
||||
let sprites = frames
|
||||
let sprites = images
|
||||
.iter()
|
||||
.flatten()
|
||||
.zip(assignments.iter())
|
||||
.map(|(f, assignment)| {
|
||||
let start: usize = pre;
|
||||
let end: usize = pre + (f.frame.w as usize / 8) * (f.frame.h as usize / 8) * 32;
|
||||
let end: usize = pre + (f.width / 8) * (f.height / 8) * 32;
|
||||
let data = ByteString(&tile_data[start..end]);
|
||||
pre = end;
|
||||
let width = f.frame.w as usize;
|
||||
let height = f.frame.h as usize;
|
||||
let width = f.width;
|
||||
let height = f.height;
|
||||
quote! {
|
||||
Sprite::new(
|
||||
&PALETTES[#assignment],
|
||||
|
@ -160,15 +153,13 @@ pub fn include_aseprite_inner(input: TokenStream) -> TokenStream {
|
|||
|
||||
let tags = tags
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, tag)| {
|
||||
tag.iter().map(move |tag| (i, tag)).map(|(i, tag)| {
|
||||
let offset: usize = frames[0..i].iter().map(|s| s.len()).sum();
|
||||
let start = tag.from as usize + offset;
|
||||
let end = tag.to as usize + offset;
|
||||
let direction = tag.direction as usize;
|
||||
.map(|(tag, num_images)| {
|
||||
tag.iter().map(move |tag| {
|
||||
let start = tag.from_frame() as usize + num_images;
|
||||
let end = tag.to_frame() as usize + num_images;
|
||||
let direction = tag.animation_direction() as usize;
|
||||
|
||||
let name = &tag.name;
|
||||
let name = tag.name();
|
||||
assert!(start <= end, "Tag {} has start > end", name);
|
||||
|
||||
quote! {
|
||||
|
|
78
agb/Cargo.lock
generated
78
agb/Cargo.lock
generated
|
@ -41,11 +41,11 @@ dependencies = [
|
|||
name = "agb_image_converter"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"asefile",
|
||||
"image",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"syn",
|
||||
"toml",
|
||||
]
|
||||
|
@ -80,6 +80,20 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "asefile"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0d5f7de918fd4cb18249819fc4bd27f6a5dbfbc9dcb271727f27dacf17ce880"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"flate2",
|
||||
"image",
|
||||
"log",
|
||||
"nohash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
|
@ -140,6 +154,18 @@ dependencies = [
|
|||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crc32fast",
|
||||
"libc",
|
||||
"miniz_oxide 0.4.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.5"
|
||||
|
@ -181,18 +207,21 @@ dependencies = [
|
|||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.5.1"
|
||||
|
@ -202,6 +231,16 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield"
|
||||
version = "0.11.2"
|
||||
|
@ -223,6 +262,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nohash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0f889fb66f7acdf83442c35775764b51fed3c606ab9cee51500dbde2cf528ca"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -323,7 +368,7 @@ dependencies = [
|
|||
"bitflags",
|
||||
"crc32fast",
|
||||
"deflate",
|
||||
"miniz_oxide",
|
||||
"miniz_oxide 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -402,12 +447,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.136"
|
||||
|
@ -428,17 +467,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.9"
|
||||
|
|
Loading…
Reference in a new issue