241 Commits

Author SHA1 Message Date
VaDiM
571ea2da4a Don't use ImageSharp for texture processing
- returned to System.Drawing
(ImageSharp is a good lib, but too slow for such app, IMO)
2021-11-24 19:30:38 +02:00
VaDiM
9cbe91decb Improve sorting by asset names
- added alphanumeric sorting for more natural presentation of asset list
2021-11-24 14:56:28 +02:00
VaDiM
19c6c5fe73 Minor UI improvments & bugfixes
- improved "Copy text" option in right click menu, to display what exactly to copy
- added "Dump selected assets" option to right click menu
- added 'selected assets count' info to status strip when you select assets
- added 'exported count / total export count` info to status strip during export
- "Show error message" option on the "Debug" tab renamed to "Show all error messages" and is now disabled by default
- "fixed" an issue with getting stuck during the "Building tree structure" step
- fixed a bug with listSearch that could make it not work in some conditions
- fixed a rare bug for resource files with the same name, that caused their data to be overwritten and become incorrect
2021-11-24 14:55:38 +02:00
VaDiM
792850dbb2 Update projects 2021-11-22 16:00:51 +02:00
Perfare
2ce9cae957 Modify the prompt statement 2021-11-20 03:11:02 +08:00
Perfare
af5e50cfa9 Update README.md 2021-11-20 02:52:53 +08:00
Perfare
ce1172ca9a rename. closed #817 2021-11-19 18:24:18 +08:00
Perfare
a7e6d91f5b Fixed bug 2021-11-19 18:22:39 +08:00
Perfare
34a0af683a Fixed bug 2021-11-19 18:11:00 +08:00
Perfare
91410a33b1 Improve the handling of compressed files. 2021-11-19 17:54:06 +08:00
Perfare
d08b78c2cf support 2021.2 2021-11-12 10:25:22 +08:00
Perfare
2ef52afe1e Fixed #835 2021-11-12 09:30:12 +08:00
Perfare
05a41d2f1e Merge pull request #855 from nikitalita/fix-assembly-loading
Fix AssemblyLoading bug
2021-11-08 09:36:03 +08:00
nikitalita
34c38e1415 Fix AssemblyLoading bug
If the AssemblyLoader attempted to load a non-csil dll
while iterating through the file list, it would catch the exception
OUTSIDE the loop, and wouldn't load the rest.
This fix makes it catch inside the loop so it will continue iterating.
2021-10-07 13:36:03 -07:00
Perfare
c85873b729 0.16.0 2021-07-06 16:03:54 +08:00
Perfare
b146d251a7 add option to not show error message 2021-07-06 15:57:59 +08:00
Perfare
3129d67fc1 Improve ShaderConverter 2021-07-06 12:45:24 +08:00
Perfare
850ba63a10 support exporting VideoClips with a size above 2gb. close #765 2021-07-02 03:26:46 +08:00
Perfare
17b91984d6 fixed bug 2021-07-02 02:29:03 +08:00
Perfare
7ab2cda120 refactor the file reading part 2021-07-02 02:17:59 +08:00
Perfare
4345885cc9 remember the last opened path, close #646 2021-06-30 22:41:16 +08:00
Perfare
53720e37ab Fixed #435 2021-06-30 06:31:05 +08:00
Perfare
7c3cb36630 update project files 2021-06-29 11:03:19 +08:00
Perfare
c1cddce031 added option to support version stripped files, close #766 2021-06-29 10:32:19 +08:00
Perfare
973a1076e4 support exporting AnimationClip versions below 4.3 2021-06-29 02:43:42 +08:00
Perfare
089e164756 improved Sprite export 2021-06-28 07:14:02 +08:00
Perfare
c2b6691fd9 fix build 2021-06-27 09:42:13 +08:00
Perfare
8dec094304 update project files 2021-06-27 09:27:40 +08:00
Perfare
bedee240be Use ImageSharp to process textures 2021-06-27 07:33:20 +08:00
Perfare
d963d71b12 clean up TypeDefinitionConverter code 2021-06-26 13:16:12 +08:00
Perfare
77a0c9c40a Fbx multiple uv export 2021-06-24 13:48:56 +08:00
Perfare
f3e406983b Merge pull request #768 from Fraxul/master
Fix blend shape export with multiple submeshes
2021-06-24 12:59:31 +08:00
Dan Weatherford
08b7bfcf9a Fix blend shape export with multiple submeshes
Share a single vertex list between submeshes in the exported mesh, which
makes the blend target vertex list indices line up correctly.

As a bonus, the exported FBX file will be smaller for meshes with more
than one submesh, since we're not duplicating vertices anymore.
2021-06-20 00:18:22 -05:00
Patrick King
57e4f7cefd Add an option to export all UVs as diffuse maps. 2021-06-11 17:12:15 -06:00
Patrick King
c9cf2d188e Enable FBX export for higher UV maps. 2021-06-11 14:26:37 -06:00
Perfare
ab98585b6a Fix Shader reading. Close #720 2021-05-29 05:11:05 +08:00
Perfare
075d53a455 small improvement 2021-05-28 23:19:31 +08:00
Perfare
432116d834 Improve SerializedFile reading. 2021-05-28 22:23:07 +08:00
Perfare
caa45216ef fix compilation error 2021-05-28 22:16:50 +08:00
Perfare
c9394cd957 Fixed #734 2021-05-28 03:49:46 +08:00
Perfare
46c0e8ffe1 Improve stream file processing 2021-05-28 03:43:32 +08:00
Perfare
d14c232015 Improve the error message 2021-05-28 03:27:50 +08:00
Perfare
4002bdecb8 Update README.md 2021-05-27 03:55:37 +08:00
StarHeart
17259e00c7 correct grammar (#749) 2021-05-27 03:49:40 +08:00
Perfare
44b02b92d8 fix lzma decompression 2021-05-27 03:46:15 +08:00
Joshua May
251854cc41 Adds exporter for list of assets to XML (#710) 2021-04-18 01:27:15 +08:00
Perfare
6f7b77245d Merge pull request #639 from sk-zk/nul-fix
[GUI] Fix \0 chars in TextAssets cutting off preview
2021-04-18 01:21:16 +08:00
Perfare
6d99f5ebf6 Improve vertex format parsing. Close #689 2021-04-12 15:11:17 +08:00
Perfare
f1f2430f97 Support 2021.1 2021-04-11 23:49:44 +08:00
Perfare
b52696c965 Merge pull request #713 from K0lb3/patch-1
Update ClassIDType according to official reference
2021-04-11 21:54:45 +08:00
K0lb3
5fba52dc83 Update ClassIDType according to official reference
I noticed that Unity has made a [ClassID Reference table](https://docs.unity3d.com/Manual/ClassIDReference.html) and thought that copying it over here might be useful for dumps.
2021-03-28 14:24:20 -07:00
Perfare
dfb74baf79 Fix for mesh weights output 2021-01-15 09:32:57 +08:00
Perfare
978e90a403 Fix if AudioClip does not contain subsound. Close #672 2021-01-15 05:39:45 +08:00
Perfare
c17d7d6331 Update README.md 2021-01-15 04:38:54 +08:00
Perfare
9fef18d6ea fixes bug 2021-01-15 04:33:54 +08:00
Perfare
ee0cd4ab52 Fixed #609 2021-01-15 03:43:52 +08:00
Perfare
f904bc138b typo 2021-01-15 02:17:11 +08:00
Perfare
7ed5345b1b Fixed #652 2021-01-15 02:12:54 +08:00
Perfare
d7f652d572 improved Sprite export 2021-01-14 19:27:57 +08:00
Perfare
32ce032655 Support 2020.2 2021-01-14 05:23:19 +08:00
Perfare
e1cf36aa3c Fixed #650 2020-12-14 21:20:04 +08:00
sk-zk
f644396a15 Fix \0 chars in TextAssets cutting off preview 2020-10-30 23:08:06 +01:00
Perfare
3e77c34bd5 Fixed #618 2020-09-29 07:08:14 +08:00
Perfare
052c60f629 Fix file occupation conflict 2020-09-26 23:29:38 +08:00
Perfare
a1f2e3e7fe Merge pull request #613 from Ishotihadus/master
Problems in exporting fbx with multiple blendshapes
2020-09-26 10:18:42 -05:00
Ishotihadus
32ee8b326f fix problems in exporting fbx with multiple blendshapes 2020-09-16 19:44:11 +09:00
Perfare
06ce479eb6 Fixes #591 2020-08-26 09:50:25 +08:00
Perfare
03f74bac64 Fix BlendShape output error 2020-08-24 22:00:53 +08:00
Perfare
344b675745 Update README.md 2020-08-16 18:53:55 +08:00
Perfare
86590d95a5 Add dump viewer 2020-08-14 17:38:43 +08:00
Perfare
bbea1341b2 Update README.md 2020-08-14 15:50:45 +08:00
Perfare
ca60dd9834 Support exporting MonoBehaviour to json. Close #477 2020-08-14 15:45:48 +08:00
Perfare
7aa35b5b8c Fix get class from divided UnityEngine.dll 2020-08-14 01:31:49 +08:00
Perfare
bd2decdb8f Fix element alignment errors 2020-08-14 01:18:43 +08:00
Perfare
9b2c85bcae Refactor MonoBehaviour reading 2020-08-14 00:02:59 +08:00
Perfare
efbab7c43a using Nuget 2020-08-12 22:22:04 +08:00
Perfare
729a8a8263 implemented SPIR-V shader export 2020-08-12 22:11:26 +08:00
Perfare
0ec29f62ca Improve shader conversion, fixes #589 2020-08-12 20:49:36 +08:00
Perfare
796317f9d9 support 2020.1 2020-08-12 19:13:10 +08:00
Perfare
7596dcc7cd keep path when extracting folder 2020-08-12 02:55:02 +08:00
Perfare
422851cdab Fix mesh index errors 2020-08-12 02:24:08 +08:00
Perfare
ec0a2a47f1 can choose the directory to save the extracted files 2020-08-10 14:07:29 +08:00
Perfare
8ce5b947f6 Update README.md 2020-08-10 11:01:37 +08:00
Perfare
419ca63f9d Set Runtime Library to /MT 2020-08-10 09:52:09 +08:00
Perfare
6fdb0c7b0e add ResourceManager 2020-08-06 23:17:44 +08:00
Perfare
4e97b4b898 improve export 2020-08-06 21:07:37 +08:00
Perfare
1766dcbdeb Fixed #570 2020-08-06 13:31:17 +08:00
Perfare
ef38471ff1 move code 2020-08-06 13:11:41 +08:00
Perfare
217a7993e9 fixed bug 2020-08-06 12:56:47 +08:00
Perfare
0a41615763 fix UV problems 2020-08-06 12:34:59 +08:00
Perfare
9d34f668d5 modify project file 2020-08-06 11:59:35 +08:00
Perfare
9269a36725 Merge pull request #555 from Jayatubi/allowdrag
Allow drag and drop files or folder
2020-08-05 21:42:32 -05:00
Jayatubi
813e8b10a6 Export local keywords of shader as well as global keywords (#554)
* Export local keywords of shader

* Export local keywords of shader
2020-08-06 10:39:48 +08:00
Tahvohck
84c75fadf5 Sort code for PathID (change to numeric) (#550)
* Sort code for PathID (change to numeric)

* Remove comments (were only for reference)

* Match Perfare formatting
2020-08-06 10:38:12 +08:00
hozuki
c76e41b1ab Replace C++/CLI components with P/Invoke components (#562)
* Replace C++/CLI components with P/Invoke

* Deleted C++/CLI projects

* Use Utf8StringHandle to marshal UTF-8 strings

* Use plaform-default calling convention

* Handle DLL preloading on Linux and macOS

* Change intermediate and output directories of native projects

* Improve P/Invoke documentation
2020-08-06 10:35:50 +08:00
jayatubi
fefeea5f35 Allow drag and drop files or folder 2020-05-18 14:17:42 +08:00
Perfare
4a81c461e8 Modify Sprite processing function as an extension function 2020-04-10 18:57:04 +08:00
Perfare
b10d03d50d fixed bug 2020-04-10 18:51:43 +08:00
Perfare
da98a0c5b8 fixed bug 2020-04-10 18:20:45 +08:00
Perfare
76d17bacf5 improve type read 2020-04-10 18:11:56 +08:00
Perfare
6678ce082b refactor BundleFile read 2020-04-07 16:13:04 +08:00
Perfare
07074b3deb improve SerializedFile read 2020-04-07 08:59:04 +08:00
Perfare
df5d9f90d4 Add copy function to assetListView 2020-04-07 08:55:51 +08:00
Perfare
4f2d30552a set UV1 to NormalMap channel 2020-04-07 08:23:13 +08:00
Perfare
d259c7a5cd multiple uv export 2020-04-06 19:29:15 +08:00
Perfare
c71ceb7ea6 improve SerializedType read 2020-04-06 19:21:48 +08:00
Perfare
85cf134a49 Fixed if the container has the same key 2020-03-30 09:01:25 +08:00
Perfare
687b1d3a0d Fixed get triangles of mesh #510 2020-03-30 08:52:16 +08:00
Perfare
a30a0d0bc5 Update README.md 2020-03-28 15:52:15 +08:00
Perfare
e1dc54d6d7 use list to store objects in their original order 2020-03-28 14:13:25 +08:00
Perfare
c4270e186d fixed bug 2020-03-28 13:46:30 +08:00
Perfare
182a42ace2 optimize ResourceReader 2020-03-28 13:33:37 +08:00
Perfare
06fbe69a97 performance improvement 2020-03-28 04:24:32 +08:00
Perfare
a0bf4f9acd update LICENSE 2020-03-28 01:22:26 +08:00
Perfare
12568ba044 fix ico 2020-03-27 21:52:16 +08:00
Perfare
de95b02285 update to .net framework 4.7.2 2020-03-27 21:42:40 +08:00
Perfare
286edfe72c improve texture channel filter 2020-03-27 16:52:21 +08:00
Perfare
d717b223b7 delete some useless features 2020-03-27 01:06:22 +08:00
Perfare
9e195832ef reduce memory usage 2020-03-26 03:44:07 +08:00
Perfare
c8d08b2793 improve file type check 2020-03-26 02:17:48 +08:00
Perfare
2bcd9662be improve export 2020-03-26 01:01:02 +08:00
Perfare
ea461ee3d2 improve Texture2D decode 2020-03-25 22:45:53 +08:00
Perfare
fda821b441 add more information to the asset list 2020-03-25 14:01:59 +08:00
Perfare
5c193c761a using strong typing for setting 2020-03-25 11:18:12 +08:00
Perfare
14f47c6d30 fixed bug 2020-03-24 14:09:54 +08:00
Perfare
e53eacef78 improved 2020-03-24 11:31:57 +08:00
Perfare
ada26db659 improved 2020-03-24 10:42:39 +08:00
Perfare
48ca96807f Merge pull request #485 from K0lb3/patch-1
kSPMTight fix
2020-03-24 10:29:01 +08:00
Perfare
2018028853 fixed bug 2020-03-24 09:17:26 +08:00
Perfare
6f138dcc05 Update README.md 2020-03-24 08:52:30 +08:00
Perfare
69bcd2be67 update project 2020-03-24 07:45:47 +08:00
Perfare
45ad53b19a using Nuget 2020-03-24 07:19:59 +08:00
Perfare
6230240ee3 Merge pull request #499 from qiankanglai/master
corner case as protection
2020-03-24 07:09:18 +08:00
Perfare
73ec9f4bee update FBX SDK 2020.0.1 VS2017 2020-03-24 07:04:42 +08:00
Perfare
f3a0bf505e refactor Texture2D convert 2020-03-24 06:41:58 +08:00
Kanglai Qian
290708876d corner case as protection 2020-03-14 21:17:34 +08:00
Perfare
5b96a29cca move file 2020-03-14 16:06:21 +08:00
Perfare
948e2c4d92 Merge pull request #495 from qiankanglai/texchannel
texture channel support
2020-03-14 00:02:33 +08:00
Perfare
76da1c33ae Merge pull request #493 from Druhin13/master
Optimized images
2020-03-14 00:01:13 +08:00
Perfare
72b84ee24d Merge pull request #494 from qiankanglai/tga
support exporting texture2d as tga
2020-03-14 00:00:40 +08:00
Kanglai Qian
7b33d41172 texture channel 2020-03-03 12:46:51 +08:00
Kanglai Qian
c7043c1a83 support export texture2d as tga 2020-03-03 11:23:36 +08:00
Druhin Tarafder
d0baf26c61 Merge pull request #1 from Druhin13/imgbot
Optimized images
2020-03-02 14:39:00 +05:30
ImgBotApp
60ac10b043 [ImgBot] Optimize images
/AssetStudioGUI/Resources/preview.png -- 6.89kb -> 3.87kb (43.78%)

Signed-off-by: ImgBotApp <ImgBotHelp@gmail.com>
2020-03-02 08:56:17 +00:00
Perfare
80dc24b487 Update README.md 2020-02-28 15:41:39 +08:00
Perfare
9d32a9dd6a 2019.3 support 2020-02-28 15:39:11 +08:00
Perfare
d96cc3c762 Merge pull request #489 from DaZombieKiller/2020
Support for SerializedFile version 22
2020-02-27 23:09:26 +08:00
Zombie
509df42730 Support for SerializedFile version 22 2020-02-27 20:29:02 +10:00
K0lb3
4efa5b0507 kSPMTight fix
SpritePackingMode.kSPMTight can occur outside of settingsRaw.packed == 1.

[sample file](https://cdn.discordapp.com/attachments/603359898507673632/678238497894563860/kuroyukiwedding_base_1_a)
from Dengeki Bunko: Crossing Void
2020-02-20 09:42:19 +01:00
Perfare
cffe96b409 Skip reading failed assets 2019-10-20 08:05:55 +08:00
Perfare
16dddc01e3 always show the debug menu 2019-08-12 05:50:04 +08:00
Perfare
b5d2c2cadb improved 2019-08-12 04:36:07 +08:00
Perfare
1d2c0ab6cb Fixed #428 2019-08-12 04:17:06 +08:00
Perfare
c6b7e04c47 improved 2019-08-06 17:57:14 +08:00
Perfare
5704813b28 Improved UI 2019-08-06 17:43:51 +08:00
Perfare
465c989e75 fixed bug 2019-08-06 15:49:41 +08:00
Perfare
d335aaef9e improved 2019-08-06 09:48:21 +08:00
Perfare
495b48c783 improved Sprite export 2019-08-01 15:23:36 +08:00
Perfare
05b55722fb change text 2019-07-30 03:34:15 +08:00
Perfare
de54257eef improved bone export 2019-07-29 13:41:42 +08:00
Perfare
e62b6c3d77 improved 2019-07-29 00:31:43 +08:00
Perfare
dc05e5b5eb Fixed bug 2019-07-29 00:25:26 +08:00
Perfare
f377381e26 Support for exporting raw data 2019-07-28 19:48:06 +08:00
Perfare
20f9fe493f add more options for export model 2019-07-28 18:55:08 +08:00
Perfare
0b462754a5 Implemented BlendShape export 2019-07-28 16:41:23 +08:00
Perfare
b1ea8dd346 clean up code 2019-07-28 03:47:12 +08:00
Perfare
4a46f897bd add default values to materials 2019-07-28 00:26:56 +08:00
Perfare
6a5ec80de7 fixed bug 2019-07-27 23:20:47 +08:00
Perfare
4f2046d412 improved 2019-07-27 22:54:18 +08:00
Perfare
1cf59e8d67 fixed bug 2019-07-27 18:01:57 +08:00
Perfare
e9e8390bbc Supported merge GameObject to export 2019-07-17 12:51:00 +08:00
Perfare
738b084440 Fixed bug 2019-07-16 17:53:50 +08:00
Perfare
32cce894ac Fixed #373 2019-07-16 17:49:10 +08:00
Perfare
a6264b39d1 improved morph export 2019-07-16 13:21:32 +08:00
Perfare
eb4981808b Fixed coding errors 2019-07-16 05:32:54 +08:00
Perfare
50c17c2ec4 improved model export 2019-07-16 04:33:37 +08:00
Perfare
e001dff3de fixed bug 2019-06-14 16:17:56 +08:00
Perfare
3a0100ed37 update 2019-06-14 12:47:22 +08:00
Perfare
58ab3116db Implemented AnimationEvent 2019-06-14 11:58:59 +08:00
Perfare
6b93df41f2 fixed bug 2019-06-09 07:44:50 +08:00
Perfare
b9cf7d5874 fixed bug 2019-06-04 18:56:18 +08:00
Perfare
da4eb15d6b Fixed #400 2019-06-04 13:34:59 +08:00
Perfare
378840bc1b improved Texture2D convert 2019-06-04 13:05:49 +08:00
Perfare
3441135b2f Change the way rename same name assets 2019-06-02 14:36:35 +08:00
Perfare
afcbba8182 fixed SpriteAtlas 2019-04-26 10:48:24 +08:00
Perfare
cefdf08873 Fixed #390 2019-04-26 09:51:02 +08:00
Perfare
59be547a82 fixed bug 2019-04-18 14:07:17 +08:00
Perfare
a2be5ebdac fixed bug 2019-04-18 13:58:06 +08:00
Perfare
f76d3d8fcd fixed bugs 2019-04-18 12:31:16 +08:00
Perfare
edb6256fc9 fixed bugs 2019-04-18 11:07:51 +08:00
Perfare
8946a4fba5 2019.1 support 2019-04-18 10:46:06 +08:00
Perfare
87e1739208 Fixed #386 2019-04-14 20:17:38 +08:00
Perfare
10f4aaa39f Update README.md 2019-04-05 01:59:18 +08:00
Perfare
957073b041 move file 2019-04-04 21:14:52 +08:00
Perfare
e1bb9a6cf0 Fixed ASTC Decoding 2019-04-04 21:05:44 +08:00
Perfare
558adb0b66 Fixed #376 2019-03-28 02:55:58 +08:00
Perfare
6a4979f999 fixed bugs 2019-03-07 04:50:36 +08:00
Perfare
9e76d94eea Remove SharpDX 2019-01-24 01:03:45 +08:00
Perfare
fa91820016 FIxed #351 2019-01-24 00:35:42 +08:00
Perfare
be091ecebb Fixed #344 2019-01-15 07:37:30 +08:00
Perfare
903be743ac Fixed #345
Fixed bug
2019-01-13 23:21:45 +08:00
Perfare
c3c4697562 small fixed 2019-01-03 09:02:12 +08:00
Perfare
e6ed312de2 change math library
fixed bug
2019-01-03 08:55:43 +08:00
Perfare
33461e068f small improved 2018-12-28 10:24:32 +08:00
Perfare
7f13c90189 small improved 2018-12-24 17:38:12 +08:00
Perfare
54ed3971a2 small improved 2018-12-24 17:31:35 +08:00
Perfare
e602a5cf3b Fixed #332 2018-12-24 08:46:20 +08:00
Perfare
dec0a22ffe Fixed #297 2018-12-24 08:28:26 +08:00
Perfare
911272167a Fixed #331 2018-12-24 04:47:12 +08:00
Perfare
54d78d55a0 Fixed #326 2018-12-24 04:25:55 +08:00
Perfare
ff550b457f improved mesh read 2018-12-23 23:17:01 +08:00
Perfare
f449d7a8ab improved script dump 2018-12-23 15:51:00 +08:00
Perfare
761579ab1a Fixed bug 2018-12-18 09:59:48 +08:00
Perfare
5cd4cf67cf Update README.md 2018-12-18 02:08:55 +08:00
Perfare
fabfc77a52 improved console shader export 2018-12-17 23:12:24 +08:00
Perfare
f8ffaa0400 Fixed bug 2018-12-11 23:36:15 +08:00
Perfare
d156b5d947 small fixed 2018-12-11 15:24:49 +08:00
Perfare
d7551bdeb2 small fixed 2018-12-11 15:21:23 +08:00
Perfare
7d5e06bce4 improved shader export 2018-12-11 13:01:10 +08:00
Perfare
0bc17f0ff5 Fixed bug 2018-12-11 10:47:35 +08:00
Perfare
9edc268cd4 small improvement 2018-12-11 05:22:39 +08:00
Perfare
356d5fa8a4 Fixed Sprite read
improved script dump
2018-12-11 04:50:38 +08:00
Perfare
eb170d4f34 minor improvements 2018-12-09 11:56:24 +08:00
Perfare
324c5ec7a2 Fixed bug 2018-12-05 23:16:02 +08:00
Perfare
ae155ca603 Fixed bug 2018-12-05 23:08:39 +08:00
Perfare
eb13585174 2018.3.0b support
Refactor mesh read
Fixed bug
2018-12-05 22:35:05 +08:00
Perfare
98c9eea58a Improved file reading 2018-12-03 02:42:07 +08:00
John Lyu
067517740f try to fix IO exceptions with valid assetsFile. (#317) 2018-11-28 20:16:18 +08:00
Perfare
3addb0e894 improve Sprite export 2018-11-28 15:02:31 +08:00
Perfare
7452d4275e minor improvements 2018-11-26 08:47:20 +08:00
Perfare
96ea522e83 minor improvements 2018-11-25 15:50:28 +08:00
Perfare
ab24f049cf Completed tight Sprite export 2018-11-25 12:37:55 +08:00
Perfare
ec9184ba93 Fixed #302 2018-11-24 23:30:04 +08:00
Perfare
0a5b866a03 rename
move files
improve Sprite read
2018-11-24 23:02:05 +08:00
Perfare
58d5a3fc37 minor fixes 2018-11-24 04:42:45 +08:00
Perfare
19534ebb4d minor fixes 2018-11-22 14:45:28 +08:00
Perfare
0a764c74d6 Fixed #284 2018-11-22 13:38:07 +08:00
Perfare
ab5f5fbd9d Restore the extension of TextAsset
Export Animator to a separate folder
2018-11-22 12:17:16 +08:00
Perfare
7dbc2ff95d Fixed #311 2018-11-21 16:13:32 +08:00
Perfare
bfaa207853 Refactor read assets
Generic PPtr
Misc
2018-11-21 15:37:56 +08:00
Perfare
8c749e21e1 improve 2018-11-20 16:47:35 +08:00
252 changed files with 46340 additions and 10547 deletions

172
.gitignore vendored
View File

@@ -1,7 +1,10 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
@@ -15,13 +18,22 @@
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
build/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
@@ -36,18 +48,28 @@ TestResult.xml
[Rr]eleasePS/
dlldata.c
# DNX
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
@@ -57,6 +79,7 @@ artifacts/
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
@@ -72,14 +95,21 @@ _Chutzpah*
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
@@ -101,9 +131,18 @@ _TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
@@ -131,47 +170,68 @@ publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
## TODO: Comment the next line if you want to checkin your
## web deploy settings but do note that will include unencrypted
## passwords
#*.pubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Windows Azure Build Output
# Microsoft Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
!?*.[Cc]ache/
# Others
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
@@ -182,21 +242,30 @@ _UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- Backup*.rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
@@ -204,7 +273,68 @@ FakesAssemblies/
# Visual Studio 6 workspace options file
*.opt
# LightSwitch generated files
GeneratedArtifacts/
_Pvt_Extensions/
ModelManifest.xml
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb

View File

@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.8.1</Version>
<AssemblyVersion>0.16.8.1</AssemblyVersion>
<FileVersion>0.16.8.1</FileVersion>
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,124 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace AssetStudio.PInvoke
{
public static class DllLoader
{
public static void PreloadDll(string dllName)
{
var dllDir = GetDirectedDllDirectory();
// Not using OperatingSystem.Platform.
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Win32.LoadDll(dllDir, dllName);
}
else
{
Posix.LoadDll(dllDir, dllName);
}
}
private static string GetDirectedDllDirectory()
{
var localPath = Process.GetCurrentProcess().MainModule.FileName;
var localDir = Path.GetDirectoryName(localPath);
var subDir = Environment.Is64BitProcess ? "x64" : "x86";
var directedDllDir = Path.Combine(localDir, subDir);
return directedDllDir;
}
private static class Win32
{
internal static void LoadDll(string dllDir, string dllName)
{
var dllFileName = $"{dllName}.dll";
var directedDllPath = Path.Combine(dllDir, dllFileName);
// Specify SEARCH_DLL_LOAD_DIR to load dependent libraries located in the same platform-specific directory.
var hLibrary = LoadLibraryEx(directedDllPath, IntPtr.Zero, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
if (hLibrary == IntPtr.Zero)
{
var errorCode = Marshal.GetLastWin32Error();
var exception = new Win32Exception(errorCode);
throw new DllNotFoundException(exception.Message, exception);
}
}
// HMODULE LoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
// HMODULE LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string lpLibFileName, IntPtr hFile, uint dwFlags);
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
}
private static class Posix
{
internal static void LoadDll(string dllDir, string dllName)
{
string dllExtension;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
dllExtension = ".so";
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
dllExtension = ".dylib";
}
else
{
throw new NotSupportedException();
}
var dllFileName = $"lib{dllName}{dllExtension}";
var directedDllPath = Path.Combine(dllDir, dllFileName);
const int ldFlags = RTLD_NOW | RTLD_GLOBAL;
var hLibrary = DlOpen(directedDllPath, ldFlags);
if (hLibrary == IntPtr.Zero)
{
var pErrStr = DlError();
// `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325),
// which in turn interprets the byte sequence with system default codepage. On OSX and Linux
// the codepage is UTF-8 so the error message should be handled correctly.
var errorMessage = Marshal.PtrToStringAnsi(pErrStr);
throw new DllNotFoundException(errorMessage);
}
}
// OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms.
// void *dlopen(const char *filename, int flag);
[DllImport("libdl", EntryPoint = "dlopen")]
private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags);
// char *dlerror(void);
[DllImport("libdl", EntryPoint = "dlerror")]
private static extern IntPtr DlError();
private const int RTLD_LAZY = 0x1;
private const int RTLD_NOW = 0x2;
private const int RTLD_GLOBAL = 0x100;
}
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
namespace AssetStudio.PInvoke
{
// Generally the technique from Steamworks.NET
public class Utf8StringHandle : SafeHandleZeroOrMinusOneIsInvalid
{
static Utf8StringHandle()
{
Utf8 = new UTF8Encoding(false);
}
public Utf8StringHandle(string str)
: base(true)
{
IntPtr buffer;
if (str == null)
{
buffer = IntPtr.Zero;
}
else
{
if (str.Length == 0)
{
buffer = Marshal.AllocHGlobal(1);
unsafe
{
*(byte*)buffer = 0;
}
}
else
{
var strlen = Utf8.GetByteCount(str);
var strBuffer = new byte[strlen + 1];
Utf8.GetBytes(str, 0, str.Length, strBuffer, 0);
buffer = Marshal.AllocHGlobal(strBuffer.Length);
Marshal.Copy(strBuffer, 0, buffer, strBuffer.Length);
}
}
SetHandle(buffer);
}
public static string ReadUtf8StringFromPointer(IntPtr lpstr)
{
if (lpstr == IntPtr.Zero || lpstr == new IntPtr(-1))
{
return null;
}
var byteCount = 0;
unsafe
{
var p = (byte*)lpstr.ToPointer();
while (*p != 0)
{
byteCount += 1;
p += 1;
}
}
if (byteCount == 0)
{
return string.Empty;
}
var strBuffer = new byte[byteCount];
Marshal.Copy(lpstr, strBuffer, 0, byteCount);
var str = Utf8.GetString(strBuffer);
return str;
}
protected override bool ReleaseHandle()
{
if (!IsInvalid)
{
Marshal.FreeHGlobal(handle);
}
return true;
}
private static readonly UTF8Encoding Utf8;
}
}

View File

@@ -1,61 +1,141 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2024
# Visual Studio Version 16
VisualStudioVersion = 16.0.31410.357
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio.PInvoke", "AssetStudio.PInvoke\AssetStudio.PInvoke.csproj", "{0B2BE613-3049-4021-85D1-21C325F729F4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioTools", "AssetStudioTools\AssetStudioTools.csproj", "{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}"
ProjectSection(ProjectDependencies) = postProject
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{AF56B63C-1764-41B7-9E60-8D485422AC3B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{29EAD018-1C67-497A-AB8E-727D595AD756}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}"
ProjectSection(ProjectDependencies) = postProject
{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.ActiveCfg = Debug|x64
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.Build.0 = Debug|x64
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.ActiveCfg = Debug|x86
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.Build.0 = Debug|x86
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.ActiveCfg = Release|x64
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.Build.0 = Release|x64
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.ActiveCfg = Release|x86
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.Build.0 = Release|x86
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.ActiveCfg = Debug|x64
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.Build.0 = Debug|x64
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.ActiveCfg = Debug|Win32
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.Build.0 = Debug|Win32
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.ActiveCfg = Release|x64
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.Build.0 = Release|x64
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.ActiveCfg = Release|Win32
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.Build.0 = Release|Win32
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|x86
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.Build.0 = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.Build.0 = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.ActiveCfg = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.Build.0 = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.ActiveCfg = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.Build.0 = Release|Any CPU
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.Build.0 = Debug|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x86.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|Any CPU.Build.0 = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.ActiveCfg = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.Build.0 = Debug|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.ActiveCfg = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x86.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|Any CPU.Build.0 = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.ActiveCfg = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F5C476A6-2B3B-416F-8BD5-6FE454FF3972}
SolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}
EndGlobalSection
EndGlobal

View File

@@ -1,148 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AF56B63C-1764-41B7-9E60-8D485422AC3B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio</RootNamespace>
<AssemblyName>AssetStudio</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<Version>0.16.8.1</Version>
<AssemblyVersion>0.16.8.1</AssemblyVersion>
<FileVersion>0.16.8.1</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
<DebugType>none</DebugType>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="SharpDX.Mathematics">
<HintPath>Libraries\SharpDX.Mathematics.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Half">
<HintPath>Libraries\System.Half.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="7zip\Common\CommandLineParser.cs" />
<Compile Include="7zip\Common\CRC.cs" />
<Compile Include="7zip\Common\InBuffer.cs" />
<Compile Include="7zip\Common\OutBuffer.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaBase.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaDecoder.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaEncoder.cs" />
<Compile Include="7zip\Compress\LZ\IMatchFinder.cs" />
<Compile Include="7zip\Compress\LZ\LzBinTree.cs" />
<Compile Include="7zip\Compress\LZ\LzInWindow.cs" />
<Compile Include="7zip\Compress\LZ\LzOutWindow.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoder.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
<Compile Include="7zip\ICoder.cs" />
<Compile Include="Utility\IImported.cs" />
<Compile Include="SerializedFile.cs" />
<Compile Include="AssetsManager.cs" />
<Compile Include="Extensions\BinaryReaderExtensions.cs" />
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
<Compile Include="Brotli\BitReader.cs" />
<Compile Include="Brotli\BrotliInputStream.cs" />
<Compile Include="Brotli\BrotliRuntimeException.cs" />
<Compile Include="Brotli\Context.cs" />
<Compile Include="Brotli\Decode.cs" />
<Compile Include="Brotli\Dictionary.cs" />
<Compile Include="Brotli\Huffman.cs" />
<Compile Include="Brotli\HuffmanTreeGroup.cs" />
<Compile Include="Brotli\IntReader.cs" />
<Compile Include="Brotli\Prefix.cs" />
<Compile Include="Brotli\RunningState.cs" />
<Compile Include="Brotli\State.cs" />
<Compile Include="Brotli\Transform.cs" />
<Compile Include="Brotli\Utils.cs" />
<Compile Include="Brotli\WordTransformType.cs" />
<Compile Include="BuildTarget.cs" />
<Compile Include="BuildType.cs" />
<Compile Include="BundleFile.cs" />
<Compile Include="Classes\Animation.cs" />
<Compile Include="Classes\AnimationClip.cs" />
<Compile Include="Classes\Animator.cs" />
<Compile Include="Classes\AnimatorController.cs" />
<Compile Include="Classes\AnimatorOverrideController.cs" />
<Compile Include="Classes\AssetBundle.cs" />
<Compile Include="Classes\AudioClip.cs" />
<Compile Include="Classes\Avatar.cs" />
<Compile Include="Classes\Behaviour.cs" />
<Compile Include="Classes\BuildSettings.cs" />
<Compile Include="Classes\Component.cs" />
<Compile Include="Classes\EditorExtension.cs" />
<Compile Include="Classes\Font.cs" />
<Compile Include="Classes\GameObject.cs" />
<Compile Include="Classes\Material.cs" />
<Compile Include="Classes\Mesh.cs" />
<Compile Include="Classes\MeshFilter.cs" />
<Compile Include="Classes\MeshRenderer.cs" />
<Compile Include="Classes\MonoBehaviour.cs" />
<Compile Include="Classes\MonoScript.cs" />
<Compile Include="Classes\MovieTexture.cs" />
<Compile Include="Classes\NamedObject.cs" />
<Compile Include="Classes\Object.cs" />
<Compile Include="Classes\PlayerSettings.cs" />
<Compile Include="Classes\RectTransform.cs" />
<Compile Include="Classes\Renderer.cs" />
<Compile Include="Classes\Shader.cs" />
<Compile Include="Classes\SkinnedMeshRenderer.cs" />
<Compile Include="Classes\Sprite.cs" />
<Compile Include="Classes\SpriteAtlas.cs" />
<Compile Include="Classes\TextAsset.cs" />
<Compile Include="Classes\Texture.cs" />
<Compile Include="Classes\Texture2D.cs" />
<Compile Include="Classes\Transform.cs" />
<Compile Include="Classes\VideoClip.cs" />
<Compile Include="ClassIDType.cs" />
<Compile Include="CommonString.cs" />
<Compile Include="EndianBinaryReader.cs" />
<Compile Include="FileIdentifier.cs" />
<Compile Include="Utility\ILogger.cs" />
<Compile Include="ImportHelper.cs" />
<Compile Include="Utility\IProgress.cs" />
<Compile Include="LocalSerializedObjectIdentifier.cs" />
<Compile Include="Utility\Logger.cs" />
<Compile Include="Lz4DecoderStream.cs" />
<Compile Include="ObjectInfo.cs" />
<Compile Include="ObjectReader.cs" />
<Compile Include="Classes\PPtr.cs" />
<Compile Include="Utility\Progress.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourcesHelper.cs" />
<Compile Include="SerializedFileHeader.cs" />
<Compile Include="SerializedType.cs" />
<Compile Include="SevenZipHelper.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" />
<Compile Include="WebFile.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>

View File

@@ -1,21 +1,25 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using static AssetStudio.ImportHelper;
namespace AssetStudio
{
public class AssetsManager
{
public string SpecifyUnityVersion;
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>();
internal Dictionary<string, EndianBinaryReader> resourceFileReaders = new Dictionary<string, EndianBinaryReader>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
private List<string> importFiles = new List<string>();
private HashSet<string> importFilesHash = new HashSet<string>();
private HashSet<string> assetsfileListHash = new HashSet<string>();
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
public void LoadFiles(string[] files)
public void LoadFiles(params string[] files)
{
var path = Path.GetDirectoryName(files[0]);
MergeSplitAssets(path);
@@ -36,8 +40,9 @@ namespace AssetStudio
foreach (var file in files)
{
importFiles.Add(file);
importFilesHash.Add(Path.GetFileName(file).ToUpper());
importFilesHash.Add(Path.GetFileName(file));
}
Progress.Reset();
//use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++)
@@ -45,49 +50,65 @@ namespace AssetStudio
LoadFile(importFiles[i]);
Progress.Report(i + 1, importFiles.Count);
}
importFiles.Clear();
importFilesHash.Clear();
assetsfileListHash.Clear();
assetsFileListHash.Clear();
ReadAssets();
ProcessAssets();
}
private void LoadFile(string fullName)
{
switch (CheckFileType(fullName, out var reader))
var reader = new FileReader(fullName);
LoadFile(reader);
}
private void LoadFile(FileReader reader)
{
switch (reader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFile(fullName, reader);
LoadAssetsFile(reader);
break;
case FileType.BundleFile:
LoadBundleFile(fullName, reader);
LoadBundleFile(reader);
break;
case FileType.WebFile:
LoadWebFile(fullName, reader);
LoadWebFile(reader);
break;
case FileType.GZipFile:
LoadFile(DecompressGZip(reader));
break;
case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader));
break;
}
}
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
private void LoadAssetsFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid)
Logger.Info($"Loading {reader.FileName}");
try
{
var assetsFile = new SerializedFile(reader, this);
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
assetsFileListHash.Add(assetsFile.fileName);
foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName.ToUpper()))
if (!importFilesHash.Contains(sharedFileName))
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
@@ -97,13 +118,14 @@ namespace AssetStudio
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName.ToUpper());
importFilesHash.Add(sharedFileName);
}
}
}
}
else
catch (Exception e)
{
Logger.Error($"Error while reading assets file {reader.FileName}", e);
reader.Dispose();
}
}
@@ -113,80 +135,308 @@ namespace AssetStudio
}
}
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
{
var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid)
try
{
var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath;
if (assetsFile.header.m_Version < 7)
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.kUnknown_7)
{
assetsFile.SetVersion(unityVersion);
}
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
assetsFileListHash.Add(assetsFile.fileName);
}
else
catch (Exception e)
{
resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.reader);
Logger.Error($"Error while reading assets file {reader.FileName} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(reader.FileName, reader);
}
}
}
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
private void LoadBundleFile(FileReader reader, string originalPath = null)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Decompressing " + fileName);
var bundleFile = new BundleFile(reader, fullName);
reader.Dispose();
foreach (var file in bundleFile.fileList)
Logger.Info("Loading " + reader.FileName);
try
{
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
var bundleFile = new BundleFile(reader);
foreach (var file in bundleFile.fileList)
{
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{
LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
}
else if (!resourceFileReaders.ContainsKey(file.fileName))
{
resourceFileReaders.Add(file.fileName, subReader);
}
}
}
catch (Exception e)
{
var str = $"Error while reading bundle file {reader.FileName}";
if (originalPath != null)
{
str += $" from {Path.GetFileName(originalPath)}";
}
Logger.Error(str, e);
}
finally
{
reader.Dispose();
}
}
private void LoadWebFile(string fullName, EndianBinaryReader reader)
private void LoadWebFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
var webFile = new WebFile(reader);
reader.Dispose();
foreach (var file in webFile.fileList)
Logger.Info("Loading " + reader.FileName);
try
{
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
switch (CheckFileType(file.stream, out reader))
var webFile = new WebFile(reader);
foreach (var file in webFile.fileList)
{
case FileType.AssetsFile:
LoadAssetsFromMemory(dummyPath, reader, fullName);
break;
case FileType.BundleFile:
LoadBundleFile(dummyPath, reader, fullName);
break;
case FileType.WebFile:
LoadWebFile(dummyPath, reader);
break;
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
switch (subReader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFromMemory(subReader, reader.FullPath);
break;
case FileType.BundleFile:
LoadBundleFile(subReader, reader.FullPath);
break;
case FileType.WebFile:
LoadWebFile(subReader);
break;
case FileType.ResourceFile:
resourceFileReaders[file.fileName] = subReader; //TODO
break;
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading web file {reader.FileName}", e);
}
finally
{
reader.Dispose();
}
}
public void CheckStrippedVersion(SerializedFile assetsFile)
{
if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
{
throw new Exception("The Unity version has been stripped, please set the version in the options");
}
if (!string.IsNullOrEmpty(SpecifyUnityVersion))
{
assetsFile.SetVersion(SpecifyUnityVersion);
}
}
public void Clear()
{
foreach (var assetsFile in assetsFileList)
{
assetsFile.Objects.Clear();
assetsFile.reader.Close();
}
assetsFileList.Clear();
foreach (var resourceFileReader in resourceFileReaders)
{
resourceFileReader.Value.Close();
}
resourceFileReaders.Clear();
assetsFileIndexCache.Clear();
}
private void ReadAssets()
{
Logger.Info("Read assets...");
var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);
int i = 0;
Progress.Reset();
foreach (var assetsFile in assetsFileList)
{
foreach (var objectInfo in assetsFile.m_Objects)
{
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
try
{
Object obj;
switch (objectReader.type)
{
case ClassIDType.Animation:
obj = new Animation(objectReader);
break;
case ClassIDType.AnimationClip:
obj = new AnimationClip(objectReader);
break;
case ClassIDType.Animator:
obj = new Animator(objectReader);
break;
case ClassIDType.AnimatorController:
obj = new AnimatorController(objectReader);
break;
case ClassIDType.AnimatorOverrideController:
obj = new AnimatorOverrideController(objectReader);
break;
case ClassIDType.AssetBundle:
obj = new AssetBundle(objectReader);
break;
case ClassIDType.AudioClip:
obj = new AudioClip(objectReader);
break;
case ClassIDType.Avatar:
obj = new Avatar(objectReader);
break;
case ClassIDType.Font:
obj = new Font(objectReader);
break;
case ClassIDType.GameObject:
obj = new GameObject(objectReader);
break;
case ClassIDType.Material:
obj = new Material(objectReader);
break;
case ClassIDType.Mesh:
obj = new Mesh(objectReader);
break;
case ClassIDType.MeshFilter:
obj = new MeshFilter(objectReader);
break;
case ClassIDType.MeshRenderer:
obj = new MeshRenderer(objectReader);
break;
case ClassIDType.MonoBehaviour:
obj = new MonoBehaviour(objectReader);
break;
case ClassIDType.MonoScript:
obj = new MonoScript(objectReader);
break;
case ClassIDType.MovieTexture:
obj = new MovieTexture(objectReader);
break;
case ClassIDType.PlayerSettings:
obj = new PlayerSettings(objectReader);
break;
case ClassIDType.RectTransform:
obj = new RectTransform(objectReader);
break;
case ClassIDType.Shader:
obj = new Shader(objectReader);
break;
case ClassIDType.SkinnedMeshRenderer:
obj = new SkinnedMeshRenderer(objectReader);
break;
case ClassIDType.Sprite:
obj = new Sprite(objectReader);
break;
case ClassIDType.SpriteAtlas:
obj = new SpriteAtlas(objectReader);
break;
case ClassIDType.TextAsset:
obj = new TextAsset(objectReader);
break;
case ClassIDType.Texture2D:
obj = new Texture2D(objectReader);
break;
case ClassIDType.Transform:
obj = new Transform(objectReader);
break;
case ClassIDType.VideoClip:
obj = new VideoClip(objectReader);
break;
case ClassIDType.ResourceManager:
obj = new ResourceManager(objectReader);
break;
default:
obj = new Object(objectReader);
break;
}
assetsFile.AddObject(obj);
}
catch (Exception e)
{
var sb = new StringBuilder();
sb.AppendLine("Unable to load object")
.AppendLine($"Assets {assetsFile.fileName}")
.AppendLine($"Type {objectReader.type}")
.AppendLine($"PathID {objectInfo.m_PathID}")
.Append(e);
Logger.Error(sb.ToString());
}
Progress.Report(++i, progressCount);
}
}
}
private void ProcessAssets()
{
Logger.Info("Process Assets...");
foreach (var assetsFile in assetsFileList)
{
foreach (var obj in assetsFile.Objects)
{
if (obj is GameObject m_GameObject)
{
foreach (var pptr in m_GameObject.m_Components)
{
if (pptr.TryGet(out var m_Component))
{
switch (m_Component)
{
case Transform m_Transform:
m_GameObject.m_Transform = m_Transform;
break;
case MeshRenderer m_MeshRenderer:
m_GameObject.m_MeshRenderer = m_MeshRenderer;
break;
case MeshFilter m_MeshFilter:
m_GameObject.m_MeshFilter = m_MeshFilter;
break;
case SkinnedMeshRenderer m_SkinnedMeshRenderer:
m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;
break;
case Animator m_Animator:
m_GameObject.m_Animator = m_Animator;
break;
case Animation m_Animation:
m_GameObject.m_Animation = m_Animation;
break;
}
}
}
}
else if (obj is SpriteAtlas m_SpriteAtlas)
{
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
{
if (m_PackedSprite.TryGet(out var m_Sprite))
{
if (m_Sprite.m_SpriteAtlas.IsNull)
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
}
}
}
}
}
}
}
}

View File

@@ -7,7 +7,7 @@ namespace AssetStudio
{
public enum BuildTarget
{
UnknownPlatform = 3716,
NoTarget = -2,
DashboardWidget = 1,
StandaloneOSX = 2,
StandaloneOSXPPC = 3,
@@ -42,6 +42,12 @@ namespace AssetStudio
WiiU,
tvOS,
Switch,
NoTarget = -2
Lumin,
Stadia,
CloudRendering,
GameCoreXboxSeries,
GameCoreXboxOne,
PS5,
UnknownPlatform = 9999
}
}

View File

@@ -1,246 +1,314 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Lz4;
namespace AssetStudio
{
public class StreamFile
{
public string fileName;
public Stream stream;
}
public class BlockInfo
{
public uint compressedSize;
public uint uncompressedSize;
public short flag;
}
public class BundleFile
{
private string path;
public string versionPlayer;
public string versionEngine;
public List<StreamFile> fileList = new List<StreamFile>();
public BundleFile(EndianBinaryReader bundleReader, string path)
public class Header
{
this.path = path;
var signature = bundleReader.ReadStringToNull();
switch (signature)
public string signature;
public uint version;
public string unityVersion;
public string unityRevision;
public long size;
public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize;
public uint flags;
}
public class StorageBlock
{
public uint compressedSize;
public uint uncompressedSize;
public ushort flags;
}
public class Node
{
public long offset;
public long size;
public uint flags;
public string path;
}
public Header m_Header;
private StorageBlock[] m_BlocksInfo;
private Node[] m_DirectoryInfo;
public StreamFile[] fileList;
public BundleFile(FileReader reader)
{
m_Header = new Header();
m_Header.signature = reader.ReadStringToNull();
m_Header.version = reader.ReadUInt32();
m_Header.unityVersion = reader.ReadStringToNull();
m_Header.unityRevision = reader.ReadStringToNull();
switch (m_Header.signature)
{
case "UnityArchive":
break; //TODO
case "UnityWeb":
case "UnityRaw":
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
if (m_Header.version == 6)
{
var format = bundleReader.ReadInt32();
versionPlayer = bundleReader.ReadStringToNull();
versionEngine = bundleReader.ReadStringToNull();
if (format < 6)
{
int bundleSize = bundleReader.ReadInt32();
}
else if (format == 6)
{
ReadFormat6(bundleReader, true);
return;
}
short dummy2 = bundleReader.ReadInt16();
int offset = bundleReader.ReadInt16();
int dummy3 = bundleReader.ReadInt32();
int lzmaChunks = bundleReader.ReadInt32();
int lzmaSize = 0;
long streamSize = 0;
for (int i = 0; i < lzmaChunks; i++)
{
lzmaSize = bundleReader.ReadInt32();
streamSize = bundleReader.ReadInt32();
}
bundleReader.Position = offset;
switch (signature)
{
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA": //.bytes
case "UnityWeb":
{
var lzmaBuffer = bundleReader.ReadBytes(lzmaSize);
using (var lzmaStream = new EndianBinaryReader(SevenZipHelper.StreamDecompress(new MemoryStream(lzmaBuffer))))
{
GetAssetsFiles(lzmaStream, 0);
}
break;
}
case "UnityRaw":
{
GetAssetsFiles(bundleReader, offset);
break;
}
}
break;
goto case "UnityFS";
}
ReadHeaderAndBlocksInfo(reader);
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocksAndDirectory(reader, blocksStream);
ReadFiles(blocksStream, reader.FullPath);
}
break;
case "UnityFS":
ReadHeader(reader);
ReadBlocksInfoAndDirectory(reader);
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
var format = bundleReader.ReadInt32();
versionPlayer = bundleReader.ReadStringToNull();
versionEngine = bundleReader.ReadStringToNull();
if (format == 6)
{
ReadFormat6(bundleReader);
}
break;
ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, reader.FullPath);
}
break;
}
}
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
{
int fileCount = reader.ReadInt32();
for (int i = 0; i < fileCount; i++)
var isCompressed = m_Header.signature == "UnityWeb";
if (m_Header.version >= 4)
{
var file = new StreamFile();
file.fileName = Path.GetFileName(reader.ReadStringToNull());
int fileOffset = reader.ReadInt32();
fileOffset += offset;
int fileSize = reader.ReadInt32();
long nextFile = reader.Position;
reader.Position = fileOffset;
var buffer = reader.ReadBytes(fileSize);
file.stream = new MemoryStream(buffer);
fileList.Add(file);
reader.Position = nextFile;
var hash = reader.ReadBytes(16);
var crc = reader.ReadUInt32();
}
var minimumStreamedBytes = reader.ReadUInt32();
m_Header.size = reader.ReadUInt32();
var numberOfLevelsToDownloadBeforeStreaming = reader.ReadUInt32();
var levelCount = reader.ReadInt32();
m_BlocksInfo = new StorageBlock[1];
for (int i = 0; i < levelCount; i++)
{
var storageBlock = new StorageBlock()
{
compressedSize = reader.ReadUInt32(),
uncompressedSize = reader.ReadUInt32(),
flags = (ushort)(isCompressed ? 1 : 0)
};
if (i == levelCount - 1)
{
m_BlocksInfo[0] = storageBlock;
}
}
if (m_Header.version >= 2)
{
var completeFileSize = reader.ReadUInt32();
}
if (m_Header.version >= 3)
{
var fileInfoHeaderSize = reader.ReadUInt32();
}
reader.Position = m_Header.size;
}
private void ReadFormat6(EndianBinaryReader bundleReader, bool padding = false)
private Stream CreateBlocksStream(string path)
{
var bundleSize = bundleReader.ReadInt64();
int compressedSize = bundleReader.ReadInt32();
int uncompressedSize = bundleReader.ReadInt32();
int flag = bundleReader.ReadInt32();
if (padding)
bundleReader.ReadByte();
byte[] blocksInfoBytes;
if ((flag & 0x80) != 0)//at end of file
Stream blocksStream;
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum >= int.MaxValue)
{
var position = bundleReader.Position;
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
bundleReader.Position = position;
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
}
else
{
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
blocksStream = new MemoryStream((int)uncompressedSizeSum);
}
MemoryStream blocksInfoStream;
switch (flag & 0x3F)
return blocksStream;
}
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
{
foreach (var blockInfo in m_BlocksInfo)
{
default://None
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
if (blockInfo.flags == 1)
{
using (var memoryStream = new MemoryStream(uncompressedBytes))
{
blocksInfoStream = new MemoryStream(blocksInfoBytes);
break;
}
case 1://LZMA
{
blocksInfoStream = SevenZipHelper.StreamDecompress(new MemoryStream(blocksInfoBytes));
break;
}
case 2://LZ4
case 3://LZ4HC
{
byte[] uncompressedBytes = new byte[uncompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(blocksInfoBytes)))
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
{
decoder.Read(uncompressedBytes, 0, uncompressedSize);
uncompressedBytes = decompressStream.ToArray();
}
blocksInfoStream = new MemoryStream(uncompressedBytes);
break;
}
//case 4:LZHAM?
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoStream))
{
blocksInfoReader.Position = 0x10;
int blockcount = blocksInfoReader.ReadInt32();
var blockInfos = new BlockInfo[blockcount];
for (int i = 0; i < blockcount; i++)
{
blockInfos[i] = new BlockInfo
{
uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(),
flag = blocksInfoReader.ReadInt16()
};
}
Stream dataStream;
var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum > int.MaxValue)
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++)
{
m_DirectoryInfo[i] = new Node
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/
dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
path = blocksReader.ReadStringToNull(),
offset = blocksReader.ReadUInt32(),
size = blocksReader.ReadUInt32()
};
}
}
public void ReadFiles(Stream blocksStream, string path)
{
fileList = new StreamFile[m_DirectoryInfo.Length];
for (int i = 0; i < m_DirectoryInfo.Length; i++)
{
var node = m_DirectoryInfo[i];
var file = new StreamFile();
fileList[i] = file;
file.path = node.path;
file.fileName = Path.GetFileName(node.path);
if (node.size >= int.MaxValue)
{
/*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);
}
else
{
dataStream = new MemoryStream();
file.stream = new MemoryStream((int)node.size);
}
foreach (var blockInfo in blockInfos)
{
switch (blockInfo.flag & 0x3F)
blocksStream.Position = node.offset;
blocksStream.CopyTo(file.stream, node.size);
file.stream.Position = 0;
}
}
private void ReadHeader(EndianBinaryReader reader)
{
m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
m_Header.flags = reader.ReadUInt32();
if (m_Header.signature != "UnityFS")
{
reader.ReadByte();
}
}
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)
{
byte[] blocksInfoBytes;
if (m_Header.version >= 7)
{
reader.AlignStream(16);
}
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd
{
var position = reader.Position;
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
reader.Position = position;
}
else //0x40 kArchiveBlocksAndDirectoryInfoCombined
{
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
}
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
MemoryStream blocksInfoUncompresseddStream;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
{
default: //None
{
default://None
{
bundleReader.BaseStream.CopyTo(dataStream, blockInfo.compressedSize);
break;
}
case 1://LZMA
{
SevenZipHelper.StreamDecompress(bundleReader.BaseStream, dataStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break;
}
case 2://LZ4
case 3://LZ4HC
{
var lz4Stream = new Lz4DecoderStream(bundleReader.BaseStream, blockInfo.compressedSize);
lz4Stream.CopyTo(dataStream, blockInfo.uncompressedSize);
break;
}
//case 4:LZHAM?
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
break;
}
case 1: //LZMA
{
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
blocksInfoUncompresseddStream.Position = 0;
blocksInfoCompressedStream.Close();
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
{
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
}
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break;
}
}
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
{
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
var blocksInfoCount = blocksInfoReader.ReadInt32();
m_BlocksInfo = new StorageBlock[blocksInfoCount];
for (int i = 0; i < blocksInfoCount; i++)
{
m_BlocksInfo[i] = new StorageBlock
{
uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(),
flags = blocksInfoReader.ReadUInt16()
};
}
dataStream.Position = 0;
using (dataStream)
var nodesCount = blocksInfoReader.ReadInt32();
m_DirectoryInfo = new Node[nodesCount];
for (int i = 0; i < nodesCount; i++)
{
var entryinfo_count = blocksInfoReader.ReadInt32();
for (int i = 0; i < entryinfo_count; i++)
m_DirectoryInfo[i] = new Node
{
var file = new StreamFile();
var entryinfo_offset = blocksInfoReader.ReadInt64();
var entryinfo_size = blocksInfoReader.ReadInt64();
flag = blocksInfoReader.ReadInt32();
file.fileName = Path.GetFileName(blocksInfoReader.ReadStringToNull());
if (entryinfo_size > int.MaxValue)
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
file.stream = memoryMappedFile.CreateViewStream();*/
var extractPath = path + "_unpacked\\";
Directory.CreateDirectory(extractPath);
file.stream = File.Create(extractPath + file.fileName);
}
else
{
file.stream = new MemoryStream();
}
dataStream.Position = entryinfo_offset;
dataStream.CopyTo(file.stream, entryinfo_size);
file.stream.Position = 0;
fileList.Add(file);
}
offset = blocksInfoReader.ReadInt64(),
size = blocksInfoReader.ReadInt64(),
flags = blocksInfoReader.ReadUInt32(),
path = blocksInfoReader.ReadStringToNull(),
};
}
}
}
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
{
foreach (var blockInfo in m_BlocksInfo)
{
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask
{
default: //None
{
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
break;
}
case 1: //LZMA
{
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
{
lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
}
break;
}
}
}
blocksStream.Position = 0;
}
}
}

View File

@@ -1,4 +1,5 @@
namespace AssetStudio
// official Class ID Reference: https://docs.unity3d.com/Manual/ClassIDReference.html
namespace AssetStudio
{
public enum ClassIDType
{
@@ -26,7 +27,7 @@
ParticleRenderer = 26,
Texture = 27,
Texture2D = 28,
SceneSettings = 29,
OcclusionCullingSettings = 29,
GraphicsSettings = 30,
MeshFilter = 33,
OcclusionPortal = 41,
@@ -49,7 +50,7 @@
PhysicsMaterial2D = 62,
MeshCollider = 64,
BoxCollider = 65,
SpriteCollider2D = 66,
CompositeCollider2D = 66,
EdgeCollider2D = 68,
CapsuleCollider2D = 70,
ComputeShader = 72,
@@ -92,6 +93,7 @@
FlareLayer = 124,
HaloLayer = 125,
NavMeshAreas = 126,
NavMeshProjectSettings = 126,
HaloManager = 127,
Font = 128,
PlayerSettings = 129,
@@ -158,7 +160,7 @@
BlendTree = 206,
Motion = 207,
NavMeshObstacle = 208,
TerrainInstance = 210,
SortingGroup = 210,
SpriteRenderer = 212,
Sprite = 213,
CachedSpriteAtlas = 214,
@@ -216,15 +218,19 @@
PerformanceReportingManager = 305,
UnityConnectSettings = 310,
AvatarMask = 319,
PlayableDirector = 320,
VideoPlayer = 328,
VideoClip = 329,
ParticleSystemForceField = 330,
SpriteMask = 331,
WorldAnchor = 362,
OcclusionCullingData = 363,
//kLargestRuntimeClassID = 364
SmallestEditorClassID = 1000,
Prefab = 1001,
PrefabInstance = 1001,
EditorExtensionImpl = 1002,
AssetImporter = 1003,
AssetDatabase = 1004,
AssetDatabaseV1 = 1004,
Mesh3DSImporter = 1005,
TextureImporter = 1006,
ShaderImporter = 1007,
@@ -259,13 +265,13 @@
AnimatorState = 1102,
HumanTemplate = 1105,
AnimatorStateMachine = 1107,
PreviewAssetType = 1108,
PreviewAnimationClip = 1108,
AnimatorTransition = 1109,
SpeedTreeImporter = 1110,
AnimatorTransitionBase = 1111,
SubstanceImporter = 1112,
LightmapParameters = 1113,
LightmapSnapshot = 1120,
LightingDataAsset = 1120,
GISRaster = 1121,
GISRasterImporter = 1122,
CadImporter = 1123,
@@ -276,11 +282,98 @@
ActivationLogComponent = 2000,
//kLargestEditorClassID = 2001
//kClassIdOutOfHierarchy = 100000
SubDerived = 367388927,
//int = 100000,
//bool = 100001,
//float = 100002,
MonoObject = 100003,
Collision = 100004,
Vector3f = 100005,
RootMotionData = 100006,
Collision2D = 100007,
AudioMixerLiveUpdateFloat = 100008,
AudioMixerLiveUpdateBool = 100009,
Polygon2D = 100010,
//void = 100011,
TilemapCollider2D = 19719996,
AssetImporterLog = 41386430,
VFXRenderer = 73398921,
SerializableManagedRefTestClass = 76251197,
Grid = 156049354,
ScenesUsingAssets = 156483287,
ArticulationBody = 171741748,
Preset = 181963792,
EmptyObject = 277625683,
IConstraint = 285090594,
TestObjectWithSpecialLayoutOne = 293259124,
AssemblyDefinitionReferenceImporter = 294290339,
SiblingDerived = 334799969,
TestObjectWithSerializedMapStringNonAlignedStruct = 342846651,
SubDerived = 367388927,
AssetImportInProgressProxy = 369655926,
PluginBuildInfo = 382020655,
EditorProjectAccess = 426301858,
PrefabImporter = 468431735,
TestObjectWithSerializedArray = 478637458,
TestObjectWithSerializedAnimationCurve = 478637459,
TilemapRenderer = 483693784,
ScriptableCamera = 488575907,
SpriteAtlasAsset = 612988286,
SpriteAtlasDatabase = 638013454,
AudioBuildInfo = 641289076,
CachedSpriteAtlasRuntimeData = 644342135,
RendererFake = 646504946,
AssemblyDefinitionReferenceAsset = 662584278,
BuiltAssetBundleInfoSet = 668709126,
SpriteAtlas = 687078895,
RayTracingShaderImporter = 747330370,
RayTracingShader = 825902497,
LightingSettings = 850595691,
PlatformModuleSetup = 877146078,
VersionControlSettings = 890905787,
AimConstraint = 895512359,
VFXManager = 937362698,
VisualEffectSubgraph = 994735392,
VisualEffectSubgraphOperator = 994735403,
VisualEffectSubgraphBlock = 994735404,
LocalizationImporter = 1027052791,
Derived = 1091556383,
PropertyModificationsTargetTestObject = 1111377672,
ReferencesArtifactGenerator = 1114811875,
AssemblyDefinitionAsset = 1152215463,
SceneVisibilityState = 1154873562,
LookAtConstraint = 1183024399,
SpriteAtlasImporter = 1210832254,
MultiArtifactTestImporter = 1223240404,
GameObjectRecorder = 1268269756,
LightingDataAssetParent = 1325145578,
PresetManager = 1386491679,
TestObjectWithSpecialLayoutTwo = 1392443030,
StreamingManager = 1403656975,
LowerResBlitTexture = 1480428607,
RenderPassAttachment = 1571458007
StreamingController = 1542919678,
RenderPassAttachment = 1571458007,
TestObjectVectorPairStringBool = 1628831178,
GridLayout = 1742807556,
AssemblyDefinitionImporter = 1766753193,
ParentConstraint = 1773428102,
FakeComponent = 1803986026,
PositionConstraint = 1818360608,
RotationConstraint = 1818360609,
ScaleConstraint = 1818360610,
Tilemap = 1839735485,
PackageManifest = 1896753125,
PackageManifestImporter = 1896753126,
TerrainLayer = 1953259897,
SpriteShapeRenderer = 1971053207,
NativeObjectType = 1977754360,
TestObjectWithSerializedMapStringBool = 1981279845,
SerializableManagedHost = 1995898324,
VisualEffectAsset = 2058629509,
VisualEffectImporter = 2058629510,
VisualEffectResource = 2058629511,
VisualEffectObject = 2059678085,
VisualEffect = 2083052967,
LocalizationAsset = 2083778819,
ScriptedImporter = 2089858483
}
}

View File

@@ -7,16 +7,16 @@ namespace AssetStudio
{
public sealed class Animation : Behaviour
{
public List<PPtr> m_Animations;
public PPtr<AnimationClip>[] m_Animations;
public Animation(ObjectReader reader) : base(reader)
{
var m_Animation = reader.ReadPPtr();
var m_Animation = new PPtr<AnimationClip>(reader);
int numAnimations = reader.ReadInt32();
m_Animations = new List<PPtr>(numAnimations);
m_Animations = new PPtr<AnimationClip>[numAnimations];
for (int i = 0; i < numAnimations; i++)
{
m_Animations.Add(reader.ReadPPtr());
m_Animations[i] = new PPtr<AnimationClip>(reader);
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using SharpDX;
using System.Linq;
namespace AssetStudio
{
@@ -22,7 +22,7 @@ namespace AssetStudio
value = readerFunc();
inSlope = readerFunc();
outSlope = readerFunc();
if (reader.version[0] >= 2018)
if (reader.version[0] >= 2018) //2018 and up
{
weightedMode = reader.ReadInt32();
inWeight = readerFunc();
@@ -33,7 +33,7 @@ namespace AssetStudio
public class AnimationCurve<T>
{
public List<Keyframe<T>> m_Curve;
public Keyframe<T>[] m_Curve;
public int m_PreInfinity;
public int m_PostInfinity;
public int m_RotationOrder;
@@ -42,10 +42,10 @@ namespace AssetStudio
{
var version = reader.version;
int numCurves = reader.ReadInt32();
m_Curve = new List<Keyframe<T>>(numCurves);
m_Curve = new Keyframe<T>[numCurves];
for (int i = 0; i < numCurves; i++)
{
m_Curve.Add(new Keyframe<T>(reader, readerFunc));
m_Curve[i] = new Keyframe<T>(reader, readerFunc);
}
m_PreInfinity = reader.ReadInt32();
@@ -85,10 +85,10 @@ namespace AssetStudio
int numData = reader.ReadInt32();
m_Data = reader.ReadBytes(numData);
reader.AlignStream(4);
reader.AlignStream();
m_BitSize = reader.ReadByte();
reader.AlignStream(4);
reader.AlignStream();
}
public float[] UnpackFloats(int itemCountInChunk, int chunkStride, int start = 0, int numChunks = -1)
@@ -142,10 +142,10 @@ namespace AssetStudio
int numData = reader.ReadInt32();
m_Data = reader.ReadBytes(numData);
reader.AlignStream(4);
reader.AlignStream();
m_BitSize = reader.ReadByte();
reader.AlignStream(4);
reader.AlignStream();
}
public int[] UnpackInts()
@@ -187,7 +187,7 @@ namespace AssetStudio
int numData = reader.ReadInt32();
m_Data = reader.ReadBytes(numData);
reader.AlignStream(4);
reader.AlignStream();
}
public Quaternion[] UnpackQuats()
@@ -292,8 +292,8 @@ namespace AssetStudio
public AnimationCurve<float> curve;
public string attribute;
public string path;
public int classID;
public PPtr script;
public ClassIDType classID;
public PPtr<MonoScript> script;
public FloatCurve(ObjectReader reader)
@@ -301,73 +301,73 @@ namespace AssetStudio
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString();
classID = reader.ReadInt32();
script = reader.ReadPPtr();
classID = (ClassIDType)reader.ReadInt32();
script = new PPtr<MonoScript>(reader);
}
}
public class PPtrKeyframe
{
public float time;
public PPtr value;
public PPtr<Object> value;
public PPtrKeyframe(ObjectReader reader)
{
time = reader.ReadSingle();
value = reader.ReadPPtr();
value = new PPtr<Object>(reader);
}
}
public class PPtrCurve
{
public List<PPtrKeyframe> curve;
public PPtrKeyframe[] curve;
public string attribute;
public string path;
public int classID;
public PPtr script;
public PPtr<MonoScript> script;
public PPtrCurve(ObjectReader reader)
{
int numCurves = reader.ReadInt32();
curve = new List<PPtrKeyframe>(numCurves);
curve = new PPtrKeyframe[numCurves];
for (int i = 0; i < numCurves; i++)
{
curve.Add(new PPtrKeyframe(reader));
curve[i] = new PPtrKeyframe(reader);
}
attribute = reader.ReadAlignedString();
path = reader.ReadAlignedString();
classID = reader.ReadInt32();
script = reader.ReadPPtr();
script = new PPtr<MonoScript>(reader);
}
}
public class AABB
{
public Vector3 m_Center;
public Vector3 m_Extend;
public Vector3 m_Extent;
public AABB(ObjectReader reader)
{
m_Center = reader.ReadVector3();
m_Extend = reader.ReadVector3();
m_Extent = reader.ReadVector3();
}
}
public class xform
{
public object t;
public Vector3 t;
public Quaternion q;
public object s;
public Vector3 s;
public xform(ObjectReader reader)
{
var version = reader.version;
t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
q = reader.ReadQuaternion();
s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
}
}
@@ -383,10 +383,7 @@ namespace AssetStudio
public HandPose(ObjectReader reader)
{
m_GrabX = new xform(reader);
int numDoFs = reader.ReadInt32();
m_DoFArray = reader.ReadSingleArray(numDoFs);
m_DoFArray = reader.ReadSingleArray();
m_Override = reader.ReadSingle();
m_CloseOpen = reader.ReadSingle();
m_InOut = reader.ReadSingle();
@@ -399,7 +396,7 @@ namespace AssetStudio
public xform m_X;
public float m_WeightT;
public float m_WeightR;
public object m_HintT;
public Vector3 m_HintT;
public float m_HintWeightT;
public HumanGoal(ObjectReader reader)
@@ -410,7 +407,7 @@ namespace AssetStudio
m_WeightR = reader.ReadSingle();
if (version[0] >= 5)//5.0 and up
{
m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_HintWeightT = reader.ReadSingle();
}
}
@@ -419,41 +416,40 @@ namespace AssetStudio
public class HumanPose
{
public xform m_RootX;
public object m_LookAtPosition;
public Vector3 m_LookAtPosition;
public Vector4 m_LookAtWeight;
public List<HumanGoal> m_GoalArray;
public HumanGoal[] m_GoalArray;
public HandPose m_LeftHandPose;
public HandPose m_RightHandPose;
public float[] m_DoFArray;
public object[] m_TDoFArray;
public Vector3[] m_TDoFArray;
public HumanPose(ObjectReader reader)
{
var version = reader.version;
m_RootX = new xform(reader);
m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_LookAtWeight = reader.ReadVector4();
int numGoals = reader.ReadInt32();
m_GoalArray = new List<HumanGoal>(numGoals);
m_GoalArray = new HumanGoal[numGoals];
for (int i = 0; i < numGoals; i++)
{
m_GoalArray.Add(new HumanGoal(reader));
m_GoalArray[i] = new HumanGoal(reader);
}
m_LeftHandPose = new HandPose(reader);
m_RightHandPose = new HandPose(reader);
int numDoFs = reader.ReadInt32();
m_DoFArray = reader.ReadSingleArray(numDoFs);
m_DoFArray = reader.ReadSingleArray();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2))//5.2 and up
{
int numTDof = reader.ReadInt32();
m_TDoFArray = new object[numTDof];
m_TDoFArray = new Vector3[numTDof];
for (int i = 0; i < numTDof; i++)
{
m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
}
}
}
@@ -466,8 +462,7 @@ namespace AssetStudio
public StreamedClip(ObjectReader reader)
{
int numData = reader.ReadInt32();
data = reader.ReadUInt32Array(numData);
data = reader.ReadUInt32Array();
curveCount = reader.ReadUInt32();
}
@@ -509,17 +504,17 @@ namespace AssetStudio
public class StreamedFrame
{
public float time;
public List<StreamedCurveKey> keyList;
public StreamedCurveKey[] keyList;
public StreamedFrame(BinaryReader reader)
{
time = reader.ReadSingle();
int numKeys = reader.ReadInt32();
keyList = new List<StreamedCurveKey>(numKeys);
keyList = new StreamedCurveKey[numKeys];
for (int i = 0; i < numKeys; i++)
{
keyList.Add(new StreamedCurveKey(reader));
keyList[i] = new StreamedCurveKey(reader);
}
}
}
@@ -527,14 +522,13 @@ namespace AssetStudio
public List<StreamedFrame> ReadData()
{
var frameList = new List<StreamedFrame>();
using (Stream stream = new MemoryStream())
var buffer = new byte[data.Length * 4];
Buffer.BlockCopy(data, 0, buffer, 0, buffer.Length);
using (var reader = new BinaryReader(new MemoryStream(buffer)))
{
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(data);
stream.Position = 0;
while (stream.Position < stream.Length)
while (reader.BaseStream.Position < reader.BaseStream.Length)
{
frameList.Add(new StreamedFrame(new BinaryReader(stream)));
frameList.Add(new StreamedFrame(reader));
}
}
@@ -546,7 +540,7 @@ namespace AssetStudio
for (int i = frameIndex - 1; i >= 0; i--)
{
var preFrame = frameList[i];
var preCurveKey = preFrame.keyList.Find(x => x.index == curveKey.index);
var preCurveKey = preFrame.keyList.FirstOrDefault(x => x.index == curveKey.index);
if (preCurveKey != null)
{
curveKey.inSlope = preCurveKey.CalculateNextInSlope(frame.time - preFrame.time, curveKey);
@@ -573,9 +567,7 @@ namespace AssetStudio
m_CurveCount = reader.ReadUInt32();
m_SampleRate = reader.ReadSingle();
m_BeginTime = reader.ReadSingle();
int numSamples = reader.ReadInt32();
m_SampleArray = reader.ReadSingleArray(numSamples);
m_SampleArray = reader.ReadSingleArray();
}
}
@@ -585,8 +577,7 @@ namespace AssetStudio
public ConstantClip(ObjectReader reader)
{
int numData = reader.ReadInt32();
data = reader.ReadSingleArray(numData);
data = reader.ReadSingleArray();
}
}
@@ -612,15 +603,15 @@ namespace AssetStudio
public class ValueArrayConstant
{
public List<ValueConstant> m_ValueArray;
public ValueConstant[] m_ValueArray;
public ValueArrayConstant(ObjectReader reader)
{
int numVals = reader.ReadInt32();
m_ValueArray = new List<ValueConstant>(numVals);
m_ValueArray = new ValueConstant[numVals];
for (int i = 0; i < numVals; i++)
{
m_ValueArray.Add(new ValueConstant(reader));
m_ValueArray[i] = new ValueConstant(reader);
}
}
}
@@ -641,7 +632,54 @@ namespace AssetStudio
{
m_ConstantClip = new ConstantClip(reader);
}
m_Binding = new ValueArrayConstant(reader);
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 3)) //2018.3 down
{
m_Binding = new ValueArrayConstant(reader);
}
}
public AnimationClipBindingConstant ConvertValueArrayToGenericBinding()
{
var bindings = new AnimationClipBindingConstant();
var genericBindings = new List<GenericBinding>();
var values = m_Binding;
for (int i = 0; i < values.m_ValueArray.Length;)
{
var curveID = values.m_ValueArray[i].m_ID;
var curveTypeID = values.m_ValueArray[i].m_TypeID;
var binding = new GenericBinding();
genericBindings.Add(binding);
if (curveTypeID == 4174552735) //CRC(PositionX))
{
binding.path = curveID;
binding.attribute = 1; //kBindTransformPosition
binding.typeID = ClassIDType.Transform;
i += 3;
}
else if (curveTypeID == 2211994246) //CRC(QuaternionX))
{
binding.path = curveID;
binding.attribute = 2; //kBindTransformRotation
binding.typeID = ClassIDType.Transform;
i += 4;
}
else if (curveTypeID == 1512518241) //CRC(ScaleX))
{
binding.path = curveID;
binding.attribute = 3; //kBindTransformScale
binding.typeID = ClassIDType.Transform;
i += 3;
}
else
{
binding.typeID = ClassIDType.Animator;
binding.path = 0;
binding.attribute = curveID;
i++;
}
}
bindings.genericBindings = genericBindings.ToArray();
return bindings;
}
}
@@ -666,7 +704,7 @@ namespace AssetStudio
public xform m_RightFootStartX;
public xform m_MotionStartX;
public xform m_MotionStopX;
public object m_AverageSpeed;
public Vector3 m_AverageSpeed;
public Clip m_Clip;
public float m_StartTime;
public float m_StopTime;
@@ -675,7 +713,7 @@ namespace AssetStudio
public float m_CycleOffset;
public float m_AverageAngularSpeed;
public int[] m_IndexArray;
public List<ValueDelta> m_ValueArrayDelta;
public ValueDelta[] m_ValueArrayDelta;
public float[] m_ValueArrayReferencePose;
public bool m_Mirror;
public bool m_LoopTime;
@@ -705,7 +743,7 @@ namespace AssetStudio
m_MotionStartX = new xform(reader);
m_MotionStopX = new xform(reader);
}
m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4();//5.4 and up
m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_Clip = new Clip(reader);
m_StartTime = reader.ReadSingle();
m_StopTime = reader.ReadSingle();
@@ -714,30 +752,27 @@ namespace AssetStudio
m_CycleOffset = reader.ReadSingle();
m_AverageAngularSpeed = reader.ReadSingle();
int numIndices = reader.ReadInt32();
m_IndexArray = reader.ReadInt32Array(numIndices);
m_IndexArray = reader.ReadInt32Array();
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
{
int numAdditionalCurveIndexs = reader.ReadInt32();
var m_AdditionalCurveIndexArray = new List<int>(numAdditionalCurveIndexs);
for (int i = 0; i < numAdditionalCurveIndexs; i++)
{
m_AdditionalCurveIndexArray.Add(reader.ReadInt32());
}
var m_AdditionalCurveIndexArray = reader.ReadInt32Array();
}
int numDeltas = reader.ReadInt32();
m_ValueArrayDelta = new List<ValueDelta>(numDeltas);
m_ValueArrayDelta = new ValueDelta[numDeltas];
for (int i = 0; i < numDeltas; i++)
{
m_ValueArrayDelta.Add(new ValueDelta(reader));
m_ValueArrayDelta[i] = new ValueDelta(reader);
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
{
m_ValueArrayReferencePose = reader.ReadSingleArray(reader.ReadInt32());
m_ValueArrayReferencePose = reader.ReadSingleArray();
}
m_Mirror = reader.ReadBoolean();
m_LoopTime = reader.ReadBoolean();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
m_LoopTime = reader.ReadBoolean();
}
m_LoopBlend = reader.ReadBoolean();
m_LoopBlendOrientation = reader.ReadBoolean();
m_LoopBlendPositionY = reader.ReadBoolean();
@@ -750,7 +785,7 @@ namespace AssetStudio
m_KeepOriginalPositionY = reader.ReadBoolean();
m_KeepOriginalPositionXZ = reader.ReadBoolean();
m_HeightFromFeet = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -758,17 +793,19 @@ namespace AssetStudio
{
public uint path;
public uint attribute;
public PPtr script;
public PPtr<Object> script;
public ClassIDType typeID;
public byte customType;
public byte isPPtrCurve;
public GenericBinding() { }
public GenericBinding(ObjectReader reader)
{
var version = reader.version;
path = reader.ReadUInt32();
attribute = reader.ReadUInt32();
script = reader.ReadPPtr();
script = new PPtr<Object>(reader);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{
typeID = (ClassIDType)reader.ReadInt32();
@@ -779,29 +816,31 @@ namespace AssetStudio
}
customType = reader.ReadByte();
isPPtrCurve = reader.ReadByte();
reader.AlignStream(4);
reader.AlignStream();
}
}
public class AnimationClipBindingConstant
{
public List<GenericBinding> genericBindings;
public List<PPtr> pptrCurveMapping;
public GenericBinding[] genericBindings;
public PPtr<Object>[] pptrCurveMapping;
public AnimationClipBindingConstant() { }
public AnimationClipBindingConstant(ObjectReader reader)
{
int numBindings = reader.ReadInt32();
genericBindings = new List<GenericBinding>(numBindings);
genericBindings = new GenericBinding[numBindings];
for (int i = 0; i < numBindings; i++)
{
genericBindings.Add(new GenericBinding(reader));
genericBindings[i] = new GenericBinding(reader);
}
int numMappings = reader.ReadInt32();
pptrCurveMapping = new List<PPtr>(numMappings);
pptrCurveMapping = new PPtr<Object>[numMappings];
for (int i = 0; i < numMappings; i++)
{
pptrCurveMapping.Add(reader.ReadPPtr());
pptrCurveMapping[i] = new PPtr<Object>(reader);
}
}
@@ -841,6 +880,33 @@ namespace AssetStudio
}
}
public class AnimationEvent
{
public float time;
public string functionName;
public string data;
public PPtr<Object> objectReferenceParameter;
public float floatParameter;
public int intParameter;
public int messageOptions;
public AnimationEvent(ObjectReader reader)
{
var version = reader.version;
time = reader.ReadSingle();
functionName = reader.ReadAlignedString();
data = reader.ReadAlignedString();
objectReferenceParameter = new PPtr<Object>(reader);
floatParameter = reader.ReadSingle();
if (version[0] >= 3) //3 and up
{
intParameter = reader.ReadInt32();
}
messageOptions = reader.ReadInt32();
}
}
public enum AnimationType
{
kLegacy = 1,
@@ -854,20 +920,20 @@ namespace AssetStudio
public bool m_Legacy;
public bool m_Compressed;
public bool m_UseHighQualityCurve;
public List<QuaternionCurve> m_RotationCurves;
public List<CompressedAnimationCurve> m_CompressedRotationCurves;
public List<Vector3Curve> m_EulerCurves;
public List<Vector3Curve> m_PositionCurves;
public List<Vector3Curve> m_ScaleCurves;
public List<FloatCurve> m_FloatCurves;
public List<PPtrCurve> m_PPtrCurves;
public QuaternionCurve[] m_RotationCurves;
public CompressedAnimationCurve[] m_CompressedRotationCurves;
public Vector3Curve[] m_EulerCurves;
public Vector3Curve[] m_PositionCurves;
public Vector3Curve[] m_ScaleCurves;
public FloatCurve[] m_FloatCurves;
public PPtrCurve[] m_PPtrCurves;
public float m_SampleRate;
public int m_WrapMode;
public AABB m_Bounds;
public uint m_MuscleClipSize;
public ClipMuscleConstant m_MuscleClip;
public AnimationClipBindingConstant m_ClipBindingConstant;
//public List<AnimationEvent> m_Events;
public AnimationEvent[] m_Events;
public AnimationClip(ObjectReader reader) : base(reader)
@@ -891,59 +957,59 @@ namespace AssetStudio
{
m_UseHighQualityCurve = reader.ReadBoolean();
}
reader.AlignStream(4);
reader.AlignStream();
int numRCurves = reader.ReadInt32();
m_RotationCurves = new List<QuaternionCurve>(numRCurves);
m_RotationCurves = new QuaternionCurve[numRCurves];
for (int i = 0; i < numRCurves; i++)
{
m_RotationCurves.Add(new QuaternionCurve(reader));
m_RotationCurves[i] = new QuaternionCurve(reader);
}
int numCRCurves = reader.ReadInt32();
m_CompressedRotationCurves = new List<CompressedAnimationCurve>(numCRCurves);
m_CompressedRotationCurves = new CompressedAnimationCurve[numCRCurves];
for (int i = 0; i < numCRCurves; i++)
{
m_CompressedRotationCurves.Add(new CompressedAnimationCurve(reader));
m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader);
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
{
int numEulerCurves = reader.ReadInt32();
m_EulerCurves = new List<Vector3Curve>(numEulerCurves);
m_EulerCurves = new Vector3Curve[numEulerCurves];
for (int i = 0; i < numEulerCurves; i++)
{
m_EulerCurves.Add(new Vector3Curve(reader));
m_EulerCurves[i] = new Vector3Curve(reader);
}
}
int numPCurves = reader.ReadInt32();
m_PositionCurves = new List<Vector3Curve>(numPCurves);
m_PositionCurves = new Vector3Curve[numPCurves];
for (int i = 0; i < numPCurves; i++)
{
m_PositionCurves.Add(new Vector3Curve(reader));
m_PositionCurves[i] = new Vector3Curve(reader);
}
int numSCurves = reader.ReadInt32();
m_ScaleCurves = new List<Vector3Curve>(numSCurves);
m_ScaleCurves = new Vector3Curve[numSCurves];
for (int i = 0; i < numSCurves; i++)
{
m_ScaleCurves.Add(new Vector3Curve(reader));
m_ScaleCurves[i] = new Vector3Curve(reader);
}
int numFCurves = reader.ReadInt32();
m_FloatCurves = new List<FloatCurve>(numFCurves);
m_FloatCurves = new FloatCurve[numFCurves];
for (int i = 0; i < numFCurves; i++)
{
m_FloatCurves.Add(new FloatCurve(reader));
m_FloatCurves[i] = new FloatCurve(reader);
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
int numPtrCurves = reader.ReadInt32();
m_PPtrCurves = new List<PPtrCurve>(numPtrCurves);
m_PPtrCurves = new PPtrCurve[numPtrCurves];
for (int i = 0; i < numPtrCurves; i++)
{
m_PPtrCurves.Add(new PPtrCurve(reader));
m_PPtrCurves[i] = new PPtrCurve(reader);
}
}
@@ -962,12 +1028,22 @@ namespace AssetStudio
{
m_ClipBindingConstant = new AnimationClipBindingConstant(reader);
}
/*int numEvents = reader.ReadInt32();
m_Events = new List<AnimationEvent>(numEvents);
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
{
var m_HasGenericRootTransform = reader.ReadBoolean();
var m_HasMotionFloatCurves = reader.ReadBoolean();
reader.AlignStream();
}
int numEvents = reader.ReadInt32();
m_Events = new AnimationEvent[numEvents];
for (int i = 0; i < numEvents; i++)
{
m_Events.Add(new AnimationEvent(stream, file.Version[0] - '0'));
}*/
m_Events[i] = new AnimationEvent(reader);
}
if (version[0] >= 2017) //2017 and up
{
reader.AlignStream();
}
}
}
}

View File

@@ -7,14 +7,14 @@ namespace AssetStudio
{
public sealed class Animator : Behaviour
{
public PPtr m_Avatar;
public PPtr m_Controller;
public bool m_HasTransformHierarchy;
public PPtr<Avatar> m_Avatar;
public PPtr<RuntimeAnimatorController> m_Controller;
public bool m_HasTransformHierarchy = true;
public Animator(ObjectReader reader) : base(reader)
{
m_Avatar = reader.ReadPPtr();
m_Controller = reader.ReadPPtr();
m_Avatar = new PPtr<Avatar>(reader);
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
@@ -25,13 +25,17 @@ namespace AssetStudio
var m_ApplyRootMotion = reader.ReadBoolean();
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
{
reader.AlignStream(4);
reader.AlignStream();
}
if (version[0] >= 5) //5.0 and up
{
var m_LinearVelocityBlending = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{
var m_StabilizeFeet = reader.ReadBoolean();
}
reader.AlignStream();
}
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
@@ -50,13 +54,13 @@ namespace AssetStudio
}
if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down
{
reader.AlignStream(4);
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
{
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
}

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpDX;
namespace AssetStudio
{
@@ -14,9 +13,11 @@ namespace AssetStudio
public HumanPoseMask(ObjectReader reader)
{
var version = reader.version;
word0 = reader.ReadUInt32();
word1 = reader.ReadUInt32();
if (reader.version[0] >= 5) //5.0 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{
word2 = reader.ReadUInt32();
}
@@ -64,16 +65,24 @@ namespace AssetStudio
public LayerConstant(ObjectReader reader)
{
var version = reader.version;
m_StateMachineIndex = reader.ReadUInt32();
m_StateMachineMotionSetIndex = reader.ReadUInt32();
m_BodyMask = new HumanPoseMask(reader);
m_SkeletonMask = new SkeletonMask(reader);
m_Binding = reader.ReadUInt32();
m_LayerBlendingMode = reader.ReadInt32();
m_DefaultWeight = reader.ReadSingle();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
{
m_DefaultWeight = reader.ReadSingle();
}
m_IKPass = reader.ReadBoolean();
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
{
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
}
reader.AlignStream();
}
}
@@ -113,6 +122,7 @@ namespace AssetStudio
public TransitionConstant(ObjectReader reader)
{
var version = reader.version;
int numConditions = reader.ReadInt32();
m_ConditionConstantArray = new ConditionConstant[numConditions];
for (int i = 0; i < numConditions; i++)
@@ -135,7 +145,7 @@ namespace AssetStudio
m_ExitTime = reader.ReadSingle();
m_HasExitTime = reader.ReadBoolean();
m_HasFixedDuration = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
m_InterruptionSource = reader.ReadInt32();
m_OrderedInterruption = reader.ReadBoolean();
}
@@ -144,8 +154,12 @@ namespace AssetStudio
m_Atomic = reader.ReadBoolean();
}
m_CanTransitionToSelf = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{
m_CanTransitionToSelf = reader.ReadBoolean();
}
reader.AlignStream();
}
}
@@ -156,7 +170,7 @@ namespace AssetStudio
public LeafInfoConstant(ObjectReader reader)
{
m_IDArray = reader.ReadUInt32Array(reader.ReadInt32());
m_IDArray = reader.ReadUInt32Array();
m_IndexOffset = reader.ReadUInt32();
}
}
@@ -167,7 +181,7 @@ namespace AssetStudio
public MotionNeighborList(ObjectReader reader)
{
m_NeighborArray = reader.ReadUInt32Array(reader.ReadInt32());
m_NeighborArray = reader.ReadUInt32Array();
}
}
@@ -181,10 +195,10 @@ namespace AssetStudio
public Blend2dDataConstant(ObjectReader reader)
{
m_ChildPositionArray = reader.ReadVector2Array(reader.ReadInt32());
m_ChildMagnitudeArray = reader.ReadSingleArray(reader.ReadInt32());
m_ChildPairVectorArray = reader.ReadVector2Array(reader.ReadInt32());
m_ChildPairAvgMagInvArray = reader.ReadSingleArray(reader.ReadInt32());
m_ChildPositionArray = reader.ReadVector2Array();
m_ChildMagnitudeArray = reader.ReadSingleArray();
m_ChildPairVectorArray = reader.ReadVector2Array();
m_ChildPairAvgMagInvArray = reader.ReadSingleArray();
int numNeighbours = reader.ReadInt32();
m_ChildNeighborListArray = new MotionNeighborList[numNeighbours];
@@ -201,7 +215,7 @@ namespace AssetStudio
public Blend1dDataConstant(ObjectReader reader)
{
m_ChildThresholdArray = reader.ReadSingleArray(reader.ReadInt32());
m_ChildThresholdArray = reader.ReadSingleArray();
}
}
@@ -212,9 +226,9 @@ namespace AssetStudio
public BlendDirectDataConstant(ObjectReader reader)
{
m_ChildBlendEventIDArray = reader.ReadUInt32Array(reader.ReadInt32());
m_ChildBlendEventIDArray = reader.ReadUInt32Array();
m_NormalizedBlendValues = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -224,6 +238,7 @@ namespace AssetStudio
public uint m_BlendEventID;
public uint m_BlendEventYID;
public uint[] m_ChildIndices;
public float[] m_ChildThresholdArray;
public Blend1dDataConstant m_Blend1dData;
public Blend2dDataConstant m_Blend2dData;
public BlendDirectDataConstant m_BlendDirectData;
@@ -236,42 +251,72 @@ namespace AssetStudio
public BlendTreeNodeConstant(ObjectReader reader)
{
var version = reader.version;
m_BlendType = reader.ReadUInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{
m_BlendType = reader.ReadUInt32();
}
m_BlendEventID = reader.ReadUInt32();
m_BlendEventYID = reader.ReadUInt32();
m_ChildIndices = reader.ReadUInt32Array(reader.ReadInt32());
m_Blend1dData = new Blend1dDataConstant(reader);
m_Blend2dData = new Blend2dDataConstant(reader);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 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
{
m_ChildThresholdArray = reader.ReadSingleArray();
}
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{
m_Blend1dData = new Blend1dDataConstant(reader);
m_Blend2dData = new Blend2dDataConstant(reader);
}
if (version[0] >= 5) //5.0 and up
{
m_BlendDirectData = new BlendDirectDataConstant(reader);
}
m_ClipID = reader.ReadUInt32();
if (version[0] < 5) //5.0 down
if (version[0] == 4 && version[1] >= 5) //4.5 - 5.0
{
m_ClipIndex = reader.ReadUInt32();
}
m_Duration = reader.ReadSingle();
m_CycleOffset = reader.ReadSingle();
m_Mirror = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 4
|| (version[0] == 4 && version[1] > 1)
|| (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up
{
m_CycleOffset = reader.ReadSingle();
m_Mirror = reader.ReadBoolean();
reader.AlignStream();
}
}
}
public class BlendTreeConstant
{
public BlendTreeNodeConstant[] m_NodeArray;
public ValueArrayConstant m_BlendEventArrayConstant;
public BlendTreeConstant(ObjectReader reader)
{
var version = reader.version;
int numNodes = reader.ReadInt32();
m_NodeArray = new BlendTreeNodeConstant[numNodes];
for (int i = 0; i < numNodes; i++)
{
m_NodeArray[i] = new BlendTreeNodeConstant(reader);
}
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
{
m_BlendEventArrayConstant = new ValueArrayConstant(reader);
}
}
}
@@ -299,6 +344,7 @@ namespace AssetStudio
public StateConstant(ObjectReader reader)
{
var version = reader.version;
int numTransistions = reader.ReadInt32();
m_TransitionConstantArray = new TransitionConstant[numTransistions];
for (int i = 0; i < numTransistions; i++)
@@ -306,14 +352,9 @@ namespace AssetStudio
m_TransitionConstantArray[i] = new TransitionConstant(reader);
}
int numBlendIndices = reader.ReadInt32();
m_BlendTreeConstantIndexArray = new int[numBlendIndices];
for (int i = 0; i < numBlendIndices; i++)
{
m_BlendTreeConstantIndexArray[i] = reader.ReadInt32();
}
m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
if (version[0] < 5) //5.0 down
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
{
int numInfos = reader.ReadInt32();
m_LeafInfoArray = new LeafInfoConstant[numInfos];
@@ -331,14 +372,17 @@ namespace AssetStudio
}
m_NameID = reader.ReadUInt32();
m_PathID = reader.ReadUInt32();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
m_PathID = reader.ReadUInt32();
}
if (version[0] >= 5) //5.0 and up
{
m_FullPathID = reader.ReadUInt32();
}
m_TagID = reader.ReadUInt32();
if (version[0] >= 5) //5.0 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
{
m_SpeedParamID = reader.ReadUInt32();
m_MirrorParamID = reader.ReadUInt32();
@@ -351,7 +395,10 @@ namespace AssetStudio
}
m_Speed = reader.ReadSingle();
m_CycleOffset = reader.ReadSingle();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{
m_CycleOffset = reader.ReadSingle();
}
m_IKOnFeet = reader.ReadBoolean();
if (version[0] >= 5) //5.0 and up
{
@@ -359,8 +406,12 @@ namespace AssetStudio
}
m_Loop = reader.ReadBoolean();
m_Mirror = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{
m_Mirror = reader.ReadBoolean();
}
reader.AlignStream();
}
}
@@ -399,7 +450,7 @@ namespace AssetStudio
m_FullPathID = reader.ReadUInt32();
m_isEntry = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -414,6 +465,7 @@ namespace AssetStudio
public StateMachineConstant(ObjectReader reader)
{
var version = reader.version;
int numStates = reader.ReadInt32();
m_StateConstantArray = new StateConstant[numStates];
for (int i = 0; i < numStates; i++)
@@ -448,57 +500,52 @@ namespace AssetStudio
public bool[] m_BoolValues;
public int[] m_IntValues;
public float[] m_FloatValues;
public object[] m_PositionValues;
public Vector4[] m_VectorValues;
public Vector3[] m_PositionValues;
public Vector4[] m_QuaternionValues;
public object[] m_ScaleValues;
public Vector3[] m_ScaleValues;
public ValueArray(ObjectReader reader)
{
var version = reader.version;
if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
{
int numBools = reader.ReadInt32();
m_BoolValues = new bool[numBools];
for (int i = 0; i < numBools; i++)
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
m_IntValues = reader.ReadInt32Array();
m_FloatValues = reader.ReadSingleArray();
}
if (version[0] < 4 || (version[0] == 4 && version[1] < 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++)
{
m_BoolValues[i] = reader.ReadBoolean();
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
}
reader.AlignStream(4);
m_QuaternionValues = reader.ReadVector4Array();
m_IntValues = reader.ReadInt32Array(reader.ReadInt32());
m_FloatValues = reader.ReadSingleArray(reader.ReadInt32());
}
int numPosValues = reader.ReadInt32();
m_PositionValues = new object[numPosValues];
for (int i = 0; i < numPosValues; i++)
{
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 and up
}
m_QuaternionValues = reader.ReadVector4Array(reader.ReadInt32());
int numScaleValues = reader.ReadInt32();
m_ScaleValues = new object[numScaleValues];
for (int i = 0; i < numScaleValues; i++)
{
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? (object)reader.ReadVector3() : (object)reader.ReadVector4(); //5.4 adn up
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{
m_FloatValues = reader.ReadSingleArray(reader.ReadInt32());
m_IntValues = reader.ReadInt32Array(reader.ReadInt32());
int numBools = reader.ReadInt32();
m_BoolValues = new bool[numBools];
for (int i = 0; i < numBools; i++)
int numScaleValues = reader.ReadInt32();
m_ScaleValues = new Vector3[numScaleValues];
for (int i = 0; i < numScaleValues; i++)
{
m_BoolValues[i] = reader.ReadBoolean();
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
}
reader.AlignStream(4);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{
m_FloatValues = reader.ReadSingleArray();
m_IntValues = reader.ReadInt32Array();
m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream();
}
}
}
}
@@ -531,9 +578,9 @@ namespace AssetStudio
}
}
public sealed class AnimatorController : NamedObject
public sealed class AnimatorController : RuntimeAnimatorController
{
public PPtr[] m_AnimationClips;
public PPtr<AnimationClip>[] m_AnimationClips;
public AnimatorController(ObjectReader reader) : base(reader)
{
@@ -541,17 +588,17 @@ namespace AssetStudio
var m_Controller = new ControllerConstant(reader);
int tosSize = reader.ReadInt32();
var m_TOS = new List<KeyValuePair<uint, string>>(tosSize);
var m_TOS = new KeyValuePair<uint, string>[tosSize];
for (int i = 0; i < tosSize; i++)
{
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
}
int numClips = reader.ReadInt32();
m_AnimationClips = new PPtr[numClips];
m_AnimationClips = new PPtr<AnimationClip>[numClips];
for (int i = 0; i < numClips; i++)
{
m_AnimationClips[i] = reader.ReadPPtr();
m_AnimationClips[i] = new PPtr<AnimationClip>(reader);
}
}
}

View File

@@ -5,22 +5,32 @@ using System.Text;
namespace AssetStudio
{
public class AnimatorOverrideController : NamedObject
public class AnimationClipOverride
{
public PPtr m_Controller;
public PPtr[][] m_Clips;
public PPtr<AnimationClip> m_OriginalClip;
public PPtr<AnimationClip> m_OverrideClip;
public AnimationClipOverride(ObjectReader reader)
{
m_OriginalClip = new PPtr<AnimationClip>(reader);
m_OverrideClip = new PPtr<AnimationClip>(reader);
}
}
public sealed class AnimatorOverrideController : RuntimeAnimatorController
{
public PPtr<RuntimeAnimatorController> m_Controller;
public AnimationClipOverride[] m_Clips;
public AnimatorOverrideController(ObjectReader reader) : base(reader)
{
m_Controller = reader.ReadPPtr();
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
int numOverrides = reader.ReadInt32();
m_Clips = new PPtr[numOverrides][];
m_Clips = new AnimationClipOverride[numOverrides];
for (int i = 0; i < numOverrides; i++)
{
m_Clips[i] = new PPtr[2];
m_Clips[i][0] = reader.ReadPPtr();
m_Clips[i][1] = reader.ReadPPtr();
m_Clips[i] = new AnimationClipOverride(reader);
}
}
}

View File

@@ -5,41 +5,39 @@ using System.Text;
namespace AssetStudio
{
public class AssetInfo
{
public int preloadIndex;
public int preloadSize;
public PPtr<Object> asset;
public AssetInfo(ObjectReader reader)
{
preloadIndex = reader.ReadInt32();
preloadSize = reader.ReadInt32();
asset = new PPtr<Object>(reader);
}
}
public sealed class AssetBundle : NamedObject
{
public class AssetInfo
{
public int preloadIndex;
public int preloadSize;
public PPtr asset;
}
public class ContainerData
{
public string first;
public AssetInfo second;
}
public List<ContainerData> m_Container = new List<ContainerData>();
public PPtr<Object>[] m_PreloadTable;
public KeyValuePair<string, AssetInfo>[] m_Container;
public AssetBundle(ObjectReader reader) : base(reader)
{
var size = reader.ReadInt32();
for (int i = 0; i < size; i++)
var m_PreloadTableSize = reader.ReadInt32();
m_PreloadTable = new PPtr<Object>[m_PreloadTableSize];
for (int i = 0; i < m_PreloadTableSize; i++)
{
reader.ReadPPtr();
m_PreloadTable[i] = new PPtr<Object>(reader);
}
size = reader.ReadInt32();
for (int i = 0; i < size; i++)
var m_ContainerSize = reader.ReadInt32();
m_Container = new KeyValuePair<string, AssetInfo>[m_ContainerSize];
for (int i = 0; i < m_ContainerSize; i++)
{
var temp = new ContainerData();
temp.first = reader.ReadAlignedString();
temp.second = new AssetInfo();
temp.second.preloadIndex = reader.ReadInt32();
temp.second.preloadSize = reader.ReadInt32();
temp.second.asset = reader.ReadPPtr();
m_Container.Add(temp);
m_Container[i] = new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader));
}
}
}

View File

@@ -27,11 +27,11 @@ namespace AssetStudio
public AudioCompressionFormat m_CompressionFormat;
public string m_Source;
public long m_Offset;
public long m_Size;
public byte[] m_AudioData;
public long m_Offset; //ulong
public long m_Size; //ulong
public ResourceReader m_AudioData;
public AudioClip(ObjectReader reader, bool readData) : base(reader)
public AudioClip(ObjectReader reader) : base(reader)
{
if (version[0] < 5)
{
@@ -39,7 +39,7 @@ namespace AssetStudio
m_Type = (AudioType)reader.ReadInt32();
m_3D = reader.ReadBoolean();
m_UseHardware = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5
{
@@ -48,8 +48,8 @@ namespace AssetStudio
var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
{
m_Offset = reader.ReadInt32();
m_Source = sourceFile.fullName + ".resS";
m_Offset = reader.ReadUInt32();
m_Source = assetsFile.fullName + ".resS";
}
}
else
@@ -65,32 +65,30 @@ namespace AssetStudio
m_BitsPerSample = reader.ReadInt32();
m_Length = reader.ReadSingle();
m_IsTrackerFormat = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
m_SubsoundIndex = reader.ReadInt32();
m_PreloadAudioData = reader.ReadBoolean();
m_LoadInBackground = reader.ReadBoolean();
m_Legacy3D = reader.ReadBoolean();
reader.AlignStream(4);
m_3D = m_Legacy3D;
reader.AlignStream();
//StreamedResource m_Resource
m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64();
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
}
if (readData)
ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_Source))
{
if (!string.IsNullOrEmpty(m_Source))
{
m_AudioData = ResourcesHelper.GetData(m_Source, sourceFile, m_Offset, (int)m_Size);
}
else
{
if (m_Size > 0)
m_AudioData = reader.ReadBytes((int)m_Size);
}
resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_Size);
}
m_AudioData = resourceReader;
}
}

View File

@@ -1,5 +1,5 @@
using SharpDX;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
namespace AssetStudio
{
@@ -66,68 +66,53 @@ namespace AssetStudio
public class Skeleton
{
public List<Node> m_Node;
public List<uint> m_ID;
public List<Axes> m_AxesArray;
public Node[] m_Node;
public uint[] m_ID;
public Axes[] m_AxesArray;
public Skeleton(ObjectReader reader)
{
int numNodes = reader.ReadInt32();
m_Node = new List<Node>(numNodes);
m_Node = new Node[numNodes];
for (int i = 0; i < numNodes; i++)
{
m_Node.Add(new Node(reader));
m_Node[i] = new Node(reader);
}
int numIDs = reader.ReadInt32();
m_ID = new List<uint>(numIDs);
for (int i = 0; i < numIDs; i++)
{
m_ID.Add(reader.ReadUInt32());
}
m_ID = reader.ReadUInt32Array();
int numAxes = reader.ReadInt32();
m_AxesArray = new List<Axes>(numAxes);
m_AxesArray = new Axes[numAxes];
for (int i = 0; i < numAxes; i++)
{
m_AxesArray.Add(new Axes(reader));
m_AxesArray[i] = new Axes(reader);
}
}
}
public class SkeletonPose
{
public List<xform> m_X;
public SkeletonPose()
{
m_X = new List<xform>();
}
public xform[] m_X;
public SkeletonPose(ObjectReader reader)
{
int numXforms = reader.ReadInt32();
m_X = new List<xform>(numXforms);
m_X = new xform[numXforms];
for (int i = 0; i < numXforms; i++)
{
m_X.Add(new xform(reader));
m_X[i] = new xform(reader);
}
}
}
public class Hand
{
public List<int> m_HandBoneIndex;
public int[] m_HandBoneIndex;
public Hand(ObjectReader reader)
{
int numIndexes = reader.ReadInt32();
m_HandBoneIndex = new List<int>(numIndexes);
for (int i = 0; i < numIndexes; i++)
{
m_HandBoneIndex.Add(reader.ReadInt32());
}
m_HandBoneIndex = reader.ReadInt32Array();
}
}
@@ -178,11 +163,11 @@ namespace AssetStudio
public SkeletonPose m_SkeletonPose;
public Hand m_LeftHand;
public Hand m_RightHand;
public List<Handle> m_Handles;
public List<Collider> m_ColliderArray;
public List<int> m_HumanBoneIndex;
public List<float> m_HumanBoneMass;
public List<int> m_ColliderIndex;
public Handle[] m_Handles;
public Collider[] m_ColliderArray;
public int[] m_HumanBoneIndex;
public float[] m_HumanBoneMass;
public int[] m_ColliderIndex;
public float m_Scale;
public float m_ArmTwist;
public float m_ForeArmTwist;
@@ -207,42 +192,27 @@ namespace AssetStudio
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{
int numHandles = reader.ReadInt32();
m_Handles = new List<Handle>(numHandles);
m_Handles = new Handle[numHandles];
for (int i = 0; i < numHandles; i++)
{
m_Handles.Add(new Handle(reader));
m_Handles[i] = new Handle(reader);
}
int numColliders = reader.ReadInt32();
m_ColliderArray = new List<Collider>(numColliders);
m_ColliderArray = new Collider[numColliders];
for (int i = 0; i < numColliders; i++)
{
m_ColliderArray.Add(new Collider(reader));
m_ColliderArray[i] = new Collider(reader);
}
}
int numIndexes = reader.ReadInt32();
m_HumanBoneIndex = new List<int>(numIndexes);
for (int i = 0; i < numIndexes; i++)
{
m_HumanBoneIndex.Add(reader.ReadInt32());
}
m_HumanBoneIndex = reader.ReadInt32Array();
int numMasses = reader.ReadInt32();
m_HumanBoneMass = new List<float>(numMasses);
for (int i = 0; i < numMasses; i++)
{
m_HumanBoneMass.Add(reader.ReadSingle());
}
m_HumanBoneMass = reader.ReadSingleArray();
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{
int numColliderIndexes = reader.ReadInt32();
m_ColliderIndex = new List<int>(numColliderIndexes);
for (int i = 0; i < numColliderIndexes; i++)
{
m_ColliderIndex.Add(reader.ReadInt32());
}
m_ColliderIndex = reader.ReadInt32Array();
}
m_Scale = reader.ReadSingle();
@@ -255,8 +225,11 @@ namespace AssetStudio
m_FeetSpacing = reader.ReadSingle();
m_HasLeftHand = reader.ReadBoolean();
m_HasRightHand = reader.ReadBoolean();
m_HasTDoF = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{
m_HasTDoF = reader.ReadBoolean();
}
reader.AlignStream();
}
}
@@ -265,15 +238,15 @@ namespace AssetStudio
public Skeleton m_AvatarSkeleton;
public SkeletonPose m_AvatarSkeletonPose;
public SkeletonPose m_DefaultPose;
public List<uint> m_SkeletonNameIDArray;
public uint[] m_SkeletonNameIDArray;
public Human m_Human;
public List<int> m_HumanSkeletonIndexArray;
public List<int> m_HumanSkeletonReverseIndexArray;
public int[] m_HumanSkeletonIndexArray;
public int[] m_HumanSkeletonReverseIndexArray;
public int m_RootMotionBoneIndex;
public xform m_RootMotionBoneX;
public Skeleton m_RootMotionSkeleton;
public SkeletonPose m_RootMotionSkeletonPose;
public List<int> m_RootMotionSkeletonIndexArray;
public int[] m_RootMotionSkeletonIndexArray;
public AvatarConstant(ObjectReader reader)
{
@@ -284,31 +257,17 @@ namespace AssetStudio
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
m_DefaultPose = new SkeletonPose(reader);
int numIDs = reader.ReadInt32();
m_SkeletonNameIDArray = new List<uint>(numIDs);
for (int i = 0; i < numIDs; i++)
{
m_SkeletonNameIDArray.Add(reader.ReadUInt32());
}
m_SkeletonNameIDArray = reader.ReadUInt32Array();
}
m_Human = new Human(reader);
int numIndexes = reader.ReadInt32();
m_HumanSkeletonIndexArray = new List<int>(numIndexes);
for (int i = 0; i < numIndexes; i++)
{
m_HumanSkeletonIndexArray.Add(reader.ReadInt32());
}
m_HumanSkeletonIndexArray = reader.ReadInt32Array();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
int numReverseIndexes = reader.ReadInt32();
m_HumanSkeletonReverseIndexArray = new List<int>(numReverseIndexes);
for (int i = 0; i < numReverseIndexes; i++)
{
m_HumanSkeletonReverseIndexArray.Add(reader.ReadInt32());
}
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
}
m_RootMotionBoneIndex = reader.ReadInt32();
@@ -319,12 +278,7 @@ namespace AssetStudio
m_RootMotionSkeleton = new Skeleton(reader);
m_RootMotionSkeletonPose = new SkeletonPose(reader);
int numMotionIndexes = reader.ReadInt32();
m_RootMotionSkeletonIndexArray = new List<int>(numMotionIndexes);
for (int i = 0; i < numMotionIndexes; i++)
{
m_RootMotionSkeletonIndexArray.Add(reader.ReadInt32());
}
m_RootMotionSkeletonIndexArray = reader.ReadInt32Array();
}
}
}
@@ -333,7 +287,7 @@ namespace AssetStudio
{
public uint m_AvatarSize;
public AvatarConstant m_Avatar;
public List<KeyValuePair<uint, string>> m_TOS;
public KeyValuePair<uint, string>[] m_TOS;
public Avatar(ObjectReader reader) : base(reader)
{
@@ -341,28 +295,18 @@ namespace AssetStudio
m_Avatar = new AvatarConstant(reader);
int numTOS = reader.ReadInt32();
m_TOS = new List<KeyValuePair<uint, string>>(numTOS);
m_TOS = new KeyValuePair<uint, string>[numTOS];
for (int i = 0; i < numTOS; i++)
{
m_TOS.Add(new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString()));
m_TOS[i] = new KeyValuePair<uint, string>(reader.ReadUInt32(), reader.ReadAlignedString());
}
}
public string FindBoneName(uint hash)
{
foreach (var pair in m_TOS)
{
if (pair.Key == hash)
{
return pair.Value.Substring(pair.Value.LastIndexOf('/') + 1);
}
}
return null;
//HumanDescription m_HumanDescription 2019 and up
}
public string FindBonePath(uint hash)
{
return m_TOS.Find(pair => pair.Key == hash).Value;
return m_TOS.FirstOrDefault(pair => pair.Key == hash).Value;
}
}
}

View File

@@ -12,7 +12,7 @@ namespace AssetStudio
protected Behaviour(ObjectReader reader) : base(reader)
{
m_Enabled = reader.ReadByte();
reader.AlignStream(4);
reader.AlignStream();
}
}
}

View File

@@ -11,11 +11,7 @@ namespace AssetStudio
public BuildSettings(ObjectReader reader) : base(reader)
{
int levelsNum = reader.ReadInt32();
for (int i = 0; i < levelsNum; i++)
{
var level = reader.ReadAlignedString();
}
var levels = reader.ReadStringArray();
var hasRenderTexture = reader.ReadBoolean();
var hasPROVersion = reader.ReadBoolean();

View File

@@ -7,11 +7,11 @@ namespace AssetStudio
{
public abstract class Component : EditorExtension
{
public PPtr m_GameObject;
public PPtr<GameObject> m_GameObject;
protected Component(ObjectReader reader) : base(reader)
{
m_GameObject = reader.ReadPPtr();
m_GameObject = new PPtr<GameObject>(reader);
}
}
}

View File

@@ -11,8 +11,8 @@ namespace AssetStudio
{
if (platform == BuildTarget.NoTarget)
{
var m_PrefabParentObject = reader.ReadPPtr();
var m_PrefabInternal = reader.ReadPPtr();
var m_PrefabParentObject = new PPtr<EditorExtension>(reader);
var m_PrefabInternal = new PPtr<Object>(reader); //PPtr<Prefab>
}
}
}

View File

@@ -14,9 +14,9 @@ namespace AssetStudio
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
{
var m_LineSpacing = reader.ReadSingle();
var m_DefaultMaterial = reader.ReadPPtr();
var m_DefaultMaterial = new PPtr<Material>(reader);
var m_FontSize = reader.ReadSingle();
var m_Texture = reader.ReadPPtr();
var m_Texture = new PPtr<Texture>(reader);
int m_AsciiStartOffset = reader.ReadInt32();
var m_Tracking = reader.ReadSingle();
var m_CharacterSpacing = reader.ReadInt32();
@@ -68,7 +68,7 @@ namespace AssetStudio
}
int m_ConvertCase = reader.ReadInt32();
PPtr m_DefaultMaterial = reader.ReadPPtr();
var m_DefaultMaterial = new PPtr<Material>(reader);
int m_CharacterRects_size = reader.ReadInt32();
for (int i = 0; i < m_CharacterRects_size; i++)
@@ -89,11 +89,11 @@ namespace AssetStudio
if (version[0] >= 4)
{
var flipped = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
PPtr m_Texture = reader.ReadPPtr();
var m_Texture = new PPtr<Texture>(reader);
int m_KerningValues_size = reader.ReadInt32();
for (int i = 0; i < m_KerningValues_size; i++)
@@ -106,7 +106,7 @@ namespace AssetStudio
if (version[0] <= 3)
{
var m_GridFont = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
else { float m_PixelScale = reader.ReadSingle(); }

View File

@@ -7,29 +7,27 @@ namespace AssetStudio
{
public sealed class GameObject : EditorExtension
{
public List<PPtr> m_Components;
public PPtr<Component>[] m_Components;
public string m_Name;
public PPtr m_Transform;
public PPtr m_MeshRenderer;
public PPtr m_MeshFilter;
public PPtr m_SkinnedMeshRenderer;
public PPtr m_Animator;
public Transform m_Transform;
public MeshRenderer m_MeshRenderer;
public MeshFilter m_MeshFilter;
public SkinnedMeshRenderer m_SkinnedMeshRenderer;
public Animator m_Animator;
public Animation m_Animation;
public GameObject(ObjectReader reader) : base(reader)
{
int m_Component_size = reader.ReadInt32();
m_Components = new List<PPtr>(m_Component_size);
for (int j = 0; j < m_Component_size; j++)
m_Components = new PPtr<Component>[m_Component_size];
for (int i = 0; i < m_Component_size; i++)
{
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5.0 and up
{
m_Components.Add(reader.ReadPPtr());
}
else
if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down
{
int first = reader.ReadInt32();
m_Components.Add(reader.ReadPPtr());
}
m_Components[i] = new PPtr<Component>(reader);
}
var m_Layer = reader.ReadInt32();

View File

@@ -1,117 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{
public class TexEnv
public class UnityTexEnv
{
public string name;
public PPtr m_Texture;
public float[] m_Scale;
public float[] m_Offset;
public PPtr<Texture> m_Texture;
public Vector2 m_Scale;
public Vector2 m_Offset;
public UnityTexEnv(ObjectReader reader)
{
m_Texture = new PPtr<Texture>(reader);
m_Scale = reader.ReadVector2();
m_Offset = reader.ReadVector2();
}
}
public class strFloatPair
public class UnityPropertySheet
{
public string first;
public float second;
}
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 class strColorPair
{
public string first;
public float[] second;
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[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
}
if (version[0] >= 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[i] = 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[i] = 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[i] = new KeyValuePair<string, Color>(reader.ReadAlignedString(), reader.ReadColor4());
}
}
}
public sealed class Material : NamedObject
{
public PPtr m_Shader;
public string[] m_ShaderKeywords;
public int m_CustomRenderQueue;
public TexEnv[] m_TexEnvs;
public strFloatPair[] m_Floats;
public strColorPair[] m_Colors;
public PPtr<Shader> m_Shader;
public UnityPropertySheet m_SavedProperties;
public Material(ObjectReader reader) : base(reader)
{
m_Shader = reader.ReadPPtr();
m_Shader = new PPtr<Shader>(reader);
if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && !buildType.IsAlpha)))
if (version[0] == 4 && version[1] >= 1) //4.x
{
m_ShaderKeywords = new string[reader.ReadInt32()];
for (int i = 0; i < m_ShaderKeywords.Length; i++)
{
m_ShaderKeywords[i] = reader.ReadAlignedString();
}
var m_ShaderKeywords = reader.ReadStringArray();
}
else if (version[0] >= 5)//5.0 and up
if (version[0] >= 5) //5.0 and up
{
m_ShaderKeywords = new[] { reader.ReadAlignedString() };
uint m_LightmapFlags = reader.ReadUInt32();
if (version[0] == 5 && version[1] >= 6 || version[0] > 5)//5.6.0 and up
var m_ShaderKeywords = reader.ReadAlignedString();
var m_LightmapFlags = reader.ReadUInt32();
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 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
{
var m_CustomRenderQueue = reader.ReadInt32();
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
{
var stringTagMapSize = reader.ReadInt32();
for (int i = 0; i < stringTagMapSize; i++)
{
var m_EnableInstancingVariants = reader.ReadBoolean();
//var m_DoubleSidedGI = a_Stream.ReadBoolean();//2017.x
reader.AlignStream(4);
var first = reader.ReadAlignedString();
var second = reader.ReadAlignedString();
}
}
if (version[0] > 4 || version[0] == 4 && version[1] >= 3) { m_CustomRenderQueue = reader.ReadInt32(); }
if (version[0] == 5 && version[1] >= 1 || version[0] > 5)//5.1 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{
string[][] stringTagMap = new string[reader.ReadInt32()][];
for (int i = 0; i < stringTagMap.Length; i++)
{
stringTagMap[i] = new[] { reader.ReadAlignedString(), reader.ReadAlignedString() };
}
}
//disabledShaderPasses
if ((version[0] == 5 && version[1] >= 6) || version[0] > 5)//5.6.0 and up
{
var size = reader.ReadInt32();
for (int i = 0; i < size; i++)
{
reader.ReadAlignedString();
}
}
//m_SavedProperties
m_TexEnvs = new TexEnv[reader.ReadInt32()];
for (int i = 0; i < m_TexEnvs.Length; i++)
{
TexEnv m_TexEnv = new TexEnv()
{
name = reader.ReadAlignedString(),
m_Texture = reader.ReadPPtr(),
m_Scale = new[] { reader.ReadSingle(), reader.ReadSingle() },
m_Offset = new[] { reader.ReadSingle(), reader.ReadSingle() }
};
m_TexEnvs[i] = m_TexEnv;
var disabledShaderPasses = reader.ReadStringArray();
}
m_Floats = new strFloatPair[reader.ReadInt32()];
for (int i = 0; i < m_Floats.Length; i++)
{
strFloatPair m_Float = new strFloatPair()
{
first = reader.ReadAlignedString(),
second = reader.ReadSingle()
};
m_Floats[i] = m_Float;
}
m_SavedProperties = new UnityPropertySheet(reader);
m_Colors = new strColorPair[reader.ReadInt32()];
for (int i = 0; i < m_Colors.Length; i++)
{
strColorPair m_Color = new strColorPair()
{
first = reader.ReadAlignedString(),
second = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() }
};
m_Colors[i] = m_Color;
}
//vector m_BuildTextureStacks 2020 and up
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,12 +7,11 @@ namespace AssetStudio
{
public sealed class MeshFilter : Component
{
public long preloadIndex;
public PPtr m_Mesh;
public PPtr<Mesh> m_Mesh;
public MeshFilter(ObjectReader reader) : base(reader)
{
m_Mesh = reader.ReadPPtr();
m_Mesh = new PPtr<Mesh>(reader);
}
}
}

View File

@@ -7,12 +7,12 @@ namespace AssetStudio
{
public sealed class MonoBehaviour : Behaviour
{
public PPtr m_Script;
public PPtr<MonoScript> m_Script;
public string m_Name;
public MonoBehaviour(ObjectReader reader) : base(reader)
{
m_Script = reader.ReadPPtr();
m_Script = new PPtr<MonoScript>(reader);
m_Name = reader.ReadAlignedString();
}
}

View File

@@ -8,7 +8,7 @@ namespace AssetStudio
public sealed class MonoScript : NamedObject
{
public string m_ClassName;
public string m_Namespace = string.Empty;
public string m_Namespace;
public string m_AssemblyName;
public MonoScript(ObjectReader reader) : base(reader)

View File

@@ -8,14 +8,14 @@ namespace AssetStudio
public sealed class MovieTexture : Texture
{
public byte[] m_MovieData;
public PPtr<AudioClip> m_AudioClip;
public MovieTexture(ObjectReader reader) : base(reader)
{
var m_Loop = reader.ReadBoolean();
reader.AlignStream(4);
//PPtr<AudioClip>
reader.ReadPPtr();
m_MovieData = reader.ReadBytes(reader.ReadInt32());
reader.AlignStream();
m_AudioClip = new PPtr<AudioClip>(reader);
m_MovieData = reader.ReadUInt8Array();
}
}
}

View File

@@ -9,7 +9,7 @@ namespace AssetStudio
{
public string m_Name;
public NamedObject(ObjectReader reader) : base(reader)
protected NamedObject(ObjectReader reader) : base(reader)
{
m_Name = reader.ReadAlignedString();
}

View File

@@ -1,31 +1,78 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
namespace AssetStudio
{
public abstract class Object
public class Object
{
protected SerializedFile sourceFile;
public SerializedFile assetsFile;
public ObjectReader reader;
public long m_PathID;
public int[] version;
protected BuildType buildType;
public BuildTarget platform;
public ClassIDType type;
public SerializedType serializedType;
public uint byteSize;
protected Object(ObjectReader reader)
public Object(ObjectReader reader)
{
this.reader = reader;
reader.Reset();
sourceFile = reader.assetsFile;
assetsFile = reader.assetsFile;
type = reader.type;
m_PathID = reader.m_PathID;
version = reader.version;
buildType = reader.buildType;
platform = reader.platform;
serializedType = reader.serializedType;
byteSize = reader.byteSize;
if (platform == BuildTarget.NoTarget)
{
var m_ObjectHideFlags = reader.ReadUInt32();
}
}
public string Dump()
{
if (serializedType?.m_Type != null)
{
return TypeTreeHelper.ReadTypeString(serializedType.m_Type, reader);
}
return null;
}
public string Dump(TypeTree m_Type)
{
if (m_Type != null)
{
return TypeTreeHelper.ReadTypeString(m_Type, reader);
}
return null;
}
public OrderedDictionary ToType()
{
if (serializedType?.m_Type != null)
{
return TypeTreeHelper.ReadType(serializedType.m_Type, reader);
}
return null;
}
public OrderedDictionary ToType(TypeTree m_Type)
{
if (m_Type != null)
{
return TypeTreeHelper.ReadType(m_Type, reader);
}
return null;
}
public byte[] GetRawData()
{
reader.Reset();
return reader.ReadBytes((int)byteSize);
}
}
}

View File

@@ -1,12 +1,21 @@
namespace AssetStudio
using System;
namespace AssetStudio
{
public class PPtr
public sealed class PPtr<T> where T : Object
{
public int m_FileID;
public long m_PathID;
public SerializedFile assetsFile;
public int index = -2; //-2 - Prepare, -1 - Missing
private SerializedFile assetsFile;
private int index = -2; //-2 - Prepare, -1 - Missing
public PPtr(ObjectReader reader)
{
m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < SerializedFileFormatVersion.kUnknown_14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile;
}
private bool TryGetAssetsFile(out SerializedFile result)
{
@@ -20,23 +29,23 @@
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
{
var assetsManager = assetsFile.assetsManager;
var assetsfileList = assetsManager.assetsFileList;
var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (index == -2)
{
var m_External = assetsFile.m_Externals[m_FileID - 1];
var name = m_External.fileName.ToUpper();
var name = m_External.fileName;
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsfileList.FindIndex(x => x.upperFileName == name);
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, index);
}
}
if (index >= 0)
{
result = assetsfileList[index];
result = assetsFileList[index];
return true;
}
}
@@ -44,46 +53,79 @@
return false;
}
public bool TryGet(out ObjectReader result)
public bool TryGet(out T result)
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
{
if (obj is T variable)
{
result = variable;
return true;
}
}
}
result = null;
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.ObjectReaders.TryGetValue(m_PathID, out result))
{
return true;
}
}
return false;
}
public bool TryGetTransform(out Transform m_Transform)
public bool TryGet<T2>(out T2 result) where T2 : Object
{
if (TryGetAssetsFile(out var sourceFile))
{
if (sourceFile.Transforms.TryGetValue(m_PathID, out m_Transform))
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
{
return true;
if (obj is T2 variable)
{
result = variable;
return true;
}
}
}
m_Transform = null;
result = null;
return false;
}
public bool TryGetGameObject(out GameObject m_GameObject)
public void Set(T m_Object)
{
if (TryGetAssetsFile(out var sourceFile))
var name = m_Object.assetsFile.fileName;
if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
{
if (sourceFile.GameObjects.TryGetValue(m_PathID, out m_GameObject))
m_FileID = 0;
}
else
{
m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
if (m_FileID == -1)
{
return true;
assetsFile.m_Externals.Add(new FileIdentifier
{
fileName = m_Object.assetsFile.fileName
});
m_FileID = assetsFile.m_Externals.Count;
}
else
{
m_FileID += 1;
}
}
m_GameObject = null;
return false;
var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (!assetsFileIndexCache.TryGetValue(name, out index))
{
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, index);
}
m_PathID = m_Object.m_PathID;
}
public bool IsNull => m_PathID == 0 || m_FileID < 0;
}
}

View File

@@ -20,7 +20,7 @@ namespace AssetStudio
var AndroidProfiler = reader.ReadBoolean();
//bool AndroidFilterTouchesWhenObscured 2017.2 and up
//bool AndroidEnableSustainedPerformanceMode 2018 and up
reader.AlignStream(4);
reader.AlignStream();
int defaultScreenOrientation = reader.ReadInt32();
int targetDevice = reader.ReadInt32();
if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down
@@ -38,7 +38,7 @@ namespace AssetStudio
else
{
var useOnDemandResources = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
{

View File

@@ -9,107 +9,147 @@ namespace AssetStudio
{
public ushort firstSubMesh;
public ushort subMeshCount;
public StaticBatchInfo(ObjectReader reader)
{
firstSubMesh = reader.ReadUInt16();
subMeshCount = reader.ReadUInt16();
}
}
public abstract class Renderer : Component
{
public PPtr[] m_Materials;
public PPtr<Material>[] m_Materials;
public StaticBatchInfo m_StaticBatchInfo;
public uint[] m_SubsetIndices;
protected Renderer(ObjectReader reader) : base(reader)
{
if (version[0] < 5)
if (version[0] < 5) //5.0 down
{
var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadByte();
var m_CastShadows = reader.ReadBoolean();
var m_ReceiveShadows = reader.ReadBoolean();
var m_LightmapIndex = reader.ReadByte();
}
else
else //5.0 and up
{
var m_Enabled = reader.ReadBoolean();
reader.AlignStream(4);
var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] >= 2018)//2018 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 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
{
var m_DynamicOccludee = reader.ReadByte();
}
if (version[0] >= 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
{
var m_RayTracingMode = reader.ReadByte();
}
if (version[0] >= 2020) //2020.1 and up
{
var m_RayTraceProcedural = reader.ReadByte();
}
reader.AlignStream();
}
else
{
var m_Enabled = reader.ReadBoolean();
reader.AlignStream();
var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadBoolean();
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
{
var m_RenderingLayerMask = reader.ReadUInt32();
}
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
{
var m_RendererPriority = reader.ReadInt32();
}
var m_LightmapIndex = reader.ReadUInt16();
var m_LightmapIndexDynamic = reader.ReadUInt16();
}
if (version[0] >= 3)
if (version[0] >= 3) //3.0 and up
{
reader.Position += 16;//Vector4f m_LightmapTilingOffset
var m_LightmapTilingOffset = reader.ReadVector4();
}
if (version[0] >= 5)
if (version[0] >= 5) //5.0 and up
{
reader.Position += 16;//Vector4f m_LightmapTilingOffsetDynamic
var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
}
m_Materials = new PPtr[reader.ReadInt32()];
for (int m = 0; m < m_Materials.Length; m++)
var m_MaterialsSize = reader.ReadInt32();
m_Materials = new PPtr<Material>[m_MaterialsSize];
for (int i = 0; i < m_MaterialsSize; i++)
{
m_Materials[m] = reader.ReadPPtr();
m_Materials[i] = new PPtr<Material>(reader);
}
if (version[0] < 3)
if (version[0] < 3) //3.0 down
{
reader.Position += 16;//m_LightmapTilingOffset vector4d
var m_LightmapTilingOffset = reader.ReadVector4();
}
else
else //3.0 and up
{
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5.0 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{
m_StaticBatchInfo = new StaticBatchInfo
{
firstSubMesh = reader.ReadUInt16(),
subMeshCount = reader.ReadUInt16()
};
m_StaticBatchInfo = new StaticBatchInfo(reader);
}
else
{
int numSubsetIndices = reader.ReadInt32();
m_SubsetIndices = reader.ReadUInt32Array(numSubsetIndices);
m_SubsetIndices = reader.ReadUInt32Array();
}
var m_StaticBatchRoot = reader.ReadPPtr();
var m_StaticBatchRoot = new PPtr<Transform>(reader);
}
if ((version[0] == 5 && version[1] >= 4) || version[0] > 5)//5.4.0 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 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
{
var m_UseLightProbes = reader.ReadBoolean();
reader.AlignStream();
if (version[0] >= 5)//5.0 and up
{
var m_ProbeAnchor = reader.ReadPPtr();
var m_LightProbeVolumeOverride = reader.ReadPPtr();
}
else if (version[0] >= 4 || (version[0] == 3 && version[1] >= 5))//3.5 - 5.3
{
var m_UseLightProbes = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] == 5)//5.0 and up
{
int m_ReflectionProbeUsage = reader.ReadInt32();
}
var m_LightProbeAnchor = reader.ReadPPtr();
var m_ReflectionProbeUsage = reader.ReadInt32();
}
if (version[0] >= 5 || (version[0] == 4 && version[1] >= 3))//4.3 and up
{
if (version[0] == 4 && version[1] == 3)//4.3
{
int m_SortingLayer = reader.ReadInt16();
}
else
{
int m_SortingLayerID = reader.ReadInt32();
//SInt16 m_SortingOrder 5.6 and up
}
var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor
}
int m_SortingOrder = reader.ReadInt16();
reader.AlignStream(4);
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
if (version[0] == 4 && version[1] == 3) //4.3
{
var m_SortingLayer = reader.ReadInt16();
}
else
{
var m_SortingLayerID = reader.ReadUInt32();
}
//SInt16 m_SortingLayer 5.6 and up
var m_SortingOrder = reader.ReadInt16();
reader.AlignStream();
}
}
}

View File

@@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace AssetStudio
{
public class ResourceManager : Object
{
public 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[i] = new KeyValuePair<string, PPtr<Object>>(reader.ReadAlignedString(), new PPtr<Object>(reader));
}
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public abstract class RuntimeAnimatorController : NamedObject
{
protected RuntimeAnimatorController(ObjectReader reader) : base(reader)
{
}
}
}

View File

@@ -1,13 +1,24 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AssetStudio
{
public class Hash128
{
public byte[] bytes;
public Hash128(BinaryReader reader)
{
bytes = reader.ReadBytes(16);
}
}
public class StructParameter
{
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public MatrixParameter[] m_MatrixParams;
public VectorParameter[] m_VectorParams;
public StructParameter(BinaryReader reader)
{
@@ -17,17 +28,17 @@ namespace AssetStudio
var m_StructSize = reader.ReadInt32();
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
m_VectorParams[i] = new VectorParameter(reader);
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
m_MatrixParams[i] = new MatrixParameter(reader);
}
}
}
@@ -81,49 +92,35 @@ namespace AssetStudio
{
public string m_Name;
public string m_Description;
public List<string> m_Attributes;
public string[] m_Attributes;
public SerializedPropertyType m_Type;
public uint m_Flags;
public List<float> m_DefValue;
public float[] m_DefValue;
public SerializedTextureProperty m_DefTexture;
public SerializedProperty(BinaryReader reader)
{
m_Name = reader.ReadAlignedString();
m_Description = reader.ReadAlignedString();
int numAttributes = reader.ReadInt32();
m_Attributes = new List<string>(numAttributes);
for (int i = 0; i < numAttributes; i++)
{
m_Attributes.Add(reader.ReadAlignedString());
}
m_Attributes = reader.ReadStringArray();
m_Type = (SerializedPropertyType)reader.ReadInt32();
m_Flags = reader.ReadUInt32();
int numValues = 4;
m_DefValue = new List<float>(numValues);
for (int i = 0; i < numValues; i++)
{
m_DefValue.Add(reader.ReadSingle());
}
m_DefValue = reader.ReadSingleArray(4);
m_DefTexture = new SerializedTextureProperty(reader);
}
}
public class SerializedProperties
{
public List<SerializedProperty> m_Props;
public SerializedProperty[] m_Props;
public SerializedProperties(BinaryReader reader)
{
int numProps = reader.ReadInt32();
m_Props = new List<SerializedProperty>(numProps);
m_Props = new SerializedProperty[numProps];
for (int i = 0; i < numProps; i++)
{
m_Props.Add(new SerializedProperty(reader));
m_Props[i] = new SerializedProperty(reader);
}
}
}
@@ -202,26 +199,19 @@ namespace AssetStudio
kFogDisabled = 0,
kFogLinear = 1,
kFogExp = 2,
kFogExp2 = 3,
kFogModeCount = 4
kFogExp2 = 3
};
public class SerializedShaderState
{
public string m_Name;
public SerializedShaderRTBlendState rtBlend0;
public SerializedShaderRTBlendState rtBlend1;
public SerializedShaderRTBlendState rtBlend2;
public SerializedShaderRTBlendState rtBlend3;
public SerializedShaderRTBlendState rtBlend4;
public SerializedShaderRTBlendState rtBlend5;
public SerializedShaderRTBlendState rtBlend6;
public SerializedShaderRTBlendState rtBlend7;
public SerializedShaderRTBlendState[] rtBlend;
public bool rtSeparateBlend;
public SerializedShaderFloatValue zClip;
public SerializedShaderFloatValue zTest;
public SerializedShaderFloatValue zWrite;
public SerializedShaderFloatValue culling;
public SerializedShaderFloatValue conservative;
public SerializedShaderFloatValue offsetFactor;
public SerializedShaderFloatValue offsetUnits;
public SerializedShaderFloatValue alphaToMask;
@@ -246,16 +236,13 @@ namespace AssetStudio
var version = reader.version;
m_Name = reader.ReadAlignedString();
rtBlend0 = new SerializedShaderRTBlendState(reader);
rtBlend1 = new SerializedShaderRTBlendState(reader);
rtBlend2 = new SerializedShaderRTBlendState(reader);
rtBlend3 = new SerializedShaderRTBlendState(reader);
rtBlend4 = new SerializedShaderRTBlendState(reader);
rtBlend5 = new SerializedShaderRTBlendState(reader);
rtBlend6 = new SerializedShaderRTBlendState(reader);
rtBlend7 = new SerializedShaderRTBlendState(reader);
rtBlend = new SerializedShaderRTBlendState[8];
for (int i = 0; i < 8; i++)
{
rtBlend[i] = new SerializedShaderRTBlendState(reader);
}
rtSeparateBlend = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
zClip = new SerializedShaderFloatValue(reader);
@@ -263,6 +250,10 @@ namespace AssetStudio
zTest = new SerializedShaderFloatValue(reader);
zWrite = new SerializedShaderFloatValue(reader);
culling = new SerializedShaderFloatValue(reader);
if (version[0] >= 2020) //2020.1 and up
{
conservative = new SerializedShaderFloatValue(reader);
}
offsetFactor = new SerializedShaderFloatValue(reader);
offsetUnits = new SerializedShaderFloatValue(reader);
alphaToMask = new SerializedShaderFloatValue(reader);
@@ -281,7 +272,7 @@ namespace AssetStudio
m_Tags = new SerializedTagMap(reader);
m_LOD = reader.ReadInt32();
lighting = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -299,18 +290,18 @@ namespace AssetStudio
public class ParserBindChannels
{
public List<ShaderBindChannel> m_Channels;
public ShaderBindChannel[] m_Channels;
public uint m_SourceMap;
public ParserBindChannels(BinaryReader reader)
{
int numChannels = reader.ReadInt32();
m_Channels = new List<ShaderBindChannel>(numChannels);
m_Channels = new ShaderBindChannel[numChannels];
for (int i = 0; i < numChannels; i++)
{
m_Channels.Add(new ShaderBindChannel(reader));
m_Channels[i] = new ShaderBindChannel(reader);
}
reader.AlignStream(4);
reader.AlignStream();
m_SourceMap = reader.ReadUInt32();
}
@@ -331,7 +322,7 @@ namespace AssetStudio
m_ArraySize = reader.ReadInt32();
m_Type = reader.ReadSByte();
m_Dim = reader.ReadSByte();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -350,7 +341,7 @@ namespace AssetStudio
m_ArraySize = reader.ReadInt32();
m_Type = reader.ReadSByte();
m_RowCount = reader.ReadSByte();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -373,7 +364,7 @@ namespace AssetStudio
var m_MultiSampled = reader.ReadBoolean();
}
m_Dim = reader.ReadSByte();
reader.AlignStream(4);
reader.AlignStream();
}
}
@@ -381,21 +372,29 @@ namespace AssetStudio
{
public int m_NameIndex;
public int m_Index;
public int m_ArraySize;
public BufferBinding(BinaryReader reader)
public BufferBinding(ObjectReader reader)
{
var version = reader.version;
m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32();
if (version[0] >= 2020) //2020.1 and up
{
m_ArraySize = reader.ReadInt32();
}
}
}
public class ConstantBuffer
{
public int m_NameIndex;
public List<MatrixParameter> m_MatrixParams;
public List<VectorParameter> m_VectorParams;
public List<StructParameter> m_StructParams;
public MatrixParameter[] m_MatrixParams;
public VectorParameter[] m_VectorParams;
public StructParameter[] m_StructParams;
public int m_Size;
public bool m_IsPartialCB;
public ConstantBuffer(ObjectReader reader)
{
@@ -404,28 +403,37 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32();
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
m_MatrixParams[i] = new MatrixParameter(reader);
}
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
m_VectorParams[i] = new VectorParameter(reader);
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{
int numStructParams = reader.ReadInt32();
m_StructParams = new List<StructParameter>(numStructParams);
m_StructParams = new StructParameter[numStructParams];
for (int i = 0; i < numStructParams; i++)
{
m_StructParams.Add(new StructParameter(reader));
m_StructParams[i] = 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[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{
m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream();
}
}
}
@@ -471,24 +479,101 @@ namespace AssetStudio
kShaderGpuProgramMetalVS = 23,
kShaderGpuProgramMetalFS = 24,
kShaderGpuProgramSPIRV = 25,
kShaderGpuProgramConsole = 26,
kShaderGpuProgramConsoleVS = 26,
kShaderGpuProgramConsoleFS = 27,
kShaderGpuProgramConsoleHS = 28,
kShaderGpuProgramConsoleDS = 29,
kShaderGpuProgramConsoleGS = 30,
kShaderGpuProgramRayTracing = 31,
};
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 SerializedProgramParameters(ObjectReader reader)
{
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++)
{
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);
}
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
{
m_Samplers[i] = new SamplerParameter(reader);
}
}
}
public class SerializedSubProgram
{
public uint m_BlobIndex;
public ParserBindChannels m_Channels;
public List<ushort> m_KeywordIndices;
public ushort[] m_KeywordIndices;
public sbyte m_ShaderHardwareTier;
public ShaderGpuProgramType m_GpuProgramType;
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 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 SerializedSubProgram(ObjectReader reader)
{
@@ -497,96 +582,131 @@ namespace AssetStudio
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
int numIndices = reader.ReadInt32();
m_KeywordIndices = new List<ushort>(numIndices);
for (int i = 0; i < numIndices; i++)
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
{
m_KeywordIndices.Add(reader.ReadUInt16());
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
var m_LocalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
}
if (version[0] >= 2017) //2017 and up
else
{
reader.AlignStream(4);
}
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream(4);
int numVectorParams = reader.ReadInt32();
m_VectorParams = new List<VectorParameter>(numVectorParams);
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams.Add(new VectorParameter(reader));
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new List<MatrixParameter>(numMatrixParams);
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams.Add(new MatrixParameter(reader));
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new List<TextureParameter>(numTextureParams);
for (int i = 0; i < numTextureParams; i++)
{
m_TextureParams.Add(new TextureParameter(reader));
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new List<BufferBinding>(numBufferParams);
for (int i = 0; i < numBufferParams; i++)
{
m_BufferParams.Add(new BufferBinding(reader));
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new List<ConstantBuffer>(numConstantBuffers);
for (int i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers.Add(new ConstantBuffer(reader));
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new List<BufferBinding>(numConstantBufferBindings);
for (int i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings.Add(new BufferBinding(reader));
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new List<UAVParameter>(numUAVParams);
for (int i = 0; i < numUAVParams; i++)
{
m_UAVParams.Add(new UAVParameter(reader));
}
if (version[0] >= 2017) //2017 and up
{
int numSamplers = reader.ReadInt32();
m_Samplers = new List<SamplerParameter>(numSamplers);
for (int i = 0; i < numSamplers; i++)
m_KeywordIndices = reader.ReadUInt16Array();
if (version[0] >= 2017) //2017 and up
{
m_Samplers.Add(new SamplerParameter(reader));
reader.AlignStream();
}
}
m_ShaderHardwareTier = reader.ReadSByte();
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[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 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++)
{
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
{
var m_ShaderRequirements = reader.ReadInt32();
if (version[0] >= 2021) //2021.1 and up
{
var m_ShaderRequirements = reader.ReadInt64();
}
else
{
var m_ShaderRequirements = reader.ReadInt32();
}
}
}
}
public class SerializedProgram
{
public List<SerializedSubProgram> m_SubPrograms;
public SerializedSubProgram[] m_SubPrograms;
public SerializedProgramParameters m_CommonParameters;
public SerializedProgram(ObjectReader reader)
{
var version = reader.version;
int numSubPrograms = reader.ReadInt32();
m_SubPrograms = new List<SerializedSubProgram>(numSubPrograms);
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
for (int i = 0; i < numSubPrograms; i++)
{
m_SubPrograms.Add(new SerializedSubProgram(reader));
m_SubPrograms[i] = 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[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{
m_CommonParameters = new SerializedProgramParameters(reader);
}
}
}
@@ -600,7 +720,11 @@ namespace AssetStudio
public class SerializedPass
{
public List<KeyValuePair<string, int>> m_NameIndices;
public Hash128[] m_EditorDataHash;
public byte[] m_Platforms;
public ushort[] m_LocalKeywordMask;
public ushort[] m_GlobalKeywordMask;
public KeyValuePair<string, int>[] m_NameIndices;
public PassType m_Type;
public SerializedShaderState m_State;
public uint m_ProgramMask;
@@ -609,21 +733,43 @@ namespace AssetStudio
public SerializedProgram progGeometry;
public SerializedProgram progHull;
public SerializedProgram progDomain;
public SerializedProgram progRayTracing;
public bool m_HasInstancingVariant;
public string m_UseName;
public string m_Name;
public string m_TextureName;
public SerializedTagMap m_Tags;
public ushort[] m_SerializedKeywordStateMask;
public SerializedPass(ObjectReader reader)
{
var version = reader.version;
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{
int numEditorDataHash = reader.ReadInt32();
m_EditorDataHash = new Hash128[numEditorDataHash];
for (int i = 0; i < numEditorDataHash; i++)
{
m_EditorDataHash[i] = 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
{
m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
m_GlobalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
int numIndices = reader.ReadInt32();
m_NameIndices = new List<KeyValuePair<string, int>>(numIndices);
m_NameIndices = new KeyValuePair<string, int>[numIndices];
for (int i = 0; i < numIndices; i++)
{
m_NameIndices.Add(new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32()));
m_NameIndices[i] = new KeyValuePair<string, int>(reader.ReadAlignedString(), reader.ReadInt32());
}
m_Type = (PassType)reader.ReadInt32();
@@ -634,47 +780,56 @@ 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
{
progRayTracing = new SerializedProgram(reader);
}
m_HasInstancingVariant = reader.ReadBoolean();
if (version[0] >= 2018) //2018 and up
{
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
}
reader.AlignStream(4);
reader.AlignStream();
m_UseName = reader.ReadAlignedString();
m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader);
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
}
public class SerializedTagMap
{
public List<KeyValuePair<string, string>> tags;
public KeyValuePair<string, string>[] tags;
public SerializedTagMap(BinaryReader reader)
{
int numTags = reader.ReadInt32();
tags = new List<KeyValuePair<string, string>>(numTags);
tags = new KeyValuePair<string, string>[numTags];
for (int i = 0; i < numTags; i++)
{
tags.Add(new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString()));
tags[i] = new KeyValuePair<string, string>(reader.ReadAlignedString(), reader.ReadAlignedString());
}
}
}
public class SerializedSubShader
{
public List<SerializedPass> m_Passes;
public SerializedPass[] m_Passes;
public SerializedTagMap m_Tags;
public int m_LOD;
public SerializedSubShader(ObjectReader reader)
{
int numPasses = reader.ReadInt32();
m_Passes = new List<SerializedPass>(numPasses);
m_Passes = new SerializedPass[numPasses];
for (int i = 0; i < numPasses; i++)
{
m_Passes.Add(new SerializedPass(reader));
m_Passes[i] = new SerializedPass(reader);
}
m_Tags = new SerializedTagMap(reader);
@@ -694,25 +849,49 @@ namespace AssetStudio
}
}
public class SerializedCustomEditorForRenderPipeline
{
public string customEditorName;
public string renderPipelineType;
public SerializedCustomEditorForRenderPipeline(BinaryReader reader)
{
customEditorName = reader.ReadAlignedString();
renderPipelineType = reader.ReadAlignedString();
}
}
public class SerializedShader
{
public SerializedProperties m_PropInfo;
public List<SerializedSubShader> m_SubShaders;
public SerializedSubShader[] m_SubShaders;
public string[] m_KeywordNames;
public byte[] m_KeywordFlags;
public string m_Name;
public string m_CustomEditorName;
public string m_FallbackName;
public List<SerializedShaderDependency> m_Dependencies;
public SerializedShaderDependency[] m_Dependencies;
public SerializedCustomEditorForRenderPipeline[] m_CustomEditorForRenderPipelines;
public bool m_DisableNoSubshadersMessage;
public SerializedShader(ObjectReader reader)
{
var version = reader.version;
m_PropInfo = new SerializedProperties(reader);
int numSubShaders = reader.ReadInt32();
m_SubShaders = new List<SerializedSubShader>(numSubShaders);
m_SubShaders = new SerializedSubShader[numSubShaders];
for (int i = 0; i < numSubShaders; i++)
{
m_SubShaders.Add(new SerializedSubShader(reader));
m_SubShaders[i] = new SerializedSubShader(reader);
}
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{
m_KeywordNames = reader.ReadStringArray();
m_KeywordFlags = reader.ReadUInt8Array();
reader.AlignStream();
}
m_Name = reader.ReadAlignedString();
@@ -720,17 +899,57 @@ namespace AssetStudio
m_FallbackName = reader.ReadAlignedString();
int numDependencies = reader.ReadInt32();
m_Dependencies = new List<SerializedShaderDependency>(numDependencies);
m_Dependencies = new SerializedShaderDependency[numDependencies];
for (int i = 0; i < numDependencies; i++)
{
m_Dependencies.Add(new SerializedShaderDependency(reader));
m_Dependencies[i] = new SerializedShaderDependency(reader);
}
if (version[0] >= 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[i] = new SerializedCustomEditorForRenderPipeline(reader);
}
}
m_DisableNoSubshadersMessage = reader.ReadBoolean();
reader.AlignStream(4);
reader.AlignStream();
}
}
public enum ShaderCompilerPlatform
{
kShaderCompPlatformNone = -1,
kShaderCompPlatformGL = 0,
kShaderCompPlatformD3D9 = 1,
kShaderCompPlatformXbox360 = 2,
kShaderCompPlatformPS3 = 3,
kShaderCompPlatformD3D11 = 4,
kShaderCompPlatformGLES20 = 5,
kShaderCompPlatformNaCl = 6,
kShaderCompPlatformFlash = 7,
kShaderCompPlatformD3D11_9x = 8,
kShaderCompPlatformGLES3Plus = 9,
kShaderCompPlatformPSP2 = 10,
kShaderCompPlatformPS4 = 11,
kShaderCompPlatformXboxOne = 12,
kShaderCompPlatformPSM = 13,
kShaderCompPlatformMetal = 14,
kShaderCompPlatformOpenGLCore = 15,
kShaderCompPlatformN3DS = 16,
kShaderCompPlatformWiiU = 17,
kShaderCompPlatformVulkan = 18,
kShaderCompPlatformSwitch = 19,
kShaderCompPlatformXboxOneD3D12 = 20,
kShaderCompPlatformGameCoreXboxOne = 21,
kShaderCompPlatformGameCoreScarlett = 22,
kShaderCompPlatformPS5 = 23,
kShaderCompPlatformPS5NGGC = 24,
};
public class Shader : NamedObject
{
public byte[] m_Script;
@@ -739,10 +958,10 @@ namespace AssetStudio
public byte[] m_SubProgramBlob;
//5.5 and up
public SerializedShader m_ParsedForm;
public List<uint> platforms;
public List<uint> offsets;
public List<uint> compressedLengths;
public List<uint> decompressedLengths;
public ShaderCompilerPlatform[] platforms;
public uint[] offsets;
public uint[] compressedLengths;
public uint[] decompressedLengths;
public byte[] compressedBlob;
public Shader(ObjectReader reader) : base(reader)
@@ -750,45 +969,50 @@ namespace AssetStudio
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
{
m_ParsedForm = new SerializedShader(reader);
int numPlatforms = reader.ReadInt32();
platforms = new List<uint>(numPlatforms);
for (int i = 0; i < numPlatforms; i++)
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
platforms.Add(reader.ReadUInt32());
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
}
else
{
offsets = reader.ReadUInt32Array();
compressedLengths = reader.ReadUInt32Array();
decompressedLengths = reader.ReadUInt32Array();
}
compressedBlob = reader.ReadUInt8Array();
reader.AlignStream();
var m_DependenciesCount = reader.ReadInt32();
for (int i = 0; i < m_DependenciesCount; i++)
{
new PPtr<Shader>(reader);
}
int numOffsets = reader.ReadInt32();
offsets = new List<uint>(numOffsets);
for (int i = 0; i < numOffsets; i++)
if (version[0] >= 2018)
{
offsets.Add(reader.ReadUInt32());
var m_NonModifiableTexturesCount = reader.ReadInt32();
for (int i = 0; i < m_NonModifiableTexturesCount; i++)
{
var first = reader.ReadAlignedString();
new PPtr<Texture>(reader);
}
}
int numCompressedLengths = reader.ReadInt32();
compressedLengths = new List<uint>(numCompressedLengths);
for (int i = 0; i < numCompressedLengths; i++)
{
compressedLengths.Add(reader.ReadUInt32());
}
int numDecompressedLengths = reader.ReadInt32();
decompressedLengths = new List<uint>(numDecompressedLengths);
for (int i = 0; i < numDecompressedLengths; i++)
{
decompressedLengths.Add(reader.ReadUInt32());
}
compressedBlob = reader.ReadBytes(reader.ReadInt32());
var m_ShaderIsBaked = reader.ReadBoolean();
reader.AlignStream();
}
else
{
m_Script = reader.ReadBytes(reader.ReadInt32());
reader.AlignStream(4);
m_Script = reader.ReadUInt8Array();
reader.AlignStream();
var m_PathName = reader.ReadAlignedString();
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
{
decompressedSize = reader.ReadUInt32();
m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
m_SubProgramBlob = reader.ReadUInt8Array();
}
}
}

View File

@@ -7,46 +7,33 @@ namespace AssetStudio
{
public sealed class SkinnedMeshRenderer : Renderer
{
public PPtr m_Mesh;
public PPtr[] m_Bones;
public List<float> m_BlendShapeWeights;
public PPtr<Mesh> m_Mesh;
public PPtr<Transform>[] m_Bones;
public float[] m_BlendShapeWeights;
public SkinnedMeshRenderer(ObjectReader reader) : base(reader)
{
int m_Quality = reader.ReadInt32();
var m_UpdateWhenOffscreen = reader.ReadBoolean();
var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below
reader.AlignStream(4);
reader.AlignStream();
if (version[0] == 2 && version[1] < 6)//2.6 down
if (version[0] == 2 && version[1] < 6) //2.6 down
{
var m_DisableAnimationWhenOffscreen = reader.ReadPPtr();
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
}
m_Mesh = reader.ReadPPtr();
m_Mesh = new PPtr<Mesh>(reader);
m_Bones = new PPtr[reader.ReadInt32()];
m_Bones = new PPtr<Transform>[reader.ReadInt32()];
for (int b = 0; b < m_Bones.Length; b++)
{
m_Bones[b] = reader.ReadPPtr();
m_Bones[b] = new PPtr<Transform>(reader);
}
if (version[0] < 3)
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{
int m_BindPose = reader.ReadInt32();
reader.Position += m_BindPose * 16 * 4;//Matrix4x4f
}
else
{
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up
{
int numBSWeights = reader.ReadInt32();
m_BlendShapeWeights = new List<float>(numBSWeights);
for (int i = 0; i < numBSWeights; i++)
{
m_BlendShapeWeights.Add(reader.ReadSingle());
}
}
m_BlendShapeWeights = reader.ReadSingleArray();
}
}
}

View File

@@ -1,13 +1,21 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using SharpDX;
using RectangleF = System.Drawing.RectangleF;
using System.IO;
namespace AssetStudio
{
public class SecondarySpriteTexture
{
public PPtr<Texture2D> texture;
public string name;
public SecondarySpriteTexture(ObjectReader reader)
{
texture = new PPtr<Texture2D>(reader);
name = reader.ReadStringToNull();
}
}
public enum SpritePackingRotation
{
kSPRNone = 0,
@@ -23,6 +31,12 @@ namespace AssetStudio
kSPMRectangle
};
public enum SpriteMeshType
{
kSpriteMeshTypeFullRect,
kSpriteMeshTypeTight
};
public class SpriteSettings
{
public uint settingsRaw;
@@ -30,185 +44,216 @@ namespace AssetStudio
public uint packed;
public SpritePackingMode packingMode;
public SpritePackingRotation packingRotation;
public SpriteMeshType meshType;
public SpriteSettings(ObjectReader reader)
public SpriteSettings(BinaryReader reader)
{
settingsRaw = reader.ReadUInt32();
packed = settingsRaw & 1; //1
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
//meshType = (settingsRaw >> 6) & 1; //1
meshType = (SpriteMeshType)((settingsRaw >> 6) & 1); //1
//reserved
}
}
public class SpriteVertex
{
public Vector3 pos;
public Vector2 uv;
public SpriteVertex(ObjectReader reader)
{
var version = reader.version;
pos = reader.ReadVector3();
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
{
uv = reader.ReadVector2();
}
}
}
public class SpriteRenderData
{
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public SecondarySpriteTexture[] secondaryTextures;
public SubMesh[] m_SubMeshes;
public byte[] m_IndexBuffer;
public VertexData m_VertexData;
public SpriteVertex[] vertices;
public ushort[] indices;
public Matrix4x4[] m_Bindpose;
public BoneWeights4[] m_SourceSkin;
public Rectf textureRect;
public Vector2 textureRectOffset;
public Vector2 atlasRectOffset;
public SpriteSettings settingsRaw;
public Vector4 uvTransform;
public float downscaleMultiplier;
public SpriteRenderData(ObjectReader reader)
{
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);
}
if (version[0] >= 2019) //2019 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
for (int i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures[i] = new SecondarySpriteTexture(reader);
}
}
if (version[0] > 5 || (version[0] == 5 && version[1] >= 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[i] = new SubMesh(reader);
}
m_IndexBuffer = reader.ReadUInt8Array();
reader.AlignStream();
m_VertexData = new VertexData(reader);
}
else
{
var verticesSize = reader.ReadInt32();
vertices = new SpriteVertex[verticesSize];
for (int i = 0; i < verticesSize; i++)
{
vertices[i] = new SpriteVertex(reader);
}
indices = reader.ReadUInt16Array();
reader.AlignStream();
}
if (version[0] >= 2018) //2018 and up
{
m_Bindpose = reader.ReadMatrixArray();
if (version[0] == 2018 && version[1] < 2) //2018.2 down
{
var m_SourceSkinSize = reader.ReadInt32();
for (int i = 0; i < m_SourceSkinSize; i++)
{
m_SourceSkin[i] = new BoneWeights4(reader);
}
}
}
textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 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
{
uvTransform = reader.ReadVector4();
}
if (version[0] >= 2017) //2017 and up
{
downscaleMultiplier = reader.ReadSingle();
}
}
}
public class Rectf
{
public float x;
public float y;
public float width;
public float height;
public Rectf(BinaryReader reader)
{
x = reader.ReadSingle();
y = reader.ReadSingle();
width = reader.ReadSingle();
height = reader.ReadSingle();
}
}
public sealed class Sprite : NamedObject
{
public RectangleF m_Rect;
public Rectf m_Rect;
public Vector2 m_Offset;
public Vector4 m_Border;
public float m_PixelsToUnits;
public Vector2 m_Pivot;
public Tuple<Guid, long> m_RenderDataKey;
public PPtr texture;
public PPtr m_SpriteAtlas;
public RectangleF textureRect;
public SpriteSettings settingsRaw;
public PointF[][] m_PhysicsShape; //Vector2[][]
public uint m_Extrude;
public bool m_IsPolygon;
public KeyValuePair<Guid, long> m_RenderDataKey;
public string[] m_AtlasTags;
public PPtr<SpriteAtlas> m_SpriteAtlas;
public SpriteRenderData m_RD;
public Vector2[][] m_PhysicsShape;
public Sprite(ObjectReader reader) : base(reader)
{
//Rectf m_Rect
m_Rect = reader.ReadRectangleF();
//Vector2f m_Offset
reader.Position += 8;
m_Rect = new Rectf(reader);
m_Offset = reader.ReadVector2();
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{
//Vector4f m_Border
reader.Position += 16;
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)) //5.4.2 and up
|| (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
{
//Vector2f m_Pivot
m_Pivot = reader.ReadVector2();
}
var m_Extrude = reader.ReadUInt32();
m_Extrude = reader.ReadUInt32();
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
{
var m_IsPolygon = reader.ReadBoolean();
reader.AlignStream(4);
m_IsPolygon = reader.ReadBoolean();
reader.AlignStream();
}
if (version[0] >= 2017) //2017 and up
{
//pair m_RenderDataKey
var first = new Guid(reader.ReadBytes(16));
var second = reader.ReadInt64();
m_RenderDataKey = new Tuple<Guid, long>(first, second);
//vector m_AtlasTags
var size = reader.ReadInt32();
for (int i = 0; i < size; i++)
{
var data = reader.ReadAlignedString();
}
m_RenderDataKey = new KeyValuePair<Guid, long>(first, second);
//PPtr<SpriteAtlas> m_SpriteAtlas
m_SpriteAtlas = reader.ReadPPtr();
m_AtlasTags = reader.ReadStringArray();
m_SpriteAtlas = new PPtr<SpriteAtlas>(reader);
}
//SpriteRenderData m_RD
// PPtr<Texture2D> texture
texture = reader.ReadPPtr();
// PPtr<Texture2D> alphaTexture
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{
var alphaTexture = reader.ReadPPtr();
}
m_RD = new SpriteRenderData(reader);
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{
// vector m_SubMeshes
var size = reader.ReadInt32();
// SubMesh data
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{
reader.Position += 48 * size;
}
else
{
reader.Position += 44 * size;
}
// vector m_IndexBuffer
size = reader.ReadInt32();
reader.Position += size; //UInt8 data
reader.AlignStream(4);
// VertexData m_VertexData
if (version[0] < 2018)//2018 down
{
var m_CurrentChannels = reader.ReadInt32();
}
var m_VertexCount = reader.ReadUInt32();
// vector m_Channels
size = reader.ReadInt32();
reader.Position += size * 4; //ChannelInfo data
// TypelessData m_DataSize
size = reader.ReadInt32();
reader.Position += size; //UInt8 data
reader.AlignStream(4);
if (version[0] >= 2018)//2018 and up
{
// vector m_Bindpose
// Matrix4x4f data
size = reader.ReadInt32();
reader.Position += size * 64;
if (version[0] == 2018 && version[1] < 2) //2018.2 down
{
// vector m_SourceSkin
// BoneWeights4 data
size = reader.ReadInt32();
reader.Position += size * 32;
}
}
}
else
{
// vector vertices
var size = reader.ReadInt32();
for (int i = 0; i < size; i++)
{
//SpriteVertex data
reader.Position += 12; //Vector3f pos
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
reader.Position += 8; //Vector2f uv
}
// vector indices
size = reader.ReadInt32();
reader.Position += 2 * size; //UInt16 data
reader.AlignStream(4);
}
// Rectf textureRect
textureRect = reader.ReadRectangleF();
// Vector2f textureRectOffset
reader.Position += 8;
// Vector2f atlasRectOffset - 5.6 and up
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{
reader.Position += 8;
}
// unsigned int settingsRaw
settingsRaw = new SpriteSettings(reader);
// Vector4f uvTransform - 4.5 and up
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{
reader.Position += 16;
}
if (version[0] >= 2017) //2017 and up
{
// float downscaleMultiplier - 2017 and up
reader.Position += 4;
//vector m_PhysicsShape - 2017 and up
var m_PhysicsShape_size = reader.ReadInt32();
m_PhysicsShape = new PointF[m_PhysicsShape_size][];
for (int i = 0; i < m_PhysicsShape_size; i++)
var m_PhysicsShapeSize = reader.ReadInt32();
m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];
for (int i = 0; i < m_PhysicsShapeSize; i++)
{
var data_size = reader.ReadInt32();
//Vector2f
m_PhysicsShape[i] = new PointF[data_size];
for (int j = 0; j < data_size; j++)
{
m_PhysicsShape[i][j] = new PointF(reader.ReadSingle(), reader.ReadSingle());
}
m_PhysicsShape[i] = reader.ReadVector2Array();
}
}
//vector m_Bones 2018 and up
}
}

View File

@@ -1,29 +1,26 @@
using SharpDX;
using System;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public class SpriteAtlasData
{
public PPtr texture;
public PPtr alphaTexture;
public System.Drawing.RectangleF textureRect;
public PPtr<Texture2D> texture;
public PPtr<Texture2D> alphaTexture;
public Rectf textureRect;
public Vector2 textureRectOffset;
public Vector2 atlasRectOffset;
public Vector4 uvTransform;
public float downscaleMultiplier;
public SpriteSettings settingsRaw;
public SecondarySpriteTexture[] secondaryTextures;
public SpriteAtlasData(ObjectReader reader)
{
var version = reader.version;
texture = reader.ReadPPtr();
alphaTexture = reader.ReadPPtr();
textureRect = reader.ReadRectangleF();
texture = new PPtr<Texture2D>(reader);
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
{
@@ -32,35 +29,43 @@ namespace AssetStudio
uvTransform = reader.ReadVector4();
downscaleMultiplier = reader.ReadSingle();
settingsRaw = new SpriteSettings(reader);
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{
var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
for (int i = 0; i < secondaryTexturesSize; i++)
{
secondaryTextures[i] = new SecondarySpriteTexture(reader);
}
reader.AlignStream();
}
}
}
public sealed class SpriteAtlas : NamedObject
{
public Dictionary<Tuple<Guid, long>, SpriteAtlasData> m_RenderDataMap;
public PPtr<Sprite>[] m_PackedSprites;
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
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++)
{
reader.ReadPPtr(); //PPtr<Sprite> data
m_PackedSprites[i] = new PPtr<Sprite>(reader);
}
var m_PackedSpriteNamesToIndexSize = reader.ReadInt32();
for (int i = 0; i < m_PackedSpriteNamesToIndexSize; i++)
{
reader.ReadAlignedString();
}
var m_PackedSpriteNamesToIndex = reader.ReadStringArray();
var m_RenderDataMapSize = reader.ReadInt32();
m_RenderDataMap = new Dictionary<Tuple<Guid, long>, SpriteAtlasData>(m_RenderDataMapSize);
m_RenderDataMap = new Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData>(m_RenderDataMapSize);
for (int i = 0; i < m_RenderDataMapSize; i++)
{
var first = new Guid(reader.ReadBytes(16));
var second = reader.ReadInt64();
var value = new SpriteAtlasData(reader);
m_RenderDataMap.Add(new Tuple<Guid, long>(first, second), value);
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
}
//string m_Tag
//bool m_IsVariant

View File

@@ -12,7 +12,7 @@ namespace AssetStudio
public TextAsset(ObjectReader reader) : base(reader)
{
m_Script = reader.ReadBytes(reader.ReadInt32());
m_Script = reader.ReadUInt8Array();
}
}
}

View File

@@ -13,7 +13,11 @@ namespace AssetStudio
{
var m_ForcedFallbackFormat = reader.ReadInt32();
var m_DownscaleFallback = reader.ReadBoolean();
reader.AlignStream(4);
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{
var m_IsAlphaChannelOptional = reader.ReadBoolean();
}
reader.AlignStream();
}
}
}

View File

@@ -1,80 +1,47 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace AssetStudio
{
public sealed class Texture2D : Texture
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_Width;
public int m_Height;
public int m_CompleteImageSize;
public TextureFormat m_TextureFormat;
public bool m_MipMap;
public int m_MipCount;
public bool m_IsReadable;
public bool m_ReadAllowed;
public int m_ImageCount;
public int m_TextureDimension;
//m_TextureSettings
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
public int m_LightmapFormat;
public int m_ColorSpace;
//image dataa
public int image_data_size;
public byte[] image_data;
//m_StreamData
public uint offset;
public uint size;
public string path;
public Texture2D(ObjectReader reader, bool readData) : base(reader)
public GLTextureSettings(ObjectReader reader)
{
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_CompleteImageSize = reader.ReadInt32();
m_TextureFormat = (TextureFormat)reader.ReadInt32();
var version = reader.version;
if (version[0] < 5 || (version[0] == 5 && version[1] < 2))
{
m_MipMap = reader.ReadBoolean();
}
else
{
m_MipCount = reader.ReadInt32();
}
m_IsReadable = reader.ReadBoolean(); //2.6.0 and up
m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4
//m_StreamingMipmaps 2018.2 and up
reader.AlignStream(4);
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
{
var m_StreamingMipmapsPriority = reader.ReadInt32();
}
else if (reader.HasStructMember("m_StreamingMipmapsPriority")) //will fix in some patch version bundle
{
var m_StreamingMipmapsPriority = reader.ReadInt32();
}
if (reader.HasStructMember("m_StreamingGroupID")) //What the hell is this?
{
var m_StreamingGroupID = reader.ReadUInt32();
}
m_ImageCount = reader.ReadInt32();
m_TextureDimension = reader.ReadInt32();
//m_TextureSettings
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version[0] >= 2017)//2017.x and up
{
int m_WrapU = reader.ReadInt32();
m_WrapMode = reader.ReadInt32(); //m_WrapU
int m_WrapV = reader.ReadInt32();
int m_WrapW = reader.ReadInt32();
}
@@ -82,36 +49,98 @@ namespace AssetStudio
{
m_WrapMode = reader.ReadInt32();
}
if (version[0] >= 3)
}
}
public sealed class Texture2D : Texture
{
public int m_Width;
public int m_Height;
public TextureFormat m_TextureFormat;
public bool m_MipMap;
public int m_MipCount;
public GLTextureSettings m_TextureSettings;
public ResourceReader image_data;
public StreamingInfo m_StreamData;
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_LightmapFormat = reader.ReadInt32();
if (version[0] >= 4 || version[1] >= 5)//3.5.0 and up
var m_MipsStripped = reader.ReadInt32();
}
m_TextureFormat = (TextureFormat)reader.ReadInt32();
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
{
m_MipMap = reader.ReadBoolean();
}
else
{
m_MipCount = reader.ReadInt32();
}
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
{
var m_IsReadable = reader.ReadBoolean();
}
if (version[0] >= 2020) //2020.1 and up
{
var m_IsPreProcessed = reader.ReadBoolean();
}
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
}
if (version[0] >= 3) //3.0.0 - 5.4
{
if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))
{
m_ColorSpace = reader.ReadInt32();
var m_ReadAllowed = reader.ReadBoolean();
}
}
image_data_size = reader.ReadInt32();
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 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
{
var m_StreamingMipmapsPriority = reader.ReadInt32();
}
var m_ImageCount = reader.ReadInt32();
var m_TextureDimension = reader.ReadInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version[0] >= 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
{
var m_ColorSpace = reader.ReadInt32();
}
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{
var m_PlatformBlob = reader.ReadUInt8Array();
reader.AlignStream();
}
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
{
offset = reader.ReadUInt32();
size = reader.ReadUInt32();
image_data_size = (int)size;
path = reader.ReadAlignedString();
m_StreamData = new StreamingInfo(reader);
}
if (readData)
ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_StreamData?.path))
{
if (!string.IsNullOrEmpty(path))
{
image_data = ResourcesHelper.GetData(path, sourceFile, offset, image_data_size);
}
else
{
image_data = reader.ReadBytes(image_data_size);
}
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;
}
}
@@ -174,5 +203,14 @@ namespace AssetStudio
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
}
}

View File

@@ -1,5 +1,4 @@
using SharpDX;
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,24 +7,25 @@ namespace AssetStudio
{
public class Transform : Component
{
public float[] m_LocalRotation;
public float[] m_LocalPosition;
public float[] m_LocalScale;
public List<PPtr> m_Children;
public PPtr m_Father;
public Quaternion m_LocalRotation;
public Vector3 m_LocalPosition;
public Vector3 m_LocalScale;
public PPtr<Transform>[] m_Children;
public PPtr<Transform> m_Father;
public Transform(ObjectReader reader) : base(reader)
{
m_LocalRotation = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
m_LocalPosition = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
m_LocalScale = new[] { reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle() };
m_LocalRotation = reader.ReadQuaternion();
m_LocalPosition = reader.ReadVector3();
m_LocalScale = reader.ReadVector3();
int m_ChildrenCount = reader.ReadInt32();
m_Children = new List<PPtr>(m_ChildrenCount);
for (int j = 0; j < m_ChildrenCount; j++)
m_Children = new PPtr<Transform>[m_ChildrenCount];
for (int i = 0; i < m_ChildrenCount; i++)
{
m_Children.Add(reader.ReadPPtr());
m_Children[i] = new PPtr<Transform>(reader);
}
m_Father = reader.ReadPPtr();
m_Father = new PPtr<Transform>(reader);
}
}
}

View File

@@ -1,26 +1,35 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.IO;
namespace AssetStudio
{
public class StreamedResource
{
public string m_Source;
public long m_Offset; //ulong
public long m_Size; //ulong
public StreamedResource(BinaryReader reader)
{
m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64();
}
}
public sealed class VideoClip : NamedObject
{
public byte[] m_VideoData;
public ResourceReader m_VideoData;
public string m_OriginalPath;
public string m_Source;
public ulong m_Size;
public StreamedResource m_ExternalResources;
public VideoClip(ObjectReader reader, bool readData) : base(reader)
public VideoClip(ObjectReader reader) : base(reader)
{
m_OriginalPath = reader.ReadAlignedString();
var m_ProxyWidth = reader.ReadUInt32();
var m_ProxyHeight = reader.ReadUInt32();
var Width = reader.ReadUInt32();
var Height = reader.ReadUInt32();
if (version[0] >= 2017)//2017.x and up
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
var m_PixelAspecRatioNum = reader.ReadUInt32();
var m_PixelAspecRatioDen = reader.ReadUInt32();
@@ -28,37 +37,36 @@ namespace AssetStudio
var m_FrameRate = reader.ReadDouble();
var m_FrameCount = reader.ReadUInt64();
var m_Format = reader.ReadInt32();
//m_AudioChannelCount
var size = reader.ReadInt32();
reader.Position += size * 2;
reader.AlignStream(4);
//m_AudioSampleRate
size = reader.ReadInt32();
reader.Position += size * 4;
//m_AudioLanguage
size = reader.ReadInt32();
for (int i = 0; i < size; i++)
var m_AudioChannelCount = reader.ReadUInt16Array();
reader.AlignStream();
var m_AudioSampleRate = reader.ReadUInt32Array();
var m_AudioLanguage = reader.ReadStringArray();
if (version[0] >= 2020) //2020.1 and up
{
reader.ReadAlignedString();
var m_VideoShadersSize = reader.ReadInt32();
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
for (int i = 0; i < m_VideoShadersSize; i++)
{
m_VideoShaders[i] = new PPtr<Shader>(reader);
}
}
//StreamedResource m_ExternalResources
m_Source = reader.ReadAlignedString();
var m_Offset = reader.ReadUInt64();
m_Size = reader.ReadUInt64();
m_ExternalResources = new StreamedResource(reader);
var m_HasSplitAlpha = reader.ReadBoolean();
if (readData)
if (version[0] >= 2020) //2020.1 and up
{
if (!string.IsNullOrEmpty(m_Source))
{
m_VideoData = ResourcesHelper.GetData(m_Source, sourceFile, (long)m_Offset, (int)m_Size);
}
else
{
if (m_Size > 0)
m_VideoData = reader.ReadBytes((int)m_Size);
}
var m_sRGB = reader.ReadBoolean();
}
ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))
{
resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, m_ExternalResources.m_Size);
}
else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_ExternalResources.m_Size);
}
m_VideoData = resourceReader;
}
}
}

View File

@@ -4,7 +4,7 @@ namespace AssetStudio
{
public static class CommonString
{
public static readonly Dictionary<int, string> StringBuffer = new Dictionary<int, string>
public static readonly Dictionary<uint, string> StringBuffer = new Dictionary<uint, string>
{
{0, "AABB"},
{5, "AnimationClip"},
@@ -110,7 +110,11 @@ namespace AssetStudio
{1057, "int2_storage"},
{1070, "int3_storage"},
{1083, "BoundsInt"},
{1092, "m_CorrespondingSourceObject"}
{1093, "m_CorrespondingSourceObject"},
{1121, "m_PrefabInstance"},
{1138, "m_PrefabAsset"},
{1152, "FileSize"},
{1161, "Hash128"}
};
}
}

View File

@@ -2,12 +2,16 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using SharpDX;
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)
{
var pos = reader.BaseStream.Position;
@@ -21,7 +25,7 @@ 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 > 0 && length <= reader.BaseStream.Length - reader.BaseStream.Position)
{
var stringData = reader.ReadBytes(length);
var result = Encoding.UTF8.GetString(stringData);
@@ -31,12 +35,20 @@ namespace AssetStudio
return "";
}
public static string ReadStringToNull(this BinaryReader reader)
public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767)
{
var bytes = new List<byte>();
byte b;
while (reader.BaseStream.Position != reader.BaseStream.Length && (b = reader.ReadByte()) != 0)
int count = 0;
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
{
var b = reader.ReadByte();
if (b == 0)
{
break;
}
bytes.Add(b);
count++;
}
return Encoding.UTF8.GetString(bytes.ToArray());
}
@@ -60,44 +72,94 @@ namespace AssetStudio
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
}
public static System.Drawing.RectangleF ReadRectangleF(this BinaryReader reader)
public static Color ReadColor4(this BinaryReader reader)
{
return new System.Drawing.RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
}
public static Matrix4x4 ReadMatrix(this BinaryReader reader)
{
return new Matrix4x4(reader.ReadSingleArray(16));
}
private static T[] ReadArray<T>(Func<T> del, int length)
{
var array = new T[length];
for (int i = 0; i < array.Length; i++)
for (int i = 0; i < length; i++)
{
array[i] = del();
}
return array;
}
public static bool[] ReadBooleanArray(this BinaryReader reader)
{
return ReadArray(reader.ReadBoolean, reader.ReadInt32());
}
public static byte[] ReadUInt8Array(this BinaryReader reader)
{
return reader.ReadBytes(reader.ReadInt32());
}
public static ushort[] ReadUInt16Array(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
}
public static int[] ReadInt32Array(this BinaryReader reader)
{
return ReadArray(reader.ReadInt32, reader.ReadInt32());
}
public static int[] ReadInt32Array(this BinaryReader reader, int length)
{
return ReadArray(reader.ReadInt32, length);
}
public static uint[] ReadUInt32Array(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt32, reader.ReadInt32());
}
public static uint[][] ReadUInt32ArrayArray(this BinaryReader reader)
{
return ReadArray(reader.ReadUInt32Array, reader.ReadInt32());
}
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
{
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);
}
public static Vector2[] ReadVector2Array(this BinaryReader reader, int length)
public static string[] ReadStringArray(this BinaryReader reader)
{
return ReadArray(reader.ReadVector2, length);
return ReadArray(reader.ReadAlignedString, reader.ReadInt32());
}
public static Vector4[] ReadVector4Array(this BinaryReader reader, int length)
public static Vector2[] ReadVector2Array(this BinaryReader reader)
{
return ReadArray(reader.ReadVector4, length);
return ReadArray(reader.ReadVector2, reader.ReadInt32());
}
public static Vector4[] ReadVector4Array(this BinaryReader reader)
{
return ReadArray(reader.ReadVector4, reader.ReadInt32());
}
public static Matrix4x4[] ReadMatrixArray(this BinaryReader reader)
{
return ReadArray(reader.ReadMatrix, reader.ReadInt32());
}
}
}

View File

@@ -6,19 +6,6 @@ namespace AssetStudio
{
public static class BinaryWriterExtensions
{
private static void WriteArray<T>(Action<T> del, T[] array)
{
foreach (var item in array)
{
del(item);
}
}
public static void Write(this BinaryWriter writer, uint[] array)
{
WriteArray(writer.Write, array);
}
public static void AlignStream(this BinaryWriter writer, int alignment)
{
var pos = writer.BaseStream.Position;

100
AssetStudio/FileReader.cs Normal file
View File

@@ -0,0 +1,100 @@
using System.IO;
using System.Linq;
namespace AssetStudio
{
public class FileReader : EndianBinaryReader
{
public string FullPath;
public string FileName;
public FileType FileType;
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)
{
FullPath = Path.GetFullPath(path);
FileName = Path.GetFileName(path);
FileType = CheckFileType();
}
private FileType CheckFileType()
{
var signature = this.ReadStringToNull(20);
Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
return FileType.GZipFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (brotliMagic.SequenceEqual(magic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile())
{
return FileType.AssetsFile;
}
else
{
return FileType.ResourceFile;
}
}
}
}
private bool IsSerializedFile()
{
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);
if (m_Version >= 22)
{
if (fileSize < 48)
{
Position = 0;
return false;
}
m_MetadataSize = ReadUInt32();
m_FileSize = ReadInt64();
m_DataOffset = ReadInt64();
}
Position = 0;
if (m_FileSize != fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{
return false;
}
return true;
}
}
}

18
AssetStudio/FileType.cs Normal file
View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile,
ResourceFile,
GZipFile,
BrotliFile
}
}

View File

@@ -1,14 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using SharpDX;
namespace AssetStudio
{
public interface IImported
{
List<ImportedFrame> FrameList { get; }
ImportedFrame RootFrame { get; }
List<ImportedMesh> MeshList { get; }
List<ImportedMaterial> MaterialList { get; }
List<ImportedTexture> TextureList { get; }
@@ -16,12 +14,12 @@ namespace AssetStudio
List<ImportedMorph> MorphList { get; }
}
public class ImportedFrame : IEnumerable<ImportedFrame>
public class ImportedFrame
{
public string Name { get; set; }
public float[] LocalRotation { get; set; }
public float[] LocalPosition { get; set; }
public float[] LocalScale { get; set; }
public Vector3 LocalRotation { get; set; }
public Vector3 LocalPosition { get; set; }
public Vector3 LocalScale { get; set; }
public ImportedFrame Parent { get; set; }
private List<ImportedFrame> children;
@@ -30,60 +28,135 @@ namespace AssetStudio
public int Count => children.Count;
public void InitChildren(int count)
public string Path
{
children = new List<ImportedFrame>(count);
get
{
var frame = this;
var path = frame.Name;
while (frame.Parent != null)
{
frame = frame.Parent;
path = frame.Name + "/" + path;
}
return path;
}
}
public ImportedFrame(int childrenCount = 0)
{
children = new List<ImportedFrame>(childrenCount);
}
public void AddChild(ImportedFrame obj)
{
children.Add(obj);
obj.Parent?.Remove(obj);
obj.Parent = this;
}
public void ClearChild()
public void Remove(ImportedFrame frame)
{
children.Clear();
children.Remove(frame);
}
public IEnumerator<ImportedFrame> GetEnumerator()
public ImportedFrame FindFrameByPath(string path)
{
return children.GetEnumerator();
var name = path.Substring(path.LastIndexOf('/') + 1);
foreach (var frame in FindChilds(name))
{
if (frame.Path.EndsWith(path, StringComparison.Ordinal))
{
return frame;
}
}
return null;
}
IEnumerator IEnumerable.GetEnumerator()
public ImportedFrame FindFrame(string name)
{
return GetEnumerator();
if (Name == name)
{
return this;
}
foreach (var child in children)
{
var frame = child.FindFrame(name);
if (frame != null)
{
return frame;
}
}
return null;
}
public ImportedFrame FindChild(string name, bool recursive = true)
{
foreach (var child in children)
{
if (recursive)
{
var frame = child.FindFrame(name);
if (frame != null)
{
return frame;
}
}
else
{
if (child.Name == name)
{
return child;
}
}
}
return null;
}
public IEnumerable<ImportedFrame> FindChilds(string name)
{
if (Name == name)
{
yield return this;
}
foreach (var child in children)
{
foreach (var item in child.FindChilds(name))
{
yield return item;
}
}
}
}
public class ImportedMesh
{
public string Name { get; set; }
public string Path { get; set; }
public List<ImportedVertex> VertexList { get; set; }
public List<ImportedSubmesh> SubmeshList { get; set; }
public List<ImportedBone> BoneList { get; set; }
public bool hasNormal { get; set; }
public bool[] hasUV { get; set; }
public bool hasTangent { get; set; }
public bool hasColor { get; set; }
}
public class ImportedSubmesh
{
public List<ImportedVertex> VertexList { get; set; }
public List<ImportedFace> FaceList { get; set; }
public string Material { get; set; }
public int BaseVertex { get; set; }
}
public class ImportedVertex
{
public Vector3 Position { get; set; }
public float[] Weights { get; set; }
public byte[] BoneIndices { get; set; }
public Vector3 Vertex { get; set; }
public Vector3 Normal { get; set; }
public float[] UV { get; set; }
public float[][] UV { get; set; }
public Vector4 Tangent { get; set; }
}
public class ImportedVertexWithColour : ImportedVertex
{
public Color4 Colour { get; set; }
public Color Color { get; set; }
public float[] Weights { get; set; }
public int[] BoneIndices { get; set; }
}
public class ImportedFace
@@ -93,21 +166,29 @@ namespace AssetStudio
public class ImportedBone
{
public string Name { get; set; }
public float[,] Matrix { get; set; }
public string Path { get; set; }
public Matrix4x4 Matrix { get; set; }
}
public class ImportedMaterial
{
public string Name { get; set; }
public Color4 Diffuse { get; set; }
public Color4 Ambient { get; set; }
public Color4 Specular { get; set; }
public Color4 Emissive { get; set; }
public float Power { get; set; }
public string[] Textures { get; set; }
public Vector2[] TexOffsets { get; set; }
public Vector2[] TexScales { get; set; }
public Color Diffuse { get; set; }
public Color Ambient { get; set; }
public Color Specular { get; set; }
public Color Emissive { get; set; }
public Color Reflection { get; set; }
public float Shininess { get; set; }
public float Transparency { get; set; }
public List<ImportedMaterialTexture> Textures { get; set; }
}
public class ImportedMaterialTexture
{
public string Name { get; set; }
public int Dest { get; set; }
public Vector2 Offset { get; set; }
public Vector2 Scale { get; set; }
}
public class ImportedTexture
@@ -125,15 +206,15 @@ namespace AssetStudio
public class ImportedKeyframedAnimation
{
public string Name { get; set; }
public float SampleRate { get; set; }
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
public ImportedAnimationKeyframedTrack FindTrack(string name)
public ImportedAnimationKeyframedTrack FindTrack(string path)
{
var track = TrackList.Find(x => x.Name == name);
var track = TrackList.Find(x => x.Path == path);
if (track == null)
{
track = new ImportedAnimationKeyframedTrack { Name = name };
track = new ImportedAnimationKeyframedTrack { Path = path };
TrackList.Add(track);
}
@@ -143,19 +224,17 @@ namespace AssetStudio
public class ImportedAnimationKeyframedTrack
{
public string Name { get; set; }
public string Path { get; set; }
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
public List<ImportedKeyframe<float>> Curve = new List<ImportedKeyframe<float>>();
public ImportedBlendShape BlendShape;
}
public class ImportedKeyframe<T>
{
public float time { get; set; }
public T value { get; set; }
public T inSlope { get; set; }
public T outSlope { get; set; }
public ImportedKeyframe(float time, T value)
{
@@ -164,85 +243,45 @@ namespace AssetStudio
}
}
public class ImportedBlendShape
{
public string ChannelName;
public List<ImportedKeyframe<float>> Keyframes = new List<ImportedKeyframe<float>>();
}
public class ImportedMorph
{
public string Path { get; set; }
public List<ImportedMorphChannel> Channels { get; set; }
}
public class ImportedMorphChannel
{
public string Name { get; set; }
public string ClipName { get; set; }
public List<Tuple<float, int, int>> Channels { get; set; }
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
}
public class ImportedMorphKeyframe
{
public string Name { get; set; }
public List<ImportedVertex> VertexList { get; set; }
public List<ushort> MorphedVertexIndices { get; set; }
public bool hasNormals { get; set; }
public bool hasTangents { get; set; }
public float Weight { get; set; }
public List<ImportedMorphVertex> VertexList { get; set; }
}
public class ImportedMorphVertex
{
public uint Index { get; set; }
public ImportedVertex Vertex { get; set; }
}
public static class ImportedHelpers
{
public static ImportedFrame FindFrame(string name, ImportedFrame root)
{
if (root.Name == name)
{
return root;
}
foreach (var child in root)
{
var frame = FindFrame(name, child);
if (frame != null)
{
return frame;
}
}
return null;
}
public static ImportedFrame FindChildOrRoot(string name, ImportedFrame root)
{
foreach (var child in root)
{
var frame = FindFrame(name, child);
if (frame != null)
{
return frame;
}
}
if (root.Name == name)
{
return root;
}
return null;
}
public static ImportedMesh FindMesh(string frameName, List<ImportedMesh> importedMeshList)
public static ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)
{
foreach (var mesh in importedMeshList)
{
if (mesh.Name == frameName)
{
return mesh;
}
}
return null;
}
public static ImportedMesh FindMesh(ImportedFrame frame, List<ImportedMesh> importedMeshList)
{
var framePath = frame.Name;
var root = frame;
while (root.Parent != null)
{
root = root.Parent;
framePath = root.Name + "/" + framePath;
}
foreach (var mesh in importedMeshList)
{
if (mesh.Name == framePath)
if (mesh.Path == path)
{
return mesh;
}

View File

@@ -1,16 +1,11 @@
using System.Collections.Generic;
using Org.Brotli.Dec;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile
}
public static class ImportHelper
{
public static void MergeSplitAssets(string path, bool allDirectories = false)
@@ -19,8 +14,8 @@ namespace AssetStudio
foreach (var splitFile in splitFiles)
{
var destFile = Path.GetFileNameWithoutExtension(splitFile);
var destPath = Path.GetDirectoryName(splitFile) + "\\";
var destFull = destPath + destFile;
var destPath = Path.GetDirectoryName(splitFile);
var destFull = Path.Combine(destPath, destFile);
if (!File.Exists(destFull))
{
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
@@ -42,7 +37,7 @@ namespace AssetStudio
public static string[] ProcessingSplitFiles(List<string> selectFile)
{
var splitFiles = selectFile.Where(x => x.Contains(".split"))
.Select(x => Path.GetDirectoryName(x) + "\\" + Path.GetFileNameWithoutExtension(x))
.Select(x => Path.Combine(Path.GetDirectoryName(x), Path.GetFileNameWithoutExtension(x)))
.Distinct()
.ToList();
selectFile.RemoveAll(x => x.Contains(".split"));
@@ -56,48 +51,31 @@ namespace AssetStudio
return selectFile.Distinct().ToArray();
}
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
public static FileReader DecompressGZip(FileReader reader)
{
reader = new EndianBinaryReader(stream);
return CheckFileType(reader);
}
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(File.OpenRead(fileName));
return CheckFileType(reader);
}
private static FileType CheckFileType(EndianBinaryReader reader)
{
var signature = reader.ReadStringToNull();
reader.Position = 0;
switch (signature)
using (reader)
{
case "UnityWeb":
case "UnityRaw":
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = reader.ReadBytes(2);
reader.Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
reader.Position = 0x20;
magic = reader.ReadBytes(6);
reader.Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
return FileType.AssetsFile;
}
var stream = new MemoryStream();
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
{
gs.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
public static FileReader DecompressBrotli(FileReader reader)
{
using (reader)
{
var stream = new MemoryStream();
using (var brotliStream = new BrotliInputStream(reader.BaseStream))
{
brotliStream.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
}

View File

@@ -1,151 +0,0 @@
FMOD, FMOD Ex, FMOD Designer and FMOD Studio are
Copyright <20> 2005-2016 Firelight Technologies Pty, Ltd.
GRANT OF LICENSE
----------------
THIS END USER LICENSE AGREEMENT GRANTS THE USER, THE RIGHT TO USE FMOD,
IN ITS LIBRARY AND TOOL FORM, IN THEIR OWN PRODUCTS, BE THEY FOR PERSONAL,
EDUCATIONAL OR COMMERCIAL USE.
THE USER MUST ADHERE TO THE LICENSING MODEL PROVIDED BY FIRELIGHT
TECHNOLOGIES, AND MUST APPLY FOR A LICENSE IF NECESSARY. THE FOLLOWING
LICENSES ARE AVAILABLE.
FMOD NON-COMMERCIAL LICENSE
------------------------------------
IF YOUR PRODUCT IS NOT INTENDED FOR COMMERCIAL GAIN AND DOES NOT
INCLUDE THE FMOD LIBRARY FOR RESALE, LICENSE OR OTHER COMMERCIAL
DISTRIBUTION, THEN USE OF FMOD IS FREE OF CHARGE. THERE ARE NO
LICENSE FEES FOR NON-COMMERCIAL APPLICATIONS.
THE USER MAY USE THIS EULA AS EVIDENCE OF THEIR LICENSE WITHOUT
CONTACTING FIRELIGHT TECHNOLOGIES.
CONDITIONS/LIMITATIONS:
- WHEN USING THIS LICENSE, THE FMOD LIBRARY CANNOT BE USED FOR
RESALE OR OTHER COMMERCIAL DISTRIBUTION
- THIS LICENSE CANNOT BE USED FOR PRODUCTS WHICH DO NOT MAKE
PROFIT BUT ARE STILL COMMERCIALLY RELEASED
- THIS LICENSE CANNOT BE USED FOR COMMERCIAL SERVICES, WHERE THE
EXECUTABLE CONTAINING FMOD IS NOT SOLD, BUT THE DATA IS.
- WHEN USING FMOD, A CREDIT LINE IS REQUIRED IN EITHER DOCUMENTATION,
OR 'ON SCREEN' FORMAT (IF POSSIBLE). IT SHOULD CONTAIN AT LEAST
THE WORDS "FMOD" (OR "FMOD STUDIO" IF APPLICABLE) AND
"FIRELIGHT TECHNOLOGIES."
LOGOS ARE AVAILABLE FOR BOX OR MANUAL ART, BUT ARE NOT MANDATORY.
AN EXAMPLE CREDIT COULD BE:
FMOD Sound System, copyright <20> Firelight Technologies Pty, Ltd., 1994-2016.
OR
FMOD Studio, copyright <20> Firelight Technologies Pty, Ltd., 1994-2016.
OR
Audio Engine supplied by FMOD by Firelight Technologies.
NOTE THIS IN ADVANCE, AS IT MUST BE DONE BEFORE SHIPPING YOUR
PRODUCT WITH FMOD.
FMOD FREE FOR INDIES LICENSE (FMOD STUDIO ONLY)
------------------------------------------------
INDIE DEVELOPERS ARE CONSIDERED BY OUR LICENSING MODEL, DEVELOPERS THAT DEVELOP
A TITLE FOR UNDER $100K USD (TYPICALLY CONSIDERED AN 'INDIE' TITLE) TOTAL
BUDGET, MEANING YOUR TOTAL COSTS ARE LESS THAN $100K USD AT TIME OF SHIPPING,
YOU CAN USE FMOD FOR FREE.
CONDITIONS/LIMITATIONS
- PLEASE WRITE TO SALES@FMOD.COM WITH THE NAME OF YOUR TITLE, RELEASE DATE
AND PLATFORMS SO WE CAN REGISTER YOU IN OUR SYSTEM.
- THERE IS NO RESTRICTION ON PLATFORM, ANY PLATFORM COMBINATION MAY BE USED.
- INCOME IS NOT RELEVANT TO THE BUDGET LEVEL, IT MUST BE EXPENSE RELATED.
- WHEN USING FMOD, A CREDIT LINE IS REQUIRED IN EITHER DOCUMENTATION,
OR 'ON SCREEN' FORMAT (IF POSSIBLE). IT SHOULD CONTAIN AT LEAST
THE WORDS FMOD STUDIO AND FIRELIGHT TECHNOLOGIES.
LOGOS ARE AVAILABLE FOR BOX OR MANUAL ART, BUT ARE NOT MANDATORY.
AN EXAMPLE CREDIT COULD BE:
FMOD STUDIO, COPYRIGHT <20> FIRELIGHT TECHNOLOGIES PTY, LTD., 1994-2016.
COMMERCIAL USAGE (FMOD EX AND FMOD STUDIO)
------------------------------------------
IF THE PRODUCT THAT USES FMOD IS INTENDED TO GENERATE INCOME, VIA DIRECT SALES
OR INDIRECT REVENUE (SUCH AS ADVERTISING, DONATIONS, CONTRACT FEE) THEN THE
DEVELOPER MUST APPLY TO FIRELIGHT TECHNOLOGIES FOR A COMMERCIAL LICENSE (UNLESS
THE USER QUALIFIES FOR AN FMOD STUDIO 'INDIE LICENSE').
TO APPLY FOR THIS LICENSE WRITE TO SALES@FMOD.COM WITH THE RELEVANT DETAILS.
REDISTRIBUTION LICENSE (FMOD EX AND FMOD STUDIO)
------------------------------------------------
IF THE USER WISHES TO REDISTRIBUTE FMOD AS PART OF AN ENGINE OR TOOL SOLUTION,
THE USER MUST APPLY TO FIRELIGHT TECHNOLOGIES TO BE GRANTED A 'REDISTRIBUTION
LICENSE'.
TO APPLY FOR THIS LICENSE WRITE TO SALES@FMOD.COM WITH THE RELEVANT DETAILS.
WARRANTY AND LIMITATION OF LIABILITY
------------------------------------
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
FMOD Uses Ogg Vorbis codec. BSD license.
-----------------------------------------
Copyright (c) 2002, Xiph.org Foundation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Xiph.org Foundation nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
For Android platform code.
--------------------------
Copyright (C) 2010 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,19 +0,0 @@
Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,22 +0,0 @@
crunch/crnlib uses the ZLIB license:
http://opensource.org/licenses/Zlib
Copyright (c) 2010-2016 Richard Geldreich, Jr. and Binomial LLC
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

Binary file not shown.

View File

@@ -1,13 +0,0 @@
Copyright (c) 2015 Harm Hanemaaijer <fgenfb@yahoo.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Binary file not shown.

Binary file not shown.

View File

@@ -14,5 +14,13 @@ namespace AssetStudio
public static void Info(string message) => Default.Log(LoggerEvent.Info, message);
public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message);
public static void Error(string message) => Default.Log(LoggerEvent.Error, message);
public static void Error(string message, Exception e)
{
var sb = new StringBuilder();
sb.AppendLine(message);
sb.AppendLine(e.ToString());
Default.Log(LoggerEvent.Error, sb.ToString());
}
}
}

84
AssetStudio/Math/Color.cs Normal file
View File

@@ -0,0 +1,84 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Color : IEquatable<Color>
{
public float R;
public float G;
public float B;
public float A;
public Color(float r, float g, float b, float a)
{
R = r;
G = g;
B = b;
A = a;
}
public override int GetHashCode()
{
return ((Vector4)this).GetHashCode();
}
public override bool Equals(object other)
{
if (!(other is Color))
return false;
return Equals((Color)other);
}
public bool Equals(Color other)
{
return R.Equals(other.R) && G.Equals(other.G) && B.Equals(other.B) && A.Equals(other.A);
}
public static Color operator +(Color a, Color b)
{
return new Color(a.R + b.R, a.G + b.G, a.B + b.B, a.A + b.A);
}
public static Color operator -(Color a, Color b)
{
return new Color(a.R - b.R, a.G - b.G, a.B - b.B, a.A - b.A);
}
public static Color operator *(Color a, Color b)
{
return new Color(a.R * b.R, a.G * b.G, a.B * b.B, a.A * b.A);
}
public static Color operator *(Color a, float b)
{
return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
}
public static Color operator *(float b, Color a)
{
return new Color(a.R * b, a.G * b, a.B * b, a.A * b);
}
public static Color operator /(Color a, float b)
{
return new Color(a.R / b, a.G / b, a.B / b, a.A / b);
}
public static bool operator ==(Color lhs, Color rhs)
{
return (Vector4)lhs == (Vector4)rhs;
}
public static bool operator !=(Color lhs, Color rhs)
{
return !(lhs == rhs);
}
public static implicit operator Vector4(Color c)
{
return new Vector4(c.R, c.G, c.B, c.A);
}
}
}

888
AssetStudio/Math/Half.cs Normal file
View File

@@ -0,0 +1,888 @@
using System;
using System.Diagnostics;
using System.Globalization;
namespace AssetStudio
{
/// <summary>
/// Represents a half-precision floating point number.
/// </summary>
/// <remarks>
/// Note:
/// Half is not fast enought and precision is also very bad,
/// so is should not be used for matemathical computation (use Single instead).
/// The main advantage of Half type is lower memory cost: two bytes per number.
/// Half is typically used in graphical applications.
///
/// Note:
/// All functions, where is used conversion half->float/float->half,
/// are approx. ten times slower than float->double/double->float, i.e. ~3ns on 2GHz CPU.
///
/// References:
/// - Fast Half Float Conversions, Jeroen van der Zijp, link: http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf
/// - IEEE 754 revision, link: http://grouper.ieee.org/groups/754/
/// </remarks>
[Serializable]
public struct Half : IComparable, IFormattable, IConvertible, IComparable<Half>, IEquatable<Half>
{
/// <summary>
/// Internal representation of the half-precision floating-point number.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
internal ushort value;
#region Constants
/// <summary>
/// Represents the smallest positive System.Half value greater than zero. This field is constant.
/// </summary>
public static readonly Half Epsilon = Half.ToHalf(0x0001);
/// <summary>
/// Represents the largest possible value of System.Half. This field is constant.
/// </summary>
public static readonly Half MaxValue = Half.ToHalf(0x7bff);
/// <summary>
/// Represents the smallest possible value of System.Half. This field is constant.
/// </summary>
public static readonly Half MinValue = Half.ToHalf(0xfbff);
/// <summary>
/// Represents not a number (NaN). This field is constant.
/// </summary>
public static readonly Half NaN = Half.ToHalf(0xfe00);
/// <summary>
/// Represents negative infinity. This field is constant.
/// </summary>
public static readonly Half NegativeInfinity = Half.ToHalf(0xfc00);
/// <summary>
/// Represents positive infinity. This field is constant.
/// </summary>
public static readonly Half PositiveInfinity = Half.ToHalf(0x7c00);
#endregion
#region Constructors
/// <summary>
/// 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); }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified 32-bit signed integer.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(int value) : this((float)value) { }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified 64-bit signed integer.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(long value) : this((float)value) { }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified double-precision floating-point number.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(double value) : this((float)value) { }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified decimal number.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(decimal value) : this((float)value) { }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified 32-bit unsigned integer.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(uint value) : this((float)value) { }
/// <summary>
/// Initializes a new instance of System.Half to the value of the specified 64-bit unsigned integer.
/// </summary>
/// <param name="value">The value to represent as a System.Half.</param>
public Half(ulong value) : this((float)value) { }
#endregion
#region Numeric operators
/// <summary>
/// Returns the result of multiplying the specified System.Half value by negative one.
/// </summary>
/// <param name="half">A System.Half.</param>
/// <returns>A System.Half with the value of half, but the opposite sign. -or- Zero, if half is zero.</returns>
public static Half Negate(Half half) { return -half; }
/// <summary>
/// Adds two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>A System.Half value that is the sum of half1 and half2.</returns>
public static Half Add(Half half1, Half half2) { return half1 + half2; }
/// <summary>
/// Subtracts one specified System.Half value from another.
/// </summary>
/// <param name="half1">A System.Half (the minuend).</param>
/// <param name="half2">A System.Half (the subtrahend).</param>
/// <returns>The System.Half result of subtracting half2 from half1.</returns>
public static Half Subtract(Half half1, Half half2) { return half1 - half2; }
/// <summary>
/// Multiplies two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half (the multiplicand).</param>
/// <param name="half2">A System.Half (the multiplier).</param>
/// <returns>A System.Half that is the result of multiplying half1 and half2.</returns>
public static Half Multiply(Half half1, Half half2) { return half1 * half2; }
/// <summary>
/// Divides two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half (the dividend).</param>
/// <param name="half2">A System.Half (the divisor).</param>
/// <returns>The System.Half that is the result of dividing half1 by half2.</returns>
/// <exception cref="System.DivideByZeroException">half2 is zero.</exception>
public static Half Divide(Half half1, Half half2) { return half1 / half2; }
/// <summary>
/// Returns the value of the System.Half operand (the sign of the operand is unchanged).
/// </summary>
/// <param name="half">The System.Half operand.</param>
/// <returns>The value of the operand, half.</returns>
public static Half operator +(Half half) { return half; }
/// <summary>
/// Negates the value of the specified System.Half operand.
/// </summary>
/// <param name="half">The System.Half operand.</param>
/// <returns>The result of half multiplied by negative one (-1).</returns>
public static Half operator -(Half half) { return HalfHelper.Negate(half); }
/// <summary>
/// Increments the System.Half operand by 1.
/// </summary>
/// <param name="half">The System.Half operand.</param>
/// <returns>The value of half incremented by 1.</returns>
public static Half operator ++(Half half) { return (Half)(half + 1f); }
/// <summary>
/// Decrements the System.Half operand by one.
/// </summary>
/// <param name="half">The System.Half operand.</param>
/// <returns>The value of half decremented by 1.</returns>
public static Half operator --(Half half) { return (Half)(half - 1f); }
/// <summary>
/// Adds two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>The System.Half result of adding half1 and half2.</returns>
public static Half operator +(Half half1, Half half2) { return (Half)((float)half1 + (float)half2); }
/// <summary>
/// Subtracts two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>The System.Half result of subtracting half1 and half2.</returns>
public static Half operator -(Half half1, Half half2) { return (Half)((float)half1 - (float)half2); }
/// <summary>
/// Multiplies two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>The System.Half result of multiplying half1 by half2.</returns>
public static Half operator *(Half half1, Half half2) { return (Half)((float)half1 * (float)half2); }
/// <summary>
/// Divides two specified System.Half values.
/// </summary>
/// <param name="half1">A System.Half (the dividend).</param>
/// <param name="half2">A System.Half (the divisor).</param>
/// <returns>The System.Half result of half1 by half2.</returns>
public static Half operator /(Half half1, Half half2) { return (Half)((float)half1 / (float)half2); }
/// <summary>
/// Returns a value indicating whether two instances of System.Half are equal.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 and half2 are equal; otherwise, false.</returns>
public static bool operator ==(Half half1, Half half2) { return (!IsNaN(half1) && (half1.value == half2.value)); }
/// <summary>
/// Returns a value indicating whether two instances of System.Half are not equal.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 and half2 are not equal; otherwise, false.</returns>
public static bool operator !=(Half half1, Half half2) { return !(half1.value == half2.value); }
/// <summary>
/// Returns a value indicating whether a specified System.Half is less than another specified System.Half.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 is less than half1; otherwise, false.</returns>
public static bool operator <(Half half1, Half half2) { return (float)half1 < (float)half2; }
/// <summary>
/// Returns a value indicating whether a specified System.Half is greater than another specified System.Half.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 is greater than half2; otherwise, false.</returns>
public static bool operator >(Half half1, Half half2) { return (float)half1 > (float)half2; }
/// <summary>
/// Returns a value indicating whether a specified System.Half is less than or equal to another specified System.Half.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 is less than or equal to half2; otherwise, false.</returns>
public static bool operator <=(Half half1, Half half2) { return (half1 == half2) || (half1 < half2); }
/// <summary>
/// Returns a value indicating whether a specified System.Half is greater than or equal to another specified System.Half.
/// </summary>
/// <param name="half1">A System.Half.</param>
/// <param name="half2">A System.Half.</param>
/// <returns>true if half1 is greater than or equal to half2; otherwise, false.</returns>
public static bool operator >=(Half half1, Half half2) { return (half1 == half2) || (half1 > half2); }
#endregion
#region Type casting operators
/// <summary>
/// Converts an 8-bit unsigned integer to a System.Half.
/// </summary>
/// <param name="value">An 8-bit unsigned integer.</param>
/// <returns>A System.Half that represents the converted 8-bit unsigned integer.</returns>
public static implicit operator Half(byte value) { return new Half((float)value); }
/// <summary>
/// Converts a 16-bit signed integer to a System.Half.
/// </summary>
/// <param name="value">A 16-bit signed integer.</param>
/// <returns>A System.Half that represents the converted 16-bit signed integer.</returns>
public static implicit operator Half(short value) { return new Half((float)value); }
/// <summary>
/// Converts a Unicode character to a System.Half.
/// </summary>
/// <param name="value">A Unicode character.</param>
/// <returns>A System.Half that represents the converted Unicode character.</returns>
public static implicit operator Half(char value) { return new Half((float)value); }
/// <summary>
/// Converts a 32-bit signed integer to a System.Half.
/// </summary>
/// <param name="value">A 32-bit signed integer.</param>
/// <returns>A System.Half that represents the converted 32-bit signed integer.</returns>
public static implicit operator Half(int value) { return new Half((float)value); }
/// <summary>
/// Converts a 64-bit signed integer to a System.Half.
/// </summary>
/// <param name="value">A 64-bit signed integer.</param>
/// <returns>A System.Half that represents the converted 64-bit signed integer.</returns>
public static implicit operator Half(long value) { return new Half((float)value); }
/// <summary>
/// Converts a single-precision floating-point number to a System.Half.
/// </summary>
/// <param name="value">A single-precision floating-point number.</param>
/// <returns>A System.Half that represents the converted single-precision floating point number.</returns>
public static explicit operator Half(float value) { return new Half((float)value); }
/// <summary>
/// Converts a double-precision floating-point number to a System.Half.
/// </summary>
/// <param name="value">A double-precision floating-point number.</param>
/// <returns>A System.Half that represents the converted double-precision floating point number.</returns>
public static explicit operator Half(double value) { return new Half((float)value); }
/// <summary>
/// Converts a decimal number to a System.Half.
/// </summary>
/// <param name="value">decimal number</param>
/// <returns>A System.Half that represents the converted decimal number.</returns>
public static explicit operator Half(decimal value) { return new Half((float)value); }
/// <summary>
/// Converts a System.Half to an 8-bit unsigned integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>An 8-bit unsigned integer that represents the converted System.Half.</returns>
public static explicit operator byte(Half value) { return (byte)(float)value; }
/// <summary>
/// Converts a System.Half to a Unicode character.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A Unicode character that represents the converted System.Half.</returns>
public static explicit operator char(Half value) { return (char)(float)value; }
/// <summary>
/// Converts a System.Half to a 16-bit signed integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 16-bit signed integer that represents the converted System.Half.</returns>
public static explicit operator short(Half value) { return (short)(float)value; }
/// <summary>
/// Converts a System.Half to a 32-bit signed integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 32-bit signed integer that represents the converted System.Half.</returns>
public static explicit operator int(Half value) { return (int)(float)value; }
/// <summary>
/// Converts a System.Half to a 64-bit signed integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 64-bit signed integer that represents the converted System.Half.</returns>
public static explicit operator long(Half value) { return (long)(float)value; }
/// <summary>
/// Converts a System.Half to a single-precision floating-point number.
/// </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); }
/// <summary>
/// Converts a System.Half to a double-precision floating-point number.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A double-precision floating-point number that represents the converted System.Half.</returns>
public static implicit operator double(Half value) { return (double)(float)value; }
/// <summary>
/// Converts a System.Half to a decimal number.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A decimal number that represents the converted System.Half.</returns>
public static explicit operator decimal(Half value) { return (decimal)(float)value; }
/// <summary>
/// Converts an 8-bit signed integer to a System.Half.
/// </summary>
/// <param name="value">An 8-bit signed integer.</param>
/// <returns>A System.Half that represents the converted 8-bit signed integer.</returns>
public static implicit operator Half(sbyte value) { return new Half((float)value); }
/// <summary>
/// Converts a 16-bit unsigned integer to a System.Half.
/// </summary>
/// <param name="value">A 16-bit unsigned integer.</param>
/// <returns>A System.Half that represents the converted 16-bit unsigned integer.</returns>
public static implicit operator Half(ushort value) { return new Half((float)value); }
/// <summary>
/// Converts a 32-bit unsigned integer to a System.Half.
/// </summary>
/// <param name="value">A 32-bit unsigned integer.</param>
/// <returns>A System.Half that represents the converted 32-bit unsigned integer.</returns>
public static implicit operator Half(uint value) { return new Half((float)value); }
/// <summary>
/// Converts a 64-bit unsigned integer to a System.Half.
/// </summary>
/// <param name="value">A 64-bit unsigned integer.</param>
/// <returns>A System.Half that represents the converted 64-bit unsigned integer.</returns>
public static implicit operator Half(ulong value) { return new Half((float)value); }
/// <summary>
/// Converts a System.Half to an 8-bit signed integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>An 8-bit signed integer that represents the converted System.Half.</returns>
public static explicit operator sbyte(Half value) { return (sbyte)(float)value; }
/// <summary>
/// Converts a System.Half to a 16-bit unsigned integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 16-bit unsigned integer that represents the converted System.Half.</returns>
public static explicit operator ushort(Half value) { return (ushort)(float)value; }
/// <summary>
/// Converts a System.Half to a 32-bit unsigned integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 32-bit unsigned integer that represents the converted System.Half.</returns>
public static explicit operator uint(Half value) { return (uint)(float)value; }
/// <summary>
/// Converts a System.Half to a 64-bit unsigned integer.
/// </summary>
/// <param name="value">A System.Half to convert.</param>
/// <returns>A 64-bit unsigned integer that represents the converted System.Half.</returns>
public static explicit operator ulong(Half value) { return (ulong)(float)value; }
#endregion
/// <summary>
/// Compares this instance to a specified System.Half object.
/// </summary>
/// <param name="other">A System.Half object.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and value.
/// Return Value Meaning Less than zero This instance is less than value. Zero
/// This instance is equal to value. Greater than zero This instance is greater than value.
/// </returns>
public int CompareTo(Half other)
{
int result = 0;
if (this < other)
{
result = -1;
}
else if (this > other)
{
result = 1;
}
else if (this != other)
{
if (!IsNaN(this))
{
result = 1;
}
else if (!IsNaN(other))
{
result = -1;
}
}
return result;
}
/// <summary>
/// Compares this instance to a specified System.Object.
/// </summary>
/// <param name="obj">An System.Object or null.</param>
/// <returns>
/// A signed number indicating the relative values of this instance and value.
/// Return Value Meaning Less than zero This instance is less than value. Zero
/// This instance is equal to value. Greater than zero This instance is greater
/// than value. -or- value is null.
/// </returns>
/// <exception cref="System.ArgumentException">value is not a System.Half</exception>
public int CompareTo(object obj)
{
int result = 0;
if (obj == null)
{
result = 1;
}
else
{
if (obj is Half)
{
result = CompareTo((Half)obj);
}
else
{
throw new ArgumentException("Object must be of type Half.");
}
}
return result;
}
/// <summary>
/// Returns a value indicating whether this instance and a specified System.Half object represent the same value.
/// </summary>
/// <param name="other">A System.Half object to compare to this instance.</param>
/// <returns>true if value is equal to this instance; otherwise, false.</returns>
public bool Equals(Half other)
{
return ((other == this) || (IsNaN(other) && IsNaN(this)));
}
/// <summary>
/// Returns a value indicating whether this instance and a specified System.Object
/// represent the same type and value.
/// </summary>
/// <param name="obj">An System.Object.</param>
/// <returns>true if value is a System.Half and equal to this instance; otherwise, false.</returns>
public override bool Equals(object obj)
{
bool result = false;
if (obj is Half)
{
Half half = (Half)obj;
if ((half == this) || (IsNaN(half) && IsNaN(this)))
{
result = true;
}
}
return result;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return value.GetHashCode();
}
/// <summary>
/// Returns the System.TypeCode for value type System.Half.
/// </summary>
/// <returns>The enumerated constant (TypeCode)255.</returns>
public TypeCode GetTypeCode()
{
return (TypeCode)255;
}
#region BitConverter & Math methods for Half
/// <summary>
/// Returns the specified half-precision floating point value as an array of bytes.
/// </summary>
/// <param name="value">The number to convert.</param>
/// <returns>An array of bytes with length 2.</returns>
public static byte[] GetBytes(Half value)
{
return BitConverter.GetBytes(value.value);
}
/// <summary>
/// Converts the value of a specified instance of System.Half to its equivalent binary representation.
/// </summary>
/// <param name="value">A System.Half value.</param>
/// <returns>A 16-bit unsigned integer that contain the binary representation of value.</returns>
public static ushort GetBits(Half value)
{
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.
/// </summary>
/// <param name="value">A signed number.</param>
/// <returns>
/// A number indicating the sign of value. Number Description -1 value is less
/// than zero. 0 value is equal to zero. 1 value is greater than zero.
/// </returns>
/// <exception cref="System.ArithmeticException">value is equal to System.Half.NaN.</exception>
public static int Sign(Half value)
{
if (value < 0)
{
return -1;
}
else if (value > 0)
{
return 1;
}
else
{
if (value != 0)
{
throw new ArithmeticException("Function does not accept floating point Not-a-Number values.");
}
}
return 0;
}
/// <summary>
/// Returns the absolute value of a half-precision floating-point number.
/// </summary>
/// <param name="value">A number in the range System.Half.MinValue ≤ value ≤ System.Half.MaxValue.</param>
/// <returns>A half-precision floating-point number, x, such that 0 ≤ x ≤System.Half.MaxValue.</returns>
public static Half Abs(Half value)
{
return HalfHelper.Abs(value);
}
/// <summary>
/// Returns the larger of two half-precision floating-point numbers.
/// </summary>
/// <param name="value1">The first of two half-precision floating-point numbers to compare.</param>
/// <param name="value2">The second of two half-precision floating-point numbers to compare.</param>
/// <returns>
/// Parameter value1 or value2, whichever is larger. If value1, or value2, or both val1
/// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.
/// </returns>
public static Half Max(Half value1, Half value2)
{
return (value1 < value2) ? value2 : value1;
}
/// <summary>
/// Returns the smaller of two half-precision floating-point numbers.
/// </summary>
/// <param name="value1">The first of two half-precision floating-point numbers to compare.</param>
/// <param name="value2">The second of two half-precision floating-point numbers to compare.</param>
/// <returns>
/// Parameter value1 or value2, whichever is smaller. If value1, or value2, or both val1
/// and value2 are equal to System.Half.NaN, System.Half.NaN is returned.
/// </returns>
public static Half Min(Half value1, Half value2)
{
return (value1 < value2) ? value1 : value2;
}
#endregion
/// <summary>
/// Returns a value indicating whether the specified number evaluates to not a number (System.Half.NaN).
/// </summary>
/// <param name="half">A half-precision floating-point number.</param>
/// <returns>true if value evaluates to not a number (System.Half.NaN); otherwise, false.</returns>
public static bool IsNaN(Half half)
{
return HalfHelper.IsNaN(half);
}
/// <summary>
/// Returns a value indicating whether the specified number evaluates to negative or positive infinity.
/// </summary>
/// <param name="half">A half-precision floating-point number.</param>
/// <returns>true if half evaluates to System.Half.PositiveInfinity or System.Half.NegativeInfinity; otherwise, false.</returns>
public static bool IsInfinity(Half half)
{
return HalfHelper.IsInfinity(half);
}
/// <summary>
/// Returns a value indicating whether the specified number evaluates to negative infinity.
/// </summary>
/// <param name="half">A half-precision floating-point number.</param>
/// <returns>true if half evaluates to System.Half.NegativeInfinity; otherwise, false.</returns>
public static bool IsNegativeInfinity(Half half)
{
return HalfHelper.IsNegativeInfinity(half);
}
/// <summary>
/// Returns a value indicating whether the specified number evaluates to positive infinity.
/// </summary>
/// <param name="half">A half-precision floating-point number.</param>
/// <returns>true if half evaluates to System.Half.PositiveInfinity; otherwise, false.</returns>
public static bool IsPositiveInfinity(Half half)
{
return HalfHelper.IsPositiveInfinity(half);
}
#region String operations (Parse and ToString)
/// <summary>
/// Converts the string representation of a number to its System.Half equivalent.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <returns>The System.Half number equivalent to the number contained in value.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
public static Half Parse(string value)
{
return (Half)float.Parse(value, CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts the string representation of a number to its System.Half equivalent
/// using the specified culture-specific format information.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <param name="provider">An System.IFormatProvider that supplies culture-specific parsing information about value.</param>
/// <returns>The System.Half number equivalent to the number contained in s as specified by provider.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
public static Half Parse(string value, IFormatProvider provider)
{
return (Half)float.Parse(value, provider);
}
/// <summary>
/// Converts the string representation of a number in a specified style to its System.Half equivalent.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <param name="style">
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
/// the style elements that can be present in value. A typical value to specify is
/// System.Globalization.NumberStyles.Number.
/// </param>
/// <returns>The System.Half number equivalent to the number contained in s as specified by style.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentException">
/// style is not a System.Globalization.NumberStyles value. -or- style is the
/// System.Globalization.NumberStyles.AllowHexSpecifier value.
/// </exception>
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
public static Half Parse(string value, NumberStyles style)
{
return (Half)float.Parse(value, style, CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts the string representation of a number to its System.Half equivalent
/// using the specified style and culture-specific format.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <param name="style">
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
/// the style elements that can be present in value. A typical value to specify is
/// System.Globalization.NumberStyles.Number.
/// </param>
/// <param name="provider">An System.IFormatProvider object that supplies culture-specific information about the format of value.</param>
/// <returns>The System.Half number equivalent to the number contained in s as specified by style and provider.</returns>
/// <exception cref="System.ArgumentNullException">value is null.</exception>
/// <exception cref="System.ArgumentException">
/// style is not a System.Globalization.NumberStyles value. -or- style is the
/// System.Globalization.NumberStyles.AllowHexSpecifier value.
/// </exception>
/// <exception cref="System.FormatException">value is not in the correct format.</exception>
/// <exception cref="System.OverflowException">value represents a number less than System.Half.MinValue or greater than System.Half.MaxValue.</exception>
public static Half Parse(string value, NumberStyles style, IFormatProvider provider)
{
return (Half)float.Parse(value, style, provider);
}
/// <summary>
/// Converts the string representation of a number to its System.Half equivalent.
/// A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <param name="result">
/// When this method returns, contains the System.Half number that is equivalent
/// to the numeric value contained in value, if the conversion succeeded, or is zero
/// if the conversion failed. The conversion fails if the s parameter is null,
/// is not a number in a valid format, or represents a number less than System.Half.MinValue
/// or greater than System.Half.MaxValue. This parameter is passed uninitialized.
/// </param>
/// <returns>true if s was converted successfully; otherwise, false.</returns>
public static bool TryParse(string value, out Half result)
{
float f;
if (float.TryParse(value, out f))
{
result = (Half)f;
return true;
}
result = new Half();
return false;
}
/// <summary>
/// Converts the string representation of a number to its System.Half equivalent
/// using the specified style and culture-specific format. A return value indicates
/// whether the conversion succeeded or failed.
/// </summary>
/// <param name="value">The string representation of the number to convert.</param>
/// <param name="style">
/// A bitwise combination of System.Globalization.NumberStyles values that indicates
/// the permitted format of value. A typical value to specify is System.Globalization.NumberStyles.Number.
/// </param>
/// <param name="provider">An System.IFormatProvider object that supplies culture-specific parsing information about value.</param>
/// <param name="result">
/// When this method returns, contains the System.Half number that is equivalent
/// to the numeric value contained in value, if the conversion succeeded, or is zero
/// if the conversion failed. The conversion fails if the s parameter is null,
/// is not in a format compliant with style, or represents a number less than
/// System.Half.MinValue or greater than System.Half.MaxValue. This parameter is passed uninitialized.
/// </param>
/// <returns>true if s was converted successfully; otherwise, false.</returns>
/// <exception cref="System.ArgumentException">
/// style is not a System.Globalization.NumberStyles value. -or- style
/// is the System.Globalization.NumberStyles.AllowHexSpecifier value.
/// </exception>
public static bool TryParse(string value, NumberStyles style, IFormatProvider provider, out Half result)
{
bool parseResult = false;
float f;
if (float.TryParse(value, style, provider, out f))
{
result = (Half)f;
parseResult = true;
}
else
{
result = new Half();
}
return parseResult;
}
/// <summary>
/// Converts the numeric value of this instance to its equivalent string representation.
/// </summary>
/// <returns>A string that represents the value of this instance.</returns>
public override string ToString()
{
return ((float)this).ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts the numeric value of this instance to its equivalent string representation
/// using the specified culture-specific format information.
/// </summary>
/// <param name="formatProvider">An System.IFormatProvider that supplies culture-specific formatting information.</param>
/// <returns>The string representation of the value of this instance as specified by provider.</returns>
public string ToString(IFormatProvider formatProvider)
{
return ((float)this).ToString(formatProvider);
}
/// <summary>
/// Converts the numeric value of this instance to its equivalent string representation, using the specified format.
/// </summary>
/// <param name="format">A numeric format string.</param>
/// <returns>The string representation of the value of this instance as specified by format.</returns>
public string ToString(string format)
{
return ((float)this).ToString(format, CultureInfo.InvariantCulture);
}
/// <summary>
/// Converts the numeric value of this instance to its equivalent string representation
/// using the specified format and culture-specific format information.
/// </summary>
/// <param name="format">A numeric format string.</param>
/// <param name="formatProvider">An System.IFormatProvider that supplies culture-specific formatting information.</param>
/// <returns>The string representation of the value of this instance as specified by format and provider.</returns>
/// <exception cref="System.FormatException">format is invalid.</exception>
public string ToString(string format, IFormatProvider formatProvider)
{
return ((float)this).ToString(format, formatProvider);
}
#endregion
#region IConvertible Members
float IConvertible.ToSingle(IFormatProvider provider)
{
return (float)this;
}
TypeCode IConvertible.GetTypeCode()
{
return GetTypeCode();
}
bool IConvertible.ToBoolean(IFormatProvider provider)
{
return Convert.ToBoolean((float)this);
}
byte IConvertible.ToByte(IFormatProvider provider)
{
return Convert.ToByte((float)this);
}
char IConvertible.ToChar(IFormatProvider provider)
{
throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, "Invalid cast from '{0}' to '{1}'.", "Half", "Char"));
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
throw new InvalidCastException(string.Format(CultureInfo.CurrentCulture, "Invalid cast from '{0}' to '{1}'.", "Half", "DateTime"));
}
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal((float)this);
}
double IConvertible.ToDouble(IFormatProvider provider)
{
return Convert.ToDouble((float)this);
}
short IConvertible.ToInt16(IFormatProvider provider)
{
return Convert.ToInt16((float)this);
}
int IConvertible.ToInt32(IFormatProvider provider)
{
return Convert.ToInt32((float)this);
}
long IConvertible.ToInt64(IFormatProvider provider)
{
return Convert.ToInt64((float)this);
}
sbyte IConvertible.ToSByte(IFormatProvider provider)
{
return Convert.ToSByte((float)this);
}
string IConvertible.ToString(IFormatProvider provider)
{
return Convert.ToString((float)this, CultureInfo.InvariantCulture);
}
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
return (((float)this) as IConvertible).ToType(conversionType, provider);
}
ushort IConvertible.ToUInt16(IFormatProvider provider)
{
return Convert.ToUInt16((float)this);
}
uint IConvertible.ToUInt32(IFormatProvider provider)
{
return Convert.ToUInt32((float)this);
}
ulong IConvertible.ToUInt64(IFormatProvider provider)
{
return Convert.ToUInt64((float)this);
}
#endregion
}
}

View File

@@ -0,0 +1,212 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
/// <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
{
private static uint[] mantissaTable = GenerateMantissaTable();
private static uint[] exponentTable = GenerateExponentTable();
private static ushort[] offsetTable = GenerateOffsetTable();
private static ushort[] baseTable = GenerateBaseTable();
private static sbyte[] shiftTable = GenerateShiftTable();
// Transforms the subnormal representation to a normalized one.
private static uint ConvertMantissa(int i)
{
uint m = (uint)(i << 13); // Zero pad mantissa bits
uint e = 0; // Zero exponent
// While not normalized
while ((m & 0x00800000) == 0)
{
e -= 0x00800000; // Decrement exponent (1<<23)
m <<= 1; // Shift mantissa
}
m &= unchecked((uint)~0x00800000); // Clear leading 1 bit
e += 0x38800000; // Adjust bias ((127-14)<<23)
return m | e; // Return combined number
}
private static uint[] GenerateMantissaTable()
{
uint[] mantissaTable = new uint[2048];
mantissaTable[0] = 0;
for (int i = 1; i < 1024; i++)
{
mantissaTable[i] = ConvertMantissa(i);
}
for (int i = 1024; i < 2048; i++)
{
mantissaTable[i] = (uint)(0x38000000 + ((i - 1024) << 13));
}
return mantissaTable;
}
private static uint[] GenerateExponentTable()
{
uint[] exponentTable = new uint[64];
exponentTable[0] = 0;
for (int i = 1; i < 31; i++)
{
exponentTable[i] = (uint)(i << 23);
}
exponentTable[31] = 0x47800000;
exponentTable[32] = 0x80000000;
for (int i = 33; i < 63; i++)
{
exponentTable[i] = (uint)(0x80000000 + ((i - 32) << 23));
}
exponentTable[63] = 0xc7800000;
return exponentTable;
}
private static ushort[] GenerateOffsetTable()
{
ushort[] offsetTable = new ushort[64];
offsetTable[0] = 0;
for (int i = 1; i < 32; i++)
{
offsetTable[i] = 1024;
}
offsetTable[32] = 0;
for (int i = 33; i < 64; i++)
{
offsetTable[i] = 1024;
}
return offsetTable;
}
private static ushort[] GenerateBaseTable()
{
ushort[] baseTable = new ushort[512];
for (int i = 0; i < 256; ++i)
{
sbyte e = (sbyte)(127 - i);
if (e > 24)
{ // Very small numbers map to zero
baseTable[i | 0x000] = 0x0000;
baseTable[i | 0x100] = 0x8000;
}
else if (e > 14)
{ // Small numbers map to denorms
baseTable[i | 0x000] = (ushort)(0x0400 >> (18 + e));
baseTable[i | 0x100] = (ushort)((0x0400 >> (18 + e)) | 0x8000);
}
else if (e >= -15)
{ // Normal numbers just lose precision
baseTable[i | 0x000] = (ushort)((15 - e) << 10);
baseTable[i | 0x100] = (ushort)(((15 - e) << 10) | 0x8000);
}
else if (e > -128)
{ // Large numbers map to Infinity
baseTable[i | 0x000] = 0x7c00;
baseTable[i | 0x100] = 0xfc00;
}
else
{ // Infinity and NaN's stay Infinity and NaN's
baseTable[i | 0x000] = 0x7c00;
baseTable[i | 0x100] = 0xfc00;
}
}
return baseTable;
}
private static sbyte[] GenerateShiftTable()
{
sbyte[] shiftTable = new sbyte[512];
for (int i = 0; i < 256; ++i)
{
sbyte e = (sbyte)(127 - i);
if (e > 24)
{ // Very small numbers map to zero
shiftTable[i | 0x000] = 24;
shiftTable[i | 0x100] = 24;
}
else if (e > 14)
{ // Small numbers map to denorms
shiftTable[i | 0x000] = (sbyte)(e - 1);
shiftTable[i | 0x100] = (sbyte)(e - 1);
}
else if (e >= -15)
{ // Normal numbers just lose precision
shiftTable[i | 0x000] = 13;
shiftTable[i | 0x100] = 13;
}
else if (e > -128)
{ // Large numbers map to Infinity
shiftTable[i | 0x000] = 24;
shiftTable[i | 0x100] = 24;
}
else
{ // Infinity and NaN's stay Infinity and NaN's
shiftTable[i | 0x000] = 13;
shiftTable[i | 0x100] = 13;
}
}
return shiftTable;
}
/*public static unsafe float HalfToSingle(Half half)
{
uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10];
return *((float*)&result);
}
public static unsafe Half SingleToHalf(float single)
{
uint value = *((uint*)&single);
ushort result = (ushort)(baseTable[(value >> 23) & 0x1ff] + ((value & 0x007fffff) >> shiftTable[value >> 23]));
return Half.ToHalf(result);
}*/
public static float HalfToSingle(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));
}
public static Half Abs(Half half)
{
return Half.ToHalf((ushort)(half.value & 0x7fff));
}
public static bool IsNaN(Half half)
{
return ((half.value & 0x7fff) > 0x7c00);
}
public static bool IsInfinity(Half half)
{
return ((half.value & 0x7fff) == 0x7c00);
}
public static bool IsPositiveInfinity(Half half)
{
return (half.value == 0x7c00);
}
public static bool IsNegativeInfinity(Half half)
{
return (half.value == 0xfc00);
}
}
}

View File

@@ -0,0 +1,241 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Matrix4x4 : IEquatable<Matrix4x4>
{
public float M00;
public float M10;
public float M20;
public float M30;
public float M01;
public float M11;
public float M21;
public float M31;
public float M02;
public float M12;
public float M22;
public float M32;
public float M03;
public float M13;
public float M23;
public float M33;
public Matrix4x4(float[] values)
{
if (values == null)
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.");
M00 = values[0];
M10 = values[1];
M20 = values[2];
M30 = values[3];
M01 = values[4];
M11 = values[5];
M21 = values[6];
M31 = values[7];
M02 = values[8];
M12 = values[9];
M22 = values[10];
M32 = values[11];
M03 = values[12];
M13 = values[13];
M23 = values[14];
M33 = values[15];
}
public float this[int row, int column]
{
get => this[row + column * 4];
set => this[row + column * 4] = value;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return M00;
case 1: return M10;
case 2: return M20;
case 3: return M30;
case 4: return M01;
case 5: return M11;
case 6: return M21;
case 7: return M31;
case 8: return M02;
case 9: return M12;
case 10: return M22;
case 11: return M32;
case 12: return M03;
case 13: return M13;
case 14: return M23;
case 15: return M33;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
}
}
set
{
switch (index)
{
case 0: M00 = value; break;
case 1: M10 = value; break;
case 2: M20 = value; break;
case 3: M30 = value; break;
case 4: M01 = value; break;
case 5: M11 = value; break;
case 6: M21 = value; break;
case 7: M31 = value; break;
case 8: M02 = value; break;
case 9: M12 = value; break;
case 10: M22 = value; break;
case 11: M32 = value; break;
case 12: M03 = value; break;
case 13: M13 = value; break;
case 14: M23 = value; break;
case 15: M33 = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Matrix4x4 index!");
}
}
}
public override int GetHashCode()
{
return GetColumn(0).GetHashCode() ^ (GetColumn(1).GetHashCode() << 2) ^ (GetColumn(2).GetHashCode() >> 2) ^ (GetColumn(3).GetHashCode() >> 1);
}
public override bool Equals(object other)
{
if (!(other is Matrix4x4))
return false;
return Equals((Matrix4x4)other);
}
public bool Equals(Matrix4x4 other)
{
return GetColumn(0).Equals(other.GetColumn(0))
&& GetColumn(1).Equals(other.GetColumn(1))
&& GetColumn(2).Equals(other.GetColumn(2))
&& GetColumn(3).Equals(other.GetColumn(3));
}
public Vector4 GetColumn(int index)
{
switch (index)
{
case 0: return new Vector4(M00, M10, M20, M30);
case 1: return new Vector4(M01, M11, M21, M31);
case 2: return new Vector4(M02, M12, M22, M32);
case 3: return new Vector4(M03, M13, M23, M33);
default: throw new IndexOutOfRangeException("Invalid column index!");
}
}
public Vector4 GetRow(int index)
{
switch (index)
{
case 0: return new Vector4(M00, M01, M02, M03);
case 1: return new Vector4(M10, M11, M12, M13);
case 2: return new Vector4(M20, M21, M22, M23);
case 3: return new Vector4(M30, M31, M32, M33);
default: throw new IndexOutOfRangeException("Invalid row index!");
}
}
public static Matrix4x4 operator *(Matrix4x4 lhs, Matrix4x4 rhs)
{
Matrix4x4 res;
res.M00 = lhs.M00 * rhs.M00 + lhs.M01 * rhs.M10 + lhs.M02 * rhs.M20 + lhs.M03 * rhs.M30;
res.M01 = lhs.M00 * rhs.M01 + lhs.M01 * rhs.M11 + lhs.M02 * rhs.M21 + lhs.M03 * rhs.M31;
res.M02 = lhs.M00 * rhs.M02 + lhs.M01 * rhs.M12 + lhs.M02 * rhs.M22 + lhs.M03 * rhs.M32;
res.M03 = lhs.M00 * rhs.M03 + lhs.M01 * rhs.M13 + lhs.M02 * rhs.M23 + lhs.M03 * rhs.M33;
res.M10 = lhs.M10 * rhs.M00 + lhs.M11 * rhs.M10 + lhs.M12 * rhs.M20 + lhs.M13 * rhs.M30;
res.M11 = lhs.M10 * rhs.M01 + lhs.M11 * rhs.M11 + lhs.M12 * rhs.M21 + lhs.M13 * rhs.M31;
res.M12 = lhs.M10 * rhs.M02 + lhs.M11 * rhs.M12 + lhs.M12 * rhs.M22 + lhs.M13 * rhs.M32;
res.M13 = lhs.M10 * rhs.M03 + lhs.M11 * rhs.M13 + lhs.M12 * rhs.M23 + lhs.M13 * rhs.M33;
res.M20 = lhs.M20 * rhs.M00 + lhs.M21 * rhs.M10 + lhs.M22 * rhs.M20 + lhs.M23 * rhs.M30;
res.M21 = lhs.M20 * rhs.M01 + lhs.M21 * rhs.M11 + lhs.M22 * rhs.M21 + lhs.M23 * rhs.M31;
res.M22 = lhs.M20 * rhs.M02 + lhs.M21 * rhs.M12 + lhs.M22 * rhs.M22 + lhs.M23 * rhs.M32;
res.M23 = lhs.M20 * rhs.M03 + lhs.M21 * rhs.M13 + lhs.M22 * rhs.M23 + lhs.M23 * rhs.M33;
res.M30 = lhs.M30 * rhs.M00 + lhs.M31 * rhs.M10 + lhs.M32 * rhs.M20 + lhs.M33 * rhs.M30;
res.M31 = lhs.M30 * rhs.M01 + lhs.M31 * rhs.M11 + lhs.M32 * rhs.M21 + lhs.M33 * rhs.M31;
res.M32 = lhs.M30 * rhs.M02 + lhs.M31 * rhs.M12 + lhs.M32 * rhs.M22 + lhs.M33 * rhs.M32;
res.M33 = lhs.M30 * rhs.M03 + lhs.M31 * rhs.M13 + lhs.M32 * rhs.M23 + lhs.M33 * rhs.M33;
return res;
}
public static bool operator ==(Matrix4x4 lhs, Matrix4x4 rhs)
{
return lhs.GetColumn(0) == rhs.GetColumn(0)
&& lhs.GetColumn(1) == rhs.GetColumn(1)
&& lhs.GetColumn(2) == rhs.GetColumn(2)
&& lhs.GetColumn(3) == rhs.GetColumn(3);
}
public static bool operator !=(Matrix4x4 lhs, Matrix4x4 rhs)
{
return !(lhs == rhs);
}
public static Matrix4x4 Scale(Vector3 vector)
{
Matrix4x4 m;
m.M00 = vector.X; m.M01 = 0F; m.M02 = 0F; m.M03 = 0F;
m.M10 = 0F; m.M11 = vector.Y; m.M12 = 0F; m.M13 = 0F;
m.M20 = 0F; m.M21 = 0F; m.M22 = vector.Z; m.M23 = 0F;
m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
return m;
}
public static Matrix4x4 Translate(Vector3 vector)
{
Matrix4x4 m;
m.M00 = 1F; m.M01 = 0F; m.M02 = 0F; m.M03 = vector.X;
m.M10 = 0F; m.M11 = 1F; m.M12 = 0F; m.M13 = vector.Y;
m.M20 = 0F; m.M21 = 0F; m.M22 = 1F; m.M23 = vector.Z;
m.M30 = 0F; m.M31 = 0F; m.M32 = 0F; m.M33 = 1F;
return m;
}
public static Matrix4x4 Rotate(Quaternion q)
{
float x = q.X * 2.0F;
float y = q.Y * 2.0F;
float z = q.Z * 2.0F;
float xx = q.X * x;
float yy = q.Y * y;
float zz = q.Z * z;
float xy = q.X * y;
float xz = q.X * z;
float yz = q.Y * z;
float wx = q.W * x;
float wy = q.W * y;
float wz = q.W * z;
Matrix4x4 m;
m.M00 = 1.0f - (yy + zz); m.M10 = xy + wz; m.M20 = xz - wy; m.M30 = 0.0F;
m.M01 = xy - wz; m.M11 = 1.0f - (xx + zz); m.M21 = yz + wx; m.M31 = 0.0F;
m.M02 = xz + wy; m.M12 = yz - wx; m.M22 = 1.0f - (xx + yy); m.M32 = 0.0F;
m.M03 = 0.0F; m.M13 = 0.0F; m.M23 = 0.0F; m.M33 = 1.0F;
return m;
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Quaternion : IEquatable<Quaternion>
{
public float X;
public float Y;
public float Z;
public float W;
public Quaternion(float x, float y, float z, float w)
{
X = x;
Y = y;
Z = z;
W = w;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
case 3: return W;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
}
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
case 2: Z = value; break;
case 3: W = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Quaternion index!");
}
}
}
public override int GetHashCode()
{
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
}
public override bool Equals(object other)
{
if (!(other is Quaternion))
return false;
return Equals((Quaternion)other);
}
public bool Equals(Quaternion other)
{
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
}
public static float Dot(Quaternion a, Quaternion b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z + a.W * b.W;
}
private static bool IsEqualUsingDot(float dot)
{
return dot > 1.0f - kEpsilon;
}
public static bool operator ==(Quaternion lhs, Quaternion rhs)
{
return IsEqualUsingDot(Dot(lhs, rhs));
}
public static bool operator !=(Quaternion lhs, Quaternion rhs)
{
return !(lhs == rhs);
}
private const float kEpsilon = 0.000001F;
}
}

148
AssetStudio/Math/Vector2.cs Normal file
View File

@@ -0,0 +1,148 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Vector2 : IEquatable<Vector2>
{
public float X;
public float Y;
public Vector2(float x, float y)
{
X = x;
Y = y;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
}
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector2 index!");
}
}
}
public override int GetHashCode()
{
return X.GetHashCode() ^ (Y.GetHashCode() << 2);
}
public override bool Equals(object other)
{
if (!(other is Vector2))
return false;
return Equals((Vector2)other);
}
public bool Equals(Vector2 other)
{
return X.Equals(other.X) && Y.Equals(other.Y);
}
public void Normalize()
{
var length = Length();
if (length > kEpsilon)
{
var invNorm = 1.0f / length;
X *= invNorm;
Y *= invNorm;
}
else
{
X = 0;
Y = 0;
}
}
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
}
public float LengthSquared()
{
return X * X + Y * Y;
}
public static Vector2 Zero => new Vector2();
public static Vector2 operator +(Vector2 a, Vector2 b)
{
return new Vector2(a.X + b.X, a.Y + b.Y);
}
public static Vector2 operator -(Vector2 a, Vector2 b)
{
return new Vector2(a.X - b.X, a.Y - b.Y);
}
public static Vector2 operator *(Vector2 a, Vector2 b)
{
return new Vector2(a.X * b.X, a.Y * b.Y);
}
public static Vector2 operator /(Vector2 a, Vector2 b)
{
return new Vector2(a.X / b.X, a.Y / b.Y);
}
public static Vector2 operator -(Vector2 a)
{
return new Vector2(-a.X, -a.Y);
}
public static Vector2 operator *(Vector2 a, float d)
{
return new Vector2(a.X * d, a.Y * d);
}
public static Vector2 operator *(float d, Vector2 a)
{
return new Vector2(a.X * d, a.Y * d);
}
public static Vector2 operator /(Vector2 a, float d)
{
return new Vector2(a.X / d, a.Y / d);
}
public static bool operator ==(Vector2 lhs, Vector2 rhs)
{
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
}
public static bool operator !=(Vector2 lhs, Vector2 rhs)
{
return !(lhs == rhs);
}
public static implicit operator Vector3(Vector2 v)
{
return new Vector3(v.X, v.Y, 0);
}
public static implicit operator Vector4(Vector2 v)
{
return new Vector4(v.X, v.Y, 0.0F, 0.0F);
}
private const float kEpsilon = 0.00001F;
}
}

146
AssetStudio/Math/Vector3.cs Normal file
View File

@@ -0,0 +1,146 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Vector3 : IEquatable<Vector3>
{
public float X;
public float Y;
public float Z;
public Vector3(float x, float y, float z)
{
X = x;
Y = y;
Z = z;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
}
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
case 2: Z = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector3 index!");
}
}
}
public override int GetHashCode()
{
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2);
}
public override bool Equals(object other)
{
if (!(other is Vector3))
return false;
return Equals((Vector3)other);
}
public bool Equals(Vector3 other)
{
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z);
}
public void Normalize()
{
var length = Length();
if (length > kEpsilon)
{
var invNorm = 1.0f / length;
X *= invNorm;
Y *= invNorm;
Z *= invNorm;
}
else
{
X = 0;
Y = 0;
Z = 0;
}
}
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
}
public float LengthSquared()
{
return X * X + Y * Y + Z * Z;
}
public static Vector3 Zero => new Vector3();
public static Vector3 One => new Vector3(1.0f, 1.0f, 1.0f);
public static Vector3 operator +(Vector3 a, Vector3 b)
{
return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
public static Vector3 operator -(Vector3 a, Vector3 b)
{
return new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
public static Vector3 operator -(Vector3 a)
{
return new Vector3(-a.X, -a.Y, -a.Z);
}
public static Vector3 operator *(Vector3 a, float d)
{
return new Vector3(a.X * d, a.Y * d, a.Z * d);
}
public static Vector3 operator *(float d, Vector3 a)
{
return new Vector3(a.X * d, a.Y * d, a.Z * d);
}
public static Vector3 operator /(Vector3 a, float d)
{
return new Vector3(a.X / d, a.Y / d, a.Z / d);
}
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
}
public static bool operator !=(Vector3 lhs, Vector3 rhs)
{
return !(lhs == rhs);
}
public static implicit operator Vector2(Vector3 v)
{
return new Vector2(v.X, v.Y);
}
public static implicit operator Vector4(Vector3 v)
{
return new Vector4(v.X, v.Y, v.Z, 0.0F);
}
private const float kEpsilon = 0.00001F;
}
}

163
AssetStudio/Math/Vector4.cs Normal file
View File

@@ -0,0 +1,163 @@
using System;
using System.Runtime.InteropServices;
namespace AssetStudio
{
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct Vector4 : IEquatable<Vector4>
{
public float X;
public float Y;
public float Z;
public float W;
public Vector4(float x, float y, float z, float w)
{
X = x;
Y = y;
Z = z;
W = w;
}
public Vector4(Vector3 value, float w)
{
X = value.X;
Y = value.Y;
Z = value.Z;
W = w;
}
public float this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
case 3: return W;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
}
}
set
{
switch (index)
{
case 0: X = value; break;
case 1: Y = value; break;
case 2: Z = value; break;
case 3: W = value; break;
default: throw new ArgumentOutOfRangeException(nameof(index), "Invalid Vector4 index!");
}
}
}
public override int GetHashCode()
{
return X.GetHashCode() ^ (Y.GetHashCode() << 2) ^ (Z.GetHashCode() >> 2) ^ (W.GetHashCode() >> 1);
}
public override bool Equals(object other)
{
if (!(other is Vector4))
return false;
return Equals((Vector4)other);
}
public bool Equals(Vector4 other)
{
return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z) && W.Equals(other.W);
}
public void Normalize()
{
var length = Length();
if (length > kEpsilon)
{
var invNorm = 1.0f / length;
X *= invNorm;
Y *= invNorm;
Z *= invNorm;
W *= invNorm;
}
else
{
X = 0;
Y = 0;
Z = 0;
W = 0;
}
}
public float Length()
{
return (float)Math.Sqrt(LengthSquared());
}
public float LengthSquared()
{
return X * X + Y * Y + Z * Z + W * W;
}
public static Vector4 Zero => new Vector4();
public static Vector4 operator +(Vector4 a, Vector4 b)
{
return new Vector4(a.X + b.X, a.Y + b.Y, a.Z + b.Z, a.W + b.W);
}
public static Vector4 operator -(Vector4 a, Vector4 b)
{
return new Vector4(a.X - b.X, a.Y - b.Y, a.Z - b.Z, a.W - b.W);
}
public static Vector4 operator -(Vector4 a)
{
return new Vector4(-a.X, -a.Y, -a.Z, -a.W);
}
public static Vector4 operator *(Vector4 a, float d)
{
return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
}
public static Vector4 operator *(float d, Vector4 a)
{
return new Vector4(a.X * d, a.Y * d, a.Z * d, a.W * d);
}
public static Vector4 operator /(Vector4 a, float d)
{
return new Vector4(a.X / d, a.Y / d, a.Z / d, a.W / d);
}
public static bool operator ==(Vector4 lhs, Vector4 rhs)
{
return (lhs - rhs).LengthSquared() < kEpsilon * kEpsilon;
}
public static bool operator !=(Vector4 lhs, Vector4 rhs)
{
return !(lhs == rhs);
}
public static implicit operator Vector2(Vector4 v)
{
return new Vector2(v.X, v.Y);
}
public static implicit operator Vector3(Vector4 v)
{
return new Vector3(v.X, v.Y, v.Z);
}
public static implicit operator Color(Vector4 v)
{
return new Color(v.X, v.Y, v.Z, v.W);
}
private const float kEpsilon = 0.00001F;
}
}

View File

@@ -7,13 +7,13 @@ namespace AssetStudio
{
public class ObjectInfo
{
public uint byteStart;
public long byteStart;
public uint byteSize;
public int typeID;
public int classID;
public ushort isDestroyed;
public byte stripped;
//custom
public long m_PathID;
public SerializedType serializedType;
}

View File

@@ -10,12 +10,12 @@ namespace AssetStudio
{
public SerializedFile assetsFile;
public long m_PathID;
public uint byteStart;
public long byteStart;
public uint byteSize;
public ClassIDType type;
public SerializedType serializedType;
public BuildTarget platform;
private uint m_Version;
public SerializedFileFormatVersion m_Version;
public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType;
@@ -43,38 +43,5 @@ namespace AssetStudio
{
Position = byteStart;
}
public string Dump()
{
Reset();
if (serializedType?.m_Nodes != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, this);
return sb.ToString();
}
return null;
}
public bool HasStructMember(string name)
{
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
}
public PPtr ReadPPtr()
{
return new PPtr
{
m_FileID = ReadInt32(),
m_PathID = m_Version < 14 ? ReadInt32() : ReadInt64(),
assetsFile = assetsFile
};
}
public byte[] GetRawData()
{
Reset();
return ReadBytes((int)byteSize);
}
}
}

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudio")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudio")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("af56b63c-1764-41b7-9e60-8d485422ac3b")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,82 @@
using System.IO;
namespace AssetStudio
{
public class ResourceReader
{
private bool needSearch;
private string path;
private SerializedFile assetsFile;
private long offset;
private long size;
private BinaryReader reader;
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{
needSearch = true;
this.path = path;
this.assetsFile = assetsFile;
this.offset = offset;
this.size = size;
}
public ResourceReader(BinaryReader reader, long offset, long size)
{
this.reader = reader;
this.offset = offset;
this.size = size;
}
private BinaryReader GetReader()
{
if (needSearch)
{
var resourceFileName = Path.GetFileName(path);
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
{
needSearch = false;
return reader;
}
var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = Path.Combine(assetsFileDirectory, resourceFileName);
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
resourceFilePath = findFiles[0];
}
}
if (File.Exists(resourceFilePath))
{
needSearch = false;
reader = new BinaryReader(File.OpenRead(resourceFilePath));
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
return reader;
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
else
{
return reader;
}
}
public byte[] GetData()
{
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
return binaryReader.ReadBytes((int)size);
}
public void WriteData(string path)
{
var binaryReader = GetReader();
binaryReader.BaseStream.Position = offset;
using (var writer = File.OpenWrite(path))
{
binaryReader.BaseStream.CopyTo(writer, size);
}
}
}
}

View File

@@ -1,43 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudio
{
internal static class ResourcesHelper
{
public static byte[] GetData(string path, SerializedFile assetsFile, long offset, int size)
{
var resourceFileName = Path.GetFileName(path);
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
{
reader.Position = offset;
return reader.ReadBytes(size);
}
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
resourceFilePath = findFiles[0];
}
}
if (File.Exists(resourceFilePath))
{
using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath)))
{
resourceReader.BaseStream.Position = offset;
return resourceReader.ReadBytes(size);
}
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
}
}

View File

@@ -9,257 +9,304 @@ namespace AssetStudio
public class SerializedFile
{
public AssetsManager assetsManager;
public EndianBinaryReader reader;
public FileReader reader;
public string fullName;
public string originalPath;
public string fileName;
public string upperFileName;
public int[] version = { 0, 0, 0, 0 };
public BuildType buildType;
public bool valid;
public Dictionary<long, ObjectReader> ObjectReaders = new Dictionary<long, ObjectReader>();
public Dictionary<long, GameObject> GameObjects = new Dictionary<long, GameObject>();
public Dictionary<long, Transform> Transforms = new Dictionary<long, Transform>();
public List<Object> Objects;
public Dictionary<long, Object> ObjectsDic;
public SerializedFileHeader header;
private EndianType m_FileEndianess;
private byte m_FileEndianess;
public string unityVersion = "2.5.0f5";
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
private bool m_EnableTypeTree = true;
public List<SerializedType> m_Types;
private List<ObjectInfo> m_Objects;
public int bigIDEnabled = 0;
public List<ObjectInfo> m_Objects;
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
public List<FileIdentifier> m_Externals;
public List<SerializedType> m_RefTypes;
public string userInformation;
public SerializedFile(AssetsManager assetsManager, string fullName, EndianBinaryReader reader)
public SerializedFile(FileReader reader, AssetsManager assetsManager)
{
this.assetsManager = assetsManager;
this.reader = reader;
this.fullName = fullName;
fileName = Path.GetFileName(fullName);
upperFileName = fileName.ToUpper();
try
{
//ReadHeader
header = new SerializedFileHeader();
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadUInt32();
header.m_Version = reader.ReadUInt32();
header.m_DataOffset = reader.ReadUInt32();
fullName = reader.FullPath;
fileName = reader.FileName;
if (header.m_Version >= 9)
// ReadHeader
header = new SerializedFileHeader();
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadUInt32();
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
header.m_DataOffset = reader.ReadUInt32();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_9)
{
header.m_Endianess = reader.ReadByte();
header.m_Reserved = reader.ReadBytes(3);
m_FileEndianess = header.m_Endianess;
}
else
{
reader.Position = header.m_FileSize - header.m_MetadataSize;
m_FileEndianess = reader.ReadByte();
}
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
{
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadInt64();
header.m_DataOffset = reader.ReadInt64();
reader.ReadInt64(); // unknown
}
// ReadMetadata
if (m_FileEndianess == 0)
{
reader.endian = EndianType.LittleEndian;
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7)
{
unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion);
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_8)
{
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
{
header.m_Endianess = reader.ReadByte();
header.m_Reserved = reader.ReadBytes(3);
m_FileEndianess = (EndianType)header.m_Endianess;
m_TargetPlatform = BuildTarget.UnknownPlatform;
}
}
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
{
m_EnableTypeTree = reader.ReadBoolean();
}
// Read Types
int typeCount = reader.ReadInt32();
m_Types = new List<SerializedType>(typeCount);
for (int i = 0; i < typeCount; i++)
{
m_Types.Add(ReadSerializedType(false));
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7 && header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
bigIDEnabled = reader.ReadInt32();
}
// Read Objects
int objectCount = reader.ReadInt32();
m_Objects = new List<ObjectInfo>(objectCount);
Objects = new List<Object>(objectCount);
ObjectsDic = new Dictionary<long, Object>(objectCount);
for (int i = 0; i < objectCount; i++)
{
var objectInfo = new ObjectInfo();
if (bigIDEnabled != 0)
{
objectInfo.m_PathID = reader.ReadInt64();
}
else if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
objectInfo.m_PathID = reader.ReadInt32();
}
else
{
reader.Position = header.m_FileSize - header.m_MetadataSize;
m_FileEndianess = (EndianType)reader.ReadByte();
reader.AlignStream();
objectInfo.m_PathID = reader.ReadInt64();
}
//ReadMetadata
if (m_FileEndianess == EndianType.LittleEndian)
{
reader.endian = EndianType.LittleEndian;
}
if (header.m_Version >= 7)
{
unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion);
}
if (header.m_Version >= 8)
{
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
{
m_TargetPlatform = BuildTarget.UnknownPlatform;
}
}
if (header.m_Version >= 13)
{
m_EnableTypeTree = reader.ReadBoolean();
}
//ReadTypes
int typeCount = reader.ReadInt32();
m_Types = new List<SerializedType>(typeCount);
for (int i = 0; i < typeCount; i++)
{
m_Types.Add(ReadSerializedType());
}
if (header.m_Version >= 7 && header.m_Version < 14)
{
var bigIDEnabled = reader.ReadInt32();
}
//ReadObjects
int objectCount = reader.ReadInt32();
m_Objects = new List<ObjectInfo>(objectCount);
for (int i = 0; i < objectCount; i++)
{
var objectInfo = new ObjectInfo();
if (header.m_Version < 14)
{
objectInfo.m_PathID = reader.ReadInt32();
}
else
{
reader.AlignStream(4);
objectInfo.m_PathID = reader.ReadInt64();
}
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
objectInfo.byteStart = reader.ReadInt64();
else
objectInfo.byteStart = reader.ReadUInt32();
objectInfo.byteStart += header.m_DataOffset;
objectInfo.byteSize = reader.ReadUInt32();
objectInfo.typeID = reader.ReadInt32();
if (header.m_Version < 16)
objectInfo.byteStart += header.m_DataOffset;
objectInfo.byteSize = reader.ReadUInt32();
objectInfo.typeID = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kRefactoredClassId)
{
objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
}
else
{
var type = m_Types[objectInfo.typeID];
objectInfo.serializedType = type;
objectInfo.classID = type.classID;
}
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex)
{
objectInfo.isDestroyed = reader.ReadUInt16();
}
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.kRefactorTypeData)
{
var m_ScriptTypeIndex = reader.ReadInt16();
if (objectInfo.serializedType != null)
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
}
if (header.m_Version == SerializedFileFormatVersion.kSupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.kRefactoredClassId)
{
objectInfo.stripped = reader.ReadByte();
}
m_Objects.Add(objectInfo);
}
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex)
{
int scriptCount = reader.ReadInt32();
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
for (int i = 0; i < scriptCount; i++)
{
var m_ScriptType = new LocalSerializedObjectIdentifier();
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
objectInfo.isDestroyed = reader.ReadUInt16();
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
}
else
{
var type = m_Types[objectInfo.typeID];
objectInfo.serializedType = type;
objectInfo.classID = type.classID;
reader.AlignStream();
m_ScriptType.localIdentifierInFile = reader.ReadInt64();
}
if (header.m_Version == 15 || header.m_Version == 16)
{
var stripped = reader.ReadByte();
}
m_Objects.Add(objectInfo);
//Create Reader
var objectReader = new ObjectReader(reader, this, objectInfo);
ObjectReaders.Add(objectInfo.m_PathID, objectReader);
m_ScriptTypes.Add(m_ScriptType);
}
if (header.m_Version >= 11)
{
int scriptCount = reader.ReadInt32();
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
for (int i = 0; i < scriptCount; i++)
{
var m_ScriptType = new LocalSerializedObjectIdentifier();
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
if (header.m_Version < 14)
{
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
}
else
{
reader.AlignStream(4);
m_ScriptType.localIdentifierInFile = reader.ReadInt64();
}
m_ScriptTypes.Add(m_ScriptType);
}
}
int externalsCount = reader.ReadInt32();
m_Externals = new List<FileIdentifier>(externalsCount);
for (int i = 0; i < externalsCount; i++)
{
var m_External = new FileIdentifier();
if (header.m_Version >= 6)
{
var tempEmpty = reader.ReadStringToNull();
}
if (header.m_Version >= 5)
{
m_External.guid = new Guid(reader.ReadBytes(16));
m_External.type = reader.ReadInt32();
}
m_External.pathName = reader.ReadStringToNull();
m_External.fileName = Path.GetFileName(m_External.pathName);
m_Externals.Add(m_External);
}
if (header.m_Version >= 5)
{
//var userInformation = reader.ReadStringToNull();
}
valid = true;
}
catch
int externalsCount = reader.ReadInt32();
m_Externals = new List<FileIdentifier>(externalsCount);
for (int i = 0; i < externalsCount; i++)
{
// ignored
var m_External = new FileIdentifier();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_6)
{
var tempEmpty = reader.ReadStringToNull();
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
{
m_External.guid = new Guid(reader.ReadBytes(16));
m_External.type = reader.ReadInt32();
}
m_External.pathName = reader.ReadStringToNull();
m_External.fileName = Path.GetFileName(m_External.pathName);
m_Externals.Add(m_External);
}
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject)
{
int refTypesCount = reader.ReadInt32();
m_RefTypes = new List<SerializedType>(refTypesCount);
for (int i = 0; i < refTypesCount; i++)
{
m_RefTypes.Add(ReadSerializedType(true));
}
}
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
{
userInformation = reader.ReadStringToNull();
}
//reader.AlignStream(16);
}
public void SetVersion(string stringVersion)
{
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
buildType = new BuildType(buildSplit[0]);
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = versionSplit.Select(int.Parse).ToArray();
if (stringVersion != strippedVersion)
{
unityVersion = stringVersion;
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
buildType = new BuildType(buildSplit[0]);
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = versionSplit.Select(int.Parse).ToArray();
}
}
private SerializedType ReadSerializedType()
private SerializedType ReadSerializedType(bool isRefType)
{
var type = new SerializedType();
type.classID = reader.ReadInt32();
if (header.m_Version >= 16)
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId)
{
type.m_IsStrippedType = reader.ReadBoolean();
}
if (header.m_Version >= 17)
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData)
{
type.m_ScriptTypeIndex = reader.ReadInt16();
}
if (header.m_Version >= 13)
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
{
if ((header.m_Version < 16 && type.classID < 0) || (header.m_Version >= 16 && type.classID == 114))
if (isRefType && type.m_ScriptTypeIndex >= 0)
{
type.m_ScriptID = reader.ReadBytes(16); //Hash128
type.m_ScriptID = reader.ReadBytes(16);
}
type.m_OldTypeHash = reader.ReadBytes(16); //Hash128
else if ((header.m_Version < SerializedFileFormatVersion.kRefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId && type.classID == 114))
{
type.m_ScriptID = reader.ReadBytes(16);
}
type.m_OldTypeHash = reader.ReadBytes(16);
}
if (m_EnableTypeTree)
{
var typeTree = new List<TypeTreeNode>();
if (header.m_Version >= 12 || header.m_Version == 10)
type.m_Type = new TypeTree();
type.m_Type.m_Nodes = new List<TypeTreeNode>();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_12 || header.m_Version == SerializedFileFormatVersion.kUnknown_10)
{
ReadTypeTree5(typeTree);
TypeTreeBlobRead(type.m_Type);
}
else
{
ReadTypeTree(typeTree);
ReadTypeTree(type.m_Type);
}
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies)
{
if (isRefType)
{
type.m_KlassName = reader.ReadStringToNull();
type.m_NameSpace = reader.ReadStringToNull();
type.m_AsmName = reader.ReadStringToNull();
}
else
{
type.m_TypeDependencies = reader.ReadInt32Array();
}
}
type.m_Nodes = typeTree;
}
return type;
}
private void ReadTypeTree(List<TypeTreeNode> typeTree, int depth = 0)
private void ReadTypeTree(TypeTree m_Type, int level = 0)
{
var typeTreeNode = new TypeTreeNode();
typeTree.Add(typeTreeNode);
typeTreeNode.m_Level = depth;
m_Type.m_Nodes.Add(typeTreeNode);
typeTreeNode.m_Level = level;
typeTreeNode.m_Type = reader.ReadStringToNull();
typeTreeNode.m_Name = reader.ReadStringToNull();
typeTreeNode.m_ByteSize = reader.ReadInt32();
if (header.m_Version == 2)
if (header.m_Version == SerializedFileFormatVersion.kUnknown_2)
{
var variableCount = reader.ReadInt32();
}
if (header.m_Version != 3)
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
{
typeTreeNode.m_Index = reader.ReadInt32();
}
typeTreeNode.m_IsArray = reader.ReadInt32();
typeTreeNode.m_TypeFlags = reader.ReadInt32();
typeTreeNode.m_Version = reader.ReadInt32();
if (header.m_Version != 3)
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
{
typeTreeNode.m_MetaFlag = reader.ReadInt32();
}
@@ -267,57 +314,68 @@ namespace AssetStudio
int childrenCount = reader.ReadInt32();
for (int i = 0; i < childrenCount; i++)
{
ReadTypeTree(typeTree, depth + 1);
ReadTypeTree(m_Type, level + 1);
}
}
private void ReadTypeTree5(List<TypeTreeNode> typeTree)
private void TypeTreeBlobRead(TypeTree m_Type)
{
int numberOfNodes = reader.ReadInt32();
int stringBufferSize = reader.ReadInt32();
reader.Position += numberOfNodes * 24;
using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize))))
for (int i = 0; i < numberOfNodes; i++)
{
var typeTreeNode = new TypeTreeNode();
m_Type.m_Nodes.Add(typeTreeNode);
typeTreeNode.m_Version = reader.ReadUInt16();
typeTreeNode.m_Level = reader.ReadByte();
typeTreeNode.m_TypeFlags = reader.ReadByte();
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags)
{
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
}
}
m_Type.m_StringBuffer = reader.ReadBytes(stringBufferSize);
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_Type.m_StringBuffer)))
{
reader.Position -= numberOfNodes * 24 + stringBufferSize;
for (int i = 0; i < numberOfNodes; i++)
{
var typeTreeNode = new TypeTreeNode();
typeTree.Add(typeTreeNode);
typeTreeNode.m_Version = reader.ReadUInt16();
typeTreeNode.m_Level = reader.ReadByte();
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
var m_TypeStrOffset = reader.ReadUInt16();
var temp = reader.ReadUInt16();
if (temp == 0)
{
stringBufferReader.BaseStream.Position = m_TypeStrOffset;
typeTreeNode.m_Type = stringBufferReader.ReadStringToNull();
}
else
{
typeTreeNode.m_Type = CommonString.StringBuffer.ContainsKey(m_TypeStrOffset) ? CommonString.StringBuffer[m_TypeStrOffset] : m_TypeStrOffset.ToString();
}
var m_NameStrOffset = reader.ReadUInt16();
temp = reader.ReadUInt16();
if (temp == 0)
{
stringBufferReader.BaseStream.Position = m_NameStrOffset;
typeTreeNode.m_Name = stringBufferReader.ReadStringToNull();
}
else
{
typeTreeNode.m_Name = CommonString.StringBuffer.ContainsKey(m_NameStrOffset) ? CommonString.StringBuffer[m_NameStrOffset] : m_NameStrOffset.ToString();
}
typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32();
var m_Node = m_Type.m_Nodes[i];
m_Node.m_Type = ReadString(stringBufferReader, m_Node.m_TypeStrOffset);
m_Node.m_Name = ReadString(stringBufferReader, m_Node.m_NameStrOffset);
}
reader.Position += stringBufferSize;
}
string ReadString(BinaryReader stringBufferReader, uint value)
{
var isOffset = (value & 0x80000000) == 0;
if (isOffset)
{
stringBufferReader.BaseStream.Position = value;
return stringBufferReader.ReadStringToNull();
}
var offset = value & 0x7FFFFFFF;
if (CommonString.StringBuffer.TryGetValue(offset, out var str))
{
return str;
}
return offset.ToString();
}
}
public void AddObject(Object obj)
{
Objects.Add(obj);
ObjectsDic.Add(obj.m_PathID, obj);
}
public bool IsVersionStripped => unityVersion == strippedVersion;
private const string strippedVersion = "0.0.0";
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum SerializedFileFormatVersion
{
kUnsupported = 1,
kUnknown_2 = 2,
kUnknown_3 = 3,
/// <summary>
/// 1.2.0 to 2.0.0
/// </summary>
kUnknown_5 = 5,
/// <summary>
/// 2.1.0 to 2.6.1
/// </summary>
kUnknown_6 = 6,
/// <summary>
/// 3.0.0b
/// </summary>
kUnknown_7 = 7,
/// <summary>
/// 3.0.0 to 3.4.2
/// </summary>
kUnknown_8 = 8,
/// <summary>
/// 3.5.0 to 4.7.2
/// </summary>
kUnknown_9 = 9,
/// <summary>
/// 5.0.0aunk1
/// </summary>
kUnknown_10 = 10,
/// <summary>
/// 5.0.0aunk2
/// </summary>
kHasScriptTypeIndex = 11,
/// <summary>
/// 5.0.0aunk3
/// </summary>
kUnknown_12 = 12,
/// <summary>
/// 5.0.0aunk4
/// </summary>
kHasTypeTreeHashes = 13,
/// <summary>
/// 5.0.0unk
/// </summary>
kUnknown_14 = 14,
/// <summary>
/// 5.0.1 to 5.4.0
/// </summary>
kSupportsStrippedObject = 15,
/// <summary>
/// 5.5.0a
/// </summary>
kRefactoredClassId = 16,
/// <summary>
/// 5.5.0unk to 2018.4
/// </summary>
kRefactorTypeData = 17,
/// <summary>
/// 2019.1a
/// </summary>
kRefactorShareableTypeTreeData = 18,
/// <summary>
/// 2019.1unk
/// </summary>
kTypeTreeNodeWithTypeFlags = 19,
/// <summary>
/// 2019.2
/// </summary>
kSupportsRefObject = 20,
/// <summary>
/// 2019.3 to 2019.4
/// </summary>
kStoresTypeDependencies = 21,
/// <summary>
/// 2020.1 to x
/// </summary>
kLargeFilesSupport = 22
}
}

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