Compare commits
21 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
067bde3454 | |
|
|
c526585f77 | |
|
|
3576df7d27 | |
|
|
d9bfa6e639 | |
|
|
b9729d8579 | |
|
|
6483ebfc56 | |
|
|
760dded5eb | |
|
|
6a19b0fbb0 | |
|
|
1d7e43fa5c | |
|
|
c3b959f632 | |
|
|
c46de6ebae | |
|
|
4868671e78 | |
|
|
8ef65376b8 | |
|
|
6e75fff4e4 | |
|
|
08aecd4004 | |
|
|
ef54eef2e0 | |
|
|
a9426fc3b9 | |
|
|
25fa59820f | |
|
|
5c963e1d9d | |
|
|
533ad95e11 | |
|
|
5851f52780 |
31
CHANGELOG.md
31
CHANGELOG.md
|
|
@ -1,10 +1,39 @@
|
|||
# Changelog
|
||||
|
||||
## [0.4.1]
|
||||
|
||||
### Fixed
|
||||
|
||||
- Improved material parsing, big thanks to [bevity](https://github.com/gamedolphin/bevity).
|
||||
|
||||
## [0.4.0]
|
||||
|
||||
### Added
|
||||
|
||||
- New flag `--get_materials_from_prefabs` for updating model textures based on prefabs and materials.
|
||||
|
||||
## [0.3.0]
|
||||
|
||||
### Added
|
||||
|
||||
- New flag `--copy-meta-files` for copying meta files alongside assets.
|
||||
|
||||
### Changed
|
||||
|
||||
- Multithreaded unpacking improvements.
|
||||
- Split code.
|
||||
|
||||
## [0.2.1]
|
||||
|
||||
### Added
|
||||
|
||||
- Working deploy for major platforms.
|
||||
|
||||
## [0.2.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Ignoring extensions during unpacking
|
||||
- Ignoring extensions during unpacking.
|
||||
|
||||
## [0.1.0]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,66 +1,88 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.5"
|
||||
version = "0.6.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
|
||||
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.4"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.3"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.2"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.2"
|
||||
version = "3.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
|
||||
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
name = "anyhow"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
|
|
@ -70,9 +92,27 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
|
@ -82,9 +122,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.11"
|
||||
version = "4.5.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
|
||||
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -92,9 +132,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.11"
|
||||
version = "4.5.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
|
||||
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -104,9 +144,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
version = "4.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
@ -116,164 +156,301 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.4"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.16"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.17"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.8"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.23"
|
||||
name = "fdeflate"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
|
||||
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"libredox",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
|
||||
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
name = "gltf"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
checksum = "e3ce1918195723ce6ac74e80542c5a96a40c2b26162c1957a5cd70799b8cacf7"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"byteorder",
|
||||
"gltf-json",
|
||||
"image",
|
||||
"lazy_static",
|
||||
"serde_json",
|
||||
"urlencoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gltf-derive"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14070e711538afba5d6c807edb74bcb84e5dbb9211a3bf5dea0dfab5b24f4c51"
|
||||
dependencies = [
|
||||
"inflections",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gltf-json"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6176f9d60a7eab0a877e8e96548605dedbde9190a7ae1e80bbcc1c9af03ab14"
|
||||
dependencies = [
|
||||
"gltf-derive",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"num-traits",
|
||||
"png",
|
||||
"zune-core",
|
||||
"zune-jpeg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflections"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a257582fdcde896fd96463bf2d40eefea0580021c0712a0e2b028b60b47a837a"
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
version = "0.2.169"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.12"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "lwa_unity_unpack"
|
||||
version = "0.2.0"
|
||||
version = "0.4.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"flate2",
|
||||
"gltf",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"tar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.1"
|
||||
name = "png"
|
||||
version = "0.17.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
|
||||
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"bitflags 1.3.2",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.70"
|
||||
version = "1.0.92"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
|
||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
|
@ -281,9 +458,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.0"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
|
|
@ -291,20 +468,49 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
version = "0.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.28"
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
|
|
@ -312,16 +518,73 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.217"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.134"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.41"
|
||||
version = "2.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269"
|
||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -330,9 +593,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.40"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b16afcea1f22891c49a00c751c7b63b2233284064f11a200fc624137c51e2ddb"
|
||||
checksum = "c65998313f8e17d0d553d28f91a0df93e4dbbbf770279c7bc21ca0f09ea1a1f6"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
|
|
@ -341,34 +604,47 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "urlencoding"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
|
|
@ -377,53 +653,74 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.0"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
version = "1.1.3"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995"
|
||||
checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
||||
|
||||
[[package]]
|
||||
name = "zune-jpeg"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028"
|
||||
dependencies = [
|
||||
"zune-core",
|
||||
]
|
||||
|
|
|
|||
13
Cargo.toml
13
Cargo.toml
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "lwa_unity_unpack"
|
||||
version = "0.2.0"
|
||||
version = "0.4.1"
|
||||
edition = "2021"
|
||||
repository = "https://github.com/Leinnan/lwa_unity_unpack"
|
||||
homepage = "https://github.com/Leinnan/lwa_unity_unpack"
|
||||
|
|
@ -20,7 +20,12 @@ lto = true
|
|||
opt-level = 2
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
flate2 = "1.0"
|
||||
rayon = "1.8.0"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
flate2 = "1"
|
||||
gltf = "1"
|
||||
rayon = "1"
|
||||
regex = "1"
|
||||
tar = "0.4"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_yaml = "0.9"
|
||||
anyhow = "1"
|
||||
|
|
|
|||
|
|
@ -16,8 +16,12 @@ Options:
|
|||
-i, --input <INPUT> .unitypackage file to extract
|
||||
-o, --output <OUTPUT> target directory
|
||||
-f, --fbx-to-gltf <FBX_TO_GLTF> optional- path to the tool that will auto convert fbx files to gltf during unpacking
|
||||
--get-materials-from-prefabs
|
||||
checks if material base texture in prefabs differ from the one specified in fbx model that is converted to GLTF and overrides it with the one from prefab and copy texture to models folder
|
||||
--ignore-extensions <IGNORE_EXTENSIONS>
|
||||
optional- extensions that will be ignored during unpacking
|
||||
--copy-meta-files
|
||||
copy meta files alongside regular files
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
|
|
@ -28,7 +32,9 @@ Options:
|
|||
|
||||
## Install
|
||||
|
||||
For now Rust Cargo is required:
|
||||
It can be downloaded by going to Releases page.
|
||||
|
||||
It can be also installed using Rust Cargo:
|
||||
|
||||
```sh
|
||||
cargo install lwa_unity_unpack
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
use clap::Parser;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Program for unpacking unitypackages files.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
/// .unitypackage file to extract
|
||||
#[arg(short, long)]
|
||||
pub input: PathBuf,
|
||||
/// target directory
|
||||
#[arg(short, long)]
|
||||
pub output: PathBuf,
|
||||
|
||||
/// optional- path to the tool that will auto convert fbx files to gltf during unpacking
|
||||
#[arg(long)]
|
||||
pub fbx_to_gltf: Option<PathBuf>,
|
||||
|
||||
/// checks if material base texture in prefabs differ from the one specified in fbx model
|
||||
/// that is converted to GLTF and overrides it with the one from prefab and copy texture to models folder
|
||||
#[arg(long, default_value = "false", default_missing_value = "true")]
|
||||
pub get_materials_from_prefabs: bool,
|
||||
|
||||
/// optional- extensions that will be ignored during unpacking
|
||||
#[arg(long, action = clap::ArgAction::Append)]
|
||||
pub ignore_extensions: Option<Vec<String>>,
|
||||
|
||||
/// copy meta files alongside regular files
|
||||
#[arg(long, default_value = "false", default_missing_value = "true")]
|
||||
pub copy_meta_files: bool,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn check(&self) {
|
||||
if let Some(path) = &self.fbx_to_gltf {
|
||||
assert!(
|
||||
is_executable(&path),
|
||||
"fbx_to_gltf require a path to executable"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn is_executable(path: &PathBuf) -> bool {
|
||||
if let Some(extension) = path.extension() {
|
||||
extension.to_str().unwrap().ends_with("exe")
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn is_executable(path: &PathBuf) -> bool {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
if let Ok(metadata) = std::fs::metadata(path) {
|
||||
let permissions = metadata.permissions();
|
||||
permissions.mode() & 0o111 != 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
use crate::primitives::materials::read_single_material;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs;
|
||||
use std::fs::DirEntry;
|
||||
use std::fs::File;
|
||||
use std::io::BufRead;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Asset {
|
||||
pub extension: Option<String>,
|
||||
pub guid: String,
|
||||
pub path: String,
|
||||
pub has_meta: bool,
|
||||
pub asset_type: AssetType,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
pub enum AssetType {
|
||||
FbxModel,
|
||||
Material,
|
||||
Prefab,
|
||||
Scene,
|
||||
Other(String),
|
||||
}
|
||||
|
||||
impl Asset {
|
||||
pub fn try_get_mat_texture_guid(&self) -> Option<String> {
|
||||
match &self.asset_type {
|
||||
AssetType::Material => {}
|
||||
_ => return None,
|
||||
}
|
||||
let content = fs::read_to_string(&self.path).unwrap();
|
||||
let material = read_single_material(&content);
|
||||
if let Ok(mat) = material {
|
||||
return mat
|
||||
.properties
|
||||
.tex_envs
|
||||
.iter()
|
||||
.find_map(|tex| tex.get("_MainTex"))
|
||||
.and_then(|t| t.texture.guid.clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn prepare_directory(&self) {
|
||||
println!("{}: {:?}", self.guid, self.path);
|
||||
let base_path = Path::new(&self.path);
|
||||
let result_dir = base_path.parent();
|
||||
if result_dir.is_none() {
|
||||
eprintln!("{} is none", &self.path);
|
||||
}
|
||||
let result_dir = result_dir.unwrap();
|
||||
if !result_dir.exists() {
|
||||
let result = fs::create_dir_all(result_dir);
|
||||
if result.is_err() {
|
||||
eprintln!(
|
||||
"Error {}: {}",
|
||||
result_dir.to_str().unwrap(),
|
||||
result.err().unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_path(entry: &DirEntry, output_dir: &Path) -> Option<Asset> {
|
||||
let root_file = entry.path();
|
||||
if !root_file.is_dir() {
|
||||
return None;
|
||||
}
|
||||
let guid = entry.file_name().into_string().unwrap();
|
||||
let mut real_path = String::new();
|
||||
let mut extension = None;
|
||||
let mut has_asset = false;
|
||||
let mut has_meta = false;
|
||||
for sub_entry in fs::read_dir(root_file.clone()).unwrap() {
|
||||
let sub_entry = sub_entry.unwrap();
|
||||
let file_name = sub_entry.file_name().into_string().unwrap();
|
||||
match file_name.as_str() {
|
||||
"pathname" => {
|
||||
let path = sub_entry.path();
|
||||
let file = File::open(path).unwrap();
|
||||
let buf_reader = BufReader::new(file);
|
||||
let line = buf_reader.lines().next();
|
||||
match line {
|
||||
Some(Ok(path)) => {
|
||||
real_path = output_dir.join(path).to_str().unwrap().to_string();
|
||||
if let Some(e) =
|
||||
Path::new(&real_path).extension().and_then(OsStr::to_str)
|
||||
{
|
||||
extension = Some(String::from(e));
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
"asset" => has_asset = true,
|
||||
"asset.meta" => has_meta = true,
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
if has_asset {
|
||||
let asset_type = match &extension {
|
||||
Some(str) => match str.as_str() {
|
||||
"fbx" => AssetType::FbxModel,
|
||||
"prefab" => AssetType::Prefab,
|
||||
"unity" => AssetType::Scene,
|
||||
"mat" => AssetType::Material,
|
||||
_ => AssetType::Other(str.clone()),
|
||||
},
|
||||
_ => AssetType::Other(String::new()),
|
||||
};
|
||||
Some(Asset {
|
||||
extension,
|
||||
guid,
|
||||
path: real_path,
|
||||
has_meta,
|
||||
asset_type,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
182
src/main.rs
182
src/main.rs
|
|
@ -1,173 +1,19 @@
|
|||
use flate2::read::GzDecoder;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{fs, io, sync::Arc};
|
||||
use tar::Archive;
|
||||
|
||||
mod args;
|
||||
pub mod asset;
|
||||
pub mod primitives;
|
||||
mod unpacker;
|
||||
mod yaml_helpers;
|
||||
use clap::Parser;
|
||||
use rayon::prelude::*;
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::process::Command;
|
||||
|
||||
/// Program for unpacking unitypackages files.
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// .unitypackage file to extract
|
||||
#[arg(short, long)]
|
||||
input: PathBuf,
|
||||
/// target directory
|
||||
#[arg(short, long)]
|
||||
output: PathBuf,
|
||||
|
||||
/// optional- path to the tool that will auto convert fbx files to gltf during unpacking
|
||||
#[arg(short, long)]
|
||||
fbx_to_gltf: Option<PathBuf>,
|
||||
|
||||
/// optional- extensions that will be ignored during unpacking
|
||||
#[arg(long, action = clap::ArgAction::Append)]
|
||||
ignore_extensions: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub fn extract_archive(archive_path: &Path, extract_to: &Path) -> io::Result<()> {
|
||||
let tar_gz = File::open(archive_path)?;
|
||||
let tar = GzDecoder::new(tar_gz);
|
||||
let mut archive = Archive::new(tar);
|
||||
archive.unpack(extract_to)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Args = Args::parse();
|
||||
let ignored_extensions = args.ignore_extensions.unwrap_or_default();
|
||||
let archive_path = Path::new(&args.input);
|
||||
let tmp_dir = Path::new("./tmp_dir");
|
||||
let output_dir = Path::new(&args.output);
|
||||
if !archive_path.exists() {
|
||||
panic!("Input file does not exits");
|
||||
}
|
||||
if tmp_dir.exists() {
|
||||
println!("Temp directory exits, cleaning up first.");
|
||||
fs::remove_dir_all(tmp_dir).unwrap();
|
||||
}
|
||||
if let Err(e) = extract_archive(archive_path, tmp_dir) {
|
||||
println!("Failed to extract archive: {}", e);
|
||||
}
|
||||
if output_dir.exists() {
|
||||
println!("Output directory exits, cleaning up first.");
|
||||
fs::remove_dir_all(output_dir).unwrap();
|
||||
}
|
||||
fs::create_dir(output_dir).unwrap();
|
||||
let mut mapping: HashMap<String, String> = HashMap::new();
|
||||
let args = crate::args::Args::parse();
|
||||
let mut unpacker = crate::unpacker::Unpacker {
|
||||
args,
|
||||
assets: vec![],
|
||||
};
|
||||
|
||||
for entry in fs::read_dir(tmp_dir).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let root_file = entry.path();
|
||||
let asset = entry.file_name().into_string().unwrap();
|
||||
if root_file.is_dir() {
|
||||
let mut real_path = String::new();
|
||||
let mut extension = None;
|
||||
let mut has_asset = false;
|
||||
for sub_entry in fs::read_dir(root_file.clone()).unwrap() {
|
||||
let sub_entry = sub_entry.unwrap();
|
||||
let file_name = sub_entry.file_name().into_string().unwrap();
|
||||
if file_name == "pathname" {
|
||||
let path = sub_entry.path();
|
||||
let file = File::open(path).unwrap();
|
||||
let buf_reader = BufReader::new(file);
|
||||
let line = buf_reader.lines().next();
|
||||
match line {
|
||||
Some(Ok(path)) => {
|
||||
real_path = path;
|
||||
if let Some(e) =
|
||||
Path::new(&real_path).extension().and_then(OsStr::to_str)
|
||||
{
|
||||
extension = Some(String::from(e));
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
} else if file_name == "asset" {
|
||||
has_asset = true;
|
||||
}
|
||||
}
|
||||
if has_asset && !ignored_extensions.contains(&extension.unwrap_or_default()) {
|
||||
mapping.insert(asset, real_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("Results:");
|
||||
let mapping_arc = Arc::new(mapping);
|
||||
let tmp_dir = Arc::new(tmp_dir);
|
||||
let output_dir = Arc::new(output_dir);
|
||||
|
||||
mapping_arc.par_iter().for_each(|(asset_hash, asset_path)| {
|
||||
let path = Path::new(asset_path);
|
||||
let source_asset = Path::new(&*tmp_dir).join(asset_hash).join("asset");
|
||||
let result_path = output_dir.join(path);
|
||||
|
||||
process_directory(asset_hash, asset_path, &result_path);
|
||||
check_source_asset_exists(&source_asset);
|
||||
|
||||
if args.fbx_to_gltf.is_some() {
|
||||
if let Some("fbx") = path.extension().and_then(OsStr::to_str) {
|
||||
process_fbx_file(
|
||||
&source_asset,
|
||||
&result_path,
|
||||
&args.fbx_to_gltf.clone().unwrap(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
process_non_fbx_file(&source_asset, &result_path);
|
||||
});
|
||||
|
||||
fs::remove_dir_all(Path::new(&*tmp_dir)).unwrap();
|
||||
|
||||
fn process_directory(asset_hash: &str, asset_path: &str, result_path: &Path) {
|
||||
println!("{}: {:?}", asset_hash, asset_path);
|
||||
let result_dir = result_path.parent().unwrap();
|
||||
if !result_dir.exists() {
|
||||
fs::create_dir_all(result_dir).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn check_source_asset_exists(source_asset: &Path) {
|
||||
if !source_asset.exists() {
|
||||
panic!("SOURCE ASSET DOES NOT EXIST: {}", source_asset.display());
|
||||
}
|
||||
}
|
||||
|
||||
fn process_fbx_file(source_asset: &Path, result_path: &Path, tool: &PathBuf) {
|
||||
let out_path = result_path.with_extension("");
|
||||
println!(
|
||||
"{:?}",
|
||||
&[
|
||||
"--input",
|
||||
source_asset.to_str().unwrap(),
|
||||
"--output",
|
||||
out_path.to_str().unwrap()
|
||||
]
|
||||
);
|
||||
let output = Command::new(tool)
|
||||
.args([
|
||||
"--input",
|
||||
source_asset.to_str().unwrap(),
|
||||
"-b",
|
||||
"--output",
|
||||
out_path.to_str().unwrap(),
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
let output_result = String::from_utf8_lossy(&output.stdout);
|
||||
println!("output: {}", output_result);
|
||||
}
|
||||
|
||||
fn process_non_fbx_file(source_asset: &Path, result_path: &Path) {
|
||||
fs::rename(source_asset, result_path).unwrap();
|
||||
}
|
||||
unpacker.prepare_environment();
|
||||
unpacker.extract();
|
||||
unpacker.process_data();
|
||||
unpacker.update_gltf_materials();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
use crate::primitives::reference::FileReference;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
// use bevy::prelude::*;
|
||||
use crate::yaml_helpers::parse_unity_yaml;
|
||||
use anyhow::{bail, Context, Result};
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||
pub struct UnityMaterial {
|
||||
#[serde(alias = "m_Name")]
|
||||
pub name: String,
|
||||
|
||||
#[serde(alias = "m_Shader")]
|
||||
pub shader: FileReference,
|
||||
|
||||
#[serde(alias = "m_SavedProperties")]
|
||||
pub properties: SavedProperties,
|
||||
|
||||
#[serde(default, alias = "stringTagMap")]
|
||||
pub string_tags: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||
pub struct SavedProperties {
|
||||
#[serde(alias = "serializedVersion")]
|
||||
pub serialized_version: u64,
|
||||
|
||||
#[serde(alias = "m_TexEnvs")]
|
||||
pub tex_envs: Vec<HashMap<String, TextureInfo>>,
|
||||
|
||||
#[serde(alias = "m_Floats")]
|
||||
pub floats: Vec<HashMap<String, f32>>,
|
||||
|
||||
#[serde(alias = "m_Colors")]
|
||||
pub colors: Vec<HashMap<String, UnityColor>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug)]
|
||||
pub struct TextureInfo {
|
||||
#[serde(alias = "m_Texture")]
|
||||
pub texture: FileReference,
|
||||
#[serde(alias = "m_Scale")]
|
||||
pub scale: UnityVector2,
|
||||
#[serde(alias = "m_Offset")]
|
||||
pub offset: UnityVector2,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Copy, Clone)]
|
||||
pub struct UnityVector2 {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Copy, Clone)]
|
||||
pub struct UnityColor {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
pub b: f32,
|
||||
pub a: f32,
|
||||
}
|
||||
|
||||
// impl From<UnityColor> for Color {
|
||||
// fn from(value: UnityColor) -> Self {
|
||||
// Color::Rgba {
|
||||
// red: value.r,
|
||||
// green: value.g,
|
||||
// blue: value.b,
|
||||
// alpha: value.a,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// impl From<&UnityColor> for Color {
|
||||
// fn from(value: &UnityColor) -> Self {
|
||||
// Color::Rgba {
|
||||
// red: value.r,
|
||||
// green: value.g,
|
||||
// blue: value.b,
|
||||
// alpha: value.a,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(tag = "object_type")]
|
||||
enum MaterialContainer {
|
||||
Material(UnityMaterial),
|
||||
#[serde(other)]
|
||||
DontCare,
|
||||
}
|
||||
|
||||
pub fn read_single_material(contents: &str) -> Result<UnityMaterial> {
|
||||
let map = parse_unity_yaml(contents)?;
|
||||
|
||||
let (_, output) = map.into_iter().next().context("0 items in material file")?;
|
||||
|
||||
let MaterialContainer::Material(mat) = output else {
|
||||
bail!("invalid material file");
|
||||
};
|
||||
|
||||
Ok(mat)
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
pub mod materials;
|
||||
pub mod reference;
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
use serde::{
|
||||
de::{self, Visitor},
|
||||
Deserialize, Deserializer, Serialize,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||
pub struct FileReference {
|
||||
#[serde(alias = "fileID")]
|
||||
pub file_id: i64,
|
||||
#[serde(default, deserialize_with = "deserialize_option_string_or_float")]
|
||||
pub guid: Option<String>,
|
||||
}
|
||||
|
||||
fn deserialize_option_string_or_float<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct StringOrFloat;
|
||||
|
||||
impl<'de> Visitor<'de> for StringOrFloat {
|
||||
type Value = Option<String>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("a string or a float")
|
||||
}
|
||||
|
||||
fn visit_str<E: de::Error>(self, value: &str) -> Result<Self::Value, E> {
|
||||
Ok(Some(value.to_owned()))
|
||||
}
|
||||
|
||||
fn visit_string<E: de::Error>(self, value: String) -> Result<Self::Value, E> {
|
||||
Ok(Some(value))
|
||||
}
|
||||
|
||||
fn visit_f64<E: de::Error>(self, _: f64) -> Result<Self::Value, E> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_f32<E: de::Error>(self, _: f32) -> Result<Self::Value, E> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(StringOrFloat)
|
||||
}
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
use crate::asset::{Asset, AssetType};
|
||||
use flate2::read::GzDecoder;
|
||||
use gltf::{json, Document};
|
||||
use rayon::prelude::*;
|
||||
use std::borrow::Cow;
|
||||
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use std::sync::mpsc::channel;
|
||||
use std::sync::Arc;
|
||||
use std::{fs, io};
|
||||
use tar::Archive;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Unpacker {
|
||||
pub args: crate::args::Args,
|
||||
pub assets: Vec<Asset>,
|
||||
}
|
||||
|
||||
impl Unpacker {
|
||||
pub fn prepare_environment(&self) {
|
||||
self.args.check();
|
||||
let archive_path = Path::new(&self.args.input);
|
||||
let output_dir = Path::new(&self.args.output);
|
||||
let tmp_path = Path::new("./tmp_dir");
|
||||
if !archive_path.exists() {
|
||||
panic!("Input file does not exits");
|
||||
}
|
||||
if tmp_path.exists() {
|
||||
println!("Temp directory exits, cleaning up first.");
|
||||
fs::remove_dir_all(tmp_path).unwrap();
|
||||
}
|
||||
if output_dir.exists() {
|
||||
println!("Output directory exits, cleaning up first.");
|
||||
fs::remove_dir_all(output_dir).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extract(&mut self) {
|
||||
let archive_path = Path::new(&self.args.input);
|
||||
let tmp_path = Path::new("./tmp_dir");
|
||||
let output_dir = Path::new(&self.args.output);
|
||||
|
||||
if let Err(e) = Unpacker::extract_archive(archive_path, tmp_path) {
|
||||
println!("Failed to extract archive: {}", e);
|
||||
}
|
||||
|
||||
let (sender, receiver) = channel();
|
||||
let ignored_extensions = self.args.clone().ignore_extensions.unwrap_or_default();
|
||||
|
||||
fs::read_dir(tmp_path)
|
||||
.unwrap()
|
||||
.par_bridge()
|
||||
.for_each_with(sender, |s, entry| {
|
||||
let entry = entry.unwrap();
|
||||
let asset = crate::asset::Asset::from_path(&entry, output_dir);
|
||||
if let Some(asset) = asset {
|
||||
let extension = &asset.extension.clone().unwrap_or_default();
|
||||
if !ignored_extensions.contains(extension) {
|
||||
s.send(asset).unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
self.assets = receiver.iter().collect();
|
||||
}
|
||||
|
||||
pub fn assets_of_type(&self, asset_type: AssetType) -> Vec<Asset> {
|
||||
self.assets
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|a| a.asset_type == asset_type)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn update_gltf_materials(&self) {
|
||||
if self.args.fbx_to_gltf.is_none() || !self.args.get_materials_from_prefabs {
|
||||
return;
|
||||
}
|
||||
let fbx_models = self.assets_of_type(AssetType::FbxModel);
|
||||
let prefabs = self.assets_of_type(AssetType::Prefab);
|
||||
let materials = self.assets_of_type(AssetType::Material);
|
||||
println!(
|
||||
"There are {} models, {} prefabs and {} materials",
|
||||
fbx_models.len(),
|
||||
prefabs.len(),
|
||||
materials.len()
|
||||
);
|
||||
|
||||
prefabs.par_iter().for_each(|prefab| {
|
||||
let path = Path::new(&prefab.path);
|
||||
let prefab_content = fs::read_to_string(path).unwrap();
|
||||
let matching_materials: Vec<Asset> = materials
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|a| prefab_content.contains(&a.guid))
|
||||
.collect();
|
||||
let matching_models: Vec<Asset> = fbx_models
|
||||
.clone()
|
||||
.into_iter()
|
||||
.filter(|a| prefab_content.contains(&a.guid))
|
||||
.collect();
|
||||
if matching_materials.len() != 1 || 1 != matching_models.len() {
|
||||
return;
|
||||
}
|
||||
let material = matching_materials.first().unwrap();
|
||||
let model: &Asset = matching_models.first().unwrap();
|
||||
let texture_guid: Option<String> = material.try_get_mat_texture_guid();
|
||||
|
||||
let texture_asset: &Asset = match &texture_guid {
|
||||
Some(guid) => self.assets.iter().find(|a| guid.eq(&a.guid)).unwrap(),
|
||||
None => return,
|
||||
};
|
||||
// here we should read gltf file and replace material texture with Uri based on texture_asset
|
||||
let model_path = Path::new(&model.path).with_extension("glb");
|
||||
Self::update_material(&model_path, Path::new(&texture_asset.path));
|
||||
});
|
||||
}
|
||||
|
||||
fn align_to_multiple_of_four(n: &mut usize) {
|
||||
*n = (*n + 3) & !3;
|
||||
}
|
||||
|
||||
fn update_material(gltf_path: &Path, texture_asset: &Path) {
|
||||
let file = fs::File::open(gltf_path).unwrap();
|
||||
let reader = io::BufReader::new(file);
|
||||
let mut gltf = gltf::Gltf::from_reader(reader).unwrap();
|
||||
let mut json = gltf.document.into_json();
|
||||
for image in json.images.iter_mut() {
|
||||
let result = texture_asset
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let required_file = gltf_path.with_file_name(&result);
|
||||
if !required_file.exists() {
|
||||
fs::copy(texture_asset, gltf_path.with_file_name(&result)).unwrap();
|
||||
}
|
||||
if let Some(old_path) = &image.uri {
|
||||
if old_path.eq(&result) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
println!(
|
||||
"Image{:?}: {:?} to be replaced with: {}",
|
||||
image.name, image.uri, &result
|
||||
);
|
||||
image.uri = Some(result);
|
||||
}
|
||||
|
||||
gltf.document = Document::from_json(json.clone()).unwrap();
|
||||
// Save the modified glTF
|
||||
let json_string = json::serialize::to_string(&json).expect("Serialization error");
|
||||
let mut json_offset = json_string.len();
|
||||
Self::align_to_multiple_of_four(&mut json_offset);
|
||||
let blob = gltf.blob.clone().unwrap_or_default();
|
||||
let buffer_length = blob.len();
|
||||
let glb = gltf::binary::Glb {
|
||||
header: gltf::binary::Header {
|
||||
magic: *b"glTF",
|
||||
version: 2,
|
||||
// N.B., the size of binary glTF file is limited to range of `u32`.
|
||||
length: (json_offset + buffer_length)
|
||||
.try_into()
|
||||
.expect("file size exceeds binary glTF limit"),
|
||||
},
|
||||
bin: Some(Cow::Owned(gltf.blob.unwrap_or_default())),
|
||||
json: Cow::Owned(json_string.into_bytes()),
|
||||
};
|
||||
let writer = std::fs::File::create(gltf_path).expect("I/O error");
|
||||
glb.to_writer(writer).expect("glTF binary output error");
|
||||
}
|
||||
|
||||
pub fn process_data(&self) {
|
||||
let output_dir = Path::new(&self.args.output);
|
||||
let copy_meta_files = self.args.copy_meta_files;
|
||||
let tmp_path = Path::new("./tmp_dir");
|
||||
|
||||
let tmp_dir = Arc::new(tmp_path);
|
||||
fs::create_dir(output_dir).unwrap();
|
||||
|
||||
self.assets.par_iter().for_each(|asset| {
|
||||
let asset_hash = &asset.guid;
|
||||
let path = Path::new(&asset.path);
|
||||
let source_asset = Path::new(&*tmp_dir).join(asset_hash).join("asset");
|
||||
|
||||
asset.prepare_directory();
|
||||
if copy_meta_files && asset.has_meta {
|
||||
let source_meta = Path::new(&*tmp_dir).join(asset_hash).join("asset.meta");
|
||||
let mut meta_path = asset.path.clone();
|
||||
meta_path.push_str(".meta");
|
||||
fs::rename(source_meta, meta_path).unwrap();
|
||||
}
|
||||
|
||||
if !source_asset.exists() {
|
||||
panic!("SOURCE ASSET DOES NOT EXIST: {}", source_asset.display());
|
||||
}
|
||||
|
||||
if self.args.fbx_to_gltf.is_some() && asset.asset_type == AssetType::FbxModel {
|
||||
self.process_fbx_file(&source_asset, path);
|
||||
} else {
|
||||
fs::rename(source_asset, path).unwrap();
|
||||
}
|
||||
});
|
||||
|
||||
fs::remove_dir_all(Path::new(&*tmp_dir)).unwrap();
|
||||
}
|
||||
|
||||
fn process_fbx_file(&self, source_asset: &Path, result_path: &Path) {
|
||||
let tool = self.args.fbx_to_gltf.clone().unwrap();
|
||||
let out_path = result_path.with_extension("");
|
||||
let _output = Command::new(tool)
|
||||
.args([
|
||||
"--input",
|
||||
source_asset.to_str().unwrap(),
|
||||
"-b",
|
||||
"--output",
|
||||
out_path.to_str().unwrap(),
|
||||
])
|
||||
.output()
|
||||
.unwrap();
|
||||
println!(
|
||||
"Fbx converted to GLTF: {}",
|
||||
out_path.with_extension("glb").to_str().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
fn extract_archive(archive_path: &Path, extract_to: &Path) -> io::Result<()> {
|
||||
let tar_gz = File::open(archive_path)?;
|
||||
let tar = GzDecoder::new(tar_gz);
|
||||
let mut archive = Archive::new(tar);
|
||||
archive.unpack(extract_to)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
use anyhow::Result;
|
||||
use serde::de::DeserializeOwned;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn parse_unity_yaml<T: DeserializeOwned>(file: &str) -> Result<HashMap<i64, T>> {
|
||||
let file = cleanup_unity_yaml(file)?;
|
||||
let parse: HashMap<i64, T> = serde_yaml::from_str(&file)?;
|
||||
|
||||
Ok(parse)
|
||||
}
|
||||
|
||||
fn cleanup_unity_yaml(yaml: &str) -> Result<String> {
|
||||
let lines: Vec<String> = yaml
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
if line.starts_with("%YAML") || line.starts_with("%TAG") {
|
||||
// unity specific headers. SKIP!
|
||||
None
|
||||
} else if line.starts_with("--- !u!") {
|
||||
// unity object id declared on this line
|
||||
// --- !u!104 &2 => 104 is object type and 2 is object id
|
||||
let mut splits = line.split_whitespace();
|
||||
let object_id: i64 = splits
|
||||
.find(|&part| part.starts_with('&'))
|
||||
.and_then(|num| num[1..].parse().ok())?;
|
||||
|
||||
Some(format!("{}:", object_id))
|
||||
} else if line.starts_with(' ') {
|
||||
Some(line.to_string())
|
||||
} else {
|
||||
Some(format!(" object_type: {}", line.replace(':', "")))
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut lines = lines.join("\n");
|
||||
|
||||
lines.push('\n'); // insert new line at the end
|
||||
|
||||
Ok(lines)
|
||||
}
|
||||
Loading…
Reference in New Issue