Compare commits

...

68 Commits

Author SHA1 Message Date
Perfare d158e864b5 support 2022.1 2022-06-16 18:41:55 +08:00
Perfare b70b5196e3 update enum 2022-06-16 17:45:54 +08:00
Perfare 4f88841026 Fixed #962 2022-06-01 15:33:01 +08:00
Perfare dc9429feac minor improvements 2022-05-21 21:16:34 +08:00
Kanglai Qian a3c16ed3d6 avoid useless search for non exist files (#967) 2022-05-21 21:10:02 +08:00
Perfare 5b83eebdda support 2021.3 2022-05-21 17:38:40 +08:00
Perfare 1fcf7a4364 BundleFile fix 2022-05-21 17:24:54 +08:00
Perfare 973d50ce8b Fix type conversion bug 2022-05-21 05:46:44 +08:00
Perfare 50485a9bd3 update project file 2022-03-24 10:38:52 +08:00
Perfare dbb3d3fef7 revert 2022-03-24 09:47:36 +08:00
Perfare e1cfff63c3 minor fixes and improvements 2022-03-23 01:41:59 +08:00
Perfare 44514a4e10 Fixed #941 2022-03-22 22:54:49 +08:00
Perfare b1205808e2 Fix and improve Texture2D convert 2022-03-22 01:00:20 +08:00
Perfare 7d3a4a10fc Create build.yml 2022-03-20 02:36:32 +08:00
Perfare b909857820 Fixed #924 2022-03-19 08:06:03 +08:00
Perfare b674e66407 Fixed #929 2022-03-19 07:48:39 +08:00
Perfare d7dcd3f405 improved Sprite export
Fixed #944
Fixed #923
2022-03-19 07:43:53 +08:00
Perfare 44145e0b9c using IProgress 2022-03-19 06:40:51 +08:00
Perfare d4e21f824c Fixed #919 2022-02-17 01:07:24 +08:00
Rudolf Kolbe e7a4604a65 fix apk loading issues (#913)
* fix apk loading issues

Someone contacted me some days ago and notified me that some problems showed up with my APK loading implementation.
Namely:

file reference registration (importFilesHash) was missing
split files weren't handled
external resource files weren't registered
This pr fixes those problems.

* revert weird changes

* fix missing }

* fix formatting

* use entry.FullName for the basePath instead of entry.Name
2022-02-15 11:19:50 +08:00
Rudolf Kolbe 8d193a63cd Zip (including APK) Loading (#902)
* load ZipFile

makes it possible to directly load apk files

* use LoadFile for recursive zip opening

* set System.IO.Compression version

* keep identical format in AssetStudio.csproj

* try/catch the loading of each zip entry

* remove extra new line in FileReader.cs

* apply requested changes
2021-12-27 15:59:18 +08:00
brianpow e61a317185 use FullPath instead of FileName for easier identification of broken file (#900)
* use FullPath instead of FileName for easier identification of broken file.

* use FullPath instead of FileName for easier identification of broken file
2021-12-24 13:23:09 +08:00
scriptkitz 0e1a886e0b 修正UV导出计算错误问题。 (#891) 2021-12-11 15:48:54 +08:00
Perfare 97b5f51f3a Fix build 2021-12-09 20:23:25 +08:00
Perfare 7295feda72 Update README.md 2021-12-09 19:16:13 +08:00
Perfare fe95c91759 Add net6.0 target framework 2021-12-09 19:00:59 +08:00
Perfare d220315d9b Add detailed export progress in the status bar 2021-12-09 18:08:56 +08:00
Perfare a94caa5e34 Update project 2021-12-09 17:21:44 +08:00
Perfare 3660b4ed67 Some improvements 2021-12-09 17:13:21 +08:00
Perfare 3370f93037 Fixed bug 2021-12-06 17:37:59 +08:00
Perfare 80653711cd Performance improvement 2021-12-06 13:36:22 +08:00
Perfare 88c5804586 Fixed #886 2021-12-04 09:23:41 +08:00
Perfare e501940f03 Use a better way to crop Sprite 2021-12-04 08:44:33 +08:00
Perfare d4060cde6d Fixed bug 2021-12-04 02:05:35 +08:00
Perfare 582a779441 Update project file 2021-12-03 19:46:20 +08:00
Perfare 5fa4934787 Add net5.0 target framework 2021-12-03 17:21:24 +08:00
Perfare 18277fbea8 fixed bug 2021-12-03 17:05:06 +08:00
Perfare 2ce9cae957 Modify the prompt statement 2021-11-20 03:11:02 +08:00
Perfare af5e50cfa9 Update README.md 2021-11-20 02:52:53 +08:00
Perfare ce1172ca9a rename. closed #817 2021-11-19 18:24:18 +08:00
Perfare a7e6d91f5b Fixed bug 2021-11-19 18:22:39 +08:00
Perfare 34a0af683a Fixed bug 2021-11-19 18:11:00 +08:00
Perfare 91410a33b1 Improve the handling of compressed files. 2021-11-19 17:54:06 +08:00
Perfare d08b78c2cf support 2021.2 2021-11-12 10:25:22 +08:00
Perfare 2ef52afe1e Fixed #835 2021-11-12 09:30:12 +08:00
Perfare 05a41d2f1e Merge pull request #855 from nikitalita/fix-assembly-loading
Fix AssemblyLoading bug
2021-11-08 09:36:03 +08:00
nikitalita 34c38e1415 Fix AssemblyLoading bug
If the AssemblyLoader attempted to load a non-csil dll
while iterating through the file list, it would catch the exception
OUTSIDE the loop, and wouldn't load the rest.
This fix makes it catch inside the loop so it will continue iterating.
2021-10-07 13:36:03 -07:00
Perfare c85873b729 0.16.0 2021-07-06 16:03:54 +08:00
Perfare b146d251a7 add option to not show error message 2021-07-06 15:57:59 +08:00
Perfare 3129d67fc1 Improve ShaderConverter 2021-07-06 12:45:24 +08:00
Perfare 850ba63a10 support exporting VideoClips with a size above 2gb. close #765 2021-07-02 03:26:46 +08:00
Perfare 17b91984d6 fixed bug 2021-07-02 02:29:03 +08:00
Perfare 7ab2cda120 refactor the file reading part 2021-07-02 02:17:59 +08:00
Perfare 4345885cc9 remember the last opened path, close #646 2021-06-30 22:41:16 +08:00
Perfare 53720e37ab Fixed #435 2021-06-30 06:31:05 +08:00
Perfare 7c3cb36630 update project files 2021-06-29 11:03:19 +08:00
Perfare c1cddce031 added option to support version stripped files, close #766 2021-06-29 10:32:19 +08:00
Perfare 973a1076e4 support exporting AnimationClip versions below 4.3 2021-06-29 02:43:42 +08:00
Perfare 089e164756 improved Sprite export 2021-06-28 07:14:02 +08:00
Perfare c2b6691fd9 fix build 2021-06-27 09:42:13 +08:00
Perfare 8dec094304 update project files 2021-06-27 09:27:40 +08:00
Perfare bedee240be Use ImageSharp to process textures 2021-06-27 07:33:20 +08:00
Perfare d963d71b12 clean up TypeDefinitionConverter code 2021-06-26 13:16:12 +08:00
Perfare 77a0c9c40a Fbx multiple uv export 2021-06-24 13:48:56 +08:00
Perfare f3e406983b Merge pull request #768 from Fraxul/master
Fix blend shape export with multiple submeshes
2021-06-24 12:59:31 +08:00
Dan Weatherford 08b7bfcf9a Fix blend shape export with multiple submeshes
Share a single vertex list between submeshes in the exported mesh, which
makes the blend target vertex list indices line up correctly.

As a bonus, the exported FBX file will be smaller for meshes with more
than one submesh, since we're not duplicating vertices anymore.
2021-06-20 00:18:22 -05:00
Patrick King 57e4f7cefd Add an option to export all UVs as diffuse maps. 2021-06-11 17:12:15 -06:00
Patrick King c9cf2d188e Enable FBX export for higher UV maps. 2021-06-11 14:26:37 -06:00
96 changed files with 3998 additions and 9323 deletions
+57
View File
@@ -0,0 +1,57 @@
name: AssetStudioBuild
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: microsoft/setup-msbuild@v1.1
- name: Download FBX SDK
run: |
md fbx
cd fbx
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_win.exe" -OutFile "fbxsdk.exe"
Start-Process -FilePath "fbxsdk.exe" /S -Wait
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_pdbs.exe" -OutFile "fbxpdb.exe"
Start-Process -FilePath "fbxpdb.exe" /S -Wait
cd ..
- name: Nuget Restore
run: nuget restore
- name: Build .Net472
run: msbuild /p:Configuration=Release /p:TargetFramework=net472 /verbosity:minimal
- name: Build .Net5
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net5.0-windows /p:SelfContained=false /verbosity:minimal
- name: Build .Net6
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net6.0-windows /p:SelfContained=false /verbosity:minimal
- name: Upload .Net472 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net472
path: AssetStudioGUI/bin/Release/net472
- name: Upload .Net5 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net5
path: AssetStudioGUI/bin/Release/net5.0-windows/publish
- name: Upload .Net6 Artifact
uses: actions/upload-artifact@v2
with:
name: AssetStudio.net6
path: AssetStudioGUI/bin/Release/net6.0-windows/publish
+9 -47
View File
@@ -1,51 +1,13 @@
<?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>
<ProjectGuid>{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio.PInvoke</RootNamespace>
<AssemblyName>AssetStudio.PInvoke</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <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> </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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DllLoader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utf8StringHandle.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudio.PInvoke")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudio.PInvoke")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("40c796b5-88ce-4adc-acd6-2f4862b7f136")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+84 -84
View File
@@ -1,29 +1,29 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 16
VisualStudioVersion = 16.0.29920.165 VisualStudioVersion = 16.0.31410.357
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{80AEC261-21EE-4E4F-A93B-7A744DC84888}" 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}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "AssetStudioFBXNative\AssetStudioFBXNative.vcxproj", "{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{BD76E63F-1517-47FA-8233-33E853A3ACEE}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027} {11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{29EAD018-1C67-497A-AB8E-727D595AD756}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Texture2DDecoderWrapper", "Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj", "{2AFCE830-B463-49B3-A026-877E5EAFC0A4}" 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 ProjectSection(ProjectDependencies) = postProject
{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD} {29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio.PInvoke", "AssetStudio.PInvoke\AssetStudio.PInvoke.csproj", "{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}" 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
@@ -35,42 +35,78 @@ Global
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.Build.0 = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.ActiveCfg = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.ActiveCfg = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = Debug|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.ActiveCfg = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.Build.0 = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.ActiveCfg = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.ActiveCfg = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU {422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|Any CPU {0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.Build.0 = Release|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|Any CPU {E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = 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.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Debug|x64
@@ -83,18 +119,6 @@ Global
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = 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.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32 {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x64.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.ActiveCfg = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Debug|x86.Build.0 = Debug|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|Any CPU.Build.0 = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x64.Build.0 = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.ActiveCfg = Release|Any CPU
{BD76E63F-1517-47FA-8233-33E853A3ACEE}.Release|x86.Build.0 = Release|Any CPU
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|Any CPU.ActiveCfg = Debug|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|Any CPU.Build.0 = Debug|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64 {29356642-C46E-4144-83D8-22DC09D0D7FD}.Debug|x64.ActiveCfg = Debug|x64
@@ -107,35 +131,11 @@ Global
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = 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.ActiveCfg = Release|Win32
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32 {29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x64.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Debug|x86.Build.0 = Debug|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|Any CPU.Build.0 = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x64.Build.0 = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.ActiveCfg = Release|Any CPU
{2AFCE830-B463-49B3-A026-877E5EAFC0A4}.Release|x86.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|Any CPU.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x64.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.ActiveCfg = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Debug|x86.Build.0 = Debug|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|Any CPU.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x64.Build.0 = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.ActiveCfg = Release|Any CPU
{40C796B5-88CE-4ADC-ACD6-2F4862B7F136}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F8734F96-97B6-40CA-B791-6D5467F2F713} SolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal
+17 -144
View File
@@ -1,149 +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>{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}</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.7.2</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" />
</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="AssetsManager.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\PPtr.cs" />
<Compile Include="Classes\RectTransform.cs" />
<Compile Include="Classes\Renderer.cs" />
<Compile Include="Classes\ResourceManager.cs" />
<Compile Include="Classes\RuntimeAnimatorController.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="Extensions\BinaryReaderExtensions.cs" />
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="FileIdentifier.cs" />
<Compile Include="IImported.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="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="ObjectInfo.cs" />
<Compile Include="ObjectReader.cs" />
<Compile Include="Progress.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ResourceReader.cs" />
<Compile Include="SerializedFile.cs" />
<Compile Include="SerializedFileFormatVersion.cs" />
<Compile Include="SerializedFileHeader.cs" />
<Compile Include="SerializedType.cs" />
<Compile Include="SevenZipHelper.cs" />
<Compile Include="StreamFile.cs" />
<Compile Include="TypeTree.cs" />
<Compile Include="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" />
<Compile Include="WebFile.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
+200 -51
View File
@@ -1,6 +1,7 @@
using System; 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.Linq;
using System.Text; using System.Text;
using static AssetStudio.ImportHelper; using static AssetStudio.ImportHelper;
@@ -9,17 +10,20 @@ 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>(StringComparer.OrdinalIgnoreCase); internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(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>(StringComparer.OrdinalIgnoreCase); private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private 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);
@@ -51,6 +55,7 @@ namespace AssetStudio
importFiles.Clear(); importFiles.Clear();
importFilesHash.Clear(); importFilesHash.Clear();
noexistFiles.Clear();
assetsFileListHash.Clear(); assetsFileListHash.Clear();
ReadAssets(); ReadAssets();
@@ -59,106 +64,129 @@ namespace AssetStudio
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))
{ {
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.fileName); assetsFileListHash.Add(assetsFile.fileName);
foreach (var sharedFile in assetsFile.m_Externals) foreach (var sharedFile in assetsFile.m_Externals)
{ {
var sharedFilePath = Path.Combine(Path.GetDirectoryName(fullName), sharedFile.fileName);
var sharedFileName = sharedFile.fileName; var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName)) 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);
} }
} }
} }
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading assets file {fileName}", e); Logger.Error($"Error while reading assets file {reader.FullPath}", e);
reader.Dispose(); reader.Dispose();
} }
} }
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 fileName = Path.GetFileName(fullName); if (!assetsFileListHash.Contains(reader.FileName))
if (!assetsFileListHash.Contains(fileName))
{ {
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 < SerializedFileFormatVersion.kUnknown_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.fileName); assetsFileListHash.Add(assetsFile.fileName);
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading assets file {fileName} from {Path.GetFileName(originalPath)}", e); Logger.Error($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(fileName, reader); resourceFileReaders.Add(reader.FileName, 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 subReader = new EndianBinaryReader(file.stream); var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
if (SerializedFile.IsSerializedFile(subReader)) var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{ {
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName; LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
} }
else else
{ {
@@ -168,10 +196,10 @@ namespace AssetStudio
} }
catch (Exception e) catch (Exception e)
{ {
var str = $"Error while reading 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, e); Logger.Error(str, e);
} }
@@ -181,36 +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.Combine(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; break;
case FileType.ResourceFile: case FileType.ResourceFile:
resourceFileReaders[file.fileName] = fileReader; //TODO resourceFileReaders[file.fileName] = subReader; //TODO
break; break;
} }
} }
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Error($"Error while reading web file {fileName}", e); Logger.Error($"Error while reading web file {reader.FullPath}", e);
} }
finally finally
{ {
@@ -218,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)
@@ -348,6 +488,7 @@ namespace AssetStudio
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.AppendLine("Unable to load object") sb.AppendLine("Unable to load object")
.AppendLine($"Assets {assetsFile.fileName}") .AppendLine($"Assets {assetsFile.fileName}")
.AppendLine($"Path {assetsFile.originalPath}")
.AppendLine($"Type {objectReader.type}") .AppendLine($"Type {objectReader.type}")
.AppendLine($"PathID {objectInfo.m_PathID}") .AppendLine($"PathID {objectInfo.m_PathID}")
.Append(e); .Append(e);
@@ -407,6 +548,14 @@ namespace AssetStudio
{ {
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas); m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
} }
else
{
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
if (m_SpriteAtlaOld.m_IsVariant)
{
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
}
}
} }
} }
} }
+10
View File
@@ -0,0 +1,10 @@
using System.Buffers;
namespace AssetStudio
{
public static class BigArrayPool<T>
{
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
public static ArrayPool<T> Shared => s_shared;
}
}
+6 -1
View File
@@ -8,7 +8,8 @@ namespace AssetStudio
public enum BuildTarget public enum BuildTarget
{ {
NoTarget = -2, 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,
@@ -48,6 +51,8 @@ namespace AssetStudio
GameCoreXboxSeries, GameCoreXboxSeries,
GameCoreXboxOne, GameCoreXboxOne,
PS5, PS5,
EmbeddedLinux,
QNX,
UnknownPlatform = 9999 UnknownPlatform = 9999
} }
} }
+89 -44
View File
@@ -1,11 +1,36 @@
using System; using K4os.Compression.LZ4;
using System.Collections.Generic; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Lz4;
namespace AssetStudio namespace AssetStudio
{ {
[Flags]
public enum ArchiveFlags
{
CompressionTypeMask = 0x3f,
BlocksAndDirectoryInfoCombined = 0x40,
BlocksInfoAtTheEnd = 0x80,
OldWebPluginCompatibility = 0x100,
BlockInfoNeedPaddingAtStart = 0x200
}
[Flags]
public enum StorageBlockFlags
{
CompressionTypeMask = 0x3f,
Streamed = 0x40
}
public enum CompressionType
{
None,
Lzma,
Lz4,
Lz4HC,
Lzham
}
public class BundleFile public class BundleFile
{ {
public class Header public class Header
@@ -17,14 +42,14 @@ namespace AssetStudio
public long size; public long size;
public uint compressedBlocksInfoSize; public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize; public uint uncompressedBlocksInfoSize;
public uint flags; public ArchiveFlags flags;
} }
public class StorageBlock public class StorageBlock
{ {
public uint compressedSize; public uint compressedSize;
public uint uncompressedSize; public uint uncompressedSize;
public ushort flags; public StorageBlockFlags flags;
} }
public class Node public class Node
@@ -41,7 +66,7 @@ namespace AssetStudio
public StreamFile[] fileList; public StreamFile[] fileList;
public BundleFile(EndianBinaryReader reader, string path) public BundleFile(FileReader reader)
{ {
m_Header = new Header(); m_Header = new Header();
m_Header.signature = reader.ReadStringToNull(); m_Header.signature = reader.ReadStringToNull();
@@ -59,19 +84,19 @@ namespace AssetStudio
goto case "UnityFS"; goto case "UnityFS";
} }
ReadHeaderAndBlocksInfo(reader); ReadHeaderAndBlocksInfo(reader);
using (var blocksStream = CreateBlocksStream(path)) using (var blocksStream = CreateBlocksStream(reader.FullPath))
{ {
ReadBlocksAndDirectory(reader, blocksStream); ReadBlocksAndDirectory(reader, blocksStream);
ReadFiles(blocksStream, path); ReadFiles(blocksStream, reader.FullPath);
} }
break; break;
case "UnityFS": case "UnityFS":
ReadHeader(reader); ReadHeader(reader);
ReadBlocksInfoAndDirectory(reader); ReadBlocksInfoAndDirectory(reader);
using (var blocksStream = CreateBlocksStream(path)) using (var blocksStream = CreateBlocksStream(reader.FullPath))
{ {
ReadBlocks(reader, blocksStream); ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, path); ReadFiles(blocksStream, reader.FullPath);
} }
break; break;
} }
@@ -79,7 +104,6 @@ namespace AssetStudio
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader) private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
{ {
var isCompressed = m_Header.signature == "UnityWeb";
if (m_Header.version >= 4) if (m_Header.version >= 4)
{ {
var hash = reader.ReadBytes(16); var hash = reader.ReadBytes(16);
@@ -96,7 +120,6 @@ namespace AssetStudio
{ {
compressedSize = reader.ReadUInt32(), compressedSize = reader.ReadUInt32(),
uncompressedSize = reader.ReadUInt32(), uncompressedSize = reader.ReadUInt32(),
flags = (ushort)(isCompressed ? 1 : 0)
}; };
if (i == levelCount - 1) if (i == levelCount - 1)
{ {
@@ -120,7 +143,7 @@ namespace AssetStudio
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize); var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum >= int.MaxValue) if (uncompressedSizeSum >= int.MaxValue)
{ {
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum); /*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/ assetsDataStream = memoryMappedFile.CreateViewStream();*/
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose); blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
} }
@@ -133,10 +156,11 @@ namespace AssetStudio
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream) private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
{ {
var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
{ {
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize); var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
if (blockInfo.flags == 1) if (isCompressed)
{ {
using (var memoryStream = new MemoryStream(uncompressedBytes)) using (var memoryStream = new MemoryStream(uncompressedBytes))
{ {
@@ -175,7 +199,7 @@ namespace AssetStudio
file.fileName = Path.GetFileName(node.path); file.fileName = Path.GetFileName(node.path);
if (node.size >= int.MaxValue) if (node.size >= int.MaxValue)
{ {
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size); /*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size);
file.stream = memoryMappedFile.CreateViewStream();*/ file.stream = memoryMappedFile.CreateViewStream();*/
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar; var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
Directory.CreateDirectory(extractPath); Directory.CreateDirectory(extractPath);
@@ -196,7 +220,7 @@ namespace AssetStudio
m_Header.size = reader.ReadInt64(); m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
m_Header.flags = reader.ReadUInt32(); m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
if (m_Header.signature != "UnityFS") if (m_Header.signature != "UnityFS")
{ {
reader.ReadByte(); reader.ReadByte();
@@ -210,45 +234,51 @@ namespace AssetStudio
{ {
reader.AlignStream(16); reader.AlignStream(16);
} }
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
{ {
var position = reader.Position; var position = reader.Position;
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize; reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
reader.Position = position; reader.Position = position;
} }
else //0x40 kArchiveBlocksAndDirectoryInfoCombined else //0x40 BlocksAndDirectoryInfoCombined
{ {
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
} }
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
MemoryStream blocksInfoUncompresseddStream; MemoryStream blocksInfoUncompresseddStream;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
switch (compressionType)
{ {
default: //None case CompressionType.None:
{ {
blocksInfoUncompresseddStream = blocksInfoCompressedStream; blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
break; break;
} }
case 1: //LZMA case CompressionType.Lzma:
{ {
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize)); blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
blocksInfoUncompresseddStream.Position = 0;
blocksInfoCompressedStream.Close();
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
{ {
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length); 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); blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break; break;
} }
default:
throw new IOException($"Unsupported compression type {compressionType}");
} }
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream)) using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
{ {
@@ -261,7 +291,7 @@ namespace AssetStudio
{ {
uncompressedSize = blocksInfoReader.ReadUInt32(), uncompressedSize = blocksInfoReader.ReadUInt32(),
compressedSize = blocksInfoReader.ReadUInt32(), compressedSize = blocksInfoReader.ReadUInt32(),
flags = blocksInfoReader.ReadUInt16() flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()
}; };
} }
@@ -278,34 +308,49 @@ namespace AssetStudio
}; };
} }
} }
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
{
reader.AlignStream(16);
}
} }
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
{ {
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
{ {
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
switch (compressionType)
{ {
default: //None case CompressionType.None:
{ {
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
break; break;
} }
case 1: //LZMA case CompressionType.Lzma:
{ {
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break; break;
} }
case 2: //LZ4 case CompressionType.Lz4:
case 3: //LZ4HC case CompressionType.Lz4HC:
{ {
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize)); var compressedSize = (int)blockInfo.compressedSize;
using (var lz4Stream = new Lz4DecoderStream(compressedStream)) 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)
{ {
lz4Stream.CopyTo(blocksStream, blockInfo.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; break;
} }
default:
throw new IOException($"Unsupported compression type {compressionType}");
} }
} }
blocksStream.Position = 0; blocksStream.Position = 0;
+57 -4
View File
@@ -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
+4
View File
@@ -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();
} }
+44 -27
View File
@@ -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,8 +27,8 @@ namespace AssetStudio
public AudioCompressionFormat m_CompressionFormat; public AudioCompressionFormat m_CompressionFormat;
public string m_Source; public string m_Source;
public ulong m_Offset; public long m_Offset; //ulong
public long m_Size; public long m_Size; //ulong
public ResourceReader m_AudioData; public ResourceReader m_AudioData;
public AudioClip(ObjectReader reader) : base(reader) public AudioClip(ObjectReader reader) : base(reader)
@@ -36,7 +36,7 @@ namespace AssetStudio
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();
@@ -74,7 +74,7 @@ namespace AssetStudio
//StreamedResource m_Resource //StreamedResource m_Resource
m_Source = reader.ReadAlignedString(); m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadUInt64(); m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64(); m_Size = reader.ReadInt64();
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32(); m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
} }
@@ -82,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 = resourceReader; 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
} }
} }
+10 -1
View File
@@ -74,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();
} }
+107 -102
View File
@@ -396,14 +396,14 @@ namespace AssetStudio
} }
} }
public enum GfxPrimitiveType : int public enum GfxPrimitiveType
{ {
kPrimitiveTriangles = 0, Triangles = 0,
kPrimitiveTriangleStrip = 1, TriangleStrip = 1,
kPrimitiveQuads = 2, Quads = 2,
kPrimitiveLines = 3, Lines = 3,
kPrimitiveLineStrip = 4, LineStrip = 4,
kPrimitivePoints = 5, Points = 5
}; };
public class SubMesh public class SubMesh
@@ -651,6 +651,11 @@ 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.ReadUInt8Array(); var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
@@ -681,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();
} }
} }
@@ -729,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++)
{ {
@@ -1060,7 +1065,7 @@ namespace AssetStudio
} }
var indexCount = m_SubMesh.indexCount; var indexCount = m_SubMesh.indexCount;
var topology = m_SubMesh.topology; var topology = m_SubMesh.topology;
if (topology == GfxPrimitiveType.kPrimitiveTriangles) if (topology == GfxPrimitiveType.Triangles)
{ {
for (int i = 0; i < indexCount; i += 3) for (int i = 0; i < indexCount; i += 3)
{ {
@@ -1069,7 +1074,7 @@ namespace AssetStudio
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]); m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
} }
} }
else if (version[0] < 4 || topology == GfxPrimitiveType.kPrimitiveTriangleStrip) else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
{ {
// de-stripify : // de-stripify :
uint triIndex = 0; uint triIndex = 0;
@@ -1100,7 +1105,7 @@ namespace AssetStudio
//fix indexCount //fix indexCount
m_SubMesh.indexCount = triIndex; m_SubMesh.indexCount = triIndex;
} }
else if (topology == GfxPrimitiveType.kPrimitiveQuads) else if (topology == GfxPrimitiveType.Quads)
{ {
for (int q = 0; q < indexCount; q += 4) for (int q = 0; q < indexCount; q += 4)
{ {
@@ -1193,44 +1198,44 @@ namespace AssetStudio
{ {
public enum VertexChannelFormat public enum VertexChannelFormat
{ {
kChannelFormatFloat, Float,
kChannelFormatFloat16, Float16,
kChannelFormatColor, Color,
kChannelFormatByte, Byte,
kChannelFormatUInt32 UInt32
} }
public enum VertexFormat2017 public enum VertexFormat2017
{ {
kVertexFormatFloat, Float,
kVertexFormatFloat16, Float16,
kVertexFormatColor, Color,
kVertexFormatUNorm8, UNorm8,
kVertexFormatSNorm8, SNorm8,
kVertexFormatUNorm16, UNorm16,
kVertexFormatSNorm16, SNorm16,
kVertexFormatUInt8, UInt8,
kVertexFormatSInt8, SInt8,
kVertexFormatUInt16, UInt16,
kVertexFormatSInt16, SInt16,
kVertexFormatUInt32, UInt32,
kVertexFormatSInt32 SInt32
} }
public enum VertexFormat public enum VertexFormat
{ {
kVertexFormatFloat, Float,
kVertexFormatFloat16, Float16,
kVertexFormatUNorm8, UNorm8,
kVertexFormatSNorm8, SNorm8,
kVertexFormatUNorm16, UNorm16,
kVertexFormatSNorm16, SNorm16,
kVertexFormatUInt8, UInt8,
kVertexFormatSInt8, SInt8,
kVertexFormatUInt16, UInt16,
kVertexFormatSInt16, SInt16,
kVertexFormatUInt32, UInt32,
kVertexFormatSInt32 SInt32
} }
public static VertexFormat ToVertexFormat(int format, int[] version) public static VertexFormat ToVertexFormat(int format, int[] version)
@@ -1239,16 +1244,16 @@ namespace AssetStudio
{ {
switch ((VertexChannelFormat)format) switch ((VertexChannelFormat)format)
{ {
case VertexChannelFormat.kChannelFormatFloat: case VertexChannelFormat.Float:
return VertexFormat.kVertexFormatFloat; return VertexFormat.Float;
case VertexChannelFormat.kChannelFormatFloat16: case VertexChannelFormat.Float16:
return VertexFormat.kVertexFormatFloat16; return VertexFormat.Float16;
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4 case VertexChannelFormat.Color: //in 4.x is size 4
return VertexFormat.kVertexFormatUNorm8; return VertexFormat.UNorm8;
case VertexChannelFormat.kChannelFormatByte: case VertexChannelFormat.Byte:
return VertexFormat.kVertexFormatUInt8; return VertexFormat.UInt8;
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x case VertexChannelFormat.UInt32: //in 5.x
return VertexFormat.kVertexFormatUInt32; return VertexFormat.UInt32;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
@@ -1257,31 +1262,31 @@ namespace AssetStudio
{ {
switch ((VertexFormat2017)format) switch ((VertexFormat2017)format)
{ {
case VertexFormat2017.kVertexFormatFloat: case VertexFormat2017.Float:
return VertexFormat.kVertexFormatFloat; return VertexFormat.Float;
case VertexFormat2017.kVertexFormatFloat16: case VertexFormat2017.Float16:
return VertexFormat.kVertexFormatFloat16; return VertexFormat.Float16;
case VertexFormat2017.kVertexFormatColor: case VertexFormat2017.Color:
case VertexFormat2017.kVertexFormatUNorm8: case VertexFormat2017.UNorm8:
return VertexFormat.kVertexFormatUNorm8; return VertexFormat.UNorm8;
case VertexFormat2017.kVertexFormatSNorm8: case VertexFormat2017.SNorm8:
return VertexFormat.kVertexFormatSNorm8; return VertexFormat.SNorm8;
case VertexFormat2017.kVertexFormatUNorm16: case VertexFormat2017.UNorm16:
return VertexFormat.kVertexFormatUNorm16; return VertexFormat.UNorm16;
case VertexFormat2017.kVertexFormatSNorm16: case VertexFormat2017.SNorm16:
return VertexFormat.kVertexFormatSNorm16; return VertexFormat.SNorm16;
case VertexFormat2017.kVertexFormatUInt8: case VertexFormat2017.UInt8:
return VertexFormat.kVertexFormatUInt8; return VertexFormat.UInt8;
case VertexFormat2017.kVertexFormatSInt8: case VertexFormat2017.SInt8:
return VertexFormat.kVertexFormatSInt8; return VertexFormat.SInt8;
case VertexFormat2017.kVertexFormatUInt16: case VertexFormat2017.UInt16:
return VertexFormat.kVertexFormatUInt16; return VertexFormat.UInt16;
case VertexFormat2017.kVertexFormatSInt16: case VertexFormat2017.SInt16:
return VertexFormat.kVertexFormatSInt16; return VertexFormat.SInt16;
case VertexFormat2017.kVertexFormatUInt32: case VertexFormat2017.UInt32:
return VertexFormat.kVertexFormatUInt32; return VertexFormat.UInt32;
case VertexFormat2017.kVertexFormatSInt32: case VertexFormat2017.SInt32:
return VertexFormat.kVertexFormatSInt32; return VertexFormat.SInt32;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
@@ -1297,20 +1302,20 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatFloat: case VertexFormat.Float:
case VertexFormat.kVertexFormatUInt32: case VertexFormat.UInt32:
case VertexFormat.kVertexFormatSInt32: case VertexFormat.SInt32:
return 4u; return 4u;
case VertexFormat.kVertexFormatFloat16: case VertexFormat.Float16:
case VertexFormat.kVertexFormatUNorm16: case VertexFormat.UNorm16:
case VertexFormat.kVertexFormatSNorm16: case VertexFormat.SNorm16:
case VertexFormat.kVertexFormatUInt16: case VertexFormat.UInt16:
case VertexFormat.kVertexFormatSInt16: case VertexFormat.SInt16:
return 2u; return 2u;
case VertexFormat.kVertexFormatUNorm8: case VertexFormat.UNorm8:
case VertexFormat.kVertexFormatSNorm8: case VertexFormat.SNorm8:
case VertexFormat.kVertexFormatUInt8: case VertexFormat.UInt8:
case VertexFormat.kVertexFormatSInt8: case VertexFormat.SInt8:
return 1u; return 1u;
default: default:
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
@@ -1319,7 +1324,7 @@ namespace AssetStudio
public static bool IsIntFormat(VertexFormat format) public static bool IsIntFormat(VertexFormat format)
{ {
return format >= VertexFormat.kVertexFormatUInt8; return format >= VertexFormat.UInt8;
} }
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format) public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
@@ -1331,22 +1336,22 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatFloat: case VertexFormat.Float:
result[i] = BitConverter.ToSingle(inputBytes, i * 4); result[i] = BitConverter.ToSingle(inputBytes, i * 4);
break; break;
case VertexFormat.kVertexFormatFloat16: case VertexFormat.Float16:
result[i] = Half.ToHalf(inputBytes, i * 2); result[i] = Half.ToHalf(inputBytes, i * 2);
break; break;
case VertexFormat.kVertexFormatUNorm8: case VertexFormat.UNorm8:
result[i] = inputBytes[i] / 255f; result[i] = inputBytes[i] / 255f;
break; break;
case VertexFormat.kVertexFormatSNorm8: case VertexFormat.SNorm8:
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f); result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
break; break;
case VertexFormat.kVertexFormatUNorm16: case VertexFormat.UNorm16:
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f; result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
break; break;
case VertexFormat.kVertexFormatSNorm16: case VertexFormat.SNorm16:
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f); result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
break; break;
} }
@@ -1363,16 +1368,16 @@ namespace AssetStudio
{ {
switch (format) switch (format)
{ {
case VertexFormat.kVertexFormatUInt8: case VertexFormat.UInt8:
case VertexFormat.kVertexFormatSInt8: case VertexFormat.SInt8:
result[i] = inputBytes[i]; result[i] = inputBytes[i];
break; break;
case VertexFormat.kVertexFormatUInt16: case VertexFormat.UInt16:
case VertexFormat.kVertexFormatSInt16: case VertexFormat.SInt16:
result[i] = BitConverter.ToInt16(inputBytes, i * 2); result[i] = BitConverter.ToInt16(inputBytes, i * 2);
break; break;
case VertexFormat.kVertexFormatUInt32: case VertexFormat.UInt32:
case VertexFormat.kVertexFormatSInt32: case VertexFormat.SInt32:
result[i] = BitConverter.ToInt32(inputBytes, i * 4); result[i] = BitConverter.ToInt32(inputBytes, i * 4);
break; break;
} }
+1 -1
View File
@@ -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 < SerializedFileFormatVersion.kUnknown_14 ? reader.ReadInt32() : reader.ReadInt64(); m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile; assetsFile = reader.assetsFile;
} }
+129 -103
View File
@@ -56,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
@@ -81,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
@@ -195,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
@@ -427,10 +427,10 @@ namespace AssetStudio
m_Size = reader.ReadInt32(); m_Size = reader.ReadInt32();
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x (version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 to 2021.1.x (version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{ {
m_IsPartialCB = reader.ReadBoolean(); m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
@@ -454,38 +454,39 @@ 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,
kShaderGpuProgramConsoleVS = 26, ConsoleVS = 26,
kShaderGpuProgramConsoleFS = 27, ConsoleFS = 27,
kShaderGpuProgramConsoleHS = 28, ConsoleHS = 28,
kShaderGpuProgramConsoleDS = 29, ConsoleDS = 29,
kShaderGpuProgramConsoleGS = 30, ConsoleGS = 30,
kShaderGpuProgramRayTracing = 31, RayTracing = 31,
PS5NGGC = 32
}; };
public class SerializedProgramParameters public class SerializedProgramParameters
@@ -583,7 +584,7 @@ namespace AssetStudio
m_BlobIndex = reader.ReadUInt32(); m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader); m_Channels = new ParserBindChannels(reader);
if (version[0] >= 2019) //2019 and up if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
{ {
var m_GlobalKeywordIndices = reader.ReadUInt16Array(); var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -604,10 +605,10 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x (version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 to 2021.1.x (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
{ {
m_Parameters = new SerializedProgramParameters(reader); m_Parameters = new SerializedProgramParameters(reader);
} }
@@ -691,6 +692,7 @@ namespace AssetStudio
{ {
public SerializedSubProgram[] m_SubPrograms; public SerializedSubProgram[] m_SubPrograms;
public SerializedProgramParameters m_CommonParameters; public SerializedProgramParameters m_CommonParameters;
public ushort[] m_SerializedKeywordStateMask;
public SerializedProgram(ObjectReader reader) public SerializedProgram(ObjectReader reader)
{ {
@@ -704,21 +706,27 @@ namespace AssetStudio
} }
if ((version[0] == 2020 && version[1] > 3) || if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) || (version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x (version[0] > 2021) ||
(version[0] == 2021 && version[1] > 1) || (version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 to 2021.1.x (version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
{ {
m_CommonParameters = new SerializedProgramParameters(reader); 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
@@ -742,6 +750,7 @@ namespace AssetStudio
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)
{ {
@@ -758,10 +767,13 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
m_Platforms = reader.ReadUInt8Array(); m_Platforms = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
m_LocalKeywordMask = reader.ReadUInt16Array(); if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
reader.AlignStream(); {
m_GlobalKeywordMask = reader.ReadUInt16Array(); m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
m_GlobalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
}
} }
int numIndices = reader.ReadInt32(); int numIndices = reader.ReadInt32();
@@ -793,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();
}
} }
} }
@@ -859,6 +876,8 @@ namespace AssetStudio
{ {
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;
@@ -879,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();
@@ -907,32 +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,
kShaderCompPlatformGameCoreXboxOne = 21, GameCoreXboxOne = 21,
kShaderCompPlatformGameCoreScarlett = 22, GameCoreScarlett = 22,
kShaderCompPlatformPS5 = 23, PS5 = 23,
kShaderCompPlatformPS5NGGC = 24, PS5NGGC = 24
}; };
public class Shader : NamedObject public class Shader : NamedObject
@@ -944,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)
@@ -957,15 +983,15 @@ namespace AssetStudio
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray(); platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); compressedLengths = reader.ReadUInt32ArrayArray();
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); decompressedLengths = reader.ReadUInt32ArrayArray();
} }
else else
{ {
offsets = reader.ReadUInt32Array(); offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
compressedLengths = reader.ReadUInt32Array(); compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
decompressedLengths = reader.ReadUInt32Array(); decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
} }
compressedBlob = reader.ReadUInt8Array(); compressedBlob = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
+10 -10
View File
@@ -18,23 +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 public enum SpriteMeshType
{ {
kSpriteMeshTypeFullRect, FullRect,
kSpriteMeshTypeTight Tight
}; };
public class SpriteSettings public class SpriteSettings
@@ -197,7 +197,7 @@ namespace AssetStudio
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;
+4 -2
View File
@@ -46,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)
{ {
@@ -67,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();
} }
} }
} }
+14 -10
View File
@@ -4,7 +4,7 @@ namespace AssetStudio
{ {
public class StreamingInfo public class StreamingInfo
{ {
public ulong offset; public long offset; //ulong
public uint size; public uint size;
public string path; public string path;
@@ -14,7 +14,7 @@ namespace AssetStudio
if (version[0] >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
offset = reader.ReadUInt64(); offset = reader.ReadInt64();
} }
else else
{ {
@@ -134,7 +134,7 @@ 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
{ {
@@ -151,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,
@@ -165,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,
+6 -6
View File
@@ -5,14 +5,14 @@ namespace AssetStudio
public class StreamedResource public class StreamedResource
{ {
public string m_Source; public string m_Source;
public ulong m_Offset; public long m_Offset; //ulong
public ulong m_Size; public long m_Size; //ulong
public StreamedResource(BinaryReader reader) public StreamedResource(BinaryReader reader)
{ {
m_Source = reader.ReadAlignedString(); m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadUInt64(); m_Offset = reader.ReadInt64();
m_Size = reader.ReadUInt64(); m_Size = reader.ReadInt64();
} }
} }
@@ -60,11 +60,11 @@ namespace AssetStudio
ResourceReader resourceReader; ResourceReader resourceReader;
if (!string.IsNullOrEmpty(m_ExternalResources.m_Source)) if (!string.IsNullOrEmpty(m_ExternalResources.m_Source))
{ {
resourceReader = new ResourceReader(m_ExternalResources.m_Source, assetsFile, m_ExternalResources.m_Offset, (int)m_ExternalResources.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_ExternalResources.m_Size); resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_ExternalResources.m_Size);
} }
m_VideoData = resourceReader; m_VideoData = resourceReader;
} }
+32 -42
View File
@@ -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();
} }
+14
View File
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum EndianType
{
LittleEndian,
BigEndian
}
}
+103
View File
@@ -0,0 +1,103 @@
using System.IO;
using System.Linq;
namespace AssetStudio
{
public class FileReader : EndianBinaryReader
{
public string FullPath;
public string FileName;
public FileType FileType;
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)
{
FullPath = Path.GetFullPath(path);
FileName = Path.GetFileName(path);
FileType = CheckFileType();
}
private FileType CheckFileType()
{
var signature = this.ReadStringToNull(20);
Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
byte[] magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
return FileType.GZipFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (brotliMagic.SequenceEqual(magic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile())
{
return FileType.AssetsFile;
}
magic = ReadBytes(4);
Position = 0;
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
return FileType.ZipFile;
return FileType.ResourceFile;
}
}
}
private bool IsSerializedFile()
{
var fileSize = BaseStream.Length;
if (fileSize < 20)
{
return false;
}
var m_MetadataSize = ReadUInt32();
long m_FileSize = ReadUInt32();
var m_Version = ReadUInt32();
long m_DataOffset = ReadUInt32();
var m_Endianess = ReadByte();
var m_Reserved = ReadBytes(3);
if (m_Version >= 22)
{
if (fileSize < 48)
{
Position = 0;
return false;
}
m_MetadataSize = ReadUInt32();
m_FileSize = ReadInt64();
m_DataOffset = ReadInt64();
}
Position = 0;
if (m_FileSize != fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{
return false;
}
return true;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile,
ResourceFile,
GZipFile,
BrotliFile,
ZipFile
}
}
+24 -1
View File
@@ -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,6 +154,7 @@ 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 hasNormal { get; set; }
@@ -142,9 +165,9 @@ namespace AssetStudio
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
-17
View File
@@ -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) { }
}
}
+26 -56
View File
@@ -1,17 +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,
ResourceFile
}
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)
@@ -57,55 +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.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
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 "UnityArchive": {
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);
}
if (SerializedFile.IsSerializedFile(reader))
{
return FileType.AssetsFile;
}
else
{
return FileType.ResourceFile;
}
}
} }
} }
} }
-540
View File
@@ -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
}
}
+3 -3
View File
@@ -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.
+3 -2
View File
@@ -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.
+1 -1
View File
@@ -20,7 +20,7 @@ namespace AssetStudio
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;
+4 -2
View File
@@ -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()
-36
View File
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudio")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudio")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("7662f8c2-7bfd-442e-a948-a43b4f7eb06e")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+37 -16
View File
@@ -8,41 +8,39 @@ 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, ulong offset, int size) public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{ {
needSearch = true; needSearch = true;
this.path = path; this.path = path;
this.assetsFile = assetsFile; this.assetsFile = assetsFile;
this.offset = (long)offset; this.offset = offset;
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, out reader))
{ {
needSearch = false; needSearch = false;
reader.BaseStream.Position = offset; return reader;
return reader.ReadBytes(size);
} }
var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName); var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = assetsFileDirectory + Path.DirectorySeparatorChar + resourceFileName; var resourceFilePath = Path.Combine(assetsFileDirectory, resourceFileName);
if (!File.Exists(resourceFilePath)) if (!File.Exists(resourceFilePath))
{ {
var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories); var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);
@@ -53,18 +51,41 @@ namespace AssetStudio
} }
if (File.Exists(resourceFilePath)) if (File.Exists(resourceFilePath))
{ {
reader = new BinaryReader(File.OpenRead(resourceFilePath));
needSearch = false; needSearch = false;
reader = new BinaryReader(File.OpenRead(resourceFilePath));
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader); assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
reader.BaseStream.Position = offset; return reader;
return reader.ReadBytes(size);
} }
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);
}
} }
} }
} }
+44 -74
View File
@@ -9,7 +9,7 @@ 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;
@@ -31,12 +31,12 @@ namespace AssetStudio
public List<SerializedType> m_RefTypes; public List<SerializedType> m_RefTypes;
public string userInformation; 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;
// ReadHeader // ReadHeader
header = new SerializedFileHeader(); header = new SerializedFileHeader();
@@ -45,7 +45,7 @@ namespace AssetStudio
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32(); header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
header.m_DataOffset = reader.ReadUInt32(); header.m_DataOffset = reader.ReadUInt32();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_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);
@@ -57,7 +57,7 @@ namespace AssetStudio
m_FileEndianess = reader.ReadByte(); m_FileEndianess = reader.ReadByte();
} }
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport) if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
{ {
header.m_MetadataSize = reader.ReadUInt32(); header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadInt64(); header.m_FileSize = reader.ReadInt64();
@@ -68,14 +68,14 @@ namespace AssetStudio
// ReadMetadata // ReadMetadata
if (m_FileEndianess == 0) if (m_FileEndianess == 0)
{ {
reader.endian = EndianType.LittleEndian; reader.Endian = EndianType.LittleEndian;
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7) if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
{ {
unityVersion = reader.ReadStringToNull(); unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion); SetVersion(unityVersion);
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_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))
@@ -83,7 +83,7 @@ namespace AssetStudio
m_TargetPlatform = BuildTarget.UnknownPlatform; m_TargetPlatform = BuildTarget.UnknownPlatform;
} }
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes) if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{ {
m_EnableTypeTree = reader.ReadBoolean(); m_EnableTypeTree = reader.ReadBoolean();
} }
@@ -96,7 +96,7 @@ namespace AssetStudio
m_Types.Add(ReadSerializedType(false)); m_Types.Add(ReadSerializedType(false));
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7 && header.m_Version < SerializedFileFormatVersion.kUnknown_14) if (header.m_Version >= SerializedFileFormatVersion.Unknown_7 && header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
bigIDEnabled = reader.ReadInt32(); bigIDEnabled = reader.ReadInt32();
} }
@@ -113,7 +113,7 @@ namespace AssetStudio
{ {
objectInfo.m_PathID = reader.ReadInt64(); objectInfo.m_PathID = reader.ReadInt64();
} }
else if (header.m_Version < SerializedFileFormatVersion.kUnknown_14) else if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
objectInfo.m_PathID = reader.ReadInt32(); objectInfo.m_PathID = reader.ReadInt32();
} }
@@ -123,7 +123,7 @@ namespace AssetStudio
objectInfo.m_PathID = reader.ReadInt64(); objectInfo.m_PathID = reader.ReadInt64();
} }
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport) if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
objectInfo.byteStart = reader.ReadInt64(); objectInfo.byteStart = reader.ReadInt64();
else else
objectInfo.byteStart = reader.ReadUInt32(); objectInfo.byteStart = reader.ReadUInt32();
@@ -131,7 +131,7 @@ namespace AssetStudio
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 < SerializedFileFormatVersion.kRefactoredClassId) 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);
@@ -142,24 +142,24 @@ namespace AssetStudio
objectInfo.serializedType = type; objectInfo.serializedType = type;
objectInfo.classID = type.classID; objectInfo.classID = type.classID;
} }
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex) if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)
{ {
objectInfo.isDestroyed = reader.ReadUInt16(); objectInfo.isDestroyed = reader.ReadUInt16();
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.kRefactorTypeData) if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.RefactorTypeData)
{ {
var m_ScriptTypeIndex = reader.ReadInt16(); var m_ScriptTypeIndex = reader.ReadInt16();
if (objectInfo.serializedType != null) if (objectInfo.serializedType != null)
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex; objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
} }
if (header.m_Version == SerializedFileFormatVersion.kSupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.kRefactoredClassId) if (header.m_Version == SerializedFileFormatVersion.SupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.RefactoredClassId)
{ {
objectInfo.stripped = reader.ReadByte(); objectInfo.stripped = reader.ReadByte();
} }
m_Objects.Add(objectInfo); m_Objects.Add(objectInfo);
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex) 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);
@@ -167,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 < SerializedFileFormatVersion.kUnknown_14) if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
{ {
m_ScriptType.localIdentifierInFile = reader.ReadInt32(); m_ScriptType.localIdentifierInFile = reader.ReadInt32();
} }
@@ -185,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 >= SerializedFileFormatVersion.kUnknown_6) if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)
{ {
var tempEmpty = reader.ReadStringToNull(); var tempEmpty = reader.ReadStringToNull();
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_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();
@@ -199,7 +199,7 @@ namespace AssetStudio
m_Externals.Add(m_External); m_Externals.Add(m_External);
} }
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject) if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)
{ {
int refTypesCount = reader.ReadInt32(); int refTypesCount = reader.ReadInt32();
m_RefTypes = new List<SerializedType>(refTypesCount); m_RefTypes = new List<SerializedType>(refTypesCount);
@@ -209,7 +209,7 @@ namespace AssetStudio
} }
} }
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5) if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
{ {
userInformation = reader.ReadStringToNull(); userInformation = reader.ReadStringToNull();
} }
@@ -219,11 +219,14 @@ namespace AssetStudio
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(bool isRefType) private SerializedType ReadSerializedType(bool isRefType)
@@ -232,23 +235,23 @@ namespace AssetStudio
type.classID = reader.ReadInt32(); type.classID = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId) if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)
{ {
type.m_IsStrippedType = reader.ReadBoolean(); type.m_IsStrippedType = reader.ReadBoolean();
} }
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData) if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)
{ {
type.m_ScriptTypeIndex = reader.ReadInt16(); type.m_ScriptTypeIndex = reader.ReadInt16();
} }
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes) if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
{ {
if (isRefType && type.m_ScriptTypeIndex >= 0) if (isRefType && type.m_ScriptTypeIndex >= 0)
{ {
type.m_ScriptID = reader.ReadBytes(16); type.m_ScriptID = reader.ReadBytes(16);
} }
else if ((header.m_Version < SerializedFileFormatVersion.kRefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId && type.classID == 114)) 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_ScriptID = reader.ReadBytes(16);
} }
@@ -259,7 +262,7 @@ namespace AssetStudio
{ {
type.m_Type = new TypeTree(); type.m_Type = new TypeTree();
type.m_Type.m_Nodes = new List<TypeTreeNode>(); type.m_Type.m_Nodes = new List<TypeTreeNode>();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_12 || header.m_Version == SerializedFileFormatVersion.kUnknown_10) if (header.m_Version >= SerializedFileFormatVersion.Unknown_12 || header.m_Version == SerializedFileFormatVersion.Unknown_10)
{ {
TypeTreeBlobRead(type.m_Type); TypeTreeBlobRead(type.m_Type);
} }
@@ -267,7 +270,7 @@ namespace AssetStudio
{ {
ReadTypeTree(type.m_Type); ReadTypeTree(type.m_Type);
} }
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies) if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)
{ {
if (isRefType) if (isRefType)
{ {
@@ -293,17 +296,17 @@ namespace AssetStudio
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 == SerializedFileFormatVersion.kUnknown_2) if (header.m_Version == SerializedFileFormatVersion.Unknown_2)
{ {
var variableCount = reader.ReadInt32(); var variableCount = reader.ReadInt32();
} }
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3) if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
{ {
typeTreeNode.m_Index = reader.ReadInt32(); typeTreeNode.m_Index = reader.ReadInt32();
} }
typeTreeNode.m_TypeFlags = reader.ReadInt32(); typeTreeNode.m_TypeFlags = reader.ReadInt32();
typeTreeNode.m_Version = reader.ReadInt32(); typeTreeNode.m_Version = reader.ReadInt32();
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3) if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
{ {
typeTreeNode.m_MetaFlag = reader.ReadInt32(); typeTreeNode.m_MetaFlag = reader.ReadInt32();
} }
@@ -331,7 +334,7 @@ namespace AssetStudio
typeTreeNode.m_ByteSize = reader.ReadInt32(); typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32(); typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32(); typeTreeNode.m_MetaFlag = reader.ReadInt32();
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags) if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)
{ {
typeTreeNode.m_RefTypeHash = reader.ReadUInt64(); typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
} }
@@ -371,41 +374,8 @@ namespace AssetStudio
ObjectsDic.Add(obj.m_PathID, obj); ObjectsDic.Add(obj.m_PathID, obj);
} }
public static bool IsSerializedFile(EndianBinaryReader reader) public bool IsVersionStripped => unityVersion == strippedVersion;
{
var fileSize = reader.BaseStream.Length; private const string strippedVersion = "0.0.0";
if (fileSize < 20)
{
return false;
}
var m_MetadataSize = reader.ReadUInt32();
long m_FileSize = reader.ReadUInt32();
var m_Version = reader.ReadUInt32();
long m_DataOffset = reader.ReadUInt32();
var m_Endianess = reader.ReadByte();
var m_Reserved = reader.ReadBytes(3);
if (m_Version >= 22)
{
if (fileSize < 48)
{
return false;
}
m_MetadataSize = reader.ReadUInt32();
m_FileSize = reader.ReadInt64();
m_DataOffset = reader.ReadInt64();
}
if (m_FileSize != fileSize)
{
reader.Position = 0;
return false;
}
if (m_DataOffset > fileSize)
{
reader.Position = 0;
return false;
}
reader.Position = 0;
return true;
}
} }
} }
+21 -21
View File
@@ -8,80 +8,80 @@ namespace AssetStudio
{ {
public enum SerializedFileFormatVersion public enum SerializedFileFormatVersion
{ {
kUnsupported = 1, Unsupported = 1,
kUnknown_2 = 2, Unknown_2 = 2,
kUnknown_3 = 3, Unknown_3 = 3,
/// <summary> /// <summary>
/// 1.2.0 to 2.0.0 /// 1.2.0 to 2.0.0
/// </summary> /// </summary>
kUnknown_5 = 5, Unknown_5 = 5,
/// <summary> /// <summary>
/// 2.1.0 to 2.6.1 /// 2.1.0 to 2.6.1
/// </summary> /// </summary>
kUnknown_6 = 6, Unknown_6 = 6,
/// <summary> /// <summary>
/// 3.0.0b /// 3.0.0b
/// </summary> /// </summary>
kUnknown_7 = 7, Unknown_7 = 7,
/// <summary> /// <summary>
/// 3.0.0 to 3.4.2 /// 3.0.0 to 3.4.2
/// </summary> /// </summary>
kUnknown_8 = 8, Unknown_8 = 8,
/// <summary> /// <summary>
/// 3.5.0 to 4.7.2 /// 3.5.0 to 4.7.2
/// </summary> /// </summary>
kUnknown_9 = 9, Unknown_9 = 9,
/// <summary> /// <summary>
/// 5.0.0aunk1 /// 5.0.0aunk1
/// </summary> /// </summary>
kUnknown_10 = 10, Unknown_10 = 10,
/// <summary> /// <summary>
/// 5.0.0aunk2 /// 5.0.0aunk2
/// </summary> /// </summary>
kHasScriptTypeIndex = 11, HasScriptTypeIndex = 11,
/// <summary> /// <summary>
/// 5.0.0aunk3 /// 5.0.0aunk3
/// </summary> /// </summary>
kUnknown_12 = 12, Unknown_12 = 12,
/// <summary> /// <summary>
/// 5.0.0aunk4 /// 5.0.0aunk4
/// </summary> /// </summary>
kHasTypeTreeHashes = 13, HasTypeTreeHashes = 13,
/// <summary> /// <summary>
/// 5.0.0unk /// 5.0.0unk
/// </summary> /// </summary>
kUnknown_14 = 14, Unknown_14 = 14,
/// <summary> /// <summary>
/// 5.0.1 to 5.4.0 /// 5.0.1 to 5.4.0
/// </summary> /// </summary>
kSupportsStrippedObject = 15, SupportsStrippedObject = 15,
/// <summary> /// <summary>
/// 5.5.0a /// 5.5.0a
/// </summary> /// </summary>
kRefactoredClassId = 16, RefactoredClassId = 16,
/// <summary> /// <summary>
/// 5.5.0unk to 2018.4 /// 5.5.0unk to 2018.4
/// </summary> /// </summary>
kRefactorTypeData = 17, RefactorTypeData = 17,
/// <summary> /// <summary>
/// 2019.1a /// 2019.1a
/// </summary> /// </summary>
kRefactorShareableTypeTreeData = 18, RefactorShareableTypeTreeData = 18,
/// <summary> /// <summary>
/// 2019.1unk /// 2019.1unk
/// </summary> /// </summary>
kTypeTreeNodeWithTypeFlags = 19, TypeTreeNodeWithTypeFlags = 19,
/// <summary> /// <summary>
/// 2019.2 /// 2019.2
/// </summary> /// </summary>
kSupportsRefObject = 20, SupportsRefObject = 20,
/// <summary> /// <summary>
/// 2019.3 to 2019.4 /// 2019.3 to 2019.4
/// </summary> /// </summary>
kStoresTypeDependencies = 21, StoresTypeDependencies = 21,
/// <summary> /// <summary>
/// 2020.1 to x /// 2020.1 to x
/// </summary> /// </summary>
kLargeFilesSupport = 22 LargeFilesSupport = 22
} }
} }
+12 -5
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Text; using System.Text;
@@ -39,9 +40,11 @@ namespace AssetStudio
value = reader.ReadSByte(); value = reader.ReadSByte();
break; break;
case "UInt8": case "UInt8":
case "char":
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();
@@ -81,7 +84,8 @@ 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 "map": case "map":
{ {
@@ -190,9 +194,11 @@ namespace AssetStudio
value = reader.ReadSByte(); value = reader.ReadSByte();
break; break;
case "UInt8": case "UInt8":
case "char":
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();
@@ -230,7 +236,8 @@ 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":
{ {
+2 -50
View File
@@ -1,17 +1,11 @@
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 static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public StreamFile[] fileList; public StreamFile[] fileList;
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)
@@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
@@ -100,14 +100,14 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> <IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@@ -119,7 +119,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
@@ -128,7 +128,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -137,14 +137,14 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries> <IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
@@ -156,7 +156,7 @@
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary> <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
@@ -165,7 +165,7 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
@@ -1,60 +1,18 @@
<?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>
<ProjectGuid>{BD76E63F-1517-47FA-8233-33E853A3ACEE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio.FbxInterop</RootNamespace>
<AssemblyName>AssetStudioFBXWrapper</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <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> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
<Reference Include="System.Core" /> <ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="Fbx.PInvoke.cs" />
<Compile Include="FbxDll.cs" />
<Compile Include="FbxExporterContext.cs" />
<Compile Include="FbxExporterContext.PInvoke.cs" />
<Compile Include="Fbx.cs" />
<Compile Include="FbxExporter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
+2 -2
View File
@@ -28,7 +28,7 @@ namespace AssetStudio
{ {
public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision, public static void Export(string path, IImported imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii) 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 file = new FileInfo(path);
var dir = file.Directory; var dir = file.Directory;
@@ -43,7 +43,7 @@ namespace AssetStudio
var name = Path.GetFileName(path); var name = Path.GetFileName(path);
using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, scaleFactor, versionIndex, isAscii)) using (var exporter = new FbxExporter(name, imported, allNodes, skins, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii))
{ {
exporter.Initialize(); exporter.Initialize();
exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision); exporter.ExportAll(blendShape, animation, eulerFilter, filterPrecision);
+4 -2
View File
@@ -15,11 +15,12 @@ namespace AssetStudio.FbxInterop
private readonly bool _exportSkins; private readonly bool _exportSkins;
private readonly bool _castToBone; private readonly bool _castToBone;
private readonly float _boneSize; private readonly float _boneSize;
private readonly bool _exportAllUvsAsDiffuseMaps;
private readonly float _scaleFactor; private readonly float _scaleFactor;
private readonly int _versionIndex; private readonly int _versionIndex;
private readonly bool _isAscii; private readonly bool _isAscii;
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, float scaleFactor, int versionIndex, 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(); _context = new FbxExporterContext();
@@ -29,6 +30,7 @@ namespace AssetStudio.FbxInterop
_exportSkins = exportSkins; _exportSkins = exportSkins;
_castToBone = castToBone; _castToBone = castToBone;
_boneSize = boneSize; _boneSize = boneSize;
_exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps;
_scaleFactor = scaleFactor; _scaleFactor = scaleFactor;
_versionIndex = versionIndex; _versionIndex = versionIndex;
_isAscii = isAscii; _isAscii = isAscii;
@@ -171,7 +173,7 @@ namespace AssetStudio.FbxInterop
{ {
foreach (var meshFrame in meshFrames) foreach (var meshFrame in meshFrames)
{ {
_context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins); _context.ExportMeshFromFrame(rootFrame, meshFrame, _imported.MeshList, _imported.MaterialList, _imported.TextureList, _exportSkins, _exportAllUvsAsDiffuseMaps);
} }
} }
+71 -77
View File
@@ -173,12 +173,12 @@ namespace AssetStudio.FbxInterop
AsFbxPrepareMaterials(_pContext, materialCount, textureCount); AsFbxPrepareMaterials(_pContext, materialCount, textureCount);
} }
internal void ExportMeshFromFrame(ImportedFrame rootFrame, ImportedFrame meshFrame, List<ImportedMesh> meshList, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, bool exportSkins) 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 meshNode = _frameToNode[meshFrame];
var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList); var mesh = ImportedHelpers.FindMesh(meshFrame.Path, meshList);
ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins); ExportMesh(rootFrame, materialList, textureList, meshNode, mesh, exportSkins, exportAllUvsAsDiffuseMaps);
} }
private IntPtr ExportTexture(ImportedTexture texture) private IntPtr ExportTexture(ImportedTexture texture)
@@ -207,7 +207,7 @@ namespace AssetStudio.FbxInterop
return pTex; return pTex;
} }
private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins) private void ExportMesh(ImportedFrame rootFrame, List<ImportedMaterial> materialList, List<ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins, bool exportAllUvsAsDiffuseMaps)
{ {
var boneList = importedMesh.BoneList; var boneList = importedMesh.BoneList;
var totalBoneCount = 0; var totalBoneCount = 0;
@@ -246,28 +246,25 @@ namespace AssetStudio.FbxInterop
var mesh = AsFbxMeshCreateMesh(_pContext, frameNode); var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);
var totalVertexCount = 0; AsFbxMeshInitControlPoints(mesh, importedMesh.VertexList.Count);
foreach (var m in importedMesh.SubmeshList)
{
totalVertexCount += m.VertexList.Count;
}
AsFbxMeshInitControlPoints(mesh, totalVertexCount);
if (importedMesh.hasNormal) if (importedMesh.hasNormal)
{ {
AsFbxMeshCreateElementNormal(mesh); AsFbxMeshCreateElementNormal(mesh);
} }
if (importedMesh.hasUV[0]) for (int i = 0; i < importedMesh.hasUV.Length; i++)
{ {
AsFbxMeshCreateDiffuseUV(mesh, 0); if (!importedMesh.hasUV[i]) { continue; }
}
if (importedMesh.hasUV[1]) if (i == 1 && !exportAllUvsAsDiffuseMaps)
{ {
AsFbxMeshCreateNormalMapUV(mesh, 1); AsFbxMeshCreateNormalMapUV(mesh, 1);
}
else
{
AsFbxMeshCreateDiffuseUV(mesh, i);
}
} }
if (importedMesh.hasTangent) if (importedMesh.hasTangent)
@@ -282,8 +279,6 @@ namespace AssetStudio.FbxInterop
AsFbxMeshCreateElementMaterial(mesh); AsFbxMeshCreateElementMaterial(mesh);
var firstVertex = 0;
foreach (var meshObj in importedMesh.SubmeshList) foreach (var meshObj in importedMesh.SubmeshList)
{ {
var materialIndex = 0; var materialIndex = 0;
@@ -345,71 +340,70 @@ namespace AssetStudio.FbxInterop
} }
} }
var vertexList = meshObj.VertexList;
var vertexCount = vertexList.Count;
for (var j = 0; j < vertexCount; j += 1)
{
var importedVertex = vertexList[j];
var vertex = importedVertex.Vertex;
AsFbxMeshSetControlPoint(mesh, j + firstVertex, 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 < 2; 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 + firstVertex, boneWeights[k]);
}
}
}
}
foreach (var face in meshObj.FaceList) foreach (var face in meshObj.FaceList)
{ {
var index0 = face.VertexIndices[0] + firstVertex; var index0 = face.VertexIndices[0] + meshObj.BaseVertex;
var index1 = face.VertexIndices[1] + firstVertex; var index1 = face.VertexIndices[1] + meshObj.BaseVertex;
var index2 = face.VertexIndices[2] + firstVertex; var index2 = face.VertexIndices[2] + meshObj.BaseVertex;
AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2); AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);
} }
firstVertex += vertexCount;
} }
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) if (hasBones)
{ {
IntPtr pSkinContext = IntPtr.Zero; IntPtr pSkinContext = IntPtr.Zero;
@@ -1,19 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("AssetStudioFBXWrapper")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioFBXWrapper")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020; Copyright © hozuki 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("bd76e63f-1517-47fa-8233-33e853a3acee")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+83 -153
View File
@@ -1,154 +1,84 @@
<?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> <OutputType>WinExe</OutputType>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <TargetFrameworks>net472;net5.0-windows;net6.0-windows</TargetFrameworks>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <UseWindowsForms>true</UseWindowsForms>
<ProjectGuid>{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}</ProjectGuid> <ApplicationIcon>Resources\as.ico</ApplicationIcon>
<OutputType>WinExe</OutputType> <Version>0.16.0.0</Version>
<RootNamespace>AssetStudioGUI</RootNamespace> <AssemblyVersion>0.16.0.0</AssemblyVersion>
<AssemblyName>AssetStudioGUI</AssemblyName> <FileVersion>0.16.0.0</FileVersion>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> <Copyright>Copyright © Perfare 2018-2022</Copyright>
<FileAlignment>512</FileAlignment> <DebugType>embedded</DebugType>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> </PropertyGroup>
<Deterministic>true</Deterministic>
</PropertyGroup> <ItemGroup>
<PropertyGroup> <ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
<ApplicationIcon>Resources\as.ico</ApplicationIcon> <ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
</PropertyGroup> </ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols> <ItemGroup>
<OutputPath>bin\Debug\</OutputPath> <None Include="Properties\Settings.settings">
<DefineConstants>DEBUG;TRACE</DefineConstants> <Generator>SettingsSingleFileGenerator</Generator>
<DebugType>full</DebugType> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
<PlatformTarget>AnyCPU</PlatformTarget> </None>
<LangVersion>7.3</LangVersion> <Compile Update="Properties\Settings.Designer.cs">
<ErrorReport>prompt</ErrorReport> <AutoGen>True</AutoGen>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <DependentUpon>Settings.settings</DependentUpon>
<Prefer32Bit>false</Prefer32Bit> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</PropertyGroup> </Compile>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> </ItemGroup>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants> <ItemGroup>
<Optimize>true</Optimize> <EmbeddedResource Update="Properties\Resources.resx">
<DebugType>pdbonly</DebugType> <Generator>ResXFileCodeGenerator</Generator>
<PlatformTarget>AnyCPU</PlatformTarget> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
<LangVersion>7.3</LangVersion> </EmbeddedResource>
<ErrorReport>prompt</ErrorReport> <Compile Update="Properties\Resources.Designer.cs">
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> <AutoGen>True</AutoGen>
<Prefer32Bit>false</Prefer32Bit> <DependentUpon>Resources.resx</DependentUpon>
</PropertyGroup> <DesignTime>True</DesignTime>
<ItemGroup> </Compile>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> </ItemGroup>
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> <ItemGroup>
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> <ContentWithTargetPath Include="Libraries\x86\fmod.dll">
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Reference> <TargetPath>x86\fmod.dll</TargetPath>
<Reference Include="OpenTK.GLControl, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> </ContentWithTargetPath>
<HintPath>..\packages\OpenTK.GLControl.3.1.0\lib\net20\OpenTK.GLControl.dll</HintPath> <ContentWithTargetPath Include="Libraries\x64\fmod.dll">
</Reference> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Reference Include="System" /> <TargetPath>x64\fmod.dll</TargetPath>
<Reference Include="System.Core" /> </ContentWithTargetPath>
<Reference Include="System.Xml.Linq" /> </ItemGroup>
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
<Reference Include="System.Data" /> <PackageReference Include="OpenTK" Version="4.6.7" />
<Reference Include="System.Deployment" /> <Reference Include="OpenTK.WinForms">
<Reference Include="System.Drawing" /> <HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
<Reference Include="System.Net.Http" /> </Reference>
<Reference Include="System.Windows.Forms" /> </ItemGroup>
<Reference Include="System.Xml" />
</ItemGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<ItemGroup> <PackageReference Include="OpenTK" Version="3.1.0" />
<Compile Include="AssetStudioGUIForm.cs"> <PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
<SubType>Form</SubType> </ItemGroup>
</Compile>
<Compile Include="AssetStudioGUIForm.designer.cs"> <ItemGroup>
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</Compile> </ItemGroup>
<Compile Include="Components\AssetItem.cs" />
<Compile Include="Components\GameObjectTreeNode.cs" /> <Target Name="CopyExtraFiles" AfterTargets="AfterBuild">
<Compile Include="Components\GOHierarchy.cs"> <Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<SubType>Component</SubType> <Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
</Compile> <Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Compile Include="Components\OpenFolderDialog.cs" /> <Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
<Compile Include="Components\TreeViewExtensions.cs" /> </Target>
<Compile Include="Components\TypeTreeItem.cs" />
<Compile Include="Exporter.cs" /> <Target Name="PublishExtraFiles" AfterTargets="Publish">
<Compile Include="ExportOptions.cs"> <Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<SubType>Form</SubType> <Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
</Compile> <Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Compile Include="ExportOptions.designer.cs"> <Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
<DependentUpon>ExportOptions.cs</DependentUpon> </Target>
</Compile>
<Compile Include="GUILogger.cs" />
<Compile Include="GUIProgress.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Studio.cs" />
<EmbeddedResource Include="AssetStudioGUIForm.resx">
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
</EmbeddedResource>
<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>
<None Include="OpenTK.dll.config" />
<None Include="packages.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>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\preview.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\as.ico" />
</ItemGroup>
<ItemGroup>
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>x86\fmod.dll</TargetPath>
</ContentWithTargetPath>
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<TargetPath>x64\fmod.dll</TargetPath>
</ContentWithTargetPath>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj">
<Project>{80aec261-21ee-4e4f-a93b-7a744dc84888}</Project>
<Name>AssetStudioUtility</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
</Target>
</Project> </Project>
+42 -11
View File
@@ -41,6 +41,8 @@
this.displayAll = new System.Windows.Forms.ToolStripMenuItem(); this.displayAll = new System.Windows.Forms.ToolStripMenuItem();
this.enablePreview = new System.Windows.Forms.ToolStripMenuItem(); this.enablePreview = new System.Windows.Forms.ToolStripMenuItem();
this.displayInfo = new System.Windows.Forms.ToolStripMenuItem(); this.displayInfo = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();
this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();
this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem(); this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem();
this.modelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.modelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAllObjectssplitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.exportAllObjectssplitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@@ -72,6 +74,7 @@
this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();
this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.tabControl1 = new System.Windows.Forms.TabControl(); this.tabControl1 = new System.Windows.Forms.TabControl();
@@ -210,6 +213,7 @@
this.displayAll, this.displayAll,
this.enablePreview, this.enablePreview,
this.displayInfo, this.displayInfo,
this.toolStripMenuItem14,
this.showExpOpt}); this.showExpOpt});
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21); this.optionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
@@ -249,6 +253,20 @@
"t, audio bitrate, etc."; "t, audio bitrate, etc.";
this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check); this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check);
// //
// toolStripMenuItem14
//
this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.specifyUnityVersion});
this.toolStripMenuItem14.Name = "toolStripMenuItem14";
this.toolStripMenuItem14.Size = new System.Drawing.Size(223, 22);
this.toolStripMenuItem14.Text = "Specify Unity version";
//
// specifyUnityVersion
//
this.specifyUnityVersion.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F);
this.specifyUnityVersion.Name = "specifyUnityVersion";
this.specifyUnityVersion.Size = new System.Drawing.Size(100, 23);
//
// showExpOpt // showExpOpt
// //
this.showExpOpt.Name = "showExpOpt"; this.showExpOpt.Name = "showExpOpt";
@@ -429,7 +447,7 @@
// toolStripSeparator2 // toolStripSeparator2
// //
this.toolStripSeparator2.Name = "toolStripSeparator2"; this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(396, 6); this.toolStripSeparator2.Size = new System.Drawing.Size(281, 6);
// //
// toolStripMenuItem10 // toolStripMenuItem10
// //
@@ -438,27 +456,27 @@
this.toolStripMenuItem12, this.toolStripMenuItem12,
this.toolStripMenuItem13}); this.toolStripMenuItem13});
this.toolStripMenuItem10.Name = "toolStripMenuItem10"; this.toolStripMenuItem10.Name = "toolStripMenuItem10";
this.toolStripMenuItem10.Size = new System.Drawing.Size(399, 34); this.toolStripMenuItem10.Size = new System.Drawing.Size(284, 22);
this.toolStripMenuItem10.Text = "Asset list to XML"; this.toolStripMenuItem10.Text = "Asset list to XML";
// //
// toolStripMenuItem11 // toolStripMenuItem11
// //
this.toolStripMenuItem11.Name = "toolStripMenuItem11"; this.toolStripMenuItem11.Name = "toolStripMenuItem11";
this.toolStripMenuItem11.Size = new System.Drawing.Size(270, 34); this.toolStripMenuItem11.Size = new System.Drawing.Size(165, 22);
this.toolStripMenuItem11.Text = "All assets"; this.toolStripMenuItem11.Text = "All assets";
this.toolStripMenuItem11.Click += new System.EventHandler(this.toolStripMenuItem11_Click); this.toolStripMenuItem11.Click += new System.EventHandler(this.toolStripMenuItem11_Click);
// //
// toolStripMenuItem12 // toolStripMenuItem12
// //
this.toolStripMenuItem12.Name = "toolStripMenuItem12"; this.toolStripMenuItem12.Name = "toolStripMenuItem12";
this.toolStripMenuItem12.Size = new System.Drawing.Size(270, 34); this.toolStripMenuItem12.Size = new System.Drawing.Size(165, 22);
this.toolStripMenuItem12.Text = "Selected assets"; this.toolStripMenuItem12.Text = "Selected assets";
this.toolStripMenuItem12.Click += new System.EventHandler(this.toolStripMenuItem12_Click); this.toolStripMenuItem12.Click += new System.EventHandler(this.toolStripMenuItem12_Click);
// //
// toolStripMenuItem13 // toolStripMenuItem13
// //
this.toolStripMenuItem13.Name = "toolStripMenuItem13"; this.toolStripMenuItem13.Name = "toolStripMenuItem13";
this.toolStripMenuItem13.Size = new System.Drawing.Size(270, 34); this.toolStripMenuItem13.Size = new System.Drawing.Size(165, 22);
this.toolStripMenuItem13.Text = "Filtered assets"; this.toolStripMenuItem13.Text = "Filtered assets";
this.toolStripMenuItem13.Click += new System.EventHandler(this.toolStripMenuItem13_Click); this.toolStripMenuItem13.Click += new System.EventHandler(this.toolStripMenuItem13_Click);
// //
@@ -483,11 +501,22 @@
// debugMenuItem // debugMenuItem
// //
this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem15,
this.exportClassStructuresMenuItem}); this.exportClassStructuresMenuItem});
this.debugMenuItem.Name = "debugMenuItem"; this.debugMenuItem.Name = "debugMenuItem";
this.debugMenuItem.Size = new System.Drawing.Size(59, 21); this.debugMenuItem.Size = new System.Drawing.Size(59, 21);
this.debugMenuItem.Text = "Debug"; this.debugMenuItem.Text = "Debug";
// //
// toolStripMenuItem15
//
this.toolStripMenuItem15.Checked = true;
this.toolStripMenuItem15.CheckOnClick = true;
this.toolStripMenuItem15.CheckState = System.Windows.Forms.CheckState.Checked;
this.toolStripMenuItem15.Name = "toolStripMenuItem15";
this.toolStripMenuItem15.Size = new System.Drawing.Size(207, 22);
this.toolStripMenuItem15.Text = "Show error message";
this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click);
//
// exportClassStructuresMenuItem // exportClassStructuresMenuItem
// //
this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem"; this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem";
@@ -790,20 +819,21 @@
// //
// FMODtimerLabel // FMODtimerLabel
// //
this.FMODtimerLabel.AutoSize = true;
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODtimerLabel.Location = new System.Drawing.Point(404, 235); this.FMODtimerLabel.Location = new System.Drawing.Point(460, 235);
this.FMODtimerLabel.Name = "FMODtimerLabel"; this.FMODtimerLabel.Name = "FMODtimerLabel";
this.FMODtimerLabel.Size = new System.Drawing.Size(155, 12); this.FMODtimerLabel.Size = new System.Drawing.Size(95, 12);
this.FMODtimerLabel.TabIndex = 7; this.FMODtimerLabel.TabIndex = 7;
this.FMODtimerLabel.Text = "0:00.0 / 0:00.0"; this.FMODtimerLabel.Text = "0:00.0 / 0:00.0";
this.FMODtimerLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
// //
// FMODstatusLabel // FMODstatusLabel
// //
this.FMODstatusLabel.AutoSize = true;
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235); this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235);
this.FMODstatusLabel.Name = "FMODstatusLabel"; this.FMODstatusLabel.Name = "FMODstatusLabel";
this.FMODstatusLabel.Size = new System.Drawing.Size(50, 12); this.FMODstatusLabel.Size = new System.Drawing.Size(47, 12);
this.FMODstatusLabel.TabIndex = 6; this.FMODstatusLabel.TabIndex = 6;
this.FMODstatusLabel.Text = "Stopped"; this.FMODstatusLabel.Text = "Stopped";
// //
@@ -1036,8 +1066,6 @@
// AssetStudioGUIForm // AssetStudioGUIForm
// //
this.AllowDrop = true; this.AllowDrop = true;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(1264, 681); this.ClientSize = new System.Drawing.Size(1264, 681);
this.Controls.Add(this.splitContainer1); this.Controls.Add(this.splitContainer1);
this.Controls.Add(this.menuStrip1); this.Controls.Add(this.menuStrip1);
@@ -1178,6 +1206,9 @@
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14;
private System.Windows.Forms.ToolStripTextBox specifyUnityVersion;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15;
} }
} }
+94 -61
View File
@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text; using System.Drawing.Text;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
@@ -19,16 +18,21 @@ using System.Timers;
using System.Windows.Forms; using System.Windows.Forms;
using static AssetStudioGUI.Studio; using static AssetStudioGUI.Studio;
using Font = AssetStudio.Font; using Font = AssetStudio.Font;
using PixelFormat = System.Drawing.Imaging.PixelFormat; #if NET472
using Vector3 = OpenTK.Vector3; using Vector3 = OpenTK.Vector3;
using Vector4 = OpenTK.Vector4; using Vector4 = OpenTK.Vector4;
#else
using Vector3 = OpenTK.Mathematics.Vector3;
using Vector4 = OpenTK.Mathematics.Vector4;
using Matrix4 = OpenTK.Mathematics.Matrix4;
#endif
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
partial class AssetStudioGUIForm : Form partial class AssetStudioGUIForm : Form
{ {
private AssetItem lastSelectedItem; private AssetItem lastSelectedItem;
private Bitmap imageTexture; private DirectBitmap imageTexture;
private string tempClipboard; private string tempClipboard;
private FMOD.System system; private FMOD.System system;
@@ -81,6 +85,11 @@ namespace AssetStudioGUI
private int nextGObject; private int nextGObject;
private List<TreeNode> treeSrcResults = new List<TreeNode>(); private List<TreeNode> treeSrcResults = new List<TreeNode>();
private string openDirectoryBackup = string.Empty;
private string saveDirectoryBackup = string.Empty;
private GUILogger logger;
[DllImport("gdi32.dll")] [DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts); private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
@@ -96,8 +105,9 @@ namespace AssetStudioGUI
enablePreview.Checked = Properties.Settings.Default.enablePreview; enablePreview.Checked = Properties.Settings.Default.enablePreview;
FMODinit(); FMODinit();
Logger.Default = new GUILogger(StatusStripUpdate); logger = new GUILogger(StatusStripUpdate);
Progress.Default = new GUIProgress(SetProgressBarValue); Logger.Default = logger;
Progress.Default = new Progress<int>(SetProgressBarValue);
Studio.StatusStripUpdate = StatusStripUpdate; Studio.StatusStripUpdate = StatusStripUpdate;
} }
@@ -115,7 +125,7 @@ namespace AssetStudioGUI
if (paths.Length > 0) if (paths.Length > 0)
{ {
ResetForm(); ResetForm();
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
if (paths.Length == 1 && Directory.Exists(paths[0])) if (paths.Length == 1 && Directory.Exists(paths[0]))
{ {
await Task.Run(() => assetsManager.LoadFolder(paths[0])); await Task.Run(() => assetsManager.LoadFolder(paths[0]));
@@ -124,16 +134,18 @@ namespace AssetStudioGUI
{ {
await Task.Run(() => assetsManager.LoadFiles(paths)); await Task.Run(() => assetsManager.LoadFiles(paths));
} }
BuildAssetStructures(); BuildAssetStructures();
} }
} }
private async void loadFile_Click(object sender, EventArgs e) private async void loadFile_Click(object sender, EventArgs e)
{ {
if (openFileDialog1.ShowDialog() == DialogResult.OK) openFileDialog1.InitialDirectory = openDirectoryBackup;
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{ {
ResetForm(); ResetForm();
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames)); await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames));
BuildAssetStructures(); BuildAssetStructures();
} }
@@ -142,9 +154,12 @@ namespace AssetStudioGUI
private async void loadFolder_Click(object sender, EventArgs e) private async void loadFolder_Click(object sender, EventArgs e)
{ {
var openFolderDialog = new OpenFolderDialog(); var openFolderDialog = new OpenFolderDialog();
openFolderDialog.InitialFolder = openDirectoryBackup;
if (openFolderDialog.ShowDialog(this) == DialogResult.OK) if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
ResetForm(); ResetForm();
openDirectoryBackup = openFolderDialog.Folder;
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFolder(openFolderDialog.Folder)); await Task.Run(() => assetsManager.LoadFolder(openFolderDialog.Folder));
BuildAssetStructures(); BuildAssetStructures();
} }
@@ -152,7 +167,7 @@ namespace AssetStudioGUI
private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e) private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e)
{ {
if (openFileDialog1.ShowDialog() == DialogResult.OK) if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.Title = "Select the save folder"; saveFolderDialog.Title = "Select the save folder";
@@ -187,7 +202,7 @@ namespace AssetStudioGUI
{ {
if (assetsManager.assetsFileList.Count == 0) if (assetsManager.assetsFileList.Count == 0)
{ {
StatusStripUpdate("No file was loaded."); StatusStripUpdate("No Unity file can be loaded.");
return; return;
} }
@@ -207,10 +222,6 @@ namespace AssetStudioGUI
sceneTreeView.BeginUpdate(); sceneTreeView.BeginUpdate();
sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray()); sceneTreeView.Nodes.AddRange(treeNodeCollection.ToArray());
foreach (var node in treeNodeCollection)
{
node.HideCheckBox();
}
sceneTreeView.EndUpdate(); sceneTreeView.EndUpdate();
treeNodeCollection.Clear(); treeNodeCollection.Clear();
@@ -350,7 +361,7 @@ namespace AssetStudioGUI
var versionPath = Path.Combine(savePath, item.Group.Header); var versionPath = Path.Combine(savePath, item.Group.Header);
Directory.CreateDirectory(versionPath); Directory.CreateDirectory(versionPath);
var saveFile = $"{versionPath}\\{item.SubItems[1].Text} {item.Text}.txt"; var saveFile = $"{versionPath}{Path.DirectorySeparatorChar}{item.SubItems[1].Text} {item.Text}.txt";
File.WriteAllText(saveFile, item.ToString()); File.WriteAllText(saveFile, item.ToString());
Progress.Report(++i, count); Progress.Report(++i, count);
@@ -378,7 +389,7 @@ namespace AssetStudioGUI
{ {
if (enablePreview.Checked && imageTexture != null) if (enablePreview.Checked && imageTexture != null)
{ {
previewPanel.BackgroundImage = imageTexture; previewPanel.BackgroundImage = imageTexture.Bitmap;
} }
else else
{ {
@@ -446,7 +457,7 @@ namespace AssetStudioGUI
private void showExpOpt_Click(object sender, EventArgs e) private void showExpOpt_Click(object sender, EventArgs e)
{ {
var exportOpt = new ExportOptions(); var exportOpt = new ExportOptions();
exportOpt.ShowDialog(); exportOpt.ShowDialog(this);
} }
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
@@ -741,9 +752,11 @@ namespace AssetStudioGUI
private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D) private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
{ {
var bitmap = m_Texture2D.ConvertToBitmap(true); var image = m_Texture2D.ConvertToImage(true);
if (bitmap != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image.ConvertToBytes(), m_Texture2D.m_Width, m_Texture2D.m_Height);
image.Dispose();
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}"; assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode) switch (m_Texture2D.m_TextureSettings.m_FilterMode)
{ {
@@ -771,13 +784,11 @@ namespace AssetStudioGUI
assetItem.InfoText += "None"; assetItem.InfoText += "None";
if (validChannel != 4) if (validChannel != 4)
{ {
var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var bytes = bitmap.Bits;
var bytes = new byte[bitmap.Width * bitmap.Height * 4]; for (int i = 0; i < bitmap.Height; i++)
Marshal.Copy(bmpData.Scan0, bytes, 0, bytes.Length);
for (int i = 0; i < bmpData.Height; i++)
{ {
int offset = Math.Abs(bmpData.Stride) * i; int offset = Math.Abs(bitmap.Stride) * i;
for (int j = 0; j < bmpData.Width; j++) for (int j = 0; j < bitmap.Width; j++)
{ {
bytes[offset] = textureChannels[0] ? bytes[offset] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue; bytes[offset] = textureChannels[0] ? bytes[offset] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;
bytes[offset + 1] = textureChannels[1] ? bytes[offset + 1] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue; bytes[offset + 1] = textureChannels[1] ? bytes[offset + 1] : validChannel == 1 && textureChannels[3] ? byte.MaxValue : byte.MinValue;
@@ -786,8 +797,6 @@ namespace AssetStudioGUI
offset += 4; offset += 4;
} }
} }
Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length);
bitmap.UnlockBits(bmpData);
} }
PreviewTexture(bitmap); PreviewTexture(bitmap);
@@ -807,40 +816,40 @@ namespace AssetStudioGUI
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.ACC: case FMODSoundType.ACC:
assetItem.InfoText += "Acc"; assetItem.InfoText += "Acc";
break; break;
case AudioType.AIFF: case FMODSoundType.AIFF:
assetItem.InfoText += "AIFF"; assetItem.InfoText += "AIFF";
break; break;
case AudioType.IT: case FMODSoundType.IT:
assetItem.InfoText += "Impulse tracker"; assetItem.InfoText += "Impulse tracker";
break; break;
case AudioType.MOD: case FMODSoundType.MOD:
assetItem.InfoText += "Protracker / Fasttracker MOD"; assetItem.InfoText += "Protracker / Fasttracker MOD";
break; break;
case AudioType.MPEG: case FMODSoundType.MPEG:
assetItem.InfoText += "MP2/MP3 MPEG"; assetItem.InfoText += "MP2/MP3 MPEG";
break; break;
case AudioType.OGGVORBIS: case FMODSoundType.OGGVORBIS:
assetItem.InfoText += "Ogg vorbis"; assetItem.InfoText += "Ogg vorbis";
break; break;
case AudioType.S3M: case FMODSoundType.S3M:
assetItem.InfoText += "ScreamTracker 3"; assetItem.InfoText += "ScreamTracker 3";
break; break;
case AudioType.WAV: case FMODSoundType.WAV:
assetItem.InfoText += "Microsoft WAV"; assetItem.InfoText += "Microsoft WAV";
break; break;
case AudioType.XM: case FMODSoundType.XM:
assetItem.InfoText += "FastTracker 2 XM"; assetItem.InfoText += "FastTracker 2 XM";
break; break;
case AudioType.XMA: case FMODSoundType.XMA:
assetItem.InfoText += "Xbox360 XMA"; assetItem.InfoText += "Xbox360 XMA";
break; break;
case AudioType.VAG: case FMODSoundType.VAG:
assetItem.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
assetItem.InfoText += "iPhone"; assetItem.InfoText += "iPhone";
break; break;
default: default:
@@ -864,7 +873,7 @@ namespace AssetStudioGUI
case AudioCompressionFormat.MP3: case AudioCompressionFormat.MP3:
assetItem.InfoText += "MP3"; assetItem.InfoText += "MP3";
break; break;
case AudioCompressionFormat.VAG: case AudioCompressionFormat.PSMVAG:
assetItem.InfoText += "PlayStation Portable ADPCM"; assetItem.InfoText += "PlayStation Portable ADPCM";
break; break;
case AudioCompressionFormat.HEVAG: case AudioCompressionFormat.HEVAG:
@@ -1151,11 +1160,12 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite) private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{ {
var bitmap = m_Sprite.GetImage(); var image = m_Sprite.GetImage();
if (bitmap != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image.ConvertToBytes(), image.Width, image.Height);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n"; assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap); PreviewTexture(bitmap);
} }
else else
@@ -1164,11 +1174,11 @@ namespace AssetStudioGUI
} }
} }
private void PreviewTexture(Bitmap bitmap) private void PreviewTexture(DirectBitmap bitmap)
{ {
imageTexture?.Dispose(); imageTexture?.Dispose();
imageTexture = bitmap; imageTexture = bitmap;
previewPanel.BackgroundImage = imageTexture; previewPanel.BackgroundImage = imageTexture.Bitmap;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height) if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom; previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else else
@@ -1219,6 +1229,7 @@ namespace AssetStudioGUI
classesListView.Groups.Clear(); classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview; previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose(); imageTexture?.Dispose();
imageTexture = null;
previewPanel.BackgroundImageLayout = ImageLayout.Center; previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false; assetInfoLabel.Visible = false;
assetInfoLabel.Text = null; assetInfoLabel.Text = null;
@@ -1305,9 +1316,11 @@ namespace AssetStudioGUI
if (animator != null) if (animator != null)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
var exportPath = saveFolderDialog.Folder + "\\Animator\\"; saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar;
ExportAnimatorWithAnimationClip(animator, animationList, exportPath); ExportAnimatorWithAnimationClip(animator, animationList, exportPath);
} }
} }
@@ -1328,9 +1341,11 @@ namespace AssetStudioGUI
if (sceneTreeView.Nodes.Count > 0) if (sceneTreeView.Nodes.Count > 0)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
var exportPath = saveFolderDialog.Folder + "\\GameObject\\"; saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "GameObject") + Path.DirectorySeparatorChar;
List<AssetItem> animationList = null; List<AssetItem> animationList = null;
if (animation) if (animation)
{ {
@@ -1365,23 +1380,32 @@ namespace AssetStudioGUI
{ {
var gameObjects = new List<GameObject>(); var gameObjects = new List<GameObject>();
GetSelectedParentNode(sceneTreeView.Nodes, gameObjects); GetSelectedParentNode(sceneTreeView.Nodes, gameObjects);
var saveFileDialog = new SaveFileDialog(); if (gameObjects.Count > 0)
saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
saveFileDialog.AddExtension = false;
saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{ {
var exportPath = saveFileDialog.FileName; var saveFileDialog = new SaveFileDialog();
List<AssetItem> animationList = null; saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
if (animation) saveFileDialog.AddExtension = false;
saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
saveFileDialog.InitialDirectory = saveDirectoryBackup;
if (saveFileDialog.ShowDialog(this) == DialogResult.OK)
{ {
animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList(); saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
if (animationList.Count == 0) var exportPath = saveFileDialog.FileName;
List<AssetItem> animationList = null;
if (animation)
{ {
animationList = null; animationList = GetSelectedAssets().Where(x => x.Type == ClassIDType.AnimationClip).ToList();
if (animationList.Count == 0)
{
animationList = null;
}
} }
ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList);
} }
ExportObjectsMergeWithAnimationClip(exportPath, gameObjects, animationList); }
else
{
StatusStripUpdate("No Object selected for export.");
} }
} }
} }
@@ -1461,8 +1485,10 @@ namespace AssetStudioGUI
if (sceneTreeView.Nodes.Count > 0) if (sceneTreeView.Nodes.Count > 0)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
saveDirectoryBackup = saveFolderDialog.Folder;
var savePath = saveFolderDialog.Folder + Path.DirectorySeparatorChar; var savePath = saveFolderDialog.Folder + Path.DirectorySeparatorChar;
ExportSplitObjects(savePath, sceneTreeView.Nodes); ExportSplitObjects(savePath, sceneTreeView.Nodes);
} }
@@ -1521,10 +1547,11 @@ namespace AssetStudioGUI
if (exportableAssets.Count > 0) if (exportableAssets.Count > 0)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
timer.Stop(); timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
List<AssetItem> toExportAssets = null; List<AssetItem> toExportAssets = null;
switch (type) switch (type)
{ {
@@ -1554,10 +1581,11 @@ namespace AssetStudioGUI
if (exportableAssets.Count > 0) if (exportableAssets.Count > 0)
{ {
var saveFolderDialog = new OpenFolderDialog(); var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK) if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
timer.Stop(); timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
List<AssetItem> toExportAssets = null; List<AssetItem> toExportAssets = null;
switch (type) switch (type)
{ {
@@ -2016,6 +2044,11 @@ namespace AssetStudioGUI
} }
} }
private void toolStripMenuItem15_Click(object sender, EventArgs e)
{
logger.ShowErrorMessage = toolStripMenuItem15.Checked;
}
private void glControl1_MouseWheel(object sender, MouseEventArgs e) private void glControl1_MouseWheel(object sender, MouseEventArgs e)
{ {
if (glControl1.Visible) if (glControl1.Visible)
@@ -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;
+21 -12
View File
@@ -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);
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace AssetStudioGUI
{
public sealed class DirectBitmap : IDisposable
{
public DirectBitmap(byte[] buff, int width, int height)
{
Width = width;
Height = height;
Bits = buff;
m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());
}
private void Dispose(bool disposing)
{
if (disposing)
{
m_bitmap.Dispose();
m_handle.Free();
}
m_bitmap = null;
}
public void Dispose()
{
Dispose(true);
}
public int Height { get; }
public int Width { get; }
public int Stride => Width * 4;
public byte[] Bits { get; }
public Bitmap Bitmap => m_bitmap;
private Bitmap m_bitmap;
private readonly GCHandle m_handle;
}
}
+36 -17
View File
@@ -28,6 +28,7 @@
/// </summary> /// </summary>
private void InitializeComponent() private void InitializeComponent()
{ {
this.components = new System.ComponentModel.Container();
this.OKbutton = new System.Windows.Forms.Button(); this.OKbutton = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button(); this.Cancel = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
@@ -43,6 +44,7 @@
this.tobmp = new System.Windows.Forms.RadioButton(); this.tobmp = new System.Windows.Forms.RadioButton();
this.converttexture = new System.Windows.Forms.CheckBox(); this.converttexture = new System.Windows.Forms.CheckBox();
this.groupBox2 = new System.Windows.Forms.GroupBox(); this.groupBox2 = new System.Windows.Forms.GroupBox();
this.exportAllUvsAsDiffuseMaps = new System.Windows.Forms.CheckBox();
this.exportBlendShape = new System.Windows.Forms.CheckBox(); this.exportBlendShape = new System.Windows.Forms.CheckBox();
this.exportAnimations = new System.Windows.Forms.CheckBox(); this.exportAnimations = new System.Windows.Forms.CheckBox();
this.scaleFactor = new System.Windows.Forms.NumericUpDown(); this.scaleFactor = new System.Windows.Forms.NumericUpDown();
@@ -59,6 +61,7 @@
this.castToBone = new System.Windows.Forms.CheckBox(); this.castToBone = new System.Windows.Forms.CheckBox();
this.exportAllNodes = new System.Windows.Forms.CheckBox(); this.exportAllNodes = new System.Windows.Forms.CheckBox();
this.eulerFilter = new System.Windows.Forms.CheckBox(); this.eulerFilter = new System.Windows.Forms.CheckBox();
this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components);
this.groupBox1.SuspendLayout(); this.groupBox1.SuspendLayout();
this.panel1.SuspendLayout(); this.panel1.SuspendLayout();
this.groupBox2.SuspendLayout(); this.groupBox2.SuspendLayout();
@@ -69,7 +72,7 @@
// //
// OKbutton // OKbutton
// //
this.OKbutton.Location = new System.Drawing.Point(308, 320); this.OKbutton.Location = new System.Drawing.Point(318, 351);
this.OKbutton.Name = "OKbutton"; this.OKbutton.Name = "OKbutton";
this.OKbutton.Size = new System.Drawing.Size(75, 21); this.OKbutton.Size = new System.Drawing.Size(75, 21);
this.OKbutton.TabIndex = 6; this.OKbutton.TabIndex = 6;
@@ -80,7 +83,7 @@
// Cancel // Cancel
// //
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Cancel.Location = new System.Drawing.Point(389, 320); this.Cancel.Location = new System.Drawing.Point(399, 351);
this.Cancel.Name = "Cancel"; this.Cancel.Name = "Cancel";
this.Cancel.Size = new System.Drawing.Size(75, 21); this.Cancel.Size = new System.Drawing.Size(75, 21);
this.Cancel.TabIndex = 7; this.Cancel.TabIndex = 7;
@@ -100,7 +103,7 @@
this.groupBox1.Controls.Add(this.converttexture); this.groupBox1.Controls.Add(this.converttexture);
this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Location = new System.Drawing.Point(12, 12);
this.groupBox1.Name = "groupBox1"; this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(232, 302); this.groupBox1.Size = new System.Drawing.Size(232, 334);
this.groupBox1.TabIndex = 9; this.groupBox1.TabIndex = 9;
this.groupBox1.TabStop = false; this.groupBox1.TabStop = false;
this.groupBox1.Text = "Export"; this.groupBox1.Text = "Export";
@@ -182,7 +185,7 @@
this.totga.Name = "totga"; this.totga.Name = "totga";
this.totga.Size = new System.Drawing.Size(41, 16); this.totga.Size = new System.Drawing.Size(41, 16);
this.totga.TabIndex = 2; this.totga.TabIndex = 2;
this.totga.Text = "TGA"; this.totga.Text = "Tga";
this.totga.UseVisualStyleBackColor = true; this.totga.UseVisualStyleBackColor = true;
// //
// tojpg // tojpg
@@ -192,7 +195,7 @@
this.tojpg.Name = "tojpg"; this.tojpg.Name = "tojpg";
this.tojpg.Size = new System.Drawing.Size(47, 16); this.tojpg.Size = new System.Drawing.Size(47, 16);
this.tojpg.TabIndex = 4; this.tojpg.TabIndex = 4;
this.tojpg.Text = "JPEG"; this.tojpg.Text = "Jpeg";
this.tojpg.UseVisualStyleBackColor = true; this.tojpg.UseVisualStyleBackColor = true;
// //
// topng // topng
@@ -204,7 +207,7 @@
this.topng.Size = new System.Drawing.Size(41, 16); this.topng.Size = new System.Drawing.Size(41, 16);
this.topng.TabIndex = 3; this.topng.TabIndex = 3;
this.topng.TabStop = true; this.topng.TabStop = true;
this.topng.Text = "PNG"; this.topng.Text = "Png";
this.topng.UseVisualStyleBackColor = true; this.topng.UseVisualStyleBackColor = true;
// //
// tobmp // tobmp
@@ -214,7 +217,7 @@
this.tobmp.Name = "tobmp"; this.tobmp.Name = "tobmp";
this.tobmp.Size = new System.Drawing.Size(41, 16); this.tobmp.Size = new System.Drawing.Size(41, 16);
this.tobmp.TabIndex = 2; this.tobmp.TabIndex = 2;
this.tobmp.Text = "BMP"; this.tobmp.Text = "Bmp";
this.tobmp.UseVisualStyleBackColor = true; this.tobmp.UseVisualStyleBackColor = true;
// //
// converttexture // converttexture
@@ -232,6 +235,7 @@
// groupBox2 // groupBox2
// //
this.groupBox2.AutoSize = true; this.groupBox2.AutoSize = true;
this.groupBox2.Controls.Add(this.exportAllUvsAsDiffuseMaps);
this.groupBox2.Controls.Add(this.exportBlendShape); this.groupBox2.Controls.Add(this.exportBlendShape);
this.groupBox2.Controls.Add(this.exportAnimations); this.groupBox2.Controls.Add(this.exportAnimations);
this.groupBox2.Controls.Add(this.scaleFactor); this.groupBox2.Controls.Add(this.scaleFactor);
@@ -250,11 +254,24 @@
this.groupBox2.Controls.Add(this.eulerFilter); this.groupBox2.Controls.Add(this.eulerFilter);
this.groupBox2.Location = new System.Drawing.Point(250, 12); this.groupBox2.Location = new System.Drawing.Point(250, 12);
this.groupBox2.Name = "groupBox2"; this.groupBox2.Name = "groupBox2";
this.groupBox2.Size = new System.Drawing.Size(214, 302); this.groupBox2.Size = new System.Drawing.Size(224, 334);
this.groupBox2.TabIndex = 11; this.groupBox2.TabIndex = 11;
this.groupBox2.TabStop = false; this.groupBox2.TabStop = false;
this.groupBox2.Text = "Fbx"; this.groupBox2.Text = "Fbx";
// //
// exportAllUvsAsDiffuseMaps
//
this.exportAllUvsAsDiffuseMaps.AccessibleDescription = "";
this.exportAllUvsAsDiffuseMaps.AutoSize = true;
this.exportAllUvsAsDiffuseMaps.Location = new System.Drawing.Point(6, 171);
this.exportAllUvsAsDiffuseMaps.Name = "exportAllUvsAsDiffuseMaps";
this.exportAllUvsAsDiffuseMaps.Size = new System.Drawing.Size(204, 16);
this.exportAllUvsAsDiffuseMaps.TabIndex = 23;
this.exportAllUvsAsDiffuseMaps.Text = "Export all UVs as diffuse maps";
this.exportUvsTooltip.SetToolTip(this.exportAllUvsAsDiffuseMaps, "Unchecked: UV1 exported as normal map. Check this if your export is missing a UV " +
"map.");
this.exportAllUvsAsDiffuseMaps.UseVisualStyleBackColor = true;
//
// exportBlendShape // exportBlendShape
// //
this.exportBlendShape.AutoSize = true; this.exportBlendShape.AutoSize = true;
@@ -287,7 +304,7 @@
0, 0,
0, 0,
131072}); 131072});
this.scaleFactor.Location = new System.Drawing.Point(83, 202); this.scaleFactor.Location = new System.Drawing.Point(83, 224);
this.scaleFactor.Name = "scaleFactor"; this.scaleFactor.Name = "scaleFactor";
this.scaleFactor.Size = new System.Drawing.Size(60, 21); this.scaleFactor.Size = new System.Drawing.Size(60, 21);
this.scaleFactor.TabIndex = 20; this.scaleFactor.TabIndex = 20;
@@ -301,7 +318,7 @@
// label5 // label5
// //
this.label5.AutoSize = true; this.label5.AutoSize = true;
this.label5.Location = new System.Drawing.Point(6, 204); this.label5.Location = new System.Drawing.Point(6, 226);
this.label5.Name = "label5"; this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(71, 12); this.label5.Size = new System.Drawing.Size(71, 12);
this.label5.TabIndex = 19; this.label5.TabIndex = 19;
@@ -314,7 +331,7 @@
this.fbxFormat.Items.AddRange(new object[] { this.fbxFormat.Items.AddRange(new object[] {
"Binary", "Binary",
"Ascii"}); "Ascii"});
this.fbxFormat.Location = new System.Drawing.Point(77, 233); this.fbxFormat.Location = new System.Drawing.Point(77, 254);
this.fbxFormat.Name = "fbxFormat"; this.fbxFormat.Name = "fbxFormat";
this.fbxFormat.Size = new System.Drawing.Size(61, 20); this.fbxFormat.Size = new System.Drawing.Size(61, 20);
this.fbxFormat.TabIndex = 18; this.fbxFormat.TabIndex = 18;
@@ -322,7 +339,7 @@
// label4 // label4
// //
this.label4.AutoSize = true; this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(6, 236); this.label4.Location = new System.Drawing.Point(6, 258);
this.label4.Name = "label4"; this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(59, 12); this.label4.Size = new System.Drawing.Size(59, 12);
this.label4.TabIndex = 17; this.label4.TabIndex = 17;
@@ -339,7 +356,7 @@
"7.3", "7.3",
"7.4", "7.4",
"7.5"}); "7.5"});
this.fbxVersion.Location = new System.Drawing.Point(77, 262); this.fbxVersion.Location = new System.Drawing.Point(77, 284);
this.fbxVersion.Name = "fbxVersion"; this.fbxVersion.Name = "fbxVersion";
this.fbxVersion.Size = new System.Drawing.Size(47, 20); this.fbxVersion.Size = new System.Drawing.Size(47, 20);
this.fbxVersion.TabIndex = 16; this.fbxVersion.TabIndex = 16;
@@ -347,7 +364,7 @@
// label3 // label3
// //
this.label3.AutoSize = true; this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(6, 265); this.label3.Location = new System.Drawing.Point(6, 287);
this.label3.Name = "label3"; this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(65, 12); this.label3.Size = new System.Drawing.Size(65, 12);
this.label3.TabIndex = 15; this.label3.TabIndex = 15;
@@ -355,7 +372,7 @@
// //
// boneSize // boneSize
// //
this.boneSize.Location = new System.Drawing.Point(65, 175); this.boneSize.Location = new System.Drawing.Point(65, 197);
this.boneSize.Name = "boneSize"; this.boneSize.Name = "boneSize";
this.boneSize.Size = new System.Drawing.Size(46, 21); this.boneSize.Size = new System.Drawing.Size(46, 21);
this.boneSize.TabIndex = 11; this.boneSize.TabIndex = 11;
@@ -368,7 +385,7 @@
// label2 // label2
// //
this.label2.AutoSize = true; this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(6, 177); this.label2.Location = new System.Drawing.Point(6, 199);
this.label2.Name = "label2"; this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(53, 12); this.label2.Size = new System.Drawing.Size(53, 12);
this.label2.TabIndex = 10; this.label2.TabIndex = 10;
@@ -453,7 +470,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.Cancel; this.CancelButton = this.Cancel;
this.ClientSize = new System.Drawing.Size(477, 351); this.ClientSize = new System.Drawing.Size(486, 384);
this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1); this.Controls.Add(this.groupBox1);
this.Controls.Add(this.Cancel); this.Controls.Add(this.Cancel);
@@ -512,5 +529,7 @@
private System.Windows.Forms.Label label6; private System.Windows.Forms.Label label6;
private System.Windows.Forms.CheckBox restoreExtensionName; private System.Windows.Forms.CheckBox restoreExtensionName;
private System.Windows.Forms.CheckBox openAfterExport; private System.Windows.Forms.CheckBox openAfterExport;
private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;
private System.Windows.Forms.ToolTip exportUvsTooltip;
} }
} }
+8 -10
View File
@@ -1,11 +1,5 @@
using System; using AssetStudio;
using System.Collections.Generic; using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
namespace AssetStudioGUI namespace AssetStudioGUI
@@ -19,7 +13,7 @@ namespace AssetStudioGUI
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName; restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
converttexture.Checked = Properties.Settings.Default.convertTexture; converttexture.Checked = Properties.Settings.Default.convertTexture;
convertAudio.Checked = Properties.Settings.Default.convertAudio; convertAudio.Checked = Properties.Settings.Default.convertAudio;
var str = Properties.Settings.Default.convertType; var str = Properties.Settings.Default.convertType.ToString();
foreach (Control c in panel1.Controls) foreach (Control c in panel1.Controls)
{ {
if (c.Text == str) if (c.Text == str)
@@ -36,10 +30,12 @@ namespace AssetStudioGUI
exportAnimations.Checked = Properties.Settings.Default.exportAnimations; exportAnimations.Checked = Properties.Settings.Default.exportAnimations;
exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape; exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape;
castToBone.Checked = Properties.Settings.Default.castToBone; castToBone.Checked = Properties.Settings.Default.castToBone;
exportAllUvsAsDiffuseMaps.Checked = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
boneSize.Value = Properties.Settings.Default.boneSize; boneSize.Value = Properties.Settings.Default.boneSize;
scaleFactor.Value = Properties.Settings.Default.scaleFactor; scaleFactor.Value = Properties.Settings.Default.scaleFactor;
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion; fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat; fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
} }
private void OKbutton_Click(object sender, EventArgs e) private void OKbutton_Click(object sender, EventArgs e)
@@ -52,7 +48,7 @@ namespace AssetStudioGUI
{ {
if (((RadioButton)c).Checked) if (((RadioButton)c).Checked)
{ {
Properties.Settings.Default.convertType = c.Text; Properties.Settings.Default.convertType = (ImageFormat)Enum.Parse(typeof(ImageFormat), c.Text);
break; break;
} }
} }
@@ -64,6 +60,7 @@ namespace AssetStudioGUI
Properties.Settings.Default.exportAnimations = exportAnimations.Checked; Properties.Settings.Default.exportAnimations = exportAnimations.Checked;
Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked; Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked;
Properties.Settings.Default.castToBone = castToBone.Checked; Properties.Settings.Default.castToBone = castToBone.Checked;
Properties.Settings.Default.exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;
Properties.Settings.Default.boneSize = boneSize.Value; Properties.Settings.Default.boneSize = boneSize.Value;
Properties.Settings.Default.scaleFactor = scaleFactor.Value; Properties.Settings.Default.scaleFactor = scaleFactor.Value;
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex; Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
@@ -78,5 +75,6 @@ namespace AssetStudioGUI
DialogResult = DialogResult.Cancel; DialogResult = DialogResult.Cancel;
Close(); Close();
} }
} }
} }
+3
View File
@@ -117,4 +117,7 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>
+27 -68
View File
@@ -1,11 +1,9 @@
using System.Collections.Generic; using AssetStudio;
using System.Drawing.Imaging; using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using AssetStudio;
using Newtonsoft.Json;
using TGASharpLib;
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
@@ -16,40 +14,20 @@ namespace AssetStudioGUI
var m_Texture2D = (Texture2D)item.Asset; var m_Texture2D = (Texture2D)item.Asset;
if (Properties.Settings.Default.convertTexture) if (Properties.Settings.Default.convertTexture)
{ {
var bitmap = m_Texture2D.ConvertToBitmap(true); var type = Properties.Settings.Default.convertType;
if (bitmap == null) if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false; return false;
ImageFormat format = null; var image = m_Texture2D.ConvertToImage(true);
var ext = Properties.Settings.Default.convertType; if (image == null)
bool tga = false;
switch (ext)
{
case "BMP":
format = ImageFormat.Bmp;
break;
case "PNG":
format = ImageFormat.Png;
break;
case "JPEG":
format = ImageFormat.Jpeg;
break;
case "TGA":
tga = true;
break;
}
if (!TryExportFile(exportPath, item, "." + ext.ToLower(), out var exportFullPath))
return false; return false;
if (tga) using (image)
{ {
var file = new TGA(bitmap); using (var file = File.OpenWrite(exportFullPath))
file.Save(exportFullPath); {
image.WriteToStream(file, type);
}
return true;
} }
else
{
bitmap.Save(exportFullPath, format);
}
bitmap.Dispose();
return true;
} }
else else
{ {
@@ -174,6 +152,7 @@ namespace AssetStudioGUI
#region UV #region UV
if (m_Mesh.m_UV0?.Length > 0) if (m_Mesh.m_UV0?.Length > 0)
{ {
c = 4;
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2) if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
{ {
c = 2; c = 2;
@@ -230,12 +209,11 @@ namespace AssetStudioGUI
public static bool ExportVideoClip(AssetItem item, string exportPath) public static bool ExportVideoClip(AssetItem item, string exportPath)
{ {
var m_VideoClip = (VideoClip)item.Asset; var m_VideoClip = (VideoClip)item.Asset;
var m_VideoData = m_VideoClip.m_VideoData.GetData(); if (m_VideoClip.m_ExternalResources.m_Size > 0)
if (m_VideoData != null && m_VideoData.Length != 0)
{ {
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath)) if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
return false; return false;
File.WriteAllBytes(exportFullPath, m_VideoData); m_VideoClip.m_VideoData.WriteData(exportFullPath);
return true; return true;
} }
return false; return false;
@@ -252,40 +230,20 @@ namespace AssetStudioGUI
public static bool ExportSprite(AssetItem item, string exportPath) public static bool ExportSprite(AssetItem item, string exportPath)
{ {
ImageFormat format = null;
var type = Properties.Settings.Default.convertType; var type = Properties.Settings.Default.convertType;
bool tga = false; if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
switch (type)
{
case "BMP":
format = ImageFormat.Bmp;
break;
case "PNG":
format = ImageFormat.Png;
break;
case "JPEG":
format = ImageFormat.Jpeg;
break;
case "TGA":
tga = true;
break;
}
if (!TryExportFile(exportPath, item, "." + type.ToLower(), out var exportFullPath))
return false; return false;
var bitmap = ((Sprite)item.Asset).GetImage(); var image = ((Sprite)item.Asset).GetImage();
if (bitmap != null) if (image != null)
{ {
if (tga) using (image)
{ {
var file = new TGA(bitmap); using (var file = File.OpenWrite(exportFullPath))
file.Save(exportFullPath); {
image.WriteToStream(file, type);
}
return true;
} }
else
{
bitmap.Save(exportFullPath, format);
}
bitmap.Dispose();
return true;
} }
return false; return false;
} }
@@ -359,11 +317,12 @@ namespace AssetStudioGUI
var exportBlendShape = Properties.Settings.Default.exportBlendShape; var exportBlendShape = Properties.Settings.Default.exportBlendShape;
var castToBone = Properties.Settings.Default.castToBone; var castToBone = Properties.Settings.Default.castToBone;
var boneSize = (int)Properties.Settings.Default.boneSize; var boneSize = (int)Properties.Settings.Default.boneSize;
var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
var scaleFactor = (float)Properties.Settings.Default.scaleFactor; var scaleFactor = (float)Properties.Settings.Default.scaleFactor;
var fbxVersion = Properties.Settings.Default.fbxVersion; var fbxVersion = Properties.Settings.Default.fbxVersion;
var fbxFormat = Properties.Settings.Default.fbxFormat; var fbxFormat = Properties.Settings.Default.fbxFormat;
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, scaleFactor, fbxVersion, fbxFormat == 1); exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
} }
public static bool ExportDumpFile(AssetItem item, string exportPath) public static bool ExportDumpFile(AssetItem item, string exportPath)
+5 -1
View File
@@ -6,6 +6,7 @@ namespace AssetStudioGUI
{ {
class GUILogger : ILogger class GUILogger : ILogger
{ {
public bool ShowErrorMessage = true;
private Action<string> action; private Action<string> action;
public GUILogger(Action<string> action) public GUILogger(Action<string> action)
@@ -18,7 +19,10 @@ namespace AssetStudioGUI
switch (loggerEvent) switch (loggerEvent)
{ {
case LoggerEvent.Error: case LoggerEvent.Error:
MessageBox.Show(message); if (ShowErrorMessage)
{
MessageBox.Show(message);
}
break; break;
default: default:
action(message); action(message);
-23
View File
@@ -1,23 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AssetStudio;
namespace AssetStudioGUI
{
class GUIProgress : IProgress
{
private Action<int> action;
public GUIProgress(Action<int> action)
{
this.action = action;
}
public void Report(int value)
{
action(value);
}
}
}
Binary file not shown.
-25
View File
@@ -1,25 +0,0 @@
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
<!-- XQuartz compatibility (X11 on Mac) -->
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>
+5 -2
View File
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -9,11 +9,14 @@ namespace AssetStudioGUI
static class Program static class Program
{ {
/// <summary> /// <summary>
/// 应用程序的主入口点。 /// The main entry point for the application.
/// </summary> /// </summary>
[STAThread] [STAThread]
static void Main() static void Main()
{ {
#if !NETFRAMEWORK
Application.SetHighDpiMode(HighDpiMode.SystemAware);
#endif
Application.EnableVisualStyles(); Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AssetStudioGUIForm()); Application.Run(new AssetStudioGUIForm());
-36
View File
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudioGUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioGUI")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("52b196fb-4c8a-499b-b877-1a0eb4f33ec0")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+2 -2
View File
@@ -47,8 +47,8 @@ namespace AssetStudioGUI.Properties {
} }
/// <summary> /// <summary>
/// 重写当前线程的 CurrentUICulture 属性 /// 重写当前线程的 CurrentUICulture 属性,对
/// 重写当前线程的 CurrentUICulture 属性 /// 使用此强类型资源类的所有资源查找执行重写
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture { internal static global::System.Globalization.CultureInfo Culture {
+16 -4
View File
@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -109,10 +109,10 @@ namespace AssetStudioGUI.Properties {
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("PNG")] [global::System.Configuration.DefaultSettingValueAttribute("Png")]
public string convertType { public global::AssetStudio.ImageFormat convertType {
get { get {
return ((string)(this["convertType"])); return ((global::AssetStudio.ImageFormat)(this["convertType"]));
} }
set { set {
this["convertType"] = value; this["convertType"] = value;
@@ -262,5 +262,17 @@ namespace AssetStudioGUI.Properties {
this["restoreExtensionName"] = value; this["restoreExtensionName"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool exportAllUvsAsDiffuseMaps {
get {
return ((bool)(this["exportAllUvsAsDiffuseMaps"]));
}
set {
this["exportAllUvsAsDiffuseMaps"] = value;
}
}
} }
} }
+5 -2
View File
@@ -23,8 +23,8 @@
<Setting Name="convertAudio" Type="System.Boolean" Scope="User"> <Setting Name="convertAudio" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="convertType" Type="System.String" Scope="User"> <Setting Name="convertType" Type="AssetStudio.ImageFormat" Scope="User">
<Value Profile="(Default)">PNG</Value> <Value Profile="(Default)">Png</Value>
</Setting> </Setting>
<Setting Name="eulerFilter" Type="System.Boolean" Scope="User"> <Setting Name="eulerFilter" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
@@ -62,5 +62,8 @@
<Setting Name="restoreExtensionName" Type="System.Boolean" Scope="User"> <Setting Name="restoreExtensionName" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="exportAllUvsAsDiffuseMaps" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>
+38 -30
View File
@@ -72,37 +72,37 @@ namespace AssetStudioGUI
public static int ExtractFile(string fileName, string savePath) public static int ExtractFile(string fileName, string savePath)
{ {
int extractedCount = 0; int extractedCount = 0;
var type = ImportHelper.CheckFileType(fileName, out var reader); var reader = new FileReader(fileName);
if (type == FileType.BundleFile) if (reader.FileType == FileType.BundleFile)
extractedCount += ExtractBundleFile(fileName, reader, savePath); extractedCount += ExtractBundleFile(reader, savePath);
else if (type == FileType.WebFile) else if (reader.FileType == FileType.WebFile)
extractedCount += ExtractWebDataFile(fileName, reader, savePath); extractedCount += ExtractWebDataFile(reader, savePath);
else else
reader.Dispose(); reader.Dispose();
return extractedCount; return extractedCount;
} }
private static int ExtractBundleFile(string bundleFilePath, EndianBinaryReader reader, string savePath) private static int ExtractBundleFile(FileReader reader, string savePath)
{ {
StatusStripUpdate($"Decompressing {Path.GetFileName(bundleFilePath)} ..."); StatusStripUpdate($"Decompressing {reader.FileName} ...");
var bundleFile = new BundleFile(reader, bundleFilePath); var bundleFile = new BundleFile(reader);
reader.Dispose(); reader.Dispose();
if (bundleFile.fileList.Length > 0) if (bundleFile.fileList.Length > 0)
{ {
var extractPath = Path.Combine(savePath, Path.GetFileName(bundleFilePath) + "_unpacked"); var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked");
return ExtractStreamFile(extractPath, bundleFile.fileList); return ExtractStreamFile(extractPath, bundleFile.fileList);
} }
return 0; return 0;
} }
private static int ExtractWebDataFile(string webFilePath, EndianBinaryReader reader, string savePath) private static int ExtractWebDataFile(FileReader reader, string savePath)
{ {
StatusStripUpdate($"Decompressing {Path.GetFileName(webFilePath)} ..."); StatusStripUpdate($"Decompressing {reader.FileName} ...");
var webFile = new WebFile(reader); var webFile = new WebFile(reader);
reader.Dispose(); reader.Dispose();
if (webFile.fileList.Length > 0) if (webFile.fileList.Length > 0)
{ {
var extractPath = Path.Combine(savePath, Path.GetFileName(webFilePath) + "_unpacked"); var extractPath = Path.Combine(savePath, reader.FileName + "_unpacked");
return ExtractStreamFile(extractPath, webFile.fileList); return ExtractStreamFile(extractPath, webFile.fileList);
} }
return 0; return 0;
@@ -265,7 +265,7 @@ namespace AssetStudioGUI
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode var fileNode = new TreeNode(assetsFile.fileName); //RootNode
foreach (var obj in assetsFile.Objects) foreach (var obj in assetsFile.Objects)
{ {
@@ -307,11 +307,12 @@ namespace AssetStudioGUI
{ {
if (m_Father.m_GameObject.TryGet(out var parentGameObject)) if (m_Father.m_GameObject.TryGet(out var parentGameObject))
{ {
if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode)) if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))
{ {
parentNode = new GameObjectTreeNode(parentGameObject); parentGameObjectNode = new GameObjectTreeNode(parentGameObject);
treeNodeDictionary.Add(parentGameObject, parentNode); treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
} }
parentNode = parentGameObjectNode;
} }
} }
} }
@@ -413,7 +414,7 @@ namespace AssetStudioGUI
break; break;
} }
exportPath += Path.DirectorySeparatorChar; exportPath += Path.DirectorySeparatorChar;
StatusStripUpdate($"Exporting {asset.TypeString}: {asset.Text}"); StatusStripUpdate($"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
try try
{ {
switch (exportType) switch (exportType)
@@ -457,7 +458,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && exportedCount > 0) if (Properties.Settings.Default.openAfterExport && exportedCount > 0)
{ {
Process.Start(savePath); OpenFolderInExplorer(savePath);
} }
}); });
} }
@@ -502,7 +503,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0) if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)
{ {
Process.Start(savePath); OpenFolderInExplorer(savePath);
} }
}); });
} }
@@ -514,7 +515,7 @@ namespace AssetStudioGUI
var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count); var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count);
int k = 0; int k = 0;
Progress.Reset(); Progress.Reset();
foreach (GameObjectTreeNode node in nodes) foreach (TreeNode node in nodes)
{ {
//遍历一级子节点 //遍历一级子节点
foreach (GameObjectTreeNode j in node.Nodes) foreach (GameObjectTreeNode j in node.Nodes)
@@ -531,13 +532,13 @@ namespace AssetStudioGUI
//处理非法文件名 //处理非法文件名
var filename = FixFileName(j.Text); var filename = FixFileName(j.Text);
//每个文件存放在单独的文件夹 //每个文件存放在单独的文件夹
var targetPath = $"{savePath}{filename}\\"; var targetPath = $"{savePath}{filename}{Path.DirectorySeparatorChar}";
//重名文件处理 //重名文件处理
for (int i = 1; ; i++) for (int i = 1; ; i++)
{ {
if (Directory.Exists(targetPath)) if (Directory.Exists(targetPath))
{ {
targetPath = $"{savePath}{filename} ({i})\\"; targetPath = $"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}";
} }
else else
{ {
@@ -562,7 +563,7 @@ namespace AssetStudioGUI
} }
if (Properties.Settings.Default.openAfterExport) if (Properties.Settings.Default.openAfterExport)
{ {
Process.Start(savePath); OpenFolderInExplorer(savePath);
} }
StatusStripUpdate("Finished"); StatusStripUpdate("Finished");
}); });
@@ -588,7 +589,7 @@ namespace AssetStudioGUI
ExportAnimator(animator, exportPath, animationList); ExportAnimator(animator, exportPath, animationList);
if (Properties.Settings.Default.openAfterExport) if (Properties.Settings.Default.openAfterExport)
{ {
Process.Start(exportPath); OpenFolderInExplorer(exportPath);
} }
Progress.Report(1, 1); Progress.Report(1, 1);
StatusStripUpdate($"Finished exporting {animator.Text}"); StatusStripUpdate($"Finished exporting {animator.Text}");
@@ -630,12 +631,12 @@ namespace AssetStudioGUI
} }
if (Properties.Settings.Default.openAfterExport) if (Properties.Settings.Default.openAfterExport)
{ {
Process.Start(exportPath); OpenFolderInExplorer(exportPath);
} }
} }
else else
{ {
StatusStripUpdate("No Object can be exported."); StatusStripUpdate("No Object selected for export.");
} }
}); });
} }
@@ -660,18 +661,18 @@ namespace AssetStudioGUI
} }
if (Properties.Settings.Default.openAfterExport) if (Properties.Settings.Default.openAfterExport)
{ {
Process.Start(Path.GetDirectoryName(exportPath)); OpenFolderInExplorer(Path.GetDirectoryName(exportPath));
} }
}); });
} }
public static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects) public static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects)
{ {
foreach (GameObjectTreeNode i in nodes) foreach (TreeNode i in nodes)
{ {
if (i.Checked) if (i is GameObjectTreeNode gameObjectTreeNode && i.Checked)
{ {
gameObjects.Add(i.gameObject); gameObjects.Add(gameObjectTreeNode.gameObject);
} }
else else
{ {
@@ -708,5 +709,12 @@ namespace AssetStudioGUI
} }
return str; return str;
} }
public static void OpenFolderInExplorer(string path)
{
var info = new ProcessStartInfo(path);
info.UseShellExecute = true;
Process.Start(info);
}
} }
} }
-75
View File
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="AssetStudioGUI.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<userSettings>
<AssetStudioGUI.Properties.Settings>
<setting name="displayAll" serializeAs="String">
<value>False</value>
</setting>
<setting name="enablePreview" serializeAs="String">
<value>True</value>
</setting>
<setting name="displayInfo" serializeAs="String">
<value>True</value>
</setting>
<setting name="openAfterExport" serializeAs="String">
<value>True</value>
</setting>
<setting name="assetGroupOption" serializeAs="String">
<value>0</value>
</setting>
<setting name="convertTexture" serializeAs="String">
<value>True</value>
</setting>
<setting name="convertAudio" serializeAs="String">
<value>True</value>
</setting>
<setting name="convertType" serializeAs="String">
<value>PNG</value>
</setting>
<setting name="eulerFilter" serializeAs="String">
<value>True</value>
</setting>
<setting name="filterPrecision" serializeAs="String">
<value>0.25</value>
</setting>
<setting name="exportAllNodes" serializeAs="String">
<value>True</value>
</setting>
<setting name="exportSkins" serializeAs="String">
<value>True</value>
</setting>
<setting name="exportAnimations" serializeAs="String">
<value>True</value>
</setting>
<setting name="boneSize" serializeAs="String">
<value>10</value>
</setting>
<setting name="fbxVersion" serializeAs="String">
<value>3</value>
</setting>
<setting name="fbxFormat" serializeAs="String">
<value>0</value>
</setting>
<setting name="scaleFactor" serializeAs="String">
<value>1</value>
</setting>
<setting name="exportBlendShape" serializeAs="String">
<value>True</value>
</setting>
<setting name="castToBone" serializeAs="String">
<value>False</value>
</setting>
<setting name="restoreExtensionName" serializeAs="String">
<value>True</value>
</setting>
</AssetStudioGUI.Properties.Settings>
</userSettings>
</configuration>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="OpenTK" version="3.1.0" targetFramework="net472" />
<package id="OpenTK.GLControl" version="3.1.0" targetFramework="net472" />
</packages>
+6 -6
View File
@@ -15,18 +15,18 @@ namespace AssetStudio
var resolver = new MyAssemblyResolver(); var resolver = new MyAssemblyResolver();
var readerParameters = new ReaderParameters(); var readerParameters = new ReaderParameters();
readerParameters.AssemblyResolver = resolver; readerParameters.AssemblyResolver = resolver;
try foreach (var file in files)
{ {
foreach (var file in files) try
{ {
var assembly = AssemblyDefinition.ReadAssembly(file, readerParameters); var assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);
resolver.Register(assembly); resolver.Register(assembly);
moduleDic.Add(assembly.MainModule.Name, assembly.MainModule); moduleDic.Add(assembly.MainModule.Name, assembly.MainModule);
} }
} catch
catch {
{ // ignored
// ignored }
} }
Loaded = true; Loaded = true;
} }
+17 -101
View File
@@ -1,108 +1,24 @@
<?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>{80AEC261-21EE-4E4F-A93B-7A744DC84888}</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>AssetStudioUtility</RootNamespace> <DebugType>embedded</DebugType>
<AssemblyName>AssetStudioUtility</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <PackageReference Include="Mono.Cecil" Version="0.11.3" />
<Reference Include="System.Core" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta13" />
<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.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="Unity.Cecil">
<HintPath>Libraries\Unity.Cecil.dll</HintPath>
</Reference>
<Reference Include="Unity.CecilTools">
<HintPath>Libraries\Unity.CecilTools.dll</HintPath>
</Reference>
<Reference Include="Unity.SerializationLogic">
<HintPath>Libraries\Unity.SerializationLogic.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="AssemblyLoader.cs" /> <ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
<Compile Include="AudioClipConverter.cs" /> <ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj" />
<Compile Include="CSspv\Disassembler.cs" /> <ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
<Compile Include="CSspv\EnumValuesExtensions.cs" /> <ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj" />
<Compile Include="CSspv\Instruction.cs" />
<Compile Include="CSspv\Module.cs" />
<Compile Include="CSspv\OperandType.cs" />
<Compile Include="CSspv\ParsedInstruction.cs" />
<Compile Include="CSspv\Reader.cs" />
<Compile Include="CSspv\SpirV.Core.Grammar.cs" />
<Compile Include="CSspv\SpirV.Meta.cs" />
<Compile Include="CSspv\Types.cs" />
<Compile Include="FMOD Studio API\fmod.cs" />
<Compile Include="FMOD Studio API\fmod_dsp.cs" />
<Compile Include="FMOD Studio API\fmod_errors.cs" />
<Compile Include="ModelConverter.cs" />
<Compile Include="ModelExporter.cs" />
<Compile Include="MonoBehaviourConverter.cs" />
<Compile Include="SerializedTypeHelper.cs" />
<Compile Include="TGASharpLib.cs" />
<Compile Include="TypeDefinitionConverter.cs" />
<Compile Include="MyAssemblyResolver.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ShaderConverter.cs" />
<Compile Include="Smolv\OpData.cs" />
<Compile Include="Smolv\SmolvDecoder.cs" />
<Compile Include="Smolv\SpvOp.cs" />
<Compile Include="SpirVShaderConverter.cs" />
<Compile Include="SpriteHelper.cs" />
<Compile Include="Texture2DConverter.cs" />
<Compile Include="Texture2DExtensions.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj">
<Project>{bd76e63f-1517-47fa-8233-33e853a3acee}</Project>
<Name>AssetStudioFBXWrapper</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{7662f8c2-7bfd-442e-a948-a43b4f7eb06e}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj">
<Project>{2afce830-b463-49b3-a026-877e5eafc0a4}</Project>
<Name>Texture2DDecoderWrapper</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>
+20 -20
View File
@@ -94,29 +94,29 @@ namespace AssetStudio
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.ACC: case FMODSoundType.ACC:
return ".m4a"; return ".m4a";
case AudioType.AIFF: case FMODSoundType.AIFF:
return ".aif"; return ".aif";
case AudioType.IT: case FMODSoundType.IT:
return ".it"; return ".it";
case AudioType.MOD: case FMODSoundType.MOD:
return ".mod"; return ".mod";
case AudioType.MPEG: case FMODSoundType.MPEG:
return ".mp3"; return ".mp3";
case AudioType.OGGVORBIS: case FMODSoundType.OGGVORBIS:
return ".ogg"; return ".ogg";
case AudioType.S3M: case FMODSoundType.S3M:
return ".s3m"; return ".s3m";
case AudioType.WAV: case FMODSoundType.WAV:
return ".wav"; return ".wav";
case AudioType.XM: case FMODSoundType.XM:
return ".xm"; return ".xm";
case AudioType.XMA: case FMODSoundType.XMA:
return ".wav"; return ".wav";
case AudioType.VAG: case FMODSoundType.VAG:
return ".vag"; return ".vag";
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
return ".fsb"; return ".fsb";
} }
@@ -133,7 +133,7 @@ namespace AssetStudio
return ".fsb"; return ".fsb";
case AudioCompressionFormat.MP3: case AudioCompressionFormat.MP3:
return ".fsb"; return ".fsb";
case AudioCompressionFormat.VAG: case AudioCompressionFormat.PSMVAG:
return ".fsb"; return ".fsb";
case AudioCompressionFormat.HEVAG: case AudioCompressionFormat.HEVAG:
return ".fsb"; return ".fsb";
@@ -159,13 +159,13 @@ namespace AssetStudio
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case AudioType.AIFF: case FMODSoundType.AIFF:
case AudioType.IT: case FMODSoundType.IT:
case AudioType.MOD: case FMODSoundType.MOD:
case AudioType.S3M: case FMODSoundType.S3M:
case AudioType.XM: case FMODSoundType.XM:
case AudioType.XMA: case FMODSoundType.XMA:
case AudioType.AUDIOQUEUE: case FMODSoundType.AUDIOQUEUE:
return true; return true;
default: default:
return false; return false;
+55
View File
@@ -0,0 +1,55 @@
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.Formats.Tga;
using SixLabors.ImageSharp.PixelFormats;
using System.IO;
using System.Runtime.InteropServices;
namespace AssetStudio
{
public static class ImageExtensions
{
public static void WriteToStream(this Image image, Stream stream, ImageFormat imageFormat)
{
switch (imageFormat)
{
case ImageFormat.Jpeg:
image.SaveAsJpeg(stream);
break;
case ImageFormat.Png:
image.SaveAsPng(stream);
break;
case ImageFormat.Bmp:
image.Save(stream, new BmpEncoder
{
BitsPerPixel = BmpBitsPerPixel.Pixel32,
SupportTransparency = true
});
break;
case ImageFormat.Tga:
image.Save(stream, new TgaEncoder
{
BitsPerPixel = TgaBitsPerPixel.Pixel32,
Compression = TgaCompression.None
});
break;
}
}
public static MemoryStream ConvertToStream(this Image image, ImageFormat imageFormat)
{
var stream = new MemoryStream();
image.WriteToStream(stream, imageFormat);
return stream;
}
public static byte[] ConvertToBytes<TPixel>(this Image<TPixel> image) where TPixel : unmanaged, IPixel<TPixel>
{
if (image.TryGetSinglePixelSpan(out var pixelSpan))
{
return MemoryMarshal.AsBytes(pixelSpan).ToArray();
}
return null;
}
}
}
+10
View File
@@ -0,0 +1,10 @@
namespace AssetStudio
{
public enum ImageFormat
{
Jpeg,
Png,
Bmp,
Tga
}
}
Binary file not shown.
Binary file not shown.
+111 -131
View File
@@ -1,10 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using TGASharpLib;
namespace AssetStudio namespace AssetStudio
{ {
@@ -17,15 +14,16 @@ namespace AssetStudio
public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>(); public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>();
public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>(); public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();
private string imageFormat; private ImageFormat imageFormat;
private Avatar avatar; private Avatar avatar;
private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>(); private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
private Dictionary<AnimationClip, string> boundAnimationPathDic = new Dictionary<AnimationClip, string>();
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>(); private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>(); private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>(); private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>();
Dictionary<uint, string> morphChannelNames = new Dictionary<uint, string>(); Dictionary<uint, string> morphChannelNames = new Dictionary<uint, string>();
public ModelConverter(GameObject m_GameObject, string imageFormat, AnimationClip[] animationList = null) public ModelConverter(GameObject m_GameObject, ImageFormat imageFormat, AnimationClip[] animationList = null)
{ {
this.imageFormat = imageFormat; this.imageFormat = imageFormat;
if (m_GameObject.m_Animator != null) if (m_GameObject.m_Animator != null)
@@ -50,7 +48,7 @@ namespace AssetStudio
ConvertAnimations(); ConvertAnimations();
} }
public ModelConverter(string rootName, List<GameObject> m_GameObjects, string imageFormat, AnimationClip[] animationList = null) public ModelConverter(string rootName, List<GameObject> m_GameObjects, ImageFormat imageFormat, AnimationClip[] animationList = null)
{ {
this.imageFormat = imageFormat; this.imageFormat = imageFormat;
RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One); RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One);
@@ -80,7 +78,7 @@ namespace AssetStudio
ConvertAnimations(); ConvertAnimations();
} }
public ModelConverter(Animator m_Animator, string imageFormat, AnimationClip[] animationList = null) public ModelConverter(Animator m_Animator, ImageFormat imageFormat, AnimationClip[] animationList = null)
{ {
this.imageFormat = imageFormat; this.imageFormat = imageFormat;
InitWithAnimator(m_Animator); InitWithAnimator(m_Animator);
@@ -166,6 +164,10 @@ namespace AssetStudio
{ {
if (animation.TryGet(out var animationClip)) if (animation.TryGet(out var animationClip))
{ {
if (!boundAnimationPathDic.ContainsKey(animationClip))
{
boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform));
}
animationClipHashSet.Add(animationClip); animationClipHashSet.Add(animationClip);
} }
} }
@@ -319,79 +321,8 @@ namespace AssetStudio
} }
ImportedMaterial iMat = ConvertMaterial(mat); ImportedMaterial iMat = ConvertMaterial(mat);
iSubmesh.Material = iMat.Name; iSubmesh.Material = iMat.Name;
iSubmesh.VertexList = new List<ImportedVertex>((int)submesh.vertexCount); iSubmesh.BaseVertex = (int)mesh.m_SubMeshes[i].firstVertex;
for (var j = mesh.m_SubMeshes[i].firstVertex; j < mesh.m_SubMeshes[i].firstVertex + mesh.m_SubMeshes[i].vertexCount; j++)
{
var iVertex = new ImportedVertex();
//Vertices
int c = 3;
if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4)
{
c = 4;
}
iVertex.Vertex = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]);
//Normals
if (iMesh.hasNormal)
{
if (mesh.m_Normals.Length == mesh.m_VertexCount * 3)
{
c = 3;
}
else if (mesh.m_Normals.Length == mesh.m_VertexCount * 4)
{
c = 4;
}
iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]);
}
//UV
iVertex.UV = new float[8][];
for (int uv = 0; uv < 8; uv++)
{
if (iMesh.hasUV[uv])
{
var m_UV = mesh.GetUV(uv);
if (m_UV.Length == mesh.m_VertexCount * 2)
{
c = 2;
}
else if (m_UV.Length == mesh.m_VertexCount * 3)
{
c = 3;
}
iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] };
}
}
//Tangent
if (iMesh.hasTangent)
{
iVertex.Tangent = new Vector4(-mesh.m_Tangents[j * 4], mesh.m_Tangents[j * 4 + 1], mesh.m_Tangents[j * 4 + 2], mesh.m_Tangents[j * 4 + 3]);
}
//Colors
if (iMesh.hasColor)
{
if (mesh.m_Colors.Length == mesh.m_VertexCount * 3)
{
iVertex.Color = new Color(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f);
}
else
{
iVertex.Color = new Color(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]);
}
}
//BoneInfluence
if (mesh.m_Skin?.Length > 0)
{
var inf = mesh.m_Skin[j];
iVertex.BoneIndices = new int[4];
iVertex.Weights = new float[4];
for (var k = 0; k < 4; k++)
{
iVertex.BoneIndices[k] = inf.boneIndex[k];
iVertex.Weights[k] = inf.weight[k];
}
}
iSubmesh.VertexList.Add(iVertex);
}
//Face //Face
iSubmesh.FaceList = new List<ImportedFace>(numFaces); iSubmesh.FaceList = new List<ImportedFace>(numFaces);
var end = firstFace + numFaces; var end = firstFace + numFaces;
@@ -405,9 +336,85 @@ namespace AssetStudio
iSubmesh.FaceList.Add(face); iSubmesh.FaceList.Add(face);
} }
firstFace = end; firstFace = end;
iMesh.SubmeshList.Add(iSubmesh); iMesh.SubmeshList.Add(iSubmesh);
} }
// Shared vertex list
iMesh.VertexList = new List<ImportedVertex>((int)mesh.m_VertexCount);
for (var j = 0; j < mesh.m_VertexCount; j++)
{
var iVertex = new ImportedVertex();
//Vertices
int c = 3;
if (mesh.m_Vertices.Length == mesh.m_VertexCount * 4)
{
c = 4;
}
iVertex.Vertex = new Vector3(-mesh.m_Vertices[j * c], mesh.m_Vertices[j * c + 1], mesh.m_Vertices[j * c + 2]);
//Normals
if (iMesh.hasNormal)
{
if (mesh.m_Normals.Length == mesh.m_VertexCount * 3)
{
c = 3;
}
else if (mesh.m_Normals.Length == mesh.m_VertexCount * 4)
{
c = 4;
}
iVertex.Normal = new Vector3(-mesh.m_Normals[j * c], mesh.m_Normals[j * c + 1], mesh.m_Normals[j * c + 2]);
}
//UV
iVertex.UV = new float[8][];
for (int uv = 0; uv < 8; uv++)
{
if (iMesh.hasUV[uv])
{
var m_UV = mesh.GetUV(uv);
if (m_UV.Length == mesh.m_VertexCount * 2)
{
c = 2;
}
else if (m_UV.Length == mesh.m_VertexCount * 3)
{
c = 3;
}
iVertex.UV[uv] = new[] { m_UV[j * c], m_UV[j * c + 1] };
}
}
//Tangent
if (iMesh.hasTangent)
{
iVertex.Tangent = new Vector4(-mesh.m_Tangents[j * 4], mesh.m_Tangents[j * 4 + 1], mesh.m_Tangents[j * 4 + 2], mesh.m_Tangents[j * 4 + 3]);
}
//Colors
if (iMesh.hasColor)
{
if (mesh.m_Colors.Length == mesh.m_VertexCount * 3)
{
iVertex.Color = new Color(mesh.m_Colors[j * 3], mesh.m_Colors[j * 3 + 1], mesh.m_Colors[j * 3 + 2], 1.0f);
}
else
{
iVertex.Color = new Color(mesh.m_Colors[j * 4], mesh.m_Colors[j * 4 + 1], mesh.m_Colors[j * 4 + 2], mesh.m_Colors[j * 4 + 3]);
}
}
//BoneInfluence
if (mesh.m_Skin?.Length > 0)
{
var inf = mesh.m_Skin[j];
iVertex.BoneIndices = new int[4];
iVertex.Weights = new float[4];
for (var k = 0; k < 4; k++)
{
iVertex.BoneIndices[k] = inf.boneIndex[k];
iVertex.Weights[k] = inf.weight[k];
}
}
iMesh.VertexList.Add(iVertex);
}
if (meshR is SkinnedMeshRenderer sMesh) if (meshR is SkinnedMeshRenderer sMesh)
{ {
//Bone //Bone
@@ -524,7 +531,7 @@ namespace AssetStudio
keyframe.VertexList.Add(destVertex); keyframe.VertexList.Add(destVertex);
var morphVertex = mesh.m_Shapes.vertices[j]; var morphVertex = mesh.m_Shapes.vertices[j];
destVertex.Index = morphVertex.index; destVertex.Index = morphVertex.index;
var sourceVertex = GetSourceVertex(iMesh.SubmeshList, (int)morphVertex.index); var sourceVertex = iMesh.VertexList[(int)morphVertex.index];
destVertex.Vertex = new ImportedVertex(); destVertex.Vertex = new ImportedVertex();
var morphPos = morphVertex.vertex; var morphPos = morphVertex.vertex;
destVertex.Vertex.Vertex = sourceVertex.Vertex + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z); destVertex.Vertex.Vertex = sourceVertex.Vertex + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z);
@@ -598,6 +605,15 @@ namespace AssetStudio
return null; return null;
} }
private string FixBonePath(AnimationClip m_AnimationClip, string path)
{
if (boundAnimationPathDic.TryGetValue(m_AnimationClip, out var basePath))
{
path = basePath + "/" + path;
}
return FixBonePath(path);
}
private string FixBonePath(string path) private string FixBonePath(string path)
{ {
var frame = RootFrame.FindFrameByPath(path); var frame = RootFrame.FindFrameByPath(path);
@@ -694,7 +710,7 @@ namespace AssetStudio
texture.Dest = dest; texture.Dest = dest;
var ext = $".{imageFormat.ToLower()}"; var ext = $".{imageFormat.ToString().ToLower()}";
if (textureNameDictionary.TryGetValue(m_Texture2D, out var textureName)) if (textureNameDictionary.TryGetValue(m_Texture2D, out var textureName))
{ {
texture.Name = textureName; texture.Name = textureName;
@@ -740,30 +756,13 @@ namespace AssetStudio
return; return;
} }
var bitmap = m_Texture2D.ConvertToBitmap(true); var stream = m_Texture2D.ConvertToStream(imageFormat, true);
if (bitmap != null) if (stream != null)
{ {
using (var stream = new MemoryStream()) using (stream)
{ {
switch (imageFormat)
{
case "BMP":
bitmap.Save(stream, ImageFormat.Bmp);
break;
case "PNG":
bitmap.Save(stream, ImageFormat.Png);
break;
case "JPEG":
bitmap.Save(stream, ImageFormat.Jpeg);
break;
case "TGA":
var tga = new TGA(bitmap);
tga.Save(stream);
break;
}
iTex = new ImportedTexture(stream, name); iTex = new ImportedTexture(stream, name);
TextureList.Add(iTex); TextureList.Add(iTex);
bitmap.Dispose();
} }
} }
} }
@@ -794,7 +793,7 @@ namespace AssetStudio
{ {
foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves) foreach (var m_CompressedRotationCurve in animationClip.m_CompressedRotationCurves)
{ {
var track = iAnim.FindTrack(FixBonePath(m_CompressedRotationCurve.m_Path)); var track = iAnim.FindTrack(FixBonePath(animationClip, m_CompressedRotationCurve.m_Path));
var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems; var numKeys = m_CompressedRotationCurve.m_Times.m_NumItems;
var data = m_CompressedRotationCurve.m_Times.UnpackInts(); var data = m_CompressedRotationCurve.m_Times.UnpackInts();
@@ -816,7 +815,7 @@ namespace AssetStudio
} }
foreach (var m_RotationCurve in animationClip.m_RotationCurves) foreach (var m_RotationCurve in animationClip.m_RotationCurves)
{ {
var track = iAnim.FindTrack(FixBonePath(m_RotationCurve.path)); var track = iAnim.FindTrack(FixBonePath(animationClip, m_RotationCurve.path));
foreach (var m_Curve in m_RotationCurve.curve.m_Curve) foreach (var m_Curve in m_RotationCurve.curve.m_Curve)
{ {
var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W)); var value = Fbx.QuaternionToEuler(new Quaternion(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z, m_Curve.value.W));
@@ -825,7 +824,7 @@ namespace AssetStudio
} }
foreach (var m_PositionCurve in animationClip.m_PositionCurves) foreach (var m_PositionCurve in animationClip.m_PositionCurves)
{ {
var track = iAnim.FindTrack(FixBonePath(m_PositionCurve.path)); var track = iAnim.FindTrack(FixBonePath(animationClip, m_PositionCurve.path));
foreach (var m_Curve in m_PositionCurve.curve.m_Curve) foreach (var m_Curve in m_PositionCurve.curve.m_Curve)
{ {
track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z))); track.Translations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(-m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
@@ -833,7 +832,7 @@ namespace AssetStudio
} }
foreach (var m_ScaleCurve in animationClip.m_ScaleCurves) foreach (var m_ScaleCurve in animationClip.m_ScaleCurves)
{ {
var track = iAnim.FindTrack(FixBonePath(m_ScaleCurve.path)); var track = iAnim.FindTrack(FixBonePath(animationClip, m_ScaleCurve.path));
foreach (var m_Curve in m_ScaleCurve.curve.m_Curve) foreach (var m_Curve in m_ScaleCurve.curve.m_Curve)
{ {
track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z))); track.Scalings.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, m_Curve.value.Y, m_Curve.value.Z)));
@@ -843,7 +842,7 @@ namespace AssetStudio
{ {
foreach (var m_EulerCurve in animationClip.m_EulerCurves) foreach (var m_EulerCurve in animationClip.m_EulerCurves)
{ {
var track = iAnim.FindTrack(FixBonePath(m_EulerCurve.path)); var track = iAnim.FindTrack(FixBonePath(animationClip, m_EulerCurve.path));
foreach (var m_Curve in m_EulerCurve.curve.m_Curve) foreach (var m_Curve in m_EulerCurve.curve.m_Curve)
{ {
track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z))); track.Rotations.Add(new ImportedKeyframe<Vector3>(m_Curve.time, new Vector3(m_Curve.value.X, -m_Curve.value.Y, -m_Curve.value.Z)));
@@ -861,7 +860,7 @@ namespace AssetStudio
channelName = channelName.Substring(dotPos + 1); channelName = channelName.Substring(dotPos + 1);
} }
var path = FixBonePath(m_FloatCurve.path); var path = FixBonePath(animationClip, m_FloatCurve.path);
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
{ {
path = GetPathByChannelName(channelName); path = GetPathByChannelName(channelName);
@@ -880,7 +879,7 @@ namespace AssetStudio
{ {
var m_Clip = animationClip.m_MuscleClip.m_Clip; var m_Clip = animationClip.m_MuscleClip.m_Clip;
var streamedFrames = m_Clip.m_StreamedClip.ReadData(); var streamedFrames = m_Clip.m_StreamedClip.ReadData();
var m_ClipBindingConstant = animationClip.m_ClipBindingConstant; var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding();
for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++) for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
{ {
var frame = streamedFrames[frameIndex]; var frame = streamedFrames[frameIndex];
@@ -1014,20 +1013,6 @@ namespace AssetStudio
return boneName; return boneName;
} }
private static ImportedVertex GetSourceVertex(List<ImportedSubmesh> submeshList, int morphVertIndex)
{
foreach (var submesh in submeshList)
{
var vertList = submesh.VertexList;
if (morphVertIndex < vertList.Count)
{
return vertList[morphVertIndex];
}
morphVertIndex -= vertList.Count;
}
return null;
}
private void CreateBonePathHash(Transform m_Transform) private void CreateBonePathHash(Transform m_Transform)
{ {
var name = GetTransformPathByFather(m_Transform); var name = GetTransformPathByFather(m_Transform);
@@ -1078,26 +1063,21 @@ namespace AssetStudio
else else
{ {
transformName = strs.Last(); transformName = strs.Last();
var parentFrameName = strs[strs.Length - 2]; var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
parentFrame = RootFrame.FindChild(parentFrameName); parentFrame = RootFrame.FindRelativeFrameWithPath(parentFramePath);
//var parentFramePath = path.Substring(0, path.LastIndexOf('/'));
//parentFrame = RootFrame.FindFrameByPath(parentFramePath);
} }
var skeletonPose = avatar.m_Avatar.m_DefaultPose; var skeletonPose = avatar.m_Avatar.m_DefaultPose;
var xform = skeletonPose.m_X[i]; var xform = skeletonPose.m_X[i];
var frame = RootFrame.FindChild(transformName); var frame = RootFrame.FindChild(transformName);
if (frame != null) if (frame != null)
{ {
SetFrame(frame, xform.t, xform.q, xform.s); SetFrame(frame, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
} }
else else
{ {
frame = CreateFrame(transformName, xform.t, xform.q, xform.s); frame = CreateFrame(transformName, xform.t, xform.q, xform.s);
parentFrame.AddChild(frame);
} }
parentFrame.AddChild(frame);
} }
} }
+2 -2
View File
@@ -3,9 +3,9 @@
public static class ModelExporter public static class ModelExporter
{ {
public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision, public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision,
bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, float scaleFactor, int versionIndex, bool isAscii) bool allNodes, bool skins, bool animation, bool blendShape, bool castToBone, float boneSize, bool exportAllUvsAsDiffuseMaps, float scaleFactor, int versionIndex, bool isAscii)
{ {
Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allNodes, skins, animation, blendShape, castToBone, boneSize, scaleFactor, versionIndex, isAscii); Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allNodes, skins, animation, blendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, versionIndex, isAscii);
} }
} }
} }
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudioUtility")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioUtility")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018-2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("80aec261-21ee-4e4f-a93b-7a744dc84888")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
+503 -209
View File
@@ -1,9 +1,10 @@
using System; using K4os.Compression.LZ4;
using System;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Lz4;
namespace AssetStudio namespace AssetStudio
{ {
@@ -14,13 +15,11 @@ namespace AssetStudio
if (shader.m_SubProgramBlob != null) //5.3 - 5.4 if (shader.m_SubProgramBlob != null) //5.3 - 5.4
{ {
var decompressedBytes = new byte[shader.decompressedSize]; var decompressedBytes = new byte[shader.decompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob))) LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes);
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
}
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{ {
var program = new ShaderProgram(blobReader, shader.version); var program = new ShaderProgram(blobReader, shader.version);
program.Read(blobReader, 0);
return header + program.Export(Encoding.UTF8.GetString(shader.m_Script)); return header + program.Export(Encoding.UTF8.GetString(shader.m_Script));
} }
} }
@@ -35,19 +34,25 @@ namespace AssetStudio
private static string ConvertSerializedShader(Shader shader) private static string ConvertSerializedShader(Shader shader)
{ {
var shaderPrograms = new ShaderProgram[shader.platforms.Length]; var length = shader.platforms.Length;
for (var i = 0; i < shader.platforms.Length; i++) var shaderPrograms = new ShaderProgram[length];
for (var i = 0; i < length; i++)
{ {
var compressedBytes = new byte[shader.compressedLengths[i]]; for (var j = 0; j < shader.offsets[i].Length; j++)
Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]);
var decompressedBytes = new byte[shader.decompressedLengths[i]];
using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
{ {
decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]); var offset = shader.offsets[i][j];
} var compressedLength = shader.compressedLengths[i][j];
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) var decompressedLength = shader.decompressedLengths[i][j];
{ var decompressedBytes = new byte[decompressedLength];
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version); LZ4Codec.Decode(shader.compressedBlob, (int)offset, (int)compressedLength, decompressedBytes, 0, (int)decompressedLength);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
if (j == 0)
{
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);
}
shaderPrograms[i].Read(blobReader, j);
}
} }
} }
@@ -104,17 +109,17 @@ namespace AssetStudio
var sb = new StringBuilder(); var sb = new StringBuilder();
switch (m_Passe.m_Type) switch (m_Passe.m_Type)
{ {
case PassType.kPassTypeNormal: case PassType.Normal:
sb.Append(" Pass "); sb.Append(" Pass ");
break; break;
case PassType.kPassTypeUse: case PassType.Use:
sb.Append(" UsePass "); sb.Append(" UsePass ");
break; break;
case PassType.kPassTypeGrab: case PassType.Grab:
sb.Append(" GrabPass "); sb.Append(" GrabPass ");
break; break;
} }
if (m_Passe.m_Type == PassType.kPassTypeUse) if (m_Passe.m_Type == PassType.Use)
{ {
sb.Append($"\"{m_Passe.m_UseName}\"\n"); sb.Append($"\"{m_Passe.m_UseName}\"\n");
} }
@@ -122,7 +127,7 @@ namespace AssetStudio
{ {
sb.Append("{\n"); sb.Append("{\n");
if (m_Passe.m_Type == PassType.kPassTypeGrab) if (m_Passe.m_Type == PassType.Grab)
{ {
if (!string.IsNullOrEmpty(m_Passe.m_TextureName)) if (!string.IsNullOrEmpty(m_Passe.m_TextureName))
{ {
@@ -229,7 +234,7 @@ namespace AssetStudio
sb.Append(ConvertSerializedTagMap(m_State.m_Tags, 2)); sb.Append(ConvertSerializedTagMap(m_State.m_Tags, 2));
sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend)); sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend, m_State.rtSeparateBlend));
if (m_State.alphaToMask.val > 0f) if (m_State.alphaToMask.val > 0f)
{ {
@@ -300,9 +305,111 @@ namespace AssetStudio
sb.Append($" Offset {m_State.offsetFactor.val}, {m_State.offsetUnits.val}\n"); sb.Append($" Offset {m_State.offsetFactor.val}, {m_State.offsetUnits.val}\n");
} }
//TODO Stencil if (m_State.stencilRef.val != 0f ||
m_State.stencilReadMask.val != 255f ||
m_State.stencilWriteMask.val != 255f ||
m_State.stencilOp.pass.val != 0f ||
m_State.stencilOp.fail.val != 0f ||
m_State.stencilOp.zFail.val != 0f ||
m_State.stencilOp.comp.val != 8f ||
m_State.stencilOpFront.pass.val != 0f ||
m_State.stencilOpFront.fail.val != 0f ||
m_State.stencilOpFront.zFail.val != 0f ||
m_State.stencilOpFront.comp.val != 8f ||
m_State.stencilOpBack.pass.val != 0f ||
m_State.stencilOpBack.fail.val != 0f ||
m_State.stencilOpBack.zFail.val != 0f ||
m_State.stencilOpBack.comp.val != 8f)
{
sb.Append(" Stencil {\n");
if (m_State.stencilRef.val != 0f)
{
sb.Append($" Ref {m_State.stencilRef.val}\n");
}
if (m_State.stencilReadMask.val != 255f)
{
sb.Append($" ReadMask {m_State.stencilReadMask.val}\n");
}
if (m_State.stencilWriteMask.val != 255f)
{
sb.Append($" WriteMask {m_State.stencilWriteMask.val}\n");
}
if (m_State.stencilOp.pass.val != 0f ||
m_State.stencilOp.fail.val != 0f ||
m_State.stencilOp.zFail.val != 0f ||
m_State.stencilOp.comp.val != 8f)
{
sb.Append(ConvertSerializedStencilOp(m_State.stencilOp, ""));
}
if (m_State.stencilOpFront.pass.val != 0f ||
m_State.stencilOpFront.fail.val != 0f ||
m_State.stencilOpFront.zFail.val != 0f ||
m_State.stencilOpFront.comp.val != 8f)
{
sb.Append(ConvertSerializedStencilOp(m_State.stencilOpFront, "Front"));
}
if (m_State.stencilOpBack.pass.val != 0f ||
m_State.stencilOpBack.fail.val != 0f ||
m_State.stencilOpBack.zFail.val != 0f ||
m_State.stencilOpBack.comp.val != 8f)
{
sb.Append(ConvertSerializedStencilOp(m_State.stencilOpBack, "Back"));
}
sb.Append(" }\n");
}
//TODO Fog if (m_State.fogMode != FogMode.Unknown ||
m_State.fogColor.x.val != 0f ||
m_State.fogColor.y.val != 0f ||
m_State.fogColor.z.val != 0f ||
m_State.fogColor.w.val != 0f ||
m_State.fogDensity.val != 0f ||
m_State.fogStart.val != 0f ||
m_State.fogEnd.val != 0f)
{
sb.Append(" Fog {\n");
if (m_State.fogMode != FogMode.Unknown)
{
sb.Append(" Mode ");
switch (m_State.fogMode)
{
case FogMode.Disabled:
sb.Append("Off");
break;
case FogMode.Linear:
sb.Append("Linear");
break;
case FogMode.Exp:
sb.Append("Exp");
break;
case FogMode.Exp2:
sb.Append("Exp2");
break;
}
sb.Append("\n");
}
if (m_State.fogColor.x.val != 0f ||
m_State.fogColor.y.val != 0f ||
m_State.fogColor.z.val != 0f ||
m_State.fogColor.w.val != 0f)
{
sb.AppendFormat(" Color ({0},{1},{2},{3})\n",
m_State.fogColor.x.val.ToString(CultureInfo.InvariantCulture),
m_State.fogColor.y.val.ToString(CultureInfo.InvariantCulture),
m_State.fogColor.z.val.ToString(CultureInfo.InvariantCulture),
m_State.fogColor.w.val.ToString(CultureInfo.InvariantCulture));
}
if (m_State.fogDensity.val != 0f)
{
sb.Append($" Density {m_State.fogDensity.val.ToString(CultureInfo.InvariantCulture)}\n");
}
if (m_State.fogStart.val != 0f ||
m_State.fogEnd.val != 0f)
{
sb.Append($" Range {m_State.fogStart.val.ToString(CultureInfo.InvariantCulture)}, {m_State.fogEnd.val.ToString(CultureInfo.InvariantCulture)}\n");
}
sb.Append(" }\n");
}
if (m_State.lighting) if (m_State.lighting)
{ {
@@ -314,27 +421,220 @@ namespace AssetStudio
return sb.ToString(); return sb.ToString();
} }
private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend) private static string ConvertSerializedStencilOp(SerializedStencilOp stencilOp, string suffix)
{ {
//TODO Blend
var sb = new StringBuilder(); var sb = new StringBuilder();
/*for (var i = 0; i < rtBlend.Length; i++) sb.Append($" Comp{suffix} {ConvertStencilComp(stencilOp.comp)}\n");
sb.Append($" Pass{suffix} {ConvertStencilOp(stencilOp.pass)}\n");
sb.Append($" Fail{suffix} {ConvertStencilOp(stencilOp.fail)}\n");
sb.Append($" ZFail{suffix} {ConvertStencilOp(stencilOp.zFail)}\n");
return sb.ToString();
}
private static string ConvertStencilOp(SerializedShaderFloatValue op)
{
switch (op.val)
{
case 0f:
default:
return "Keep";
case 1f:
return "Zero";
case 2f:
return "Replace";
case 3f:
return "IncrSat";
case 4f:
return "DecrSat";
case 5f:
return "Invert";
case 6f:
return "IncrWrap";
case 7f:
return "DecrWrap";
}
}
private static string ConvertStencilComp(SerializedShaderFloatValue comp)
{
switch (comp.val)
{
case 0f:
return "Disabled";
case 1f:
return "Never";
case 2f:
return "Less";
case 3f:
return "Equal";
case 4f:
return "LEqual";
case 5f:
return "Greater";
case 6f:
return "NotEqual";
case 7f:
return "GEqual";
case 8f:
default:
return "Always";
}
}
private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend, bool rtSeparateBlend)
{
var sb = new StringBuilder();
for (var i = 0; i < rtBlend.Length; i++)
{ {
var blend = rtBlend[i]; var blend = rtBlend[i];
if (!blend.srcBlend.val.Equals(1f) || if (blend.srcBlend.val != 1f ||
!blend.destBlend.val.Equals(0f) || blend.destBlend.val != 0f ||
!blend.srcBlendAlpha.val.Equals(1f) || blend.srcBlendAlpha.val != 1f ||
!blend.destBlendAlpha.val.Equals(0f)) blend.destBlendAlpha.val != 0f)
{ {
sb.Append(" Blend "); sb.Append(" Blend ");
sb.Append($"{i} "); if (i != 0 || rtSeparateBlend)
sb.Append('\n'); {
sb.Append($"{i} ");
}
sb.Append($"{ConvertBlendFactor(blend.srcBlend)} {ConvertBlendFactor(blend.destBlend)}");
if (blend.srcBlendAlpha.val != 1f ||
blend.destBlendAlpha.val != 0f)
{
sb.Append($", {ConvertBlendFactor(blend.srcBlendAlpha)} {ConvertBlendFactor(blend.destBlendAlpha)}");
}
sb.Append("\n");
} }
}*/
if (blend.blendOp.val != 0f ||
blend.blendOpAlpha.val != 0f)
{
sb.Append(" BlendOp ");
if (i != 0 || rtSeparateBlend)
{
sb.Append($"{i} ");
}
sb.Append(ConvertBlendOp(blend.blendOp));
if (blend.blendOpAlpha.val != 0f)
{
sb.Append($", {ConvertBlendOp(blend.blendOpAlpha)}");
}
sb.Append("\n");
}
var val = (int)blend.colMask.val;
if (val != 0xf)
{
sb.Append(" ColorMask ");
if (val == 0)
{
sb.Append(0);
}
else
{
if ((val & 0x2) != 0)
{
sb.Append("R");
}
if ((val & 0x4) != 0)
{
sb.Append("G");
}
if ((val & 0x8) != 0)
{
sb.Append("B");
}
if ((val & 0x1) != 0)
{
sb.Append("A");
}
}
sb.Append($" {i}\n");
}
}
return sb.ToString(); return sb.ToString();
} }
private static string ConvertBlendOp(SerializedShaderFloatValue op)
{
switch (op.val)
{
case 0f:
default:
return "Add";
case 1f:
return "Sub";
case 2f:
return "RevSub";
case 3f:
return "Min";
case 4f:
return "Max";
case 5f:
return "LogicalClear";
case 6f:
return "LogicalSet";
case 7f:
return "LogicalCopy";
case 8f:
return "LogicalCopyInverted";
case 9f:
return "LogicalNoop";
case 10f:
return "LogicalInvert";
case 11f:
return "LogicalAnd";
case 12f:
return "LogicalNand";
case 13f:
return "LogicalOr";
case 14f:
return "LogicalNor";
case 15f:
return "LogicalXor";
case 16f:
return "LogicalEquiv";
case 17f:
return "LogicalAndReverse";
case 18f:
return "LogicalAndInverted";
case 19f:
return "LogicalOrReverse";
case 20f:
return "LogicalOrInverted";
}
}
private static string ConvertBlendFactor(SerializedShaderFloatValue factor)
{
switch (factor.val)
{
case 0f:
return "Zero";
case 1f:
default:
return "One";
case 2f:
return "DstColor";
case 3f:
return "SrcColor";
case 4f:
return "OneMinusDstColor";
case 5f:
return "SrcAlpha";
case 6f:
return "OneMinusSrcColor";
case 7f:
return "DstAlpha";
case 8f:
return "OneMinusDstAlpha";
case 9f:
return "SrcAlphaSaturate";
case 10f:
return "OneMinusSrcAlpha";
}
}
private static string ConvertSerializedTagMap(SerializedTagMap m_Tags, int intent) private static string ConvertSerializedTagMap(SerializedTagMap m_Tags, int intent)
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
@@ -374,37 +674,37 @@ namespace AssetStudio
sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", "); sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", ");
switch (m_Prop.m_Type) switch (m_Prop.m_Type)
{ {
case SerializedPropertyType.kColor: case SerializedPropertyType.Color:
sb.Append("Color"); sb.Append("Color");
break; break;
case SerializedPropertyType.kVector: case SerializedPropertyType.Vector:
sb.Append("Vector"); sb.Append("Vector");
break; break;
case SerializedPropertyType.kFloat: case SerializedPropertyType.Float:
sb.Append("Float"); sb.Append("Float");
break; break;
case SerializedPropertyType.kRange: case SerializedPropertyType.Range:
sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})"); sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})");
break; break;
case SerializedPropertyType.kTexture: case SerializedPropertyType.Texture:
switch (m_Prop.m_DefTexture.m_TexDim) switch (m_Prop.m_DefTexture.m_TexDim)
{ {
case TextureDimension.kTexDimAny: case TextureDimension.Any:
sb.Append("any"); sb.Append("any");
break; break;
case TextureDimension.kTexDim2D: case TextureDimension.Tex2D:
sb.Append("2D"); sb.Append("2D");
break; break;
case TextureDimension.kTexDim3D: case TextureDimension.Tex3D:
sb.Append("3D"); sb.Append("3D");
break; break;
case TextureDimension.kTexDimCUBE: case TextureDimension.Cube:
sb.Append("Cube"); sb.Append("Cube");
break; break;
case TextureDimension.kTexDim2DArray: case TextureDimension.Tex2DArray:
sb.Append("2DArray"); sb.Append("2DArray");
break; break;
case TextureDimension.kTexDimCubeArray: case TextureDimension.CubeArray:
sb.Append("CubeArray"); sb.Append("CubeArray");
break; break;
} }
@@ -413,15 +713,15 @@ namespace AssetStudio
sb.Append(") = "); sb.Append(") = ");
switch (m_Prop.m_Type) switch (m_Prop.m_Type)
{ {
case SerializedPropertyType.kColor: case SerializedPropertyType.Color:
case SerializedPropertyType.kVector: case SerializedPropertyType.Vector:
sb.Append($"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})"); sb.Append($"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})");
break; break;
case SerializedPropertyType.kFloat: case SerializedPropertyType.Float:
case SerializedPropertyType.kRange: case SerializedPropertyType.Range:
sb.Append(m_Prop.m_DefValue[0]); sb.Append(m_Prop.m_DefValue[0]);
break; break;
case SerializedPropertyType.kTexture: case SerializedPropertyType.Texture:
sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}"); sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}");
break; break;
default: default:
@@ -435,100 +735,65 @@ namespace AssetStudio
{ {
switch (platform) switch (platform)
{ {
case ShaderCompilerPlatform.kShaderCompPlatformGL: case ShaderCompilerPlatform.GL:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLLegacy; return programType == ShaderGpuProgramType.GLLegacy;
case ShaderCompilerPlatform.kShaderCompPlatformD3D9: case ShaderCompilerPlatform.D3D9:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20 return programType == ShaderGpuProgramType.DX9VertexSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30 || programType == ShaderGpuProgramType.DX9VertexSM30
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20 || programType == ShaderGpuProgramType.DX9PixelSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30; || programType == ShaderGpuProgramType.DX9PixelSM30;
case ShaderCompilerPlatform.kShaderCompPlatformXbox360: case ShaderCompilerPlatform.Xbox360:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS case ShaderCompilerPlatform.PS3:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS case ShaderCompilerPlatform.PSP2:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS case ShaderCompilerPlatform.PS4:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS case ShaderCompilerPlatform.XboxOne:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.N3DS:
case ShaderCompilerPlatform.kShaderCompPlatformPS3: case ShaderCompilerPlatform.WiiU:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS case ShaderCompilerPlatform.Switch:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS case ShaderCompilerPlatform.XboxOneD3D12:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS case ShaderCompilerPlatform.GameCoreXboxOne:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS case ShaderCompilerPlatform.GameCoreScarlett:
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS; case ShaderCompilerPlatform.PS5:
case ShaderCompilerPlatform.kShaderCompPlatformD3D11: return programType == ShaderGpuProgramType.ConsoleVS
return programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40 || programType == ShaderGpuProgramType.ConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50 || programType == ShaderGpuProgramType.ConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40 || programType == ShaderGpuProgramType.ConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50 || programType == ShaderGpuProgramType.ConsoleGS;
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40 case ShaderCompilerPlatform.PS5NGGC:
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50 return programType == ShaderGpuProgramType.PS5NGGC;
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50 case ShaderCompilerPlatform.D3D11:
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50; return programType == ShaderGpuProgramType.DX11VertexSM40
case ShaderCompilerPlatform.kShaderCompPlatformGLES20: || programType == ShaderGpuProgramType.DX11VertexSM50
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES; || programType == ShaderGpuProgramType.DX11PixelSM40
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: //Obsolete || programType == ShaderGpuProgramType.DX11PixelSM50
|| programType == ShaderGpuProgramType.DX11GeometrySM40
|| programType == ShaderGpuProgramType.DX11GeometrySM50
|| programType == ShaderGpuProgramType.DX11HullSM50
|| programType == ShaderGpuProgramType.DX11DomainSM50;
case ShaderCompilerPlatform.GLES20:
return programType == ShaderGpuProgramType.GLES;
case ShaderCompilerPlatform.NaCl: //Obsolete
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformFlash: //Obsolete case ShaderCompilerPlatform.Flash: //Obsolete
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x: case ShaderCompilerPlatform.D3D11_9x:
return programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex return programType == ShaderGpuProgramType.DX10Level9Vertex
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel; || programType == ShaderGpuProgramType.DX10Level9Pixel;
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus: case ShaderCompilerPlatform.GLES3Plus:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP return programType == ShaderGpuProgramType.GLES31AEP
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES31 || programType == ShaderGpuProgramType.GLES31
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES3; || programType == ShaderGpuProgramType.GLES3;
case ShaderCompilerPlatform.kShaderCompPlatformPSP2: case ShaderCompilerPlatform.PSM: //Unknown
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformPSM: //Unknown
throw new NotSupportedException(); throw new NotSupportedException();
case ShaderCompilerPlatform.kShaderCompPlatformMetal: case ShaderCompilerPlatform.Metal:
return programType == ShaderGpuProgramType.kShaderGpuProgramMetalVS return programType == ShaderGpuProgramType.MetalVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramMetalFS; || programType == ShaderGpuProgramType.MetalFS;
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore: case ShaderCompilerPlatform.OpenGLCore:
return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32 return programType == ShaderGpuProgramType.GLCore32
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41 || programType == ShaderGpuProgramType.GLCore41
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43; || programType == ShaderGpuProgramType.GLCore43;
case ShaderCompilerPlatform.kShaderCompPlatformN3DS: case ShaderCompilerPlatform.Vulkan:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS return programType == ShaderGpuProgramType.SPIRV;
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformVulkan:
return programType == ShaderGpuProgramType.kShaderGpuProgramSPIRV;
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
@@ -538,48 +803,56 @@ namespace AssetStudio
{ {
switch (platform) switch (platform)
{ {
case ShaderCompilerPlatform.kShaderCompPlatformGL: case ShaderCompilerPlatform.GL:
return "openGL"; return "openGL";
case ShaderCompilerPlatform.kShaderCompPlatformD3D9: case ShaderCompilerPlatform.D3D9:
return "d3d9"; return "d3d9";
case ShaderCompilerPlatform.kShaderCompPlatformXbox360: case ShaderCompilerPlatform.Xbox360:
return "xbox360"; return "xbox360";
case ShaderCompilerPlatform.kShaderCompPlatformPS3: case ShaderCompilerPlatform.PS3:
return "ps3"; return "ps3";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11: case ShaderCompilerPlatform.D3D11:
return "d3d11"; return "d3d11";
case ShaderCompilerPlatform.kShaderCompPlatformGLES20: case ShaderCompilerPlatform.GLES20:
return "gles"; return "gles";
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: case ShaderCompilerPlatform.NaCl:
return "glesdesktop"; return "glesdesktop";
case ShaderCompilerPlatform.kShaderCompPlatformFlash: case ShaderCompilerPlatform.Flash:
return "flash"; return "flash";
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x: case ShaderCompilerPlatform.D3D11_9x:
return "d3d11_9x"; return "d3d11_9x";
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus: case ShaderCompilerPlatform.GLES3Plus:
return "gles3"; return "gles3";
case ShaderCompilerPlatform.kShaderCompPlatformPSP2: case ShaderCompilerPlatform.PSP2:
return "psp2"; return "psp2";
case ShaderCompilerPlatform.kShaderCompPlatformPS4: case ShaderCompilerPlatform.PS4:
return "ps4"; return "ps4";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne: case ShaderCompilerPlatform.XboxOne:
return "xboxone"; return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformPSM: case ShaderCompilerPlatform.PSM:
return "psm"; return "psm";
case ShaderCompilerPlatform.kShaderCompPlatformMetal: case ShaderCompilerPlatform.Metal:
return "metal"; return "metal";
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore: case ShaderCompilerPlatform.OpenGLCore:
return "glcore"; return "glcore";
case ShaderCompilerPlatform.kShaderCompPlatformN3DS: case ShaderCompilerPlatform.N3DS:
return "n3ds"; return "n3ds";
case ShaderCompilerPlatform.kShaderCompPlatformWiiU: case ShaderCompilerPlatform.WiiU:
return "wiiu"; return "wiiu";
case ShaderCompilerPlatform.kShaderCompPlatformVulkan: case ShaderCompilerPlatform.Vulkan:
return "vulkan"; return "vulkan";
case ShaderCompilerPlatform.kShaderCompPlatformSwitch: case ShaderCompilerPlatform.Switch:
return "switch"; return "switch";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12: case ShaderCompilerPlatform.XboxOneD3D12:
return "xboxone_d3d12"; return "xboxone_d3d12";
case ShaderCompilerPlatform.GameCoreXboxOne:
return "xboxone";
case ShaderCompilerPlatform.GameCoreScarlett:
return "xbox_scarlett";
case ShaderCompilerPlatform.PS5:
return "ps5";
case ShaderCompilerPlatform.PS5NGGC:
return "ps5_nggc";
default: default:
return "unknown"; return "unknown";
} }
@@ -592,29 +865,49 @@ namespace AssetStudio
"///////////////////////////////////////////\n"; "///////////////////////////////////////////\n";
} }
public class ShaderSubProgramEntry
{
public int Offset;
public int Length;
public int Segment;
public ShaderSubProgramEntry(BinaryReader reader, int[] version)
{
Offset = reader.ReadInt32();
Length = reader.ReadInt32();
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
Segment = reader.ReadInt32();
}
}
}
public class ShaderProgram public class ShaderProgram
{ {
public ShaderSubProgramEntry[] entries;
public ShaderSubProgram[] m_SubPrograms; public ShaderSubProgram[] m_SubPrograms;
public ShaderProgram(BinaryReader reader, int[] version) public ShaderProgram(BinaryReader reader, int[] version)
{ {
var subProgramsCapacity = reader.ReadInt32(); var subProgramsCapacity = reader.ReadInt32();
m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; entries = new ShaderSubProgramEntry[subProgramsCapacity];
int entrySize;
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{
entrySize = 12;
}
else
{
entrySize = 8;
}
for (int i = 0; i < subProgramsCapacity; i++) for (int i = 0; i < subProgramsCapacity; i++)
{ {
reader.BaseStream.Position = 4 + i * entrySize; entries[i] = new ShaderSubProgramEntry(reader, version);
var offset = reader.ReadInt32(); }
reader.BaseStream.Position = offset; m_SubPrograms = new ShaderSubProgram[subProgramsCapacity];
m_SubPrograms[i] = new ShaderSubProgram(reader); }
public void Read(BinaryReader reader, int segment)
{
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
if (entry.Segment == segment)
{
reader.BaseStream.Position = entry.Offset;
m_SubPrograms[i] = new ShaderSubProgram(reader);
}
} }
} }
@@ -647,7 +940,8 @@ namespace AssetStudio
//201609010 - Unity 5.6, 2017.1 & 2017.2 //201609010 - Unity 5.6, 2017.1 & 2017.2
//201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1 //201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1
//201802150 - Unity 2018.2 & Unity 2018.3 //201802150 - Unity 2018.2 & Unity 2018.3
//201806140 - Unity 2019.1~2020.1 //201806140 - Unity 2019.1~2021.1
//202012090 - Unity 2021.2
m_Version = reader.ReadInt32(); m_Version = reader.ReadInt32();
m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32(); m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32();
reader.BaseStream.Position += 12; reader.BaseStream.Position += 12;
@@ -661,7 +955,7 @@ namespace AssetStudio
{ {
m_Keywords[i] = reader.ReadAlignedString(); m_Keywords[i] = reader.ReadAlignedString();
} }
if (m_Version >= 201806140) if (m_Version >= 201806140 && m_Version < 202012090)
{ {
var m_LocalKeywordsSize = reader.ReadInt32(); var m_LocalKeywordsSize = reader.ReadInt32();
m_LocalKeywords = new string[m_LocalKeywordsSize]; m_LocalKeywords = new string[m_LocalKeywordsSize];
@@ -703,36 +997,36 @@ namespace AssetStudio
{ {
switch (m_ProgramType) switch (m_ProgramType)
{ {
case ShaderGpuProgramType.kShaderGpuProgramGLLegacy: case ShaderGpuProgramType.GLLegacy:
case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP: case ShaderGpuProgramType.GLES31AEP:
case ShaderGpuProgramType.kShaderGpuProgramGLES31: case ShaderGpuProgramType.GLES31:
case ShaderGpuProgramType.kShaderGpuProgramGLES3: case ShaderGpuProgramType.GLES3:
case ShaderGpuProgramType.kShaderGpuProgramGLES: case ShaderGpuProgramType.GLES:
case ShaderGpuProgramType.kShaderGpuProgramGLCore32: case ShaderGpuProgramType.GLCore32:
case ShaderGpuProgramType.kShaderGpuProgramGLCore41: case ShaderGpuProgramType.GLCore41:
case ShaderGpuProgramType.kShaderGpuProgramGLCore43: case ShaderGpuProgramType.GLCore43:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode)); sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break; break;
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20: case ShaderGpuProgramType.DX9VertexSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30: case ShaderGpuProgramType.DX9VertexSM30:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20: case ShaderGpuProgramType.DX9PixelSM20:
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30: case ShaderGpuProgramType.DX9PixelSM30:
{ {
/*var shaderBytecode = new ShaderBytecode(m_ProgramCode); /*var shaderBytecode = new ShaderBytecode(m_ProgramCode);
sb.Append(shaderBytecode.Disassemble());*/ sb.Append(shaderBytecode.Disassemble());*/
sb.Append("// shader disassembly not supported on DXBC"); sb.Append("// shader disassembly not supported on DXBC");
break; break;
} }
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex: case ShaderGpuProgramType.DX10Level9Vertex:
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel: case ShaderGpuProgramType.DX10Level9Pixel:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40: case ShaderGpuProgramType.DX11VertexSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50: case ShaderGpuProgramType.DX11VertexSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40: case ShaderGpuProgramType.DX11PixelSM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50: case ShaderGpuProgramType.DX11PixelSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40: case ShaderGpuProgramType.DX11GeometrySM40:
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50: case ShaderGpuProgramType.DX11GeometrySM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50: case ShaderGpuProgramType.DX11HullSM50:
case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50: case ShaderGpuProgramType.DX11DomainSM50:
{ {
/*int start = 6; /*int start = 6;
if (m_Version == 201509030) // 5.3 if (m_Version == 201509030) // 5.3
@@ -746,8 +1040,8 @@ namespace AssetStudio
sb.Append("// shader disassembly not supported on DXBC"); sb.Append("// shader disassembly not supported on DXBC");
break; break;
} }
case ShaderGpuProgramType.kShaderGpuProgramMetalVS: case ShaderGpuProgramType.MetalVS:
case ShaderGpuProgramType.kShaderGpuProgramMetalFS: case ShaderGpuProgramType.MetalFS:
using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode))) using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))
{ {
var fourCC = reader.ReadUInt32(); var fourCC = reader.ReadUInt32();
@@ -761,7 +1055,7 @@ namespace AssetStudio
sb.Append(Encoding.UTF8.GetString(buff)); sb.Append(Encoding.UTF8.GetString(buff));
} }
break; break;
case ShaderGpuProgramType.kShaderGpuProgramSPIRV: case ShaderGpuProgramType.SPIRV:
try try
{ {
sb.Append(SpirVShaderConverter.Convert(m_ProgramCode)); sb.Append(SpirVShaderConverter.Convert(m_ProgramCode));
@@ -771,11 +1065,11 @@ namespace AssetStudio
sb.Append($"// disassembly error {e.Message}\n"); sb.Append($"// disassembly error {e.Message}\n");
} }
break; break;
case ShaderGpuProgramType.kShaderGpuProgramConsoleVS: case ShaderGpuProgramType.ConsoleVS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleFS: case ShaderGpuProgramType.ConsoleFS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleHS: case ShaderGpuProgramType.ConsoleHS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleDS: case ShaderGpuProgramType.ConsoleDS:
case ShaderGpuProgramType.kShaderGpuProgramConsoleGS: case ShaderGpuProgramType.ConsoleGS:
sb.Append(Encoding.UTF8.GetString(m_ProgramCode)); sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
break; break;
default: default:
+55 -67
View File
@@ -1,117 +1,105 @@
using System.Collections.Generic; using SixLabors.ImageSharp;
using System.Drawing; using SixLabors.ImageSharp.Drawing;
using System.Drawing.Drawing2D; using SixLabors.ImageSharp.Drawing.Processing;
using System.Drawing.Imaging; using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Numerics;
namespace AssetStudio namespace AssetStudio
{ {
public static class SpriteHelper public static class SpriteHelper
{ {
public static Bitmap GetImage(this Sprite m_Sprite) public static Image<Bgra32> GetImage(this Sprite m_Sprite)
{ {
if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas)) if (m_Sprite.m_SpriteAtlas != null && m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlas))
{ {
if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D)) if (m_SpriteAtlas.m_RenderDataMap.TryGetValue(m_Sprite.m_RenderDataKey, out var spriteAtlasData) && spriteAtlasData.texture.TryGet(out var m_Texture2D))
{ {
return CutImage(m_Texture2D, m_Sprite, spriteAtlasData.textureRect, spriteAtlasData.textureRectOffset, spriteAtlasData.settingsRaw); return CutImage(m_Sprite, m_Texture2D, spriteAtlasData.textureRect, spriteAtlasData.textureRectOffset, spriteAtlasData.downscaleMultiplier, spriteAtlasData.settingsRaw);
} }
} }
else else
{ {
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D)) if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D))
{ {
return CutImage(m_Texture2D, m_Sprite, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.settingsRaw); return CutImage(m_Sprite, m_Texture2D, m_Sprite.m_RD.textureRect, m_Sprite.m_RD.textureRectOffset, m_Sprite.m_RD.downscaleMultiplier, m_Sprite.m_RD.settingsRaw);
} }
} }
return null; return null;
} }
private static Bitmap CutImage(Texture2D m_Texture2D, Sprite m_Sprite, Rectf textureRect, Vector2 textureRectOffset, SpriteSettings settingsRaw) private static Image<Bgra32> CutImage(Sprite m_Sprite, Texture2D m_Texture2D, Rectf textureRect, Vector2 textureRectOffset, float downscaleMultiplier, SpriteSettings settingsRaw)
{ {
var originalImage = m_Texture2D.ConvertToBitmap(false); var originalImage = m_Texture2D.ConvertToImage(false);
if (originalImage != null) if (originalImage != null)
{ {
using (originalImage) using (originalImage)
{ {
//var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb); if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
var rectf = new RectangleF(textureRect.x, textureRect.y, textureRect.width, textureRect.height);
var rect = Rectangle.Round(rectf);
if (rect.Width == 0)
{ {
rect.Width = 1; var width = (int)(m_Texture2D.m_Width / downscaleMultiplier);
} var height = (int)(m_Texture2D.m_Height / downscaleMultiplier);
if (rect.Height == 0) originalImage.Mutate(x => x.Resize(width, height));
{
rect.Height = 1;
}
var spriteImage = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
var destRect = new Rectangle(0, 0, rect.Width, rect.Height);
using (var graphic = Graphics.FromImage(spriteImage))
{
graphic.DrawImage(originalImage, destRect, rect, GraphicsUnit.Pixel);
} }
var rectX = (int)Math.Floor(textureRect.x);
var rectY = (int)Math.Floor(textureRect.y);
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
rectRight = Math.Min(rectRight, originalImage.Width);
rectBottom = Math.Min(rectBottom, originalImage.Height);
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
var spriteImage = originalImage.Clone(x => x.Crop(rect));
if (settingsRaw.packed == 1) if (settingsRaw.packed == 1)
{ {
//RotateAndFlip //RotateAndFlip
switch (settingsRaw.packingRotation) switch (settingsRaw.packingRotation)
{ {
case SpritePackingRotation.kSPRFlipHorizontal: case SpritePackingRotation.FlipHorizontal:
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipX); spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
break; break;
case SpritePackingRotation.kSPRFlipVertical: case SpritePackingRotation.FlipVertical:
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY); spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
break; break;
case SpritePackingRotation.kSPRRotate180: case SpritePackingRotation.Rotate180:
spriteImage.RotateFlip(RotateFlipType.Rotate180FlipNone); spriteImage.Mutate(x => x.Rotate(180));
break; break;
case SpritePackingRotation.kSPRRotate90: case SpritePackingRotation.Rotate90:
spriteImage.RotateFlip(RotateFlipType.Rotate270FlipNone); spriteImage.Mutate(x => x.Rotate(270));
break; break;
} }
} }
//Tight //Tight
if (settingsRaw.packingMode == SpritePackingMode.kSPMTight) if (settingsRaw.packingMode == SpritePackingMode.Tight)
{ {
try try
{ {
var triangles = GetTriangles(m_Sprite.m_RD); var triangles = GetTriangles(m_Sprite.m_RD);
var points = triangles.Select(x => x.Select(y => new PointF(y.X, y.Y)).ToArray()); var polygons = triangles.Select(x => new Polygon(new LinearLineSegment(x.Select(y => new PointF(y.X, y.Y)).ToArray()))).ToArray();
using (var path = new GraphicsPath()) IPathCollection path = new PathCollection(polygons);
var matrix = Matrix3x2.CreateScale(m_Sprite.m_PixelsToUnits);
matrix *= Matrix3x2.CreateTranslation(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
path = path.Transform(matrix);
var graphicsOptions = new GraphicsOptions
{ {
foreach (var p in points) Antialias = false,
{ AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
path.AddPolygon(p); };
} var options = new DrawingOptions
using (var matr = new Matrix()) {
{ GraphicsOptions = graphicsOptions
var version = m_Sprite.version; };
if (version[0] < 5 using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))
|| (version[0] == 5 && version[1] < 4) {
|| (version[0] == 5 && version[1] == 4 && version[2] <= 1)) //5.4.1p3 down mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));
{ var bursh = new ImageBrush(mask);
matr.Translate(m_Sprite.m_Rect.width * 0.5f - textureRectOffset.X, m_Sprite.m_Rect.height * 0.5f - textureRectOffset.Y); spriteImage.Mutate(x => x.Fill(graphicsOptions, bursh));
} spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
else return spriteImage;
{
matr.Translate(m_Sprite.m_Rect.width * m_Sprite.m_Pivot.X - textureRectOffset.X, m_Sprite.m_Rect.height * m_Sprite.m_Pivot.Y - textureRectOffset.Y);
}
matr.Scale(m_Sprite.m_PixelsToUnits, m_Sprite.m_PixelsToUnits);
path.Transform(matr);
var bitmap = new Bitmap(rect.Width, rect.Height);
using (var graphic = Graphics.FromImage(bitmap))
{
using (var brush = new TextureBrush(spriteImage))
{
graphic.FillPath(brush, path);
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
spriteImage.Dispose();
return bitmap;
}
}
}
} }
} }
catch catch
@@ -121,7 +109,7 @@ namespace AssetStudio
} }
//Rectangle //Rectangle
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY); spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
return spriteImage; return spriteImage;
} }
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+36 -3
View File
@@ -1,13 +1,46 @@
using System.Drawing; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System.IO;
namespace AssetStudio namespace AssetStudio
{ {
public static class Texture2DExtensions public static class Texture2DExtensions
{ {
public static Bitmap ConvertToBitmap(this Texture2D m_Texture2D, bool flip) public static Image<Bgra32> ConvertToImage(this Texture2D m_Texture2D, bool flip)
{ {
var converter = new Texture2DConverter(m_Texture2D); var converter = new Texture2DConverter(m_Texture2D);
return converter.ConvertToBitmap(flip); var buff = BigArrayPool<byte>.Shared.Rent(m_Texture2D.m_Width * m_Texture2D.m_Height * 4);
try
{
if (converter.DecodeTexture2D(buff))
{
var image = Image.LoadPixelData<Bgra32>(buff, m_Texture2D.m_Width, m_Texture2D.m_Height);
if (flip)
{
image.Mutate(x => x.Flip(FlipMode.Vertical));
}
return image;
}
return null;
}
finally
{
BigArrayPool<byte>.Shared.Return(buff);
}
}
public static MemoryStream ConvertToStream(this Texture2D m_Texture2D, ImageFormat imageFormat, bool flip)
{
var image = ConvertToImage(m_Texture2D, flip);
if (image != null)
{
using (image)
{
return image.ConvertToStream(imageFormat);
}
}
return null;
} }
} }
} }
+42 -61
View File
@@ -26,22 +26,22 @@ namespace AssetStudio
{ {
var nodes = new List<TypeTreeNode>(); var nodes = new List<TypeTreeNode>();
Stack<TypeReference> baseTypes = new Stack<TypeReference>(); var baseTypes = new Stack<TypeReference>();
TypeReference baseType = TypeDef.BaseType; var lastBaseType = TypeDef.BaseType;
while (!UnitySerializationLogic.IsNonSerialized(baseType)) while (!UnitySerializationLogic.IsNonSerialized(lastBaseType))
{ {
GenericInstanceType genericInstanceType = baseType as GenericInstanceType; var genericInstanceType = lastBaseType as GenericInstanceType;
if (genericInstanceType != null) if (genericInstanceType != null)
{ {
TypeResolver.Add(genericInstanceType); TypeResolver.Add(genericInstanceType);
} }
baseTypes.Push(baseType); baseTypes.Push(lastBaseType);
baseType = baseType.Resolve().BaseType; lastBaseType = lastBaseType.Resolve().BaseType;
} }
while (baseTypes.Count > 0) while (baseTypes.Count > 0)
{ {
TypeReference typeReference = baseTypes.Pop(); var typeReference = baseTypes.Pop();
TypeDefinition typeDefinition = typeReference.Resolve(); var typeDefinition = typeReference.Resolve();
foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize)) foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize))
{ {
if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef)) if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef))
@@ -50,15 +50,15 @@ namespace AssetStudio
} }
} }
var genericInstanceType2 = typeReference as GenericInstanceType; var genericInstanceType = typeReference as GenericInstanceType;
if (genericInstanceType2 != null) if (genericInstanceType != null)
{ {
TypeResolver.Remove(genericInstanceType2); TypeResolver.Remove(genericInstanceType);
} }
} }
foreach (FieldDefinition fieldDefinition2 in FilteredFields()) foreach (var field in FilteredFields())
{ {
nodes.AddRange(ProcessingFieldRef(fieldDefinition2)); nodes.AddRange(ProcessingFieldRef(field));
} }
return nodes; return nodes;
@@ -66,75 +66,60 @@ namespace AssetStudio
private bool WillUnitySerialize(FieldDefinition fieldDefinition) private bool WillUnitySerialize(FieldDefinition fieldDefinition)
{ {
bool result;
try try
{ {
TypeReference typeReference = TypeResolver.Resolve(fieldDefinition.FieldType); var resolvedFieldType = TypeResolver.Resolve(fieldDefinition.FieldType);
if (UnitySerializationLogic.ShouldNotTryToResolve(typeReference)) if (UnitySerializationLogic.ShouldNotTryToResolve(resolvedFieldType))
{ {
result = false; return false;
} }
else if (!UnityEngineTypePredicates.IsUnityEngineObject(resolvedFieldType))
{ {
if (!UnityEngineTypePredicates.IsUnityEngineObject(typeReference)) if (resolvedFieldType.FullName == fieldDefinition.DeclaringType.FullName)
{ {
if (typeReference.FullName == fieldDefinition.DeclaringType.FullName) return false;
{
return false;
}
} }
result = UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);
} }
return UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);
} }
catch (Exception ex) catch (Exception ex)
{ {
throw new Exception(string.Format("Exception while processing {0} {1}, error {2}", fieldDefinition.FieldType.FullName, fieldDefinition.FullName, ex.Message)); throw new Exception(string.Format("Exception while processing {0} {1}, error {2}", fieldDefinition.FieldType.FullName, fieldDefinition.FullName, ex.Message));
} }
return result;
} }
private static bool IsHiddenByParentClass(IEnumerable<TypeReference> parentTypes, FieldDefinition fieldDefinition, TypeDefinition processingType) private static bool IsHiddenByParentClass(IEnumerable<TypeReference> parentTypes, FieldDefinition fieldDefinition, TypeDefinition processingType)
{ {
return processingType.Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name) || parentTypes.Any((TypeReference t) => t.Resolve().Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name)); return processingType.Fields.Any(f => f.Name == fieldDefinition.Name) || parentTypes.Any(t => t.Resolve().Fields.Any(f => f.Name == fieldDefinition.Name));
} }
private IEnumerable<FieldDefinition> FilteredFields() private IEnumerable<FieldDefinition> FilteredFields()
{ {
foreach (var f in TypeDef.Fields.Where(WillUnitySerialize)) return TypeDef.Fields.Where(WillUnitySerialize).Where(f =>
{ UnitySerializationLogic.IsSupportedCollection(f.FieldType) ||
if (UnitySerializationLogic.IsSupportedCollection(f.FieldType) || !f.FieldType.IsGenericInstance || UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve())) !f.FieldType.IsGenericInstance ||
{ UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()));
yield return f;
}
}
yield break;
} }
private FieldReference ResolveGenericFieldReference(FieldReference fieldRef) private FieldReference ResolveGenericFieldReference(FieldReference fieldRef)
{ {
FieldReference field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType)); var field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType));
return TypeDef.Module.ImportReference(field); return TypeDef.Module.ImportReference(field);
} }
private TypeReference ResolveDeclaringType(TypeReference declaringType) private TypeReference ResolveDeclaringType(TypeReference declaringType)
{ {
TypeDefinition typeDefinition = declaringType.Resolve(); var typeDefinition = declaringType.Resolve();
TypeReference result;
if (typeDefinition == null || !typeDefinition.HasGenericParameters) if (typeDefinition == null || !typeDefinition.HasGenericParameters)
{ {
result = typeDefinition; return typeDefinition;
} }
else var genericInstanceType = new GenericInstanceType(typeDefinition);
foreach (var genericParameter in typeDefinition.GenericParameters)
{ {
GenericInstanceType genericInstanceType = new GenericInstanceType(typeDefinition); genericInstanceType.GenericArguments.Add(genericParameter);
foreach (GenericParameter item in typeDefinition.GenericParameters)
{
genericInstanceType.GenericArguments.Add(item);
}
result = TypeResolver.Resolve(genericInstanceType);
} }
return result; return TypeResolver.Resolve(genericInstanceType);
} }
private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef) private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef)
@@ -155,7 +140,6 @@ namespace AssetStudio
private static bool RequiresAlignment(TypeReference typeRef) private static bool RequiresAlignment(TypeReference typeRef)
{ {
bool result;
switch (typeRef.MetadataType) switch (typeRef.MetadataType)
{ {
case MetadataType.Boolean: case MetadataType.Boolean:
@@ -164,13 +148,10 @@ namespace AssetStudio
case MetadataType.Byte: case MetadataType.Byte:
case MetadataType.Int16: case MetadataType.Int16:
case MetadataType.UInt16: case MetadataType.UInt16:
result = true; return true;
break;
default: default:
result = (UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef))); return UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef));
break;
} }
return result;
} }
private static bool IsSystemString(TypeReference typeRef) private static bool IsSystemString(TypeReference typeRef)
@@ -272,28 +253,28 @@ namespace AssetStudio
switch (typeRef.FullName) switch (typeRef.FullName)
{ {
case "UnityEngine.AnimationCurve": case "UnityEngine.AnimationCurve":
Helper.AddAnimationCurve(nodes, name, indent + 1); Helper.AddAnimationCurve(nodes, name, indent);
break; break;
case "UnityEngine.Gradient": case "UnityEngine.Gradient":
Helper.AddGradient(nodes, name, indent + 1); Helper.AddGradient(nodes, name, indent);
break; break;
case "UnityEngine.GUIStyle": case "UnityEngine.GUIStyle":
Helper.AddGUIStyle(nodes, name, indent + 1); Helper.AddGUIStyle(nodes, name, indent);
break; break;
case "UnityEngine.RectOffset": case "UnityEngine.RectOffset":
Helper.AddRectOffset(nodes, name, indent + 1); Helper.AddRectOffset(nodes, name, indent);
break; break;
case "UnityEngine.Color32": case "UnityEngine.Color32":
Helper.AddColor32(nodes, name, indent + 1); Helper.AddColor32(nodes, name, indent);
break; break;
case "UnityEngine.Matrix4x4": case "UnityEngine.Matrix4x4":
Helper.AddMatrix4x4(nodes, name, indent + 1); Helper.AddMatrix4x4(nodes, name, indent);
break; break;
case "UnityEngine.Rendering.SphericalHarmonicsL2": case "UnityEngine.Rendering.SphericalHarmonicsL2":
Helper.AddSphericalHarmonicsL2(nodes, name, indent + 1); Helper.AddSphericalHarmonicsL2(nodes, name, indent);
break; break;
case "UnityEngine.PropertyName": case "UnityEngine.PropertyName":
Helper.AddPropertyName(nodes, name, indent + 1); Helper.AddPropertyName(nodes, name, indent);
break; break;
} }
} }
@@ -0,0 +1,65 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Unity.CecilTools.Extensions;
namespace Unity.CecilTools
{
public static class CecilUtils
{
public static MethodDefinition FindInTypeExplicitImplementationFor(MethodDefinition interfaceMethod, TypeDefinition typeDefinition)
{
return typeDefinition.Methods.SingleOrDefault(m => m.Overrides.Any(o => o.CheckedResolve().SameAs(interfaceMethod)));
}
public static IEnumerable<TypeDefinition> AllInterfacesImplementedBy(TypeDefinition typeDefinition)
{
return TypeAndBaseTypesOf(typeDefinition).SelectMany(t => t.Interfaces).Select(i => i.InterfaceType.CheckedResolve()).Distinct();
}
public static IEnumerable<TypeDefinition> TypeAndBaseTypesOf(TypeReference typeReference)
{
while (typeReference != null)
{
var typeDefinition = typeReference.CheckedResolve();
yield return typeDefinition;
typeReference = typeDefinition.BaseType;
}
}
public static IEnumerable<TypeDefinition> BaseTypesOf(TypeReference typeReference)
{
return TypeAndBaseTypesOf(typeReference).Skip(1);
}
public static bool IsGenericList(TypeReference type)
{
return type.Name == "List`1" && type.SafeNamespace() == "System.Collections.Generic";
}
public static bool IsGenericDictionary(TypeReference type)
{
if (type is GenericInstanceType)
type = ((GenericInstanceType)type).ElementType;
return type.Name == "Dictionary`2" && type.SafeNamespace() == "System.Collections.Generic";
}
public static TypeReference ElementTypeOfCollection(TypeReference type)
{
var at = type as ArrayType;
if (at != null)
return at.ElementType;
if (IsGenericList(type))
return ((GenericInstanceType)type).GenericArguments.Single();
throw new ArgumentException();
}
}
}
@@ -0,0 +1,21 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using Mono.Cecil;
namespace Unity.CecilTools
{
static public class ElementType
{
public static TypeReference For(TypeReference byRefType)
{
var refType = byRefType as TypeSpecification;
if (refType != null)
return refType.ElementType;
throw new ArgumentException(string.Format("TypeReference isn't a TypeSpecification {0} ", byRefType));
}
}
}
@@ -0,0 +1,50 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using Mono.Cecil;
namespace Unity.CecilTools.Extensions
{
static class MethodDefinitionExtensions
{
public static bool SameAs(this MethodDefinition self, MethodDefinition other)
{
// FIXME: should be able to compare MethodDefinition references directly
return self.FullName == other.FullName;
}
public static string PropertyName(this MethodDefinition self)
{
return self.Name.Substring(4);
}
public static bool IsConversionOperator(this MethodDefinition method)
{
if (!method.IsSpecialName)
return false;
return method.Name == "op_Implicit" || method.Name == "op_Explicit";
}
public static bool IsSimpleSetter(this MethodDefinition original)
{
return original.IsSetter && original.Parameters.Count == 1;
}
public static bool IsSimpleGetter(this MethodDefinition original)
{
return original.IsGetter && original.Parameters.Count == 0;
}
public static bool IsSimplePropertyAccessor(this MethodDefinition method)
{
return method.IsSimpleGetter() || method.IsSimpleSetter();
}
public static bool IsDefaultConstructor(MethodDefinition m)
{
return m.IsConstructor && !m.IsStatic && m.Parameters.Count == 0;
}
}
}
@@ -0,0 +1,36 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using Mono.Cecil;
namespace Unity.CecilTools.Extensions
{
public static class ResolutionExtensions
{
public static TypeDefinition CheckedResolve(this TypeReference type)
{
return Resolve(type, reference => reference.Resolve());
}
public static MethodDefinition CheckedResolve(this MethodReference method)
{
return Resolve(method, reference => reference.Resolve());
}
private static TDefinition Resolve<TReference, TDefinition>(TReference reference, Func<TReference, TDefinition> resolve)
where TReference : MemberReference
where TDefinition : class, IMemberDefinition
{
if (reference.Module == null)
throw new ResolutionException(reference);
var definition = resolve(reference);
if (definition == null)
throw new ResolutionException(reference);
return definition;
}
}
}
@@ -0,0 +1,47 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil;
namespace Unity.CecilTools.Extensions
{
public static class TypeDefinitionExtensions
{
public static bool IsSubclassOf(this TypeDefinition type, string baseTypeName)
{
var baseType = type.BaseType;
if (baseType == null)
return false;
if (baseType.FullName == baseTypeName)
return true;
var baseTypeDef = baseType.Resolve();
if (baseTypeDef == null)
return false;
return IsSubclassOf(baseTypeDef, baseTypeName);
}
public static bool IsSubclassOf(this TypeDefinition type, params string[] baseTypeNames)
{
var baseType = type.BaseType;
if (baseType == null)
return false;
for (int i = 0; i < baseTypeNames.Length; i++)
if (baseType.FullName == baseTypeNames[i])
return true;
var baseTypeDef = baseType.Resolve();
if (baseTypeDef == null)
return false;
return IsSubclassOf(baseTypeDef, baseTypeNames);
}
}
}
@@ -0,0 +1,53 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using Mono.Cecil;
namespace Unity.CecilTools.Extensions
{
public static class TypeReferenceExtensions
{
public static string SafeNamespace(this TypeReference type)
{
if (type.IsGenericInstance)
return ((GenericInstanceType)type).ElementType.SafeNamespace();
if (type.IsNested)
return type.DeclaringType.SafeNamespace();
return type.Namespace;
}
public static bool IsAssignableTo(this TypeReference typeRef, string typeName)
{
try
{
if (typeRef.IsGenericInstance)
return ElementType.For(typeRef).IsAssignableTo(typeName);
if (typeRef.FullName == typeName)
return true;
return typeRef.CheckedResolve().IsSubclassOf(typeName);
}
catch (AssemblyResolutionException) // If we can't resolve our typeref or one of its base types,
{ // let's assume it is not assignable to our target type
return false;
}
}
public static bool IsEnum(this TypeReference type)
{
return type.IsValueType && !type.IsPrimitive && type.CheckedResolve().IsEnum;
}
public static bool IsStruct(this TypeReference type)
{
return type.IsValueType && !type.IsPrimitive && !type.IsEnum() && !IsSystemDecimal(type);
}
private static bool IsSystemDecimal(TypeReference type)
{
return type.FullName == "System.Decimal";
}
}
}
@@ -0,0 +1,168 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System.Collections.Generic;
using Unity.CecilTools.Extensions;
using Mono.Cecil;
namespace Unity.SerializationLogic
{
public class UnityEngineTypePredicates
{
private static readonly HashSet<string> TypesThatShouldHaveHadSerializableAttribute = new HashSet<string>
{
"Vector3",
"Vector2",
"Vector4",
"Rect",
"RectInt",
"Quaternion",
"Matrix4x4",
"Color",
"Color32",
"LayerMask",
"Bounds",
"BoundsInt",
"Vector3Int",
"Vector2Int",
};
private const string Gradient = "UnityEngine.Gradient";
private const string GUIStyle = "UnityEngine.GUIStyle";
private const string RectOffset = "UnityEngine.RectOffset";
protected const string UnityEngineObject = "UnityEngine.Object";
public const string MonoBehaviour = "UnityEngine.MonoBehaviour";
public const string ScriptableObject = "UnityEngine.ScriptableObject";
protected const string Matrix4x4 = "UnityEngine.Matrix4x4";
protected const string Color32 = "UnityEngine.Color32";
private const string SerializeFieldAttribute = "UnityEngine.SerializeField";
private const string SerializeReferenceAttribute = "UnityEngine.SerializeReference";
private static string[] serializableClasses = new[]
{
"UnityEngine.AnimationCurve",
"UnityEngine.Gradient",
"UnityEngine.GUIStyle",
"UnityEngine.RectOffset"
};
private static string[] serializableStructs = new[]
{
// NOTE: assumes all types here are NOT interfaces
"UnityEngine.Color32",
"UnityEngine.Matrix4x4",
"UnityEngine.Rendering.SphericalHarmonicsL2",
"UnityEngine.PropertyName",
};
public static bool IsMonoBehaviour(TypeReference type)
{
return IsMonoBehaviour(type.CheckedResolve());
}
private static bool IsMonoBehaviour(TypeDefinition typeDefinition)
{
return typeDefinition.IsSubclassOf(MonoBehaviour);
}
public static bool IsScriptableObject(TypeReference type)
{
return IsScriptableObject(type.CheckedResolve());
}
private static bool IsScriptableObject(TypeDefinition temp)
{
return temp.IsSubclassOf(ScriptableObject);
}
public static bool IsColor32(TypeReference type)
{
return type.IsAssignableTo(Color32);
}
//Do NOT remove these, cil2as still depends on these in 4.x
public static bool IsMatrix4x4(TypeReference type)
{
return type.IsAssignableTo(Matrix4x4);
}
public static bool IsGradient(TypeReference type)
{
return type.IsAssignableTo(Gradient);
}
public static bool IsGUIStyle(TypeReference type)
{
return type.IsAssignableTo(GUIStyle);
}
public static bool IsRectOffset(TypeReference type)
{
return type.IsAssignableTo(RectOffset);
}
public static bool IsSerializableUnityClass(TypeReference type)
{
foreach (var unityClasses in serializableClasses)
{
if (type.IsAssignableTo(unityClasses))
return true;
}
return false;
}
public static bool IsSerializableUnityStruct(TypeReference type)
{
foreach (var unityStruct in serializableStructs)
{
// NOTE: structs cannot inherit from structs, and can only inherit from interfaces
// since we know all types in serializableStructs are not interfaces,
// we can just do a direct comparison.
if (type.FullName == unityStruct)
return true;
}
if (type.FullName.IndexOf("UnityEngine.LazyLoadReference`1") == 0)
return true;
return false;
}
public static bool IsUnityEngineObject(TypeReference type)
{
//todo: somehow solve this elegantly. CheckedResolve() drops the [] of a type.
if (type.IsArray)
return false;
if (type.FullName == UnityEngineObject)
return true;
var typeDefinition = type.Resolve();
if (typeDefinition == null)
return false;
return typeDefinition.IsSubclassOf(UnityEngineObject);
}
public static bool ShouldHaveHadSerializableAttribute(TypeReference type)
{
return IsUnityEngineValueType(type);
}
public static bool IsUnityEngineValueType(TypeReference type)
{
return type.SafeNamespace() == "UnityEngine" && TypesThatShouldHaveHadSerializableAttribute.Contains(type.Name);
}
public static bool IsSerializeFieldAttribute(TypeReference attributeType)
{
return attributeType.FullName == SerializeFieldAttribute;
}
public static bool IsSerializeReferenceAttribute(TypeReference attributeType)
{
return attributeType.FullName == SerializeReferenceAttribute;
}
}
}
@@ -0,0 +1,612 @@
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Collections.Generic;
using Unity.CecilTools;
using Unity.CecilTools.Extensions;
namespace Unity.SerializationLogic
{
internal class GenericInstanceHolder
{
public int Count;
public IGenericInstance GenericInstance;
}
public class TypeResolver
{
private readonly IGenericInstance _typeDefinitionContext;
private readonly IGenericInstance _methodDefinitionContext;
private readonly Dictionary<string, GenericInstanceHolder> _context = new Dictionary<string, GenericInstanceHolder>();
public TypeResolver()
{
}
public TypeResolver(IGenericInstance typeDefinitionContext)
{
_typeDefinitionContext = typeDefinitionContext;
}
public TypeResolver(GenericInstanceMethod methodDefinitionContext)
{
_methodDefinitionContext = methodDefinitionContext;
}
public TypeResolver(IGenericInstance typeDefinitionContext, IGenericInstance methodDefinitionContext)
{
_typeDefinitionContext = typeDefinitionContext;
_methodDefinitionContext = methodDefinitionContext;
}
public void Add(GenericInstanceType genericInstanceType)
{
Add(ElementTypeFor(genericInstanceType).FullName, genericInstanceType);
}
public void Remove(GenericInstanceType genericInstanceType)
{
Remove(genericInstanceType.ElementType.FullName, genericInstanceType);
}
public void Add(GenericInstanceMethod genericInstanceMethod)
{
Add(ElementTypeFor(genericInstanceMethod).FullName, genericInstanceMethod);
}
private static MemberReference ElementTypeFor(TypeSpecification genericInstanceType)
{
return genericInstanceType.ElementType;
}
private static MemberReference ElementTypeFor(MethodSpecification genericInstanceMethod)
{
return genericInstanceMethod.ElementMethod;
}
public void Remove(GenericInstanceMethod genericInstanceMethod)
{
Remove(genericInstanceMethod.ElementMethod.FullName, genericInstanceMethod);
}
public TypeReference Resolve(TypeReference typeReference)
{
var genericParameter = typeReference as GenericParameter;
if (genericParameter != null)
{
var resolved = ResolveGenericParameter(genericParameter);
if (genericParameter == resolved) // Resolving failed, return what we have.
return resolved;
return Resolve(resolved);
}
var arrayType = typeReference as ArrayType;
if (arrayType != null)
return new ArrayType(Resolve(arrayType.ElementType), arrayType.Rank);
var pointerType = typeReference as PointerType;
if (pointerType != null)
return new PointerType(Resolve(pointerType.ElementType));
var byReferenceType = typeReference as ByReferenceType;
if (byReferenceType != null)
return new ByReferenceType(Resolve(byReferenceType.ElementType));
var genericInstanceType = typeReference as GenericInstanceType;
if (genericInstanceType != null)
{
var newGenericInstanceType = new GenericInstanceType(Resolve(genericInstanceType.ElementType));
foreach (var genericArgument in genericInstanceType.GenericArguments)
newGenericInstanceType.GenericArguments.Add(Resolve(genericArgument));
return newGenericInstanceType;
}
var pinnedType = typeReference as PinnedType;
if (pinnedType != null)
return new PinnedType(Resolve(pinnedType.ElementType));
var reqModifierType = typeReference as RequiredModifierType;
if (reqModifierType != null)
return Resolve(reqModifierType.ElementType);
var optModifierType = typeReference as OptionalModifierType;
if (optModifierType != null)
return new OptionalModifierType(Resolve(optModifierType.ModifierType), Resolve(optModifierType.ElementType));
var sentinelType = typeReference as SentinelType;
if (sentinelType != null)
return new SentinelType(Resolve(sentinelType.ElementType));
var funcPtrType = typeReference as FunctionPointerType;
if (funcPtrType != null)
throw new NotSupportedException("Function pointer types are not supported by the SerializationWeaver");
if (typeReference is TypeSpecification)
throw new NotSupportedException();
return typeReference;
}
private TypeReference ResolveGenericParameter(GenericParameter genericParameter)
{
if (genericParameter.Owner == null)
throw new NotSupportedException();
var memberReference = genericParameter.Owner as MemberReference;
if (memberReference == null)
throw new NotSupportedException();
var key = memberReference.FullName;
if (!_context.ContainsKey(key))
{
if (genericParameter.Type == GenericParameterType.Type)
{
if (_typeDefinitionContext != null)
return _typeDefinitionContext.GenericArguments[genericParameter.Position];
return genericParameter;
}
if (_methodDefinitionContext != null)
return _methodDefinitionContext.GenericArguments[genericParameter.Position];
return genericParameter;
}
return GenericArgumentAt(key, genericParameter.Position);
}
private TypeReference GenericArgumentAt(string key, int position)
{
return _context[key].GenericInstance.GenericArguments[position];
}
private void Add(string key, IGenericInstance value)
{
GenericInstanceHolder oldValue;
if (_context.TryGetValue(key, out oldValue))
{
var memberReference = value as MemberReference;
if (memberReference == null)
throw new NotSupportedException();
var storedValue = (MemberReference)oldValue.GenericInstance;
if (storedValue.FullName != memberReference.FullName)
throw new ArgumentException("Duplicate key!", "key");
oldValue.Count++;
return;
}
_context.Add(key, new GenericInstanceHolder { Count = 1, GenericInstance = value });
}
private void Remove(string key, IGenericInstance value)
{
GenericInstanceHolder oldValue;
if (_context.TryGetValue(key, out oldValue))
{
var memberReference = value as MemberReference;
if (memberReference == null)
throw new NotSupportedException();
var storedValue = (MemberReference)oldValue.GenericInstance;
if (storedValue.FullName != memberReference.FullName)
throw new ArgumentException("Invalid value!", "value");
oldValue.Count--;
if (oldValue.Count == 0)
_context.Remove(key);
return;
}
throw new ArgumentException("Invalid key!", "key");
}
}
public static class UnitySerializationLogic
{
public static bool WillUnitySerialize(FieldDefinition fieldDefinition)
{
return WillUnitySerialize(fieldDefinition, new TypeResolver(null));
}
public static bool WillUnitySerialize(FieldDefinition fieldDefinition, TypeResolver typeResolver)
{
if (fieldDefinition == null)
return false;
//skip static, const and NotSerialized fields before even checking the type
if (fieldDefinition.IsStatic || IsConst(fieldDefinition) || fieldDefinition.IsNotSerialized || fieldDefinition.IsInitOnly)
return false;
// The field must have correct visibility/decoration to be serialized.
if (!fieldDefinition.IsPublic &&
!ShouldHaveHadAllFieldsPublic(fieldDefinition) &&
!HasSerializeFieldAttribute(fieldDefinition) &&
!HasSerializeReferenceAttribute(fieldDefinition))
return false;
// Don't try to resolve types that come from Windows assembly,
// as serialization weaver will fail to resolve that (due to it being in platform specific SDKs)
if (ShouldNotTryToResolve(fieldDefinition.FieldType))
return false;
if (IsFixedBuffer(fieldDefinition))
return true;
// Resolving types is more complex and slower than checking their names or attributes,
// thus keep those checks below
var typeReference = typeResolver.Resolve(fieldDefinition.FieldType);
//the type of the field must be serializable in the first place.
if (typeReference.MetadataType == MetadataType.String)
return true;
if (typeReference.IsValueType)
return IsValueTypeSerializable(typeReference);
if (typeReference is ArrayType || CecilUtils.IsGenericList(typeReference))
{
if (!HasSerializeReferenceAttribute(fieldDefinition))
return IsSupportedCollection(typeReference);
}
if (!IsReferenceTypeSerializable(typeReference) && !HasSerializeReferenceAttribute(fieldDefinition))
return false;
if (IsDelegate(typeReference))
return false;
return true;
}
private static bool IsDelegate(TypeReference typeReference)
{
return typeReference.IsAssignableTo("System.Delegate");
}
public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition)
{
return ShouldFieldBePPtrRemapped(fieldDefinition, new TypeResolver(null));
}
public static bool ShouldFieldBePPtrRemapped(FieldDefinition fieldDefinition, TypeResolver typeResolver)
{
if (!WillUnitySerialize(fieldDefinition, typeResolver))
return false;
return CanTypeContainUnityEngineObjectReference(typeResolver.Resolve(fieldDefinition.FieldType));
}
private static bool CanTypeContainUnityEngineObjectReference(TypeReference typeReference)
{
if (IsUnityEngineObject(typeReference))
return true;
if (typeReference.IsEnum())
return false;
if (IsSerializablePrimitive(typeReference))
return false;
if (IsSupportedCollection(typeReference))
return CanTypeContainUnityEngineObjectReference(CecilUtils.ElementTypeOfCollection(typeReference));
var definition = typeReference.Resolve();
if (definition == null)
return false;
return HasFieldsThatCanContainUnityEngineObjectReferences(definition, new TypeResolver(typeReference as GenericInstanceType));
}
private static bool HasFieldsThatCanContainUnityEngineObjectReferences(TypeDefinition definition, TypeResolver typeResolver)
{
return AllFieldsFor(definition, typeResolver).Where(kv => kv.Value.Resolve(kv.Key.FieldType).Resolve() != definition).Any(kv => CanFieldContainUnityEngineObjectReference(definition, kv.Key, kv.Value));
}
private static IEnumerable<KeyValuePair<FieldDefinition, TypeResolver>> AllFieldsFor(TypeDefinition definition, TypeResolver typeResolver)
{
var baseType = definition.BaseType;
if (baseType != null)
{
var genericBaseInstanceType = baseType as GenericInstanceType;
if (genericBaseInstanceType != null)
typeResolver.Add(genericBaseInstanceType);
foreach (var kv in AllFieldsFor(baseType.Resolve(), typeResolver))
yield return kv;
if (genericBaseInstanceType != null)
typeResolver.Remove(genericBaseInstanceType);
}
foreach (var fieldDefinition in definition.Fields)
yield return new KeyValuePair<FieldDefinition, TypeResolver>(fieldDefinition, typeResolver);
}
private static bool CanFieldContainUnityEngineObjectReference(TypeReference typeReference, FieldDefinition t, TypeResolver typeResolver)
{
if (typeResolver.Resolve(t.FieldType) == typeReference)
return false;
if (!WillUnitySerialize(t, typeResolver))
return false;
if (UnityEngineTypePredicates.IsUnityEngineValueType(typeReference))
return false;
return true;
}
private static bool IsConst(FieldDefinition fieldDefinition)
{
return fieldDefinition.IsLiteral && !fieldDefinition.IsInitOnly;
}
public static bool HasSerializeFieldAttribute(FieldDefinition field)
{
//return FieldAttributes(field).Any(UnityEngineTypePredicates.IsSerializeFieldAttribute);
foreach (var attribute in FieldAttributes(field))
if (UnityEngineTypePredicates.IsSerializeFieldAttribute(attribute))
return true;
return false;
}
public static bool HasSerializeReferenceAttribute(FieldDefinition field)
{
foreach (var attribute in FieldAttributes(field))
if (UnityEngineTypePredicates.IsSerializeReferenceAttribute(attribute))
return true;
return false;
}
private static IEnumerable<TypeReference> FieldAttributes(FieldDefinition field)
{
return field.CustomAttributes.Select(_ => _.AttributeType);
}
public static bool ShouldNotTryToResolve(TypeReference typeReference)
{
var typeReferenceScopeName = typeReference.Scope.Name;
if (typeReferenceScopeName == "Windows")
{
return true;
}
if (typeReferenceScopeName == "mscorlib")
{
var resolved = typeReference.Resolve();
return resolved == null;
}
try
{ // This will throw an exception if typereference thinks it's referencing a .dll,
// but actually there's .winmd file in the current directory. RRW will fix this
// at a later step, so we will not try to resolve this type. This is OK, as any
// type defined in a winmd cannot be serialized.
typeReference.Resolve();
}
catch
{
return true;
}
return false;
}
private static bool IsFieldTypeSerializable(TypeReference typeReference, FieldDefinition fieldDefinition)
{
return IsTypeSerializable(typeReference) || IsSupportedCollection(typeReference) || IsFixedBuffer(fieldDefinition);
}
private static bool IsValueTypeSerializable(TypeReference typeReference)
{
if (typeReference.IsPrimitive)
return IsSerializablePrimitive(typeReference);
return UnityEngineTypePredicates.IsSerializableUnityStruct(typeReference) ||
typeReference.IsEnum() ||
ShouldImplementIDeserializable(typeReference);
}
private static bool IsReferenceTypeSerializable(TypeReference typeReference)
{
if (typeReference.MetadataType == MetadataType.String)
return IsSerializablePrimitive(typeReference);
if (IsGenericDictionary(typeReference))
return false;
if (IsUnityEngineObject(typeReference) ||
ShouldImplementIDeserializable(typeReference) ||
UnityEngineTypePredicates.IsSerializableUnityClass(typeReference))
return true;
return false;
}
private static bool IsTypeSerializable(TypeReference typeReference)
{
if (typeReference.MetadataType == MetadataType.String)
return true;
if (typeReference.IsValueType)
return IsValueTypeSerializable(typeReference);
return IsReferenceTypeSerializable(typeReference);
}
private static bool IsGenericDictionary(TypeReference typeReference)
{
var current = typeReference;
if (current != null)
{
if (CecilUtils.IsGenericDictionary(current))
return true;
}
return false;
}
public static bool IsFixedBuffer(FieldDefinition fieldDefinition)
{
return GetFixedBufferAttribute(fieldDefinition) != null;
}
public static CustomAttribute GetFixedBufferAttribute(FieldDefinition fieldDefinition)
{
if (!fieldDefinition.HasCustomAttributes)
return null;
return fieldDefinition.CustomAttributes.SingleOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.FixedBufferAttribute");
}
public static int GetFixedBufferLength(FieldDefinition fieldDefinition)
{
var fixedBufferAttribute = GetFixedBufferAttribute(fieldDefinition);
if (fixedBufferAttribute == null)
throw new ArgumentException(string.Format("Field '{0}' is not a fixed buffer field.", fieldDefinition.FullName));
var size = (Int32)fixedBufferAttribute.ConstructorArguments[1].Value;
return size;
}
public static int PrimitiveTypeSize(TypeReference type)
{
switch (type.MetadataType)
{
case MetadataType.Boolean:
case MetadataType.Byte:
case MetadataType.SByte:
return 1;
case MetadataType.Char:
case MetadataType.Int16:
case MetadataType.UInt16:
return 2;
case MetadataType.Int32:
case MetadataType.UInt32:
case MetadataType.Single:
return 4;
case MetadataType.Int64:
case MetadataType.UInt64:
case MetadataType.Double:
return 8;
default:
throw new ArgumentException(string.Format("Unsupported {0}", type.MetadataType));
}
}
private static bool IsSerializablePrimitive(TypeReference typeReference)
{
switch (typeReference.MetadataType)
{
case MetadataType.SByte:
case MetadataType.Byte:
case MetadataType.Char:
case MetadataType.Int16:
case MetadataType.UInt16:
case MetadataType.Int64:
case MetadataType.UInt64:
case MetadataType.Int32:
case MetadataType.UInt32:
case MetadataType.Single:
case MetadataType.Double:
case MetadataType.Boolean:
case MetadataType.String:
return true;
}
return false;
}
public static bool IsSupportedCollection(TypeReference typeReference)
{
if (!(typeReference is ArrayType || CecilUtils.IsGenericList(typeReference)))
return false;
// We don't support arrays like byte[,] etc
if (typeReference.IsArray && ((ArrayType)typeReference).Rank > 1)
return false;
return IsTypeSerializable(CecilUtils.ElementTypeOfCollection(typeReference));
}
private static bool ShouldHaveHadAllFieldsPublic(FieldDefinition field)
{
return UnityEngineTypePredicates.IsUnityEngineValueType(field.DeclaringType);
}
private static bool IsUnityEngineObject(TypeReference typeReference)
{
return UnityEngineTypePredicates.IsUnityEngineObject(typeReference);
}
public static bool IsNonSerialized(TypeReference typeDeclaration)
{
if (typeDeclaration == null)
return true;
if (typeDeclaration.HasGenericParameters)
return true;
if (typeDeclaration.MetadataType == MetadataType.Object)
return true;
var fullName = typeDeclaration.FullName;
if (fullName.StartsWith("System.")) //can this be done better?
return true;
if (typeDeclaration.IsArray)
return true;
if (typeDeclaration.FullName == UnityEngineTypePredicates.MonoBehaviour)
return true;
if (typeDeclaration.FullName == UnityEngineTypePredicates.ScriptableObject)
return true;
if (typeDeclaration.IsEnum())
return true;
return false;
}
public static bool ShouldImplementIDeserializable(TypeReference typeDeclaration)
{
if (typeDeclaration.FullName == "UnityEngine.ExposedReference`1")
return true;
if (IsNonSerialized(typeDeclaration))
return false;
try
{
if (UnityEngineTypePredicates.ShouldHaveHadSerializableAttribute(typeDeclaration))
return true;
var resolvedTypeDeclaration = typeDeclaration.CheckedResolve();
if (resolvedTypeDeclaration.IsValueType)
{
return resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains("System.Runtime.CompilerServices.CompilerGenerated"));
}
else
{
return (resolvedTypeDeclaration.IsSerializable && !resolvedTypeDeclaration.CustomAttributes.Any(a => a.AttributeType.FullName.Contains("System.Runtime.CompilerServices.CompilerGenerated"))) ||
resolvedTypeDeclaration.IsSubclassOf(UnityEngineTypePredicates.MonoBehaviour, UnityEngineTypePredicates.ScriptableObject);
}
}
catch (Exception)
{
return false;
}
}
}
}
+10 -4
View File
@@ -7,7 +7,7 @@ AssetStudio is a tool for exploring, extracting and exporting assets and assetbu
## Features ## Features
* Support version: * Support version:
* 2.5 - 2021.1 * 3.4 - 2022.1
* Support asset types: * Support asset types:
* **Texture2D** : convert to png, tga, jpeg, bmp * **Texture2D** : convert to png, tga, jpeg, bmp
* **Sprite** : crop Texture2D to png, tga, jpeg, bmp * **Sprite** : crop Texture2D to png, tga, jpeg, bmp
@@ -23,7 +23,13 @@ AssetStudio is a tool for exploring, extracting and exporting assets and assetbu
## Requirements ## Requirements
- [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472) - AssetStudio.net472
- [.NET Framework 4.7.2](https://dotnet.microsoft.com/download/dotnet-framework/net472)
- AssetStudio.net5
- [.NET Desktop Runtime 5.0](https://dotnet.microsoft.com/download/dotnet/5.0)
- AssetStudio.net6
- [.NET Desktop Runtime 6.0](https://dotnet.microsoft.com/download/dotnet/6.0)
## Usage ## Usage
@@ -63,8 +69,8 @@ First, use my another program [Il2CppDumper](https://github.com/Perfare/Il2CppDu
## Build ## Build
* Visual Studio 2019 or newer * Visual Studio 2022 or newer
* **AssetStudioFBXNative** uses FBX SDK 2020.0.1 VS2017, before building, you need to install the FBX SDK and modify the project file, change include directory and library directory to point to the FBX SDK directory * **AssetStudioFBXNative** uses [FBX SDK 2020.2.1](https://www.autodesk.com/developer-network/platform-technologies/fbx-sdk-2020-2-1), before building, you need to install the FBX SDK and modify the project file, change include directory and library directory to point to the FBX SDK directory
## Open source libraries used ## Open source libraries used
@@ -67,26 +67,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset> <PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
@@ -1,19 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Texture2DDecoder")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Texture2DDecoder")]
[assembly: AssemblyCopyright("Copyright © Perfare 2020; Copyright © hozuki 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("2afce830-b463-49b3-a026-877e5eafc0a4")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,53 +1,17 @@
<?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>
<ProjectGuid>{2AFCE830-B463-49B3-A026-877E5EAFC0A4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Texture2DDecoder</RootNamespace>
<AssemblyName>Texture2DDecoderWrapper</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <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> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="T2DDll.cs" />
<Compile Include="TextureDecoder.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TextureDecoder.PInvoke.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj">
<Project>{40c796b5-88ce-4adc-acd6-2f4862b7f136}</Project>
<Name>AssetStudio.PInvoke</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>