Add WIP model parser (works for levels and Blender importer
This commit is contained in:
parent
45f38885ec
commit
8e0df74541
6 changed files with 2365 additions and 0 deletions
802
tools/remaster/scrap_parse/Cargo.lock
generated
Normal file
802
tools/remaster/scrap_parse/Cargo.lock
generated
Normal file
|
@ -0,0 +1,802 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
|
||||
|
||||
[[package]]
|
||||
name = "array-init"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "binrw"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "272caaf6e0bfb7d508c0606e541e2c68f85c0d6352b62d0b299924eed59fe384"
|
||||
dependencies = [
|
||||
"array-init",
|
||||
"binrw_derive",
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binrw_derive"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb4b28c1e534d96213c8966bb9240095757aa0909128985f97d16afd2e7257a8"
|
||||
dependencies = [
|
||||
"either",
|
||||
"owo-colors",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-humanize"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32dce1ea1988dbdf9f9815ff11425828523bd2a134ec0805d2ac8af26ee6096e"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"is-terminal",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||
dependencies = [
|
||||
"termcolor",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "configparser"
|
||||
version = "3.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5458d9d1a587efaf5091602c59d299696a3877a439c8f6d461a2d3cce11df87a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
"cxxbridge-macro",
|
||||
"link-cplusplus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"scratch",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno-dragonfly"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs-err"
|
||||
version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.53"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||
dependencies = [
|
||||
"cxx",
|
||||
"cxx-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||
dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a53d79ba8304ac1c4f9eb3b9d281f21f7be9d4626f72ce7df4ad8fbde4f38a74"
|
||||
dependencies = [
|
||||
"modular-bitfield-impl",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "modular-bitfield-impl"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rhexdump"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5e9af64574935e39f24d1c0313a997c8b880ca0e087c888bc6af8af31579847"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
|
||||
|
||||
[[package]]
|
||||
name = "scrap_parse"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"binrw",
|
||||
"chrono",
|
||||
"chrono-humanize",
|
||||
"clap",
|
||||
"configparser",
|
||||
"flate2",
|
||||
"fs-err",
|
||||
"indexmap",
|
||||
"modular-bitfield",
|
||||
"rhexdump",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.84"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.45.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
21
tools/remaster/scrap_parse/Cargo.toml
Normal file
21
tools/remaster/scrap_parse/Cargo.toml
Normal file
|
@ -0,0 +1,21 @@
|
|||
[package]
|
||||
name = "scrap_parse"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.69"
|
||||
binrw = "0.11.1"
|
||||
chrono = { version = "0.4.23", features = ["serde"] }
|
||||
chrono-humanize = "0.2.2"
|
||||
clap = { version = "4.1.6", features = ["derive"] }
|
||||
configparser = { version = "3.0.2", features = ["indexmap"] }
|
||||
flate2 = "1.0.25"
|
||||
fs-err = "2.9.0"
|
||||
indexmap = { version = "1.9.2", features = ["serde"] }
|
||||
modular-bitfield = "0.11.2"
|
||||
rhexdump = "0.1.1"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = { version = "1.0.93", features = ["unbounded_depth"] }
|
507
tools/remaster/scrap_parse/blender_import.py
Normal file
507
tools/remaster/scrap_parse/blender_import.py
Normal file
|
@ -0,0 +1,507 @@
|
|||
import bpy
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
import gzip
|
||||
import argparse
|
||||
import shutil
|
||||
from glob import glob
|
||||
from mathutils import Vector
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import itertools as ITT
|
||||
from pprint import pprint
|
||||
import bmesh
|
||||
from bpy.props import StringProperty, BoolProperty
|
||||
from bpy_extras.io_utils import ImportHelper
|
||||
from bpy.types import Operator
|
||||
|
||||
cmdline = None
|
||||
if "--" in sys.argv:
|
||||
args = sys.argv[sys.argv.index("--") + 1 :]
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--save", action="store_true")
|
||||
parser.add_argument("file_list", nargs="+")
|
||||
cmdline = parser.parse_args(args)
|
||||
|
||||
|
||||
def fix_pos(xyz):
|
||||
x, y, z = xyz
|
||||
return x, z, y
|
||||
|
||||
|
||||
class ScrapImporter(object):
|
||||
def __init__(self, options):
|
||||
self.unhandled = set()
|
||||
filepath = options.pop("filepath")
|
||||
self.options = options
|
||||
self.model_scale = 1000.0
|
||||
self.spawn_pos = {}
|
||||
self.objects = {}
|
||||
print("Loading", filepath)
|
||||
with gzip.open(filepath, "r") as fh:
|
||||
data = json.load(fh)
|
||||
self.path = data.pop("path")
|
||||
self.root = data.pop("root")
|
||||
self.config = data.pop("config")
|
||||
self.dummies = data.pop("dummies")["DUM"]["dummies"]
|
||||
self.moredummies = data.pop("moredummies")
|
||||
self.emi = data.pop("emi")["EMI"]
|
||||
self.sm3 = data.pop("sm3")["SM3"]
|
||||
|
||||
def make_empty(self, name, pos, rot=None):
|
||||
empty = bpy.data.objects.new(name, None)
|
||||
empty.empty_display_type = "PLAIN_AXES"
|
||||
empty.empty_display_size = 0.1
|
||||
empty.location = Vector(pos).xzy / self.model_scale
|
||||
if rot:
|
||||
empty.rotation_euler = Vector(rot).xzy
|
||||
empty.name = name
|
||||
empty.show_name = True
|
||||
bpy.context.scene.collection.objects.link(empty)
|
||||
|
||||
def create_tracks(self):
|
||||
points = {}
|
||||
for dummy in self.dummies:
|
||||
if dummy["name"].startswith("DM_Track"):
|
||||
try:
|
||||
_, name, idx = dummy["name"].split("_")
|
||||
except ValueError:
|
||||
continue
|
||||
pos = Vector(dummy["pos"]).xzy / self.model_scale
|
||||
points.setdefault(name, []).append((int(idx), pos))
|
||||
self.dummies=[d for d in self.dummies if not d["name"].startswith("DM_Track")]
|
||||
for name, points in points.items():
|
||||
crv = bpy.data.curves.new(name, "CURVE")
|
||||
crv.dimensions = "3D"
|
||||
crv.path_duration = (
|
||||
(bpy.context.scene.frame_end - bpy.context.scene.frame_start) + 1
|
||||
)
|
||||
crv.twist_mode = "Z_UP"
|
||||
crv.twist_smooth = 1.0
|
||||
spline = crv.splines.new(type="NURBS")
|
||||
spline.points.add(len(points) - 1)
|
||||
spline.use_endpoint_u = True
|
||||
spline.use_cyclic_u = True
|
||||
spline.use_endpoint_v = True
|
||||
spline.use_cyclic_v = True
|
||||
points.sort()
|
||||
for p, (_, co) in zip(spline.points, points):
|
||||
p.co = list(co) + [1.0]
|
||||
obj = bpy.data.objects.new(name, crv)
|
||||
bpy.context.scene.collection.objects.link(obj)
|
||||
|
||||
def create_dummies(self):
|
||||
for dummy in self.dummies:
|
||||
self.make_empty(dummy["name"], dummy["pos"], dummy["rot"])
|
||||
if dummy["name"].startswith("DM_Player_Spawn"):
|
||||
self.spawn_pos[dummy["name"]] = dummy["pos"]
|
||||
for name, dummy in self.moredummies.items():
|
||||
if not "Pos" in dummy:
|
||||
continue
|
||||
pos = list(float(v) for v in dummy["Pos"])
|
||||
rot = [0, 0, 0]
|
||||
if "Rot" in dummy:
|
||||
rot = list(float(v) for v in dummy["Rot"])
|
||||
self.make_empty(name, pos, rot)
|
||||
|
||||
def add_light(self, name, node):
|
||||
light = bpy.data.lights.new(name, "POINT")
|
||||
light.energy = 100
|
||||
r = node["unk_10"][0] / 255 # *(node['unk_10'][3]/255)
|
||||
g = node["unk_10"][1] / 255 # *(node['unk_10'][3]/255)
|
||||
b = node["unk_10"][2] / 255 # *(node['unk_10'][3]/255)
|
||||
light.color = (r, g, b)
|
||||
light = bpy.data.objects.new(name, light)
|
||||
light.location = Vector(node["pos"]).xzy / self.model_scale
|
||||
light.rotation_euler = Vector(node["rot"]).xzy
|
||||
bpy.context.scene.collection.objects.link(light)
|
||||
|
||||
def create_nodes(self):
|
||||
for node in self.sm3["scene"]["nodes"]:
|
||||
node_name = node["name"]
|
||||
node = node.get("content", {})
|
||||
if not node:
|
||||
continue
|
||||
if node["type"] == "Camera":
|
||||
print(f"CAM:{node_name}")
|
||||
pprint(node)
|
||||
elif node["type"] == "Light":
|
||||
print(f"LIGHT:{node_name}")
|
||||
# self.add_light(node_name, node)
|
||||
|
||||
def run(self):
|
||||
self.import_emi()
|
||||
self.join_objects(self.options['merge_objects'])
|
||||
if self.options['create_tracks']:
|
||||
self.create_tracks()
|
||||
if self.options['create_dummies']:
|
||||
self.create_dummies()
|
||||
if self.options['create_nodes']:
|
||||
self.create_nodes()
|
||||
if self.unhandled:
|
||||
print("Unhandled textures:",self.unhandled)
|
||||
|
||||
def join_objects(self, do_merge=False):
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
ctx = {}
|
||||
for name, objs in self.objects.items():
|
||||
if len(objs) <= 1:
|
||||
continue
|
||||
ctx = {
|
||||
"active_object": objs[0],
|
||||
"object": objs[0],
|
||||
"selected_objects": objs,
|
||||
"selected_editable_objects": objs,
|
||||
}
|
||||
with bpy.context.temp_override(**ctx):
|
||||
if do_merge:
|
||||
bpy.ops.object.join()
|
||||
objs[0].name=name
|
||||
else:
|
||||
coll=bpy.data.collections.new(name)
|
||||
bpy.context.scene.collection.children.link(coll)
|
||||
for n,obj in enumerate(objs):
|
||||
obj.name=f"{name}_{n:04}"
|
||||
coll.objects.link(obj)
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
|
||||
def import_emi(self):
|
||||
mats = {0: None}
|
||||
maps = {0: None}
|
||||
for mat in self.emi["materials"]:
|
||||
mats[mat[0]] = mat[1]
|
||||
for tex_map in self.emi["maps"]:
|
||||
maps[tex_map["key"]] = tex_map["data"]
|
||||
for tri in self.emi["tri"]:
|
||||
name = tri["name"]
|
||||
if tri["data"]:
|
||||
tris = tri["data"]["tris"]
|
||||
for n, verts in enumerate(
|
||||
[tri["data"]["verts_1"], tri["data"]["verts_2"]], 1
|
||||
):
|
||||
if not (tris and verts):
|
||||
continue
|
||||
self.create_mesh(
|
||||
name=f"{name}_{n}",
|
||||
verts=verts,
|
||||
faces=tris,
|
||||
m_map=(tri["data"]["map_key"], maps[tri["data"]["map_key"]]),
|
||||
m_mat=(tri["data"]["mat_key"], mats[tri["data"]["mat_key"]]),
|
||||
)
|
||||
|
||||
def normalize_path(self, path):
|
||||
return path.replace("\\", os.sep).replace("/", os.sep)
|
||||
|
||||
def resolve_path(self, path):
|
||||
file_extensions = [".png", ".bmp", ".dds", ".tga", ".alpha.dds"]
|
||||
root_path = Path(self.normalize_path(self.root).lower())
|
||||
start_folder = Path(self.normalize_path(self.path).lower()).parent
|
||||
try:
|
||||
texture_path = Path(self.config["model"]["texturepath"] + "/")
|
||||
except KeyError:
|
||||
texture_path = None
|
||||
path = Path(path.replace("/", os.sep).lower())
|
||||
if texture_path:
|
||||
folders = ITT.chain(
|
||||
[start_folder],
|
||||
start_folder.parents,
|
||||
[texture_path],
|
||||
texture_path.parents,
|
||||
)
|
||||
else:
|
||||
folders = ITT.chain([start_folder], start_folder.parents)
|
||||
for folder in folders:
|
||||
for suffix in file_extensions:
|
||||
for dds in [".", "dds"]:
|
||||
resolved_path = (
|
||||
root_path / folder / path.parent / dds / path.name
|
||||
).with_suffix(suffix)
|
||||
if resolved_path.exists():
|
||||
return str(resolved_path)
|
||||
print(f"Failed to resolve {path}")
|
||||
return None
|
||||
|
||||
def get_input(self, node, name, dtype):
|
||||
return list(filter(lambda i: (i.type, i.name) == (dtype, name), node.inputs))
|
||||
|
||||
|
||||
def build_material(self, mat_key, mat_def):
|
||||
mat_props = dict(m.groups() for m in re.finditer(r"\(\+(\w+)(?::(\w*))?\)",mat_key))
|
||||
for k,v in mat_props.items():
|
||||
mat_props[k]=v or True
|
||||
skip_names = ["entorno", "noise_trazado", "noise128", "pbasicometal"]
|
||||
overrides = {
|
||||
"zonaautoiluminada-a.dds" : {
|
||||
# "light"
|
||||
},
|
||||
"flecha.000.dds": {
|
||||
"shader": "hologram"
|
||||
},
|
||||
"mayor.000.dds": {
|
||||
"shader": "hologram"
|
||||
},
|
||||
}
|
||||
settings = {
|
||||
"Emission Strength": 10.0,
|
||||
"Specular": 0.0,
|
||||
"Roughness": 0.0,
|
||||
"Metallic": 0.0,
|
||||
}
|
||||
transparent_settings = {
|
||||
"Transmission": 1.0,
|
||||
"Transmission Roughness": 0.0,
|
||||
"IOR": 1.0,
|
||||
}
|
||||
glass_settings = {
|
||||
"Base Color": ( .8, .8, .8, 1.0),
|
||||
"Metallic": 0.2,
|
||||
"Roughness": 0.0,
|
||||
"Specular": 0.2,
|
||||
}
|
||||
tex_slots=[
|
||||
"Base Color",
|
||||
"Metallic",
|
||||
None, # "Clearcoat" ? env map?
|
||||
"Normal",
|
||||
"Emission"
|
||||
]
|
||||
|
||||
mat = bpy.data.materials.new(mat_key)
|
||||
mat.use_nodes = True
|
||||
node_tree = mat.node_tree
|
||||
nodes = node_tree.nodes
|
||||
imgs = {}
|
||||
animated_textures={}
|
||||
is_transparent = True
|
||||
for slot,tex in zip(tex_slots,mat_def["maps"]):
|
||||
if (slot is None) and tex:
|
||||
self.unhandled.add(tex["texture"])
|
||||
print(f"Don't know what to do with {tex}")
|
||||
if not (tex and slot):
|
||||
continue
|
||||
tex_file = self.resolve_path(tex["texture"])
|
||||
if tex_file is None:
|
||||
continue
|
||||
tex_name = os.path.basename(tex_file)
|
||||
if ".000." in tex_name:
|
||||
tex_files=glob(tex_file.replace(".000.",".*."))
|
||||
num_frames=len(tex_files)
|
||||
animated_textures[slot]=num_frames
|
||||
mat_props.update(overrides.get(tex_name,{}))
|
||||
if any(
|
||||
tex_name.find(fragment) != -1
|
||||
for fragment in skip_names
|
||||
):
|
||||
continue
|
||||
else:
|
||||
is_transparent = False
|
||||
imgs[slot]=bpy.data.images.load(tex_file)
|
||||
for n in nodes:
|
||||
nodes.remove(n)
|
||||
out = nodes.new("ShaderNodeOutputMaterial")
|
||||
out.name = "Output"
|
||||
shader = nodes.new("ShaderNodeBsdfPrincipled")
|
||||
is_transparent|=mat_props.get("shader")=="glass"
|
||||
is_transparent|=mat_props.get("transp") in {"premult","filter"}
|
||||
if is_transparent:
|
||||
settings.update(transparent_settings)
|
||||
if mat_props.get("shader")=="glass":
|
||||
settings.update(glass_settings)
|
||||
for name, value in settings.items():
|
||||
shader.inputs[name].default_value = value
|
||||
sockets_used = set()
|
||||
for socket,img in imgs.items():
|
||||
img_node = nodes.new("ShaderNodeTexImage")
|
||||
img_node.name = img.name
|
||||
img_node.image = img
|
||||
if socket in animated_textures:
|
||||
img.source="SEQUENCE"
|
||||
num_frames=animated_textures[socket]
|
||||
fps_div = 2 # TODO: read from .emi file
|
||||
drv=img_node.image_user.driver_add("frame_offset")
|
||||
drv.driver.type="SCRIPTED"
|
||||
drv.driver.expression=f"((frame/{fps_div})%{num_frames})-1"
|
||||
img_node.image_user.frame_duration=1
|
||||
img_node.image_user.use_cyclic=True
|
||||
img_node.image_user.use_auto_refresh=True
|
||||
tex_mix_node = nodes.new("ShaderNodeMixRGB")
|
||||
tex_mix_node.blend_type = "MULTIPLY"
|
||||
tex_mix_node.inputs["Fac"].default_value = 0.0
|
||||
node_tree.links.new(
|
||||
img_node.outputs["Color"], tex_mix_node.inputs["Color1"]
|
||||
)
|
||||
node_tree.links.new(
|
||||
img_node.outputs["Alpha"], tex_mix_node.inputs["Color2"]
|
||||
)
|
||||
imgs[socket] = tex_mix_node
|
||||
output_node = tex_mix_node.outputs["Color"]
|
||||
print(img.name, "->", socket)
|
||||
if socket == "Normal":
|
||||
normal_map = nodes.new("ShaderNodeNormalMap")
|
||||
node_tree.links.new(output_node, normal_map.inputs["Color"])
|
||||
output_node = normal_map.outputs["Normal"]
|
||||
normal_map.inputs["Strength"].default_value = 0.4
|
||||
node_tree.links.new(output_node, shader.inputs[socket])
|
||||
shader_out=shader.outputs["BSDF"]
|
||||
if mat_props.get("shader")=="hologram":
|
||||
mix_shader = nodes.new("ShaderNodeMixShader")
|
||||
transp_shader = nodes.new("ShaderNodeBsdfTransparent")
|
||||
mix_in_1 = self.get_input(mix_shader,"Shader","SHADER")[0]
|
||||
mix_in_2 = self.get_input(mix_shader,"Shader","SHADER")[1]
|
||||
node_tree.links.new(transp_shader.outputs["BSDF"], mix_in_1)
|
||||
node_tree.links.new(shader.outputs["BSDF"], mix_in_2)
|
||||
node_tree.links.new(imgs["Base Color"].outputs["Color"],mix_shader.inputs["Fac"])
|
||||
node_tree.links.new(imgs["Base Color"].outputs["Color"],shader.inputs["Emission"])
|
||||
shader.inputs["Emission Strength"].default_value=50.0
|
||||
shader_out=mix_shader.outputs["Shader"]
|
||||
if settings.get("Transmission",0.0)>0.0:
|
||||
light_path = nodes.new("ShaderNodeLightPath")
|
||||
mix_shader = nodes.new("ShaderNodeMixShader")
|
||||
transp_shader = nodes.new("ShaderNodeBsdfTransparent")
|
||||
mix_in_1 = self.get_input(mix_shader,"Shader","SHADER")[0]
|
||||
mix_in_2 = self.get_input(mix_shader,"Shader","SHADER")[1]
|
||||
node_tree.links.new(shader.outputs["BSDF"], mix_in_1)
|
||||
node_tree.links.new(transp_shader.outputs["BSDF"], mix_in_2)
|
||||
node_tree.links.new(light_path.outputs["Is Shadow Ray"], mix_shader.inputs["Fac"])
|
||||
if mat_props.get("transp")=="filter" or mat_props.get("shader")=="glass":
|
||||
node_tree.links.new(imgs["Base Color"].outputs["Color"],transp_shader.inputs["Color"])
|
||||
shader_out=mix_shader.outputs["Shader"]
|
||||
node_tree.links.new(shader_out, out.inputs["Surface"])
|
||||
return mat
|
||||
|
||||
def apply_maps(self, ob, m_mat, m_map):
|
||||
mat_key, m_mat = m_mat
|
||||
map_key, m_map = m_map # TODO?: MAP
|
||||
if mat_key == 0:
|
||||
return
|
||||
mat_name = m_mat.get("name", f"MAT:{mat_key:08X}")
|
||||
map_name = f"MAP:{map_key:08X}"
|
||||
if mat_name not in bpy.data.materials:
|
||||
ob.active_material = self.build_material(mat_name, m_mat)
|
||||
else:
|
||||
ob.active_material = bpy.data.materials[mat_name]
|
||||
|
||||
def create_mesh(self, name, verts, faces, m_mat, m_map):
|
||||
if not verts["inner"]:
|
||||
return
|
||||
me = bpy.data.meshes.new(name)
|
||||
me.use_auto_smooth = True
|
||||
pos = np.array([Vector(v["xyz"]).xzy for v in verts["inner"]["data"]])
|
||||
pos /= self.model_scale
|
||||
me.from_pydata(pos, [], faces)
|
||||
normals = [v["normal"] for v in verts["inner"]["data"]]
|
||||
vcols = [v["diffuse"] for v in verts["inner"]["data"]]
|
||||
if all(normals):
|
||||
normals = np.array(normals)
|
||||
me.vertices.foreach_set("normal", normals.flatten())
|
||||
if not me.vertex_colors:
|
||||
me.vertex_colors.new()
|
||||
for (vcol, vert) in zip(vcols, me.vertex_colors[0].data):
|
||||
vert.color = [vcol["r"], vcol["g"], vcol["b"], vcol["a"]]
|
||||
uvlayers = {}
|
||||
tex = [f"tex_{n+1}" for n in range(8)]
|
||||
for face in me.polygons:
|
||||
for vert_idx, loop_idx in zip(face.vertices, face.loop_indices):
|
||||
vert = verts["inner"]["data"][vert_idx]
|
||||
for tex_name in tex:
|
||||
if not vert[tex_name]:
|
||||
continue
|
||||
if not tex_name in uvlayers:
|
||||
uvlayers[tex_name] = me.uv_layers.new(name=tex_name)
|
||||
u, v = vert[tex_name]
|
||||
uvlayers[tex_name].data[loop_idx].uv = (u, 1.0 - v)
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(me)
|
||||
if self.options['remove_dup_verts']:
|
||||
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.0001)
|
||||
bm.to_mesh(me)
|
||||
me.update(calc_edges=True)
|
||||
bm.clear()
|
||||
for poly in me.polygons:
|
||||
poly.use_smooth = True
|
||||
ob = bpy.data.objects.new(name, me)
|
||||
self.apply_maps(ob, m_mat, m_map)
|
||||
bpy.context.scene.collection.objects.link(ob)
|
||||
self.objects.setdefault(name, []).append(ob)
|
||||
return ob
|
||||
|
||||
|
||||
class Scrap_Load(Operator, ImportHelper):
|
||||
|
||||
bl_idname = "scrap_utils.import_json"
|
||||
bl_label = "Import JSON"
|
||||
|
||||
filename_ext = ".json.gz"
|
||||
filter_glob: StringProperty(default="*.json.gz", options={"HIDDEN"})
|
||||
|
||||
create_dummies: BoolProperty(
|
||||
name="Import dummies",
|
||||
default=True
|
||||
)
|
||||
|
||||
create_nodes: BoolProperty(
|
||||
name="Import nodes (lights, cameras, etc)",
|
||||
default=True
|
||||
)
|
||||
|
||||
create_tracks: BoolProperty(
|
||||
name="Create track curves",
|
||||
default=True
|
||||
)
|
||||
|
||||
merge_objects: BoolProperty(
|
||||
name="Merge objects by name",
|
||||
default=False
|
||||
)
|
||||
|
||||
remove_dup_verts: BoolProperty(
|
||||
name="Remove overlapping vertices\nfor smoother meshes",
|
||||
default=True
|
||||
)
|
||||
|
||||
# remove_dup_verts: BoolProperty(
|
||||
# name="Remove overlapping vertices for smoother meshes",
|
||||
# default=False
|
||||
# )
|
||||
|
||||
|
||||
def execute(self, context):
|
||||
bpy.ops.preferences.addon_enable(module = "node_arrange")
|
||||
bpy.ops.outliner.orphans_purge(do_recursive=True)
|
||||
importer = ScrapImporter(self.as_keywords())
|
||||
importer.run()
|
||||
dg = bpy.context.evaluated_depsgraph_get()
|
||||
dg.update()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_class(Scrap_Load)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_class(Scrap_Load)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if cmdline is None or not cmdline.file_list:
|
||||
register()
|
||||
bpy.ops.scrap_utils.import_json("INVOKE_DEFAULT")
|
||||
else:
|
||||
for file in cmdline.file_list:
|
||||
bpy.context.preferences.view.show_splash = False
|
||||
objs = bpy.data.objects
|
||||
for obj in objs.keys():
|
||||
objs.remove(objs[obj], do_unlink=True)
|
||||
cols=bpy.data.collections
|
||||
for col in cols:
|
||||
cols.remove(col)
|
||||
importer = ScrapImporter(file)
|
||||
importer.run()
|
||||
if cmdline.save:
|
||||
targetpath = Path(file).name.partition(".")[0] + ".blend"
|
||||
targetpath = os.path.abspath(targetpath)
|
||||
print("Saving", targetpath)
|
||||
bpy.ops.wm.save_as_mainfile(filepath=targetpath)
|
103
tools/remaster/scrap_parse/packed_loader.py
Normal file
103
tools/remaster/scrap_parse/packed_loader.py
Normal file
|
@ -0,0 +1,103 @@
|
|||
bl_info = {
|
||||
"name": "Riot Archive File (RAF)",
|
||||
"blender": (2, 71, 0),
|
||||
"location": "File > Import",
|
||||
"description": "Import LoL data of an Riot Archive File",
|
||||
"category": "Import-Export"}
|
||||
|
||||
|
||||
import bpy
|
||||
from io_scene_lolraf import raf_utils
|
||||
from bpy.props import (StringProperty, BoolProperty, CollectionProperty,
|
||||
IntProperty)
|
||||
|
||||
|
||||
class ImportFilearchives(bpy.types.Operator):
|
||||
"""Import whole filearchives directory."""
|
||||
bl_idname = "import_scene.rafs"
|
||||
bl_label = 'Import LoL filearchives'
|
||||
|
||||
directory = StringProperty(name="'filearchives' folder",
|
||||
subtype="DIR_PATH", options={'HIDDEN'})
|
||||
filter_folder = BoolProperty(default=True, options={'HIDDEN'})
|
||||
filter_glob = StringProperty(default="", options={'HIDDEN'})
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {'RUNNING_MODAL'}
|
||||
|
||||
def execute(self, context):
|
||||
# TODO: Validate filepath
|
||||
bpy.ops.ui.raf_browser('INVOKE_DEFAULT',filepath=self.directory)
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RAFEntry(bpy.types.PropertyGroup):
|
||||
name = bpy.props.StringProperty()
|
||||
selected = bpy.props.BoolProperty(name="")
|
||||
|
||||
|
||||
archive = None
|
||||
class RAFBrowser(bpy.types.Operator):
|
||||
bl_idname = "ui.raf_browser"
|
||||
bl_label = "RAF-browser"
|
||||
bl_options = {'INTERNAL'}
|
||||
|
||||
filepath = StringProperty()
|
||||
current_dir = CollectionProperty(type=RAFEntry)
|
||||
selected_index = IntProperty(default=0)
|
||||
|
||||
def invoke(self, context, event):
|
||||
global archive
|
||||
archive = raf_utils.RAFArchive(self.filepath)
|
||||
return context.window_manager.invoke_props_dialog(self)
|
||||
|
||||
def draw(self, context):
|
||||
if self.selected_index != -1:
|
||||
print("new selected_index: " + str(self.selected_index))
|
||||
global archive
|
||||
# TODO: change current directory of archive
|
||||
self.current_dir.clear()
|
||||
for dir in archive.current_dir():
|
||||
entry = self.current_dir.add()
|
||||
entry.name = dir
|
||||
self.selected_index = -1
|
||||
self.layout.template_list("RAFDirList", "", self, "current_dir", self, "selected_index")
|
||||
|
||||
def execute(self, context):
|
||||
print("execute")
|
||||
return {'FINISHED'}
|
||||
|
||||
|
||||
class RAFDirList(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
operator = data
|
||||
raf_entry = item
|
||||
|
||||
if self.layout_type in {'DEFAULT', 'COMPACT'}:
|
||||
layout.prop(raf_entry, "name", text="", emboss=False, icon_value=icon)
|
||||
layout.prop(raf_entry, "selected")
|
||||
elif self.layout_type in {'GRID'}:
|
||||
layout.alignment = 'CENTER'
|
||||
layout.label(text="", icon_value=icon)
|
||||
|
||||
|
||||
def menu_func_import(self, context):
|
||||
self.layout.operator(ImportFilearchives.bl_idname, text="LoL Filearchives")
|
||||
|
||||
|
||||
def register():
|
||||
bpy.utils.register_module(__name__)
|
||||
bpy.types.INFO_MT_file_import.append(menu_func_import)
|
||||
|
||||
|
||||
def unregister():
|
||||
bpy.utils.unregister_module(__name__)
|
||||
bpy.types.INFO_MT_file_import.remove(menu_func_import)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import imp
|
||||
imp.reload(raf_utils)
|
||||
bpy.utils.register_module(__name__)
|
||||
|
906
tools/remaster/scrap_parse/src/main.rs
Normal file
906
tools/remaster/scrap_parse/src/main.rs
Normal file
|
@ -0,0 +1,906 @@
|
|||
#![allow(clippy::upper_case_acronyms, non_camel_case_types)]
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use binrw::args;
|
||||
use binrw::prelude::*;
|
||||
use binrw::until_exclusive;
|
||||
use chrono::{DateTime, NaiveDateTime, Utc};
|
||||
use clap::Parser;
|
||||
use configparser::ini::Ini;
|
||||
use flate2::write::GzEncoder;
|
||||
use flate2::Compression;
|
||||
use fs_err as fs;
|
||||
use indexmap::IndexMap;
|
||||
use modular_bitfield::bitfield;
|
||||
use modular_bitfield::specifiers::B2;
|
||||
use modular_bitfield::specifiers::B4;
|
||||
use modular_bitfield::BitfieldSpecifier;
|
||||
use serde::Serialize;
|
||||
use serde_json::Map;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, Seek};
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[binread]
|
||||
#[derive(Serialize, Debug)]
|
||||
#[br(import(msg: &'static str))]
|
||||
struct Unparsed<const SIZE: u64> {
|
||||
#[br(count=SIZE, try_map=|data: Vec<u8>| Err(anyhow!("Unparsed data: {}\n{}", msg, rhexdump::hexdump(&data))))]
|
||||
data: (),
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Serialize, Debug)]
|
||||
struct RawTable<const SIZE: u32> {
|
||||
num_entries: u32,
|
||||
#[br(assert(entry_size==SIZE))]
|
||||
entry_size: u32,
|
||||
#[br(count=num_entries, args {inner: args!{count: entry_size.try_into().unwrap()}})]
|
||||
data: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Serialize, Debug)]
|
||||
struct Table<T: for<'a> BinRead<Args<'a> = ()> + 'static> {
|
||||
num_entries: u32,
|
||||
entry_size: u32,
|
||||
#[br(count=num_entries)]
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
// impl<T: for<'a> BinRead<Args<'a> = ()>> Serialize for Table<T> where T: Serialize {
|
||||
// fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
// where
|
||||
// S: serde::Serializer {
|
||||
// self.data.serialize(serializer)
|
||||
// }
|
||||
// }
|
||||
|
||||
#[binread]
|
||||
struct Optional<T: for<'a> BinRead<Args<'a> = ()>> {
|
||||
#[br(temp)]
|
||||
has_value: u32,
|
||||
#[br(if(has_value!=0))]
|
||||
value: Option<T>,
|
||||
}
|
||||
|
||||
impl<T: for<'a> BinRead<Args<'a> = ()> + Debug> Debug for Optional<T>
|
||||
where
|
||||
T: Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.value.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: for<'a> BinRead<Args<'a> = ()> + std::ops::Deref> std::ops::Deref for Optional<T> {
|
||||
type Target = Option<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: for<'a> BinRead<Args<'a> = ()> + Serialize> Serialize for Optional<T> {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.value.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Serialize, Debug)]
|
||||
struct Chunk {
|
||||
#[br(map=|c:[u8;4]| c.into_iter().map(|v| v as char).collect())]
|
||||
magic: Vec<char>,
|
||||
size: u32,
|
||||
#[br(temp,count=size)]
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
struct PascalString {
|
||||
#[br(temp)]
|
||||
length: u32,
|
||||
#[br(count=length, map=|bytes: Vec<u8>| {
|
||||
String::from_utf8_lossy(&bytes.iter().copied().take_while(|&v| v!=0).collect::<Vec<u8>>()).into_owned()
|
||||
})]
|
||||
string: String,
|
||||
}
|
||||
|
||||
impl Serialize for PascalString {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.string.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for PascalString {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.string.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct IniSection {
|
||||
#[br(temp)]
|
||||
num_lines: u32,
|
||||
#[br(count=num_lines)]
|
||||
sections: Vec<PascalString>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"INI\0")]
|
||||
#[derive(Debug)]
|
||||
struct INI {
|
||||
size: u32,
|
||||
#[br(temp)]
|
||||
num_sections: u32,
|
||||
#[br(count=num_sections)]
|
||||
sections: Vec<IniSection>,
|
||||
}
|
||||
|
||||
impl Serialize for INI {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let blocks: Vec<String> = self
|
||||
.sections
|
||||
.iter()
|
||||
.flat_map(|s| s.sections.iter())
|
||||
.map(|s| s.string.clone())
|
||||
.collect();
|
||||
Ini::new().read(blocks.join("\n")).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
struct RGBA {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
a: u8,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
#[br(import(n_dims: usize))]
|
||||
struct TexCoords(#[br(count=n_dims)] Vec<f32>);
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
#[br(import(vert_fmt: FVF))]
|
||||
// https://github.com/elishacloud/dxwrapper/blob/23ffb74c4c93c4c760bb5f1de347a0b039897210/ddraw/IDirect3DDeviceX.cpp#L2642
|
||||
struct Vertex {
|
||||
xyz: [f32; 3],
|
||||
// #[br(if(vert_fmt.pos()==Pos::XYZRHW))] // seems to be unused
|
||||
// rhw: Option<f32>,
|
||||
#[br(if(vert_fmt.normal()))]
|
||||
normal: Option<[f32; 3]>,
|
||||
#[br(if(vert_fmt.point_size()))]
|
||||
point_size: Option<[f32; 3]>,
|
||||
#[br(if(vert_fmt.diffuse()))]
|
||||
diffuse: Option<RGBA>,
|
||||
#[br(if(vert_fmt.specular()))]
|
||||
specular: Option<RGBA>,
|
||||
#[br(if(vert_fmt.tex_count()>=1), args (vert_fmt.tex_dims(0),))]
|
||||
tex_1: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=2), args (vert_fmt.tex_dims(1),))]
|
||||
tex_2: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=3), args (vert_fmt.tex_dims(2),))]
|
||||
tex_3: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=4), args (vert_fmt.tex_dims(3),))]
|
||||
tex_4: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=5), args (vert_fmt.tex_dims(4),))]
|
||||
tex_5: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=6), args (vert_fmt.tex_dims(5),))]
|
||||
tex_6: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=7), args (vert_fmt.tex_dims(6),))]
|
||||
tex_7: Option<TexCoords>,
|
||||
#[br(if(vert_fmt.tex_count()>=8), args (vert_fmt.tex_dims(7),))]
|
||||
tex_8: Option<TexCoords>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq, Eq, BitfieldSpecifier)]
|
||||
#[bits = 3]
|
||||
enum Pos {
|
||||
XYZ,
|
||||
XYZRHW,
|
||||
XYZB1,
|
||||
XYZB2,
|
||||
XYZB3,
|
||||
XYZB4,
|
||||
XYZB5,
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Serialize, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct FVF {
|
||||
reserved_1: bool,
|
||||
pos: Pos,
|
||||
normal: bool,
|
||||
point_size: bool,
|
||||
diffuse: bool,
|
||||
specular: bool,
|
||||
tex_count: B4,
|
||||
tex_1: B2,
|
||||
tex_2: B2,
|
||||
tex_3: B2,
|
||||
tex_4: B2,
|
||||
tex_5: B2,
|
||||
tex_6: B2,
|
||||
tex_7: B2,
|
||||
tex_8: B2,
|
||||
rest: B4,
|
||||
}
|
||||
|
||||
impl FVF {
|
||||
fn tex_dims(&self, tex: u8) -> usize {
|
||||
let tex: u8 = match tex {
|
||||
0 => self.tex_1(),
|
||||
1 => self.tex_2(),
|
||||
2 => self.tex_3(),
|
||||
3 => self.tex_4(),
|
||||
4 => self.tex_5(),
|
||||
5 => self.tex_6(),
|
||||
6 => self.tex_7(),
|
||||
7 => self.tex_8(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
match tex {
|
||||
0 => 2,
|
||||
1 => 3,
|
||||
2 => 4,
|
||||
3 => 1,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn num_w(&self) -> usize {
|
||||
use Pos::*;
|
||||
match self.pos() {
|
||||
XYZ | XYZRHW => 0,
|
||||
XYZB1 => 1,
|
||||
XYZB2 => 2,
|
||||
XYZB3 => 3,
|
||||
XYZB4 => 4,
|
||||
XYZB5 => 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn vertex_size_from_id(fmt_id: u32) -> Result<u32> {
|
||||
let fmt_size = match fmt_id {
|
||||
0 => 0x0,
|
||||
1 | 8 | 10 => 0x20,
|
||||
2 => 0x28,
|
||||
3 | 0xd => 0x1c,
|
||||
4 | 7 => 0x24,
|
||||
5 => 0x2c,
|
||||
6 => 0x34,
|
||||
0xb => 4,
|
||||
0xc => 0x18,
|
||||
0xe => 0x12,
|
||||
0xf | 0x10 => 0x16,
|
||||
0x11 => 0x1a,
|
||||
other => bail!("Invalid vertex format id: {other}"),
|
||||
};
|
||||
Ok(fmt_size)
|
||||
}
|
||||
|
||||
fn vertex_format_from_id(fmt_id: u32, fmt: u32) -> Result<FVF> {
|
||||
let fvf = match fmt_id {
|
||||
0 => 0x0,
|
||||
1 => 0x112,
|
||||
2 => 0x212,
|
||||
3 => 0x1c2,
|
||||
4 => 0x116,
|
||||
5 => 0x252,
|
||||
6 => 0x352,
|
||||
7 => 0x152,
|
||||
8 => 0x1c4,
|
||||
10 => 0x242,
|
||||
other => bail!("Invalid vertex format id: {other}"),
|
||||
};
|
||||
if fvf != fmt {
|
||||
bail!("Vertex format mismatch: {fvf}!={fmt}");
|
||||
}
|
||||
Ok(FVF::from(fvf))
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(import(fmt_id: u32))]
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
struct LFVFInner {
|
||||
#[br(try_map=|v: u32| vertex_format_from_id(fmt_id,v))]
|
||||
vert_fmt: FVF,
|
||||
#[br(assert(vert_size==vertex_size_from_id(fmt_id).unwrap()))]
|
||||
vert_size: u32,
|
||||
num_verts: u32,
|
||||
#[br(count=num_verts, args {inner: (vert_fmt,)})]
|
||||
data: Vec<Vertex>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"LFVF")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct LFVF {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"invalid LFVF version"))]
|
||||
version: u32,
|
||||
#[br(assert((0..=0x11).contains(&fmt_id),"invalid LFVF format_id"))]
|
||||
fmt_id: u32,
|
||||
#[br(if(fmt_id!=0),args(fmt_id))]
|
||||
inner: Option<LFVFInner>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"MD3D")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct MD3D {
|
||||
// TODO: mesh
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid MD3D version"))]
|
||||
version: u32,
|
||||
name: PascalString,
|
||||
num_tris: u32,
|
||||
#[br(assert(tri_size==6,"Invalid MD3D tri size"))]
|
||||
tri_size: u32,
|
||||
#[br(count=num_tris)]
|
||||
tris: Vec<[u16; 3]>,
|
||||
mesh_data: LFVF,
|
||||
unk_table_1: RawTable<2>,
|
||||
// TODO:
|
||||
// ==
|
||||
// unk_t1_count: u32,
|
||||
// #[br(assert(unk_t1_size==2))]
|
||||
// unk_t1_size: u32,
|
||||
// #[br(count=unk_t1_count)]
|
||||
// unk_t1_list: Vec<u16>,
|
||||
// // ==
|
||||
// unk_t2_count: u32,
|
||||
// #[br(assert(unk_t1_size==2))]
|
||||
// unk_t2_size: u32,
|
||||
// #[br(count=unk_t1_count)]
|
||||
// unk_t2_list: Vec<u16>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
enum NodeData {
|
||||
#[br(magic = 0x0u32)]
|
||||
Null,
|
||||
#[br(magic = 0xa1_00_00_01_u32)]
|
||||
TriangleMesh, // Empty?
|
||||
#[br(magic = 0xa1_00_00_02_u32)]
|
||||
Mesh(MD3D),
|
||||
#[br(magic = 0xa2_00_00_04_u32)]
|
||||
Camera(CAM),
|
||||
#[br(magic = 0xa3_00_00_08_u32)]
|
||||
Light(LUZ),
|
||||
#[br(magic = 0xa4_00_00_10_u32)]
|
||||
Ground(SUEL),
|
||||
#[br(magic = 0xa5_00_00_20_u32)]
|
||||
SisPart(Unparsed<0x10>), // TODO: Particles
|
||||
#[br(magic = 0xa6_00_00_40_u32)]
|
||||
Graphic3D(SPR3),
|
||||
#[br(magic = 0xa6_00_00_80_u32)]
|
||||
Flare(Unparsed<0x10>), // TODO: LensFlare?
|
||||
#[br(magic = 0xa7_00_01_00u32)]
|
||||
Portal(PORT),
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"SPR3")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SPR3 {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid SPR3 version"))]
|
||||
version: u32,
|
||||
pos: [f32; 3],
|
||||
unk_1: [u8; 8],
|
||||
name_1: PascalString,
|
||||
name_2: PascalString,
|
||||
unk_2: u32,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"SUEL")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SUEL {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid SUEL version"))]
|
||||
version: u32,
|
||||
bbox: [[f32; 3]; 2],
|
||||
pos: [f32; 3],
|
||||
unk_3: [u8; 4],
|
||||
num_nodes: u32,
|
||||
unk_4: [u8; 4],
|
||||
bbox_2: [[f32; 3]; 2],
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"CAM\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct CAM {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid CAM version"))]
|
||||
version: u32,
|
||||
unk_1: [f32; 3],
|
||||
origin: [f32; 3],
|
||||
destination: [f32; 3],
|
||||
unk_4: [u8; 4],
|
||||
unk_5: [u8; 4],
|
||||
unk_6: [u8; 4],
|
||||
unk_7: [u8; 4],
|
||||
unk_8: [u8; 4],
|
||||
unk_9: [u8; 4],
|
||||
unk_10: [u8; 4],
|
||||
unk_11: [u8; 4],
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"LUZ\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct LUZ {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid LUZ version"))]
|
||||
version: u32,
|
||||
col: u32,
|
||||
brightness: u32,
|
||||
unk_3: u8,
|
||||
pos: [f32; 3],
|
||||
rot: [f32; 3],
|
||||
unk_6: [u8; 8],
|
||||
unk_7: [u8; 4],
|
||||
unk_8: [u8; 4],
|
||||
unk_9: [u8; 4],
|
||||
unk_10: [u8; 4],
|
||||
unk_11: [u8; 4],
|
||||
unk_12: [u8; 4],
|
||||
unk_13: u32,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"PORT")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct PORT {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid PORT version"))]
|
||||
version: u32,
|
||||
width: u32,
|
||||
height: u32,
|
||||
sides: [u32; 2],
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Node {
|
||||
unk_f17_0x44: u32,
|
||||
unk_f18_0x48: u32,
|
||||
unk_f19_0x4c: u32,
|
||||
flags: u32,
|
||||
unk_f20_0x50: u32,
|
||||
name: PascalString,
|
||||
parent: PascalString,
|
||||
unk_f7_0x1c: [f32; 3], // 0xc
|
||||
unk_f10_0x28: [f32; 4], // 0x10
|
||||
unk_f14_0x38: f32, // 0x4
|
||||
unk_f23_0x5c: [[f32; 4]; 4], // 0x40 4x4 Matrix
|
||||
unk_f39_0x9c: [[f32; 4]; 4], // 0x40 4x4 Matrix
|
||||
unk_f55_0xdc: [f32; 4], // 0x10 Vector?
|
||||
unk_f59_0xec: [f32; 3], // 0xc Vector?
|
||||
node_info: Optional<INI>,
|
||||
content: Optional<NodeData>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"MAP\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct MAP {
|
||||
size: u32,
|
||||
#[br(assert((2..=3).contains(&version),"invalid MAP version"))]
|
||||
version: u32,
|
||||
texture: PascalString,
|
||||
unk_1: [u8; 7],
|
||||
unk_bbox: [[f32; 2]; 2],
|
||||
unk_2: f32,
|
||||
#[br(if(version==3))]
|
||||
unk_3: Option<[u8; 0xc]>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"MAT\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct MAT {
|
||||
size: u32,
|
||||
#[br(assert((1..=3).contains(&version),"invalid MAT version"))]
|
||||
version: u32,
|
||||
#[br(if(version>1))]
|
||||
name: Option<PascalString>,
|
||||
unk_f: [RGBA; 7],
|
||||
unk_data: [RGBA; 0x18 / 4],
|
||||
maps: [Optional<MAP>; 5], // Base Color, Metallic?, ???, Normal, Emission
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"SCN\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SCN {
|
||||
// 0x650220
|
||||
size: u32,
|
||||
#[br(temp,assert(version==1))]
|
||||
version: u32,
|
||||
model_name: PascalString,
|
||||
node_name: PascalString,
|
||||
node_props: Optional<INI>,
|
||||
unk_f_1: [f32; (8 + 8) / 4],
|
||||
unk_1: [f32; 0x18 / 4],
|
||||
unk_f_2: f32,
|
||||
user_props: Optional<INI>,
|
||||
num_materials: u32,
|
||||
#[br(count=num_materials)]
|
||||
mat: Vec<MAT>,
|
||||
#[br(temp,assert(unk_3==1))]
|
||||
unk_3: u32,
|
||||
num_nodes: u32,
|
||||
#[br(count = num_nodes)] // 32
|
||||
nodes: Vec<Node>,
|
||||
ani: Optional<ANI>, // TODO:?
|
||||
}
|
||||
|
||||
fn convert_timestamp(dt: u32) -> Result<DateTime<Utc>> {
|
||||
let Some(dt) = NaiveDateTime::from_timestamp_opt(dt.into(),0) else {
|
||||
bail!("Invalid timestamp");
|
||||
};
|
||||
Ok(DateTime::from_utc(dt, Utc))
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct VertexAnim {
|
||||
n_tr: u32,
|
||||
maybe_duration: f32,
|
||||
#[br(count=n_tr)]
|
||||
tris: Vec<[u8; 3]>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"EVA\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct EVA {
|
||||
size: u32,
|
||||
#[br(assert(version==1,"Invalid EVA version"))]
|
||||
version: u32,
|
||||
num_verts: u32,
|
||||
#[br(count=num_verts)]
|
||||
verts: Vec<Optional<VertexAnim>>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"NAM\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct NAM {
|
||||
size: u32,
|
||||
#[br(assert(version==1))]
|
||||
version: u32,
|
||||
primer_frames: u32,
|
||||
frames: u32,
|
||||
#[br(assert(flags&0xffffef60==0,"Invalid NAM flags"))]
|
||||
flags: u32,
|
||||
#[br(assert(opt_flags&0xfff8==0,"Invalid NAM opt_flags"))]
|
||||
opt_flags: u32,
|
||||
#[br(assert(stm_flags&0xfff8==0,"Invalid NAM stm_flags"))]
|
||||
stm_flags: u32,
|
||||
#[br(map=|_:()| flags&(opt_flags|0x8000)&stm_flags)]
|
||||
combined_flags: u32,
|
||||
#[br(if(combined_flags&0x1!=0))]
|
||||
unk_flags_1: Option<u32>,
|
||||
#[br(if(combined_flags&0x2!=0))]
|
||||
unk_flags_2: Option<u32>,
|
||||
#[br(if(combined_flags&0x4!=0))]
|
||||
unk_flags_3: Option<u32>,
|
||||
#[br(if(combined_flags&0x8!=0))]
|
||||
unk_flags_4: Option<u32>,
|
||||
#[br(if(combined_flags&0x10!=0))]
|
||||
unk_flags_5: Option<u32>,
|
||||
#[br(if(combined_flags&0x80!=0))]
|
||||
unk_flags_6: Option<u32>,
|
||||
#[br(if(flags&0x1000!=0))]
|
||||
eva: Option<EVA>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"NABK")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct NABK {
|
||||
size: u32,
|
||||
#[br(temp,count=size)]
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"ANI\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct ANI {
|
||||
size: u32,
|
||||
#[br(assert(version==2, "Invalid ANI version"))]
|
||||
version: u32,
|
||||
fps: f32,
|
||||
unk_1: u32,
|
||||
unk_2: u32,
|
||||
num_objects: u32,
|
||||
unk_flags: u32,
|
||||
num: u32,
|
||||
#[br(temp,count=num)]
|
||||
data: Vec<u8>,
|
||||
nabk: NABK,
|
||||
#[br(count=num_objects)]
|
||||
nam: Vec<NAM>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"SM3\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct SM3 {
|
||||
size: u32,
|
||||
#[br(temp,assert(const_1==0x6515f8,"Invalid timestamp"))]
|
||||
const_1: u32,
|
||||
#[br(try_map=convert_timestamp)]
|
||||
time_1: DateTime<Utc>,
|
||||
#[br(try_map=convert_timestamp)]
|
||||
time_2: DateTime<Utc>,
|
||||
scene: SCN,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"CM3\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct CM3 {
|
||||
size: u32,
|
||||
#[br(temp,assert(const_1==0x6515f8,"Invalid timestamp"))]
|
||||
const_1: u32,
|
||||
#[br(try_map=convert_timestamp)]
|
||||
time_1: DateTime<Utc>,
|
||||
#[br(try_map=convert_timestamp)]
|
||||
time_2: DateTime<Utc>,
|
||||
scene: SCN,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct Dummy {
|
||||
name: PascalString,
|
||||
pos: [f32; 3],
|
||||
rot: [f32; 3],
|
||||
info: Optional<INI>,
|
||||
has_next: u32,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"DUM\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct DUM {
|
||||
size: u32,
|
||||
#[br(assert(version==1, "Invalid DUM version"))]
|
||||
version: u32,
|
||||
num_dummies: u32,
|
||||
unk_1: u32,
|
||||
#[br(count=num_dummies)]
|
||||
dummies: Vec<Dummy>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"QUAD")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct QUAD {
|
||||
size: u32,
|
||||
#[br(assert(version==1, "Invalid QUAD version"))]
|
||||
version: u32,
|
||||
mesh: u32,
|
||||
table: Table<u16>,
|
||||
f_4: [f32; 4],
|
||||
num_children: u32,
|
||||
#[br(count=num_children)]
|
||||
children: Vec<QUAD>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"CMSH")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct CMSH {
|
||||
size: u32,
|
||||
#[br(assert(version==2, "Invalid CMSH version"))]
|
||||
version: u32,
|
||||
#[br(assert(collide_mesh_size==0x34, "Invalid collision mesh size"))]
|
||||
collide_mesh_size: u32,
|
||||
name: PascalString,
|
||||
unk_1: u16,
|
||||
sector: u16,
|
||||
unk_2: u16,
|
||||
index: u8,
|
||||
unk_4: u8,
|
||||
bbox_1: [[f32; 3]; 2],
|
||||
#[br(temp)]
|
||||
t_1: Table<[f32; 3]>,
|
||||
#[br(temp)]
|
||||
t_2: RawTable<0x1c>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"AMC\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct AMC {
|
||||
size: u32,
|
||||
#[br(assert(version==100,"Invalid AMC version"))]
|
||||
version: u32,
|
||||
#[br(assert(version_code==0, "Invalid AMC version_code"))]
|
||||
version_code: u32,
|
||||
bbox_1: [[f32; 3]; 2],
|
||||
scale: f32,
|
||||
bbox_2: [[f32; 3]; 2],
|
||||
unk: [f32; 3],
|
||||
cmsh: [CMSH; 2],
|
||||
num_sectors: u32,
|
||||
#[br(count=num_sectors)]
|
||||
sector_col: Vec<[CMSH; 2]>,
|
||||
unk_num_1: u32,
|
||||
unk_num_2: u32,
|
||||
unk_f: [f32; 4],
|
||||
num_quads: u32,
|
||||
#[br(count=num_quads)]
|
||||
quads: Vec<QUAD>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(import(version: u32))]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct TriV104 {
|
||||
#[br(if(version>=0x69))]
|
||||
name_2: Option<PascalString>,
|
||||
mat_key: u32,
|
||||
map_key: u32,
|
||||
num_tris: u32,
|
||||
#[br(count=num_tris)]
|
||||
tris: Vec<[u16; 3]>,
|
||||
verts_1: LFVF,
|
||||
verts_2: LFVF,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"TRI\0", import(version: u32))]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct TRI {
|
||||
size: u32,
|
||||
unk_int: u32,
|
||||
name: PascalString,
|
||||
unk_int_2: u32, // if 0xffffffff sometimes TriV104 has no name_2 field
|
||||
#[br(args(version))]
|
||||
data: TriV104,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct EMI_Textures {
|
||||
key: u32,
|
||||
#[br(if(key!=0))]
|
||||
data: Option<(PascalString, u32, PascalString)>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[br(magic = b"EMI\0")]
|
||||
#[derive(Debug, Serialize)]
|
||||
struct EMI {
|
||||
size: u32,
|
||||
#[br(assert((103..=105).contains(&version)))]
|
||||
version: u32,
|
||||
num_materials: u32,
|
||||
#[br(count=num_materials)]
|
||||
materials: Vec<(u32, MAT)>,
|
||||
#[br(parse_with = until_exclusive(|v: &EMI_Textures| v.key==0))]
|
||||
maps: Vec<EMI_Textures>,
|
||||
num_lists: u32,
|
||||
#[br(count=num_lists,args{inner: (version,)})]
|
||||
tri: Vec<TRI>,
|
||||
}
|
||||
|
||||
#[binread]
|
||||
#[derive(Debug, Serialize)]
|
||||
enum Data {
|
||||
SM3(SM3),
|
||||
CM3(CM3),
|
||||
DUM(DUM),
|
||||
AMC(AMC),
|
||||
EMI(EMI),
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
root: PathBuf,
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
fn parse_file(path: &PathBuf) -> Result<Data> {
|
||||
let mut rest_size = 0;
|
||||
let mut fh = BufReader::new(fs::File::open(path)?);
|
||||
let ret = fh.read_le()?;
|
||||
let pos = fh
|
||||
.stream_position()
|
||||
.unwrap_or(0)
|
||||
.try_into()
|
||||
.unwrap_or(u32::MAX);
|
||||
println!("Read {} bytes from {}", pos, path.display());
|
||||
let mut buffer = [0u8; 0x1000];
|
||||
if let Ok(n) = fh.read(&mut buffer) {
|
||||
if n != 0 {
|
||||
println!("Rest:\n{}", rhexdump::hexdump_offset(&buffer[..n], pos));
|
||||
}
|
||||
};
|
||||
while let Ok(n) = fh.read(&mut buffer) {
|
||||
if n == 0 {
|
||||
break;
|
||||
}
|
||||
rest_size += n;
|
||||
}
|
||||
println!("+{rest_size} unparsed bytes");
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn load_ini(path: &PathBuf) -> IndexMap<String, IndexMap<String, Option<String>>> {
|
||||
Ini::new().load(path).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn load_data(root: &Path, path: &Path) -> Result<Value> {
|
||||
let full_path = &root.join(path);
|
||||
let emi_path = full_path.join("map").join("map3d.emi");
|
||||
let sm3_path = emi_path.with_extension("sm3");
|
||||
let dum_path = emi_path.with_extension("dum");
|
||||
let config_file = emi_path.with_extension("ini");
|
||||
let moredummies = emi_path.with_file_name("moredummies").with_extension("ini");
|
||||
let mut data = serde_json::to_value(HashMap::<(), ()>::default())?;
|
||||
data["config"] = serde_json::to_value(load_ini(&config_file))?;
|
||||
data["moredummies"] = serde_json::to_value(load_ini(&moredummies))?;
|
||||
data["emi"] = serde_json::to_value(parse_file(&emi_path)?)?;
|
||||
data["sm3"] = serde_json::to_value(parse_file(&sm3_path)?)?;
|
||||
data["dummies"] = serde_json::to_value(parse_file(&dum_path)?)?;
|
||||
data["path"] = serde_json::to_value(path)?;
|
||||
data["root"] = serde_json::to_value(root)?;
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::try_parse()?;
|
||||
let out_path = PathBuf::from(
|
||||
args.path
|
||||
.components()
|
||||
.last()
|
||||
.unwrap()
|
||||
.as_os_str()
|
||||
.to_string_lossy()
|
||||
.into_owned(),
|
||||
)
|
||||
.with_extension("json.gz");
|
||||
let full_path = &args.root.join(&args.path);
|
||||
let data = if full_path.is_dir() {
|
||||
load_data(&args.root, &args.path)?
|
||||
} else {
|
||||
serde_json::to_value(parse_file(full_path)?)?
|
||||
};
|
||||
let mut dumpfile = GzEncoder::new(File::create(&out_path)?, Compression::best());
|
||||
serde_json::to_writer_pretty(&mut dumpfile, &data)?;
|
||||
println!("Wrote {path}", path = out_path.display());
|
||||
Ok(())
|
||||
}
|
26
tools/remaster/scrap_parse/src/pixel_shader.rs
Normal file
26
tools/remaster/scrap_parse/src/pixel_shader.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// #[derive(Debug)]
|
||||
// enum VecArg {
|
||||
// Tex(f32,f32,f32,f32),
|
||||
// Reg(f32,f32,f32,f32),
|
||||
// Ver(f32,f32,f32,f32),
|
||||
// Col(f32,f32,f32,f32),
|
||||
// Vec(f32,f32,f32,f32),
|
||||
// }
|
||||
|
||||
// struct Arg {
|
||||
// arg: VecArg,
|
||||
// idx: Option<usize>
|
||||
// }
|
||||
|
||||
// #[derive(Debug)]
|
||||
// enum Inst {
|
||||
// Tex(Arg),
|
||||
// Add(Arg,Arg,Arag),
|
||||
// Sub(Arg,Arg,Arag),
|
||||
// Mul(Arg,Arg,Arag),
|
||||
// Mov(Arg,Arg),
|
||||
// }
|
||||
|
||||
fn parse(path: &str) {
|
||||
|
||||
}
|
Loading…
Reference in a new issue