Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 97b5f51f3a | |||
| 7295feda72 | |||
| fe95c91759 | |||
| d220315d9b | |||
| a94caa5e34 | |||
| 3660b4ed67 | |||
| 3370f93037 | |||
| 80653711cd | |||
| 88c5804586 | |||
| e501940f03 | |||
| d4060cde6d | |||
| 582a779441 | |||
| 5fa4934787 | |||
| 18277fbea8 | |||
| 2ce9cae957 | |||
| af5e50cfa9 | |||
| ce1172ca9a | |||
| a7e6d91f5b | |||
| 34a0af683a | |||
| 91410a33b1 | |||
| d08b78c2cf | |||
| 2ef52afe1e | |||
| 05a41d2f1e | |||
| 34c38e1415 | |||
| c85873b729 | |||
| b146d251a7 | |||
| 3129d67fc1 | |||
| 850ba63a10 | |||
| 17b91984d6 | |||
| 7ab2cda120 | |||
| 4345885cc9 | |||
| 53720e37ab | |||
| 7c3cb36630 | |||
| c1cddce031 | |||
| 973a1076e4 | |||
| 089e164756 | |||
| c2b6691fd9 | |||
| 8dec094304 | |||
| bedee240be | |||
| d963d71b12 | |||
| 77a0c9c40a | |||
| f3e406983b | |||
| 08b7bfcf9a | |||
| 57e4f7cefd | |||
| c9cf2d188e |
@@ -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
@@ -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
-145
@@ -1,149 +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="SerializedFileFormatVersion.cs" />
|
||||
<Compile Include="SerializedFileHeader.cs" />
|
||||
<Compile Include="SerializedType.cs" />
|
||||
<Compile Include="SevenZipHelper.cs" />
|
||||
<Compile Include="StreamFile.cs" />
|
||||
<Compile Include="TypeTree.cs" />
|
||||
<Compile Include="TypeTreeHelper.cs" />
|
||||
<Compile Include="TypeTreeNode.cs" />
|
||||
<Compile Include="WebFile.cs" />
|
||||
|
||||
<ItemGroup 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>
|
||||
|
||||
@@ -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 < SerializedFileFormatVersion.kUnknown_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))
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -427,10 +427,9 @@ namespace AssetStudio
|
||||
m_Size = reader.ReadInt32();
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x
|
||||
(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 to 2021.1.x
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
{
|
||||
m_IsPartialCB = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
@@ -583,7 +582,7 @@ namespace AssetStudio
|
||||
m_BlobIndex = reader.ReadUInt32();
|
||||
m_Channels = new ParserBindChannels(reader);
|
||||
|
||||
if (version[0] >= 2019) //2019 and up
|
||||
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
|
||||
{
|
||||
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -604,10 +603,9 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x
|
||||
(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 to 2021.1.x
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
{
|
||||
m_Parameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
@@ -704,10 +702,9 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] > 0) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] == 0 && version[3] >= 2) || //2020.3.0f2 to 2020.3.x
|
||||
(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 to 2021.1.x
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
{
|
||||
m_CommonParameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
@@ -742,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)
|
||||
{
|
||||
@@ -758,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();
|
||||
@@ -793,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -859,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;
|
||||
@@ -879,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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,540 +0,0 @@
|
||||
#define CHECK_ARGS
|
||||
#define CHECK_EOF
|
||||
//#define LOCAL_SHADOW
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Lz4
|
||||
{
|
||||
public class Lz4DecoderStream : Stream
|
||||
{
|
||||
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
Reset(input, inputLength);
|
||||
}
|
||||
|
||||
private void Reset(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
this.inputLength = inputLength;
|
||||
this.input = input;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
|
||||
decodeBufferPos = 0;
|
||||
|
||||
litLen = 0;
|
||||
matLen = 0;
|
||||
matDst = 0;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing && input != null)
|
||||
{
|
||||
input.Close();
|
||||
}
|
||||
input = null;
|
||||
decodeBuffer = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
private long inputLength;
|
||||
private Stream input;
|
||||
|
||||
//because we might not be able to match back across invocations,
|
||||
//we have to keep the last window's worth of bytes around for reuse
|
||||
//we use a circular buffer for this - every time we write into this
|
||||
//buffer, we also write the same into our output buffer
|
||||
|
||||
private const int DecBufLen = 0x10000;
|
||||
private const int DecBufMask = 0xFFFF;
|
||||
|
||||
private const int InBufLen = 128;
|
||||
|
||||
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
|
||||
private int decodeBufferPos, inBufPos, inBufEnd;
|
||||
|
||||
//we keep track of which phase we're in so that we can jump right back
|
||||
//into the correct part of decoding
|
||||
|
||||
private DecodePhase phase;
|
||||
|
||||
private enum DecodePhase
|
||||
{
|
||||
ReadToken,
|
||||
ReadExLiteralLength,
|
||||
CopyLiteral,
|
||||
ReadOffset,
|
||||
ReadExMatchLength,
|
||||
CopyMatch,
|
||||
}
|
||||
|
||||
//state within interruptable phases and across phase boundaries is
|
||||
//kept here - again, so that we can punt out and restart freely
|
||||
|
||||
private int litLen, matLen, matDst;
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
#if CHECK_ARGS
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset < 0 || count < 0 || buffer.Length - count < offset)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
if (input == null)
|
||||
throw new InvalidOperationException();
|
||||
#endif
|
||||
int nRead, nToRead = count;
|
||||
|
||||
var decBuf = decodeBuffer;
|
||||
|
||||
//the stringy gotos are obnoxious, but their purpose is to
|
||||
//make it *blindingly* obvious how the state machine transitions
|
||||
//back and forth as it reads - remember, we can yield out of
|
||||
//this routine in several places, and we must be able to re-enter
|
||||
//and pick up where we left off!
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
var phase = this.phase;
|
||||
var inBufPos = this.inBufPos;
|
||||
var inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
switch (phase)
|
||||
{
|
||||
case DecodePhase.ReadToken:
|
||||
goto readToken;
|
||||
|
||||
case DecodePhase.ReadExLiteralLength:
|
||||
goto readExLiteralLength;
|
||||
|
||||
case DecodePhase.CopyLiteral:
|
||||
goto copyLiteral;
|
||||
|
||||
case DecodePhase.ReadOffset:
|
||||
goto readOffset;
|
||||
|
||||
case DecodePhase.ReadExMatchLength:
|
||||
goto readExMatchLength;
|
||||
|
||||
case DecodePhase.CopyMatch:
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readToken:
|
||||
int tok;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
tok = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
|
||||
tok = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (tok == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen = tok >> 4;
|
||||
matLen = (tok & 0xF) + 4;
|
||||
|
||||
switch (litLen)
|
||||
{
|
||||
case 0:
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
case 0xF:
|
||||
phase = DecodePhase.ReadExLiteralLength;
|
||||
goto readExLiteralLength;
|
||||
|
||||
default:
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
readExLiteralLength:
|
||||
int exLitLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exLitLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exLitLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
|
||||
#if CHECK_EOF
|
||||
if (exLitLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen += exLitLen;
|
||||
if (exLitLen == 255)
|
||||
goto readExLiteralLength;
|
||||
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
|
||||
copyLiteral:
|
||||
int nReadLit = litLen < nToRead ? litLen : nToRead;
|
||||
if (nReadLit != 0)
|
||||
{
|
||||
if (inBufPos + nReadLit <= inBufEnd)
|
||||
{
|
||||
int ofs = offset;
|
||||
|
||||
for (int c = nReadLit; c-- != 0;)
|
||||
buffer[ofs++] = decBuf[inBufPos++];
|
||||
|
||||
nRead = nReadLit;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
nRead = ReadCore(buffer, offset, nReadLit);
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
offset += nRead;
|
||||
nToRead -= nRead;
|
||||
|
||||
litLen -= nRead;
|
||||
|
||||
if (litLen != 0)
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
readOffset:
|
||||
if (inBufPos + 1 < inBufEnd)
|
||||
{
|
||||
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
|
||||
inBufPos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
matDst = ReadOffsetCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (matDst == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (matLen == 15 + 4)
|
||||
{
|
||||
phase = DecodePhase.ReadExMatchLength;
|
||||
goto readExMatchLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readExMatchLength:
|
||||
int exMatLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exMatLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exMatLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (exMatLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
matLen += exMatLen;
|
||||
if (exMatLen == 255)
|
||||
goto readExMatchLength;
|
||||
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
|
||||
copyMatch:
|
||||
int nCpyMat = matLen < nToRead ? matLen : nToRead;
|
||||
if (nCpyMat != 0)
|
||||
{
|
||||
nRead = count - nToRead;
|
||||
|
||||
int bufDst = matDst - nRead;
|
||||
if (bufDst > 0)
|
||||
{
|
||||
//offset is fairly far back, we need to pull from the buffer
|
||||
|
||||
int bufSrc = decodeBufferPos - bufDst;
|
||||
if (bufSrc < 0)
|
||||
bufSrc += DecBufLen;
|
||||
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
|
||||
|
||||
for (int c = bufCnt; c-- != 0;)
|
||||
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
|
||||
}
|
||||
else
|
||||
{
|
||||
bufDst = 0;
|
||||
}
|
||||
|
||||
int sOfs = offset - matDst;
|
||||
for (int i = bufDst; i < nCpyMat; i++)
|
||||
buffer[offset++] = buffer[sOfs++];
|
||||
|
||||
nToRead -= nCpyMat;
|
||||
matLen -= nCpyMat;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
goto readToken;
|
||||
|
||||
finish:
|
||||
nRead = count - nToRead;
|
||||
|
||||
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
|
||||
int repPos = offset - nToBuf;
|
||||
|
||||
if (nToBuf == DecBufLen)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
|
||||
decodeBufferPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int decPos = decodeBufferPos;
|
||||
|
||||
while (nToBuf-- != 0)
|
||||
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
|
||||
|
||||
decodeBufferPos = decPos & DecBufMask;
|
||||
}
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
this.phase = phase;
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
return nRead;
|
||||
}
|
||||
|
||||
private int ReadByteCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
return buf[inBufPos++];
|
||||
}
|
||||
|
||||
private int ReadOffsetCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
if (inBufEnd - inBufPos == 1)
|
||||
{
|
||||
buf[DecBufLen] = buf[inBufPos];
|
||||
|
||||
int nRead = input.Read(buf, DecBufLen + 1,
|
||||
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
{
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead + 1;
|
||||
}
|
||||
|
||||
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
|
||||
inBufPos += 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int ReadCore(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int nToRead = count;
|
||||
|
||||
var buf = decodeBuffer;
|
||||
int inBufLen = inBufEnd - inBufPos;
|
||||
|
||||
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
|
||||
if (fromBuf != 0)
|
||||
{
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
if (nToRead != 0)
|
||||
{
|
||||
int nRead;
|
||||
|
||||
if (nToRead >= InBufLen)
|
||||
{
|
||||
nRead = input.Read(buffer, offset,
|
||||
nToRead < inputLength ? nToRead : (int)inputLength);
|
||||
nToRead -= nRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
|
||||
fromBuf = nToRead < nRead ? nToRead : nRead;
|
||||
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
inputLength -= nRead;
|
||||
}
|
||||
|
||||
return count - nToRead;
|
||||
}
|
||||
|
||||
#region Stream internals
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Length => throw new NotSupportedException();
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Diagnostics;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System
|
||||
namespace AssetStudio
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a half-precision floating point number.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System
|
||||
namespace AssetStudio
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for Half conversions and some low level operations.
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace AssetStudio
|
||||
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;
|
||||
|
||||
@@ -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")]
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -31,12 +31,12 @@ namespace AssetStudio
|
||||
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
|
||||
header = new SerializedFileHeader();
|
||||
@@ -68,7 +68,7 @@ namespace AssetStudio
|
||||
// ReadMetadata
|
||||
if (m_FileEndianess == 0)
|
||||
{
|
||||
reader.endian = EndianType.LittleEndian;
|
||||
reader.Endian = EndianType.LittleEndian;
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7)
|
||||
{
|
||||
@@ -219,11 +219,14 @@ 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(bool isRefType)
|
||||
@@ -371,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";
|
||||
}
|
||||
}
|
||||
|
||||
+2
-50
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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")]
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Generated
+36
-17
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
+26
-68
@@ -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
|
||||
{
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
@@ -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>
|
||||
@@ -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());
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
+28
-21
@@ -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;
|
||||
@@ -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));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -708,5 +708,12 @@ namespace AssetStudioGUI
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static void OpenFolderInExplorer(string path)
|
||||
{
|
||||
var info = new ProcessStartInfo(path);
|
||||
info.UseShellExecute = true;
|
||||
Process.Start(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum ImageFormat
|
||||
{
|
||||
Jpeg,
|
||||
Png,
|
||||
Bmp,
|
||||
Tga
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")]
|
||||
@@ -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);
|
||||
@@ -229,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)
|
||||
{
|
||||
@@ -300,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)
|
||||
{
|
||||
@@ -314,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();
|
||||
@@ -443,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
|
||||
@@ -476,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:
|
||||
@@ -503,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();
|
||||
}
|
||||
@@ -580,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";
|
||||
}
|
||||
@@ -647,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;
|
||||
@@ -661,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];
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user