mirror of
https://github.com/aelurum/AssetStudio.git
synced 2026-08-27 10:56:58 -04:00
Add AssetStudioCLI project
- Updated projects and dependencies
This commit is contained in:
@@ -35,6 +35,9 @@ bld/
|
|||||||
# Visual Studio 2017 auto generated files
|
# Visual Studio 2017 auto generated files
|
||||||
Generated\ Files/
|
Generated\ Files/
|
||||||
|
|
||||||
|
# Launch Settings
|
||||||
|
*launchSettings.json
|
||||||
|
|
||||||
# MSTest test Results
|
# MSTest test Results
|
||||||
[Tt]est[Rr]esult*/
|
[Tt]est[Rr]esult*/
|
||||||
[Bb]uild[Ll]og.*
|
[Bb]uild[Ll]og.*
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -4,33 +4,29 @@ using System.Diagnostics;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
namespace AssetStudio.PInvoke
|
namespace AssetStudio.PInvoke
|
||||||
{
|
{
|
||||||
public static class DllLoader
|
public static class DllLoader
|
||||||
{
|
{
|
||||||
|
|
||||||
public static void PreloadDll(string dllName)
|
public static void PreloadDll(string dllName)
|
||||||
{
|
{
|
||||||
var dllDir = GetDirectedDllDirectory();
|
var localPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||||
|
var localDir = Path.GetDirectoryName(localPath);
|
||||||
|
|
||||||
// Not using OperatingSystem.Platform.
|
// Not using OperatingSystem.Platform.
|
||||||
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
|
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
Win32.LoadDll(dllDir, dllName);
|
Win32.LoadDll(GetDirectedDllDirectory(localDir), dllName);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Posix.LoadDll(dllDir, dllName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetDirectedDllDirectory()
|
private static string GetDirectedDllDirectory(string localDir)
|
||||||
{
|
{
|
||||||
var localPath = Process.GetCurrentProcess().MainModule.FileName;
|
var win32Path = Path.Combine("runtimes", "win-x86", "native");
|
||||||
var localDir = Path.GetDirectoryName(localPath);
|
var win64Path = Path.Combine("runtimes", "win-x64", "native");
|
||||||
|
var subDir = Environment.Is64BitProcess ? win64Path : win32Path;
|
||||||
var subDir = Environment.Is64BitProcess ? "x64" : "x86";
|
|
||||||
|
|
||||||
var directedDllDir = Path.Combine(localDir, subDir);
|
var directedDllDir = Path.Combine(localDir, subDir);
|
||||||
|
|
||||||
@@ -64,61 +60,7 @@ namespace AssetStudio.PInvoke
|
|||||||
|
|
||||||
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
|
private const uint LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x1000;
|
||||||
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
|
private const uint LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x100;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Posix
|
|
||||||
{
|
|
||||||
|
|
||||||
internal static void LoadDll(string dllDir, string dllName)
|
|
||||||
{
|
|
||||||
string dllExtension;
|
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
|
||||||
{
|
|
||||||
dllExtension = ".so";
|
|
||||||
}
|
|
||||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
|
||||||
{
|
|
||||||
dllExtension = ".dylib";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
var dllFileName = $"lib{dllName}{dllExtension}";
|
|
||||||
var directedDllPath = Path.Combine(dllDir, dllFileName);
|
|
||||||
|
|
||||||
const int ldFlags = RTLD_NOW | RTLD_GLOBAL;
|
|
||||||
var hLibrary = DlOpen(directedDllPath, ldFlags);
|
|
||||||
|
|
||||||
if (hLibrary == IntPtr.Zero)
|
|
||||||
{
|
|
||||||
var pErrStr = DlError();
|
|
||||||
// `PtrToStringAnsi` always uses the specific constructor of `String` (see dotnet/core#2325),
|
|
||||||
// which in turn interprets the byte sequence with system default codepage. On OSX and Linux
|
|
||||||
// the codepage is UTF-8 so the error message should be handled correctly.
|
|
||||||
var errorMessage = Marshal.PtrToStringAnsi(pErrStr);
|
|
||||||
|
|
||||||
throw new DllNotFoundException(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OSX and most Linux OS use LP64 so `int` is still 32-bit even on 64-bit platforms.
|
|
||||||
// void *dlopen(const char *filename, int flag);
|
|
||||||
[DllImport("libdl", EntryPoint = "dlopen")]
|
|
||||||
private static extern IntPtr DlOpen([MarshalAs(UnmanagedType.LPStr)] string fileName, int flags);
|
|
||||||
|
|
||||||
// char *dlerror(void);
|
|
||||||
[DllImport("libdl", EntryPoint = "dlerror")]
|
|
||||||
private static extern IntPtr DlError();
|
|
||||||
|
|
||||||
private const int RTLD_LAZY = 0x1;
|
|
||||||
private const int RTLD_NOW = 0x2;
|
|
||||||
private const int RTLD_GLOBAL = 0x100;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
+20
-2
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.31410.357
|
VisualStudioVersion = 17.5.33414.496
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -25,6 +25,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "Ass
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudioCLI", "AssetStudioCLI\AssetStudioCLI.csproj", "{34B6329B-0E73-45AC-B8CC-015F119F63DC}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{422FEC21-EF60-4F29-AA56-95DFDA23C913} = {422FEC21-EF60-4F29-AA56-95DFDA23C913}
|
||||||
|
{65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF} = {65EAFFA3-01D3-4EF5-B092-8B4647E9A1FF}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -131,6 +137,18 @@ Global
|
|||||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
|
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x64.Build.0 = Release|x64
|
||||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
|
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
|
{29356642-C46E-4144-83D8-22DC09D0D7FD}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{34B6329B-0E73-45AC-B8CC-015F119F63DC}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.2.16" />
|
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||||
|
<AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle>
|
||||||
|
<Version>0.16.48.1</Version>
|
||||||
|
<Copyright>Copyright © Perfare; Copyright © aelurum 2023</Copyright>
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>embedded</DebugType>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
|
||||||
|
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Use local compiled win-x86 and win-x64 Texture2DDecoder libs, because libs from Kyaru.Texture2DDecoder.Windows were compiled with /MD flag -->
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||||
|
<Message Text="Copying extra files for $(TargetFramework)... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x64\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesPortableNet" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||||
|
<Message Text="Copying extra files for .NET ($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x86\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libfmod.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-arm64\libfmod.dylib" DestinationFolder="$(TargetDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||||
|
<Message Text="Publishing extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesPortableNet" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||||
|
<Message Text="Publishing extra files for Portable .NET build ($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\linux-x86\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libfmod.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\osx-arm64\native\libfmod.dylib" DestinationFolder="$(PublishDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x86' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesWin64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\win-x64\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesWin" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('win-x')) ">
|
||||||
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\fmod.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesLinux64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesLinux64" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||||
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\libfmod.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesMac64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'osx-x64' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libfmod.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesMacArm64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'osx-arm64' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\osx-arm64\libfmod.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesMac" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||||
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\libfmod.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using AssetStudioCLI.Options;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal enum LogOutputMode
|
||||||
|
{
|
||||||
|
Console,
|
||||||
|
File,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CLILogger : ILogger
|
||||||
|
{
|
||||||
|
private readonly LogOutputMode logOutput;
|
||||||
|
private readonly LoggerEvent logMinLevel;
|
||||||
|
public string LogName;
|
||||||
|
public string LogPath;
|
||||||
|
|
||||||
|
public CLILogger(CLIOptions options)
|
||||||
|
{
|
||||||
|
logOutput = options.o_logOutput.Value;
|
||||||
|
logMinLevel = options.o_logLevel.Value;
|
||||||
|
LogName = $"AssetStudioCLI_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
||||||
|
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
|
||||||
|
|
||||||
|
var ver = typeof(Program).Assembly.GetName().Version;
|
||||||
|
LogToFile(LoggerEvent.Verbose, $"---AssetStudioCLI v{ver} | Logger launched---\n" +
|
||||||
|
$"CMD Args: {string.Join(" ", options.cliArgs)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ColorLogLevel(LoggerEvent logLevel)
|
||||||
|
{
|
||||||
|
string formattedLevel = $"[{logLevel}]";
|
||||||
|
switch (logLevel)
|
||||||
|
{
|
||||||
|
case LoggerEvent.Info:
|
||||||
|
return $"{formattedLevel.Color(CLIAnsiColors.BrightCyan)}";
|
||||||
|
case LoggerEvent.Warning:
|
||||||
|
return $"{formattedLevel.Color(CLIAnsiColors.BrightYellow)}";
|
||||||
|
case LoggerEvent.Error:
|
||||||
|
return $"{formattedLevel.Color(CLIAnsiColors.BrightRed)}";
|
||||||
|
default:
|
||||||
|
return formattedLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string FormatMessage(LoggerEvent logMsgLevel, string message, bool consoleMode = false)
|
||||||
|
{
|
||||||
|
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
message = message.TrimEnd();
|
||||||
|
var multiLine = message.Contains('\n');
|
||||||
|
|
||||||
|
string formattedMessage;
|
||||||
|
if (consoleMode)
|
||||||
|
{
|
||||||
|
string colorLogLevel = ColorLogLevel(logMsgLevel);
|
||||||
|
formattedMessage = $"{colorLogLevel} {message}";
|
||||||
|
if (multiLine)
|
||||||
|
{
|
||||||
|
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = Regex.Replace(message, @"\e\[[0-9;]*m(?:\e\[K)?", ""); //Delete ANSI colors
|
||||||
|
var logLevel = $"{logMsgLevel.ToString().ToUpper(),-7}";
|
||||||
|
formattedMessage = $"{curTime} | {logLevel} | {message}";
|
||||||
|
if (multiLine)
|
||||||
|
{
|
||||||
|
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formattedMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LogToConsole(LoggerEvent logMsgLevel, string message)
|
||||||
|
{
|
||||||
|
if (logOutput != LogOutputMode.File)
|
||||||
|
{
|
||||||
|
Console.WriteLine(FormatMessage(logMsgLevel, message, consoleMode: true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void LogToFile(LoggerEvent logMsgLevel, string message)
|
||||||
|
{
|
||||||
|
if (logOutput != LogOutputMode.Console)
|
||||||
|
{
|
||||||
|
using (var sw = new StreamWriter(LogPath, append: true, System.Text.Encoding.UTF8))
|
||||||
|
{
|
||||||
|
await sw.WriteLineAsync(FormatMessage(logMsgLevel, message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Log(LoggerEvent logMsgLevel, string message)
|
||||||
|
{
|
||||||
|
if (logMsgLevel < logMinLevel || string.IsNullOrEmpty(message))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logOutput != LogOutputMode.File)
|
||||||
|
{
|
||||||
|
LogToConsole(logMsgLevel, message);
|
||||||
|
}
|
||||||
|
if (logOutput != LogOutputMode.Console)
|
||||||
|
{
|
||||||
|
LogToFile(logMsgLevel, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal class AssetItem
|
||||||
|
{
|
||||||
|
public Object Asset;
|
||||||
|
public SerializedFile SourceFile;
|
||||||
|
public string Container = string.Empty;
|
||||||
|
public string TypeString;
|
||||||
|
public long m_PathID;
|
||||||
|
public long FullSize;
|
||||||
|
public ClassIDType Type;
|
||||||
|
public string Text;
|
||||||
|
public string UniqueID;
|
||||||
|
|
||||||
|
public AssetItem(Object asset)
|
||||||
|
{
|
||||||
|
Asset = asset;
|
||||||
|
SourceFile = asset.assetsFile;
|
||||||
|
Type = asset.type;
|
||||||
|
TypeString = Type.ToString();
|
||||||
|
m_PathID = asset.m_PathID;
|
||||||
|
FullSize = asset.byteSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
// Represents set with 16 base colors using ANSI escape codes, which should be supported in most terminals
|
||||||
|
// (well, except for windows editions before windows 10)
|
||||||
|
public static class CLIAnsiColors
|
||||||
|
{
|
||||||
|
public static readonly string
|
||||||
|
Black = "\u001b[30m",
|
||||||
|
Red = "\u001b[31m",
|
||||||
|
Green = "\u001b[32m",
|
||||||
|
Yellow = "\u001b[33m", //remapped to ~BrightWhite in Windows PowerShell 6
|
||||||
|
Blue = "\u001b[34m",
|
||||||
|
Magenta = "\u001b[35m", //remapped to ~Blue in Windows PowerShell 6
|
||||||
|
Cyan = "\u001b[36m",
|
||||||
|
White = "\u001b[37m",
|
||||||
|
BrightBlack = "\u001b[30;1m",
|
||||||
|
BrightRed = "\u001b[31;1m",
|
||||||
|
BrightGreen = "\u001b[32;1m",
|
||||||
|
BrightYellow = "\u001b[33;1m",
|
||||||
|
BrightBlue = "\u001b[34;1m",
|
||||||
|
BrightMagenta = "\u001b[35;1m",
|
||||||
|
BrightCyan = "\u001b[36;1m",
|
||||||
|
BrightWhite = "\u001b[37;1m";
|
||||||
|
private static readonly string Reset = "\u001b[0m";
|
||||||
|
|
||||||
|
public static string Color(this string str, string ansiColor)
|
||||||
|
{
|
||||||
|
if (!CLIWinAnsiFix.isAnsiSupported)
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{ansiColor}{str}{Reset}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ANSICodesTest()
|
||||||
|
{
|
||||||
|
Console.WriteLine("ANSI escape codes test");
|
||||||
|
Console.WriteLine($"Supported: {CLIWinAnsiFix.isAnsiSupported}");
|
||||||
|
Console.WriteLine("\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m");
|
||||||
|
Console.WriteLine("\u001b[34m E \u001b[35m F \u001b[36m G \u001b[37m H \u001b[0m");
|
||||||
|
Console.WriteLine("\u001b[30;1m A \u001b[31;1m B \u001b[32;1m C \u001b[33;1m D \u001b[0m");
|
||||||
|
Console.WriteLine("\u001b[34;1m E \u001b[35;1m F \u001b[36;1m G \u001b[37;1m H \u001b[0m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// Based on code by tomzorz (https://gist.github.com/tomzorz/6142d69852f831fb5393654c90a1f22e)
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
static class CLIWinAnsiFix
|
||||||
|
{
|
||||||
|
public static readonly bool isAnsiSupported;
|
||||||
|
private const int STD_OUTPUT_HANDLE = -11;
|
||||||
|
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
|
||||||
|
|
||||||
|
[DllImport("kernel32.dll")]
|
||||||
|
private static extern IntPtr GetStdHandle(int nStdHandle);
|
||||||
|
|
||||||
|
static CLIWinAnsiFix()
|
||||||
|
{
|
||||||
|
bool isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||||
|
if (isWin)
|
||||||
|
{
|
||||||
|
isAnsiSupported = TryEnableVTMode();
|
||||||
|
if (!isAnsiSupported)
|
||||||
|
{
|
||||||
|
//Check for bash terminal emulator. E.g., Git Bash, Cmder
|
||||||
|
isAnsiSupported = Environment.GetEnvironmentVariable("TERM") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isAnsiSupported = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable support for ANSI escape codes
|
||||||
|
// (but probably only suitable for windows 10+)
|
||||||
|
// https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
|
||||||
|
private static bool TryEnableVTMode()
|
||||||
|
{
|
||||||
|
var iStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
if (!GetConsoleMode(iStdOut, out uint outConsoleMode))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
|
|
||||||
|
if (!SetConsoleMode(iStdOut, outConsoleMode))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using AssetStudioCLI.Options;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal static class Exporter
|
||||||
|
{
|
||||||
|
public static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
||||||
|
|
||||||
|
public static bool ExportTexture2D(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
var m_Texture2D = (Texture2D)item.Asset;
|
||||||
|
if (options.convertTexture)
|
||||||
|
{
|
||||||
|
var type = options.o_imageFormat.Value;
|
||||||
|
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
var image = m_Texture2D.ConvertToImage(flip: true);
|
||||||
|
if (image == null)
|
||||||
|
{
|
||||||
|
Logger.Error($"Failed to convert texture \"{m_Texture2D.m_Name}\" into image");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
using (image)
|
||||||
|
{
|
||||||
|
using (var file = File.OpenWrite(exportFullPath))
|
||||||
|
{
|
||||||
|
image.WriteToStream(file, type);
|
||||||
|
}
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportAudioClip(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
string exportFullPath;
|
||||||
|
var m_AudioClip = (AudioClip)item.Asset;
|
||||||
|
var m_AudioData = m_AudioClip.m_AudioData.GetData();
|
||||||
|
if (m_AudioData == null || m_AudioData.Length == 0)
|
||||||
|
{
|
||||||
|
Logger.Error($"[{item.Text}]: AudioData was not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var converter = new AudioClipConverter(m_AudioClip);
|
||||||
|
if (options.o_audioFormat.Value != AudioFormat.None && converter.IsSupport)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Logger.Debug($"Converting \"{m_AudioClip.m_Name}\" to wav..\n" +
|
||||||
|
$"AudioClip sound compression: {m_AudioClip.m_CompressionFormat}\n" +
|
||||||
|
$"AudioClip channel count: {m_AudioClip.m_Channels}\n" +
|
||||||
|
$"AudioClip sample rate: {m_AudioClip.m_Frequency}\n" +
|
||||||
|
$"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}");
|
||||||
|
|
||||||
|
var buffer = converter.ConvertToWav(m_AudioData);
|
||||||
|
if (buffer == null)
|
||||||
|
{
|
||||||
|
Logger.Error($"[{item.Text}]: Failed to convert to Wav");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
File.WriteAllBytes(exportFullPath, buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out exportFullPath))
|
||||||
|
return false;
|
||||||
|
File.WriteAllBytes(exportFullPath, m_AudioData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportVideoClip(AssetItem item, string exportPath)
|
||||||
|
{
|
||||||
|
var m_VideoClip = (VideoClip)item.Asset;
|
||||||
|
if (m_VideoClip.m_ExternalResources.m_Size > 0)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, Path.GetExtension(m_VideoClip.m_OriginalPath), out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
m_VideoClip.m_VideoData.WriteData(exportFullPath);
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportShader(AssetItem item, string exportPath)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
var m_Shader = (Shader)item.Asset;
|
||||||
|
var str = m_Shader.Convert();
|
||||||
|
File.WriteAllText(exportFullPath, str);
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportTextAsset(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
var m_TextAsset = (TextAsset)item.Asset;
|
||||||
|
var extension = ".txt";
|
||||||
|
if (!options.f_notRestoreExtensionName.Value)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(item.Container))
|
||||||
|
{
|
||||||
|
extension = Path.GetExtension(item.Container);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
File.WriteAllBytes(exportFullPath, m_TextAsset.m_Script);
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportMonoBehaviour(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".json", out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
|
||||||
|
var type = m_MonoBehaviour.ToType();
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
var m_Type = MonoBehaviourToTypeTree(m_MonoBehaviour, options);
|
||||||
|
type = m_MonoBehaviour.ToType(m_Type);
|
||||||
|
}
|
||||||
|
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
|
||||||
|
File.WriteAllText(exportFullPath, str);
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportFont(AssetItem item, string exportPath)
|
||||||
|
{
|
||||||
|
var m_Font = (Font)item.Asset;
|
||||||
|
if (m_Font.m_FontData != null)
|
||||||
|
{
|
||||||
|
var extension = ".ttf";
|
||||||
|
if (m_Font.m_FontData[0] == 79 && m_Font.m_FontData[1] == 84 && m_Font.m_FontData[2] == 84 && m_Font.m_FontData[3] == 79)
|
||||||
|
{
|
||||||
|
extension = ".otf";
|
||||||
|
}
|
||||||
|
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
File.WriteAllBytes(exportFullPath, m_Font.m_FontData);
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportSprite(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
var type = options.o_imageFormat.Value;
|
||||||
|
var alphaMask = SpriteMaskMode.On;
|
||||||
|
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
var image = ((Sprite)item.Asset).GetImage(alphaMask);
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
using (image)
|
||||||
|
{
|
||||||
|
using (var file = File.OpenWrite(exportFullPath))
|
||||||
|
{
|
||||||
|
image.WriteToStream(file, type);
|
||||||
|
}
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportRawFile(AssetItem item, string exportPath)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||||
|
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportDumpFile(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||||
|
return false;
|
||||||
|
var str = item.Asset.Dump();
|
||||||
|
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
||||||
|
{
|
||||||
|
var m_Type = MonoBehaviourToTypeTree(m_MonoBehaviour, options);
|
||||||
|
str = m_MonoBehaviour.Dump(m_Type);
|
||||||
|
}
|
||||||
|
if (str != null)
|
||||||
|
{
|
||||||
|
File.WriteAllText(exportFullPath, str);
|
||||||
|
Logger.Debug($"{item.TypeString}: \"{item.Text}\" saved to \"{exportFullPath}\"");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
|
||||||
|
{
|
||||||
|
var fileName = FixFileName(item.Text);
|
||||||
|
fullPath = Path.Combine(dir, fileName + extension);
|
||||||
|
if (!File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||||
|
if (!File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dir);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Logger.Error($"Export error. File \"{fullPath.Color(CLIAnsiColors.BrightRed)}\" already exist");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExportConvertFile(AssetItem item, string exportPath, CLIOptions options)
|
||||||
|
{
|
||||||
|
switch (item.Type)
|
||||||
|
{
|
||||||
|
case ClassIDType.Texture2D:
|
||||||
|
return ExportTexture2D(item, exportPath, options);
|
||||||
|
case ClassIDType.AudioClip:
|
||||||
|
return ExportAudioClip(item, exportPath, options);
|
||||||
|
case ClassIDType.VideoClip:
|
||||||
|
return ExportVideoClip(item, exportPath);
|
||||||
|
case ClassIDType.Shader:
|
||||||
|
return ExportShader(item, exportPath);
|
||||||
|
case ClassIDType.TextAsset:
|
||||||
|
return ExportTextAsset(item, exportPath, options);
|
||||||
|
case ClassIDType.MonoBehaviour:
|
||||||
|
return ExportMonoBehaviour(item, exportPath, options);
|
||||||
|
case ClassIDType.Font:
|
||||||
|
return ExportFont(item, exportPath);
|
||||||
|
case ClassIDType.Sprite:
|
||||||
|
return ExportSprite(item, exportPath, options);
|
||||||
|
default:
|
||||||
|
return ExportRawFile(item, exportPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour, CLIOptions options)
|
||||||
|
{
|
||||||
|
if (!assemblyLoader.Loaded)
|
||||||
|
{
|
||||||
|
var assemblyFolder = options.o_assemblyPath.Value;
|
||||||
|
if (assemblyFolder != "")
|
||||||
|
{
|
||||||
|
assemblyLoader.Load(assemblyFolder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assemblyLoader.Loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string FixFileName(string str)
|
||||||
|
{
|
||||||
|
if (str.Length >= 260) return Path.GetRandomFileName();
|
||||||
|
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,790 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI.Options
|
||||||
|
{
|
||||||
|
internal enum HelpGroups
|
||||||
|
{
|
||||||
|
General,
|
||||||
|
Convert,
|
||||||
|
Logger,
|
||||||
|
Advanced,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum WorkMode
|
||||||
|
{
|
||||||
|
Export,
|
||||||
|
ExportRaw,
|
||||||
|
Dump,
|
||||||
|
Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum AssetGroupOption
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
TypeName,
|
||||||
|
ContainerPath,
|
||||||
|
SourceFileName,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum ExportListType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
XML,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum AudioFormat
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Wav,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal enum FilterBy
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Name,
|
||||||
|
Container,
|
||||||
|
PathID,
|
||||||
|
NameOrContainer,
|
||||||
|
NameAndContainer,
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class GroupedOption<T> : Option<T>
|
||||||
|
{
|
||||||
|
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionHelpGroup, isFlag)
|
||||||
|
{
|
||||||
|
CLIOptions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CLIOptions
|
||||||
|
{
|
||||||
|
public bool isParsed;
|
||||||
|
public bool showHelp;
|
||||||
|
public string[] cliArgs;
|
||||||
|
public string inputPath;
|
||||||
|
public FilterBy filterBy;
|
||||||
|
private static Dictionary<string, string> optionsDict;
|
||||||
|
private static Dictionary<string, string> flagsDict;
|
||||||
|
private static Dictionary<HelpGroups, Dictionary<string, string>> optionGroups;
|
||||||
|
private List<ClassIDType> supportedAssetTypes;
|
||||||
|
//general
|
||||||
|
public Option<WorkMode> o_workMode;
|
||||||
|
public Option<List<ClassIDType>> o_exportAssetTypes;
|
||||||
|
public Option<AssetGroupOption> o_groupAssetsBy;
|
||||||
|
public Option<string> o_outputFolder;
|
||||||
|
public Option<bool> o_displayHelp;
|
||||||
|
//logger
|
||||||
|
public Option<LoggerEvent> o_logLevel;
|
||||||
|
public Option<LogOutputMode> o_logOutput;
|
||||||
|
//convert
|
||||||
|
public bool convertTexture;
|
||||||
|
public Option<ImageFormat> o_imageFormat;
|
||||||
|
public Option<AudioFormat> o_audioFormat;
|
||||||
|
//advanced
|
||||||
|
public Option<ExportListType> o_exportAssetList;
|
||||||
|
public Option<List<string>> o_filterByName;
|
||||||
|
public Option<List<string>> o_filterByContainer;
|
||||||
|
public Option<List<string>> o_filterByPathID;
|
||||||
|
public Option<List<string>> o_filterByText;
|
||||||
|
public Option<string> o_assemblyPath;
|
||||||
|
public Option<string> o_unityVersion;
|
||||||
|
public Option<bool> f_notRestoreExtensionName;
|
||||||
|
|
||||||
|
public CLIOptions(string[] args)
|
||||||
|
{
|
||||||
|
cliArgs = args;
|
||||||
|
InitOptions();
|
||||||
|
ParseArgs(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitOptions()
|
||||||
|
{
|
||||||
|
isParsed = false;
|
||||||
|
showHelp = false;
|
||||||
|
inputPath = "";
|
||||||
|
filterBy = FilterBy.None;
|
||||||
|
optionsDict = new Dictionary<string, string>();
|
||||||
|
flagsDict = new Dictionary<string, string>();
|
||||||
|
optionGroups = new Dictionary<HelpGroups, Dictionary<string, string>>();
|
||||||
|
supportedAssetTypes = new List<ClassIDType>
|
||||||
|
{
|
||||||
|
ClassIDType.Texture2D,
|
||||||
|
ClassIDType.Sprite,
|
||||||
|
ClassIDType.TextAsset,
|
||||||
|
ClassIDType.MonoBehaviour,
|
||||||
|
ClassIDType.Font,
|
||||||
|
ClassIDType.Shader,
|
||||||
|
ClassIDType.AudioClip,
|
||||||
|
ClassIDType.VideoClip,
|
||||||
|
};
|
||||||
|
|
||||||
|
#region Init General Options
|
||||||
|
o_workMode = new GroupedOption<WorkMode>
|
||||||
|
(
|
||||||
|
optionDefaultValue: WorkMode.Export,
|
||||||
|
optionName: "-m, --mode <value>",
|
||||||
|
optionDescription: "Specify working mode\n" +
|
||||||
|
"<Value: export(default) | exportRaw | dump | info>\n" +
|
||||||
|
"Export - Exports converted assets\n" +
|
||||||
|
"ExportRaw - Exports raw data\n" +
|
||||||
|
"Dump - Makes asset dumps\n" +
|
||||||
|
"Info - Loads file(s), shows the number of supported for export assets and exits\n" +
|
||||||
|
"Example: \"-m info\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.General
|
||||||
|
);
|
||||||
|
o_exportAssetTypes = new GroupedOption<List<ClassIDType>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: supportedAssetTypes,
|
||||||
|
optionName: "-t, --asset-type <value(s)>",
|
||||||
|
optionDescription: "Specify asset type(s) to export\n" +
|
||||||
|
"<Value(s): tex2d, sprite, textAsset, monoBehaviour, font, shader, \naudio, video | all(default)>\n" +
|
||||||
|
"All - export all asset types, which are listed in the values\n" +
|
||||||
|
"*To specify multiple asset types, write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Examples: \"-t sprite\" or \"-t all\" or \"-t tex2d,sprite,audio\" or \"-t tex2d;sprite;font\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.General
|
||||||
|
);
|
||||||
|
o_groupAssetsBy = new GroupedOption<AssetGroupOption>
|
||||||
|
(
|
||||||
|
optionDefaultValue: AssetGroupOption.ContainerPath,
|
||||||
|
optionName: "-g, --group-option <value>",
|
||||||
|
optionDescription: "Specify the way in which exported assets should be grouped\n" +
|
||||||
|
"<Value: none | type | container(default) | filename>\n" +
|
||||||
|
"None - Do not group exported assets\n" +
|
||||||
|
"Type - Group exported assets by type name\n" +
|
||||||
|
"Container - Group exported assets by container path\n" +
|
||||||
|
"Filename - Group exported assets by source file name\n" +
|
||||||
|
"Example: \"-g container\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.General
|
||||||
|
);
|
||||||
|
o_outputFolder = new GroupedOption<string>
|
||||||
|
(
|
||||||
|
optionDefaultValue: "",
|
||||||
|
optionName: "-o, --output <path>",
|
||||||
|
optionDescription: "Specify path to the output folder\n" +
|
||||||
|
"If path isn't specifyed, 'ASExport' folder will be created in the program's work folder\n",
|
||||||
|
optionHelpGroup: HelpGroups.General
|
||||||
|
);
|
||||||
|
o_displayHelp = new GroupedOption<bool>
|
||||||
|
(
|
||||||
|
optionDefaultValue: false,
|
||||||
|
optionName: "-h, --help",
|
||||||
|
optionDescription: "Display help and exit",
|
||||||
|
optionHelpGroup: HelpGroups.General
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Init Logger Options
|
||||||
|
o_logLevel = new GroupedOption<LoggerEvent>
|
||||||
|
(
|
||||||
|
optionDefaultValue: LoggerEvent.Info,
|
||||||
|
optionName: "--log-level <value>",
|
||||||
|
optionDescription: "Specify the log level\n" +
|
||||||
|
"<Value: verbose | debug | info(default) | warning | error>\n" +
|
||||||
|
"Example: \"--log-level warning\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Logger
|
||||||
|
);
|
||||||
|
o_logOutput = new GroupedOption<LogOutputMode>
|
||||||
|
(
|
||||||
|
optionDefaultValue: LogOutputMode.Console,
|
||||||
|
optionName: "--log-output <value>",
|
||||||
|
optionDescription: "Specify the log output\n" +
|
||||||
|
"<Value: console(default) | file | both>\n" +
|
||||||
|
"Example: \"--log-output both\"",
|
||||||
|
optionHelpGroup: HelpGroups.Logger
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Init Convert Options
|
||||||
|
convertTexture = true;
|
||||||
|
o_imageFormat = new GroupedOption<ImageFormat>
|
||||||
|
(
|
||||||
|
optionDefaultValue: ImageFormat.Png,
|
||||||
|
optionName: "--image-format <value>",
|
||||||
|
optionDescription: "Specify the format for converting image assets\n" +
|
||||||
|
"<Value: none | jpg | png(default) | bmp | tga | webp>\n" +
|
||||||
|
"None - Do not convert images and export them as texture data (.tex)\n" +
|
||||||
|
"Example: \"--image-format jpg\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Convert
|
||||||
|
);
|
||||||
|
o_audioFormat = new GroupedOption<AudioFormat>
|
||||||
|
(
|
||||||
|
optionDefaultValue: AudioFormat.Wav,
|
||||||
|
optionName: "--audio-format <value>",
|
||||||
|
optionDescription: "Specify the format for converting audio assets\n" +
|
||||||
|
"<Value: none | wav(default)>\n" +
|
||||||
|
"None - Do not convert audios and export them in their own format\n" +
|
||||||
|
"Example: \"--audio-format wav\"",
|
||||||
|
optionHelpGroup: HelpGroups.Convert
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Init Advanced Options
|
||||||
|
o_exportAssetList = new GroupedOption<ExportListType>
|
||||||
|
(
|
||||||
|
optionDefaultValue: ExportListType.None,
|
||||||
|
optionName: "--export-asset-list <value>",
|
||||||
|
optionDescription: "Specify the format in which you want to export asset list\n" +
|
||||||
|
"<Value: none(default) | xml>\n" +
|
||||||
|
"None - Do not export asset list\n" +
|
||||||
|
"Example: \"--export-asset-list xml\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_filterByName = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-name <text>",
|
||||||
|
optionDescription: "Specify the name by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple names write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-name char\" or \"--filter-by-name char,bg\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_filterByContainer = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-container <text>",
|
||||||
|
optionDescription: "Specify the container by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple containers write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-container arts\" or \"--filter-by-container arts,icons\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_filterByPathID = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-pathid <text>",
|
||||||
|
optionDescription: "Specify the PathID by which assets should be filtered\n" +
|
||||||
|
"*To specify multiple PathIDs write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-pathid 7238605633795851352,-2430306240205277265\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_filterByText = new GroupedOption<List<string>>
|
||||||
|
(
|
||||||
|
optionDefaultValue: new List<string>(),
|
||||||
|
optionName: "--filter-by-text <text>",
|
||||||
|
optionDescription: "Specify the text by which assets should be filtered\n" +
|
||||||
|
"Looks for assets that contain the specified text in their names or containers\n" +
|
||||||
|
"*To specify multiple values write them separated by ',' or ';' without spaces\n" +
|
||||||
|
"Example: \"--filter-by-text portrait\" or \"--filter-by-text portrait,art\"\n",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_assemblyPath = new GroupedOption<string>
|
||||||
|
(
|
||||||
|
optionDefaultValue: "",
|
||||||
|
optionName: "--assembly-folder <path>",
|
||||||
|
optionDescription: "Specify the path to the assembly folder",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
o_unityVersion = new GroupedOption<string>
|
||||||
|
(
|
||||||
|
optionDefaultValue: "",
|
||||||
|
optionName: "--unity-version <text>",
|
||||||
|
optionDescription: "Specify Unity version. Example: \"--unity-version 2017.4.39f1\"",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced
|
||||||
|
);
|
||||||
|
f_notRestoreExtensionName = new GroupedOption<bool>
|
||||||
|
(
|
||||||
|
optionDefaultValue: false,
|
||||||
|
optionName: "--not-restore-extension",
|
||||||
|
optionDescription: "(Flag) If specified, AssetStudio will not try to restore TextAssets extension name, \nand will just export all TextAssets with the \".txt\" extension",
|
||||||
|
optionHelpGroup: HelpGroups.Advanced,
|
||||||
|
isFlag: true
|
||||||
|
);
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void OptionGrouping(string name, string desc, HelpGroups group, bool isFlag)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var optionDict = new Dictionary<string, string>() { { name, desc } };
|
||||||
|
if (!optionGroups.ContainsKey(group))
|
||||||
|
{
|
||||||
|
optionGroups.Add(group, optionDict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionGroups[group].Add(name, desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFlag)
|
||||||
|
{
|
||||||
|
flagsDict.Add(name, desc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
optionsDict.Add(name, desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ParseArgs(string[] args)
|
||||||
|
{
|
||||||
|
var brightYellow = CLIAnsiColors.BrightYellow;
|
||||||
|
var brightRed = CLIAnsiColors.BrightRed;
|
||||||
|
|
||||||
|
if (args.Length == 0 || args.Any(x => x == "-h" || x == "--help"))
|
||||||
|
{
|
||||||
|
showHelp = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args[0].StartsWith("-"))
|
||||||
|
{
|
||||||
|
inputPath = Path.GetFullPath(args[0]).Replace("\"", "");
|
||||||
|
if (!Directory.Exists(inputPath) && !File.Exists(inputPath))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error:".Color(brightRed)} Invalid input path \"{args[0].Color(brightRed)}\".\n" +
|
||||||
|
$"Specified file or folder was not found. The input path must be specified as the first argument.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
o_outputFolder.Value = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ASExport");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error:".Color(brightRed)} Input path was empty. Specify the input path as the first argument.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var resplittedArgs = new List<string>();
|
||||||
|
for (int i = 1; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
string arg = args[i];
|
||||||
|
|
||||||
|
if (arg.Contains('='))
|
||||||
|
{
|
||||||
|
var splittedArgs = arg.Split('=');
|
||||||
|
resplittedArgs.Add(splittedArgs[0]);
|
||||||
|
resplittedArgs.Add(splittedArgs[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resplittedArgs.Add(arg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#region Parse Flags
|
||||||
|
for (int i = 0; i < resplittedArgs.Count; i++)
|
||||||
|
{
|
||||||
|
string flag = resplittedArgs[i].ToLower();
|
||||||
|
|
||||||
|
switch(flag)
|
||||||
|
{
|
||||||
|
case "--not-restore-extension":
|
||||||
|
f_notRestoreExtensionName.Value = true;
|
||||||
|
resplittedArgs.RemoveAt(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Parse Options
|
||||||
|
for (int i = 0; i < resplittedArgs.Count; i++)
|
||||||
|
{
|
||||||
|
var option = resplittedArgs[i].ToLower();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var value = resplittedArgs[i + 1].Replace("\"", "");
|
||||||
|
switch (option)
|
||||||
|
{
|
||||||
|
case "-m":
|
||||||
|
case "--mode":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "export":
|
||||||
|
o_workMode.Value = WorkMode.Export;
|
||||||
|
break;
|
||||||
|
case "raw":
|
||||||
|
case "exportraw":
|
||||||
|
o_workMode.Value = WorkMode.ExportRaw;
|
||||||
|
break;
|
||||||
|
case "dump":
|
||||||
|
o_workMode.Value = WorkMode.Dump;
|
||||||
|
break;
|
||||||
|
case "info":
|
||||||
|
o_workMode.Value = WorkMode.Info;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported working mode: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_workMode.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "-t":
|
||||||
|
case "--asset-type":
|
||||||
|
var splittedTypes = ValueSplitter(value);
|
||||||
|
o_exportAssetTypes.Value = new List<ClassIDType>();
|
||||||
|
foreach (var type in splittedTypes)
|
||||||
|
{
|
||||||
|
switch (type.ToLower())
|
||||||
|
{
|
||||||
|
case "tex2d":
|
||||||
|
case "texture2d":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.Texture2D);
|
||||||
|
break;
|
||||||
|
case "sprite":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.Sprite);
|
||||||
|
break;
|
||||||
|
case "textasset":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.TextAsset);
|
||||||
|
break;
|
||||||
|
case "monobehaviour":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.MonoBehaviour);
|
||||||
|
break;
|
||||||
|
case "font":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.Font);
|
||||||
|
break;
|
||||||
|
case "shader":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.Shader);
|
||||||
|
break;
|
||||||
|
case "audio":
|
||||||
|
case "audioclip":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.AudioClip);
|
||||||
|
break;
|
||||||
|
case "video":
|
||||||
|
case "videoclip":
|
||||||
|
o_exportAssetTypes.Value.Add(ClassIDType.VideoClip);
|
||||||
|
break;
|
||||||
|
case "all":
|
||||||
|
o_exportAssetTypes.Value = supportedAssetTypes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported asset type: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_exportAssetTypes.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "-g":
|
||||||
|
case "--group-option":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "type":
|
||||||
|
o_groupAssetsBy.Value = AssetGroupOption.TypeName;
|
||||||
|
break;
|
||||||
|
case "container":
|
||||||
|
o_groupAssetsBy.Value = AssetGroupOption.ContainerPath;
|
||||||
|
break;
|
||||||
|
case "filename":
|
||||||
|
o_groupAssetsBy.Value = AssetGroupOption.SourceFileName;
|
||||||
|
break;
|
||||||
|
case "none":
|
||||||
|
o_groupAssetsBy.Value = AssetGroupOption.None;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported grouping option: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_groupAssetsBy.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "-o":
|
||||||
|
case "--output":
|
||||||
|
try
|
||||||
|
{
|
||||||
|
value = Path.GetFullPath(value);
|
||||||
|
if (!Directory.Exists(value))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(value);
|
||||||
|
}
|
||||||
|
o_outputFolder.Value = value;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Warning:".Color(brightYellow)} Invalid output folder \"{value.Color(brightYellow)}\".\n{ex.Message}");
|
||||||
|
Console.WriteLine($"Working folder \"{o_outputFolder.Value.Color(brightYellow)}\" will be used as the output folder.\n");
|
||||||
|
Console.WriteLine("Press ESC to exit or any other key to continue...\n");
|
||||||
|
switch (Console.ReadKey(intercept: true).Key)
|
||||||
|
{
|
||||||
|
case ConsoleKey.Escape:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--log-level":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "verbose":
|
||||||
|
o_logLevel.Value = LoggerEvent.Verbose;
|
||||||
|
break;
|
||||||
|
case "debug":
|
||||||
|
o_logLevel.Value = LoggerEvent.Debug;
|
||||||
|
break;
|
||||||
|
case "info":
|
||||||
|
o_logLevel.Value = LoggerEvent.Info;
|
||||||
|
break;
|
||||||
|
case "warning":
|
||||||
|
o_logLevel.Value = LoggerEvent.Warning;
|
||||||
|
break;
|
||||||
|
case "error":
|
||||||
|
o_logLevel.Value = LoggerEvent.Error;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported log level value: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_logLevel.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--log-output":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "console":
|
||||||
|
o_logOutput.Value = LogOutputMode.Console;
|
||||||
|
break;
|
||||||
|
case "file":
|
||||||
|
o_logOutput.Value = LogOutputMode.File;
|
||||||
|
break;
|
||||||
|
case "both":
|
||||||
|
o_logOutput.Value = LogOutputMode.Both;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported log output mode: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_logOutput.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--image-format":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "jpg":
|
||||||
|
case "jpeg":
|
||||||
|
o_imageFormat.Value = ImageFormat.Jpeg;
|
||||||
|
break;
|
||||||
|
case "png":
|
||||||
|
o_imageFormat.Value = ImageFormat.Png;
|
||||||
|
break;
|
||||||
|
case "bmp":
|
||||||
|
o_imageFormat.Value = ImageFormat.Bmp;
|
||||||
|
break;
|
||||||
|
case "tga":
|
||||||
|
o_imageFormat.Value = ImageFormat.Tga;
|
||||||
|
break;
|
||||||
|
case "webp":
|
||||||
|
o_imageFormat.Value = ImageFormat.Webp;
|
||||||
|
break;
|
||||||
|
case "none":
|
||||||
|
convertTexture = false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported image format: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_imageFormat.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--audio-format":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "wav":
|
||||||
|
case "wave":
|
||||||
|
o_audioFormat.Value = AudioFormat.Wav;
|
||||||
|
break;
|
||||||
|
case "none":
|
||||||
|
o_audioFormat.Value = AudioFormat.None;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported audio format: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_audioFormat.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--export-asset-list":
|
||||||
|
switch (value.ToLower())
|
||||||
|
{
|
||||||
|
case "xml":
|
||||||
|
o_exportAssetList.Value = ExportListType.XML;
|
||||||
|
break;
|
||||||
|
case "none":
|
||||||
|
o_exportAssetList.Value = ExportListType.None;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Unsupported asset list export option: [{value.Color(brightRed)}].\n");
|
||||||
|
Console.WriteLine(o_exportAssetList.Description);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--filter-by-name":
|
||||||
|
o_filterByName.Value.AddRange(ValueSplitter(value));
|
||||||
|
filterBy = filterBy == FilterBy.None ? FilterBy.Name : filterBy == FilterBy.Container ? FilterBy.NameAndContainer : filterBy;
|
||||||
|
break;
|
||||||
|
case "--filter-by-container":
|
||||||
|
o_filterByContainer.Value.AddRange(ValueSplitter(value));
|
||||||
|
filterBy = filterBy == FilterBy.None ? FilterBy.Container : filterBy == FilterBy.Name ? FilterBy.NameAndContainer : filterBy;
|
||||||
|
break;
|
||||||
|
case "--filter-by-pathid":
|
||||||
|
o_filterByPathID.Value.AddRange(ValueSplitter(value));
|
||||||
|
filterBy = FilterBy.PathID;
|
||||||
|
break;
|
||||||
|
case "--filter-by-text":
|
||||||
|
o_filterByText.Value.AddRange(ValueSplitter(value));
|
||||||
|
filterBy = FilterBy.NameOrContainer;
|
||||||
|
break;
|
||||||
|
case "--assembly-folder":
|
||||||
|
if (Directory.Exists(value))
|
||||||
|
{
|
||||||
|
o_assemblyPath.Value = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error".Color(brightRed)} during parsing [{option}] option. Assembly folder [{value.Color(brightRed)}] was not found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "--unity-version":
|
||||||
|
o_unityVersion.Value = value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Console.WriteLine($"{"Error:".Color(brightRed)} Unknown option [{option.Color(brightRed)}].\n");
|
||||||
|
if (!TryShowOptionDescription(option, optionsDict))
|
||||||
|
{
|
||||||
|
TryShowOptionDescription(option, flagsDict);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
catch (IndexOutOfRangeException)
|
||||||
|
{
|
||||||
|
if (optionsDict.Any(x => x.Key.Contains(option)))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error during parsing options:".Color(brightRed)} Value for [{option.Color(brightRed)}] option was not found.\n");
|
||||||
|
TryShowOptionDescription(option, optionsDict);
|
||||||
|
}
|
||||||
|
else if (flagsDict.Any(x => x.Key.Contains(option)))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error:".Color(brightRed)} Unknown flag [{option.Color(brightRed)}].\n");
|
||||||
|
TryShowOptionDescription(option, flagsDict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{"Error:".Color(brightRed)} Unknown option [{option.Color(brightRed)}].");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Unknown Error.".Color(CLIAnsiColors.Red));
|
||||||
|
Console.WriteLine(ex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isParsed = true;
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string[] ValueSplitter(string value)
|
||||||
|
{
|
||||||
|
var separator = value.Contains(';') ? ';' : ',';
|
||||||
|
return value.Split(separator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryShowOptionDescription(string option, Dictionary<string, string> descDict)
|
||||||
|
{
|
||||||
|
var optionDesc = descDict.Where(x => x.Key.Contains(option));
|
||||||
|
if (optionDesc.Any())
|
||||||
|
{
|
||||||
|
var rand = new Random();
|
||||||
|
var rndOption = optionDesc.ElementAt(rand.Next(0, optionDesc.Count()));
|
||||||
|
Console.WriteLine($"Did you mean [{ $"{rndOption.Key}".Color(CLIAnsiColors.BrightYellow) }] option?");
|
||||||
|
Console.WriteLine($"Here's a description of it: \n\n{rndOption.Value}");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowHelp(bool showUsageOnly = false)
|
||||||
|
{
|
||||||
|
const int indent = 22;
|
||||||
|
var helpMessage = new StringBuilder();
|
||||||
|
var usage = new StringBuilder();
|
||||||
|
var appAssembly = typeof(Program).Assembly.GetName();
|
||||||
|
usage.Append($"Usage: {appAssembly.Name} <input path to asset file/folder> ");
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
foreach (var optionsGroup in optionGroups.Keys)
|
||||||
|
{
|
||||||
|
helpMessage.AppendLine($"{optionsGroup} Options:");
|
||||||
|
foreach (var optionDict in optionGroups[optionsGroup])
|
||||||
|
{
|
||||||
|
var optionName = $"{optionDict.Key,-indent - 8}";
|
||||||
|
var optionDesc = optionDict.Value.Replace("\n", $"{"\n",-indent - 11}");
|
||||||
|
helpMessage.AppendLine($" {optionName}{optionDesc}");
|
||||||
|
|
||||||
|
usage.Append($"[{optionDict.Key}] ");
|
||||||
|
if (i++ % 2 == 0)
|
||||||
|
{
|
||||||
|
usage.Append($"\n{"",indent}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
helpMessage.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showUsageOnly)
|
||||||
|
{
|
||||||
|
Console.WriteLine(usage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"# {appAssembly.Name}\n# Based on AssetStudio Mod v{appAssembly.Version}\n");
|
||||||
|
Console.WriteLine($"{usage}\n\n{helpMessage}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ShowCurrentFilter()
|
||||||
|
{
|
||||||
|
switch (filterBy)
|
||||||
|
{
|
||||||
|
case FilterBy.Name:
|
||||||
|
return $"# Filter by {filterBy}(s): \"{string.Join("\", \"", o_filterByName.Value)}\"";
|
||||||
|
case FilterBy.Container:
|
||||||
|
return $"# Filter by {filterBy}(s): \"{string.Join("\", \"", o_filterByContainer.Value)}\"";
|
||||||
|
case FilterBy.PathID:
|
||||||
|
return $"# Filter by {filterBy}(s): \"{string.Join("\", \"", o_filterByPathID.Value)}\"";
|
||||||
|
case FilterBy.NameOrContainer:
|
||||||
|
return $"# Filter by Text: \"{string.Join("\", \"", o_filterByText.Value)}\"";
|
||||||
|
case FilterBy.NameAndContainer:
|
||||||
|
return $"# Filter by Name(s): \"{string.Join("\", \"", o_filterByName.Value)}\"\n# Filter by Container(s): \"{string.Join("\", \"", o_filterByContainer.Value)}\"";
|
||||||
|
default:
|
||||||
|
return $"# Filter by: {filterBy}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowCurrentOptions()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("[Current Options]");
|
||||||
|
sb.AppendLine($"# Working Mode: {o_workMode}");
|
||||||
|
sb.AppendLine($"# Input Path: \"{inputPath}\"");
|
||||||
|
if (o_workMode.Value != WorkMode.Info)
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Output Path: \"{o_outputFolder}\"");
|
||||||
|
sb.AppendLine($"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}");
|
||||||
|
sb.AppendLine($"# Asset Group Option: {o_groupAssetsBy}");
|
||||||
|
sb.AppendLine($"# Export Image Format: {o_imageFormat}");
|
||||||
|
sb.AppendLine($"# Export Audio Format: {o_audioFormat}");
|
||||||
|
sb.AppendLine($"# Log Level: {o_logLevel}");
|
||||||
|
sb.AppendLine($"# Log Output: {o_logOutput}");
|
||||||
|
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
||||||
|
sb.AppendLine(ShowCurrentFilter());
|
||||||
|
sb.AppendLine($"# Assebmly Path: \"{o_assemblyPath}\"");
|
||||||
|
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
||||||
|
sb.AppendLine($"# Restore TextAsset extension: {!f_notRestoreExtensionName.Value}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.AppendLine($"# Export Asset Type(s): {string.Join(", ", o_exportAssetTypes.Value)}");
|
||||||
|
sb.AppendLine($"# Log Level: {o_logLevel}");
|
||||||
|
sb.AppendLine($"# Log Output: {o_logOutput}");
|
||||||
|
sb.AppendLine($"# Export Asset List: {o_exportAssetList}");
|
||||||
|
sb.AppendLine(ShowCurrentFilter());
|
||||||
|
sb.AppendLine($"# Unity Version: \"{o_unityVersion}\"");
|
||||||
|
}
|
||||||
|
sb.AppendLine("======");
|
||||||
|
Logger.Info(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
namespace AssetStudioCLI.Options
|
||||||
|
{
|
||||||
|
internal class Option<T>
|
||||||
|
{
|
||||||
|
public string Name { get; }
|
||||||
|
public string Description { get; }
|
||||||
|
public T Value { get; set; }
|
||||||
|
public T DefaultValue { get; }
|
||||||
|
public HelpGroups HelpGroup { get; }
|
||||||
|
public bool IsFlag { get; }
|
||||||
|
|
||||||
|
public Option(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag)
|
||||||
|
{
|
||||||
|
Name = optionName;
|
||||||
|
Description = optionDescription;
|
||||||
|
DefaultValue = optionDefaultValue;
|
||||||
|
Value = DefaultValue;
|
||||||
|
HelpGroup = optionHelpGroup;
|
||||||
|
IsFlag = isFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Value != null ? Value.ToString() : string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using AssetStudioCLI.Options;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var options = new CLIOptions(args);
|
||||||
|
if (options.isParsed)
|
||||||
|
{
|
||||||
|
CLIRun(options);
|
||||||
|
}
|
||||||
|
else if (options.showHelp)
|
||||||
|
{
|
||||||
|
options.ShowHelp();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
options.ShowHelp(showUsageOnly: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CLIRun(CLIOptions options)
|
||||||
|
{
|
||||||
|
var cliLogger = new CLILogger(options);
|
||||||
|
Logger.Default = cliLogger;
|
||||||
|
var studio = new Studio(options);
|
||||||
|
options.ShowCurrentOptions();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (studio.LoadAssets())
|
||||||
|
{
|
||||||
|
studio.ParseAssets();
|
||||||
|
if (options.filterBy != FilterBy.None)
|
||||||
|
{
|
||||||
|
studio.FilterAssets();
|
||||||
|
}
|
||||||
|
if (options.o_exportAssetList.Value != ExportListType.None)
|
||||||
|
{
|
||||||
|
studio.ExportAssetList();
|
||||||
|
}
|
||||||
|
if (options.o_workMode.Value == WorkMode.Info)
|
||||||
|
{
|
||||||
|
studio.ShowExportableAssetsInfo();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
studio.ExportAssets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error(ex.ToString());
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
cliLogger.LogToFile(LoggerEvent.Verbose, "---Program ended---");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,376 @@
|
|||||||
|
using AssetStudio;
|
||||||
|
using AssetStudioCLI.Options;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using static AssetStudioCLI.Exporter;
|
||||||
|
using Ansi = AssetStudioCLI.CLIAnsiColors;
|
||||||
|
|
||||||
|
namespace AssetStudioCLI
|
||||||
|
{
|
||||||
|
internal class Studio
|
||||||
|
{
|
||||||
|
public AssetsManager assetsManager = new AssetsManager();
|
||||||
|
public List<AssetItem> parsedAssetsList = new List<AssetItem>();
|
||||||
|
private readonly CLIOptions options;
|
||||||
|
|
||||||
|
public Studio(CLIOptions cliOptions)
|
||||||
|
{
|
||||||
|
Progress.Default = new Progress<int>(ShowCurProgressValue);
|
||||||
|
options = cliOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ShowCurProgressValue(int value)
|
||||||
|
{
|
||||||
|
Console.Write($"[{value:000}%]\r");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool LoadAssets()
|
||||||
|
{
|
||||||
|
var isLoaded = false;
|
||||||
|
assetsManager.SpecifyUnityVersion = options.o_unityVersion.Value;
|
||||||
|
|
||||||
|
if (Directory.Exists(options.inputPath))
|
||||||
|
{
|
||||||
|
assetsManager.LoadFolder(options.inputPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assetsManager.LoadFiles(options.inputPath);
|
||||||
|
}
|
||||||
|
if (assetsManager.assetsFileList.Count == 0)
|
||||||
|
{
|
||||||
|
Logger.Warning("No Unity file can be loaded.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isLoaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ParseAssets()
|
||||||
|
{
|
||||||
|
Logger.Info("Parse assets...");
|
||||||
|
|
||||||
|
var fileAssetsList = new List<AssetItem>();
|
||||||
|
var containers = new Dictionary<AssetStudio.Object, string>();
|
||||||
|
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||||
|
|
||||||
|
Progress.Reset();
|
||||||
|
var i = 0;
|
||||||
|
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||||
|
{
|
||||||
|
foreach (var asset in assetsFile.Objects)
|
||||||
|
{
|
||||||
|
var assetItem = new AssetItem(asset);
|
||||||
|
assetItem.UniqueID = "_#" + i;
|
||||||
|
var isExportable = false;
|
||||||
|
switch (asset)
|
||||||
|
{
|
||||||
|
case AssetBundle m_AssetBundle:
|
||||||
|
foreach (var m_Container in m_AssetBundle.m_Container)
|
||||||
|
{
|
||||||
|
var preloadIndex = m_Container.Value.preloadIndex;
|
||||||
|
var preloadSize = m_Container.Value.preloadSize;
|
||||||
|
var preloadEnd = preloadIndex + preloadSize;
|
||||||
|
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||||
|
{
|
||||||
|
var pptr = m_AssetBundle.m_PreloadTable[k];
|
||||||
|
if (pptr.TryGet(out var obj))
|
||||||
|
{
|
||||||
|
containers[obj] = m_Container.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ResourceManager m_ResourceManager:
|
||||||
|
foreach (var m_Container in m_ResourceManager.m_Container)
|
||||||
|
{
|
||||||
|
if (m_Container.Value.TryGet(out var obj))
|
||||||
|
{
|
||||||
|
containers[obj] = m_Container.Key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Texture2D m_Texture2D:
|
||||||
|
if (!string.IsNullOrEmpty(m_Texture2D.m_StreamData?.path))
|
||||||
|
assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size;
|
||||||
|
assetItem.Text = m_Texture2D.m_Name;
|
||||||
|
break;
|
||||||
|
case AudioClip m_AudioClip:
|
||||||
|
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
|
||||||
|
assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
|
||||||
|
assetItem.Text = m_AudioClip.m_Name;
|
||||||
|
break;
|
||||||
|
case VideoClip m_VideoClip:
|
||||||
|
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
|
||||||
|
assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size;
|
||||||
|
assetItem.Text = m_VideoClip.m_Name;
|
||||||
|
break;
|
||||||
|
case TextAsset _:
|
||||||
|
case Font _:
|
||||||
|
case Sprite _:
|
||||||
|
assetItem.Text = ((NamedObject)asset).m_Name;
|
||||||
|
break;
|
||||||
|
case Shader m_Shader:
|
||||||
|
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
||||||
|
break;
|
||||||
|
case MonoBehaviour m_MonoBehaviour:
|
||||||
|
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||||
|
{
|
||||||
|
assetItem.Text = m_Script.m_ClassName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assetItem.Text = m_MonoBehaviour.m_Name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (assetItem.Text == "")
|
||||||
|
{
|
||||||
|
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
||||||
|
}
|
||||||
|
|
||||||
|
isExportable = options.o_exportAssetTypes.Value.Contains(asset.type);
|
||||||
|
if (isExportable)
|
||||||
|
{
|
||||||
|
fileAssetsList.Add(assetItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
Progress.Report(++i, objectCount);
|
||||||
|
}
|
||||||
|
foreach (var asset in fileAssetsList)
|
||||||
|
{
|
||||||
|
if (containers.ContainsKey(asset.Asset))
|
||||||
|
{
|
||||||
|
asset.Container = containers[asset.Asset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parsedAssetsList.AddRange(fileAssetsList);
|
||||||
|
containers.Clear();
|
||||||
|
fileAssetsList.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ShowExportableAssetsInfo()
|
||||||
|
{
|
||||||
|
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
|
||||||
|
if (parsedAssetsList.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var asset in parsedAssetsList)
|
||||||
|
{
|
||||||
|
if (exportableAssetsCountDict.ContainsKey(asset.Type))
|
||||||
|
{
|
||||||
|
exportableAssetsCountDict[asset.Type] += 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exportableAssetsCountDict.Add(asset.Type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var info = "\n[Exportable Assets Count]\n";
|
||||||
|
foreach (var assetType in exportableAssetsCountDict.Keys)
|
||||||
|
{
|
||||||
|
info += $"# {assetType}: {exportableAssetsCountDict[assetType]}\n";
|
||||||
|
}
|
||||||
|
if (exportableAssetsCountDict.Count > 1)
|
||||||
|
{
|
||||||
|
info += $"#\n# Total: {parsedAssetsList.Count} assets";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.o_logLevel.Value > LoggerEvent.Info)
|
||||||
|
{
|
||||||
|
Console.WriteLine(info);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Info(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void FilterAssets()
|
||||||
|
{
|
||||||
|
var assetsCount = parsedAssetsList.Count;
|
||||||
|
var filteredAssets = new List<AssetItem>();
|
||||||
|
|
||||||
|
switch(options.filterBy)
|
||||||
|
{
|
||||||
|
case FilterBy.Name:
|
||||||
|
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
|
Logger.Info(
|
||||||
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
|
$"that contain {$"\"{string.Join("\", \"", options.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FilterBy.Container:
|
||||||
|
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByContainer.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
|
Logger.Info(
|
||||||
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
|
$"that contain {$"\"{string.Join("\", \"", options.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FilterBy.PathID:
|
||||||
|
filteredAssets = parsedAssetsList.FindAll(x => options.o_filterByPathID.Value.Any(y => x.m_PathID.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||||
|
Logger.Info(
|
||||||
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
|
$"that contain {$"\"{string.Join("\", \"", options.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FilterBy.NameOrContainer:
|
||||||
|
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||||
|
options.o_filterByText.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||||
|
options.o_filterByText.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
|
);
|
||||||
|
Logger.Info(
|
||||||
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
|
$"that contain {$"\"{string.Join("\", \"", options.o_filterByText.Value)}\"".Color(Ansi.BrightYellow)} in their Names or Contaniers."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FilterBy.NameAndContainer:
|
||||||
|
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||||
|
options.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) &&
|
||||||
|
options.o_filterByContainer.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||||
|
);
|
||||||
|
Logger.Info(
|
||||||
|
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||||
|
$"that contain {$"\"{string.Join("\", \"", options.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers " +
|
||||||
|
$"and {$"\"{string.Join("\", \"", options.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parsedAssetsList.Clear();
|
||||||
|
parsedAssetsList = filteredAssets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExportAssets()
|
||||||
|
{
|
||||||
|
var savePath = options.o_outputFolder.Value;
|
||||||
|
var toExportCount = parsedAssetsList.Count;
|
||||||
|
var exportedCount = 0;
|
||||||
|
|
||||||
|
foreach (var asset in parsedAssetsList)
|
||||||
|
{
|
||||||
|
string exportPath;
|
||||||
|
switch (options.o_groupAssetsBy.Value)
|
||||||
|
{
|
||||||
|
case AssetGroupOption.TypeName:
|
||||||
|
exportPath = Path.Combine(savePath, asset.TypeString);
|
||||||
|
break;
|
||||||
|
case AssetGroupOption.ContainerPath:
|
||||||
|
if (!string.IsNullOrEmpty(asset.Container))
|
||||||
|
{
|
||||||
|
exportPath = Path.Combine(savePath, Path.GetDirectoryName(asset.Container));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exportPath = savePath;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AssetGroupOption.SourceFileName:
|
||||||
|
if (string.IsNullOrEmpty(asset.SourceFile.originalPath))
|
||||||
|
{
|
||||||
|
exportPath = Path.Combine(savePath, asset.SourceFile.fileName + "_export");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exportPath = savePath;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
exportPath += Path.DirectorySeparatorChar;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (options.o_workMode.Value)
|
||||||
|
{
|
||||||
|
case WorkMode.ExportRaw:
|
||||||
|
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
|
if (ExportRawFile(asset, exportPath))
|
||||||
|
{
|
||||||
|
exportedCount++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WorkMode.Dump:
|
||||||
|
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
|
if (ExportDumpFile(asset, exportPath, options))
|
||||||
|
{
|
||||||
|
exportedCount++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WorkMode.Export:
|
||||||
|
Logger.Debug($"{options.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||||
|
if (ExportConvertFile(asset, exportPath, options))
|
||||||
|
{
|
||||||
|
exportedCount++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.Error($"{asset.SourceFile.originalPath}: [{$"{asset.Type}: {asset.Text}".Color(Ansi.BrightRed)}] : Export error\n{ex}");
|
||||||
|
}
|
||||||
|
Console.Write($"Exported [{exportedCount}/{toExportCount}]\r");
|
||||||
|
}
|
||||||
|
Console.WriteLine("");
|
||||||
|
|
||||||
|
if (exportedCount == 0)
|
||||||
|
{
|
||||||
|
Logger.Info("Nothing exported.");
|
||||||
|
}
|
||||||
|
else if (toExportCount > exportedCount)
|
||||||
|
{
|
||||||
|
Logger.Info($"Finished exporting {exportedCount} asset(s) to \"{options.o_outputFolder.Value.Color(Ansi.BrightYellow)}\".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Info($"Finished exporting {exportedCount} asset(s) to \"{options.o_outputFolder.Value.Color(Ansi.BrightGreen)}\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toExportCount > exportedCount)
|
||||||
|
{
|
||||||
|
Logger.Info($"{toExportCount - exportedCount} asset(s) skipped (not extractable or file(s) already exist).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExportAssetList()
|
||||||
|
{
|
||||||
|
var savePath = options.o_outputFolder.Value;
|
||||||
|
|
||||||
|
switch (options.o_exportAssetList.Value)
|
||||||
|
{
|
||||||
|
case ExportListType.XML:
|
||||||
|
var filename = Path.Combine(savePath, "assets.xml");
|
||||||
|
var doc = new XDocument(
|
||||||
|
new XElement("Assets",
|
||||||
|
new XAttribute("filename", filename),
|
||||||
|
new XAttribute("createdAt", DateTime.UtcNow.ToString("s")),
|
||||||
|
parsedAssetsList.Select(
|
||||||
|
asset => new XElement("Asset",
|
||||||
|
new XElement("Name", asset.Text),
|
||||||
|
new XElement("Container", asset.Container),
|
||||||
|
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
|
||||||
|
new XElement("PathID", asset.m_PathID),
|
||||||
|
new XElement("Source", asset.SourceFile.fullName),
|
||||||
|
new XElement("Size", asset.FullSize)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
doc.Save(filename);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Logger.Info($"Finished exporting asset list with {parsedAssetsList.Count} items.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
using AssetStudio.FbxInterop;
|
using AssetStudio.FbxInterop;
|
||||||
using AssetStudio.PInvoke;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
|
using AssetStudio.PInvoke;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public static partial class Fbx
|
public static partial class Fbx
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
static Fbx()
|
static Fbx()
|
||||||
{
|
{
|
||||||
DllLoader.PreloadDll(FbxDll.DllName);
|
DllLoader.PreloadDll(FbxDll.DllName);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static Vector3 QuaternionToEuler(Quaternion q)
|
public static Vector3 QuaternionToEuler(Quaternion q)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
<AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle>
|
<AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -40,44 +40,76 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ContentWithTargetPath Include="Libraries\x86\fmod.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<TargetPath>x86\fmod.dll</TargetPath>
|
|
||||||
</ContentWithTargetPath>
|
|
||||||
<ContentWithTargetPath Include="Libraries\x64\fmod.dll">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<TargetPath>x64\fmod.dll</TargetPath>
|
|
||||||
</ContentWithTargetPath>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
<PackageReference Include="OpenTK" Version="4.6.7" />
|
<PackageReference Include="OpenTK" Version="4.7.7" />
|
||||||
<Reference Include="OpenTK.WinForms">
|
<Reference Include="OpenTK.WinForms">
|
||||||
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
<PackageReference Include="OpenTK" Version="3.1.0" />
|
<PackageReference Include="OpenTK" Version="3.3.3" />
|
||||||
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
|
<PackageReference Include="OpenTK.GLControl" Version="3.3.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="CopyExtraFiles" AfterTargets="AfterBuild">
|
<!-- Use local compiled win-x86 and win-x64 Texture2DDecoder libs, because libs from Kyaru.Texture2DDecoder.Windows were compiled with /MD flag -->
|
||||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
|
||||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' OR '$(TargetFramework)' == 'net472' ">
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
<Message Text="Copying extra files for $(TargetFramework)... " Importance="high" />
|
||||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\x86\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\x64\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="PublishExtraFiles" AfterTargets="Publish">
|
<!-- Publishing an app as framework-dependent produces a cross-platform binary as a dll file, and a platform-specific executable that targets your current platform.
|
||||||
<Copy SourceFiles="$(TargetDir)x86\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
|
The dll is cross-platform while the executable isn't -->
|
||||||
<Copy SourceFiles="$(TargetDir)x64\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
|
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||||
<Copy SourceFiles="$(TargetDir)x86\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x86" ContinueOnError="true" />
|
<Message Text="Publishing extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||||
<Copy SourceFiles="$(TargetDir)x64\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)x64" ContinueOnError="true" />
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
|
||||||
|
<!-- Published net472 build of AssetStudioGUI is only suitable for x32(x86)-bit OS -->
|
||||||
|
<Target Name="PublishExtraFilesNet472Warning" AfterTargets="Publish" Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
|
<Message Text="%0a NOTE: Published net472 build of AssetStudioGUI is only suitable for x32(x86)-bit OS." Importance="high" />
|
||||||
|
<Message Text=" If u need cross-architecture support (x32/x64) in net472, using the binaries created after the build is highly recommended (no need to publish).%0a" Importance="high" />
|
||||||
|
|
||||||
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x86' OR ( '$(RuntimeIdentifier)' == 'win7-x86' AND '$(TargetFramework)' != 'net472' ) ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\x86\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CopyExtraFilesWin64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">
|
||||||
|
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(ProjectDir)Libraries\x64\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="PublishExtraFilesWin" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('win-x')) OR ( '$(RuntimeIdentifier)' == 'win7-x86' AND '$(TargetFramework)' != 'net472' ) ">
|
||||||
|
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\fmod.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
</Project>
|
||||||
|
|||||||
+29
-16
@@ -79,6 +79,7 @@
|
|||||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||||
|
this.sceneTreeView = new AssetStudioGUI.GOHierarchy();
|
||||||
this.treeSearch = new System.Windows.Forms.TextBox();
|
this.treeSearch = new System.Windows.Forms.TextBox();
|
||||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||||
this.filterExcludeMode = new System.Windows.Forms.CheckBox();
|
this.filterExcludeMode = new System.Windows.Forms.CheckBox();
|
||||||
@@ -127,7 +128,6 @@
|
|||||||
this.dumpSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.dumpSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
this.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.sceneTreeView = new AssetStudioGUI.GOHierarchy();
|
|
||||||
this.menuStrip1.SuspendLayout();
|
this.menuStrip1.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
|
||||||
this.splitContainer1.Panel1.SuspendLayout();
|
this.splitContainer1.Panel1.SuspendLayout();
|
||||||
@@ -573,6 +573,17 @@
|
|||||||
this.tabPage1.Text = "Scene Hierarchy";
|
this.tabPage1.Text = "Scene Hierarchy";
|
||||||
this.tabPage1.UseVisualStyleBackColor = true;
|
this.tabPage1.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// sceneTreeView
|
||||||
|
//
|
||||||
|
this.sceneTreeView.CheckBoxes = true;
|
||||||
|
this.sceneTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.sceneTreeView.HideSelection = false;
|
||||||
|
this.sceneTreeView.Location = new System.Drawing.Point(0, 20);
|
||||||
|
this.sceneTreeView.Name = "sceneTreeView";
|
||||||
|
this.sceneTreeView.Size = new System.Drawing.Size(472, 587);
|
||||||
|
this.sceneTreeView.TabIndex = 1;
|
||||||
|
this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);
|
||||||
|
//
|
||||||
// treeSearch
|
// treeSearch
|
||||||
//
|
//
|
||||||
this.treeSearch.Dock = System.Windows.Forms.DockStyle.Top;
|
this.treeSearch.Dock = System.Windows.Forms.DockStyle.Top;
|
||||||
@@ -599,7 +610,7 @@
|
|||||||
this.tabPage2.Text = "Asset List";
|
this.tabPage2.Text = "Asset List";
|
||||||
this.tabPage2.UseVisualStyleBackColor = true;
|
this.tabPage2.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// filterExludeMode
|
// filterExcludeMode
|
||||||
//
|
//
|
||||||
this.filterExcludeMode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
this.filterExcludeMode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
this.filterExcludeMode.AutoSize = true;
|
this.filterExcludeMode.AutoSize = true;
|
||||||
@@ -607,14 +618,15 @@
|
|||||||
this.filterExcludeMode.Enabled = false;
|
this.filterExcludeMode.Enabled = false;
|
||||||
this.filterExcludeMode.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
this.filterExcludeMode.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
|
||||||
this.filterExcludeMode.ForeColor = System.Drawing.SystemColors.ControlText;
|
this.filterExcludeMode.ForeColor = System.Drawing.SystemColors.ControlText;
|
||||||
|
this.filterExcludeMode.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.filterExcludeMode.Location = new System.Drawing.Point(409, 2);
|
this.filterExcludeMode.Location = new System.Drawing.Point(409, 2);
|
||||||
this.filterExcludeMode.Name = "filterExludeMode";
|
this.filterExcludeMode.Name = "filterExcludeMode";
|
||||||
this.filterExcludeMode.Size = new System.Drawing.Size(61, 17);
|
this.filterExcludeMode.Size = new System.Drawing.Size(61, 17);
|
||||||
this.filterExcludeMode.TabIndex = 2;
|
this.filterExcludeMode.TabIndex = 2;
|
||||||
this.filterExcludeMode.Text = "Exclude";
|
this.filterExcludeMode.Text = "Exclude";
|
||||||
this.filterExcludeMode.TextAlign = System.Drawing.ContentAlignment.BottomRight;
|
this.filterExcludeMode.TextAlign = System.Drawing.ContentAlignment.BottomRight;
|
||||||
this.filterExcludeMode.UseVisualStyleBackColor = false;
|
this.filterExcludeMode.UseVisualStyleBackColor = false;
|
||||||
this.filterExcludeMode.CheckedChanged += new System.EventHandler(this.filterExludeMode_CheckedChanged);
|
this.filterExcludeMode.CheckedChanged += new System.EventHandler(this.filterExcludeMode_CheckedChanged);
|
||||||
//
|
//
|
||||||
// assetListView
|
// assetListView
|
||||||
//
|
//
|
||||||
@@ -731,6 +743,7 @@
|
|||||||
// progressBar1
|
// progressBar1
|
||||||
//
|
//
|
||||||
this.progressBar1.Dock = System.Windows.Forms.DockStyle.Bottom;
|
this.progressBar1.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
|
this.progressBar1.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.progressBar1.Location = new System.Drawing.Point(1, 3);
|
this.progressBar1.Location = new System.Drawing.Point(1, 3);
|
||||||
this.progressBar1.Name = "progressBar1";
|
this.progressBar1.Name = "progressBar1";
|
||||||
this.progressBar1.Size = new System.Drawing.Size(478, 18);
|
this.progressBar1.Size = new System.Drawing.Size(478, 18);
|
||||||
@@ -782,6 +795,7 @@
|
|||||||
this.assetInfoLabel.AutoSize = true;
|
this.assetInfoLabel.AutoSize = true;
|
||||||
this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;
|
this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;
|
||||||
this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
|
this.assetInfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.assetInfoLabel.Location = new System.Drawing.Point(4, 8);
|
this.assetInfoLabel.Location = new System.Drawing.Point(4, 8);
|
||||||
this.assetInfoLabel.Name = "assetInfoLabel";
|
this.assetInfoLabel.Name = "assetInfoLabel";
|
||||||
this.assetInfoLabel.Size = new System.Drawing.Size(0, 13);
|
this.assetInfoLabel.Size = new System.Drawing.Size(0, 13);
|
||||||
@@ -811,6 +825,7 @@
|
|||||||
//
|
//
|
||||||
this.FMODcopyright.AutoSize = true;
|
this.FMODcopyright.AutoSize = true;
|
||||||
this.FMODcopyright.ForeColor = System.Drawing.SystemColors.ControlLight;
|
this.FMODcopyright.ForeColor = System.Drawing.SystemColors.ControlLight;
|
||||||
|
this.FMODcopyright.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODcopyright.Location = new System.Drawing.Point(214, 365);
|
this.FMODcopyright.Location = new System.Drawing.Point(214, 365);
|
||||||
this.FMODcopyright.Name = "FMODcopyright";
|
this.FMODcopyright.Name = "FMODcopyright";
|
||||||
this.FMODcopyright.Size = new System.Drawing.Size(283, 13);
|
this.FMODcopyright.Size = new System.Drawing.Size(283, 13);
|
||||||
@@ -821,6 +836,7 @@
|
|||||||
//
|
//
|
||||||
this.FMODinfoLabel.AutoSize = true;
|
this.FMODinfoLabel.AutoSize = true;
|
||||||
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
|
this.FMODinfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255);
|
this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255);
|
||||||
this.FMODinfoLabel.Name = "FMODinfoLabel";
|
this.FMODinfoLabel.Name = "FMODinfoLabel";
|
||||||
this.FMODinfoLabel.Size = new System.Drawing.Size(0, 13);
|
this.FMODinfoLabel.Size = new System.Drawing.Size(0, 13);
|
||||||
@@ -830,6 +846,7 @@
|
|||||||
//
|
//
|
||||||
this.FMODtimerLabel.AutoSize = true;
|
this.FMODtimerLabel.AutoSize = true;
|
||||||
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
|
this.FMODtimerLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253);
|
this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253);
|
||||||
this.FMODtimerLabel.Name = "FMODtimerLabel";
|
this.FMODtimerLabel.Name = "FMODtimerLabel";
|
||||||
this.FMODtimerLabel.Size = new System.Drawing.Size(102, 13);
|
this.FMODtimerLabel.Size = new System.Drawing.Size(102, 13);
|
||||||
@@ -840,6 +857,7 @@
|
|||||||
//
|
//
|
||||||
this.FMODstatusLabel.AutoSize = true;
|
this.FMODstatusLabel.AutoSize = true;
|
||||||
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||||
|
this.FMODstatusLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255);
|
this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255);
|
||||||
this.FMODstatusLabel.Name = "FMODstatusLabel";
|
this.FMODstatusLabel.Name = "FMODstatusLabel";
|
||||||
this.FMODstatusLabel.Size = new System.Drawing.Size(47, 13);
|
this.FMODstatusLabel.Size = new System.Drawing.Size(47, 13);
|
||||||
@@ -849,6 +867,7 @@
|
|||||||
// FMODprogressBar
|
// FMODprogressBar
|
||||||
//
|
//
|
||||||
this.FMODprogressBar.AutoSize = false;
|
this.FMODprogressBar.AutoSize = false;
|
||||||
|
this.FMODprogressBar.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODprogressBar.Location = new System.Drawing.Point(213, 274);
|
this.FMODprogressBar.Location = new System.Drawing.Point(213, 274);
|
||||||
this.FMODprogressBar.Maximum = 1000;
|
this.FMODprogressBar.Maximum = 1000;
|
||||||
this.FMODprogressBar.Name = "FMODprogressBar";
|
this.FMODprogressBar.Name = "FMODprogressBar";
|
||||||
@@ -861,6 +880,7 @@
|
|||||||
//
|
//
|
||||||
// FMODvolumeBar
|
// FMODvolumeBar
|
||||||
//
|
//
|
||||||
|
this.FMODvolumeBar.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODvolumeBar.LargeChange = 2;
|
this.FMODvolumeBar.LargeChange = 2;
|
||||||
this.FMODvolumeBar.Location = new System.Drawing.Point(460, 303);
|
this.FMODvolumeBar.Location = new System.Drawing.Point(460, 303);
|
||||||
this.FMODvolumeBar.Name = "FMODvolumeBar";
|
this.FMODvolumeBar.Name = "FMODvolumeBar";
|
||||||
@@ -873,6 +893,7 @@
|
|||||||
// FMODloopButton
|
// FMODloopButton
|
||||||
//
|
//
|
||||||
this.FMODloopButton.Appearance = System.Windows.Forms.Appearance.Button;
|
this.FMODloopButton.Appearance = System.Windows.Forms.Appearance.Button;
|
||||||
|
this.FMODloopButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODloopButton.Location = new System.Drawing.Point(399, 303);
|
this.FMODloopButton.Location = new System.Drawing.Point(399, 303);
|
||||||
this.FMODloopButton.Name = "FMODloopButton";
|
this.FMODloopButton.Name = "FMODloopButton";
|
||||||
this.FMODloopButton.Size = new System.Drawing.Size(55, 46);
|
this.FMODloopButton.Size = new System.Drawing.Size(55, 46);
|
||||||
@@ -884,6 +905,7 @@
|
|||||||
//
|
//
|
||||||
// FMODstopButton
|
// FMODstopButton
|
||||||
//
|
//
|
||||||
|
this.FMODstopButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODstopButton.Location = new System.Drawing.Point(338, 303);
|
this.FMODstopButton.Location = new System.Drawing.Point(338, 303);
|
||||||
this.FMODstopButton.Name = "FMODstopButton";
|
this.FMODstopButton.Name = "FMODstopButton";
|
||||||
this.FMODstopButton.Size = new System.Drawing.Size(55, 46);
|
this.FMODstopButton.Size = new System.Drawing.Size(55, 46);
|
||||||
@@ -894,6 +916,7 @@
|
|||||||
//
|
//
|
||||||
// FMODpauseButton
|
// FMODpauseButton
|
||||||
//
|
//
|
||||||
|
this.FMODpauseButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODpauseButton.Location = new System.Drawing.Point(277, 303);
|
this.FMODpauseButton.Location = new System.Drawing.Point(277, 303);
|
||||||
this.FMODpauseButton.Name = "FMODpauseButton";
|
this.FMODpauseButton.Name = "FMODpauseButton";
|
||||||
this.FMODpauseButton.Size = new System.Drawing.Size(55, 46);
|
this.FMODpauseButton.Size = new System.Drawing.Size(55, 46);
|
||||||
@@ -904,6 +927,7 @@
|
|||||||
//
|
//
|
||||||
// FMODplayButton
|
// FMODplayButton
|
||||||
//
|
//
|
||||||
|
this.FMODplayButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||||
this.FMODplayButton.Location = new System.Drawing.Point(216, 303);
|
this.FMODplayButton.Location = new System.Drawing.Point(216, 303);
|
||||||
this.FMODplayButton.Name = "FMODplayButton";
|
this.FMODplayButton.Name = "FMODplayButton";
|
||||||
this.FMODplayButton.Size = new System.Drawing.Size(55, 46);
|
this.FMODplayButton.Size = new System.Drawing.Size(55, 46);
|
||||||
@@ -945,7 +969,7 @@
|
|||||||
// textPreviewBox
|
// textPreviewBox
|
||||||
//
|
//
|
||||||
this.textPreviewBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
this.textPreviewBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.textPreviewBox.Font = new System.Drawing.Font("Consolas", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
this.textPreviewBox.Font = new System.Drawing.Font("Consolas", 9.75F);
|
||||||
this.textPreviewBox.Location = new System.Drawing.Point(0, 0);
|
this.textPreviewBox.Location = new System.Drawing.Point(0, 0);
|
||||||
this.textPreviewBox.Multiline = true;
|
this.textPreviewBox.Multiline = true;
|
||||||
this.textPreviewBox.Name = "textPreviewBox";
|
this.textPreviewBox.Name = "textPreviewBox";
|
||||||
@@ -1080,17 +1104,6 @@
|
|||||||
this.showOriginalFileToolStripMenuItem.Visible = false;
|
this.showOriginalFileToolStripMenuItem.Visible = false;
|
||||||
this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);
|
this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);
|
||||||
//
|
//
|
||||||
// sceneTreeView
|
|
||||||
//
|
|
||||||
this.sceneTreeView.CheckBoxes = true;
|
|
||||||
this.sceneTreeView.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
||||||
this.sceneTreeView.HideSelection = false;
|
|
||||||
this.sceneTreeView.Location = new System.Drawing.Point(0, 20);
|
|
||||||
this.sceneTreeView.Name = "sceneTreeView";
|
|
||||||
this.sceneTreeView.Size = new System.Drawing.Size(472, 587);
|
|
||||||
this.sceneTreeView.TabIndex = 1;
|
|
||||||
this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);
|
|
||||||
//
|
|
||||||
// AssetStudioGUIForm
|
// AssetStudioGUIForm
|
||||||
//
|
//
|
||||||
this.AllowDrop = true;
|
this.AllowDrop = true;
|
||||||
|
|||||||
@@ -1579,7 +1579,7 @@ namespace AssetStudioGUI
|
|||||||
return selectedAssets;
|
return selectedAssets;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterExludeMode_CheckedChanged(object sender, EventArgs e)
|
private void filterExcludeMode_CheckedChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
FilterAssetList();
|
FilterAssetList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,37 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
<PackageReference Include="Mono.Cecil" Version="0.11.3" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup Condition=" !$(TargetFramework.Contains('windows')) ">
|
||||||
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
|
<PackageReference Include="Kyaru.Texture2DDecoder.Linux" Version="0.1.0" />
|
||||||
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj" />
|
<PackageReference Include="Kyaru.Texture2DDecoder.macOS" Version="0.1.0" />
|
||||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
</ItemGroup>
|
||||||
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj" />
|
|
||||||
</ItemGroup>
|
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||||
|
<PackageReference Include="Kyaru.Texture2DDecoder.Windows" Version="0.1.0" />
|
||||||
|
<PackageReference Include="Kyaru.Texture2DDecoder">
|
||||||
|
<Version>0.17.0</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\AssetStudio.PInvoke\AssetStudio.PInvoke.csproj" />
|
||||||
|
<ProjectReference Include="..\AssetStudioFBXWrapper\AssetStudioFBXWrapper.csproj" />
|
||||||
|
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||||
|
<ProjectReference Include="..\Texture2DDecoderWrapper\Texture2DDecoderWrapper.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
using AssetStudio.PInvoke;
|
using AssetStudio.PInvoke;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace FMOD
|
namespace FMOD
|
||||||
{
|
{
|
||||||
@@ -749,10 +752,12 @@ namespace FMOD
|
|||||||
*/
|
*/
|
||||||
public struct Factory
|
public struct Factory
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
static Factory()
|
static Factory()
|
||||||
{
|
{
|
||||||
DllLoader.PreloadDll(VERSION.dll);
|
DllLoader.PreloadDll(VERSION.dll);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static RESULT System_Create(out System system)
|
public static RESULT System_Create(out System system)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
<TargetFramework>net472</TargetFramework>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.16.47.1</Version>
|
<Version>0.16.48.1</Version>
|
||||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,16 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
#if NETFRAMEWORK
|
||||||
using AssetStudio.PInvoke;
|
using AssetStudio.PInvoke;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Texture2DDecoder
|
namespace Texture2DDecoder
|
||||||
{
|
{
|
||||||
public static unsafe partial class TextureDecoder
|
public static unsafe partial class TextureDecoder
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
static TextureDecoder()
|
static TextureDecoder()
|
||||||
{
|
{
|
||||||
DllLoader.PreloadDll(T2DDll.DllName);
|
DllLoader.PreloadDll(T2DDll.DllName);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image)
|
public static bool DecodeDXT1(byte[] data, int width, int height, byte[] image)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user