Compare commits
208 Commits
| 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 |
@@ -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
|
||||||
+151
-21
@@ -1,7 +1,10 @@
|
|||||||
## Ignore Visual Studio temporary files, build results, and
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
## files generated by popular Visual Studio add-ons.
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
# User-specific files
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
*.suo
|
*.suo
|
||||||
*.user
|
*.user
|
||||||
*.userosscache
|
*.userosscache
|
||||||
@@ -15,13 +18,22 @@
|
|||||||
[Dd]ebugPublic/
|
[Dd]ebugPublic/
|
||||||
[Rr]elease/
|
[Rr]elease/
|
||||||
[Rr]eleases/
|
[Rr]eleases/
|
||||||
build/
|
x64/
|
||||||
|
x86/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
bld/
|
bld/
|
||||||
[Bb]in/
|
[Bb]in/
|
||||||
[Oo]bj/
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
# Visual Studio 2015 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.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
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
@@ -36,18 +48,28 @@ TestResult.xml
|
|||||||
[Rr]eleasePS/
|
[Rr]eleasePS/
|
||||||
dlldata.c
|
dlldata.c
|
||||||
|
|
||||||
# DNX
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
project.lock.json
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
artifacts/
|
artifacts/
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
*_i.c
|
*_i.c
|
||||||
*_p.c
|
*_p.c
|
||||||
*_i.h
|
*_h.h
|
||||||
*.ilk
|
*.ilk
|
||||||
*.meta
|
*.meta
|
||||||
*.obj
|
*.obj
|
||||||
|
*.iobj
|
||||||
*.pch
|
*.pch
|
||||||
*.pdb
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
*.pgc
|
*.pgc
|
||||||
*.pgd
|
*.pgd
|
||||||
*.rsp
|
*.rsp
|
||||||
@@ -57,6 +79,7 @@ artifacts/
|
|||||||
*.tlh
|
*.tlh
|
||||||
*.tmp
|
*.tmp
|
||||||
*.tmp_proj
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
*.log
|
*.log
|
||||||
*.vspscc
|
*.vspscc
|
||||||
*.vssscc
|
*.vssscc
|
||||||
@@ -72,14 +95,21 @@ _Chutzpah*
|
|||||||
ipch/
|
ipch/
|
||||||
*.aps
|
*.aps
|
||||||
*.ncb
|
*.ncb
|
||||||
|
*.opendb
|
||||||
*.opensdf
|
*.opensdf
|
||||||
*.sdf
|
*.sdf
|
||||||
*.cachefile
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
# Visual Studio profiler
|
# Visual Studio profiler
|
||||||
*.psess
|
*.psess
|
||||||
*.vsp
|
*.vsp
|
||||||
*.vspx
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
# TFS 2012 Local Workspace
|
# TFS 2012 Local Workspace
|
||||||
$tf/
|
$tf/
|
||||||
@@ -101,9 +131,18 @@ _TeamCity*
|
|||||||
# DotCover is a Code Coverage Tool
|
# DotCover is a Code Coverage Tool
|
||||||
*.dotCover
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
# MightyMoose
|
# MightyMoose
|
||||||
*.mm.*
|
*.mm.*
|
||||||
@@ -131,47 +170,68 @@ publish/
|
|||||||
# Publish Web Output
|
# Publish Web Output
|
||||||
*.[Pp]ublish.xml
|
*.[Pp]ublish.xml
|
||||||
*.azurePubxml
|
*.azurePubxml
|
||||||
## TODO: Comment the next line if you want to checkin your
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
## web deploy settings but do note that will include unencrypted
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
## passwords
|
*.pubxml
|
||||||
#*.pubxml
|
|
||||||
|
|
||||||
*.publishproj
|
*.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
|
# NuGet Packages
|
||||||
*.nupkg
|
*.nupkg
|
||||||
# The packages folder can be ignored because of Package Restore
|
# The packages folder can be ignored because of Package Restore
|
||||||
**/packages/*
|
**/[Pp]ackages/*
|
||||||
# except build/, which is used as an MSBuild target.
|
# 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
|
# 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/
|
csx/
|
||||||
*.build.csdef
|
*.build.csdef
|
||||||
|
|
||||||
# Windows Store app package directory
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
AppPackages/
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
|
||||||
# Visual Studio cache files
|
# Visual Studio cache files
|
||||||
# files ending in .cache can be ignored
|
# files ending in .cache can be ignored
|
||||||
*.[Cc]ache
|
*.[Cc]ache
|
||||||
# but keep track of directories ending in .cache
|
# but keep track of directories ending in .cache
|
||||||
!*.[Cc]ache/
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
# Others
|
# Others
|
||||||
ClientBin/
|
ClientBin/
|
||||||
[Ss]tyle[Cc]op.*
|
|
||||||
~$*
|
~$*
|
||||||
*~
|
*~
|
||||||
*.dbmdl
|
*.dbmdl
|
||||||
*.dbproj.schemaview
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
*.pfx
|
*.pfx
|
||||||
*.publishsettings
|
*.publishsettings
|
||||||
node_modules/
|
|
||||||
orleans.codegen.cs
|
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
|
# RIA/Silverlight projects
|
||||||
Generated_Code/
|
Generated_Code/
|
||||||
|
|
||||||
@@ -182,21 +242,30 @@ _UpgradeReport_Files/
|
|||||||
Backup*/
|
Backup*/
|
||||||
UpgradeLog*.XML
|
UpgradeLog*.XML
|
||||||
UpgradeLog*.htm
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
# SQL Server files
|
# SQL Server files
|
||||||
*.mdf
|
*.mdf
|
||||||
*.ldf
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
# Business Intelligence projects
|
# Business Intelligence projects
|
||||||
*.rdl.data
|
*.rdl.data
|
||||||
*.bim.layout
|
*.bim.layout
|
||||||
*.bim_*.settings
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- Backup*.rdl
|
||||||
|
|
||||||
# Microsoft Fakes
|
# Microsoft Fakes
|
||||||
FakesAssemblies/
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
# Node.js Tools for Visual Studio
|
# Node.js Tools for Visual Studio
|
||||||
.ntvs_analysis.dat
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
# Visual Studio 6 build log
|
# Visual Studio 6 build log
|
||||||
*.plg
|
*.plg
|
||||||
@@ -204,7 +273,68 @@ FakesAssemblies/
|
|||||||
# Visual Studio 6 workspace options file
|
# Visual Studio 6 workspace options file
|
||||||
*.opt
|
*.opt
|
||||||
|
|
||||||
# LightSwitch generated files
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
GeneratedArtifacts/
|
*.vbw
|
||||||
_Pvt_Extensions/
|
|
||||||
ModelManifest.xml
|
# 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
|
||||||
@@ -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>
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+119
-39
@@ -1,61 +1,141 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio Version 16
|
||||||
VisualStudioVersion = 15.0.27130.2024
|
VisualStudioVersion = 16.0.31410.357
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
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
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.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
|
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
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.ActiveCfg = Debug|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x64.Build.0 = Debug|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.ActiveCfg = Debug|x86
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.Build.0 = Debug|x86
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.ActiveCfg = Release|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x64.Build.0 = Release|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.ActiveCfg = Release|x86
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.Build.0 = Release|x86
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.ActiveCfg = Debug|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x64.Build.0 = Debug|x64
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.ActiveCfg = Debug|Win32
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Debug|x86.Build.0 = Debug|Win32
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.ActiveCfg = Release|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.Build.0 = Release|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.ActiveCfg = Release|Win32
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.Build.0 = Release|Win32
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|x86
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|x86
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|x64
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|x86
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|x86
|
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.Build.0 = Debug|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.Build.0 = Debug|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.ActiveCfg = Release|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.Build.0 = Release|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.ActiveCfg = Release|Any CPU
|
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.Build.0 = 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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {F5C476A6-2B3B-416F-8BD5-6FE454FF3972}
|
SolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
+17
-148
@@ -1,153 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<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')" />
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Version>0.16.0.0</Version>
|
||||||
<ProjectGuid>{AF56B63C-1764-41B7-9E60-8D485422AC3B}</ProjectGuid>
|
<AssemblyVersion>0.16.0.0</AssemblyVersion>
|
||||||
<OutputType>Library</OutputType>
|
<FileVersion>0.16.0.0</FileVersion>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<RootNamespace>AssetStudio</RootNamespace>
|
<DebugType>embedded</DebugType>
|
||||||
<AssemblyName>AssetStudio</AssemblyName>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
<FileAlignment>512</FileAlignment>
|
|
||||||
<Deterministic>true</Deterministic>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
<DebugType>full</DebugType>
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
|
||||||
<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="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="7zip\Common\CommandLineParser.cs" />
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
<Compile Include="7zip\Common\CRC.cs" />
|
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||||
<Compile Include="7zip\Common\InBuffer.cs" />
|
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
|
||||||
<Compile Include="7zip\Common\OutBuffer.cs" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
|
||||||
<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="Classes\RuntimeAnimatorController.cs" />
|
|
||||||
<Compile Include="Math\Color.cs" />
|
|
||||||
<Compile Include="Math\Half.cs" />
|
|
||||||
<Compile Include="Math\HalfHelper.cs" />
|
|
||||||
<Compile Include="Math\Matrix4x4.cs" />
|
|
||||||
<Compile Include="Math\Quaternion.cs" />
|
|
||||||
<Compile Include="Math\Vector2.cs" />
|
|
||||||
<Compile Include="Math\Vector3.cs" />
|
|
||||||
<Compile Include="Math\Vector4.cs" />
|
|
||||||
<Compile Include="UType.cs" />
|
|
||||||
<Compile Include="ResourceReader.cs" />
|
|
||||||
<Compile Include="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="ILogger.cs" />
|
|
||||||
<Compile Include="ImportHelper.cs" />
|
|
||||||
<Compile Include="IProgress.cs" />
|
|
||||||
<Compile Include="LocalSerializedObjectIdentifier.cs" />
|
|
||||||
<Compile Include="Logger.cs" />
|
|
||||||
<Compile Include="Lz4DecoderStream.cs" />
|
|
||||||
<Compile Include="ObjectInfo.cs" />
|
|
||||||
<Compile Include="ObjectReader.cs" />
|
|
||||||
<Compile Include="Classes\PPtr.cs" />
|
|
||||||
<Compile Include="Progress.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.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>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
</Project>
|
</Project>
|
||||||
+343
-154
@@ -1,23 +1,29 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using static AssetStudio.ImportHelper;
|
using static AssetStudio.ImportHelper;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class AssetsManager
|
public class AssetsManager
|
||||||
{
|
{
|
||||||
|
public string SpecifyUnityVersion;
|
||||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
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 List<string> importFiles = new List<string>();
|
||||||
private HashSet<string> importFilesHash = new HashSet<string>();
|
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
private HashSet<string> assetsFileListHash = new HashSet<string>();
|
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public void LoadFiles(params string[] files)
|
public void LoadFiles(params string[] files)
|
||||||
{
|
{
|
||||||
var path = Path.GetDirectoryName(files[0]);
|
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
|
||||||
MergeSplitAssets(path);
|
MergeSplitAssets(path);
|
||||||
var toReadFile = ProcessingSplitFiles(files.ToList());
|
var toReadFile = ProcessingSplitFiles(files.ToList());
|
||||||
Load(toReadFile);
|
Load(toReadFile);
|
||||||
@@ -36,7 +42,7 @@ namespace AssetStudio
|
|||||||
foreach (var file in files)
|
foreach (var file in files)
|
||||||
{
|
{
|
||||||
importFiles.Add(file);
|
importFiles.Add(file);
|
||||||
importFilesHash.Add(Path.GetFileName(file).ToUpper());
|
importFilesHash.Add(Path.GetFileName(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
Progress.Reset();
|
Progress.Reset();
|
||||||
@@ -49,124 +55,153 @@ namespace AssetStudio
|
|||||||
|
|
||||||
importFiles.Clear();
|
importFiles.Clear();
|
||||||
importFilesHash.Clear();
|
importFilesHash.Clear();
|
||||||
|
noexistFiles.Clear();
|
||||||
assetsFileListHash.Clear();
|
assetsFileListHash.Clear();
|
||||||
|
|
||||||
ReadAssets();
|
ReadAssets();
|
||||||
ProcessGameObject();
|
ProcessAssets();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadFile(string fullName)
|
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:
|
case FileType.AssetsFile:
|
||||||
LoadAssetsFile(fullName, reader);
|
LoadAssetsFile(reader);
|
||||||
break;
|
break;
|
||||||
case FileType.BundleFile:
|
case FileType.BundleFile:
|
||||||
LoadBundleFile(fullName, reader);
|
LoadBundleFile(reader);
|
||||||
break;
|
break;
|
||||||
case FileType.WebFile:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
|
private void LoadAssetsFile(FileReader reader)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(fullName);
|
if (!assetsFileListHash.Contains(reader.FileName))
|
||||||
if (!assetsFileListHash.Contains(fileName.ToUpper()))
|
|
||||||
{
|
{
|
||||||
Logger.Info($"Loading {fileName}");
|
Logger.Info($"Loading {reader.FullPath}");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var assetsFile = new SerializedFile(this, fullName, reader);
|
var assetsFile = new SerializedFile(reader, this);
|
||||||
|
CheckStrippedVersion(assetsFile);
|
||||||
assetsFileList.Add(assetsFile);
|
assetsFileList.Add(assetsFile);
|
||||||
assetsFileListHash.Add(assetsFile.upperFileName);
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
|
|
||||||
foreach (var sharedFile in assetsFile.m_Externals)
|
foreach (var sharedFile in assetsFile.m_Externals)
|
||||||
{
|
{
|
||||||
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
|
|
||||||
var sharedFileName = 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 (!File.Exists(sharedFilePath))
|
||||||
if (findFiles.Length > 0)
|
|
||||||
{
|
{
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
Logger.Error($"Error while reading assets file {reader.FullPath}", e);
|
||||||
reader.Dispose();
|
reader.Dispose();
|
||||||
//Logger.Error($"Unable to load assets file {fileName}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Logger.Info($"Skipping {reader.FullPath}");
|
||||||
reader.Dispose();
|
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 upperFileName = Path.GetFileName(fullName).ToUpper();
|
if (!assetsFileListHash.Contains(reader.FileName))
|
||||||
if (!assetsFileListHash.Contains(upperFileName))
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var assetsFile = new SerializedFile(this, fullName, reader);
|
var assetsFile = new SerializedFile(reader, this);
|
||||||
assetsFile.originalPath = originalPath;
|
assetsFile.originalPath = originalPath;
|
||||||
if (assetsFile.header.m_Version < 7)
|
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
|
||||||
{
|
{
|
||||||
assetsFile.SetVersion(unityVersion);
|
assetsFile.SetVersion(unityVersion);
|
||||||
}
|
}
|
||||||
|
CheckStrippedVersion(assetsFile);
|
||||||
assetsFileList.Add(assetsFile);
|
assetsFileList.Add(assetsFile);
|
||||||
assetsFileListHash.Add(assetsFile.upperFileName);
|
assetsFileListHash.Add(assetsFile.fileName);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//Logger.Error($"Unable to load assets file {fileName} from {Path.GetFileName(originalPath)}");
|
Logger.Error($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}", e);
|
||||||
}
|
resourceFileReaders.Add(reader.FileName, reader);
|
||||||
finally
|
|
||||||
{
|
|
||||||
resourceFileReaders.Add(upperFileName, reader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
|
private void LoadBundleFile(FileReader reader, string originalPath = null)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(fullName);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
Logger.Info("Loading " + fileName);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var bundleFile = new BundleFile(reader, fullName);
|
var bundleFile = new BundleFile(reader);
|
||||||
foreach (var file in bundleFile.fileList)
|
foreach (var file in bundleFile.fileList)
|
||||||
{
|
{
|
||||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
|
||||||
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
|
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
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
/*var str = $"Unable to load bundle file {fileName}";
|
var str = $"Error while reading bundle file {reader.FullPath}";
|
||||||
if (parentPath != null)
|
if (originalPath != null)
|
||||||
{
|
{
|
||||||
str += $" from {Path.GetFileName(parentPath)}";
|
str += $" from {Path.GetFileName(originalPath)}";
|
||||||
}
|
}
|
||||||
Logger.Error(str);*/
|
Logger.Error(str, e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -174,33 +209,36 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadWebFile(string fullName, EndianBinaryReader reader)
|
private void LoadWebFile(FileReader reader)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(fullName);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
Logger.Info("Loading " + fileName);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var webFile = new WebFile(reader);
|
var webFile = new WebFile(reader);
|
||||||
foreach (var file in webFile.fileList)
|
foreach (var file in webFile.fileList)
|
||||||
{
|
{
|
||||||
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
|
||||||
switch (CheckFileType(file.stream, out var fileReader))
|
var subReader = new FileReader(dummyPath, file.stream);
|
||||||
|
switch (subReader.FileType)
|
||||||
{
|
{
|
||||||
case FileType.AssetsFile:
|
case FileType.AssetsFile:
|
||||||
LoadAssetsFromMemory(dummyPath, fileReader, fullName);
|
LoadAssetsFromMemory(subReader, reader.FullPath);
|
||||||
break;
|
break;
|
||||||
case FileType.BundleFile:
|
case FileType.BundleFile:
|
||||||
LoadBundleFile(dummyPath, fileReader, fullName);
|
LoadBundleFile(subReader, reader.FullPath);
|
||||||
break;
|
break;
|
||||||
case FileType.WebFile:
|
case FileType.WebFile:
|
||||||
LoadWebFile(dummyPath, fileReader);
|
LoadWebFile(subReader);
|
||||||
|
break;
|
||||||
|
case FileType.ResourceFile:
|
||||||
|
resourceFileReaders[file.fileName] = subReader; //TODO
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//Logger.Error($"Unable to load web file {fileName}");
|
Logger.Error($"Error while reading web file {reader.FullPath}", e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -208,6 +246,118 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadZipFile(FileReader reader)
|
||||||
|
{
|
||||||
|
Logger.Info("Loading " + reader.FileName);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read))
|
||||||
|
{
|
||||||
|
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()
|
public void Clear()
|
||||||
{
|
{
|
||||||
foreach (var assetsFile in assetsFileList)
|
foreach (var assetsFile in assetsFileList)
|
||||||
@@ -235,96 +385,114 @@ namespace AssetStudio
|
|||||||
Progress.Reset();
|
Progress.Reset();
|
||||||
foreach (var assetsFile in assetsFileList)
|
foreach (var assetsFile in assetsFileList)
|
||||||
{
|
{
|
||||||
assetsFile.Objects = new Dictionary<long, Object>(assetsFile.m_Objects.Count);
|
|
||||||
foreach (var objectInfo in assetsFile.m_Objects)
|
foreach (var objectInfo in assetsFile.m_Objects)
|
||||||
{
|
{
|
||||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
|
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
|
||||||
switch (objectReader.type)
|
try
|
||||||
{
|
{
|
||||||
case ClassIDType.Animation:
|
Object obj;
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Animation(objectReader));
|
switch (objectReader.type)
|
||||||
break;
|
{
|
||||||
case ClassIDType.AnimationClip:
|
case ClassIDType.Animation:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimationClip(objectReader));
|
obj = new Animation(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Animator:
|
case ClassIDType.AnimationClip:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Animator(objectReader));
|
obj = new AnimationClip(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AnimatorController:
|
case ClassIDType.Animator:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorController(objectReader));
|
obj = new Animator(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AnimatorOverrideController:
|
case ClassIDType.AnimatorController:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AnimatorOverrideController(objectReader));
|
obj = new AnimatorController(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AssetBundle:
|
case ClassIDType.AnimatorOverrideController:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AssetBundle(objectReader));
|
obj = new AnimatorOverrideController(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AudioClip:
|
case ClassIDType.AssetBundle:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new AudioClip(objectReader));
|
obj = new AssetBundle(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Avatar:
|
case ClassIDType.AudioClip:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Avatar(objectReader));
|
obj = new AudioClip(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Font:
|
case ClassIDType.Avatar:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Font(objectReader));
|
obj = new Avatar(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.GameObject:
|
case ClassIDType.Font:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new GameObject(objectReader));
|
obj = new Font(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Material:
|
case ClassIDType.GameObject:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Material(objectReader));
|
obj = new GameObject(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Mesh:
|
case ClassIDType.Material:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Mesh(objectReader));
|
obj = new Material(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MeshFilter:
|
case ClassIDType.Mesh:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshFilter(objectReader));
|
obj = new Mesh(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MeshRenderer:
|
case ClassIDType.MeshFilter:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MeshRenderer(objectReader));
|
obj = new MeshFilter(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MonoBehaviour:
|
case ClassIDType.MeshRenderer:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoBehaviour(objectReader));
|
obj = new MeshRenderer(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MonoScript:
|
case ClassIDType.MonoBehaviour:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MonoScript(objectReader));
|
obj = new MonoBehaviour(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MovieTexture:
|
case ClassIDType.MonoScript:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new MovieTexture(objectReader));
|
obj = new MonoScript(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.PlayerSettings:
|
case ClassIDType.MovieTexture:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new PlayerSettings(objectReader));
|
obj = new MovieTexture(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.RectTransform:
|
case ClassIDType.PlayerSettings:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new RectTransform(objectReader));
|
obj = new PlayerSettings(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Shader:
|
case ClassIDType.RectTransform:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Shader(objectReader));
|
obj = new RectTransform(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.SkinnedMeshRenderer:
|
case ClassIDType.Shader:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new SkinnedMeshRenderer(objectReader));
|
obj = new Shader(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Sprite:
|
case ClassIDType.SkinnedMeshRenderer:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Sprite(objectReader));
|
obj = new SkinnedMeshRenderer(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.SpriteAtlas:
|
case ClassIDType.Sprite:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new SpriteAtlas(objectReader));
|
obj = new Sprite(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.TextAsset:
|
case ClassIDType.SpriteAtlas:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new TextAsset(objectReader));
|
obj = new SpriteAtlas(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Texture2D:
|
case ClassIDType.TextAsset:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Texture2D(objectReader));
|
obj = new TextAsset(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Transform:
|
case ClassIDType.Texture2D:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Transform(objectReader));
|
obj = new Texture2D(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.VideoClip:
|
case ClassIDType.Transform:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new VideoClip(objectReader));
|
obj = new Transform(objectReader);
|
||||||
break;
|
break;
|
||||||
default:
|
case ClassIDType.VideoClip:
|
||||||
assetsFile.Objects.Add(objectInfo.m_PathID, new Object(objectReader));
|
obj = new VideoClip(objectReader);
|
||||||
break;
|
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);
|
Progress.Report(++i, progressCount);
|
||||||
@@ -332,13 +500,13 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ProcessGameObject()
|
private void ProcessAssets()
|
||||||
{
|
{
|
||||||
Logger.Info("Process GameObject...");
|
Logger.Info("Process Assets...");
|
||||||
|
|
||||||
foreach (var assetsFile in assetsFileList)
|
foreach (var assetsFile in assetsFileList)
|
||||||
{
|
{
|
||||||
foreach (var obj in assetsFile.Objects.Values)
|
foreach (var obj in assetsFile.Objects)
|
||||||
{
|
{
|
||||||
if (obj is GameObject m_GameObject)
|
if (obj is GameObject m_GameObject)
|
||||||
{
|
{
|
||||||
@@ -370,6 +538,27 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
public enum BuildTarget
|
||||||
{
|
{
|
||||||
UnknownPlatform = 3716,
|
NoTarget = -2,
|
||||||
DashboardWidget = 1,
|
AnyPlayer = -1,
|
||||||
|
ValidPlayer = 1,
|
||||||
StandaloneOSX = 2,
|
StandaloneOSX = 2,
|
||||||
StandaloneOSXPPC = 3,
|
StandaloneOSXPPC = 3,
|
||||||
StandaloneOSXIntel = 4,
|
StandaloneOSXIntel = 4,
|
||||||
@@ -19,8 +20,10 @@ namespace AssetStudio
|
|||||||
iOS = 9,
|
iOS = 9,
|
||||||
PS3,
|
PS3,
|
||||||
XBOX360,
|
XBOX360,
|
||||||
|
Broadcom = 12,
|
||||||
Android = 13,
|
Android = 13,
|
||||||
StandaloneGLESEmu = 14,
|
StandaloneGLESEmu = 14,
|
||||||
|
StandaloneGLES20Emu = 15,
|
||||||
NaCl = 16,
|
NaCl = 16,
|
||||||
StandaloneLinux = 17,
|
StandaloneLinux = 17,
|
||||||
FlashPlayer = 18,
|
FlashPlayer = 18,
|
||||||
@@ -42,6 +45,14 @@ namespace AssetStudio
|
|||||||
WiiU,
|
WiiU,
|
||||||
tvOS,
|
tvOS,
|
||||||
Switch,
|
Switch,
|
||||||
NoTarget = -2
|
Lumin,
|
||||||
|
Stadia,
|
||||||
|
CloudRendering,
|
||||||
|
GameCoreXboxSeries,
|
||||||
|
GameCoreXboxOne,
|
||||||
|
PS5,
|
||||||
|
EmbeddedLinux,
|
||||||
|
QNX,
|
||||||
|
UnknownPlatform = 9999
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+302
-189
@@ -1,246 +1,359 @@
|
|||||||
using System.Collections.Generic;
|
using K4os.Compression.LZ4;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Lz4;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class StreamFile
|
[Flags]
|
||||||
|
public enum ArchiveFlags
|
||||||
{
|
{
|
||||||
public string fileName;
|
CompressionTypeMask = 0x3f,
|
||||||
public Stream stream;
|
BlocksAndDirectoryInfoCombined = 0x40,
|
||||||
|
BlocksInfoAtTheEnd = 0x80,
|
||||||
|
OldWebPluginCompatibility = 0x100,
|
||||||
|
BlockInfoNeedPaddingAtStart = 0x200
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlockInfo
|
[Flags]
|
||||||
|
public enum StorageBlockFlags
|
||||||
{
|
{
|
||||||
public uint compressedSize;
|
CompressionTypeMask = 0x3f,
|
||||||
public uint uncompressedSize;
|
Streamed = 0x40
|
||||||
public short flag;
|
}
|
||||||
|
|
||||||
|
public enum CompressionType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Lzma,
|
||||||
|
Lz4,
|
||||||
|
Lz4HC,
|
||||||
|
Lzham
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BundleFile
|
public class BundleFile
|
||||||
{
|
{
|
||||||
private string path;
|
public class Header
|
||||||
public string versionPlayer;
|
|
||||||
public string versionEngine;
|
|
||||||
public List<StreamFile> fileList = new List<StreamFile>();
|
|
||||||
|
|
||||||
public BundleFile(EndianBinaryReader bundleReader, string path)
|
|
||||||
{
|
{
|
||||||
this.path = path;
|
public string signature;
|
||||||
var signature = bundleReader.ReadStringToNull();
|
public uint version;
|
||||||
switch (signature)
|
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 "UnityWeb":
|
||||||
case "UnityRaw":
|
case "UnityRaw":
|
||||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
if (m_Header.version == 6)
|
||||||
{
|
{
|
||||||
var format = bundleReader.ReadInt32();
|
goto case "UnityFS";
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
ReadHeaderAndBlocksInfo(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(reader.FullPath))
|
||||||
|
{
|
||||||
|
ReadBlocksAndDirectory(reader, blocksStream);
|
||||||
|
ReadFiles(blocksStream, reader.FullPath);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case "UnityFS":
|
case "UnityFS":
|
||||||
|
ReadHeader(reader);
|
||||||
|
ReadBlocksInfoAndDirectory(reader);
|
||||||
|
using (var blocksStream = CreateBlocksStream(reader.FullPath))
|
||||||
{
|
{
|
||||||
var format = bundleReader.ReadInt32();
|
ReadBlocks(reader, blocksStream);
|
||||||
versionPlayer = bundleReader.ReadStringToNull();
|
ReadFiles(blocksStream, reader.FullPath);
|
||||||
versionEngine = bundleReader.ReadStringToNull();
|
|
||||||
if (format == 6)
|
|
||||||
{
|
|
||||||
ReadFormat6(bundleReader);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetAssetsFiles(EndianBinaryReader reader, int offset)
|
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||||
{
|
{
|
||||||
int fileCount = reader.ReadInt32();
|
if (m_Header.version >= 4)
|
||||||
for (int i = 0; i < fileCount; i++)
|
|
||||||
{
|
{
|
||||||
var file = new StreamFile();
|
var hash = reader.ReadBytes(16);
|
||||||
file.fileName = Path.GetFileName(reader.ReadStringToNull());
|
var crc = reader.ReadUInt32();
|
||||||
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 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();
|
Stream blocksStream;
|
||||||
int compressedSize = bundleReader.ReadInt32();
|
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
|
||||||
int uncompressedSize = bundleReader.ReadInt32();
|
if (uncompressedSizeSum >= int.MaxValue)
|
||||||
int flag = bundleReader.ReadInt32();
|
|
||||||
if (padding)
|
|
||||||
bundleReader.ReadByte();
|
|
||||||
byte[] blocksInfoBytes;
|
|
||||||
if ((flag & 0x80) != 0)//at end of file
|
|
||||||
{
|
{
|
||||||
var position = bundleReader.Position;
|
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
|
||||||
bundleReader.Position = bundleReader.BaseStream.Length - compressedSize;
|
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
||||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
||||||
bundleReader.Position = position;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
blocksInfoBytes = bundleReader.ReadBytes(compressedSize);
|
blocksStream = new MemoryStream((int)uncompressedSizeSum);
|
||||||
}
|
}
|
||||||
MemoryStream blocksInfoStream;
|
return blocksStream;
|
||||||
switch (flag & 0x3F)
|
}
|
||||||
|
|
||||||
|
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);
|
using (var decompressStream = SevenZipHelper.StreamDecompress(memoryStream))
|
||||||
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)))
|
|
||||||
{
|
{
|
||||||
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;
|
blocksStream.Write(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||||
var uncompressedSizeSum = blockInfos.Sum(x => x.uncompressedSize);
|
}
|
||||||
if (uncompressedSizeSum > int.MaxValue)
|
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);
|
path = blocksReader.ReadStringToNull(),
|
||||||
assetsDataStream = memoryMappedFile.CreateViewStream();*/
|
offset = blocksReader.ReadUInt32(),
|
||||||
dataStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
|
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
|
else
|
||||||
{
|
{
|
||||||
dataStream = new MemoryStream();
|
file.stream = new MemoryStream((int)node.size);
|
||||||
}
|
}
|
||||||
foreach (var blockInfo in blockInfos)
|
blocksStream.Position = node.offset;
|
||||||
{
|
blocksStream.CopyTo(file.stream, node.size);
|
||||||
switch (blockInfo.flag & 0x3F)
|
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
|
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
|
||||||
{
|
break;
|
||||||
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?
|
|
||||||
}
|
}
|
||||||
|
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();
|
m_DirectoryInfo[i] = new Node
|
||||||
for (int i = 0; i < entryinfo_count; i++)
|
|
||||||
{
|
{
|
||||||
var file = new StreamFile();
|
offset = blocksInfoReader.ReadInt64(),
|
||||||
var entryinfo_offset = blocksInfoReader.ReadInt64();
|
size = blocksInfoReader.ReadInt64(),
|
||||||
var entryinfo_size = blocksInfoReader.ReadInt64();
|
flags = blocksInfoReader.ReadUInt32(),
|
||||||
flag = blocksInfoReader.ReadInt32();
|
path = blocksInfoReader.ReadStringToNull(),
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+103
-10
@@ -1,4 +1,5 @@
|
|||||||
namespace AssetStudio
|
// official Class ID Reference: https://docs.unity3d.com/Manual/ClassIDReference.html
|
||||||
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public enum ClassIDType
|
public enum ClassIDType
|
||||||
{
|
{
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
ParticleRenderer = 26,
|
ParticleRenderer = 26,
|
||||||
Texture = 27,
|
Texture = 27,
|
||||||
Texture2D = 28,
|
Texture2D = 28,
|
||||||
SceneSettings = 29,
|
OcclusionCullingSettings = 29,
|
||||||
GraphicsSettings = 30,
|
GraphicsSettings = 30,
|
||||||
MeshFilter = 33,
|
MeshFilter = 33,
|
||||||
OcclusionPortal = 41,
|
OcclusionPortal = 41,
|
||||||
@@ -49,7 +50,7 @@
|
|||||||
PhysicsMaterial2D = 62,
|
PhysicsMaterial2D = 62,
|
||||||
MeshCollider = 64,
|
MeshCollider = 64,
|
||||||
BoxCollider = 65,
|
BoxCollider = 65,
|
||||||
SpriteCollider2D = 66,
|
CompositeCollider2D = 66,
|
||||||
EdgeCollider2D = 68,
|
EdgeCollider2D = 68,
|
||||||
CapsuleCollider2D = 70,
|
CapsuleCollider2D = 70,
|
||||||
ComputeShader = 72,
|
ComputeShader = 72,
|
||||||
@@ -92,6 +93,7 @@
|
|||||||
FlareLayer = 124,
|
FlareLayer = 124,
|
||||||
HaloLayer = 125,
|
HaloLayer = 125,
|
||||||
NavMeshAreas = 126,
|
NavMeshAreas = 126,
|
||||||
|
NavMeshProjectSettings = 126,
|
||||||
HaloManager = 127,
|
HaloManager = 127,
|
||||||
Font = 128,
|
Font = 128,
|
||||||
PlayerSettings = 129,
|
PlayerSettings = 129,
|
||||||
@@ -158,7 +160,7 @@
|
|||||||
BlendTree = 206,
|
BlendTree = 206,
|
||||||
Motion = 207,
|
Motion = 207,
|
||||||
NavMeshObstacle = 208,
|
NavMeshObstacle = 208,
|
||||||
TerrainInstance = 210,
|
SortingGroup = 210,
|
||||||
SpriteRenderer = 212,
|
SpriteRenderer = 212,
|
||||||
Sprite = 213,
|
Sprite = 213,
|
||||||
CachedSpriteAtlas = 214,
|
CachedSpriteAtlas = 214,
|
||||||
@@ -216,15 +218,19 @@
|
|||||||
PerformanceReportingManager = 305,
|
PerformanceReportingManager = 305,
|
||||||
UnityConnectSettings = 310,
|
UnityConnectSettings = 310,
|
||||||
AvatarMask = 319,
|
AvatarMask = 319,
|
||||||
|
PlayableDirector = 320,
|
||||||
VideoPlayer = 328,
|
VideoPlayer = 328,
|
||||||
VideoClip = 329,
|
VideoClip = 329,
|
||||||
|
ParticleSystemForceField = 330,
|
||||||
|
SpriteMask = 331,
|
||||||
|
WorldAnchor = 362,
|
||||||
OcclusionCullingData = 363,
|
OcclusionCullingData = 363,
|
||||||
//kLargestRuntimeClassID = 364
|
//kLargestRuntimeClassID = 364
|
||||||
SmallestEditorClassID = 1000,
|
SmallestEditorClassID = 1000,
|
||||||
Prefab = 1001,
|
PrefabInstance = 1001,
|
||||||
EditorExtensionImpl = 1002,
|
EditorExtensionImpl = 1002,
|
||||||
AssetImporter = 1003,
|
AssetImporter = 1003,
|
||||||
AssetDatabase = 1004,
|
AssetDatabaseV1 = 1004,
|
||||||
Mesh3DSImporter = 1005,
|
Mesh3DSImporter = 1005,
|
||||||
TextureImporter = 1006,
|
TextureImporter = 1006,
|
||||||
ShaderImporter = 1007,
|
ShaderImporter = 1007,
|
||||||
@@ -259,13 +265,13 @@
|
|||||||
AnimatorState = 1102,
|
AnimatorState = 1102,
|
||||||
HumanTemplate = 1105,
|
HumanTemplate = 1105,
|
||||||
AnimatorStateMachine = 1107,
|
AnimatorStateMachine = 1107,
|
||||||
PreviewAssetType = 1108,
|
PreviewAnimationClip = 1108,
|
||||||
AnimatorTransition = 1109,
|
AnimatorTransition = 1109,
|
||||||
SpeedTreeImporter = 1110,
|
SpeedTreeImporter = 1110,
|
||||||
AnimatorTransitionBase = 1111,
|
AnimatorTransitionBase = 1111,
|
||||||
SubstanceImporter = 1112,
|
SubstanceImporter = 1112,
|
||||||
LightmapParameters = 1113,
|
LightmapParameters = 1113,
|
||||||
LightmapSnapshot = 1120,
|
LightingDataAsset = 1120,
|
||||||
GISRaster = 1121,
|
GISRaster = 1121,
|
||||||
GISRasterImporter = 1122,
|
GISRasterImporter = 1122,
|
||||||
CadImporter = 1123,
|
CadImporter = 1123,
|
||||||
@@ -276,11 +282,98 @@
|
|||||||
ActivationLogComponent = 2000,
|
ActivationLogComponent = 2000,
|
||||||
//kLargestEditorClassID = 2001
|
//kLargestEditorClassID = 2001
|
||||||
//kClassIdOutOfHierarchy = 100000
|
//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,
|
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,
|
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,
|
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,
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -292,7 +292,7 @@ namespace AssetStudio
|
|||||||
public AnimationCurve<float> curve;
|
public AnimationCurve<float> curve;
|
||||||
public string attribute;
|
public string attribute;
|
||||||
public string path;
|
public string path;
|
||||||
public int classID;
|
public ClassIDType classID;
|
||||||
public PPtr<MonoScript> script;
|
public PPtr<MonoScript> script;
|
||||||
|
|
||||||
|
|
||||||
@@ -301,7 +301,7 @@ namespace AssetStudio
|
|||||||
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
||||||
attribute = reader.ReadAlignedString();
|
attribute = reader.ReadAlignedString();
|
||||||
path = reader.ReadAlignedString();
|
path = reader.ReadAlignedString();
|
||||||
classID = reader.ReadInt32();
|
classID = (ClassIDType)reader.ReadInt32();
|
||||||
script = new PPtr<MonoScript>(reader);
|
script = new PPtr<MonoScript>(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -637,6 +637,50 @@ namespace AssetStudio
|
|||||||
m_Binding = new ValueArrayConstant(reader);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ValueDelta
|
public class ValueDelta
|
||||||
@@ -753,6 +797,9 @@ namespace AssetStudio
|
|||||||
public ClassIDType typeID;
|
public ClassIDType typeID;
|
||||||
public byte customType;
|
public byte customType;
|
||||||
public byte isPPtrCurve;
|
public byte isPPtrCurve;
|
||||||
|
public byte isIntCurve;
|
||||||
|
|
||||||
|
public GenericBinding() { }
|
||||||
|
|
||||||
public GenericBinding(ObjectReader reader)
|
public GenericBinding(ObjectReader reader)
|
||||||
{
|
{
|
||||||
@@ -770,6 +817,10 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
customType = reader.ReadByte();
|
customType = reader.ReadByte();
|
||||||
isPPtrCurve = reader.ReadByte();
|
isPPtrCurve = reader.ReadByte();
|
||||||
|
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||||
|
{
|
||||||
|
isIntCurve = reader.ReadByte();
|
||||||
|
}
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -779,6 +830,8 @@ namespace AssetStudio
|
|||||||
public GenericBinding[] genericBindings;
|
public GenericBinding[] genericBindings;
|
||||||
public PPtr<Object>[] pptrCurveMapping;
|
public PPtr<Object>[] pptrCurveMapping;
|
||||||
|
|
||||||
|
public AnimationClipBindingConstant() { }
|
||||||
|
|
||||||
public AnimationClipBindingConstant(ObjectReader reader)
|
public AnimationClipBindingConstant(ObjectReader reader)
|
||||||
{
|
{
|
||||||
int numBindings = reader.ReadInt32();
|
int numBindings = reader.ReadInt32();
|
||||||
@@ -861,9 +914,9 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum AnimationType
|
public enum AnimationType
|
||||||
{
|
{
|
||||||
kLegacy = 1,
|
Legacy = 1,
|
||||||
kGeneric = 2,
|
Generic = 2,
|
||||||
kHumanoid = 3
|
Humanoid = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public sealed class AnimationClip : NamedObject
|
public sealed class AnimationClip : NamedObject
|
||||||
@@ -897,7 +950,7 @@ namespace AssetStudio
|
|||||||
else if (version[0] >= 4)//4.0 and up
|
else if (version[0] >= 4)//4.0 and up
|
||||||
{
|
{
|
||||||
m_AnimationType = (AnimationType)reader.ReadInt32();
|
m_AnimationType = (AnimationType)reader.ReadInt32();
|
||||||
if (m_AnimationType == AnimationType.kLegacy)
|
if (m_AnimationType == AnimationType.Legacy)
|
||||||
m_Legacy = true;
|
m_Legacy = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ namespace AssetStudio
|
|||||||
if (version[0] >= 5) //5.0 and up
|
if (version[0] >= 5) //5.0 and up
|
||||||
{
|
{
|
||||||
var m_LinearVelocityBlending = reader.ReadBoolean();
|
var m_LinearVelocityBlending = reader.ReadBoolean();
|
||||||
|
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
|
||||||
|
{
|
||||||
|
var m_StabilizeFeet = reader.ReadBoolean();
|
||||||
|
}
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace AssetStudio
|
|||||||
public sealed class AudioClip : NamedObject
|
public sealed class AudioClip : NamedObject
|
||||||
{
|
{
|
||||||
public int m_Format;
|
public int m_Format;
|
||||||
public AudioType m_Type;
|
public FMODSoundType m_Type;
|
||||||
public bool m_3D;
|
public bool m_3D;
|
||||||
public bool m_UseHardware;
|
public bool m_UseHardware;
|
||||||
|
|
||||||
@@ -27,16 +27,16 @@ namespace AssetStudio
|
|||||||
public AudioCompressionFormat m_CompressionFormat;
|
public AudioCompressionFormat m_CompressionFormat;
|
||||||
|
|
||||||
public string m_Source;
|
public string m_Source;
|
||||||
public long m_Offset;
|
public long m_Offset; //ulong
|
||||||
public long m_Size;
|
public long m_Size; //ulong
|
||||||
public Lazy<byte[]> m_AudioData;
|
public ResourceReader m_AudioData;
|
||||||
|
|
||||||
public AudioClip(ObjectReader reader) : base(reader)
|
public AudioClip(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
if (version[0] < 5)
|
if (version[0] < 5)
|
||||||
{
|
{
|
||||||
m_Format = reader.ReadInt32();
|
m_Format = reader.ReadInt32();
|
||||||
m_Type = (AudioType)reader.ReadInt32();
|
m_Type = (FMODSoundType)reader.ReadInt32();
|
||||||
m_3D = reader.ReadBoolean();
|
m_3D = reader.ReadBoolean();
|
||||||
m_UseHardware = reader.ReadBoolean();
|
m_UseHardware = reader.ReadBoolean();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
@@ -48,7 +48,7 @@ namespace AssetStudio
|
|||||||
var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;
|
var tsize = m_Size % 4 != 0 ? m_Size + 4 - m_Size % 4 : m_Size;
|
||||||
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
|
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
|
||||||
{
|
{
|
||||||
m_Offset = reader.ReadInt32();
|
m_Offset = reader.ReadUInt32();
|
||||||
m_Source = assetsFile.fullName + ".resS";
|
m_Source = assetsFile.fullName + ".resS";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,6 +72,7 @@ namespace AssetStudio
|
|||||||
m_Legacy3D = reader.ReadBoolean();
|
m_Legacy3D = reader.ReadBoolean();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
|
|
||||||
|
//StreamedResource m_Resource
|
||||||
m_Source = reader.ReadAlignedString();
|
m_Source = reader.ReadAlignedString();
|
||||||
m_Offset = reader.ReadInt64();
|
m_Offset = reader.ReadInt64();
|
||||||
m_Size = reader.ReadInt64();
|
m_Size = reader.ReadInt64();
|
||||||
@@ -81,44 +82,61 @@ namespace AssetStudio
|
|||||||
ResourceReader resourceReader;
|
ResourceReader resourceReader;
|
||||||
if (!string.IsNullOrEmpty(m_Source))
|
if (!string.IsNullOrEmpty(m_Source))
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, (int)m_Size);
|
resourceReader = new ResourceReader(m_Source, assetsFile, m_Offset, m_Size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_Size);
|
||||||
}
|
}
|
||||||
m_AudioData = new Lazy<byte[]>(resourceReader.GetData);
|
m_AudioData = resourceReader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AudioType
|
public enum FMODSoundType
|
||||||
{
|
{
|
||||||
UNKNOWN,
|
UNKNOWN = 0,
|
||||||
ACC,
|
ACC = 1,
|
||||||
AIFF,
|
AIFF = 2,
|
||||||
|
ASF = 3,
|
||||||
|
AT3 = 4,
|
||||||
|
CDDA = 5,
|
||||||
|
DLS = 6,
|
||||||
|
FLAC = 7,
|
||||||
|
FSB = 8,
|
||||||
|
GCADPCM = 9,
|
||||||
IT = 10,
|
IT = 10,
|
||||||
|
MIDI = 11,
|
||||||
MOD = 12,
|
MOD = 12,
|
||||||
MPEG,
|
MPEG = 13,
|
||||||
OGGVORBIS,
|
OGGVORBIS = 14,
|
||||||
|
PLAYLIST = 15,
|
||||||
|
RAW = 16,
|
||||||
S3M = 17,
|
S3M = 17,
|
||||||
|
SF2 = 18,
|
||||||
|
USER = 19,
|
||||||
WAV = 20,
|
WAV = 20,
|
||||||
XM,
|
XM = 21,
|
||||||
XMA,
|
XMA = 22,
|
||||||
VAG,
|
VAG = 23,
|
||||||
AUDIOQUEUE
|
AUDIOQUEUE = 24,
|
||||||
|
XWMA = 25,
|
||||||
|
BCWAV = 26,
|
||||||
|
AT9 = 27,
|
||||||
|
VORBIS = 28,
|
||||||
|
MEDIA_FOUNDATION = 29
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AudioCompressionFormat
|
public enum AudioCompressionFormat
|
||||||
{
|
{
|
||||||
PCM,
|
PCM = 0,
|
||||||
Vorbis,
|
Vorbis = 1,
|
||||||
ADPCM,
|
ADPCM = 2,
|
||||||
MP3,
|
MP3 = 3,
|
||||||
VAG,
|
PSMVAG = 4,
|
||||||
HEVAG,
|
HEVAG = 5,
|
||||||
XMA,
|
XMA = 6,
|
||||||
AAC,
|
AAC = 7,
|
||||||
GCADPCM,
|
GCADPCM = 8,
|
||||||
ATRAC9
|
ATRAC9 = 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ namespace AssetStudio
|
|||||||
public class UnityPropertySheet
|
public class UnityPropertySheet
|
||||||
{
|
{
|
||||||
public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;
|
public KeyValuePair<string, UnityTexEnv>[] m_TexEnvs;
|
||||||
|
public KeyValuePair<string, int>[] m_Ints;
|
||||||
public KeyValuePair<string, float>[] m_Floats;
|
public KeyValuePair<string, float>[] m_Floats;
|
||||||
public KeyValuePair<string, Color>[] m_Colors;
|
public KeyValuePair<string, Color>[] m_Colors;
|
||||||
|
|
||||||
public UnityPropertySheet(ObjectReader reader)
|
public UnityPropertySheet(ObjectReader reader)
|
||||||
{
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
int m_TexEnvsSize = reader.ReadInt32();
|
int m_TexEnvsSize = reader.ReadInt32();
|
||||||
m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];
|
m_TexEnvs = new KeyValuePair<string, UnityTexEnv>[m_TexEnvsSize];
|
||||||
for (int i = 0; i < m_TexEnvsSize; i++)
|
for (int i = 0; i < m_TexEnvsSize; i++)
|
||||||
@@ -31,6 +34,16 @@ namespace AssetStudio
|
|||||||
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
|
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();
|
int m_FloatsSize = reader.ReadInt32();
|
||||||
m_Floats = new KeyValuePair<string, float>[m_FloatsSize];
|
m_Floats = new KeyValuePair<string, float>[m_FloatsSize];
|
||||||
for (int i = 0; i < m_FloatsSize; i++)
|
for (int i = 0; i < m_FloatsSize; i++)
|
||||||
@@ -61,9 +74,18 @@ namespace AssetStudio
|
|||||||
var m_ShaderKeywords = reader.ReadStringArray();
|
var m_ShaderKeywords = reader.ReadStringArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version[0] >= 5) //5.0 and up
|
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 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();
|
var m_ShaderKeywords = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
var m_LightmapFlags = reader.ReadUInt32();
|
var m_LightmapFlags = reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +117,8 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_SavedProperties = new UnityPropertySheet(reader);
|
m_SavedProperties = new UnityPropertySheet(reader);
|
||||||
|
|
||||||
|
//vector m_BuildTextureStacks 2020 and up
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+360
-101
@@ -166,19 +166,19 @@ namespace AssetStudio
|
|||||||
|
|
||||||
if (version[0] < 4) //4.0 down
|
if (version[0] < 4) //4.0 down
|
||||||
{
|
{
|
||||||
GetChannels();
|
GetChannels(version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else //5.0 and up
|
else //5.0 and up
|
||||||
{
|
{
|
||||||
GetStreams();
|
GetStreams(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_DataSize = reader.ReadBytes(reader.ReadInt32());
|
m_DataSize = reader.ReadUInt8Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetStreams()
|
private void GetStreams(int[] version)
|
||||||
{
|
{
|
||||||
var streamCount = m_Channels.Max(x => x.stream) + 1;
|
var streamCount = m_Channels.Max(x => x.stream) + 1;
|
||||||
m_Streams = new StreamInfo[streamCount];
|
m_Streams = new StreamInfo[streamCount];
|
||||||
@@ -195,7 +195,7 @@ namespace AssetStudio
|
|||||||
if (m_Channel.dimension > 0)
|
if (m_Channel.dimension > 0)
|
||||||
{
|
{
|
||||||
chnMask |= 1u << chn;
|
chnMask |= 1u << chn;
|
||||||
stride += m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format);
|
stride += m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -213,7 +213,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GetChannels()
|
private void GetChannels(int[] version)
|
||||||
{
|
{
|
||||||
m_Channels = new ChannelInfo[6];
|
m_Channels = new ChannelInfo[6];
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
@@ -253,7 +253,7 @@ namespace AssetStudio
|
|||||||
m_Channel.dimension = 4;
|
m_Channel.dimension = 4;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
offset += (byte)(m_Channel.dimension * MeshHelper.GetChannelFormatSize(m_Channel.format));
|
offset += (byte)(m_Channel.dimension * MeshHelper.GetFormatSize(MeshHelper.ToVertexFormat(m_Channel.format, version)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -396,11 +396,21 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum GfxPrimitiveType
|
||||||
|
{
|
||||||
|
Triangles = 0,
|
||||||
|
TriangleStrip = 1,
|
||||||
|
Quads = 2,
|
||||||
|
Lines = 3,
|
||||||
|
LineStrip = 4,
|
||||||
|
Points = 5
|
||||||
|
};
|
||||||
|
|
||||||
public class SubMesh
|
public class SubMesh
|
||||||
{
|
{
|
||||||
public uint firstByte;
|
public uint firstByte;
|
||||||
public uint indexCount;
|
public uint indexCount;
|
||||||
public int topology;
|
public GfxPrimitiveType topology;
|
||||||
public uint triangleCount;
|
public uint triangleCount;
|
||||||
public uint baseVertex;
|
public uint baseVertex;
|
||||||
public uint firstVertex;
|
public uint firstVertex;
|
||||||
@@ -413,7 +423,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
firstByte = reader.ReadUInt32();
|
firstByte = reader.ReadUInt32();
|
||||||
indexCount = reader.ReadUInt32();
|
indexCount = reader.ReadUInt32();
|
||||||
topology = reader.ReadInt32();
|
topology = (GfxPrimitiveType)reader.ReadInt32();
|
||||||
|
|
||||||
if (version[0] < 4) //4.0 down
|
if (version[0] < 4) //4.0 down
|
||||||
{
|
{
|
||||||
@@ -436,7 +446,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public sealed class Mesh : NamedObject
|
public sealed class Mesh : NamedObject
|
||||||
{
|
{
|
||||||
private bool m_Use16BitIndices = true; //3.5.0 and newer always uses 16bit indices;
|
private bool m_Use16BitIndices = true;
|
||||||
public SubMesh[] m_SubMeshes;
|
public SubMesh[] m_SubMeshes;
|
||||||
private uint[] m_IndexBuffer;
|
private uint[] m_IndexBuffer;
|
||||||
public BlendShapeData m_Shapes;
|
public BlendShapeData m_Shapes;
|
||||||
@@ -451,12 +461,16 @@ namespace AssetStudio
|
|||||||
public float[] m_UV1;
|
public float[] m_UV1;
|
||||||
public float[] m_UV2;
|
public float[] m_UV2;
|
||||||
public float[] m_UV3;
|
public float[] m_UV3;
|
||||||
|
public float[] m_UV4;
|
||||||
|
public float[] m_UV5;
|
||||||
|
public float[] m_UV6;
|
||||||
|
public float[] m_UV7;
|
||||||
public float[] m_Tangents;
|
public float[] m_Tangents;
|
||||||
private VertexData m_VertexData;
|
private VertexData m_VertexData;
|
||||||
private CompressedMesh m_CompressedMesh;
|
private CompressedMesh m_CompressedMesh;
|
||||||
private StreamingInfo m_StreamData;
|
private StreamingInfo m_StreamData;
|
||||||
|
|
||||||
public List<uint> m_Indices = new List<uint>(); //use a list because I don't always know the facecount for triangle strips
|
public List<uint> m_Indices = new List<uint>();
|
||||||
|
|
||||||
public Mesh(ObjectReader reader) : base(reader)
|
public Mesh(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
@@ -536,6 +550,7 @@ namespace AssetStudio
|
|||||||
((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
|
((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
|
||||||
{
|
{
|
||||||
var m_IndexFormat = reader.ReadInt32();
|
var m_IndexFormat = reader.ReadInt32();
|
||||||
|
m_Use16BitIndices = m_IndexFormat == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_IndexBuffer_size = reader.ReadInt32();
|
int m_IndexBuffer_size = reader.ReadInt32();
|
||||||
@@ -636,11 +651,16 @@ namespace AssetStudio
|
|||||||
|
|
||||||
int m_MeshUsageFlags = reader.ReadInt32();
|
int m_MeshUsageFlags = reader.ReadInt32();
|
||||||
|
|
||||||
|
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||||
|
{
|
||||||
|
int m_CookingOptions = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
if (version[0] >= 5) //5.0 and up
|
if (version[0] >= 5) //5.0 and up
|
||||||
{
|
{
|
||||||
var m_BakedConvexCollisionMesh = reader.ReadBytes(reader.ReadInt32());
|
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
var m_BakedTriangleCollisionMesh = reader.ReadBytes(reader.ReadInt32());
|
var m_BakedTriangleCollisionMesh = reader.ReadUInt8Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -666,7 +686,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (m_VertexData.m_VertexCount > 0)
|
if (m_VertexData.m_VertexCount > 0)
|
||||||
{
|
{
|
||||||
var resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size);
|
var resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
|
||||||
m_VertexData.m_DataSize = resourceReader.GetData();
|
m_VertexData.m_DataSize = resourceReader.GetData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -680,7 +700,7 @@ namespace AssetStudio
|
|||||||
DecompressCompressedMesh();
|
DecompressCompressedMesh();
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildFaces();
|
GetTriangles();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadVertexData()
|
private void ReadVertexData()
|
||||||
@@ -696,12 +716,13 @@ namespace AssetStudio
|
|||||||
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
|
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
|
||||||
if (channelMask.Get(chn))
|
if (channelMask.Get(chn))
|
||||||
{
|
{
|
||||||
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2)
|
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
|
||||||
{
|
{
|
||||||
m_Channel.dimension = 4;
|
m_Channel.dimension = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
var componentByteSize = (int)MeshHelper.GetChannelFormatSize(m_Channel.format);
|
var vertexFormat = MeshHelper.ToVertexFormat(m_Channel.format, version);
|
||||||
|
var componentByteSize = (int)MeshHelper.GetFormatSize(vertexFormat);
|
||||||
var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize];
|
var componentBytes = new byte[m_VertexCount * m_Channel.dimension * componentByteSize];
|
||||||
for (int v = 0; v < m_VertexCount; v++)
|
for (int v = 0; v < m_VertexCount; v++)
|
||||||
{
|
{
|
||||||
@@ -713,7 +734,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
|
if (reader.Endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
|
||||||
{
|
{
|
||||||
for (var i = 0; i < componentBytes.Length / componentByteSize; i++)
|
for (var i = 0; i < componentBytes.Length / componentByteSize; i++)
|
||||||
{
|
{
|
||||||
@@ -726,10 +747,10 @@ namespace AssetStudio
|
|||||||
|
|
||||||
int[] componentsIntArray = null;
|
int[] componentsIntArray = null;
|
||||||
float[] componentsFloatArray = null;
|
float[] componentsFloatArray = null;
|
||||||
if (m_Channel.format == 10 || m_Channel.format == 11)
|
if (MeshHelper.IsIntFormat(vertexFormat))
|
||||||
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes);
|
componentsIntArray = MeshHelper.BytesToIntArray(componentBytes, vertexFormat);
|
||||||
else
|
else
|
||||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, componentByteSize);
|
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||||
|
|
||||||
if (version[0] >= 2018)
|
if (version[0] >= 2018)
|
||||||
{
|
{
|
||||||
@@ -759,10 +780,18 @@ namespace AssetStudio
|
|||||||
case 7: //kShaderChannelTexCoord3
|
case 7: //kShaderChannelTexCoord3
|
||||||
m_UV3 = componentsFloatArray;
|
m_UV3 = componentsFloatArray;
|
||||||
break;
|
break;
|
||||||
//kShaderChannelTexCoord4 8
|
case 8: //kShaderChannelTexCoord4
|
||||||
//kShaderChannelTexCoord5 9
|
m_UV4 = componentsFloatArray;
|
||||||
//kShaderChannelTexCoord6 10
|
break;
|
||||||
//kShaderChannelTexCoord7 11
|
case 9: //kShaderChannelTexCoord5
|
||||||
|
m_UV5 = componentsFloatArray;
|
||||||
|
break;
|
||||||
|
case 10: //kShaderChannelTexCoord6
|
||||||
|
m_UV6 = componentsFloatArray;
|
||||||
|
break;
|
||||||
|
case 11: //kShaderChannelTexCoord7
|
||||||
|
m_UV7 = componentsFloatArray;
|
||||||
|
break;
|
||||||
//2018.2 and up
|
//2018.2 and up
|
||||||
case 12: //kShaderChannelBlendWeight
|
case 12: //kShaderChannelBlendWeight
|
||||||
if (m_Skin == null)
|
if (m_Skin == null)
|
||||||
@@ -840,23 +869,40 @@ namespace AssetStudio
|
|||||||
if (m_CompressedMesh.m_Vertices.m_NumItems > 0)
|
if (m_CompressedMesh.m_Vertices.m_NumItems > 0)
|
||||||
{
|
{
|
||||||
m_VertexCount = (int)m_CompressedMesh.m_Vertices.m_NumItems / 3;
|
m_VertexCount = (int)m_CompressedMesh.m_Vertices.m_NumItems / 3;
|
||||||
m_Vertices = m_CompressedMesh.m_Vertices.UnpackFloats(3, 4);
|
m_Vertices = m_CompressedMesh.m_Vertices.UnpackFloats(3, 3 * 4);
|
||||||
}
|
}
|
||||||
//UV
|
//UV
|
||||||
if (m_CompressedMesh.m_UV.m_NumItems > 0)
|
if (m_CompressedMesh.m_UV.m_NumItems > 0)
|
||||||
{
|
{
|
||||||
m_UV0 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, 0, m_VertexCount);
|
var m_UVInfo = m_CompressedMesh.m_UVInfo;
|
||||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 4)
|
if (m_UVInfo != 0)
|
||||||
{
|
{
|
||||||
m_UV1 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 2, m_VertexCount);
|
const int kInfoBitsPerUV = 4;
|
||||||
|
const int kUVDimensionMask = 3;
|
||||||
|
const int kUVChannelExists = 4;
|
||||||
|
const int kMaxTexCoordShaderChannels = 8;
|
||||||
|
|
||||||
|
int uvSrcOffset = 0;
|
||||||
|
for (int uv = 0; uv < kMaxTexCoordShaderChannels; uv++)
|
||||||
|
{
|
||||||
|
var texCoordBits = m_UVInfo >> (uv * kInfoBitsPerUV);
|
||||||
|
texCoordBits &= (1u << kInfoBitsPerUV) - 1u;
|
||||||
|
if ((texCoordBits & kUVChannelExists) != 0)
|
||||||
|
{
|
||||||
|
var uvDim = 1 + (int)(texCoordBits & kUVDimensionMask);
|
||||||
|
var m_UV = m_CompressedMesh.m_UV.UnpackFloats(uvDim, uvDim * 4, uvSrcOffset, m_VertexCount);
|
||||||
|
SetUV(uv, m_UV);
|
||||||
|
uvSrcOffset += uvDim * m_VertexCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 6)
|
else
|
||||||
{
|
{
|
||||||
m_UV2 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 4, m_VertexCount);
|
m_UV0 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, 0, m_VertexCount);
|
||||||
}
|
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 4)
|
||||||
if (m_CompressedMesh.m_UV.m_NumItems >= m_VertexCount * 8)
|
{
|
||||||
{
|
m_UV1 = m_CompressedMesh.m_UV.UnpackFloats(2, 2 * 4, m_VertexCount * 2, m_VertexCount);
|
||||||
m_UV3 = m_CompressedMesh.m_UV.UnpackFloats(2, 4, m_VertexCount * 6, m_VertexCount);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//BindPose
|
//BindPose
|
||||||
@@ -1008,7 +1054,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildFaces()
|
private void GetTriangles()
|
||||||
{
|
{
|
||||||
foreach (var m_SubMesh in m_SubMeshes)
|
foreach (var m_SubMesh in m_SubMeshes)
|
||||||
{
|
{
|
||||||
@@ -1017,43 +1063,65 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
firstIndex /= 2;
|
firstIndex /= 2;
|
||||||
}
|
}
|
||||||
|
var indexCount = m_SubMesh.indexCount;
|
||||||
if (m_SubMesh.topology == 0)
|
var topology = m_SubMesh.topology;
|
||||||
|
if (topology == GfxPrimitiveType.Triangles)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_SubMesh.indexCount / 3; i++)
|
for (int i = 0; i < indexCount; i += 3)
|
||||||
{
|
{
|
||||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3]);
|
m_Indices.Add(m_IndexBuffer[firstIndex + i]);
|
||||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 1]);
|
m_Indices.Add(m_IndexBuffer[firstIndex + i + 1]);
|
||||||
m_Indices.Add(m_IndexBuffer[firstIndex + i * 3 + 2]);
|
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
|
||||||
|
{
|
||||||
|
// de-stripify :
|
||||||
|
uint triIndex = 0;
|
||||||
|
for (int i = 0; i < indexCount - 2; i++)
|
||||||
|
{
|
||||||
|
var a = m_IndexBuffer[firstIndex + i];
|
||||||
|
var b = m_IndexBuffer[firstIndex + i + 1];
|
||||||
|
var c = m_IndexBuffer[firstIndex + i + 2];
|
||||||
|
|
||||||
|
// skip degenerates
|
||||||
|
if (a == b || a == c || b == c)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// do the winding flip-flop of strips :
|
||||||
|
if ((i & 1) == 1)
|
||||||
|
{
|
||||||
|
m_Indices.Add(b);
|
||||||
|
m_Indices.Add(a);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Indices.Add(a);
|
||||||
|
m_Indices.Add(b);
|
||||||
|
}
|
||||||
|
m_Indices.Add(c);
|
||||||
|
triIndex += 3;
|
||||||
|
}
|
||||||
|
//fix indexCount
|
||||||
|
m_SubMesh.indexCount = triIndex;
|
||||||
|
}
|
||||||
|
else if (topology == GfxPrimitiveType.Quads)
|
||||||
|
{
|
||||||
|
for (int q = 0; q < indexCount; q += 4)
|
||||||
|
{
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q]);
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q + 1]);
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q]);
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q + 2]);
|
||||||
|
m_Indices.Add(m_IndexBuffer[firstIndex + q + 3]);
|
||||||
|
}
|
||||||
|
//fix indexCount
|
||||||
|
m_SubMesh.indexCount = indexCount / 2 * 3;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint j = 0;
|
throw new NotSupportedException("Failed getting triangles. Submesh topology is lines or points.");
|
||||||
for (int i = 0; i < m_SubMesh.indexCount - 2; i++)
|
|
||||||
{
|
|
||||||
uint fa = m_IndexBuffer[firstIndex + i];
|
|
||||||
uint fb = m_IndexBuffer[firstIndex + i + 1];
|
|
||||||
uint fc = m_IndexBuffer[firstIndex + i + 2];
|
|
||||||
|
|
||||||
if ((fa != fb) && (fa != fc) && (fc != fb))
|
|
||||||
{
|
|
||||||
m_Indices.Add(fa);
|
|
||||||
if ((i % 2) == 0)
|
|
||||||
{
|
|
||||||
m_Indices.Add(fb);
|
|
||||||
m_Indices.Add(fc);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Indices.Add(fc);
|
|
||||||
m_Indices.Add(fb);
|
|
||||||
}
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//fix indexCount
|
|
||||||
m_SubMesh.indexCount = j * 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1066,62 +1134,253 @@ namespace AssetStudio
|
|||||||
m_Skin[i] = new BoneWeights4();
|
m_Skin[i] = new BoneWeights4();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetUV(int uv, float[] m_UV)
|
||||||
|
{
|
||||||
|
switch (uv)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
m_UV0 = m_UV;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_UV1 = m_UV;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m_UV2 = m_UV;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
m_UV3 = m_UV;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
m_UV4 = m_UV;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
m_UV5 = m_UV;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
m_UV6 = m_UV;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
m_UV7 = m_UV;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float[] GetUV(int uv)
|
||||||
|
{
|
||||||
|
switch (uv)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return m_UV0;
|
||||||
|
case 1:
|
||||||
|
return m_UV1;
|
||||||
|
case 2:
|
||||||
|
return m_UV2;
|
||||||
|
case 3:
|
||||||
|
return m_UV3;
|
||||||
|
case 4:
|
||||||
|
return m_UV4;
|
||||||
|
case 5:
|
||||||
|
return m_UV5;
|
||||||
|
case 6:
|
||||||
|
return m_UV6;
|
||||||
|
case 7:
|
||||||
|
return m_UV7;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class MeshHelper
|
public static class MeshHelper
|
||||||
{
|
{
|
||||||
public static uint GetChannelFormatSize(int format)
|
public enum VertexChannelFormat
|
||||||
{
|
{
|
||||||
switch (format)
|
Float,
|
||||||
|
Float16,
|
||||||
|
Color,
|
||||||
|
Byte,
|
||||||
|
UInt32
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VertexFormat2017
|
||||||
|
{
|
||||||
|
Float,
|
||||||
|
Float16,
|
||||||
|
Color,
|
||||||
|
UNorm8,
|
||||||
|
SNorm8,
|
||||||
|
UNorm16,
|
||||||
|
SNorm16,
|
||||||
|
UInt8,
|
||||||
|
SInt8,
|
||||||
|
UInt16,
|
||||||
|
SInt16,
|
||||||
|
UInt32,
|
||||||
|
SInt32
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum VertexFormat
|
||||||
|
{
|
||||||
|
Float,
|
||||||
|
Float16,
|
||||||
|
UNorm8,
|
||||||
|
SNorm8,
|
||||||
|
UNorm16,
|
||||||
|
SNorm16,
|
||||||
|
UInt8,
|
||||||
|
SInt8,
|
||||||
|
UInt16,
|
||||||
|
SInt16,
|
||||||
|
UInt32,
|
||||||
|
SInt32
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VertexFormat ToVertexFormat(int format, int[] version)
|
||||||
|
{
|
||||||
|
if (version[0] < 2017)
|
||||||
{
|
{
|
||||||
case 0: //kChannelFormatFloat
|
switch ((VertexChannelFormat)format)
|
||||||
return 4u;
|
{
|
||||||
case 1: //kChannelFormatFloat16
|
case VertexChannelFormat.Float:
|
||||||
return 2u;
|
return VertexFormat.Float;
|
||||||
case 2: //kChannelFormatColor
|
case VertexChannelFormat.Float16:
|
||||||
return 1u;
|
return VertexFormat.Float16;
|
||||||
case 3: //kChannelFormatByte
|
case VertexChannelFormat.Color: //in 4.x is size 4
|
||||||
return 1u;
|
return VertexFormat.UNorm8;
|
||||||
case 4: //kChannelFormatUInt32
|
case VertexChannelFormat.Byte:
|
||||||
return 4u;
|
return VertexFormat.UInt8;
|
||||||
case 10: //kChannelFormatInt32
|
case VertexChannelFormat.UInt32: //in 5.x
|
||||||
return 4u;
|
return VertexFormat.UInt32;
|
||||||
case 11: //kChannelFormatInt32
|
default:
|
||||||
return 4u;
|
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||||
default:
|
}
|
||||||
return 0;
|
}
|
||||||
|
else if (version[0] < 2019)
|
||||||
|
{
|
||||||
|
switch ((VertexFormat2017)format)
|
||||||
|
{
|
||||||
|
case VertexFormat2017.Float:
|
||||||
|
return VertexFormat.Float;
|
||||||
|
case VertexFormat2017.Float16:
|
||||||
|
return VertexFormat.Float16;
|
||||||
|
case VertexFormat2017.Color:
|
||||||
|
case VertexFormat2017.UNorm8:
|
||||||
|
return VertexFormat.UNorm8;
|
||||||
|
case VertexFormat2017.SNorm8:
|
||||||
|
return VertexFormat.SNorm8;
|
||||||
|
case VertexFormat2017.UNorm16:
|
||||||
|
return VertexFormat.UNorm16;
|
||||||
|
case VertexFormat2017.SNorm16:
|
||||||
|
return VertexFormat.SNorm16;
|
||||||
|
case VertexFormat2017.UInt8:
|
||||||
|
return VertexFormat.UInt8;
|
||||||
|
case VertexFormat2017.SInt8:
|
||||||
|
return VertexFormat.SInt8;
|
||||||
|
case VertexFormat2017.UInt16:
|
||||||
|
return VertexFormat.UInt16;
|
||||||
|
case VertexFormat2017.SInt16:
|
||||||
|
return VertexFormat.SInt16;
|
||||||
|
case VertexFormat2017.UInt32:
|
||||||
|
return VertexFormat.UInt32;
|
||||||
|
case VertexFormat2017.SInt32:
|
||||||
|
return VertexFormat.SInt32;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (VertexFormat)format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float[] BytesToFloatArray(byte[] inputBytes, int size)
|
|
||||||
|
public static uint GetFormatSize(VertexFormat format)
|
||||||
{
|
{
|
||||||
var result = new float[inputBytes.Length / size];
|
switch (format)
|
||||||
for (int i = 0; i < inputBytes.Length / size; i++)
|
|
||||||
{
|
{
|
||||||
var value = 0f;
|
case VertexFormat.Float:
|
||||||
switch (size)
|
case VertexFormat.UInt32:
|
||||||
|
case VertexFormat.SInt32:
|
||||||
|
return 4u;
|
||||||
|
case VertexFormat.Float16:
|
||||||
|
case VertexFormat.UNorm16:
|
||||||
|
case VertexFormat.SNorm16:
|
||||||
|
case VertexFormat.UInt16:
|
||||||
|
case VertexFormat.SInt16:
|
||||||
|
return 2u;
|
||||||
|
case VertexFormat.UNorm8:
|
||||||
|
case VertexFormat.SNorm8:
|
||||||
|
case VertexFormat.UInt8:
|
||||||
|
case VertexFormat.SInt8:
|
||||||
|
return 1u;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsIntFormat(VertexFormat format)
|
||||||
|
{
|
||||||
|
return format >= VertexFormat.UInt8;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
|
||||||
|
{
|
||||||
|
var size = GetFormatSize(format);
|
||||||
|
var len = inputBytes.Length / size;
|
||||||
|
var result = new float[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
switch (format)
|
||||||
{
|
{
|
||||||
case 1:
|
case VertexFormat.Float:
|
||||||
value = inputBytes[i] / 255.0f;
|
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case VertexFormat.Float16:
|
||||||
value = Half.ToHalf(inputBytes, i * 2);
|
result[i] = Half.ToHalf(inputBytes, i * 2);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case VertexFormat.UNorm8:
|
||||||
value = BitConverter.ToSingle(inputBytes, i * 4);
|
result[i] = inputBytes[i] / 255f;
|
||||||
|
break;
|
||||||
|
case VertexFormat.SNorm8:
|
||||||
|
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
|
||||||
|
break;
|
||||||
|
case VertexFormat.UNorm16:
|
||||||
|
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
|
||||||
|
break;
|
||||||
|
case VertexFormat.SNorm16:
|
||||||
|
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result[i] = value;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int[] BytesToIntArray(byte[] inputBytes)
|
public static int[] BytesToIntArray(byte[] inputBytes, VertexFormat format)
|
||||||
{
|
{
|
||||||
var result = new int[inputBytes.Length / 4];
|
var size = GetFormatSize(format);
|
||||||
for (int i = 0; i < inputBytes.Length / 4; i++)
|
var len = inputBytes.Length / size;
|
||||||
|
var result = new int[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
|
switch (format)
|
||||||
|
{
|
||||||
|
case VertexFormat.UInt8:
|
||||||
|
case VertexFormat.SInt8:
|
||||||
|
result[i] = inputBytes[i];
|
||||||
|
break;
|
||||||
|
case VertexFormat.UInt16:
|
||||||
|
case VertexFormat.SInt16:
|
||||||
|
result[i] = BitConverter.ToInt16(inputBytes, i * 2);
|
||||||
|
break;
|
||||||
|
case VertexFormat.UInt32:
|
||||||
|
case VertexFormat.SInt32:
|
||||||
|
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace AssetStudio
|
|||||||
public sealed class MonoScript : NamedObject
|
public sealed class MonoScript : NamedObject
|
||||||
{
|
{
|
||||||
public string m_ClassName;
|
public string m_ClassName;
|
||||||
public string m_Namespace = string.Empty;
|
public string m_Namespace;
|
||||||
public string m_AssemblyName;
|
public string m_AssemblyName;
|
||||||
|
|
||||||
public MonoScript(ObjectReader reader) : base(reader)
|
public MonoScript(ObjectReader reader) : base(reader)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace AssetStudio
|
|||||||
var m_Loop = reader.ReadBoolean();
|
var m_Loop = reader.ReadBoolean();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
m_AudioClip = new PPtr<AudioClip>(reader);
|
m_AudioClip = new PPtr<AudioClip>(reader);
|
||||||
m_MovieData = reader.ReadBytes(reader.ReadInt32());
|
m_MovieData = reader.ReadUInt8Array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Specialized;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
@@ -36,19 +33,38 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool HasStructMember(string name)
|
|
||||||
{
|
|
||||||
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Dump()
|
public string Dump()
|
||||||
{
|
{
|
||||||
reader.Reset();
|
if (serializedType?.m_Type != null)
|
||||||
if (serializedType?.m_Nodes != null)
|
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
return TypeTreeHelper.ReadTypeString(serializedType.m_Type, reader);
|
||||||
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, reader);
|
}
|
||||||
return sb.ToString();
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace AssetStudio
|
|||||||
public PPtr(ObjectReader reader)
|
public PPtr(ObjectReader reader)
|
||||||
{
|
{
|
||||||
m_FileID = reader.ReadInt32();
|
m_FileID = reader.ReadInt32();
|
||||||
m_PathID = reader.m_Version < 14 ? reader.ReadInt32() : reader.ReadInt64();
|
m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
|
||||||
assetsFile = reader.assetsFile;
|
assetsFile = reader.assetsFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,10 +35,10 @@ namespace AssetStudio
|
|||||||
if (index == -2)
|
if (index == -2)
|
||||||
{
|
{
|
||||||
var m_External = assetsFile.m_Externals[m_FileID - 1];
|
var m_External = assetsFile.m_Externals[m_FileID - 1];
|
||||||
var name = m_External.fileName.ToUpper();
|
var name = m_External.fileName;
|
||||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
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);
|
assetsFileIndexCache.Add(name, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (TryGetAssetsFile(out var sourceFile))
|
if (TryGetAssetsFile(out var sourceFile))
|
||||||
{
|
{
|
||||||
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
|
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||||
{
|
{
|
||||||
if (obj is T variable)
|
if (obj is T variable)
|
||||||
{
|
{
|
||||||
@@ -75,7 +75,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (TryGetAssetsFile(out var sourceFile))
|
if (TryGetAssetsFile(out var sourceFile))
|
||||||
{
|
{
|
||||||
if (sourceFile.Objects.TryGetValue(m_PathID, out var obj))
|
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||||
{
|
{
|
||||||
if (obj is T2 variable)
|
if (obj is T2 variable)
|
||||||
{
|
{
|
||||||
@@ -91,8 +91,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public void Set(T m_Object)
|
public void Set(T m_Object)
|
||||||
{
|
{
|
||||||
var name = m_Object.assetsFile.upperFileName;
|
var name = m_Object.assetsFile.fileName;
|
||||||
if (string.Equals(assetsFile.upperFileName, name, StringComparison.Ordinal))
|
if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
m_FileID = 0;
|
m_FileID = 0;
|
||||||
}
|
}
|
||||||
@@ -119,13 +119,13 @@ namespace AssetStudio
|
|||||||
|
|
||||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
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);
|
assetsFileIndexCache.Add(name, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_PathID = m_Object.m_PathID;
|
m_PathID = m_Object.m_PathID;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsNull() => m_PathID == 0 || m_FileID < 0;
|
public bool IsNull => m_PathID == 0 || m_FileID < 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,13 +39,25 @@ namespace AssetStudio
|
|||||||
var m_Enabled = reader.ReadBoolean();
|
var m_Enabled = reader.ReadBoolean();
|
||||||
var m_CastShadows = reader.ReadByte();
|
var m_CastShadows = reader.ReadByte();
|
||||||
var m_ReceiveShadows = reader.ReadByte();
|
var m_ReceiveShadows = reader.ReadByte();
|
||||||
if (version[0] > 2017 || (version[0] == 2017 && version[0] >= 2)) //2017.2 and up
|
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||||
{
|
{
|
||||||
var m_DynamicOccludee = reader.ReadByte();
|
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_MotionVectors = reader.ReadByte();
|
||||||
var m_LightProbeUsage = reader.ReadByte();
|
var m_LightProbeUsage = reader.ReadByte();
|
||||||
var m_ReflectionProbeUsage = 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();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+370
-119
@@ -5,6 +5,16 @@ using System.Linq;
|
|||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
|
public class Hash128
|
||||||
|
{
|
||||||
|
public byte[] bytes;
|
||||||
|
|
||||||
|
public Hash128(BinaryReader reader)
|
||||||
|
{
|
||||||
|
bytes = reader.ReadBytes(16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class StructParameter
|
public class StructParameter
|
||||||
{
|
{
|
||||||
public MatrixParameter[] m_MatrixParams;
|
public MatrixParameter[] m_MatrixParams;
|
||||||
@@ -46,15 +56,14 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
public enum TextureDimension
|
public enum TextureDimension
|
||||||
{
|
{
|
||||||
kTexDimUnknown = -1,
|
Unknown = -1,
|
||||||
kTexDimNone = 0,
|
None = 0,
|
||||||
kTexDimAny = 1,
|
Any = 1,
|
||||||
kTexDim2D = 2,
|
Tex2D = 2,
|
||||||
kTexDim3D = 3,
|
Tex3D = 3,
|
||||||
kTexDimCUBE = 4,
|
Cube = 4,
|
||||||
kTexDim2DArray = 5,
|
Tex2DArray = 5,
|
||||||
kTexDimCubeArray = 6,
|
CubeArray = 6
|
||||||
kTexDimForce32Bit = 2147483647
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SerializedTextureProperty
|
public class SerializedTextureProperty
|
||||||
@@ -71,11 +80,12 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum SerializedPropertyType
|
public enum SerializedPropertyType
|
||||||
{
|
{
|
||||||
kColor = 0,
|
Color = 0,
|
||||||
kVector = 1,
|
Vector = 1,
|
||||||
kFloat = 2,
|
Float = 2,
|
||||||
kRange = 3,
|
Range = 3,
|
||||||
kTexture = 4
|
Texture = 4,
|
||||||
|
Int = 5
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SerializedProperty
|
public class SerializedProperty
|
||||||
@@ -185,11 +195,11 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum FogMode
|
public enum FogMode
|
||||||
{
|
{
|
||||||
kFogUnknown = -1,
|
Unknown = -1,
|
||||||
kFogDisabled = 0,
|
Disabled = 0,
|
||||||
kFogLinear = 1,
|
Linear = 1,
|
||||||
kFogExp = 2,
|
Exp = 2,
|
||||||
kFogExp2 = 3
|
Exp2 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SerializedShaderState
|
public class SerializedShaderState
|
||||||
@@ -201,6 +211,7 @@ namespace AssetStudio
|
|||||||
public SerializedShaderFloatValue zTest;
|
public SerializedShaderFloatValue zTest;
|
||||||
public SerializedShaderFloatValue zWrite;
|
public SerializedShaderFloatValue zWrite;
|
||||||
public SerializedShaderFloatValue culling;
|
public SerializedShaderFloatValue culling;
|
||||||
|
public SerializedShaderFloatValue conservative;
|
||||||
public SerializedShaderFloatValue offsetFactor;
|
public SerializedShaderFloatValue offsetFactor;
|
||||||
public SerializedShaderFloatValue offsetUnits;
|
public SerializedShaderFloatValue offsetUnits;
|
||||||
public SerializedShaderFloatValue alphaToMask;
|
public SerializedShaderFloatValue alphaToMask;
|
||||||
@@ -239,6 +250,10 @@ namespace AssetStudio
|
|||||||
zTest = new SerializedShaderFloatValue(reader);
|
zTest = new SerializedShaderFloatValue(reader);
|
||||||
zWrite = new SerializedShaderFloatValue(reader);
|
zWrite = new SerializedShaderFloatValue(reader);
|
||||||
culling = new SerializedShaderFloatValue(reader);
|
culling = new SerializedShaderFloatValue(reader);
|
||||||
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
|
{
|
||||||
|
conservative = new SerializedShaderFloatValue(reader);
|
||||||
|
}
|
||||||
offsetFactor = new SerializedShaderFloatValue(reader);
|
offsetFactor = new SerializedShaderFloatValue(reader);
|
||||||
offsetUnits = new SerializedShaderFloatValue(reader);
|
offsetUnits = new SerializedShaderFloatValue(reader);
|
||||||
alphaToMask = new SerializedShaderFloatValue(reader);
|
alphaToMask = new SerializedShaderFloatValue(reader);
|
||||||
@@ -357,11 +372,18 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public int m_NameIndex;
|
public int m_NameIndex;
|
||||||
public int m_Index;
|
public int m_Index;
|
||||||
|
public int m_ArraySize;
|
||||||
|
|
||||||
public BufferBinding(BinaryReader reader)
|
public BufferBinding(ObjectReader reader)
|
||||||
{
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
m_NameIndex = reader.ReadInt32();
|
m_NameIndex = reader.ReadInt32();
|
||||||
m_Index = reader.ReadInt32();
|
m_Index = reader.ReadInt32();
|
||||||
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
|
{
|
||||||
|
m_ArraySize = reader.ReadInt32();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +394,7 @@ namespace AssetStudio
|
|||||||
public VectorParameter[] m_VectorParams;
|
public VectorParameter[] m_VectorParams;
|
||||||
public StructParameter[] m_StructParams;
|
public StructParameter[] m_StructParams;
|
||||||
public int m_Size;
|
public int m_Size;
|
||||||
|
public bool m_IsPartialCB;
|
||||||
|
|
||||||
public ConstantBuffer(ObjectReader reader)
|
public ConstantBuffer(ObjectReader reader)
|
||||||
{
|
{
|
||||||
@@ -402,6 +425,16 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_Size = reader.ReadInt32();
|
m_Size = reader.ReadInt32();
|
||||||
|
|
||||||
|
if ((version[0] == 2020 && version[1] > 3) ||
|
||||||
|
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||||
|
(version[0] > 2021) ||
|
||||||
|
(version[0] == 2021 && version[1] > 1) ||
|
||||||
|
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||||
|
{
|
||||||
|
m_IsPartialCB = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,42 +454,43 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum ShaderGpuProgramType
|
public enum ShaderGpuProgramType
|
||||||
{
|
{
|
||||||
kShaderGpuProgramUnknown = 0,
|
Unknown = 0,
|
||||||
kShaderGpuProgramGLLegacy = 1,
|
GLLegacy = 1,
|
||||||
kShaderGpuProgramGLES31AEP = 2,
|
GLES31AEP = 2,
|
||||||
kShaderGpuProgramGLES31 = 3,
|
GLES31 = 3,
|
||||||
kShaderGpuProgramGLES3 = 4,
|
GLES3 = 4,
|
||||||
kShaderGpuProgramGLES = 5,
|
GLES = 5,
|
||||||
kShaderGpuProgramGLCore32 = 6,
|
GLCore32 = 6,
|
||||||
kShaderGpuProgramGLCore41 = 7,
|
GLCore41 = 7,
|
||||||
kShaderGpuProgramGLCore43 = 8,
|
GLCore43 = 8,
|
||||||
kShaderGpuProgramDX9VertexSM20 = 9,
|
DX9VertexSM20 = 9,
|
||||||
kShaderGpuProgramDX9VertexSM30 = 10,
|
DX9VertexSM30 = 10,
|
||||||
kShaderGpuProgramDX9PixelSM20 = 11,
|
DX9PixelSM20 = 11,
|
||||||
kShaderGpuProgramDX9PixelSM30 = 12,
|
DX9PixelSM30 = 12,
|
||||||
kShaderGpuProgramDX10Level9Vertex = 13,
|
DX10Level9Vertex = 13,
|
||||||
kShaderGpuProgramDX10Level9Pixel = 14,
|
DX10Level9Pixel = 14,
|
||||||
kShaderGpuProgramDX11VertexSM40 = 15,
|
DX11VertexSM40 = 15,
|
||||||
kShaderGpuProgramDX11VertexSM50 = 16,
|
DX11VertexSM50 = 16,
|
||||||
kShaderGpuProgramDX11PixelSM40 = 17,
|
DX11PixelSM40 = 17,
|
||||||
kShaderGpuProgramDX11PixelSM50 = 18,
|
DX11PixelSM50 = 18,
|
||||||
kShaderGpuProgramDX11GeometrySM40 = 19,
|
DX11GeometrySM40 = 19,
|
||||||
kShaderGpuProgramDX11GeometrySM50 = 20,
|
DX11GeometrySM50 = 20,
|
||||||
kShaderGpuProgramDX11HullSM50 = 21,
|
DX11HullSM50 = 21,
|
||||||
kShaderGpuProgramDX11DomainSM50 = 22,
|
DX11DomainSM50 = 22,
|
||||||
kShaderGpuProgramMetalVS = 23,
|
MetalVS = 23,
|
||||||
kShaderGpuProgramMetalFS = 24,
|
MetalFS = 24,
|
||||||
kShaderGpuProgramSPIRV = 25,
|
SPIRV = 25,
|
||||||
kShaderGpuProgramConsole = 26
|
ConsoleVS = 26,
|
||||||
|
ConsoleFS = 27,
|
||||||
|
ConsoleHS = 28,
|
||||||
|
ConsoleDS = 29,
|
||||||
|
ConsoleGS = 30,
|
||||||
|
RayTracing = 31,
|
||||||
|
PS5NGGC = 32
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SerializedSubProgram
|
public class SerializedProgramParameters
|
||||||
{
|
{
|
||||||
public uint m_BlobIndex;
|
|
||||||
public ParserBindChannels m_Channels;
|
|
||||||
public ushort[] m_KeywordIndices;
|
|
||||||
public sbyte m_ShaderHardwareTier;
|
|
||||||
public ShaderGpuProgramType m_GpuProgramType;
|
|
||||||
public VectorParameter[] m_VectorParams;
|
public VectorParameter[] m_VectorParams;
|
||||||
public MatrixParameter[] m_MatrixParams;
|
public MatrixParameter[] m_MatrixParams;
|
||||||
public TextureParameter[] m_TextureParams;
|
public TextureParameter[] m_TextureParams;
|
||||||
@@ -466,33 +500,8 @@ namespace AssetStudio
|
|||||||
public UAVParameter[] m_UAVParams;
|
public UAVParameter[] m_UAVParams;
|
||||||
public SamplerParameter[] m_Samplers;
|
public SamplerParameter[] m_Samplers;
|
||||||
|
|
||||||
public SerializedSubProgram(ObjectReader reader)
|
public SerializedProgramParameters(ObjectReader reader)
|
||||||
{
|
{
|
||||||
var version = reader.version;
|
|
||||||
|
|
||||||
m_BlobIndex = reader.ReadUInt32();
|
|
||||||
m_Channels = new ParserBindChannels(reader);
|
|
||||||
|
|
||||||
if (version[0] >= 2019) //2019 and up
|
|
||||||
{
|
|
||||||
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
|
||||||
reader.AlignStream();
|
|
||||||
var m_LocalKeywordIndices = reader.ReadUInt16Array();
|
|
||||||
reader.AlignStream();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_KeywordIndices = reader.ReadUInt16Array();
|
|
||||||
if (version[0] >= 2017) //2017 and up
|
|
||||||
{
|
|
||||||
reader.AlignStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_ShaderHardwareTier = reader.ReadSByte();
|
|
||||||
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
|
||||||
reader.AlignStream();
|
|
||||||
|
|
||||||
int numVectorParams = reader.ReadInt32();
|
int numVectorParams = reader.ReadInt32();
|
||||||
m_VectorParams = new VectorParameter[numVectorParams];
|
m_VectorParams = new VectorParameter[numVectorParams];
|
||||||
for (int i = 0; i < numVectorParams; i++)
|
for (int i = 0; i < numVectorParams; i++)
|
||||||
@@ -542,18 +551,139 @@ namespace AssetStudio
|
|||||||
m_UAVParams[i] = new UAVParameter(reader);
|
m_UAVParams[i] = new UAVParameter(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version[0] >= 2017) //2017 and up
|
int numSamplers = reader.ReadInt32();
|
||||||
|
m_Samplers = new SamplerParameter[numSamplers];
|
||||||
|
for (int i = 0; i < numSamplers; i++)
|
||||||
{
|
{
|
||||||
int numSamplers = reader.ReadInt32();
|
m_Samplers[i] = new SamplerParameter(reader);
|
||||||
m_Samplers = new SamplerParameter[numSamplers];
|
}
|
||||||
for (int i = 0; i < numSamplers; i++)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SerializedSubProgram
|
||||||
|
{
|
||||||
|
public uint m_BlobIndex;
|
||||||
|
public ParserBindChannels m_Channels;
|
||||||
|
public ushort[] m_KeywordIndices;
|
||||||
|
public sbyte m_ShaderHardwareTier;
|
||||||
|
public ShaderGpuProgramType m_GpuProgramType;
|
||||||
|
public SerializedProgramParameters m_Parameters;
|
||||||
|
public VectorParameter[] m_VectorParams;
|
||||||
|
public MatrixParameter[] m_MatrixParams;
|
||||||
|
public TextureParameter[] m_TextureParams;
|
||||||
|
public BufferBinding[] m_BufferParams;
|
||||||
|
public ConstantBuffer[] m_ConstantBuffers;
|
||||||
|
public BufferBinding[] m_ConstantBufferBindings;
|
||||||
|
public UAVParameter[] m_UAVParams;
|
||||||
|
public SamplerParameter[] m_Samplers;
|
||||||
|
|
||||||
|
public SerializedSubProgram(ObjectReader reader)
|
||||||
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
|
m_BlobIndex = reader.ReadUInt32();
|
||||||
|
m_Channels = new ParserBindChannels(reader);
|
||||||
|
|
||||||
|
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
|
||||||
|
{
|
||||||
|
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
var m_LocalKeywordIndices = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_KeywordIndices = reader.ReadUInt16Array();
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
{
|
{
|
||||||
m_Samplers[i] = new SamplerParameter(reader);
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ShaderHardwareTier = reader.ReadSByte();
|
||||||
|
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
if ((version[0] == 2020 && version[1] > 3) ||
|
||||||
|
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||||
|
(version[0] > 2021) ||
|
||||||
|
(version[0] == 2021 && version[1] > 1) ||
|
||||||
|
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||||
|
{
|
||||||
|
m_Parameters = new SerializedProgramParameters(reader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int numVectorParams = reader.ReadInt32();
|
||||||
|
m_VectorParams = new VectorParameter[numVectorParams];
|
||||||
|
for (int i = 0; i < numVectorParams; i++)
|
||||||
|
{
|
||||||
|
m_VectorParams[i] = new VectorParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numMatrixParams = reader.ReadInt32();
|
||||||
|
m_MatrixParams = new MatrixParameter[numMatrixParams];
|
||||||
|
for (int i = 0; i < numMatrixParams; i++)
|
||||||
|
{
|
||||||
|
m_MatrixParams[i] = new MatrixParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numTextureParams = reader.ReadInt32();
|
||||||
|
m_TextureParams = new TextureParameter[numTextureParams];
|
||||||
|
for (int i = 0; i < numTextureParams; i++)
|
||||||
|
{
|
||||||
|
m_TextureParams[i] = new TextureParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numBufferParams = reader.ReadInt32();
|
||||||
|
m_BufferParams = new BufferBinding[numBufferParams];
|
||||||
|
for (int i = 0; i < numBufferParams; i++)
|
||||||
|
{
|
||||||
|
m_BufferParams[i] = new BufferBinding(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numConstantBuffers = reader.ReadInt32();
|
||||||
|
m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];
|
||||||
|
for (int i = 0; i < numConstantBuffers; i++)
|
||||||
|
{
|
||||||
|
m_ConstantBuffers[i] = new ConstantBuffer(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numConstantBufferBindings = reader.ReadInt32();
|
||||||
|
m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];
|
||||||
|
for (int i = 0; i < numConstantBufferBindings; i++)
|
||||||
|
{
|
||||||
|
m_ConstantBufferBindings[i] = new BufferBinding(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
int numUAVParams = reader.ReadInt32();
|
||||||
|
m_UAVParams = new UAVParameter[numUAVParams];
|
||||||
|
for (int i = 0; i < numUAVParams; i++)
|
||||||
|
{
|
||||||
|
m_UAVParams[i] = new UAVParameter(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2017) //2017 and up
|
||||||
|
{
|
||||||
|
int numSamplers = reader.ReadInt32();
|
||||||
|
m_Samplers = new SamplerParameter[numSamplers];
|
||||||
|
for (int i = 0; i < numSamplers; i++)
|
||||||
|
{
|
||||||
|
m_Samplers[i] = new SamplerParameter(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||||
{
|
{
|
||||||
var m_ShaderRequirements = reader.ReadInt32();
|
if (version[0] >= 2021) //2021.1 and up
|
||||||
|
{
|
||||||
|
var m_ShaderRequirements = reader.ReadInt64();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var m_ShaderRequirements = reader.ReadInt32();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -561,27 +691,50 @@ namespace AssetStudio
|
|||||||
public class SerializedProgram
|
public class SerializedProgram
|
||||||
{
|
{
|
||||||
public SerializedSubProgram[] m_SubPrograms;
|
public SerializedSubProgram[] m_SubPrograms;
|
||||||
|
public SerializedProgramParameters m_CommonParameters;
|
||||||
|
public ushort[] m_SerializedKeywordStateMask;
|
||||||
|
|
||||||
public SerializedProgram(ObjectReader reader)
|
public SerializedProgram(ObjectReader reader)
|
||||||
{
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
int numSubPrograms = reader.ReadInt32();
|
int numSubPrograms = reader.ReadInt32();
|
||||||
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
|
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
|
||||||
for (int i = 0; i < numSubPrograms; i++)
|
for (int i = 0; i < numSubPrograms; i++)
|
||||||
{
|
{
|
||||||
m_SubPrograms[i] = new SerializedSubProgram(reader);
|
m_SubPrograms[i] = new SerializedSubProgram(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((version[0] == 2020 && version[1] > 3) ||
|
||||||
|
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||||
|
(version[0] > 2021) ||
|
||||||
|
(version[0] == 2021 && version[1] > 1) ||
|
||||||
|
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||||
|
{
|
||||||
|
m_CommonParameters = new SerializedProgramParameters(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||||
|
{
|
||||||
|
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PassType
|
public enum PassType
|
||||||
{
|
{
|
||||||
kPassTypeNormal = 0,
|
Normal = 0,
|
||||||
kPassTypeUse = 1,
|
Use = 1,
|
||||||
kPassTypeGrab = 2
|
Grab = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SerializedPass
|
public class SerializedPass
|
||||||
{
|
{
|
||||||
|
public Hash128[] m_EditorDataHash;
|
||||||
|
public byte[] m_Platforms;
|
||||||
|
public ushort[] m_LocalKeywordMask;
|
||||||
|
public ushort[] m_GlobalKeywordMask;
|
||||||
public KeyValuePair<string, int>[] m_NameIndices;
|
public KeyValuePair<string, int>[] m_NameIndices;
|
||||||
public PassType m_Type;
|
public PassType m_Type;
|
||||||
public SerializedShaderState m_State;
|
public SerializedShaderState m_State;
|
||||||
@@ -591,16 +744,38 @@ namespace AssetStudio
|
|||||||
public SerializedProgram progGeometry;
|
public SerializedProgram progGeometry;
|
||||||
public SerializedProgram progHull;
|
public SerializedProgram progHull;
|
||||||
public SerializedProgram progDomain;
|
public SerializedProgram progDomain;
|
||||||
|
public SerializedProgram progRayTracing;
|
||||||
public bool m_HasInstancingVariant;
|
public bool m_HasInstancingVariant;
|
||||||
public string m_UseName;
|
public string m_UseName;
|
||||||
public string m_Name;
|
public string m_Name;
|
||||||
public string m_TextureName;
|
public string m_TextureName;
|
||||||
public SerializedTagMap m_Tags;
|
public SerializedTagMap m_Tags;
|
||||||
|
public ushort[] m_SerializedKeywordStateMask;
|
||||||
|
|
||||||
public SerializedPass(ObjectReader reader)
|
public SerializedPass(ObjectReader reader)
|
||||||
{
|
{
|
||||||
var version = reader.version;
|
var version = reader.version;
|
||||||
|
|
||||||
|
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||||
|
{
|
||||||
|
int numEditorDataHash = reader.ReadInt32();
|
||||||
|
m_EditorDataHash = new Hash128[numEditorDataHash];
|
||||||
|
for (int i = 0; i < numEditorDataHash; i++)
|
||||||
|
{
|
||||||
|
m_EditorDataHash[i] = new Hash128(reader);
|
||||||
|
}
|
||||||
|
reader.AlignStream();
|
||||||
|
m_Platforms = reader.ReadUInt8Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
|
||||||
|
{
|
||||||
|
m_LocalKeywordMask = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
m_GlobalKeywordMask = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int numIndices = reader.ReadInt32();
|
int numIndices = reader.ReadInt32();
|
||||||
m_NameIndices = new KeyValuePair<string, int>[numIndices];
|
m_NameIndices = new KeyValuePair<string, int>[numIndices];
|
||||||
for (int i = 0; i < numIndices; i++)
|
for (int i = 0; i < numIndices; i++)
|
||||||
@@ -616,6 +791,10 @@ namespace AssetStudio
|
|||||||
progGeometry = new SerializedProgram(reader);
|
progGeometry = new SerializedProgram(reader);
|
||||||
progHull = new SerializedProgram(reader);
|
progHull = new SerializedProgram(reader);
|
||||||
progDomain = new SerializedProgram(reader);
|
progDomain = new SerializedProgram(reader);
|
||||||
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
|
{
|
||||||
|
progRayTracing = new SerializedProgram(reader);
|
||||||
|
}
|
||||||
m_HasInstancingVariant = reader.ReadBoolean();
|
m_HasInstancingVariant = reader.ReadBoolean();
|
||||||
if (version[0] >= 2018) //2018 and up
|
if (version[0] >= 2018) //2018 and up
|
||||||
{
|
{
|
||||||
@@ -626,6 +805,11 @@ namespace AssetStudio
|
|||||||
m_Name = reader.ReadAlignedString();
|
m_Name = reader.ReadAlignedString();
|
||||||
m_TextureName = reader.ReadAlignedString();
|
m_TextureName = reader.ReadAlignedString();
|
||||||
m_Tags = new SerializedTagMap(reader);
|
m_Tags = new SerializedTagMap(reader);
|
||||||
|
if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
|
||||||
|
{
|
||||||
|
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,18 +860,35 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class SerializedCustomEditorForRenderPipeline
|
||||||
|
{
|
||||||
|
public string customEditorName;
|
||||||
|
public string renderPipelineType;
|
||||||
|
|
||||||
|
public SerializedCustomEditorForRenderPipeline(BinaryReader reader)
|
||||||
|
{
|
||||||
|
customEditorName = reader.ReadAlignedString();
|
||||||
|
renderPipelineType = reader.ReadAlignedString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class SerializedShader
|
public class SerializedShader
|
||||||
{
|
{
|
||||||
public SerializedProperties m_PropInfo;
|
public SerializedProperties m_PropInfo;
|
||||||
public SerializedSubShader[] m_SubShaders;
|
public SerializedSubShader[] m_SubShaders;
|
||||||
|
public string[] m_KeywordNames;
|
||||||
|
public byte[] m_KeywordFlags;
|
||||||
public string m_Name;
|
public string m_Name;
|
||||||
public string m_CustomEditorName;
|
public string m_CustomEditorName;
|
||||||
public string m_FallbackName;
|
public string m_FallbackName;
|
||||||
public SerializedShaderDependency[] m_Dependencies;
|
public SerializedShaderDependency[] m_Dependencies;
|
||||||
|
public SerializedCustomEditorForRenderPipeline[] m_CustomEditorForRenderPipelines;
|
||||||
public bool m_DisableNoSubshadersMessage;
|
public bool m_DisableNoSubshadersMessage;
|
||||||
|
|
||||||
public SerializedShader(ObjectReader reader)
|
public SerializedShader(ObjectReader reader)
|
||||||
{
|
{
|
||||||
|
var version = reader.version;
|
||||||
|
|
||||||
m_PropInfo = new SerializedProperties(reader);
|
m_PropInfo = new SerializedProperties(reader);
|
||||||
|
|
||||||
int numSubShaders = reader.ReadInt32();
|
int numSubShaders = reader.ReadInt32();
|
||||||
@@ -697,6 +898,13 @@ namespace AssetStudio
|
|||||||
m_SubShaders[i] = new SerializedSubShader(reader);
|
m_SubShaders[i] = new SerializedSubShader(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
|
||||||
|
{
|
||||||
|
m_KeywordNames = reader.ReadStringArray();
|
||||||
|
m_KeywordFlags = reader.ReadUInt8Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
}
|
||||||
|
|
||||||
m_Name = reader.ReadAlignedString();
|
m_Name = reader.ReadAlignedString();
|
||||||
m_CustomEditorName = reader.ReadAlignedString();
|
m_CustomEditorName = reader.ReadAlignedString();
|
||||||
m_FallbackName = reader.ReadAlignedString();
|
m_FallbackName = reader.ReadAlignedString();
|
||||||
@@ -708,6 +916,16 @@ namespace AssetStudio
|
|||||||
m_Dependencies[i] = new SerializedShaderDependency(reader);
|
m_Dependencies[i] = new SerializedShaderDependency(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2021) //2021.1 and up
|
||||||
|
{
|
||||||
|
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
|
||||||
|
m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];
|
||||||
|
for (int i = 0; i < m_CustomEditorForRenderPipelinesSize; i++)
|
||||||
|
{
|
||||||
|
m_CustomEditorForRenderPipelines[i] = new SerializedCustomEditorForRenderPipeline(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_DisableNoSubshadersMessage = reader.ReadBoolean();
|
m_DisableNoSubshadersMessage = reader.ReadBoolean();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
@@ -715,28 +933,32 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum ShaderCompilerPlatform
|
public enum ShaderCompilerPlatform
|
||||||
{
|
{
|
||||||
kShaderCompPlatformNone = -1,
|
None = -1,
|
||||||
kShaderCompPlatformGL = 0,
|
GL = 0,
|
||||||
kShaderCompPlatformD3D9 = 1,
|
D3D9 = 1,
|
||||||
kShaderCompPlatformXbox360 = 2,
|
Xbox360 = 2,
|
||||||
kShaderCompPlatformPS3 = 3,
|
PS3 = 3,
|
||||||
kShaderCompPlatformD3D11 = 4,
|
D3D11 = 4,
|
||||||
kShaderCompPlatformGLES20 = 5,
|
GLES20 = 5,
|
||||||
kShaderCompPlatformNaCl = 6,
|
NaCl = 6,
|
||||||
kShaderCompPlatformFlash = 7,
|
Flash = 7,
|
||||||
kShaderCompPlatformD3D11_9x = 8,
|
D3D11_9x = 8,
|
||||||
kShaderCompPlatformGLES3Plus = 9,
|
GLES3Plus = 9,
|
||||||
kShaderCompPlatformPSP2 = 10,
|
PSP2 = 10,
|
||||||
kShaderCompPlatformPS4 = 11,
|
PS4 = 11,
|
||||||
kShaderCompPlatformXboxOne = 12,
|
XboxOne = 12,
|
||||||
kShaderCompPlatformPSM = 13,
|
PSM = 13,
|
||||||
kShaderCompPlatformMetal = 14,
|
Metal = 14,
|
||||||
kShaderCompPlatformOpenGLCore = 15,
|
OpenGLCore = 15,
|
||||||
kShaderCompPlatformN3DS = 16,
|
N3DS = 16,
|
||||||
kShaderCompPlatformWiiU = 17,
|
WiiU = 17,
|
||||||
kShaderCompPlatformVulkan = 18,
|
Vulkan = 18,
|
||||||
kShaderCompPlatformSwitch = 19,
|
Switch = 19,
|
||||||
kShaderCompPlatformXboxOneD3D12 = 20
|
XboxOneD3D12 = 20,
|
||||||
|
GameCoreXboxOne = 21,
|
||||||
|
GameCoreScarlett = 22,
|
||||||
|
PS5 = 23,
|
||||||
|
PS5NGGC = 24
|
||||||
};
|
};
|
||||||
|
|
||||||
public class Shader : NamedObject
|
public class Shader : NamedObject
|
||||||
@@ -748,9 +970,9 @@ namespace AssetStudio
|
|||||||
//5.5 and up
|
//5.5 and up
|
||||||
public SerializedShader m_ParsedForm;
|
public SerializedShader m_ParsedForm;
|
||||||
public ShaderCompilerPlatform[] platforms;
|
public ShaderCompilerPlatform[] platforms;
|
||||||
public uint[] offsets;
|
public uint[][] offsets;
|
||||||
public uint[] compressedLengths;
|
public uint[][] compressedLengths;
|
||||||
public uint[] decompressedLengths;
|
public uint[][] decompressedLengths;
|
||||||
public byte[] compressedBlob;
|
public byte[] compressedBlob;
|
||||||
|
|
||||||
public Shader(ObjectReader reader) : base(reader)
|
public Shader(ObjectReader reader) : base(reader)
|
||||||
@@ -759,20 +981,49 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
m_ParsedForm = new SerializedShader(reader);
|
m_ParsedForm = new SerializedShader(reader);
|
||||||
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
||||||
offsets = reader.ReadUInt32Array();
|
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||||
compressedLengths = reader.ReadUInt32Array();
|
{
|
||||||
decompressedLengths = reader.ReadUInt32Array();
|
offsets = reader.ReadUInt32ArrayArray();
|
||||||
compressedBlob = reader.ReadBytes(reader.ReadInt32());
|
compressedLengths = reader.ReadUInt32ArrayArray();
|
||||||
|
decompressedLengths = reader.ReadUInt32ArrayArray();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||||
|
compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||||
|
decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||||
|
}
|
||||||
|
compressedBlob = reader.ReadUInt8Array();
|
||||||
|
reader.AlignStream();
|
||||||
|
|
||||||
|
var m_DependenciesCount = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < m_DependenciesCount; i++)
|
||||||
|
{
|
||||||
|
new PPtr<Shader>(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version[0] >= 2018)
|
||||||
|
{
|
||||||
|
var m_NonModifiableTexturesCount = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < m_NonModifiableTexturesCount; i++)
|
||||||
|
{
|
||||||
|
var first = reader.ReadAlignedString();
|
||||||
|
new PPtr<Texture>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var m_ShaderIsBaked = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
m_Script = reader.ReadUInt8Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
var m_PathName = reader.ReadAlignedString();
|
var m_PathName = reader.ReadAlignedString();
|
||||||
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
|
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
|
||||||
{
|
{
|
||||||
decompressedSize = reader.ReadUInt32();
|
decompressedSize = reader.ReadUInt32();
|
||||||
m_SubProgramBlob = reader.ReadBytes(reader.ReadInt32());
|
m_SubProgramBlob = reader.ReadUInt8Array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
@@ -19,17 +18,23 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public enum SpritePackingRotation
|
public enum SpritePackingRotation
|
||||||
{
|
{
|
||||||
kSPRNone = 0,
|
None = 0,
|
||||||
kSPRFlipHorizontal = 1,
|
FlipHorizontal = 1,
|
||||||
kSPRFlipVertical = 2,
|
FlipVertical = 2,
|
||||||
kSPRRotate180 = 3,
|
Rotate180 = 3,
|
||||||
kSPRRotate90 = 4
|
Rotate90 = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
public enum SpritePackingMode
|
public enum SpritePackingMode
|
||||||
{
|
{
|
||||||
kSPMTight = 0,
|
Tight = 0,
|
||||||
kSPMRectangle
|
Rectangle
|
||||||
|
};
|
||||||
|
|
||||||
|
public enum SpriteMeshType
|
||||||
|
{
|
||||||
|
FullRect,
|
||||||
|
Tight
|
||||||
};
|
};
|
||||||
|
|
||||||
public class SpriteSettings
|
public class SpriteSettings
|
||||||
@@ -39,6 +44,7 @@ namespace AssetStudio
|
|||||||
public uint packed;
|
public uint packed;
|
||||||
public SpritePackingMode packingMode;
|
public SpritePackingMode packingMode;
|
||||||
public SpritePackingRotation packingRotation;
|
public SpritePackingRotation packingRotation;
|
||||||
|
public SpriteMeshType meshType;
|
||||||
|
|
||||||
public SpriteSettings(BinaryReader reader)
|
public SpriteSettings(BinaryReader reader)
|
||||||
{
|
{
|
||||||
@@ -47,8 +53,7 @@ namespace AssetStudio
|
|||||||
packed = settingsRaw & 1; //1
|
packed = settingsRaw & 1; //1
|
||||||
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
|
packingMode = (SpritePackingMode)((settingsRaw >> 1) & 1); //1
|
||||||
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
|
packingRotation = (SpritePackingRotation)((settingsRaw >> 2) & 0xf); //4
|
||||||
|
meshType = (SpriteMeshType)((settingsRaw >> 6) & 1); //1
|
||||||
//meshType = (settingsRaw >> 6) & 1; //1
|
|
||||||
//reserved
|
//reserved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,7 +87,7 @@ namespace AssetStudio
|
|||||||
public ushort[] indices;
|
public ushort[] indices;
|
||||||
public Matrix4x4[] m_Bindpose;
|
public Matrix4x4[] m_Bindpose;
|
||||||
public BoneWeights4[] m_SourceSkin;
|
public BoneWeights4[] m_SourceSkin;
|
||||||
public RectangleF textureRect;
|
public Rectf textureRect;
|
||||||
public Vector2 textureRectOffset;
|
public Vector2 textureRectOffset;
|
||||||
public Vector2 atlasRectOffset;
|
public Vector2 atlasRectOffset;
|
||||||
public SpriteSettings settingsRaw;
|
public SpriteSettings settingsRaw;
|
||||||
@@ -118,7 +123,7 @@ namespace AssetStudio
|
|||||||
m_SubMeshes[i] = new SubMesh(reader);
|
m_SubMeshes[i] = new SubMesh(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IndexBuffer = reader.ReadBytes(reader.ReadInt32());
|
m_IndexBuffer = reader.ReadUInt8Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
|
|
||||||
m_VertexData = new VertexData(reader);
|
m_VertexData = new VertexData(reader);
|
||||||
@@ -150,7 +155,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textureRect = reader.ReadRectangleF();
|
textureRect = new Rectf(reader);
|
||||||
textureRectOffset = reader.ReadVector2();
|
textureRectOffset = reader.ReadVector2();
|
||||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
{
|
{
|
||||||
@@ -170,13 +175,29 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 sealed class Sprite : NamedObject
|
||||||
{
|
{
|
||||||
public RectangleF m_Rect;
|
public Rectf m_Rect;
|
||||||
public Vector2 m_Offset;
|
public Vector2 m_Offset;
|
||||||
public Vector4 m_Border;
|
public Vector4 m_Border;
|
||||||
public float m_PixelsToUnits;
|
public float m_PixelsToUnits;
|
||||||
public Vector2 m_Pivot;
|
public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
|
||||||
public uint m_Extrude;
|
public uint m_Extrude;
|
||||||
public bool m_IsPolygon;
|
public bool m_IsPolygon;
|
||||||
public KeyValuePair<Guid, long> m_RenderDataKey;
|
public KeyValuePair<Guid, long> m_RenderDataKey;
|
||||||
@@ -187,7 +208,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public Sprite(ObjectReader reader) : base(reader)
|
public Sprite(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
m_Rect = reader.ReadRectangleF();
|
m_Rect = new Rectf(reader);
|
||||||
m_Offset = reader.ReadVector2();
|
m_Offset = reader.ReadVector2();
|
||||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,19 +7,20 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public PPtr<Texture2D> texture;
|
public PPtr<Texture2D> texture;
|
||||||
public PPtr<Texture2D> alphaTexture;
|
public PPtr<Texture2D> alphaTexture;
|
||||||
public System.Drawing.RectangleF textureRect;
|
public Rectf textureRect;
|
||||||
public Vector2 textureRectOffset;
|
public Vector2 textureRectOffset;
|
||||||
public Vector2 atlasRectOffset;
|
public Vector2 atlasRectOffset;
|
||||||
public Vector4 uvTransform;
|
public Vector4 uvTransform;
|
||||||
public float downscaleMultiplier;
|
public float downscaleMultiplier;
|
||||||
public SpriteSettings settingsRaw;
|
public SpriteSettings settingsRaw;
|
||||||
|
public SecondarySpriteTexture[] secondaryTextures;
|
||||||
|
|
||||||
public SpriteAtlasData(ObjectReader reader)
|
public SpriteAtlasData(ObjectReader reader)
|
||||||
{
|
{
|
||||||
var version = reader.version;
|
var version = reader.version;
|
||||||
texture = new PPtr<Texture2D>(reader);
|
texture = new PPtr<Texture2D>(reader);
|
||||||
alphaTexture = new PPtr<Texture2D>(reader);
|
alphaTexture = new PPtr<Texture2D>(reader);
|
||||||
textureRect = reader.ReadRectangleF();
|
textureRect = new Rectf(reader);
|
||||||
textureRectOffset = reader.ReadVector2();
|
textureRectOffset = reader.ReadVector2();
|
||||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||||
{
|
{
|
||||||
@@ -28,6 +29,16 @@ namespace AssetStudio
|
|||||||
uvTransform = reader.ReadVector4();
|
uvTransform = reader.ReadVector4();
|
||||||
downscaleMultiplier = reader.ReadSingle();
|
downscaleMultiplier = reader.ReadSingle();
|
||||||
settingsRaw = new SpriteSettings(reader);
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +46,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public PPtr<Sprite>[] m_PackedSprites;
|
public PPtr<Sprite>[] m_PackedSprites;
|
||||||
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
|
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
|
||||||
|
public bool m_IsVariant;
|
||||||
|
|
||||||
public SpriteAtlas(ObjectReader reader) : base(reader)
|
public SpriteAtlas(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
@@ -56,8 +68,9 @@ namespace AssetStudio
|
|||||||
var value = new SpriteAtlasData(reader);
|
var value = new SpriteAtlasData(reader);
|
||||||
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
|
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
|
||||||
}
|
}
|
||||||
//string m_Tag
|
var m_Tag = reader.ReadAlignedString();
|
||||||
//bool m_IsVariant
|
m_IsVariant = reader.ReadBoolean();
|
||||||
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public TextAsset(ObjectReader reader) : base(reader)
|
public TextAsset(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
m_Script = reader.ReadBytes(reader.ReadInt32());
|
m_Script = reader.ReadUInt8Array();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
var m_ForcedFallbackFormat = reader.ReadInt32();
|
var m_ForcedFallbackFormat = reader.ReadInt32();
|
||||||
var m_DownscaleFallback = reader.ReadBoolean();
|
var m_DownscaleFallback = reader.ReadBoolean();
|
||||||
|
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||||
|
{
|
||||||
|
var m_IsAlphaChannelOptional = reader.ReadBoolean();
|
||||||
|
}
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
|
||||||
using System.Drawing.Imaging;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class StreamingInfo
|
public class StreamingInfo
|
||||||
{
|
{
|
||||||
public uint offset;
|
public long offset; //ulong
|
||||||
public uint size;
|
public uint size;
|
||||||
public string path;
|
public string path;
|
||||||
|
|
||||||
public StreamingInfo(ObjectReader reader)
|
public StreamingInfo(ObjectReader reader)
|
||||||
{
|
{
|
||||||
offset = reader.ReadUInt32();
|
var version = reader.version;
|
||||||
|
|
||||||
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
|
{
|
||||||
|
offset = reader.ReadInt64();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
offset = reader.ReadUInt32();
|
||||||
|
}
|
||||||
size = reader.ReadUInt32();
|
size = reader.ReadUInt32();
|
||||||
path = reader.ReadAlignedString();
|
path = reader.ReadAlignedString();
|
||||||
}
|
}
|
||||||
@@ -56,7 +60,7 @@ namespace AssetStudio
|
|||||||
public bool m_MipMap;
|
public bool m_MipMap;
|
||||||
public int m_MipCount;
|
public int m_MipCount;
|
||||||
public GLTextureSettings m_TextureSettings;
|
public GLTextureSettings m_TextureSettings;
|
||||||
public Lazy<byte[]> image_data;
|
public ResourceReader image_data;
|
||||||
public StreamingInfo m_StreamData;
|
public StreamingInfo m_StreamData;
|
||||||
|
|
||||||
public Texture2D(ObjectReader reader) : base(reader)
|
public Texture2D(ObjectReader reader) : base(reader)
|
||||||
@@ -64,6 +68,10 @@ namespace AssetStudio
|
|||||||
m_Width = reader.ReadInt32();
|
m_Width = reader.ReadInt32();
|
||||||
m_Height = reader.ReadInt32();
|
m_Height = reader.ReadInt32();
|
||||||
var m_CompleteImageSize = reader.ReadInt32();
|
var m_CompleteImageSize = reader.ReadInt32();
|
||||||
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
|
{
|
||||||
|
var m_MipsStripped = reader.ReadInt32();
|
||||||
|
}
|
||||||
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
||||||
{
|
{
|
||||||
@@ -73,9 +81,29 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
m_MipCount = reader.ReadInt32();
|
m_MipCount = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
var m_IsReadable = reader.ReadBoolean(); //2.6.0 and up
|
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
|
||||||
var m_ReadAllowed = reader.ReadBoolean(); //3.0.0 - 5.4
|
{
|
||||||
//bool m_StreamingMipmaps 2018.2 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))
|
||||||
|
{
|
||||||
|
var m_ReadAllowed = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||||
|
{
|
||||||
|
var m_StreamingMipmaps = reader.ReadBoolean();
|
||||||
|
}
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||||
{
|
{
|
||||||
@@ -92,6 +120,11 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
var m_ColorSpace = reader.ReadInt32();
|
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();
|
var image_data_size = reader.ReadInt32();
|
||||||
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
||||||
{
|
{
|
||||||
@@ -101,13 +134,13 @@ namespace AssetStudio
|
|||||||
ResourceReader resourceReader;
|
ResourceReader resourceReader;
|
||||||
if (!string.IsNullOrEmpty(m_StreamData?.path))
|
if (!string.IsNullOrEmpty(m_StreamData?.path))
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size);
|
resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
|
||||||
}
|
}
|
||||||
image_data = new Lazy<byte[]>(resourceReader.GetData);
|
image_data = resourceReader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,10 +151,13 @@ namespace AssetStudio
|
|||||||
RGB24,
|
RGB24,
|
||||||
RGBA32,
|
RGBA32,
|
||||||
ARGB32,
|
ARGB32,
|
||||||
RGB565 = 7,
|
ARGBFloat,
|
||||||
R16 = 9,
|
RGB565,
|
||||||
|
BGR24,
|
||||||
|
R16,
|
||||||
DXT1,
|
DXT1,
|
||||||
DXT5 = 12,
|
DXT3,
|
||||||
|
DXT5,
|
||||||
RGBA4444,
|
RGBA4444,
|
||||||
BGRA32,
|
BGRA32,
|
||||||
RHalf,
|
RHalf,
|
||||||
@@ -132,11 +168,12 @@ namespace AssetStudio
|
|||||||
RGBAFloat,
|
RGBAFloat,
|
||||||
YUY2,
|
YUY2,
|
||||||
RGB9e5Float,
|
RGB9e5Float,
|
||||||
BC4 = 26,
|
RGBFloat,
|
||||||
BC5,
|
BC6H,
|
||||||
BC6H = 24,
|
|
||||||
BC7,
|
BC7,
|
||||||
DXT1Crunched = 28,
|
BC4,
|
||||||
|
BC5,
|
||||||
|
DXT1Crunched,
|
||||||
DXT5Crunched,
|
DXT5Crunched,
|
||||||
PVRTC_RGB2,
|
PVRTC_RGB2,
|
||||||
PVRTC_RGBA2,
|
PVRTC_RGBA2,
|
||||||
@@ -170,5 +207,14 @@ namespace AssetStudio
|
|||||||
R8,
|
R8,
|
||||||
ETC_RGB4Crunched,
|
ETC_RGB4Crunched,
|
||||||
ETC2_RGBA8Crunched,
|
ETC2_RGBA8Crunched,
|
||||||
|
ASTC_HDR_4x4,
|
||||||
|
ASTC_HDR_5x5,
|
||||||
|
ASTC_HDR_6x6,
|
||||||
|
ASTC_HDR_8x8,
|
||||||
|
ASTC_HDR_10x10,
|
||||||
|
ASTC_HDR_12x12,
|
||||||
|
RG32,
|
||||||
|
RGB48,
|
||||||
|
RGBA64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,26 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
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 sealed class VideoClip : NamedObject
|
||||||
{
|
{
|
||||||
public Lazy<byte[]> m_VideoData;
|
public ResourceReader m_VideoData;
|
||||||
public string m_OriginalPath;
|
public string m_OriginalPath;
|
||||||
public string m_Source;
|
public StreamedResource m_ExternalResources;
|
||||||
public ulong m_Size;
|
|
||||||
|
|
||||||
public VideoClip(ObjectReader reader) : base(reader)
|
public VideoClip(ObjectReader reader) : base(reader)
|
||||||
{
|
{
|
||||||
@@ -32,22 +41,32 @@ namespace AssetStudio
|
|||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
var m_AudioSampleRate = reader.ReadUInt32Array();
|
var m_AudioSampleRate = reader.ReadUInt32Array();
|
||||||
var m_AudioLanguage = reader.ReadStringArray();
|
var m_AudioLanguage = reader.ReadStringArray();
|
||||||
//StreamedResource m_ExternalResources
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
m_Source = reader.ReadAlignedString();
|
{
|
||||||
var m_Offset = reader.ReadUInt64();
|
var m_VideoShadersSize = reader.ReadInt32();
|
||||||
m_Size = reader.ReadUInt64();
|
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
|
||||||
|
for (int i = 0; i < m_VideoShadersSize; i++)
|
||||||
|
{
|
||||||
|
m_VideoShaders[i] = new PPtr<Shader>(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_ExternalResources = new StreamedResource(reader);
|
||||||
var m_HasSplitAlpha = reader.ReadBoolean();
|
var m_HasSplitAlpha = reader.ReadBoolean();
|
||||||
|
if (version[0] >= 2020) //2020.1 and up
|
||||||
|
{
|
||||||
|
var m_sRGB = reader.ReadBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
ResourceReader resourceReader;
|
ResourceReader resourceReader;
|
||||||
if (!string.IsNullOrEmpty(m_Source))
|
if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(m_Source, assetsFile, (long)m_Offset, (int)m_Size);
|
resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, m_ExternalResources.m_Size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
|
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_ExternalResources.m_Size);
|
||||||
}
|
}
|
||||||
m_VideoData = new Lazy<byte[]>(resourceReader.GetData);
|
m_VideoData = resourceReader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,7 +112,9 @@ namespace AssetStudio
|
|||||||
{1083, "BoundsInt"},
|
{1083, "BoundsInt"},
|
||||||
{1093, "m_CorrespondingSourceObject"},
|
{1093, "m_CorrespondingSourceObject"},
|
||||||
{1121, "m_PrefabInstance"},
|
{1121, "m_PrefabInstance"},
|
||||||
{1138, "m_PrefabAsset"}
|
{1138, "m_PrefabAsset"},
|
||||||
|
{1152, "FileSize"},
|
||||||
|
{1161, "Hash128"}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Buffers.Binary;
|
||||||
using System.Text;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public enum EndianType
|
|
||||||
{
|
|
||||||
LittleEndian,
|
|
||||||
BigEndian
|
|
||||||
}
|
|
||||||
|
|
||||||
public class EndianBinaryReader : BinaryReader
|
public class EndianBinaryReader : BinaryReader
|
||||||
{
|
{
|
||||||
public EndianType endian;
|
private readonly byte[] buffer;
|
||||||
|
|
||||||
|
public EndianType Endian;
|
||||||
|
|
||||||
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
|
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
|
||||||
{
|
{
|
||||||
this.endian = endian;
|
Endian = endian;
|
||||||
|
buffer = new byte[8];
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Position
|
public long Position
|
||||||
@@ -28,88 +24,82 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public override short ReadInt16()
|
public override short ReadInt16()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(2);
|
Read(buffer, 0, 2);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadInt16BigEndian(buffer);
|
||||||
return BitConverter.ToInt16(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadInt16();
|
return base.ReadInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int ReadInt32()
|
public override int ReadInt32()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(4);
|
Read(buffer, 0, 4);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadInt32BigEndian(buffer);
|
||||||
return BitConverter.ToInt32(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadInt32();
|
return base.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long ReadInt64()
|
public override long ReadInt64()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(8);
|
Read(buffer, 0, 8);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadInt64BigEndian(buffer);
|
||||||
return BitConverter.ToInt64(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadInt64();
|
return base.ReadInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ushort ReadUInt16()
|
public override ushort ReadUInt16()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(2);
|
Read(buffer, 0, 2);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
|
||||||
return BitConverter.ToUInt16(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadUInt16();
|
return base.ReadUInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override uint ReadUInt32()
|
public override uint ReadUInt32()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(4);
|
Read(buffer, 0, 4);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
|
||||||
return BitConverter.ToUInt32(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadUInt32();
|
return base.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override ulong ReadUInt64()
|
public override ulong ReadUInt64()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(8);
|
Read(buffer, 0, 8);
|
||||||
Array.Reverse(buff);
|
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||||
return BitConverter.ToUInt64(buff, 0);
|
|
||||||
}
|
}
|
||||||
return base.ReadUInt64();
|
return base.ReadUInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float ReadSingle()
|
public override float ReadSingle()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(4);
|
Read(buffer, 0, 4);
|
||||||
Array.Reverse(buff);
|
Array.Reverse(buffer, 0, 4);
|
||||||
return BitConverter.ToSingle(buff, 0);
|
return BitConverter.ToSingle(buffer, 0);
|
||||||
}
|
}
|
||||||
return base.ReadSingle();
|
return base.ReadSingle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override double ReadDouble()
|
public override double ReadDouble()
|
||||||
{
|
{
|
||||||
if (endian == EndianType.BigEndian)
|
if (Endian == EndianType.BigEndian)
|
||||||
{
|
{
|
||||||
var buff = ReadBytes(8);
|
Read(buffer, 0, 8);
|
||||||
Array.Reverse(buff);
|
Array.Reverse(buffer);
|
||||||
return BitConverter.ToUInt64(buff, 0);
|
return BitConverter.ToDouble(buffer, 0);
|
||||||
}
|
}
|
||||||
return base.ReadDouble();
|
return base.ReadDouble();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -72,11 +72,6 @@ namespace AssetStudio
|
|||||||
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
return new Vector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static System.Drawing.RectangleF ReadRectangleF(this BinaryReader reader)
|
|
||||||
{
|
|
||||||
return new System.Drawing.RectangleF(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Color ReadColor4(this BinaryReader reader)
|
public static Color ReadColor4(this BinaryReader reader)
|
||||||
{
|
{
|
||||||
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
return new Color(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
|
||||||
@@ -102,6 +97,11 @@ namespace AssetStudio
|
|||||||
return ReadArray(reader.ReadBoolean, reader.ReadInt32());
|
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)
|
public static ushort[] ReadUInt16Array(this BinaryReader reader)
|
||||||
{
|
{
|
||||||
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
|
return ReadArray(reader.ReadUInt16, reader.ReadInt32());
|
||||||
@@ -122,6 +122,11 @@ namespace AssetStudio
|
|||||||
return ReadArray(reader.ReadUInt32, reader.ReadInt32());
|
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)
|
public static uint[] ReadUInt32Array(this BinaryReader reader, int length)
|
||||||
{
|
{
|
||||||
return ReadArray(reader.ReadUInt32, length);
|
return ReadArray(reader.ReadUInt32, length);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
+56
-19
@@ -73,6 +73,28 @@ namespace AssetStudio
|
|||||||
return null;
|
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)
|
public ImportedFrame FindFrame(string name)
|
||||||
{
|
{
|
||||||
if (Name == name)
|
if (Name == name)
|
||||||
@@ -132,30 +154,31 @@ namespace AssetStudio
|
|||||||
public class ImportedMesh
|
public class ImportedMesh
|
||||||
{
|
{
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public List<ImportedVertex> VertexList { get; set; }
|
||||||
public List<ImportedSubmesh> SubmeshList { get; set; }
|
public List<ImportedSubmesh> SubmeshList { get; set; }
|
||||||
public List<ImportedBone> BoneList { 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 class ImportedSubmesh
|
||||||
{
|
{
|
||||||
public List<ImportedVertex> VertexList { get; set; }
|
|
||||||
public List<ImportedFace> FaceList { get; set; }
|
public List<ImportedFace> FaceList { get; set; }
|
||||||
public string Material { get; set; }
|
public string Material { get; set; }
|
||||||
|
public int BaseVertex { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedVertex
|
public class ImportedVertex
|
||||||
{
|
{
|
||||||
public Vector3 Position { get; set; }
|
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 float[] Weights { get; set; }
|
||||||
public int[] BoneIndices { get; set; }
|
public int[] BoneIndices { get; set; }
|
||||||
public Vector3 Normal { get; set; }
|
|
||||||
public float[] UV { get; set; }
|
|
||||||
public Vector4 Tangent { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ImportedVertexWithColour : ImportedVertex
|
|
||||||
{
|
|
||||||
public Color Colour { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedFace
|
public class ImportedFace
|
||||||
@@ -205,7 +228,7 @@ namespace AssetStudio
|
|||||||
public class ImportedKeyframedAnimation
|
public class ImportedKeyframedAnimation
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
public float SampleRate { get; set; }
|
||||||
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
public List<ImportedAnimationKeyframedTrack> TrackList { get; set; }
|
||||||
|
|
||||||
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
public ImportedAnimationKeyframedTrack FindTrack(string path)
|
||||||
@@ -227,14 +250,13 @@ namespace AssetStudio
|
|||||||
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Scalings = new List<ImportedKeyframe<Vector3>>();
|
||||||
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Rotations = new List<ImportedKeyframe<Vector3>>();
|
||||||
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
public List<ImportedKeyframe<Vector3>> Translations = new List<ImportedKeyframe<Vector3>>();
|
||||||
|
public ImportedBlendShape BlendShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedKeyframe<T>
|
public class ImportedKeyframe<T>
|
||||||
{
|
{
|
||||||
public float time { get; set; }
|
public float time { get; set; }
|
||||||
public T value { get; set; }
|
public T value { get; set; }
|
||||||
public T inSlope { get; set; }
|
|
||||||
public T outSlope { get; set; }
|
|
||||||
|
|
||||||
public ImportedKeyframe(float time, T value)
|
public ImportedKeyframe(float time, T value)
|
||||||
{
|
{
|
||||||
@@ -243,21 +265,36 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ImportedBlendShape
|
||||||
|
{
|
||||||
|
public string ChannelName;
|
||||||
|
public List<ImportedKeyframe<float>> Keyframes = new List<ImportedKeyframe<float>>();
|
||||||
|
}
|
||||||
|
|
||||||
public class ImportedMorph
|
public class ImportedMorph
|
||||||
{
|
{
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public string ClipName { get; set; }
|
public List<ImportedMorphChannel> Channels { get; set; }
|
||||||
public List<Tuple<float, int, int>> Channels { get; set; }
|
}
|
||||||
|
|
||||||
|
public class ImportedMorphChannel
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
public List<ImportedMorphKeyframe> KeyframeList { get; set; }
|
||||||
public List<ushort> MorphedVertexIndices { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportedMorphKeyframe
|
public class ImportedMorphKeyframe
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public bool hasNormals { get; set; }
|
||||||
public List<ImportedVertex> VertexList { get; set; }
|
public bool hasTangents { get; set; }
|
||||||
public List<ushort> MorphedVertexIndices { get; set; }
|
|
||||||
public float Weight { 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 class ImportedHelpers
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
public interface IProgress
|
|
||||||
{
|
|
||||||
void Report(int value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class DummyProgress : IProgress
|
|
||||||
{
|
|
||||||
public void Report(int value) { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+29
-51
@@ -1,16 +1,11 @@
|
|||||||
using System.Collections.Generic;
|
using Org.Brotli.Dec;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public enum FileType
|
|
||||||
{
|
|
||||||
AssetsFile,
|
|
||||||
BundleFile,
|
|
||||||
WebFile
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ImportHelper
|
public static class ImportHelper
|
||||||
{
|
{
|
||||||
public static void MergeSplitAssets(string path, bool allDirectories = false)
|
public static void MergeSplitAssets(string path, bool allDirectories = false)
|
||||||
@@ -19,8 +14,8 @@ namespace AssetStudio
|
|||||||
foreach (var splitFile in splitFiles)
|
foreach (var splitFile in splitFiles)
|
||||||
{
|
{
|
||||||
var destFile = Path.GetFileNameWithoutExtension(splitFile);
|
var destFile = Path.GetFileNameWithoutExtension(splitFile);
|
||||||
var destPath = Path.GetDirectoryName(splitFile) + "\\";
|
var destPath = Path.GetDirectoryName(splitFile);
|
||||||
var destFull = destPath + destFile;
|
var destFull = Path.Combine(destPath, destFile);
|
||||||
if (!File.Exists(destFull))
|
if (!File.Exists(destFull))
|
||||||
{
|
{
|
||||||
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
|
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
|
||||||
@@ -42,7 +37,7 @@ namespace AssetStudio
|
|||||||
public static string[] ProcessingSplitFiles(List<string> selectFile)
|
public static string[] ProcessingSplitFiles(List<string> selectFile)
|
||||||
{
|
{
|
||||||
var splitFiles = selectFile.Where(x => x.Contains(".split"))
|
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()
|
.Distinct()
|
||||||
.ToList();
|
.ToList();
|
||||||
selectFile.RemoveAll(x => x.Contains(".split"));
|
selectFile.RemoveAll(x => x.Contains(".split"));
|
||||||
@@ -56,48 +51,31 @@ namespace AssetStudio
|
|||||||
return selectFile.Distinct().ToArray();
|
return selectFile.Distinct().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
|
public static FileReader DecompressGZip(FileReader reader)
|
||||||
{
|
{
|
||||||
reader = new EndianBinaryReader(stream);
|
using (reader)
|
||||||
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(20);
|
|
||||||
reader.Position = 0;
|
|
||||||
switch (signature)
|
|
||||||
{
|
{
|
||||||
case "UnityWeb":
|
var stream = new MemoryStream();
|
||||||
case "UnityRaw":
|
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
|
||||||
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
|
{
|
||||||
case "UnityFS":
|
gs.CopyTo(stream);
|
||||||
return FileType.BundleFile;
|
}
|
||||||
case "UnityWebData1.0":
|
stream.Position = 0;
|
||||||
return FileType.WebFile;
|
return new FileReader(reader.FullPath, stream);
|
||||||
default:
|
}
|
||||||
{
|
}
|
||||||
var magic = reader.ReadBytes(2);
|
|
||||||
reader.Position = 0;
|
public static FileReader DecompressBrotli(FileReader reader)
|
||||||
if (WebFile.gzipMagic.SequenceEqual(magic))
|
{
|
||||||
{
|
using (reader)
|
||||||
return FileType.WebFile;
|
{
|
||||||
}
|
var stream = new MemoryStream();
|
||||||
reader.Position = 0x20;
|
using (var brotliStream = new BrotliInputStream(reader.BaseStream))
|
||||||
magic = reader.ReadBytes(6);
|
{
|
||||||
reader.Position = 0;
|
brotliStream.CopyTo(stream);
|
||||||
if (WebFile.brotliMagic.SequenceEqual(magic))
|
}
|
||||||
{
|
stream.Position = 0;
|
||||||
return FileType.WebFile;
|
return new FileReader(reader.FullPath, stream);
|
||||||
}
|
|
||||||
return FileType.AssetsFile;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,5 +14,13 @@ namespace AssetStudio
|
|||||||
public static void Info(string message) => Default.Log(LoggerEvent.Info, message);
|
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 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) => 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
using System.Diagnostics;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace System
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a half-precision floating point number.
|
/// Represents a half-precision floating point number.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace System
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper class for Half conversions and some low level operations.
|
/// Helper class for Half conversions and some low level operations.
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static Vector3 Zero => new Vector3();
|
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)
|
public static Vector3 operator +(Vector3 a, Vector3 b)
|
||||||
{
|
{
|
||||||
return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
return new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
|
||||||
|
|||||||
@@ -7,10 +7,12 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public class ObjectInfo
|
public class ObjectInfo
|
||||||
{
|
{
|
||||||
public uint byteStart;
|
public long byteStart;
|
||||||
public uint byteSize;
|
public uint byteSize;
|
||||||
public int typeID;
|
public int typeID;
|
||||||
public int classID;
|
public int classID;
|
||||||
|
public ushort isDestroyed;
|
||||||
|
public byte stripped;
|
||||||
|
|
||||||
public long m_PathID;
|
public long m_PathID;
|
||||||
public SerializedType serializedType;
|
public SerializedType serializedType;
|
||||||
|
|||||||
@@ -10,17 +10,17 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
public SerializedFile assetsFile;
|
public SerializedFile assetsFile;
|
||||||
public long m_PathID;
|
public long m_PathID;
|
||||||
public uint byteStart;
|
public long byteStart;
|
||||||
public uint byteSize;
|
public uint byteSize;
|
||||||
public ClassIDType type;
|
public ClassIDType type;
|
||||||
public SerializedType serializedType;
|
public SerializedType serializedType;
|
||||||
public BuildTarget platform;
|
public BuildTarget platform;
|
||||||
public uint m_Version;
|
public SerializedFileFormatVersion m_Version;
|
||||||
|
|
||||||
public int[] version => assetsFile.version;
|
public int[] version => assetsFile.version;
|
||||||
public BuildType buildType => assetsFile.buildType;
|
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;
|
this.assetsFile = assetsFile;
|
||||||
m_PathID = objectInfo.m_PathID;
|
m_PathID = objectInfo.m_PathID;
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
namespace AssetStudio
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public static class Progress
|
public static class Progress
|
||||||
{
|
{
|
||||||
public static IProgress Default = new DummyProgress();
|
public static IProgress<int> Default = new Progress<int>();
|
||||||
private static int preValue;
|
private static int preValue;
|
||||||
|
|
||||||
public static void Reset()
|
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")]
|
|
||||||
@@ -8,11 +8,12 @@ namespace AssetStudio
|
|||||||
private string path;
|
private string path;
|
||||||
private SerializedFile assetsFile;
|
private SerializedFile assetsFile;
|
||||||
private long offset;
|
private long offset;
|
||||||
private int size;
|
private long size;
|
||||||
private BinaryReader reader;
|
private BinaryReader reader;
|
||||||
|
|
||||||
|
public int Size { get => (int)size; }
|
||||||
|
|
||||||
public ResourceReader(string path, SerializedFile assetsFile, long offset, int size)
|
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
|
||||||
{
|
{
|
||||||
needSearch = true;
|
needSearch = true;
|
||||||
this.path = path;
|
this.path = path;
|
||||||
@@ -21,30 +22,28 @@ namespace AssetStudio
|
|||||||
this.size = size;
|
this.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResourceReader(BinaryReader reader, long offset, int size)
|
public ResourceReader(BinaryReader reader, long offset, long size)
|
||||||
{
|
{
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetData()
|
private BinaryReader GetReader()
|
||||||
{
|
{
|
||||||
if (needSearch)
|
if (needSearch)
|
||||||
{
|
{
|
||||||
var resourceFileName = Path.GetFileName(path);
|
var resourceFileName = Path.GetFileName(path);
|
||||||
|
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
|
||||||
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
|
|
||||||
{
|
{
|
||||||
reader.Position = offset;
|
needSearch = false;
|
||||||
return reader.ReadBytes(size);
|
return reader;
|
||||||
}
|
}
|
||||||
|
var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);
|
||||||
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
|
var resourceFilePath = Path.Combine(assetsFileDirectory, resourceFileName);
|
||||||
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
|
|
||||||
if (!File.Exists(resourceFilePath))
|
if (!File.Exists(resourceFilePath))
|
||||||
{
|
{
|
||||||
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
|
var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);
|
||||||
if (findFiles.Length > 0)
|
if (findFiles.Length > 0)
|
||||||
{
|
{
|
||||||
resourceFilePath = findFiles[0];
|
resourceFilePath = findFiles[0];
|
||||||
@@ -52,18 +51,41 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
if (File.Exists(resourceFilePath))
|
if (File.Exists(resourceFilePath))
|
||||||
{
|
{
|
||||||
using (var resourceReader = new BinaryReader(File.OpenRead(resourceFilePath)))
|
needSearch = false;
|
||||||
{
|
reader = new BinaryReader(File.OpenRead(resourceFilePath));
|
||||||
resourceReader.BaseStream.Position = offset;
|
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
|
||||||
return resourceReader.ReadBytes(size);
|
return reader;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
|
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
reader.BaseStream.Position = offset;
|
public byte[] GetData()
|
||||||
return reader.ReadBytes(size);
|
{
|
||||||
|
var binaryReader = GetReader();
|
||||||
|
binaryReader.BaseStream.Position = offset;
|
||||||
|
return binaryReader.ReadBytes((int)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetData(byte[] buff)
|
||||||
|
{
|
||||||
|
var binaryReader = GetReader();
|
||||||
|
binaryReader.BaseStream.Position = offset;
|
||||||
|
binaryReader.Read(buff, 0, (int)size);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteData(string path)
|
||||||
|
{
|
||||||
|
var binaryReader = GetReader();
|
||||||
|
binaryReader.BaseStream.Position = offset;
|
||||||
|
using (var writer = File.OpenWrite(path))
|
||||||
|
{
|
||||||
|
binaryReader.BaseStream.CopyTo(writer, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+154
-88
@@ -9,63 +9,73 @@ namespace AssetStudio
|
|||||||
public class SerializedFile
|
public class SerializedFile
|
||||||
{
|
{
|
||||||
public AssetsManager assetsManager;
|
public AssetsManager assetsManager;
|
||||||
public EndianBinaryReader reader;
|
public FileReader reader;
|
||||||
public string fullName;
|
public string fullName;
|
||||||
public string originalPath;
|
public string originalPath;
|
||||||
public string fileName;
|
public string fileName;
|
||||||
public string upperFileName;
|
|
||||||
public int[] version = { 0, 0, 0, 0 };
|
public int[] version = { 0, 0, 0, 0 };
|
||||||
public BuildType buildType;
|
public BuildType buildType;
|
||||||
public Dictionary<long, Object> Objects;
|
public List<Object> Objects;
|
||||||
|
public Dictionary<long, Object> ObjectsDic;
|
||||||
|
|
||||||
public SerializedFileHeader header;
|
public SerializedFileHeader header;
|
||||||
private EndianType m_FileEndianess;
|
private byte m_FileEndianess;
|
||||||
public string unityVersion = "2.5.0f5";
|
public string unityVersion = "2.5.0f5";
|
||||||
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
|
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
|
||||||
private bool m_EnableTypeTree = true;
|
private bool m_EnableTypeTree = true;
|
||||||
public List<SerializedType> m_Types;
|
public List<SerializedType> m_Types;
|
||||||
|
public int bigIDEnabled = 0;
|
||||||
public List<ObjectInfo> m_Objects;
|
public List<ObjectInfo> m_Objects;
|
||||||
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
|
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
|
||||||
public List<FileIdentifier> m_Externals;
|
public List<FileIdentifier> m_Externals;
|
||||||
|
public List<SerializedType> m_RefTypes;
|
||||||
|
public string userInformation;
|
||||||
|
|
||||||
public SerializedFile(AssetsManager assetsManager, string fullName, EndianBinaryReader reader)
|
public SerializedFile(FileReader reader, AssetsManager assetsManager)
|
||||||
{
|
{
|
||||||
this.assetsManager = assetsManager;
|
this.assetsManager = assetsManager;
|
||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
this.fullName = fullName;
|
fullName = reader.FullPath;
|
||||||
fileName = Path.GetFileName(fullName);
|
fileName = reader.FileName;
|
||||||
upperFileName = fileName.ToUpper();
|
|
||||||
|
|
||||||
//ReadHeader
|
// ReadHeader
|
||||||
header = new SerializedFileHeader();
|
header = new SerializedFileHeader();
|
||||||
header.m_MetadataSize = reader.ReadUInt32();
|
header.m_MetadataSize = reader.ReadUInt32();
|
||||||
header.m_FileSize = reader.ReadUInt32();
|
header.m_FileSize = reader.ReadUInt32();
|
||||||
header.m_Version = reader.ReadUInt32();
|
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
|
||||||
header.m_DataOffset = reader.ReadUInt32();
|
header.m_DataOffset = reader.ReadUInt32();
|
||||||
|
|
||||||
if (header.m_Version >= 9)
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_9)
|
||||||
{
|
{
|
||||||
header.m_Endianess = reader.ReadByte();
|
header.m_Endianess = reader.ReadByte();
|
||||||
header.m_Reserved = reader.ReadBytes(3);
|
header.m_Reserved = reader.ReadBytes(3);
|
||||||
m_FileEndianess = (EndianType)header.m_Endianess;
|
m_FileEndianess = header.m_Endianess;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reader.Position = header.m_FileSize - header.m_MetadataSize;
|
reader.Position = header.m_FileSize - header.m_MetadataSize;
|
||||||
m_FileEndianess = (EndianType)reader.ReadByte();
|
m_FileEndianess = reader.ReadByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadMetadata
|
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
|
||||||
if (m_FileEndianess == EndianType.LittleEndian)
|
|
||||||
{
|
{
|
||||||
reader.endian = EndianType.LittleEndian;
|
header.m_MetadataSize = reader.ReadUInt32();
|
||||||
|
header.m_FileSize = reader.ReadInt64();
|
||||||
|
header.m_DataOffset = reader.ReadInt64();
|
||||||
|
reader.ReadInt64(); // unknown
|
||||||
}
|
}
|
||||||
if (header.m_Version >= 7)
|
|
||||||
|
// ReadMetadata
|
||||||
|
if (m_FileEndianess == 0)
|
||||||
|
{
|
||||||
|
reader.Endian = EndianType.LittleEndian;
|
||||||
|
}
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
|
||||||
{
|
{
|
||||||
unityVersion = reader.ReadStringToNull();
|
unityVersion = reader.ReadStringToNull();
|
||||||
SetVersion(unityVersion);
|
SetVersion(unityVersion);
|
||||||
}
|
}
|
||||||
if (header.m_Version >= 8)
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
|
||||||
{
|
{
|
||||||
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
|
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
|
||||||
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
|
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
|
||||||
@@ -73,31 +83,37 @@ namespace AssetStudio
|
|||||||
m_TargetPlatform = BuildTarget.UnknownPlatform;
|
m_TargetPlatform = BuildTarget.UnknownPlatform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (header.m_Version >= 13)
|
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
|
||||||
{
|
{
|
||||||
m_EnableTypeTree = reader.ReadBoolean();
|
m_EnableTypeTree = reader.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadTypes
|
// Read Types
|
||||||
int typeCount = reader.ReadInt32();
|
int typeCount = reader.ReadInt32();
|
||||||
m_Types = new List<SerializedType>(typeCount);
|
m_Types = new List<SerializedType>(typeCount);
|
||||||
for (int i = 0; i < typeCount; i++)
|
for (int i = 0; i < typeCount; i++)
|
||||||
{
|
{
|
||||||
m_Types.Add(ReadSerializedType());
|
m_Types.Add(ReadSerializedType(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 7 && header.m_Version < 14)
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7 && header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||||
{
|
{
|
||||||
var bigIDEnabled = reader.ReadInt32();
|
bigIDEnabled = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReadObjects
|
// Read Objects
|
||||||
int objectCount = reader.ReadInt32();
|
int objectCount = reader.ReadInt32();
|
||||||
m_Objects = new List<ObjectInfo>(objectCount);
|
m_Objects = new List<ObjectInfo>(objectCount);
|
||||||
|
Objects = new List<Object>(objectCount);
|
||||||
|
ObjectsDic = new Dictionary<long, Object>(objectCount);
|
||||||
for (int i = 0; i < objectCount; i++)
|
for (int i = 0; i < objectCount; i++)
|
||||||
{
|
{
|
||||||
var objectInfo = new ObjectInfo();
|
var objectInfo = new ObjectInfo();
|
||||||
if (header.m_Version < 14)
|
if (bigIDEnabled != 0)
|
||||||
|
{
|
||||||
|
objectInfo.m_PathID = reader.ReadInt64();
|
||||||
|
}
|
||||||
|
else if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||||
{
|
{
|
||||||
objectInfo.m_PathID = reader.ReadInt32();
|
objectInfo.m_PathID = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
@@ -106,15 +122,19 @@ namespace AssetStudio
|
|||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
objectInfo.m_PathID = reader.ReadInt64();
|
objectInfo.m_PathID = reader.ReadInt64();
|
||||||
}
|
}
|
||||||
objectInfo.byteStart = reader.ReadUInt32();
|
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
|
||||||
|
objectInfo.byteStart = reader.ReadInt64();
|
||||||
|
else
|
||||||
|
objectInfo.byteStart = reader.ReadUInt32();
|
||||||
|
|
||||||
objectInfo.byteStart += header.m_DataOffset;
|
objectInfo.byteStart += header.m_DataOffset;
|
||||||
objectInfo.byteSize = reader.ReadUInt32();
|
objectInfo.byteSize = reader.ReadUInt32();
|
||||||
objectInfo.typeID = reader.ReadInt32();
|
objectInfo.typeID = reader.ReadInt32();
|
||||||
if (header.m_Version < 16)
|
if (header.m_Version < SerializedFileFormatVersion.RefactoredClassId)
|
||||||
{
|
{
|
||||||
objectInfo.classID = reader.ReadUInt16();
|
objectInfo.classID = reader.ReadUInt16();
|
||||||
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
||||||
var isDestroyed = reader.ReadUInt16();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -122,14 +142,24 @@ namespace AssetStudio
|
|||||||
objectInfo.serializedType = type;
|
objectInfo.serializedType = type;
|
||||||
objectInfo.classID = type.classID;
|
objectInfo.classID = type.classID;
|
||||||
}
|
}
|
||||||
if (header.m_Version == 15 || header.m_Version == 16)
|
if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)
|
||||||
{
|
{
|
||||||
var stripped = reader.ReadByte();
|
objectInfo.isDestroyed = reader.ReadUInt16();
|
||||||
|
}
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.RefactorTypeData)
|
||||||
|
{
|
||||||
|
var m_ScriptTypeIndex = reader.ReadInt16();
|
||||||
|
if (objectInfo.serializedType != null)
|
||||||
|
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
|
||||||
|
}
|
||||||
|
if (header.m_Version == SerializedFileFormatVersion.SupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.RefactoredClassId)
|
||||||
|
{
|
||||||
|
objectInfo.stripped = reader.ReadByte();
|
||||||
}
|
}
|
||||||
m_Objects.Add(objectInfo);
|
m_Objects.Add(objectInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 11)
|
if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex)
|
||||||
{
|
{
|
||||||
int scriptCount = reader.ReadInt32();
|
int scriptCount = reader.ReadInt32();
|
||||||
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
|
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
|
||||||
@@ -137,7 +167,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
var m_ScriptType = new LocalSerializedObjectIdentifier();
|
var m_ScriptType = new LocalSerializedObjectIdentifier();
|
||||||
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
|
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
|
||||||
if (header.m_Version < 14)
|
if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||||
{
|
{
|
||||||
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
|
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
@@ -155,11 +185,11 @@ namespace AssetStudio
|
|||||||
for (int i = 0; i < externalsCount; i++)
|
for (int i = 0; i < externalsCount; i++)
|
||||||
{
|
{
|
||||||
var m_External = new FileIdentifier();
|
var m_External = new FileIdentifier();
|
||||||
if (header.m_Version >= 6)
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)
|
||||||
{
|
{
|
||||||
var tempEmpty = reader.ReadStringToNull();
|
var tempEmpty = reader.ReadStringToNull();
|
||||||
}
|
}
|
||||||
if (header.m_Version >= 5)
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
|
||||||
{
|
{
|
||||||
m_External.guid = new Guid(reader.ReadBytes(16));
|
m_External.guid = new Guid(reader.ReadBytes(16));
|
||||||
m_External.type = reader.ReadInt32();
|
m_External.type = reader.ReadInt32();
|
||||||
@@ -169,83 +199,114 @@ namespace AssetStudio
|
|||||||
m_Externals.Add(m_External);
|
m_Externals.Add(m_External);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 5)
|
if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)
|
||||||
{
|
{
|
||||||
//var userInformation = reader.ReadStringToNull();
|
int refTypesCount = reader.ReadInt32();
|
||||||
|
m_RefTypes = new List<SerializedType>(refTypesCount);
|
||||||
|
for (int i = 0; i < refTypesCount; i++)
|
||||||
|
{
|
||||||
|
m_RefTypes.Add(ReadSerializedType(true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
|
||||||
|
{
|
||||||
|
userInformation = reader.ReadStringToNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
//reader.AlignStream(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetVersion(string stringVersion)
|
public void SetVersion(string stringVersion)
|
||||||
{
|
{
|
||||||
unityVersion = stringVersion;
|
if (stringVersion != strippedVersion)
|
||||||
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
{
|
||||||
buildType = new BuildType(buildSplit[0]);
|
unityVersion = stringVersion;
|
||||||
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
version = versionSplit.Select(int.Parse).ToArray();
|
buildType = new BuildType(buildSplit[0]);
|
||||||
|
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
version = versionSplit.Select(int.Parse).ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SerializedType ReadSerializedType()
|
private SerializedType ReadSerializedType(bool isRefType)
|
||||||
{
|
{
|
||||||
var type = new SerializedType();
|
var type = new SerializedType();
|
||||||
|
|
||||||
type.classID = reader.ReadInt32();
|
type.classID = reader.ReadInt32();
|
||||||
|
|
||||||
if (header.m_Version >= 16)
|
if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)
|
||||||
{
|
{
|
||||||
type.m_IsStrippedType = reader.ReadBoolean();
|
type.m_IsStrippedType = reader.ReadBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 17)
|
if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)
|
||||||
{
|
{
|
||||||
type.m_ScriptTypeIndex = reader.ReadInt16();
|
type.m_ScriptTypeIndex = reader.ReadInt16();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.m_Version >= 13)
|
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
|
||||||
{
|
{
|
||||||
if ((header.m_Version < 16 && type.classID < 0) || (header.m_Version >= 16 && type.classID == 114))
|
if (isRefType && type.m_ScriptTypeIndex >= 0)
|
||||||
{
|
{
|
||||||
type.m_ScriptID = reader.ReadBytes(16); //Hash128
|
type.m_ScriptID = reader.ReadBytes(16);
|
||||||
}
|
}
|
||||||
type.m_OldTypeHash = reader.ReadBytes(16); //Hash128
|
else if ((header.m_Version < SerializedFileFormatVersion.RefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId && type.classID == 114))
|
||||||
|
{
|
||||||
|
type.m_ScriptID = reader.ReadBytes(16);
|
||||||
|
}
|
||||||
|
type.m_OldTypeHash = reader.ReadBytes(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_EnableTypeTree)
|
if (m_EnableTypeTree)
|
||||||
{
|
{
|
||||||
var typeTree = new List<TypeTreeNode>();
|
type.m_Type = new TypeTree();
|
||||||
if (header.m_Version >= 12 || header.m_Version == 10)
|
type.m_Type.m_Nodes = new List<TypeTreeNode>();
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.Unknown_12 || header.m_Version == SerializedFileFormatVersion.Unknown_10)
|
||||||
{
|
{
|
||||||
ReadTypeTree5(typeTree);
|
TypeTreeBlobRead(type.m_Type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ReadTypeTree(typeTree);
|
ReadTypeTree(type.m_Type);
|
||||||
|
}
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)
|
||||||
|
{
|
||||||
|
if (isRefType)
|
||||||
|
{
|
||||||
|
type.m_KlassName = reader.ReadStringToNull();
|
||||||
|
type.m_NameSpace = reader.ReadStringToNull();
|
||||||
|
type.m_AsmName = reader.ReadStringToNull();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type.m_TypeDependencies = reader.ReadInt32Array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type.m_Nodes = typeTree;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadTypeTree(List<TypeTreeNode> typeTree, int level = 0)
|
private void ReadTypeTree(TypeTree m_Type, int level = 0)
|
||||||
{
|
{
|
||||||
var typeTreeNode = new TypeTreeNode();
|
var typeTreeNode = new TypeTreeNode();
|
||||||
typeTree.Add(typeTreeNode);
|
m_Type.m_Nodes.Add(typeTreeNode);
|
||||||
typeTreeNode.m_Level = level;
|
typeTreeNode.m_Level = level;
|
||||||
typeTreeNode.m_Type = reader.ReadStringToNull();
|
typeTreeNode.m_Type = reader.ReadStringToNull();
|
||||||
typeTreeNode.m_Name = reader.ReadStringToNull();
|
typeTreeNode.m_Name = reader.ReadStringToNull();
|
||||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||||
if (header.m_Version == 2)
|
if (header.m_Version == SerializedFileFormatVersion.Unknown_2)
|
||||||
{
|
{
|
||||||
var variableCount = reader.ReadInt32();
|
var variableCount = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
if (header.m_Version != 3)
|
if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
|
||||||
{
|
{
|
||||||
typeTreeNode.m_Index = reader.ReadInt32();
|
typeTreeNode.m_Index = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
typeTreeNode.m_IsArray = reader.ReadInt32();
|
typeTreeNode.m_TypeFlags = reader.ReadInt32();
|
||||||
typeTreeNode.m_Version = reader.ReadInt32();
|
typeTreeNode.m_Version = reader.ReadInt32();
|
||||||
if (header.m_Version != 3)
|
if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
|
||||||
{
|
{
|
||||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
@@ -253,46 +314,41 @@ namespace AssetStudio
|
|||||||
int childrenCount = reader.ReadInt32();
|
int childrenCount = reader.ReadInt32();
|
||||||
for (int i = 0; i < childrenCount; i++)
|
for (int i = 0; i < childrenCount; i++)
|
||||||
{
|
{
|
||||||
ReadTypeTree(typeTree, level + 1);
|
ReadTypeTree(m_Type, level + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadTypeTree5(List<TypeTreeNode> typeTree)
|
private void TypeTreeBlobRead(TypeTree m_Type)
|
||||||
{
|
{
|
||||||
int numberOfNodes = reader.ReadInt32();
|
int numberOfNodes = reader.ReadInt32();
|
||||||
int stringBufferSize = reader.ReadInt32();
|
int stringBufferSize = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < numberOfNodes; i++)
|
||||||
var nodeSize = 24;
|
|
||||||
if (header.m_Version > 17)
|
|
||||||
{
|
{
|
||||||
nodeSize = 32;
|
var typeTreeNode = new TypeTreeNode();
|
||||||
|
m_Type.m_Nodes.Add(typeTreeNode);
|
||||||
|
typeTreeNode.m_Version = reader.ReadUInt16();
|
||||||
|
typeTreeNode.m_Level = reader.ReadByte();
|
||||||
|
typeTreeNode.m_TypeFlags = reader.ReadByte();
|
||||||
|
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
|
||||||
|
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
|
||||||
|
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||||
|
typeTreeNode.m_Index = reader.ReadInt32();
|
||||||
|
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||||
|
if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)
|
||||||
|
{
|
||||||
|
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reader.Position += numberOfNodes * nodeSize;
|
m_Type.m_StringBuffer = reader.ReadBytes(stringBufferSize);
|
||||||
using (var stringBufferReader = new BinaryReader(new MemoryStream(reader.ReadBytes(stringBufferSize))))
|
|
||||||
|
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_Type.m_StringBuffer)))
|
||||||
{
|
{
|
||||||
reader.Position -= numberOfNodes * nodeSize + stringBufferSize;
|
|
||||||
for (int i = 0; i < numberOfNodes; i++)
|
for (int i = 0; i < numberOfNodes; i++)
|
||||||
{
|
{
|
||||||
var typeTreeNode = new TypeTreeNode();
|
var m_Node = m_Type.m_Nodes[i];
|
||||||
typeTree.Add(typeTreeNode);
|
m_Node.m_Type = ReadString(stringBufferReader, m_Node.m_TypeStrOffset);
|
||||||
typeTreeNode.m_Version = reader.ReadUInt16();
|
m_Node.m_Name = ReadString(stringBufferReader, m_Node.m_NameStrOffset);
|
||||||
typeTreeNode.m_Level = reader.ReadByte();
|
|
||||||
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
|
|
||||||
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
|
|
||||||
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
|
|
||||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
|
||||||
typeTreeNode.m_Index = reader.ReadInt32();
|
|
||||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
|
||||||
|
|
||||||
if (header.m_Version > 17)
|
|
||||||
{
|
|
||||||
reader.Position += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
|
|
||||||
typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
|
|
||||||
}
|
}
|
||||||
reader.Position += stringBufferSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string ReadString(BinaryReader stringBufferReader, uint value)
|
string ReadString(BinaryReader stringBufferReader, uint value)
|
||||||
@@ -311,5 +367,15 @@ namespace AssetStudio
|
|||||||
return offset.ToString();
|
return offset.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddObject(Object obj)
|
||||||
|
{
|
||||||
|
Objects.Add(obj);
|
||||||
|
ObjectsDic.Add(obj.m_PathID, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsVersionStripped => unityVersion == strippedVersion;
|
||||||
|
|
||||||
|
private const string strippedVersion = "0.0.0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public enum SerializedFileFormatVersion
|
||||||
|
{
|
||||||
|
Unsupported = 1,
|
||||||
|
Unknown_2 = 2,
|
||||||
|
Unknown_3 = 3,
|
||||||
|
/// <summary>
|
||||||
|
/// 1.2.0 to 2.0.0
|
||||||
|
/// </summary>
|
||||||
|
Unknown_5 = 5,
|
||||||
|
/// <summary>
|
||||||
|
/// 2.1.0 to 2.6.1
|
||||||
|
/// </summary>
|
||||||
|
Unknown_6 = 6,
|
||||||
|
/// <summary>
|
||||||
|
/// 3.0.0b
|
||||||
|
/// </summary>
|
||||||
|
Unknown_7 = 7,
|
||||||
|
/// <summary>
|
||||||
|
/// 3.0.0 to 3.4.2
|
||||||
|
/// </summary>
|
||||||
|
Unknown_8 = 8,
|
||||||
|
/// <summary>
|
||||||
|
/// 3.5.0 to 4.7.2
|
||||||
|
/// </summary>
|
||||||
|
Unknown_9 = 9,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.0aunk1
|
||||||
|
/// </summary>
|
||||||
|
Unknown_10 = 10,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.0aunk2
|
||||||
|
/// </summary>
|
||||||
|
HasScriptTypeIndex = 11,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.0aunk3
|
||||||
|
/// </summary>
|
||||||
|
Unknown_12 = 12,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.0aunk4
|
||||||
|
/// </summary>
|
||||||
|
HasTypeTreeHashes = 13,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.0unk
|
||||||
|
/// </summary>
|
||||||
|
Unknown_14 = 14,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.0.1 to 5.4.0
|
||||||
|
/// </summary>
|
||||||
|
SupportsStrippedObject = 15,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.5.0a
|
||||||
|
/// </summary>
|
||||||
|
RefactoredClassId = 16,
|
||||||
|
/// <summary>
|
||||||
|
/// 5.5.0unk to 2018.4
|
||||||
|
/// </summary>
|
||||||
|
RefactorTypeData = 17,
|
||||||
|
/// <summary>
|
||||||
|
/// 2019.1a
|
||||||
|
/// </summary>
|
||||||
|
RefactorShareableTypeTreeData = 18,
|
||||||
|
/// <summary>
|
||||||
|
/// 2019.1unk
|
||||||
|
/// </summary>
|
||||||
|
TypeTreeNodeWithTypeFlags = 19,
|
||||||
|
/// <summary>
|
||||||
|
/// 2019.2
|
||||||
|
/// </summary>
|
||||||
|
SupportsRefObject = 20,
|
||||||
|
/// <summary>
|
||||||
|
/// 2019.3 to 2019.4
|
||||||
|
/// </summary>
|
||||||
|
StoresTypeDependencies = 21,
|
||||||
|
/// <summary>
|
||||||
|
/// 2020.1 to x
|
||||||
|
/// </summary>
|
||||||
|
LargeFilesSupport = 22
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,9 @@ namespace AssetStudio
|
|||||||
public class SerializedFileHeader
|
public class SerializedFileHeader
|
||||||
{
|
{
|
||||||
public uint m_MetadataSize;
|
public uint m_MetadataSize;
|
||||||
public uint m_FileSize;
|
public long m_FileSize;
|
||||||
public uint m_Version;
|
public SerializedFileFormatVersion m_Version;
|
||||||
public uint m_DataOffset;
|
public long m_DataOffset;
|
||||||
public byte m_Endianess;
|
public byte m_Endianess;
|
||||||
public byte[] m_Reserved;
|
public byte[] m_Reserved;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,12 @@ namespace AssetStudio
|
|||||||
public int classID;
|
public int classID;
|
||||||
public bool m_IsStrippedType;
|
public bool m_IsStrippedType;
|
||||||
public short m_ScriptTypeIndex = -1;
|
public short m_ScriptTypeIndex = -1;
|
||||||
public List<TypeTreeNode> m_Nodes;
|
public TypeTree m_Type;
|
||||||
public byte[] m_ScriptID; //Hash128
|
public byte[] m_ScriptID; //Hash128
|
||||||
public byte[] m_OldTypeHash; //Hash128
|
public byte[] m_OldTypeHash; //Hash128
|
||||||
|
public int[] m_TypeDependencies;
|
||||||
|
public string m_KlassName;
|
||||||
|
public string m_NameSpace;
|
||||||
|
public string m_AsmName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,15 +34,16 @@ namespace AssetStudio
|
|||||||
return newOutStream;
|
return newOutStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void StreamDecompress(Stream inStream, Stream outStream, long inSize, long outSize)
|
public static void StreamDecompress(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize)
|
||||||
{
|
{
|
||||||
|
var basePosition = compressedStream.Position;
|
||||||
var decoder = new Decoder();
|
var decoder = new Decoder();
|
||||||
var properties = new byte[5];
|
var properties = new byte[5];
|
||||||
if (inStream.Read(properties, 0, 5) != 5)
|
if (compressedStream.Read(properties, 0, 5) != 5)
|
||||||
throw new Exception("input .lzma is too short");
|
throw new Exception("input .lzma is too short");
|
||||||
decoder.SetDecoderProperties(properties);
|
decoder.SetDecoderProperties(properties);
|
||||||
inSize -= 5L;
|
decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null);
|
||||||
decoder.Code(inStream, outStream, inSize, outSize, null);
|
compressedStream.Position = basePosition + compressedSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class StreamFile
|
||||||
|
{
|
||||||
|
public string path;
|
||||||
|
public string fileName;
|
||||||
|
public Stream stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class TypeTree
|
||||||
|
{
|
||||||
|
public List<TypeTreeNode> m_Nodes;
|
||||||
|
public byte[] m_StringBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
+104
-220
@@ -1,30 +1,39 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public static class TypeTreeHelper
|
public static class TypeTreeHelper
|
||||||
{
|
{
|
||||||
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader)
|
public static string ReadTypeString(TypeTree m_Type, ObjectReader reader)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < members.Count; i++)
|
reader.Reset();
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var m_Nodes = m_Type.m_Nodes;
|
||||||
|
for (int i = 0; i < m_Nodes.Count; i++)
|
||||||
{
|
{
|
||||||
ReadStringValue(sb, members, reader, ref i);
|
ReadStringValue(sb, m_Nodes, reader, ref i);
|
||||||
}
|
}
|
||||||
|
var readed = reader.Position - reader.byteStart;
|
||||||
|
if (readed != reader.byteSize)
|
||||||
|
{
|
||||||
|
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var m_Node = m_Nodes[i];
|
||||||
var level = member.m_Level;
|
var level = m_Node.m_Level;
|
||||||
var varTypeStr = member.m_Type;
|
var varTypeStr = m_Node.m_Type;
|
||||||
var varNameStr = member.m_Name;
|
var varNameStr = m_Node.m_Name;
|
||||||
object value = null;
|
object value = null;
|
||||||
var append = true;
|
var append = true;
|
||||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
var align = (m_Node.m_MetaFlag & 0x4000) != 0;
|
||||||
switch (varTypeStr)
|
switch (varTypeStr)
|
||||||
{
|
{
|
||||||
case "SInt8":
|
case "SInt8":
|
||||||
@@ -33,6 +42,9 @@ namespace AssetStudio
|
|||||||
case "UInt8":
|
case "UInt8":
|
||||||
value = reader.ReadByte();
|
value = reader.ReadByte();
|
||||||
break;
|
break;
|
||||||
|
case "char":
|
||||||
|
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
|
||||||
|
break;
|
||||||
case "short":
|
case "short":
|
||||||
case "SInt16":
|
case "SInt16":
|
||||||
value = reader.ReadInt16();
|
value = reader.ReadInt16();
|
||||||
@@ -56,6 +68,7 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
case "UInt64":
|
case "UInt64":
|
||||||
case "unsigned long long":
|
case "unsigned long long":
|
||||||
|
case "FileSize":
|
||||||
value = reader.ReadUInt64();
|
value = reader.ReadUInt64();
|
||||||
break;
|
break;
|
||||||
case "float":
|
case "float":
|
||||||
@@ -71,43 +84,23 @@ namespace AssetStudio
|
|||||||
append = false;
|
append = false;
|
||||||
var str = reader.ReadAlignedString();
|
var str = reader.ReadAlignedString();
|
||||||
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
||||||
i += 3;
|
var toSkip = GetNodes(m_Nodes, i);
|
||||||
|
i += toSkip.Count - 1;
|
||||||
break;
|
break;
|
||||||
case "vector":
|
|
||||||
{
|
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
|
||||||
align = true;
|
|
||||||
append = false;
|
|
||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
|
||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
|
||||||
var size = reader.ReadInt32();
|
|
||||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
|
||||||
var vector = GetMembers(members, level, i);
|
|
||||||
i += vector.Count - 1;
|
|
||||||
vector.RemoveRange(0, 3);
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
|
||||||
int tmp = 0;
|
|
||||||
ReadStringValue(sb, vector, reader, ref tmp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "map":
|
case "map":
|
||||||
{
|
{
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
align = true;
|
align = true;
|
||||||
append = false;
|
append = false;
|
||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||||
var size = reader.ReadInt32();
|
var size = reader.ReadInt32();
|
||||||
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
||||||
var map = GetMembers(members, level, i);
|
var map = GetNodes(m_Nodes, i);
|
||||||
i += map.Count - 1;
|
i += map.Count - 1;
|
||||||
map.RemoveRange(0, 4);
|
var first = GetNodes(map, 4);
|
||||||
var first = GetMembers(map, map[0].m_Level, 0);
|
var next = 4 + first.Count;
|
||||||
map.RemoveRange(0, first.Count);
|
var second = GetNodes(map, next);
|
||||||
var second = map;
|
|
||||||
for (int j = 0; j < size; j++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||||
@@ -131,20 +124,37 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (i != members.Count && members[i + 1].m_Type == "Array")
|
if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == "Array") //Array
|
||||||
{
|
{
|
||||||
goto case "vector";
|
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
|
align = true;
|
||||||
|
append = false;
|
||||||
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||||
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
|
||||||
|
var size = reader.ReadInt32();
|
||||||
|
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
|
||||||
|
var vector = GetNodes(m_Nodes, i);
|
||||||
|
i += vector.Count - 1;
|
||||||
|
for (int j = 0; j < size; j++)
|
||||||
|
{
|
||||||
|
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
|
||||||
|
int tmp = 3;
|
||||||
|
ReadStringValue(sb, vector, reader, ref tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
append = false;
|
else //Class
|
||||||
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
|
||||||
var @class = GetMembers(members, level, i);
|
|
||||||
@class.RemoveAt(0);
|
|
||||||
i += @class.Count;
|
|
||||||
for (int j = 0; j < @class.Count; j++)
|
|
||||||
{
|
{
|
||||||
ReadStringValue(sb, @class, reader, ref j);
|
append = false;
|
||||||
|
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
|
||||||
|
var @class = GetNodes(m_Nodes, i);
|
||||||
|
i += @class.Count - 1;
|
||||||
|
for (int j = 1; j < @class.Count; j++)
|
||||||
|
{
|
||||||
|
ReadStringValue(sb, @class, reader, ref j);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (append)
|
if (append)
|
||||||
@@ -153,25 +163,31 @@ namespace AssetStudio
|
|||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UType ReadUType(List<TypeTreeNode> members, BinaryReader reader)
|
public static OrderedDictionary ReadType(TypeTree m_Types, ObjectReader reader)
|
||||||
{
|
{
|
||||||
var obj = new UType();
|
reader.Reset();
|
||||||
for (int i = 1; i < members.Count; i++)
|
var obj = new OrderedDictionary();
|
||||||
|
var m_Nodes = m_Types.m_Nodes;
|
||||||
|
for (int i = 1; i < m_Nodes.Count; i++)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var m_Node = m_Nodes[i];
|
||||||
var varNameStr = member.m_Name;
|
var varNameStr = m_Node.m_Name;
|
||||||
obj[varNameStr] = ReadValue(members, reader, ref i);
|
obj[varNameStr] = ReadValue(m_Nodes, reader, ref i);
|
||||||
|
}
|
||||||
|
var readed = reader.Position - reader.byteStart;
|
||||||
|
if (readed != reader.byteSize)
|
||||||
|
{
|
||||||
|
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
private static object ReadValue(List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var m_Node = m_Nodes[i];
|
||||||
var level = member.m_Level;
|
var varTypeStr = m_Node.m_Type;
|
||||||
var varTypeStr = member.m_Type;
|
|
||||||
object value;
|
object value;
|
||||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
var align = (m_Node.m_MetaFlag & 0x4000) != 0;
|
||||||
switch (varTypeStr)
|
switch (varTypeStr)
|
||||||
{
|
{
|
||||||
case "SInt8":
|
case "SInt8":
|
||||||
@@ -180,6 +196,9 @@ namespace AssetStudio
|
|||||||
case "UInt8":
|
case "UInt8":
|
||||||
value = reader.ReadByte();
|
value = reader.ReadByte();
|
||||||
break;
|
break;
|
||||||
|
case "char":
|
||||||
|
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
|
||||||
|
break;
|
||||||
case "short":
|
case "short":
|
||||||
case "SInt16":
|
case "SInt16":
|
||||||
value = reader.ReadInt16();
|
value = reader.ReadInt16();
|
||||||
@@ -203,6 +222,7 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
case "UInt64":
|
case "UInt64":
|
||||||
case "unsigned long long":
|
case "unsigned long long":
|
||||||
|
case "FileSize":
|
||||||
value = reader.ReadUInt64();
|
value = reader.ReadUInt64();
|
||||||
break;
|
break;
|
||||||
case "float":
|
case "float":
|
||||||
@@ -216,20 +236,20 @@ namespace AssetStudio
|
|||||||
break;
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
value = reader.ReadAlignedString();
|
value = reader.ReadAlignedString();
|
||||||
i += 3;
|
var toSkip = GetNodes(m_Nodes, i);
|
||||||
|
i += toSkip.Count - 1;
|
||||||
break;
|
break;
|
||||||
case "map":
|
case "map":
|
||||||
{
|
{
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
align = true;
|
align = true;
|
||||||
|
var map = GetNodes(m_Nodes, i);
|
||||||
|
i += map.Count - 1;
|
||||||
|
var first = GetNodes(map, 4);
|
||||||
|
var next = 4 + first.Count;
|
||||||
|
var second = GetNodes(map, next);
|
||||||
var size = reader.ReadInt32();
|
var size = reader.ReadInt32();
|
||||||
var dic = new List<KeyValuePair<object, object>>(size);
|
var dic = new List<KeyValuePair<object, object>>(size);
|
||||||
var map = GetMembers(members, level, i);
|
|
||||||
i += map.Count - 1;
|
|
||||||
map.RemoveRange(0, 4);
|
|
||||||
var first = GetMembers(map, map[0].m_Level, 0);
|
|
||||||
map.RemoveRange(0, first.Count);
|
|
||||||
var second = map;
|
|
||||||
for (int j = 0; j < size; j++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
int tmp1 = 0;
|
int tmp1 = 0;
|
||||||
@@ -248,18 +268,17 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
if (i != members.Count && members[i + 1].m_Type == "Array") //Array
|
if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == "Array") //Array
|
||||||
{
|
{
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
|
||||||
align = true;
|
align = true;
|
||||||
|
var vector = GetNodes(m_Nodes, i);
|
||||||
|
i += vector.Count - 1;
|
||||||
var size = reader.ReadInt32();
|
var size = reader.ReadInt32();
|
||||||
var list = new List<object>(size);
|
var list = new List<object>(size);
|
||||||
var vector = GetMembers(members, level, i);
|
|
||||||
i += vector.Count - 1;
|
|
||||||
vector.RemoveRange(0, 3);
|
|
||||||
for (int j = 0; j < size; j++)
|
for (int j = 0; j < size; j++)
|
||||||
{
|
{
|
||||||
int tmp = 0;
|
int tmp = 3;
|
||||||
list.Add(ReadValue(vector, reader, ref tmp));
|
list.Add(ReadValue(vector, reader, ref tmp));
|
||||||
}
|
}
|
||||||
value = list;
|
value = list;
|
||||||
@@ -267,11 +286,10 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
else //Class
|
else //Class
|
||||||
{
|
{
|
||||||
var @class = GetMembers(members, level, i);
|
var @class = GetNodes(m_Nodes, i);
|
||||||
@class.RemoveAt(0);
|
i += @class.Count - 1;
|
||||||
i += @class.Count;
|
var obj = new OrderedDictionary();
|
||||||
var obj = new UType();
|
for (int j = 1; j < @class.Count; j++)
|
||||||
for (int j = 0; j < @class.Count; j++)
|
|
||||||
{
|
{
|
||||||
var classmember = @class[j];
|
var classmember = @class[j];
|
||||||
var name = classmember.m_Name;
|
var name = classmember.m_Name;
|
||||||
@@ -287,156 +305,22 @@ namespace AssetStudio
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<TypeTreeNode> GetMembers(List<TypeTreeNode> members, int level, int index)
|
private static List<TypeTreeNode> GetNodes(List<TypeTreeNode> m_Nodes, int index)
|
||||||
{
|
{
|
||||||
var member2 = new List<TypeTreeNode>();
|
var nodes = new List<TypeTreeNode>();
|
||||||
member2.Add(members[0]);
|
nodes.Add(m_Nodes[index]);
|
||||||
for (int i = index + 1; i < members.Count; i++)
|
var level = m_Nodes[index].m_Level;
|
||||||
|
for (int i = index + 1; i < m_Nodes.Count; i++)
|
||||||
{
|
{
|
||||||
var member = members[i];
|
var member = m_Nodes[i];
|
||||||
var level2 = member.m_Level;
|
var level2 = member.m_Level;
|
||||||
if (level2 <= level)
|
if (level2 <= level)
|
||||||
{
|
{
|
||||||
return member2;
|
return nodes;
|
||||||
}
|
}
|
||||||
member2.Add(member);
|
nodes.Add(member);
|
||||||
}
|
}
|
||||||
return member2;
|
return nodes;
|
||||||
}
|
|
||||||
|
|
||||||
public static byte[] WriteUType(UType obj, List<TypeTreeNode> members)
|
|
||||||
{
|
|
||||||
var stream = new MemoryStream();
|
|
||||||
var write = new BinaryWriter(stream);
|
|
||||||
for (int i = 0; i < members.Count; i++)
|
|
||||||
{
|
|
||||||
var member = members[i];
|
|
||||||
var varNameStr = member.m_Name;
|
|
||||||
WriteValue(obj[varNameStr], members, write, ref i);
|
|
||||||
}
|
|
||||||
return stream.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void WriteValue(object value, List<TypeTreeNode> members, BinaryWriter write, ref int i)
|
|
||||||
{
|
|
||||||
var member = members[i];
|
|
||||||
var level = member.m_Level;
|
|
||||||
var varTypeStr = member.m_Type;
|
|
||||||
var align = (member.m_MetaFlag & 0x4000) != 0;
|
|
||||||
switch (varTypeStr)
|
|
||||||
{
|
|
||||||
case "SInt8":
|
|
||||||
write.Write((sbyte)value);
|
|
||||||
break;
|
|
||||||
case "UInt8":
|
|
||||||
write.Write((byte)value);
|
|
||||||
break;
|
|
||||||
case "short":
|
|
||||||
case "SInt16":
|
|
||||||
write.Write((short)value);
|
|
||||||
break;
|
|
||||||
case "UInt16":
|
|
||||||
case "unsigned short":
|
|
||||||
write.Write((ushort)value);
|
|
||||||
break;
|
|
||||||
case "int":
|
|
||||||
case "SInt32":
|
|
||||||
write.Write((int)value);
|
|
||||||
break;
|
|
||||||
case "UInt32":
|
|
||||||
case "unsigned int":
|
|
||||||
case "Type*":
|
|
||||||
write.Write((uint)value);
|
|
||||||
break;
|
|
||||||
case "long long":
|
|
||||||
case "SInt64":
|
|
||||||
write.Write((long)value);
|
|
||||||
break;
|
|
||||||
case "UInt64":
|
|
||||||
case "unsigned long long":
|
|
||||||
write.Write((ulong)value);
|
|
||||||
break;
|
|
||||||
case "float":
|
|
||||||
write.Write((float)value);
|
|
||||||
break;
|
|
||||||
case "double":
|
|
||||||
write.Write((double)value);
|
|
||||||
break;
|
|
||||||
case "bool":
|
|
||||||
write.Write((bool)value);
|
|
||||||
break;
|
|
||||||
case "string":
|
|
||||||
write.WriteAlignedString((string)value);
|
|
||||||
i += 3;
|
|
||||||
break;
|
|
||||||
case "map":
|
|
||||||
{
|
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
|
||||||
align = true;
|
|
||||||
var dic = (List<KeyValuePair<object, object>>)value;
|
|
||||||
var size = dic.Count;
|
|
||||||
write.Write(size);
|
|
||||||
var map = GetMembers(members, level, i);
|
|
||||||
i += map.Count - 1;
|
|
||||||
map.RemoveRange(0, 4);
|
|
||||||
var first = GetMembers(map, map[0].m_Level, 0);
|
|
||||||
map.RemoveRange(0, first.Count);
|
|
||||||
var second = map;
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
int tmp1 = 0;
|
|
||||||
int tmp2 = 0;
|
|
||||||
WriteValue(dic[j].Key, first, write, ref tmp1);
|
|
||||||
WriteValue(dic[j].Value, second, write, ref tmp2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "TypelessData":
|
|
||||||
{
|
|
||||||
var bytes = ((object[])value).Cast<byte>().ToArray();
|
|
||||||
var size = bytes.Length;
|
|
||||||
write.Write(size);
|
|
||||||
write.Write(bytes);
|
|
||||||
i += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
if (i != members.Count && members[i + 1].m_Type == "Array") //Array
|
|
||||||
{
|
|
||||||
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
|
|
||||||
align = true;
|
|
||||||
var list = (List<object>)value;
|
|
||||||
var size = list.Count;
|
|
||||||
write.Write(size);
|
|
||||||
var vector = GetMembers(members, level, i);
|
|
||||||
i += vector.Count - 1;
|
|
||||||
vector.RemoveRange(0, 3);
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
int tmp = 0;
|
|
||||||
WriteValue(list[j], vector, write, ref tmp);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else //Class
|
|
||||||
{
|
|
||||||
var @class = GetMembers(members, level, i);
|
|
||||||
@class.RemoveAt(0);
|
|
||||||
i += @class.Count;
|
|
||||||
var obj = (UType)value;
|
|
||||||
for (int j = 0; j < @class.Count; j++)
|
|
||||||
{
|
|
||||||
var classmember = @class[j];
|
|
||||||
var name = classmember.m_Name;
|
|
||||||
WriteValue(obj[name], @class, write, ref j);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (align)
|
|
||||||
write.AlignStream(4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,22 @@ namespace AssetStudio
|
|||||||
public string m_Name;
|
public string m_Name;
|
||||||
public int m_ByteSize;
|
public int m_ByteSize;
|
||||||
public int m_Index;
|
public int m_Index;
|
||||||
public int m_IsArray;
|
public int m_TypeFlags; //m_IsArray
|
||||||
public int m_Version;
|
public int m_Version;
|
||||||
public int m_MetaFlag;
|
public int m_MetaFlag;
|
||||||
public int m_Level;
|
public int m_Level;
|
||||||
public uint m_TypeStrOffset;
|
public uint m_TypeStrOffset;
|
||||||
public uint m_NameStrOffset;
|
public uint m_NameStrOffset;
|
||||||
|
public ulong m_RefTypeHash;
|
||||||
|
|
||||||
|
public TypeTreeNode() { }
|
||||||
|
|
||||||
|
public TypeTreeNode(string type, string name, int level, bool align)
|
||||||
|
{
|
||||||
|
m_Type = type;
|
||||||
|
m_Name = name;
|
||||||
|
m_Level = level;
|
||||||
|
m_MetaFlag = align ? 0x4000 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,155 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
public class UType : IDictionary<string, object>
|
|
||||||
{
|
|
||||||
private List<string> keys;
|
|
||||||
private List<object> values;
|
|
||||||
|
|
||||||
public UType()
|
|
||||||
{
|
|
||||||
keys = new List<string>();
|
|
||||||
values = new List<object>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GetValueIndex(string name)
|
|
||||||
{
|
|
||||||
for (int i = 0, n = keys.Count; i < n; i++)
|
|
||||||
{
|
|
||||||
if (string.Equals(keys[i], name, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetValue<T>(string key, out T value)
|
|
||||||
{
|
|
||||||
var index = GetValueIndex(key);
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
value = (T)values[index];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = default(T);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public object this[string key]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var index = GetValueIndex(key);
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
return values[index];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
var index = GetValueIndex(key);
|
|
||||||
if (index == -1)
|
|
||||||
{
|
|
||||||
keys.Add(key);
|
|
||||||
values.Add(value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
values[index] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ICollection<string> Keys => keys;
|
|
||||||
|
|
||||||
public ICollection<object> Values => values;
|
|
||||||
|
|
||||||
public int Count => keys.Count;
|
|
||||||
|
|
||||||
public bool IsReadOnly => false;
|
|
||||||
|
|
||||||
public void Add(string key, object value)
|
|
||||||
{
|
|
||||||
keys.Add(key);
|
|
||||||
values.Add(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
keys.Add(item.Key);
|
|
||||||
values.Add(item.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
keys.Clear();
|
|
||||||
values.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Contains(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ContainsKey(string key)
|
|
||||||
{
|
|
||||||
return GetValueIndex(key) != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
|
||||||
{
|
|
||||||
for (int i = 0, n = keys.Count; i < n; i++)
|
|
||||||
{
|
|
||||||
yield return new KeyValuePair<string, object>(keys[i], values[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(string key)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(KeyValuePair<string, object> item)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetValue(string key, out object value)
|
|
||||||
{
|
|
||||||
var index = GetValueIndex(key);
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
value = values[index];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
|
||||||
{
|
|
||||||
return GetEnumerator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+8
-54
@@ -1,18 +1,12 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Org.Brotli.Dec;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class WebFile
|
public class WebFile
|
||||||
{
|
{
|
||||||
public static byte[] gzipMagic = { 0x1f, 0x8b };
|
public StreamFile[] fileList;
|
||||||
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
|
||||||
public List<StreamFile> fileList = new List<StreamFile>();
|
|
||||||
|
|
||||||
private class WebData
|
private class WebData
|
||||||
{
|
{
|
||||||
@@ -23,50 +17,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public WebFile(EndianBinaryReader reader)
|
public WebFile(EndianBinaryReader reader)
|
||||||
{
|
{
|
||||||
var magic = reader.ReadBytes(2);
|
reader.Endian = EndianType.LittleEndian;
|
||||||
reader.Position = 0;
|
|
||||||
if (gzipMagic.SequenceEqual(magic))
|
|
||||||
{
|
|
||||||
var stream = new MemoryStream();
|
|
||||||
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
|
|
||||||
{
|
|
||||||
gs.CopyTo(stream);
|
|
||||||
}
|
|
||||||
stream.Position = 0;
|
|
||||||
using (var binaryReader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
ReadWebData(binaryReader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reader.Position = 0x20;
|
|
||||||
magic = reader.ReadBytes(6);
|
|
||||||
reader.Position = 0;
|
|
||||||
if (brotliMagic.SequenceEqual(magic))
|
|
||||||
{
|
|
||||||
var brotliStream = new BrotliInputStream(reader.BaseStream);
|
|
||||||
var stream = new MemoryStream();
|
|
||||||
brotliStream.CopyTo(stream);
|
|
||||||
stream.Position = 0;
|
|
||||||
using (var binaryReader = new BinaryReader(stream))
|
|
||||||
{
|
|
||||||
ReadWebData(binaryReader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reader.endian = EndianType.LittleEndian;
|
|
||||||
ReadWebData(reader);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReadWebData(BinaryReader reader)
|
|
||||||
{
|
|
||||||
var signature = reader.ReadStringToNull();
|
var signature = reader.ReadStringToNull();
|
||||||
if (signature != "UnityWebData1.0")
|
|
||||||
return;
|
|
||||||
var headLength = reader.ReadInt32();
|
var headLength = reader.ReadInt32();
|
||||||
var dataList = new List<WebData>();
|
var dataList = new List<WebData>();
|
||||||
while (reader.BaseStream.Position < headLength)
|
while (reader.BaseStream.Position < headLength)
|
||||||
@@ -78,14 +30,16 @@ namespace AssetStudio
|
|||||||
data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));
|
data.path = Encoding.UTF8.GetString(reader.ReadBytes(pathLength));
|
||||||
dataList.Add(data);
|
dataList.Add(data);
|
||||||
}
|
}
|
||||||
|
fileList = new StreamFile[dataList.Count];
|
||||||
foreach (var data in dataList)
|
for (int i = 0; i < dataList.Count; i++)
|
||||||
{
|
{
|
||||||
|
var data = dataList[i];
|
||||||
var file = new StreamFile();
|
var file = new StreamFile();
|
||||||
|
file.path = data.path;
|
||||||
file.fileName = Path.GetFileName(data.path);
|
file.fileName = Path.GetFileName(data.path);
|
||||||
reader.BaseStream.Position = data.dataOffset;
|
reader.BaseStream.Position = data.dataOffset;
|
||||||
file.stream = new MemoryStream(reader.ReadBytes(data.dataLength));
|
file.stream = new MemoryStream(reader.ReadBytes(data.dataLength));
|
||||||
fileList.Add(file);
|
fileList[i] = file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
using namespace System;
|
|
||||||
using namespace System::Reflection;
|
|
||||||
using namespace System::Runtime::CompilerServices;
|
|
||||||
using namespace System::Runtime::InteropServices;
|
|
||||||
using namespace System::Security::Permissions;
|
|
||||||
|
|
||||||
[assembly:AssemblyTitleAttribute(L"AssetStudioFBX")];
|
|
||||||
[assembly:AssemblyDescriptionAttribute(L"")];
|
|
||||||
[assembly:AssemblyConfigurationAttribute(L"")];
|
|
||||||
[assembly:AssemblyCompanyAttribute(L"")];
|
|
||||||
[assembly:AssemblyProductAttribute(L"AssetStudioFBX")];
|
|
||||||
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2018")];
|
|
||||||
[assembly:AssemblyTrademarkAttribute(L"")];
|
|
||||||
[assembly:AssemblyCultureAttribute(L"")];
|
|
||||||
|
|
||||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
|
||||||
|
|
||||||
[assembly:ComVisible(false)];
|
|
||||||
|
|
||||||
[assembly:CLSCompliantAttribute(true)];
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#include "AssetStudioFBX.h"
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
char* Fbx::StringToCharArray(String^ s)
|
|
||||||
{
|
|
||||||
return (char*)(void*)Marshal::StringToHGlobalAnsi(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Init(FbxManager** pSdkManager, FbxScene** pScene)
|
|
||||||
{
|
|
||||||
*pSdkManager = FbxManager::Create();
|
|
||||||
if (!pSdkManager)
|
|
||||||
{
|
|
||||||
throw gcnew Exception(gcnew String("Unable to create the FBX SDK manager"));
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxIOSettings* ios = FbxIOSettings::Create(*pSdkManager, IOSROOT);
|
|
||||||
(*pSdkManager)->SetIOSettings(ios);
|
|
||||||
*pScene = FbxScene::Create(*pSdkManager, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 Fbx::QuaternionToEuler(Quaternion q)
|
|
||||||
{
|
|
||||||
FbxAMatrix lMatrixRot;
|
|
||||||
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
|
|
||||||
FbxVector4 lEuler = lMatrixRot.GetR();
|
|
||||||
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quaternion Fbx::EulerToQuaternion(Vector3 v)
|
|
||||||
{
|
|
||||||
FbxAMatrix lMatrixRot;
|
|
||||||
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
|
|
||||||
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
|
|
||||||
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <fbxsdk.h>
|
|
||||||
|
|
||||||
#ifdef IOS_REF
|
|
||||||
#undef IOS_REF
|
|
||||||
#define IOS_REF (*(pSdkManager->GetIOSettings()))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace System;
|
|
||||||
using namespace System::Collections::Generic;
|
|
||||||
using namespace System::IO;
|
|
||||||
using namespace System::Runtime::InteropServices;
|
|
||||||
|
|
||||||
#define WITH_MARSHALLED_STRING(name,str,block)\
|
|
||||||
{ \
|
|
||||||
char* name; \
|
|
||||||
try \
|
|
||||||
{ \
|
|
||||||
name = StringToCharArray(str); \
|
|
||||||
block \
|
|
||||||
} \
|
|
||||||
finally \
|
|
||||||
{ \
|
|
||||||
Marshal::FreeHGlobal((IntPtr)name); \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* FBXVersion[] =
|
|
||||||
{
|
|
||||||
FBX_2010_00_COMPATIBLE,
|
|
||||||
FBX_2011_00_COMPATIBLE,
|
|
||||||
FBX_2012_00_COMPATIBLE,
|
|
||||||
FBX_2013_00_COMPATIBLE,
|
|
||||||
FBX_2014_00_COMPATIBLE,
|
|
||||||
FBX_2016_00_COMPATIBLE
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace AssetStudio {
|
|
||||||
|
|
||||||
public ref class Fbx
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static Vector3 QuaternionToEuler(Quaternion q);
|
|
||||||
static Quaternion EulerToQuaternion(Vector3 v);
|
|
||||||
static char* StringToCharArray(String^ s);
|
|
||||||
static void Init(FbxManager** pSdkManager, FbxScene** pScene);
|
|
||||||
|
|
||||||
ref class Exporter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii);
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool exportSkins;
|
|
||||||
float boneSize;
|
|
||||||
IImported^ imported;
|
|
||||||
HashSet<String^>^ framePaths;
|
|
||||||
Dictionary<ImportedFrame^, size_t>^ frameToNode;
|
|
||||||
List<ImportedFrame^>^ meshFrames;
|
|
||||||
|
|
||||||
char* cDest;
|
|
||||||
FbxManager* pSdkManager;
|
|
||||||
FbxScene* pScene;
|
|
||||||
FbxExporter* pExporter;
|
|
||||||
FbxArray<FbxSurfacePhong*>* pMaterials;
|
|
||||||
FbxArray<FbxFileTexture*>* pTextures;
|
|
||||||
FbxPose* pBindPose;
|
|
||||||
|
|
||||||
Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii);
|
|
||||||
~Exporter();
|
|
||||||
|
|
||||||
void Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop);
|
|
||||||
void SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones);
|
|
||||||
HashSet<String^>^ SearchHierarchy();
|
|
||||||
void SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames);
|
|
||||||
void SetJointsFromImportedMeshes(bool allBones);
|
|
||||||
void ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame);
|
|
||||||
void ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList);
|
|
||||||
FbxFileTexture* ExportTexture(ImportedTexture^ matTex);
|
|
||||||
void ExportAnimations(bool eulerFilter, float filterValue, bool flatInbetween);
|
|
||||||
void ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween);
|
|
||||||
void ExportMorphs(bool morphMask, bool flatInbetween);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Debug|x64">
|
|
||||||
<Configuration>Debug</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|Win32">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>Win32</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
<ProjectConfiguration Include="Release|x64">
|
|
||||||
<Configuration>Release</Configuration>
|
|
||||||
<Platform>x64</Platform>
|
|
||||||
</ProjectConfiguration>
|
|
||||||
</ItemGroup>
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
|
||||||
<ProjectGuid>{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}</ProjectGuid>
|
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
|
||||||
<Keyword>ManagedCProj</Keyword>
|
|
||||||
<RootNamespace>AssetStudioFBX</RootNamespace>
|
|
||||||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
|
||||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
|
||||||
<PlatformToolset>v140</PlatformToolset>
|
|
||||||
<CLRSupport>true</CLRSupport>
|
|
||||||
<CharacterSet>Unicode</CharacterSet>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
|
||||||
<ImportGroup Label="ExtensionSettings">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="Shared">
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
|
||||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
|
||||||
</ImportGroup>
|
|
||||||
<PropertyGroup Label="UserMacros" />
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<LinkIncremental>true</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<LinkIncremental>false</LinkIncremental>
|
|
||||||
</PropertyGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<Optimization>Disabled</Optimization>
|
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>Level3</WarningLevel>
|
|
||||||
<PreprocessorDefinitions>FBXSDK_SHARED;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
|
||||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
<Link>
|
|
||||||
<AdditionalDependencies>libfbxsdk.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
|
||||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2019.0\lib\vs2015\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
|
||||||
</Link>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="AssemblyInfo.cpp" />
|
|
||||||
<ClCompile Include="AssetStudioFBX.cpp" />
|
|
||||||
<ClCompile Include="AssetStudioFBXExporter.cpp" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="AssetStudioFBX.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
|
||||||
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
|
||||||
<ImportGroup Label="ExtensionTargets">
|
|
||||||
</ImportGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<Filter Include="源文件">
|
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
|
||||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="头文件">
|
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
|
||||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="AssemblyInfo.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="AssetStudioFBX.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="AssetStudioFBXExporter.cpp">
|
|
||||||
<Filter>源文件</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="AssetStudioFBX.h">
|
|
||||||
<Filter>头文件</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,969 +0,0 @@
|
|||||||
#include "AssetStudioFBX.h"
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
void Fbx::Exporter::Export(String^ path, IImported^ imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii)
|
|
||||||
{
|
|
||||||
FileInfo^ file = gcnew FileInfo(path);
|
|
||||||
DirectoryInfo^ dir = file->Directory;
|
|
||||||
if (!dir->Exists)
|
|
||||||
{
|
|
||||||
dir->Create();
|
|
||||||
}
|
|
||||||
String^ currentDir = Directory::GetCurrentDirectory();
|
|
||||||
Directory::SetCurrentDirectory(dir->FullName);
|
|
||||||
path = Path::GetFileName(path);
|
|
||||||
|
|
||||||
Exporter^ exporter = gcnew Exporter(path, imported, allFrames, allBones, skins, boneSize, scaleFactor, versionIndex, isAscii);
|
|
||||||
//TODO exporter->ExportMorphs(false, flatInbetween);
|
|
||||||
exporter->ExportAnimations(eulerFilter, filterPrecision, flatInbetween);
|
|
||||||
exporter->pExporter->Export(exporter->pScene);
|
|
||||||
delete exporter;
|
|
||||||
|
|
||||||
Directory::SetCurrentDirectory(currentDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
Fbx::Exporter::Exporter(String^ path, IImported^ imported, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, int versionIndex, bool isAscii)
|
|
||||||
{
|
|
||||||
this->imported = imported;
|
|
||||||
exportSkins = skins;
|
|
||||||
this->boneSize = boneSize;
|
|
||||||
|
|
||||||
cDest = NULL;
|
|
||||||
pSdkManager = NULL;
|
|
||||||
pScene = NULL;
|
|
||||||
pExporter = NULL;
|
|
||||||
pMaterials = NULL;
|
|
||||||
pTextures = NULL;
|
|
||||||
|
|
||||||
pin_ptr<FbxManager*> pSdkManagerPin = &pSdkManager;
|
|
||||||
pin_ptr<FbxScene*> pScenePin = &pScene;
|
|
||||||
Init(pSdkManagerPin, pScenePin);
|
|
||||||
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_MATERIAL, true);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_TEXTURE, true);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_EMBEDDED, false);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_SHAPE, true);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_GOBO, true);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_ANIMATION, true);
|
|
||||||
IOS_REF.SetBoolProp(EXP_FBX_GLOBAL_SETTINGS, true);
|
|
||||||
|
|
||||||
FbxGlobalSettings& globalSettings = pScene->GetGlobalSettings();
|
|
||||||
globalSettings.SetSystemUnit(FbxSystemUnit(scaleFactor));
|
|
||||||
|
|
||||||
cDest = StringToCharArray(path);
|
|
||||||
pExporter = FbxExporter::Create(pScene, "");
|
|
||||||
|
|
||||||
int pFileFormat = 0;
|
|
||||||
if (versionIndex == 0)
|
|
||||||
{
|
|
||||||
pFileFormat = 3;
|
|
||||||
if (isAscii)
|
|
||||||
{
|
|
||||||
pFileFormat = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pExporter->SetFileExportVersion(FBXVersion[versionIndex]);
|
|
||||||
if (isAscii)
|
|
||||||
{
|
|
||||||
pFileFormat = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pExporter->Initialize(cDest, pFileFormat, pSdkManager->GetIOSettings()))
|
|
||||||
{
|
|
||||||
throw gcnew Exception(gcnew String("Failed to initialize FbxExporter: ") + gcnew String(pExporter->GetStatus().GetErrorString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
framePaths = nullptr;
|
|
||||||
if (!allFrames)
|
|
||||||
{
|
|
||||||
framePaths = SearchHierarchy();
|
|
||||||
if (!framePaths)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pBindPose = FbxPose::Create(pScene, "BindPose");
|
|
||||||
pBindPose->SetIsBindPose(true);
|
|
||||||
|
|
||||||
frameToNode = gcnew Dictionary<ImportedFrame^, size_t>();
|
|
||||||
meshFrames = imported->MeshList != nullptr ? gcnew List<ImportedFrame^>() : nullptr;
|
|
||||||
ExportFrame(pScene->GetRootNode(), imported->RootFrame);
|
|
||||||
|
|
||||||
if (imported->MeshList != nullptr)
|
|
||||||
{
|
|
||||||
SetJointsFromImportedMeshes(allBones);
|
|
||||||
|
|
||||||
pMaterials = new FbxArray<FbxSurfacePhong*>();
|
|
||||||
pTextures = new FbxArray<FbxFileTexture*>();
|
|
||||||
pMaterials->Reserve(imported->MaterialList->Count);
|
|
||||||
pTextures->Reserve(imported->TextureList->Count);
|
|
||||||
|
|
||||||
for (int i = 0; i < meshFrames->Count; i++)
|
|
||||||
{
|
|
||||||
auto meshFram = meshFrames[i];
|
|
||||||
FbxNode* meshNode = (FbxNode*)frameToNode[meshFram];
|
|
||||||
ImportedMesh^ mesh = ImportedHelpers::FindMesh(meshFram->Path, imported->MeshList);
|
|
||||||
ExportMesh(meshNode, mesh);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetJointsNode(imported->RootFrame, nullptr, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Fbx::Exporter::~Exporter()
|
|
||||||
{
|
|
||||||
imported = nullptr;
|
|
||||||
if (framePaths != nullptr)
|
|
||||||
{
|
|
||||||
framePaths->Clear();
|
|
||||||
}
|
|
||||||
if (frameToNode != nullptr)
|
|
||||||
{
|
|
||||||
frameToNode->Clear();
|
|
||||||
}
|
|
||||||
if (meshFrames != nullptr)
|
|
||||||
{
|
|
||||||
meshFrames->Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pMaterials != NULL)
|
|
||||||
{
|
|
||||||
delete pMaterials;
|
|
||||||
}
|
|
||||||
if (pTextures != NULL)
|
|
||||||
{
|
|
||||||
delete pTextures;
|
|
||||||
}
|
|
||||||
if (pExporter != NULL)
|
|
||||||
{
|
|
||||||
pExporter->Destroy();
|
|
||||||
}
|
|
||||||
if (pScene != NULL)
|
|
||||||
{
|
|
||||||
pScene->Destroy();
|
|
||||||
}
|
|
||||||
if (pSdkManager != NULL)
|
|
||||||
{
|
|
||||||
pSdkManager->Destroy();
|
|
||||||
}
|
|
||||||
if (cDest != NULL)
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)cDest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::SetJointsNode(ImportedFrame^ frame, HashSet<String^>^ bonePaths, bool allBones)
|
|
||||||
{
|
|
||||||
size_t pointer;
|
|
||||||
if (frameToNode->TryGetValue(frame, pointer))
|
|
||||||
{
|
|
||||||
auto pNode = (FbxNode*)pointer;
|
|
||||||
if (allBones || bonePaths->Contains(frame->Path))
|
|
||||||
{
|
|
||||||
FbxSkeleton* pJoint = FbxSkeleton::Create(pScene, "");
|
|
||||||
pJoint->Size.Set(FbxDouble(boneSize));
|
|
||||||
pJoint->SetSkeletonType(FbxSkeleton::eLimbNode);
|
|
||||||
pNode->SetNodeAttribute(pJoint);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FbxNull* pNull = FbxNull::Create(pScene, "");
|
|
||||||
if (pNode->GetChildCount() > 0)
|
|
||||||
{
|
|
||||||
pNull->Look.Set(FbxNull::eNone);
|
|
||||||
}
|
|
||||||
|
|
||||||
pNode->SetNodeAttribute(pNull);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int i = 0; i < frame->Count; i++)
|
|
||||||
{
|
|
||||||
SetJointsNode(frame[i], bonePaths, allBones);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HashSet<String^>^ Fbx::Exporter::SearchHierarchy()
|
|
||||||
{
|
|
||||||
if (imported->MeshList == nullptr || imported->MeshList->Count == 0)
|
|
||||||
{
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
HashSet<String^>^ exportFrames = gcnew HashSet<String^>();
|
|
||||||
SearchHierarchy(imported->RootFrame, exportFrames);
|
|
||||||
return exportFrames;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::SearchHierarchy(ImportedFrame^ frame, HashSet<String^>^ exportFrames)
|
|
||||||
{
|
|
||||||
ImportedMesh^ meshListSome = ImportedHelpers::FindMesh(frame->Path, imported->MeshList);
|
|
||||||
if (meshListSome != nullptr)
|
|
||||||
{
|
|
||||||
ImportedFrame^ parent = frame;
|
|
||||||
while (parent != nullptr)
|
|
||||||
{
|
|
||||||
exportFrames->Add(parent->Path);
|
|
||||||
parent = parent->Parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ImportedBone^>^ boneList = meshListSome->BoneList;
|
|
||||||
if (boneList != nullptr)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
|
||||||
{
|
|
||||||
if (!exportFrames->Contains(boneList[i]->Path))
|
|
||||||
{
|
|
||||||
ImportedFrame^ boneParent = imported->RootFrame->FindFrameByPath(boneList[i]->Path);
|
|
||||||
while (boneParent != nullptr)
|
|
||||||
{
|
|
||||||
exportFrames->Add(boneParent->Path);
|
|
||||||
boneParent = boneParent->Parent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < frame->Count; i++)
|
|
||||||
{
|
|
||||||
SearchHierarchy(frame[i], exportFrames);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::SetJointsFromImportedMeshes(bool allBones)
|
|
||||||
{
|
|
||||||
if (!exportSkins)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HashSet<String^>^ bonePaths = gcnew HashSet<String^>();
|
|
||||||
for (int i = 0; i < imported->MeshList->Count; i++)
|
|
||||||
{
|
|
||||||
ImportedMesh^ meshList = imported->MeshList[i];
|
|
||||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
|
||||||
if (boneList != nullptr)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < boneList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedBone^ bone = boneList[j];
|
|
||||||
bonePaths->Add(bone->Path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetJointsNode(imported->RootFrame, bonePaths, allBones);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportFrame(FbxNode* pParentNode, ImportedFrame^ frame)
|
|
||||||
{
|
|
||||||
if (framePaths == nullptr || framePaths->Contains(frame->Path))
|
|
||||||
{
|
|
||||||
FbxNode* pFrameNode;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pName,
|
|
||||||
frame->Name,
|
|
||||||
pFrameNode = FbxNode::Create(pScene, pName);
|
|
||||||
);
|
|
||||||
|
|
||||||
pFrameNode->LclScaling.Set(FbxDouble3(frame->LocalScale.X, frame->LocalScale.Y, frame->LocalScale.Z));
|
|
||||||
pFrameNode->LclRotation.Set(FbxDouble3(frame->LocalRotation.X, frame->LocalRotation.Y, frame->LocalRotation.Z));
|
|
||||||
pFrameNode->LclTranslation.Set(FbxDouble3(frame->LocalPosition.X, frame->LocalPosition.Y, frame->LocalPosition.Z));
|
|
||||||
pFrameNode->SetPreferedAngle(pFrameNode->LclRotation.Get());
|
|
||||||
pParentNode->AddChild(pFrameNode);
|
|
||||||
pBindPose->Add(pFrameNode, pFrameNode->EvaluateGlobalTransform());
|
|
||||||
|
|
||||||
if (imported->MeshList != nullptr && ImportedHelpers::FindMesh(frame->Path, imported->MeshList) != nullptr)
|
|
||||||
{
|
|
||||||
meshFrames->Add(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
frameToNode->Add(frame, (size_t)pFrameNode);
|
|
||||||
|
|
||||||
for (int i = 0; i < frame->Count; i++)
|
|
||||||
{
|
|
||||||
ExportFrame(pFrameNode, frame[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMesh(FbxNode* pFrameNode, ImportedMesh^ meshList)
|
|
||||||
{
|
|
||||||
List<ImportedBone^>^ boneList = meshList->BoneList;
|
|
||||||
bool hasBones;
|
|
||||||
if (exportSkins && boneList != nullptr)
|
|
||||||
{
|
|
||||||
hasBones = boneList->Count > 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hasBones = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxArray<FbxNode*>* pBoneNodeList = nullptr;
|
|
||||||
FbxArray<FbxCluster*>* pClusterArray = nullptr;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (hasBones)
|
|
||||||
{
|
|
||||||
pBoneNodeList = new FbxArray<FbxNode*>();
|
|
||||||
pBoneNodeList->Reserve(boneList->Count);
|
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
|
||||||
{
|
|
||||||
auto bone = boneList[i];
|
|
||||||
auto frame = imported->RootFrame->FindFrameByPath(bone->Path);
|
|
||||||
auto frameNode = (FbxNode*)frameToNode[frame];
|
|
||||||
pBoneNodeList->Add(frameNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
pClusterArray = new FbxArray<FbxCluster*>();
|
|
||||||
pClusterArray->Reserve(boneList->Count);
|
|
||||||
for (int i = 0; i < boneList->Count; i++)
|
|
||||||
{
|
|
||||||
FbxNode* pNode = pBoneNodeList->GetAt(i);
|
|
||||||
FbxString lClusterName = pNode->GetNameOnly() + FbxString("Cluster");
|
|
||||||
FbxCluster* pCluster = FbxCluster::Create(pScene, lClusterName.Buffer());
|
|
||||||
pCluster->SetLink(pNode);
|
|
||||||
pCluster->SetLinkMode(FbxCluster::eTotalOne);
|
|
||||||
pClusterArray->Add(pCluster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxMesh* pMesh = FbxMesh::Create(pScene, "");
|
|
||||||
pFrameNode->SetNodeAttribute(pMesh);
|
|
||||||
|
|
||||||
int vertexCount = 0;
|
|
||||||
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
|
||||||
{
|
|
||||||
vertexCount += meshList->SubmeshList[i]->VertexList->Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMesh->InitControlPoints(vertexCount);
|
|
||||||
FbxVector4* pControlPoints = pMesh->GetControlPoints();
|
|
||||||
|
|
||||||
FbxGeometryElementNormal* lGeometryElementNormal = pMesh->CreateElementNormal();
|
|
||||||
lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
|
|
||||||
FbxGeometryElementUV* lGeometryElementUV = pMesh->CreateElementUV("UV0");
|
|
||||||
lGeometryElementUV->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementUV->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
|
|
||||||
FbxGeometryElementTangent* lGeometryElementTangent = pMesh->CreateElementTangent();
|
|
||||||
lGeometryElementTangent->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementTangent->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
|
|
||||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = nullptr;
|
|
||||||
bool vertexColours = vertexCount > 0 && dynamic_cast<ImportedVertexWithColour^>(meshList->SubmeshList[0]->VertexList[0]) != nullptr;
|
|
||||||
if (vertexColours)
|
|
||||||
{
|
|
||||||
lGeometryElementVertexColor = pMesh->CreateElementVertexColor();
|
|
||||||
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxGeometryElementMaterial* lGeometryElementMaterial = pMesh->CreateElementMaterial();
|
|
||||||
lGeometryElementMaterial->SetMappingMode(FbxGeometryElement::eByPolygon);
|
|
||||||
lGeometryElementMaterial->SetReferenceMode(FbxGeometryElement::eIndexToDirect);
|
|
||||||
|
|
||||||
int firstVertex = 0;
|
|
||||||
for (int i = 0; i < meshList->SubmeshList->Count; i++)
|
|
||||||
{
|
|
||||||
ImportedSubmesh^ meshObj = meshList->SubmeshList[i];
|
|
||||||
List<ImportedVertex^>^ vertexList = meshObj->VertexList;
|
|
||||||
List<ImportedFace^>^ faceList = meshObj->FaceList;
|
|
||||||
|
|
||||||
int materialIndex = 0;
|
|
||||||
ImportedMaterial^ mat = ImportedHelpers::FindMaterial(meshObj->Material, imported->MaterialList);
|
|
||||||
if (mat != nullptr)
|
|
||||||
{
|
|
||||||
char* pMatName = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pMatName = StringToCharArray(mat->Name);
|
|
||||||
int foundMat = -1;
|
|
||||||
for (int j = 0; j < pMaterials->GetCount(); j++)
|
|
||||||
{
|
|
||||||
FbxSurfacePhong* pMatTemp = pMaterials->GetAt(j);
|
|
||||||
if (strcmp(pMatTemp->GetName(), pMatName) == 0)
|
|
||||||
{
|
|
||||||
foundMat = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxSurfacePhong* pMat;
|
|
||||||
if (foundMat >= 0)
|
|
||||||
{
|
|
||||||
pMat = pMaterials->GetAt(foundMat);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FbxString lShadingName = "Phong";
|
|
||||||
Color diffuse = mat->Diffuse;
|
|
||||||
Color ambient = mat->Ambient;
|
|
||||||
Color emissive = mat->Emissive;
|
|
||||||
Color specular = mat->Specular;
|
|
||||||
Color reflection = mat->Reflection;
|
|
||||||
pMat = FbxSurfacePhong::Create(pScene, pMatName);
|
|
||||||
pMat->Diffuse.Set(FbxDouble3(diffuse.R, diffuse.G, diffuse.B));
|
|
||||||
pMat->DiffuseFactor.Set(FbxDouble(diffuse.A));
|
|
||||||
pMat->Ambient.Set(FbxDouble3(ambient.R, ambient.G, ambient.B));
|
|
||||||
pMat->AmbientFactor.Set(FbxDouble(ambient.A));
|
|
||||||
pMat->Emissive.Set(FbxDouble3(emissive.R, emissive.G, emissive.B));
|
|
||||||
pMat->EmissiveFactor.Set(FbxDouble(emissive.A));
|
|
||||||
pMat->Specular.Set(FbxDouble3(specular.R, specular.G, specular.B));
|
|
||||||
pMat->SpecularFactor.Set(FbxDouble(specular.A));
|
|
||||||
pMat->Reflection.Set(FbxDouble3(reflection.R, reflection.G, reflection.B));
|
|
||||||
pMat->ReflectionFactor.Set(FbxDouble(reflection.A));
|
|
||||||
pMat->Shininess.Set(FbxDouble(mat->Shininess));
|
|
||||||
pMat->TransparencyFactor.Set(FbxDouble(mat->Transparency));
|
|
||||||
pMat->ShadingModel.Set(lShadingName);
|
|
||||||
pMaterials->Add(pMat);
|
|
||||||
}
|
|
||||||
materialIndex = pFrameNode->AddMaterial(pMat);
|
|
||||||
|
|
||||||
bool hasTexture = false;
|
|
||||||
|
|
||||||
for each (ImportedMaterialTexture^ texture in mat->Textures)
|
|
||||||
{
|
|
||||||
auto pTexture = ExportTexture(ImportedHelpers::FindTexture(texture->Name, imported->TextureList));
|
|
||||||
if (pTexture != NULL)
|
|
||||||
{
|
|
||||||
if (texture->Dest == 0)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Diffuse);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 1)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->NormalMap);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 2)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Specular);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
else if (texture->Dest == 3)
|
|
||||||
{
|
|
||||||
LinkTexture(texture, pTexture, pMat->Bump);
|
|
||||||
hasTexture = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasTexture)
|
|
||||||
{
|
|
||||||
pFrameNode->SetShadingMode(FbxNode::eTextureShading);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pMatName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < vertexList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedVertex^ vertex = vertexList[j];
|
|
||||||
|
|
||||||
Vector3 coords = vertex->Position;
|
|
||||||
pControlPoints[j + firstVertex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
|
||||||
|
|
||||||
Vector3 normal = vertex->Normal;
|
|
||||||
lGeometryElementNormal->GetDirectArray().Add(FbxVector4(normal.X, normal.Y, normal.Z, 0));
|
|
||||||
|
|
||||||
array<float>^ uv = vertex->UV;
|
|
||||||
if (uv != nullptr)
|
|
||||||
{
|
|
||||||
lGeometryElementUV->GetDirectArray().Add(FbxVector2(uv[0], uv[1]));
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector4 tangent = vertex->Tangent;
|
|
||||||
lGeometryElementTangent->GetDirectArray().Add(FbxVector4(tangent.X, tangent.Y, tangent.Z, tangent.W));
|
|
||||||
|
|
||||||
if (vertexColours)
|
|
||||||
{
|
|
||||||
ImportedVertexWithColour^ vert = (ImportedVertexWithColour^)vertexList[j];
|
|
||||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(vert->Colour.R, vert->Colour.G, vert->Colour.B, vert->Colour.A));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBones && vertex->BoneIndices != nullptr)
|
|
||||||
{
|
|
||||||
auto boneIndices = vertex->BoneIndices;
|
|
||||||
auto weights4 = vertex->Weights;
|
|
||||||
for (int k = 0; k < 4; k++)
|
|
||||||
{
|
|
||||||
if (boneIndices[k] < boneList->Count && weights4[k] > 0)
|
|
||||||
{
|
|
||||||
FbxCluster* pCluster = pClusterArray->GetAt(boneIndices[k]);
|
|
||||||
pCluster->AddControlPointIndex(j + firstVertex, weights4[k]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < faceList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedFace^ face = faceList[j];
|
|
||||||
pMesh->BeginPolygon(materialIndex);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[0] + firstVertex);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[1] + firstVertex);
|
|
||||||
pMesh->AddPolygon(face->VertexIndices[2] + firstVertex);
|
|
||||||
pMesh->EndPolygon();
|
|
||||||
}
|
|
||||||
|
|
||||||
firstVertex += vertexList->Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasBones)
|
|
||||||
{
|
|
||||||
FbxSkin* pSkin = FbxSkin::Create(pScene, "");
|
|
||||||
FbxAMatrix lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
|
||||||
for (int j = 0; j < boneList->Count; j++)
|
|
||||||
{
|
|
||||||
FbxCluster* pCluster = pClusterArray->GetAt(j);
|
|
||||||
if (pCluster->GetControlPointIndicesCount() > 0)
|
|
||||||
{
|
|
||||||
auto boneMatrix = boneList[j]->Matrix;
|
|
||||||
FbxAMatrix lBoneMatrix;
|
|
||||||
for (int m = 0; m < 4; m++)
|
|
||||||
{
|
|
||||||
for (int n = 0; n < 4; n++)
|
|
||||||
{
|
|
||||||
lBoneMatrix.mData[m][n] = boneMatrix[m, n];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pCluster->SetTransformMatrix(lMeshMatrix);
|
|
||||||
pCluster->SetTransformLinkMatrix(lMeshMatrix * lBoneMatrix.Inverse());
|
|
||||||
|
|
||||||
pSkin->AddCluster(pCluster);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pSkin->GetClusterCount() > 0)
|
|
||||||
{
|
|
||||||
pMesh->AddDeformer(pSkin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (pBoneNodeList != NULL)
|
|
||||||
{
|
|
||||||
delete pBoneNodeList;
|
|
||||||
}
|
|
||||||
if (pClusterArray != NULL)
|
|
||||||
{
|
|
||||||
delete pClusterArray;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxFileTexture* Fbx::Exporter::ExportTexture(ImportedTexture^ matTex)
|
|
||||||
{
|
|
||||||
FbxFileTexture* pTex = NULL;
|
|
||||||
|
|
||||||
if (matTex != nullptr)
|
|
||||||
{
|
|
||||||
String^ matTexName = matTex->Name;
|
|
||||||
char* pTexName = NULL;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pTexName = StringToCharArray(matTexName);
|
|
||||||
int foundTex = -1;
|
|
||||||
for (int i = 0; i < pTextures->GetCount(); i++)
|
|
||||||
{
|
|
||||||
FbxFileTexture* pTexTemp = pTextures->GetAt(i);
|
|
||||||
if (strcmp(pTexTemp->GetName(), pTexName) == 0)
|
|
||||||
{
|
|
||||||
foundTex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundTex >= 0)
|
|
||||||
{
|
|
||||||
pTex = pTextures->GetAt(foundTex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pTex = FbxFileTexture::Create(pScene, pTexName);
|
|
||||||
pTex->SetFileName(pTexName);
|
|
||||||
pTex->SetTextureUse(FbxTexture::eStandard);
|
|
||||||
pTex->SetMappingType(FbxTexture::eUV);
|
|
||||||
pTex->SetMaterialUse(FbxFileTexture::eModelMaterial);
|
|
||||||
pTex->SetSwapUV(false);
|
|
||||||
pTex->SetTranslation(0.0, 0.0);
|
|
||||||
pTex->SetScale(1.0, 1.0);
|
|
||||||
pTex->SetRotation(0.0, 0.0);
|
|
||||||
pTextures->Add(pTex);
|
|
||||||
|
|
||||||
String^ path = Path::GetDirectoryName(gcnew String(pExporter->GetFileName().Buffer()));
|
|
||||||
if (path == String::Empty)
|
|
||||||
{
|
|
||||||
path = ".";
|
|
||||||
}
|
|
||||||
FileInfo^ file = gcnew FileInfo(path + Path::DirectorySeparatorChar + Path::GetFileName(matTex->Name));
|
|
||||||
DirectoryInfo^ dir = file->Directory;
|
|
||||||
if (!dir->Exists)
|
|
||||||
{
|
|
||||||
dir->Create();
|
|
||||||
}
|
|
||||||
BinaryWriter^ writer = gcnew BinaryWriter(file->Create());
|
|
||||||
writer->Write(matTex->Data);
|
|
||||||
writer->Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pTexName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pTex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::LinkTexture(ImportedMaterialTexture^ texture, FbxFileTexture* pTexture, FbxProperty& prop)
|
|
||||||
{
|
|
||||||
pTexture->SetTranslation(texture->Offset.X, texture->Offset.Y);
|
|
||||||
pTexture->SetScale(texture->Scale.X, texture->Scale.Y);
|
|
||||||
prop.ConnectSrcObject(pTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportAnimations(bool eulerFilter, float filterPrecision, bool flatInbetween)
|
|
||||||
{
|
|
||||||
auto importedAnimationList = imported->AnimationList;
|
|
||||||
if (importedAnimationList == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FbxAnimCurveFilterUnroll* lFilter = eulerFilter ? new FbxAnimCurveFilterUnroll() : NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < importedAnimationList->Count; i++)
|
|
||||||
{
|
|
||||||
auto importedAnimation = importedAnimationList[i];
|
|
||||||
FbxString kTakeName;
|
|
||||||
if (importedAnimation->Name)
|
|
||||||
{
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pClipName,
|
|
||||||
importedAnimation->Name,
|
|
||||||
kTakeName = FbxString(pClipName);
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
kTakeName = FbxString("Take") + FbxString(i);
|
|
||||||
}
|
|
||||||
ExportKeyframedAnimation(importedAnimation, kTakeName, lFilter, filterPrecision, flatInbetween);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportKeyframedAnimation(ImportedKeyframedAnimation^ parser, FbxString& kTakeName, FbxAnimCurveFilterUnroll* eulerFilter, float filterPrecision, bool flatInbetween)
|
|
||||||
{
|
|
||||||
List<ImportedAnimationKeyframedTrack^>^ pAnimationList = parser->TrackList;
|
|
||||||
|
|
||||||
char* lTakeName = kTakeName.Buffer();
|
|
||||||
|
|
||||||
FbxAnimStack* lAnimStack = FbxAnimStack::Create(pScene, lTakeName);
|
|
||||||
FbxAnimLayer* lAnimLayer = FbxAnimLayer::Create(pScene, "Base Layer");
|
|
||||||
lAnimStack->AddMember(lAnimLayer);
|
|
||||||
|
|
||||||
for (int j = 0; j < pAnimationList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedAnimationKeyframedTrack^ keyframeList = pAnimationList[j];
|
|
||||||
if (keyframeList->Path == nullptr)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto frame = imported->RootFrame->FindFrameByPath(keyframeList->Path);
|
|
||||||
if (frame != nullptr)
|
|
||||||
{
|
|
||||||
FbxNode* pNode = (FbxNode*)frameToNode[frame];
|
|
||||||
|
|
||||||
FbxAnimCurve* lCurveSX = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
|
||||||
FbxAnimCurve* lCurveSY = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveSZ = pNode->LclScaling.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
FbxAnimCurve* lCurveRX = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
|
||||||
FbxAnimCurve* lCurveRY = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveRZ = pNode->LclRotation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
FbxAnimCurve* lCurveTX = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
|
|
||||||
FbxAnimCurve* lCurveTY = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
|
|
||||||
FbxAnimCurve* lCurveTZ = pNode->LclTranslation.GetCurve(lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);
|
|
||||||
|
|
||||||
lCurveSX->KeyModifyBegin();
|
|
||||||
lCurveSY->KeyModifyBegin();
|
|
||||||
lCurveSZ->KeyModifyBegin();
|
|
||||||
lCurveRX->KeyModifyBegin();
|
|
||||||
lCurveRY->KeyModifyBegin();
|
|
||||||
lCurveRZ->KeyModifyBegin();
|
|
||||||
lCurveTX->KeyModifyBegin();
|
|
||||||
lCurveTY->KeyModifyBegin();
|
|
||||||
lCurveTZ->KeyModifyBegin();
|
|
||||||
|
|
||||||
FbxTime lTime;
|
|
||||||
|
|
||||||
for each (auto Scaling in keyframeList->Scalings)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Scaling->time);
|
|
||||||
|
|
||||||
lCurveSX->KeySet(lCurveSX->KeyAdd(lTime), lTime, Scaling->value.X);
|
|
||||||
lCurveSY->KeySet(lCurveSY->KeyAdd(lTime), lTime, Scaling->value.Y);
|
|
||||||
lCurveSZ->KeySet(lCurveSZ->KeyAdd(lTime), lTime, Scaling->value.Z);
|
|
||||||
}
|
|
||||||
for each (auto Rotation in keyframeList->Rotations)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Rotation->time);
|
|
||||||
|
|
||||||
lCurveRX->KeySet(lCurveRX->KeyAdd(lTime), lTime, Rotation->value.X);
|
|
||||||
lCurveRY->KeySet(lCurveRY->KeyAdd(lTime), lTime, Rotation->value.Y);
|
|
||||||
lCurveRZ->KeySet(lCurveRZ->KeyAdd(lTime), lTime, Rotation->value.Z);
|
|
||||||
}
|
|
||||||
for each (auto Translation in keyframeList->Translations)
|
|
||||||
{
|
|
||||||
lTime.SetSecondDouble(Translation->time);
|
|
||||||
|
|
||||||
lCurveTX->KeySet(lCurveTX->KeyAdd(lTime), lTime, Translation->value.X);
|
|
||||||
lCurveTY->KeySet(lCurveTY->KeyAdd(lTime), lTime, Translation->value.Y);
|
|
||||||
lCurveTZ->KeySet(lCurveTZ->KeyAdd(lTime), lTime, Translation->value.Z);
|
|
||||||
}
|
|
||||||
|
|
||||||
lCurveSX->KeyModifyEnd();
|
|
||||||
lCurveSY->KeyModifyEnd();
|
|
||||||
lCurveSZ->KeyModifyEnd();
|
|
||||||
lCurveRX->KeyModifyEnd();
|
|
||||||
lCurveRY->KeyModifyEnd();
|
|
||||||
lCurveRZ->KeyModifyEnd();
|
|
||||||
lCurveTX->KeyModifyEnd();
|
|
||||||
lCurveTY->KeyModifyEnd();
|
|
||||||
lCurveTZ->KeyModifyEnd();
|
|
||||||
|
|
||||||
if (eulerFilter)
|
|
||||||
{
|
|
||||||
FbxAnimCurve* lCurve[3];
|
|
||||||
lCurve[0] = lCurveRX;
|
|
||||||
lCurve[1] = lCurveRY;
|
|
||||||
lCurve[2] = lCurveRZ;
|
|
||||||
eulerFilter->Reset();
|
|
||||||
eulerFilter->SetQualityTolerance(filterPrecision);
|
|
||||||
eulerFilter->Apply(lCurve, 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fbx::Exporter::ExportMorphs(bool morphMask, bool flatInbetween)
|
|
||||||
{
|
|
||||||
/*if (imported->MeshList == nullptr)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int meshIdx = 0; meshIdx < imported->MeshList->Count; meshIdx++)
|
|
||||||
{
|
|
||||||
ImportedMesh^ meshList = imported->MeshList[meshIdx];
|
|
||||||
FbxNode* pBaseNode = NULL;
|
|
||||||
for (int nodeIdx = 0; nodeIdx < pMeshNodes->GetCount(); nodeIdx++)
|
|
||||||
{
|
|
||||||
FbxNode* pMeshNode = pMeshNodes->GetAt(nodeIdx);
|
|
||||||
String^ framePath = gcnew String(pMeshNode->GetName());
|
|
||||||
FbxNode* rootNode = pMeshNode;
|
|
||||||
while ((rootNode = rootNode->GetParent()) != pScene->GetRootNode())
|
|
||||||
{
|
|
||||||
framePath = gcnew String(rootNode->GetName()) + "/" + framePath;
|
|
||||||
}
|
|
||||||
if (framePath == meshList->Path)
|
|
||||||
{
|
|
||||||
pBaseNode = pMeshNode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pBaseNode == NULL)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for each (ImportedMorph^ morph in imported->MorphList)
|
|
||||||
{
|
|
||||||
if (morph->Path != meshList->Path)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int meshVertexIndex = 0;
|
|
||||||
for (int meshObjIdx = pBaseNode->GetChildCount() - meshList->SubmeshList->Count; meshObjIdx < meshList->SubmeshList->Count; meshObjIdx++)
|
|
||||||
{
|
|
||||||
List<ImportedVertex^>^ vertList = meshList->SubmeshList[meshObjIdx]->VertexList;
|
|
||||||
FbxNode* pBaseMeshNode = pBaseNode->GetChild(meshObjIdx);
|
|
||||||
FbxMesh* pBaseMesh = pBaseMeshNode->GetMesh();
|
|
||||||
int numColourSets = pBaseMesh->GetElementVertexColorCount();
|
|
||||||
|
|
||||||
FbxBlendShape* lBlendShape;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pShapeName,
|
|
||||||
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty),
|
|
||||||
lBlendShape = FbxBlendShape::Create(pScene, pShapeName);
|
|
||||||
);
|
|
||||||
FbxProperty rootGroupProp = FbxProperty::Create(lBlendShape, FbxStringDT, "RootGroup");
|
|
||||||
pBaseMesh->AddDeformer(lBlendShape);
|
|
||||||
List<ImportedMorphKeyframe^>^ keyframes = morph->KeyframeList;
|
|
||||||
for (int i = 0; i < morph->Channels->Count; i++)
|
|
||||||
{
|
|
||||||
FbxBlendShapeChannel* lBlendShapeChannel;
|
|
||||||
if (!flatInbetween)
|
|
||||||
{
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pChannelName,
|
|
||||||
gcnew String(lBlendShape->GetName()) + "." + keyframes[morph->Channels[i]->Item2]->Name->Substring(0, keyframes[morph->Channels[i]->Item2]->Name->LastIndexOf("_")),
|
|
||||||
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, pChannelName);
|
|
||||||
);
|
|
||||||
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
|
|
||||||
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int frameIdx = 0; frameIdx < morph->Channels[i]->Item3; frameIdx++)
|
|
||||||
{
|
|
||||||
int shapeIdx = morph->Channels[i]->Item2 + frameIdx;
|
|
||||||
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
|
|
||||||
|
|
||||||
FbxShape* pShape;
|
|
||||||
if (!flatInbetween)
|
|
||||||
{
|
|
||||||
char* pMorphShapeName;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
pMorphShapeName = StringToCharArray(keyframe->Name);
|
|
||||||
if (pScene->FindMember<FbxShape>(pMorphShapeName))
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
|
|
||||||
pMorphShapeName = StringToCharArray(morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "__" + keyframe->Name);
|
|
||||||
}
|
|
||||||
pShape = FbxShape::Create(pScene, pMorphShapeName);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Marshal::FreeHGlobal((IntPtr)pMorphShapeName);
|
|
||||||
}
|
|
||||||
if (frameIdx == morph->Channels[i]->Item3 - 1)
|
|
||||||
{
|
|
||||||
FbxProperty::Create(lBlendShape, FbxStringDT, rootGroupProp.GetName() + "|" + pShape->GetName());
|
|
||||||
}
|
|
||||||
lBlendShapeChannel->AddTargetShape(pShape, keyframe->Weight);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lBlendShapeChannel = FbxBlendShapeChannel::Create(pScene, "");
|
|
||||||
lBlendShapeChannel->DeformPercent = morph->Channels[i]->Item1;
|
|
||||||
lBlendShape->AddBlendShapeChannel(lBlendShapeChannel);
|
|
||||||
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pMorphShapeName,
|
|
||||||
morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
|
|
||||||
pShape = FbxShape::Create(pScene, pMorphShapeName);
|
|
||||||
);
|
|
||||||
lBlendShapeChannel->AddTargetShape(pShape, 100);
|
|
||||||
|
|
||||||
FbxProperty weightProp;
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pWeightName,
|
|
||||||
gcnew String(pShape->GetName()) + ".Weight",
|
|
||||||
weightProp = FbxProperty::Create(pBaseMesh, FbxDoubleDT, pWeightName);
|
|
||||||
);
|
|
||||||
weightProp.ModifyFlag(FbxPropertyFlags::eUserDefined, true);
|
|
||||||
weightProp.Set<double>(keyframe->Weight);
|
|
||||||
}
|
|
||||||
|
|
||||||
pShape->InitControlPoints(vertList->Count);
|
|
||||||
FbxVector4* pControlPoints = pShape->GetControlPoints();
|
|
||||||
|
|
||||||
for (int j = 0; j < vertList->Count; j++)
|
|
||||||
{
|
|
||||||
ImportedVertex^ vertex = vertList[j];
|
|
||||||
Vector3 coords = vertex->Position;
|
|
||||||
pControlPoints[j] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
|
||||||
}
|
|
||||||
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
|
|
||||||
for (int j = 0; j < meshIndices->Count; j++)
|
|
||||||
{
|
|
||||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
|
||||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
|
||||||
{
|
|
||||||
Vector3 coords = keyframe->VertexList[j]->Position;
|
|
||||||
pControlPoints[controlPointIndex] = FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (flatInbetween && meshIndices->Count == 0)
|
|
||||||
{
|
|
||||||
Vector3 coords = vertList[0]->Position;
|
|
||||||
pControlPoints[0] = FbxVector4(coords.X - 1.0e-6, coords.Y, coords.Z, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flatInbetween && frameIdx > 0)
|
|
||||||
{
|
|
||||||
int shapeIdx = morph->Channels[i]->Item2 + frameIdx - 1;
|
|
||||||
ImportedMorphKeyframe^ keyframe = keyframes[shapeIdx];
|
|
||||||
|
|
||||||
List<unsigned short>^ meshIndices = keyframe->MorphedVertexIndices;
|
|
||||||
for (int j = 0; j < meshIndices->Count; j++)
|
|
||||||
{
|
|
||||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
|
||||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
|
||||||
{
|
|
||||||
Vector3 coords = keyframe->VertexList[j]->Position - vertList[controlPointIndex]->Position;
|
|
||||||
pControlPoints[controlPointIndex] -= FbxVector4(coords.X, coords.Y, coords.Z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (morphMask && frameIdx == 0)
|
|
||||||
{
|
|
||||||
int colourSetIdx = numColourSets + shapeIdx;
|
|
||||||
FbxGeometryElementVertexColor* lGeometryElementVertexColor = pBaseMesh->GetElementVertexColor(colourSetIdx);
|
|
||||||
if (lGeometryElementVertexColor == NULL)
|
|
||||||
{
|
|
||||||
lGeometryElementVertexColor = pBaseMesh->CreateElementVertexColor();
|
|
||||||
}
|
|
||||||
lGeometryElementVertexColor->SetMappingMode(FbxGeometryElement::eByControlPoint);
|
|
||||||
lGeometryElementVertexColor->SetReferenceMode(FbxGeometryElement::eDirect);
|
|
||||||
WITH_MARSHALLED_STRING
|
|
||||||
(
|
|
||||||
pColourLayerName, morph->ClipName + (meshList->SubmeshList->Count > 1 ? "_" + meshObjIdx : String::Empty) + "." + keyframe->Name,
|
|
||||||
lGeometryElementVertexColor->SetName(pColourLayerName);
|
|
||||||
);
|
|
||||||
for (int j = 0; j < vertList->Count; j++)
|
|
||||||
{
|
|
||||||
lGeometryElementVertexColor->GetDirectArray().Add(FbxColor(1, 1, 1));
|
|
||||||
}
|
|
||||||
for (int j = 0; j < meshIndices->Count; j++)
|
|
||||||
{
|
|
||||||
int controlPointIndex = meshIndices[j] - meshVertexIndex;
|
|
||||||
if (controlPointIndex >= 0 && controlPointIndex < vertList->Count)
|
|
||||||
{
|
|
||||||
lGeometryElementVertexColor->GetDirectArray().SetAt(controlPointIndex, FbxColor(0, 0, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
meshVertexIndex += meshList->SubmeshList[meshObjIdx]->VertexList->Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
// Microsoft Visual C++ generated resource script.
|
||||||
|
//
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
#define APSTUDIO_READONLY_SYMBOLS
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 2 resource.
|
||||||
|
//
|
||||||
|
#include "winres.h"
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#undef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Language neutral resources
|
||||||
|
|
||||||
|
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
|
||||||
|
LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
|
#pragma code_page(65001)
|
||||||
|
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// TEXTINCLUDE
|
||||||
|
//
|
||||||
|
|
||||||
|
1 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"resource.h\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
2 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"#include ""winres.h""\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
3 TEXTINCLUDE
|
||||||
|
BEGIN
|
||||||
|
"\r\n"
|
||||||
|
"\0"
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // APSTUDIO_INVOKED
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Version
|
||||||
|
//
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION 1,0,0,1
|
||||||
|
PRODUCTVERSION 1,0,0,1
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS 0x1L
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS 0x40004L
|
||||||
|
FILETYPE 0x2L
|
||||||
|
FILESUBTYPE 0x0L
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "000004b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "FileDescription", "AssetStudioFBXNative"
|
||||||
|
VALUE "FileVersion", "1.0.0.1"
|
||||||
|
VALUE "InternalName", "AssetStudioFBXNative.dll"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) Perfare 2018-2020; Copyright (C) hozuki 2020"
|
||||||
|
VALUE "OriginalFilename", "AssetStudioFBXNative.dll"
|
||||||
|
VALUE "ProductName", "AssetStudioFBXNative"
|
||||||
|
VALUE "ProductVersion", "1.0.0.1"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x0, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
|
|
||||||
|
#endif // Language neutral resources
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef APSTUDIO_INVOKED
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Generated from the TEXTINCLUDE 3 resource.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
#endif // not APSTUDIO_INVOKED
|
||||||
|
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>16.0</VCProjectVersion>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<ProjectGuid>{11ea25a3-ed68-40ee-a9d0-7fde3b583027}</ProjectGuid>
|
||||||
|
<RootNamespace>AssetStudioFBXNative</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<TargetExt>.dll</TargetExt>
|
||||||
|
<OutDir>bin\$(Platform)\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="asfbx_anim_context.cpp" />
|
||||||
|
<ClCompile Include="asfbx_context.cpp" />
|
||||||
|
<ClCompile Include="api.cpp" />
|
||||||
|
<ClCompile Include="asfbx_morph_context.cpp" />
|
||||||
|
<ClCompile Include="asfbx_skin_context.cpp" />
|
||||||
|
<ClCompile Include="utils.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="api.h" />
|
||||||
|
<ClInclude Include="asfbx_anim_context.h" />
|
||||||
|
<ClInclude Include="asfbx_context.h" />
|
||||||
|
<ClInclude Include="asfbx_morph_context.h" />
|
||||||
|
<ClInclude Include="asfbx_skin_context.h" />
|
||||||
|
<ClInclude Include="bool32_t.h" />
|
||||||
|
<ClInclude Include="dllexport.h" />
|
||||||
|
<ClInclude Include="resource.h" />
|
||||||
|
<ClInclude Include="utils.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="AssetStudioFBXNative.rc" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
<MSBuild Condition=" '$(Platform)' == 'Win32' " Projects="$(MSBuildProjectFile)" Properties="Platform=x64;PlatFormTarget=x64" RunEachTargetSeparately="true" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="源文件">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="头文件">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="资源文件">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="utils.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="api.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="asfbx_context.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="asfbx_skin_context.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="asfbx_anim_context.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="asfbx_morph_context.cpp">
|
||||||
|
<Filter>源文件</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="dllexport.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="api.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="utils.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="bool32_t.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="asfbx_context.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="asfbx_skin_context.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="asfbx_anim_context.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="asfbx_morph_context.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="resource.h">
|
||||||
|
<Filter>头文件</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="cpp.hint" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="AssetStudioFBXNative.rc">
|
||||||
|
<Filter>资源文件</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dllexport.h"
|
||||||
|
#include "bool32_t.h"
|
||||||
|
|
||||||
|
namespace fbxsdk
|
||||||
|
{
|
||||||
|
class FbxNode;
|
||||||
|
class FbxFileTexture;
|
||||||
|
template<typename T, const int Alignment = 16>
|
||||||
|
class FbxArray;
|
||||||
|
class FbxCluster;
|
||||||
|
class FbxMesh;
|
||||||
|
class FbxSurfacePhong;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AsFbxContext;
|
||||||
|
struct AsFbxSkinContext;
|
||||||
|
struct AsFbxAnimContext;
|
||||||
|
struct AsFbxMorphContext;
|
||||||
|
|
||||||
|
AS_API(void) AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, float* vx, float* vy, float* vz);
|
||||||
|
|
||||||
|
AS_API(void) AsUtilEulerToQuaternion(float vx, float vy, float vz, float* qx, float* qy, float* qz, float* qw);
|
||||||
|
|
||||||
|
// All strings ([const] char *) in this header are UTF-8 strings.
|
||||||
|
|
||||||
|
AS_API(AsFbxContext*) AsFbxCreateContext();
|
||||||
|
|
||||||
|
// Do not free pErrMsg
|
||||||
|
AS_API(bool32_t) AsFbxInitializeContext(AsFbxContext* pContext, const char* pFileName, float scaleFactor, int32_t versionIndex, bool32_t isAscii, bool32_t is60Fps, const char** pErrMsg);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxDisposeContext(AsFbxContext** ppContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxSetFramePaths(AsFbxContext* pContext, const char* ppPaths[], int32_t count);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxExportScene(AsFbxContext* pContext);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxNode*) AsFbxGetSceneRootNode(AsFbxContext* pContext);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxNode*) AsFbxExportSingleFrame(AsFbxContext* pContext, fbxsdk::FbxNode* pParentNode, const char* pFramePath, const char* pFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxSetJointsNode_CastToBone(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxSetJointsNode_BoneInPath(AsFbxContext* pContext, fbxsdk::FbxNode* pNode, float boneSize);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxSetJointsNode_Generic(AsFbxContext* pContext, fbxsdk::FbxNode* pNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxPrepareMaterials(AsFbxContext* pContext, int32_t materialCount, int32_t textureCount);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxFileTexture*) AsFbxCreateTexture(AsFbxContext* pContext, const char* pMatTexName);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxLinkTexture(int32_t dest, fbxsdk::FbxFileTexture* pTexture, fbxsdk::FbxSurfacePhong* pMaterial, float offsetX, float offsetY, float scaleX, float scaleY);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxArray<fbxsdk::FbxCluster*>*) AsFbxMeshCreateClusterArray(int32_t boneCount);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshDisposeClusterArray(fbxsdk::FbxArray<fbxsdk::FbxCluster*>** ppArray);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxCluster*) AsFbxMeshCreateCluster(AsFbxContext* pContext, fbxsdk::FbxNode* pBoneNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshAddCluster(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pArray, /* CanBeNull */ fbxsdk::FbxCluster* pCluster);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxMesh*) AsFbxMeshCreateMesh(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshInitControlPoints(fbxsdk::FbxMesh* pMesh, int32_t vertexCount);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateElementNormal(fbxsdk::FbxMesh* pMesh);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateDiffuseUV(fbxsdk::FbxMesh* pMesh, int32_t uv);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateNormalMapUV(fbxsdk::FbxMesh* pMesh, int32_t uv);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateElementTangent(fbxsdk::FbxMesh* pMesh);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateElementVertexColor(fbxsdk::FbxMesh* pMesh);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshCreateElementMaterial(fbxsdk::FbxMesh* pMesh);
|
||||||
|
|
||||||
|
AS_API(fbxsdk::FbxSurfacePhong*) AsFbxCreateMaterial(AsFbxContext* pContext, const char* pMatName,
|
||||||
|
float diffuseR, float diffuseG, float diffuseB,
|
||||||
|
float ambientR, float ambientG, float ambientB,
|
||||||
|
float emissiveR, float emissiveG, float emissiveB,
|
||||||
|
float specularR, float specularG, float specularB,
|
||||||
|
float reflectR, float reflectG, float reflectB,
|
||||||
|
float shininess, float transparency);
|
||||||
|
|
||||||
|
AS_API(int32_t) AsFbxAddMaterialToFrame(fbxsdk::FbxNode* pFrameNode, fbxsdk::FbxSurfacePhong* pMaterial);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxSetFrameShadingModeToTextureShading(fbxsdk::FbxNode* pFrameNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshSetControlPoint(fbxsdk::FbxMesh* pMesh, int32_t index, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshAddPolygon(fbxsdk::FbxMesh* pMesh, int32_t materialIndex, int32_t index0, int32_t index1, int32_t index2);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshElementNormalAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshElementUVAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float u, float v);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshElementTangentAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float x, float y, float z, float w);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshElementVertexColorAdd(fbxsdk::FbxMesh* pMesh, int32_t elementIndex, float r, float g, float b, float a);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshSetBoneWeight(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t boneIndex, int32_t vertexIndex, float weight);
|
||||||
|
|
||||||
|
AS_API(AsFbxSkinContext*) AsFbxMeshCreateSkinContext(AsFbxContext* pContext, fbxsdk::FbxNode* pFrameNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshDisposeSkinContext(AsFbxSkinContext** ppSkinContext);
|
||||||
|
|
||||||
|
AS_API(bool32_t) FbxClusterArray_HasItemAt(fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshSkinAddCluster(AsFbxSkinContext* pSkinContext, fbxsdk::FbxArray<fbxsdk::FbxCluster*>* pClusterArray, int32_t index, float pBoneMatrix[16]);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMeshAddDeformer(AsFbxSkinContext* pSkinContext, fbxsdk::FbxMesh* pMesh);
|
||||||
|
|
||||||
|
AS_API(AsFbxAnimContext*) AsFbxAnimCreateContext(bool32_t eulerFilter);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimDisposeContext(AsFbxAnimContext** ppAnimContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimPrepareStackAndLayer(AsFbxContext* pContext, AsFbxAnimContext* pAnimContext, const char* pTakeName);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimLoadCurves(fbxsdk::FbxNode* pNode, AsFbxAnimContext* pAnimContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimBeginKeyModify(AsFbxAnimContext* pAnimContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimEndKeyModify(AsFbxAnimContext* pAnimContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimAddScalingKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimAddRotationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimAddTranslationKey(AsFbxAnimContext* pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimApplyEulerFilter(AsFbxAnimContext* pAnimContext, float filterPrecision);
|
||||||
|
|
||||||
|
AS_API(int32_t) AsFbxAnimGetCurrentBlendShapeChannelCount(AsFbxAnimContext* pAnimContext, fbxsdk::FbxNode* pNode);
|
||||||
|
|
||||||
|
AS_API(bool32_t) AsFbxAnimIsBlendShapeChannelMatch(AsFbxAnimContext* pAnimContext, int32_t channelIndex, const char* channelName);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimBeginBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext, int32_t channelIndex);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimEndBlendShapeAnimCurve(AsFbxAnimContext* pAnimContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxAnimAddBlendShapeKeyframe(AsFbxAnimContext* pAnimContext, float time, float value);
|
||||||
|
|
||||||
|
AS_API(AsFbxMorphContext*) AsFbxMorphCreateContext();
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphInitializeContext(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, fbxsdk::FbxNode* pNode);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphDisposeContext(AsFbxMorphContext** ppMorphContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphAddBlendShapeChannel(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, const char* channelName);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphAddBlendShapeChannelShape(AsFbxContext* pContext, AsFbxMorphContext* pMorphContext, float weight, const char* shapeName);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphCopyBlendShapeControlPoints(AsFbxMorphContext* pMorphContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphSetBlendShapeVertex(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphCopyBlendShapeControlPointsNormal(AsFbxMorphContext* pMorphContext);
|
||||||
|
|
||||||
|
AS_API(void) AsFbxMorphSetBlendShapeVertexNormal(AsFbxMorphContext* pMorphContext, uint32_t index, float x, float y, float z);
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
#include "asfbx_anim_context.h"
|
||||||
|
|
||||||
|
AsFbxAnimContext::AsFbxAnimContext(bool32_t eulerFilter)
|
||||||
|
: lFilter(nullptr)
|
||||||
|
{
|
||||||
|
if (eulerFilter)
|
||||||
|
{
|
||||||
|
lFilter = new FbxAnimCurveFilterUnroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
lAnimStack = nullptr;
|
||||||
|
lAnimLayer = nullptr;
|
||||||
|
|
||||||
|
lCurveSX = nullptr;
|
||||||
|
lCurveSY = nullptr;
|
||||||
|
lCurveSZ = nullptr;
|
||||||
|
lCurveRX = nullptr;
|
||||||
|
lCurveRY = nullptr;
|
||||||
|
lCurveRZ = nullptr;
|
||||||
|
lCurveTX = nullptr;
|
||||||
|
lCurveTY = nullptr;
|
||||||
|
lCurveTZ = nullptr;
|
||||||
|
|
||||||
|
pMesh = nullptr;
|
||||||
|
lBlendShape = nullptr;
|
||||||
|
lAnimCurve = nullptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fbxsdk.h>
|
||||||
|
|
||||||
|
#include "bool32_t.h"
|
||||||
|
|
||||||
|
struct AsFbxAnimContext
|
||||||
|
{
|
||||||
|
|
||||||
|
FbxAnimCurveFilterUnroll* lFilter;
|
||||||
|
|
||||||
|
FbxAnimStack* lAnimStack;
|
||||||
|
FbxAnimLayer* lAnimLayer;
|
||||||
|
|
||||||
|
FbxAnimCurve* lCurveSX;
|
||||||
|
FbxAnimCurve* lCurveSY;
|
||||||
|
FbxAnimCurve* lCurveSZ;
|
||||||
|
FbxAnimCurve* lCurveRX;
|
||||||
|
FbxAnimCurve* lCurveRY;
|
||||||
|
FbxAnimCurve* lCurveRZ;
|
||||||
|
FbxAnimCurve* lCurveTX;
|
||||||
|
FbxAnimCurve* lCurveTY;
|
||||||
|
FbxAnimCurve* lCurveTZ;
|
||||||
|
|
||||||
|
FbxMesh* pMesh;
|
||||||
|
FbxBlendShape* lBlendShape;
|
||||||
|
FbxAnimCurve* lAnimCurve;
|
||||||
|
|
||||||
|
AsFbxAnimContext(bool32_t eulerFilter);
|
||||||
|
~AsFbxAnimContext() = default;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include <fbxsdk.h>
|
||||||
|
|
||||||
|
#include "asfbx_context.h"
|
||||||
|
|
||||||
|
AsFbxContext::AsFbxContext()
|
||||||
|
{
|
||||||
|
pSdkManager = nullptr;
|
||||||
|
pScene = nullptr;
|
||||||
|
pTextures = nullptr;
|
||||||
|
pMaterials = nullptr;
|
||||||
|
pExporter = nullptr;
|
||||||
|
pBindPose = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxContext::~AsFbxContext()
|
||||||
|
{
|
||||||
|
framePaths.clear();
|
||||||
|
|
||||||
|
delete pMaterials;
|
||||||
|
delete pTextures;
|
||||||
|
|
||||||
|
if (pExporter != nullptr) {
|
||||||
|
pExporter->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pScene != nullptr) {
|
||||||
|
pScene->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSdkManager != nullptr) {
|
||||||
|
pSdkManager->Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
|
struct AsFbxContext
|
||||||
|
{
|
||||||
|
|
||||||
|
fbxsdk::FbxManager* pSdkManager;
|
||||||
|
fbxsdk::FbxScene* pScene;
|
||||||
|
fbxsdk::FbxArray<fbxsdk::FbxFileTexture*>* pTextures;
|
||||||
|
fbxsdk::FbxArray<fbxsdk::FbxSurfacePhong*>* pMaterials;
|
||||||
|
fbxsdk::FbxExporter* pExporter;
|
||||||
|
fbxsdk::FbxPose* pBindPose;
|
||||||
|
|
||||||
|
std::unordered_set<std::string> framePaths;
|
||||||
|
|
||||||
|
AsFbxContext();
|
||||||
|
~AsFbxContext();
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#include "asfbx_morph_context.h"
|
||||||
|
|
||||||
|
AsFbxMorphContext::AsFbxMorphContext()
|
||||||
|
{
|
||||||
|
pMesh = nullptr;
|
||||||
|
lBlendShape = nullptr;
|
||||||
|
lBlendShapeChannel = nullptr;
|
||||||
|
lShape = nullptr;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fbxsdk.h>
|
||||||
|
|
||||||
|
struct AsFbxMorphContext
|
||||||
|
{
|
||||||
|
|
||||||
|
FbxMesh* pMesh;
|
||||||
|
FbxBlendShape* lBlendShape;
|
||||||
|
FbxBlendShapeChannel* lBlendShapeChannel;
|
||||||
|
FbxShape* lShape;
|
||||||
|
|
||||||
|
AsFbxMorphContext();
|
||||||
|
~AsFbxMorphContext() = default;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include "asfbx_skin_context.h"
|
||||||
|
#include "asfbx_context.h"
|
||||||
|
|
||||||
|
AsFbxSkinContext::AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode)
|
||||||
|
: pSkin(nullptr)
|
||||||
|
{
|
||||||
|
if (pContext != nullptr && pContext->pScene != nullptr)
|
||||||
|
{
|
||||||
|
pSkin = FbxSkin::Create(pContext->pScene, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pFrameNode != nullptr)
|
||||||
|
{
|
||||||
|
lMeshMatrix = pFrameNode->EvaluateGlobalTransform();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fbxsdk.h>
|
||||||
|
|
||||||
|
struct AsFbxContext;
|
||||||
|
|
||||||
|
struct AsFbxSkinContext
|
||||||
|
{
|
||||||
|
|
||||||
|
FbxSkin* pSkin;
|
||||||
|
FbxAMatrix lMeshMatrix;
|
||||||
|
|
||||||
|
AsFbxSkinContext(AsFbxContext* pContext, FbxNode* pFrameNode);
|
||||||
|
~AsFbxSkinContext() = default;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
typedef uint32_t bool32_t;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#define AS_API(ret_type)
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#if _MSC_VER < 1910 // MSVC 2017-
|
||||||
|
#error MSVC 2017 or later is required.
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW__)
|
||||||
|
#ifdef _AS_DLL
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define _AS_EXPORT __attribute__ ((dllexport))
|
||||||
|
#else
|
||||||
|
#define _AS_EXPORT __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define _AS_EXPORT __attribute__ ((dllimport))
|
||||||
|
#else
|
||||||
|
#define _AS_EXPORT __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#define _AS_LOCAL
|
||||||
|
#else
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define _AS_EXPORT __attribute__ ((visibility ("default")))
|
||||||
|
#define _AS_LOCAL __attribute__ ((visibility ("hidden")))
|
||||||
|
#else
|
||||||
|
#define _AS_EXPORT
|
||||||
|
#define _AS_LOCAL
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
#ifndef _EXTERN_C_STMT
|
||||||
|
#define _EXTERN_C_STMT extern "C"
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifndef _EXTERN_C_STMT
|
||||||
|
#define _EXTERN_C_STMT
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _AS_CALL
|
||||||
|
#if defined(WIN32) || defined(_WIN32)
|
||||||
|
#define _AS_CALL __stdcall
|
||||||
|
#else
|
||||||
|
#define _AS_CALL /* __cdecl */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT ret_type _AS_CALL
|
||||||
|
#else
|
||||||
|
#define AS_API(ret_type) _EXTERN_C_STMT _AS_EXPORT _AS_CALL ret_type
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
//{{NO_DEPENDENCIES}}
|
||||||
|
// Microsoft Visual C++ generated include file.
|
||||||
|
// Used by AssetStudioFBXNative.rc
|
||||||
|
|
||||||
|
// 新对象的下一组默认值
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
#include <fbxsdk.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
Vector3::Vector3()
|
||||||
|
: X(0), Y(0), Z(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3::Vector3(float x, float y, float z)
|
||||||
|
: X(x), Y(y), Z(z)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion::Quaternion()
|
||||||
|
: X(0), Y(0), Z(0), W(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion::Quaternion(float x, float y, float z)
|
||||||
|
: X(x), Y(y), Z(z), W(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion::Quaternion(float x, float y, float z, float w)
|
||||||
|
: X(x), Y(y), Z(z), W(w)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 QuaternionToEuler(Quaternion q) {
|
||||||
|
FbxAMatrix lMatrixRot;
|
||||||
|
lMatrixRot.SetQ(FbxQuaternion(q.X, q.Y, q.Z, q.W));
|
||||||
|
FbxVector4 lEuler = lMatrixRot.GetR();
|
||||||
|
return Vector3((float)lEuler[0], (float)lEuler[1], (float)lEuler[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quaternion EulerToQuaternion(Vector3 v) {
|
||||||
|
FbxAMatrix lMatrixRot;
|
||||||
|
lMatrixRot.SetR(FbxVector4(v.X, v.Y, v.Z));
|
||||||
|
FbxQuaternion lQuaternion = lMatrixRot.GetQ();
|
||||||
|
return Quaternion((float)lQuaternion[0], (float)lQuaternion[1], (float)lQuaternion[2], (float)lQuaternion[3]);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct Vector3 {
|
||||||
|
|
||||||
|
float X;
|
||||||
|
float Y;
|
||||||
|
float Z;
|
||||||
|
|
||||||
|
Vector3();
|
||||||
|
Vector3(float x, float y, float z);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Quaternion {
|
||||||
|
|
||||||
|
float X;
|
||||||
|
float Y;
|
||||||
|
float Z;
|
||||||
|
float W;
|
||||||
|
|
||||||
|
Quaternion();
|
||||||
|
Quaternion(float x, float y, float z);
|
||||||
|
Quaternion(float x, float y, float z, float w);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector3 QuaternionToEuler(Quaternion q);
|
||||||
|
|
||||||
|
Quaternion EulerToQuaternion(Vector3 v);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<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 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
|
||||||
|
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using AssetStudio.FbxInterop;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
partial class Fbx
|
||||||
|
{
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsUtilQuaternionToEuler(float qx, float qy, float qz, float qw, out float vx, out float vy, out float vz);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsUtilEulerToQuaternion(float vx, float vy, float vz, out float qx, out float qy, out float qz, out float qw);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using AssetStudio.FbxInterop;
|
||||||
|
using AssetStudio.PInvoke;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static partial class Fbx
|
||||||
|
{
|
||||||
|
|
||||||
|
static Fbx()
|
||||||
|
{
|
||||||
|
DllLoader.PreloadDll(FbxDll.DllName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3 QuaternionToEuler(Quaternion q)
|
||||||
|
{
|
||||||
|
AsUtilQuaternionToEuler(q.X, q.Y, q.Z, q.W, out var x, out var y, out var z);
|
||||||
|
return new Vector3(x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Quaternion EulerToQuaternion(Vector3 v)
|
||||||
|
{
|
||||||
|
AsUtilEulerToQuaternion(v.X, v.Y, v.Z, out var x, out var y, out var z, out var w);
|
||||||
|
return new Quaternion(x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Exporter
|
||||||
|
{
|
||||||
|
|
||||||
|
public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,
|
||||||
|
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)
|
||||||
|
{
|
||||||
|
var file = new FileInfo(path);
|
||||||
|
var dir = file.Directory;
|
||||||
|
|
||||||
|
if (!dir.Exists)
|
||||||
|
{
|
||||||
|
dir.Create();
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentDir = Directory.GetCurrentDirectory();
|
||||||
|
Directory.SetCurrentDirectory(dir.FullName);
|
||||||
|
|
||||||
|
var name = Path.GetFileName(path);
|
||||||
|
|
||||||
|
using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii))
|
||||||
|
{
|
||||||
|
exporter.Initialize();
|
||||||
|
exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory.SetCurrentDirectory(currentDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace AssetStudio.FbxInterop
|
||||||
|
{
|
||||||
|
internal static class FbxDll
|
||||||
|
{
|
||||||
|
|
||||||
|
internal const string DllName = "AssetStudioFBXNative";
|
||||||
|
internal const string FbxsdkDllName = "libfbxsdk";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,244 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace AssetStudio.FbxInterop
|
||||||
|
{
|
||||||
|
internal sealed class FbxExporter : IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
private FbxExporterContext _context;
|
||||||
|
|
||||||
|
private readonly string _fileName;
|
||||||
|
private readonly IImported _imported;
|
||||||
|
private readonly bool _allNodes;
|
||||||
|
private readonly bool _exportSkins;
|
||||||
|
private readonly bool _castToBone;
|
||||||
|
private readonly float _boneSize;
|
||||||
|
private readonly bool _exportAllUvsAsDiffuseMaps;
|
||||||
|
private readonly float _scaleFactor;
|
||||||
|
private readonly int _versionIndex;
|
||||||
|
private readonly bool _isAscii;
|
||||||
|
|
||||||
|
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)
|
||||||
|
{
|
||||||
|
_context = new FbxExporterContext();
|
||||||
|
|
||||||
|
_fileName = fileName;
|
||||||
|
_imported = imported;
|
||||||
|
_allNodes = allNodes;
|
||||||
|
_exportSkins = exportSkins;
|
||||||
|
_castToBone = castToBone;
|
||||||
|
_boneSize = boneSize;
|
||||||
|
_exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps;
|
||||||
|
_scaleFactor = scaleFactor;
|
||||||
|
_versionIndex = versionIndex;
|
||||||
|
_isAscii = isAscii;
|
||||||
|
}
|
||||||
|
|
||||||
|
~FbxExporter()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (IsDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_context.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Initialize()
|
||||||
|
{
|
||||||
|
var is60Fps = _imported.AnimationList.Count > 0 && _imported.AnimationList[0].SampleRate.Equals(60.0f);
|
||||||
|
|
||||||
|
_context.Initialize(_fileName, _scaleFactor, _versionIndex, _isAscii, is60Fps);
|
||||||
|
|
||||||
|
if (!_allNodes)
|
||||||
|
{
|
||||||
|
var framePaths = SearchHierarchy();
|
||||||
|
|
||||||
|
_context.SetFramePaths(framePaths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportAll(bool blendShape, bool animation, bool eulerFilter, float filterPrecision)
|
||||||
|
{
|
||||||
|
var meshFrames = new List<ImportedFrame>();
|
||||||
|
|
||||||
|
ExportRootFrame(meshFrames);
|
||||||
|
|
||||||
|
if (_imported.MeshList != null)
|
||||||
|
{
|
||||||
|
SetJointsFromImportedMeshes();
|
||||||
|
|
||||||
|
PrepareMaterials();
|
||||||
|
|
||||||
|
ExportMeshFrames(_imported.RootFrame, meshFrames);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SetJointsNode(_imported.RootFrame, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (blendShape)
|
||||||
|
{
|
||||||
|
ExportMorphs();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animation)
|
||||||
|
{
|
||||||
|
ExportAnimations(eulerFilter, filterPrecision);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportMorphs()
|
||||||
|
{
|
||||||
|
_context.ExportMorphs(_imported.RootFrame, _imported.MorphList);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportAnimations(bool eulerFilter, float filterPrecision)
|
||||||
|
{
|
||||||
|
_context.ExportAnimations(_imported.RootFrame, _imported.AnimationList, eulerFilter, filterPrecision);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportRootFrame(List<ImportedFrame> meshFrames)
|
||||||
|
{
|
||||||
|
_context.ExportFrame(_imported.MeshList, meshFrames, _imported.RootFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportScene()
|
||||||
|
{
|
||||||
|
_context.ExportScene();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetJointsFromImportedMeshes()
|
||||||
|
{
|
||||||
|
if (!_exportSkins)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(_imported.MeshList != null);
|
||||||
|
|
||||||
|
var bonePaths = new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var mesh in _imported.MeshList)
|
||||||
|
{
|
||||||
|
var boneList = mesh.BoneList;
|
||||||
|
|
||||||
|
if (boneList != null)
|
||||||
|
{
|
||||||
|
foreach (var bone in boneList)
|
||||||
|
{
|
||||||
|
bonePaths.Add(bone.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetJointsNode(_imported.RootFrame, bonePaths, _castToBone);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone)
|
||||||
|
{
|
||||||
|
_context.SetJointsNode(rootFrame, bonePaths, castToBone, _boneSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrepareMaterials()
|
||||||
|
{
|
||||||
|
_context.PrepareMaterials(_imported.MaterialList.Count, _imported.TextureList.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportMeshFrames(ImportedFrame rootFrame, List<ImportedFrame> meshFrames)
|
||||||
|
{
|
||||||
|
foreach (var meshFrame in meshFrames)
|
||||||
|
{
|
||||||
|
_context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins, _exportAllUvsAsDiffuseMaps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<string> SearchHierarchy()
|
||||||
|
{
|
||||||
|
if (_imported.MeshList == null || _imported.MeshList.Count == 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var exportFrames = new HashSet<string>();
|
||||||
|
|
||||||
|
SearchHierarchy(_imported.RootFrame, _imported.MeshList, exportFrames);
|
||||||
|
|
||||||
|
return exportFrames;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SearchHierarchy(ImportedFrame rootFrame, List<ImportedMesh> meshList, HashSet<string> exportFrames)
|
||||||
|
{
|
||||||
|
var frameStack = new Stack<ImportedFrame>();
|
||||||
|
|
||||||
|
frameStack.Push(rootFrame);
|
||||||
|
|
||||||
|
while (frameStack.Count > 0)
|
||||||
|
{
|
||||||
|
var frame = frameStack.Pop();
|
||||||
|
|
||||||
|
var meshListSome = ImportedHelpers.FindMesh(frame.Path, meshList);
|
||||||
|
|
||||||
|
if (meshListSome != null)
|
||||||
|
{
|
||||||
|
var parent = frame;
|
||||||
|
|
||||||
|
while (parent != null)
|
||||||
|
{
|
||||||
|
exportFrames.Add(parent.Path);
|
||||||
|
parent = parent.Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var boneList = meshListSome.BoneList;
|
||||||
|
|
||||||
|
if (boneList != null)
|
||||||
|
{
|
||||||
|
foreach (var bone in boneList)
|
||||||
|
{
|
||||||
|
if (!exportFrames.Contains(bone.Path))
|
||||||
|
{
|
||||||
|
var boneParent = rootFrame.FindFrameByPath(bone.Path);
|
||||||
|
|
||||||
|
while (boneParent != null)
|
||||||
|
{
|
||||||
|
exportFrames.Add(boneParent.Path);
|
||||||
|
boneParent = boneParent.Parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||||
|
{
|
||||||
|
frameStack.Push(frame[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,325 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using AssetStudio.PInvoke;
|
||||||
|
|
||||||
|
namespace AssetStudio.FbxInterop
|
||||||
|
{
|
||||||
|
partial class FbxExporterContext
|
||||||
|
{
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxCreateContext();
|
||||||
|
|
||||||
|
private static bool AsFbxInitializeContext(IntPtr context, string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps, out string errorMessage)
|
||||||
|
{
|
||||||
|
bool b;
|
||||||
|
IntPtr pErrMsg;
|
||||||
|
|
||||||
|
using (var fileNameUtf8 = new Utf8StringHandle(fileName))
|
||||||
|
{
|
||||||
|
b = AsFbxInitializeContext(context, fileNameUtf8.DangerousGetHandle(), scaleFactor, versionIndex, isAscii, is60Fps, out pErrMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
errorMessage = Utf8StringHandle.ReadUtf8StringFromPointer(pErrMsg);
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not free the pointer strErrorMessage
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool AsFbxInitializeContext(IntPtr context, IntPtr strFileName, float scaleFactor, int versionIndex, [MarshalAs(UnmanagedType.Bool)] bool isAscii, [MarshalAs(UnmanagedType.Bool)] bool is60Fps, out IntPtr strErrorMessage);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxDisposeContext(ref IntPtr ppContext);
|
||||||
|
|
||||||
|
private static void AsFbxSetFramePaths(IntPtr context, string[] framePaths)
|
||||||
|
{
|
||||||
|
var framePathCount = framePaths.Length;
|
||||||
|
|
||||||
|
if (framePathCount == 0)
|
||||||
|
{
|
||||||
|
AsFbxSetFramePaths(context, Array.Empty<IntPtr>(), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var utf8Paths = new Utf8StringHandle[framePathCount];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (var i = 0; i < framePathCount; i += 1)
|
||||||
|
{
|
||||||
|
utf8Paths[i] = new Utf8StringHandle(framePaths[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pathPointers = new IntPtr[framePathCount];
|
||||||
|
|
||||||
|
for (var i = 0; i < framePathCount; i += 1)
|
||||||
|
{
|
||||||
|
pathPointers[i] = utf8Paths[i].DangerousGetHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxSetFramePaths(context, pathPointers, framePathCount);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
foreach (var path in utf8Paths)
|
||||||
|
{
|
||||||
|
path?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxSetFramePaths(IntPtr context, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] strFramePaths, int count);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxExportScene(IntPtr context);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxGetSceneRootNode(IntPtr context);
|
||||||
|
|
||||||
|
private static IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, string framePath, string frameName, in Vector3 localPosition, in Vector3 localRotation, in Vector3 localScale)
|
||||||
|
{
|
||||||
|
using (var framePathUtf8 = new Utf8StringHandle(framePath))
|
||||||
|
{
|
||||||
|
using (var frameNameUtf8 = new Utf8StringHandle(frameName))
|
||||||
|
{
|
||||||
|
return AsFbxExportSingleFrame(context, parentNode, framePathUtf8.DangerousGetHandle(), frameNameUtf8.DangerousGetHandle(), localPosition.X, localPosition.Y, localPosition.Z, localRotation.X, localRotation.Y, localRotation.Z, localScale.X, localScale.Y, localScale.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxExportSingleFrame(IntPtr context, IntPtr parentNode, IntPtr strFramePath, IntPtr strFrameName, float localPositionX, float localPositionY, float localPositionZ, float localRotationX, float localRotationY, float localRotationZ, float localScaleX, float localScaleY, float localScaleZ);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxSetJointsNode_CastToBone(IntPtr context, IntPtr node, float boneSize);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxSetJointsNode_BoneInPath(IntPtr context, IntPtr node, float boneSize);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxSetJointsNode_Generic(IntPtr context, IntPtr node);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxPrepareMaterials(IntPtr context, int materialCount, int textureCount);
|
||||||
|
|
||||||
|
private static IntPtr AsFbxCreateTexture(IntPtr context, string matTexName)
|
||||||
|
{
|
||||||
|
using (var matTexNameUtf8 = new Utf8StringHandle(matTexName))
|
||||||
|
{
|
||||||
|
return AsFbxCreateTexture(context, matTexNameUtf8.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxCreateTexture(IntPtr context, IntPtr strMatTexName);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxLinkTexture(int dest, IntPtr texture, IntPtr material, float offsetX, float offsetY, float scaleX, float scaleY);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxMeshCreateClusterArray(int boneCount);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshDisposeClusterArray(ref IntPtr ppArray);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxMeshCreateCluster(IntPtr context, IntPtr boneNode);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshAddCluster(IntPtr array, IntPtr cluster);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxMeshCreateMesh(IntPtr context, IntPtr frameNode);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshInitControlPoints(IntPtr mesh, int vertexCount);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateElementNormal(IntPtr mesh);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateDiffuseUV(IntPtr mesh, int uv);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateNormalMapUV(IntPtr mesh, int uv);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateElementTangent(IntPtr mesh);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateElementVertexColor(IntPtr mesh);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshCreateElementMaterial(IntPtr mesh);
|
||||||
|
|
||||||
|
private static IntPtr AsFbxCreateMaterial(IntPtr pContext, string matName, in Color diffuse, in Color ambient, in Color emissive, in Color specular, in Color reflection, float shininess, float transparency)
|
||||||
|
{
|
||||||
|
using (var matNameUtf8 = new Utf8StringHandle(matName))
|
||||||
|
{
|
||||||
|
return AsFbxCreateMaterial(pContext, matNameUtf8.DangerousGetHandle(), diffuse.R, diffuse.G, diffuse.B, ambient.R, ambient.G, ambient.B, emissive.R, emissive.G, emissive.B, specular.R, specular.G, specular.B, reflection.R, reflection.G, reflection.B, shininess, transparency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxCreateMaterial(IntPtr pContext, IntPtr pMatName,
|
||||||
|
float diffuseR, float diffuseG, float diffuseB,
|
||||||
|
float ambientR, float ambientG, float ambientB,
|
||||||
|
float emissiveR, float emissiveG, float emissiveB,
|
||||||
|
float specularR, float specularG, float specularB,
|
||||||
|
float reflectR, float reflectG, float reflectB,
|
||||||
|
float shininess, float transparency);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern int AsFbxAddMaterialToFrame(IntPtr frameNode, IntPtr material);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxSetFrameShadingModeToTextureShading(IntPtr frameNode);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshSetControlPoint(IntPtr mesh, int index, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshAddPolygon(IntPtr mesh, int materialIndex, int index0, int index1, int index2);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshElementNormalAdd(IntPtr mesh, int elementIndex, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshElementUVAdd(IntPtr mesh, int elementIndex, float u, float v);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshElementTangentAdd(IntPtr mesh, int elementIndex, float x, float y, float z, float w);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshElementVertexColorAdd(IntPtr mesh, int elementIndex, float r, float g, float b, float a);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshSetBoneWeight(IntPtr pClusterArray, int boneIndex, int vertexIndex, float weight);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxMeshCreateSkinContext(IntPtr context, IntPtr frameNode);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshDisposeSkinContext(ref IntPtr ppSkinContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool FbxClusterArray_HasItemAt(IntPtr pClusterArray, int index);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private unsafe static extern void AsFbxMeshSkinAddCluster(IntPtr pSkinContext, IntPtr pClusterArray, int index, float* pBoneMatrix);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMeshAddDeformer(IntPtr pSkinContext, IntPtr pMesh);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxAnimCreateContext([MarshalAs(UnmanagedType.Bool)] bool eulerFilter);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimDisposeContext(ref IntPtr ppAnimContext);
|
||||||
|
|
||||||
|
private static void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, string takeName)
|
||||||
|
{
|
||||||
|
using (var takeNameUtf8 = new Utf8StringHandle(takeName))
|
||||||
|
{
|
||||||
|
AsFbxAnimPrepareStackAndLayer(pContext, pAnimContext, takeNameUtf8.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimPrepareStackAndLayer(IntPtr pContext, IntPtr pAnimContext, IntPtr strTakeName);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimLoadCurves(IntPtr pNode, IntPtr pAnimContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimBeginKeyModify(IntPtr pAnimContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimEndKeyModify(IntPtr pAnimContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimAddScalingKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimAddRotationKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimAddTranslationKey(IntPtr pAnimContext, float time, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimApplyEulerFilter(IntPtr pAnimContext, float filterPrecision);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern int AsFbxAnimGetCurrentBlendShapeChannelCount(IntPtr pAnimContext, IntPtr pNode);
|
||||||
|
|
||||||
|
private static bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, string channelName)
|
||||||
|
{
|
||||||
|
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
|
||||||
|
{
|
||||||
|
return AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, channelNameUtf8.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static extern bool AsFbxAnimIsBlendShapeChannelMatch(IntPtr pAnimContext, int channelIndex, IntPtr strChannelName);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimBeginBlendShapeAnimCurve(IntPtr pAnimContext, int channelIndex);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimEndBlendShapeAnimCurve(IntPtr pAnimContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxAnimAddBlendShapeKeyframe(IntPtr pAnimContext, float time, float value);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern IntPtr AsFbxMorphCreateContext();
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphInitializeContext(IntPtr pContext, IntPtr pMorphContext, IntPtr pNode);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphDisposeContext(ref IntPtr ppMorphContext);
|
||||||
|
|
||||||
|
private static void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, string channelName)
|
||||||
|
{
|
||||||
|
using (var channelNameUtf8 = new Utf8StringHandle(channelName))
|
||||||
|
{
|
||||||
|
AsFbxMorphAddBlendShapeChannel(pContext, pMorphContext, channelNameUtf8.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphAddBlendShapeChannel(IntPtr pContext, IntPtr pMorphContext, IntPtr strChannelName);
|
||||||
|
|
||||||
|
private static void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, string shapeName)
|
||||||
|
{
|
||||||
|
using (var shapeNameUtf8 = new Utf8StringHandle(shapeName))
|
||||||
|
{
|
||||||
|
AsFbxMorphAddBlendShapeChannelShape(pContext, pMorphContext, weight, shapeNameUtf8.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphAddBlendShapeChannelShape(IntPtr pContext, IntPtr pMorphContext, float weight, IntPtr strShapeName);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphCopyBlendShapeControlPoints(IntPtr pMorphContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphSetBlendShapeVertex(IntPtr pMorphContext, uint index, float x, float y, float z);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphCopyBlendShapeControlPointsNormal(IntPtr pMorphContext);
|
||||||
|
|
||||||
|
[DllImport(FbxDll.DllName, CallingConvention = CallingConvention.Winapi)]
|
||||||
|
private static extern void AsFbxMorphSetBlendShapeVertexNormal(IntPtr pMorphContext, uint index, float x, float y, float z);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,643 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace AssetStudio.FbxInterop
|
||||||
|
{
|
||||||
|
internal sealed partial class FbxExporterContext : IDisposable
|
||||||
|
{
|
||||||
|
|
||||||
|
private IntPtr _pContext;
|
||||||
|
private readonly Dictionary<ImportedFrame, IntPtr> _frameToNode;
|
||||||
|
private readonly List<KeyValuePair<string, IntPtr>> _createdMaterials;
|
||||||
|
private readonly Dictionary<string, IntPtr> _createdTextures;
|
||||||
|
|
||||||
|
public FbxExporterContext()
|
||||||
|
{
|
||||||
|
_pContext = AsFbxCreateContext();
|
||||||
|
_frameToNode = new Dictionary<ImportedFrame, IntPtr>();
|
||||||
|
_createdMaterials = new List<KeyValuePair<string, IntPtr>>();
|
||||||
|
_createdTextures = new Dictionary<string, IntPtr>();
|
||||||
|
}
|
||||||
|
|
||||||
|
~FbxExporterContext()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (IsDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
IsDisposed = true;
|
||||||
|
|
||||||
|
_frameToNode.Clear();
|
||||||
|
_createdMaterials.Clear();
|
||||||
|
_createdTextures.Clear();
|
||||||
|
|
||||||
|
AsFbxDisposeContext(ref _pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureNotDisposed()
|
||||||
|
{
|
||||||
|
if (IsDisposed)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(nameof(FbxExporterContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void Initialize(string fileName, float scaleFactor, int versionIndex, bool isAscii, bool is60Fps)
|
||||||
|
{
|
||||||
|
EnsureNotDisposed();
|
||||||
|
|
||||||
|
var b = AsFbxInitializeContext(_pContext, fileName, scaleFactor, versionIndex, isAscii, is60Fps, out var errorMessage);
|
||||||
|
|
||||||
|
if (!b)
|
||||||
|
{
|
||||||
|
var fullMessage = $"Failed to initialize FbxExporter: {errorMessage}";
|
||||||
|
throw new ApplicationException(fullMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetFramePaths(HashSet<string> framePaths)
|
||||||
|
{
|
||||||
|
EnsureNotDisposed();
|
||||||
|
|
||||||
|
if (framePaths == null || framePaths.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var framePathList = new List<string>(framePaths);
|
||||||
|
var framePathArray = framePathList.ToArray();
|
||||||
|
|
||||||
|
AsFbxSetFramePaths(_pContext, framePathArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportScene()
|
||||||
|
{
|
||||||
|
EnsureNotDisposed();
|
||||||
|
|
||||||
|
AsFbxExportScene(_pContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportFrame(List<ImportedMesh> meshList, List<ImportedFrame> meshFrames, ImportedFrame rootFrame)
|
||||||
|
{
|
||||||
|
var rootNode = AsFbxGetSceneRootNode(_pContext);
|
||||||
|
|
||||||
|
Debug.Assert(rootNode != IntPtr.Zero);
|
||||||
|
|
||||||
|
var nodeStack = new Stack<IntPtr>();
|
||||||
|
var frameStack = new Stack<ImportedFrame>();
|
||||||
|
|
||||||
|
nodeStack.Push(rootNode);
|
||||||
|
frameStack.Push(rootFrame);
|
||||||
|
|
||||||
|
while (nodeStack.Count > 0)
|
||||||
|
{
|
||||||
|
var parentNode = nodeStack.Pop();
|
||||||
|
var frame = frameStack.Pop();
|
||||||
|
|
||||||
|
var childNode = AsFbxExportSingleFrame(_pContext, parentNode, frame.Path, frame.Name, frame.LocalPosition, frame.LocalRotation, frame.LocalScale);
|
||||||
|
|
||||||
|
if (meshList != null && ImportedHelpers.FindMesh(frame.Path, meshList) != null)
|
||||||
|
{
|
||||||
|
meshFrames.Add(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
_frameToNode.Add(frame, childNode);
|
||||||
|
|
||||||
|
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||||
|
{
|
||||||
|
nodeStack.Push(childNode);
|
||||||
|
frameStack.Push(frame[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetJointsNode(ImportedFrame rootFrame, HashSet<string> bonePaths, bool castToBone, float boneSize)
|
||||||
|
{
|
||||||
|
var frameStack = new Stack<ImportedFrame>();
|
||||||
|
|
||||||
|
frameStack.Push(rootFrame);
|
||||||
|
|
||||||
|
while (frameStack.Count > 0)
|
||||||
|
{
|
||||||
|
var frame = frameStack.Pop();
|
||||||
|
|
||||||
|
if (_frameToNode.TryGetValue(frame, out var node))
|
||||||
|
{
|
||||||
|
Debug.Assert(node != IntPtr.Zero);
|
||||||
|
|
||||||
|
if (castToBone)
|
||||||
|
{
|
||||||
|
AsFbxSetJointsNode_CastToBone(_pContext, node, boneSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(bonePaths != null);
|
||||||
|
|
||||||
|
if (bonePaths.Contains(frame.Path))
|
||||||
|
{
|
||||||
|
AsFbxSetJointsNode_BoneInPath(_pContext, node, boneSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AsFbxSetJointsNode_Generic(_pContext, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = frame.Count - 1; i >= 0; i -= 1)
|
||||||
|
{
|
||||||
|
frameStack.Push(frame[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void PrepareMaterials(int materialCount, int textureCount)
|
||||||
|
{
|
||||||
|
AsFbxPrepareMaterials(_pContext, materialCount, textureCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins, bool exportAllUvsAsDiffuseMaps)
|
||||||
|
{
|
||||||
|
var meshNode = _frameToNode[meshFrame];
|
||||||
|
var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);
|
||||||
|
|
||||||
|
ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IntPtr ExportTexture(ImportedTexture texture)
|
||||||
|
{
|
||||||
|
if (texture == null)
|
||||||
|
{
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_createdTextures.ContainsKey(texture.Name))
|
||||||
|
{
|
||||||
|
return _createdTextures[texture.Name];
|
||||||
|
}
|
||||||
|
|
||||||
|
var pTex = AsFbxCreateTexture(_pContext, texture.Name);
|
||||||
|
|
||||||
|
_createdTextures.Add(texture.Name, pTex);
|
||||||
|
|
||||||
|
var file = new FileInfo(texture.Name);
|
||||||
|
|
||||||
|
using (var writer = new BinaryWriter(file.Create()))
|
||||||
|
{
|
||||||
|
writer.Write(texture.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps)
|
||||||
|
{
|
||||||
|
var boneList = importedMesh.BoneList;
|
||||||
|
var totalBoneCount = 0;
|
||||||
|
var hasBones = false;
|
||||||
|
if (exportSkins && boneList?.Count > 0)
|
||||||
|
{
|
||||||
|
totalBoneCount = boneList.Count;
|
||||||
|
hasBones = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pClusterArray = IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (hasBones)
|
||||||
|
{
|
||||||
|
pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount);
|
||||||
|
|
||||||
|
foreach (var bone in boneList)
|
||||||
|
{
|
||||||
|
if (bone.Path != null)
|
||||||
|
{
|
||||||
|
var frame = rootFrame.FindFrameByPath(bone.Path);
|
||||||
|
var boneNode = _frameToNode[frame];
|
||||||
|
|
||||||
|
var cluster = AsFbxMeshCreateCluster(_pContext, boneNode);
|
||||||
|
|
||||||
|
AsFbxMeshAddCluster(pClusterArray, cluster);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);
|
||||||
|
|
||||||
|
AsFbxMeshInitControlPoints(mesh, importedMesh.VertexList.Count);
|
||||||
|
|
||||||
|
if (importedMesh.hasNormal)
|
||||||
|
{
|
||||||
|
AsFbxMeshCreateElementNormal(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < importedMesh.hasUV.Length; i++)
|
||||||
|
{
|
||||||
|
if (!importedMesh.hasUV[i]) { continue; }
|
||||||
|
|
||||||
|
if (i == 1 && !exportAllUvsAsDiffuseMaps)
|
||||||
|
{
|
||||||
|
AsFbxMeshCreateNormalMapUV(mesh, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AsFbxMeshCreateDiffuseUV(mesh, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importedMesh.hasTangent)
|
||||||
|
{
|
||||||
|
AsFbxMeshCreateElementTangent(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importedMesh.hasColor)
|
||||||
|
{
|
||||||
|
AsFbxMeshCreateElementVertexColor(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxMeshCreateElementMaterial(mesh);
|
||||||
|
|
||||||
|
foreach (var meshObj in importedMesh.SubmeshList)
|
||||||
|
{
|
||||||
|
var materialIndex = 0;
|
||||||
|
var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList);
|
||||||
|
|
||||||
|
if (mat != null)
|
||||||
|
{
|
||||||
|
var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name);
|
||||||
|
IntPtr pMat;
|
||||||
|
|
||||||
|
if (foundMat >= 0)
|
||||||
|
{
|
||||||
|
pMat = _createdMaterials[foundMat].Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var diffuse = mat.Diffuse;
|
||||||
|
var ambient = mat.Ambient;
|
||||||
|
var emissive = mat.Emissive;
|
||||||
|
var specular = mat.Specular;
|
||||||
|
var reflection = mat.Reflection;
|
||||||
|
|
||||||
|
pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency);
|
||||||
|
|
||||||
|
_createdMaterials.Add(new KeyValuePair<string, IntPtr>(mat.Name, pMat));
|
||||||
|
}
|
||||||
|
|
||||||
|
materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat);
|
||||||
|
|
||||||
|
var hasTexture = false;
|
||||||
|
|
||||||
|
foreach (var texture in mat.Textures)
|
||||||
|
{
|
||||||
|
var tex = ImportedHelpers.FindTexture(texture.Name, textureList);
|
||||||
|
var pTexture = ExportTexture(tex);
|
||||||
|
|
||||||
|
if (pTexture != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
switch (texture.Dest)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y);
|
||||||
|
hasTexture = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasTexture)
|
||||||
|
{
|
||||||
|
AsFbxSetFrameShadingModeToTextureShading(frameNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var face in meshObj.FaceList)
|
||||||
|
{
|
||||||
|
var index0 = face.VertexIndices[0] + meshObj.BaseVertex;
|
||||||
|
var index1 = face.VertexIndices[1] + meshObj.BaseVertex;
|
||||||
|
var index2 = face.VertexIndices[2] + meshObj.BaseVertex;
|
||||||
|
|
||||||
|
AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var vertexList = importedMesh.VertexList;
|
||||||
|
|
||||||
|
var vertexCount = vertexList.Count;
|
||||||
|
|
||||||
|
for (var j = 0; j < vertexCount; j += 1)
|
||||||
|
{
|
||||||
|
var importedVertex = vertexList[j];
|
||||||
|
|
||||||
|
var vertex = importedVertex.Vertex;
|
||||||
|
AsFbxMeshSetControlPoint(mesh, j, vertex.X, vertex.Y, vertex.Z);
|
||||||
|
|
||||||
|
if (importedMesh.hasNormal)
|
||||||
|
{
|
||||||
|
var normal = importedVertex.Normal;
|
||||||
|
AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var uvIndex = 0; uvIndex < importedMesh.hasUV.Length; uvIndex += 1)
|
||||||
|
{
|
||||||
|
if (importedMesh.hasUV[uvIndex])
|
||||||
|
{
|
||||||
|
var uv = importedVertex.UV[uvIndex];
|
||||||
|
AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importedMesh.hasTangent)
|
||||||
|
{
|
||||||
|
var tangent = importedVertex.Tangent;
|
||||||
|
AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (importedMesh.hasColor)
|
||||||
|
{
|
||||||
|
var color = importedVertex.Color;
|
||||||
|
AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasBones && importedVertex.BoneIndices != null)
|
||||||
|
{
|
||||||
|
var boneIndices = importedVertex.BoneIndices;
|
||||||
|
var boneWeights = importedVertex.Weights;
|
||||||
|
|
||||||
|
for (var k = 0; k < 4; k += 1)
|
||||||
|
{
|
||||||
|
if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0)
|
||||||
|
{
|
||||||
|
AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j, boneWeights[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hasBones)
|
||||||
|
{
|
||||||
|
IntPtr pSkinContext = IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode);
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var boneMatrix = stackalloc float[16];
|
||||||
|
|
||||||
|
for (var j = 0; j < totalBoneCount; j += 1)
|
||||||
|
{
|
||||||
|
if (!FbxClusterArray_HasItemAt(pClusterArray, j))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var m = boneList[j].Matrix;
|
||||||
|
|
||||||
|
CopyMatrix4x4(in m, boneMatrix);
|
||||||
|
|
||||||
|
AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxMeshAddDeformer(pSkinContext, mesh);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AsFbxMeshDisposeSkinContext(ref pSkinContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AsFbxMeshDisposeClusterArray(ref pClusterArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static unsafe void CopyMatrix4x4(in Matrix4x4 matrix, float* buffer)
|
||||||
|
{
|
||||||
|
for (var m = 0; m < 4; m += 1)
|
||||||
|
{
|
||||||
|
for (var n = 0; n < 4; n += 1)
|
||||||
|
{
|
||||||
|
var index = IndexFrom4x4(m, n);
|
||||||
|
buffer[index] = matrix[m, n];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int IndexFrom4x4(int m, int n)
|
||||||
|
{
|
||||||
|
return 4 * m + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportAnimations(ImportedFrame rootFrame, List<ImportedKeyframedAnimation> animationList, bool eulerFilter, float filterPrecision)
|
||||||
|
{
|
||||||
|
if (animationList == null || animationList.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pAnimContext = IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pAnimContext = AsFbxAnimCreateContext(eulerFilter);
|
||||||
|
|
||||||
|
for (int i = 0; i < animationList.Count; i++)
|
||||||
|
{
|
||||||
|
var importedAnimation = animationList[i];
|
||||||
|
string takeName;
|
||||||
|
|
||||||
|
if (importedAnimation.Name != null)
|
||||||
|
{
|
||||||
|
takeName = importedAnimation.Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
takeName = $"Take{i.ToString()}";
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxAnimPrepareStackAndLayer(_pContext, pAnimContext, takeName);
|
||||||
|
|
||||||
|
ExportKeyframedAnimation(rootFrame, importedAnimation, pAnimContext, filterPrecision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AsFbxAnimDisposeContext(ref pAnimContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExportKeyframedAnimation(ImportedFrame rootFrame, ImportedKeyframedAnimation parser, IntPtr pAnimContext, float filterPrecision)
|
||||||
|
{
|
||||||
|
foreach (var track in parser.TrackList)
|
||||||
|
{
|
||||||
|
if (track.Path == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var frame = rootFrame.FindFrameByPath(track.Path);
|
||||||
|
|
||||||
|
if (frame == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pNode = _frameToNode[frame];
|
||||||
|
|
||||||
|
AsFbxAnimLoadCurves(pNode, pAnimContext);
|
||||||
|
|
||||||
|
AsFbxAnimBeginKeyModify(pAnimContext);
|
||||||
|
|
||||||
|
foreach (var scaling in track.Scalings)
|
||||||
|
{
|
||||||
|
var value = scaling.value;
|
||||||
|
AsFbxAnimAddScalingKey(pAnimContext, scaling.time, value.X, value.Y, value.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var rotation in track.Rotations)
|
||||||
|
{
|
||||||
|
var value = rotation.value;
|
||||||
|
AsFbxAnimAddRotationKey(pAnimContext, rotation.time, value.X, value.Y, value.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var translation in track.Translations)
|
||||||
|
{
|
||||||
|
var value = translation.value;
|
||||||
|
AsFbxAnimAddTranslationKey(pAnimContext, translation.time, value.X, value.Y, value.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxAnimEndKeyModify(pAnimContext);
|
||||||
|
|
||||||
|
AsFbxAnimApplyEulerFilter(pAnimContext, filterPrecision);
|
||||||
|
|
||||||
|
var blendShape = track.BlendShape;
|
||||||
|
|
||||||
|
if (blendShape != null)
|
||||||
|
{
|
||||||
|
var channelCount = AsFbxAnimGetCurrentBlendShapeChannelCount(pAnimContext, pNode);
|
||||||
|
|
||||||
|
if (channelCount > 0)
|
||||||
|
{
|
||||||
|
for (var channelIndex = 0; channelIndex < channelCount; channelIndex += 1)
|
||||||
|
{
|
||||||
|
if (!AsFbxAnimIsBlendShapeChannelMatch(pAnimContext, channelIndex, blendShape.ChannelName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxAnimBeginBlendShapeAnimCurve(pAnimContext, channelIndex);
|
||||||
|
|
||||||
|
foreach (var keyframe in blendShape.Keyframes)
|
||||||
|
{
|
||||||
|
AsFbxAnimAddBlendShapeKeyframe(pAnimContext, keyframe.time, keyframe.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
AsFbxAnimEndBlendShapeAnimCurve(pAnimContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ExportMorphs(ImportedFrame rootFrame, List<ImportedMorph> morphList)
|
||||||
|
{
|
||||||
|
if (morphList == null || morphList.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var morph in morphList)
|
||||||
|
{
|
||||||
|
var frame = rootFrame.FindFrameByPath(morph.Path);
|
||||||
|
|
||||||
|
if (frame == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pNode = _frameToNode[frame];
|
||||||
|
|
||||||
|
var pMorphContext = IntPtr.Zero;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pMorphContext = AsFbxMorphCreateContext();
|
||||||
|
|
||||||
|
AsFbxMorphInitializeContext(_pContext, pMorphContext, pNode);
|
||||||
|
|
||||||
|
foreach (var channel in morph.Channels)
|
||||||
|
{
|
||||||
|
AsFbxMorphAddBlendShapeChannel(_pContext, pMorphContext, channel.Name);
|
||||||
|
|
||||||
|
for (var i = 0; i < channel.KeyframeList.Count; i++)
|
||||||
|
{
|
||||||
|
var keyframe = channel.KeyframeList[i];
|
||||||
|
|
||||||
|
AsFbxMorphAddBlendShapeChannelShape(_pContext, pMorphContext, keyframe.Weight, i == 0 ? channel.Name : $"{channel.Name}_{i + 1}");
|
||||||
|
|
||||||
|
AsFbxMorphCopyBlendShapeControlPoints(pMorphContext);
|
||||||
|
|
||||||
|
foreach (var vertex in keyframe.VertexList)
|
||||||
|
{
|
||||||
|
var v = vertex.Vertex.Vertex;
|
||||||
|
AsFbxMorphSetBlendShapeVertex(pMorphContext, vertex.Index, v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyframe.hasNormals)
|
||||||
|
{
|
||||||
|
AsFbxMorphCopyBlendShapeControlPointsNormal(pMorphContext);
|
||||||
|
|
||||||
|
foreach (var vertex in keyframe.VertexList)
|
||||||
|
{
|
||||||
|
var v = vertex.Vertex.Normal;
|
||||||
|
AsFbxMorphSetBlendShapeVertexNormal(pMorphContext, vertex.Index, v.X, v.Y, v.Z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
AsFbxMorphDisposeContext(ref pMorphContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,192 +1,84 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<OutputType>WinExe</OutputType>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
<TargetFrameworks>net472;net5.0-windows;net6.0-windows</TargetFrameworks>
|
||||||
<ProductVersion>8.0.30703</ProductVersion>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
<ProjectGuid>{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}</ProjectGuid>
|
<Version>0.16.0.0</Version>
|
||||||
<OutputType>WinExe</OutputType>
|
<AssemblyVersion>0.16.0.0</AssemblyVersion>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<FileVersion>0.16.0.0</FileVersion>
|
||||||
<RootNamespace>AssetStudioGUI</RootNamespace>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<AssemblyName>AssetStudioGUI</AssemblyName>
|
<DebugType>embedded</DebugType>
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
</PropertyGroup>
|
||||||
<TargetFrameworkProfile>
|
|
||||||
</TargetFrameworkProfile>
|
<ItemGroup>
|
||||||
<FileAlignment>512</FileAlignment>
|
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
|
||||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||||
<PublishUrl>publish\</PublishUrl>
|
</ItemGroup>
|
||||||
<Install>true</Install>
|
|
||||||
<InstallFrom>Disk</InstallFrom>
|
<ItemGroup>
|
||||||
<UpdateEnabled>false</UpdateEnabled>
|
<None Include="Properties\Settings.settings">
|
||||||
<UpdateMode>Foreground</UpdateMode>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
<UpdateInterval>7</UpdateInterval>
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
</None>
|
||||||
<UpdatePeriodically>false</UpdatePeriodically>
|
<Compile Update="Properties\Settings.Designer.cs">
|
||||||
<UpdateRequired>false</UpdateRequired>
|
<AutoGen>True</AutoGen>
|
||||||
<MapFileExtensions>true</MapFileExtensions>
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
<ApplicationRevision>0</ApplicationRevision>
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
</Compile>
|
||||||
<UseApplicationTrust>false</UseApplicationTrust>
|
</ItemGroup>
|
||||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
|
||||||
</PropertyGroup>
|
<ItemGroup>
|
||||||
<PropertyGroup>
|
<EmbeddedResource Update="Properties\Resources.resx">
|
||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
</PropertyGroup>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
</EmbeddedResource>
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<Compile Update="Properties\Resources.Designer.cs">
|
||||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
<AutoGen>True</AutoGen>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
<DebugType>full</DebugType>
|
<DesignTime>True</DesignTime>
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
</Compile>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
</ItemGroup>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
|
||||||
</PropertyGroup>
|
<ItemGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
|
||||||
<OutputPath>bin\x64\Release\</OutputPath>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<TargetPath>x86\fmod.dll</TargetPath>
|
||||||
<Optimize>true</Optimize>
|
</ContentWithTargetPath>
|
||||||
<DebugType>pdbonly</DebugType>
|
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
|
||||||
<PlatformTarget>x64</PlatformTarget>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<TargetPath>x64\fmod.dll</TargetPath>
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
</ContentWithTargetPath>
|
||||||
</PropertyGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
|
||||||
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
</PropertyGroup>
|
<PackageReference Include="OpenTK" Version="4.6.7" />
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
<Reference Include="OpenTK.WinForms">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
||||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
</Reference>
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
</ItemGroup>
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<PackageReference Include="OpenTK" Version="3.1.0" />
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
|
||||||
</PropertyGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
|
||||||
<OutputPath>bin\x86\Release\</OutputPath>
|
<ItemGroup>
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<Optimize>true</Optimize>
|
</ItemGroup>
|
||||||
<DebugType>pdbonly</DebugType>
|
|
||||||
<PlatformTarget>x86</PlatformTarget>
|
<Target Name="CopyExtraFiles" AfterTargets="AfterBuild">
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||||
</PropertyGroup>
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||||
<ItemGroup>
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||||
<Reference Include="OpenTK">
|
</Target>
|
||||||
<HintPath>Libraries\OpenTK.dll</HintPath>
|
|
||||||
</Reference>
|
<Target Name="PublishExtraFiles" AfterTargets="Publish">
|
||||||
<Reference Include="OpenTK.GLControl">
|
<Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
|
||||||
<HintPath>Libraries\OpenTK.GLControl.dll</HintPath>
|
<Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
|
||||||
</Reference>
|
<Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
|
||||||
<Reference Include="System" />
|
<Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
|
||||||
<Reference Include="System.Core" />
|
</Target>
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Drawing" />
|
|
||||||
<Reference Include="System.Windows.Forms" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="GUILogger.cs" />
|
|
||||||
<Compile Include="GUIProgress.cs" />
|
|
||||||
<Compile Include="Components\GameObjectTreeNode.cs" />
|
|
||||||
<Compile Include="Components\OpenFolderDialog.cs" />
|
|
||||||
<Compile Include="Components\AssetItem.cs" />
|
|
||||||
<Compile Include="Exporter.cs" />
|
|
||||||
<Compile Include="Studio.cs" />
|
|
||||||
<Compile Include="ExportOptions.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="ExportOptions.Designer.cs">
|
|
||||||
<DependentUpon>ExportOptions.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Components\GOHierarchy.cs">
|
|
||||||
<SubType>Component</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Program.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
<Compile Include="AssetStudioGUIForm.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="AssetStudioGUIForm.Designer.cs">
|
|
||||||
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Components\TypeTreeItem.cs" />
|
|
||||||
<Compile Include="Components\TreeViewExtensions.cs" />
|
|
||||||
<EmbeddedResource Include="ExportOptions.resx">
|
|
||||||
<DependentUpon>ExportOptions.cs</DependentUpon>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<Compile Include="Properties\Resources.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Resources.resx</DependentUpon>
|
|
||||||
<DesignTime>True</DesignTime>
|
|
||||||
</Compile>
|
|
||||||
<EmbeddedResource Include="AssetStudioGUIForm.resx">
|
|
||||||
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</EmbeddedResource>
|
|
||||||
<None Include="app.config" />
|
|
||||||
<None Include="Properties\Settings.settings">
|
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
|
||||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
|
||||||
</None>
|
|
||||||
<Compile Include="Properties\Settings.Designer.cs">
|
|
||||||
<AutoGen>True</AutoGen>
|
|
||||||
<DependentUpon>Settings.settings</DependentUpon>
|
|
||||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
|
||||||
</Compile>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
|
|
||||||
<Install>true</Install>
|
|
||||||
</BootstrapperPackage>
|
|
||||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
|
||||||
<Install>false</Install>
|
|
||||||
</BootstrapperPackage>
|
|
||||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
|
|
||||||
<Visible>False</Visible>
|
|
||||||
<ProductName>Windows Installer 4.5</ProductName>
|
|
||||||
<Install>true</Install>
|
|
||||||
</BootstrapperPackage>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\preview.png" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="Resources\as.ico" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj">
|
|
||||||
<Project>{9131c403-7fe8-444d-9af5-5fe5df76ff24}</Project>
|
|
||||||
<Name>AssetStudioUtility</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
|
|
||||||
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
|
|
||||||
<Name>AssetStudio</Name>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
|
||||||
<PropertyGroup>
|
|
||||||
<PostBuildEvent>xcopy /y "$(ProjectDir)Libraries" "$(TargetDir)"
|
|
||||||
xcopy /y "$(ProjectDir)Libraries\$(PlatformName)" "$(TargetDir)"</PostBuildEvent>
|
|
||||||
</PropertyGroup>
|
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
|
||||||
<Target Name="BeforeBuild">
|
|
||||||
</Target>
|
|
||||||
<Target Name="AfterBuild">
|
|
||||||
</Target>
|
|
||||||
-->
|
|
||||||
</Project>
|
</Project>
|
||||||
+411
-241
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -147,9 +147,6 @@ The quick brown fox jumps over the lazy dog. 1234567890</value>
|
|||||||
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="openFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>636, 17</value>
|
<value>636, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<metadata name="saveFileDialog1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>784, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="contextMenuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>147, 17</value>
|
<value>147, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
public Object Asset;
|
public Object Asset;
|
||||||
public SerializedFile SourceFile;
|
public SerializedFile SourceFile;
|
||||||
|
public string Container = string.Empty;
|
||||||
|
public string TypeString;
|
||||||
|
public long m_PathID;
|
||||||
public long FullSize;
|
public long FullSize;
|
||||||
public ClassIDType Type;
|
public ClassIDType Type;
|
||||||
public string TypeString;
|
|
||||||
|
|
||||||
public string Extension;
|
|
||||||
public string InfoText;
|
public string InfoText;
|
||||||
public string UniqueID;
|
public string UniqueID;
|
||||||
public GameObjectTreeNode TreeNode;
|
public GameObjectTreeNode TreeNode;
|
||||||
@@ -20,9 +20,21 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
Asset = asset;
|
Asset = asset;
|
||||||
SourceFile = asset.assetsFile;
|
SourceFile = asset.assetsFile;
|
||||||
FullSize = asset.byteSize;
|
|
||||||
Type = asset.type;
|
Type = asset.type;
|
||||||
TypeString = Type.ToString();
|
TypeString = Type.ToString();
|
||||||
|
m_PathID = asset.m_PathID;
|
||||||
|
FullSize = asset.byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetSubItems()
|
||||||
|
{
|
||||||
|
SubItems.AddRange(new[]
|
||||||
|
{
|
||||||
|
Container, //Container
|
||||||
|
TypeString, //Type
|
||||||
|
m_PathID.ToString(), //PathID
|
||||||
|
FullSize.ToString(), //Size
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
public GameObject gameObject;
|
public GameObject gameObject;
|
||||||
|
|
||||||
public GameObjectTreeNode(string name)
|
|
||||||
{
|
|
||||||
Text = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GameObjectTreeNode(GameObject gameObject)
|
public GameObjectTreeNode(GameObject gameObject)
|
||||||
{
|
{
|
||||||
this.gameObject = gameObject;
|
this.gameObject = gameObject;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@@ -15,12 +14,13 @@ namespace AssetStudioGUI
|
|||||||
|
|
||||||
internal DialogResult ShowDialog(IWin32Window owner = null)
|
internal DialogResult ShowDialog(IWin32Window owner = null)
|
||||||
{
|
{
|
||||||
|
//#if NETFRAMEWORK
|
||||||
if (Environment.OSVersion.Version.Major >= 6)
|
if (Environment.OSVersion.Version.Major >= 6)
|
||||||
{
|
{
|
||||||
return ShowVistaDialog(owner);
|
return ShowVistaDialog(owner);
|
||||||
}
|
}
|
||||||
|
//#endif
|
||||||
return ShowLegacyDialog(owner);
|
return ShowFolderBrowserDialog(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
private DialogResult ShowVistaDialog(IWin32Window owner)
|
private DialogResult ShowVistaDialog(IWin32Window owner)
|
||||||
@@ -29,9 +29,11 @@ namespace AssetStudioGUI
|
|||||||
frm.GetOptions(out var options);
|
frm.GetOptions(out var options);
|
||||||
options |= NativeMethods.FOS_PICKFOLDERS | NativeMethods.FOS_FORCEFILESYSTEM | NativeMethods.FOS_NOVALIDATE | NativeMethods.FOS_NOTESTFILECREATE | NativeMethods.FOS_DONTADDTORECENT;
|
options |= NativeMethods.FOS_PICKFOLDERS | NativeMethods.FOS_FORCEFILESYSTEM | NativeMethods.FOS_NOVALIDATE | NativeMethods.FOS_NOTESTFILECREATE | NativeMethods.FOS_DONTADDTORECENT;
|
||||||
frm.SetOptions(options);
|
frm.SetOptions(options);
|
||||||
if (Title != null)
|
if (!string.IsNullOrEmpty(Title))
|
||||||
|
{
|
||||||
frm.SetTitle(Title);
|
frm.SetTitle(Title);
|
||||||
if (InitialFolder != null)
|
}
|
||||||
|
if (!string.IsNullOrEmpty(InitialFolder))
|
||||||
{
|
{
|
||||||
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
||||||
if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
|
if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
|
||||||
@@ -39,7 +41,7 @@ namespace AssetStudioGUI
|
|||||||
frm.SetFolder(directoryShellItem);
|
frm.SetFolder(directoryShellItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (DefaultFolder != null)
|
if (!string.IsNullOrEmpty(DefaultFolder))
|
||||||
{
|
{
|
||||||
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
|
||||||
if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
|
if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
|
||||||
@@ -72,7 +74,7 @@ namespace AssetStudioGUI
|
|||||||
return DialogResult.Cancel;
|
return DialogResult.Cancel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DialogResult ShowLegacyDialog(IWin32Window owner)
|
private DialogResult ShowFolderBrowserDialog(IWin32Window owner)
|
||||||
{
|
{
|
||||||
using (var frm = new FolderBrowserDialog())
|
using (var frm = new FolderBrowserDialog())
|
||||||
{
|
{
|
||||||
@@ -80,13 +82,20 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
frm.SelectedPath = InitialFolder;
|
frm.SelectedPath = InitialFolder;
|
||||||
}
|
}
|
||||||
if ((owner == null ? frm.ShowDialog() : frm.ShowDialog(owner)) == DialogResult.OK)
|
#if !NETFRAMEWORK
|
||||||
|
if (Title != null)
|
||||||
{
|
{
|
||||||
Folder = Path.GetDirectoryName(frm.SelectedPath);
|
frm.Description = Title;
|
||||||
return DialogResult.OK;
|
frm.UseDescriptionForTitle = true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return DialogResult.Cancel;
|
var result = owner == null ? frm.ShowDialog() : frm.ShowDialog(owner);
|
||||||
|
if (result == DialogResult.OK)
|
||||||
|
{
|
||||||
|
Folder = frm.SelectedPath;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
namespace AssetStudioGUI
|
|
||||||
{
|
|
||||||
internal static class TreeViewExtensions
|
|
||||||
{
|
|
||||||
private const int TVIF_STATE = 0x8;
|
|
||||||
private const int TVIS_STATEIMAGEMASK = 0xF000;
|
|
||||||
private const int TV_FIRST = 0x1100;
|
|
||||||
private const int TVM_SETITEM = TV_FIRST + 63;
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
|
|
||||||
private struct TVITEM
|
|
||||||
{
|
|
||||||
public int mask;
|
|
||||||
public IntPtr hItem;
|
|
||||||
public int state;
|
|
||||||
public int stateMask;
|
|
||||||
[MarshalAs(UnmanagedType.LPTStr)]
|
|
||||||
public string lpszText;
|
|
||||||
public int cchTextMax;
|
|
||||||
public int iImage;
|
|
||||||
public int iSelectedImage;
|
|
||||||
public int cChildren;
|
|
||||||
public IntPtr lParam;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
||||||
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hides the checkbox for the specified node on a TreeView control.
|
|
||||||
/// </summary>
|
|
||||||
public static void HideCheckBox(this TreeNode node)
|
|
||||||
{
|
|
||||||
var tvi = new TVITEM
|
|
||||||
{
|
|
||||||
hItem = node.Handle,
|
|
||||||
mask = TVIF_STATE,
|
|
||||||
stateMask = TVIS_STATEIMAGEMASK,
|
|
||||||
state = 0
|
|
||||||
};
|
|
||||||
SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user