separate code into library

misc
This commit is contained in:
Perfare 2018-11-19 06:48:06 +08:00
parent b93866d196
commit 8ea998b81f
89 changed files with 2492 additions and 2273 deletions

View File

@ -3,11 +3,13 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2024
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioGUI", "AssetStudioGUI\AssetStudioGUI.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBX", "AssetStudioFBX\AssetStudioFBX.vcxproj", "{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioUtility", "AssetStudioUtility\AssetStudioUtility.csproj", "{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudioTools", "AssetStudioTools\AssetStudioTools.csproj", "{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{AF56B63C-1764-41B7-9E60-8D485422AC3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -33,14 +35,22 @@ Global
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x64.Build.0 = Release|x64
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.ActiveCfg = Release|Win32
{4F8EF5EF-732B-49CF-9EB3-B23E19AE6267}.Release|x86.Build.0 = Release|Win32
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|Any CPU
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.ActiveCfg = Debug|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x64.Build.0 = Debug|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.ActiveCfg = Debug|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Debug|x86.Build.0 = Debug|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.ActiveCfg = Release|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x64.Build.0 = Release|x64
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.ActiveCfg = Release|x86
{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}.Release|x86.Build.0 = Release|x86
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.ActiveCfg = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x64.Build.0 = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.ActiveCfg = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Debug|x86.Build.0 = Debug|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.ActiveCfg = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x64.Build.0 = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.ActiveCfg = Release|Any CPU
{AF56B63C-1764-41B7-9E60-8D485422AC3B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -2,7 +2,7 @@
namespace SevenZip
{
class CRC
public class CRC
{
public static readonly uint[] Table;

View File

@ -1,163 +1,72 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<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)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}</ProjectGuid>
<OutputType>WinExe</OutputType>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AF56B63C-1764-41B7-9E60-8D485422AC3B}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio</RootNamespace>
<AssemblyName>AssetStudio</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="dnlib">
<HintPath>Libraries\dnlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OpenTK">
<HintPath>Libraries\OpenTK.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OpenTK.GLControl">
<HintPath>Libraries\OpenTK.GLControl.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX">
<HintPath>Libraries\SharpDX.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX.D3DCompiler">
<HintPath>Libraries\SharpDX.D3DCompiler.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="SharpDX.Mathematics">
<HintPath>Libraries\SharpDX.Mathematics.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Half">
<HintPath>Libraries\System.Half.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="7zip\Common\CommandLineParser.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Common\CRC.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Common\InBuffer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Common\OutBuffer.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZMA\LzmaBase.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZMA\LzmaDecoder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZMA\LzmaEncoder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZ\IMatchFinder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZ\LzBinTree.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZ\LzInWindow.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\LZ\LzOutWindow.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\RangeCoder\RangeCoder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\ICoder.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="7zip\Common\CommandLineParser.cs" />
<Compile Include="7zip\Common\CRC.cs" />
<Compile Include="7zip\Common\InBuffer.cs" />
<Compile Include="7zip\Common\OutBuffer.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaBase.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaDecoder.cs" />
<Compile Include="7zip\Compress\LZMA\LzmaEncoder.cs" />
<Compile Include="7zip\Compress\LZ\IMatchFinder.cs" />
<Compile Include="7zip\Compress\LZ\LzBinTree.cs" />
<Compile Include="7zip\Compress\LZ\LzInWindow.cs" />
<Compile Include="7zip\Compress\LZ\LzOutWindow.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoder.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBit.cs" />
<Compile Include="7zip\Compress\RangeCoder\RangeCoderBitTree.cs" />
<Compile Include="7zip\ICoder.cs" />
<Compile Include="Utility\IImported.cs" />
<Compile Include="SerializedFile.cs" />
<Compile Include="AssetsManager.cs" />
<Compile Include="Extensions\BinaryReaderExtensions.cs" />
<Compile Include="Extensions\BinaryWriterExtensions.cs" />
<Compile Include="Brotli\BitReader.cs" />
<Compile Include="Brotli\BrotliInputStream.cs" />
<Compile Include="Brotli\BrotliRuntimeException.cs" />
@ -173,170 +82,67 @@
<Compile Include="Brotli\Transform.cs" />
<Compile Include="Brotli\Utils.cs" />
<Compile Include="Brotli\WordTransformType.cs" />
<Compile Include="Classes\Behaviour.cs" />
<Compile Include="Classes\Component.cs" />
<Compile Include="Classes\EditorExtension.cs" />
<Compile Include="Classes\MonoScript.cs" />
<Compile Include="Classes\NamedObject.cs" />
<Compile Include="Classes\Object.cs" />
<Compile Include="StudioClasses\ObjectReader.cs" />
<Compile Include="StudioClasses\PPtr.cs" />
<Compile Include="Classes\Renderer.cs" />
<Compile Include="Classes\Texture.cs" />
<Compile Include="StudioClasses\AudioClipConverter.cs" />
<Compile Include="StudioClasses\CommonString.cs" />
<Compile Include="StudioClasses\FileIdentifier.cs" />
<Compile Include="StudioClasses\GameObjectTreeNode.cs" />
<Compile Include="StudioClasses\LocalSerializedObjectIdentifier.cs" />
<Compile Include="StudioClasses\ObjectInfo.cs" />
<Compile Include="StudioClasses\ScriptHelper.cs" />
<Compile Include="StudioClasses\SerializedFileHeader.cs" />
<Compile Include="StudioClasses\SerializedType.cs" />
<Compile Include="StudioClasses\SevenZipHelper.cs">
<SubType>Code</SubType>
</Compile>
<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\Avatar.cs" />
<Compile Include="OpenFolderDialog.cs" />
<Compile Include="StudioClasses\BinaryReaderExtensions.cs" />
<Compile Include="StudioClasses\BinaryWriterExtensions.cs" />
<Compile Include="StudioClasses\BuildTarget.cs" />
<Compile Include="StudioClasses\ClassIDType.cs" />
<Compile Include="StudioClasses\ShaderConverter.cs" />
<Compile Include="StudioClasses\TypeTreeNode.cs" />
<Compile Include="StudioClasses\TypeTreeHelper.cs" />
<Compile Include="StudioClasses\ResourcesHelper.cs" />
<Compile Include="Classes\AssetBundle.cs" />
<Compile Include="Classes\MovieTexture.cs" />
<Compile Include="Classes\Sprite.cs" />
<Compile Include="Classes\SpriteAtlas.cs" />
<Compile Include="Classes\VideoClip.cs" />
<Compile Include="StudioClasses\AssetItem.cs" />
<Compile Include="Classes\AudioClip.cs" />
<Compile Include="Classes\Avatar.cs" />
<Compile Include="Classes\Behaviour.cs" />
<Compile Include="Classes\BuildSettings.cs" />
<Compile Include="StudioClasses\BundleFile.cs" />
<Compile Include="StudioClasses\TypeTreeItem.cs" />
<Compile Include="StudioClasses\SpriteHelper.cs" />
<Compile Include="StudioClasses\Exporter.cs" />
<Compile Include="StudioClasses\Importer.cs" />
<Compile Include="StudioClasses\StreamExtensions.cs" />
<Compile Include="StudioClasses\Studio.cs" />
<Compile Include="StudioClasses\EndianBinaryReader.cs" />
<Compile Include="ExportOptions.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExportOptions.Designer.cs">
<DependentUpon>ExportOptions.cs</DependentUpon>
</Compile>
<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="Classes\Component.cs" />
<Compile Include="Classes\EditorExtension.cs" />
<Compile Include="Classes\Font.cs" />
<Compile Include="GOHierarchy.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Lz4DecoderStream.cs" />
<Compile Include="Classes\GameObject.cs" />
<Compile Include="Classes\Material.cs" />
<Compile Include="Classes\Mesh.cs" />
<Compile Include="Classes\GameObject.cs" />
<Compile Include="Classes\MeshFilter.cs" />
<Compile Include="Classes\MeshRenderer.cs" />
<Compile Include="Classes\MonoBehaviour.cs" />
<Compile Include="Classes\MonoScript.cs" />
<Compile Include="Classes\MovieTexture.cs" />
<Compile Include="Classes\NamedObject.cs" />
<Compile Include="Classes\Object.cs" />
<Compile Include="Classes\PlayerSettings.cs" />
<Compile Include="Classes\RectTransform.cs" />
<Compile Include="Classes\MeshRenderer.cs" />
<Compile Include="Classes\Renderer.cs" />
<Compile Include="Classes\Shader.cs" />
<Compile Include="Classes\SkinnedMeshRenderer.cs" />
<Compile Include="Classes\MeshFilter.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="Program.cs" />
<Compile Include="Classes\VideoClip.cs" />
<Compile Include="ClassIDType.cs" />
<Compile Include="CommonString.cs" />
<Compile Include="EndianBinaryReader.cs" />
<Compile Include="FileIdentifier.cs" />
<Compile Include="Utility\ILogger.cs" />
<Compile Include="ImportHelper.cs" />
<Compile Include="Utility\IProgress.cs" />
<Compile Include="LocalSerializedObjectIdentifier.cs" />
<Compile Include="Utility\Logger.cs" />
<Compile Include="Lz4DecoderStream.cs" />
<Compile Include="ObjectInfo.cs" />
<Compile Include="ObjectReader.cs" />
<Compile Include="Classes\PPtr.cs" />
<Compile Include="Utility\Progress.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="StudioClasses\AssetsFile.cs" />
<Compile Include="StudioClasses\ModelConverter.cs" />
<Compile Include="StudioClasses\Texture2DConverter.cs" />
<Compile Include="StudioClasses\WebFile.cs" />
<Compile Include="AssetStudioForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AssetStudioForm.Designer.cs">
<DependentUpon>AssetStudioForm.cs</DependentUpon>
</Compile>
<Compile Include="TreeViewExtensions.cs" />
<EmbeddedResource Include="ExportOptions.resx">
<DependentUpon>ExportOptions.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="AssetStudioForm.resx">
<DependentUpon>AssetStudioForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
<Visible>False</Visible>
<ProductName>Windows Installer 4.5</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="Resources\preview.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioFBX\AssetStudioFBX.vcxproj">
<Project>{4f8ef5ef-732b-49cf-9eb3-b23e19ae6267}</Project>
<Name>AssetStudioFBX</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj">
<Project>{9131c403-7fe8-444d-9af5-5fe5df76ff24}</Project>
<Name>AssetStudioUtility</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Resources\as.ico" />
<Compile Include="ResourcesHelper.cs" />
<Compile Include="SerializedFileHeader.cs" />
<Compile Include="SerializedType.cs" />
<Compile Include="SevenZipHelper.cs" />
<Compile Include="Extensions\StreamExtensions.cs" />
<Compile Include="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" />
<Compile Include="WebFile.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy /y "$(ProjectDir)Libraries" "$(TargetDir)"
xcopy /y "$(ProjectDir)Libraries\$(PlatformName)" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,192 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static AssetStudio.ImportHelper;
namespace AssetStudio
{
public class AssetsManager
{
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>();
internal Dictionary<string, EndianBinaryReader> resourceFileReaders = new Dictionary<string, EndianBinaryReader>();
private List<string> importFiles = new List<string>();
private HashSet<string> importFilesHash = new HashSet<string>();
private HashSet<string> assetsfileListHash = new HashSet<string>();
public void LoadFiles(string[] files)
{
var path = Path.GetDirectoryName(files[0]);
MergeSplitAssets(path);
var toReadFile = ProcessingSplitFiles(files.ToList());
Load(toReadFile);
}
public void LoadFolder(string path)
{
MergeSplitAssets(path, true);
var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).ToList();
var toReadFile = ProcessingSplitFiles(files);
Load(toReadFile);
}
private void Load(string[] files)
{
foreach (var file in files)
{
importFiles.Add(file);
importFilesHash.Add(Path.GetFileName(file).ToUpper());
}
Progress.Reset();
//use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++)
{
LoadFile(importFiles[i]);
Progress.Report(i + 1, importFiles.Count);
}
importFiles.Clear();
importFilesHash.Clear();
assetsfileListHash.Clear();
}
private void LoadFile(string fullName)
{
switch (CheckFileType(fullName, out var reader))
{
case FileType.AssetsFile:
LoadAssetsFile(fullName, reader);
break;
case FileType.BundleFile:
LoadBundleFile(fullName, reader);
break;
case FileType.WebFile:
LoadWebFile(fullName, reader);
break;
}
}
private void LoadAssetsFile(string fullName, EndianBinaryReader reader)
{
var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
{
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid)
{
assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName.ToUpper()))
{
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
}
}
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName.ToUpper());
}
}
}
}
else
{
reader.Dispose();
}
}
else
{
reader.Dispose();
}
}
private void LoadAssetsFromMemory(string fullName, EndianBinaryReader reader, string originalPath, string unityVersion = null)
{
var fileName = Path.GetFileName(fullName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
{
Logger.Info($"Loading {fileName}");
var assetsFile = new SerializedFile(this, fullName, reader);
if (assetsFile.valid)
{
assetsFile.originalPath = originalPath;
if (assetsFile.header.m_Version < 7)
{
assetsFile.SetVersion(unityVersion);
}
assetsFileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
}
else
{
resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.reader);
}
}
}
private void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Decompressing " + fileName);
var bundleFile = new BundleFile(reader, fullName);
reader.Dispose();
foreach (var file in bundleFile.fileList)
{
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
LoadAssetsFromMemory(dummyPath, new EndianBinaryReader(file.stream), parentPath ?? fullName, bundleFile.versionEngine);
}
}
private void LoadWebFile(string fullName, EndianBinaryReader reader)
{
var fileName = Path.GetFileName(fullName);
Logger.Info("Loading " + fileName);
var webFile = new WebFile(reader);
reader.Dispose();
foreach (var file in webFile.fileList)
{
var dummyPath = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
switch (CheckFileType(file.stream, out reader))
{
case FileType.AssetsFile:
LoadAssetsFromMemory(dummyPath, reader, fullName);
break;
case FileType.BundleFile:
LoadBundleFile(dummyPath, reader, fullName);
break;
case FileType.WebFile:
LoadWebFile(dummyPath, reader);
break;
}
}
}
public void Clear()
{
foreach (var assetsFile in assetsFileList)
{
assetsFile.reader.Close();
}
assetsFileList.Clear();
foreach (var resourceFileReader in resourceFileReaders)
{
resourceFileReader.Value.Close();
}
resourceFileReaders.Clear();
assetsFileIndexCache.Clear();
}
}
}

20
AssetStudio/BuildType.cs Normal file
View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public class BuildType
{
private string buildType;
public BuildType(string type)
{
buildType = type;
}
public bool IsAlpha => buildType == "a";
public bool IsPatch => buildType == "p";
}
}

View File

@ -102,7 +102,7 @@ namespace AssetStudio
for (int i = 0; i < fileCount; i++)
{
var file = new StreamFile();
file.fileName = reader.ReadStringToNull();
file.fileName = Path.GetFileName(reader.ReadStringToNull());
int fileOffset = reader.ReadInt32();
fileOffset += offset;
int fileSize = reader.ReadInt32();

View File

@ -1,9 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using SharpDX;
namespace AssetStudio

View File

@ -5,7 +5,7 @@ using System.Text;
namespace AssetStudio
{
class AnimatorOverrideController : NamedObject
public class AnimatorOverrideController : NamedObject
{
public PPtr m_Controller;
public PPtr[][] m_Clips;

View File

@ -49,7 +49,7 @@ namespace AssetStudio
if (reader.byteSize + reader.byteStart - reader.Position != tsize)
{
m_Offset = reader.ReadInt32();
m_Source = sourceFile.filePath + ".resS";
m_Source = sourceFile.fullName + ".resS";
}
}
else
@ -83,7 +83,7 @@ namespace AssetStudio
{
if (!string.IsNullOrEmpty(m_Source))
{
m_AudioData = ResourcesHelper.GetData(m_Source, sourceFile.filePath, m_Offset, (int)m_Size);
m_AudioData = ResourcesHelper.GetData(m_Source, sourceFile, m_Offset, (int)m_Size);
}
else
{

View File

@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
{

View File

@ -38,7 +38,7 @@ namespace AssetStudio
{
m_Shader = reader.ReadPPtr();
if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && buildType[0] != "a")))
if (version[0] == 4 && (version[1] >= 2 || (version[1] == 1 && !buildType.IsAlpha)))
{
m_ShaderKeywords = new string[reader.ReadInt32()];
for (int i = 0; i < m_ShaderKeywords.Length; i++)

View File

@ -20,10 +20,10 @@ namespace AssetStudio
public float[] m_Vertices;
public float[] m_Normals;
public float[] m_Colors;
public float[] m_UV0;
public float[] m_UV1;
public float[] m_UV2;
public float[] m_UV3;
public float[] m_UV4;
public float[] m_Tangents;
public uint[] m_BoneNameHashes;
public BlendShapeData m_Shapes;
@ -295,7 +295,7 @@ namespace AssetStudio
#endregion
#region BlendShapeData for 4.1.0 to 4.2.x, excluding 4.1.0 alpha
if (version[0] == 4 && ((version[1] == 1 && buildType[0] != "a") || (version[1] > 1 && version[1] <= 2)))
if (version[0] == 4 && ((version[1] == 1 && !buildType.IsAlpha) || (version[1] > 1 && version[1] <= 2)))
{
int m_Shapes_size = reader.ReadInt32();
if (m_Shapes_size > 0)
@ -359,7 +359,7 @@ namespace AssetStudio
reader.AlignStream(4);
//This is a bug fixed in 2017.3.1p1 and later versions
if ((version[0] > 2017 || (version[0] == 2017 && version[1] >= 4)) || //2017.4
((version[0] == 2017 && version[1] == 3 && version[2] == 1) && buildType[0] == "p") || //fixed after 2017.3.1px
((version[0] == 2017 && version[1] == 3 && version[2] == 1) && buildType.IsPatch) || //fixed after 2017.3.1px
((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
{
var m_IndexFormat = reader.ReadInt32();
@ -407,12 +407,12 @@ namespace AssetStudio
}
int m_UV1_size = reader.ReadInt32();
m_UV1 = new float[m_UV1_size * 2];
for (int v = 0; v < m_UV1_size * 2; v++) { m_UV1[v] = reader.ReadSingle(); }
m_UV0 = new float[m_UV1_size * 2];
for (int v = 0; v < m_UV1_size * 2; v++) { m_UV0[v] = reader.ReadSingle(); }
int m_UV2_size = reader.ReadInt32();
m_UV2 = new float[m_UV2_size * 2];
for (int v = 0; v < m_UV2_size * 2; v++) { m_UV2[v] = reader.ReadSingle(); }
m_UV1 = new float[m_UV2_size * 2];
for (int v = 0; v < m_UV2_size * 2; v++) { m_UV1[v] = reader.ReadSingle(); }
if (version[0] == 2 && version[1] <= 5)
{
@ -631,16 +631,16 @@ namespace AssetStudio
m_Colors = componentsFloatArray;
break;
case 4: //kShaderChannelTexCoord0
m_UV1 = componentsFloatArray;
m_UV0 = componentsFloatArray;
break;
case 5: //kShaderChannelTexCoord1
m_UV2 = componentsFloatArray;
m_UV1 = componentsFloatArray;
break;
case 6: //kShaderChannelTexCoord2
m_UV3 = componentsFloatArray;
m_UV2 = componentsFloatArray;
break;
case 7: //kShaderChannelTexCoord3
m_UV4 = componentsFloatArray;
m_UV3 = componentsFloatArray;
break;
//kShaderChannelTexCoord4 8
//kShaderChannelTexCoord5 9
@ -744,15 +744,15 @@ namespace AssetStudio
m_Colors = componentsFloatArray;
break;
case 3: //kShaderChannelTexCoord0
m_UV1 = componentsFloatArray;
m_UV0 = componentsFloatArray;
break;
case 4: //kShaderChannelTexCoord1
m_UV2 = componentsFloatArray;
m_UV1 = componentsFloatArray;
break;
case 5: //kShaderChannelTangent & kShaderChannelTexCoord2
if (version[0] >= 5)
{
m_UV3 = componentsFloatArray;
m_UV2 = componentsFloatArray;
}
else
{
@ -760,7 +760,7 @@ namespace AssetStudio
}
break;
case 6: //kShaderChannelTexCoord3
m_UV4 = componentsFloatArray;
m_UV3 = componentsFloatArray;
break;
case 7: //kShaderChannelTangent
m_Tangents = componentsFloatArray;
@ -831,8 +831,8 @@ namespace AssetStudio
case 0: m_Vertices = componentsArray; break;
case 1: m_Normals = componentsArray; break;
case 2: m_Colors = componentsArray; break;
case 3: m_UV1 = componentsArray; break;
case 4: m_UV2 = componentsArray; break;
case 3: m_UV0 = componentsArray; break;
case 4: m_UV1 = componentsArray; break;
case 5: m_Tangents = componentsArray; break;
}
@ -864,18 +864,18 @@ namespace AssetStudio
var m_UV_Packed = new PackedFloatVector(reader);
if (m_UV_Packed.m_NumItems > 0)
{
m_UV1 = m_UV_Packed.UnpackFloats(2, 4, 0, m_VertexCount);
m_UV0 = m_UV_Packed.UnpackFloats(2, 4, 0, m_VertexCount);
if (m_UV_Packed.m_NumItems >= m_VertexCount * 4)
{
m_UV2 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 2, m_VertexCount);
m_UV1 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 2, m_VertexCount);
}
if (m_UV_Packed.m_NumItems >= m_VertexCount * 6)
{
m_UV3 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 4, m_VertexCount);
m_UV2 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 4, m_VertexCount);
}
if (m_UV_Packed.m_NumItems >= m_VertexCount * 8)
{
m_UV4 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 6, m_VertexCount);
m_UV3 = m_UV_Packed.UnpackFloats(2, 4, m_VertexCount * 6, m_VertexCount);
}
}
#endregion

View File

@ -7,10 +7,10 @@ namespace AssetStudio
{
public abstract class Object
{
protected AssetsFile sourceFile;
protected SerializedFile sourceFile;
public ObjectReader reader;
public int[] version;
protected string[] buildType;
protected BuildType buildType;
public BuildTarget platform;
protected Object(ObjectReader reader)

View File

@ -1,17 +1,14 @@
using static AssetStudio.Studio;
namespace AssetStudio
namespace AssetStudio
{
public class PPtr
{
public int m_FileID;
public long m_PathID;
//custom
public AssetsFile assetsFile;
public SerializedFile assetsFile;
public int index = -2; //-2 - Prepare, -1 - Missing
private bool TryGetAssetsFile(out AssetsFile result)
private bool TryGetAssetsFile(out SerializedFile result)
{
result = null;
if (m_FileID == 0)
@ -22,6 +19,10 @@ namespace AssetStudio
if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
{
var assetsManager = assetsFile.assetsManager;
var assetsfileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (index == -2)
{
var m_External = assetsFile.m_Externals[m_FileID - 1];

View File

@ -105,7 +105,7 @@ namespace AssetStudio
{
if (!string.IsNullOrEmpty(path))
{
image_data = ResourcesHelper.GetData(path, sourceFile.filePath, offset, image_data_size);
image_data = ResourcesHelper.GetData(path, sourceFile, offset, image_data_size);
}
else
{

View File

@ -51,7 +51,7 @@ namespace AssetStudio
{
if (!string.IsNullOrEmpty(m_Source))
{
m_VideoData = ResourcesHelper.GetData(m_Source, sourceFile.filePath, (long)m_Offset, (int)m_Size);
m_VideoData = ResourcesHelper.GetData(m_Source, sourceFile, (long)m_Offset, (int)m_Size);
}
else
{

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace AssetStudio
{

View File

@ -14,13 +14,11 @@ namespace AssetStudio
public class EndianBinaryReader : BinaryReader
{
public EndianType endian;
private byte[] a16 = new byte[2];
private byte[] a32 = new byte[4];
private byte[] a64 = new byte[8];
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian)
: base(stream)
{ this.endian = endian; }
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
{
this.endian = endian;
}
public long Position
{
@ -32,9 +30,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a16 = ReadBytes(2);
Array.Reverse(a16);
return BitConverter.ToInt16(a16, 0);
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToInt16(buff, 0);
}
return base.ReadInt16();
}
@ -43,9 +41,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a32 = ReadBytes(4);
Array.Reverse(a32);
return BitConverter.ToInt32(a32, 0);
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToInt32(buff, 0);
}
return base.ReadInt32();
}
@ -54,9 +52,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a64 = ReadBytes(8);
Array.Reverse(a64);
return BitConverter.ToInt64(a64, 0);
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToInt64(buff, 0);
}
return base.ReadInt64();
}
@ -65,9 +63,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a16 = ReadBytes(2);
Array.Reverse(a16);
return BitConverter.ToUInt16(a16, 0);
var buff = ReadBytes(2);
Array.Reverse(buff);
return BitConverter.ToUInt16(buff, 0);
}
return base.ReadUInt16();
}
@ -76,9 +74,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a32 = ReadBytes(4);
Array.Reverse(a32);
return BitConverter.ToUInt32(a32, 0);
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToUInt32(buff, 0);
}
return base.ReadUInt32();
}
@ -87,9 +85,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a64 = ReadBytes(8);
Array.Reverse(a64);
return BitConverter.ToUInt64(a64, 0);
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
}
return base.ReadUInt64();
}
@ -98,9 +96,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a32 = ReadBytes(4);
Array.Reverse(a32);
return BitConverter.ToSingle(a32, 0);
var buff = ReadBytes(4);
Array.Reverse(buff);
return BitConverter.ToSingle(buff, 0);
}
return base.ReadSingle();
}
@ -109,9 +107,9 @@ namespace AssetStudio
{
if (endian == EndianType.BigEndian)
{
a64 = ReadBytes(8);
Array.Reverse(a64);
return BitConverter.ToUInt64(a64, 0);
var buff = ReadBytes(8);
Array.Reverse(buff);
return BitConverter.ToUInt64(buff, 0);
}
return base.ReadDouble();
}

View File

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SharpDX;

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudio

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.IO;
namespace AssetStudio
{

104
AssetStudio/ImportHelper.cs Normal file
View File

@ -0,0 +1,104 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AssetStudio
{
public enum FileType
{
AssetsFile,
BundleFile,
WebFile
}
public static class ImportHelper
{
public static void MergeSplitAssets(string path, bool allDirectories = false)
{
var splitFiles = Directory.GetFiles(path, "*.split0", allDirectories ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
foreach (var splitFile in splitFiles)
{
var destFile = Path.GetFileNameWithoutExtension(splitFile);
var destPath = Path.GetDirectoryName(splitFile) + "\\";
var destFull = destPath + destFile;
if (!File.Exists(destFull))
{
var splitParts = Directory.GetFiles(destPath, destFile + ".split*");
using (var destStream = File.Create(destFull))
{
for (int i = 0; i < splitParts.Length; i++)
{
var splitPart = destFull + ".split" + i;
using (var sourceStream = File.OpenRead(splitPart))
{
sourceStream.CopyTo(destStream);
}
}
}
}
}
}
public static string[] ProcessingSplitFiles(List<string> selectFile)
{
var splitFiles = selectFile.Where(x => x.Contains(".split"))
.Select(x => Path.GetDirectoryName(x) + "\\" + Path.GetFileNameWithoutExtension(x))
.Distinct()
.ToList();
selectFile.RemoveAll(x => x.Contains(".split"));
foreach (var file in splitFiles)
{
if (File.Exists(file))
{
selectFile.Add(file);
}
}
return selectFile.Distinct().ToArray();
}
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(stream);
return CheckFileType(reader);
}
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(File.OpenRead(fileName));
return CheckFileType(reader);
}
private static FileType CheckFileType(EndianBinaryReader reader)
{
var signature = reader.ReadStringToNull();
reader.Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = reader.ReadBytes(2);
reader.Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
reader.Position = 0x20;
magic = reader.ReadBytes(6);
reader.Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
return FileType.AssetsFile;
}
}
}
}
}

View File

@ -14,7 +14,7 @@ namespace Lz4
Reset(input, inputLength);
}
public void Reset(Stream input, long inputLength = long.MaxValue)
private void Reset(Stream input, long inputLength = long.MaxValue)
{
this.inputLength = inputLength;
this.input = input;
@ -40,6 +40,7 @@ namespace Lz4
input.Close();
}
input = null;
decodeBuffer = null;
}
finally
{

View File

@ -8,7 +8,7 @@ namespace AssetStudio
{
public class ObjectReader : EndianBinaryReader
{
public AssetsFile assetsFile;
public SerializedFile assetsFile;
public long m_PathID;
public uint byteStart;
public uint byteSize;
@ -18,11 +18,9 @@ namespace AssetStudio
private uint m_Version;
public int[] version => assetsFile.version;
public string[] buildType => assetsFile.buildType;
public BuildType buildType => assetsFile.buildType;
public string exportName; //TODO Remove it
public ObjectReader(EndianBinaryReader reader, AssetsFile 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;

View File

@ -2,35 +2,35 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudio")]
[assembly: AssemblyDescription("AssetStudio is a tool for exploring, extracting and exporting assets and assetbundles.")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudio")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("05c04c20-dd89-4895-9f06-33d5cfbfe925")]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("af56b63c-1764-41b7-9e60-8d485422ac3b")]
// Version information for an assembly consists of the following four values:
// 程序集的版本信息由下列四个值组成:
//
// Major Version
// Minor Version
// Build Number
// Revision
// 主版本
// 次版本
// 生成号
// 修订号
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
//通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.11.0.0")]
[assembly: AssemblyFileVersion("0.11.0.0")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -3,26 +3,26 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
{
public static class ResourcesHelper
internal static class ResourcesHelper
{
public static byte[] GetData(string path, string sourceFilePath, long offset, int size)
public static byte[] GetData(string path, SerializedFile assetsFile, long offset, int size)
{
var resourceFileName = Path.GetFileName(path);
if (Studio.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName.ToUpper(), out var reader))
{
reader.Position = offset;
return reader.ReadBytes(size);
}
var resourceFilePath = Path.GetDirectoryName(sourceFilePath) + "\\" + resourceFileName;
var currentDirectory = Path.GetDirectoryName(assetsFile.fullName);
var resourceFilePath = currentDirectory + "\\" + resourceFileName;
if (!File.Exists(resourceFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(sourceFilePath), resourceFileName, SearchOption.AllDirectories);
var findFiles = Directory.GetFiles(currentDirectory, resourceFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
resourceFilePath = findFiles[0];
@ -36,11 +36,8 @@ namespace AssetStudio
return resourceReader.ReadBytes(size);
}
}
else
{
MessageBox.Show($"can't find the resource file {resourceFileName}");
return null;
}
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
}
}
}

View File

@ -6,41 +6,41 @@ using System.Text.RegularExpressions;
namespace AssetStudio
{
public class AssetsFile
public class SerializedFile
{
public AssetsManager assetsManager;
public EndianBinaryReader reader;
public string filePath;
public string parentPath;
public string fullName;
public string originalPath;
public string fileName;
public string upperFileName;
public int[] version = { 0, 0, 0, 0 };
public string[] buildType;
public string platformStr;
public BuildType buildType;
public bool valid;
public Dictionary<long, ObjectReader> ObjectReaders = new Dictionary<long, ObjectReader>();
public Dictionary<long, GameObject> GameObjects = new Dictionary<long, GameObject>();
public Dictionary<long, Transform> Transforms = new Dictionary<long, Transform>();
//class SerializedFile
public SerializedFileHeader header;
private EndianType m_FileEndianess;
public string unityVersion = "2.5.0f5";
public BuildTarget m_TargetPlatform = BuildTarget.UnknownPlatform;
private bool m_EnableTypeTree = true;
public List<SerializedType> m_Types;
public Dictionary<long, ObjectInfo> m_Objects;
private List<ObjectInfo> m_Objects;
private List<LocalSerializedObjectIdentifier> m_ScriptTypes;
public List<FileIdentifier> m_Externals;
public AssetsFile(string fullName, EndianBinaryReader reader)
public SerializedFile(AssetsManager assetsManager, string fullName, EndianBinaryReader reader)
{
this.assetsManager = assetsManager;
this.reader = reader;
filePath = fullName;
this.fullName = fullName;
fileName = Path.GetFileName(fullName);
upperFileName = fileName.ToUpper();
try
{
//SerializedFile::ReadHeader
//ReadHeader
header = new SerializedFileHeader();
header.m_MetadataSize = reader.ReadUInt32();
header.m_FileSize = reader.ReadUInt32();
@ -59,7 +59,7 @@ namespace AssetStudio
m_FileEndianess = (EndianType)reader.ReadByte();
}
//SerializedFile::ReadMetadata
//ReadMetadata
if (m_FileEndianess == EndianType.LittleEndian)
{
reader.endian = EndianType.LittleEndian;
@ -67,6 +67,7 @@ namespace AssetStudio
if (header.m_Version >= 7)
{
unityVersion = reader.ReadStringToNull();
SetVersion(unityVersion);
}
if (header.m_Version >= 8)
{
@ -76,13 +77,12 @@ namespace AssetStudio
m_TargetPlatform = BuildTarget.UnknownPlatform;
}
}
platformStr = m_TargetPlatform.ToString();
if (header.m_Version >= 13)
{
m_EnableTypeTree = reader.ReadBoolean();
}
//Read types
//ReadTypes
int typeCount = reader.ReadInt32();
m_Types = new List<SerializedType>(typeCount);
for (int i = 0; i < typeCount; i++)
@ -95,9 +95,9 @@ namespace AssetStudio
var bigIDEnabled = reader.ReadInt32();
}
//Read Objects
//ReadObjects
int objectCount = reader.ReadInt32();
m_Objects = new Dictionary<long, ObjectInfo>(objectCount);
m_Objects = new List<ObjectInfo>(objectCount);
for (int i = 0; i < objectCount; i++)
{
var objectInfo = new ObjectInfo();
@ -130,23 +130,11 @@ namespace AssetStudio
{
var stripped = reader.ReadByte();
}
m_Objects.Add(objectInfo.m_PathID, objectInfo);
m_Objects.Add(objectInfo);
//Create Reader
var objectReader = new ObjectReader(reader, this, objectInfo);
ObjectReaders.Add(objectInfo.m_PathID, objectReader);
#region read BuildSettings to get version for version 2.x files
if (objectReader.type == ClassIDType.BuildSettings && header.m_Version == 6)
{
var nextAsset = reader.Position;
var buildSettings = new BuildSettings(objectReader);
unityVersion = buildSettings.m_Version;
reader.Position = nextAsset;
}
#endregion
}
if (header.m_Version >= 11)
@ -194,10 +182,6 @@ namespace AssetStudio
//var userInformation = reader.ReadStringToNull();
}
buildType = Regex.Replace(unityVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
var versionSplit = Regex.Replace(unityVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = versionSplit.Select(int.Parse).ToArray();
valid = true;
}
catch
@ -206,6 +190,14 @@ namespace AssetStudio
}
}
public void SetVersion(string 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()
{
var type = new SerializedType();

View File

@ -11,18 +11,18 @@ namespace AssetStudio
{
var decoder = new Decoder();
inStream.Seek(0, 0);
inStream.Seek(0, SeekOrigin.Begin);
var newOutStream = new MemoryStream();
var properties = new byte[5];
if (inStream.Read(properties, 0, 5) != 5)
throw (new Exception("input .lzma is too short"));
throw new Exception("input .lzma is too short");
long outSize = 0;
for (var i = 0; i < 8; i++)
{
var v = inStream.ReadByte();
if (v < 0)
throw (new Exception("Can't Read 1"));
throw new Exception("Can't Read 1");
outSize |= ((long)(byte)v) << (8 * i);
}
decoder.SetDecoderProperties(properties);

View File

@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
{
public class GameObjectTreeNode : TreeNode
{
public GameObject gameObject;
public GameObjectTreeNode(GameObject gameObject)
{
if (gameObject != null)
{
this.gameObject = gameObject;
Text = gameObject.m_Name;
}
}
}
}

View File

@ -1,183 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using static AssetStudio.Studio;
namespace AssetStudio
{
static class Importer
{
public static List<string> importFiles = new List<string>(); //files to load
public static HashSet<string> importFilesHash = new HashSet<string>(); //to improve the loading speed
public static HashSet<string> assetsfileListHash = new HashSet<string>(); //to improve the loading speed
public static void LoadFile(string fullName)
{
switch (CheckFileType(fullName, out var reader))
{
case FileType.AssetsFile:
LoadAssetsFile(fullName, reader);
break;
case FileType.BundleFile:
LoadBundleFile(fullName, reader);
break;
case FileType.WebFile:
LoadWebFile(fullName, reader);
break;
}
}
private static void LoadAssetsFile(string fullName, EndianBinaryReader reader, string parentPath = null)
{
var fileName = Path.GetFileName(fullName);
StatusStripUpdate("Loading " + fileName);
if (!assetsfileListHash.Contains(fileName.ToUpper()))
{
var assetsFile = new AssetsFile(fullName, reader);
if (assetsFile.valid)
{
assetsFile.parentPath = parentPath;
assetsfileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
#region for 2.6.x find mainData and get string version
if (assetsFile.header.m_Version == 6 && fileName != "mainData")
{
var mainDataFile = assetsfileList.Find(aFile => aFile.fileName == "mainData");
if (mainDataFile != null)
{
assetsFile.unityVersion = mainDataFile.unityVersion;
assetsFile.version = mainDataFile.version;
assetsFile.buildType = mainDataFile.buildType;
}
else if (File.Exists(Path.GetDirectoryName(fullName) + "\\mainData"))
{
mainDataFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\mainData", new EndianBinaryReader(File.OpenRead(Path.GetDirectoryName(fullName) + "\\mainData")));
assetsFile.unityVersion = mainDataFile.unityVersion;
assetsFile.version = mainDataFile.version;
assetsFile.buildType = mainDataFile.buildType;
}
}
#endregion
int value = 0;
foreach (var sharedFile in assetsFile.m_Externals)
{
var sharedFilePath = Path.GetDirectoryName(fullName) + "\\" + sharedFile.fileName;
var sharedFileName = sharedFile.fileName;
if (!importFilesHash.Contains(sharedFileName.ToUpper()))
{
if (!File.Exists(sharedFilePath))
{
var findFiles = Directory.GetFiles(Path.GetDirectoryName(fullName), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0)
{
sharedFilePath = findFiles[0];
}
}
if (File.Exists(sharedFilePath))
{
importFiles.Add(sharedFilePath);
importFilesHash.Add(sharedFileName.ToUpper());
value++;
}
}
}
if (value > 0)
ProgressBarMaximumAdd(value);
}
else
reader.Dispose();
}
}
private static void LoadBundleFile(string fullName, EndianBinaryReader reader, string parentPath = null)
{
var fileName = Path.GetFileName(fullName);
StatusStripUpdate("Decompressing " + fileName);
var bundleFile = new BundleFile(reader, fullName);
reader.Dispose();
foreach (var file in bundleFile.fileList)
{
if (!assetsfileListHash.Contains(file.fileName.ToUpper()))
{
StatusStripUpdate("Loading " + file.fileName);
var assetsFile = new AssetsFile(Path.GetDirectoryName(fullName) + "\\" + file.fileName, new EndianBinaryReader(file.stream));
if (assetsFile.valid)
{
assetsFile.parentPath = parentPath ?? fullName;
if (assetsFile.header.m_Version == 6) //2.6.x and earlier don't have a string version before the preload table
{
//make use of the bundle file version
assetsFile.unityVersion = bundleFile.versionEngine;
assetsFile.version = Regex.Matches(bundleFile.versionEngine, @"\d").Cast<Match>().Select(m => int.Parse(m.Value)).ToArray();
assetsFile.buildType = Regex.Replace(bundleFile.versionEngine, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
}
assetsfileList.Add(assetsFile);
assetsfileListHash.Add(assetsFile.upperFileName);
}
else
{
resourceFileReaders.Add(assetsFile.upperFileName, assetsFile.reader);
}
}
}
}
private static void LoadWebFile(string fullName, EndianBinaryReader reader)
{
var fileName = Path.GetFileName(fullName);
StatusStripUpdate("Loading " + fileName);
var webFile = new WebFile(reader);
reader.Dispose();
foreach (var file in webFile.fileList)
{
var dummyName = Path.GetDirectoryName(fullName) + "\\" + file.fileName;
switch (CheckFileType(file.stream, out reader))
{
case FileType.AssetsFile:
LoadAssetsFile(dummyName, reader, fullName);
break;
case FileType.BundleFile:
LoadBundleFile(dummyName, reader, fullName);
break;
case FileType.WebFile:
LoadWebFile(dummyName, reader);
break;
}
resourceFileReaders.Add(file.fileName.ToUpper(), reader);
}
}
public static void MergeSplitAssets(string dirPath)
{
string[] splitFiles = Directory.GetFiles(dirPath, "*.split0");
foreach (var splitFile in splitFiles)
{
string destFile = Path.GetFileNameWithoutExtension(splitFile);
string destPath = Path.GetDirectoryName(splitFile) + "\\";
var destFull = destPath + destFile;
if (!File.Exists(destFull))
{
string[] splitParts = Directory.GetFiles(destPath, destFile + ".split*");
using (var destStream = File.Create(destFull))
{
for (int i = 0; i < splitParts.Length; i++)
{
string splitPart = destFull + ".split" + i;
using (var sourceStream = File.OpenRead(splitPart))
sourceStream.CopyTo(destStream);
}
}
}
}
}
}
}

View File

@ -1,759 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using static AssetStudio.Exporter;
namespace AssetStudio
{
internal static class Studio
{
public static List<AssetsFile> assetsfileList = new List<AssetsFile>(); //loaded files
public static Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>();
public static Dictionary<string, EndianBinaryReader> resourceFileReaders = new Dictionary<string, EndianBinaryReader>(); //use for read res files
public static List<AssetItem> exportableAssets = new List<AssetItem>(); //used to hold all assets while the ListView is filtered
private static HashSet<string> assetsNameHash = new HashSet<string>(); //avoid the same name asset
public static List<AssetItem> visibleAssets = new List<AssetItem>(); //used to build the ListView from all or filtered assets
public static Dictionary<string, SortedDictionary<int, TypeTreeItem>> AllTypeMap = new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();
public static List<GameObjectTreeNode> treeNodeCollection = new List<GameObjectTreeNode>();
public static Dictionary<GameObject, GameObjectTreeNode> treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>();
public static string mainPath;
public static string productName = string.Empty;
//UI
public static Action<int> SetProgressBarValue;
public static Action<int> SetProgressBarMaximum;
public static Action ProgressBarPerformStep;
public static Action<string> StatusStripUpdate;
public static Action<int> ProgressBarMaximumAdd;
public enum FileType
{
AssetsFile,
BundleFile,
WebFile
}
public static FileType CheckFileType(Stream stream, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(stream);
return CheckFileType(reader);
}
public static FileType CheckFileType(string fileName, out EndianBinaryReader reader)
{
reader = new EndianBinaryReader(File.OpenRead(fileName));
return CheckFileType(reader);
}
private static FileType CheckFileType(EndianBinaryReader reader)
{
var signature = reader.ReadStringToNull();
reader.Position = 0;
switch (signature)
{
case "UnityWeb":
case "UnityRaw":
case "\xFA\xFA\xFA\xFA\xFA\xFA\xFA\xFA":
case "UnityFS":
return FileType.BundleFile;
case "UnityWebData1.0":
return FileType.WebFile;
default:
{
var magic = reader.ReadBytes(2);
reader.Position = 0;
if (WebFile.gzipMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
reader.Position = 0x20;
magic = reader.ReadBytes(6);
reader.Position = 0;
if (WebFile.brotliMagic.SequenceEqual(magic))
{
return FileType.WebFile;
}
return FileType.AssetsFile;
}
}
}
public static void ExtractFile(string[] fileNames)
{
ThreadPool.QueueUserWorkItem(state =>
{
int extractedCount = 0;
foreach (var fileName in fileNames)
{
var type = CheckFileType(fileName, out var reader);
if (type == FileType.BundleFile)
extractedCount += ExtractBundleFile(fileName, reader);
else if (type == FileType.WebFile)
extractedCount += ExtractWebDataFile(fileName, reader);
else
reader.Dispose();
ProgressBarPerformStep();
}
StatusStripUpdate($"Finished extracting {extractedCount} files.");
});
}
private static int ExtractBundleFile(string bundleFileName, EndianBinaryReader reader)
{
StatusStripUpdate($"Decompressing {Path.GetFileName(bundleFileName)} ...");
var bundleFile = new BundleFile(reader, bundleFileName);
reader.Dispose();
if (bundleFile.fileList.Count > 0)
{
var extractPath = bundleFileName + "_unpacked\\";
Directory.CreateDirectory(extractPath);
return ExtractStreamFile(extractPath, bundleFile.fileList);
}
return 0;
}
private static int ExtractWebDataFile(string webFileName, EndianBinaryReader reader)
{
StatusStripUpdate($"Decompressing {Path.GetFileName(webFileName)} ...");
var webFile = new WebFile(reader);
reader.Dispose();
if (webFile.fileList.Count > 0)
{
var extractPath = webFileName + "_unpacked\\";
Directory.CreateDirectory(extractPath);
return ExtractStreamFile(extractPath, webFile.fileList);
}
return 0;
}
private static int ExtractStreamFile(string extractPath, List<StreamFile> fileList)
{
int extractedCount = 0;
foreach (var file in fileList)
{
var filePath = extractPath + file.fileName;
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
if (!File.Exists(filePath) && file.stream is MemoryStream stream)
{
File.WriteAllBytes(filePath, stream.ToArray());
extractedCount += 1;
}
file.stream.Dispose();
}
return extractedCount;
}
public static void BuildAssetStructures(bool loadAssets, bool displayAll, bool buildHierarchy, bool buildClassStructures, bool displayOriginalName)
{
var tempDic = new Dictionary<ObjectReader, AssetItem>();
// first loop - read asset data & create list
if (loadAssets)
{
SetProgressBarValue(0);
SetProgressBarMaximum(assetsfileList.Sum(x => x.ObjectReaders.Count));
StatusStripUpdate("Building asset list...");
var fileIDfmt = "D" + assetsfileList.Count.ToString().Length;
for (var i = 0; i < assetsfileList.Count; i++)
{
var assetsFile = assetsfileList[i];
var tempExportableAssets = new List<AssetItem>();
var fileID = i.ToString(fileIDfmt);
AssetBundle ab = null;
var j = 0;
var assetIDfmt = "D" + assetsFile.m_Objects.Count.ToString().Length;
foreach (var objectReader in assetsFile.ObjectReaders.Values)
{
var assetItem = new AssetItem(objectReader);
tempDic.Add(objectReader, assetItem);
assetItem.UniqueID = fileID + j.ToString(assetIDfmt);
var exportable = false;
switch (assetItem.Type)
{
case ClassIDType.GameObject:
{
var m_GameObject = new GameObject(objectReader);
assetItem.Text = m_GameObject.m_Name;
assetsFile.GameObjects.Add(objectReader.m_PathID, m_GameObject);
break;
}
case ClassIDType.Transform:
{
var m_Transform = new Transform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Transform);
break;
}
case ClassIDType.RectTransform:
{
var m_Rect = new RectTransform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Rect);
break;
}
case ClassIDType.Texture2D:
{
var m_Texture2D = new Texture2D(objectReader, false);
if (!string.IsNullOrEmpty(m_Texture2D.path))
assetItem.FullSize = objectReader.byteSize + m_Texture2D.size;
assetItem.Text = m_Texture2D.m_Name;
exportable = true;
break;
}
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(objectReader, false);
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = objectReader.byteSize + m_AudioClip.m_Size;
assetItem.Text = m_AudioClip.m_Name;
exportable = true;
break;
}
case ClassIDType.VideoClip:
{
var m_VideoClip = new VideoClip(objectReader, false);
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
assetItem.FullSize = objectReader.byteSize + (long)m_VideoClip.m_Size;
assetItem.Text = m_VideoClip.m_Name;
exportable = true;
break;
}
case ClassIDType.Shader:
{
var m_Shader = new Shader(objectReader);
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
exportable = true;
break;
}
case ClassIDType.Mesh:
case ClassIDType.TextAsset:
case ClassIDType.AnimationClip:
case ClassIDType.Font:
case ClassIDType.MovieTexture:
case ClassIDType.Sprite:
{
var obj = new NamedObject(objectReader);
assetItem.Text = obj.m_Name;
exportable = true;
break;
}
case ClassIDType.Avatar:
case ClassIDType.AnimatorController:
case ClassIDType.AnimatorOverrideController:
case ClassIDType.Material:
case ClassIDType.MonoScript:
case ClassIDType.SpriteAtlas:
{
var obj = new NamedObject(objectReader);
assetItem.Text = obj.m_Name;
break;
}
case ClassIDType.Animator:
{
exportable = true;
break;
}
case ClassIDType.MonoBehaviour:
{
var m_MonoBehaviour = new MonoBehaviour(objectReader);
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var script))
{
var m_Script = new MonoScript(script);
assetItem.Text = m_Script.m_ClassName;
}
else
{
assetItem.Text = m_MonoBehaviour.m_Name;
}
exportable = true;
break;
}
case ClassIDType.PlayerSettings:
{
var plSet = new PlayerSettings(objectReader);
productName = plSet.productName;
break;
}
case ClassIDType.AssetBundle:
{
ab = new AssetBundle(objectReader);
assetItem.Text = ab.m_Name;
break;
}
}
if (assetItem.Text == "")
{
assetItem.Text = assetItem.TypeString + " #" + assetItem.UniqueID;
}
assetItem.SubItems.AddRange(new[] { assetItem.TypeString, assetItem.FullSize.ToString() });
//处理同名文件
if (!assetsNameHash.Add((assetItem.TypeString + assetItem.Text).ToUpper()))
{
assetItem.Text += " #" + assetItem.UniqueID;
}
//处理非法文件名
assetItem.Text = FixFileName(assetItem.Text);
if (displayAll)
{
exportable = true;
}
if (exportable)
{
tempExportableAssets.Add(assetItem);
}
objectReader.exportName = assetItem.Text;
ProgressBarPerformStep();
j++;
}
if (displayOriginalName)
{
foreach (var x in tempExportableAssets)
{
var replacename = ab?.m_Container.Find(y => y.second.asset.m_PathID == x.reader.m_PathID)?.first;
if (!string.IsNullOrEmpty(replacename))
{
var ex = Path.GetExtension(replacename);
x.Text = !string.IsNullOrEmpty(ex) ? replacename.Replace(ex, "") : replacename;
x.reader.exportName = x.Text;
}
}
}
exportableAssets.AddRange(tempExportableAssets);
tempExportableAssets.Clear();
}
visibleAssets = exportableAssets;
assetsNameHash.Clear();
}
// second loop - build tree structure
if (buildHierarchy)
{
var gameObjectCount = assetsfileList.Sum(x => x.GameObjects.Count);
if (gameObjectCount > 0)
{
SetProgressBarValue(0);
SetProgressBarMaximum(gameObjectCount);
StatusStripUpdate("Building tree structure...");
foreach (var assetsFile in assetsfileList)
{
var fileNode = new GameObjectTreeNode(null); //RootNode
fileNode.Text = assetsFile.fileName;
foreach (var m_GameObject in assetsFile.GameObjects.Values)
{
foreach (var m_Component in m_GameObject.m_Components)
{
if (m_Component.TryGet(out var asset))
{
switch (asset.type)
{
case ClassIDType.Transform:
{
m_GameObject.m_Transform = m_Component;
break;
}
case ClassIDType.MeshRenderer:
{
m_GameObject.m_MeshRenderer = m_Component;
break;
}
case ClassIDType.MeshFilter:
{
m_GameObject.m_MeshFilter = m_Component;
if (m_Component.TryGet(out var objectReader))
{
var m_MeshFilter = new MeshFilter(objectReader);
if (m_MeshFilter.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.gameObject = m_GameObject;
}
}
break;
}
case ClassIDType.SkinnedMeshRenderer:
{
m_GameObject.m_SkinnedMeshRenderer = m_Component;
if (m_Component.TryGet(out var objectReader))
{
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(objectReader);
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.gameObject = m_GameObject;
}
}
break;
}
case ClassIDType.Animator:
{
m_GameObject.m_Animator = m_Component;
var item = tempDic[asset];
item.Text = m_GameObject.reader.exportName;
asset.exportName = m_GameObject.reader.exportName;
break;
}
}
}
}
var parentNode = fileNode;
if (m_GameObject.m_Transform != null && m_GameObject.m_Transform.TryGetTransform(out var m_Transform))
{
if (m_Transform.m_Father.TryGetTransform(out var m_Father))
{
if (m_Father.m_GameObject.TryGetGameObject(out var parentGameObject))
{
if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode))
{
parentNode = new GameObjectTreeNode(parentGameObject);
treeNodeDictionary.Add(parentGameObject, parentNode);
}
}
}
}
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
{
currentNode = new GameObjectTreeNode(m_GameObject);
treeNodeDictionary.Add(m_GameObject, currentNode);
}
parentNode.Nodes.Add(currentNode);
ProgressBarPerformStep();
}
if (fileNode.Nodes.Count > 0)
{
treeNodeCollection.Add(fileNode);
}
}
}
}
tempDic.Clear();
// build list of class strucutres
if (buildClassStructures)
{
foreach (var assetsFile in assetsfileList)
{
if (AllTypeMap.TryGetValue(assetsFile.unityVersion, out var curVer))
{
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
curVer[key] = new TypeTreeItem(key, type.m_Nodes);
}
}
else
{
var items = new SortedDictionary<int, TypeTreeItem>();
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
items.Add(key, new TypeTreeItem(key, type.m_Nodes));
}
AllTypeMap.Add(assetsFile.unityVersion, items);
}
}
}
}
public static string FixFileName(string str)
{
if (str.Length >= 260) return Path.GetRandomFileName();
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
}
public static string[] ProcessingSplitFiles(List<string> selectFile)
{
var splitFiles = selectFile.Where(x => x.Contains(".split"))
.Select(x => Path.GetDirectoryName(x) + "\\" + Path.GetFileNameWithoutExtension(x))
.Distinct()
.ToList();
selectFile.RemoveAll(x => x.Contains(".split"));
foreach (var file in splitFiles)
{
if (File.Exists(file))
{
selectFile.Add(file);
}
}
return selectFile.Distinct().ToArray();
}
public static void ExportAssets(string savePath, List<AssetItem> toExportAssets, int assetGroupSelectedIndex, bool openAfterExport)
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
int toExport = toExportAssets.Count;
int exportedCount = 0;
SetProgressBarValue(0);
SetProgressBarMaximum(toExport);
foreach (var asset in toExportAssets)
{
var exportpath = savePath + "\\";
if (assetGroupSelectedIndex == 1)
{
exportpath += Path.GetFileNameWithoutExtension(asset.sourceFile.filePath) + "_export\\";
}
else if (assetGroupSelectedIndex == 0)
{
exportpath = savePath + "\\" + asset.TypeString + "\\";
}
StatusStripUpdate($"Exporting {asset.TypeString}: {asset.Text}");
var reader = asset.reader;
try
{
switch (asset.Type)
{
case ClassIDType.Texture2D:
if (ExportTexture2D(reader, exportpath, true))
{
exportedCount++;
}
break;
case ClassIDType.AudioClip:
if (ExportAudioClip(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Shader:
if (ExportShader(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.TextAsset:
if (ExportTextAsset(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.MonoBehaviour:
if (ExportMonoBehaviour(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Font:
if (ExportFont(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Mesh:
if (ExportMesh(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.VideoClip:
if (ExportVideoClip(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.MovieTexture:
if (ExportMovieTexture(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Sprite:
if (ExportSprite(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Animator:
if (ExportAnimator(reader, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.AnimationClip:
break;
default:
if (ExportRawFile(reader, exportpath))
{
exportedCount++;
}
break;
}
}
catch (Exception ex)
{
MessageBox.Show($"Export {asset.Type}:{asset.Text} error\r\n{ex.Message}\r\n{ex.StackTrace}");
}
ProgressBarPerformStep();
}
var statusText = exportedCount == 0 ? "Nothing exported." : $"Finished exporting {exportedCount} assets.";
if (toExport > exportedCount)
{
statusText += $" {toExport - exportedCount} assets skipped (not extractable or files already exist)";
}
StatusStripUpdate(statusText);
if (openAfterExport && exportedCount > 0)
{
Process.Start(savePath);
}
});
}
public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes)
{
ThreadPool.QueueUserWorkItem(state =>
{
foreach (GameObjectTreeNode node in nodes)
{
//遍历一级子节点
foreach (GameObjectTreeNode j in node.Nodes)
{
ProgressBarPerformStep();
//收集所有子节点
var gameObjects = new List<GameObject>();
CollectNode(j, gameObjects);
//跳过一些不需要导出的object
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
continue;
//处理非法文件名
var filename = FixFileName(j.Text);
//每个文件存放在单独的文件夹
var targetPath = $"{savePath}{filename}\\";
//重名文件处理
for (int i = 1; ; i++)
{
if (Directory.Exists(targetPath))
{
targetPath = $"{savePath}{filename} ({i})\\";
}
else
{
break;
}
}
Directory.CreateDirectory(targetPath);
//导出FBX
StatusStripUpdate($"Exporting {filename}.fbx");
try
{
ExportGameObject(j.gameObject, targetPath);
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
}
StatusStripUpdate($"Finished exporting {filename}.fbx");
}
}
StatusStripUpdate("Finished");
});
}
private static void CollectNode(GameObjectTreeNode node, List<GameObject> gameObjects)
{
gameObjects.Add(node.gameObject);
foreach (GameObjectTreeNode i in node.Nodes)
{
CollectNode(i, gameObjects);
}
}
public static void ExportAnimatorWithAnimationClip(AssetItem animator, List<AssetItem> animationList, string exportPath)
{
ThreadPool.QueueUserWorkItem(state =>
{
StatusStripUpdate($"Exporting {animator.Text}");
try
{
ExportAnimator(animator.reader, exportPath, animationList);
StatusStripUpdate($"Finished exporting {animator.Text}");
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
StatusStripUpdate("Error in export");
}
ProgressBarPerformStep();
});
}
public static void ExportObjectsWithAnimationClip(string exportPath, TreeNodeCollection nodes, List<AssetItem> animationList = null)
{
ThreadPool.QueueUserWorkItem(state =>
{
var gameObjects = new List<GameObject>();
GetSelectedParentNode(nodes, gameObjects);
if (gameObjects.Count > 0)
{
SetProgressBarValue(0);
SetProgressBarMaximum(gameObjects.Count);
foreach (var gameObject in gameObjects)
{
StatusStripUpdate($"Exporting {gameObject.m_Name}");
try
{
ExportGameObject(gameObject, exportPath, animationList);
StatusStripUpdate($"Finished exporting {gameObject.m_Name}");
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
StatusStripUpdate("Error in export");
}
ProgressBarPerformStep();
}
}
else
{
StatusStripUpdate("No Object can be exported.");
}
});
}
private static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects)
{
foreach (GameObjectTreeNode i in nodes)
{
if (i.Checked)
{
gameObjects.Add(i.gameObject);
}
else
{
GetSelectedParentNode(i.Nodes, gameObjects);
}
}
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
@ -154,15 +153,14 @@ namespace AssetStudio
reader.AlignStream(4);
}
public static ExpandoObject ReadDynamicType(List<TypeTreeNode> members, EndianBinaryReader reader)
public static Dictionary<string, object> ReadBoxingType(List<TypeTreeNode> members, EndianBinaryReader reader)
{
var obj = new ExpandoObject();
var objdic = (IDictionary<string, object>)obj;
var obj = new Dictionary<string, object>();
for (int i = 0; i < members.Count; i++)
{
var member = members[i];
var varNameStr = member.m_Name;
objdic[varNameStr] = ReadValue(members, reader, ref i);
obj[varNameStr] = ReadValue(members, reader, ref i);
}
return obj;
}
@ -274,13 +272,12 @@ namespace AssetStudio
var @class = GetMembers(members, level, i);
@class.RemoveAt(0);
i += @class.Count;
var obj = new ExpandoObject();
var objdic = (IDictionary<string, object>)obj;
var obj = new Dictionary<string, object>();
for (int j = 0; j < @class.Count; j++)
{
var classmember = @class[j];
var name = classmember.m_Name;
objdic[name] = ReadValue(@class, reader, ref j);
obj[name] = ReadValue(@class, reader, ref j);
}
value = obj;
break;
@ -308,16 +305,15 @@ namespace AssetStudio
return member2;
}
public static byte[] WriteDynamicType(ExpandoObject obj, List<TypeTreeNode> members)
public static byte[] WriteBoxingType(Dictionary<string, object> obj, List<TypeTreeNode> members)
{
var stream = new MemoryStream();
var write = new BinaryWriter(stream);
var objdic = (IDictionary<string, object>)obj;
for (int i = 0; i < members.Count; i++)
{
var member = members[i];
var varNameStr = member.m_Name;
WriteValue(objdic[varNameStr], members, write, ref i);
WriteValue(obj[varNameStr], members, write, ref i);
}
return stream.ToArray();
}
@ -431,13 +427,12 @@ namespace AssetStudio
var @class = GetMembers(members, level, i);
@class.RemoveAt(0);
i += @class.Count;
var obj = (ExpandoObject)value;
var objdic = (IDictionary<string, object>)obj;
var obj = (Dictionary<string, object>)value;
for (int j = 0; j < @class.Count; j++)
{
var classmember = @class[j];
var name = classmember.m_Name;
WriteValue(objdic[name], @class, write, ref j);
WriteValue(obj[name], @class, write, ref j);
}
break;
}

View File

@ -219,7 +219,7 @@ namespace AssetStudio
public static ImportedMesh FindMesh(string frameName, List<ImportedMesh> importedMeshList)
{
foreach (ImportedMesh mesh in importedMeshList)
foreach (var mesh in importedMeshList)
{
if (mesh.Name == frameName)
{
@ -232,15 +232,15 @@ namespace AssetStudio
public static ImportedMesh FindMesh(ImportedFrame frame, List<ImportedMesh> importedMeshList)
{
string framePath = frame.Name;
ImportedFrame root = frame;
var framePath = frame.Name;
var root = frame;
while (root.Parent != null)
{
root = root.Parent;
framePath = root.Name + "/" + framePath;
}
foreach (ImportedMesh mesh in importedMeshList)
foreach (var mesh in importedMeshList)
{
if (mesh.Name == framePath)
{
@ -253,7 +253,7 @@ namespace AssetStudio
public static ImportedMaterial FindMaterial(string name, List<ImportedMaterial> importedMats)
{
foreach (ImportedMaterial mat in importedMats)
foreach (var mat in importedMats)
{
if (mat.Name == name)
{
@ -271,7 +271,7 @@ namespace AssetStudio
return null;
}
foreach (ImportedTexture tex in importedTextureList)
foreach (var tex in importedTextureList)
{
if (tex.Name == name)
{

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public enum LoggerEvent
{
Verbose,
Debug,
Info,
Warning,
Error,
}
public interface ILogger
{
void Log(LoggerEvent loggerEvent, string message);
}
public sealed class DummyLogger : ILogger
{
public void Log(LoggerEvent loggerEvent, string message) { }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public interface IProgress
{
void Report(int value);
}
public sealed class DummyProgress : IProgress
{
public void Report(int value) { }
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{
public static class Logger
{
public static ILogger Default = new DummyLogger();
public static void Verbose(string message) => Default.Log(LoggerEvent.Verbose, message);
public static void Debug(string message) => Default.Log(LoggerEvent.Debug, message);
public static void Info(string message) => Default.Log(LoggerEvent.Info, message);
public static void Warning(string message) => Default.Log(LoggerEvent.Warning, message);
public static void Error(string message) => Default.Log(LoggerEvent.Error, message);
}
}

View File

@ -0,0 +1,29 @@
namespace AssetStudio
{
public static class Progress
{
public static IProgress Default = new DummyProgress();
private static int preValue;
public static void Reset()
{
preValue = 0;
Default.Report(0);
}
public static void Report(int current, int total)
{
var value = (int)(current * 100f / total);
Report(value);
}
private static void Report(int value)
{
if (value > preValue)
{
preValue = value;
Default.Report(value);
}
}
}
}

View File

@ -14,15 +14,13 @@ namespace AssetStudio
public static byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
public List<StreamFile> fileList = new List<StreamFile>();
public class WebData
private class WebData
{
public int dataOffset;
public int dataLength;
public string path;
}
public WebFile(EndianBinaryReader reader)
{
var magic = reader.ReadBytes(2);

View File

@ -1,69 +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="AssetStudio.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<AssetStudio.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="displayOriginalName" serializeAs="String">
<value>False</value>
</setting>
<setting name="eulerFilter" serializeAs="String">
<value>True</value>
</setting>
<setting name="filterPrecision" serializeAs="String">
<value>0.25</value>
</setting>
<setting name="allFrames" serializeAs="String">
<value>False</value>
</setting>
<setting name="allBones" serializeAs="String">
<value>True</value>
</setting>
<setting name="skins" serializeAs="String">
<value>True</value>
</setting>
<setting name="boneSize" serializeAs="String">
<value>10</value>
</setting>
<setting name="flatInbetween" serializeAs="String">
<value>False</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>
</AssetStudio.Properties.Settings>
</userSettings>
</configuration>

View File

@ -9,7 +9,7 @@ using namespace System::Security::Permissions;
[assembly:AssemblyConfigurationAttribute(L"")];
[assembly:AssemblyCompanyAttribute(L"")];
[assembly:AssemblyProductAttribute(L"AssetStudioFBX")];
[assembly:AssemblyCopyrightAttribute(L"Copyright © 2018")];
[assembly:AssemblyCopyrightAttribute(L"Copyright © Perfare 2018")];
[assembly:AssemblyTrademarkAttribute(L"")];
[assembly:AssemblyCultureAttribute(L"")];

View File

@ -150,8 +150,8 @@
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj">
<Project>{9131c403-7fe8-444d-9af5-5fe5df76ff24}</Project>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -487,42 +487,39 @@ namespace AssetStudio
pMeshNode->AddMaterial(pMat);
bool hasTexture = false;
FbxFileTexture* pTextureDiffuse = ExportTexture(ImportedHelpers::FindTexture((String^)mat->Textures[0], imported->TextureList), pMesh);
FbxFileTexture* pTextureDiffuse = ExportTexture(ImportedHelpers::FindTexture(mat->Textures[0], imported->TextureList), pMesh);
if (pTextureDiffuse != NULL)
{
LinkTexture(mat, 0, pTextureDiffuse, pMat->Diffuse);
hasTexture = true;
}
FbxFileTexture* pTextureAmbient = ExportTexture(ImportedHelpers::FindTexture((String^)mat->Textures[1], imported->TextureList), pMesh);
FbxFileTexture* pTextureAmbient = ExportTexture(ImportedHelpers::FindTexture(mat->Textures[1], imported->TextureList), pMesh);
if (pTextureAmbient != NULL)
{
LinkTexture(mat, 1, pTextureAmbient, pMat->Ambient);
hasTexture = true;
}
FbxFileTexture* pTextureEmissive = ExportTexture(ImportedHelpers::FindTexture((String^)mat->Textures[2], imported->TextureList), pMesh);
FbxFileTexture* pTextureEmissive = ExportTexture(ImportedHelpers::FindTexture(mat->Textures[2], imported->TextureList), pMesh);
if (pTextureEmissive != NULL)
{
LinkTexture(mat, 2, pTextureEmissive, pMat->Emissive);
hasTexture = true;
}
FbxFileTexture* pTextureSpecular = ExportTexture(ImportedHelpers::FindTexture((String^)mat->Textures[3], imported->TextureList), pMesh);
FbxFileTexture* pTextureSpecular = ExportTexture(ImportedHelpers::FindTexture(mat->Textures[3], imported->TextureList), pMesh);
if (pTextureSpecular != NULL)
{
LinkTexture(mat, 3, pTextureSpecular, pMat->Specular);
hasTexture = true;
}
if (mat->Textures->Length > 4)
FbxFileTexture* pTextureBump = ExportTexture(ImportedHelpers::FindTexture(mat->Textures[4], imported->TextureList), pMesh);
if (pTextureBump != NULL)
{
FbxFileTexture* pTextureBump = ExportTexture(ImportedHelpers::FindTexture((String^)mat->Textures[4], imported->TextureList), pMesh);
if (pTextureBump != NULL)
{
LinkTexture(mat, 4, pTextureBump, pMat->Bump);
hasTexture = true;
}
LinkTexture(mat, 4, pTextureBump, pMat->Bump);
hasTexture = true;
}
if (hasTexture)

View File

@ -0,0 +1,201 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudioGUI</RootNamespace>
<AssemblyName>AssetStudioGUI</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="dnlib, Version=3.0.0.0, Culture=neutral, PublicKeyToken=50e96378b6e77999, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\AssetStudio\Libraries\dnlib.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OpenTK, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\AssetStudio\Libraries\OpenTK.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="OpenTK.GLControl, Version=3.0.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\AssetStudio\Libraries\OpenTK.GLControl.dll</HintPath>
<Private>False</Private>
</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.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="GUILogger.cs" />
<Compile Include="GUIProgress.cs" />
<Compile Include="Components\GameObjectTreeNode.cs" />
<Compile Include="Components\OpenFolderDialog.cs" />
<Compile Include="Components\AssetItem.cs" />
<Compile Include="Exporter.cs" />
<Compile Include="Studio.cs" />
<Compile Include="ExportOptions.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ExportOptions.Designer.cs">
<DependentUpon>ExportOptions.cs</DependentUpon>
</Compile>
<Compile Include="Components\GOHierarchy.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AssetStudioGUIForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AssetStudioGUIForm.Designer.cs">
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
</Compile>
<Compile Include="Components\TypeTreeItem.cs" />
<Compile Include="Components\TreeViewExtensions.cs" />
<EmbeddedResource Include="ExportOptions.resx">
<DependentUpon>ExportOptions.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<EmbeddedResource Include="AssetStudioGUIForm.resx">
<DependentUpon>AssetStudioGUIForm.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0,Profile=Client">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4 Client Profile %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.4.5">
<Visible>False</Visible>
<ProductName>Windows Installer 4.5</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup>
<None Include="Resources\preview.png" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\as.ico" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioTools\AssetStudioTools.csproj">
<Project>{9131c403-7fe8-444d-9af5-5fe5df76ff24}</Project>
<Name>AssetStudioTools</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>xcopy /y "$(SolutionDir)AssetStudio\Libraries" "$(TargetDir)"
xcopy /y "$(SolutionDir)AssetStudio\Libraries\$(PlatformName)" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,6 +1,6 @@
namespace AssetStudio
namespace AssetStudioGUI
{
partial class AssetStudioForm
partial class AssetStudioGUIForm
{
/// <summary>
/// Required designer variable.
@ -29,7 +29,7 @@
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AssetStudioForm));
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AssetStudioGUIForm));
this.menuStrip1 = new System.Windows.Forms.MenuStrip();
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.loadFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@ -66,7 +66,7 @@
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.sceneTreeView = new AssetStudio.GOHierarchy();
this.sceneTreeView = new AssetStudioGUI.GOHierarchy();
this.treeSearch = new System.Windows.Forms.TextBox();
this.tabPage2 = new System.Windows.Forms.TabPage();
this.assetListView = new System.Windows.Forms.ListView();
@ -574,7 +574,7 @@
// previewPanel
//
this.previewPanel.BackColor = System.Drawing.SystemColors.ControlDark;
this.previewPanel.BackgroundImage = global::AssetStudio.Properties.Resources.preview;
this.previewPanel.BackgroundImage = global::AssetStudioGUI.Properties.Resources.preview;
this.previewPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.previewPanel.Controls.Add(this.assetInfoLabel);
this.previewPanel.Controls.Add(this.FMODpanel);
@ -913,20 +913,20 @@
this.showOriginalFileToolStripMenuItem.Visible = false;
this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);
//
// AssetStudioForm
// AssetStudioGUIForm
//
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);
this.Icon = global::AssetStudio.Properties.Resources._as;
this.Icon = global::AssetStudioGUI.Properties.Resources._as;
this.KeyPreview = true;
this.MainMenuStrip = this.menuStrip1;
this.MinimumSize = new System.Drawing.Size(620, 372);
this.Name = "AssetStudioForm";
this.Name = "AssetStudioGUIForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "AssetStudio";
this.Text = "AssetStudioGUI";
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
this.menuStrip1.ResumeLayout(false);
this.menuStrip1.PerformLayout();

View File

@ -1,13 +1,11 @@
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms;
using AssetStudio;
namespace AssetStudio
namespace AssetStudioGUI
{
public class AssetItem : ListViewItem
internal class AssetItem : ListViewItem
{
public AssetsFile sourceFile;
public SerializedFile sourceFile;
public ObjectReader reader;
public long FullSize;
public ClassIDType Type;

View File

@ -4,9 +4,9 @@ using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
namespace AssetStudioGUI
{
public class GOHierarchy : TreeView
internal class GOHierarchy : TreeView
{
protected override void WndProc(ref Message m)
{

View File

@ -0,0 +1,21 @@
using System.Windows.Forms;
using AssetStudio;
namespace AssetStudioGUI
{
internal class GameObjectTreeNode : TreeNode
{
public GameObject gameObject;
public GameObjectTreeNode(string name)
{
Text = name;
}
public GameObjectTreeNode(GameObject gameObject)
{
this.gameObject = gameObject;
Text = gameObject.m_Name;
}
}
}

View File

@ -4,9 +4,9 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace AssetStudio
namespace AssetStudioGUI
{
class OpenFolderDialog
internal class OpenFolderDialog
{
public string InitialFolder { get; set; }
public string DefaultFolder { get; set; }

View File

@ -1,13 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
namespace AssetStudioGUI
{
public static class TreeViewExtensions
internal static class TreeViewExtensions
{
private const int TVIF_STATE = 0x8;
private const int TVIS_STATEIMAGEMASK = 0xF000;

View File

@ -1,14 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using AssetStudio;
namespace AssetStudio
namespace AssetStudioGUI
{
public class TypeTreeItem : ListViewItem
internal class TypeTreeItem : ListViewItem
{
public List<TypeTreeNode> m_Nodes;
private List<TypeTreeNode> m_Nodes;
public TypeTreeItem(int typeID, List<TypeTreeNode> m_Nodes)
{

View File

@ -1,4 +1,4 @@
namespace AssetStudio
namespace AssetStudioGUI
{
partial class ExportOptions
{

View File

@ -8,7 +8,7 @@ using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace AssetStudio
namespace AssetStudioGUI
{
public partial class ExportOptions : Form
{

View File

@ -1,25 +1,24 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using AssetStudio;
namespace AssetStudio
namespace AssetStudioGUI
{
static class Exporter
internal static class Exporter
{
public static bool ExportTexture2D(ObjectReader reader, string exportPathName, bool flip)
public static bool ExportTexture2D(AssetItem item, string exportPathName)
{
var m_Texture2D = new Texture2D(reader, true);
var m_Texture2D = new Texture2D(item.reader, true);
if (m_Texture2D.image_data == null || m_Texture2D.image_data.Length == 0)
return false;
var converter = new Texture2DConverter(m_Texture2D);
var convertTexture = (bool)Properties.Settings.Default["convertTexture"];
if (convertTexture)
{
var bitmap = converter.ConvertToBitmap(flip);
var bitmap = converter.ConvertToBitmap(true);
if (bitmap == null)
return false;
ImageFormat format = null;
@ -36,7 +35,7 @@ namespace AssetStudio
format = ImageFormat.Jpeg;
break;
}
var exportFullName = exportPathName + reader.exportName + "." + ext.ToLower();
var exportFullName = exportPathName + item.Text + "." + ext.ToLower();
if (ExportFileExists(exportFullName))
return false;
bitmap.Save(exportFullName, format);
@ -45,7 +44,7 @@ namespace AssetStudio
}
else
{
var exportFullName = exportPathName + reader.exportName + converter.GetExtensionName();
var exportFullName = exportPathName + item.Text + converter.GetExtensionName();
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, converter.ConvertToContainer());
@ -53,16 +52,16 @@ namespace AssetStudio
}
}
public static bool ExportAudioClip(ObjectReader reader, string exportPath)
public static bool ExportAudioClip(AssetItem item, string exportPath)
{
var m_AudioClip = new AudioClip(reader, true);
var m_AudioClip = new AudioClip(item.reader, true);
if (m_AudioClip.m_AudioData == null)
return false;
var convertAudio = (bool)Properties.Settings.Default["convertAudio"];
var converter = new AudioClipConverter(m_AudioClip);
if (convertAudio && converter.IsFMODSupport)
{
var exportFullName = exportPath + reader.exportName + ".wav";
var exportFullName = exportPath + item.Text + ".wav";
if (ExportFileExists(exportFullName))
return false;
var buffer = converter.ConvertToWav();
@ -72,7 +71,7 @@ namespace AssetStudio
}
else
{
var exportFullName = exportPath + reader.exportName + converter.GetExtensionName();
var exportFullName = exportPath + item.Text + converter.GetExtensionName();
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_AudioClip.m_AudioData);
@ -80,10 +79,10 @@ namespace AssetStudio
return true;
}
public static bool ExportShader(ObjectReader reader, string exportPath)
public static bool ExportShader(AssetItem item, string exportPath)
{
var m_Shader = new Shader(reader);
var exportFullName = exportPath + reader.exportName + ".shader";
var m_Shader = new Shader(item.reader);
var exportFullName = exportPath + item.Text + ".shader";
if (ExportFileExists(exportFullName))
return false;
var str = ShaderConverter.Convert(m_Shader);
@ -91,22 +90,22 @@ namespace AssetStudio
return true;
}
public static bool ExportTextAsset(ObjectReader reader, string exportPath)
public static bool ExportTextAsset(AssetItem item, string exportPath)
{
var m_TextAsset = new TextAsset(reader);
var exportFullName = exportPath + reader.exportName + ".txt";
var m_TextAsset = new TextAsset(item.reader);
var exportFullName = exportPath + item.Text + ".txt";
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_TextAsset.m_Script);
return true;
}
public static bool ExportMonoBehaviour(ObjectReader reader, string exportPath)
public static bool ExportMonoBehaviour(AssetItem item, string exportPath)
{
var exportFullName = exportPath + reader.exportName + ".txt";
var exportFullName = exportPath + item.Text + ".txt";
if (ExportFileExists(exportFullName))
return false;
var m_MonoBehaviour = new MonoBehaviour(reader);
var reader = item.reader;
string str;
if (reader.serializedType?.m_Nodes != null)
{
@ -114,15 +113,15 @@ namespace AssetStudio
}
else
{
str = ScriptHelper.GetScriptString(reader);
str = Studio.GetScriptString(reader);
}
File.WriteAllText(exportFullName, str);
return true;
}
public static bool ExportFont(ObjectReader reader, string exportPath)
public static bool ExportFont(AssetItem item, string exportPath)
{
var m_Font = new Font(reader);
var m_Font = new Font(item.reader);
if (m_Font.m_FontData != null)
{
var extension = ".ttf";
@ -130,7 +129,7 @@ namespace AssetStudio
{
extension = ".otf";
}
var exportFullName = exportPath + reader.exportName + extension;
var exportFullName = exportPath + item.Text + extension;
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_Font.m_FontData);
@ -139,12 +138,12 @@ namespace AssetStudio
return false;
}
public static bool ExportMesh(ObjectReader reader, string exportPath)
public static bool ExportMesh(AssetItem item, string exportPath)
{
var m_Mesh = new Mesh(reader);
var m_Mesh = new Mesh(item.reader);
if (m_Mesh.m_VertexCount <= 0)
return false;
var exportFullName = exportPath + reader.exportName + ".obj";
var exportFullName = exportPath + item.Text + ".obj";
if (ExportFileExists(exportFullName))
return false;
var sb = new StringBuilder();
@ -166,20 +165,20 @@ namespace AssetStudio
#endregion
#region UV
if (m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length == m_Mesh.m_VertexCount * 2)
if (m_Mesh.m_UV0 != null && m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
{
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
{
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV0[v * 2], m_Mesh.m_UV0[v * 2 + 1]);
}
}
else if (m_Mesh.m_UV1 != null && m_Mesh.m_UV1.Length == m_Mesh.m_VertexCount * 2)
{
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
{
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV1[v * 2], m_Mesh.m_UV1[v * 2 + 1]);
}
}
else if (m_Mesh.m_UV2 != null && m_Mesh.m_UV2.Length == m_Mesh.m_VertexCount * 2)
{
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
{
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV2[v * 2], m_Mesh.m_UV2[v * 2 + 1]);
}
}
#endregion
#region Normals
@ -220,12 +219,12 @@ namespace AssetStudio
return true;
}
public static bool ExportVideoClip(ObjectReader reader, string exportPath)
public static bool ExportVideoClip(AssetItem item, string exportPath)
{
var m_VideoClip = new VideoClip(reader, true);
var m_VideoClip = new VideoClip(item.reader, true);
if (m_VideoClip.m_VideoData != null)
{
var exportFullName = exportPath + reader.exportName + Path.GetExtension(m_VideoClip.m_OriginalPath);
var exportFullName = exportPath + item.Text + Path.GetExtension(m_VideoClip.m_OriginalPath);
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_VideoClip.m_VideoData);
@ -234,17 +233,17 @@ namespace AssetStudio
return false;
}
public static bool ExportMovieTexture(ObjectReader reader, string exportPath)
public static bool ExportMovieTexture(AssetItem item, string exportPath)
{
var m_MovieTexture = new MovieTexture(reader);
var exportFullName = exportPath + reader.exportName + ".ogv";
var m_MovieTexture = new MovieTexture(item.reader);
var exportFullName = exportPath + item.Text + ".ogv";
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, m_MovieTexture.m_MovieData);
return true;
}
public static bool ExportSprite(ObjectReader reader, string exportPath)
public static bool ExportSprite(AssetItem item, string exportPath)
{
ImageFormat format = null;
var type = (string)Properties.Settings.Default["convertType"];
@ -260,10 +259,10 @@ namespace AssetStudio
format = ImageFormat.Jpeg;
break;
}
var exportFullName = exportPath + reader.exportName + "." + type.ToLower();
var exportFullName = exportPath + item.Text + "." + type.ToLower();
if (ExportFileExists(exportFullName))
return false;
var bitmap = SpriteHelper.GetImageFromSprite(new Sprite(reader));
var bitmap = SpriteHelper.GetImageFromSprite(new Sprite(item.reader));
if (bitmap != null)
{
bitmap.Save(exportFullName, format);
@ -273,12 +272,12 @@ namespace AssetStudio
return false;
}
public static bool ExportRawFile(ObjectReader reader, string exportPath)
public static bool ExportRawFile(AssetItem item, string exportPath)
{
var exportFullName = exportPath + reader.exportName + ".dat";
var exportFullName = exportPath + item.Text + ".dat";
if (ExportFileExists(exportFullName))
return false;
File.WriteAllBytes(exportFullName, reader.GetRawData());
File.WriteAllBytes(exportFullName, item.reader.GetRawData());
return true;
}
@ -292,22 +291,22 @@ namespace AssetStudio
return false;
}
public static bool ExportAnimator(ObjectReader animator, string exportPath, List<AssetItem> animationList = null)
public static bool ExportAnimator(AssetItem item, string exportPath, List<AssetItem> animationList = null)
{
var m_Animator = new Animator(animator);
var convert = animationList != null ? new ModelConverter(m_Animator, animationList) : new ModelConverter(m_Animator);
exportPath = exportPath + Studio.FixFileName(animator.exportName) + ".fbx";
return ModelConverter(convert, exportPath);
var m_Animator = new Animator(item.reader);
var convert = animationList != null ? new ModelConverter(m_Animator, animationList.Select(x => x.reader).ToArray()) : new ModelConverter(m_Animator);
exportPath = exportPath + item.Text + ".fbx";
return ExportFbx(convert, exportPath);
}
public static bool ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{
var convert = animationList != null ? new ModelConverter(gameObject, animationList) : new ModelConverter(gameObject);
var convert = animationList != null ? new ModelConverter(gameObject, animationList.Select(x => x.reader).ToArray()) : new ModelConverter(gameObject);
exportPath = exportPath + Studio.FixFileName(gameObject.m_Name) + ".fbx";
return ModelConverter(convert, exportPath);
return ExportFbx(convert, exportPath);
}
private static bool ModelConverter(ModelConverter convert, string exportPath)
private static bool ExportFbx(IImported convert, string exportPath)
{
var eulerFilter = (bool)Properties.Settings.Default["eulerFilter"];
var filterPrecision = (float)(decimal)Properties.Settings.Default["filterPrecision"];
@ -319,7 +318,7 @@ namespace AssetStudio
var flatInbetween = (bool)Properties.Settings.Default["flatInbetween"];
var fbxVersion = (int)Properties.Settings.Default["fbxVersion"];
var fbxFormat = (int)Properties.Settings.Default["fbxFormat"];
Fbx.Exporter.Export(exportPath, convert, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, fbxVersion, fbxFormat == 1);
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, fbxVersion, fbxFormat == 1);
return true;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AssetStudio;
namespace AssetStudioGUI
{
class GUILogger : ILogger
{
private Action<string> action;
public GUILogger(Action<string> action)
{
this.action = action;
}
public void Log(LoggerEvent loggerEvent, string message)
{
action(message);
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AssetStudio;
namespace AssetStudioGUI
{
class GUIProgress : IProgress
{
private Action<int> action;
public GUIProgress(Action<int> action)
{
this.action = action;
}
public void Report(int value)
{
action(value);
}
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace AssetStudio
namespace AssetStudioGUI
{
static class Program
{
@ -15,7 +15,7 @@ namespace AssetStudio
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new AssetStudioForm());
Application.Run(new AssetStudioGUIForm());
}
}
}

View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("AssetStudioGUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioGUI")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("05c04c20-dd89-4895-9f06-33d5cfbfe925")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace AssetStudio.Properties {
namespace AssetStudioGUI.Properties {
using System;
@ -39,16 +39,15 @@ namespace AssetStudio.Properties {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AssetStudio.Properties.Resources", typeof(Resources).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AssetStudioGUI.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// 使用此强类型资源类,为所有资源查找
/// 重写当前线程的 CurrentUICulture 属性。
/// 重写当前线程的 CurrentUICulture 属性
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {

View File

@ -8,11 +8,11 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace AssetStudio.Properties {
namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.8.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

View File

@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="AssetStudio.Properties" GeneratedClassName="Settings">
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="AssetStudioGUI.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="displayAll" Type="System.Boolean" Scope="User">

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

711
AssetStudioGUI/Studio.cs Normal file
View File

@ -0,0 +1,711 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using AssetStudio;
using dnlib.DotNet;
using static AssetStudioGUI.Exporter;
namespace AssetStudioGUI
{
internal static class Studio
{
public static AssetsManager assetsManager = new AssetsManager();
private static HashSet<string> assetsNameHash = new HashSet<string>();
public static List<AssetItem> exportableAssets = new List<AssetItem>();
public static List<AssetItem> visibleAssets = new List<AssetItem>();
public static Dictionary<string, SortedDictionary<int, TypeTreeItem>> AllTypeMap = new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();
public static Dictionary<GameObject, GameObjectTreeNode> treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>();
public static bool ModuleLoaded;
public static Dictionary<string, ModuleDef> LoadedModuleDic = new Dictionary<string, ModuleDef>();
public static void ExtractFile(string[] fileNames)
{
ThreadPool.QueueUserWorkItem(state =>
{
int extractedCount = 0;
Progress.Reset();
for (var i = 0; i < fileNames.Length; i++)
{
var fileName = fileNames[i];
var type = ImportHelper.CheckFileType(fileName, out var reader);
if (type == FileType.BundleFile)
extractedCount += ExtractBundleFile(fileName, reader);
else if (type == FileType.WebFile)
extractedCount += ExtractWebDataFile(fileName, reader);
else
reader.Dispose();
Progress.Report(i + 1, fileName.Length);
}
Logger.Info($"Finished extracting {extractedCount} files.");
});
}
private static int ExtractBundleFile(string bundleFileName, EndianBinaryReader reader)
{
Logger.Info($"Decompressing {Path.GetFileName(bundleFileName)} ...");
var bundleFile = new BundleFile(reader, bundleFileName);
reader.Dispose();
if (bundleFile.fileList.Count > 0)
{
var extractPath = bundleFileName + "_unpacked\\";
Directory.CreateDirectory(extractPath);
return ExtractStreamFile(extractPath, bundleFile.fileList);
}
return 0;
}
private static int ExtractWebDataFile(string webFileName, EndianBinaryReader reader)
{
Logger.Info($"Decompressing {Path.GetFileName(webFileName)} ...");
var webFile = new WebFile(reader);
reader.Dispose();
if (webFile.fileList.Count > 0)
{
var extractPath = webFileName + "_unpacked\\";
Directory.CreateDirectory(extractPath);
return ExtractStreamFile(extractPath, webFile.fileList);
}
return 0;
}
private static int ExtractStreamFile(string extractPath, List<StreamFile> fileList)
{
int extractedCount = 0;
foreach (var file in fileList)
{
var filePath = extractPath + file.fileName;
if (!Directory.Exists(extractPath))
{
Directory.CreateDirectory(extractPath);
}
if (!File.Exists(filePath) && file.stream is MemoryStream stream)
{
File.WriteAllBytes(filePath, stream.ToArray());
extractedCount += 1;
}
file.stream.Dispose();
}
return extractedCount;
}
public static void BuildAssetList(Dictionary<ObjectReader, AssetItem> tempDic, bool displayAll, bool displayOriginalName, out string productName)
{
productName = string.Empty;
Logger.Info("Building asset list...");
var progressCount = assetsManager.assetsFileList.Sum(x => x.ObjectReaders.Count);
int j = 0;
Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList)
{
var tempExportableAssets = new List<AssetItem>();
AssetBundle ab = null;
foreach (var objectReader in assetsFile.ObjectReaders.Values)
{
var assetItem = new AssetItem(objectReader);
tempDic.Add(objectReader, assetItem);
assetItem.UniqueID = " #" + j;
var exportable = false;
switch (assetItem.Type)
{
case ClassIDType.GameObject:
{
var m_GameObject = new GameObject(objectReader);
assetItem.Text = m_GameObject.m_Name;
assetsFile.GameObjects.Add(objectReader.m_PathID, m_GameObject);
break;
}
case ClassIDType.Transform:
{
var m_Transform = new Transform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Transform);
break;
}
case ClassIDType.RectTransform:
{
var m_Rect = new RectTransform(objectReader);
assetsFile.Transforms.Add(objectReader.m_PathID, m_Rect);
break;
}
case ClassIDType.Texture2D:
{
var m_Texture2D = new Texture2D(objectReader, false);
if (!string.IsNullOrEmpty(m_Texture2D.path))
assetItem.FullSize = objectReader.byteSize + m_Texture2D.size;
assetItem.Text = m_Texture2D.m_Name;
exportable = true;
break;
}
case ClassIDType.AudioClip:
{
var m_AudioClip = new AudioClip(objectReader, false);
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = objectReader.byteSize + m_AudioClip.m_Size;
assetItem.Text = m_AudioClip.m_Name;
exportable = true;
break;
}
case ClassIDType.VideoClip:
{
var m_VideoClip = new VideoClip(objectReader, false);
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
assetItem.FullSize = objectReader.byteSize + (long)m_VideoClip.m_Size;
assetItem.Text = m_VideoClip.m_Name;
exportable = true;
break;
}
case ClassIDType.Shader:
{
var m_Shader = new Shader(objectReader);
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
exportable = true;
break;
}
case ClassIDType.Mesh:
case ClassIDType.TextAsset:
case ClassIDType.AnimationClip:
case ClassIDType.Font:
case ClassIDType.MovieTexture:
case ClassIDType.Sprite:
{
var obj = new NamedObject(objectReader);
assetItem.Text = obj.m_Name;
exportable = true;
break;
}
case ClassIDType.Avatar:
case ClassIDType.AnimatorController:
case ClassIDType.AnimatorOverrideController:
case ClassIDType.Material:
case ClassIDType.MonoScript:
case ClassIDType.SpriteAtlas:
{
var obj = new NamedObject(objectReader);
assetItem.Text = obj.m_Name;
break;
}
case ClassIDType.Animator:
{
exportable = true;
break;
}
case ClassIDType.MonoBehaviour:
{
var m_MonoBehaviour = new MonoBehaviour(objectReader);
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var script))
{
var m_Script = new MonoScript(script);
assetItem.Text = m_Script.m_ClassName;
}
else
{
assetItem.Text = m_MonoBehaviour.m_Name;
}
exportable = true;
break;
}
case ClassIDType.PlayerSettings:
{
var plSet = new PlayerSettings(objectReader);
productName = plSet.productName;
break;
}
case ClassIDType.AssetBundle:
{
ab = new AssetBundle(objectReader);
assetItem.Text = ab.m_Name;
break;
}
}
if (assetItem.Text == "")
{
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
}
assetItem.SubItems.AddRange(new[] { assetItem.TypeString, assetItem.FullSize.ToString() });
//处理同名文件
if (!assetsNameHash.Add((assetItem.TypeString + assetItem.Text).ToUpper()))
{
assetItem.Text += assetItem.UniqueID;
}
//处理非法文件名
assetItem.Text = FixFileName(assetItem.Text);
if (displayAll)
{
exportable = true;
}
if (exportable)
{
tempExportableAssets.Add(assetItem);
}
Progress.Report(++j, progressCount);
}
if (displayOriginalName && ab != null)
{
foreach (var x in tempExportableAssets)
{
var replacename = ab.m_Container.Find(y => y.second.asset.m_PathID == x.reader.m_PathID)?.first;
if (!string.IsNullOrEmpty(replacename))
{
var ex = Path.GetExtension(replacename);
x.Text = !string.IsNullOrEmpty(ex) ? replacename.Replace(ex, "") : replacename;
if (!assetsNameHash.Add((x.TypeString + x.Text).ToUpper()))
{
x.Text = Path.GetDirectoryName(replacename) + "\\" + Path.GetFileNameWithoutExtension(replacename) + x.UniqueID;
}
}
}
}
exportableAssets.AddRange(tempExportableAssets);
tempExportableAssets.Clear();
}
visibleAssets = exportableAssets;
assetsNameHash.Clear();
}
public static List<GameObjectTreeNode> BuildTreeStructure(Dictionary<ObjectReader, AssetItem> tempDic)
{
var treeNodeCollection = new List<GameObjectTreeNode>();
var gameObjectCount = assetsManager.assetsFileList.Sum(x => x.GameObjects.Count);
if (gameObjectCount > 0)
{
Logger.Info("Building tree structure...");
int i = 0;
Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList)
{
var fileNode = new GameObjectTreeNode(assetsFile.fileName); //RootNode
foreach (var m_GameObject in assetsFile.GameObjects.Values)
{
foreach (var m_Component in m_GameObject.m_Components)
{
if (m_Component.TryGet(out var asset))
{
switch (asset.type)
{
case ClassIDType.Transform:
{
m_GameObject.m_Transform = m_Component;
break;
}
case ClassIDType.MeshRenderer:
{
m_GameObject.m_MeshRenderer = m_Component;
break;
}
case ClassIDType.MeshFilter:
{
m_GameObject.m_MeshFilter = m_Component;
if (m_Component.TryGet(out var objectReader))
{
var m_MeshFilter = new MeshFilter(objectReader);
if (m_MeshFilter.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.gameObject = m_GameObject;
}
}
break;
}
case ClassIDType.SkinnedMeshRenderer:
{
m_GameObject.m_SkinnedMeshRenderer = m_Component;
if (m_Component.TryGet(out var objectReader))
{
var m_SkinnedMeshRenderer = new SkinnedMeshRenderer(objectReader);
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out objectReader))
{
var item = tempDic[objectReader];
item.gameObject = m_GameObject;
}
}
break;
}
case ClassIDType.Animator:
{
m_GameObject.m_Animator = m_Component;
var item = tempDic[asset];
item.Text = tempDic[m_GameObject.reader].Text;
break;
}
}
}
}
var parentNode = fileNode;
if (m_GameObject.m_Transform != null && m_GameObject.m_Transform.TryGetTransform(out var m_Transform))
{
if (m_Transform.m_Father.TryGetTransform(out var m_Father))
{
if (m_Father.m_GameObject.TryGetGameObject(out var parentGameObject))
{
if (!treeNodeDictionary.TryGetValue(parentGameObject, out parentNode))
{
parentNode = new GameObjectTreeNode(parentGameObject);
treeNodeDictionary.Add(parentGameObject, parentNode);
}
}
}
}
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
{
currentNode = new GameObjectTreeNode(m_GameObject);
treeNodeDictionary.Add(m_GameObject, currentNode);
}
parentNode.Nodes.Add(currentNode);
Progress.Report(++i, gameObjectCount);
}
if (fileNode.Nodes.Count > 0)
{
treeNodeCollection.Add(fileNode);
}
}
}
return treeNodeCollection;
}
public static void BuildClassStructure()
{
foreach (var assetsFile in assetsManager.assetsFileList)
{
if (AllTypeMap.TryGetValue(assetsFile.unityVersion, out var curVer))
{
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
curVer[key] = new TypeTreeItem(key, type.m_Nodes);
}
}
else
{
var items = new SortedDictionary<int, TypeTreeItem>();
foreach (var type in assetsFile.m_Types.Where(x => x.m_Nodes != null))
{
var key = type.classID;
if (type.m_ScriptTypeIndex >= 0)
{
key = -1 - type.m_ScriptTypeIndex;
}
items.Add(key, new TypeTreeItem(key, type.m_Nodes));
}
AllTypeMap.Add(assetsFile.unityVersion, items);
}
}
}
public static string FixFileName(string str)
{
if (str.Length >= 260) return Path.GetRandomFileName();
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
}
public static void ExportAssets(string savePath, List<AssetItem> toExportAssets, int assetGroupSelectedIndex, bool openAfterExport)
{
ThreadPool.QueueUserWorkItem(state =>
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
int toExportCount = toExportAssets.Count;
int exportedCount = 0;
int i = 0;
Progress.Reset();
foreach (var asset in toExportAssets)
{
var exportpath = savePath + "\\";
if (assetGroupSelectedIndex == 1)
{
exportpath += Path.GetFileNameWithoutExtension(asset.sourceFile.fullName) + "_export\\";
}
else if (assetGroupSelectedIndex == 0)
{
exportpath = savePath + "\\" + asset.TypeString + "\\";
}
Logger.Info($"Exporting {asset.TypeString}: {asset.Text}");
try
{
switch (asset.Type)
{
case ClassIDType.Texture2D:
if (ExportTexture2D(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.AudioClip:
if (ExportAudioClip(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Shader:
if (ExportShader(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.TextAsset:
if (ExportTextAsset(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.MonoBehaviour:
if (ExportMonoBehaviour(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Font:
if (ExportFont(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Mesh:
if (ExportMesh(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.VideoClip:
if (ExportVideoClip(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.MovieTexture:
if (ExportMovieTexture(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Sprite:
if (ExportSprite(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.Animator:
if (ExportAnimator(asset, exportpath))
{
exportedCount++;
}
break;
case ClassIDType.AnimationClip:
break;
default:
if (ExportRawFile(asset, exportpath))
{
exportedCount++;
}
break;
}
}
catch (Exception ex)
{
MessageBox.Show($"Export {asset.Type}:{asset.Text} error\r\n{ex.Message}\r\n{ex.StackTrace}");
}
Progress.Report(++i, toExportCount);
}
var statusText = exportedCount == 0 ? "Nothing exported." : $"Finished exporting {exportedCount} assets.";
if (toExportCount > exportedCount)
{
statusText += $" {toExportCount - exportedCount} assets skipped (not extractable or files already exist)";
}
Logger.Info(statusText);
if (openAfterExport && exportedCount > 0)
{
Process.Start(savePath);
}
});
}
public static void ExportSplitObjects(string savePath, TreeNodeCollection nodes)
{
ThreadPool.QueueUserWorkItem(state =>
{
var count = nodes.Cast<TreeNode>().Sum(x => x.Nodes.Count);
int k = 0;
Progress.Reset();
foreach (GameObjectTreeNode node in nodes)
{
//遍历一级子节点
foreach (GameObjectTreeNode j in node.Nodes)
{
//收集所有子节点
var gameObjects = new List<GameObject>();
CollectNode(j, gameObjects);
//跳过一些不需要导出的object
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
continue;
//处理非法文件名
var filename = FixFileName(j.Text);
//每个文件存放在单独的文件夹
var targetPath = $"{savePath}{filename}\\";
//重名文件处理
for (int i = 1; ; i++)
{
if (Directory.Exists(targetPath))
{
targetPath = $"{savePath}{filename} ({i})\\";
}
else
{
break;
}
}
Directory.CreateDirectory(targetPath);
//导出FBX
Logger.Info($"Exporting {filename}.fbx");
try
{
ExportGameObject(j.gameObject, targetPath);
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
}
Progress.Report(++k, count);
Logger.Info($"Finished exporting {filename}.fbx");
}
}
Logger.Info("Finished");
});
}
private static void CollectNode(GameObjectTreeNode node, List<GameObject> gameObjects)
{
gameObjects.Add(node.gameObject);
foreach (GameObjectTreeNode i in node.Nodes)
{
CollectNode(i, gameObjects);
}
}
public static void ExportAnimatorWithAnimationClip(AssetItem animator, List<AssetItem> animationList, string exportPath)
{
ThreadPool.QueueUserWorkItem(state =>
{
Logger.Info($"Exporting {animator.Text}");
try
{
ExportAnimator(animator, exportPath, animationList);
Logger.Info($"Finished exporting {animator.Text}");
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
Logger.Info("Error in export");
}
});
}
public static void ExportObjectsWithAnimationClip(string exportPath, TreeNodeCollection nodes, List<AssetItem> animationList = null)
{
ThreadPool.QueueUserWorkItem(state =>
{
var gameObjects = new List<GameObject>();
GetSelectedParentNode(nodes, gameObjects);
if (gameObjects.Count > 0)
{
var count = gameObjects.Count;
int i = 0;
Progress.Reset();
foreach (var gameObject in gameObjects)
{
Logger.Info($"Exporting {gameObject.m_Name}");
try
{
ExportGameObject(gameObject, exportPath, animationList);
Logger.Info($"Finished exporting {gameObject.m_Name}");
}
catch (Exception ex)
{
MessageBox.Show($"{ex.Message}\r\n{ex.StackTrace}");
Logger.Info("Error in export");
}
Progress.Report(++i, count);
}
}
else
{
Logger.Info("No Object can be exported.");
}
});
}
private static void GetSelectedParentNode(TreeNodeCollection nodes, List<GameObject> gameObjects)
{
foreach (GameObjectTreeNode i in nodes)
{
if (i.Checked)
{
gameObjects.Add(i.gameObject);
}
else
{
GetSelectedParentNode(i.Nodes, gameObjects);
}
}
}
public static string GetScriptString(ObjectReader reader)
{
if (!ModuleLoaded)
{
var openFolderDialog = new OpenFolderDialog();
openFolderDialog.Title = "Select Assembly Folder";
if (openFolderDialog.ShowDialog() == DialogResult.OK)
{
var files = Directory.GetFiles(openFolderDialog.Folder, "*.dll");
var moduleContext = new ModuleContext();
var asmResolver = new AssemblyResolver(moduleContext, true);
var resolver = new Resolver(asmResolver);
moduleContext.AssemblyResolver = asmResolver;
moduleContext.Resolver = resolver;
try
{
foreach (var file in files)
{
var module = ModuleDefMD.Load(file, moduleContext);
LoadedModuleDic.Add(Path.GetFileName(file), module);
}
}
catch
{
// ignored
}
}
ModuleLoaded = true;
}
return ScriptHelper.GetScriptString(reader, LoadedModuleDic);
}
}
}

69
AssetStudioGUI/app.config Normal file
View File

@ -0,0 +1,69 @@
<?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>
<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="displayOriginalName" serializeAs="String">
<value>False</value>
</setting>
<setting name="eulerFilter" serializeAs="String">
<value>True</value>
</setting>
<setting name="filterPrecision" serializeAs="String">
<value>0.25</value>
</setting>
<setting name="allFrames" serializeAs="String">
<value>False</value>
</setting>
<setting name="allBones" serializeAs="String">
<value>True</value>
</setting>
<setting name="skins" serializeAs="String">
<value>True</value>
</setting>
<setting name="boneSize" serializeAs="String">
<value>10</value>
</setting>
<setting name="flatInbetween" serializeAs="String">
<value>False</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>
</AssetStudioGUI.Properties.Settings>
</userSettings>
</configuration>

View File

@ -0,0 +1,101 @@
<?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>{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudio</RootNamespace>
<AssemblyName>AssetStudioTools</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="dnlib">
<HintPath>..\AssetStudio\Libraries\dnlib.dll</HintPath>
</Reference>
<Reference Include="SharpDX, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\AssetStudio\Libraries\SharpDX.dll</HintPath>
</Reference>
<Reference Include="SharpDX.D3DCompiler">
<HintPath>..\AssetStudio\Libraries\SharpDX.D3DCompiler.dll</HintPath>
</Reference>
<Reference Include="SharpDX.Mathematics">
<HintPath>..\AssetStudio\Libraries\SharpDX.Mathematics.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Half">
<HintPath>..\AssetStudio\Libraries\System.Half.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AudioClipConverter.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="Properties\AssemblyInfo.cs" />
<Compile Include="ScriptHelper.cs" />
<Compile Include="ShaderConverter.cs" />
<Compile Include="SpriteHelper.cs" />
<Compile Include="Texture2DConverter.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetStudioFBX\AssetStudioFBX.vcxproj">
<Project>{4f8ef5ef-732b-49cf-9eb3-b23e19ae6267}</Project>
<Name>AssetStudioFBX</Name>
</ProjectReference>
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj">
<Project>{af56b63c-1764-41b7-9e60-8d485422ac3b}</Project>
<Name>AssetStudio</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
@ -32,13 +30,13 @@ namespace AssetStudio
result = sound.getSubSound(0, out var subsound);
if (result != FMOD.RESULT.OK)
return null;
result = subsound.getFormat(out var type, out var format, out int NumChannels, out int BitsPerSample);
result = subsound.getFormat(out var type, out var format, out int channels, out int bits);
if (result != FMOD.RESULT.OK)
return null;
result = subsound.getDefaults(out var frequency, out int priority);
if (result != FMOD.RESULT.OK)
return null;
var SampleRate = (int)frequency;
var sampleRate = (int)frequency;
result = subsound.getLength(out var length, FMOD.TIMEUNIT.PCMBYTES);
if (result != FMOD.RESULT.OK)
return null;
@ -52,11 +50,11 @@ namespace AssetStudio
Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8);
BitConverter.GetBytes(16).CopyTo(buffer, 16);
BitConverter.GetBytes((short)1).CopyTo(buffer, 20);
BitConverter.GetBytes((short)NumChannels).CopyTo(buffer, 22);
BitConverter.GetBytes(SampleRate).CopyTo(buffer, 24);
BitConverter.GetBytes(SampleRate * NumChannels * BitsPerSample / 8).CopyTo(buffer, 28);
BitConverter.GetBytes((short)(NumChannels * BitsPerSample / 8)).CopyTo(buffer, 32);
BitConverter.GetBytes((short)BitsPerSample).CopyTo(buffer, 34);
BitConverter.GetBytes((short)channels).CopyTo(buffer, 22);
BitConverter.GetBytes(sampleRate).CopyTo(buffer, 24);
BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28);
BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32);
BitConverter.GetBytes((short)bits).CopyTo(buffer, 34);
Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36);
BitConverter.GetBytes(len1).CopyTo(buffer, 40);
Marshal.Copy(ptr1, buffer, 44, (int)len1);

View File

@ -8,7 +8,7 @@ using SharpDX;
namespace AssetStudio
{
class ModelConverter : IImported
public class ModelConverter : IImported
{
public List<ImportedFrame> FrameList { get; protected set; } = new List<ImportedFrame>();
public List<ImportedMesh> MeshList { get; protected set; } = new List<ImportedMesh>();
@ -21,6 +21,7 @@ namespace AssetStudio
private Dictionary<uint, string> morphChannelInfo = new Dictionary<uint, string>();
private HashSet<ObjectReader> animationClipHashSet = new HashSet<ObjectReader>();
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
private Dictionary<ObjectReader, string> textureNameDictionary = new Dictionary<ObjectReader, string>();
public ModelConverter(GameObject m_GameObject)
{
@ -35,7 +36,7 @@ namespace AssetStudio
ConvertAnimations();
}
public ModelConverter(GameObject m_GameObject, List<AssetItem> animationList)
public ModelConverter(GameObject m_GameObject, ObjectReader[] animationList)
{
if (m_GameObject.m_Animator != null && m_GameObject.m_Animator.TryGet(out var m_Animator))
{
@ -44,9 +45,9 @@ namespace AssetStudio
}
else
InitWithGameObject(m_GameObject);
foreach (var assetPreloadData in animationList)
foreach (var animationClip in animationList)
{
animationClipHashSet.Add(assetPreloadData.reader);
animationClipHashSet.Add(animationClip);
}
ConvertAnimations();
}
@ -58,12 +59,12 @@ namespace AssetStudio
ConvertAnimations();
}
public ModelConverter(Animator m_Animator, List<AssetItem> animationList)
public ModelConverter(Animator m_Animator, ObjectReader[] animationList)
{
InitWithAnimator(m_Animator);
foreach (var assetPreloadData in animationList)
foreach (var animationClip in animationList)
{
animationClipHashSet.Add(assetPreloadData.reader);
animationClipHashSet.Add(animationClip);
}
ConvertAnimations();
}
@ -338,14 +339,14 @@ namespace AssetStudio
}
}
//UV
if (mesh.m_UV1 != null && mesh.m_UV1.Length == mesh.m_VertexCount * 2)
if (mesh.m_UV0 != null && mesh.m_UV0.Length == mesh.m_VertexCount * 2)
{
iVertex.UV = new[] { mesh.m_UV0[j * 2], -mesh.m_UV0[j * 2 + 1] };
}
else if (mesh.m_UV1 != null && mesh.m_UV1.Length == mesh.m_VertexCount * 2)
{
iVertex.UV = new[] { mesh.m_UV1[j * 2], -mesh.m_UV1[j * 2 + 1] };
}
else if (mesh.m_UV2 != null && mesh.m_UV2.Length == mesh.m_VertexCount * 2)
{
iVertex.UV = new[] { mesh.m_UV2[j * 2], -mesh.m_UV2[j * 2 + 1] };
}
//Tangent
if (mesh.m_Tangents != null && mesh.m_Tangents.Length == mesh.m_VertexCount * 4)
{
@ -534,7 +535,7 @@ namespace AssetStudio
}
}
//TODO
//TODO combine mesh
if (combine)
{
meshR.m_GameObject.TryGetGameObject(out var m_GameObject);
@ -673,25 +674,55 @@ namespace AssetStudio
iMat.TexScales = new Vector2[5];
foreach (var texEnv in mat.m_TexEnvs)
{
Texture2D tex2D = null;
if (texEnv.m_Texture.TryGet(out var TexturePD) && TexturePD.type == ClassIDType.Texture2D)//TODO other Texture
Texture2D m_Texture2D = null;
if (texEnv.m_Texture.TryGet(out var m_Texture) && m_Texture.type == ClassIDType.Texture2D) //TODO other Texture
{
tex2D = new Texture2D(TexturePD, true);
m_Texture2D = new Texture2D(m_Texture, true);
}
if (tex2D == null)
if (m_Texture2D == null)
{
continue;
}
int dest = texEnv.name == "_MainTex" ? 0 : texEnv.name == "_BumpMap" ? 4 : texEnv.name.Contains("Spec") ? 2 : texEnv.name.Contains("Norm") ? 3 : -1;
int dest = -1;
if (texEnv.name == "_MainTex")
dest = 0;
else if (texEnv.name == "_BumpMap")
dest = 4;
else if (texEnv.name.Contains("Spec"))
dest = 2;
else if (texEnv.name.Contains("Norm"))
dest = 3;
if (dest < 0 || iMat.Textures[dest] != null)
{
continue;
}
iMat.Textures[dest] = TexturePD.exportName + ".png";
if (textureNameDictionary.TryGetValue(m_Texture, out var textureName))
{
iMat.Textures[dest] = textureName;
}
else if (ImportedHelpers.FindTexture(m_Texture2D.m_Name + ".png", TextureList) != null) //已有相同名字的图片
{
for (int i = 1; ; i++)
{
var name = m_Texture2D.m_Name + $" ({i}).png";
if (ImportedHelpers.FindTexture(name, TextureList) == null)
{
iMat.Textures[dest] = name;
textureNameDictionary.Add(m_Texture, name);
break;
}
}
}
else
{
iMat.Textures[dest] = m_Texture2D.m_Name + ".png";
textureNameDictionary.Add(m_Texture, iMat.Textures[dest]);
}
iMat.TexOffsets[dest] = new Vector2(texEnv.m_Offset[0], texEnv.m_Offset[1]);
iMat.TexScales[dest] = new Vector2(texEnv.m_Scale[0], texEnv.m_Scale[1]);
ConvertTexture2D(tex2D, iMat.Textures[dest]);
ConvertTexture2D(m_Texture2D, iMat.Textures[dest]);
}
MaterialList.Add(iMat);

View File

@ -0,0 +1,10 @@
namespace AssetStudio
{
public static class ModelExporter
{
public static void ExportFbx(string path, IImported imported, bool eulerFilter, float filterPrecision, bool allFrames, bool allBones, bool skins, float boneSize, float scaleFactor, bool flatInbetween, int versionIndex, bool isAscii)
{
Fbx.Exporter.Export(path, imported, eulerFilter, filterPrecision, allFrames, allBones, skins, boneSize, scaleFactor, flatInbetween, versionIndex, isAscii);
}
}
}

View File

@ -5,12 +5,12 @@ using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("AssetStudioUtility")]
[assembly: AssemblyTitle("AssetStudioTools")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AssetStudioUtility")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyProduct("AssetStudioTools")]
[assembly: AssemblyCopyright("Copyright © Perfare 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

View File

@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using dnlib.DotNet;
namespace AssetStudio
@ -11,45 +9,14 @@ namespace AssetStudio
//TODO unfinished
public static class ScriptHelper
{
public static bool moduleLoaded;
public static Dictionary<string, ModuleDef> LoadedModuleDic = new Dictionary<string, ModuleDef>();
public static string GetScriptString(ObjectReader reader)
public static string GetScriptString(ObjectReader reader, Dictionary<string, ModuleDef> moduleDic)
{
if (!moduleLoaded)
{
var openFolderDialog = new OpenFolderDialog();
openFolderDialog.Title = "Select Assembly Folder";
if (openFolderDialog.ShowDialog() == DialogResult.OK)
{
var files = Directory.GetFiles(openFolderDialog.Folder, "*.dll");
var moduleContext = new ModuleContext();
var asmResolver = new AssemblyResolver(moduleContext, true);
var resolver = new Resolver(asmResolver);
moduleContext.AssemblyResolver = asmResolver;
moduleContext.Resolver = resolver;
try
{
foreach (var file in files)
{
var module = ModuleDefMD.Load(file, moduleContext);
LoadedModuleDic.Add(Path.GetFileName(file), module);
}
}
catch
{
// ignored
}
}
moduleLoaded = true;
}
var m_MonoBehaviour = new MonoBehaviour(reader);
var sb = CreateMonoBehaviourHeader(m_MonoBehaviour);
if (m_MonoBehaviour.m_Script.TryGet(out var script))
{
var m_Script = new MonoScript(script);
if (!LoadedModuleDic.TryGetValue(m_Script.m_AssemblyName, out var module))
if (!moduleDic.TryGetValue(m_Script.m_AssemblyName, out var module))
{
return sb.ToString();
}
@ -153,7 +120,6 @@ namespace AssetStudio
}
var size = reader.ReadInt32();
sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}");
sb.AppendLine($"{new string('\t', indent + 1)}Array Array");
sb.AppendLine($"{new string('\t', indent + 1)}int size = {size}");
for (int i = 0; i < size; i++)
{
@ -173,7 +139,6 @@ namespace AssetStudio
}
var size = reader.ReadInt32();
sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}");
sb.AppendLine($"{new string('\t', indent + 1)}Array Array");
sb.AppendLine($"{new string('\t', indent + 1)}int size = {size}");
for (int i = 0; i < size; i++)
{

View File

@ -50,7 +50,7 @@ namespace AssetStudio
public class ShaderProgram
{
public ShaderSubProgram[] m_SubPrograms;
private ShaderSubProgram[] m_SubPrograms;
public ShaderProgram(BinaryReader reader)
{

View File

@ -1,14 +1,10 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
namespace AssetStudio
{
static class SpriteHelper
public static class SpriteHelper
{
public static Bitmap GetImageFromSprite(Sprite m_Sprite)
{

View File

@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace AssetStudio
{
@ -16,7 +14,7 @@ namespace AssetStudio
private int m_Height;
private TextureFormat m_TextureFormat;
private int image_data_size;
public byte[] image_data;
private byte[] image_data;
private int[] version;
//DDS Start
@ -967,9 +965,9 @@ namespace AssetStudio
IntPtr uncompressedData;
int uncompressedSize;
bool result;
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3) //2017.3 and up
|| m_TextureFormat == TextureFormat.ETC_RGB4Crunched
|| m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched) //2017.3 and up
|| m_TextureFormat == TextureFormat.ETC2_RGBA8Crunched)
{
result = DecompressUnityCRN(image_data, image_data_size, out uncompressedData, out uncompressedSize);
}

View File

@ -1,49 +0,0 @@
<?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>{9131C403-7FE8-444D-9AF5-5FE5DF76FF24}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AssetStudioUtility</RootNamespace>
<AssemblyName>AssetStudioUtility</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="SharpDX.Mathematics">
<HintPath>..\AssetStudio\Libraries\SharpDX.Mathematics.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.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Imported.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>