This commit is contained in:
Piotr Siuszko 2025-01-08 11:36:21 +01:00
parent 82419d165d
commit 9729ac02e3
7 changed files with 443 additions and 110 deletions

246
Cargo.lock generated
View File

@ -282,7 +282,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -336,7 +336,7 @@ checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -465,7 +465,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -500,7 +500,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -607,6 +607,32 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "basis-universal"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "555fb05709f4e12fa2f6b93a480facf167eb0ecb2558ba41f610f588e77cbd14"
dependencies = [
"basis-universal-sys",
"bitflags 1.3.2",
"lazy_static",
]
[[package]]
name = "basis-universal-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd9bde5e9547958fb0e77d79fc7879edcf91d5e0c8e372ef8959916cf35e8506"
dependencies = [
"cc",
]
[[package]]
name = "bcdec_rs"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9934c2b68e46448d814db20e34a840ef9b4e7b3b7c8b1da91161481230f6350"
[[package]]
name = "bevy"
version = "0.15.1"
@ -694,7 +720,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -761,7 +787,7 @@ checksum = "b962df2a1bef274ae76ec75279eb6f8ef0ffd85b5e4c43433f5d08ba57b3d071"
dependencies = [
"bevy_macro_utils",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -810,7 +836,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -855,7 +881,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -965,7 +991,7 @@ checksum = "9bdb3a681c24abace65bf18ed467ad8befbedb42468b32e459811bfdb01e506c"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"toml_edit",
]
@ -1075,7 +1101,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"uuid",
]
@ -1134,7 +1160,7 @@ dependencies = [
"bevy_macro_utils",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -1260,7 +1286,7 @@ checksum = "4a0c3244d543cc964545b7aa074f6fb18a915a7121cf3de5d7ed37a4aae8662d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -1298,7 +1324,7 @@ dependencies = [
"regex",
"rustc-hash",
"shlex",
"syn",
"syn 2.0.95",
]
[[package]]
@ -1437,7 +1463,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -1589,7 +1615,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -1857,6 +1883,18 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
[[package]]
name = "ddsfile"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479dfe1e6737aa9e96c6ac7b69689dc4c32da8383f2c12744739d76afa8b66c4"
dependencies = [
"bitflags 2.6.0",
"byteorder",
"enum-primitive-derive",
"num-traits",
]
[[package]]
name = "derive_more"
version = "1.0.0"
@ -1874,7 +1912,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"unicode-xid",
]
@ -1902,7 +1940,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2130,7 +2168,7 @@ checksum = "f97b51c5cc57ef7c5f7a0c57c250251c49ee4c28f819f87ac32f4aceabc36792"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2157,7 +2195,18 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
name = "enum-primitive-derive"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c375b9c5eadb68d0a6efee2999fef292f45854c3444c86f09d8ab086ba942b0e"
dependencies = [
"num-traits",
"quote",
"syn 1.0.109",
]
[[package]]
@ -2178,7 +2227,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2189,7 +2238,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2390,7 +2439,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2450,7 +2499,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2697,6 +2746,7 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888"
dependencies = [
"bytemuck",
"cfg-if",
"crunchy",
]
@ -2727,6 +2777,12 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "hermit-abi"
version = "0.4.0"
@ -2886,7 +2942,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2943,6 +2999,22 @@ dependencies = [
"quick-error",
]
[[package]]
name = "image_dds"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c6d1a2d80bc7dd2928b2a72a46d71bccbb6becf8ce207522b0b92daf0a417f"
dependencies = [
"bcdec_rs",
"bytemuck",
"ddsfile",
"half",
"image",
"intel_tex_2",
"strum",
"thiserror 1.0.69",
]
[[package]]
name = "imagesize"
version = "0.12.0"
@ -2974,6 +3046,15 @@ dependencies = [
"hashbrown 0.15.2",
]
[[package]]
name = "intel_tex_2"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd699c0e6adcac28c06db24a220c834c8ec811e0d2d80f0261bb14e01737b4dc"
dependencies = [
"ispc_rt",
]
[[package]]
name = "interpolate_name"
version = "0.2.4"
@ -2982,7 +3063,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -2991,6 +3072,16 @@ version = "1.70.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
[[package]]
name = "ispc_rt"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d30e08ddfd6fe26c3ee2e856dff022420cd0514ed16f5ccf2dc3e1d5cae578"
dependencies = [
"libc",
"num_cpus",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -3441,7 +3532,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -3474,6 +3565,16 @@ dependencies = [
"libm",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi 0.3.9",
"libc",
]
[[package]]
name = "num_enum"
version = "0.7.3"
@ -3492,7 +3593,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -3831,7 +3932,7 @@ checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -3884,7 +3985,7 @@ checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
dependencies = [
"cfg-if",
"concurrent-queue",
"hermit-abi",
"hermit-abi 0.4.0",
"pin-project-lite",
"rustix",
"tracing",
@ -3928,7 +4029,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705"
dependencies = [
"proc-macro2",
"syn",
"syn 2.0.95",
]
[[package]]
@ -3965,7 +4066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30"
dependencies = [
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4325,10 +4426,12 @@ dependencies = [
name = "rpack_cli"
version = "0.0.0"
dependencies = [
"basis-universal",
"bevy_rpack",
"clap",
"glob",
"image",
"image_dds",
"serde",
"serde_json",
"texture_packer",
@ -4385,6 +4488,12 @@ dependencies = [
"untrusted",
]
[[package]]
name = "rustversion"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.18"
@ -4435,7 +4544,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4458,7 +4567,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4652,6 +4761,28 @@ version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn 2.0.95",
]
[[package]]
name = "subtle"
version = "2.6.1"
@ -4674,6 +4805,17 @@ dependencies = [
"siphasher",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.95"
@ -4693,7 +4835,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4773,7 +4915,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4784,7 +4926,7 @@ checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -4921,7 +5063,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -5226,7 +5368,7 @@ dependencies = [
"log",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"wasm-bindgen-shared",
]
@ -5261,7 +5403,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -5589,7 +5731,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -5600,7 +5742,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -5972,7 +6114,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"synstructure",
]
@ -6068,7 +6210,7 @@ checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"zbus-lockstep",
"zbus_xml",
"zvariant 4.2.0",
@ -6083,7 +6225,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"zvariant_utils 2.1.0",
]
@ -6096,7 +6238,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"zbus_names 4.1.0",
"zvariant 5.1.0",
"zvariant_utils 3.0.2",
@ -6156,7 +6298,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -6176,7 +6318,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"synstructure",
]
@ -6205,7 +6347,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -6270,7 +6412,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"zvariant_utils 2.1.0",
]
@ -6283,7 +6425,7 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
"zvariant_utils 3.0.2",
]
@ -6295,7 +6437,7 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.95",
]
[[package]]
@ -6308,6 +6450,6 @@ dependencies = [
"quote",
"serde",
"static_assertions",
"syn",
"syn 2.0.95",
"winnow",
]

View File

@ -72,7 +72,7 @@ pub enum RpackAtlasAssetError {
#[error("could not load asset: {0}")]
Io(#[from] std::io::Error),
#[error("could not parse asset: {0}")]
ParsinError(#[from] serde_json::Error),
ParsingError(#[from] serde_json::Error),
/// A Bevy [`LoadDirectError`](bevy::asset::LoadDirectError) that occured
/// while loading a [`RpackAtlasAsset::image`](crate::RpackAtlasAsset::image).
#[error("could not load asset: {0}")]
@ -116,8 +116,8 @@ impl AssetLoader for RpackAtlasAssetLoader {
.asset_path()
.path()
.parent()
.unwrap_or(&std::path::Path::new(""))
.join(asset.name);
.unwrap_or(std::path::Path::new(""))
.join(asset.filename);
let mut image: Image = load_context
.loader()

View File

@ -23,6 +23,6 @@ pub struct AtlasFrame {
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct AtlasAsset {
pub size: [u32; 2],
pub name: String,
pub filename: String,
pub frames: Vec<AtlasFrame>,
}

View File

@ -102,9 +102,7 @@ impl TemplateApp {
.to_owned()
.replace("\\", "/");
let Some(image) = dynamic_image_from_file(file) else {
return None;
};
let image = dynamic_image_from_file(file)?;
Some(ImageFile { id, image })
}
@ -117,13 +115,19 @@ impl TemplateApp {
.flat_map(|f| Self::image_from_dropped_file(f, &prefix))
.collect();
self.data = Some(Spritesheet::build(
self.config,
&images,
"name".to_owned(),
));
self.data = Some(Spritesheet::build(self.config, &images, "name"));
if let Some(Ok(data)) = &self.data {
ctx.include_bytes("bytes://output.png", data.image_data.clone());
let mut out_vec = vec![];
let mut img =
image::DynamicImage::new_rgba8(data.atlas_asset.size[0], data.atlas_asset.size[1]);
image::imageops::overlay(&mut img, &data.image_data, 0, 0);
img.write_to(
&mut std::io::Cursor::new(&mut out_vec),
image::ImageFormat::Png,
)
.unwrap();
ctx.include_bytes("bytes://output.png", out_vec);
self.image =
Some(Image::from_uri("bytes://output.png").max_size(Vec2::new(256.0, 256.0)));
}
@ -134,7 +138,7 @@ impl TemplateApp {
let Some(Ok(data)) = &self.data else {
return;
};
let data = data.image_data.clone();
let data = data.image_data.as_bytes().to_vec();
let filename = format!("{}.png", self.name);
#[cfg(not(target_arch = "wasm32"))]
{
@ -396,9 +400,7 @@ fn file_path(file: &DroppedFile) -> String {
fn dynamic_image_from_file(file: &DroppedFile) -> Option<DynamicImage> {
#[cfg(target_arch = "wasm32")]
{
let Some(bytes) = file.bytes.as_ref().clone() else {
return None;
};
let bytes = file.bytes.as_ref().clone()?;
if let Ok(r) = ImageImporter::import_from_memory(&bytes.unwrap()) {
Some(r.into())
@ -408,9 +410,7 @@ fn dynamic_image_from_file(file: &DroppedFile) -> Option<DynamicImage> {
}
#[cfg(not(target_arch = "wasm32"))]
{
let Some(path) = file.path.as_ref() else {
return None;
};
let path = file.path.as_ref()?;
if let Ok(r) = ImageImporter::import_from_file(path) {
Some(r)

View File

@ -5,14 +5,18 @@ license = "MIT"
edition = "2021"
[features]
default = ["cli"]
default = ["cli", "dds"]
cli = ["dep:clap", "dep:glob"]
basis = ["dep:basis-universal"]
dds = ["dep:image_dds"]
[dependencies]
clap = { version = "4", features = ["derive"], optional = true}
clap = { version = "4", features = ["derive"], optional = true }
bevy_rpack = { default-features = false, path = "../bevy_rpack" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
texture_packer = { version = "0.29", features = ["common"] }
image = { version = "0.25", features = ["jpeg", "png"] }
glob = {version = "0.3", optional = true}
glob = { version = "0.3", optional = true }
basis-universal = { version = "0.3.1", optional = true }
image_dds = { version = "0.6.2", optional = true }

View File

@ -1,12 +1,12 @@
use bevy_rpack::{AtlasFrame, SerializableRect};
use image::DynamicImage;
use serde_json::Value;
use std::{io::Cursor, path::PathBuf};
use std::path::Path;
use texture_packer::{importer::ImageImporter, TexturePacker, TexturePackerConfig};
#[derive(Clone)]
pub struct Spritesheet {
pub image_data: Vec<u8>,
pub image_data: DynamicImage,
pub atlas_asset: bevy_rpack::AtlasAsset,
pub atlas_asset_json: Value,
}
@ -18,15 +18,16 @@ pub struct ImageFile {
}
impl ImageFile {
pub fn at_path<P>(path: &PathBuf, id: P) -> Option<ImageFile>
pub fn at_path<P>(path: &Path, id: P) -> Option<ImageFile>
where
P: AsRef<str>,
{
if let Ok(image) = ImageImporter::import_from_file(&path) {
Some(ImageFile {
image,
id: id.as_ref().to_owned().replace("\\", "/"),
})
let mut id = id.as_ref().to_owned().replace("\\", "/");
if let Some((before, _)) = id.split_once('.') {
id = before.to_string();
}
if let Ok(image) = ImageImporter::import_from_file(path) {
Some(ImageFile { image, id })
} else {
None
}
@ -34,11 +35,14 @@ impl ImageFile {
}
impl Spritesheet {
pub fn build(
pub fn build<P>(
config: TexturePackerConfig,
images: &[ImageFile],
name: String,
) -> Result<Self, String> {
filename: P,
) -> Result<Self, String>
where
P: AsRef<str>,
{
let mut packer = TexturePacker::new_skyline(config);
for image in images.iter() {
if !packer.can_pack(&image.image) {
@ -54,17 +58,13 @@ impl Spritesheet {
));
}
}
let mut out_vec = vec![];
let exported_image =
texture_packer::exporter::ImageExporter::export(&packer, None).unwrap();
let mut img = image::DynamicImage::new_rgba8(config.max_width, config.max_height);
image::imageops::overlay(&mut img, &exported_image, 0, 0);
let Ok(image_data) = texture_packer::exporter::ImageExporter::export(&packer, None) else {
return Err("Failed to export image".to_owned());
};
img.write_to(&mut Cursor::new(&mut out_vec), image::ImageFormat::Png)
.unwrap();
let atlas_asset = bevy_rpack::AtlasAsset {
size: [img.width(), img.height()],
name,
size: [image_data.width(), image_data.height()],
filename: filename.as_ref().to_owned(),
frames: packer
.get_frames()
.values()
@ -86,9 +86,147 @@ impl Spritesheet {
};
Ok(Spritesheet {
image_data: out_vec.clone(),
image_data,
atlas_asset,
atlas_asset_json,
})
}
#[cfg(feature = "dds")]
pub fn save_as_dds<R>(&self, output_path: R)
where
R: AsRef<str>,
{
let rgba_image = self.image_data.to_rgba8();
let dds = image_dds::dds_from_image(
&rgba_image,
image_dds::ImageFormat::Rgba8Unorm,
image_dds::Quality::Fast,
image_dds::Mipmaps::GeneratedAutomatic,
)
.unwrap();
let mut writer =
std::io::BufWriter::new(std::fs::File::create(output_path.as_ref()).unwrap());
dds.write(&mut writer).unwrap();
}
#[cfg(feature = "basis")]
pub fn save_as_basis<R>(&self, output_path: R)
where
R: AsRef<str>,
{
use basis_universal::{
BasisTextureFormat, Compressor, TranscodeParameters, Transcoder,
TranscoderTextureFormat,
};
use image::{EncodableLayout, GenericImageView};
let rgba_image = self.image_data.to_rgba8();
let channel_count = 4;
let (pixel_width, pixel_height) = self.image_data.dimensions();
let mut compressor_params = basis_universal::CompressorParams::new();
compressor_params.set_generate_mipmaps(true);
compressor_params.set_basis_format(BasisTextureFormat::UASTC4x4);
compressor_params.set_uastc_quality_level(basis_universal::UASTC_QUALITY_DEFAULT);
compressor_params.set_print_status_to_stdout(false);
let mut compressor_image = compressor_params.source_image_mut(0);
compressor_image.init(
rgba_image.as_bytes(),
pixel_width,
pixel_height,
channel_count,
);
//
// Create the compressor and compress
//
let mut compressor = Compressor::default();
let compression_time = unsafe {
compressor.init(&compressor_params);
let t0 = std::time::Instant::now();
compressor.process().unwrap();
let t1 = std::time::Instant::now();
t1 - t0
};
// You could write it to disk like this
let basis_file = compressor.basis_file();
// std::fs::write("example_encoded_image.basis", basis_file).unwrap();
let mut transcoder = Transcoder::new();
let mip_level_count = transcoder.image_level_count(basis_file, 0);
println!(
"Compressed {} mip levels to {} total bytes in {} ms",
mip_level_count,
compressor.basis_file_size(),
compression_time.as_secs_f64() * 1000.0
);
let userdata = transcoder.user_data(basis_file).unwrap();
println!("Basis file has user data {:?}", userdata);
//
// Now lets transcode it back to raw images
//
transcoder.prepare_transcoding(basis_file).unwrap();
let t0 = std::time::Instant::now();
let result = transcoder
.transcode_image_level(
basis_file,
TranscoderTextureFormat::ASTC_4x4_RGBA,
TranscodeParameters {
image_index: 0,
level_index: 0,
..Default::default()
},
)
.unwrap();
let t1 = std::time::Instant::now();
println!(
"Transcoded mip level 0 to ASTC_4x4_RGBA: {} bytes {} ms",
result.len(),
(t1 - t0).as_secs_f64() * 1000.0
);
let t0 = std::time::Instant::now();
let result = transcoder
.transcode_image_level(
basis_file,
TranscoderTextureFormat::RGBA32,
TranscodeParameters {
image_index: 0,
level_index: 0,
..Default::default()
},
)
.unwrap();
let t1 = std::time::Instant::now();
println!(
"Transcoded mip level 0 to RGBA32: {} bytes {} ms",
result.len(),
(t1 - t0).as_secs_f64() * 1000.0
);
transcoder.end_transcoding();
let description = transcoder
.image_level_description(basis_file, 0, 0)
.unwrap();
let image = image::RgbaImage::from_raw(
description.original_width,
description.original_height,
result,
)
.unwrap();
// TODO THIS DOESNT WORK, NEED TO FIX THIS
image
.save_with_format(output_path.as_ref(), image::ImageFormat::Png)
.unwrap();
}
}

View File

@ -1,23 +1,54 @@
use std::io::Write;
use std::{fmt::Display, io::Write, path::Path};
use clap::Parser;
use clap::{Parser, ValueEnum};
use rpack_cli::{ImageFile, Spritesheet};
#[derive(Clone, Debug, Default, Copy, ValueEnum)]
pub enum SaveImageFormat {
#[default]
Png,
Dds,
}
impl Display for SaveImageFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SaveImageFormat::Png => f.write_str(".png"),
SaveImageFormat::Dds => f.write_str(".dds"),
}
}
}
impl From<SaveImageFormat> for image::ImageFormat {
fn from(val: SaveImageFormat) -> Self {
match val {
SaveImageFormat::Png => image::ImageFormat::Png,
SaveImageFormat::Dds => image::ImageFormat::Dds,
}
}
}
/// Build rpack tilemaps with ease
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
/// Name of the tilemap to build, when no value is provided uses 'tilemap'
#[arg(short, long)]
#[arg(action)]
name: Option<String>,
/// size of the tilemap, default: 512
#[arg(long)]
size: Option<u32>,
/// Image format
#[clap(short, long)]
format: Option<SaveImageFormat>,
}
fn main() {
let args = Args::parse();
let name = args.name.unwrap_or("tilemap".to_owned());
let format = args.format.unwrap_or_default();
let atlas_filename = format!("{}{}", name, format);
let atlas_json_filename = format!("{}.png", name);
let size = args.size.unwrap_or(512);
let images: Vec<ImageFile> = glob::glob("**/*png")
@ -38,23 +69,41 @@ fn main() {
texture_outlines: false,
},
&images,
name.clone(),
&atlas_filename,
)
.expect("Failed to build spritesheet");
let mut file = std::fs::File::create(format!("{}.png", name)).unwrap();
let write_result = file.write_all(&spritesheet.image_data);
if Path::new(&atlas_json_filename).exists() {
std::fs::remove_file(&atlas_json_filename).expect("Could not remove the old file");
}
if Path::new(&atlas_filename).exists() {
std::fs::remove_file(&atlas_filename).expect("Could not remove the old file");
}
match format {
SaveImageFormat::Dds => {
#[cfg(feature = "dds")]
spritesheet.save_as_dds(&atlas_filename);
#[cfg(not(feature = "dds"))]
panic!("Program is compiled without support for dds. Compile it yourself with feature `dds` enabled.");
}
f => {
let write_result = spritesheet
.image_data
.save_with_format(&atlas_filename, f.into());
if write_result.is_err() {
eprintln!(
"Could not make atlas, error: {:?}",
write_result.unwrap_err()
);
} else {
println!("Output texture stored in {:?}", file);
println!("Output texture stored in {}", atlas_json_filename);
}
}
}
let json = serde_json::to_string_pretty(&spritesheet.atlas_asset_json).unwrap();
let mut file = std::fs::File::create(format!("{}.rpack.json", name)).unwrap();
let write_result = file.write_all(&json.as_bytes());
let write_result = file.write_all(json.as_bytes());
if write_result.is_err() {
eprintln!(
"Could not make atlas, error: {:?}",