Compare commits

...

49 Commits

Author SHA1 Message Date
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
Perfare ab98585b6a Fix Shader reading. Close #720 2021-05-29 05:11:05 +08:00
Perfare 075d53a455 small improvement 2021-05-28 23:19:31 +08:00
Perfare 432116d834 Improve SerializedFile reading. 2021-05-28 22:23:07 +08:00
Perfare caa45216ef fix compilation error 2021-05-28 22:16:50 +08:00
96 changed files with 3411 additions and 8822 deletions
+9 -48
View File
@@ -1,51 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{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>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright>
</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
# Visual Studio Version 16
VisualStudioVersion = 16.0.29920.165
VisualStudioVersion = 16.0.31410.357
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
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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}"
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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioFBXWrapper", "AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj", "{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}"
ProjectSection(ProjectDependencies) = postProject
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027} = {11EA25A3-ED68-40EE-A9D0-7FDE3B583027}
EndProjectSection
EndProject
Project("{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
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
{29356642-C46E-4144-83D8-22DC09D0D7FD} = {29356642-C46E-4144-83D8-22DC09D0D7FD}
EndProjectSection
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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -35,42 +35,78 @@ Global
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x64.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.ActiveCfg = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Debug|x86.Build.0 = Debug|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|Any CPU.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x64.Build.0 = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.ActiveCfg = Release|Any CPU
{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}.Release|x86.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x64.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.ActiveCfg = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Debug|x86.Build.0 = Debug|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|Any CPU.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x64.Build.0 = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.ActiveCfg = Release|Any CPU
{80AEC261-21EE-4E4F-A93B-7A744DC84888}.Release|x86.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x64.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.ActiveCfg = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Debug|x86.Build.0 = Debug|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|Any CPU.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x64.Build.0 = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.ActiveCfg = Release|Any CPU
{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}.Release|x86.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|Any CPU.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x64.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.ActiveCfg = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Debug|x86.Build.0 = Debug|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|Any CPU.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x64.Build.0 = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.ActiveCfg = Release|Any CPU
{422FEC21-EF60-4F29-AA56-95DFDA23C913}.Release|x86.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x64.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.ActiveCfg = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Debug|x86.Build.0 = Debug|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|Any CPU.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x64.Build.0 = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.ActiveCfg = Release|Any CPU
{0B2BE613-3049-4021-85D1-21C325F729F4}.Release|x86.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x64.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.ActiveCfg = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Debug|x86.Build.0 = Debug|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|Any CPU.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x64.Build.0 = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.ActiveCfg = Release|Any CPU
{E301AFEA-84E7-4BCE-8D65-A2576D8D105B}.Release|x86.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x64.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.ActiveCfg = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Debug|x86.Build.0 = Debug|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|Any CPU.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x64.Build.0 = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.ActiveCfg = Release|Any CPU
{29EAD018-1C67-497A-AB8E-727D595AD756}.Release|x86.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x64.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.ActiveCfg = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Debug|x86.Build.0 = Debug|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|Any CPU.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x64.Build.0 = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.ActiveCfg = Release|Any CPU
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}.Release|x86.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x64.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.ActiveCfg = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Debug|x86.Build.0 = Debug|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|Any CPU.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x64.Build.0 = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.ActiveCfg = Release|Any CPU
{6438FEC1-56B0-488C-A5E2-FBDB23E9574B}.Release|x86.Build.0 = Release|Any CPU
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.ActiveCfg = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|Any CPU.Build.0 = Debug|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Debug|x64.ActiveCfg = Debug|x64
@@ -83,18 +119,6 @@ Global
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x64.Build.0 = Release|x64
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.ActiveCfg = Release|Win32
{11EA25A3-ED68-40EE-A9D0-7FDE3B583027}.Release|x86.Build.0 = Release|Win32
{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.Build.0 = Debug|Win32
{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|x86.ActiveCfg = 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
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F8734F96-97B6-40CA-B791-6D5467F2F713}
SolutionGuid = {3C074481-9CDD-4780-B9F6-57BBC5092EA2}
EndGlobalSection
EndGlobal
+16 -143
View File
@@ -1,147 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7662F8C2-7BFD-442E-A948-A43B4F7EB06E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio</RootNamespace>
<AssemblyName>AssetStudio</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<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 Condition=" '$(TargetFramework)' != 'net472' ">
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
</ItemGroup>
<ItemGroup>
<Compile Include="7zip\Common\CommandLineParser.cs" />
<Compile Include="7zip\Common\CRC.cs" />
<Compile Include="7zip\Common\InBuffer.cs" />
<Compile Include="7zip\Common\OutBuffer.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaBase.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaDecoder.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaEncoder.cs" />
<Compile Include="7zip\Compress\LZ\IMatchFinder.cs" />
<Compile Include="7zip\Compress\LZ\LzBinTree.cs" />
<Compile Include="7zip\Compress\LZ\LzInWindow.cs" />
<Compile Include="7zip\Compress\LZ\LzOutWindow.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoder.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
<Compile Include="7zip\ICoder.cs" />
<Compile Include="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="SerializedFileHeader.cs" />
<Compile Include="SerializedType.cs" />
<Compile Include="SevenZipHelper.cs" />
<Compile Include="StreamFile.cs" />
<Compile Include="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" />
<Compile Include="WebFile.cs" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="System.Memory" Version="4.5.4" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
</Project>
+70 -41
View File
@@ -9,7 +9,9 @@ namespace AssetStudio
{
public class AssetsManager
{
public string SpecifyUnityVersion;
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
@@ -19,7 +21,7 @@ namespace AssetStudio
public void LoadFiles(params string[] files)
{
var path = Path.GetDirectoryName(files[0]);
var path = Path.GetDirectoryName(Path.GetFullPath(files[0]));
MergeSplitAssets(path);
var toReadFile = ProcessingSplitFiles(files.ToList());
Load(toReadFile);
@@ -59,42 +61,54 @@ namespace AssetStudio
private void LoadFile(string fullName)
{
switch (CheckFileType(fullName, out var reader))
var reader = new FileReader(fullName);
LoadFile(reader);
}
private void LoadFile(FileReader reader)
{
switch (reader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFile(fullName, reader);
LoadAssetsFile(reader);
break;
case FileType.BundleFile:
LoadBundleFile(fullName, reader);
LoadBundleFile(reader);
break;
case FileType.WebFile:
LoadWebFile(fullName, reader);
LoadWebFile(reader);
break;
case FileType.GZipFile:
LoadFile(DecompressGZip(reader));
break;
case FileType.BrotliFile:
LoadFile(DecompressBrotli(reader));
break;
}
}
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
private void LoadAssetsFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
if (!assetsFileListHash.Contains(fileName))
if (!assetsFileListHash.Contains(reader.FileName))
{
Logger.Info($"Loading {fileName}");
Logger.Info($"Loading {reader.FileName}");
try
{
var assetsFile = new SerializedFile(this, fullName, reader);
var assetsFile = new SerializedFile(reader, this);
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(fullName), sharedFile.fileName);
var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName))
{
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
@@ -111,7 +125,7 @@ namespace AssetStudio
}
catch (Exception e)
{
Logger.Error($"Error while reading assets file {fileName}", e);
Logger.Error($"Error while reading assets file {reader.FileName}", e);
reader.Dispose();
}
}
@@ -121,44 +135,43 @@ namespace AssetStudio
}
}
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
{
var fileName = Path.GetFileName(fullName);
if (!assetsFileListHash.Contains(fileName))
if (!assetsFileListHash.Contains(reader.FileName))
{
try
{
var assetsFile = new SerializedFile(this, fullName, reader);
var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath;
if (assetsFile.header.m_Version < 7)
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.kUnknown_7)
{
assetsFile.SetVersion(unityVersion);
}
CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName);
}
catch (Exception e)
{
Logger.Error($"Error while reading assets file {fileName} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(fileName, reader);
Logger.Error($"Error while reading assets file {reader.FileName} from {Path.GetFileName(originalPath)}", e);
resourceFileReaders.Add(reader.FileName, reader);
}
}
}
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
private void LoadBundleFile(FileReader reader, string originalPath = null)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
Logger.Info("Loading " + reader.FileName);
try
{
var bundleFile = new BundleFile(reader, fullName);
var bundleFile = new BundleFile(reader);
foreach (var file in bundleFile.fileList)
{
var subReader = new EndianBinaryReader(file.stream);
if (SerializedFile.IsSerializedFile(subReader))
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile)
{
var dummyPath = Path.GetDirectoryName(fullName) + Path.DirectorySeparatorChar + file.fileName;
LoadAssetsFromMemory(dummyPath, subReader, parentPath ?? fullName, bundleFile.m_Header.unityRevision);
LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
}
else
{
@@ -168,10 +181,10 @@ namespace AssetStudio
}
catch (Exception e)
{
var str = $"Error while reading bundle file {fileName}";
if (parentPath != null)
var str = $"Error while reading bundle file {reader.FileName}";
if (originalPath != null)
{
str += $" from {Path.GetFileName(parentPath)}";
str += $" from {Path.GetFileName(originalPath)}";
}
Logger.Error(str, e);
}
@@ -181,36 +194,36 @@ namespace AssetStudio
}
}
private void LoadWebFile(string fullName, EndianBinaryReader reader)
private void LoadWebFile(FileReader reader)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
Logger.Info("Loading " + reader.FileName);
try
{
var webFile = new WebFile(reader);
foreach (var file in webFile.fileList)
{
var dummyPath = Path.Combine(Path.GetDirectoryName(fullName), file.fileName);
switch (CheckFileType(file.stream, out var fileReader))
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream);
switch (subReader.FileType)
{
case FileType.AssetsFile:
LoadAssetsFromMemory(dummyPath, fileReader, fullName);
LoadAssetsFromMemory(subReader, reader.FullPath);
break;
case FileType.BundleFile:
LoadBundleFile(dummyPath, fileReader, fullName);
LoadBundleFile(subReader, reader.FullPath);
break;
case FileType.WebFile:
LoadWebFile(dummyPath, fileReader);
LoadWebFile(subReader);
break;
case FileType.ResourceFile:
resourceFileReaders[file.fileName] = fileReader; //TODO
resourceFileReaders[file.fileName] = subReader; //TODO
break;
}
}
}
catch (Exception e)
{
Logger.Error($"Error while reading web file {fileName}", e);
Logger.Error($"Error while reading web file {reader.FileName}", e);
}
finally
{
@@ -218,6 +231,18 @@ namespace AssetStudio
}
}
public void CheckStrippedVersion(SerializedFile assetsFile)
{
if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
{
throw new Exception("The Unity version has been stripped, please set the version in the options");
}
if (!string.IsNullOrEmpty(SpecifyUnityVersion))
{
assetsFile.SetVersion(SpecifyUnityVersion);
}
}
public void Clear()
{
foreach (var assetsFile in assetsFileList)
@@ -399,6 +424,10 @@ namespace AssetStudio
}
else if (obj is SpriteAtlas m_SpriteAtlas)
{
if (m_SpriteAtlas.m_IsVariant)
{
continue;
}
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
{
if (m_PackedSprite.TryGet(out var m_Sprite))
+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;
}
}
+30 -21
View File
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using K4os.Compression.LZ4;
using System.IO;
using System.Linq;
using Lz4;
namespace AssetStudio
{
@@ -41,7 +39,7 @@ namespace AssetStudio
public StreamFile[] fileList;
public BundleFile(EndianBinaryReader reader, string path)
public BundleFile(FileReader reader)
{
m_Header = new Header();
m_Header.signature = reader.ReadStringToNull();
@@ -59,19 +57,19 @@ namespace AssetStudio
goto case "UnityFS";
}
ReadHeaderAndBlocksInfo(reader);
using (var blocksStream = CreateBlocksStream(path))
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocksAndDirectory(reader, blocksStream);
ReadFiles(blocksStream, path);
ReadFiles(blocksStream, reader.FullPath);
}
break;
case "UnityFS":
ReadHeader(reader);
ReadBlocksInfoAndDirectory(reader);
using (var blocksStream = CreateBlocksStream(path))
using (var blocksStream = CreateBlocksStream(reader.FullPath))
{
ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, path);
ReadFiles(blocksStream, reader.FullPath);
}
break;
}
@@ -120,7 +118,7 @@ namespace AssetStudio
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
if (uncompressedSizeSum >= int.MaxValue)
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(Path.GetFileName(path), uncompressedSizeSum);
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, uncompressedSizeSum);
assetsDataStream = memoryMappedFile.CreateViewStream();*/
blocksStream = new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose);
}
@@ -175,7 +173,7 @@ namespace AssetStudio
file.fileName = Path.GetFileName(node.path);
if (node.size >= int.MaxValue)
{
/*var memoryMappedFile = MemoryMappedFile.CreateNew(file.fileName, entryinfo_size);
/*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size);
file.stream = memoryMappedFile.CreateViewStream();*/
var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar;
Directory.CreateDirectory(extractPath);
@@ -221,30 +219,33 @@ namespace AssetStudio
{
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
}
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
MemoryStream blocksInfoUncompresseddStream;
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
{
default: //None
{
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
break;
}
case 1: //LZMA
{
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
}
blocksInfoUncompresseddStream.Position = 0;
blocksInfoCompressedStream.Close();
break;
}
case 2: //LZ4
case 3: //LZ4HC
{
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
var uncompressedBytes = new byte[uncompressedSize];
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
if (numWrite != uncompressedSize)
{
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
break;
@@ -299,11 +300,19 @@ namespace AssetStudio
case 2: //LZ4
case 3: //LZ4HC
{
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
var compressedSize = (int)blockInfo.compressedSize;
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
reader.Read(compressedBytes, 0, compressedSize);
var uncompressedSize = (int)blockInfo.uncompressedSize;
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
if (numWrite != uncompressedSize)
{
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;
}
}
+48
View File
@@ -637,6 +637,50 @@ namespace AssetStudio
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
@@ -754,6 +798,8 @@ namespace AssetStudio
public byte customType;
public byte isPPtrCurve;
public GenericBinding() { }
public GenericBinding(ObjectReader reader)
{
var version = reader.version;
@@ -779,6 +825,8 @@ namespace AssetStudio
public GenericBinding[] genericBindings;
public PPtr<Object>[] pptrCurveMapping;
public AnimationClipBindingConstant() { }
public AnimationClipBindingConstant(ObjectReader reader)
{
int numBindings = reader.ReadInt32();
+4
View File
@@ -31,6 +31,10 @@ namespace AssetStudio
if (version[0] >= 5) //5.0 and up
{
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();
}
+5 -5
View File
@@ -27,8 +27,8 @@ namespace AssetStudio
public AudioCompressionFormat m_CompressionFormat;
public string m_Source;
public ulong m_Offset;
public long m_Size;
public long m_Offset; //ulong
public long m_Size; //ulong
public ResourceReader m_AudioData;
public AudioClip(ObjectReader reader) : base(reader)
@@ -74,7 +74,7 @@ namespace AssetStudio
//StreamedResource m_Resource
m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadUInt64();
m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64();
m_CompressionFormat = (AudioCompressionFormat)reader.ReadInt32();
}
@@ -82,11 +82,11 @@ namespace AssetStudio
ResourceReader resourceReader;
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
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, (int)m_Size);
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, m_Size);
}
m_AudioData = resourceReader;
}
+2 -2
View File
@@ -681,7 +681,7 @@ namespace AssetStudio
{
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();
}
}
@@ -729,7 +729,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++)
{
+11 -23
View File
@@ -1,7 +1,4 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
namespace AssetStudio
{
@@ -36,47 +33,38 @@ namespace AssetStudio
}
}
protected bool HasStructMember(string name)
{
return serializedType?.m_Nodes != null && serializedType.m_Nodes.Any(x => x.m_Name == name);
}
public string Dump()
{
if (serializedType?.m_Nodes != null)
if (serializedType?.m_Type != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, serializedType.m_Nodes, reader);
return sb.ToString();
return TypeTreeHelper.ReadTypeString(serializedType.m_Type, reader);
}
return null;
}
public string Dump(List<TypeTreeNode> m_Nodes)
public string Dump(TypeTree m_Type)
{
if (m_Nodes != null)
if (m_Type != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, m_Nodes, reader);
return sb.ToString();
return TypeTreeHelper.ReadTypeString(m_Type, reader);
}
return null;
}
public OrderedDictionary ToType()
{
if (serializedType?.m_Nodes != null)
if (serializedType?.m_Type != null)
{
return TypeTreeHelper.ReadType(serializedType.m_Nodes, reader);
return TypeTreeHelper.ReadType(serializedType.m_Type, reader);
}
return null;
}
public OrderedDictionary ToType(List<TypeTreeNode> m_Nodes)
public OrderedDictionary ToType(TypeTree m_Type)
{
if (m_Nodes != null)
if (m_Type != null)
{
return TypeTreeHelper.ReadType(m_Nodes, reader);
return TypeTreeHelper.ReadType(m_Type, reader);
}
return null;
}
+1 -1
View File
@@ -13,7 +13,7 @@ namespace AssetStudio
public PPtr(ObjectReader reader)
{
m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < 14 ? reader.ReadInt32() : reader.ReadInt64();
m_PathID = reader.m_Version < SerializedFileFormatVersion.kUnknown_14 ? reader.ReadInt32() : reader.ReadInt64();
assetsFile = reader.assetsFile;
}
+183 -41
View File
@@ -394,6 +394,7 @@ namespace AssetStudio
public VectorParameter[] m_VectorParams;
public StructParameter[] m_StructParams;
public int m_Size;
public bool m_IsPartialCB;
public ConstantBuffer(ObjectReader reader)
{
@@ -424,6 +425,15 @@ namespace AssetStudio
}
}
m_Size = reader.ReadInt32();
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{
m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream();
}
}
}
@@ -477,13 +487,8 @@ namespace AssetStudio
kShaderGpuProgramRayTracing = 31,
};
public class SerializedSubProgram
public class SerializedProgramParameters
{
public uint m_BlobIndex;
public ParserBindChannels m_Channels;
public ushort[] m_KeywordIndices;
public sbyte m_ShaderHardwareTier;
public ShaderGpuProgramType m_GpuProgramType;
public VectorParameter[] m_VectorParams;
public MatrixParameter[] m_MatrixParams;
public TextureParameter[] m_TextureParams;
@@ -493,33 +498,8 @@ namespace AssetStudio
public UAVParameter[] m_UAVParams;
public SamplerParameter[] m_Samplers;
public SerializedSubProgram(ObjectReader reader)
public SerializedProgramParameters(ObjectReader reader)
{
var version = reader.version;
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
if (version[0] >= 2019) //2019 and up
{
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
var m_LocalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
}
else
{
m_KeywordIndices = reader.ReadUInt16Array();
if (version[0] >= 2017) //2017 and up
{
reader.AlignStream();
}
}
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream();
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
@@ -569,15 +549,128 @@ namespace AssetStudio
m_UAVParams[i] = new UAVParameter(reader);
}
if (version[0] >= 2017) //2017 and up
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
{
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
m_Samplers[i] = new SamplerParameter(reader);
}
}
}
public class SerializedSubProgram
{
public uint m_BlobIndex;
public ParserBindChannels m_Channels;
public ushort[] m_KeywordIndices;
public sbyte m_ShaderHardwareTier;
public ShaderGpuProgramType m_GpuProgramType;
public SerializedProgramParameters m_Parameters;
public VectorParameter[] m_VectorParams;
public MatrixParameter[] m_MatrixParams;
public TextureParameter[] m_TextureParams;
public BufferBinding[] m_BufferParams;
public ConstantBuffer[] m_ConstantBuffers;
public BufferBinding[] m_ConstantBufferBindings;
public UAVParameter[] m_UAVParams;
public SamplerParameter[] m_Samplers;
public SerializedSubProgram(ObjectReader reader)
{
var version = reader.version;
m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader);
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
{
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
var m_LocalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream();
}
else
{
m_KeywordIndices = reader.ReadUInt16Array();
if (version[0] >= 2017) //2017 and up
{
m_Samplers[i] = new SamplerParameter(reader);
reader.AlignStream();
}
}
m_ShaderHardwareTier = reader.ReadSByte();
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream();
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{
m_Parameters = new SerializedProgramParameters(reader);
}
else
{
int numVectorParams = reader.ReadInt32();
m_VectorParams = new VectorParameter[numVectorParams];
for (int i = 0; i < numVectorParams; i++)
{
m_VectorParams[i] = new VectorParameter(reader);
}
int numMatrixParams = reader.ReadInt32();
m_MatrixParams = new MatrixParameter[numMatrixParams];
for (int i = 0; i < numMatrixParams; i++)
{
m_MatrixParams[i] = new MatrixParameter(reader);
}
int numTextureParams = reader.ReadInt32();
m_TextureParams = new TextureParameter[numTextureParams];
for (int i = 0; i < numTextureParams; i++)
{
m_TextureParams[i] = new TextureParameter(reader);
}
int numBufferParams = reader.ReadInt32();
m_BufferParams = new BufferBinding[numBufferParams];
for (int i = 0; i < numBufferParams; i++)
{
m_BufferParams[i] = new BufferBinding(reader);
}
int numConstantBuffers = reader.ReadInt32();
m_ConstantBuffers = new ConstantBuffer[numConstantBuffers];
for (int i = 0; i < numConstantBuffers; i++)
{
m_ConstantBuffers[i] = new ConstantBuffer(reader);
}
int numConstantBufferBindings = reader.ReadInt32();
m_ConstantBufferBindings = new BufferBinding[numConstantBufferBindings];
for (int i = 0; i < numConstantBufferBindings; i++)
{
m_ConstantBufferBindings[i] = new BufferBinding(reader);
}
int numUAVParams = reader.ReadInt32();
m_UAVParams = new UAVParameter[numUAVParams];
for (int i = 0; i < numUAVParams; i++)
{
m_UAVParams[i] = new UAVParameter(reader);
}
if (version[0] >= 2017) //2017 and up
{
int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers];
for (int i = 0; i < numSamplers; i++)
{
m_Samplers[i] = new SamplerParameter(reader);
}
}
}
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{
if (version[0] >= 2021) //2021.1 and up
@@ -595,15 +688,26 @@ namespace AssetStudio
public class SerializedProgram
{
public SerializedSubProgram[] m_SubPrograms;
public SerializedProgramParameters m_CommonParameters;
public SerializedProgram(ObjectReader reader)
{
var version = reader.version;
int numSubPrograms = reader.ReadInt32();
m_SubPrograms = new SerializedSubProgram[numSubPrograms];
for (int i = 0; i < numSubPrograms; i++)
{
m_SubPrograms[i] = new SerializedSubProgram(reader);
}
if ((version[0] == 2020 && version[1] > 3) ||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
(version[0] == 2021 && version[1] > 1) ||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
{
m_CommonParameters = new SerializedProgramParameters(reader);
}
}
}
@@ -635,6 +739,7 @@ namespace AssetStudio
public string m_Name;
public string m_TextureName;
public SerializedTagMap m_Tags;
public ushort[] m_SerializedKeywordStateMask;
public SerializedPass(ObjectReader reader)
{
@@ -651,10 +756,13 @@ namespace AssetStudio
reader.AlignStream();
m_Platforms = reader.ReadUInt8Array();
reader.AlignStream();
m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
m_GlobalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
{
m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
m_GlobalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
int numIndices = reader.ReadInt32();
@@ -686,6 +794,11 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader);
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream();
}
}
}
@@ -752,6 +865,8 @@ namespace AssetStudio
{
public SerializedProperties m_PropInfo;
public SerializedSubShader[] m_SubShaders;
public string[] m_KeywordNames;
public byte[] m_KeywordFlags;
public string m_Name;
public string m_CustomEditorName;
public string m_FallbackName;
@@ -772,6 +887,13 @@ namespace AssetStudio
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_CustomEditorName = reader.ReadAlignedString();
m_FallbackName = reader.ReadAlignedString();
@@ -861,6 +983,26 @@ namespace AssetStudio
decompressedLengths = reader.ReadUInt32Array();
}
compressedBlob = reader.ReadUInt8Array();
reader.AlignStream();
var m_DependenciesCount = reader.ReadInt32();
for (int i = 0; i < m_DependenciesCount; i++)
{
new PPtr<Shader>(reader);
}
if (version[0] >= 2018)
{
var m_NonModifiableTexturesCount = reader.ReadInt32();
for (int i = 0; i < m_NonModifiableTexturesCount; i++)
{
var first = reader.ReadAlignedString();
new PPtr<Texture>(reader);
}
}
var m_ShaderIsBaked = reader.ReadBoolean();
reader.AlignStream();
}
else
{
+1 -1
View File
@@ -197,7 +197,7 @@ namespace AssetStudio
public Vector2 m_Offset;
public Vector4 m_Border;
public float m_PixelsToUnits;
public Vector2 m_Pivot;
public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
public uint m_Extrude;
public bool m_IsPolygon;
public KeyValuePair<Guid, long> m_RenderDataKey;
+4 -2
View File
@@ -46,6 +46,7 @@ namespace AssetStudio
{
public PPtr<Sprite>[] m_PackedSprites;
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
public bool m_IsVariant;
public SpriteAtlas(ObjectReader reader) : base(reader)
{
@@ -67,8 +68,9 @@ namespace AssetStudio
var value = new SpriteAtlasData(reader);
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
}
//string m_Tag
//bool m_IsVariant
var m_Tag = reader.ReadAlignedString();
m_IsVariant = reader.ReadBoolean();
reader.AlignStream();
}
}
}
+3 -3
View File
@@ -4,7 +4,7 @@ namespace AssetStudio
{
public class StreamingInfo
{
public ulong offset;
public long offset; //ulong
public uint size;
public string path;
@@ -14,7 +14,7 @@ namespace AssetStudio
if (version[0] >= 2020) //2020.1 and up
{
offset = reader.ReadUInt64();
offset = reader.ReadInt64();
}
else
{
@@ -134,7 +134,7 @@ namespace AssetStudio
ResourceReader resourceReader;
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
{
+6 -6
View File
@@ -5,14 +5,14 @@ namespace AssetStudio
public class StreamedResource
{
public string m_Source;
public ulong m_Offset;
public ulong m_Size;
public long m_Offset; //ulong
public long m_Size; //ulong
public StreamedResource(BinaryReader reader)
{
m_Source = reader.ReadAlignedString();
m_Offset = reader.ReadUInt64();
m_Size = reader.ReadUInt64();
m_Offset = reader.ReadInt64();
m_Size = reader.ReadInt64();
}
}
@@ -60,11 +60,11 @@ namespace AssetStudio
ResourceReader resourceReader;
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
{
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;
}
+32 -42
View File
@@ -1,23 +1,19 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Buffers.Binary;
using System.IO;
namespace AssetStudio
{
public enum EndianType
{
LittleEndian,
BigEndian
}
public class EndianBinaryReader : BinaryReader
{
public EndianType endian;
private readonly byte[] buffer;
public EndianType Endian;
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
{
this.endian = endian;
Endian = endian;
buffer = new byte[8];
}
public long Position
@@ -28,88 +24,82 @@ namespace AssetStudio
public override short ReadInt16()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToInt16(buff, 0);
Read(buffer, 0, 2);
return BinaryPrimitives.ReadInt16BigEndian(buffer);
}
return base.ReadInt16();
}
public override int ReadInt32()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToInt32(buff, 0);
Read(buffer, 0, 4);
return BinaryPrimitives.ReadInt32BigEndian(buffer);
}
return base.ReadInt32();
}
public override long ReadInt64()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToInt64(buff, 0);
Read(buffer, 0, 8);
return BinaryPrimitives.ReadInt64BigEndian(buffer);
}
return base.ReadInt64();
}
public override ushort ReadUInt16()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToUInt16(buff, 0);
Read(buffer, 0, 2);
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
}
return base.ReadUInt16();
}
public override uint ReadUInt32()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToUInt32(buff, 0);
Read(buffer, 0, 4);
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
}
return base.ReadUInt32();
}
public override ulong ReadUInt64()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
Read(buffer, 0, 8);
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
}
return base.ReadUInt64();
}
public override float ReadSingle()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToSingle(buff, 0);
Read(buffer, 0, 4);
Array.Reverse(buffer, 0, 4);
return BitConverter.ToSingle(buffer, 0);
}
return base.ReadSingle();
}
public override double ReadDouble()
{
if (endian == EndianType.BigEndian)
if (Endian == EndianType.BigEndian)
{
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
Read(buffer, 0, 8);
Array.Reverse(buffer);
return BitConverter.ToDouble(buffer, 0);
}
return base.ReadDouble();
}
+14
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
}
}
+100
View File
@@ -0,0 +1,100 @@
using System.IO;
using System.Linq;
namespace AssetStudio
{
public class FileReader : EndianBinaryReader
{
public string FullPath;
public string FileName;
public FileType FileType;
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
public FileReader(string path, Stream stream) : base(stream, EndianType.BigEndian)
{
FullPath = Path.GetFullPath(path);
FileName = Path.GetFileName(path);
FileType = CheckFileType();
}
private FileType CheckFileType()
{
var signature = this.ReadStringToNull(20);
Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
return FileType.GZipFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (brotliMagic.SequenceEqual(magic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile())
{
return FileType.AssetsFile;
}
else
{
return FileType.ResourceFile;
}
}
}
}
private bool IsSerializedFile()
{
var fileSize = BaseStream.Length;
if (fileSize < 20)
{
return false;
}
var m_MetadataSize = ReadUInt32();
long m_FileSize = ReadUInt32();
var m_Version = ReadUInt32();
long m_DataOffset = ReadUInt32();
var m_Endianess = ReadByte();
var m_Reserved = ReadBytes(3);
if (m_Version >= 22)
{
if (fileSize < 48)
{
Position = 0;
return false;
}
m_MetadataSize = ReadUInt32();
m_FileSize = ReadInt64();
m_DataOffset = ReadInt64();
}
Position = 0;
if (m_FileSize != fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{
return false;
}
return true;
}
}
}
+18
View File
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile,
ResourceFile,
GZipFile,
BrotliFile
}
}
+2 -1
View File
@@ -132,6 +132,7 @@ namespace AssetStudio
public class ImportedMesh
{
public string Path { get; set; }
public List<ImportedVertex> VertexList { get; set; }
public List<ImportedSubmesh> SubmeshList { get; set; }
public List<ImportedBone> BoneList { get; set; }
public bool hasNormal { get; set; }
@@ -142,9 +143,9 @@ namespace AssetStudio
public class ImportedSubmesh
{
public List<ImportedVertex> VertexList { get; set; }
public List<ImportedFace> FaceList { get; set; }
public string Material { get; set; }
public int BaseVertex { get; set; }
}
public class ImportedVertex
+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.Compression;
using System.Linq;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile,
ResourceFile
}
public static class ImportHelper
{
public static void MergeSplitAssets(string path, bool allDirectories = false)
@@ -57,55 +51,31 @@ namespace AssetStudio
return selectFile.Distinct().ToArray();
}
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
public static FileReader DecompressGZip(FileReader reader)
{
reader = new EndianBinaryReader(stream);
return CheckFileType(reader);
}
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(File.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)
using (reader)
{
case "UnityWeb":
case "UnityRaw":
case "UnityArchive":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = reader.ReadBytes(2);
reader.Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
reader.Position = 0x20;
magic = reader.ReadBytes(6);
reader.Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
if (SerializedFile.IsSerializedFile(reader))
{
return FileType.AssetsFile;
}
else
{
return FileType.ResourceFile;
}
}
var stream = new MemoryStream();
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
{
gs.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
public static FileReader DecompressBrotli(FileReader reader)
{
using (reader)
{
var stream = new MemoryStream();
using (var brotliStream = new BrotliInputStream(reader.BaseStream))
{
brotliStream.CopyTo(stream);
}
stream.Position = 0;
return new FileReader(reader.FullPath, stream);
}
}
}
-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.Runtime.InteropServices;
namespace System
namespace AssetStudio
{
/// <summary>
/// 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>
/// Helper class for Half conversions and some low level operations.
+2
View File
@@ -11,6 +11,8 @@ namespace AssetStudio
public uint byteSize;
public int typeID;
public int classID;
public ushort isDestroyed;
public byte stripped;
public long m_PathID;
public SerializedType serializedType;
+2 -2
View File
@@ -15,12 +15,12 @@ namespace AssetStudio
public ClassIDType type;
public SerializedType serializedType;
public BuildTarget platform;
public uint m_Version;
public SerializedFileFormatVersion m_Version;
public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType;
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.endian)
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
{
this.assetsFile = assetsFile;
m_PathID = objectInfo.m_PathID;
-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 SerializedFile assetsFile;
private long offset;
private int size;
private long size;
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;
this.path = path;
this.assetsFile = assetsFile;
this.offset = (long)offset;
this.offset = offset;
this.size = size;
}
public ResourceReader(BinaryReader reader, long offset, int size)
public ResourceReader(BinaryReader reader, long offset, long size)
{
this.reader = reader;
this.offset = offset;
this.size = size;
}
public byte[] GetData()
private BinaryReader GetReader()
{
if (needSearch)
{
var resourceFileName = Path.GetFileName(path);
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
{
needSearch = false;
reader.BaseStream.Position = offset;
return reader.ReadBytes(size);
return reader;
}
var assetsFileDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = assetsFileDirectory + Path.DirectorySeparatorChar + resourceFileName;
var resourceFilePath = Path.Combine(assetsFileDirectory, resourceFileName);
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(assetsFileDirectory, resourceFileName, SearchOption.AllDirectories);
@@ -53,18 +51,41 @@ namespace AssetStudio
}
if (File.Exists(resourceFilePath))
{
reader = new BinaryReader(File.OpenRead(resourceFilePath));
needSearch = false;
reader = new BinaryReader(File.OpenRead(resourceFilePath));
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
reader.BaseStream.Position = offset;
return reader.ReadBytes(size);
return reader;
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
else
{
return reader;
}
}
reader.BaseStream.Position = offset;
return reader.ReadBytes(size);
public byte[] GetData()
{
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);
}
}
}
}
+94 -112
View File
@@ -9,7 +9,7 @@ namespace AssetStudio
public class SerializedFile
{
public AssetsManager assetsManager;
public EndianBinaryReader reader;
public FileReader reader;
public string fullName;
public string originalPath;
public string fileName;
@@ -19,43 +19,45 @@ namespace AssetStudio
public Dictionary<long, Object> ObjectsDic;
public SerializedFileHeader header;
private EndianType m_FileEndianess;
private byte m_FileEndianess;
public string unityVersion = "2.5.0f5";
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
private bool m_EnableTypeTree = true;
public List<SerializedType> m_Types;
public List<SerializedType> m_RefTypes;
public int bigIDEnabled = 0;
public List<ObjectInfo> m_Objects;
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
public List<FileIdentifier> m_Externals;
public List<SerializedType> m_RefTypes;
public string userInformation;
public SerializedFile(AssetsManager assetsManager, string fullName, EndianBinaryReader reader)
public SerializedFile(FileReader reader, AssetsManager assetsManager)
{
this.assetsManager = assetsManager;
this.reader = reader;
this.fullName = fullName;
fileName = Path.GetFileName(fullName);
fullName = reader.FullPath;
fileName = reader.FileName;
//ReadHeader
// ReadHeader
header = new SerializedFileHeader();
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadUInt32();
header.m_Version = reader.ReadUInt32();
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
header.m_DataOffset = reader.ReadUInt32();
if (header.m_Version >= 9)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_9)
{
header.m_Endianess = reader.ReadByte();
header.m_Reserved = reader.ReadBytes(3);
m_FileEndianess = (EndianType)header.m_Endianess;
m_FileEndianess = header.m_Endianess;
}
else
{
reader.Position = header.m_FileSize - header.m_MetadataSize;
m_FileEndianess = (EndianType)reader.ReadByte();
m_FileEndianess = reader.ReadByte();
}
if (header.m_Version >= 22)
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
{
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadInt64();
@@ -63,17 +65,17 @@ namespace AssetStudio
reader.ReadInt64(); // unknown
}
//ReadMetadata
if (m_FileEndianess == EndianType.LittleEndian)
// ReadMetadata
if (m_FileEndianess == 0)
{
reader.endian = EndianType.LittleEndian;
reader.Endian = EndianType.LittleEndian;
}
if (header.m_Version >= 7)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7)
{
unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion);
}
if (header.m_Version >= 8)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_8)
{
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
@@ -81,26 +83,25 @@ namespace AssetStudio
m_TargetPlatform = BuildTarget.UnknownPlatform;
}
}
if (header.m_Version >= 13)
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
{
m_EnableTypeTree = reader.ReadBoolean();
}
//ReadTypes
// Read Types
int typeCount = reader.ReadInt32();
m_Types = new List<SerializedType>(typeCount);
for (int i = 0; i < typeCount; i++)
{
m_Types.Add(ReadSerializedType());
m_Types.Add(ReadSerializedType(false));
}
var bigIDEnabled = 0;
if (header.m_Version >= 7 && header.m_Version < 14)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7 && header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
bigIDEnabled = reader.ReadInt32();
}
//ReadObjects
// Read Objects
int objectCount = reader.ReadInt32();
m_Objects = new List<ObjectInfo>(objectCount);
Objects = new List<Object>(objectCount);
@@ -112,7 +113,7 @@ namespace AssetStudio
{
objectInfo.m_PathID = reader.ReadInt64();
}
else if (header.m_Version < 14)
else if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
objectInfo.m_PathID = reader.ReadInt32();
}
@@ -122,7 +123,7 @@ namespace AssetStudio
objectInfo.m_PathID = reader.ReadInt64();
}
if (header.m_Version >= 22)
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
objectInfo.byteStart = reader.ReadInt64();
else
objectInfo.byteStart = reader.ReadUInt32();
@@ -130,7 +131,7 @@ namespace AssetStudio
objectInfo.byteStart += header.m_DataOffset;
objectInfo.byteSize = reader.ReadUInt32();
objectInfo.typeID = reader.ReadInt32();
if (header.m_Version < 16)
if (header.m_Version < SerializedFileFormatVersion.kRefactoredClassId)
{
objectInfo.classID = reader.ReadUInt16();
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
@@ -141,24 +142,24 @@ namespace AssetStudio
objectInfo.serializedType = type;
objectInfo.classID = type.classID;
}
if (header.m_Version < 11)
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex)
{
var isDestroyed = reader.ReadUInt16();
objectInfo.isDestroyed = reader.ReadUInt16();
}
if (header.m_Version >= 11 && header.m_Version < 17)
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.kRefactorTypeData)
{
var m_ScriptTypeIndex = reader.ReadInt16();
if (objectInfo.serializedType != null)
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
}
if (header.m_Version == 15 || header.m_Version == 16)
if (header.m_Version == SerializedFileFormatVersion.kSupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.kRefactoredClassId)
{
var stripped = reader.ReadByte();
objectInfo.stripped = reader.ReadByte();
}
m_Objects.Add(objectInfo);
}
if (header.m_Version >= 11)
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex)
{
int scriptCount = reader.ReadInt32();
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
@@ -166,7 +167,7 @@ namespace AssetStudio
{
var m_ScriptType = new LocalSerializedObjectIdentifier();
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
if (header.m_Version < 14)
if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
{
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
}
@@ -184,11 +185,11 @@ namespace AssetStudio
for (int i = 0; i < externalsCount; i++)
{
var m_External = new FileIdentifier();
if (header.m_Version >= 6)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_6)
{
var tempEmpty = reader.ReadStringToNull();
}
if (header.m_Version >= 5)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
{
m_External.guid = new Guid(reader.ReadBytes(16));
m_External.type = reader.ReadInt32();
@@ -198,19 +199,19 @@ namespace AssetStudio
m_Externals.Add(m_External);
}
if (header.m_Version >= 20)
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject)
{
int refTypesCount = reader.ReadInt32();
m_RefTypes = new List<SerializedType>(refTypesCount);
for (int i = 0; i < refTypesCount; i++)
{
m_RefTypes.Add(ReadSerializedType());
m_RefTypes.Add(ReadSerializedType(true));
}
}
if (header.m_Version >= 5)
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
{
var userInformation = reader.ReadStringToNull();
userInformation = reader.ReadStringToNull();
}
//reader.AlignStream(16);
@@ -218,80 +219,94 @@ namespace AssetStudio
public void SetVersion(string stringVersion)
{
unityVersion = stringVersion;
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
buildType = new BuildType(buildSplit[0]);
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = versionSplit.Select(int.Parse).ToArray();
if (stringVersion != strippedVersion)
{
unityVersion = stringVersion;
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
buildType = new BuildType(buildSplit[0]);
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = versionSplit.Select(int.Parse).ToArray();
}
}
private SerializedType ReadSerializedType()
private SerializedType ReadSerializedType(bool isRefType)
{
var type = new SerializedType();
type.classID = reader.ReadInt32();
if (header.m_Version >= 16)
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId)
{
type.m_IsStrippedType = reader.ReadBoolean();
}
if (header.m_Version >= 17)
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData)
{
type.m_ScriptTypeIndex = reader.ReadInt16();
}
if (header.m_Version >= 13)
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
{
if ((header.m_Version < 16 && type.classID < 0) || (header.m_Version >= 16 && type.classID == 114))
if (isRefType && type.m_ScriptTypeIndex >= 0)
{
type.m_ScriptID = reader.ReadBytes(16); //Hash128
type.m_ScriptID = reader.ReadBytes(16);
}
type.m_OldTypeHash = reader.ReadBytes(16); //Hash128
else if ((header.m_Version < SerializedFileFormatVersion.kRefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId && type.classID == 114))
{
type.m_ScriptID = reader.ReadBytes(16);
}
type.m_OldTypeHash = reader.ReadBytes(16);
}
if (m_EnableTypeTree)
{
var typeTree = new List<TypeTreeNode>();
if (header.m_Version >= 12 || header.m_Version == 10)
type.m_Type = new TypeTree();
type.m_Type.m_Nodes = new List<TypeTreeNode>();
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_12 || header.m_Version == SerializedFileFormatVersion.kUnknown_10)
{
TypeTreeBlobRead(typeTree);
TypeTreeBlobRead(type.m_Type);
}
else
{
ReadTypeTree(typeTree);
ReadTypeTree(type.m_Type);
}
if (header.m_Version >= 21)
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies)
{
type.m_TypeDependencies = reader.ReadInt32Array();
if (isRefType)
{
type.m_KlassName = reader.ReadStringToNull();
type.m_NameSpace = reader.ReadStringToNull();
type.m_AsmName = reader.ReadStringToNull();
}
else
{
type.m_TypeDependencies = reader.ReadInt32Array();
}
}
type.m_Nodes = typeTree;
}
return type;
}
private void ReadTypeTree(List<TypeTreeNode> typeTree, int level = 0)
private void ReadTypeTree(TypeTree m_Type, int level = 0)
{
var typeTreeNode = new TypeTreeNode();
typeTree.Add(typeTreeNode);
m_Type.m_Nodes.Add(typeTreeNode);
typeTreeNode.m_Level = level;
typeTreeNode.m_Type = reader.ReadStringToNull();
typeTreeNode.m_Name = reader.ReadStringToNull();
typeTreeNode.m_ByteSize = reader.ReadInt32();
if (header.m_Version == 2)
if (header.m_Version == SerializedFileFormatVersion.kUnknown_2)
{
var variableCount = reader.ReadInt32();
}
if (header.m_Version != 3)
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
{
typeTreeNode.m_Index = reader.ReadInt32();
}
typeTreeNode.m_IsArray = reader.ReadInt32();
typeTreeNode.m_TypeFlags = reader.ReadInt32();
typeTreeNode.m_Version = reader.ReadInt32();
if (header.m_Version != 3)
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
{
typeTreeNode.m_MetaFlag = reader.ReadInt32();
}
@@ -299,40 +314,40 @@ namespace AssetStudio
int childrenCount = reader.ReadInt32();
for (int i = 0; i < childrenCount; i++)
{
ReadTypeTree(typeTree, level + 1);
ReadTypeTree(m_Type, level + 1);
}
}
private void TypeTreeBlobRead(List<TypeTreeNode> typeTree)
private void TypeTreeBlobRead(TypeTree m_Type)
{
int numberOfNodes = reader.ReadInt32();
int stringBufferSize = reader.ReadInt32();
for (int i = 0; i < numberOfNodes; i++)
{
var typeTreeNode = new TypeTreeNode();
typeTree.Add(typeTreeNode);
m_Type.m_Nodes.Add(typeTreeNode);
typeTreeNode.m_Version = reader.ReadUInt16();
typeTreeNode.m_Level = reader.ReadByte();
typeTreeNode.m_IsArray = reader.ReadBoolean() ? 1 : 0;
typeTreeNode.m_TypeFlags = reader.ReadByte();
typeTreeNode.m_TypeStrOffset = reader.ReadUInt32();
typeTreeNode.m_NameStrOffset = reader.ReadUInt32();
typeTreeNode.m_ByteSize = reader.ReadInt32();
typeTreeNode.m_Index = reader.ReadInt32();
typeTreeNode.m_MetaFlag = reader.ReadInt32();
if (header.m_Version >= 19)
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags)
{
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
}
}
var m_StringBuffer = reader.ReadBytes(stringBufferSize);
m_Type.m_StringBuffer = reader.ReadBytes(stringBufferSize);
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_StringBuffer)))
using (var stringBufferReader = new BinaryReader(new MemoryStream(m_Type.m_StringBuffer)))
{
for (int i = 0; i < numberOfNodes; i++)
{
var typeTreeNode = typeTree[i];
typeTreeNode.m_Type = ReadString(stringBufferReader, typeTreeNode.m_TypeStrOffset);
typeTreeNode.m_Name = ReadString(stringBufferReader, typeTreeNode.m_NameStrOffset);
var m_Node = m_Type.m_Nodes[i];
m_Node.m_Type = ReadString(stringBufferReader, m_Node.m_TypeStrOffset);
m_Node.m_Name = ReadString(stringBufferReader, m_Node.m_NameStrOffset);
}
}
@@ -359,41 +374,8 @@ namespace AssetStudio
ObjectsDic.Add(obj.m_PathID, obj);
}
public static bool IsSerializedFile(EndianBinaryReader reader)
{
var fileSize = reader.BaseStream.Length;
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;
}
public bool IsVersionStripped => unityVersion == strippedVersion;
private const string strippedVersion = "0.0.0";
}
}
@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AssetStudio
{
public enum SerializedFileFormatVersion
{
kUnsupported = 1,
kUnknown_2 = 2,
kUnknown_3 = 3,
/// <summary>
/// 1.2.0 to 2.0.0
/// </summary>
kUnknown_5 = 5,
/// <summary>
/// 2.1.0 to 2.6.1
/// </summary>
kUnknown_6 = 6,
/// <summary>
/// 3.0.0b
/// </summary>
kUnknown_7 = 7,
/// <summary>
/// 3.0.0 to 3.4.2
/// </summary>
kUnknown_8 = 8,
/// <summary>
/// 3.5.0 to 4.7.2
/// </summary>
kUnknown_9 = 9,
/// <summary>
/// 5.0.0aunk1
/// </summary>
kUnknown_10 = 10,
/// <summary>
/// 5.0.0aunk2
/// </summary>
kHasScriptTypeIndex = 11,
/// <summary>
/// 5.0.0aunk3
/// </summary>
kUnknown_12 = 12,
/// <summary>
/// 5.0.0aunk4
/// </summary>
kHasTypeTreeHashes = 13,
/// <summary>
/// 5.0.0unk
/// </summary>
kUnknown_14 = 14,
/// <summary>
/// 5.0.1 to 5.4.0
/// </summary>
kSupportsStrippedObject = 15,
/// <summary>
/// 5.5.0a
/// </summary>
kRefactoredClassId = 16,
/// <summary>
/// 5.5.0unk to 2018.4
/// </summary>
kRefactorTypeData = 17,
/// <summary>
/// 2019.1a
/// </summary>
kRefactorShareableTypeTreeData = 18,
/// <summary>
/// 2019.1unk
/// </summary>
kTypeTreeNodeWithTypeFlags = 19,
/// <summary>
/// 2019.2
/// </summary>
kSupportsRefObject = 20,
/// <summary>
/// 2019.3 to 2019.4
/// </summary>
kStoresTypeDependencies = 21,
/// <summary>
/// 2020.1 to x
/// </summary>
kLargeFilesSupport = 22
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ namespace AssetStudio
{
public uint m_MetadataSize;
public long m_FileSize;
public uint m_Version;
public SerializedFileFormatVersion m_Version;
public long m_DataOffset;
public byte m_Endianess;
public byte[] m_Reserved;
+4 -1
View File
@@ -10,9 +10,12 @@ namespace AssetStudio
public int classID;
public bool m_IsStrippedType;
public short m_ScriptTypeIndex = -1;
public List<TypeTreeNode> m_Nodes;
public TypeTree m_Type;
public byte[] m_ScriptID; //Hash128
public byte[] m_OldTypeHash; //Hash128
public int[] m_TypeDependencies;
public string m_KlassName;
public string m_NameSpace;
public string m_AsmName;
}
}
+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 class TypeTree
{
public List<TypeTreeNode> m_Nodes;
public byte[] m_StringBuffer;
}
}
+47 -43
View File
@@ -7,29 +7,32 @@ namespace AssetStudio
{
public static class TypeTreeHelper
{
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, ObjectReader reader)
public static string ReadTypeString(TypeTree m_Type, ObjectReader reader)
{
reader.Reset();
for (int i = 0; i < members.Count; i++)
var sb = new StringBuilder();
var m_Nodes = m_Type.m_Nodes;
for (int i = 0; i < m_Nodes.Count; i++)
{
ReadStringValue(sb, members, reader, ref i);
ReadStringValue(sb, m_Nodes, reader, ref i);
}
var readed = reader.Position - reader.byteStart;
if (readed != reader.byteSize)
{
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
}
return sb.ToString();
}
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)
{
var member = members[i];
var level = member.m_Level;
var varTypeStr = member.m_Type;
var varNameStr = member.m_Name;
var m_Node = m_Nodes[i];
var level = m_Node.m_Level;
var varTypeStr = m_Node.m_Type;
var varNameStr = m_Node.m_Name;
object value = null;
var append = true;
var align = (member.m_MetaFlag & 0x4000) != 0;
var align = (m_Node.m_MetaFlag & 0x4000) != 0;
switch (varTypeStr)
{
case "SInt8":
@@ -82,18 +85,18 @@ namespace AssetStudio
break;
case "map":
{
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
var size = reader.ReadInt32();
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
var map = GetMembers(members, i);
var map = GetNodes(m_Nodes, i);
i += map.Count - 1;
var first = GetMembers(map, 4);
var first = GetNodes(map, 4);
var next = 4 + first.Count;
var second = GetMembers(map, next);
var second = GetNodes(map, next);
for (int j = 0; j < size; j++)
{
sb.AppendFormat("{0}[{1}]\r\n", (new string('\t', level + 2)), j);
@@ -117,16 +120,16 @@ namespace AssetStudio
}
default:
{
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == "Array") //Array
{
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level + 1)), "Array", "Array");
var size = reader.ReadInt32();
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level + 1)), "int", "size", size);
var vector = GetMembers(members, i);
var vector = GetNodes(m_Nodes, i);
i += vector.Count - 1;
for (int j = 0; j < size; j++)
{
@@ -140,7 +143,7 @@ namespace AssetStudio
{
append = false;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
var @class = GetMembers(members, i);
var @class = GetNodes(m_Nodes, i);
i += @class.Count - 1;
for (int j = 1; j < @class.Count; j++)
{
@@ -156,15 +159,16 @@ namespace AssetStudio
reader.AlignStream();
}
public static OrderedDictionary ReadType(List<TypeTreeNode> members, ObjectReader reader)
public static OrderedDictionary ReadType(TypeTree m_Types, ObjectReader reader)
{
reader.Reset();
var obj = new OrderedDictionary();
for (int i = 1; i < members.Count; i++)
var m_Nodes = m_Types.m_Nodes;
for (int i = 1; i < m_Nodes.Count; i++)
{
var member = members[i];
var varNameStr = member.m_Name;
obj[varNameStr] = ReadValue(members, reader, ref i);
var m_Node = m_Nodes[i];
var varNameStr = m_Node.m_Name;
obj[varNameStr] = ReadValue(m_Nodes, reader, ref i);
}
var readed = reader.Position - reader.byteStart;
if (readed != reader.byteSize)
@@ -174,12 +178,12 @@ namespace AssetStudio
return obj;
}
private static object ReadValue(List<TypeTreeNode> members, BinaryReader reader, ref int i)
private static object ReadValue(List<TypeTreeNode> m_Nodes, BinaryReader reader, ref int i)
{
var member = members[i];
var varTypeStr = member.m_Type;
var m_Node = m_Nodes[i];
var varTypeStr = m_Node.m_Type;
object value;
var align = (member.m_MetaFlag & 0x4000) != 0;
var align = (m_Node.m_MetaFlag & 0x4000) != 0;
switch (varTypeStr)
{
case "SInt8":
@@ -230,13 +234,13 @@ namespace AssetStudio
break;
case "map":
{
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
var map = GetMembers(members, i);
var map = GetNodes(m_Nodes, i);
i += map.Count - 1;
var first = GetMembers(map, 4);
var first = GetNodes(map, 4);
var next = 4 + first.Count;
var second = GetMembers(map, next);
var second = GetNodes(map, next);
var size = reader.ReadInt32();
var dic = new List<KeyValuePair<object, object>>(size);
for (int j = 0; j < size; j++)
@@ -257,11 +261,11 @@ namespace AssetStudio
}
default:
{
if (i < members.Count - 1 && members[i + 1].m_Type == "Array") //Array
if (i < m_Nodes.Count - 1 && m_Nodes[i + 1].m_Type == "Array") //Array
{
if ((members[i + 1].m_MetaFlag & 0x4000) != 0)
if ((m_Nodes[i + 1].m_MetaFlag & 0x4000) != 0)
align = true;
var vector = GetMembers(members, i);
var vector = GetNodes(m_Nodes, i);
i += vector.Count - 1;
var size = reader.ReadInt32();
var list = new List<object>(size);
@@ -275,7 +279,7 @@ namespace AssetStudio
}
else //Class
{
var @class = GetMembers(members, i);
var @class = GetNodes(m_Nodes, i);
i += @class.Count - 1;
var obj = new OrderedDictionary();
for (int j = 1; j < @class.Count; j++)
@@ -294,22 +298,22 @@ namespace AssetStudio
return value;
}
private static List<TypeTreeNode> GetMembers(List<TypeTreeNode> members, int index)
private static List<TypeTreeNode> GetNodes(List<TypeTreeNode> m_Nodes, int index)
{
var member2 = new List<TypeTreeNode>();
member2.Add(members[index]);
var level = members[index].m_Level;
for (int i = index + 1; i < members.Count; i++)
var nodes = new List<TypeTreeNode>();
nodes.Add(m_Nodes[index]);
var level = m_Nodes[index].m_Level;
for (int i = index + 1; i < m_Nodes.Count; i++)
{
var member = members[i];
var member = m_Nodes[i];
var level2 = member.m_Level;
if (level2 <= level)
{
return member2;
return nodes;
}
member2.Add(member);
nodes.Add(member);
}
return member2;
return nodes;
}
}
}
+1 -1
View File
@@ -11,7 +11,7 @@ namespace AssetStudio
public string m_Name;
public int m_ByteSize;
public int m_Index;
public int m_IsArray; //m_TypeFlags
public int m_TypeFlags; //m_IsArray
public int m_Version;
public int m_MetaFlag;
public int m_Level;
+2 -50
View File
@@ -1,17 +1,11 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using Org.Brotli.Dec;
namespace AssetStudio
{
public class WebFile
{
public static byte[] gzipMagic = { 0x1f, 0x8b };
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public StreamFile[] fileList;
private class WebData
@@ -23,50 +17,8 @@ namespace AssetStudio
public WebFile(EndianBinaryReader reader)
{
var magic = reader.ReadBytes(2);
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)
{
reader.Endian = EndianType.LittleEndian;
var signature = reader.ReadStringToNull();
if (signature != "UnityWebData1.0")
return;
var headLength = reader.ReadInt32();
var dataList = new List<WebData>();
while (reader.BaseStream.Position < headLength)
@@ -29,26 +29,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@@ -100,14 +100,14 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.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>
</Link>
</ItemDefinitionGroup>
@@ -119,7 +119,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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>
</ClCompile>
<Link>
@@ -128,7 +128,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.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>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -137,14 +137,14 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.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>
</Link>
</ItemDefinitionGroup>
@@ -156,7 +156,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<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>
</ClCompile>
<Link>
@@ -165,7 +165,7 @@
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.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>
</ItemDefinitionGroup>
<ItemGroup>
-12
View File
@@ -4,18 +4,6 @@
#include <string>
#include <unordered_set>
namespace fbxsdk
{
class FbxManager;
class FbxScene;
class FbxExporter;
template<typename T, const int Alignment = 16>
class FbxArray;
class FbxFileTexture;
class FbxSurfacePhong;
class FbxPose;
}
struct AsFbxContext
{
@@ -1,60 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{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>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021; Copyright © hozuki 2020</Copyright>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
</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,
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 dir = file.Directory;
@@ -43,7 +43,7 @@ namespace AssetStudio
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.ExportAll(blendShape, animation, eulerFilter, filterPrecision);
+4 -2
View File
@@ -15,11 +15,12 @@ namespace AssetStudio.FbxInterop
private readonly bool _exportSkins;
private readonly bool _castToBone;
private readonly float _boneSize;
private readonly bool _exportAllUvsAsDiffuseMaps;
private readonly float _scaleFactor;
private readonly int _versionIndex;
private readonly bool _isAscii;
internal FbxExporter(string fileName, IImported imported, bool allNodes, bool exportSkins, bool castToBone, float boneSize, 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();
@@ -29,6 +30,7 @@ namespace AssetStudio.FbxInterop
_exportSkins = exportSkins;
_castToBone = castToBone;
_boneSize = boneSize;
_exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps;
_scaleFactor = scaleFactor;
_versionIndex = versionIndex;
_isAscii = isAscii;
@@ -171,7 +173,7 @@ namespace AssetStudio.FbxInterop
{
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);
}
}
+72 -78
View File
@@ -173,12 +173,12 @@ namespace AssetStudio.FbxInterop
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 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)
@@ -207,7 +207,7 @@ namespace AssetStudio.FbxInterop
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 totalBoneCount = 0;
@@ -246,28 +246,25 @@ namespace AssetStudio.FbxInterop
var mesh = AsFbxMeshCreateMesh(_pContext, frameNode);
var totalVertexCount = 0;
foreach (var m in importedMesh.SubmeshList)
{
totalVertexCount += m.VertexList.Count;
}
AsFbxMeshInitControlPoints(mesh, totalVertexCount);
AsFbxMeshInitControlPoints(mesh, importedMesh.VertexList.Count);
if (importedMesh.hasNormal)
{
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])
{
AsFbxMeshCreateNormalMapUV(mesh, 1);
if (i == 1 && !exportAllUvsAsDiffuseMaps)
{
AsFbxMeshCreateNormalMapUV(mesh, 1);
}
else
{
AsFbxMeshCreateDiffuseUV(mesh, i);
}
}
if (importedMesh.hasTangent)
@@ -282,8 +279,6 @@ namespace AssetStudio.FbxInterop
AsFbxMeshCreateElementMaterial(mesh);
var firstVertex = 0;
foreach (var meshObj in importedMesh.SubmeshList)
{
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)
{
var index0 = face.VertexIndices[0] + firstVertex;
var index1 = face.VertexIndices[1] + firstVertex;
var index2 = face.VertexIndices[2] + firstVertex;
var index0 = face.VertexIndices[0] + meshObj.BaseVertex;
var index1 = face.VertexIndices[1] + meshObj.BaseVertex;
var index2 = face.VertexIndices[2] + meshObj.BaseVertex;
AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2);
}
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)
{
IntPtr pSkinContext = IntPtr.Zero;
@@ -646,4 +640,4 @@ namespace AssetStudio.FbxInterop
}
}
}
}
@@ -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")]
+82 -153
View File
@@ -1,154 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{52B196FB-4C8A-499B-B877-1A0EB4F33EC0}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>AssetStudioGUI</RootNamespace>
<AssemblyName>AssetStudioGUI</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
</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>
<Prefer32Bit>false</Prefer32Bit>
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
</Reference>
<Reference Include="OpenTK.GLControl, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\OpenTK.GLControl.3.1.0\lib\net20\OpenTK.GLControl.dll</HintPath>
</Reference>
<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.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssetStudioGUIForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AssetStudioGUIForm.designer.cs">
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
</Compile>
<Compile Include="Components\AssetItem.cs" />
<Compile Include="Components\GameObjectTreeNode.cs" />
<Compile Include="Components\GOHierarchy.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Components\OpenFolderDialog.cs" />
<Compile Include="Components\TreeViewExtensions.cs" />
<Compile Include="Components\TypeTreeItem.cs" />
<Compile Include="Exporter.cs" />
<Compile Include="ExportOptions.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExportOptions.designer.cs">
<DependentUpon>ExportOptions.cs</DependentUpon>
</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 Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFrameworks>net472;net5.0-windows;net6.0-windows</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
</ItemGroup>
<ItemGroup>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Update="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<Compile Update="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
</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 Condition=" '$(TargetFramework)' != 'net472' ">
<PackageReference Include="OpenTK" Version="4.6.7" />
<Reference Include="OpenTK.WinForms">
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="OpenTK" Version="3.1.0" />
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<Target Name="CopyExtraFiles" AfterTargets="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>
<Target Name="PublishExtraFiles" AfterTargets="Publish">
<Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
<Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
</Target>
</Project>
+42 -11
View File
@@ -41,6 +41,8 @@
this.displayAll = new System.Windows.Forms.ToolStripMenuItem();
this.enablePreview = 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.modelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAllObjectssplitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@@ -72,6 +74,7 @@
this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.allToolStripMenuItem = 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.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.tabControl1 = new System.Windows.Forms.TabControl();
@@ -210,6 +213,7 @@
this.displayAll,
this.enablePreview,
this.displayInfo,
this.toolStripMenuItem14,
this.showExpOpt});
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
this.optionsToolStripMenuItem.Size = new System.Drawing.Size(66, 21);
@@ -249,6 +253,20 @@
"t, audio bitrate, etc.";
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
//
this.showExpOpt.Name = "showExpOpt";
@@ -429,7 +447,7 @@
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(396, 6);
this.toolStripSeparator2.Size = new System.Drawing.Size(281, 6);
//
// toolStripMenuItem10
//
@@ -438,27 +456,27 @@
this.toolStripMenuItem12,
this.toolStripMenuItem13});
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";
//
// 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.Click += new System.EventHandler(this.toolStripMenuItem11_Click);
//
// 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.Click += new System.EventHandler(this.toolStripMenuItem12_Click);
//
// 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.Click += new System.EventHandler(this.toolStripMenuItem13_Click);
//
@@ -483,11 +501,22 @@
// debugMenuItem
//
this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.toolStripMenuItem15,
this.exportClassStructuresMenuItem});
this.debugMenuItem.Name = "debugMenuItem";
this.debugMenuItem.Size = new System.Drawing.Size(59, 21);
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
//
this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem";
@@ -790,20 +819,21 @@
//
// FMODtimerLabel
//
this.FMODtimerLabel.AutoSize = true;
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.Size = new System.Drawing.Size(155, 12);
this.FMODtimerLabel.Size = new System.Drawing.Size(95, 12);
this.FMODtimerLabel.TabIndex = 7;
this.FMODtimerLabel.Text = "0:00.0 / 0:00.0";
this.FMODtimerLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// FMODstatusLabel
//
this.FMODstatusLabel.AutoSize = true;
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODstatusLabel.Location = new System.Drawing.Point(213, 235);
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.Text = "Stopped";
//
@@ -1036,8 +1066,6 @@
// AssetStudioGUIForm
//
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.Controls.Add(this.splitContainer1);
this.Controls.Add(this.menuStrip1);
@@ -1178,6 +1206,9 @@
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem11;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem12;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem13;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem14;
private System.Windows.Forms.ToolStripTextBox specifyUnityVersion;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15;
}
}
+60 -30
View File
@@ -6,7 +6,6 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.Globalization;
using System.IO;
@@ -19,16 +18,21 @@ using System.Timers;
using System.Windows.Forms;
using static AssetStudioGUI.Studio;
using Font = AssetStudio.Font;
using PixelFormat = System.Drawing.Imaging.PixelFormat;
#if NET472
using Vector3 = OpenTK.Vector3;
using Vector4 = OpenTK.Vector4;
#else
using Vector3 = OpenTK.Mathematics.Vector3;
using Vector4 = OpenTK.Mathematics.Vector4;
using Matrix4 = OpenTK.Mathematics.Matrix4;
#endif
namespace AssetStudioGUI
{
partial class AssetStudioGUIForm : Form
{
private AssetItem lastSelectedItem;
private Bitmap imageTexture;
private DirectBitmap imageTexture;
private string tempClipboard;
private FMOD.System system;
@@ -81,6 +85,11 @@ namespace AssetStudioGUI
private int nextGObject;
private List<TreeNode> treeSrcResults = new List<TreeNode>();
private string openDirectoryBackup = string.Empty;
private string saveDirectoryBackup = string.Empty;
private GUILogger logger;
[DllImport("gdi32.dll")]
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
@@ -96,7 +105,8 @@ namespace AssetStudioGUI
enablePreview.Checked = Properties.Settings.Default.enablePreview;
FMODinit();
Logger.Default = new GUILogger(StatusStripUpdate);
logger = new GUILogger(StatusStripUpdate);
Logger.Default = logger;
Progress.Default = new GUIProgress(SetProgressBarValue);
Studio.StatusStripUpdate = StatusStripUpdate;
}
@@ -115,7 +125,7 @@ namespace AssetStudioGUI
if (paths.Length > 0)
{
ResetForm();
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
if (paths.Length == 1 && Directory.Exists(paths[0]))
{
await Task.Run(() => assetsManager.LoadFolder(paths[0]));
@@ -124,16 +134,18 @@ namespace AssetStudioGUI
{
await Task.Run(() => assetsManager.LoadFiles(paths));
}
BuildAssetStructures();
}
}
private async void loadFile_Click(object sender, EventArgs e)
{
openFileDialog1.InitialDirectory = openDirectoryBackup;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
ResetForm();
openDirectoryBackup = Path.GetDirectoryName(openFileDialog1.FileNames[0]);
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFiles(openFileDialog1.FileNames));
BuildAssetStructures();
}
@@ -142,9 +154,12 @@ namespace AssetStudioGUI
private async void loadFolder_Click(object sender, EventArgs e)
{
var openFolderDialog = new OpenFolderDialog();
openFolderDialog.InitialFolder = openDirectoryBackup;
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
{
ResetForm();
openDirectoryBackup = openFolderDialog.Folder;
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFolder(openFolderDialog.Folder));
BuildAssetStructures();
}
@@ -187,7 +202,7 @@ namespace AssetStudioGUI
{
if (assetsManager.assetsFileList.Count == 0)
{
StatusStripUpdate("No file was loaded.");
StatusStripUpdate("No Unity file can be loaded.");
return;
}
@@ -350,7 +365,7 @@ namespace AssetStudioGUI
var versionPath = Path.Combine(savePath, item.Group.Header);
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());
Progress.Report(++i, count);
@@ -378,7 +393,7 @@ namespace AssetStudioGUI
{
if (enablePreview.Checked && imageTexture != null)
{
previewPanel.BackgroundImage = imageTexture;
previewPanel.BackgroundImage = imageTexture.Bitmap;
}
else
{
@@ -741,9 +756,11 @@ namespace AssetStudioGUI
private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
{
var bitmap = m_Texture2D.ConvertToBitmap(true);
if (bitmap != null)
var image = m_Texture2D.ConvertToImage(true);
if (image != null)
{
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), 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}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
{
@@ -771,13 +788,11 @@ namespace AssetStudioGUI
assetItem.InfoText += "None";
if (validChannel != 4)
{
var bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
var bytes = new byte[bitmap.Width * bitmap.Height * 4];
Marshal.Copy(bmpData.Scan0, bytes, 0, bytes.Length);
for (int i = 0; i < bmpData.Height; i++)
var bytes = bitmap.Bits;
for (int i = 0; i < bitmap.Height; i++)
{
int offset = Math.Abs(bmpData.Stride) * i;
for (int j = 0; j < bmpData.Width; j++)
int offset = Math.Abs(bitmap.Stride) * i;
for (int j = 0; j < bitmap.Width; j++)
{
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;
@@ -786,8 +801,6 @@ namespace AssetStudioGUI
offset += 4;
}
}
Marshal.Copy(bytes, 0, bmpData.Scan0, bytes.Length);
bitmap.UnlockBits(bmpData);
}
PreviewTexture(bitmap);
@@ -943,8 +956,8 @@ namespace AssetStudioGUI
var obj = m_MonoBehaviour.ToType();
if (obj == null)
{
var nodes = MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
obj = m_MonoBehaviour.ToType(nodes);
var type = MonoBehaviourToTypeTree(m_MonoBehaviour);
obj = m_MonoBehaviour.ToType(type);
}
var str = JsonConvert.SerializeObject(obj, Formatting.Indented);
PreviewText(str);
@@ -1151,11 +1164,12 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{
var bitmap = m_Sprite.GetImage();
if (bitmap != null)
var image = m_Sprite.GetImage();
if (image != null)
{
var bitmap = new DirectBitmap(image.ConvertToBgra32Bytes(), image.Width, image.Height);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap);
}
else
@@ -1164,11 +1178,11 @@ namespace AssetStudioGUI
}
}
private void PreviewTexture(Bitmap bitmap)
private void PreviewTexture(DirectBitmap bitmap)
{
imageTexture?.Dispose();
imageTexture = bitmap;
previewPanel.BackgroundImage = imageTexture;
previewPanel.BackgroundImage = imageTexture.Bitmap;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else
@@ -1219,6 +1233,7 @@ namespace AssetStudioGUI
classesListView.Groups.Clear();
previewPanel.BackgroundImage = Properties.Resources.preview;
imageTexture?.Dispose();
imageTexture = null;
previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false;
assetInfoLabel.Text = null;
@@ -1305,9 +1320,11 @@ namespace AssetStudioGUI
if (animator != null)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
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);
}
}
@@ -1328,9 +1345,11 @@ namespace AssetStudioGUI
if (sceneTreeView.Nodes.Count > 0)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
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;
if (animation)
{
@@ -1369,8 +1388,10 @@ namespace AssetStudioGUI
saveFileDialog.FileName = gameObjects[0].m_Name + " (merge).fbx";
saveFileDialog.AddExtension = false;
saveFileDialog.Filter = "Fbx file (*.fbx)|*.fbx";
saveFileDialog.InitialDirectory = saveDirectoryBackup;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
saveDirectoryBackup = Path.GetDirectoryName(saveFileDialog.FileName);
var exportPath = saveFileDialog.FileName;
List<AssetItem> animationList = null;
if (animation)
@@ -1461,8 +1482,10 @@ namespace AssetStudioGUI
if (sceneTreeView.Nodes.Count > 0)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
saveDirectoryBackup = saveFolderDialog.Folder;
var savePath = saveFolderDialog.Folder + Path.DirectorySeparatorChar;
ExportSplitObjects(savePath, sceneTreeView.Nodes);
}
@@ -1521,10 +1544,11 @@ namespace AssetStudioGUI
if (exportableAssets.Count > 0)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
List<AssetItem> toExportAssets = null;
switch (type)
{
@@ -1554,10 +1578,11 @@ namespace AssetStudioGUI
if (exportableAssets.Count > 0)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
List<AssetItem> toExportAssets = null;
switch (type)
{
@@ -2016,6 +2041,11 @@ namespace AssetStudioGUI
}
}
private void toolStripMenuItem15_Click(object sender, EventArgs e)
{
logger.ShowErrorMessage = toolStripMenuItem15.Checked;
}
private void glControl1_MouseWheel(object sender, MouseEventArgs e)
{
if (glControl1.Visible)
+21 -12
View File
@@ -1,5 +1,4 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ -15,12 +14,13 @@ namespace AssetStudioGUI
internal DialogResult ShowDialog(IWin32Window owner = null)
{
#if NETFRAMEWORK
if (Environment.OSVersion.Version.Major >= 6)
{
return ShowVistaDialog(owner);
}
return ShowLegacyDialog(owner);
#endif
return ShowFolderBrowserDialog(owner);
}
private DialogResult ShowVistaDialog(IWin32Window owner)
@@ -29,9 +29,11 @@ namespace AssetStudioGUI
frm.GetOptions(out var options);
options |= NativeMethods.FOS_PICKFOLDERS | NativeMethods.FOS_FORCEFILESYSTEM | NativeMethods.FOS_NOVALIDATE | NativeMethods.FOS_NOTESTFILECREATE | NativeMethods.FOS_DONTADDTORECENT;
frm.SetOptions(options);
if (Title != null)
if (!string.IsNullOrEmpty(Title))
{
frm.SetTitle(Title);
if (InitialFolder != null)
}
if (!string.IsNullOrEmpty(InitialFolder))
{
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
if (NativeMethods.SHCreateItemFromParsingName(InitialFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
@@ -39,7 +41,7 @@ namespace AssetStudioGUI
frm.SetFolder(directoryShellItem);
}
}
if (DefaultFolder != null)
if (!string.IsNullOrEmpty(DefaultFolder))
{
var riid = new Guid("43826D1E-E718-42EE-BC55-A1E261C37BFE"); //IShellItem
if (NativeMethods.SHCreateItemFromParsingName(DefaultFolder, IntPtr.Zero, ref riid, out var directoryShellItem) == NativeMethods.S_OK)
@@ -72,7 +74,7 @@ namespace AssetStudioGUI
return DialogResult.Cancel;
}
private DialogResult ShowLegacyDialog(IWin32Window owner)
private DialogResult ShowFolderBrowserDialog(IWin32Window owner)
{
using (var frm = new FolderBrowserDialog())
{
@@ -80,13 +82,20 @@ namespace AssetStudioGUI
{
frm.SelectedPath = InitialFolder;
}
if ((owner == null ? frm.ShowDialog() : frm.ShowDialog(owner)) == DialogResult.OK)
#if !NETFRAMEWORK
if (Title != null)
{
Folder = Path.GetDirectoryName(frm.SelectedPath);
return DialogResult.OK;
frm.Description = Title;
frm.UseDescriptionForTitle = true;
}
return DialogResult.Cancel;
#endif
var result = owner == null ? frm.ShowDialog() : frm.ShowDialog(owner);
if (result == DialogResult.OK)
{
Folder = frm.SelectedPath;
return result;
}
return result;
}
}
}
+5 -5
View File
@@ -7,19 +7,19 @@ namespace AssetStudioGUI
{
internal class TypeTreeItem : ListViewItem
{
private List<TypeTreeNode> m_Nodes;
private TypeTree m_Type;
public TypeTreeItem(int typeID, List<TypeTreeNode> m_Nodes)
public TypeTreeItem(int typeID, TypeTree m_Type)
{
this.m_Nodes = m_Nodes;
Text = m_Nodes[0].m_Type + " " + m_Nodes[0].m_Name;
this.m_Type = m_Type;
Text = m_Type.m_Nodes[0].m_Type + " " + m_Type.m_Nodes[0].m_Name;
SubItems.Add(typeID.ToString());
}
public override string ToString()
{
var sb = new StringBuilder();
foreach (var i in m_Nodes)
foreach (var i in m_Type.m_Nodes)
{
sb.AppendFormat("{0}{1} {2} {3} {4}\r\n", new string('\t', i.m_Level), i.m_Type, i.m_Name, i.m_ByteSize, (i.m_MetaFlag & 0x4000) != 0);
}
+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>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.OKbutton = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
@@ -43,6 +44,7 @@
this.tobmp = new System.Windows.Forms.RadioButton();
this.converttexture = new System.Windows.Forms.CheckBox();
this.groupBox2 = new System.Windows.Forms.GroupBox();
this.exportAllUvsAsDiffuseMaps = new System.Windows.Forms.CheckBox();
this.exportBlendShape = new System.Windows.Forms.CheckBox();
this.exportAnimations = new System.Windows.Forms.CheckBox();
this.scaleFactor = new System.Windows.Forms.NumericUpDown();
@@ -59,6 +61,7 @@
this.castToBone = new System.Windows.Forms.CheckBox();
this.exportAllNodes = 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.panel1.SuspendLayout();
this.groupBox2.SuspendLayout();
@@ -69,7 +72,7 @@
//
// 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.Size = new System.Drawing.Size(75, 21);
this.OKbutton.TabIndex = 6;
@@ -80,7 +83,7 @@
// 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.Size = new System.Drawing.Size(75, 21);
this.Cancel.TabIndex = 7;
@@ -100,7 +103,7 @@
this.groupBox1.Controls.Add(this.converttexture);
this.groupBox1.Location = new System.Drawing.Point(12, 12);
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.TabStop = false;
this.groupBox1.Text = "Export";
@@ -182,7 +185,7 @@
this.totga.Name = "totga";
this.totga.Size = new System.Drawing.Size(41, 16);
this.totga.TabIndex = 2;
this.totga.Text = "TGA";
this.totga.Text = "Tga";
this.totga.UseVisualStyleBackColor = true;
//
// tojpg
@@ -192,7 +195,7 @@
this.tojpg.Name = "tojpg";
this.tojpg.Size = new System.Drawing.Size(47, 16);
this.tojpg.TabIndex = 4;
this.tojpg.Text = "JPEG";
this.tojpg.Text = "Jpeg";
this.tojpg.UseVisualStyleBackColor = true;
//
// topng
@@ -204,7 +207,7 @@
this.topng.Size = new System.Drawing.Size(41, 16);
this.topng.TabIndex = 3;
this.topng.TabStop = true;
this.topng.Text = "PNG";
this.topng.Text = "Png";
this.topng.UseVisualStyleBackColor = true;
//
// tobmp
@@ -214,7 +217,7 @@
this.tobmp.Name = "tobmp";
this.tobmp.Size = new System.Drawing.Size(41, 16);
this.tobmp.TabIndex = 2;
this.tobmp.Text = "BMP";
this.tobmp.Text = "Bmp";
this.tobmp.UseVisualStyleBackColor = true;
//
// converttexture
@@ -232,6 +235,7 @@
// groupBox2
//
this.groupBox2.AutoSize = true;
this.groupBox2.Controls.Add(this.exportAllUvsAsDiffuseMaps);
this.groupBox2.Controls.Add(this.exportBlendShape);
this.groupBox2.Controls.Add(this.exportAnimations);
this.groupBox2.Controls.Add(this.scaleFactor);
@@ -250,11 +254,24 @@
this.groupBox2.Controls.Add(this.eulerFilter);
this.groupBox2.Location = new System.Drawing.Point(250, 12);
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.TabStop = false;
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
//
this.exportBlendShape.AutoSize = true;
@@ -287,7 +304,7 @@
0,
0,
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.Size = new System.Drawing.Size(60, 21);
this.scaleFactor.TabIndex = 20;
@@ -301,7 +318,7 @@
// label5
//
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.Size = new System.Drawing.Size(71, 12);
this.label5.TabIndex = 19;
@@ -314,7 +331,7 @@
this.fbxFormat.Items.AddRange(new object[] {
"Binary",
"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.Size = new System.Drawing.Size(61, 20);
this.fbxFormat.TabIndex = 18;
@@ -322,7 +339,7 @@
// label4
//
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.Size = new System.Drawing.Size(59, 12);
this.label4.TabIndex = 17;
@@ -339,7 +356,7 @@
"7.3",
"7.4",
"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.Size = new System.Drawing.Size(47, 20);
this.fbxVersion.TabIndex = 16;
@@ -347,7 +364,7 @@
// label3
//
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.Size = new System.Drawing.Size(65, 12);
this.label3.TabIndex = 15;
@@ -355,7 +372,7 @@
//
// 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.Size = new System.Drawing.Size(46, 21);
this.boneSize.TabIndex = 11;
@@ -368,7 +385,7 @@
// label2
//
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.Size = new System.Drawing.Size(53, 12);
this.label2.TabIndex = 10;
@@ -453,7 +470,7 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
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.groupBox1);
this.Controls.Add(this.Cancel);
@@ -512,5 +529,7 @@
private System.Windows.Forms.Label label6;
private System.Windows.Forms.CheckBox restoreExtensionName;
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 System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using AssetStudio;
using System;
using System.Windows.Forms;
namespace AssetStudioGUI
@@ -19,7 +13,7 @@ namespace AssetStudioGUI
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
converttexture.Checked = Properties.Settings.Default.convertTexture;
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)
{
if (c.Text == str)
@@ -36,10 +30,12 @@ namespace AssetStudioGUI
exportAnimations.Checked = Properties.Settings.Default.exportAnimations;
exportBlendShape.Checked = Properties.Settings.Default.exportBlendShape;
castToBone.Checked = Properties.Settings.Default.castToBone;
exportAllUvsAsDiffuseMaps.Checked = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
boneSize.Value = Properties.Settings.Default.boneSize;
scaleFactor.Value = Properties.Settings.Default.scaleFactor;
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
}
private void OKbutton_Click(object sender, EventArgs e)
@@ -52,7 +48,7 @@ namespace AssetStudioGUI
{
if (((RadioButton)c).Checked)
{
Properties.Settings.Default.convertType = c.Text;
Properties.Settings.Default.convertType = (ImageFormat)Enum.Parse(typeof(ImageFormat), c.Text);
break;
}
}
@@ -64,6 +60,7 @@ namespace AssetStudioGUI
Properties.Settings.Default.exportAnimations = exportAnimations.Checked;
Properties.Settings.Default.exportBlendShape = exportBlendShape.Checked;
Properties.Settings.Default.castToBone = castToBone.Checked;
Properties.Settings.Default.exportAllUvsAsDiffuseMaps = exportAllUvsAsDiffuseMaps.Checked;
Properties.Settings.Default.boneSize = boneSize.Value;
Properties.Settings.Default.scaleFactor = scaleFactor.Value;
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
@@ -78,5 +75,6 @@ namespace AssetStudioGUI
DialogResult = DialogResult.Cancel;
Close();
}
}
}
+3
View File
@@ -117,4 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</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>
+30 -72
View File
@@ -1,11 +1,9 @@
using System.Collections.Generic;
using System.Drawing.Imaging;
using AssetStudio;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using AssetStudio;
using Newtonsoft.Json;
using TGASharpLib;
namespace AssetStudioGUI
{
@@ -16,40 +14,20 @@ namespace AssetStudioGUI
var m_Texture2D = (Texture2D)item.Asset;
if (Properties.Settings.Default.convertTexture)
{
var bitmap = m_Texture2D.ConvertToBitmap(true);
if (bitmap == null)
var type = Properties.Settings.Default.convertType;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
ImageFormat format = null;
var ext = Properties.Settings.Default.convertType;
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))
var image = m_Texture2D.ConvertToImage(true);
if (image == null)
return false;
if (tga)
using (image)
{
var file = new TGA(bitmap);
file.Save(exportFullPath);
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
else
{
bitmap.Save(exportFullPath, format);
}
bitmap.Dispose();
return true;
}
else
{
@@ -120,8 +98,8 @@ namespace AssetStudioGUI
var type = m_MonoBehaviour.ToType();
if (type == null)
{
var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
type = m_MonoBehaviour.ToType(nodes);
var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
type = m_MonoBehaviour.ToType(m_Type);
}
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
File.WriteAllText(exportFullPath, str);
@@ -230,12 +208,11 @@ namespace AssetStudioGUI
public static bool ExportVideoClip(AssetItem item, string exportPath)
{
var m_VideoClip = (VideoClip)item.Asset;
var m_VideoData = m_VideoClip.m_VideoData.GetData();
if (m_VideoData != null && m_VideoData.Length != 0)
if (m_VideoClip.m_ExternalResources.m_Size > 0)
{
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_VideoData);
m_VideoClip.m_VideoData.WriteData(exportFullPath);
return true;
}
return false;
@@ -252,40 +229,20 @@ namespace AssetStudioGUI
public static bool ExportSprite(AssetItem item, string exportPath)
{
ImageFormat format = null;
var type = Properties.Settings.Default.convertType;
bool tga = false;
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))
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
var bitmap = ((Sprite)item.Asset).GetImage();
if (bitmap != null)
var image = ((Sprite)item.Asset).GetImage();
if (image != null)
{
if (tga)
using (image)
{
var file = new TGA(bitmap);
file.Save(exportFullPath);
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
else
{
bitmap.Save(exportFullPath, format);
}
bitmap.Dispose();
return true;
}
return false;
}
@@ -359,11 +316,12 @@ namespace AssetStudioGUI
var exportBlendShape = Properties.Settings.Default.exportBlendShape;
var castToBone = Properties.Settings.Default.castToBone;
var boneSize = (int)Properties.Settings.Default.boneSize;
var exportAllUvsAsDiffuseMaps = Properties.Settings.Default.exportAllUvsAsDiffuseMaps;
var scaleFactor = (float)Properties.Settings.Default.scaleFactor;
var fbxVersion = Properties.Settings.Default.fbxVersion;
var fbxFormat = Properties.Settings.Default.fbxFormat;
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)
@@ -373,8 +331,8 @@ namespace AssetStudioGUI
var str = item.Asset.Dump();
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
{
var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(nodes);
var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(m_Type);
}
if (str != null)
{
+5 -1
View File
@@ -6,6 +6,7 @@ namespace AssetStudioGUI
{
class GUILogger : ILogger
{
public bool ShowErrorMessage = true;
private Action<string> action;
public GUILogger(Action<string> action)
@@ -18,7 +19,10 @@ namespace AssetStudioGUI
switch (loggerEvent)
{
case LoggerEvent.Error:
MessageBox.Show(message);
if (ShowErrorMessage)
{
MessageBox.Show(message);
}
break;
default:
action(message);
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.Linq;
using System.Threading.Tasks;
@@ -9,11 +9,14 @@ namespace AssetStudioGUI
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
#if !NETFRAMEWORK
Application.SetHighDpiMode(HighDpiMode.SystemAware);
#endif
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
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>
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性
/// 重写当前线程的 CurrentUICulture 属性,对
/// 使用此强类型资源类的所有资源查找执行重写
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
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.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 {
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.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("PNG")]
public string convertType {
[global::System.Configuration.DefaultSettingValueAttribute("Png")]
public global::AssetStudio.ImageFormat convertType {
get {
return ((string)(this["convertType"]));
return ((global::AssetStudio.ImageFormat)(this["convertType"]));
}
set {
this["convertType"] = value;
@@ -262,5 +262,17 @@ namespace AssetStudioGUI.Properties {
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">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="convertType" Type="System.String" Scope="User">
<Value Profile="(Default)">PNG</Value>
<Setting Name="convertType" Type="AssetStudio.ImageFormat" Scope="User">
<Value Profile="(Default)">Png</Value>
</Setting>
<Setting Name="eulerFilter" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
@@ -62,5 +62,8 @@
<Setting Name="restoreExtensionName" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="exportAllUvsAsDiffuseMaps" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
</Settings>
</SettingsFile>
+36 -29
View File
@@ -72,37 +72,37 @@ namespace AssetStudioGUI
public static int ExtractFile(string fileName, string savePath)
{
int extractedCount = 0;
var type = ImportHelper.CheckFileType(fileName, out var reader);
if (type == FileType.BundleFile)
extractedCount += ExtractBundleFile(fileName, reader, savePath);
else if (type == FileType.WebFile)
extractedCount += ExtractWebDataFile(fileName, reader, savePath);
var reader = new FileReader(fileName);
if (reader.FileType == FileType.BundleFile)
extractedCount += ExtractBundleFile(reader, savePath);
else if (reader.FileType == FileType.WebFile)
extractedCount += ExtractWebDataFile(reader, savePath);
else
reader.Dispose();
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)} ...");
var bundleFile = new BundleFile(reader, bundleFilePath);
StatusStripUpdate($"Decompressing {reader.FileName} ...");
var bundleFile = new BundleFile(reader);
reader.Dispose();
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 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);
reader.Dispose();
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 0;
@@ -341,27 +341,27 @@ namespace AssetStudioGUI
{
if (typeMap.TryGetValue(assetsFile.unityVersion, out var curVer))
{
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
curVer[key] = new TypeTreeItem(key, type.m_Nodes);
curVer[key] = new TypeTreeItem(key, type.m_Type);
}
}
else
{
var items = new SortedDictionary<int, TypeTreeItem>();
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
items[key] = new TypeTreeItem(key, type.m_Nodes);
items[key] = new TypeTreeItem(key, type.m_Type);
}
typeMap.Add(assetsFile.unityVersion, items);
}
@@ -413,7 +413,7 @@ namespace AssetStudioGUI
break;
}
exportPath += Path.DirectorySeparatorChar;
StatusStripUpdate($"Exporting {asset.TypeString}: {asset.Text}");
StatusStripUpdate($"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
try
{
switch (exportType)
@@ -457,7 +457,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && exportedCount > 0)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
});
}
@@ -502,7 +502,7 @@ namespace AssetStudioGUI
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
});
}
@@ -531,13 +531,13 @@ namespace AssetStudioGUI
//处理非法文件名
var filename = FixFileName(j.Text);
//每个文件存放在单独的文件夹
var targetPath = $"{savePath}{filename}\\";
var targetPath = $"{savePath}{filename}{Path.DirectorySeparatorChar}";
//重名文件处理
for (int i = 1; ; i++)
{
if (Directory.Exists(targetPath))
{
targetPath = $"{savePath}{filename} ({i})\\";
targetPath = $"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}";
}
else
{
@@ -562,7 +562,7 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(savePath);
OpenFolderInExplorer(savePath);
}
StatusStripUpdate("Finished");
});
@@ -588,7 +588,7 @@ namespace AssetStudioGUI
ExportAnimator(animator, exportPath, animationList);
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(exportPath);
OpenFolderInExplorer(exportPath);
}
Progress.Report(1, 1);
StatusStripUpdate($"Finished exporting {animator.Text}");
@@ -630,7 +630,7 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(exportPath);
OpenFolderInExplorer(exportPath);
}
}
else
@@ -660,7 +660,7 @@ namespace AssetStudioGUI
}
if (Properties.Settings.Default.openAfterExport)
{
Process.Start(Path.GetDirectoryName(exportPath));
OpenFolderInExplorer(Path.GetDirectoryName(exportPath));
}
});
}
@@ -680,7 +680,7 @@ namespace AssetStudioGUI
}
}
public static List<TypeTreeNode> MonoBehaviourToTypeTreeNodes(MonoBehaviour m_MonoBehaviour)
public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour)
{
if (!assemblyLoader.Loaded)
{
@@ -695,7 +695,7 @@ namespace AssetStudioGUI
assemblyLoader.Loaded = true;
}
}
return m_MonoBehaviour.ConvertToTypeTreeNodes(assemblyLoader);
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
}
public static string DumpAsset(Object obj)
@@ -703,10 +703,17 @@ namespace AssetStudioGUI
var str = obj.Dump();
if (str == null && obj is MonoBehaviour m_MonoBehaviour)
{
var nodes = MonoBehaviourToTypeTreeNodes(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(nodes);
var type = MonoBehaviourToTypeTree(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(type);
}
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 readerParameters = new ReaderParameters();
readerParameters.AssemblyResolver = resolver;
try
foreach (var file in files)
{
foreach (var file in files)
try
{
var assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);
resolver.Register(assembly);
moduleDic.Add(assembly.MainModule.Name, assembly.MainModule);
}
}
catch
{
// ignored
catch
{
// ignored
}
}
Loaded = true;
}
+17 -102
View File
@@ -1,108 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{80AEC261-21EE-4E4F-A93B-7A744DC84888}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudioUtility</RootNamespace>
<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>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2018-2021</Copyright>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.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>
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta13" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyLoader.cs" />
<Compile Include="AudioClipConverter.cs" />
<Compile Include="CSspv\Disassembler.cs" />
<Compile Include="CSspv\EnumValuesExtensions.cs" />
<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" />
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj" />
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj" />
</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>
+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[] ConvertToBgra32Bytes(this Image<Bgra32> image)
{
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.
+108 -123
View File
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using TGASharpLib;
namespace AssetStudio
{
@@ -17,15 +14,16 @@ namespace AssetStudio
public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>();
public List<ImportedMorph> MorphList { get; protected set; } = new List<ImportedMorph>();
private string imageFormat;
private ImageFormat imageFormat;
private Avatar avatar;
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<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
private Dictionary<Transform, ImportedFrame> transformDictionary = new Dictionary<Transform, ImportedFrame>();
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;
if (m_GameObject.m_Animator != null)
@@ -50,7 +48,7 @@ namespace AssetStudio
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;
RootFrame = CreateFrame(rootName, Vector3.Zero, new Quaternion(0, 0, 0, 0), Vector3.One);
@@ -80,7 +78,7 @@ namespace AssetStudio
ConvertAnimations();
}
public ModelConverter(Animator m_Animator, string imageFormat, AnimationClip[] animationList = null)
public ModelConverter(Animator m_Animator, ImageFormat imageFormat, AnimationClip[] animationList = null)
{
this.imageFormat = imageFormat;
InitWithAnimator(m_Animator);
@@ -166,6 +164,10 @@ namespace AssetStudio
{
if (animation.TryGet(out var animationClip))
{
if (!boundAnimationPathDic.ContainsKey(animationClip))
{
boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform));
}
animationClipHashSet.Add(animationClip);
}
}
@@ -319,79 +321,8 @@ namespace AssetStudio
}
ImportedMaterial iMat = ConvertMaterial(mat);
iSubmesh.Material = iMat.Name;
iSubmesh.VertexList = new List<ImportedVertex>((int)submesh.vertexCount);
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);
}
iSubmesh.BaseVertex = (int)mesh.m_SubMeshes[i].firstVertex;
//Face
iSubmesh.FaceList = new List<ImportedFace>(numFaces);
var end = firstFace + numFaces;
@@ -405,9 +336,85 @@ namespace AssetStudio
iSubmesh.FaceList.Add(face);
}
firstFace = end;
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)
{
//Bone
@@ -524,7 +531,7 @@ namespace AssetStudio
keyframe.VertexList.Add(destVertex);
var morphVertex = mesh.m_Shapes.vertices[j];
destVertex.Index = morphVertex.index;
var sourceVertex = GetSourceVertex(iMesh.SubmeshList, (int)morphVertex.index);
var sourceVertex = iMesh.VertexList[(int)morphVertex.index];
destVertex.Vertex = new ImportedVertex();
var morphPos = morphVertex.vertex;
destVertex.Vertex.Vertex = sourceVertex.Vertex + new Vector3(-morphPos.X, morphPos.Y, morphPos.Z);
@@ -598,6 +605,15 @@ namespace AssetStudio
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)
{
var frame = RootFrame.FindFrameByPath(path);
@@ -694,7 +710,7 @@ namespace AssetStudio
texture.Dest = dest;
var ext = $".{imageFormat.ToLower()}";
var ext = $".{imageFormat.ToString().ToLower()}";
if (textureNameDictionary.TryGetValue(m_Texture2D, out var textureName))
{
texture.Name = textureName;
@@ -740,30 +756,13 @@ namespace AssetStudio
return;
}
var bitmap = m_Texture2D.ConvertToBitmap(true);
if (bitmap != null)
var stream = m_Texture2D.ConvertToStream(imageFormat, true);
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);
TextureList.Add(iTex);
bitmap.Dispose();
}
}
}
@@ -794,7 +793,7 @@ namespace AssetStudio
{
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 data = m_CompressedRotationCurve.m_Times.UnpackInts();
@@ -816,7 +815,7 @@ namespace AssetStudio
}
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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);
}
var path = FixBonePath(m_FloatCurve.path);
var path = FixBonePath(animationClip, m_FloatCurve.path);
if (string.IsNullOrEmpty(path))
{
path = GetPathByChannelName(channelName);
@@ -880,7 +879,7 @@ namespace AssetStudio
{
var m_Clip = animationClip.m_MuscleClip.m_Clip;
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++)
{
var frame = streamedFrames[frameIndex];
@@ -1014,20 +1013,6 @@ namespace AssetStudio
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)
{
var name = GetTransformPathByFather(m_Transform);
+2 -2
View File
@@ -3,9 +3,9 @@
public static class ModelExporter
{
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);
}
}
}
+6 -5
View File
@@ -4,21 +4,22 @@ namespace AssetStudio
{
public static class MonoBehaviourConverter
{
public static List<TypeTreeNode> ConvertToTypeTreeNodes(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader)
public static TypeTree ConvertToTypeTree(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader)
{
var nodes = new List<TypeTreeNode>();
var m_Type = new TypeTree();
m_Type.m_Nodes = new List<TypeTreeNode>();
var helper = new SerializedTypeHelper(m_MonoBehaviour.version);
helper.AddMonoBehaviour(nodes, 0);
helper.AddMonoBehaviour(m_Type.m_Nodes, 0);
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
var typeDef = assemblyLoader.GetTypeDefinition(m_Script.m_AssemblyName, string.IsNullOrEmpty(m_Script.m_Namespace) ? m_Script.m_ClassName : $"{m_Script.m_Namespace}.{m_Script.m_ClassName}");
if (typeDef != null)
{
var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1);
nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());
m_Type.m_Nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());
}
}
return nodes;
return m_Type;
}
}
}
@@ -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")]
+342 -72
View File
@@ -1,9 +1,10 @@
using System;
using K4os.Compression.LZ4;
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Lz4;
namespace AssetStudio
{
@@ -14,10 +15,7 @@ namespace AssetStudio
if (shader.m_SubProgramBlob != null) //5.3 - 5.4
{
var decompressedBytes = new byte[shader.decompressedSize];
using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob)))
{
decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
}
LZ4Codec.Decode(shader.m_SubProgramBlob, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
var program = new ShaderProgram(blobReader, shader.version);
@@ -41,10 +39,7 @@ namespace AssetStudio
var compressedBytes = new byte[shader.compressedLengths[i]];
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]);
}
LZ4Codec.Decode(compressedBytes, decompressedBytes);
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
{
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);
@@ -167,6 +162,13 @@ namespace AssetStudio
sb.Append(ConvertSerializedSubPrograms(m_Passe.progDomain.m_SubPrograms, platforms, shaderPrograms));
sb.Append("}\n");
}
if (m_Passe.progRayTracing?.m_SubPrograms.Length > 0)
{
sb.Append("Program \"rtp\" {\n");
sb.Append(ConvertSerializedSubPrograms(m_Passe.progRayTracing.m_SubPrograms, platforms, shaderPrograms));
sb.Append("}\n");
}
}
sb.Append("}\n");
}
@@ -222,7 +224,7 @@ namespace AssetStudio
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)
{
@@ -293,9 +295,111 @@ namespace AssetStudio
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.kFogUnknown ||
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.kFogUnknown)
{
sb.Append(" Mode ");
switch (m_State.fogMode)
{
case FogMode.kFogDisabled:
sb.Append("Off");
break;
case FogMode.kFogLinear:
sb.Append("Linear");
break;
case FogMode.kFogExp:
sb.Append("Exp");
break;
case FogMode.kFogExp2:
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)
{
@@ -307,27 +411,220 @@ namespace AssetStudio
return sb.ToString();
}
private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend)
private static string ConvertSerializedStencilOp(SerializedStencilOp stencilOp, string suffix)
{
//TODO Blend
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];
if (!blend.srcBlend.val.Equals(1f) ||
!blend.destBlend.val.Equals(0f) ||
!blend.srcBlendAlpha.val.Equals(1f) ||
!blend.destBlendAlpha.val.Equals(0f))
if (blend.srcBlend.val != 1f ||
blend.destBlend.val != 0f ||
blend.srcBlendAlpha.val != 1f ||
blend.destBlendAlpha.val != 0f)
{
sb.Append(" Blend ");
sb.Append($"{i} ");
sb.Append('\n');
if (i != 0 || rtSeparateBlend)
{
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();
}
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)
{
var sb = new StringBuilder();
@@ -436,12 +733,18 @@ namespace AssetStudio
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30;
case ShaderCompilerPlatform.kShaderCompPlatformXbox360:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
case ShaderCompilerPlatform.kShaderCompPlatformPS3:
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne:
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett:
case ShaderCompilerPlatform.kShaderCompPlatformPS5:
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
@@ -469,24 +772,6 @@ namespace AssetStudio
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES31
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES3;
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
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();
case ShaderCompilerPlatform.kShaderCompPlatformMetal:
@@ -496,32 +781,8 @@ namespace AssetStudio
return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43;
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|| 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:
throw new NotSupportedException();
}
@@ -573,6 +834,14 @@ namespace AssetStudio
return "switch";
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
return "xboxone_d3d12";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreXboxOne:
return "xboxone";
case ShaderCompilerPlatform.kShaderCompPlatformGameCoreScarlett:
return "xbox_scarlett";
case ShaderCompilerPlatform.kShaderCompPlatformPS5:
return "ps5";
case ShaderCompilerPlatform.kShaderCompPlatformPS5NGGC:
return "ps5_nggc";
default:
return "unknown";
}
@@ -640,7 +909,8 @@ namespace AssetStudio
//201609010 - Unity 5.6, 2017.1 & 2017.2
//201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1
//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_ProgramType = (ShaderGpuProgramType)reader.ReadInt32();
reader.BaseStream.Position += 12;
@@ -654,7 +924,7 @@ namespace AssetStudio
{
m_Keywords[i] = reader.ReadAlignedString();
}
if (m_Version >= 201806140)
if (m_Version >= 201806140 && m_Version < 202012090)
{
var m_LocalKeywordsSize = reader.ReadInt32();
m_LocalKeywords = new string[m_LocalKeywordsSize];
+44 -62
View File
@@ -1,15 +1,19 @@
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
namespace AssetStudio
{
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))
{
@@ -28,46 +32,37 @@ namespace AssetStudio
return null;
}
private static Bitmap CutImage(Texture2D m_Texture2D, Sprite m_Sprite, Rectf textureRect, Vector2 textureRectOffset, SpriteSettings settingsRaw)
private static Image<Bgra32> CutImage(Texture2D m_Texture2D, Sprite m_Sprite, Rectf textureRect, Vector2 textureRectOffset, SpriteSettings settingsRaw)
{
var originalImage = m_Texture2D.ConvertToBitmap(false);
var originalImage = m_Texture2D.ConvertToImage(false);
if (originalImage != null)
{
using (originalImage)
{
//var spriteImage = originalImage.Clone(textureRect, PixelFormat.Format32bppArgb);
var rectf = new RectangleF(textureRect.x, textureRect.y, textureRect.width, textureRect.height);
var rect = Rectangle.Round(rectf);
if (rect.Width == 0)
{
rect.Width = 1;
}
if (rect.Height == 0)
{
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, m_Texture2D.m_Width);
rectBottom = Math.Min(rectBottom, m_Texture2D.m_Height);
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
var spriteImage = originalImage.Clone(x => x.Crop(rect));
if (settingsRaw.packed == 1)
{
//RotateAndFlip
switch (settingsRaw.packingRotation)
{
case SpritePackingRotation.kSPRFlipHorizontal:
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
spriteImage.Mutate(x => x.Flip(FlipMode.Horizontal));
break;
case SpritePackingRotation.kSPRFlipVertical:
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
break;
case SpritePackingRotation.kSPRRotate180:
spriteImage.RotateFlip(RotateFlipType.Rotate180FlipNone);
spriteImage.Mutate(x => x.Rotate(180));
break;
case SpritePackingRotation.kSPRRotate90:
spriteImage.RotateFlip(RotateFlipType.Rotate270FlipNone);
spriteImage.Mutate(x => x.Rotate(270));
break;
}
}
@@ -78,40 +73,27 @@ namespace AssetStudio
try
{
var triangles = GetTriangles(m_Sprite.m_RD);
var points = triangles.Select(x => x.Select(y => new PointF(y.X, y.Y)).ToArray());
using (var path = new GraphicsPath())
var polygons = triangles.Select(x => new Polygon(new LinearLineSegment(x.Select(y => new PointF(y.X, y.Y)).ToArray()))).ToArray();
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)
{
path.AddPolygon(p);
}
using (var matr = new Matrix())
{
var version = m_Sprite.version;
if (version[0] < 5
|| (version[0] == 5 && version[1] < 4)
|| (version[0] == 5 && version[1] == 4 && version[2] <= 1)) //5.4.1p3 down
{
matr.Translate(m_Sprite.m_Rect.width * 0.5f - textureRectOffset.X, m_Sprite.m_Rect.height * 0.5f - textureRectOffset.Y);
}
else
{
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;
}
}
}
Antialias = false,
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
};
var options = new DrawingOptions
{
GraphicsOptions = graphicsOptions
};
using (var mask = new Image<Bgra32>(rect.Width, rect.Height, SixLabors.ImageSharp.Color.Black))
{
mask.Mutate(x => x.Fill(options, SixLabors.ImageSharp.Color.Red, path));
var bursh = new ImageBrush(mask);
spriteImage.Mutate(x => x.Fill(graphicsOptions, bursh));
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
return spriteImage;
}
}
catch
@@ -121,7 +103,7 @@ namespace AssetStudio
}
//Rectangle
spriteImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
return spriteImage;
}
}
File diff suppressed because it is too large Load Diff
+197 -285
View File
@@ -1,26 +1,20 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using Texture2DDecoder;
namespace AssetStudio
{
public class Texture2DConverter
{
private ResourceReader reader;
private int m_Width;
private int m_Height;
private TextureFormat m_TextureFormat;
private int image_data_size;
private byte[] image_data;
private int[] version;
private BuildTarget platform;
public Texture2DConverter(Texture2D m_Texture2D)
{
image_data = m_Texture2D.image_data.GetData();
image_data_size = image_data.Length;
reader = m_Texture2D.image_data;
m_Width = m_Texture2D.m_Width;
m_Height = m_Texture2D.m_Height;
m_TextureFormat = m_Texture2D.m_TextureFormat;
@@ -28,213 +22,188 @@ namespace AssetStudio
platform = m_Texture2D.platform;
}
public Bitmap ConvertToBitmap(bool flip)
public bool DecodeTexture2D(byte[] bytes)
{
if (image_data == null || image_data.Length == 0)
return null;
var buff = DecodeTexture2D();
if (buff == null)
if (reader.Size == 0 || m_Width == 0 || m_Height == 0)
{
return null;
return false;
}
var bitmap = new Bitmap(m_Width, m_Height, PixelFormat.Format32bppArgb);
var bmpData = bitmap.LockBits(new Rectangle(0, 0, m_Width, m_Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(buff, 0, bmpData.Scan0, buff.Length);
bitmap.UnlockBits(bmpData);
if (flip)
{
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
}
return bitmap;
}
public byte[] DecodeTexture2D()
{
byte[] bytes = null;
var flag = false;
var buff = BigArrayPool<byte>.Shared.Rent(reader.Size);
reader.GetData(buff);
switch (m_TextureFormat)
{
case TextureFormat.Alpha8: //test pass
bytes = DecodeAlpha8();
flag = DecodeAlpha8(buff, bytes);
break;
case TextureFormat.ARGB4444: //test pass
SwapBytesForXbox();
bytes = DecodeARGB4444();
SwapBytesForXbox(buff);
flag = DecodeARGB4444(buff, bytes);
break;
case TextureFormat.RGB24: //test pass
bytes = DecodeRGB24();
flag = DecodeRGB24(buff, bytes);
break;
case TextureFormat.RGBA32: //test pass
bytes = DecodeRGBA32();
flag = DecodeRGBA32(buff, bytes);
break;
case TextureFormat.ARGB32: //test pass
bytes = DecodeARGB32();
flag = DecodeARGB32(buff, bytes);
break;
case TextureFormat.RGB565: //test pass
SwapBytesForXbox();
bytes = DecodeRGB565();
SwapBytesForXbox(buff);
flag = DecodeRGB565(buff, bytes);
break;
case TextureFormat.R16: //test pass
bytes = DecodeR16();
flag = DecodeR16(buff, bytes);
break;
case TextureFormat.DXT1: //test pass
SwapBytesForXbox();
bytes = DecodeDXT1();
SwapBytesForXbox(buff);
flag = DecodeDXT1(buff, bytes);
break;
case TextureFormat.DXT5: //test pass
SwapBytesForXbox();
bytes = DecodeDXT5();
SwapBytesForXbox(buff);
flag = DecodeDXT5(buff, bytes);
break;
case TextureFormat.RGBA4444: //test pass
bytes = DecodeRGBA4444();
flag = DecodeRGBA4444(buff, bytes);
break;
case TextureFormat.BGRA32: //test pass
bytes = DecodeBGRA32();
flag = DecodeBGRA32(buff, bytes);
break;
case TextureFormat.RHalf:
bytes = DecodeRHalf();
flag = DecodeRHalf(buff, bytes);
break;
case TextureFormat.RGHalf:
bytes = DecodeRGHalf();
flag = DecodeRGHalf(buff, bytes);
break;
case TextureFormat.RGBAHalf: //test pass
bytes = DecodeRGBAHalf();
flag = DecodeRGBAHalf(buff, bytes);
break;
case TextureFormat.RFloat:
bytes = DecodeRFloat();
flag = DecodeRFloat(buff, bytes);
break;
case TextureFormat.RGFloat:
bytes = DecodeRGFloat();
flag = DecodeRGFloat(buff, bytes);
break;
case TextureFormat.RGBAFloat:
bytes = DecodeRGBAFloat();
flag = DecodeRGBAFloat(buff, bytes);
break;
case TextureFormat.YUY2: //test pass
bytes = DecodeYUY2();
flag = DecodeYUY2(buff, bytes);
break;
case TextureFormat.RGB9e5Float: //test pass
bytes = DecodeRGB9e5Float();
flag = DecodeRGB9e5Float(buff, bytes);
break;
case TextureFormat.BC4: //test pass
bytes = DecodeBC4();
flag = DecodeBC4(buff, bytes);
break;
case TextureFormat.BC5: //test pass
bytes = DecodeBC5();
flag = DecodeBC5(buff, bytes);
break;
case TextureFormat.BC6H: //test pass
bytes = DecodeBC6H();
flag = DecodeBC6H(buff, bytes);
break;
case TextureFormat.BC7: //test pass
bytes = DecodeBC7();
flag = DecodeBC7(buff, bytes);
break;
case TextureFormat.DXT1Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeDXT1();
}
flag = DecodeDXT1Crunched(buff, bytes);
break;
case TextureFormat.DXT5Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeDXT5();
}
flag = DecodeDXT5Crunched(buff, bytes);
break;
case TextureFormat.PVRTC_RGB2: //test pass
case TextureFormat.PVRTC_RGBA2: //test pass
bytes = DecodePVRTC(true);
flag = DecodePVRTC(buff, bytes, true);
break;
case TextureFormat.PVRTC_RGB4: //test pass
case TextureFormat.PVRTC_RGBA4: //test pass
bytes = DecodePVRTC(false);
flag = DecodePVRTC(buff, bytes, false);
break;
case TextureFormat.ETC_RGB4: //test pass
case TextureFormat.ETC_RGB4_3DS:
bytes = DecodeETC1();
flag = DecodeETC1(buff, bytes);
break;
case TextureFormat.ATC_RGB4: //test pass
bytes = DecodeATCRGB4();
flag = DecodeATCRGB4(buff, bytes);
break;
case TextureFormat.ATC_RGBA8: //test pass
bytes = DecodeATCRGBA8();
flag = DecodeATCRGBA8(buff, bytes);
break;
case TextureFormat.EAC_R: //test pass
bytes = DecodeEACR();
flag = DecodeEACR(buff, bytes);
break;
case TextureFormat.EAC_R_SIGNED:
bytes = DecodeEACRSigned();
flag = DecodeEACRSigned(buff, bytes);
break;
case TextureFormat.EAC_RG: //test pass
bytes = DecodeEACRG();
flag = DecodeEACRG(buff, bytes);
break;
case TextureFormat.EAC_RG_SIGNED:
bytes = DecodeEACRGSigned();
flag = DecodeEACRGSigned(buff, bytes);
break;
case TextureFormat.ETC2_RGB: //test pass
bytes = DecodeETC2();
flag = DecodeETC2(buff, bytes);
break;
case TextureFormat.ETC2_RGBA1: //test pass
bytes = DecodeETC2A1();
flag = DecodeETC2A1(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8: //test pass
case TextureFormat.ETC_RGBA8_3DS:
bytes = DecodeETC2A8();
flag = DecodeETC2A8(buff, bytes);
break;
case TextureFormat.ASTC_RGB_4x4: //test pass
case TextureFormat.ASTC_RGBA_4x4: //test pass
case TextureFormat.ASTC_HDR_4x4: //test pass
bytes = DecodeASTC(4);
flag = DecodeASTC(buff, bytes, 4);
break;
case TextureFormat.ASTC_RGB_5x5: //test pass
case TextureFormat.ASTC_RGBA_5x5: //test pass
case TextureFormat.ASTC_HDR_5x5: //test pass
bytes = DecodeASTC(5);
flag = DecodeASTC(buff, bytes, 5);
break;
case TextureFormat.ASTC_RGB_6x6: //test pass
case TextureFormat.ASTC_RGBA_6x6: //test pass
case TextureFormat.ASTC_HDR_6x6: //test pass
bytes = DecodeASTC(6);
flag = DecodeASTC(buff, bytes, 6);
break;
case TextureFormat.ASTC_RGB_8x8: //test pass
case TextureFormat.ASTC_RGBA_8x8: //test pass
case TextureFormat.ASTC_HDR_8x8: //test pass
bytes = DecodeASTC(8);
flag = DecodeASTC(buff, bytes, 8);
break;
case TextureFormat.ASTC_RGB_10x10: //test pass
case TextureFormat.ASTC_RGBA_10x10: //test pass
case TextureFormat.ASTC_HDR_10x10: //test pass
bytes = DecodeASTC(10);
flag = DecodeASTC(buff, bytes, 10);
break;
case TextureFormat.ASTC_RGB_12x12: //test pass
case TextureFormat.ASTC_RGBA_12x12: //test pass
case TextureFormat.ASTC_HDR_12x12: //test pass
bytes = DecodeASTC(12);
flag = DecodeASTC(buff, bytes, 12);
break;
case TextureFormat.RG16: //test pass
bytes = DecodeRG16();
flag = DecodeRG16(buff, bytes);
break;
case TextureFormat.R8: //test pass
bytes = DecodeR8();
flag = DecodeR8(buff, bytes);
break;
case TextureFormat.ETC_RGB4Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeETC1();
}
flag = DecodeETC1Crunched(buff, bytes);
break;
case TextureFormat.ETC2_RGBA8Crunched: //test pass
if (UnpackCrunch())
{
bytes = DecodeETC2A8();
}
flag = DecodeETC2A8Crunched(buff, bytes);
break;
}
return bytes;
BigArrayPool<byte>.Shared.Return(buff);
return flag;
}
private void SwapBytesForXbox()
private void SwapBytesForXbox(byte[] image_data)
{
if (platform == BuildTarget.XBOX360)
{
for (var i = 0; i < image_data_size / 2; i++)
for (var i = 0; i < reader.Size / 2; i++)
{
var b = image_data[i * 2];
image_data[i * 2] = image_data[i * 2 + 1];
@@ -243,22 +212,22 @@ namespace AssetStudio
}
}
private byte[] DecodeAlpha8()
private bool DecodeAlpha8(byte[] image_data, byte[] buff)
{
var buff = Enumerable.Repeat<byte>(0xFF, m_Width * m_Height * 4).ToArray();
var span = new Span<byte>(buff);
span.Fill(0xFF);
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4 + 3] = image_data[i];
}
return buff;
return true;
}
private byte[] DecodeARGB4444()
private bool DecodeARGB4444(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
{
var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)(pixelOldShort & 0x000f);
pixelNew[1] = (byte)((pixelOldShort & 0x00f0) >> 4);
@@ -268,12 +237,11 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
return buff;
return true;
}
private byte[] DecodeRGB24()
private bool DecodeRGB24(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4] = image_data[i * 3 + 2];
@@ -281,12 +249,11 @@ namespace AssetStudio
buff[i * 4 + 2] = image_data[i * 3 + 0];
buff[i * 4 + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBA32()
private bool DecodeRGBA32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i + 2];
@@ -294,12 +261,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 0];
buff[i + 3] = image_data[i + 3];
}
return buff;
return true;
}
private byte[] DecodeARGB32()
private bool DecodeARGB32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i + 3];
@@ -307,12 +273,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 1];
buff[i + 3] = image_data[i + 0];
}
return buff;
return true;
}
private byte[] DecodeRGB565()
private bool DecodeRGB565(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
var p = BitConverter.ToUInt16(image_data, i * 2);
@@ -321,46 +286,36 @@ namespace AssetStudio
buff[i * 4 + 2] = (byte)((p >> 8 & 0xf8) | (p >> 13));
buff[i * 4 + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeR16()
private bool DecodeR16(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4] = 0; //b
buff[i * 4 + 1] = 0; //g
buff[i * 4 + 2] = image_data[i * 2 + 1]; //r
buff[i * 4 + 3] = 255; //a
}
return buff;
return true;
}
private byte[] DecodeDXT1()
private bool DecodeDXT1(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeDXT1(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeDXT5()
private bool DecodeDXT5(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeDXT5(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeRGBA4444()
private bool DecodeRGBA4444(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
var pixelNew = new byte[4];
for (var i = 0; i < m_Width * m_Height; i++)
{
var pixelNew = new byte[4];
var pixelOldShort = BitConverter.ToUInt16(image_data, i * 2);
pixelNew[0] = (byte)((pixelOldShort & 0x00f0) >> 4);
pixelNew[1] = (byte)((pixelOldShort & 0x0f00) >> 8);
@@ -370,12 +325,11 @@ namespace AssetStudio
pixelNew[j] = (byte)((pixelNew[j] << 4) | pixelNew[j]);
pixelNew.CopyTo(buff, i * 4);
}
return buff;
return true;
}
private byte[] DecodeBGRA32()
private bool DecodeBGRA32(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = image_data[i];
@@ -383,12 +337,11 @@ namespace AssetStudio
buff[i + 2] = image_data[i + 2];
buff[i + 3] = image_data[i + 3];
}
return buff;
return true;
}
private byte[] DecodeRHalf()
private bool DecodeRHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -396,12 +349,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i / 2) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGHalf()
private bool DecodeRGHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -409,12 +361,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBAHalf()
private bool DecodeRGBAHalf(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 4) * 255f);
@@ -422,12 +373,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(Half.ToHalf(image_data, i * 2) * 255f);
buff[i + 3] = (byte)Math.Round(Half.ToHalf(image_data, i * 2 + 6) * 255f);
}
return buff;
return true;
}
private byte[] DecodeRFloat()
private bool DecodeRFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -435,12 +385,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGFloat()
private bool DecodeRGFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = 0;
@@ -448,12 +397,11 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 2) * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeRGBAFloat()
private bool DecodeRGBAFloat(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
buff[i] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 8) * 255f);
@@ -461,7 +409,7 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4) * 255f);
buff[i + 3] = (byte)Math.Round(BitConverter.ToSingle(image_data, i * 4 + 12) * 255f);
}
return buff;
return true;
}
private static byte ClampByte(int x)
@@ -469,9 +417,8 @@ namespace AssetStudio
return (byte)(byte.MaxValue < x ? byte.MaxValue : (x > byte.MinValue ? x : byte.MinValue));
}
private byte[] DecodeYUY2()
private bool DecodeYUY2(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
int p = 0;
int o = 0;
int halfWidth = m_Width / 2;
@@ -497,12 +444,11 @@ namespace AssetStudio
buff[o++] = 255;
}
}
return buff;
return true;
}
private byte[] DecodeRGB9e5Float()
private bool DecodeRGB9e5Float(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < buff.Length; i += 4)
{
var n = BitConverter.ToInt32(image_data, i);
@@ -516,195 +462,163 @@ namespace AssetStudio
buff[i + 2] = (byte)Math.Round(r * scalef * 255f);
buff[i + 3] = 255;
}
return buff;
return true;
}
private byte[] DecodeBC4()
private bool DecodeBC4(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff))
return TextureDecoder.DecodeBC4(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC5(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC6H(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff);
}
private bool DecodeBC7(byte[] image_data, byte[] buff)
{
return TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff);
}
private bool DecodeDXT1Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
return null;
if (DecodeDXT1(result, buff))
{
return true;
}
}
return buff;
return false;
}
private byte[] DecodeBC5()
private bool DecodeDXT5Crunched(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC5(image_data, m_Width, m_Height, buff))
if (UnpackCrunch(image_data, out var result))
{
return null;
if (DecodeDXT5(result, buff))
{
return true;
}
}
return buff;
return false;
}
private byte[] DecodeBC6H()
private bool DecodePVRTC(byte[] image_data, byte[] buff, bool is2bpp)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC6(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp);
}
private byte[] DecodeBC7()
private bool DecodeETC1(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeBC7(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff);
}
private byte[] DecodePVRTC(bool is2bpp)
private bool DecodeATCRGB4(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodePVRTC(image_data, m_Width, m_Height, buff, is2bpp))
{
return null;
}
return buff;
return TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeETC1()
private bool DecodeATCRGBA8(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeATCRGB4()
private bool DecodeEACR(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeATCRGB4(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeATCRGBA8()
private bool DecodeEACRSigned(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeATCRGBA8(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeEACR()
private bool DecodeEACRG(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACR(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeEACRSigned()
private bool DecodeEACRGSigned(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRSigned(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeEACRG()
private bool DecodeETC2(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRG(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeEACRGSigned()
private bool DecodeETC2A1(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeEACRGSigned(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeETC2()
private bool DecodeETC2A8(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff);
}
private byte[] DecodeETC2A1()
private bool DecodeASTC(byte[] image_data, byte[] buff, int blocksize)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2A1(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
return TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff);
}
private byte[] DecodeETC2A8()
private bool DecodeRG16(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeETC2A8(image_data, m_Width, m_Height, buff))
{
return null;
}
return buff;
}
private byte[] DecodeASTC(int blocksize)
{
var buff = new byte[m_Width * m_Height * 4];
if (!TextureDecoder.DecodeASTC(image_data, m_Width, m_Height, blocksize, blocksize, buff))
{
return null;
}
return buff;
}
private byte[] DecodeRG16()
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i += 2)
{
buff[i * 2] = 0; //B
buff[i * 2 + 1] = image_data[i + 1];//G
buff[i * 2 + 2] = image_data[i];//R
buff[i * 2 + 3] = 255;//A
}
return buff;
return true;
}
private byte[] DecodeR8()
private bool DecodeR8(byte[] image_data, byte[] buff)
{
var buff = new byte[m_Width * m_Height * 4];
for (var i = 0; i < m_Width * m_Height; i++)
{
buff[i * 4] = 0; //B
buff[i * 4 + 1] = 0; //G
buff[i * 4 + 2] = image_data[i];//R
buff[i * 4 + 3] = 255;//A
}
return buff;
return true;
}
private bool UnpackCrunch()
private bool DecodeETC1Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
if (DecodeETC1(result, buff))
{
return true;
}
}
return false;
}
private bool DecodeETC2A8Crunched(byte[] image_data, byte[] buff)
{
if (UnpackCrunch(image_data, out var result))
{
if (DecodeETC2A8(result, buff))
{
return true;
}
}
return false;
}
private bool UnpackCrunch(byte[] image_data, out byte[] result)
{
byte[] result;
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up
|| m_TextureFormat == TextureFormat.ETC_RGB4Crunched
|| m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched)
@@ -717,8 +631,6 @@ namespace AssetStudio
}
if (result != null)
{
image_data = result;
image_data_size = result.Length;
return true;
}
return false;
+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
{
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);
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;
}
}
}
+34 -53
View File
@@ -26,22 +26,22 @@ namespace AssetStudio
{
var nodes = new List<TypeTreeNode>();
Stack<TypeReference> baseTypes = new Stack<TypeReference>();
TypeReference baseType = TypeDef.BaseType;
while (!UnitySerializationLogic.IsNonSerialized(baseType))
var baseTypes = new Stack<TypeReference>();
var lastBaseType = TypeDef.BaseType;
while (!UnitySerializationLogic.IsNonSerialized(lastBaseType))
{
GenericInstanceType genericInstanceType = baseType as GenericInstanceType;
var genericInstanceType = lastBaseType as GenericInstanceType;
if (genericInstanceType != null)
{
TypeResolver.Add(genericInstanceType);
}
baseTypes.Push(baseType);
baseType = baseType.Resolve().BaseType;
baseTypes.Push(lastBaseType);
lastBaseType = lastBaseType.Resolve().BaseType;
}
while (baseTypes.Count > 0)
{
TypeReference typeReference = baseTypes.Pop();
TypeDefinition typeDefinition = typeReference.Resolve();
var typeReference = baseTypes.Pop();
var typeDefinition = typeReference.Resolve();
foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize))
{
if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef))
@@ -50,15 +50,15 @@ namespace AssetStudio
}
}
var genericInstanceType2 = typeReference as GenericInstanceType;
if (genericInstanceType2 != null)
var genericInstanceType = typeReference as GenericInstanceType;
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;
@@ -66,75 +66,60 @@ namespace AssetStudio
private bool WillUnitySerialize(FieldDefinition fieldDefinition)
{
bool result;
try
{
TypeReference typeReference = TypeResolver.Resolve(fieldDefinition.FieldType);
if (UnitySerializationLogic.ShouldNotTryToResolve(typeReference))
var resolvedFieldType = TypeResolver.Resolve(fieldDefinition.FieldType);
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)
{
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)
{
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()
{
foreach (var f in TypeDef.Fields.Where(WillUnitySerialize))
{
if (UnitySerializationLogic.IsSupportedCollection(f.FieldType) || !f.FieldType.IsGenericInstance || UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()))
{
yield return f;
}
}
yield break;
return TypeDef.Fields.Where(WillUnitySerialize).Where(f =>
UnitySerializationLogic.IsSupportedCollection(f.FieldType) ||
!f.FieldType.IsGenericInstance ||
UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()));
}
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);
}
private TypeReference ResolveDeclaringType(TypeReference declaringType)
{
TypeDefinition typeDefinition = declaringType.Resolve();
TypeReference result;
var typeDefinition = declaringType.Resolve();
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);
foreach (GenericParameter item in typeDefinition.GenericParameters)
{
genericInstanceType.GenericArguments.Add(item);
}
result = TypeResolver.Resolve(genericInstanceType);
genericInstanceType.GenericArguments.Add(genericParameter);
}
return result;
return TypeResolver.Resolve(genericInstanceType);
}
private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef)
@@ -155,7 +140,6 @@ namespace AssetStudio
private static bool RequiresAlignment(TypeReference typeRef)
{
bool result;
switch (typeRef.MetadataType)
{
case MetadataType.Boolean:
@@ -164,13 +148,10 @@ namespace AssetStudio
case MetadataType.Byte:
case MetadataType.Int16:
case MetadataType.UInt16:
result = true;
break;
return true;
default:
result = (UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef)));
break;
return UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef));
}
return result;
}
private static bool IsSystemString(TypeReference typeRef)
@@ -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
* Support version:
* 2.5 - 2021.1
* 3.4 - 2021.2
* Support asset types:
* **Texture2D** : convert 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
- [.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
@@ -63,8 +69,8 @@ First, use my another program [Il2CppDumper](https://github.com/Perfare/Il2CppDu
## Build
* Visual Studio 2019 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
* Visual Studio 2022 or newer
* **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
@@ -67,26 +67,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</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,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{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>
<TargetFrameworks>net472;netstandard2.0;net5.0;net6.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.16.0.0</Version>
<AssemblyVersion>0.16.0.0</AssemblyVersion>
<FileVersion>0.16.0.0</FileVersion>
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
</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>