171 Commits

Author SHA1 Message Date
VaDiM
6b66ec7467 Fix rendering of some packed sprites. Close #104 2025-10-15 22:23:42 +03:00
VaDiM
0021cf221e Some minor improvements 2025-10-11 14:28:05 +03:00
VaDiM
c07dc59f51 Improve support for Unity 6000.2+ assets 2025-10-10 04:11:27 +03:00
VaDiM
d1bf0c5a37 Add option to extract raw byte array from MonoBehaviour assets 2025-10-07 01:07:48 +03:00
VaDiM
6d5b633d55 Some minor fixes 2025-10-07 01:07:14 +03:00
VaDiM
6c3ff89dbf Improve lzma progress report 2025-09-12 19:57:36 +03:00
VaDiM
763f188afb Fix memory allocation for uncompressed bundles inside a multiBundle 2025-09-08 03:06:03 +03:00
VaDiM
553f0d94f3 Some fixes for Live2D export
- [CLI] Replaced "--l2d-force-bezier" with "--l2d-smooth-motions"
2025-09-06 03:50:55 +03:00
VaDiM
80e6a1d074 Update README.md 2025-09-04 23:10:34 +03:00
VaDiM
6de33d0437 Update to v0.19 & update dependencies 2025-09-04 20:07:22 +03:00
VaDiM
7ce8b8c8ae [CLI] Some minor fixes 2025-09-04 17:54:55 +03:00
VaDiM
2d449ff4cd Fix support for meshes with omitted weight values. Close #21 2025-09-03 13:12:59 +03:00
VaDiM
1d65096001 [CLI] Add more info to the "Info" mode 2025-09-01 23:38:05 +03:00
VaDiM
355c99c034 [CLI] Fix deleting of temp files 2025-09-01 22:19:48 +03:00
VaDiM
963cd6546b Improve mesh loading 2025-09-01 16:32:46 +03:00
VaDiM
ae3b5169df Some other fixes 2025-08-27 05:23:50 +03:00
VaDiM
521e2f3bbc Improve Tuanjie support 2025-08-27 05:22:46 +03:00
VaDiM
f0a69025fe Update asset export logic
- Disabled saving files with a unique id if they already exist. A unique id will only be added to files with identical names during export.
- Added an option to overwrite exisisting files.
- Fixed support of multiple model export using "Export selected objects (split)" option. (#43)
2025-08-19 20:51:38 +03:00
VaDiM
52b0a21181 Some fixes for bundle reader 2025-08-11 01:27:02 +03:00
VaDiM
be11fdf14f [GUI] Some fixes for animation export
- Disabled animation converting if animation export is disabled in the options
- Fixed a bug with ignoring animation selection order when exporting models with selected animationClips via the “Model” tab
2025-08-11 01:25:42 +03:00
VaDiM
054906a426 More spans 2025-08-11 01:25:42 +03:00
VaDiM
35324083e1 [CLI] Add flag to always decompress bundles to disk 2025-08-03 14:26:49 +03:00
VaDiM
36bd3c8342 [GUI] Rework some import options
- Added feature to load and export import options to a file (import options include unity version).
- Added option to always decompress bundles to disk. (Related issue: #58 )
2025-08-03 00:08:00 +03:00
VaDiM
c20c07b5f2 Update bundle reader
- Replaced creation of a duplicated file/memory stream with OffsetStream.
- Added separate processing of uncompressed bundles (including streamed bundles). They will be read directly from disk.
- Added progress report on LZMA decompression process.
2025-07-24 19:07:24 +03:00
VaDiM
efca2a7557 Add support for bundles with obfuscated unity version 2025-07-24 15:59:38 +03:00
VaDiM
6b41a36c7d Fix parsing of MovieTexture and MonoScript assets 2025-07-24 15:59:37 +03:00
VaDiM
35b24990c6 Allocation-safe asset reading
Try to not pre-allocate memory during asset reading
2025-07-24 04:06:33 +03:00
VaDiM
925f5c12a3 Update FileReader & EndianSpanReader 2025-07-24 04:04:03 +03:00
VaDiM
9c64f7f56d Fix parsing of Tuanjie Renderer assets 2025-07-24 04:04:03 +03:00
VaDiM
3c6b65f724 Update BuildTarget.cs 2025-07-22 03:00:56 +03:00
VaDiM
34819608c5 Fixes for zip file reading
- Fixed path for split files
- Fixed assetsFile loading from an archive
2025-07-22 03:00:56 +03:00
VaDiM
6f8f1a5a8a Use System.Half 2025-07-13 20:40:34 +03:00
VaDiM
f0029520fb Fix for TypeTreeHelper
ref: b71a7620a3
2025-07-13 01:56:09 +03:00
VaDiM
7b7eac62d8 Fixes for Live2D export
- Fixed export of live2d models from assets without containers.
- Improved method of binding model-related assets.
2025-06-27 00:41:58 +03:00
VaDiM
3a25ed9ccd [CLI] Update "current options" structure 2025-06-12 01:41:33 +03:00
VaDiM
785eeb8665 [CLI] Add name filtering support for Live2D export mode 2025-06-12 01:41:33 +03:00
VaDiM
fd50054edf [CLI] Add regex support for splitObject export mode 2025-06-12 01:41:33 +03:00
VaDiM
a1ee61c542 Some minor fixes 2025-06-10 02:06:24 +03:00
VaDiM
12799da395 [CLI] Add Animator export 2025-06-07 23:45:49 +03:00
VaDiM
60426a4b9a Improve support of Tuanjie assets 2025-06-07 23:40:49 +03:00
VaDiM
3ea01ec9bc Display animation count when exporting fbx models 2025-05-29 05:11:21 +03:00
VaDiM
7da68aedff [CLI] Add support for multiple file loading 2025-05-29 05:11:06 +03:00
VaDiM
548f8a52cf Minor fix for multibundle reader 2025-05-25 01:17:54 +03:00
VaDiM
24337f66f9 Fix parsing of Material assets from some 2021.2 versions 2025-05-21 16:08:56 +03:00
VaDiM
92a89db4e8 Fix parsing of legacy Tuanjie AnimationClip assets 2025-05-18 02:18:58 +03:00
VaDiM
c11e085e2e Fix build 2025-05-17 14:30:19 +03:00
VaDiM
55406553f6 Some minor fixes 2025-05-17 04:58:43 +03:00
VaDiM
b0a051fc47 [GUI] Add exact search option for Scene Hierarchy. Close #49 2025-05-11 09:29:11 +03:00
VaDiM
97fa42742b [CLI] Add flag to allow filtering assets using regex. Close #45
- Added --filter-with-regex flag
2025-05-11 09:29:11 +03:00
VaDiM
97bdef0891 Update UnityCN detection method 2025-05-09 03:41:54 +03:00
VaDiM
876bafdda1 Add oodle compression support (unofficial) 2025-05-09 03:41:53 +03:00
VaDiM
66229e564a Fix parsing of AnimationClip assets via typetree for Unity versions < 5 2025-05-09 02:23:42 +03:00
VaDiM
13f37ec260 Fix audioClip converting 2025-04-17 01:01:58 +03:00
VaDiM
a0c2a7bdfe Improve integration with Live2D assets
- Added container-independent method for searching AnimationClip assets
(However, it's not really universal, so it can't completely replace the container-dependent method)
2025-04-10 01:30:45 +03:00
VaDiM
0cc74b8c12 Fix Tuanjie detection 2025-04-08 02:46:11 +03:00
VaDiM
f077064a6a Fix for UV bindings 2025-04-06 00:06:09 +03:00
VaDiM
190cb68b07 [CLI] Add flag to export all UVs as diffuse maps 2025-03-31 20:14:33 +03:00
VaDiM
3fa2ef1694 Some minor fixes 2025-03-31 20:10:02 +03:00
VaDiM
40e0bd0248 [CLI] Fix export of some fbx models 2025-03-31 19:45:47 +03:00
VaDiM
e1e43439c3 Add option to manually bind UV map types 2025-03-29 23:57:59 +03:00
VaDiM
e8ca265a43 Fix multiBundle file extraction 2025-03-25 21:54:34 +03:00
VaDiM
81ed77819a [CLI] Improve UnityVersion option info 2025-03-22 19:01:07 +03:00
VaDiM
d1fed47f92 [CLI] Change color of option example string 2025-03-22 19:01:07 +03:00
VaDiM
3b10a808d3 [GUI] Add option to autoplay audioClip assets 2025-03-22 19:01:06 +03:00
VaDiM
47d67e0a49 Update FMOD to v2.03.06
- Fixed a bug that caused audioСlip preview volume to reset when selecting an asset
- Added some native libs for linux-arm64, win-arm64
2025-03-22 19:01:06 +03:00
VaDiM
bc0e32efec Add multiBundle support
including fake headers
2025-03-10 18:08:40 +03:00
VaDiM
db4eb30a27 Fix PPtrConverter (#69) 2025-03-04 04:05:22 +03:00
VaDiM
9f918d0332 Fix export of selected Live2D motions 2025-03-03 22:18:29 +03:00
VaDiM
81cd6d79d0 Add AnimationClip equality comparer 2025-03-03 22:18:29 +03:00
VaDiM
9024e6a235 Improve external data extraction for ExportRaw mode 2025-02-24 19:03:22 +03:00
VaDiM
0b7b809285 [GUI] Some visual fixes for audio player 2025-02-20 17:33:59 +03:00
VaDiM
f7e6d23084 Add support for obfuscated unity versions 2025-02-17 18:51:05 +03:00
VaDiM
6ea1ff3e96 Fix for m_MuscleClipSize 2025-02-10 17:01:21 +03:00
VaDiM
185348d9b8 Replace Math with MathF 2025-01-31 17:55:47 +03:00
VaDiM
a8bb6c714b A small refactoring for Live2D motion export 2025-01-23 18:18:47 +03:00
VaDiM
cc21d4fa4d [CLI] Add support of Extract mode 2025-01-23 17:57:42 +03:00
VaDiM
e3e343320c [GUI] AudioClip improvements
- Increased loading speed of AudioClip preview
- Optimized memory consumption of AudioClip preview
- Fixed incorrect length detection for some sound types
- Added channel count info (audio channels)
2025-01-20 13:07:25 +03:00
VaDiM
1cdb0b762a Some fixes and improvements for Live2D export
- Fixed l2d model export for bundles with multiple models inside
- Added support of grouping exported models by model name
2025-01-15 03:38:33 +03:00
VaDiM
02f64f3c97 [GUI] Workaround for progress bar in Dark mode 2025-01-15 00:41:01 +03:00
VaDiM
58917ab7dc [GUI] Add tree view for dump 2025-01-15 00:41:01 +03:00
VaDiM
b7d21e5bd8 Add support for Tuanjie AnimationClip assets 2025-01-12 04:08:20 +03:00
VaDiM
d7b4d415ca Add support for Tuanjie Mesh assets 2025-01-12 04:08:20 +03:00
VaDiM
95f7d70419 Fix support of Tuanjie GameObject assets 2025-01-12 04:08:20 +03:00
VaDiM
4e93ea5a82 Improve ExportRaw option
- External data will also be added to exported assets
2025-01-12 04:08:19 +03:00
VaDiM
6608e76471 Improve error messages for AudioClip assets 2025-01-12 04:08:19 +03:00
VaDiM
ff92d1784d [GUI] Some fixes for Dark mode 2025-01-12 04:08:19 +03:00
VaDiM
064f5cbe57 Improve integration with Live2D assets 2025-01-12 04:08:19 +03:00
VaDiM
59db27de3a [GUI] Fix a bug with OpenFolderAfterExport option
- Fixed a bug with the OpenFolderAfterExport option when it launched a file instead of opening a folder in some cases
2025-01-12 04:08:19 +03:00
VaDiM
0d4e7ba4ae [GUI] Add Dark mode support for .NET 9 (wip). Close #9
Dark mode support for winforms was added with .net9, but the feature is still not finished. It should become better in future versions.
2025-01-12 04:08:19 +03:00
VaDiM
3605bc0ff9 Update project files: add .NET 9 & update dependencies 2025-01-12 04:08:19 +03:00
VaDiM
188ee088a2 Improve support of Texture2DArray assets 2025-01-12 04:08:19 +03:00
VaDiM
341612be16 Add Tuanjie WebFile support 2025-01-12 04:08:19 +03:00
VaDiM
e16046d775 Add support for Tuanjie Texture2D assets 2025-01-12 04:08:19 +03:00
VaDiM
d2f69432e4 Add Tuanjie build targets 2025-01-12 04:08:18 +03:00
VaDiM
08d50a8013 Update BuildTarget.cs 2025-01-12 04:08:18 +03:00
VaDiM
7b1585eff0 A small refactoring of l2d extractor 2025-01-12 04:08:18 +03:00
VaDiM
70aa8bec59 Add support for exporting l2d poses (pose3.json) 2025-01-12 04:08:18 +03:00
VaDiM
18813b22c3 Add names of pptr objects to object dumps 2024-11-02 04:51:21 +03:00
VaDiM
316837dfdf Fix parsing via typetree of old Material assets
- Fixed parsing via typetree of Material assets from Unity version <5.6
2024-11-02 02:12:49 +03:00
VaDiM
fca937e5e6 Some fixes for asset parsing via typetree 2024-11-02 01:40:45 +03:00
VaDiM
c2095c4e7a Fix audio preview for some fmod formats. Close #53 2024-10-30 17:11:19 +03:00
VaDiM
f253c868d4 Fix calculations in Live2D motions
- Fixed calculation of totalPointCount and totalSegmentCount in Live2D motions.
https://github.com/Live2D/CubismNativeFramework/pull/57
2024-10-30 01:26:37 +03:00
VaDiM
8ccdd0fd4e Minor fix for PPtrConverter 2024-10-22 01:58:15 +03:00
VaDiM
bc92dfb77c Add Material loading via typetree 2024-10-20 22:29:06 +03:00
VaDiM
c37e2e65b7 Fixes and improvements for asset parsing via typetree 2024-10-18 20:55:34 +03:00
VaDiM
58ee2b8f1e Improve support for some older Unity versions (<3.0)
- Fix export of AudioClip assets from unity v2.5 and earlier
- Fix parsing of PlayerSettings assets from unity v2.6 and earlier
- Fix parsing of AnimationClip assets from unity v2.5 and earlier
2024-10-05 02:17:16 +03:00
VaDiM
c93d27d9a4 Fixes for Unity version parser 2024-10-03 16:23:51 +03:00
VaDiM
5a84a67955 Move BuildType to UnityVersion class 2024-09-25 23:40:41 +03:00
VaDiM
fa332b45df Improve support of Unity 2023+ 2024-09-25 23:38:19 +03:00
VaDiM
348aea2be8 Update CommonString.cs
Unity 6
2024-09-25 23:38:18 +03:00
VaDiM
d52f192e75 Fix support of Sprites with wrong SpriteAtlas pathID 2024-09-13 00:39:04 +03:00
VaDiM
81a1eeb2d1 Merge branch 'pr/40' into AssetStudioMod 2024-09-04 01:15:22 +03:00
VaDiM
05ea91ef5e Merge branch 'pr/44' into AssetStudioMod 2024-08-08 21:49:27 +03:00
VaDiM
e0d5e5c6b7 Display "type" as a string in object dumps 2024-08-08 18:58:42 +03:00
VaDiM
b439cfed66 Update ClassIDType.cs 2024-08-08 18:42:28 +03:00
VaDiM
573b87b570 Replace "type" with "classID" in object dumps 2024-08-08 18:16:41 +03:00
Loyie King
585b69fb36 fix bundle blocks read failed with ArchiveFlags.BlocksInfoAtTheEnd
Bundle files may be aligned and padding with zeros. Previously `ArchiveFlags.BlocksInfoAtTheEnd` will read the end padding zeros rather than the real block infos, causing decompression errors in following logics.
2024-07-10 19:23:36 +08:00
hungrydoodles
5e3fe1775f Added so when the exported animator contains MeshRenderers without meshes attached it tries to find the missing meshes by the Renderer's original name. (Fixes NagantSR0101 from Girls Frontline 2 Animator export not exporting meshes at all in any existing variant.) Also set ReShade in 3D view to be disabled by default as it is misleading otherwise 2024-05-15 00:05:50 +05:00
VaDiM
8704feb079 Merge branch 'pr/37' into AssetStudioMod 2024-05-10 03:45:06 +03:00
VaDiM
f54fe3492b [CLI] Fix Mesh export for some region formats. Close #38 2024-05-10 03:22:39 +03:00
BM85-Hz
6d953d774d simplify loop label 2024-05-08 22:30:50 -07:00
BM85-Hz
f0a793bd3d added AudioClip loop point display to GUI 2024-05-05 18:34:28 -07:00
VaDiM
d886bf1c5d Update dependencies 2024-04-25 01:23:34 +03:00
VaDiM
1623981c0e [GUI] Add ability to filter live2d model assets 2024-04-24 22:19:51 +03:00
VaDiM
2c860f004b Use system.text.json to parse typetree
well, it's still slower than some more suitable libs for such task, but stable and with minimal code changes (and has net472 support, yeah)
2024-04-14 02:17:06 +03:00
VaDiM
a3f4c7a029 [CLI] Update readme 2024-04-12 21:48:57 +03:00
VaDiM
f86b5a97ac Fix resourceFileReader for webFile 2024-04-12 21:48:53 +03:00
VaDiM
7e408a3667 [GUI] Fix displayed info for non-fmod audio clips from Unity <5 2024-04-12 21:48:53 +03:00
VaDiM
6c515aee2e Fix support for sprite assets from Unity <5.2 2024-04-10 10:34:46 +03:00
VaDiM
bb7accd04d Update version to v0.18.0
- Updated dependencies
2024-04-04 22:44:20 +03:00
VaDiM
5120999026 Update readme and other text files 2024-04-04 21:55:59 +03:00
VaDiM
1fc504e587 Optimize memory consumption of swizzled textures 2024-04-02 00:40:24 +03:00
VaDiM
4e991d85fb More fixes for unity 2019.4 assets 2024-04-01 00:56:48 +03:00
VaDiM
29b4bb59a0 [GUI] Move "loading via typetree" option to a better place 2024-04-01 00:56:48 +03:00
VaDiM
9750f486d5 Fix moc3 export 2024-04-01 00:21:51 +03:00
VaDiM
97bbfe8fbb Fix type of public "offset" property in ResourceReader 2024-04-01 00:21:50 +03:00
VaDiM
684bf5a874 Show assumed unity ver in some cases for assets with stripped ver 2024-04-01 00:21:50 +03:00
VaDiM
3cc6bed844 Raplace Unity ver array with Unity ver class 2024-04-01 00:21:50 +03:00
VaDiM
c9e9bc840c Add parallel export support for some asset types 2024-04-01 00:21:50 +03:00
VaDiM
cadcf0b492 Fix displayed info for non-fmod audio clips 2024-03-28 01:52:43 +03:00
VaDiM
1e8085da2d Fix AssetBundle structure for Unity v5.4.x. Close #31 2024-03-28 01:52:43 +03:00
VaDiM
770d7e7532 [GUI] Fix compatibility with High Contrast modes 2024-03-15 18:19:05 +03:00
VaDiM
d0d8a35f67 [GUI] Fixes for Tex2DArrayImage 2024-03-14 00:42:56 +03:00
VaDiM
3f004f74d1 Add option to disable asset loading via typetree 2024-03-13 22:52:43 +03:00
VaDiM
3effd06e64 Unity 2023.2+ Texture2D fix 2024-03-13 22:52:43 +03:00
VaDiM
4f0afffeba Add AnimationClip loading via typetree 2024-03-13 22:52:43 +03:00
VaDiM
9b69b5607c Fix DisplayInfo default value in model3.json 2024-03-10 23:17:25 +03:00
VaDiM
9b16ea8d41 Fix bug with Blend type in l2d expressions 2024-03-09 22:47:11 +03:00
VaDiM
ae4548f1c3 Add support for swizzled Switch textures
Co-Authored-By: nesrak1 <12544505+nesrak1@users.noreply.github.com>
2024-03-09 02:35:23 +03:00
VaDiM
4cd246592b [CLI] Fix wrong error handler. Fix option description msgs 2024-03-07 04:38:39 +03:00
VaDiM
f54cc004bd Add support for Zstd block compression 2024-03-07 03:49:06 +03:00
VaDiM
afdc81bca8 Some minor fixes 2024-03-05 23:42:35 +03:00
VaDiM
045f6c0ff4 Add Texture2DArray loading via typetree 2024-03-05 23:42:29 +03:00
VaDiM
bc9380b8be Add Texture2D loading via typetree 2024-03-05 23:42:29 +03:00
VaDiM
46f8023756 [GUI] Improve export of Texture2DArray images
- Do not export an entire tex2darray array if both the tex2darray and some of its images were selected for exporting
2024-03-05 23:42:07 +03:00
VaDiM
0f9afa60d7 Add support for Texture2DArray 2024-03-04 19:46:28 +03:00
VaDiM
ec7f2c393d [CLI] Update readme 2024-02-13 05:43:34 +03:00
VaDiM
3ec8169b08 [GUI] Add more details to log when exporting assets 2024-02-13 04:55:25 +03:00
VaDiM
5c24183d18 Add more options to work with Scene Hierarchy (#23)
- Added option to group exported assets by node path in scene hierarchy
- Added field with node path to exported xml asset list
2024-02-13 04:52:59 +03:00
VaDiM
c68eaa5e3c Fixes for previous fixes 2024-02-13 04:51:14 +03:00
VaDiM
8460ecef8d Show/Export object dump if typetree dump is not available 2024-02-12 05:21:23 +03:00
VaDiM
f90c0ecc00 Add option to export assets with PathID in filename (#25)
https://github.com/Perfare/AssetStudio/issues/1050
https://github.com/Perfare/AssetStudio/issues/975
https://github.com/Perfare/AssetStudio/issues/762
2024-02-11 03:01:40 +03:00
VaDiM
535153be6b Add cdi3.json support for l2d export (beta) 2024-02-09 22:35:14 +03:00
VaDiM
d4162161be [GUI] Replace "Show all error msgs" option with "Show debug msgs" 2024-02-08 22:44:57 +03:00
VaDiM
6fe12d274f [CLI] Add colors to help message 2024-02-08 22:35:48 +03:00
VaDiM
70213e3012 Improve integration with Live2D assets
- Improved export method of AnimationClip motions
- [GUI] Added display of model info on the preview tab
- [GUI] Added support for partial export:
  - selected models
  - model + selected AnimationClip motions
  - model + selected Fade motions
  - model + selected Fade Motion List
2024-02-08 22:34:00 +03:00
VaDiM
2f6d9ec77f Fixes & Cleanup 2024-01-31 22:34:12 +03:00
VaDiM
0d2aebc1f4 Fix a bug where UV is exported incorrectly.
Co-Authored-By: Razmoth <32140579+razmoth@users.noreply.github.com>
2024-01-24 23:26:13 +03:00
VaDiM
115074fdc0 [GUI] Preserve selection order of AnimationClips (#24) 2023-12-30 18:51:01 +03:00
VaDiM
c2d3b8c5f9 Improve Live2D export 2023-12-30 18:13:40 +03:00
VaDiM
67a74fd395 Bugfix for unity 2022.2+ Texture2D reader 2023-12-30 17:08:07 +03:00
209 changed files with 15110 additions and 5973 deletions

View File

@@ -1,9 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<TargetFrameworks>net472;net8.0;net8.0-windows;net9.0;net9.0-windows</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.17.4.0</Version>
<Version>0.19.0.0</Version>
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>

View File

@@ -11,7 +11,7 @@ namespace AssetStudio.PInvoke
{
public static void PreloadDll(string dllName)
{
var localPath = Process.GetCurrentProcess().MainModule.FileName;
var localPath = Process.GetCurrentProcess().MainModule?.FileName;
var localDir = Path.GetDirectoryName(localPath);
// Not using OperatingSystem.Platform.
@@ -35,7 +35,6 @@ namespace AssetStudio.PInvoke
private static class Win32
{
internal static void LoadDll(string dllDir, string dllName)
{
var dllFileName = $"{dllName}.dll";

View File

@@ -1,20 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<Version>0.17.4.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
<TargetFrameworks>net472;net8.0;net8.0-windows;net9.0;net9.0-windows</TargetFrameworks>
<Version>0.19.0.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2025</Copyright>
<DebugType>embedded</DebugType>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
<ItemGroup>
<PackageReference Include="ZstdSharp.Port" Version="0.8.6" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="9.0.8" />
<PackageReference Include="Microsoft.Bcl.Numerics" Version="9.0.8" />
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,37 +1,50 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json;
using AssetStudio.CustomOptions;
using AssetStudio.CustomOptions.Asmo;
using static AssetStudio.ImportHelper;
namespace AssetStudio
{
public class AssetsManager
{
public string SpecifyUnityVersion;
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
private HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
public bool LoadViaTypeTree = true;
public bool MeshLazyLoad = true;
public ImportOptions Options = new ImportOptions();
public readonly List<Action<OptionsFile>> OptionLoaders = new List<Action<OptionsFile>>();
public readonly List<SerializedFile> AssetsFileList = new List<SerializedFile>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
internal ConcurrentDictionary<string, BinaryReader> resourceFileReaders = new ConcurrentDictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
private List<string> importFiles = new List<string>();
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly List<string> importFiles = new List<string>();
private readonly HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
private readonly HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
public AssetsManager()
{
OptionLoaders.Add(LoadImportOptions);
}
public void SetAssetFilter(params ClassIDType[] classIDTypes)
{
if (filteredAssetTypesList.Count == 0)
{
filteredAssetTypesList.UnionWith(new HashSet<ClassIDType>
filteredAssetTypesList.UnionWith(new[]
{
ClassIDType.AssetBundle,
ClassIDType.ResourceManager,
ClassIDType.GameObject,
ClassIDType.Transform,
ClassIDType.RectTransform,
});
}
if (classIDTypes.Contains(ClassIDType.MonoBehaviour))
{
@@ -42,6 +55,23 @@ namespace AssetStudio
filteredAssetTypesList.Add(ClassIDType.Texture2D);
filteredAssetTypesList.Add(ClassIDType.SpriteAtlas);
}
if (classIDTypes.Contains(ClassIDType.Animator))
{
filteredAssetTypesList.Add(ClassIDType.AnimatorController);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
filteredAssetTypesList.Add(ClassIDType.Animation);
filteredAssetTypesList.Add(ClassIDType.AnimationClip);
filteredAssetTypesList.Add(ClassIDType.Avatar);
filteredAssetTypesList.Add(ClassIDType.Material);
filteredAssetTypesList.Add(ClassIDType.MeshFilter);
filteredAssetTypesList.Add(ClassIDType.MeshRenderer);
filteredAssetTypesList.Add(ClassIDType.SkinnedMeshRenderer);
}
if (classIDTypes.Contains(ClassIDType.AnimatorController))
{
filteredAssetTypesList.Add(ClassIDType.Animator);
filteredAssetTypesList.Add(ClassIDType.AnimatorOverrideController);
}
filteredAssetTypesList.UnionWith(classIDTypes);
}
@@ -51,32 +81,28 @@ namespace AssetStudio
SetAssetFilter(classIDTypeList.ToArray());
}
public void LoadFilesAndFolders(params string[] path)
public void LoadFilesAndFolders(params string[] paths)
{
List<string> pathList = new List<string>();
pathList.AddRange(path);
LoadFilesAndFolders(out _, pathList);
LoadFilesAndFolders(out _, paths.ToList());
}
public void LoadFilesAndFolders(out string parentPath, params string[] path)
public void LoadFilesAndFolders(out string parentPath, params string[] paths)
{
List<string> pathList = new List<string>();
pathList.AddRange(path);
LoadFilesAndFolders(out parentPath, pathList);
LoadFilesAndFolders(out parentPath, paths.ToList());
}
public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
{
List<string> fileList = new List<string>();
bool filesInPath = false;
var fileList = new List<string>();
var filesInPath = false;
parentPath = "";
foreach (var path in pathList)
{
var fullPath = Path.GetFullPath(path);
if (Directory.Exists(fullPath))
{
var parent = Directory.GetParent(fullPath).FullName;
if (!filesInPath && (parentPath == "" || parentPath.Length > parent.Length))
var parent = Directory.GetParent(fullPath)?.FullName;
if (!filesInPath && (parentPath == "" || parentPath?.Length > parent?.Length))
{
parentPath = parent;
}
@@ -94,6 +120,8 @@ namespace AssetStudio
{
MergeSplitAssets(parentPath);
}
LoadOptionFiles(fileList);
var toReadFile = ProcessingSplitFiles(fileList);
fileList.Clear();
pathList.Clear();
@@ -113,35 +141,44 @@ namespace AssetStudio
//use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++)
{
LoadFile(importFiles[i]);
if (LoadFile(importFiles[i]))
{
Progress.Report(i + 1, importFiles.Count);
}
else
{
break;
}
}
importFiles.Clear();
importFilesHash.Clear();
noexistFiles.Clear();
assetsFileListHash.Clear();
if (AssetsFileList.Count == 0)
return;
ReadAssets();
ProcessAssets();
}
private void LoadFile(string fullName)
private bool LoadFile(string fullName)
{
var reader = new FileReader(fullName);
LoadFile(reader);
return LoadFile(reader);
}
private void LoadFile(FileReader reader)
private bool LoadFile(FileReader reader, bool fromZip = false)
{
switch (reader?.FileType)
if (reader == null)
return false;
switch (reader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFile(reader);
break;
return LoadAssetsFile(reader, fromZip);
case FileType.BundleFile:
LoadBundleFile(reader);
break;
return LoadBundleFile(reader);
case FileType.WebFile:
LoadWebFile(reader);
break;
@@ -154,20 +191,27 @@ namespace AssetStudio
case FileType.ZipFile:
LoadZipFile(reader);
break;
case FileType.ResourceFile when !fromZip:
reader.Dispose();
break;
}
return true;
}
private void LoadAssetsFile(FileReader reader)
private bool LoadAssetsFile(FileReader reader, bool fromZip)
{
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {reader.FullPath}");
Logger.Info($"Loading \"{reader.FullPath}\"");
try
{
var assetsFile = new SerializedFile(reader, this);
var dirName = Path.GetDirectoryName(reader.FullPath);
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
AssetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
if (fromZip)
return true;
foreach (var sharedFile in assetsFile.m_Externals)
{
@@ -175,12 +219,12 @@ namespace AssetStudio
if (!importFilesHash.Contains(sharedFileName))
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
var sharedFilePath = Path.Combine(dirName, sharedFileName);
if (!noexistFiles.Contains(sharedFilePath))
{
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
var findFiles = Directory.GetFiles(dirName, sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
@@ -194,6 +238,7 @@ namespace AssetStudio
else
{
noexistFiles.Add(sharedFilePath);
Logger.Warning($"Dependency wasn't found: {sharedFilePath}");
}
}
}
@@ -203,21 +248,23 @@ namespace AssetStudio
{
Logger.Error(e.Message);
reader.Dispose();
return false;
}
catch (Exception e)
{
Logger.Warning($"Error while reading assets file {reader.FullPath}\r\n{e}");
Logger.Warning($"Failed to read assets file \"{reader.FullPath}\"\n{e}");
reader.Dispose();
}
}
else
{
Logger.Info($"Skipping {reader.FullPath}");
Logger.Info($"Skipping \"{reader.FullPath}\"");
reader.Dispose();
}
return true;
}
private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
private bool LoadAssetsFromMemory(FileReader reader, string originalPath, UnityVersion assetBundleUnityVer = null)
{
if (!assetsFileListHash.Contains(reader.FileName))
{
@@ -225,71 +272,117 @@ namespace AssetStudio
{
var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath;
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
if (assetBundleUnityVer != null && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
{
assetsFile.SetVersion(unityVersion);
assetsFile.version = assetBundleUnityVer;
}
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
CheckStrippedVersion(assetsFile, assetBundleUnityVer);
AssetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
}
catch (NotSupportedException e)
{
Logger.Error(e.Message);
resourceFileReaders.Add(reader.FileName, reader);
reader.Dispose();
return false;
}
catch (Exception e)
{
Logger.Warning($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}");
resourceFileReaders.Add(reader.FileName, reader);
Logger.Warning($"Failed to read assets file \"{reader.FullPath}\" from {Path.GetFileName(originalPath)}\n{e}");
resourceFileReaders.TryAdd(reader.FileName, reader);
}
}
else
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
{
Logger.Info($"Skipping \"{originalPath}\" ({reader.FileName})");
}
return true;
}
private void LoadBundleFile(FileReader reader, string originalPath = null)
private bool LoadBundleFile(FileReader reader, string originalPath = null)
{
Logger.Info("Loading " + reader.FullPath);
Logger.Info($"Loading \"{reader.FullPath}\"");
Logger.Debug($"Bundle offset: {reader.Position}");
var bundleStream = new OffsetStream(reader);
var bundleReader = new FileReader(reader.FullPath, bundleStream);
var isLoaded = false;
try
{
var bundleFile = new BundleFile(reader, SpecifyUnityVersion);
foreach (var file in bundleFile.fileList)
var bundleFile = new BundleFile(bundleReader, Options.BundleOptions);
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath);
if (!isLoaded)
return false;
while (bundleFile.IsDataAfterBundle && isLoaded)
{
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
isLoaded = false;
bundleStream.Offset = reader.Position;
bundleReader = new FileReader($"{reader.FullPath}_0x{bundleStream.Offset:X}", bundleStream);
if (bundleReader.FileType != FileType.BundleFile)
{
LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
Logger.Debug("Unknown data was detected after the end of the bundle.");
break;
}
else if (!resourceFileReaders.ContainsKey(file.fileName))
if (bundleReader.Position > 0)
{
resourceFileReaders.Add(file.fileName, subReader);
bundleStream.Offset += bundleReader.Position;
bundleReader.FullPath = $"{reader.FullPath}_0x{bundleStream.Offset:X}";
bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}";
}
Logger.Info($"[MultiBundle] Loading \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}");
bundleFile = new BundleFile(bundleReader, Options.BundleOptions, isMultiBundle: true);
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath ?? reader.FullPath);
}
return isLoaded;
}
catch (NotSupportedException e)
{
Logger.Error(e.Message);
return false;
}
catch (Exception e)
{
var str = $"Error while reading bundle file {reader.FullPath}";
var str = $"Error while reading bundle file \"{bundleReader.FullPath}\"";
if (originalPath != null)
{
str += $" from {Path.GetFileName(originalPath)}";
}
Logger.Warning($"{str}\r\n{e}");
Logger.Warning($"{str}\n{e}");
return true;
}
finally
{
reader.Dispose();
if (!isLoaded)
bundleReader.Dispose();
}
}
private bool LoadBundleFiles(FileReader reader, BundleFile bundleFile, string originalPath = null)
{
foreach (var file in bundleFile.fileList)
{
if (file.stream == null)
continue;
file.stream.Position = 0; //go to file offset
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{
if (!LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision))
return false;
}
else
{
resourceFileReaders.TryAdd(file.fileName, subReader);
}
}
return true;
}
private void LoadWebFile(FileReader reader)
{
Logger.Info("Loading " + reader.FullPath);
Logger.Info($"Loading \"{reader.FullPath}\"");
try
{
var webFile = new WebFile(reader);
@@ -309,14 +402,14 @@ namespace AssetStudio
LoadWebFile(subReader);
break;
case FileType.ResourceFile:
resourceFileReaders[file.fileName] = subReader; //TODO
resourceFileReaders.TryAdd(file.fileName, subReader);
break;
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading web file {reader.FullPath}", e);
Logger.Error($"Error while reading web file \"{reader.FullPath}\"", e);
}
finally
{
@@ -353,15 +446,16 @@ namespace AssetStudio
}
// merge split files and load the result
foreach (string basePath in splitFiles)
for (var i = 0; i < splitFiles.Count; i++)
{
var basePath = splitFiles[i].Replace("\\", "/");
try
{
Stream splitStream = new MemoryStream();
int i = 0;
var j = 0;
while (true)
{
string path = $"{basePath}.split{i++}";
string path = $"{basePath}.split{j++}";
ZipArchiveEntry entry = archive.GetEntry(path);
if (entry == null)
break;
@@ -372,11 +466,12 @@ namespace AssetStudio
}
splitStream.Seek(0, SeekOrigin.Begin);
FileReader entryReader = new FileReader(basePath, splitStream);
LoadFile(entryReader);
if (!LoadFile(entryReader, fromZip: true))
break;
}
catch (Exception e)
{
Logger.Warning($"Error while reading zip split file {basePath}\r\n{e}");
Logger.Warning($"Error while reading zip split file \"{basePath}\"\n{e}");
}
}
@@ -386,6 +481,8 @@ namespace AssetStudio
Progress.Reset();
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.Length == 0)
continue;
try
{
string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName);
@@ -400,20 +497,19 @@ namespace AssetStudio
streamReader.Position = 0;
FileReader entryReader = new FileReader(dummyPath, streamReader);
LoadFile(entryReader);
if (!LoadFile(entryReader, fromZip: true))
break;
if (entryReader.FileType == FileType.ResourceFile)
{
entryReader.Position = 0;
if (!resourceFileReaders.ContainsKey(entry.Name))
{
resourceFileReaders.Add(entry.Name, entryReader);
}
resourceFileReaders.TryAdd(entry.Name, entryReader);
}
Progress.Report(++k, progressCount);
}
catch (Exception e)
{
Logger.Warning($"Error while reading zip entry {entry.FullName}\r\n{e}");
Logger.Warning($"Error while reading zip entry \"{entry.FullName}\"\n{e}");
}
}
}
@@ -428,26 +524,92 @@ namespace AssetStudio
}
}
public void CheckStrippedVersion(SerializedFile assetsFile)
public void LoadOptionFiles(List<string> pathList)
{
if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
if (pathList.Count == 0)
return;
var optionFileIndexes = new List<int>();
for (var i = 0; i < pathList.Count; i++)
{
throw new NotSupportedException("The Unity version has been stripped, please set the version in the options");
var path = pathList[i];
if (!path.EndsWith(OptionsFile.Extension, StringComparison.OrdinalIgnoreCase))
continue;
optionFileIndexes.Add(i);
var optionsFile = LoadOptionsFile(new FileReader(path));
if (optionsFile == null)
continue;
foreach (var optionsLoader in OptionLoaders)
{
optionsLoader(optionsFile);
}
if (!string.IsNullOrEmpty(SpecifyUnityVersion))
}
for (var i = 0; i < optionFileIndexes.Count; i++)
{
assetsFile.SetVersion(SpecifyUnityVersion);
pathList.RemoveAt(optionFileIndexes[i] - i);
}
}
private static OptionsFile LoadOptionsFile(FileReader reader)
{
Logger.Info($"Loading options file \"{reader.FullPath}\"");
try
{
return new OptionsFile(reader);
}
catch (Exception e)
{
Logger.Warning($"Error while loading options file \"{reader.FullPath}\"\n{e}");
return null;
}
finally
{
reader.Dispose();
}
}
private void LoadImportOptions(OptionsFile optionsFile)
{
try
{
var importOptions = ImportOptions.FromOptionsFile(optionsFile);
if (importOptions == null)
return;
Options = importOptions;
Logger.Info("Import options successfully loaded.");
}
catch (Exception e)
{
Logger.Warning($"Error while reading import options\n{e}");
}
}
public void CheckStrippedVersion(SerializedFile assetsFile, UnityVersion bundleUnityVer = null)
{
if (assetsFile.version.IsStripped && Options.CustomUnityVersion == null)
{
var msg = "The asset's Unity version has been stripped, please set the version in the options.";
if (bundleUnityVer != null && !bundleUnityVer.IsStripped)
msg += $"\n\nAssumed Unity version based on asset bundle: {bundleUnityVer}";
throw new NotSupportedException(msg);
}
if (Options.CustomUnityVersion != null)
{
assetsFile.version = Options.CustomUnityVersion;
}
}
public void Clear()
{
foreach (var assetsFile in assetsFileList)
foreach (var assetsFile in AssetsFileList)
{
assetsFile.Objects.Clear();
assetsFile.reader.Close();
}
assetsFileList.Clear();
AssetsFileList.Clear();
foreach (var resourceFileReader in resourceFileReaders)
{
@@ -462,11 +624,20 @@ namespace AssetStudio
{
Logger.Info("Read assets...");
var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);
int i = 0;
Progress.Reset();
foreach (var assetsFile in assetsFileList)
var jsonOptions = new JsonSerializerOptions
{
Converters = { new JsonConverterHelper.ByteArrayConverter(), new JsonConverterHelper.PPtrConverter(), new JsonConverterHelper.KVPConverter() },
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
PropertyNameCaseInsensitive = true,
IncludeFields = true,
};
var progressCount = AssetsFileList.Sum(x => x.m_Objects.Count);
var i = 0;
Progress.Reset();
foreach (var assetsFile in AssetsFileList)
{
JsonConverterHelper.AssetsFile = assetsFile;
foreach (var objectInfo in assetsFile.m_Objects)
{
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
@@ -483,7 +654,9 @@ namespace AssetStudio
obj = new Animation(objectReader);
break;
case ClassIDType.AnimationClip:
obj = new AnimationClip(objectReader);
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new AnimationClip(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions, objectInfo)
: new AnimationClip(objectReader);
break;
case ClassIDType.Animator:
obj = new Animator(objectReader);
@@ -503,6 +676,9 @@ namespace AssetStudio
case ClassIDType.Avatar:
obj = new Avatar(objectReader);
break;
case ClassIDType.BuildSettings:
obj = new BuildSettings(objectReader);
break;
case ClassIDType.Font:
obj = new Font(objectReader);
break;
@@ -510,7 +686,9 @@ namespace AssetStudio
obj = new GameObject(objectReader);
break;
case ClassIDType.Material:
obj = new Material(objectReader);
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Material(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: new Material(objectReader);
break;
case ClassIDType.Mesh:
obj = new Mesh(objectReader);
@@ -540,7 +718,7 @@ namespace AssetStudio
obj = new RectTransform(objectReader);
break;
case ClassIDType.Shader:
if (objectReader.version[0] < 2021)
if (objectReader.version < 2021)
obj = new Shader(objectReader);
break;
case ClassIDType.SkinnedMeshRenderer:
@@ -556,7 +734,14 @@ namespace AssetStudio
obj = new TextAsset(objectReader);
break;
case ClassIDType.Texture2D:
obj = new Texture2D(objectReader);
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Texture2D(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: new Texture2D(objectReader);
break;
case ClassIDType.Texture2DArray:
obj = objectReader.serializedType?.m_Type != null && LoadViaTypeTree
? new Texture2DArray(objectReader, TypeTreeHelper.ReadTypeByteArray(objectReader.serializedType.m_Type, objectReader), jsonOptions)
: new Texture2DArray(objectReader);
break;
case ClassIDType.Transform:
obj = new Transform(objectReader);
@@ -572,8 +757,10 @@ namespace AssetStudio
break;
}
if (obj != null)
{
assetsFile.AddObject(obj);
}
}
catch (Exception e)
{
var sb = new StringBuilder();
@@ -595,7 +782,7 @@ namespace AssetStudio
{
Logger.Info("Process assets...");
foreach (var assetsFile in assetsFileList)
foreach (var assetsFile in AssetsFileList)
{
foreach (var obj in assetsFile.Objects)
{
@@ -625,6 +812,34 @@ namespace AssetStudio
case Animation m_Animation:
m_GameObject.m_Animation = m_Animation;
break;
case MonoBehaviour m_MonoBehaviour:
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
switch (m_Script.m_ClassName)
{
case "CubismModel":
if (m_GameObject.m_Transform == null)
break;
m_GameObject.CubismModel = new CubismModel(m_GameObject)
{
CubismModelMono = m_MonoBehaviour
};
break;
case "CubismPhysicsController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.PhysicsController = m_MonoBehaviour;
break;
case "CubismFadeController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.FadeController = m_MonoBehaviour;
break;
case "CubismExpressionController":
if (m_GameObject.CubismModel != null)
m_GameObject.CubismModel.ExpressionController = m_MonoBehaviour;
break;
}
}
break;
}
}
}
@@ -639,16 +854,17 @@ namespace AssetStudio
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
else if (m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld))
else if (m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlasOld))
{
if (m_SpriteAtlaOld.m_IsVariant)
if (m_SpriteAtlasOld.m_IsVariant)
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
else
{
Logger.Warning($"\"{m_Sprite.m_Name}\": Sprite loading error. SpriteAtlas with PathID: \"{m_Sprite.m_SpriteAtlas.m_PathID}\" was not found.");
Logger.Debug($"\"{m_Sprite.m_Name}\": The actual SpriteAtlas PathID \"{m_SpriteAtlas.m_PathID}\" does not match the specified one \"{m_Sprite.m_SpriteAtlas.m_PathID}\".");
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
}

View File

@@ -4,7 +4,11 @@ namespace AssetStudio
{
public static class BigArrayPool<T>
{
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
public static ArrayPool<T> Shared => s_shared;
public static ArrayPool<T> Shared { get; }
static BigArrayPool()
{
Shared = ArrayPool<T>.Create(256 * 1024 * 1024, 5);
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public enum BuildTarget
{
@@ -53,6 +48,18 @@ namespace AssetStudio
PS5,
EmbeddedLinux,
QNX,
VisionOS,
Switch2,
UnknownPlatform = 9999
}
public enum TuanjieBuildTarget
{
MiniGame = 47,
OpenHarmony,
HMIAndroid,
ArmLinux,
ArmLinuxServer,
VisionOS,
}
}

View File

@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public class BuildType
{
private string buildType;
public BuildType(string type)
{
buildType = type;
}
public bool IsAlpha => buildType == "a";
public bool IsPatch => buildType == "p";
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Runtime.InteropServices;
#if NETFRAMEWORK
using AssetStudio.PInvoke;
#endif
namespace BundleCompression.Oodle
{
public static class OodleLZ
{
private const string LibName = "ooz";
#if NETFRAMEWORK
static OodleLZ()
{
DllLoader.PreloadDll(LibName);
}
#endif
[DllImport(LibName)]
private static extern int Ooz_Decompress(
in byte srcBuffer,
UIntPtr srcLen,
ref byte dstBuffer,
UIntPtr dstLen,
int fuzzSafetyFlag,
int crcCheckFlag,
int logVerbosityFlag,
UIntPtr rawBuffer,
UIntPtr rawBufferSize,
UIntPtr chunkDecodeCallback,
UIntPtr chunkDecodeContext,
UIntPtr scratchBuf,
UIntPtr scratchBufSize,
int threadPhase);
public static int Decompress(ReadOnlySpan<byte> srcSpanBuffer, Span<byte> dstSpanBuffer)
{
return Ooz_Decompress(in srcSpanBuffer[0], (UIntPtr)srcSpanBuffer.Length, ref dstSpanBuffer[0], (UIntPtr)dstSpanBuffer.Length,
0, 0, 0, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, UIntPtr.Zero, 0);
}
}
}

View File

@@ -22,26 +22,26 @@ namespace SevenZip
}
}
uint _value = 0xFFFFFFFF;
private uint _value = 0xFFFFFFFF;
public void Init() { _value = 0xFFFFFFFF; }
public void UpdateByte(byte b)
{
_value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
_value = Table[(byte)_value ^ b] ^ (_value >> 8);
}
public void Update(byte[] data, uint offset, uint size)
{
for (uint i = 0; i < size; i++)
_value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
_value = Table[(byte)_value ^ data[offset + i]] ^ (_value >> 8);
}
public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
static uint CalculateDigest(byte[] data, uint offset, uint size)
public static uint CalculateDigest(byte[] data, uint offset, uint size)
{
CRC crc = new CRC();
var crc = new CRC();
// crc.Init();
crc.Update(data, offset, size);
return crc.GetDigest();
@@ -49,7 +49,7 @@ namespace SevenZip
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{
return (CalculateDigest(data, offset, size) == digest);
return CalculateDigest(data, offset, size) == digest;
}
}
}

View File

@@ -1,6 +1,7 @@
// LzmaDecoder.cs
using System;
using AssetStudio;
namespace SevenZip.Compression.LZMA
{
@@ -247,6 +248,8 @@ namespace SevenZip.Compression.LZMA
m_OutWindow.PutByte(b);
nowPos64++;
}
Progress.Reset(index: 1);
while (nowPos64 < outSize64)
{
// UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
@@ -338,6 +341,8 @@ namespace SevenZip.Compression.LZMA
}
m_OutWindow.CopyBlock(rep0, len);
nowPos64 += len;
Progress.Report((int)(nowPos64 * 100f / outSize64), 100, index: 1);
}
}
}

View File

@@ -2,12 +2,11 @@ using System;
using System.IO;
using SevenZip.Compression.LZMA;
namespace AssetStudio
namespace BundleCompression.Lzma
{
public static class SevenZipHelper
public static class SevenZipLzma
{
public static MemoryStream StreamDecompress(MemoryStream inStream)
public static MemoryStream DecompressStream(MemoryStream inStream)
{
var decoder = new Decoder();
@@ -34,7 +33,7 @@ namespace AssetStudio
return newOutStream;
}
public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
public static long DecompressStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
{
var basePosition = compressedStream.Position;
var decoder = new Decoder();
@@ -44,6 +43,7 @@ namespace AssetStudio
decoder.SetDecoderProperties(properties);
decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);
compressedStream.Position = basePosition + compressedSize;
return decompressedStream.Position;
}
}
}

View File

@@ -0,0 +1,65 @@
using BundleCompression.Lzma;
using BundleCompression.Oodle;
using System;
using System.IO;
using System.Text.RegularExpressions;
using K4os.Compression.LZ4;
using ZstdSharp;
namespace AssetStudio
{
public static class BundleDecompressionHelper
{
private static readonly Decompressor ZstdDecompressor = new Decompressor();
private static readonly string MsgPattern = @"\. ";
public static MemoryStream DecompressLzmaStream(MemoryStream inStream)
{
return SevenZipLzma.DecompressStream(inStream);
}
public static long DecompressLzmaStream(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize, ref string errorMsg)
{
var numWrite = -1L;
try
{
numWrite = SevenZipLzma.DecompressStream(compressedStream, decompressedStream, compressedSize, decompressedSize);
}
catch (Exception e)
{
Logger.Debug(e.ToString());
errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})";
}
return numWrite;
}
public static int DecompressBlock(CompressionType type, ReadOnlySpan<byte> srcBuffer, Span<byte> dstBuffer, ref string errorMsg)
{
var numWrite = -1;
try
{
switch (type)
{
case CompressionType.Lz4:
case CompressionType.Lz4HC:
numWrite = LZ4Codec.Decode(srcBuffer, dstBuffer);
break;
case CompressionType.Zstd:
numWrite = ZstdDecompressor.Unwrap(srcBuffer, dstBuffer);
break;
case CompressionType.Oodle:
numWrite = OodleLZ.Decompress(srcBuffer, dstBuffer);
break;
default:
throw new NotSupportedException();
}
}
catch (Exception e)
{
Logger.Debug(e.ToString());
errorMsg = $"({Regex.Split(e.Message, MsgPattern, RegexOptions.CultureInvariant)[0]})";
}
return numWrite;
}
}
}

View File

@@ -1,7 +1,8 @@
using K4os.Compression.LZ4;
using System;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using AssetStudio.CustomOptions;
namespace AssetStudio
{
@@ -18,8 +19,8 @@ namespace AssetStudio
[Flags]
public enum CnEncryptionFlags
{
OldFlag = 0x200,
NewFlag = 0x400
V1 = 0x200,
V2_V3 = 0x1400,
}
[Flags]
@@ -31,21 +32,27 @@ namespace AssetStudio
public enum CompressionType
{
Auto = -1,
None,
Lzma,
Lz4,
Lz4HC,
Lzham
Lzham,
Zstd, //custom
Oodle, //custom
}
public class BundleFile
{
public readonly bool IsDataAfterBundle;
private readonly CustomBundleOptions _bundleOptions;
public class Header
{
public string signature;
public uint version;
public string unityVersion;
public string unityRevision;
public UnityVersion unityRevision;
public long size;
public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize;
@@ -71,15 +78,17 @@ namespace AssetStudio
private StorageBlock[] m_BlocksInfo;
private Node[] m_DirectoryInfo;
public StreamFile[] fileList;
public List<StreamFile> fileList;
public BundleFile(FileReader reader, string specUnityVer = "")
public BundleFile(FileReader reader, CustomBundleOptions bundleOptions, bool isMultiBundle = false)
{
_bundleOptions = bundleOptions;
m_Header = new Header();
m_Header.signature = reader.ReadStringToNull();
m_Header.version = reader.ReadUInt32();
m_Header.unityVersion = reader.ReadStringToNull();
m_Header.unityRevision = reader.ReadStringToNull();
m_Header.unityRevision = UnityVersion.TryParse(reader.ReadStringToNull(), out var ver) ? ver : new UnityVersion();
switch (m_Header.signature)
{
case "UnityArchive":
@@ -91,49 +100,52 @@ namespace AssetStudio
goto case "UnityFS";
}
ReadHeaderAndBlocksInfo(reader);
using (var blocksStream = CreateBlocksStream(reader.FullPath))
using (reader)
{
ReadBlocksAndDirectory(reader, blocksStream);
ReadFiles(blocksStream, reader.FullPath);
ReadFiles(ReadBlocksAndDirectory(reader));
}
break;
case "UnityFS":
ReadHeader(reader);
bool isUnityCnEnc = false;
string unityVer = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer;
int[] ver = new string(unityVer.SkipWhile(x => !char.IsDigit(x)).TakeWhile(x => char.IsDigit(x) || x == '.').ToArray()).Split('.').Select(x => int.Parse(x)).ToArray();
if (ver[0] != 0)
var bundleSize = m_Header.size;
var streamSize = reader.BaseStream.Length;
if (bundleSize > streamSize)
Logger.Warning("Bundle size is incorrect.");
IsDataAfterBundle = streamSize - bundleSize > 200;
var unityVer = m_Header.unityRevision;
var customUnityVer = _bundleOptions.Options.CustomUnityVersion;
if (customUnityVer != null)
{
// https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch
if (ver[0] < 2020 ||
(ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) ||
(ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) ||
(ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1))
if (!unityVer.IsStripped && customUnityVer != unityVer)
{
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0;
Logger.Warning($"Detected Unity version is different from the specified one ({customUnityVer.FullVersion.Color(ColorConsole.BrightCyan)}).\n" +
$"Assets may load with errors.\n" +
$"It is recommended to specify the detected Unity version: {unityVer.FullVersion.Color(ColorConsole.BrightCyan)}");
}
else
{
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0;
unityVer = customUnityVer;
}
}
if (isUnityCnEnc)
UnityCnCheck(reader, unityVer);
ReadBlocksInfoAndDirectory(reader, unityVer);
if (IsUncompressedBundle && !IsDataAfterBundle && !isMultiBundle)
{
throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
Logger.Debug($"[Uncompressed bundle] BlockData count: {m_BlocksInfo.Length}");
ReadFiles(reader.BaseStream, reader.Position);
break;
}
ReadBlocksInfoAndDirectory(reader, ver);
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, reader.FullPath);
}
ReadFiles(ReadBlocks(reader));
if (!IsDataAfterBundle)
reader.Close();
break;
}
}
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
private void ReadHeaderAndBlocksInfo(FileReader reader)
{
if (m_Header.version >= 4)
{
@@ -147,7 +159,7 @@ namespace AssetStudio
m_BlocksInfo = new StorageBlock[1];
for (int i = 0; i < levelCount; i++)
{
var storageBlock = new StorageBlock()
var storageBlock = new StorageBlock
{
compressedSize = reader.ReadUInt32(),
uncompressedSize = reader.ReadUInt32(),
@@ -170,23 +182,24 @@ namespace AssetStudio
private Stream CreateBlocksStream(string path)
{
Stream blocksStream;
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum >= int.MaxValue)
if (uncompressedSizeSum < int.MaxValue && !_bundleOptions.DecompressToDisk)
return new MemoryStream((int)uncompressedSizeSum);
if (!Directory.Exists(Path.GetDirectoryName(path)))
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
var tempDir = Path.Combine(Directory.GetCurrentDirectory(), "Studio_temp");
Directory.CreateDirectory(tempDir);
var filename = Path.GetFileName(path);
var hash = path.GetHashCode();
path = Path.Combine(tempDir, $"{filename}_{hash:X}");
}
else
{
blocksStream = new MemoryStream((int)uncompressedSizeSum);
}
return blocksStream;
return new TempFileStream(path + ".temp", FileMode.Create);
}
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
private Stream ReadBlocksAndDirectory(FileReader reader)
{
var blocksStream = CreateBlocksStream(reader.FullPath);
var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo)
{
@@ -195,7 +208,7 @@ namespace AssetStudio
{
using (var memoryStream = new MemoryStream(uncompressedBytes))
{
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
using (var decompressStream = BundleDecompressionHelper.DecompressLzmaStream(memoryStream))
{
uncompressedBytes = decompressStream.ToArray();
}
@@ -204,10 +217,11 @@ namespace AssetStudio
blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
}
blocksStream.Position = 0;
var blocksReader = new EndianBinaryReader(blocksStream);
var nodesCount = blocksReader.ReadInt32();
m_DirectoryInfo = new Node[nodesCount];
for (int i = 0; i < nodesCount; i++)
for (var i = 0; i < nodesCount; i++)
{
m_DirectoryInfo[i] = new Node
{
@@ -216,37 +230,31 @@ namespace AssetStudio
size = blocksReader.ReadUInt32()
};
}
return blocksStream;
}
public void ReadFiles(Stream blocksStream, string path)
private void ReadFiles(Stream inputStream, long blocksOffset = 0)
{
fileList = new StreamFile[m_DirectoryInfo.Length];
for (int i = 0; i < m_DirectoryInfo.Length; i++)
fileList = new List<StreamFile>(m_DirectoryInfo.Length);
foreach (var node in m_DirectoryInfo)
{
var node = m_DirectoryInfo[i];
var file = new StreamFile();
fileList[i] = file;
fileList.Add(file);
file.path = node.path;
file.fileName = Path.GetFileName(node.path);
if (node.size >= int.MaxValue)
try
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size);
file.stream = memoryMappedFile.CreateViewStream();*/
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
Directory.CreateDirectory(extractPath);
file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
file.stream = new OffsetStream(inputStream, node.offset + blocksOffset, node.size);
}
else
catch (IOException e)
{
file.stream = new MemoryStream((int)node.size);
Logger.Warning($"Failed to access {file.fileName} file.\n{e}");
}
blocksStream.Position = node.offset;
blocksStream.CopyTo(file.stream, node.size);
file.stream.Position = 0;
}
}
private void ReadHeader(EndianBinaryReader reader)
private void ReadHeader(FileReader reader)
{
m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
@@ -258,7 +266,7 @@ namespace AssetStudio
}
}
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader, int[] unityVer)
private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer, bool silent = false)
{
byte[] blocksInfoBytes;
@@ -266,7 +274,7 @@ namespace AssetStudio
{
reader.AlignStream(16);
}
else if (unityVer[0] >= 2019 && unityVer[1] >= 4)
else if (unityVer >= (2019, 4) && m_Header.flags != ArchiveFlags.BlocksAndDirectoryInfoCombined)
{
//check if we need to align the reader
//- align to 16 bytes and check if all are 0
@@ -279,58 +287,96 @@ namespace AssetStudio
}
}
var compressedSize = (int)m_Header.compressedBlocksInfoSize;
var uncompressedSize = (int)m_Header.uncompressedBlocksInfoSize;
if (uncompressedSize < 0 || compressedSize < 0 || compressedSize > reader.BaseStream.Length)
{
throw new IOException("Incorrect blockInfo length.\nBlockInfo sizes might be encrypted.\n");
}
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
{
var position = reader.Position;
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
reader.Position = m_Header.size - compressedSize;
blocksInfoBytes = reader.ReadBytes(compressedSize);
reader.Position = position;
}
else //0x40 BlocksAndDirectoryInfoCombined
{
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
blocksInfoBytes = reader.ReadBytes(compressedSize);
}
MemoryStream blocksInfoUncompresseddStream;
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
var customBlockInfoCompression = _bundleOptions.CustomBlockInfoCompression;
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
if (customBlockInfoCompression == CompressionType.Auto)
{
if (!silent && compressionType > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), compressionType))
{
Logger.Warning($"Non-standard blockInfo compression type: {(int)compressionType}. Trying to decompress as {compressionType} archive..");
}
}
else if (compressionType != CompressionType.None)
{
compressionType = customBlockInfoCompression;
if (!silent)
{
Logger.Info($"Custom blockInfo compression type: {customBlockInfoCompression}");
}
}
Logger.Debug($"BlockInfo compression: {compressionType}");
int numWrite;
var errorMsg = string.Empty;
MemoryStream blocksInfoUncompressedStream;
switch (compressionType)
{
case CompressionType.None:
{
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes);
numWrite = compressedSize;
break;
}
case CompressionType.Lzma:
{
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
blocksInfoUncompressedStream = new MemoryStream(uncompressedSize);
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
numWrite = (int)BundleDecompressionHelper.DecompressLzmaStream(blocksInfoCompressedStream, blocksInfoUncompressedStream, compressedSize, uncompressedSize, ref errorMsg);
}
blocksInfoUncompresseddStream.Position = 0;
blocksInfoUncompressedStream.Position = 0;
break;
}
case CompressionType.Lz4:
case CompressionType.Lz4HC:
case CompressionType.Zstd:
case CompressionType.Oodle:
{
var uncompressedBytes = new byte[uncompressedSize];
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
if (numWrite != uncompressedSize)
{
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, blocksInfoBytes, uncompressedBytes, ref errorMsg);
blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes);
break;
}
case CompressionType.Lzham:
throw new IOException($"Unsupported blockInfo compression type: {compressionType}.\n");
default:
throw new IOException($"Unsupported compression type {compressionType}");
throw new IOException($"Unknown blockInfo compression type: {compressionType}.\nYou may try to specify the compression type manually.\n");
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
if (numWrite != uncompressedSize)
{
var msg = $"{compressionType} blockInfo decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {uncompressedSize} bytes.";
var exMsg = compressionType > CompressionType.Lz4HC || customBlockInfoCompression != CompressionType.Auto
? "Wrong compression type or blockInfo data might be encrypted."
: "BlockInfo data might be encrypted.";
throw new IOException($"{msg}\n{exMsg}\n");
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream))
{
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
var blocksInfoCount = blocksInfoReader.ReadInt32();
m_BlocksInfo = new StorageBlock[blocksInfoCount];
for (int i = 0; i < blocksInfoCount; i++)
for (var i = 0; i < blocksInfoCount; i++)
{
m_BlocksInfo[i] = new StorageBlock
{
@@ -342,7 +388,7 @@ namespace AssetStudio
var nodesCount = blocksInfoReader.ReadInt32();
m_DirectoryInfo = new Node[nodesCount];
for (int i = 0; i < nodesCount; i++)
for (var i = 0; i < nodesCount; i++)
{
m_DirectoryInfo[i] = new Node
{
@@ -359,46 +405,149 @@ namespace AssetStudio
}
}
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
private Stream ReadBlocks(FileReader reader)
{
foreach (var blockInfo in m_BlocksInfo)
var customBlockCompression = _bundleOptions.CustomBlockCompression;
var blocksStream = CreateBlocksStream(reader.FullPath);
var blocksCompression = m_BlocksInfo.Max(x => (CompressionType)(x.flags & StorageBlockFlags.CompressionTypeMask));
var blockSize = (int)m_BlocksInfo.Max(x => x.uncompressedSize);
Logger.Debug($"BlockData compression: {blocksCompression}\n" +
$"BlockData count: {m_BlocksInfo.Length}\n" +
$"BlockSize: {blockSize}");
if (customBlockCompression == CompressionType.Auto)
{
if (blocksCompression > CompressionType.Lzham && Enum.IsDefined(typeof(CompressionType), blocksCompression))
{
Logger.Warning($"Non-standard block compression type: {(int)blocksCompression}. Trying to decompress as {blocksCompression} archive..");
}
}
else
{
Logger.Info($"Custom block compression type: {customBlockCompression}");
blocksCompression = customBlockCompression;
}
byte[] sharedCompressedBuff = null;
byte[] sharedUncompressedBuff = null;
if (blocksCompression > CompressionType.Lzma && blocksCompression != CompressionType.Lzham)
{
sharedCompressedBuff = BigArrayPool<byte>.Shared.Rent(blockSize);
sharedUncompressedBuff = BigArrayPool<byte>.Shared.Rent(blockSize);
}
try
{
for (var i = 0; i < m_BlocksInfo.Length; i++)
{
var blockInfo = m_BlocksInfo[i];
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
if (customBlockCompression != CompressionType.Auto && compressionType > 0)
{
compressionType = customBlockCompression;
}
var debugMsg = $"[{i:D2}] Compression: {compressionType} | UncompressedSize: {blockInfo.uncompressedSize} | CompressedSize: {blockInfo.compressedSize} ";
long numWrite;
var errorMsg = string.Empty;
switch (compressionType)
{
case CompressionType.None:
{
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
numWrite = blockInfo.compressedSize;
break;
}
case CompressionType.Lzma:
{
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
numWrite = BundleDecompressionHelper.DecompressLzmaStream(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize, ref errorMsg);
break;
}
case CompressionType.Lz4:
case CompressionType.Lz4HC:
{
case CompressionType.Zstd:
case CompressionType.Oodle:
var compressedSize = (int)blockInfo.compressedSize;
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
reader.Read(compressedBytes, 0, compressedSize);
var uncompressedSize = (int)blockInfo.uncompressedSize;
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
if (numWrite != uncompressedSize)
sharedCompressedBuff.AsSpan().Clear();
sharedUncompressedBuff.AsSpan().Clear();
var read = reader.Read(sharedCompressedBuff, 0, compressedSize);
debugMsg += $"(read: {read.ToString().ColorIf(read != compressedSize, ColorConsole.BrightRed)})";
var compressedSpan = new ReadOnlySpan<byte>(sharedCompressedBuff, 0, compressedSize);
var uncompressedSpan = new Span<byte>(sharedUncompressedBuff, 0, uncompressedSize);
numWrite = BundleDecompressionHelper.DecompressBlock(compressionType, compressedSpan, uncompressedSpan, ref errorMsg);
if (numWrite == uncompressedSize)
{
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
blocksStream.Write(sharedUncompressedBuff, 0, uncompressedSize);
}
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
BigArrayPool<byte>.Shared.Return(compressedBytes);
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
break;
}
case CompressionType.Lzham:
throw new IOException($"Unsupported block compression type: {compressionType}.\n");
default:
throw new IOException($"Unsupported compression type {compressionType}");
throw new IOException($"Unknown block compression type: {compressionType}.\nYou may try to specify the compression type manually.\n");
}
Logger.Debug(debugMsg);
if (numWrite != blockInfo.uncompressedSize)
{
var msg = $"{compressionType} block decompression error. {errorMsg}\nWrite {numWrite} bytes but expected {blockInfo.uncompressedSize} bytes.";
var exMsg = compressionType > CompressionType.Lz4HC || customBlockCompression != CompressionType.Auto
? "Wrong compression type or block data might be encrypted."
: "Block data might be encrypted.";
throw new IOException($"{msg}\n{exMsg}\n");
}
}
blocksStream.Position = 0;
}
finally
{
if (sharedCompressedBuff != null)
BigArrayPool<byte>.Shared.Return(sharedCompressedBuff, clearArray: true);
if (sharedUncompressedBuff != null)
BigArrayPool<byte>.Shared.Return(sharedUncompressedBuff, clearArray: true);
}
return blocksStream;
}
private void UnityCnCheck(FileReader reader, UnityVersion unityVer)
{
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
return;
var hasUnityCnFlag = false;
if (!unityVer.IsStripped)
{
// https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch
if (unityVer < 2020
|| unityVer.IsInRange(2020, (2020, 3, 34))
|| unityVer.IsInRange(2021, (2021, 3, 2))
|| unityVer.IsInRange(2022, (2022, 1, 1)))
{
hasUnityCnFlag = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.V1) != 0;
}
else
{
hasUnityCnFlag = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.V2_V3) != 0;
}
}
if (!hasUnityCnFlag)
return;
var pos = reader.Position;
reader.Position += 70;
try
{
ReadBlocksInfoAndDirectory(reader, unityVer, silent: true);
}
catch (Exception)
{
reader.Position = pos;
return;
}
throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
}
private bool IsUncompressedBundle => m_BlocksInfo.All(x => (CompressionType)(x.flags & StorageBlockFlags.CompressionTypeMask) == CompressionType.None);
}
}

View File

@@ -145,6 +145,7 @@ namespace AssetStudio
ProceduralMaterial = 185,
ProceduralTexture = 186,
Texture2DArray = 187,
Texture2DArrayImage = -187, //fake type
CubemapArray = 188,
OffMeshLink = 191,
OcclusionArea = 192,
@@ -296,6 +297,7 @@ namespace AssetStudio
//void = 100011,
TilemapCollider2D = 19719996,
AssetImporterLog = 41386430,
GraphicsStateCollection = 55640938,
VFXRenderer = 73398921,
SerializableManagedRefTestClass = 76251197,
Grid = 156049354,
@@ -308,9 +310,13 @@ namespace AssetStudio
AssemblyDefinitionReferenceImporter = 294290339,
SiblingDerived = 334799969,
TestObjectWithSerializedMapStringNonAlignedStruct = 342846651,
AudioResource = 355983997,
SubDerived = 367388927,
AssetImportInProgressProxy = 369655926,
PluginBuildInfo = 382020655,
MemorySettings = 387306366,
BuildMetaDataImporter = 403037116,
BuildInstructionImporter = 403037117,
EditorProjectAccess = 426301858,
PrefabImporter = 468431735,
TestObjectWithSerializedArray = 478637458,
@@ -322,16 +328,22 @@ namespace AssetStudio
AudioBuildInfo = 641289076,
CachedSpriteAtlasRuntimeData = 644342135,
RendererFake = 646504946,
MultiplayerManager = 655991488,
AssemblyDefinitionReferenceAsset = 662584278,
BuiltAssetBundleInfoSet = 668709126,
SpriteAtlas = 687078895,
RayTracingShaderImporter = 747330370,
BuildArchiveImporter = 780535461,
PreviewImporter = 815301076,
RayTracingShader = 825902497,
LightingSettings = 850595691,
PlatformModuleSetup = 877146078,
VersionControlSettings = 890905787,
CustomCollider2D = 893571522,
AimConstraint = 895512359,
VFXManager = 937362698,
RoslynAnalyzerConfigAsset = 947337230,
RuleSetFileAsset = 954905827,
VisualEffectSubgraph = 994735392,
VisualEffectSubgraphOperator = 994735403,
VisualEffectSubgraphBlock = 994735404,
@@ -344,25 +356,40 @@ namespace AssetStudio
LookAtConstraint = 1183024399,
SpriteAtlasImporter = 1210832254,
MultiArtifactTestImporter = 1223240404,
AudioContainerElement = 1233149941,
GameObjectRecorder = 1268269756,
AudioRandomContainer = 1307931743,
LightingDataAssetParent = 1325145578,
PresetManager = 1386491679,
TestObjectWithSpecialLayoutTwo = 1392443030,
StreamingManager = 1403656975,
LowerResBlitTexture = 1480428607,
VideoBuildInfo = 1521398425,
C4DImporter = 1541671625,
StreamingController = 1542919678,
RenderPassAttachment = 1571458007,
TestObjectVectorPairStringBool = 1628831178,
ShaderContainer = 1557264870,
RoslynAdditionalFileAsset = 1597193336,
RoslynAdditionalFileImporter = 1642787288,
MultiplayerRolesData = 1652712579,
SceneRoots = 1660057539,
BrokenPrefabAsset = 1731078267,
AndroidAssetPackImporter = 1736697216,
VulkanDeviceFilterLists = 1740304944,
GridLayout = 1742807556,
AssemblyDefinitionImporter = 1766753193,
ParentConstraint = 1773428102,
FakeComponent = 1803986026,
RuleSetFileImporter = 1777034230,
PositionConstraint = 1818360608,
RotationConstraint = 1818360609,
ScaleConstraint = 1818360610,
Tilemap = 1839735485,
PackageManifest = 1896753125,
PackageManifestImporter = 1896753126,
RoslynAnalyzerConfigImporter = 1903396204,
UIRenderer = 1931382933,
TerrainLayer = 1953259897,
SpriteShapeRenderer = 1971053207,
NativeObjectType = 1977754360,
@@ -374,6 +401,7 @@ namespace AssetStudio
VisualEffectObject = 2059678085,
VisualEffect = 2083052967,
LocalizationAsset = 2083778819,
ScriptedImporter = 2089858483
ScriptedImporter = 2089858483,
ShaderIncludeImporter = 2103361453,
}
}

View File

@@ -1,22 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class Animation : Behaviour
{
public PPtr<AnimationClip>[] m_Animations;
public List<PPtr<AnimationClip>> m_Animations;
public Animation(ObjectReader reader) : base(reader)
{
var m_Animation = new PPtr<AnimationClip>(reader);
int numAnimations = reader.ReadInt32();
m_Animations = new PPtr<AnimationClip>[numAnimations];
for (int i = 0; i < numAnimations; i++)
m_Animations = new List<PPtr<AnimationClip>>();
for (var i = 0; i < numAnimations; i++)
{
m_Animations[i] = new PPtr<AnimationClip>(reader);
m_Animations.Add(new PPtr<AnimationClip>(reader));
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class Animator : Behaviour
{
@@ -17,47 +12,57 @@ namespace AssetStudio
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
var m_CullingMode = reader.ReadInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
if (version >= (4, 5)) //4.5 and up
{
var m_UpdateMode = reader.ReadInt32();
}
if (version.IsTuanjie && (version > (2022, 3, 48) || version == (2022, 3, 48) && version.Build >= 7)) //2022.3.48t7(1.4.4) and up
{
var m_UpdateFrequencyMode = reader.ReadInt32();
var m_UpdateFrequency = reader.ReadSingle();
}
var m_ApplyRootMotion = reader.ReadBoolean();
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
if (version == 4 && version.Minor >= 5) //4.5 and up - 5.0 down
{
reader.AlignStream();
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
var m_LinearVelocityBlending = reader.ReadBoolean();
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
if (version >= (2021, 2)) //2021.2 and up
{
var m_StabilizeFeet = reader.ReadBoolean();
}
if (version >= (2023, 1)) //2023.1 and up
{
var m_AnimatePhysics = reader.ReadBoolean();
}
reader.AlignStream();
}
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
if (version < (4, 5)) //4.5 down
{
var m_AnimatePhysics = reader.ReadBoolean();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_HasTransformHierarchy = reader.ReadBoolean();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
if (version >= (4, 5)) //4.5 and up
{
var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();
}
if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down
if (version.IsInRange(5, 2018)) //5.0 and up - 2018 down
{
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
if (version >= 2018) //2018 and up
{
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
reader.AlignStream();

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
@@ -17,7 +14,7 @@ namespace AssetStudio
word0 = reader.ReadUInt32();
word1 = reader.ReadUInt32();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
if (version >= (5, 2)) //5.2 and up
{
word2 = reader.ReadUInt32();
}
@@ -38,15 +35,15 @@ namespace AssetStudio
public class SkeletonMask
{
public SkeletonMaskElement[] m_Data;
public List<SkeletonMaskElement> m_Data;
public SkeletonMask(ObjectReader reader)
{
int numElements = reader.ReadInt32();
m_Data = new SkeletonMaskElement[numElements];
for (int i = 0; i < numElements; i++)
m_Data = new List<SkeletonMaskElement>();
for (var i = 0; i < numElements; i++)
{
m_Data[i] = new SkeletonMaskElement(reader);
m_Data.Add(new SkeletonMaskElement(reader));
}
}
}
@@ -73,12 +70,12 @@ namespace AssetStudio
m_SkeletonMask = new SkeletonMask(reader);
m_Binding = reader.ReadUInt32();
m_LayerBlendingMode = reader.ReadInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
if (version >= (4, 2)) //4.2 and up
{
m_DefaultWeight = reader.ReadSingle();
}
m_IKPass = reader.ReadBoolean();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
if (version >= (4, 2)) //4.2 and up
{
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
}
@@ -124,14 +121,15 @@ namespace AssetStudio
var version = reader.version;
int numConditions = reader.ReadInt32();
m_ConditionConstantArray = new ConditionConstant[numConditions];
for (int i = 0; i < numConditions; i++)
var conditionConstantList = new List<ConditionConstant>();
for (var i = 0; i < numConditions; i++)
{
m_ConditionConstantArray[i] = new ConditionConstant(reader);
conditionConstantList.Add(new ConditionConstant(reader));
}
m_ConditionConstantArray = conditionConstantList.ToArray();
m_DestinationState = reader.ReadUInt32();
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_FullPathID = reader.ReadUInt32();
}
@@ -140,7 +138,7 @@ namespace AssetStudio
m_UserID = reader.ReadUInt32();
m_TransitionDuration = reader.ReadSingle();
m_TransitionOffset = reader.ReadSingle();
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_ExitTime = reader.ReadSingle();
m_HasExitTime = reader.ReadBoolean();
@@ -154,7 +152,7 @@ namespace AssetStudio
m_Atomic = reader.ReadBoolean();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
if (version >= (4, 5)) //4.5 and up
{
m_CanTransitionToSelf = reader.ReadBoolean();
}
@@ -201,11 +199,12 @@ namespace AssetStudio
m_ChildPairAvgMagInvArray = reader.ReadSingleArray();
int numNeighbours = reader.ReadInt32();
m_ChildNeighborListArray = new MotionNeighborList[numNeighbours];
for (int i = 0; i < numNeighbours; i++)
var childNeighborLists = new List<MotionNeighborList>();
for (var i = 0; i < numNeighbours; i++)
{
m_ChildNeighborListArray[i] = new MotionNeighborList(reader);
childNeighborLists.Add(new MotionNeighborList(reader));
}
m_ChildNeighborListArray = childNeighborLists.ToArray();
}
}
@@ -252,43 +251,41 @@ namespace AssetStudio
{
var version = reader.version;
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
if (version >= (4, 1)) //4.1 and up
{
m_BlendType = reader.ReadUInt32();
}
m_BlendEventID = reader.ReadUInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
if (version >= (4, 1)) //4.1 and up
{
m_BlendEventYID = reader.ReadUInt32();
}
m_ChildIndices = reader.ReadUInt32Array();
if (version[0] < 4 || (version[0] == 4 && version[1] < 1)) //4.1 down
if (version < (4, 1)) //4.1 down
{
m_ChildThresholdArray = reader.ReadSingleArray();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
if (version >= (4, 1)) //4.1 and up
{
m_Blend1dData = new Blend1dDataConstant(reader);
m_Blend2dData = new Blend2dDataConstant(reader);
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_BlendDirectData = new BlendDirectDataConstant(reader);
}
m_ClipID = reader.ReadUInt32();
if (version[0] == 4 && version[1] >= 5) //4.5 - 5.0
if (version == 4 && version.Minor >= 5) //4.5 - 5.0
{
m_ClipIndex = reader.ReadUInt32();
}
m_Duration = reader.ReadSingle();
if (version[0] > 4
|| (version[0] == 4 && version[1] > 1)
|| (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up
if (version >= (4, 1, 3)) //4.1.3 and up
{
m_CycleOffset = reader.ReadSingle();
m_Mirror = reader.ReadBoolean();
@@ -307,13 +304,14 @@ namespace AssetStudio
var version = reader.version;
int numNodes = reader.ReadInt32();
m_NodeArray = new BlendTreeNodeConstant[numNodes];
for (int i = 0; i < numNodes; i++)
var nodeList = new List<BlendTreeNodeConstant>();
for (var i = 0; i < numNodes; i++)
{
m_NodeArray[i] = new BlendTreeNodeConstant(reader);
nodeList.Add(new BlendTreeNodeConstant(reader));
}
m_NodeArray = nodeList.ToArray();
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
if (version < (4, 5)) //4.5 down
{
m_BlendEventArrayConstant = new ValueArrayConstant(reader);
}
@@ -345,68 +343,71 @@ namespace AssetStudio
{
var version = reader.version;
int numTransistions = reader.ReadInt32();
m_TransitionConstantArray = new TransitionConstant[numTransistions];
for (int i = 0; i < numTransistions; i++)
int numTransitions = reader.ReadInt32();
var transitionConstantList = new List<TransitionConstant>();
for (var i = 0; i < numTransitions; i++)
{
m_TransitionConstantArray[i] = new TransitionConstant(reader);
transitionConstantList.Add(new TransitionConstant(reader));
}
m_TransitionConstantArray = transitionConstantList.ToArray();
m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
if (version < (5, 2)) //5.2 down
{
int numInfos = reader.ReadInt32();
m_LeafInfoArray = new LeafInfoConstant[numInfos];
for (int i = 0; i < numInfos; i++)
var leafInfoList = new List<LeafInfoConstant>();
for (var i = 0; i < numInfos; i++)
{
m_LeafInfoArray[i] = new LeafInfoConstant(reader);
leafInfoList.Add(new LeafInfoConstant(reader));
}
m_LeafInfoArray = leafInfoList.ToArray();
}
int numBlends = reader.ReadInt32();
m_BlendTreeConstantArray = new BlendTreeConstant[numBlends];
for (int i = 0; i < numBlends; i++)
var blendTreeConstantList = new List<BlendTreeConstant>();
for (var i = 0; i < numBlends; i++)
{
m_BlendTreeConstantArray[i] = new BlendTreeConstant(reader);
blendTreeConstantList.Add(new BlendTreeConstant(reader));
}
m_BlendTreeConstantArray = blendTreeConstantList.ToArray();
m_NameID = reader.ReadUInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_PathID = reader.ReadUInt32();
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_FullPathID = reader.ReadUInt32();
}
m_TagID = reader.ReadUInt32();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
if (version >= (5, 1)) //5.1 and up
{
m_SpeedParamID = reader.ReadUInt32();
m_MirrorParamID = reader.ReadUInt32();
m_CycleOffsetParamID = reader.ReadUInt32();
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
if (version >= (2017, 2)) //2017.2 and up
{
var m_TimeParamID = reader.ReadUInt32();
}
m_Speed = reader.ReadSingle();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
if (version >= (4, 1)) //4.1 and up
{
m_CycleOffset = reader.ReadSingle();
}
m_IKOnFeet = reader.ReadBoolean();
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_WriteDefaultValues = reader.ReadBoolean();
}
m_Loop = reader.ReadBoolean();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
if (version >= (4, 1)) //4.1 and up
{
m_Mirror = reader.ReadBoolean();
}
@@ -425,11 +426,12 @@ namespace AssetStudio
m_Destination = reader.ReadUInt32();
int numConditions = reader.ReadInt32();
m_ConditionConstantArray = new ConditionConstant[numConditions];
for (int i = 0; i < numConditions; i++)
var conditionConstantList = new List<ConditionConstant>();
for (var i = 0; i < numConditions; i++)
{
m_ConditionConstantArray[i] = new ConditionConstant(reader);
conditionConstantList.Add(new ConditionConstant(reader));
}
m_ConditionConstantArray = conditionConstantList.ToArray();
}
}
@@ -442,11 +444,12 @@ namespace AssetStudio
public SelectorStateConstant(ObjectReader reader)
{
int numTransitions = reader.ReadInt32();
m_TransitionConstantArray = new SelectorTransitionConstant[numTransitions];
for (int i = 0; i < numTransitions; i++)
var transitionConstantList = new List<SelectorTransitionConstant>();
for (var i = 0; i < numTransitions; i++)
{
m_TransitionConstantArray[i] = new SelectorTransitionConstant(reader);
transitionConstantList.Add(new SelectorTransitionConstant(reader));
}
m_TransitionConstantArray = transitionConstantList.ToArray();
m_FullPathID = reader.ReadUInt32();
m_isEntry = reader.ReadBoolean();
@@ -467,27 +470,30 @@ namespace AssetStudio
var version = reader.version;
int numStates = reader.ReadInt32();
m_StateConstantArray = new StateConstant[numStates];
for (int i = 0; i < numStates; i++)
var stateConstantList = new List<StateConstant>();
for (var i = 0; i < numStates; i++)
{
m_StateConstantArray[i] = new StateConstant(reader);
stateConstantList.Add(new StateConstant(reader));
}
m_StateConstantArray = stateConstantList.ToArray();
int numAnyStates = reader.ReadInt32();
m_AnyStateTransitionConstantArray = new TransitionConstant[numAnyStates];
for (int i = 0; i < numAnyStates; i++)
var anyStateTransitionConstantList = new List<TransitionConstant>();
for (var i = 0; i < numAnyStates; i++)
{
m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader);
anyStateTransitionConstantList.Add(new TransitionConstant(reader));
}
m_AnyStateTransitionConstantArray = anyStateTransitionConstantList.ToArray();
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
int numSelectors = reader.ReadInt32();
m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors];
for (int i = 0; i < numSelectors; i++)
var selectorStateConstantList = new List<SelectorStateConstant>();
for (var i = 0; i < numSelectors; i++)
{
m_SelectorStateConstantArray[i] = new SelectorStateConstant(reader);
selectorStateConstantList.Add(new SelectorStateConstant(reader));
}
m_SelectorStateConstantArray = selectorStateConstantList.ToArray();
}
m_DefaultState = reader.ReadUInt32();
@@ -504,12 +510,13 @@ namespace AssetStudio
public Vector3[] m_PositionValues;
public Vector4[] m_QuaternionValues;
public Vector3[] m_ScaleValues;
public int[] m_EntityIdValues;
public ValueArray(ObjectReader reader)
{
var version = reader.version;
if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
if (version < (5, 5)) //5.5 down
{
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
@@ -517,34 +524,44 @@ namespace AssetStudio
m_FloatValues = reader.ReadSingleArray();
}
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
if (version < (4, 3)) //4.3 down
{
m_VectorValues = reader.ReadVector4Array();
}
else
{
int numPosValues = reader.ReadInt32();
m_PositionValues = new Vector3[numPosValues];
for (int i = 0; i < numPosValues; i++)
var positionValuesList = new List<Vector3>();
for (var i = 0; i < numPosValues; i++)
{
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
positionValuesList.Add(version >= (5, 4) //5.4 and up
? reader.ReadVector3()
: (Vector3)reader.ReadVector4());
}
m_PositionValues = positionValuesList.ToArray();
m_QuaternionValues = reader.ReadVector4Array();
int numScaleValues = reader.ReadInt32();
m_ScaleValues = new Vector3[numScaleValues];
for (int i = 0; i < numScaleValues; i++)
var scaleValuesList = new List<Vector3>();
for (var i = 0; i < numScaleValues; i++)
{
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
scaleValuesList.Add(version >= (5, 4) //5.4 and up
? reader.ReadVector3()
: (Vector3)reader.ReadVector4());
}
m_ScaleValues = scaleValuesList.ToArray();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
if (version >= (5, 5)) //5.5 and up
{
m_FloatValues = reader.ReadSingleArray();
m_IntValues = reader.ReadInt32Array();
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
if (version >= (6000, 2)) //6000.2 and up
{
m_EntityIdValues = reader.ReadInt32Array();
}
}
}
}
@@ -560,18 +577,20 @@ namespace AssetStudio
public ControllerConstant(ObjectReader reader)
{
int numLayers = reader.ReadInt32();
m_LayerArray = new LayerConstant[numLayers];
for (int i = 0; i < numLayers; i++)
var layerList = new List<LayerConstant>();
for (var i = 0; i < numLayers; i++)
{
m_LayerArray[i] = new LayerConstant(reader);
layerList.Add(new LayerConstant(reader));
}
m_LayerArray = layerList.ToArray();
int numStates = reader.ReadInt32();
m_StateMachineArray = new StateMachineConstant[numStates];
for (int i = 0; i < numStates; i++)
var stateMachineList = new List<StateMachineConstant>();
for (var i = 0; i < numStates; i++)
{
m_StateMachineArray[i] = new StateMachineConstant(reader);
stateMachineList.Add(new StateMachineConstant(reader));
}
m_StateMachineArray = stateMachineList.ToArray();
m_Values = new ValueArrayConstant(reader);
m_DefaultValues = new ValueArray(reader);
@@ -580,7 +599,8 @@ namespace AssetStudio
public sealed class AnimatorController : RuntimeAnimatorController
{
public PPtr<AnimationClip>[] m_AnimationClips;
public List<PPtr<AnimationClip>> m_AnimationClips;
public List<KeyValuePair<uint, string>> m_TOS;
public AnimatorController(ObjectReader reader) : base(reader)
{
@@ -588,17 +608,17 @@ namespace AssetStudio
var m_Controller = new ControllerConstant(reader);
int tosSize = reader.ReadInt32();
var m_TOS = new KeyValuePair<uint, string>[tosSize];
for (int i = 0; i < tosSize; i++)
m_TOS = new List<KeyValuePair<uint, string>>();
for (var i = 0; i < tosSize; i++)
{
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
}
int numClips = reader.ReadInt32();
m_AnimationClips = new PPtr<AnimationClip>[numClips];
for (int i = 0; i < numClips; i++)
m_AnimationClips = new List<PPtr<AnimationClip>>();
for (var i = 0; i < numClips; i++)
{
m_AnimationClips[i] = new PPtr<AnimationClip>(reader);
m_AnimationClips.Add(new PPtr<AnimationClip>(reader));
}
}
}

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
@@ -20,17 +17,17 @@ namespace AssetStudio
public sealed class AnimatorOverrideController : RuntimeAnimatorController
{
public PPtr<RuntimeAnimatorController> m_Controller;
public AnimationClipOverride[] m_Clips;
public List<AnimationClipOverride> m_Clips;
public AnimatorOverrideController(ObjectReader reader) : base(reader)
{
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
int numOverrides = reader.ReadInt32();
m_Clips = new AnimationClipOverride[numOverrides];
for (int i = 0; i < numOverrides; i++)
m_Clips = new List<AnimationClipOverride>();
for (var i = 0; i < numOverrides; i++)
{
m_Clips[i] = new AnimationClipOverride(reader);
m_Clips.Add(new AnimationClipOverride(reader));
}
}
}

View File

@@ -18,8 +18,8 @@ namespace AssetStudio
public sealed class AssetBundle : NamedObject
{
public PPtr<Object>[] m_PreloadTable;
public KeyValuePair<string, AssetInfo>[] m_Container;
public List<PPtr<Object>> m_PreloadTable;
public List<KeyValuePair<string, AssetInfo>> m_Container;
public string m_AssetBundleName;
public string[] m_Dependencies;
public bool m_IsStreamedSceneAssetBundle;
@@ -27,37 +27,41 @@ namespace AssetStudio
public AssetBundle(ObjectReader reader) : base(reader)
{
var m_PreloadTableSize = reader.ReadInt32();
m_PreloadTable = new PPtr<Object>[m_PreloadTableSize];
m_PreloadTable = new List<PPtr<Object>>();
for (var i = 0; i < m_PreloadTableSize; i++)
{
m_PreloadTable[i] = new PPtr<Object>(reader);
m_PreloadTable.Add(new PPtr<Object>(reader));
}
var m_ContainerSize = reader.ReadInt32();
m_Container = new KeyValuePair<string, AssetInfo>[m_ContainerSize];
m_Container = new List<KeyValuePair<string, AssetInfo>>();
for (var i = 0; i < m_ContainerSize; i++)
{
m_Container[i] = new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader));
m_Container.Add(new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader)));
}
var m_MainAsset = new AssetInfo(reader);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
if (version == (5, 4)) //5.4.x
{
var m_ClassVersionMapSize = reader.ReadInt32();
for (var i = 0; i < m_ClassVersionMapSize; i++)
{
var first = reader.ReadInt32();
var second = reader.ReadInt32();
}
}
if (version >= (4, 2)) //4.2 and up
{
var m_RuntimeCompatibility = reader.ReadUInt32();
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
m_AssetBundleName = reader.ReadAlignedString();
var m_DependenciesSize = reader.ReadInt32();
m_Dependencies = new string[m_DependenciesSize];
for (var i = 0; i < m_DependenciesSize; i++)
{
m_Dependencies[i] = reader.ReadAlignedString();
}
m_Dependencies = reader.ReadStringArray();
m_IsStreamedSceneAssetBundle = reader.ReadBoolean();
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class AudioClip : NamedObject
{
@@ -33,15 +27,23 @@ namespace AssetStudio
public AudioClip(ObjectReader reader) : base(reader)
{
if (version[0] < 5)
if (version < 5)
{
m_Format = reader.ReadInt32();
if (version >= (2, 6)) //2.6 to 5
{
m_Type = (FMODSoundType)reader.ReadInt32();
m_3D = reader.ReadBoolean();
m_UseHardware = reader.ReadBoolean();
reader.AlignStream();
if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5
}
else
{
m_Length = reader.ReadSingle();
m_Frequency = reader.ReadInt32();
m_Channels = m_Format != 0x05 ? m_Format >> 1 : 0;
}
if (version >= (3, 2)) //3.2.0 to 5
{
int m_Stream = reader.ReadInt32();
m_Size = reader.ReadInt32();
@@ -95,7 +97,7 @@ namespace AssetStudio
public enum FMODSoundType
{
UNKNOWN = 0,
ACC = 1,
AAC = 1,
AIFF = 2,
ASF = 3,
AT3 = 4,

View File

@@ -23,7 +23,7 @@ namespace AssetStudio
public Limit(ObjectReader reader)
{
var version = reader.version;
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up
if (version >= (5, 4))//5.4 and up
{
m_Min = reader.ReadVector3();
m_Max = reader.ReadVector3();
@@ -50,7 +50,7 @@ namespace AssetStudio
var version = reader.version;
m_PreQ = reader.ReadVector4();
m_PostQ = reader.ReadVector4();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
if (version >= (5, 4)) //5.4 and up
{
m_Sgn = reader.ReadVector3();
}
@@ -66,7 +66,7 @@ namespace AssetStudio
public class Skeleton
{
public Node[] m_Node;
public List<Node> m_Node;
public uint[] m_ID;
public Axes[] m_AxesArray;
@@ -74,34 +74,35 @@ namespace AssetStudio
public Skeleton(ObjectReader reader)
{
int numNodes = reader.ReadInt32();
m_Node = new Node[numNodes];
for (int i = 0; i < numNodes; i++)
m_Node = new List<Node>();
for (var i = 0; i < numNodes; i++)
{
m_Node[i] = new Node(reader);
m_Node.Add(new Node(reader));
}
m_ID = reader.ReadUInt32Array();
int numAxes = reader.ReadInt32();
m_AxesArray = new Axes[numAxes];
for (int i = 0; i < numAxes; i++)
var axesList = new List<Axes>();
for (var i = 0; i < numAxes; i++)
{
m_AxesArray[i] = new Axes(reader);
axesList.Add(new Axes(reader));
}
m_AxesArray = axesList.ToArray();
}
}
public class SkeletonPose
{
public xform[] m_X;
public List<xform> m_X;
public SkeletonPose(ObjectReader reader)
{
int numXforms = reader.ReadInt32();
m_X = new xform[numXforms];
for (int i = 0; i < numXforms; i++)
m_X = new List<xform>();
for (var i = 0; i < numXforms; i++)
{
m_X[i] = new xform(reader);
m_X.Add(new xform(reader));
}
}
}
@@ -163,7 +164,7 @@ namespace AssetStudio
public SkeletonPose m_SkeletonPose;
public Hand m_LeftHand;
public Hand m_RightHand;
public Handle[] m_Handles;
public List<Handle> m_Handles;
public Collider[] m_ColliderArray;
public int[] m_HumanBoneIndex;
public float[] m_HumanBoneMass;
@@ -189,28 +190,29 @@ namespace AssetStudio
m_LeftHand = new Hand(reader);
m_RightHand = new Hand(reader);
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
if (version < (2018, 2)) //2018.2 down
{
int numHandles = reader.ReadInt32();
m_Handles = new Handle[numHandles];
for (int i = 0; i < numHandles; i++)
m_Handles = new List<Handle>();
for (var i = 0; i < numHandles; i++)
{
m_Handles[i] = new Handle(reader);
m_Handles.Add(new Handle(reader));
}
int numColliders = reader.ReadInt32();
m_ColliderArray = new Collider[numColliders];
for (int i = 0; i < numColliders; i++)
var colliderList = new List<Collider>();
for (var i = 0; i < numColliders; i++)
{
m_ColliderArray[i] = new Collider(reader);
colliderList.Add(new Collider(reader));
}
m_ColliderArray = colliderList.ToArray();
}
m_HumanBoneIndex = reader.ReadInt32Array();
m_HumanBoneMass = reader.ReadSingleArray();
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
if (version < (2018, 2)) //2018.2 down
{
m_ColliderIndex = reader.ReadInt32Array();
}
@@ -225,7 +227,7 @@ namespace AssetStudio
m_FeetSpacing = reader.ReadSingle();
m_HasLeftHand = reader.ReadBoolean();
m_HasRightHand = reader.ReadBoolean();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
if (version >= (5, 2)) //5.2 and up
{
m_HasTDoF = reader.ReadBoolean();
}
@@ -254,7 +256,7 @@ namespace AssetStudio
m_AvatarSkeleton = new Skeleton(reader);
m_AvatarSkeletonPose = new SkeletonPose(reader);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_DefaultPose = new SkeletonPose(reader);
@@ -265,7 +267,7 @@ namespace AssetStudio
m_HumanSkeletonIndexArray = reader.ReadInt32Array();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
}
@@ -273,7 +275,7 @@ namespace AssetStudio
m_RootMotionBoneIndex = reader.ReadInt32();
m_RootMotionBoneX = new xform(reader);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_RootMotionSkeleton = new Skeleton(reader);
m_RootMotionSkeletonPose = new SkeletonPose(reader);
@@ -287,7 +289,7 @@ namespace AssetStudio
{
public uint m_AvatarSize;
public AvatarConstant m_Avatar;
public KeyValuePair<uint, string>[] m_TOS;
public List<KeyValuePair<uint, string>> m_TOS;
public Avatar(ObjectReader reader) : base(reader)
{
@@ -295,10 +297,10 @@ namespace AssetStudio
m_Avatar = new AvatarConstant(reader);
int numTOS = reader.ReadInt32();
m_TOS = new KeyValuePair<uint, string>[numTOS];
for (int i = 0; i < numTOS; i++)
m_TOS = new List<KeyValuePair<uint, string>>();
for (var i = 0; i < numTOS; i++)
{
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
}
//HumanDescription m_HumanDescription 2019 and up

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public abstract class Behaviour : Component
{
public byte m_Enabled;
public Behaviour() { }
protected Behaviour(ObjectReader reader) : base(reader)
{
m_Enabled = reader.ReadByte();

View File

@@ -1,24 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class BuildSettings : Object
{
public string m_Version;
public string[] levels;
public string[] scenes;
public BuildSettings(ObjectReader reader) : base(reader)
{
var levels = reader.ReadStringArray();
var hasRenderTexture = reader.ReadBoolean();
var hasPROVersion = reader.ReadBoolean();
var hasPublishingRights = reader.ReadBoolean();
var hasShadows = reader.ReadBoolean();
m_Version = reader.ReadAlignedString();
if (reader.version < (5, 1)) //5.1 down
{
levels = reader.ReadStringArray();
}
else
{
scenes = reader.ReadStringArray();
}
}
}
}

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public abstract class Component : EditorExtension
{
public PPtr<GameObject> m_GameObject;
public Component() { }
protected Component(ObjectReader reader) : base(reader)
{
m_GameObject = new PPtr<GameObject>(reader);

View File

@@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public abstract class EditorExtension : Object
{
protected EditorExtension() { }
protected EditorExtension(ObjectReader reader) : base(reader)
{
if (platform == BuildTarget.NoTarget)

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class Font : NamedObject
{
@@ -11,7 +6,7 @@ namespace AssetStudio
public Font(ObjectReader reader) : base(reader)
{
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
if (version >= (5, 5))//5.5 and up
{
var m_LineSpacing = reader.ReadSingle();
var m_DefaultMaterial = new PPtr<Material>(reader);
@@ -23,12 +18,12 @@ namespace AssetStudio
var m_CharacterPadding = reader.ReadInt32();
var m_ConvertCase = reader.ReadInt32();
int m_CharacterRects_size = reader.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++)
for (var i = 0; i < m_CharacterRects_size; i++)
{
reader.Position += 44;//CharacterInfo data 41
}
int m_KerningValues_size = reader.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++)
for (var i = 0; i < m_KerningValues_size; i++)
{
reader.Position += 8;
}
@@ -43,7 +38,7 @@ namespace AssetStudio
{
int m_AsciiStartOffset = reader.ReadInt32();
if (version[0] <= 3)
if (version <= 3)
{
int m_FontCountX = reader.ReadInt32();
int m_FontCountY = reader.ReadInt32();
@@ -52,10 +47,10 @@ namespace AssetStudio
float m_Kerning = reader.ReadSingle();
float m_LineSpacing = reader.ReadSingle();
if (version[0] <= 3)
if (version <= 3)
{
int m_PerCharacterKerning_size = reader.ReadInt32();
for (int i = 0; i < m_PerCharacterKerning_size; i++)
for (var i = 0; i < m_PerCharacterKerning_size; i++)
{
int first = reader.ReadInt32();
float second = reader.ReadSingle();
@@ -71,7 +66,7 @@ namespace AssetStudio
var m_DefaultMaterial = new PPtr<Material>(reader);
int m_CharacterRects_size = reader.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++)
for (var i = 0; i < m_CharacterRects_size; i++)
{
int index = reader.ReadInt32();
//Rectf uv
@@ -86,7 +81,7 @@ namespace AssetStudio
float vertheight = reader.ReadSingle();
float width = reader.ReadSingle();
if (version[0] >= 4)
if (version >= 4)
{
var flipped = reader.ReadBoolean();
reader.AlignStream();
@@ -96,14 +91,14 @@ namespace AssetStudio
var m_Texture = new PPtr<Texture>(reader);
int m_KerningValues_size = reader.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++)
for (var i = 0; i < m_KerningValues_size; i++)
{
int pairfirst = reader.ReadInt16();
int pairsecond = reader.ReadInt16();
float second = reader.ReadSingle();
}
if (version[0] <= 3)
if (version <= 3)
{
var m_GridFont = reader.ReadBoolean();
reader.AlignStream();

View File

@@ -0,0 +1,35 @@
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class GLTextureSettings
{
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
[JsonInclude]
private int m_WrapU { set => m_WrapMode = value; }
public GLTextureSettings() { }
public GLTextureSettings(ObjectReader reader)
{
var version = reader.version;
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version >= 2017)//2017.x and up
{
m_WrapMode = reader.ReadInt32(); //m_WrapU
var m_WrapV = reader.ReadInt32();
var m_WrapW = reader.ReadInt32();
}
else
{
m_WrapMode = reader.ReadInt32();
}
}
}
}

View File

@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class GameObject : EditorExtension
{
public PPtr<Component>[] m_Components;
public List<PPtr<Component>> m_Components;
public string m_Name;
public Transform m_Transform;
@@ -16,21 +14,28 @@ namespace AssetStudio
public SkinnedMeshRenderer m_SkinnedMeshRenderer;
public Animator m_Animator;
public Animation m_Animation;
[JsonIgnore]
public CubismModel CubismModel;
public GameObject(ObjectReader reader) : base(reader)
{
int m_Component_size = reader.ReadInt32();
m_Components = new PPtr<Component>[m_Component_size];
for (int i = 0; i < m_Component_size; i++)
var m_ComponentSize = reader.ReadInt32();
m_Components = new List<PPtr<Component>>();
for (var i = 0; i < m_ComponentSize; i++)
{
if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down
if (version < (5, 5)) //5.5 down
{
int first = reader.ReadInt32();
var first = reader.ReadInt32();
}
m_Components[i] = new PPtr<Component>(reader);
m_Components.Add(new PPtr<Component>(reader));
}
var m_Layer = reader.ReadInt32();
if (version.IsTuanjie && (version > (2022, 3, 2) || (version == (2022, 3, 2) && version.Build >= 11))) //2022.3.2t11(1.1.3) and up
{
var m_HasEditorInfo = reader.ReadBoolean();
reader.AlignStream();
}
m_Name = reader.ReadAlignedString();
}
}

View File

@@ -0,0 +1,711 @@
namespace AssetStudio
{
public enum GraphicsFormat
{
/// <summary>
/// The format is not specified.
/// </summary>
None,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component stored with sRGB nonlinear encoding.
/// </summary>
R8_SRGB,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit B component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
R8G8B8_SRGB,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit B component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SRGB,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component.
/// </summary>
R8_UNorm,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_UNorm,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UNorm,
/// <summary>
/// A one-component, 8-bit signed normalized format that has a single 8-bit R component.
/// </summary>
R8_SNorm,
/// <summary>
/// A two-component, 16-bit signed normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SNorm,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has a single 8-bit R component.
/// </summary>
R8_UInt,
/// <summary>
/// A two-component, 16-bit unsigned integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_UInt,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UInt,
/// <summary>
/// A one-component, 8-bit signed integer format that has a single 8-bit R component.
/// </summary>
R8_SInt,
/// <summary>
/// A two-component, 16-bit signed integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_SInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SInt,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit R component.
/// </summary>
R16_UNorm,
/// <summary>
/// A two-component, 32-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UNorm,
/// <summary>
/// A three-component, 48-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UNorm,
/// <summary>
/// A four-component, 64-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UNorm,
/// <summary>
/// A one-component, 16-bit signed normalized format that has a single 16-bit R component.
/// </summary>
R16_SNorm,
/// <summary>
/// A two-component, 32-bit signed normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SNorm,
/// <summary>
/// A three-component, 48-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SNorm,
/// <summary>
/// A four-component, 64-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SNorm,
/// <summary>
/// A one-component, 16-bit unsigned integer format that has a single 16-bit R component.
/// </summary>
R16_UInt,
/// <summary>
/// A two-component, 32-bit unsigned integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UInt,
/// <summary>
/// A three-component, 48-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UInt,
/// <summary>
/// A four-component, 64-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UInt,
/// <summary>
/// A one-component, 16-bit signed integer format that has a single 16-bit R component.
/// </summary>
R16_SInt,
/// <summary>
/// A two-component, 32-bit signed integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SInt,
/// <summary>
/// A three-component, 48-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SInt,
/// <summary>
/// A four-component, 64-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SInt,
/// <summary>
/// A one-component, 32-bit unsigned integer format that has a single 32-bit R component.
/// </summary>
R32_UInt,
/// <summary>
/// A two-component, 64-bit unsigned integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_UInt,
/// <summary>
/// A three-component, 96-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_UInt,
/// <summary>
/// A four-component, 128-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_UInt,
/// <summary>
/// A one-component, 32-bit signed integer format that has a single 32-bit R component.
/// </summary>
R32_SInt,
/// <summary>
/// A two-component, 64-bit signed integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SInt,
/// <summary>
/// A three-component, 96-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SInt,
/// <summary>
/// A four-component, 128-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SInt,
/// <summary>
/// A one-component, 16-bit signed floating-point format that has a single 16-bit R component.
/// </summary>
R16_SFloat,
/// <summary>
/// A two-component, 32-bit signed floating-point format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SFloat,
/// <summary>
/// A three-component, 48-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SFloat,
/// <summary>
/// A four-component, 64-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SFloat,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has a single 32-bit R component.
/// </summary>
R32_SFloat,
/// <summary>
/// A two-component, 64-bit signed floating-point format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SFloat,
/// <summary>
/// A three-component, 96-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SFloat,
/// <summary>
/// A four-component, 128-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SFloat,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit R component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
B8G8R8_SRGB = 56,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit R component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SNorm,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2
/// </summary>
B8G8R8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SInt,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit R component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit B component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
R4G4B4A4_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit B component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit R component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
B4G4R4A4_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit B component in bits 0..4.
/// </summary>
R5G6B5_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit R component in bits 0..4.
/// </summary>
B5G6R5_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit B component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
R5G5B5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit R component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
B5G5R5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 1-bit A component in bit 15, a 5-bit R component in bits 10..14, a 5-bit G component in bits 5..9, and a 5-bit B component in bits 0..4.
/// </summary>
A1R5G5B5_UNormPack16,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 5-bit shared exponent in bits 27..31, a 9-bit B component mantissa in bits 18..26, a 9-bit G component mantissa in bits 9..17, and a 9-bit R component mantissa in bits 0..8.
/// </summary>
E5B9G9R9_UFloatPack32,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 10-bit B component in bits 22..31, an 11-bit G component in bits 11..21, an 11-bit R component in bits 0..10.
/// </summary>
B10G11R11_UFloatPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion).
/// </summary>
R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRUNormPack32,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit depth component.
/// </summary>
D16_UNorm = 90,
/// <summary>
/// A two-component, 32-bit format that has 24 unsigned normalized bits in the depth component and, optionally: 8 bits that are unused.
/// </summary>
D24_UNorm,
/// <summary>
/// A two-component, 32-bit packed format that has 8 unsigned integer bits in the stencil component, and 24 unsigned normalized bits in the depth component.
/// </summary>
D24_UNorm_S8_UInt,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has 32-bits in the depth component.
/// </summary>
D32_SFloat,
/// <summary>
/// A two-component format that has 32 signed float bits in the depth component and 8 unsigned integer bits in the stencil component. There are optionally: 24-bits that are unused.
/// </summary>
D32_SFloat_S8_UInt,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has 8-bits in the stencil component.
/// </summary>
S8_UInt,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_SRGB,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT3_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT3_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT5_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT5_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_BC4_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_BC4_SNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_UNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_SNorm,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned floating-point RGB texel data.
/// </summary>
RGB_BC6H_UFloat,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed floating-point RGB texel data.
/// </summary>
RGB_BC6H_SFloat,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_BC7_SRGB,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_BC7_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_2Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_2Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_4Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_4Bpp_UNorm,
/// <summary>
/// A three-component, ETC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC_UNorm,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_SRGB,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_ETC2_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_EAC_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_EAC_SNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_UNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_SNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC4X4_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC5X5_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC6X6_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC8X8_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC10X10_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC12X12_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UNorm,
/// <summary>
/// YUV 4:2:2 Video resource format.
/// </summary>
YUV2,
/// <summary>
/// GraphicsFormat.YUV2.
/// </summary>
VideoAuto = 144,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UFloat,
/// <summary>
/// A two-component, 24-bit format that has 16 unsigned normalized bits in the depth component and 8 unsigned integer bits in the stencil component. Most platforms do not support this format.
/// </summary>
D16_UNorm_S8_UInt,
}
public static class GraphicsFormatExtension
{
public static TextureFormat ToTextureFormat(this GraphicsFormat graphicsFormat)
{
switch (graphicsFormat)
{
case GraphicsFormat.R8_SRGB:
case GraphicsFormat.R8_UInt:
case GraphicsFormat.R8_UNorm:
return TextureFormat.R8;
case GraphicsFormat.R8G8_SRGB:
case GraphicsFormat.R8G8_UInt:
case GraphicsFormat.R8G8_UNorm:
return TextureFormat.RG16;
case GraphicsFormat.R8G8B8_SRGB:
case GraphicsFormat.R8G8B8_UInt:
case GraphicsFormat.R8G8B8_UNorm:
return TextureFormat.RGB24;
case GraphicsFormat.R8G8B8A8_SRGB:
case GraphicsFormat.R8G8B8A8_UInt:
case GraphicsFormat.R8G8B8A8_UNorm:
return TextureFormat.RGBA32;
case GraphicsFormat.R16_UInt:
case GraphicsFormat.R16_UNorm:
return TextureFormat.R16;
case GraphicsFormat.R16G16_UInt:
case GraphicsFormat.R16G16_UNorm:
return TextureFormat.RG32;
case GraphicsFormat.R16G16B16_UInt:
case GraphicsFormat.R16G16B16_UNorm:
return TextureFormat.RGB48;
case GraphicsFormat.R16G16B16A16_UInt:
case GraphicsFormat.R16G16B16A16_UNorm:
return TextureFormat.RGBA64;
case GraphicsFormat.R16_SFloat:
return TextureFormat.RHalf;
case GraphicsFormat.R16G16_SFloat:
return TextureFormat.RGHalf;
case GraphicsFormat.R16G16B16_SFloat: //?
case GraphicsFormat.R16G16B16A16_SFloat:
return TextureFormat.RGBAHalf;
case GraphicsFormat.R32_SFloat:
return TextureFormat.RFloat;
case GraphicsFormat.R32G32_SFloat:
return TextureFormat.RGFloat;
case GraphicsFormat.R32G32B32_SFloat: //?
case GraphicsFormat.R32G32B32A32_SFloat:
return TextureFormat.RGBAFloat;
case GraphicsFormat.B8G8R8A8_SRGB:
case GraphicsFormat.B8G8R8A8_UInt:
case GraphicsFormat.B8G8R8A8_UNorm:
return TextureFormat.BGRA32;
case GraphicsFormat.E5B9G9R9_UFloatPack32:
return TextureFormat.RGB9e5Float;
case GraphicsFormat.RGBA_DXT1_SRGB:
case GraphicsFormat.RGBA_DXT1_UNorm:
return TextureFormat.DXT1;
case GraphicsFormat.RGBA_DXT3_SRGB:
case GraphicsFormat.RGBA_DXT3_UNorm:
return TextureFormat.DXT3;
case GraphicsFormat.RGBA_DXT5_SRGB:
case GraphicsFormat.RGBA_DXT5_UNorm:
return TextureFormat.DXT5;
case GraphicsFormat.R_BC4_UNorm:
return TextureFormat.BC4;
case GraphicsFormat.RG_BC5_UNorm:
return TextureFormat.BC5;
case GraphicsFormat.RGB_BC6H_SFloat:
case GraphicsFormat.RGB_BC6H_UFloat:
return TextureFormat.BC6H;
case GraphicsFormat.RGBA_BC7_SRGB:
case GraphicsFormat.RGBA_BC7_UNorm:
return TextureFormat.BC7;
case GraphicsFormat.RGB_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_2Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_2Bpp_UNorm:
return TextureFormat.PVRTC_RGBA2;
case GraphicsFormat.RGB_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_4Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_4Bpp_UNorm:
return TextureFormat.PVRTC_RGBA4;
case GraphicsFormat.RGB_ETC_UNorm:
return TextureFormat.ETC_RGB4;
case GraphicsFormat.RGB_ETC2_SRGB:
case GraphicsFormat.RGB_ETC2_UNorm:
return TextureFormat.ETC2_RGB;
case GraphicsFormat.RGB_A1_ETC2_SRGB:
case GraphicsFormat.RGB_A1_ETC2_UNorm:
return TextureFormat.ETC2_RGBA1;
case GraphicsFormat.RGBA_ETC2_SRGB:
case GraphicsFormat.RGBA_ETC2_UNorm:
return TextureFormat.ETC2_RGBA8;
case GraphicsFormat.R_EAC_UNorm:
return TextureFormat.EAC_R;
case GraphicsFormat.R_EAC_SNorm:
return TextureFormat.EAC_R_SIGNED;
case GraphicsFormat.RG_EAC_UNorm:
return TextureFormat.EAC_RG;
case GraphicsFormat.RG_EAC_SNorm:
return TextureFormat.EAC_RG_SIGNED;
case GraphicsFormat.RGBA_ASTC4X4_SRGB:
case GraphicsFormat.RGBA_ASTC4X4_UNorm:
return TextureFormat.ASTC_RGBA_4x4;
case GraphicsFormat.RGBA_ASTC5X5_SRGB:
case GraphicsFormat.RGBA_ASTC5X5_UNorm:
return TextureFormat.ASTC_RGBA_5x5;
case GraphicsFormat.RGBA_ASTC6X6_SRGB:
case GraphicsFormat.RGBA_ASTC6X6_UNorm:
return TextureFormat.ASTC_RGBA_6x6;
case GraphicsFormat.RGBA_ASTC8X8_SRGB:
case GraphicsFormat.RGBA_ASTC8X8_UNorm:
return TextureFormat.ASTC_RGBA_8x8;
case GraphicsFormat.RGBA_ASTC10X10_SRGB:
case GraphicsFormat.RGBA_ASTC10X10_UNorm:
return TextureFormat.ASTC_RGBA_10x10;
case GraphicsFormat.RGBA_ASTC12X12_SRGB:
case GraphicsFormat.RGBA_ASTC12X12_UNorm:
return TextureFormat.ASTC_RGBA_12x12;
case GraphicsFormat.YUV2:
case GraphicsFormat.VideoAuto:
return TextureFormat.YUY2;
default:
return 0;
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Text.Json;
namespace AssetStudio
{
@@ -8,6 +9,8 @@ namespace AssetStudio
public Vector2 m_Scale;
public Vector2 m_Offset;
public UnityTexEnv() { }
public UnityTexEnv(ObjectReader reader)
{
m_Texture = new PPtr<Texture>(reader);
@@ -18,44 +21,46 @@ namespace AssetStudio
public class UnityPropertySheet
{
public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;
public KeyValuePair<string, int>[] m_Ints;
public KeyValuePair<string, float>[] m_Floats;
public KeyValuePair<string, Color>[] m_Colors;
public List<KeyValuePair<string, UnityTexEnv>> m_TexEnvs;
public List<KeyValuePair<string, int>> m_Ints;
public List<KeyValuePair<string, float>> m_Floats;
public List<KeyValuePair<string, Color>> m_Colors;
public UnityPropertySheet() { }
public UnityPropertySheet(ObjectReader reader)
{
var version = reader.version;
int m_TexEnvsSize = reader.ReadInt32();
m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];
for (int i = 0; i < m_TexEnvsSize; i++)
m_TexEnvs = new List<KeyValuePair<string, UnityTexEnv>>();
for (var i = 0; i < m_TexEnvsSize; i++)
{
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
m_TexEnvs.Add(new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader)));
}
if (version[0] >= 2021) //2021.1 and up
if (version >= 2021) //2021.1 and up
{
int m_IntsSize = reader.ReadInt32();
m_Ints = new KeyValuePair<string, int>[m_IntsSize];
for (int i = 0; i < m_IntsSize; i++)
m_Ints = new List<KeyValuePair<string, int>>();
for (var i = 0; i < m_IntsSize; i++)
{
m_Ints[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());
m_Ints.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
}
}
int m_FloatsSize = reader.ReadInt32();
m_Floats = new KeyValuePair<string, float>[m_FloatsSize];
for (int i = 0; i < m_FloatsSize; i++)
m_Floats = new List<KeyValuePair<string, float>>();
for (var i = 0; i < m_FloatsSize; i++)
{
m_Floats[i] = new KeyValuePair<string, float>(reader.ReadAlignedString(), reader.ReadSingle());
m_Floats.Add(new KeyValuePair<string, float>(reader.ReadAlignedString(), reader.ReadSingle()));
}
int m_ColorsSize = reader.ReadInt32();
m_Colors = new KeyValuePair<string, Color>[m_ColorsSize];
for (int i = 0; i < m_ColorsSize; i++)
m_Colors = new List<KeyValuePair<string, Color>>();
for (var i = 0; i < m_ColorsSize; i++)
{
m_Colors[i] = new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4());
m_Colors.Add(new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4()));
}
}
}
@@ -65,53 +70,62 @@ namespace AssetStudio
public PPtr<Shader> m_Shader;
public UnityPropertySheet m_SavedProperties;
public Material() { }
public Material(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedMaterial = JsonSerializer.Deserialize<Material>(type, jsonOptions);
m_Shader = parsedMaterial.m_Shader;
m_SavedProperties = parsedMaterial.m_SavedProperties;
}
public Material(ObjectReader reader) : base(reader)
{
m_Shader = new PPtr<Shader>(reader);
if (version[0] == 4 && version[1] >= 1) //4.x
if (version == 4 && version.Minor >= 1) //4.1 - 4.7.2
{
var m_ShaderKeywords = reader.ReadStringArray();
}
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up
if (version >= (2021, 2, 18)) //2021.2.18 and up
{
var m_ValidKeywords = reader.ReadStringArray();
var m_InvalidKeywords = reader.ReadStringArray();
}
else if (version[0] >= 5) //5.0 ~ 2021.2
else if (version >= 5) //5.0 - 2021.2.17
{
var m_ShaderKeywords = reader.ReadAlignedString();
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
var m_LightmapFlags = reader.ReadUInt32();
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
if (version >= (5, 6)) //5.6 and up
{
var m_EnableInstancingVariants = reader.ReadBoolean();
//var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up
reader.AlignStream();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
var m_CustomRenderQueue = reader.ReadInt32();
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
if (version >= (5, 1)) //5.1 and up
{
var stringTagMapSize = reader.ReadInt32();
for (int i = 0; i < stringTagMapSize; i++)
for (var i = 0; i < stringTagMapSize; i++)
{
var first = reader.ReadAlignedString();
var second = reader.ReadAlignedString();
}
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
if (version >= (5, 6)) //5.6 and up
{
var disabledShaderPasses = reader.ReadStringArray();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class MeshFilter : Component
{

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class MeshRenderer : Renderer
{

View File

@@ -1,15 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class MonoBehaviour : Behaviour
public class MonoBehaviour : Behaviour
{
public PPtr<MonoScript> m_Script;
public string m_Name;
public MonoBehaviour() { }
public MonoBehaviour(ObjectReader reader) : base(reader)
{
m_Script = new PPtr<MonoScript>(reader);

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class MonoScript : NamedObject
{
@@ -13,11 +8,11 @@ namespace AssetStudio
public MonoScript(ObjectReader reader) : base(reader)
{
if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
if (version >= (3, 4)) //3.4 and up
{
var m_ExecutionOrder = reader.ReadInt32();
}
if (version[0] < 5) //5.0 down
if (version < 5) //5.0 down
{
var m_PropertiesHash = reader.ReadUInt32();
}
@@ -25,17 +20,19 @@ namespace AssetStudio
{
var m_PropertiesHash = reader.ReadBytes(16);
}
if (version[0] < 3) //3.0 down
}
if (version < 3) //3.0 down
{
var m_PathName = reader.ReadAlignedString();
}
m_ClassName = reader.ReadAlignedString();
if (version[0] >= 3) //3.0 and up
if (version >= 3) //3.0 and up
{
m_Namespace = reader.ReadAlignedString();
}
m_AssemblyName = reader.ReadAlignedString();
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
if (version < (2018, 2)) //2018.2 down
{
var m_IsEditorScript = reader.ReadBoolean();
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class MovieTexture : Texture
{
@@ -11,6 +6,8 @@ namespace AssetStudio
public PPtr<AudioClip> m_AudioClip;
public MovieTexture(ObjectReader reader) : base(reader)
{
if (reader.version < (2019, 3)) //2019.3 down
{
var m_Loop = reader.ReadBoolean();
reader.AlignStream();
@@ -18,4 +15,5 @@ namespace AssetStudio
m_MovieData = reader.ReadUInt8Array();
}
}
}
}

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public class NamedObject : EditorExtension
{
public string m_Name;
protected NamedObject() { }
protected NamedObject(ObjectReader reader) : base(reader)
{
m_Name = reader.ReadAlignedString();

View File

@@ -1,18 +1,47 @@
using System.Collections.Specialized;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class Object
{
[JsonIgnore]
public SerializedFile assetsFile;
[JsonIgnore]
public ObjectReader reader;
public long m_PathID;
public int[] version;
protected BuildType buildType;
[JsonIgnore]
public UnityVersion version;
[JsonIgnore]
public BuildTarget platform;
[JsonConverter(typeof(JsonStringEnumConverter))]
public ClassIDType type;
[JsonIgnore]
public SerializedType serializedType;
public int classID;
public uint byteSize;
[JsonIgnore]
public string Name;
private static readonly JsonSerializerOptions jsonOptions;
static Object()
{
jsonOptions = new JsonSerializerOptions
{
Converters = { new JsonConverterHelper.FloatConverter() },
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals,
ReferenceHandler = ReferenceHandler.IgnoreCycles,
PropertyNameCaseInsensitive = true,
IncludeFields = true,
WriteIndented = true,
};
}
public Object() { }
public Object(ObjectReader reader)
{
@@ -22,9 +51,9 @@ namespace AssetStudio
type = reader.type;
m_PathID = reader.m_PathID;
version = reader.version;
buildType = reader.buildType;
platform = reader.platform;
serializedType = reader.serializedType;
classID = reader.classID;
byteSize = reader.byteSize;
if (platform == BuildTarget.NoTarget)
@@ -33,39 +62,67 @@ namespace AssetStudio
}
}
public string Dump()
public string DumpObject()
{
if (serializedType?.m_Type != null)
string str = null;
try
{
return TypeTreeHelper.ReadTypeString(serializedType.m_Type, reader);
}
return null;
if (this is Mesh m_Mesh)
{
m_Mesh.ProcessData();
}
public string Dump(TypeTree m_Type)
str = JsonSerializer.Deserialize<JsonObject>(JsonSerializer.SerializeToUtf8Bytes(this, GetType(), jsonOptions))
.ToJsonString(jsonOptions).Replace(" ", " ");
}
catch
{
if (m_Type != null)
//ignore
}
return str;
}
public string Dump(TypeTree m_Type = null)
{
m_Type = m_Type ?? serializedType?.m_Type;
if (m_Type == null)
return null;
return TypeTreeHelper.ReadTypeString(m_Type, reader);
}
return null;
}
public OrderedDictionary ToType()
public OrderedDictionary ToType(TypeTree m_Type = null)
{
if (serializedType?.m_Type != null)
{
return TypeTreeHelper.ReadType(serializedType.m_Type, reader);
}
m_Type = m_Type ?? serializedType?.m_Type;
if (m_Type == null)
return null;
}
public OrderedDictionary ToType(TypeTree m_Type)
{
if (m_Type != null)
{
return TypeTreeHelper.ReadType(m_Type, reader);
}
public JsonDocument ToJsonDoc(TypeTree m_Type = null)
{
var typeDict = ToType(m_Type);
try
{
if (typeDict != null)
{
return JsonSerializer.SerializeToDocument(typeDict, jsonOptions);
}
if (this is Mesh m_Mesh)
{
m_Mesh.ProcessData();
}
return JsonSerializer.SerializeToDocument(this, GetType(), jsonOptions);
}
catch
{
//ignore
}
return null;
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Text.Json.Serialization;
namespace AssetStudio
{
@@ -6,46 +7,55 @@ namespace AssetStudio
{
public int m_FileID;
public long m_PathID;
public string Name => _assetsFile != null && TryGet(out var result) ? result.Name : string.Empty;
private SerializedFile assetsFile;
private int index = -2; //-2 - Prepare, -1 - Missing
private int _index = -2; //-2 - Prepare, -1 - Missing
private SerializedFile _assetsFile;
[JsonIgnore]
public SerializedFile AssetsFile
{
get => _assetsFile;
set => _assetsFile = value;
}
public PPtr(ObjectReader reader)
{
m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile;
_assetsFile = reader.assetsFile;
}
public PPtr() { }
private bool TryGetAssetsFile(out SerializedFile result)
{
result = null;
if (m_FileID == 0)
{
result = assetsFile;
result = _assetsFile;
return true;
}
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
if (m_FileID > 0 && m_FileID - 1 < _assetsFile.m_Externals.Count)
{
var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList;
var assetsManager = _assetsFile.assetsManager;
var assetsFileList = assetsManager.AssetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (index == -2)
if (_index == -2)
{
var m_External = assetsFile.m_Externals[m_FileID - 1];
var m_External = _assetsFile.m_Externals[m_FileID - 1];
var name = m_External.fileName;
if (!assetsFileIndexCache.TryGetValue(name, out index))
if (!assetsFileIndexCache.TryGetValue(name, out _index))
{
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, index);
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, _index);
}
}
if (index >= 0)
if (_index >= 0)
{
result = assetsFileList[index];
result = assetsFileList[_index];
return true;
}
}
@@ -53,9 +63,10 @@ namespace AssetStudio
return false;
}
public bool TryGet(out T result)
public bool TryGet(out T result, SerializedFile assetsFile = null)
{
if (TryGetAssetsFile(out var sourceFile))
_assetsFile = _assetsFile ?? assetsFile;
if (!IsNull && TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
{
@@ -71,9 +82,10 @@ namespace AssetStudio
return false;
}
public bool TryGet<T2>(out T2 result) where T2 : Object
public bool TryGet<T2>(out T2 result, SerializedFile assetsFile = null) where T2 : Object
{
if (TryGetAssetsFile(out var sourceFile))
_assetsFile = _assetsFile ?? assetsFile;
if (!IsNull && TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
{
@@ -92,20 +104,20 @@ namespace AssetStudio
public void Set(T m_Object)
{
var name = m_Object.assetsFile.fileName;
if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
if (string.Equals(_assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
{
m_FileID = 0;
}
else
{
m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
m_FileID = _assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
if (m_FileID == -1)
{
assetsFile.m_Externals.Add(new FileIdentifier
_assetsFile.m_Externals.Add(new FileIdentifier
{
fileName = m_Object.assetsFile.fileName
});
m_FileID = assetsFile.m_Externals.Count;
m_FileID = _assetsFile.m_Externals.Count;
}
else
{
@@ -113,14 +125,14 @@ namespace AssetStudio
}
}
var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList;
var assetsManager = _assetsFile.assetsManager;
var assetsFileList = assetsManager.AssetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (!assetsFileIndexCache.TryGetValue(name, out index))
if (!assetsFileIndexCache.TryGetValue(name, out _index))
{
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, index);
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, _index);
}
m_PathID = m_Object.m_PathID;

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class PlayerSettings : Object
{
@@ -12,7 +7,9 @@ namespace AssetStudio
public PlayerSettings(ObjectReader reader) : base(reader)
{
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4.0 nad up
if (version >= (3, 0))
{
if (version >= (5, 4)) //5.4.0 and up
{
var productGUID = reader.ReadBytes(16);
}
@@ -23,12 +20,12 @@ namespace AssetStudio
reader.AlignStream();
int defaultScreenOrientation = reader.ReadInt32();
int targetDevice = reader.ReadInt32();
if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down
if (version < (5, 3)) //5.3 down
{
if (version[0] < 5) //5.0 down
if (version < 5) //5.0 down
{
int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics
if (version[0] > 4 || (version[0] == 4 && version[1] >= 6)) //4.6 and up
if (version >= (4, 6)) //4.6 and up
{
var targetIOSGraphics = reader.ReadInt32();
}
@@ -40,10 +37,11 @@ namespace AssetStudio
var useOnDemandResources = reader.ReadBoolean();
reader.AlignStream();
}
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
if (version >= (3, 5)) //3.5 and up
{
var accelerometerFrequency = reader.ReadInt32();
}
}
companyName = reader.ReadAlignedString();
productName = reader.ReadAlignedString();
}

View File

@@ -1,16 +1,18 @@
namespace AssetStudio
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class PreloadData : NamedObject
{
public PPtr<Object>[] m_Assets;
public List<PPtr<Object>> m_Assets;
public PreloadData(ObjectReader reader) : base(reader)
{
var m_PreloadTableSize = reader.ReadInt32();
m_Assets = new PPtr<Object>[m_PreloadTableSize];
m_Assets = new List<PPtr<Object>>();
for (var i = 0; i < m_PreloadTableSize; i++)
{
m_Assets[i] = new PPtr<Object>(reader);
m_Assets.Add(new PPtr<Object>(reader));
}
/*

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class RectTransform : Transform
{

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
@@ -19,13 +16,13 @@ namespace AssetStudio
public abstract class Renderer : Component
{
public PPtr<Material>[] m_Materials;
public List<PPtr<Material>> m_Materials;
public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices;
protected Renderer(ObjectReader reader) : base(reader)
{
if (version[0] < 5) //5.0 down
if (version < 5) //5.0 down
{
var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadBoolean();
@@ -34,31 +31,60 @@ namespace AssetStudio
}
else //5.0 and up
{
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
if (version >= (5, 4)) //5.4 and up
{
var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadByte();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
if (version >= (2017, 2)) //2017.2 and up
{
var m_DynamicOccludee = reader.ReadByte();
}
if (version[0] >= 2021) //2021.1 and up
if (version >= 2021) //2021.1 and up
{
var m_StaticShadowCaster = reader.ReadByte();
}
var m_MotionVectors = reader.ReadByte();
var m_LightProbeUsage = reader.ReadByte();
var m_ReflectionProbeUsage = reader.ReadByte();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
if (version >= (2019, 3)) //2019.3 and up
{
var m_RayTracingMode = reader.ReadByte();
}
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
var m_RayTraceProcedural = reader.ReadByte();
}
if (version.IsTuanjie) //2022.3.2t3(1.0.0) and up
{
var m_virtualGeometry = reader.ReadByte();
var m_virtualGeometryShadow = reader.ReadByte();
if (version > (2022, 3, 48) || (version == (2022, 3, 48) && version.Build >= 3)) //2022.3.48t3(1.4.0) and up
{
reader.AlignStream();
var m_ShadingRate = reader.ReadByte();
if (version >= (2022, 3, 61)) //2022.3.61t1(1.6.0) and up
{
var m_ForceDisableGRD = reader.ReadByte();
}
}
}
if (version >= (2023, 2)) //2023.2 and up
{
var m_RayTracingAccelStructBuildFlagsOverride = reader.ReadByte();
var m_RayTracingAccelStructBuildFlags = reader.ReadByte();
}
if (version >= (2023, 3)) //2023.3 and up
{
var m_SmallMeshCulling = reader.ReadByte();
}
reader.AlignStream();
if (version >= (6000, 2)) //6000.2 and up
{
var m_ForceMeshLod = reader.ReadInt16();
reader.AlignStream();
var m_MeshLodSelectionBias = reader.ReadSingle();
}
}
else
{
@@ -69,12 +95,12 @@ namespace AssetStudio
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
if (version >= 2018) //2018 and up
{
var m_RenderingLayerMask = reader.ReadUInt32();
}
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
if (version >= (2018, 3)) //2018.3 and up
{
var m_RendererPriority = reader.ReadInt32();
}
@@ -83,30 +109,30 @@ namespace AssetStudio
var m_LightmapIndexDynamic = reader.ReadUInt16();
}
if (version[0] >= 3) //3.0 and up
if (version >= 3) //3.0 and up
{
var m_LightmapTilingOffset = reader.ReadVector4();
}
if (version[0] >= 5) //5.0 and up
if (version >= 5) //5.0 and up
{
var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
}
var m_MaterialsSize = reader.ReadInt32();
m_Materials = new PPtr<Material>[m_MaterialsSize];
for (int i = 0; i < m_MaterialsSize; i++)
m_Materials = new List<PPtr<Material>>();
for (var i = 0; i < m_MaterialsSize; i++)
{
m_Materials[i] = new PPtr<Material>(reader);
m_Materials.Add(new PPtr<Material>(reader));
}
if (version[0] < 3) //3.0 down
if (version < 3) //3.0 down
{
var m_LightmapTilingOffset = reader.ReadVector4();
}
else //3.0 and up
{
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
if (version >= (5, 5)) //5.5 and up
{
m_StaticBatchInfo = new StaticBatchInfo(reader);
}
@@ -118,17 +144,17 @@ namespace AssetStudio
var m_StaticBatchRoot = new PPtr<Transform>(reader);
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
if (version >= (5, 4)) //5.4 and up
{
var m_ProbeAnchor = new PPtr<Transform>(reader);
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
}
else if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 - 5.3
else if (version >= (3, 5)) //3.5 - 5.3
{
var m_UseLightProbes = reader.ReadBoolean();
reader.AlignStream();
if (version[0] >= 5)//5.0 and up
if (version >= 5) //5.0 and up
{
var m_ReflectionProbeUsage = reader.ReadInt32();
}
@@ -136,20 +162,29 @@ namespace AssetStudio
var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
if (version[0] == 4 && version[1] == 3) //4.3
if (version == (4, 3)) //4.3
{
var m_SortingLayer = reader.ReadInt16();
}
else
{
var m_SortingLayerID = reader.ReadUInt32();
var m_SortingLayerID = reader.ReadInt32();
}
if (version > (5, 6) || (version == (5, 6) && version.Build >= 3)) //5.6.0f3 and up
{
var m_SortingLayer = reader.ReadInt16();
}
//SInt16 m_SortingLayer 5.6 and up
var m_SortingOrder = reader.ReadInt16();
reader.AlignStream();
if (version >= (6000, 3)) //6000.3 and up
{
var m_MaskInteraction = reader.ReadInt32();
}
}
}
}

View File

@@ -4,15 +4,15 @@ namespace AssetStudio
{
public class ResourceManager : Object
{
public KeyValuePair<string, PPtr<Object>>[] m_Container;
public List<KeyValuePair<string, PPtr<Object>>> m_Container;
public ResourceManager(ObjectReader reader) : base(reader)
{
var m_ContainerSize = reader.ReadInt32();
m_Container = new KeyValuePair<string, PPtr<Object>>[m_ContainerSize];
for (int i = 0; i < m_ContainerSize; i++)
m_Container = new List<KeyValuePair<string, PPtr<Object>>>();
for (var i = 0; i < m_ContainerSize; i++)
{
m_Container[i] = new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader));
m_Container.Add(new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader)));
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public abstract class RuntimeAnimatorController : NamedObject
{

View File

@@ -17,8 +17,8 @@ namespace AssetStudio
public class StructParameter
{
public MatrixParameter[] m_MatrixParams;
public VectorParameter[] m_VectorParams;
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public StructParameter(BinaryReader reader)
{
@@ -28,17 +28,17 @@ namespace AssetStudio
var m_StructSize = reader.ReadInt32();
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams[i] = new VectorParameter(reader);
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams[i] = new MatrixParameter(reader);
m_MatrixParams.Add(new MatrixParameter(reader));
}
}
}
@@ -112,15 +112,15 @@ namespace AssetStudio
public class SerializedProperties
{
public SerializedProperty[] m_Props;
public List<SerializedProperty> m_Props;
public SerializedProperties(BinaryReader reader)
{
int numProps = reader.ReadInt32();
m_Props = new SerializedProperty[numProps];
for (int i = 0; i < numProps; i++)
m_Props = new List<SerializedProperty>();
for (var i = 0; i < numProps; i++)
{
m_Props[i] = new SerializedProperty(reader);
m_Props.Add(new SerializedProperty(reader));
}
}
}
@@ -237,20 +237,20 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString();
rtBlend = new SerializedShaderRTBlendState[8];
for (int i = 0; i < 8; i++)
for (var i = 0; i < 8; i++)
{
rtBlend[i] = new SerializedShaderRTBlendState(reader);
}
rtSeparateBlend = reader.ReadBoolean();
reader.AlignStream();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
if (version >= (2017, 2)) //2017.2 and up
{
zClip = new SerializedShaderFloatValue(reader);
}
zTest = new SerializedShaderFloatValue(reader);
zWrite = new SerializedShaderFloatValue(reader);
culling = new SerializedShaderFloatValue(reader);
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
conservative = new SerializedShaderFloatValue(reader);
}
@@ -290,16 +290,16 @@ namespace AssetStudio
public class ParserBindChannels
{
public ShaderBindChannel[] m_Channels;
public List<ShaderBindChannel> m_Channels;
public uint m_SourceMap;
public ParserBindChannels(BinaryReader reader)
{
int numChannels = reader.ReadInt32();
m_Channels = new ShaderBindChannel[numChannels];
for (int i = 0; i < numChannels; i++)
m_Channels = new List<ShaderBindChannel>();
for (var i = 0; i < numChannels; i++)
{
m_Channels[i] = new ShaderBindChannel(reader);
m_Channels.Add(new ShaderBindChannel(reader));
}
reader.AlignStream();
@@ -359,7 +359,7 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
m_SamplerIndex = reader.ReadInt32();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
if (version >= (2017, 3)) //2017.3 and up
{
var m_MultiSampled = reader.ReadBoolean();
}
@@ -380,7 +380,7 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
m_ArraySize = reader.ReadInt32();
}
@@ -390,9 +390,9 @@ namespace AssetStudio
public class ConstantBuffer
{
public int m_NameIndex;
public MatrixParameter[] m_MatrixParams;
public VectorParameter[] m_VectorParams;
public StructParameter[] m_StructParams;
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public List<StructParameter> m_StructParams;
public int m_Size;
public bool m_IsPartialCB;
@@ -403,34 +403,31 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32();
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams[i] = new MatrixParameter(reader);
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams[i] = new VectorParameter(reader);
m_VectorParams.Add(new VectorParameter(reader));
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
if (version >= (2017, 3)) //2017.3 and up
{
int numStructParams = reader.ReadInt32();
m_StructParams = new StructParameter[numStructParams];
for (int i = 0; i < numStructParams; i++)
m_StructParams = new List<StructParameter>();
for (var i = 0; i < numStructParams; i++)
{
m_StructParams[i] = new StructParameter(reader);
m_StructParams.Add(new StructParameter(reader));
}
}
m_Size = reader.ReadInt32();
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|| version >= (2021, 1, 4)) //2021.1.4f1 and up
{
m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream();
@@ -491,71 +488,74 @@ namespace AssetStudio
public class SerializedProgramParameters
{
public VectorParameter[] m_VectorParams;
public MatrixParameter[] m_MatrixParams;
public TextureParameter[] m_TextureParams;
public BufferBinding[] m_BufferParams;
public ConstantBuffer[] m_ConstantBuffers;
public BufferBinding[] m_ConstantBufferBindings;
public UAVParameter[] m_UAVParams;
public SamplerParameter[] m_Samplers;
public List<VectorParameter> m_VectorParams;
public List<MatrixParameter> m_MatrixParams;
public List<TextureParameter> m_TextureParams;
public List<BufferBinding> m_BufferParams;
public List<ConstantBuffer> m_ConstantBuffers;
public List<BufferBinding> m_ConstantBufferBindings;
public List<UAVParameter> m_UAVParams;
public List<SamplerParameter> m_Samplers;
public SerializedProgramParameters(ObjectReader reader)
{
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
m_VectorParams = new List<VectorParameter>();
for (var i = 0; i < numVectorParams; i++)
{
m_VectorParams[i] = new VectorParameter(reader);
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
m_MatrixParams = new List<MatrixParameter>();
for (var i = 0; i < numMatrixParams; i++)
{
m_MatrixParams[i] = new MatrixParameter(reader);
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new TextureParameter[numTextureParams];
for (int i = 0; i < numTextureParams; i++)
m_TextureParams = new List<TextureParameter>();
for (var i = 0; i < numTextureParams; i++)
{
m_TextureParams[i] = new TextureParameter(reader);
m_TextureParams.Add(new TextureParameter(reader));
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new BufferBinding[numBufferParams];
for (int i = 0; i < numBufferParams; i++)
m_BufferParams = new List<BufferBinding>();
for (var i = 0; i < numBufferParams; i++)
{
m_BufferParams[i] = new BufferBinding(reader);
m_BufferParams.Add(new BufferBinding(reader));
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];
for (int i = 0; i < numConstantBuffers; i++)
m_ConstantBuffers = new List<ConstantBuffer>();
for (var i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers[i] = new ConstantBuffer(reader);
m_ConstantBuffers.Add(new ConstantBuffer(reader));
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];
for (int i = 0; i < numConstantBufferBindings; i++)
m_ConstantBufferBindings = new List<BufferBinding>();
for (var i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings[i] = new BufferBinding(reader);
m_ConstantBufferBindings.Add(new BufferBinding(reader));
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new UAVParameter[numUAVParams];
for (int i = 0; i < numUAVParams; i++)
m_UAVParams = new List<UAVParameter>();
for (var i = 0; i < numUAVParams; i++)
{
m_UAVParams[i] = new UAVParameter(reader);
m_UAVParams.Add(new UAVParameter(reader));
}
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
if (reader.version >= 2017) //2017 and up
{
m_Samplers[i] = new SamplerParameter(reader);
int numSamplers = reader.ReadInt32();
m_Samplers = new List<SamplerParameter>();
for (var i = 0; i < numSamplers; i++)
{
m_Samplers.Add(new SamplerParameter(reader));
}
}
}
}
@@ -567,15 +567,7 @@ namespace AssetStudio
public ushort[] m_KeywordIndices;
public sbyte m_ShaderHardwareTier;
public ShaderGpuProgramType m_GpuProgramType;
public SerializedProgramParameters m_Parameters;
public VectorParameter[] m_VectorParams;
public MatrixParameter[] m_MatrixParams;
public TextureParameter[] m_TextureParams;
public BufferBinding[] m_BufferParams;
public ConstantBuffer[] m_ConstantBuffers;
public BufferBinding[] m_ConstantBufferBindings;
public UAVParameter[] m_UAVParams;
public SamplerParameter[] m_Samplers;
public SerializedProgramParameters m_Parameters; // nested since 2020.3.2f1 and up; 2021.1.1f1 and up
public SerializedSubProgram(ObjectReader reader)
{
@@ -584,7 +576,7 @@ namespace AssetStudio
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
if (version.IsInRange(2019, (2021, 2))) //2019 ~2021.1
{
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
@@ -594,7 +586,7 @@ namespace AssetStudio
else
{
m_KeywordIndices = reader.ReadUInt16Array();
if (version[0] >= 2017) //2017 and up
if (version >= 2017) //2017 and up
{
reader.AlignStream();
}
@@ -604,79 +596,11 @@ namespace AssetStudio
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream();
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
{
m_Parameters = new SerializedProgramParameters(reader);
}
else
{
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams[i] = new VectorParameter(reader);
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
if (version >= (2017, 2)) //2017.2 and up
{
m_MatrixParams[i] = new MatrixParameter(reader);
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new TextureParameter[numTextureParams];
for (int i = 0; i < numTextureParams; i++)
{
m_TextureParams[i] = new TextureParameter(reader);
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new BufferBinding[numBufferParams];
for (int i = 0; i < numBufferParams; i++)
{
m_BufferParams[i] = new BufferBinding(reader);
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];
for (int i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers[i] = new ConstantBuffer(reader);
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];
for (int i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings[i] = new BufferBinding(reader);
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new UAVParameter[numUAVParams];
for (int i = 0; i < numUAVParams; i++)
{
m_UAVParams[i] = new UAVParameter(reader);
}
if (version[0] >= 2017) //2017 and up
{
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
{
m_Samplers[i] = new SamplerParameter(reader);
}
}
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
if (version[0] >= 2021) //2021.1 and up
if (version >= 2021) //2021.1 and up
{
var m_ShaderRequirements = reader.ReadInt64();
}
@@ -690,7 +614,7 @@ namespace AssetStudio
public class SerializedProgram
{
public SerializedSubProgram[] m_SubPrograms;
public List<SerializedSubProgram> m_SubPrograms;
public SerializedProgramParameters m_CommonParameters;
public ushort[] m_SerializedKeywordStateMask;
@@ -699,22 +623,19 @@ namespace AssetStudio
var version = reader.version;
int numSubPrograms = reader.ReadInt32();
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
for (int i = 0; i < numSubPrograms; i++)
m_SubPrograms = new List<SerializedSubProgram>();
for (var i = 0; i < numSubPrograms; i++)
{
m_SubPrograms[i] = new SerializedSubProgram(reader);
m_SubPrograms.Add(new SerializedSubProgram(reader));
}
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|| version >= (2021, 1, 1)) //2021.1.1f1 and up
{
m_CommonParameters = new SerializedProgramParameters(reader);
}
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
if (version >= (2022, 1)) //2022.1 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
@@ -731,11 +652,11 @@ namespace AssetStudio
public class SerializedPass
{
public Hash128[] m_EditorDataHash;
public List<Hash128> m_EditorDataHash;
public byte[] m_Platforms;
public ushort[] m_LocalKeywordMask;
public ushort[] m_GlobalKeywordMask;
public KeyValuePair<string, int>[] m_NameIndices;
public List<KeyValuePair<string, int>> m_NameIndices;
public PassType m_Type;
public SerializedShaderState m_State;
public uint m_ProgramMask;
@@ -756,18 +677,18 @@ namespace AssetStudio
{
var version = reader.version;
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
if (version >= (2020, 2)) //2020.2 and up
{
int numEditorDataHash = reader.ReadInt32();
m_EditorDataHash = new Hash128[numEditorDataHash];
for (int i = 0; i < numEditorDataHash; i++)
m_EditorDataHash = new List<Hash128>();
for (var i = 0; i < numEditorDataHash; i++)
{
m_EditorDataHash[i] = new Hash128(reader);
m_EditorDataHash.Add(new Hash128(reader));
}
reader.AlignStream();
m_Platforms = reader.ReadUInt8Array();
reader.AlignStream();
if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
if (version <= (2021, 1)) //2021.1 and down
{
m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
@@ -777,10 +698,10 @@ namespace AssetStudio
}
int numIndices = reader.ReadInt32();
m_NameIndices = new KeyValuePair<string, int>[numIndices];
for (int i = 0; i < numIndices; i++)
m_NameIndices = new List<KeyValuePair<string, int>>();
for (var i = 0; i < numIndices; i++)
{
m_NameIndices[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());
m_NameIndices.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
}
m_Type = (PassType)reader.ReadInt32();
@@ -791,12 +712,12 @@ namespace AssetStudio
progGeometry = new SerializedProgram(reader);
progHull = new SerializedProgram(reader);
progDomain = new SerializedProgram(reader);
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
if (version >= (2019, 3)) //2019.3 and up
{
progRayTracing = new SerializedProgram(reader);
}
m_HasInstancingVariant = reader.ReadBoolean();
if (version[0] >= 2018) //2018 and up
if (version >= 2018) //2018 and up
{
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
}
@@ -805,7 +726,7 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader);
if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
if (version == 2021 && version.Minor >= 2) //2021.2 ~2021.x
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
@@ -815,32 +736,32 @@ namespace AssetStudio
public class SerializedTagMap
{
public KeyValuePair<string, string>[] tags;
public List<KeyValuePair<string, string>> tags;
public SerializedTagMap(BinaryReader reader)
{
int numTags = reader.ReadInt32();
tags = new KeyValuePair<string, string>[numTags];
for (int i = 0; i < numTags; i++)
tags = new List<KeyValuePair<string, string>>();
for (var i = 0; i < numTags; i++)
{
tags[i] = new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString());
tags.Add(new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString()));
}
}
}
public class SerializedSubShader
{
public SerializedPass[] m_Passes;
public List<SerializedPass> m_Passes;
public SerializedTagMap m_Tags;
public int m_LOD;
public SerializedSubShader(ObjectReader reader)
{
int numPasses = reader.ReadInt32();
m_Passes = new SerializedPass[numPasses];
for (int i = 0; i < numPasses; i++)
m_Passes = new List<SerializedPass>();
for (var i = 0; i < numPasses; i++)
{
m_Passes[i] = new SerializedPass(reader);
m_Passes.Add(new SerializedPass(reader));
}
m_Tags = new SerializedTagMap(reader);
@@ -875,14 +796,14 @@ namespace AssetStudio
public class SerializedShader
{
public SerializedProperties m_PropInfo;
public SerializedSubShader[] m_SubShaders;
public List<SerializedSubShader> m_SubShaders;
public string[] m_KeywordNames;
public byte[] m_KeywordFlags;
public string m_Name;
public string m_CustomEditorName;
public string m_FallbackName;
public SerializedShaderDependency[] m_Dependencies;
public SerializedCustomEditorForRenderPipeline[] m_CustomEditorForRenderPipelines;
public List<SerializedShaderDependency> m_Dependencies;
public List<SerializedCustomEditorForRenderPipeline> m_CustomEditorForRenderPipelines;
public bool m_DisableNoSubshadersMessage;
public SerializedShader(ObjectReader reader)
@@ -892,13 +813,13 @@ namespace AssetStudio
m_PropInfo = new SerializedProperties(reader);
int numSubShaders = reader.ReadInt32();
m_SubShaders = new SerializedSubShader[numSubShaders];
for (int i = 0; i < numSubShaders; i++)
m_SubShaders = new List<SerializedSubShader>();
for (var i = 0; i < numSubShaders; i++)
{
m_SubShaders[i] = new SerializedSubShader(reader);
m_SubShaders.Add(new SerializedSubShader(reader));
}
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
if (version >= (2021, 2)) //2021.2 and up
{
m_KeywordNames = reader.ReadStringArray();
m_KeywordFlags = reader.ReadUInt8Array();
@@ -910,19 +831,19 @@ namespace AssetStudio
m_FallbackName = reader.ReadAlignedString();
int numDependencies = reader.ReadInt32();
m_Dependencies = new SerializedShaderDependency[numDependencies];
for (int i = 0; i < numDependencies; i++)
m_Dependencies = new List<SerializedShaderDependency>();
for (var i = 0; i < numDependencies; i++)
{
m_Dependencies[i] = new SerializedShaderDependency(reader);
m_Dependencies.Add(new SerializedShaderDependency(reader));
}
if (version[0] >= 2021) //2021.1 and up
if (version >= 2021) //2021.1 and up
{
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];
for (int i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)
m_CustomEditorForRenderPipelines = new List<SerializedCustomEditorForRenderPipeline>();
for (var i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)
{
m_CustomEditorForRenderPipelines[i] = new SerializedCustomEditorForRenderPipeline(reader);
m_CustomEditorForRenderPipelines.Add(new SerializedCustomEditorForRenderPipeline(reader));
}
}
@@ -977,11 +898,11 @@ namespace AssetStudio
public Shader(ObjectReader reader) : base(reader)
{
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
if (version >= (5, 5)) //5.5 and up
{
m_ParsedForm = new SerializedShader(reader);
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
if (version >= (2019, 3)) //2019.3 and up
{
offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray();
@@ -997,18 +918,18 @@ namespace AssetStudio
reader.AlignStream();
var m_DependenciesCount = reader.ReadInt32();
for (int i = 0; i < m_DependenciesCount; i++)
for (var i = 0; i < m_DependenciesCount; i++)
{
new PPtr<Shader>(reader);
var m_Dependencies = new PPtr<Shader>(reader);
}
if (version[0] >= 2018)
if (version >= 2018)
{
var m_NonModifiableTexturesCount = reader.ReadInt32();
for (int i = 0; i < m_NonModifiableTexturesCount; i++)
for (var i = 0; i < m_NonModifiableTexturesCount; i++)
{
var first = reader.ReadAlignedString();
new PPtr<Texture>(reader);
var second = new PPtr<Texture>(reader);
}
}
@@ -1020,7 +941,7 @@ namespace AssetStudio
m_Script = reader.ReadUInt8Array();
reader.AlignStream();
var m_PathName = reader.ReadAlignedString();
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
if (version == 5 && version.Minor >= 3) //5.3 - 5.4
{
decompressedSize = reader.ReadUInt32();
m_SubProgramBlob = reader.ReadUInt8Array();

View File

@@ -1,14 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class SkinnedMeshRenderer : Renderer
{
public PPtr<Mesh> m_Mesh;
public PPtr<Transform>[] m_Bones;
public List<PPtr<Transform>> m_Bones;
public float[] m_BlendShapeWeights;
public SkinnedMeshRenderer(ObjectReader reader) : base(reader)
@@ -18,20 +15,21 @@ namespace AssetStudio
var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below
reader.AlignStream();
if (version[0] == 2 && version[1] < 6) //2.6 down
if (version < (2, 6)) //2.6 down
{
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
}
m_Mesh = new PPtr<Mesh>(reader);
m_Bones = new PPtr<Transform>[reader.ReadInt32()];
for (int b = 0; b < m_Bones.Length; b++)
var numBones = reader.ReadInt32();
m_Bones = new List<PPtr<Transform>>();
for (var b = 0; b < numBones; b++)
{
m_Bones[b] = new PPtr<Transform>(reader);
m_Bones.Add(new PPtr<Transform>(reader));
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
if (version >= (4, 3)) //4.3 and up
{
m_BlendShapeWeights = reader.ReadSingleArray();
}

View File

@@ -68,7 +68,7 @@ namespace AssetStudio
var version = reader.version;
pos = reader.ReadVector3();
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
if (version <= (4, 3)) //4.3 and down
{
uv = reader.ReadVector2();
}
@@ -79,11 +79,11 @@ namespace AssetStudio
{
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public SecondarySpriteTexture[] secondaryTextures;
public SubMesh[] m_SubMeshes;
public List<SecondarySpriteTexture> secondaryTextures;
public List<SubMesh> m_SubMeshes;
public byte[] m_IndexBuffer;
public VertexData m_VertexData;
public SpriteVertex[] vertices;
public List<SpriteVertex> vertices;
public ushort[] indices;
public Matrix4x4[] m_Bindpose;
public BoneWeights4[] m_SourceSkin;
@@ -99,28 +99,25 @@ namespace AssetStudio
var version = reader.version;
texture = new PPtr<Texture2D>(reader);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{
alphaTexture = new PPtr<Texture2D>(reader);
}
alphaTexture = version >= (5, 2) ? new PPtr<Texture2D>(reader) : new PPtr<Texture2D>(); //5.2 and up
if (version[0] >= 2019) //2019 and up
if (version >= 2019) //2019 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
for (int i = 0; i < secondaryTexturesSize; i++)
secondaryTextures = new List<SecondarySpriteTexture>();
for (var i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures[i] = new SecondarySpriteTexture(reader);
secondaryTextures.Add(new SecondarySpriteTexture(reader));
}
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
if (version >= (5, 6)) //5.6 and up
{
var m_SubMeshesSize = reader.ReadInt32();
m_SubMeshes = new SubMesh[m_SubMeshesSize];
for (int i = 0; i < m_SubMeshesSize; i++)
m_SubMeshes = new List<SubMesh>();
for (var i = 0; i < m_SubMeshesSize; i++)
{
m_SubMeshes[i] = new SubMesh(reader);
m_SubMeshes.Add(new SubMesh(reader));
}
m_IndexBuffer = reader.ReadUInt8Array();
@@ -131,24 +128,26 @@ namespace AssetStudio
else
{
var verticesSize = reader.ReadInt32();
vertices = new SpriteVertex[verticesSize];
for (int i = 0; i < verticesSize; i++)
vertices = new List<SpriteVertex>();
for (var i = 0; i < verticesSize; i++)
{
vertices[i] = new SpriteVertex(reader);
vertices.Add(new SpriteVertex(reader));
}
indices = reader.ReadUInt16Array();
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
if (version >= 2018) //2018 and up
{
m_Bindpose = reader.ReadMatrixArray();
if (version[0] == 2018 && version[1] < 2) //2018.2 down
if (version < (2018, 2)) //2018.2 down
{
var m_SourceSkinSize = reader.ReadInt32();
for (int i = 0; i < m_SourceSkinSize; i++)
reader.ThrowIfTooLarge(m_SourceSkinSize * 32f);
m_SourceSkin = new BoneWeights4[m_SourceSkinSize];
for (var i = 0; i < m_SourceSkinSize; i++)
{
m_SourceSkin[i] = new BoneWeights4(reader);
}
@@ -157,18 +156,18 @@ namespace AssetStudio
textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
if (version >= (5, 6)) //5.6 and up
{
atlasRectOffset = reader.ReadVector2();
}
settingsRaw = new SpriteSettings(reader);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
if (version >= (4, 5)) //4.5 and up
{
uvTransform = reader.ReadVector4();
}
if (version[0] >= 2017) //2017 and up
if (version >= 2017) //2017 and up
{
downscaleMultiplier = reader.ReadSingle();
}
@@ -204,34 +203,32 @@ namespace AssetStudio
public string[] m_AtlasTags;
public PPtr<SpriteAtlas> m_SpriteAtlas;
public SpriteRenderData m_RD;
public Vector2[][] m_PhysicsShape;
//public Vector2[][] m_PhysicsShape;
public Sprite(ObjectReader reader) : base(reader)
{
m_Rect = new Rectf(reader);
m_Offset = reader.ReadVector2();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
if (version >= (4, 5)) //4.5 and up
{
m_Border = reader.ReadVector4();
}
m_PixelsToUnits = reader.ReadSingle();
if (version[0] > 5
|| (version[0] == 5 && version[1] > 4)
|| (version[0] == 5 && version[1] == 4 && version[2] >= 2)
|| (version[0] == 5 && version[1] == 4 && version[2] == 1 && buildType.IsPatch && version[3] >= 3)) //5.4.1p3 and up
if (version >= (5, 4, 2)
|| version == (5, 4, 1) && version.IsPatch && version.Build >= 3) //5.4.1p3 and up
{
m_Pivot = reader.ReadVector2();
}
m_Extrude = reader.ReadUInt32();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
if (version >= (5, 3)) //5.3 and up
{
m_IsPolygon = reader.ReadBoolean();
reader.AlignStream();
}
if (version[0] >= 2017) //2017 and up
if (version >= 2017) //2017 and up
{
var first = new Guid(reader.ReadBytes(16));
var second = reader.ReadInt64();
@@ -243,17 +240,18 @@ namespace AssetStudio
}
m_RD = new SpriteRenderData(reader);
if (version[0] >= 2017) //2017 and up
/*
if (version >= 2017) //2017 and up
{
var m_PhysicsShapeSize = reader.ReadInt32();
m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];
for (int i = 0; i < m_PhysicsShapeSize; i++)
var physicsShapeList = new List<Vector2[]>();
for (var i = 0; i < m_PhysicsShapeSize; i++)
{
m_PhysicsShape[i] = reader.ReadVector2Array();
physicsShapeList.Add(reader.ReadVector2Array());
}
m_PhysicsShape = physicsShapeList.ToArray();
}
*/
//vector m_Bones 2018 and up
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace AssetStudio
{
@@ -13,7 +14,7 @@ namespace AssetStudio
public Vector4 uvTransform;
public float downscaleMultiplier;
public SpriteSettings settingsRaw;
public SecondarySpriteTexture[] secondaryTextures;
public List<SecondarySpriteTexture> secondaryTextures;
public SpriteAtlasData(ObjectReader reader)
{
@@ -22,20 +23,20 @@ namespace AssetStudio
alphaTexture = new PPtr<Texture2D>(reader);
textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
if (version >= (2017, 2)) //2017.2 and up
{
atlasRectOffset = reader.ReadVector2();
}
uvTransform = reader.ReadVector4();
downscaleMultiplier = reader.ReadSingle();
settingsRaw = new SpriteSettings(reader);
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
if (version >= (2020, 2)) //2020.2 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
for (int i = 0; i < secondaryTexturesSize; i++)
secondaryTextures = new List<SecondarySpriteTexture>();
for (var i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures[i] = new SecondarySpriteTexture(reader);
secondaryTextures.Add(new SecondarySpriteTexture(reader));
}
reader.AlignStream();
}
@@ -44,24 +45,25 @@ namespace AssetStudio
public sealed class SpriteAtlas : NamedObject
{
public PPtr<Sprite>[] m_PackedSprites;
public List<PPtr<Sprite>> m_PackedSprites;
[JsonConverter(typeof(JsonConverterHelper.RenderDataMapConverter))]
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
public bool m_IsVariant;
public SpriteAtlas(ObjectReader reader) : base(reader)
{
var m_PackedSpritesSize = reader.ReadInt32();
m_PackedSprites = new PPtr<Sprite>[m_PackedSpritesSize];
for (int i = 0; i < m_PackedSpritesSize; i++)
m_PackedSprites = new List<PPtr<Sprite>>();
for (var i = 0; i < m_PackedSpritesSize; i++)
{
m_PackedSprites[i] = new PPtr<Sprite>(reader);
m_PackedSprites.Add(new PPtr<Sprite>(reader));
}
var m_PackedSpriteNamesToIndex = reader.ReadStringArray();
var m_RenderDataMapSize = reader.ReadInt32();
m_RenderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>(m_RenderDataMapSize);
for (int i = 0; i < m_RenderDataMapSize; i++)
m_RenderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>();
for (var i = 0; i < m_RenderDataMapSize; i++)
{
var first = new Guid(reader.ReadBytes(16));
var second = reader.ReadInt64();

View File

@@ -0,0 +1,27 @@
namespace AssetStudio
{
public class StreamingInfo
{
public long offset; //ulong
public uint size;
public string path;
public StreamingInfo() { }
public StreamingInfo(ObjectReader reader)
{
var version = reader.version;
if (version >= 2020) //2020.1 and up
{
offset = reader.ReadInt64();
}
else
{
offset = reader.ReadUInt32();
}
size = reader.ReadUInt32();
path = reader.ReadAlignedString();
}
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public sealed class TextAsset : NamedObject
{

View File

@@ -1,19 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
namespace AssetStudio
{
public abstract class Texture : NamedObject
{
protected Texture() { }
protected Texture(ObjectReader reader) : base(reader)
{
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
if (version >= (2017, 3)) //2017.3 and up
{
if (version < (2023, 2)) //2023.2 down
{
var m_ForcedFallbackFormat = reader.ReadInt32();
var m_DownscaleFallback = reader.ReadBoolean();
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
}
if (version >= (2020, 2)) //2020.2 and up
{
var m_IsAlphaChannelOptional = reader.ReadBoolean();
}

View File

@@ -1,79 +1,109 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public class StreamingInfo
{
public long offset; //ulong
public uint size;
public string path;
public StreamingInfo(ObjectReader reader)
{
var version = reader.version;
if (version[0] >= 2020) //2020.1 and up
{
offset = reader.ReadInt64();
}
else
{
offset = reader.ReadUInt32();
}
size = reader.ReadUInt32();
path = reader.ReadAlignedString();
}
}
public class GLTextureSettings
{
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
public GLTextureSettings(ObjectReader reader)
{
var version = reader.version;
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version[0] >= 2017)//2017.x and up
{
m_WrapMode = reader.ReadInt32(); //m_WrapU
int m_WrapV = reader.ReadInt32();
int m_WrapW = reader.ReadInt32();
}
else
{
m_WrapMode = reader.ReadInt32();
}
}
}
public sealed class Texture2D : Texture
{
public int m_Width;
public int m_Height;
public uint m_CompleteImageSize;
public TextureFormat m_TextureFormat;
public bool m_MipMap;
public int m_MipCount;
public GLTextureSettings m_TextureSettings;
public int m_ImageCount;
public byte[] m_PlatformBlob;
[JsonPropertyName("image data")]
public ResourceReader image_data;
public StreamingInfo m_StreamData;
public StreamingInfo m_DataStreamData; //Tuanjie
public Texture2D() { }
public Texture2D(Texture2DArray m_Texture2DArray, int layer) // Texture2DArrayImage
{
reader = m_Texture2DArray.reader;
assetsFile = m_Texture2DArray.assetsFile;
version = m_Texture2DArray.version;
platform = m_Texture2DArray.platform;
m_Name = $"{m_Texture2DArray.m_Name}_{layer + 1}";
type = ClassIDType.Texture2DArrayImage;
m_PathID = m_Texture2DArray.m_PathID;
m_Width = m_Texture2DArray.m_Width;
m_Height = m_Texture2DArray.m_Height;
m_TextureFormat = m_Texture2DArray.m_Format.ToTextureFormat();
m_MipCount = m_Texture2DArray.m_MipCount;
m_TextureSettings = m_Texture2DArray.m_TextureSettings;
m_StreamData = m_Texture2DArray.m_StreamData;
m_PlatformBlob = Array.Empty<byte>();
m_MipMap = m_MipCount > 1;
m_ImageCount = 1;
//var imgActualDataSize = GetImageDataSize(m_TextureFormat);
//var mipmapSize = (int)(m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth - imgActualDataSize);
m_CompleteImageSize = (uint)(m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth);
var offset = layer * m_CompleteImageSize + m_Texture2DArray.image_data.Offset;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, offset, m_CompleteImageSize)
: new ResourceReader(reader, offset, m_CompleteImageSize);
byteSize = (uint)(m_Width * m_Height) * 4;
}
public Texture2D(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedTex2d = JsonSerializer.Deserialize<Texture2D>(type, jsonOptions);
m_Width = parsedTex2d.m_Width;
m_Height = parsedTex2d.m_Height;
m_CompleteImageSize = parsedTex2d.m_CompleteImageSize;
m_TextureFormat = parsedTex2d.m_TextureFormat;
m_MipMap = parsedTex2d.m_MipMap;
m_MipCount = parsedTex2d.m_MipCount;
m_ImageCount = parsedTex2d.m_ImageCount;
m_TextureSettings = parsedTex2d.m_TextureSettings;
m_StreamData = parsedTex2d.m_StreamData;
m_PlatformBlob = parsedTex2d.m_PlatformBlob ?? Array.Empty<byte>();
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2d.image_data.Offset, parsedTex2d.image_data.Size);
}
public Texture2D(ObjectReader reader) : base(reader)
{
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
var m_CompleteImageSize = reader.ReadInt32();
if (version[0] >= 2020) //2020.1 and up
m_CompleteImageSize = reader.ReadUInt32();
if (version >= 2020) //2020.1 and up
{
var m_MipsStripped = reader.ReadInt32();
}
if (version.IsTuanjie && (version > (2022, 3, 2) || version.Build >= 8)) //2022.3.2t8(1.1.0) and up
{
var m_WebStreaming = reader.ReadBoolean();
reader.AlignStream();
var m_PriorityLevel = reader.ReadInt32();
var m_UploadedMode = reader.ReadInt32();
m_DataStreamData = new StreamingInfo //sample is needed
{
offset = 0,
size = reader.ReadUInt32(),
path = reader.ReadAlignedString()
};
}
m_TextureFormat = (TextureFormat)reader.ReadInt32();
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
if (version.IsTuanjie && version >= (2022, 3, 62)) //2022.3.62t1(1.7.0) and up
{
var m_TextureManagerMultiFormatSettingSize = reader.ReadInt32();
reader.Position += m_TextureManagerMultiFormatSettingSize; //skip byte[] m_TextureManagerMultiFormatSetting
reader.AlignStream();
}
if (version < (5, 2)) //5.2 down
{
m_MipMap = reader.ReadBoolean();
}
@@ -81,152 +111,132 @@ namespace AssetStudio
{
m_MipCount = reader.ReadInt32();
}
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
if (version >= (2, 6)) //2.6.0 and up
{
var m_IsReadable = reader.ReadBoolean();
}
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
var m_IsPreProcessed = reader.ReadBoolean();
}
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
if (version >= (2019, 3)) //2019.3 and up
{
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
if (version >= (2022, 2)) //2022.2 and up
{
var m_IgnoreMipmapLimit = reader.ReadBoolean();
reader.AlignStream();
}
else
{
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
}
}
if (version[0] >= 3) //3.0.0 - 5.4
{
if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))
if (version.IsInRange(3, (5, 5))) //3.0.0 - 5.4
{
var m_ReadAllowed = reader.ReadBoolean();
}
}
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
if (version >= (2022, 2)) //2022.2 and up
{
var m_MipmapLimitGroupName = reader.ReadAlignedString();
reader.AlignStream();
}
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
if (version >= (2018, 2)) //2018.2 and up
{
var m_StreamingMipmaps = reader.ReadBoolean();
}
reader.AlignStream();
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
if (version >= (2018, 2)) //2018.2 and up
{
var m_StreamingMipmapsPriority = reader.ReadInt32();
}
var m_ImageCount = reader.ReadInt32();
m_ImageCount = reader.ReadInt32();
var m_TextureDimension = reader.ReadInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version[0] >= 3) //3.0 and up
if (version >= 3) //3.0 and up
{
var m_LightmapFormat = reader.ReadInt32();
}
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5.0 and up
if (version >= (3, 5)) //3.5.0 and up
{
var m_ColorSpace = reader.ReadInt32();
}
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
if (version >= (2020, 2)) //2020.2 and up
{
var m_PlatformBlob = reader.ReadUInt8Array();
m_PlatformBlob = reader.ReadUInt8Array();
reader.AlignStream();
}
else
{
m_PlatformBlob = Array.Empty<byte>();
}
var image_data_size = reader.ReadInt32();
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
if (image_data_size == 0 && version >= (5, 3))//5.3.0 and up
{
m_StreamData = new StreamingInfo(reader);
}
ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_StreamData?.path))
{
resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
image_data = resourceReader;
}
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
public enum TextureFormat
// https://docs.unity3d.com/2023.3/Documentation/Manual/class-TextureImporterOverride.html
private int GetImageDataSize(TextureFormat textureFormat)
{
Alpha8 = 1,
ARGB4444,
RGB24,
RGBA32,
ARGB32,
ARGBFloat,
RGB565,
BGR24,
R16,
DXT1,
DXT3,
DXT5,
RGBA4444,
BGRA32,
RHalf,
RGHalf,
RGBAHalf,
RFloat,
RGFloat,
RGBAFloat,
YUY2,
RGB9e5Float,
RGBFloat,
BC6H,
BC7,
BC4,
BC5,
DXT1Crunched,
DXT5Crunched,
PVRTC_RGB2,
PVRTC_RGBA2,
PVRTC_RGB4,
PVRTC_RGBA4,
ETC_RGB4,
ATC_RGB4,
ATC_RGBA8,
EAC_R = 41,
EAC_R_SIGNED,
EAC_RG,
EAC_RG_SIGNED,
ETC2_RGB,
ETC2_RGBA1,
ETC2_RGBA8,
ASTC_RGB_4x4,
ASTC_RGB_5x5,
ASTC_RGB_6x6,
ASTC_RGB_8x8,
ASTC_RGB_10x10,
ASTC_RGB_12x12,
ASTC_RGBA_4x4,
ASTC_RGBA_5x5,
ASTC_RGBA_6x6,
ASTC_RGBA_8x8,
ASTC_RGBA_10x10,
ASTC_RGBA_12x12,
ETC_RGB4_3DS,
ETC_RGBA8_3DS,
RG16,
R8,
ETC_RGB4Crunched,
ETC2_RGBA8Crunched,
ASTC_HDR_4x4,
ASTC_HDR_5x5,
ASTC_HDR_6x6,
ASTC_HDR_8x8,
ASTC_HDR_10x10,
ASTC_HDR_12x12,
RG32,
RGB48,
RGBA64
var imgDataSize = m_Width * m_Height;
switch (textureFormat)
{
case TextureFormat.ASTC_RGBA_5x5:
// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/
imgDataSize = (int)(MathF.Floor((m_Width + 4) / 5f) * MathF.Floor((m_Height + 4) / 5f) * 16);
break;
case TextureFormat.ASTC_RGBA_6x6:
imgDataSize = (int)(MathF.Floor((m_Width + 5) / 6f) * MathF.Floor((m_Height + 5) / 6f) * 16);
break;
case TextureFormat.ASTC_RGBA_8x8:
imgDataSize = (int)(MathF.Floor((m_Width + 7) / 8f) * MathF.Floor((m_Height + 7) / 8f) * 16);
break;
case TextureFormat.ASTC_RGBA_10x10:
imgDataSize = (int)(MathF.Floor((m_Width + 9) / 10f) * MathF.Floor((m_Height + 9) / 10f) * 16);
break;
case TextureFormat.ASTC_RGBA_12x12:
imgDataSize = (int)(MathF.Floor((m_Width + 11) / 12f) * MathF.Floor((m_Height + 11) / 12f) * 16);
break;
case TextureFormat.DXT1:
case TextureFormat.EAC_R:
case TextureFormat.EAC_R_SIGNED:
case TextureFormat.ATC_RGB4:
case TextureFormat.ETC_RGB4:
case TextureFormat.ETC2_RGB:
case TextureFormat.ETC2_RGBA1:
case TextureFormat.PVRTC_RGBA4:
imgDataSize /= 2;
break;
case TextureFormat.PVRTC_RGBA2:
imgDataSize /= 4;
break;
case TextureFormat.R16:
case TextureFormat.RGB565:
imgDataSize *= 2;
break;
case TextureFormat.RGB24:
imgDataSize *= 3;
break;
case TextureFormat.RG32:
case TextureFormat.RGBA32:
case TextureFormat.ARGB32:
case TextureFormat.BGRA32:
case TextureFormat.RGB9e5Float:
imgDataSize *= 4;
break;
case TextureFormat.RGB48:
imgDataSize *= 6;
break;
case TextureFormat.RGBAHalf:
case TextureFormat.RGBA64:
imgDataSize *= 8;
break;
}
return imgDataSize;
}
}
}

View File

@@ -0,0 +1,96 @@
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public sealed class Texture2DArray : Texture
{
public int m_Width;
public int m_Height;
public int m_Depth;
public GraphicsFormat m_Format;
public int m_MipCount;
public uint m_DataSize;
public GLTextureSettings m_TextureSettings;
public int m_ColorSpace;
[JsonPropertyName("image data")]
public ResourceReader image_data;
public StreamingInfo m_StreamData;
public List<Texture2D> TextureList;
public Texture2DArray() { }
public Texture2DArray(ObjectReader reader) : base(reader)
{
if (version >= 2019) //2019 and up
{
m_ColorSpace = reader.ReadInt32();
m_Format = (GraphicsFormat)reader.ReadInt32();
}
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_Depth = reader.ReadInt32();
if (version < 2019) //2019 down
{
m_Format = (GraphicsFormat)reader.ReadInt32();
}
m_MipCount = reader.ReadInt32();
if (version >= (2023, 2)) //2023.2 and up
{
var m_MipsStripped = reader.ReadInt32();
}
m_DataSize = reader.ReadUInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version < 2019) //2019 down
{
m_ColorSpace = reader.ReadInt32();
}
if (version >= (2020, 2)) //2020.2 and up
{
var m_UsageMode = reader.ReadInt32();
}
var m_IsReadable = reader.ReadBoolean();
if (version > (2023, 2)) //2023.2 and up
{
var m_IgnoreMipmapLimit = reader.ReadBoolean();
reader.AlignStream();
var m_MipmapLimitGroupName = reader.ReadAlignedString();
}
else
{
reader.AlignStream();
}
var image_data_size = reader.ReadInt32();
if (image_data_size == 0 && version >= (5, 6)) //5.6 and up
{
m_StreamData = new StreamingInfo(reader);
}
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size)
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
TextureList = new List<Texture2D>();
}
public Texture2DArray(ObjectReader reader, byte[] type, JsonSerializerOptions jsonOptions) : base(reader)
{
var parsedTex2dArray = JsonSerializer.Deserialize<Texture2DArray>(type, jsonOptions);
m_Width = parsedTex2dArray.m_Width;
m_Height = parsedTex2dArray.m_Height;
m_Depth = parsedTex2dArray.m_Depth;
m_Format = parsedTex2dArray.m_Format;
m_MipCount = parsedTex2dArray.m_MipCount;
m_DataSize = parsedTex2dArray.m_DataSize;
m_TextureSettings = parsedTex2dArray.m_TextureSettings;
m_StreamData = parsedTex2dArray.m_StreamData;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2dArray.image_data.Offset, parsedTex2dArray.image_data.Size);
TextureList = new List<Texture2D>();
}
}
}

View File

@@ -0,0 +1,282 @@
namespace AssetStudio
{
public enum TextureFormat
{
/// <summary>
/// Alpha-only texture format, 8 bit integer.
/// </summary>
Alpha8 = 1,
/// <summary>
/// A 16 bits/pixel texture format. Texture stores color with an alpha channel.
/// </summary>
ARGB4444,
/// <summary>
/// Three channel (RGB) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGB24,
/// <summary>
/// Four channel (RGBA) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGBA32,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
ARGB32,
/// <summary>
/// </summary>
ARGBFloat,
/// <summary>
/// A 16 bit color texture format.
/// </summary>
RGB565,
/// <summary>
/// </summary>
BGR24,
/// <summary>
/// Single channel (R) texture format, 16 bit integer.
/// </summary>
R16,
/// <summary>
/// Compressed color texture format.
/// </summary>
DXT1,
/// <summary>
/// </summary>
DXT3,
/// <summary>
/// Compressed color with alpha channel texture format.
/// </summary>
DXT5,
/// <summary>
/// Color and alpha texture format, 4 bit per channel.
/// </summary>
RGBA4444,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
BGRA32,
/// <summary>
/// Scalar (R) texture format, 16 bit floating point.
/// </summary>
RHalf,
/// <summary>
/// Two color (RG) texture format, 16 bit floating point per channel.
/// </summary>
RGHalf,
/// <summary>
/// RGB color and alpha texture format, 16 bit floating point per channel.
/// </summary>
RGBAHalf,
/// <summary>
/// Scalar (R) texture format, 32 bit floating point.
/// </summary>
RFloat,
/// <summary>
/// Two color (RG) texture format, 32 bit floating point per channel.
/// </summary>
RGFloat,
/// <summary>
/// RGB color and alpha texture format, 32-bit floats per channel.
/// </summary>
RGBAFloat,
/// <summary>
/// A format that uses the YUV color space and is often used for video encoding or playback.
/// </summary>
YUY2,
/// <summary>
/// RGB HDR format, with 9 bit mantissa per channel and a 5 bit shared exponent.
/// </summary>
RGB9e5Float,
/// <summary>
/// </summary>
RGBFloat,
/// <summary>
/// HDR compressed color texture format.
/// </summary>
BC6H,
/// <summary>
/// High quality compressed color texture format.
/// </summary>
BC7,
/// <summary>
/// Compressed one channel (R) texture format.
/// </summary>
BC4,
/// <summary>
/// Compressed two-channel (RG) texture format.
/// </summary>
BC5,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT1Crunched,
/// <summary>
/// Compressed color with alpha channel texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT5Crunched,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB2,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA2,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB4,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA4,
/// <summary>
/// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4,
/// <summary>
/// ATC (ATITC) 4 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGB4,
/// <summary>
/// ATC (ATITC) 8 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGBA8,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed unsigned single-channel texture format.
/// </summary>
EAC_R = 41,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed signed single-channel texture format.
/// </summary>
EAC_R_SIGNED,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed unsigned dual-channel (RG) texture format.
/// </summary>
EAC_RG,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed signed dual-channel (RG) texture format.
/// </summary>
EAC_RG_SIGNED,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC2_RGB,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel RGB+1-bit alpha texture format.
/// </summary>
ETC2_RGBA1,
/// <summary>
/// ETC2 (GL ES 3.0) 8 bits/pixel compressed RGBA texture format.
/// </summary>
ETC2_RGBA8,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_12x12,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_12x12,
/// <summary>
/// ETC 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4_3DS,
/// <summary>
/// ETC 4 bits/pixel RGB + 4 bits/pixel Alpha compressed texture format.
/// </summary>
ETC_RGBA8_3DS,
/// <summary>
/// Two color (RG) texture format, 8-bits per channel.
/// </summary>
RG16,
/// <summary>
/// Single channel (R) texture format, 8 bit integer.
/// </summary>
R8,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
ETC_RGB4Crunched,
/// <summary>
/// Compressed color with alpha channel texture format using Crunch compression for smaller storage sizes.
/// </summary>
ETC2_RGBA8Crunched,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB(A) texture format.
/// </summary>
ASTC_HDR_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_12x12,
/// <summary>
/// Two channel (RG) texture format, 16-bits unsigned integer per channel.
/// </summary>
RG32,
/// <summary>
/// Three channel (RGB) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGB48,
/// <summary>
/// Four channel (RGBA) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGBA64,
}
}

View File

@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
@@ -10,7 +7,7 @@ namespace AssetStudio
public Quaternion m_LocalRotation;
public Vector3 m_LocalPosition;
public Vector3 m_LocalScale;
public PPtr<Transform>[] m_Children;
public List<PPtr<Transform>> m_Children;
public PPtr<Transform> m_Father;
public Transform(ObjectReader reader) : base(reader)
@@ -20,10 +17,10 @@ namespace AssetStudio
m_LocalScale = reader.ReadVector3();
int m_ChildrenCount = reader.ReadInt32();
m_Children = new PPtr<Transform>[m_ChildrenCount];
for (int i = 0; i < m_ChildrenCount; i++)
m_Children = new List<PPtr<Transform>>();
for (var i = 0; i < m_ChildrenCount; i++)
{
m_Children[i] = new PPtr<Transform>(reader);
m_Children.Add(new PPtr<Transform>(reader));
}
m_Father = new PPtr<Transform>(reader);
}

View File

@@ -34,7 +34,7 @@ namespace AssetStudio
var m_ProxyHeight = reader.ReadUInt32();
Width = reader.ReadUInt32();
Height = reader.ReadUInt32();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
if (version >= (2017, 2)) //2017.2 and up
{
var m_PixelAspecRatioNum = reader.ReadUInt32();
var m_PixelAspecRatioDen = reader.ReadUInt32();
@@ -46,18 +46,17 @@ namespace AssetStudio
reader.AlignStream();
var m_AudioSampleRate = reader.ReadUInt32Array();
var m_AudioLanguage = reader.ReadStringArray();
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
var m_VideoShadersSize = reader.ReadInt32();
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
for (int i = 0; i < m_VideoShadersSize; i++)
for (var i = 0; i < m_VideoShadersSize; i++)
{
m_VideoShaders[i] = new PPtr<Shader>(reader);
var m_VideoShaders = new PPtr<Shader>(reader);
}
}
m_ExternalResources = new StreamedResource(reader);
m_HasSplitAlpha = reader.ReadBoolean();
if (version[0] >= 2020) //2020.1 and up
if (version >= 2020) //2020.1 and up
{
var m_sRGB = reader.ReadBoolean();
}

View File

@@ -28,13 +28,22 @@ namespace AssetStudio
public static string Color(this string str, string ansiColor)
{
if (!ColorConsoleHelper.isAnsiCodesSupported)
{
return str;
}
return $"{ansiColor}{str}{Reset}";
}
public static string ColorIf(this string str, bool isTrue, string ansiColor, string defaultAnsiColor = null)
{
if (isTrue)
return str.Color(ansiColor);
if (defaultAnsiColor != null)
return str.Color(defaultAnsiColor);
return str;
}
public static void AnsiCodesTest()
{
Console.WriteLine("ANSI escape codes test");
@@ -45,5 +54,4 @@ namespace AssetStudio
Console.WriteLine("\u001b[34;1m E \u001b[35;1m F \u001b[36;1m G \u001b[37;1m H \u001b[0m");
}
}
}

View File

@@ -114,7 +114,10 @@ namespace AssetStudio
{1121, "m_PrefabInstance"},
{1138, "m_PrefabAsset"},
{1152, "FileSize"},
{1161, "Hash128"}
{1161, "Hash128"},
{1169, "RenderingLayerMask"},
{1188, "fixed_array"},
{1200, "EntityId"},
};
}
}

133
AssetStudio/CubismMoc.cs Normal file
View File

@@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace AssetStudio
{
public enum CubismSDKVersion : byte
{
V30 = 1,
V33,
V40,
V42,
V50
}
public sealed class CubismMoc : IDisposable
{
public CubismSDKVersion Version { get; }
public string VersionDescription { get; }
public float CanvasWidth { get; }
public float CanvasHeight { get; }
public float CentralPosX { get; }
public float CentralPosY { get; }
public float PixelPerUnit { get; }
public uint PartCount { get; }
public uint ParamCount { get; }
public HashSet<string> PartNames { get; }
public HashSet<string> ParamNames { get; }
private byte[] modelData;
private int modelDataSize;
private bool isBigEndian;
public CubismMoc(MonoBehaviour moc)
{
var reader = moc.reader;
reader.Reset();
reader.Position += 28; //PPtr<GameObject> m_GameObject, m_Enabled, PPtr<MonoScript>
reader.ReadAlignedString(); //m_Name
modelDataSize = (int)reader.ReadUInt32();
modelData = BigArrayPool<byte>.Shared.Rent(modelDataSize);
_ = reader.Read(modelData, 0, modelDataSize);
var sdkVer = modelData[4];
if (Enum.IsDefined(typeof(CubismSDKVersion), sdkVer))
{
Version = (CubismSDKVersion)sdkVer;
VersionDescription = ParseVersion();
}
else
{
var msg = $"Unknown SDK version ({sdkVer})";
VersionDescription = msg;
Version = 0;
Logger.Warning($"Live2D model \"{moc.m_Name}\": " + msg);
return;
}
isBigEndian = BitConverter.ToBoolean(modelData, 5);
var modelDataSpan = new ReadOnlySpan<byte>(modelData, 0, modelDataSize);
//offsets
var countInfoTableOffset = (int)modelDataSpan.ReadUInt32(64, isBigEndian);
var canvasInfoOffset = (int)modelDataSpan.ReadUInt32(68, isBigEndian);
var partIdsOffset = modelDataSpan.ReadUInt32(76, isBigEndian);
var parameterIdsOffset = modelDataSpan.ReadUInt32(264, isBigEndian);
//canvas
PixelPerUnit = modelDataSpan.ReadSingle(canvasInfoOffset, isBigEndian);
CentralPosX = modelDataSpan.ReadSingle(canvasInfoOffset + 4, isBigEndian);
CentralPosY = modelDataSpan.ReadSingle(canvasInfoOffset + 8, isBigEndian);
CanvasWidth = modelDataSpan.ReadSingle(canvasInfoOffset + 12, isBigEndian);
CanvasHeight = modelDataSpan.ReadSingle(canvasInfoOffset + 16, isBigEndian);
//model
PartCount = modelDataSpan.ReadUInt32(countInfoTableOffset, isBigEndian);
ParamCount = modelDataSpan.ReadUInt32(countInfoTableOffset + 20, isBigEndian);
PartNames = ReadMocStrings(modelDataSpan, (int)partIdsOffset, (int)PartCount);
ParamNames = ReadMocStrings(modelDataSpan, (int)parameterIdsOffset, (int)ParamCount);
}
public void SaveMoc3(string savePath)
{
if (!savePath.EndsWith(".moc3"))
savePath += ".moc3";
using (var file = File.OpenWrite(savePath))
{
file.Write(modelData, 0, modelDataSize);
}
}
private string ParseVersion()
{
switch (Version)
{
case CubismSDKVersion.V30: return "SDK3.0/Cubism3.0(3.2)";
case CubismSDKVersion.V33: return "SDK3.3/Cubism3.3";
case CubismSDKVersion.V40: return "SDK4.0/Cubism4.0";
case CubismSDKVersion.V42: return "SDK4.2/Cubism4.2";
case CubismSDKVersion.V50: return "SDK5.0/Cubism5.0";
default: return "";
}
}
private static HashSet<string> ReadMocStrings(ReadOnlySpan<byte> data, int index, int count)
{
const int strLen = 64;
var strHashSet = new HashSet<string>();
for (var i = 0; i < count; i++)
{
if (index + i * strLen <= data.Length)
{
var str = data.Slice(index + i * strLen, strLen).ReadStringToNull();
strHashSet.Add(str);
}
}
return strHashSet;
}
private void Dispose(bool disposing)
{
if (disposing)
{
BigArrayPool<byte>.Shared.Return(modelData, clearArray: true);
}
}
public void Dispose()
{
Dispose(true);
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
namespace AssetStudio
{
public class CubismModel
{
public string Name { get; set; }
public string Container { get; set; }
public MonoBehaviour CubismModelMono { get; set; }
public MonoBehaviour PhysicsController { get; set; }
public MonoBehaviour FadeController { get; set; }
public MonoBehaviour ExpressionController { get; set; }
public List<MonoBehaviour> RenderTextureList { get; set; }
public List<MonoBehaviour> ParamDisplayInfoList { get; set; }
public List<MonoBehaviour> PartDisplayInfoList { get; set; }
public List<MonoBehaviour> PosePartList { get; set; }
public List<AnimationClip> ClipMotionList { get; set; }
public GameObject ModelGameObject { get; set; }
public CubismModel(GameObject m_GameObject)
{
Name = m_GameObject.m_Name;
ModelGameObject = m_GameObject;
RenderTextureList = new List<MonoBehaviour>();
ParamDisplayInfoList = new List<MonoBehaviour>();
PartDisplayInfoList = new List<MonoBehaviour>();
PosePartList = new List<MonoBehaviour>();
ClipMotionList = new List<AnimationClip>();
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Buffers.Binary;
namespace AssetStudio.CustomOptions.Asmo
{
public class OptionsFile
{
private static readonly byte[] OptionsFileSign = new byte[] { 0x41, 0x53, 0x4D, 0x4F }; //ASMO
public static readonly string Extension = ".asmo";
public byte[] Signature { get; private set; } = OptionsFileSign;
public short Version { get; private set; } = 1;
public short Reserved { get; set; }
public uint DataCrc { get; set; }
public int DataSize { get; set; }
public byte[] Data { get; set; }
public OptionsFile() { }
public OptionsFile(EndianBinaryReader reader)
{
Signature = reader.ReadBytes(4);
Version = reader.ReadInt16();
Reserved = reader.ReadInt16();
DataCrc = reader.ReadUInt32();
DataSize = reader.ReadInt32();
CheckHeader(reader.BaseStream.Length);
Data = reader.ReadBytes(DataSize);
}
public void CheckHeader(long fileLength)
{
if (!Signature.AsSpan().SequenceEqual(OptionsFileSign))
throw new NotSupportedException("Incorrect options file signature.");
if (Version != 1)
throw new NotSupportedException("Incorrect options file version.");
if (DataSize <= 0 || DataSize > fileLength)
throw new NotSupportedException("Incorrect data size.");
}
public byte[] ToByteArray()
{
var buffer = new byte[16 + DataSize];
OptionsFileSign.AsSpan().CopyTo(buffer);
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(4), Version);
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(6), Reserved);
BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(8), DataCrc);
BinaryPrimitives.WriteInt32BigEndian(buffer.AsSpan(12), DataSize);
Data.AsSpan().CopyTo(buffer.AsSpan(16));
return buffer;
}
}
}

View File

@@ -0,0 +1,40 @@
namespace AssetStudio.CustomOptions
{
public class CustomBundleOptions
{
private CompressionType _customBlockCompression = CompressionType.Auto;
private CompressionType _customBlockInfoCompression = CompressionType.Auto;
private bool _decompressToDisk;
public ImportOptions Options;
public CompressionType CustomBlockCompression
{
get => _customBlockCompression;
set => _customBlockCompression = SetOption(nameof(CustomBlockCompression), value);
}
public CompressionType CustomBlockInfoCompression
{
get => _customBlockInfoCompression;
set => _customBlockInfoCompression = SetOption(nameof(CustomBlockInfoCompression), value);
}
public bool DecompressToDisk
{
get => _decompressToDisk;
set => _decompressToDisk = SetOption(nameof(DecompressToDisk), value);
}
public CustomBundleOptions() { }
public CustomBundleOptions(ImportOptions importOptions)
{
Options = importOptions;
}
private static T SetOption<T>(string option, T value)
{
Logger.Info($"- {option}: {value}");
return value;
}
}
}

View File

@@ -0,0 +1,94 @@
using AssetStudio.CustomOptions.Asmo;
using SevenZip;
using System;
using System.IO;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio.CustomOptions
{
public class ImportOptions
{
private static JsonSerializerOptions jsonOptions;
private static string fileName = "ImportOptions";
private UnityVersion _customUnityVer;
public CustomBundleOptions BundleOptions { get; set; }
public UnityVersion CustomUnityVersion { get => _customUnityVer; set => SetUnityVersion(value); }
static ImportOptions()
{
jsonOptions = new JsonSerializerOptions
{
ReferenceHandler = ReferenceHandler.Preserve,
IncludeFields = true,
};
}
public ImportOptions()
{
BundleOptions = new CustomBundleOptions(this);
CustomUnityVersion = null;
}
public static ImportOptions FromOptionsFile(OptionsFile optionsFile)
{
if (optionsFile.Reserved != 0)
{
Logger.Debug("Skipped. Not an import options file.");
return null;
}
var utf8Bytes = Convert.FromBase64String(Encoding.ASCII.GetString(optionsFile.Data));
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
if (optionsFile.DataCrc != dataCrc)
throw new IOException("Options file data is corrupted.");
return JsonSerializer.Deserialize<ImportOptions>(utf8Bytes, jsonOptions);
}
public void SaveToFile(string outputFolder)
{
var utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, jsonOptions);
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
var base64String = Convert.ToBase64String(utf8Bytes);
var optionsFile = new OptionsFile
{
DataCrc = dataCrc,
DataSize = base64String.Length,
Data = Encoding.ASCII.GetBytes(base64String),
};
var unityVer = _customUnityVer != null
? $"_{_customUnityVer}"
: "";
var path = Path.Combine(outputFolder, $"{fileName}{unityVer}{OptionsFile.Extension}");
File.WriteAllBytes(path, optionsFile.ToByteArray());
Logger.Info($"Options file saved to \"{path}\"");
}
private void SetUnityVersion(UnityVersion value)
{
if (_customUnityVer == value)
return;
if (value == null)
{
_customUnityVer = null;
Logger.Info("- Specified Unity version: None");
return;
}
if (string.IsNullOrEmpty(value.BuildType))
{
throw new NotSupportedException("Specified Unity version is not in a correct format.\n" +
"Specify full Unity version, including letters at the end.\n" +
"Example: 2017.4.39f1");
}
_customUnityVer = value;
Logger.Info($"- Specified Unity version: {_customUnityVer}");
}
}
}

View File

@@ -82,12 +82,13 @@ namespace AssetStudio
return base.ReadUInt64();
}
#if NETFRAMEWORK
public override float ReadSingle()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
Array.Reverse(buffer, 0, 4);
buffer.AsSpan(0, 4).Reverse();
return BitConverter.ToSingle(buffer, 0);
}
return base.ReadSingle();
@@ -98,10 +99,31 @@ namespace AssetStudio
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
Array.Reverse(buffer);
buffer.AsSpan().Reverse();
return BitConverter.ToDouble(buffer, 0);
}
return base.ReadDouble();
}
#else
public override float ReadSingle()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 4);
return BinaryPrimitives.ReadSingleBigEndian(buffer);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (Endian == EndianType.BigEndian)
{
Read(buffer, 0, 8);
return BinaryPrimitives.ReadDoubleBigEndian(buffer);
}
return base.ReadDouble();
}
#endif
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Buffers.Binary;
using System.Text;
namespace AssetStudio
{
public static class EndianSpanReader
{
public static uint ReadUInt32(this Span<byte> data, int start, bool isBigEndian)
{
return ReadUInt32((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static uint ReadUInt32(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start));
}
public static long ReadUInt16(this Span<byte> data, int start, bool isBigEndian)
{
return ReadUInt16((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static uint ReadUInt16(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt16BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(start));
}
public static long ReadInt64(this Span<byte> data, int start, bool isBigEndian)
{
return ReadInt64((ReadOnlySpan<byte>)data, start, isBigEndian);
}
public static long ReadInt64(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start))
: BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start));
}
public static float ReadSingle(this Span<byte> data, int start, bool isBigEndian)
{
return ReadSingle((ReadOnlySpan<byte>)data, start, isBigEndian);
}
#if NETFRAMEWORK
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
var bytes = data.Slice(start, 4).ToArray();
if ((isBigEndian && BitConverter.IsLittleEndian) || (!isBigEndian && !BitConverter.IsLittleEndian))
bytes.AsSpan().Reverse();
return BitConverter.ToSingle(bytes, 0);
}
#else
public static float ReadSingle(this ReadOnlySpan<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadSingleBigEndian(data[start..])
: BinaryPrimitives.ReadSingleLittleEndian(data[start..]);
}
#endif
public static string ReadStringToNull(this Span<byte> data, int maxLength = 32767)
{
return ReadStringToNull((ReadOnlySpan<byte>)data, maxLength);
}
public static string ReadStringToNull(this ReadOnlySpan<byte> data, int maxLength = 32767)
{
Span<byte> bytes = stackalloc byte[maxLength];
var count = 0;
while (count != data.Length && count < maxLength)
{
var b = data[count];
if (b == 0)
{
break;
}
bytes[count] = b;
count++;
}
bytes = bytes.Slice(0, count);
#if NETFRAMEWORK
return Encoding.UTF8.GetString(bytes.ToArray());
#else
return Encoding.UTF8.GetString(bytes);
#endif
}
}
}

View File

@@ -1,18 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace AssetStudio
{
public static class BinaryReaderExtensions
{
public static void AlignStream(this BinaryReader reader)
{
reader.AlignStream(4);
}
public static void AlignStream(this BinaryReader reader, int alignment)
public static void AlignStream(this BinaryReader reader, int alignment = 4)
{
var pos = reader.BaseStream.Position;
var mod = pos % alignment;
@@ -25,11 +21,13 @@ namespace AssetStudio
public static string ReadAlignedString(this BinaryReader reader)
{
var length = reader.ReadInt32();
if (length > 0 && length <= reader.BaseStream.Length - reader.BaseStream.Position)
if (length > reader.BaseStream.Length - reader.BaseStream.Position)
throw new EndOfStreamException();
if (length > 0)
{
var stringData = reader.ReadBytes(length);
var result = Encoding.UTF8.GetString(stringData);
reader.AlignStream(4);
reader.AlignStream();
return result;
}
return "";
@@ -40,7 +38,7 @@ namespace AssetStudio
if (encoding?.CodePage == 1200) //Unicode (UTF-16LE)
return reader.ReadUnicodeStringToNull(maxLength * 2);
var bytes = new List<byte>();
Span<byte> bytes = stackalloc byte[maxLength];
var count = 0;
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
{
@@ -49,10 +47,15 @@ namespace AssetStudio
{
break;
}
bytes.Add(b);
bytes[count] = b;
count++;
}
bytes = bytes.Slice(0, count);
#if NETFRAMEWORK
return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray());
#else
return encoding?.GetString(bytes) ?? Encoding.UTF8.GetString(bytes);
#endif
}
private static string ReadUnicodeStringToNull(this BinaryReader reader, int maxLength)
@@ -97,24 +100,22 @@ namespace AssetStudio
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
}
public static Matrix4x4 ReadMatrix(this BinaryReader reader)
private static T[] ReadArray<T>(BinaryReader reader, int byteLen) where T : struct
{
return new Matrix4x4(reader.ReadSingleArray(16));
}
if (byteLen < 0)
throw new ArgumentOutOfRangeException(nameof(byteLen));
if (reader.BaseStream.Position + byteLen > reader.BaseStream.Length)
throw new EndOfStreamException();
private static T[] ReadArray<T>(Func<T> del, int length)
{
var array = new T[length];
for (int i = 0; i < length; i++)
{
array[i] = del();
}
return array;
var bytes = reader.ReadBytes(byteLen);
var span = MemoryMarshal.Cast<byte, T>(bytes);
return span.ToArray();
}
public static bool[] ReadBooleanArray(this BinaryReader reader)
{
return ReadArray(reader.ReadBoolean, reader.ReadInt32());
return ReadArray<bool>(reader, reader.ReadInt32());
}
public static byte[] ReadUInt8Array(this BinaryReader reader)
@@ -124,62 +125,65 @@ namespace AssetStudio
public static ushort[] ReadUInt16Array(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
return ReadArray<ushort>(reader, reader.ReadInt32() * 2);
}
public static int[] ReadInt32Array(this BinaryReader reader)
public static int[] ReadInt32Array(this BinaryReader reader, int length = -1)
{
return ReadArray(reader.ReadInt32, reader.ReadInt32());
if (length == -1)
length = reader.ReadInt32();
return ReadArray<int>(reader, length * 4);
}
public static int[] ReadInt32Array(this BinaryReader reader, int length)
public static uint[] ReadUInt32Array(this BinaryReader reader, int length = -1)
{
return ReadArray(reader.ReadInt32, length);
}
public static uint[] ReadUInt32Array(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt32, reader.ReadInt32());
if (length == -1)
length = reader.ReadInt32();
return ReadArray<uint>(reader, length * 4);
}
public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt32Array, reader.ReadInt32());
var length = reader.ReadInt32();
var list = new List<uint[]>();
for (var i = 0; i < length; i++)
{
list.Add(ReadArray<uint>(reader, reader.ReadInt32() * 4));
}
return list.ToArray();
}
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
public static float[] ReadSingleArray(this BinaryReader reader, int length = -1)
{
return ReadArray(reader.ReadUInt32, length);
}
public static float[] ReadSingleArray(this BinaryReader reader)
{
return ReadArray(reader.ReadSingle, reader.ReadInt32());
}
public static float[] ReadSingleArray(this BinaryReader reader, int length)
{
return ReadArray(reader.ReadSingle, length);
if (length == -1)
length = reader.ReadInt32();
return ReadArray<float>(reader, length * 4);
}
public static string[] ReadStringArray(this BinaryReader reader)
{
return ReadArray(reader.ReadAlignedString, reader.ReadInt32());
var length = reader.ReadInt32();
var list = new List<string>();
for (var i = 0; i < length; i++)
{
list.Add(reader.ReadAlignedString());
}
return list.ToArray();
}
public static Vector2[] ReadVector2Array(this BinaryReader reader)
{
return ReadArray(reader.ReadVector2, reader.ReadInt32());
return ReadArray<Vector2>(reader, reader.ReadInt32() * 8);
}
public static Vector4[] ReadVector4Array(this BinaryReader reader)
{
return ReadArray(reader.ReadVector4, reader.ReadInt32());
return ReadArray<Vector4>(reader, reader.ReadInt32() * 16);
}
public static Matrix4x4[] ReadMatrixArray(this BinaryReader reader)
{
return ReadArray(reader.ReadMatrix, reader.ReadInt32());
return ReadArray<Matrix4x4>(reader, reader.ReadInt32() * 64);
}
}
}

View File

@@ -1,5 +1,5 @@
using System.IO;
using System.Linq;
using System;
using System.IO;
namespace AssetStudio
{
@@ -13,6 +13,9 @@ namespace AssetStudio
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
private static readonly byte[] unityFsMagic = {0x55, 0x6E, 0x69, 0x74, 0x79, 0x46, 0x53, 0x00};
private static readonly int headerBuffLen = 1152;
private static byte[] headerBuff = new byte[headerBuffLen];
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
@@ -25,78 +28,117 @@ namespace AssetStudio
private FileType CheckFileType()
{
var signature = this.ReadStringToNull(20);
var buff = headerBuff.AsSpan();
buff.Clear();
var dataLen = Read(headerBuff, 0, headerBuffLen);
Position = 0;
var signature = buff.ReadStringToNull(20);
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
CheckBundleDataOffset(buff);
return FileType.BundleFile;
case "UnityWebData1.0":
case "TuanjieWebData1.0":
return FileType.WebFile;
default:
{
byte[] magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
var magic = Span<byte>.Empty;
magic = dataLen > 2 ? buff.Slice(0, 2) : magic;
if (magic.SequenceEqual(gzipMagic))
{
return FileType.GZipFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (brotliMagic.SequenceEqual(magic))
magic = dataLen > 38 ? buff.Slice(32, 6) : magic;
if (magic.SequenceEqual(brotliMagic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile())
if (IsSerializedFile(buff))
{
return FileType.AssetsFile;
}
magic = ReadBytes(4);
Position = 0;
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
magic = dataLen > 4 ? buff.Slice(0, 4): magic;
if (magic.SequenceEqual(zipMagic) || magic.SequenceEqual(zipSpannedMagic))
{
return FileType.ZipFile;
}
if (CheckBundleDataOffset(buff))
{
return FileType.BundleFile;
}
return FileType.ResourceFile;
}
}
}
private bool IsSerializedFile()
private bool IsSerializedFile(ReadOnlySpan<byte> buff)
{
var fileSize = BaseStream.Length;
if (fileSize < 20)
{
return false;
}
var m_MetadataSize = ReadUInt32();
long m_FileSize = ReadUInt32();
var m_Version = ReadUInt32();
long m_DataOffset = ReadUInt32();
var m_Endianess = ReadByte();
var m_Reserved = ReadBytes(3);
var isBigEndian = Endian == EndianType.BigEndian;
//var m_MetadataSize = buff.ReadUInt32(0, isBigEndian);
long m_FileSize = buff.ReadUInt32(4, isBigEndian);
var m_Version = buff.ReadUInt32(8, isBigEndian);
long m_DataOffset = buff.ReadUInt32(12, isBigEndian);
//var m_Endianess = buff[16];
//var m_Reserved = buff.Slice(17, 3);
if (m_Version >= 22)
{
if (fileSize < 48)
{
Position = 0;
return false;
}
m_MetadataSize = ReadUInt32();
m_FileSize = ReadInt64();
m_DataOffset = ReadInt64();
//m_MetadataSize = buff.ReadUInt32(20, isBigEndian);
m_FileSize = buff.ReadInt64(24, isBigEndian);
m_DataOffset = buff.ReadInt64(32, isBigEndian);
}
Position = 0;
if (m_FileSize != fileSize)
if (m_FileSize != fileSize || m_DataOffset > fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{
return false;
return true;
}
private bool CheckBundleDataOffset(ReadOnlySpan<byte> buff)
{
var lastOffset = buff.LastIndexOf(unityFsMagic);
if (lastOffset <= 0)
return false;
var firstOffset = buff.IndexOf(unityFsMagic);
if (firstOffset == lastOffset || lastOffset - firstOffset < 200)
{
Position = lastOffset;
return true;
}
var pos = firstOffset + 12;
pos += buff.Slice(pos).ReadStringToNull().Length + 1;
pos += buff.Slice(pos).ReadStringToNull().Length + 1;
var bundleSize = buff.ReadInt64(pos, Endian == EndianType.BigEndian);
if (bundleSize > 200 && firstOffset + bundleSize < lastOffset)
{
Position = firstOffset;
return true;
}
Position = lastOffset;
return true;
}
}

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
namespace AssetStudio
{
public enum FileType
{

View File

@@ -68,13 +68,15 @@ namespace AssetStudio
}
catch (System.Exception e)
{
Logger.Warning($"Error while decompressing gzip file {reader.FullPath}\r\n{e}");
Logger.Warning($"Error while decompressing Gzip file {reader.FullPath}\n{e}");
reader.Dispose();
return null;
}
}
public static FileReader DecompressBrotli(FileReader reader)
{
try
{
using (reader)
{
@@ -87,5 +89,12 @@ namespace AssetStudio
return new FileReader(reader.FullPath, stream);
}
}
catch (System.Exception e)
{
Logger.Warning($"Error while decompressing Brotli file {reader.FullPath}\n{e}");
reader.Dispose();
return null;
}
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public static partial class JsonConverterHelper
{
public class ByteArrayConverter : JsonConverter<byte[]>
{
public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.TokenType == JsonTokenType.StartArray
? JsonSerializer.Deserialize<List<byte>>(ref reader).ToArray() //JsonArray to ByteArray
: JsonSerializer.Deserialize<byte[]>(ref reader);
}
public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options)
{
writer.WriteBase64StringValue(value);
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public static partial class JsonConverterHelper
{
public class FloatConverter : JsonConverter<float>
{
public override float Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return JsonSerializer.Deserialize<float>(ref reader, new JsonSerializerOptions
{
NumberHandling = options.NumberHandling
});
}
public override void Write(Utf8JsonWriter writer, float value, JsonSerializerOptions options)
{
if (float.IsNaN(value) || float.IsInfinity(value))
{
if (options.NumberHandling == JsonNumberHandling.AllowNamedFloatingPointLiterals)
{
writer.WriteStringValue($"{value.ToString(CultureInfo.InvariantCulture)}");
}
else
{
writer.WriteStringValue(JsonSerializer.Serialize(value));
}
}
else
{
writer.WriteNumberValue((decimal)value + 0.0m);
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public static partial class JsonConverterHelper
{
public class KVPConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
return false;
var generic = typeToConvert.GetGenericTypeDefinition();
return generic == typeof(KeyValuePair<,>);
}
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
{
var kvpArgs = type.GetGenericArguments();
return (JsonConverter)Activator.CreateInstance(typeof(KVPConverter<,>).MakeGenericType(kvpArgs));
}
}
private class KVPConverter<TKey, TValue> : JsonConverter<KeyValuePair<TKey, TValue>>
{
public override KeyValuePair<TKey, TValue> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
//startKvpObject
reader.Read(); //propName
reader.Read(); //keyType
var key = reader.TokenType == JsonTokenType.StartObject
? JsonSerializer.Deserialize<Dictionary<string, TKey>>(ref reader).Values.First()
: JsonSerializer.Deserialize<TKey>(ref reader);
reader.Read(); //propName
reader.Read(); //startObject
var value = JsonSerializer.Deserialize<TValue>(ref reader, options);
reader.Read(); //endKvpObject
return new KeyValuePair<TKey, TValue>(key, value);
}
public override void Write(Utf8JsonWriter writer, KeyValuePair<TKey, TValue> value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
}

View File

@@ -0,0 +1,45 @@
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public static partial class JsonConverterHelper
{
public static SerializedFile AssetsFile { get; set; }
public class PPtrConverter : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (!typeToConvert.IsGenericType)
return false;
var generic = typeToConvert.GetGenericTypeDefinition();
return generic == typeof(PPtr<>);
}
public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options)
{
var elementType = type.GetGenericArguments()[0];
var converter = (JsonConverter)Activator.CreateInstance(typeof(PPtrConverter<>).MakeGenericType(elementType));
return converter;
}
}
private class PPtrConverter<T> : JsonConverter<PPtr<T>> where T : Object
{
public override PPtr<T> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var pptrObj = JsonSerializer.Deserialize<PPtr<T>>(ref reader, new JsonSerializerOptions { IncludeFields = true });
pptrObj.AssetsFile = AssetsFile;
return pptrObj;
}
public override void Write(Utf8JsonWriter writer, PPtr<T> value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
namespace AssetStudio
{
public static partial class JsonConverterHelper
{
public class RenderDataMapConverter : JsonConverter<Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>>
{
public override Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dataArray = JsonSerializer.Deserialize<KeyValuePair<JsonObject, SpriteAtlasData>[]>(ref reader, options);
var renderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>(dataArray.Length);
foreach (var kvp in dataArray)
{
var jsonFirst = kvp.Key["first"];
var first = jsonFirst.Deserialize<GUID>(options).Convert();
var second = (long) kvp.Key["second"];
renderDataMap.Add(new KeyValuePair<Guid, long>(first, second), kvp.Value);
}
return renderDataMap;
}
public override void Write(Utf8JsonWriter writer, Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> value, JsonSerializerOptions options)
{
var jsonDict = new Dictionary<string, SpriteAtlasData>();
foreach (var kv in value)
{
var strKey = $"{kv.Key.Key}, {kv.Key.Value}";
jsonDict.Add(strKey, kv.Value);
}
var strValue = JsonSerializer.SerializeToUtf8Bytes(jsonDict, options);
writer.WriteRawValue(strValue);
}
}
private class GUID
{
[JsonPropertyName("data[0]")] public uint data0 { get; set; }
[JsonPropertyName("data[1]")] public uint data1 { get; set; }
[JsonPropertyName("data[2]")] public uint data2 { get; set; }
[JsonPropertyName("data[3]")] public uint data3 { get; set; }
public Guid Convert()
{
var guidBytes = new byte[16];
BitConverter.GetBytes(data0).CopyTo(guidBytes, 0);
BitConverter.GetBytes(data1).CopyTo(guidBytes, 4);
BitConverter.GetBytes(data2).CopyTo(guidBytes, 8);
BitConverter.GetBytes(data3).CopyTo(guidBytes, 12);
return new Guid(guidBytes);
}
}
}
}

18
AssetStudio/Math/Clamp.cs Normal file
View File

@@ -0,0 +1,18 @@
using System;
using System.Runtime.CompilerServices;
namespace AssetStudio
{
public static partial class MathHelper
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Clamp(float value, float minValue, float maxValue)
{
#if NETFRAMEWORK
return Math.Max(minValue, Math.Min(value, maxValue));
#else
return Math.Clamp(value, minValue, maxValue);
#endif
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Diagnostics;
using System.Globalization;
#if NETFRAMEWORK
namespace AssetStudio
{
/// <summary>
@@ -35,27 +36,27 @@ namespace AssetStudio
/// <summary>
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
/// </summary>
public static readonly Half Epsilon = Half.ToHalf(0x0001);
public static readonly Half Epsilon = HalfHelper.ToHalf(0x0001);
/// <summary>
/// Represents the largest possible value of System.Half. This field is constant.
/// </summary>
public static readonly Half MaxValue = Half.ToHalf(0x7bff);
public static readonly Half MaxValue = HalfHelper.ToHalf(0x7bff);
/// <summary>
/// Represents the smallest possible value of System.Half. This field is constant.
/// </summary>
public static readonly Half MinValue = Half.ToHalf(0xfbff);
public static readonly Half MinValue = HalfHelper.ToHalf(0xfbff);
/// <summary>
/// Represents not a number (NaN). This field is constant.
/// </summary>
public static readonly Half NaN = Half.ToHalf(0xfe00);
public static readonly Half NaN = HalfHelper.ToHalf(0xfe00);
/// <summary>
/// Represents negative infinity. This field is constant.
/// </summary>
public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);
public static readonly Half NegativeInfinity = HalfHelper.ToHalf(0xfc00);
/// <summary>
/// Represents positive infinity. This field is constant.
/// </summary>
public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);
public static readonly Half PositiveInfinity = HalfHelper.ToHalf(0x7c00);
#endregion
#region Constructors
@@ -63,7 +64,7 @@ namespace AssetStudio
/// Initializes a new instance of System.Half to the value of the specified single-precision floating-point number.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(float value) { this = HalfHelper.SingleToHalf(value); }
public Half(float value) { this = HalfHelper.ToHalf(value); }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
/// </summary>
@@ -314,7 +315,7 @@ namespace AssetStudio
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A single-precision floating-point number that represents the converted System.Half.</returns>
public static implicit operator float(Half value) { return (float)HalfHelper.HalfToSingle(value); }
public static implicit operator float(Half value) { return value.ToSingle(); }
/// <summary>
/// Converts a System.Half to a double-precision floating-point number.
/// </summary>
@@ -508,32 +509,6 @@ namespace AssetStudio
{
return value.value;
}
/// <summary>
/// Returns a half-precision floating point number converted from two bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 1, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception>
public static Half ToHalf(byte[] value, int startIndex)
{
return Half.ToHalf((ushort)BitConverter.ToInt16(value, startIndex));
}
/// <summary>
/// Returns a half-precision floating point number converted from its binary representation.
/// </summary>
/// <param name="bits">Binary representation of System.Half value</param>
/// <returns>A half-precision floating point number formed by its binary representation.</returns>
public static Half ToHalf(ushort bits)
{
return new Half { value = bits };
}
/// <summary>
/// Returns a value indicating the sign of a half-precision floating-point number.
@@ -886,3 +861,4 @@ namespace AssetStudio
#endregion
}
}
#endif

View File

@@ -1,18 +1,32 @@
using System;
using System.Buffers.Binary;
using System.Runtime.InteropServices;
namespace AssetStudio
{
#if NET
public static class HalfHelper
{
public static Half ToHalf(ushort bits)
{
return (Half)bits;
}
public static Half ToHalf(ReadOnlySpan<byte> bytes, int startIndex)
{
return BinaryPrimitives.ReadHalfLittleEndian(bytes[startIndex..]);
}
}
#else
/// <summary>
/// Helper class for Half conversions and some low level operations.
/// This class is internally used in the Half class.
/// </summary>
/// <remarks>
/// References:
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
/// </remarks>
[ComVisible(false)]
internal static class HalfHelper
public static class HalfHelper
{
private static uint[] mantissaTable = GenerateMantissaTable();
private static uint[] exponentTable = GenerateExponentTable();
@@ -169,27 +183,54 @@ namespace AssetStudio
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return Half.ToHalf(result);
}*/
public static float HalfToSingle(Half half)
/// <summary>
/// Returns a half-precision floating point number converted from two bytes
/// at a specified position in a byte array.
/// </summary>
/// <param name="value">An array of bytes.</param>
/// <param name="startIndex">The starting position within value.</param>
/// <returns>A half-precision floating point number formed by two bytes beginning at startIndex.</returns>
/// <exception cref="System.ArgumentException">
/// startIndex is greater than or equal to the length of value minus 1, and is
/// less than or equal to the length of value minus 1.
/// </exception>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">startIndex is less than zero or greater than the length of value minus 1.</exception>
public static Half ToHalf(ReadOnlySpan<byte> value, int startIndex)
{
return ToHalf((ushort)BinaryPrimitives.ReadInt16LittleEndian(value.Slice(startIndex)));
}
/// <summary>
/// Returns a half-precision floating point number converted from its binary representation.
/// </summary>
/// <param name="bits">Binary representation of System.Half value</param>
/// <returns>A half-precision floating point number formed by its binary representation.</returns>
public static Half ToHalf(ushort bits)
{
return new Half { value = bits };
}
public static Half ToHalf(float single)
{
byte[] singleBytes = BitConverter.GetBytes(single);
uint value = BitConverter.ToUInt32(singleBytes, 0);
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return ToHalf(result);
}
public static float ToSingle(this Half half)
{
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
byte[] uintBytes = BitConverter.GetBytes(result);
return BitConverter.ToSingle(uintBytes, 0);
}
public static Half SingleToHalf(float single)
{
byte[] singleBytes = BitConverter.GetBytes(single);
uint value = BitConverter.ToUInt32(singleBytes, 0);
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return Half.ToHalf(result);
}
public static Half Negate(Half half)
{
return Half.ToHalf((ushort)(half.value ^ 0x8000));
return ToHalf((ushort)(half.value ^ 0x8000));
}
public static Half Abs(Half half)
{
return Half.ToHalf((ushort)(half.value & 0x7fff));
return ToHalf((ushort)(half.value & 0x7fff));
}
public static bool IsNaN(Half half)
@@ -209,4 +250,5 @@ namespace AssetStudio
return (half.value == 0xfc00);
}
}
#endif
}

View File

@@ -26,9 +26,9 @@ namespace AssetStudio
public float M23;
public float M33;
public Matrix4x4(float[] values)
public Matrix4x4(Span<float> values)
{
if (values == null)
if (values.IsEmpty)
throw new ArgumentNullException(nameof(values));
if (values.Length != 16)
throw new ArgumentOutOfRangeException(nameof(values), "There must be sixteen and only sixteen input values for Matrix.");

View File

@@ -45,9 +45,9 @@ namespace AssetStudio
public override bool Equals(object other)
{
if (!(other is Vector2))
if (!(other is Vector2 vector2))
return false;
return Equals((Vector2)other);
return Equals(vector2);
}
public bool Equals(Vector2 other)
@@ -73,7 +73,7 @@ namespace AssetStudio
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
return MathF.Sqrt(LengthSquared());
}
public float LengthSquared()

View File

@@ -49,9 +49,9 @@ namespace AssetStudio
public override bool Equals(object other)
{
if (!(other is Vector3))
if (!(other is Vector3 vector3))
return false;
return Equals((Vector3)other);
return Equals(vector3);
}
public bool Equals(Vector3 other)
@@ -79,7 +79,7 @@ namespace AssetStudio
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
return MathF.Sqrt(LengthSquared());
}
public float LengthSquared()

View File

@@ -61,9 +61,9 @@ namespace AssetStudio
public override bool Equals(object other)
{
if (!(other is Vector4))
if (!(other is Vector4 vector4))
return false;
return Equals((Vector4)other);
return Equals(vector4);
}
public bool Equals(Vector4 other)
@@ -93,7 +93,7 @@ namespace AssetStudio
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
return MathF.Sqrt(LengthSquared());
}
public float LengthSquared()

View File

@@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudio
{
@@ -12,13 +9,15 @@ namespace AssetStudio
public long m_PathID;
public long byteStart;
public uint byteSize;
public int classID;
public ClassIDType type;
public SerializedType serializedType;
public BuildTarget platform;
public SerializedFileFormatVersion m_Version;
public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType;
public UnityVersion version => assetsFile.version;
public long Remaining => byteStart + byteSize - Position;
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
{
@@ -26,6 +25,7 @@ namespace AssetStudio
m_PathID = objectInfo.m_PathID;
byteStart = objectInfo.byteStart;
byteSize = objectInfo.byteSize;
classID = objectInfo.classID;
if (Enum.IsDefined(typeof(ClassIDType), objectInfo.classID))
{
type = (ClassIDType)objectInfo.classID;
@@ -39,6 +39,12 @@ namespace AssetStudio
m_Version = assetsFile.header.m_Version;
}
public void ThrowIfTooLarge(float val)
{
if (val < 0 || val > Remaining)
throw new EndOfStreamException();
}
public void Reset()
{
Position = byteStart;

102
AssetStudio/OffsetStream.cs Normal file
View File

@@ -0,0 +1,102 @@
using System.IO;
namespace AssetStudio
{
public class OffsetStream : Stream
{
private readonly Stream _baseStream;
private readonly long _length;
private long _offset;
public override bool CanRead => _baseStream.CanRead;
public override bool CanSeek => _baseStream.CanSeek;
public override bool CanWrite => false;
public override long Length => _length > 0
? _length
: _baseStream.Length - _offset;
public override long Position
{
get => _baseStream.Position - _offset;
set => Seek(value, SeekOrigin.Begin);
}
public long BasePosition => _baseStream.Position;
public long Offset
{
get => _offset;
set
{
if (value < 0 || value > _baseStream.Length)
{
throw new IOException($"{nameof(Offset)} is out of stream bound");
}
_offset = value;
Seek(0, SeekOrigin.Begin);
}
}
public OffsetStream(FileReader reader)
{
_baseStream = reader.BaseStream;
Offset = reader.Position;
}
public OffsetStream(Stream stream, long offset, long length)
{
_baseStream = stream;
_length = length;
Offset = offset;
}
public override void Flush() { }
public override int Read(byte[] buffer, int offset, int count)
{
return _baseStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
if (offset > _baseStream.Length)
{
throw new IOException("Unable to seek beyond stream bound");
}
switch (origin)
{
case SeekOrigin.Begin:
_baseStream.Seek(offset + _offset, SeekOrigin.Begin);
break;
case SeekOrigin.Current:
_baseStream.Seek(offset + Position, SeekOrigin.Begin);
break;
case SeekOrigin.End:
_baseStream.Seek(offset + _baseStream.Length, SeekOrigin.Begin);
break;
}
return Position;
}
public override void SetLength(long value)
{
throw new System.NotImplementedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new System.NotImplementedException();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_baseStream.Dispose();
}
base.Dispose(disposing);
}
}
}

View File

@@ -4,28 +4,58 @@ namespace AssetStudio
{
public static class Progress
{
public static IProgress<int> Default = new Progress<int>();
private static int preValue;
private static readonly int InstanceCount = 2;
private static readonly IProgress<int>[] Instances;
private static readonly int[] PreValues;
public static void Reset()
static Progress()
{
preValue = 0;
Default.Report(0);
Instances = new IProgress<int>[InstanceCount];
for (var i = 0; i < InstanceCount; i++)
{
Instances[i] = new Progress<int>();
}
public static void Report(int current, int total)
PreValues = new int[InstanceCount];
}
public static int MaxCount => InstanceCount;
public static IProgress<int> Default //alias
{
get => Instances[0];
set => SetInstance(0, value);
}
public static void Reset(int index = 0)
{
PreValues[index] = 0;
Instances[index].Report(0);
}
public static void Report(int current, int total, int index = 0)
{
var value = (int)(current * 100f / total);
Report(value);
_Report(value, index);
}
private static void Report(int value)
private static void _Report(int value, int index)
{
if (value > preValue)
if (value > PreValues[index])
{
preValue = value;
Default.Report(value);
PreValues[index] = value;
Instances[index].Report(value);
}
}
public static void SetInstance(int index, IProgress<int> progress)
{
if (progress == null)
throw new ArgumentNullException(nameof(progress));
if (index < 0 || index >= MaxCount)
throw new ArgumentOutOfRangeException(nameof(index));
Instances[index] = progress;
}
}
}

View File

@@ -7,25 +7,31 @@ namespace AssetStudio
private bool needSearch;
private string path;
private SerializedFile assetsFile;
private long offset;
private long size;
private BinaryReader reader;
public int Size { get => (int)size; }
public int Size
{
get => (int)size;
set => size = value;
}
public long Offset { get; set; }
public ResourceReader() { }
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{
needSearch = true;
this.path = path;
this.assetsFile = assetsFile;
this.offset = offset;
this.Offset = offset;
this.size = size;
}
public ResourceReader(BinaryReader reader, long offset, long size)
{
this.reader = reader;
this.offset = offset;
this.Offset = offset;
this.size = size;
}
@@ -52,8 +58,12 @@ namespace AssetStudio
if (File.Exists(resourceFilePath))
{
needSearch = false;
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
{
return reader;
}
reader = new BinaryReader(File.OpenRead(resourceFilePath));
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
assetsFile.assetsManager.resourceFileReaders.TryAdd(resourceFileName, reader);
return reader;
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
@@ -67,21 +77,29 @@ namespace AssetStudio
public byte[] GetData()
{
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
lock (binaryReader)
{
binaryReader.BaseStream.Position = Offset;
return binaryReader.ReadBytes((int)size);
}
}
public void GetData(byte[] buff)
public int GetData(byte[] buff, int startIndex = 0)
{
int dataLen;
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
binaryReader.Read(buff, 0, (int)size);
lock (binaryReader)
{
binaryReader.BaseStream.Position = Offset;
dataLen = binaryReader.Read(buff, startIndex, (int)size);
}
return dataLen;
}
public void WriteData(string path)
{
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
binaryReader.BaseStream.Position = Offset;
using (var writer = File.OpenWrite(path))
{
binaryReader.BaseStream.CopyTo(writer, size);

Some files were not shown because too many files have changed in this diff Show More