Compare commits
274 Commits
v0.12.0
...
Perfare_ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d158e864b5 | ||
|
|
b70b5196e3 | ||
|
|
4f88841026 | ||
|
|
dc9429feac | ||
|
|
a3c16ed3d6 | ||
|
|
5b83eebdda | ||
|
|
1fcf7a4364 | ||
|
|
973d50ce8b | ||
|
|
50485a9bd3 | ||
|
|
dbb3d3fef7 | ||
|
|
e1cfff63c3 | ||
|
|
44514a4e10 | ||
|
|
b1205808e2 | ||
|
|
7d3a4a10fc | ||
|
|
b909857820 | ||
|
|
b674e66407 | ||
|
|
d7dcd3f405 | ||
|
|
44145e0b9c | ||
|
|
d4e21f824c | ||
|
|
e7a4604a65 | ||
|
|
8d193a63cd | ||
|
|
e61a317185 | ||
|
|
0e1a886e0b | ||
|
|
97b5f51f3a | ||
|
|
7295feda72 | ||
|
|
fe95c91759 | ||
|
|
d220315d9b | ||
|
|
a94caa5e34 | ||
|
|
3660b4ed67 | ||
|
|
3370f93037 | ||
|
|
80653711cd | ||
|
|
88c5804586 | ||
|
|
e501940f03 | ||
|
|
d4060cde6d | ||
|
|
582a779441 | ||
|
|
5fa4934787 | ||
|
|
18277fbea8 | ||
|
|
2ce9cae957 | ||
|
|
af5e50cfa9 | ||
|
|
ce1172ca9a | ||
|
|
a7e6d91f5b | ||
|
|
34a0af683a | ||
|
|
91410a33b1 | ||
|
|
d08b78c2cf | ||
|
|
2ef52afe1e | ||
|
|
05a41d2f1e | ||
|
|
34c38e1415 | ||
|
|
c85873b729 | ||
|
|
b146d251a7 | ||
|
|
3129d67fc1 | ||
|
|
850ba63a10 | ||
|
|
17b91984d6 | ||
|
|
7ab2cda120 | ||
|
|
4345885cc9 | ||
|
|
53720e37ab | ||
|
|
7c3cb36630 | ||
|
|
c1cddce031 | ||
|
|
973a1076e4 | ||
|
|
089e164756 | ||
|
|
c2b6691fd9 | ||
|
|
8dec094304 | ||
|
|
bedee240be | ||
|
|
d963d71b12 | ||
|
|
77a0c9c40a | ||
|
|
f3e406983b | ||
|
|
08b7bfcf9a | ||
|
|
57e4f7cefd | ||
|
|
c9cf2d188e | ||
|
|
ab98585b6a | ||
|
|
075d53a455 | ||
|
|
432116d834 | ||
|
|
caa45216ef | ||
|
|
c9394cd957 | ||
|
|
46c0e8ffe1 | ||
|
|
d14c232015 | ||
|
|
4002bdecb8 | ||
|
|
17259e00c7 | ||
|
|
44b02b92d8 | ||
|
|
251854cc41 | ||
|
|
6f7b77245d | ||
|
|
6d99f5ebf6 | ||
|
|
f1f2430f97 | ||
|
|
b52696c965 | ||
|
|
5fba52dc83 | ||
|
|
dfb74baf79 | ||
|
|
978e90a403 | ||
|
|
c17d7d6331 | ||
|
|
9fef18d6ea | ||
|
|
ee0cd4ab52 | ||
|
|
f904bc138b | ||
|
|
7ed5345b1b | ||
|
|
d7f652d572 | ||
|
|
32ce032655 | ||
|
|
e1cf36aa3c | ||
|
|
f644396a15 | ||
|
|
3e77c34bd5 | ||
|
|
052c60f629 | ||
|
|
a1f2e3e7fe | ||
|
|
32ee8b326f | ||
|
|
06ce479eb6 | ||
|
|
03f74bac64 | ||
|
|
344b675745 | ||
|
|
86590d95a5 | ||
|
|
bbea1341b2 | ||
|
|
ca60dd9834 | ||
|
|
7aa35b5b8c | ||
|
|
bd2decdb8f | ||
|
|
9b2c85bcae | ||
|
|
efbab7c43a | ||
|
|
729a8a8263 | ||
|
|
0ec29f62ca | ||
|
|
796317f9d9 | ||
|
|
7596dcc7cd | ||
|
|
422851cdab | ||
|
|
ec0a2a47f1 | ||
|
|
8ce5b947f6 | ||
|
|
419ca63f9d | ||
|
|
6fdb0c7b0e | ||
|
|
4e97b4b898 | ||
|
|
1766dcbdeb | ||
|
|
ef38471ff1 | ||
|
|
217a7993e9 | ||
|
|
0a41615763 | ||
|
|
9d34f668d5 | ||
|
|
9269a36725 | ||
|
|
813e8b10a6 | ||
|
|
84c75fadf5 | ||
|
|
c76e41b1ab | ||
|
|
fefeea5f35 | ||
|
|
4a81c461e8 | ||
|
|
b10d03d50d | ||
|
|
da98a0c5b8 | ||
|
|
76d17bacf5 | ||
|
|
6678ce082b | ||
|
|
07074b3deb | ||
|
|
df5d9f90d4 | ||
|
|
4f2d30552a | ||
|
|
d259c7a5cd | ||
|
|
c71ceb7ea6 | ||
|
|
85cf134a49 | ||
|
|
687b1d3a0d | ||
|
|
a30a0d0bc5 | ||
|
|
e1dc54d6d7 | ||
|
|
c4270e186d | ||
|
|
182a42ace2 | ||
|
|
06fbe69a97 | ||
|
|
a0bf4f9acd | ||
|
|
12568ba044 | ||
|
|
de95b02285 | ||
|
|
286edfe72c | ||
|
|
d717b223b7 | ||
|
|
9e195832ef | ||
|
|
c8d08b2793 | ||
|
|
2bcd9662be | ||
|
|
ea461ee3d2 | ||
|
|
fda821b441 | ||
|
|
5c193c761a | ||
|
|
14f47c6d30 | ||
|
|
e53eacef78 | ||
|
|
ada26db659 | ||
|
|
48ca96807f | ||
|
|
2018028853 | ||
|
|
6f138dcc05 | ||
|
|
69bcd2be67 | ||
|
|
45ad53b19a | ||
|
|
6230240ee3 | ||
|
|
73ec9f4bee | ||
|
|
f3a0bf505e | ||
|
|
290708876d | ||
|
|
5b96a29cca | ||
|
|
948e2c4d92 | ||
|
|
76da1c33ae | ||
|
|
72b84ee24d | ||
|
|
7b33d41172 | ||
|
|
c7043c1a83 | ||
|
|
d0baf26c61 | ||
|
|
60ac10b043 | ||
|
|
80dc24b487 | ||
|
|
9d32a9dd6a | ||
|
|
d96cc3c762 | ||
|
|
509df42730 | ||
|
|
4efa5b0507 | ||
|
|
cffe96b409 | ||
|
|
16dddc01e3 | ||
|
|
b5d2c2cadb | ||
|
|
1d2c0ab6cb | ||
|
|
c6b7e04c47 | ||
|
|
5704813b28 | ||
|
|
465c989e75 | ||
|
|
d335aaef9e | ||
|
|
495b48c783 | ||
|
|
05b55722fb | ||
|
|
de54257eef | ||
|
|
e62b6c3d77 | ||
|
|
dc05e5b5eb | ||
|
|
f377381e26 | ||
|
|
20f9fe493f | ||
|
|
0b462754a5 | ||
|
|
b1ea8dd346 | ||
|
|
4a46f897bd | ||
|
|
6a5ec80de7 | ||
|
|
4f2046d412 | ||
|
|
1cf59e8d67 | ||
|
|
e9e8390bbc | ||
|
|
738b084440 | ||
|
|
32cce894ac | ||
|
|
a6264b39d1 | ||
|
|
eb4981808b | ||
|
|
50c17c2ec4 | ||
|
|
e001dff3de | ||
|
|
3a0100ed37 | ||
|
|
58ab3116db | ||
|
|
6b93df41f2 | ||
|
|
b9cf7d5874 | ||
|
|
da4eb15d6b | ||
|
|
378840bc1b | ||
|
|
3441135b2f | ||
|
|
afcbba8182 | ||
|
|
cefdf08873 | ||
|
|
59be547a82 | ||
|
|
a2be5ebdac | ||
|
|
f76d3d8fcd | ||
|
|
edb6256fc9 | ||
|
|
8946a4fba5 | ||
|
|
87e1739208 | ||
|
|
10f4aaa39f | ||
|
|
957073b041 | ||
|
|
e1bb9a6cf0 | ||
|
|
558adb0b66 | ||
|
|
6a4979f999 | ||
|
|
9e76d94eea | ||
|
|
fa91820016 | ||
|
|
be091ecebb | ||
|
|
903be743ac | ||
|
|
c3c4697562 | ||
|
|
e6ed312de2 | ||
|
|
33461e068f | ||
|
|
7f13c90189 | ||
|
|
54ed3971a2 | ||
|
|
e602a5cf3b | ||
|
|
dec0a22ffe | ||
|
|
911272167a | ||
|
|
54d78d55a0 | ||
|
|
ff550b457f | ||
|
|
f449d7a8ab | ||
|
|
761579ab1a | ||
|
|
5cd4cf67cf | ||
|
|
fabfc77a52 | ||
|
|
f8ffaa0400 | ||
|
|
d156b5d947 | ||
|
|
d7551bdeb2 | ||
|
|
7d5e06bce4 | ||
|
|
0bc17f0ff5 | ||
|
|
9edc268cd4 | ||
|
|
356d5fa8a4 | ||
|
|
eb170d4f34 | ||
|
|
324c5ec7a2 | ||
|
|
ae155ca603 | ||
|
|
eb13585174 | ||
|
|
98c9eea58a | ||
|
|
067517740f | ||
|
|
3addb0e894 | ||
|
|
7452d4275e | ||
|
|
96ea522e83 | ||
|
|
ab24f049cf | ||
|
|
ec9184ba93 | ||
|
|
0a5b866a03 | ||
|
|
58d5a3fc37 | ||
|
|
19534ebb4d | ||
|
|
0a764c74d6 | ||
|
|
ab5f5fbd9d | ||
|
|
7dbc2ff95d | ||
|
|
bfaa207853 | ||
|
|
8c749e21e1 |
57
.github/workflows/build.yml
vendored
Normal file
57
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: AssetStudioBuild
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/setup-msbuild@v1.1
|
||||
|
||||
- name: Download FBX SDK
|
||||
run: |
|
||||
md fbx
|
||||
cd fbx
|
||||
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_win.exe" -OutFile "fbxsdk.exe"
|
||||
Start-Process -FilePath "fbxsdk.exe" /S -Wait
|
||||
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_pdbs.exe" -OutFile "fbxpdb.exe"
|
||||
Start-Process -FilePath "fbxpdb.exe" /S -Wait
|
||||
cd ..
|
||||
|
||||
- name: Nuget Restore
|
||||
run: nuget restore
|
||||
|
||||
- name: Build .Net472
|
||||
run: msbuild /p:Configuration=Release /p:TargetFramework=net472 /verbosity:minimal
|
||||
|
||||
- name: Build .Net5
|
||||
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net5.0-windows /p:SelfContained=false /verbosity:minimal
|
||||
|
||||
- name: Build .Net6
|
||||
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net6.0-windows /p:SelfContained=false /verbosity:minimal
|
||||
|
||||
- name: Upload .Net472 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net472
|
||||
path: AssetStudioGUI/bin/Release/net472
|
||||
|
||||
- name: Upload .Net5 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net5
|
||||
path: AssetStudioGUI/bin/Release/net5.0-windows/publish
|
||||
|
||||
- name: Upload .Net6 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net6
|
||||
path: AssetStudioGUI/bin/Release/net6.0-windows/publish
|
||||
172
.gitignore
vendored
172
.gitignore
vendored
@@ -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
|
||||
13
AssetStudio.PInvoke/AssetStudio.PInvoke.csproj
Normal file
13
AssetStudio.PInvoke/AssetStudio.PInvoke.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>0.16.0.0</Version>
|
||||
<AssemblyVersion>0.16.0.0</AssemblyVersion>
|
||||
<FileVersion>0.16.0.0</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
124
AssetStudio.PInvoke/DllLoader.cs
Normal file
124
AssetStudio.PInvoke/DllLoader.cs
Normal 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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
100
AssetStudio.PInvoke/Utf8StringHandle.cs
Normal file
100
AssetStudio.PInvoke/Utf8StringHandle.cs
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
158
AssetStudio.sln
158
AssetStudio.sln
@@ -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
|
||||
|
||||
@@ -1,148 +1,22 @@
|
||||
<?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;net5.0;net6.0</TargetFrameworks>
|
||||
<Version>0.16.0.0</Version>
|
||||
<AssemblyVersion>0.16.0.0</AssemblyVersion>
|
||||
<FileVersion>0.16.0.0</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</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>
|
||||
<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 Condition=" '$(TargetFramework)' != 'net472' ">
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
|
||||
</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 Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
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> noexistFiles = 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]);
|
||||
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
|
||||
MergeSplitAssets(path);
|
||||
var toReadFile = ProcessingSplitFiles(files.ToList());
|
||||
Load(toReadFile);
|
||||
@@ -36,8 +42,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,148 +52,515 @@ namespace AssetStudio
|
||||
LoadFile(importFiles[i]);
|
||||
Progress.Report(i + 1, importFiles.Count);
|
||||
}
|
||||
|
||||
importFiles.Clear();
|
||||
importFilesHash.Clear();
|
||||
assetsfileListHash.Clear();
|
||||
noexistFiles.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;
|
||||
case FileType.ZipFile:
|
||||
LoadZipFile(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.FullPath}");
|
||||
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))
|
||||
{
|
||||
if (!File.Exists(sharedFilePath))
|
||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
|
||||
if (!noexistFiles.Contains(sharedFilePath))
|
||||
{
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
if (!File.Exists(sharedFilePath))
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
}
|
||||
}
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
noexistFiles.Add(sharedFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName.ToUpper());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading assets file {reader.FullPath}", e);
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"Skipping {reader.FullPath}");
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
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.Unknown_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.FullPath} from {Path.GetFileName(originalPath)}", e);
|
||||
resourceFileReaders.Add(reader.FileName, reader);
|
||||
}
|
||||
}
|
||||
else
|
||||
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
||||
}
|
||||
|
||||
private void LoadBundleFile(FileReader reader, string originalPath = null)
|
||||
{
|
||||
Logger.Info("Loading " + reader.FullPath);
|
||||
try
|
||||
{
|
||||
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
|
||||
{
|
||||
resourceFileReaders[file.fileName] = subReader; //TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var str = $"Error while reading bundle file {reader.FullPath}";
|
||||
if (originalPath != null)
|
||||
{
|
||||
str += $" from {Path.GetFileName(originalPath)}";
|
||||
}
|
||||
Logger.Error(str, e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
|
||||
private void LoadWebFile(FileReader reader)
|
||||
{
|
||||
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.FullPath);
|
||||
try
|
||||
{
|
||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
||||
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
|
||||
var webFile = new WebFile(reader);
|
||||
foreach (var file in webFile.fileList)
|
||||
{
|
||||
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.FullPath}", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadWebFile(string fullName, EndianBinaryReader reader)
|
||||
private void LoadZipFile(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))
|
||||
using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read))
|
||||
{
|
||||
case FileType.AssetsFile:
|
||||
LoadAssetsFromMemory(dummyPath, reader, fullName);
|
||||
break;
|
||||
case FileType.BundleFile:
|
||||
LoadBundleFile(dummyPath, reader, fullName);
|
||||
break;
|
||||
case FileType.WebFile:
|
||||
LoadWebFile(dummyPath, reader);
|
||||
break;
|
||||
List<string> splitFiles = new List<string>();
|
||||
// register all files before parsing the assets so that the external references can be found
|
||||
// and find split files
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
if (entry.Name.Contains(".split"))
|
||||
{
|
||||
string baseName = Path.GetFileNameWithoutExtension(entry.Name);
|
||||
string basePath = Path.Combine(Path.GetDirectoryName(entry.FullName), baseName);
|
||||
if (!splitFiles.Contains(basePath))
|
||||
{
|
||||
splitFiles.Add(basePath);
|
||||
importFilesHash.Add(baseName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
importFilesHash.Add(entry.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// merge split files and load the result
|
||||
foreach (string basePath in splitFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream splitStream = new MemoryStream();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
string path = $"{basePath}.split{i++}";
|
||||
ZipArchiveEntry entry = archive.GetEntry(path);
|
||||
if (entry == null)
|
||||
break;
|
||||
using (Stream entryStream = entry.Open())
|
||||
{
|
||||
entryStream.CopyTo(splitStream);
|
||||
}
|
||||
}
|
||||
splitStream.Seek(0, SeekOrigin.Begin);
|
||||
FileReader entryReader = new FileReader(basePath, splitStream);
|
||||
LoadFile(entryReader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading zip split file {basePath}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// load all entries
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName);
|
||||
// create a new stream
|
||||
// - to store the deflated stream in
|
||||
// - to keep the data for later extraction
|
||||
Stream streamReader = new MemoryStream();
|
||||
using (Stream entryStream = entry.Open())
|
||||
{
|
||||
entryStream.CopyTo(streamReader);
|
||||
}
|
||||
streamReader.Position = 0;
|
||||
|
||||
FileReader entryReader = new FileReader(dummyPath, streamReader);
|
||||
LoadFile(entryReader);
|
||||
if (entryReader.FileType == FileType.ResourceFile)
|
||||
{
|
||||
entryReader.Position = 0;
|
||||
if (!resourceFileReaders.ContainsKey(entry.Name))
|
||||
{
|
||||
resourceFileReaders.Add(entry.Name, entryReader);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading zip entry {entry.FullName}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading zip 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($"Path {assetsFile.originalPath}")
|
||||
.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);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
|
||||
if (m_SpriteAtlaOld.m_IsVariant)
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
AssetStudio/BigArrayPool.cs
Normal file
10
AssetStudio/BigArrayPool.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Buffers;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class BigArrayPool<T>
|
||||
{
|
||||
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
|
||||
public static ArrayPool<T> Shared => s_shared;
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,9 @@ namespace AssetStudio
|
||||
{
|
||||
public enum BuildTarget
|
||||
{
|
||||
UnknownPlatform = 3716,
|
||||
DashboardWidget = 1,
|
||||
NoTarget = -2,
|
||||
AnyPlayer = -1,
|
||||
ValidPlayer = 1,
|
||||
StandaloneOSX = 2,
|
||||
StandaloneOSXPPC = 3,
|
||||
StandaloneOSXIntel = 4,
|
||||
@@ -19,8 +20,10 @@ namespace AssetStudio
|
||||
iOS = 9,
|
||||
PS3,
|
||||
XBOX360,
|
||||
Broadcom = 12,
|
||||
Android = 13,
|
||||
StandaloneGLESEmu = 14,
|
||||
StandaloneGLES20Emu = 15,
|
||||
NaCl = 16,
|
||||
StandaloneLinux = 17,
|
||||
FlashPlayer = 18,
|
||||
@@ -42,6 +45,14 @@ namespace AssetStudio
|
||||
WiiU,
|
||||
tvOS,
|
||||
Switch,
|
||||
NoTarget = -2
|
||||
Lumin,
|
||||
Stadia,
|
||||
CloudRendering,
|
||||
GameCoreXboxSeries,
|
||||
GameCoreXboxOne,
|
||||
PS5,
|
||||
EmbeddedLinux,
|
||||
QNX,
|
||||
UnknownPlatform = 9999
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,246 +1,359 @@
|
||||
using System.Collections.Generic;
|
||||
using K4os.Compression.LZ4;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Lz4;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class StreamFile
|
||||
[Flags]
|
||||
public enum ArchiveFlags
|
||||
{
|
||||
public string fileName;
|
||||
public Stream stream;
|
||||
CompressionTypeMask = 0x3f,
|
||||
BlocksAndDirectoryInfoCombined = 0x40,
|
||||
BlocksInfoAtTheEnd = 0x80,
|
||||
OldWebPluginCompatibility = 0x100,
|
||||
BlockInfoNeedPaddingAtStart = 0x200
|
||||
}
|
||||
|
||||
public class BlockInfo
|
||||
[Flags]
|
||||
public enum StorageBlockFlags
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public short flag;
|
||||
CompressionTypeMask = 0x3f,
|
||||
Streamed = 0x40
|
||||
}
|
||||
|
||||
public enum CompressionType
|
||||
{
|
||||
None,
|
||||
Lzma,
|
||||
Lz4,
|
||||
Lz4HC,
|
||||
Lzham
|
||||
}
|
||||
|
||||
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 ArchiveFlags flags;
|
||||
}
|
||||
|
||||
public class StorageBlock
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public StorageBlockFlags 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++)
|
||||
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(),
|
||||
};
|
||||
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)
|
||||
{
|
||||
var isCompressed = m_Header.signature == "UnityWeb";
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
default://None
|
||||
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
|
||||
if (isCompressed)
|
||||
{
|
||||
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 = (ArchiveFlags)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 & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
|
||||
{
|
||||
var position = reader.Position;
|
||||
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
reader.Position = position;
|
||||
}
|
||||
else //0x40 BlocksAndDirectoryInfoCombined
|
||||
{
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
}
|
||||
MemoryStream blocksInfoUncompresseddStream;
|
||||
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
|
||||
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
case CompressionType.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 = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
|
||||
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
|
||||
}
|
||||
blocksInfoUncompresseddStream.Position = 0;
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
{
|
||||
var uncompressedBytes = new byte[uncompressedSize];
|
||||
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
}
|
||||
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 = (StorageBlockFlags)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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
|
||||
{
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
case CompressionType.None:
|
||||
{
|
||||
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
{
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
}
|
||||
}
|
||||
blocksStream.Position = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,20 @@ 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 byte isIntCurve;
|
||||
|
||||
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 +817,35 @@ namespace AssetStudio
|
||||
}
|
||||
customType = reader.ReadByte();
|
||||
isPPtrCurve = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
{
|
||||
isIntCurve = reader.ReadByte();
|
||||
}
|
||||
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,11 +885,38 @@ 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,
|
||||
kGeneric = 2,
|
||||
kHumanoid = 3
|
||||
Legacy = 1,
|
||||
Generic = 2,
|
||||
Humanoid = 3
|
||||
};
|
||||
|
||||
public sealed class AnimationClip : NamedObject
|
||||
@@ -854,20 +925,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)
|
||||
@@ -879,7 +950,7 @@ namespace AssetStudio
|
||||
else if (version[0] >= 4)//4.0 and up
|
||||
{
|
||||
m_AnimationType = (AnimationType)reader.ReadInt32();
|
||||
if (m_AnimationType == AnimationType.kLegacy)
|
||||
if (m_AnimationType == AnimationType.Legacy)
|
||||
m_Legacy = true;
|
||||
}
|
||||
else
|
||||
@@ -891,59 +962,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 +1033,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace AssetStudio
|
||||
public sealed class AudioClip : NamedObject
|
||||
{
|
||||
public int m_Format;
|
||||
public AudioType m_Type;
|
||||
public FMODSoundType m_Type;
|
||||
public bool m_3D;
|
||||
public bool m_UseHardware;
|
||||
|
||||
@@ -27,19 +27,19 @@ 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)
|
||||
{
|
||||
m_Format = reader.ReadInt32();
|
||||
m_Type = (AudioType)reader.ReadInt32();
|
||||
m_Type = (FMODSoundType)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,63 +65,78 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
public enum AudioType
|
||||
public enum FMODSoundType
|
||||
{
|
||||
UNKNOWN,
|
||||
ACC,
|
||||
AIFF,
|
||||
UNKNOWN = 0,
|
||||
ACC = 1,
|
||||
AIFF = 2,
|
||||
ASF = 3,
|
||||
AT3 = 4,
|
||||
CDDA = 5,
|
||||
DLS = 6,
|
||||
FLAC = 7,
|
||||
FSB = 8,
|
||||
GCADPCM = 9,
|
||||
IT = 10,
|
||||
MIDI = 11,
|
||||
MOD = 12,
|
||||
MPEG,
|
||||
OGGVORBIS,
|
||||
MPEG = 13,
|
||||
OGGVORBIS = 14,
|
||||
PLAYLIST = 15,
|
||||
RAW = 16,
|
||||
S3M = 17,
|
||||
SF2 = 18,
|
||||
USER = 19,
|
||||
WAV = 20,
|
||||
XM,
|
||||
XMA,
|
||||
VAG,
|
||||
AUDIOQUEUE
|
||||
XM = 21,
|
||||
XMA = 22,
|
||||
VAG = 23,
|
||||
AUDIOQUEUE = 24,
|
||||
XWMA = 25,
|
||||
BCWAV = 26,
|
||||
AT9 = 27,
|
||||
VORBIS = 28,
|
||||
MEDIA_FOUNDATION = 29
|
||||
}
|
||||
|
||||
public enum AudioCompressionFormat
|
||||
{
|
||||
PCM,
|
||||
Vorbis,
|
||||
ADPCM,
|
||||
MP3,
|
||||
VAG,
|
||||
HEVAG,
|
||||
XMA,
|
||||
AAC,
|
||||
GCADPCM,
|
||||
ATRAC9
|
||||
PCM = 0,
|
||||
Vorbis = 1,
|
||||
ADPCM = 2,
|
||||
MP3 = 3,
|
||||
PSMVAG = 4,
|
||||
HEVAG = 5,
|
||||
XMA = 6,
|
||||
AAC = 7,
|
||||
GCADPCM = 8,
|
||||
ATRAC9 = 9
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
protected Behaviour(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Enabled = reader.ReadByte();
|
||||
reader.AlignStream(4);
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,117 +1,124 @@
|
||||
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] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 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_ValidKeywords = reader.ReadStringArray();
|
||||
var m_InvalidKeywords = reader.ReadStringArray();
|
||||
}
|
||||
else if (version[0] >= 5) //5.0 ~ 2021.2
|
||||
{
|
||||
var m_ShaderKeywords = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Unknown_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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
AssetStudio/Classes/ResourceManager.cs
Normal file
19
AssetStudio/Classes/ResourceManager.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
AssetStudio/Classes/RuntimeAnimatorController.cs
Normal file
15
AssetStudio/Classes/RuntimeAnimatorController.cs
Normal 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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,40 @@
|
||||
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,
|
||||
kSPRFlipHorizontal = 1,
|
||||
kSPRFlipVertical = 2,
|
||||
kSPRRotate180 = 3,
|
||||
kSPRRotate90 = 4
|
||||
None = 0,
|
||||
FlipHorizontal = 1,
|
||||
FlipVertical = 2,
|
||||
Rotate180 = 3,
|
||||
Rotate90 = 4
|
||||
};
|
||||
|
||||
public enum SpritePackingMode
|
||||
{
|
||||
kSPMTight = 0,
|
||||
kSPMRectangle
|
||||
Tight = 0,
|
||||
Rectangle
|
||||
};
|
||||
|
||||
public enum SpriteMeshType
|
||||
{
|
||||
FullRect,
|
||||
Tight
|
||||
};
|
||||
|
||||
public class SpriteSettings
|
||||
@@ -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 Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,38 +29,48 @@ 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 bool m_IsVariant;
|
||||
|
||||
public SpriteAtlas(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_PackedSpritesSize = reader.ReadInt32();
|
||||
m_PackedSprites = new PPtr<Sprite>[m_PackedSpritesSize];
|
||||
for (int i = 0; i < m_PackedSpritesSize; i++)
|
||||
{
|
||||
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
|
||||
var m_Tag = reader.ReadAlignedString();
|
||||
m_IsVariant = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
|
||||
public TextAsset(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
||||
m_Script = reader.ReadUInt8Array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,10 +151,13 @@ namespace AssetStudio
|
||||
RGB24,
|
||||
RGBA32,
|
||||
ARGB32,
|
||||
RGB565 = 7,
|
||||
R16 = 9,
|
||||
ARGBFloat,
|
||||
RGB565,
|
||||
BGR24,
|
||||
R16,
|
||||
DXT1,
|
||||
DXT5 = 12,
|
||||
DXT3,
|
||||
DXT5,
|
||||
RGBA4444,
|
||||
BGRA32,
|
||||
RHalf,
|
||||
@@ -136,11 +168,12 @@ namespace AssetStudio
|
||||
RGBAFloat,
|
||||
YUY2,
|
||||
RGB9e5Float,
|
||||
BC4 = 26,
|
||||
BC5,
|
||||
BC6H = 24,
|
||||
RGBFloat,
|
||||
BC6H,
|
||||
BC7,
|
||||
DXT1Crunched = 28,
|
||||
BC4,
|
||||
BC5,
|
||||
DXT1Crunched,
|
||||
DXT5Crunched,
|
||||
PVRTC_RGB2,
|
||||
PVRTC_RGBA2,
|
||||
@@ -174,5 +207,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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum EndianType
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
|
||||
public class EndianBinaryReader : BinaryReader
|
||||
{
|
||||
public EndianType endian;
|
||||
private readonly byte[] buffer;
|
||||
|
||||
public EndianType Endian;
|
||||
|
||||
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
|
||||
{
|
||||
this.endian = endian;
|
||||
Endian = endian;
|
||||
buffer = new byte[8];
|
||||
}
|
||||
|
||||
public long Position
|
||||
@@ -28,88 +24,82 @@ namespace AssetStudio
|
||||
|
||||
public override short ReadInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt16(buff, 0);
|
||||
Read(buffer, 0, 2);
|
||||
return BinaryPrimitives.ReadInt16BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt16();
|
||||
}
|
||||
|
||||
public override int ReadInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt32(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
return BinaryPrimitives.ReadInt32BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt32();
|
||||
}
|
||||
|
||||
public override long ReadInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
return BinaryPrimitives.ReadInt64BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt64();
|
||||
}
|
||||
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt16(buff, 0);
|
||||
Read(buffer, 0, 2);
|
||||
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt16();
|
||||
}
|
||||
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt32(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt32();
|
||||
}
|
||||
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt64();
|
||||
}
|
||||
|
||||
public override float ReadSingle()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToSingle(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
Array.Reverse(buffer, 0, 4);
|
||||
return BitConverter.ToSingle(buffer, 0);
|
||||
}
|
||||
return base.ReadSingle();
|
||||
}
|
||||
|
||||
public override double ReadDouble()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToDouble(buffer, 0);
|
||||
}
|
||||
return base.ReadDouble();
|
||||
}
|
||||
|
||||
14
AssetStudio/EndianType.cs
Normal file
14
AssetStudio/EndianType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum EndianType
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
103
AssetStudio/FileReader.cs
Normal file
103
AssetStudio/FileReader.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
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 };
|
||||
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
|
||||
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
|
||||
|
||||
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:
|
||||
{
|
||||
byte[] 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;
|
||||
}
|
||||
magic = ReadBytes(4);
|
||||
Position = 0;
|
||||
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
|
||||
return FileType.ZipFile;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
19
AssetStudio/FileType.cs
Normal file
19
AssetStudio/FileType.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
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,
|
||||
ZipFile
|
||||
}
|
||||
}
|
||||
346
AssetStudio/IImported.cs
Normal file
346
AssetStudio/IImported.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public interface IImported
|
||||
{
|
||||
ImportedFrame RootFrame { get; }
|
||||
List<ImportedMesh> MeshList { get; }
|
||||
List<ImportedMaterial> MaterialList { get; }
|
||||
List<ImportedTexture> TextureList { get; }
|
||||
List<ImportedKeyframedAnimation> AnimationList { get; }
|
||||
List<ImportedMorph> MorphList { get; }
|
||||
}
|
||||
|
||||
public class ImportedFrame
|
||||
{
|
||||
public string Name { 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;
|
||||
|
||||
public ImportedFrame this[int i] => children[i];
|
||||
|
||||
public int Count => children.Count;
|
||||
|
||||
public string Path
|
||||
{
|
||||
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 Remove(ImportedFrame frame)
|
||||
{
|
||||
children.Remove(frame);
|
||||
}
|
||||
|
||||
public ImportedFrame FindFrameByPath(string path)
|
||||
{
|
||||
var name = path.Substring(path.LastIndexOf('/') + 1);
|
||||
foreach (var frame in FindChilds(name))
|
||||
{
|
||||
if (frame.Path.EndsWith(path, StringComparison.Ordinal))
|
||||
{
|
||||
return frame;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImportedFrame FindRelativeFrameWithPath(string path)
|
||||
{
|
||||
var subs = path.Split(new[] { '/' }, 2);
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (child.Name == subs[0])
|
||||
{
|
||||
if (subs.Length == 1)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = child.FindRelativeFrameWithPath(subs[1]);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImportedFrame FindFrame(string name)
|
||||
{
|
||||
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 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<ImportedFace> FaceList { get; set; }
|
||||
public string Material { get; set; }
|
||||
public int BaseVertex { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedVertex
|
||||
{
|
||||
public Vector3 Vertex { get; set; }
|
||||
public Vector3 Normal { get; set; }
|
||||
public float[][] UV { get; set; }
|
||||
public Vector4 Tangent { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public float[] Weights { get; set; }
|
||||
public int[] BoneIndices { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedFace
|
||||
{
|
||||
public int[] VertexIndices { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedBone
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public Matrix4x4 Matrix { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedMaterial
|
||||
{
|
||||
public string Name { 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
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public ImportedTexture(MemoryStream stream, string name)
|
||||
{
|
||||
Name = name;
|
||||
Data = stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportedKeyframedAnimation
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public float SampleRate { get; set; }
|
||||
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
||||
|
||||
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
||||
{
|
||||
var track = TrackList.Find(x => x.Path == path);
|
||||
if (track == null)
|
||||
{
|
||||
track = new ImportedAnimationKeyframedTrack { Path = path };
|
||||
TrackList.Add(track);
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportedAnimationKeyframedTrack
|
||||
{
|
||||
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 ImportedBlendShape BlendShape;
|
||||
}
|
||||
|
||||
public class ImportedKeyframe<T>
|
||||
{
|
||||
public float time { get; set; }
|
||||
public T value { get; set; }
|
||||
|
||||
public ImportedKeyframe(float time, T value)
|
||||
{
|
||||
this.time = time;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
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 List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
||||
}
|
||||
|
||||
public class ImportedMorphKeyframe
|
||||
{
|
||||
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 ImportedMesh FindMesh(string path, List<ImportedMesh> importedMeshList)
|
||||
{
|
||||
foreach (var mesh in importedMeshList)
|
||||
{
|
||||
if (mesh.Path == path)
|
||||
{
|
||||
return mesh;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)
|
||||
{
|
||||
foreach (var mat in importedMats)
|
||||
{
|
||||
if (mat.Name == name)
|
||||
{
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ImportedTexture FindTexture(string name, List<ImportedTexture> importedTextureList)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach (var tex in importedTextureList)
|
||||
{
|
||||
if (tex.Name == name)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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.
|
||||
@@ -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.
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,540 +0,0 @@
|
||||
#define CHECK_ARGS
|
||||
#define CHECK_EOF
|
||||
//#define LOCAL_SHADOW
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Lz4
|
||||
{
|
||||
public class Lz4DecoderStream : Stream
|
||||
{
|
||||
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
Reset(input, inputLength);
|
||||
}
|
||||
|
||||
private void Reset(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
this.inputLength = inputLength;
|
||||
this.input = input;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
|
||||
decodeBufferPos = 0;
|
||||
|
||||
litLen = 0;
|
||||
matLen = 0;
|
||||
matDst = 0;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing && input != null)
|
||||
{
|
||||
input.Close();
|
||||
}
|
||||
input = null;
|
||||
decodeBuffer = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
private long inputLength;
|
||||
private Stream input;
|
||||
|
||||
//because we might not be able to match back across invocations,
|
||||
//we have to keep the last window's worth of bytes around for reuse
|
||||
//we use a circular buffer for this - every time we write into this
|
||||
//buffer, we also write the same into our output buffer
|
||||
|
||||
private const int DecBufLen = 0x10000;
|
||||
private const int DecBufMask = 0xFFFF;
|
||||
|
||||
private const int InBufLen = 128;
|
||||
|
||||
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
|
||||
private int decodeBufferPos, inBufPos, inBufEnd;
|
||||
|
||||
//we keep track of which phase we're in so that we can jump right back
|
||||
//into the correct part of decoding
|
||||
|
||||
private DecodePhase phase;
|
||||
|
||||
private enum DecodePhase
|
||||
{
|
||||
ReadToken,
|
||||
ReadExLiteralLength,
|
||||
CopyLiteral,
|
||||
ReadOffset,
|
||||
ReadExMatchLength,
|
||||
CopyMatch,
|
||||
}
|
||||
|
||||
//state within interruptable phases and across phase boundaries is
|
||||
//kept here - again, so that we can punt out and restart freely
|
||||
|
||||
private int litLen, matLen, matDst;
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
#if CHECK_ARGS
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset < 0 || count < 0 || buffer.Length - count < offset)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
if (input == null)
|
||||
throw new InvalidOperationException();
|
||||
#endif
|
||||
int nRead, nToRead = count;
|
||||
|
||||
var decBuf = decodeBuffer;
|
||||
|
||||
//the stringy gotos are obnoxious, but their purpose is to
|
||||
//make it *blindingly* obvious how the state machine transitions
|
||||
//back and forth as it reads - remember, we can yield out of
|
||||
//this routine in several places, and we must be able to re-enter
|
||||
//and pick up where we left off!
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
var phase = this.phase;
|
||||
var inBufPos = this.inBufPos;
|
||||
var inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
switch (phase)
|
||||
{
|
||||
case DecodePhase.ReadToken:
|
||||
goto readToken;
|
||||
|
||||
case DecodePhase.ReadExLiteralLength:
|
||||
goto readExLiteralLength;
|
||||
|
||||
case DecodePhase.CopyLiteral:
|
||||
goto copyLiteral;
|
||||
|
||||
case DecodePhase.ReadOffset:
|
||||
goto readOffset;
|
||||
|
||||
case DecodePhase.ReadExMatchLength:
|
||||
goto readExMatchLength;
|
||||
|
||||
case DecodePhase.CopyMatch:
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readToken:
|
||||
int tok;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
tok = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
|
||||
tok = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (tok == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen = tok >> 4;
|
||||
matLen = (tok & 0xF) + 4;
|
||||
|
||||
switch (litLen)
|
||||
{
|
||||
case 0:
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
case 0xF:
|
||||
phase = DecodePhase.ReadExLiteralLength;
|
||||
goto readExLiteralLength;
|
||||
|
||||
default:
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
readExLiteralLength:
|
||||
int exLitLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exLitLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exLitLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
|
||||
#if CHECK_EOF
|
||||
if (exLitLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen += exLitLen;
|
||||
if (exLitLen == 255)
|
||||
goto readExLiteralLength;
|
||||
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
|
||||
copyLiteral:
|
||||
int nReadLit = litLen < nToRead ? litLen : nToRead;
|
||||
if (nReadLit != 0)
|
||||
{
|
||||
if (inBufPos + nReadLit <= inBufEnd)
|
||||
{
|
||||
int ofs = offset;
|
||||
|
||||
for (int c = nReadLit; c-- != 0;)
|
||||
buffer[ofs++] = decBuf[inBufPos++];
|
||||
|
||||
nRead = nReadLit;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
nRead = ReadCore(buffer, offset, nReadLit);
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
offset += nRead;
|
||||
nToRead -= nRead;
|
||||
|
||||
litLen -= nRead;
|
||||
|
||||
if (litLen != 0)
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
readOffset:
|
||||
if (inBufPos + 1 < inBufEnd)
|
||||
{
|
||||
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
|
||||
inBufPos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
matDst = ReadOffsetCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (matDst == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (matLen == 15 + 4)
|
||||
{
|
||||
phase = DecodePhase.ReadExMatchLength;
|
||||
goto readExMatchLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readExMatchLength:
|
||||
int exMatLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exMatLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exMatLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (exMatLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
matLen += exMatLen;
|
||||
if (exMatLen == 255)
|
||||
goto readExMatchLength;
|
||||
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
|
||||
copyMatch:
|
||||
int nCpyMat = matLen < nToRead ? matLen : nToRead;
|
||||
if (nCpyMat != 0)
|
||||
{
|
||||
nRead = count - nToRead;
|
||||
|
||||
int bufDst = matDst - nRead;
|
||||
if (bufDst > 0)
|
||||
{
|
||||
//offset is fairly far back, we need to pull from the buffer
|
||||
|
||||
int bufSrc = decodeBufferPos - bufDst;
|
||||
if (bufSrc < 0)
|
||||
bufSrc += DecBufLen;
|
||||
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
|
||||
|
||||
for (int c = bufCnt; c-- != 0;)
|
||||
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
|
||||
}
|
||||
else
|
||||
{
|
||||
bufDst = 0;
|
||||
}
|
||||
|
||||
int sOfs = offset - matDst;
|
||||
for (int i = bufDst; i < nCpyMat; i++)
|
||||
buffer[offset++] = buffer[sOfs++];
|
||||
|
||||
nToRead -= nCpyMat;
|
||||
matLen -= nCpyMat;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
goto readToken;
|
||||
|
||||
finish:
|
||||
nRead = count - nToRead;
|
||||
|
||||
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
|
||||
int repPos = offset - nToBuf;
|
||||
|
||||
if (nToBuf == DecBufLen)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
|
||||
decodeBufferPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int decPos = decodeBufferPos;
|
||||
|
||||
while (nToBuf-- != 0)
|
||||
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
|
||||
|
||||
decodeBufferPos = decPos & DecBufMask;
|
||||
}
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
this.phase = phase;
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
return nRead;
|
||||
}
|
||||
|
||||
private int ReadByteCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
return buf[inBufPos++];
|
||||
}
|
||||
|
||||
private int ReadOffsetCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
if (inBufEnd - inBufPos == 1)
|
||||
{
|
||||
buf[DecBufLen] = buf[inBufPos];
|
||||
|
||||
int nRead = input.Read(buf, DecBufLen + 1,
|
||||
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
{
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead + 1;
|
||||
}
|
||||
|
||||
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
|
||||
inBufPos += 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int ReadCore(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int nToRead = count;
|
||||
|
||||
var buf = decodeBuffer;
|
||||
int inBufLen = inBufEnd - inBufPos;
|
||||
|
||||
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
|
||||
if (fromBuf != 0)
|
||||
{
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
if (nToRead != 0)
|
||||
{
|
||||
int nRead;
|
||||
|
||||
if (nToRead >= InBufLen)
|
||||
{
|
||||
nRead = input.Read(buffer, offset,
|
||||
nToRead < inputLength ? nToRead : (int)inputLength);
|
||||
nToRead -= nRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
|
||||
fromBuf = nToRead < nRead ? nToRead : nRead;
|
||||
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
inputLength -= nRead;
|
||||
}
|
||||
|
||||
return count - nToRead;
|
||||
}
|
||||
|
||||
#region Stream internals
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Length => throw new NotSupportedException();
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
84
AssetStudio/Math/Color.cs
Normal file
84
AssetStudio/Math/Color.cs
Normal 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
888
AssetStudio/Math/Half.cs
Normal 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
|
||||
}
|
||||
}
|
||||
212
AssetStudio/Math/HalfHelper.cs
Normal file
212
AssetStudio/Math/HalfHelper.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
241
AssetStudio/Math/Matrix4x4.cs
Normal file
241
AssetStudio/Math/Matrix4x4.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
88
AssetStudio/Math/Quaternion.cs
Normal file
88
AssetStudio/Math/Quaternion.cs
Normal 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
148
AssetStudio/Math/Vector2.cs
Normal 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
146
AssetStudio/Math/Vector3.cs
Normal 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
163
AssetStudio/Math/Vector4.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -10,17 +10,17 @@ 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;
|
||||
|
||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.endian)
|
||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
|
||||
{
|
||||
this.assetsFile = assetsFile;
|
||||
m_PathID = objectInfo.m_PathID;
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
namespace AssetStudio
|
||||
using System;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class Progress
|
||||
{
|
||||
public static IProgress Default = new DummyProgress();
|
||||
public static IProgress<int> Default = new Progress<int>();
|
||||
private static int preValue;
|
||||
|
||||
public static void Reset()
|
||||
@@ -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")]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user