Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6c6ceba1c | ||
|
|
7c0a6375b1 | ||
|
|
5c489c5f83 | ||
|
|
25c611fb9e | ||
|
|
6d3875cb2c | ||
|
|
be4ced77ea | ||
|
|
2bd762e8f4 | ||
|
|
a926644ff6 | ||
|
|
a4cdff5934 | ||
|
|
2e10e627b0 | ||
|
|
e216abd6be | ||
|
|
93c7e617d8 | ||
|
|
000916913e | ||
|
|
28f9744497 | ||
|
|
c3f99216b6 | ||
|
|
19c4835ea3 | ||
|
|
6b321da695 | ||
|
|
7cca301f7a | ||
|
|
5ac597c935 | ||
|
|
e90af43459 | ||
|
|
171962e61f | ||
|
|
c8a21838c9 | ||
|
|
cf67815d53 | ||
|
|
381a7d89ae | ||
|
|
572e3bf0d6 | ||
|
|
3d7d51b54f | ||
|
|
abbd27fde7 | ||
|
|
94c8b355fe | ||
|
|
4e41caf203 | ||
|
|
74a8555514 | ||
|
|
e1d883adf6 | ||
|
|
9784df0e16 | ||
|
|
4d919a2bfe | ||
|
|
6701f467b7 | ||
|
|
50f5da5554 | ||
|
|
2b6dcca9c8 | ||
|
|
0bdcb89b08 | ||
|
|
dcd7b98229 | ||
|
|
007e5c7e4d | ||
|
|
63564d5fff | ||
|
|
aea6cbc97f | ||
|
|
6d41693b85 | ||
|
|
5695afae7b | ||
|
|
bb9ea7d86b | ||
|
|
547659e151 | ||
|
|
2f8f57c1a6 | ||
|
|
b7d5d73f23 | ||
|
|
f0c237473c | ||
|
|
09947fd14f | ||
|
|
da216dace8 | ||
|
|
c7356875f9 | ||
|
|
02e46eaa0d | ||
|
|
b0bf5e0cfd | ||
|
|
11b9ca37da | ||
|
|
5944dd8c58 | ||
|
|
1c67e39504 | ||
|
|
2d81007556 | ||
|
|
4bae98813b | ||
|
|
90ec395b2a | ||
|
|
af3684bab8 | ||
|
|
1da51ac95b | ||
|
|
9e14f1ef00 | ||
|
|
4edadb19f8 | ||
|
|
44a1240f5f | ||
|
|
01957a9443 | ||
|
|
ad1b3b4911 | ||
|
|
0925751776 | ||
|
|
b59ba3ba94 | ||
|
|
67898c72ca | ||
|
|
0425423ca9 | ||
|
|
16a7107d4e | ||
|
|
10b7e84ffb | ||
|
|
679e7041a6 | ||
|
|
629c6248a4 | ||
|
|
7674081df7 | ||
|
|
fb574064c9 | ||
|
|
c52940abc4 | ||
|
|
5c662d64e4 | ||
|
|
b9cf95616b | ||
|
|
39490d4e03 | ||
|
|
a96d1a5d5d | ||
|
|
568daafc7f | ||
|
|
2a2216e2bf | ||
|
|
dfbe46e1e5 | ||
|
|
6a9aad510c | ||
|
|
fd21cafd29 | ||
|
|
ea09a8de64 | ||
|
|
7fa5b4f355 | ||
|
|
c22d92009a | ||
|
|
53f3e8232a | ||
|
|
2fe57a1c5d | ||
|
|
ded2dcd54e | ||
|
|
8ae3df6197 | ||
|
|
64d9718c34 | ||
|
|
220004c976 | ||
|
|
a324366be9 | ||
|
|
06b4ae9ffe | ||
|
|
77b056de5e | ||
|
|
344edb722f | ||
|
|
98c4d0c3ab | ||
|
|
23ac590648 | ||
|
|
54445475a3 | ||
|
|
7299bcba6d | ||
|
|
5487ff4e60 | ||
|
|
b3621a75b0 | ||
|
|
8b048b9e1e | ||
|
|
41a79f485f | ||
|
|
a060a392e7 | ||
|
|
0798af7c5c | ||
|
|
8ebfa16e19 | ||
|
|
d158e864b5 | ||
|
|
b70b5196e3 | ||
|
|
4f88841026 | ||
|
|
dc9429feac | ||
|
|
a3c16ed3d6 | ||
|
|
5b83eebdda | ||
|
|
1fcf7a4364 | ||
|
|
973d50ce8b | ||
|
|
50485a9bd3 | ||
|
|
dbb3d3fef7 | ||
|
|
e1cfff63c3 | ||
|
|
44514a4e10 | ||
|
|
b1205808e2 | ||
|
|
7d3a4a10fc | ||
|
|
b909857820 | ||
|
|
b674e66407 | ||
|
|
d7dcd3f405 | ||
|
|
44145e0b9c | ||
|
|
d4e21f824c | ||
|
|
e7a4604a65 | ||
|
|
74f2c3190b | ||
|
|
8d193a63cd | ||
|
|
e61a317185 | ||
|
|
f67965b1dd | ||
|
|
07a81d9bfe | ||
|
|
95fd1823c8 | ||
|
|
d25451d5b9 | ||
|
|
0e1a886e0b | ||
|
|
97b5f51f3a | ||
|
|
7295feda72 | ||
|
|
fe95c91759 | ||
|
|
d220315d9b | ||
|
|
a94caa5e34 | ||
|
|
3660b4ed67 | ||
|
|
3370f93037 | ||
|
|
80653711cd | ||
|
|
f0b23bbfe7 | ||
|
|
88c5804586 | ||
|
|
e501940f03 | ||
|
|
d4060cde6d | ||
|
|
582a779441 | ||
|
|
5fa4934787 | ||
|
|
18277fbea8 |
57
.github/workflows/build.yml
vendored
Normal file
57
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
name: AssetStudioBuild
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: microsoft/setup-msbuild@v1.1
|
||||
|
||||
- name: Download FBX SDK
|
||||
run: |
|
||||
md fbx
|
||||
cd fbx
|
||||
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_win.exe" -OutFile "fbxsdk.exe"
|
||||
Start-Process -FilePath "fbxsdk.exe" /S -Wait
|
||||
Invoke-WebRequest "https://damassets.autodesk.net/content/dam/autodesk/www/adn/fbx/2020-2-1/fbx202021_fbxsdk_vs2019_pdbs.exe" -OutFile "fbxpdb.exe"
|
||||
Start-Process -FilePath "fbxpdb.exe" /S -Wait
|
||||
cd ..
|
||||
|
||||
- name: Nuget Restore
|
||||
run: nuget restore
|
||||
|
||||
- name: Build .Net472
|
||||
run: msbuild /p:Configuration=Release /p:TargetFramework=net472 /verbosity:minimal
|
||||
|
||||
- name: Build .Net5
|
||||
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net5.0-windows /p:SelfContained=false /verbosity:minimal
|
||||
|
||||
- name: Build .Net6
|
||||
run: msbuild /t:AssetStudioGUI:publish /p:Configuration=Release /p:TargetFramework=net6.0-windows /p:SelfContained=false /verbosity:minimal
|
||||
|
||||
- name: Upload .Net472 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net472
|
||||
path: AssetStudioGUI/bin/Release/net472
|
||||
|
||||
- name: Upload .Net5 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net5
|
||||
path: AssetStudioGUI/bin/Release/net5.0-windows/publish
|
||||
|
||||
- name: Upload .Net6 Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: AssetStudio.net6
|
||||
path: AssetStudioGUI/bin/Release/net6.0-windows/publish
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -35,6 +35,9 @@ bld/
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# Launch Settings
|
||||
*launchSettings.json
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>0.16.8.1</Version>
|
||||
<AssemblyVersion>0.16.8.1</AssemblyVersion>
|
||||
<FileVersion>0.16.8.1</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2020-2021; Copyright © hozuki 2020</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<Version>1.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -4,33 +4,29 @@ using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
namespace AssetStudio.PInvoke
|
||||
{
|
||||
public static class DllLoader
|
||||
{
|
||||
|
||||
public static void PreloadDll(string dllName)
|
||||
{
|
||||
var dllDir = GetDirectedDllDirectory();
|
||||
var localPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
var localDir = Path.GetDirectoryName(localPath);
|
||||
|
||||
// Not using OperatingSystem.Platform.
|
||||
// See: https://www.mono-project.com/docs/faq/technical/#how-to-detect-the-execution-platform
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
Win32.LoadDll(dllDir, dllName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Posix.LoadDll(dllDir, dllName);
|
||||
Win32.LoadDll(GetDirectedDllDirectory(localDir), dllName);
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDirectedDllDirectory()
|
||||
private static string GetDirectedDllDirectory(string localDir)
|
||||
{
|
||||
var localPath = Process.GetCurrentProcess().MainModule.FileName;
|
||||
var localDir = Path.GetDirectoryName(localPath);
|
||||
|
||||
var subDir = Environment.Is64BitProcess ? "x64" : "x86";
|
||||
var win32Path = Path.Combine("runtimes", "win-x86", "native");
|
||||
var win64Path = Path.Combine("runtimes", "win-x64", "native");
|
||||
var subDir = Environment.Is64BitProcess ? win64Path : win32Path;
|
||||
|
||||
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_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
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31410.357
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.33414.496
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetStudio", "AssetStudio\AssetStudio.csproj", "{422FEC21-EF60-4F29-AA56-95DFDA23C913}"
|
||||
EndProject
|
||||
@@ -25,6 +25,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AssetStudioFBXNative", "Ass
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Texture2DDecoderNative", "Texture2DDecoderNative\Texture2DDecoderNative.vcxproj", "{29356642-C46E-4144-83D8-22DC09D0D7FD}"
|
||||
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
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
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|x86.ActiveCfg = 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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
|
||||
<Version>0.16.8.1</Version>
|
||||
<AssemblyVersion>0.16.8.1</AssemblyVersion>
|
||||
<FileVersion>0.16.8.1</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2018-2021</Copyright>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<Version>1.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static AssetStudio.ImportHelper;
|
||||
@@ -11,27 +12,96 @@ namespace AssetStudio
|
||||
{
|
||||
public string SpecifyUnityVersion;
|
||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||
private HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
|
||||
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private List<string> importFiles = new List<string>();
|
||||
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public void LoadFiles(params string[] files)
|
||||
public void SetAssetFilter(params ClassIDType[] classIDTypes)
|
||||
{
|
||||
var path = Path.GetDirectoryName(files[0]);
|
||||
MergeSplitAssets(path);
|
||||
var toReadFile = ProcessingSplitFiles(files.ToList());
|
||||
Load(toReadFile);
|
||||
if (filteredAssetTypesList.Count == 0)
|
||||
{
|
||||
filteredAssetTypesList.UnionWith(new HashSet<ClassIDType>
|
||||
{
|
||||
ClassIDType.AssetBundle,
|
||||
ClassIDType.ResourceManager,
|
||||
});
|
||||
}
|
||||
|
||||
if (classIDTypes.Contains(ClassIDType.MonoBehaviour))
|
||||
{
|
||||
filteredAssetTypesList.Add(ClassIDType.MonoScript);
|
||||
}
|
||||
if (classIDTypes.Contains(ClassIDType.Sprite) || classIDTypes.Contains(ClassIDType.AkPortraitSprite))
|
||||
{
|
||||
filteredAssetTypesList.UnionWith(new HashSet<ClassIDType>
|
||||
{
|
||||
ClassIDType.Texture2D,
|
||||
ClassIDType.MonoBehaviour,
|
||||
ClassIDType.MonoScript
|
||||
});
|
||||
}
|
||||
|
||||
filteredAssetTypesList.UnionWith(classIDTypes);
|
||||
}
|
||||
|
||||
public void LoadFolder(string path)
|
||||
public void SetAssetFilter(List<ClassIDType> classIDTypeList)
|
||||
{
|
||||
MergeSplitAssets(path, true);
|
||||
var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories).ToList();
|
||||
var toReadFile = ProcessingSplitFiles(files);
|
||||
SetAssetFilter(classIDTypeList.ToArray());
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(params string[] path)
|
||||
{
|
||||
List<string> pathList = new List<string>();
|
||||
pathList.AddRange(path);
|
||||
LoadFilesAndFolders(out _, pathList);
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, params string[] path)
|
||||
{
|
||||
List<string> pathList = new List<string>();
|
||||
pathList.AddRange(path);
|
||||
LoadFilesAndFolders(out parentPath, pathList);
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
|
||||
{
|
||||
List<string> fileList = new List<string>();
|
||||
bool filesInPath = false;
|
||||
parentPath = "";
|
||||
foreach (var path in pathList)
|
||||
{
|
||||
var fullPath = Path.GetFullPath(path);
|
||||
if (Directory.Exists(fullPath))
|
||||
{
|
||||
var parent = Directory.GetParent(fullPath).FullName;
|
||||
if (!filesInPath && (parentPath == "" || parentPath.Length > parent.Length))
|
||||
{
|
||||
parentPath = parent;
|
||||
}
|
||||
MergeSplitAssets(fullPath, true);
|
||||
fileList.AddRange(Directory.GetFiles(fullPath, "*.*", SearchOption.AllDirectories));
|
||||
}
|
||||
else
|
||||
{
|
||||
parentPath = Path.GetDirectoryName(fullPath);
|
||||
fileList.Add(fullPath);
|
||||
filesInPath = true;
|
||||
}
|
||||
}
|
||||
if (filesInPath)
|
||||
{
|
||||
MergeSplitAssets(parentPath);
|
||||
}
|
||||
var toReadFile = ProcessingSplitFiles(fileList);
|
||||
fileList.Clear();
|
||||
pathList.Clear();
|
||||
|
||||
Load(toReadFile);
|
||||
}
|
||||
|
||||
@@ -53,6 +123,7 @@ namespace AssetStudio
|
||||
|
||||
importFiles.Clear();
|
||||
importFilesHash.Clear();
|
||||
noexistFiles.Clear();
|
||||
assetsFileListHash.Clear();
|
||||
|
||||
ReadAssets();
|
||||
@@ -84,6 +155,9 @@ namespace AssetStudio
|
||||
case FileType.BrotliFile:
|
||||
LoadFile(DecompressBrotli(reader));
|
||||
break;
|
||||
case FileType.ZipFile:
|
||||
LoadZipFile(reader);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +165,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (!assetsFileListHash.Contains(reader.FileName))
|
||||
{
|
||||
Logger.Info($"Loading {reader.FileName}");
|
||||
Logger.Info($"Loading {reader.FullPath}");
|
||||
try
|
||||
{
|
||||
var assetsFile = new SerializedFile(reader, this);
|
||||
@@ -106,31 +180,43 @@ namespace AssetStudio
|
||||
if (!importFilesHash.Contains(sharedFileName))
|
||||
{
|
||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
|
||||
if (!File.Exists(sharedFilePath))
|
||||
if (!noexistFiles.Contains(sharedFilePath))
|
||||
{
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
if (!File.Exists(sharedFilePath))
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
}
|
||||
}
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
noexistFiles.Add(sharedFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(sharedFilePath))
|
||||
{
|
||||
importFiles.Add(sharedFilePath);
|
||||
importFilesHash.Add(sharedFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
reader.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading assets file {reader.FileName}", e);
|
||||
Logger.Warning($"Error while reading assets file {reader.FullPath}\r\n{e}");
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"Skipping {reader.FullPath}");
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -143,7 +229,7 @@ namespace AssetStudio
|
||||
{
|
||||
var assetsFile = new SerializedFile(reader, this);
|
||||
assetsFile.originalPath = originalPath;
|
||||
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.kUnknown_7)
|
||||
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
|
||||
{
|
||||
assetsFile.SetVersion(unityVersion);
|
||||
}
|
||||
@@ -151,20 +237,27 @@ namespace AssetStudio
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
resourceFileReaders.Add(reader.FileName, reader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading assets file {reader.FileName} from {Path.GetFileName(originalPath)}", e);
|
||||
Logger.Warning($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}");
|
||||
resourceFileReaders.Add(reader.FileName, reader);
|
||||
}
|
||||
}
|
||||
else
|
||||
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
||||
}
|
||||
|
||||
private void LoadBundleFile(FileReader reader, string originalPath = null)
|
||||
{
|
||||
Logger.Info("Loading " + reader.FileName);
|
||||
Logger.Info("Loading " + reader.FullPath);
|
||||
try
|
||||
{
|
||||
var bundleFile = new BundleFile(reader);
|
||||
var bundleFile = new BundleFile(reader, SpecifyUnityVersion);
|
||||
foreach (var file in bundleFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
|
||||
@@ -179,14 +272,18 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var str = $"Error while reading bundle file {reader.FileName}";
|
||||
var str = $"Error while reading bundle file {reader.FullPath}";
|
||||
if (originalPath != null)
|
||||
{
|
||||
str += $" from {Path.GetFileName(originalPath)}";
|
||||
}
|
||||
Logger.Error(str, e);
|
||||
Logger.Warning($"{str}\r\n{e}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -196,7 +293,7 @@ namespace AssetStudio
|
||||
|
||||
private void LoadWebFile(FileReader reader)
|
||||
{
|
||||
Logger.Info("Loading " + reader.FileName);
|
||||
Logger.Info("Loading " + reader.FullPath);
|
||||
try
|
||||
{
|
||||
var webFile = new WebFile(reader);
|
||||
@@ -223,7 +320,111 @@ namespace AssetStudio
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading web file {reader.FileName}", e);
|
||||
Logger.Error($"Error while reading web file {reader.FullPath}", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadZipFile(FileReader reader)
|
||||
{
|
||||
Logger.Info("Reading " + reader.FileName);
|
||||
try
|
||||
{
|
||||
using (ZipArchive archive = new ZipArchive(reader.BaseStream, ZipArchiveMode.Read))
|
||||
{
|
||||
List<string> splitFiles = new List<string>();
|
||||
// register all files before parsing the assets so that the external references can be found
|
||||
// and find split files
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
if (entry.Name.Contains(".split"))
|
||||
{
|
||||
string baseName = Path.GetFileNameWithoutExtension(entry.Name);
|
||||
string basePath = Path.Combine(Path.GetDirectoryName(entry.FullName), baseName);
|
||||
if (!splitFiles.Contains(basePath))
|
||||
{
|
||||
splitFiles.Add(basePath);
|
||||
importFilesHash.Add(baseName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
importFilesHash.Add(entry.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// merge split files and load the result
|
||||
foreach (string basePath in splitFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream splitStream = new MemoryStream();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
string path = $"{basePath}.split{i++}";
|
||||
ZipArchiveEntry entry = archive.GetEntry(path);
|
||||
if (entry == null)
|
||||
break;
|
||||
using (Stream entryStream = entry.Open())
|
||||
{
|
||||
entryStream.CopyTo(splitStream);
|
||||
}
|
||||
}
|
||||
splitStream.Seek(0, SeekOrigin.Begin);
|
||||
FileReader entryReader = new FileReader(basePath, splitStream);
|
||||
LoadFile(entryReader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while reading zip split file {basePath}\r\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
// load all entries
|
||||
var progressCount = archive.Entries.Count;
|
||||
int k = 0;
|
||||
Progress.Reset();
|
||||
foreach (ZipArchiveEntry entry in archive.Entries)
|
||||
{
|
||||
try
|
||||
{
|
||||
string dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), reader.FileName, entry.FullName);
|
||||
// create a new stream
|
||||
// - to store the deflated stream in
|
||||
// - to keep the data for later extraction
|
||||
Stream streamReader = new MemoryStream();
|
||||
using (Stream entryStream = entry.Open())
|
||||
{
|
||||
entryStream.CopyTo(streamReader);
|
||||
}
|
||||
streamReader.Position = 0;
|
||||
|
||||
FileReader entryReader = new FileReader(dummyPath, streamReader);
|
||||
LoadFile(entryReader);
|
||||
if (entryReader.FileType == FileType.ResourceFile)
|
||||
{
|
||||
entryReader.Position = 0;
|
||||
if (!resourceFileReaders.ContainsKey(entry.Name))
|
||||
{
|
||||
resourceFileReaders.Add(entry.Name, entryReader);
|
||||
}
|
||||
}
|
||||
Progress.Report(++k, progressCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while reading zip entry {entry.FullName}\r\n{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error($"Error while reading zip file {reader.FileName}", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -235,7 +436,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
|
||||
{
|
||||
throw new Exception("The Unity version has been stripped, please set the version in the options");
|
||||
throw new NotSupportedException("The Unity version has been stripped, please set the version in the options");
|
||||
}
|
||||
if (!string.IsNullOrEmpty(SpecifyUnityVersion))
|
||||
{
|
||||
@@ -273,9 +474,13 @@ namespace AssetStudio
|
||||
foreach (var objectInfo in assetsFile.m_Objects)
|
||||
{
|
||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo);
|
||||
if (filteredAssetTypesList.Count > 0 && !filteredAssetTypesList.Contains(objectReader.type))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
Object obj;
|
||||
Object obj = null;
|
||||
switch (objectReader.type)
|
||||
{
|
||||
case ClassIDType.Animation:
|
||||
@@ -336,7 +541,8 @@ namespace AssetStudio
|
||||
obj = new RectTransform(objectReader);
|
||||
break;
|
||||
case ClassIDType.Shader:
|
||||
obj = new Shader(objectReader);
|
||||
if (objectReader.version[0] < 2021)
|
||||
obj = new Shader(objectReader);
|
||||
break;
|
||||
case ClassIDType.SkinnedMeshRenderer:
|
||||
obj = new SkinnedMeshRenderer(objectReader);
|
||||
@@ -366,17 +572,19 @@ namespace AssetStudio
|
||||
obj = new Object(objectReader);
|
||||
break;
|
||||
}
|
||||
assetsFile.AddObject(obj);
|
||||
if (obj != null)
|
||||
assetsFile.AddObject(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Unable to load object")
|
||||
.AppendLine($"Assets {assetsFile.fileName}")
|
||||
.AppendLine($"Path {assetsFile.originalPath}")
|
||||
.AppendLine($"Type {objectReader.type}")
|
||||
.AppendLine($"PathID {objectInfo.m_PathID}")
|
||||
.Append(e);
|
||||
Logger.Error(sb.ToString());
|
||||
Logger.Warning(sb.ToString());
|
||||
}
|
||||
|
||||
Progress.Report(++i, progressCount);
|
||||
@@ -386,7 +594,7 @@ namespace AssetStudio
|
||||
|
||||
private void ProcessAssets()
|
||||
{
|
||||
Logger.Info("Process Assets...");
|
||||
Logger.Info("Process assets...");
|
||||
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
{
|
||||
@@ -432,6 +640,14 @@ namespace AssetStudio
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
|
||||
if (m_SpriteAtlaOld.m_IsVariant)
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,4 +655,4 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
AssetStudio/BigArrayPool.cs
Normal file
10
AssetStudio/BigArrayPool.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Buffers;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class BigArrayPool<T>
|
||||
{
|
||||
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
|
||||
public static ArrayPool<T> Shared => s_shared;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,8 @@ namespace AssetStudio
|
||||
public enum BuildTarget
|
||||
{
|
||||
NoTarget = -2,
|
||||
DashboardWidget = 1,
|
||||
AnyPlayer = -1,
|
||||
ValidPlayer = 1,
|
||||
StandaloneOSX = 2,
|
||||
StandaloneOSXPPC = 3,
|
||||
StandaloneOSXIntel = 4,
|
||||
@@ -19,8 +20,10 @@ namespace AssetStudio
|
||||
iOS = 9,
|
||||
PS3,
|
||||
XBOX360,
|
||||
Broadcom = 12,
|
||||
Android = 13,
|
||||
StandaloneGLESEmu = 14,
|
||||
StandaloneGLES20Emu = 15,
|
||||
NaCl = 16,
|
||||
StandaloneLinux = 17,
|
||||
FlashPlayer = 18,
|
||||
@@ -48,6 +51,8 @@ namespace AssetStudio
|
||||
GameCoreXboxSeries,
|
||||
GameCoreXboxOne,
|
||||
PS5,
|
||||
EmbeddedLinux,
|
||||
QNX,
|
||||
UnknownPlatform = 9999
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using K4os.Compression.LZ4;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Lz4;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
[Flags]
|
||||
public enum ArchiveFlags
|
||||
{
|
||||
CompressionTypeMask = 0x3f,
|
||||
BlocksAndDirectoryInfoCombined = 0x40,
|
||||
BlocksInfoAtTheEnd = 0x80,
|
||||
OldWebPluginCompatibility = 0x100,
|
||||
BlockInfoNeedPaddingAtStart = 0x200
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum CnEncryptionFlags
|
||||
{
|
||||
OldFlag = 0x200,
|
||||
NewFlag = 0x400
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum StorageBlockFlags
|
||||
{
|
||||
CompressionTypeMask = 0x3f,
|
||||
Streamed = 0x40
|
||||
}
|
||||
|
||||
public enum CompressionType
|
||||
{
|
||||
None,
|
||||
Lzma,
|
||||
Lz4,
|
||||
Lz4HC,
|
||||
Lzham
|
||||
}
|
||||
|
||||
public class BundleFile
|
||||
{
|
||||
public class Header
|
||||
@@ -17,14 +49,14 @@ namespace AssetStudio
|
||||
public long size;
|
||||
public uint compressedBlocksInfoSize;
|
||||
public uint uncompressedBlocksInfoSize;
|
||||
public uint flags;
|
||||
public ArchiveFlags flags;
|
||||
}
|
||||
|
||||
public class StorageBlock
|
||||
{
|
||||
public uint compressedSize;
|
||||
public uint uncompressedSize;
|
||||
public ushort flags;
|
||||
public StorageBlockFlags flags;
|
||||
}
|
||||
|
||||
public class Node
|
||||
@@ -41,7 +73,7 @@ namespace AssetStudio
|
||||
|
||||
public StreamFile[] fileList;
|
||||
|
||||
public BundleFile(FileReader reader)
|
||||
public BundleFile(FileReader reader, string specUnityVer = "")
|
||||
{
|
||||
m_Header = new Header();
|
||||
m_Header.signature = reader.ReadStringToNull();
|
||||
@@ -67,7 +99,31 @@ namespace AssetStudio
|
||||
break;
|
||||
case "UnityFS":
|
||||
ReadHeader(reader);
|
||||
ReadBlocksInfoAndDirectory(reader);
|
||||
|
||||
bool isUnityCnEnc = false;
|
||||
string unityVer = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer;
|
||||
int[] ver = new string(unityVer.SkipWhile(x => !char.IsDigit(x)).TakeWhile(x => char.IsDigit(x) || x == '.').ToArray()).Split('.').Select(x => int.Parse(x)).ToArray();
|
||||
if (ver[0] != 0)
|
||||
{
|
||||
// https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch
|
||||
if (ver[0] < 2020 ||
|
||||
(ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) ||
|
||||
(ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) ||
|
||||
(ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1))
|
||||
{
|
||||
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0;
|
||||
}
|
||||
}
|
||||
if (isUnityCnEnc)
|
||||
{
|
||||
throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
|
||||
}
|
||||
|
||||
ReadBlocksInfoAndDirectory(reader, ver);
|
||||
using (var blocksStream = CreateBlocksStream(reader.FullPath))
|
||||
{
|
||||
ReadBlocks(reader, blocksStream);
|
||||
@@ -79,7 +135,6 @@ namespace AssetStudio
|
||||
|
||||
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||
{
|
||||
var isCompressed = m_Header.signature == "UnityWeb";
|
||||
if (m_Header.version >= 4)
|
||||
{
|
||||
var hash = reader.ReadBytes(16);
|
||||
@@ -96,7 +151,6 @@ namespace AssetStudio
|
||||
{
|
||||
compressedSize = reader.ReadUInt32(),
|
||||
uncompressedSize = reader.ReadUInt32(),
|
||||
flags = (ushort)(isCompressed ? 1 : 0)
|
||||
};
|
||||
if (i == levelCount - 1)
|
||||
{
|
||||
@@ -133,10 +187,11 @@ namespace AssetStudio
|
||||
|
||||
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
|
||||
{
|
||||
var isCompressed = m_Header.signature == "UnityWeb";
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
var uncompressedBytes = reader.ReadBytes((int)blockInfo.compressedSize);
|
||||
if (blockInfo.flags == 1)
|
||||
if (isCompressed)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream(uncompressedBytes))
|
||||
{
|
||||
@@ -196,59 +251,79 @@ namespace AssetStudio
|
||||
m_Header.size = reader.ReadInt64();
|
||||
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
|
||||
m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32();
|
||||
m_Header.flags = reader.ReadUInt32();
|
||||
m_Header.flags = (ArchiveFlags)reader.ReadUInt32();
|
||||
if (m_Header.signature != "UnityFS")
|
||||
{
|
||||
reader.ReadByte();
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader)
|
||||
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader, int[] unityVer)
|
||||
{
|
||||
byte[] blocksInfoBytes;
|
||||
|
||||
if (m_Header.version >= 7)
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
if ((m_Header.flags & 0x80) != 0) //kArchiveBlocksInfoAtTheEnd
|
||||
else if (unityVer[0] >= 2019 && unityVer[1] >= 4)
|
||||
{
|
||||
//check if we need to align the reader
|
||||
//- align to 16 bytes and check if all are 0
|
||||
//- if not, reset the reader to the previous position
|
||||
var preAlign = reader.Position;
|
||||
var alignData = reader.ReadBytes((16 - (int)(preAlign % 16)) % 16);
|
||||
if (alignData.Any(x => x != 0))
|
||||
{
|
||||
reader.Position = preAlign;
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0)
|
||||
{
|
||||
var position = reader.Position;
|
||||
reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize;
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
reader.Position = position;
|
||||
}
|
||||
else //0x40 kArchiveBlocksAndDirectoryInfoCombined
|
||||
else //0x40 BlocksAndDirectoryInfoCombined
|
||||
{
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
}
|
||||
var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes);
|
||||
MemoryStream blocksInfoUncompresseddStream;
|
||||
switch (m_Header.flags & 0x3F) //kArchiveCompressionTypeMask
|
||||
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
|
||||
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
default: //None
|
||||
case CompressionType.None:
|
||||
{
|
||||
blocksInfoUncompresseddStream = blocksInfoCompressedStream;
|
||||
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
case 1: //LZMA
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
blocksInfoUncompresseddStream = new MemoryStream((int)(m_Header.uncompressedBlocksInfoSize));
|
||||
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
|
||||
blocksInfoUncompresseddStream.Position = 0;
|
||||
blocksInfoCompressedStream.Close();
|
||||
break;
|
||||
}
|
||||
case 2: //LZ4
|
||||
case 3: //LZ4HC
|
||||
{
|
||||
var uncompressedBytes = new byte[m_Header.uncompressedBlocksInfoSize];
|
||||
using (var decoder = new Lz4DecoderStream(blocksInfoCompressedStream))
|
||||
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
|
||||
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
|
||||
{
|
||||
decoder.Read(uncompressedBytes, 0, uncompressedBytes.Length);
|
||||
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
|
||||
}
|
||||
blocksInfoUncompresseddStream.Position = 0;
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
{
|
||||
var uncompressedBytes = new byte[uncompressedSize];
|
||||
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksInfoUncompresseddStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
}
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
|
||||
{
|
||||
@@ -261,7 +336,7 @@ namespace AssetStudio
|
||||
{
|
||||
uncompressedSize = blocksInfoReader.ReadUInt32(),
|
||||
compressedSize = blocksInfoReader.ReadUInt32(),
|
||||
flags = blocksInfoReader.ReadUInt16()
|
||||
flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -278,34 +353,49 @@ namespace AssetStudio
|
||||
};
|
||||
}
|
||||
}
|
||||
if ((m_Header.flags & ArchiveFlags.BlockInfoNeedPaddingAtStart) != 0)
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
|
||||
{
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
switch (blockInfo.flags & 0x3F) //kStorageBlockCompressionTypeMask
|
||||
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
default: //None
|
||||
case CompressionType.None:
|
||||
{
|
||||
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case 1: //LZMA
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case 2: //LZ4
|
||||
case 3: //LZ4HC
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
{
|
||||
var compressedStream = new MemoryStream(reader.ReadBytes((int)blockInfo.compressedSize));
|
||||
using (var lz4Stream = new Lz4DecoderStream(compressedStream))
|
||||
var compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
lz4Stream.CopyTo(blocksStream, blockInfo.uncompressedSize);
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
}
|
||||
}
|
||||
blocksStream.Position = 0;
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace AssetStudio
|
||||
{
|
||||
public enum ClassIDType
|
||||
{
|
||||
AkPortraitSprite = -2,
|
||||
UnknownType = -1,
|
||||
Object = 0,
|
||||
GameObject = 1,
|
||||
|
||||
@@ -797,6 +797,7 @@ namespace AssetStudio
|
||||
public ClassIDType typeID;
|
||||
public byte customType;
|
||||
public byte isPPtrCurve;
|
||||
public byte isIntCurve;
|
||||
|
||||
public GenericBinding() { }
|
||||
|
||||
@@ -816,6 +817,10 @@ namespace AssetStudio
|
||||
}
|
||||
customType = reader.ReadByte();
|
||||
isPPtrCurve = reader.ReadByte();
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
{
|
||||
isIntCurve = reader.ReadByte();
|
||||
}
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
@@ -909,9 +914,9 @@ namespace AssetStudio
|
||||
|
||||
public enum AnimationType
|
||||
{
|
||||
kLegacy = 1,
|
||||
kGeneric = 2,
|
||||
kHumanoid = 3
|
||||
Legacy = 1,
|
||||
Generic = 2,
|
||||
Humanoid = 3
|
||||
};
|
||||
|
||||
public sealed class AnimationClip : NamedObject
|
||||
@@ -945,7 +950,7 @@ namespace AssetStudio
|
||||
else if (version[0] >= 4)//4.0 and up
|
||||
{
|
||||
m_AnimationType = (AnimationType)reader.ReadInt32();
|
||||
if (m_AnimationType == AnimationType.kLegacy)
|
||||
if (m_AnimationType == AnimationType.Legacy)
|
||||
m_Legacy = true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace AssetStudio
|
||||
public sealed class AudioClip : NamedObject
|
||||
{
|
||||
public int m_Format;
|
||||
public AudioType m_Type;
|
||||
public FMODSoundType m_Type;
|
||||
public bool m_3D;
|
||||
public bool m_UseHardware;
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AssetStudio
|
||||
if (version[0] < 5)
|
||||
{
|
||||
m_Format = reader.ReadInt32();
|
||||
m_Type = (AudioType)reader.ReadInt32();
|
||||
m_Type = (FMODSoundType)reader.ReadInt32();
|
||||
m_3D = reader.ReadBoolean();
|
||||
m_UseHardware = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
@@ -92,34 +92,51 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public enum AudioType
|
||||
public enum FMODSoundType
|
||||
{
|
||||
UNKNOWN,
|
||||
ACC,
|
||||
AIFF,
|
||||
UNKNOWN = 0,
|
||||
ACC = 1,
|
||||
AIFF = 2,
|
||||
ASF = 3,
|
||||
AT3 = 4,
|
||||
CDDA = 5,
|
||||
DLS = 6,
|
||||
FLAC = 7,
|
||||
FSB = 8,
|
||||
GCADPCM = 9,
|
||||
IT = 10,
|
||||
MIDI = 11,
|
||||
MOD = 12,
|
||||
MPEG,
|
||||
OGGVORBIS,
|
||||
MPEG = 13,
|
||||
OGGVORBIS = 14,
|
||||
PLAYLIST = 15,
|
||||
RAW = 16,
|
||||
S3M = 17,
|
||||
SF2 = 18,
|
||||
USER = 19,
|
||||
WAV = 20,
|
||||
XM,
|
||||
XMA,
|
||||
VAG,
|
||||
AUDIOQUEUE
|
||||
XM = 21,
|
||||
XMA = 22,
|
||||
VAG = 23,
|
||||
AUDIOQUEUE = 24,
|
||||
XWMA = 25,
|
||||
BCWAV = 26,
|
||||
AT9 = 27,
|
||||
VORBIS = 28,
|
||||
MEDIA_FOUNDATION = 29
|
||||
}
|
||||
|
||||
public enum AudioCompressionFormat
|
||||
{
|
||||
PCM,
|
||||
Vorbis,
|
||||
ADPCM,
|
||||
MP3,
|
||||
VAG,
|
||||
HEVAG,
|
||||
XMA,
|
||||
AAC,
|
||||
GCADPCM,
|
||||
ATRAC9
|
||||
PCM = 0,
|
||||
Vorbis = 1,
|
||||
ADPCM = 2,
|
||||
MP3 = 3,
|
||||
PSMVAG = 4,
|
||||
HEVAG = 5,
|
||||
XMA = 6,
|
||||
AAC = 7,
|
||||
GCADPCM = 8,
|
||||
ATRAC9 = 9
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,9 +74,18 @@ namespace AssetStudio
|
||||
var m_ShaderKeywords = reader.ReadStringArray();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up
|
||||
{
|
||||
var m_ValidKeywords = reader.ReadStringArray();
|
||||
var m_InvalidKeywords = reader.ReadStringArray();
|
||||
}
|
||||
else if (version[0] >= 5) //5.0 ~ 2021.2
|
||||
{
|
||||
var m_ShaderKeywords = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
var m_LightmapFlags = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
|
||||
@@ -396,14 +396,14 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public enum GfxPrimitiveType : int
|
||||
public enum GfxPrimitiveType
|
||||
{
|
||||
kPrimitiveTriangles = 0,
|
||||
kPrimitiveTriangleStrip = 1,
|
||||
kPrimitiveQuads = 2,
|
||||
kPrimitiveLines = 3,
|
||||
kPrimitiveLineStrip = 4,
|
||||
kPrimitivePoints = 5,
|
||||
Triangles = 0,
|
||||
TriangleStrip = 1,
|
||||
Quads = 2,
|
||||
Lines = 3,
|
||||
LineStrip = 4,
|
||||
Points = 5
|
||||
};
|
||||
|
||||
public class SubMesh
|
||||
@@ -651,6 +651,11 @@ namespace AssetStudio
|
||||
|
||||
int m_MeshUsageFlags = reader.ReadInt32();
|
||||
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
{
|
||||
int m_CookingOptions = reader.ReadInt32();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
|
||||
@@ -729,7 +734,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (reader.endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
|
||||
if (reader.Endian == EndianType.BigEndian && componentByteSize > 1) //swap bytes
|
||||
{
|
||||
for (var i = 0; i < componentBytes.Length / componentByteSize; i++)
|
||||
{
|
||||
@@ -1060,7 +1065,7 @@ namespace AssetStudio
|
||||
}
|
||||
var indexCount = m_SubMesh.indexCount;
|
||||
var topology = m_SubMesh.topology;
|
||||
if (topology == GfxPrimitiveType.kPrimitiveTriangles)
|
||||
if (topology == GfxPrimitiveType.Triangles)
|
||||
{
|
||||
for (int i = 0; i < indexCount; i += 3)
|
||||
{
|
||||
@@ -1069,7 +1074,7 @@ namespace AssetStudio
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
|
||||
}
|
||||
}
|
||||
else if (version[0] < 4 || topology == GfxPrimitiveType.kPrimitiveTriangleStrip)
|
||||
else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
|
||||
{
|
||||
// de-stripify :
|
||||
uint triIndex = 0;
|
||||
@@ -1100,7 +1105,7 @@ namespace AssetStudio
|
||||
//fix indexCount
|
||||
m_SubMesh.indexCount = triIndex;
|
||||
}
|
||||
else if (topology == GfxPrimitiveType.kPrimitiveQuads)
|
||||
else if (topology == GfxPrimitiveType.Quads)
|
||||
{
|
||||
for (int q = 0; q < indexCount; q += 4)
|
||||
{
|
||||
@@ -1193,44 +1198,44 @@ namespace AssetStudio
|
||||
{
|
||||
public enum VertexChannelFormat
|
||||
{
|
||||
kChannelFormatFloat,
|
||||
kChannelFormatFloat16,
|
||||
kChannelFormatColor,
|
||||
kChannelFormatByte,
|
||||
kChannelFormatUInt32
|
||||
Float,
|
||||
Float16,
|
||||
Color,
|
||||
Byte,
|
||||
UInt32
|
||||
}
|
||||
|
||||
public enum VertexFormat2017
|
||||
{
|
||||
kVertexFormatFloat,
|
||||
kVertexFormatFloat16,
|
||||
kVertexFormatColor,
|
||||
kVertexFormatUNorm8,
|
||||
kVertexFormatSNorm8,
|
||||
kVertexFormatUNorm16,
|
||||
kVertexFormatSNorm16,
|
||||
kVertexFormatUInt8,
|
||||
kVertexFormatSInt8,
|
||||
kVertexFormatUInt16,
|
||||
kVertexFormatSInt16,
|
||||
kVertexFormatUInt32,
|
||||
kVertexFormatSInt32
|
||||
Float,
|
||||
Float16,
|
||||
Color,
|
||||
UNorm8,
|
||||
SNorm8,
|
||||
UNorm16,
|
||||
SNorm16,
|
||||
UInt8,
|
||||
SInt8,
|
||||
UInt16,
|
||||
SInt16,
|
||||
UInt32,
|
||||
SInt32
|
||||
}
|
||||
|
||||
public enum VertexFormat
|
||||
{
|
||||
kVertexFormatFloat,
|
||||
kVertexFormatFloat16,
|
||||
kVertexFormatUNorm8,
|
||||
kVertexFormatSNorm8,
|
||||
kVertexFormatUNorm16,
|
||||
kVertexFormatSNorm16,
|
||||
kVertexFormatUInt8,
|
||||
kVertexFormatSInt8,
|
||||
kVertexFormatUInt16,
|
||||
kVertexFormatSInt16,
|
||||
kVertexFormatUInt32,
|
||||
kVertexFormatSInt32
|
||||
Float,
|
||||
Float16,
|
||||
UNorm8,
|
||||
SNorm8,
|
||||
UNorm16,
|
||||
SNorm16,
|
||||
UInt8,
|
||||
SInt8,
|
||||
UInt16,
|
||||
SInt16,
|
||||
UInt32,
|
||||
SInt32
|
||||
}
|
||||
|
||||
public static VertexFormat ToVertexFormat(int format, int[] version)
|
||||
@@ -1239,16 +1244,16 @@ namespace AssetStudio
|
||||
{
|
||||
switch ((VertexChannelFormat)format)
|
||||
{
|
||||
case VertexChannelFormat.kChannelFormatFloat:
|
||||
return VertexFormat.kVertexFormatFloat;
|
||||
case VertexChannelFormat.kChannelFormatFloat16:
|
||||
return VertexFormat.kVertexFormatFloat16;
|
||||
case VertexChannelFormat.kChannelFormatColor: //in 4.x is size 4
|
||||
return VertexFormat.kVertexFormatUNorm8;
|
||||
case VertexChannelFormat.kChannelFormatByte:
|
||||
return VertexFormat.kVertexFormatUInt8;
|
||||
case VertexChannelFormat.kChannelFormatUInt32: //in 5.x
|
||||
return VertexFormat.kVertexFormatUInt32;
|
||||
case VertexChannelFormat.Float:
|
||||
return VertexFormat.Float;
|
||||
case VertexChannelFormat.Float16:
|
||||
return VertexFormat.Float16;
|
||||
case VertexChannelFormat.Color: //in 4.x is size 4
|
||||
return VertexFormat.UNorm8;
|
||||
case VertexChannelFormat.Byte:
|
||||
return VertexFormat.UInt8;
|
||||
case VertexChannelFormat.UInt32: //in 5.x
|
||||
return VertexFormat.UInt32;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
@@ -1257,31 +1262,31 @@ namespace AssetStudio
|
||||
{
|
||||
switch ((VertexFormat2017)format)
|
||||
{
|
||||
case VertexFormat2017.kVertexFormatFloat:
|
||||
return VertexFormat.kVertexFormatFloat;
|
||||
case VertexFormat2017.kVertexFormatFloat16:
|
||||
return VertexFormat.kVertexFormatFloat16;
|
||||
case VertexFormat2017.kVertexFormatColor:
|
||||
case VertexFormat2017.kVertexFormatUNorm8:
|
||||
return VertexFormat.kVertexFormatUNorm8;
|
||||
case VertexFormat2017.kVertexFormatSNorm8:
|
||||
return VertexFormat.kVertexFormatSNorm8;
|
||||
case VertexFormat2017.kVertexFormatUNorm16:
|
||||
return VertexFormat.kVertexFormatUNorm16;
|
||||
case VertexFormat2017.kVertexFormatSNorm16:
|
||||
return VertexFormat.kVertexFormatSNorm16;
|
||||
case VertexFormat2017.kVertexFormatUInt8:
|
||||
return VertexFormat.kVertexFormatUInt8;
|
||||
case VertexFormat2017.kVertexFormatSInt8:
|
||||
return VertexFormat.kVertexFormatSInt8;
|
||||
case VertexFormat2017.kVertexFormatUInt16:
|
||||
return VertexFormat.kVertexFormatUInt16;
|
||||
case VertexFormat2017.kVertexFormatSInt16:
|
||||
return VertexFormat.kVertexFormatSInt16;
|
||||
case VertexFormat2017.kVertexFormatUInt32:
|
||||
return VertexFormat.kVertexFormatUInt32;
|
||||
case VertexFormat2017.kVertexFormatSInt32:
|
||||
return VertexFormat.kVertexFormatSInt32;
|
||||
case VertexFormat2017.Float:
|
||||
return VertexFormat.Float;
|
||||
case VertexFormat2017.Float16:
|
||||
return VertexFormat.Float16;
|
||||
case VertexFormat2017.Color:
|
||||
case VertexFormat2017.UNorm8:
|
||||
return VertexFormat.UNorm8;
|
||||
case VertexFormat2017.SNorm8:
|
||||
return VertexFormat.SNorm8;
|
||||
case VertexFormat2017.UNorm16:
|
||||
return VertexFormat.UNorm16;
|
||||
case VertexFormat2017.SNorm16:
|
||||
return VertexFormat.SNorm16;
|
||||
case VertexFormat2017.UInt8:
|
||||
return VertexFormat.UInt8;
|
||||
case VertexFormat2017.SInt8:
|
||||
return VertexFormat.SInt8;
|
||||
case VertexFormat2017.UInt16:
|
||||
return VertexFormat.UInt16;
|
||||
case VertexFormat2017.SInt16:
|
||||
return VertexFormat.SInt16;
|
||||
case VertexFormat2017.UInt32:
|
||||
return VertexFormat.UInt32;
|
||||
case VertexFormat2017.SInt32:
|
||||
return VertexFormat.SInt32;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
@@ -1297,20 +1302,20 @@ namespace AssetStudio
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.kVertexFormatFloat:
|
||||
case VertexFormat.kVertexFormatUInt32:
|
||||
case VertexFormat.kVertexFormatSInt32:
|
||||
case VertexFormat.Float:
|
||||
case VertexFormat.UInt32:
|
||||
case VertexFormat.SInt32:
|
||||
return 4u;
|
||||
case VertexFormat.kVertexFormatFloat16:
|
||||
case VertexFormat.kVertexFormatUNorm16:
|
||||
case VertexFormat.kVertexFormatSNorm16:
|
||||
case VertexFormat.kVertexFormatUInt16:
|
||||
case VertexFormat.kVertexFormatSInt16:
|
||||
case VertexFormat.Float16:
|
||||
case VertexFormat.UNorm16:
|
||||
case VertexFormat.SNorm16:
|
||||
case VertexFormat.UInt16:
|
||||
case VertexFormat.SInt16:
|
||||
return 2u;
|
||||
case VertexFormat.kVertexFormatUNorm8:
|
||||
case VertexFormat.kVertexFormatSNorm8:
|
||||
case VertexFormat.kVertexFormatUInt8:
|
||||
case VertexFormat.kVertexFormatSInt8:
|
||||
case VertexFormat.UNorm8:
|
||||
case VertexFormat.SNorm8:
|
||||
case VertexFormat.UInt8:
|
||||
case VertexFormat.SInt8:
|
||||
return 1u;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
@@ -1319,7 +1324,7 @@ namespace AssetStudio
|
||||
|
||||
public static bool IsIntFormat(VertexFormat format)
|
||||
{
|
||||
return format >= VertexFormat.kVertexFormatUInt8;
|
||||
return format >= VertexFormat.UInt8;
|
||||
}
|
||||
|
||||
public static float[] BytesToFloatArray(byte[] inputBytes, VertexFormat format)
|
||||
@@ -1331,22 +1336,22 @@ namespace AssetStudio
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.kVertexFormatFloat:
|
||||
case VertexFormat.Float:
|
||||
result[i] = BitConverter.ToSingle(inputBytes, i * 4);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatFloat16:
|
||||
case VertexFormat.Float16:
|
||||
result[i] = Half.ToHalf(inputBytes, i * 2);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUNorm8:
|
||||
case VertexFormat.UNorm8:
|
||||
result[i] = inputBytes[i] / 255f;
|
||||
break;
|
||||
case VertexFormat.kVertexFormatSNorm8:
|
||||
case VertexFormat.SNorm8:
|
||||
result[i] = Math.Max((sbyte)inputBytes[i] / 127f, -1f);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUNorm16:
|
||||
case VertexFormat.UNorm16:
|
||||
result[i] = BitConverter.ToUInt16(inputBytes, i * 2) / 65535f;
|
||||
break;
|
||||
case VertexFormat.kVertexFormatSNorm16:
|
||||
case VertexFormat.SNorm16:
|
||||
result[i] = Math.Max(BitConverter.ToInt16(inputBytes, i * 2) / 32767f, -1f);
|
||||
break;
|
||||
}
|
||||
@@ -1363,16 +1368,16 @@ namespace AssetStudio
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VertexFormat.kVertexFormatUInt8:
|
||||
case VertexFormat.kVertexFormatSInt8:
|
||||
case VertexFormat.UInt8:
|
||||
case VertexFormat.SInt8:
|
||||
result[i] = inputBytes[i];
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUInt16:
|
||||
case VertexFormat.kVertexFormatSInt16:
|
||||
case VertexFormat.UInt16:
|
||||
case VertexFormat.SInt16:
|
||||
result[i] = BitConverter.ToInt16(inputBytes, i * 2);
|
||||
break;
|
||||
case VertexFormat.kVertexFormatUInt32:
|
||||
case VertexFormat.kVertexFormatSInt32:
|
||||
case VertexFormat.UInt32:
|
||||
case VertexFormat.SInt32:
|
||||
result[i] = BitConverter.ToInt32(inputBytes, i * 4);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace AssetStudio
|
||||
public PPtr(ObjectReader reader)
|
||||
{
|
||||
m_FileID = reader.ReadInt32();
|
||||
m_PathID = reader.m_Version < SerializedFileFormatVersion.kUnknown_14 ? reader.ReadInt32() : reader.ReadInt64();
|
||||
m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
|
||||
assetsFile = reader.assetsFile;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,15 +56,14 @@ namespace AssetStudio
|
||||
}
|
||||
public enum TextureDimension
|
||||
{
|
||||
kTexDimUnknown = -1,
|
||||
kTexDimNone = 0,
|
||||
kTexDimAny = 1,
|
||||
kTexDim2D = 2,
|
||||
kTexDim3D = 3,
|
||||
kTexDimCUBE = 4,
|
||||
kTexDim2DArray = 5,
|
||||
kTexDimCubeArray = 6,
|
||||
kTexDimForce32Bit = 2147483647
|
||||
Unknown = -1,
|
||||
None = 0,
|
||||
Any = 1,
|
||||
Tex2D = 2,
|
||||
Tex3D = 3,
|
||||
Cube = 4,
|
||||
Tex2DArray = 5,
|
||||
CubeArray = 6
|
||||
};
|
||||
|
||||
public class SerializedTextureProperty
|
||||
@@ -81,11 +80,12 @@ namespace AssetStudio
|
||||
|
||||
public enum SerializedPropertyType
|
||||
{
|
||||
kColor = 0,
|
||||
kVector = 1,
|
||||
kFloat = 2,
|
||||
kRange = 3,
|
||||
kTexture = 4
|
||||
Color = 0,
|
||||
Vector = 1,
|
||||
Float = 2,
|
||||
Range = 3,
|
||||
Texture = 4,
|
||||
Int = 5
|
||||
};
|
||||
|
||||
public class SerializedProperty
|
||||
@@ -195,11 +195,11 @@ namespace AssetStudio
|
||||
|
||||
public enum FogMode
|
||||
{
|
||||
kFogUnknown = -1,
|
||||
kFogDisabled = 0,
|
||||
kFogLinear = 1,
|
||||
kFogExp = 2,
|
||||
kFogExp2 = 3
|
||||
Unknown = -1,
|
||||
Disabled = 0,
|
||||
Linear = 1,
|
||||
Exp = 2,
|
||||
Exp2 = 3
|
||||
};
|
||||
|
||||
public class SerializedShaderState
|
||||
@@ -428,6 +428,7 @@ namespace AssetStudio
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
{
|
||||
@@ -453,38 +454,39 @@ namespace AssetStudio
|
||||
|
||||
public enum ShaderGpuProgramType
|
||||
{
|
||||
kShaderGpuProgramUnknown = 0,
|
||||
kShaderGpuProgramGLLegacy = 1,
|
||||
kShaderGpuProgramGLES31AEP = 2,
|
||||
kShaderGpuProgramGLES31 = 3,
|
||||
kShaderGpuProgramGLES3 = 4,
|
||||
kShaderGpuProgramGLES = 5,
|
||||
kShaderGpuProgramGLCore32 = 6,
|
||||
kShaderGpuProgramGLCore41 = 7,
|
||||
kShaderGpuProgramGLCore43 = 8,
|
||||
kShaderGpuProgramDX9VertexSM20 = 9,
|
||||
kShaderGpuProgramDX9VertexSM30 = 10,
|
||||
kShaderGpuProgramDX9PixelSM20 = 11,
|
||||
kShaderGpuProgramDX9PixelSM30 = 12,
|
||||
kShaderGpuProgramDX10Level9Vertex = 13,
|
||||
kShaderGpuProgramDX10Level9Pixel = 14,
|
||||
kShaderGpuProgramDX11VertexSM40 = 15,
|
||||
kShaderGpuProgramDX11VertexSM50 = 16,
|
||||
kShaderGpuProgramDX11PixelSM40 = 17,
|
||||
kShaderGpuProgramDX11PixelSM50 = 18,
|
||||
kShaderGpuProgramDX11GeometrySM40 = 19,
|
||||
kShaderGpuProgramDX11GeometrySM50 = 20,
|
||||
kShaderGpuProgramDX11HullSM50 = 21,
|
||||
kShaderGpuProgramDX11DomainSM50 = 22,
|
||||
kShaderGpuProgramMetalVS = 23,
|
||||
kShaderGpuProgramMetalFS = 24,
|
||||
kShaderGpuProgramSPIRV = 25,
|
||||
kShaderGpuProgramConsoleVS = 26,
|
||||
kShaderGpuProgramConsoleFS = 27,
|
||||
kShaderGpuProgramConsoleHS = 28,
|
||||
kShaderGpuProgramConsoleDS = 29,
|
||||
kShaderGpuProgramConsoleGS = 30,
|
||||
kShaderGpuProgramRayTracing = 31,
|
||||
Unknown = 0,
|
||||
GLLegacy = 1,
|
||||
GLES31AEP = 2,
|
||||
GLES31 = 3,
|
||||
GLES3 = 4,
|
||||
GLES = 5,
|
||||
GLCore32 = 6,
|
||||
GLCore41 = 7,
|
||||
GLCore43 = 8,
|
||||
DX9VertexSM20 = 9,
|
||||
DX9VertexSM30 = 10,
|
||||
DX9PixelSM20 = 11,
|
||||
DX9PixelSM30 = 12,
|
||||
DX10Level9Vertex = 13,
|
||||
DX10Level9Pixel = 14,
|
||||
DX11VertexSM40 = 15,
|
||||
DX11VertexSM50 = 16,
|
||||
DX11PixelSM40 = 17,
|
||||
DX11PixelSM50 = 18,
|
||||
DX11GeometrySM40 = 19,
|
||||
DX11GeometrySM50 = 20,
|
||||
DX11HullSM50 = 21,
|
||||
DX11DomainSM50 = 22,
|
||||
MetalVS = 23,
|
||||
MetalFS = 24,
|
||||
SPIRV = 25,
|
||||
ConsoleVS = 26,
|
||||
ConsoleFS = 27,
|
||||
ConsoleHS = 28,
|
||||
ConsoleDS = 29,
|
||||
ConsoleGS = 30,
|
||||
RayTracing = 31,
|
||||
PS5NGGC = 32
|
||||
};
|
||||
|
||||
public class SerializedProgramParameters
|
||||
@@ -604,8 +606,9 @@ namespace AssetStudio
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||
{
|
||||
m_Parameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
@@ -689,6 +692,7 @@ namespace AssetStudio
|
||||
{
|
||||
public SerializedSubProgram[] m_SubPrograms;
|
||||
public SerializedProgramParameters m_CommonParameters;
|
||||
public ushort[] m_SerializedKeywordStateMask;
|
||||
|
||||
public SerializedProgram(ObjectReader reader)
|
||||
{
|
||||
@@ -703,19 +707,26 @@ namespace AssetStudio
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||
{
|
||||
m_CommonParameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
{
|
||||
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum PassType
|
||||
{
|
||||
kPassTypeNormal = 0,
|
||||
kPassTypeUse = 1,
|
||||
kPassTypeGrab = 2
|
||||
Normal = 0,
|
||||
Use = 1,
|
||||
Grab = 2
|
||||
};
|
||||
|
||||
public class SerializedPass
|
||||
@@ -794,7 +805,7 @@ namespace AssetStudio
|
||||
m_Name = reader.ReadAlignedString();
|
||||
m_TextureName = reader.ReadAlignedString();
|
||||
m_Tags = new SerializedTagMap(reader);
|
||||
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
|
||||
if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
|
||||
{
|
||||
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -922,32 +933,32 @@ namespace AssetStudio
|
||||
|
||||
public enum ShaderCompilerPlatform
|
||||
{
|
||||
kShaderCompPlatformNone = -1,
|
||||
kShaderCompPlatformGL = 0,
|
||||
kShaderCompPlatformD3D9 = 1,
|
||||
kShaderCompPlatformXbox360 = 2,
|
||||
kShaderCompPlatformPS3 = 3,
|
||||
kShaderCompPlatformD3D11 = 4,
|
||||
kShaderCompPlatformGLES20 = 5,
|
||||
kShaderCompPlatformNaCl = 6,
|
||||
kShaderCompPlatformFlash = 7,
|
||||
kShaderCompPlatformD3D11_9x = 8,
|
||||
kShaderCompPlatformGLES3Plus = 9,
|
||||
kShaderCompPlatformPSP2 = 10,
|
||||
kShaderCompPlatformPS4 = 11,
|
||||
kShaderCompPlatformXboxOne = 12,
|
||||
kShaderCompPlatformPSM = 13,
|
||||
kShaderCompPlatformMetal = 14,
|
||||
kShaderCompPlatformOpenGLCore = 15,
|
||||
kShaderCompPlatformN3DS = 16,
|
||||
kShaderCompPlatformWiiU = 17,
|
||||
kShaderCompPlatformVulkan = 18,
|
||||
kShaderCompPlatformSwitch = 19,
|
||||
kShaderCompPlatformXboxOneD3D12 = 20,
|
||||
kShaderCompPlatformGameCoreXboxOne = 21,
|
||||
kShaderCompPlatformGameCoreScarlett = 22,
|
||||
kShaderCompPlatformPS5 = 23,
|
||||
kShaderCompPlatformPS5NGGC = 24,
|
||||
None = -1,
|
||||
GL = 0,
|
||||
D3D9 = 1,
|
||||
Xbox360 = 2,
|
||||
PS3 = 3,
|
||||
D3D11 = 4,
|
||||
GLES20 = 5,
|
||||
NaCl = 6,
|
||||
Flash = 7,
|
||||
D3D11_9x = 8,
|
||||
GLES3Plus = 9,
|
||||
PSP2 = 10,
|
||||
PS4 = 11,
|
||||
XboxOne = 12,
|
||||
PSM = 13,
|
||||
Metal = 14,
|
||||
OpenGLCore = 15,
|
||||
N3DS = 16,
|
||||
WiiU = 17,
|
||||
Vulkan = 18,
|
||||
Switch = 19,
|
||||
XboxOneD3D12 = 20,
|
||||
GameCoreXboxOne = 21,
|
||||
GameCoreScarlett = 22,
|
||||
PS5 = 23,
|
||||
PS5NGGC = 24
|
||||
};
|
||||
|
||||
public class Shader : NamedObject
|
||||
@@ -959,9 +970,9 @@ namespace AssetStudio
|
||||
//5.5 and up
|
||||
public SerializedShader m_ParsedForm;
|
||||
public ShaderCompilerPlatform[] platforms;
|
||||
public uint[] offsets;
|
||||
public uint[] compressedLengths;
|
||||
public uint[] decompressedLengths;
|
||||
public uint[][] offsets;
|
||||
public uint[][] compressedLengths;
|
||||
public uint[][] decompressedLengths;
|
||||
public byte[] compressedBlob;
|
||||
|
||||
public Shader(ObjectReader reader) : base(reader)
|
||||
@@ -972,15 +983,15 @@ namespace AssetStudio
|
||||
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray();
|
||||
offsets = reader.ReadUInt32ArrayArray();
|
||||
compressedLengths = reader.ReadUInt32ArrayArray();
|
||||
decompressedLengths = reader.ReadUInt32ArrayArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
offsets = reader.ReadUInt32Array();
|
||||
compressedLengths = reader.ReadUInt32Array();
|
||||
decompressedLengths = reader.ReadUInt32Array();
|
||||
offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||
compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||
decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray();
|
||||
}
|
||||
compressedBlob = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
|
||||
@@ -18,23 +18,23 @@ namespace AssetStudio
|
||||
|
||||
public enum SpritePackingRotation
|
||||
{
|
||||
kSPRNone = 0,
|
||||
kSPRFlipHorizontal = 1,
|
||||
kSPRFlipVertical = 2,
|
||||
kSPRRotate180 = 3,
|
||||
kSPRRotate90 = 4
|
||||
None = 0,
|
||||
FlipHorizontal = 1,
|
||||
FlipVertical = 2,
|
||||
Rotate180 = 3,
|
||||
Rotate90 = 4
|
||||
};
|
||||
|
||||
public enum SpritePackingMode
|
||||
{
|
||||
kSPMTight = 0,
|
||||
kSPMRectangle
|
||||
Tight = 0,
|
||||
Rectangle
|
||||
};
|
||||
|
||||
public enum SpriteMeshType
|
||||
{
|
||||
kSpriteMeshTypeFullRect,
|
||||
kSpriteMeshTypeTight
|
||||
FullRect,
|
||||
Tight
|
||||
};
|
||||
|
||||
public class SpriteSettings
|
||||
@@ -182,6 +182,13 @@ namespace AssetStudio
|
||||
public float width;
|
||||
public float height;
|
||||
|
||||
public Rectf(float x, float y, float w, float h) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
|
||||
public Rectf(BinaryReader reader)
|
||||
{
|
||||
x = reader.ReadSingle();
|
||||
@@ -197,7 +204,7 @@ namespace AssetStudio
|
||||
public Vector2 m_Offset;
|
||||
public Vector4 m_Border;
|
||||
public float m_PixelsToUnits;
|
||||
public Vector2 m_Pivot;
|
||||
public Vector2 m_Pivot = new Vector2(0.5f, 0.5f);
|
||||
public uint m_Extrude;
|
||||
public bool m_IsPolygon;
|
||||
public KeyValuePair<Guid, long> m_RenderDataKey;
|
||||
@@ -205,6 +212,7 @@ namespace AssetStudio
|
||||
public PPtr<SpriteAtlas> m_SpriteAtlas;
|
||||
public SpriteRenderData m_RD;
|
||||
public Vector2[][] m_PhysicsShape;
|
||||
public bool akSplitAlpha;
|
||||
|
||||
public Sprite(ObjectReader reader) : base(reader)
|
||||
{
|
||||
@@ -254,6 +262,8 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
akSplitAlpha = false;
|
||||
|
||||
//vector m_Bones 2018 and up
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ namespace AssetStudio
|
||||
{
|
||||
public PPtr<Sprite>[] m_PackedSprites;
|
||||
public Dictionary<KeyValuePair<Guid, long>, SpriteAtlasData> m_RenderDataMap;
|
||||
public bool m_IsVariant;
|
||||
|
||||
public SpriteAtlas(ObjectReader reader) : base(reader)
|
||||
{
|
||||
@@ -67,8 +68,9 @@ namespace AssetStudio
|
||||
var value = new SpriteAtlasData(reader);
|
||||
m_RenderDataMap.Add(new KeyValuePair<Guid, long>(first, second), value);
|
||||
}
|
||||
//string m_Tag
|
||||
//bool m_IsVariant
|
||||
var m_Tag = reader.ReadAlignedString();
|
||||
m_IsVariant = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,14 @@ namespace AssetStudio
|
||||
}
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
{
|
||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
|
||||
{
|
||||
var m_IgnoreMipmapLimit = reader.ReadBoolean();
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
if (version[0] >= 3) //3.0.0 - 5.4
|
||||
{
|
||||
@@ -100,6 +107,11 @@ namespace AssetStudio
|
||||
var m_ReadAllowed = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
|
||||
{
|
||||
var m_MipmapLimitGroupName = reader.ReadAlignedString();
|
||||
reader.AlignStream();
|
||||
}
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
{
|
||||
var m_StreamingMipmaps = reader.ReadBoolean();
|
||||
@@ -151,10 +163,13 @@ namespace AssetStudio
|
||||
RGB24,
|
||||
RGBA32,
|
||||
ARGB32,
|
||||
RGB565 = 7,
|
||||
R16 = 9,
|
||||
ARGBFloat,
|
||||
RGB565,
|
||||
BGR24,
|
||||
R16,
|
||||
DXT1,
|
||||
DXT5 = 12,
|
||||
DXT3,
|
||||
DXT5,
|
||||
RGBA4444,
|
||||
BGRA32,
|
||||
RHalf,
|
||||
@@ -165,11 +180,12 @@ namespace AssetStudio
|
||||
RGBAFloat,
|
||||
YUY2,
|
||||
RGB9e5Float,
|
||||
BC4 = 26,
|
||||
BC5,
|
||||
BC6H = 24,
|
||||
RGBFloat,
|
||||
BC6H,
|
||||
BC7,
|
||||
DXT1Crunched = 28,
|
||||
BC4,
|
||||
BC5,
|
||||
DXT1Crunched,
|
||||
DXT5Crunched,
|
||||
PVRTC_RGB2,
|
||||
PVRTC_RGBA2,
|
||||
|
||||
@@ -21,22 +21,27 @@ namespace AssetStudio
|
||||
public ResourceReader m_VideoData;
|
||||
public string m_OriginalPath;
|
||||
public StreamedResource m_ExternalResources;
|
||||
public uint Width;
|
||||
public uint Height;
|
||||
public double m_FrameRate;
|
||||
public int m_Format;
|
||||
public bool m_HasSplitAlpha;
|
||||
|
||||
public VideoClip(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_OriginalPath = reader.ReadAlignedString();
|
||||
var m_ProxyWidth = reader.ReadUInt32();
|
||||
var m_ProxyHeight = reader.ReadUInt32();
|
||||
var Width = reader.ReadUInt32();
|
||||
var Height = reader.ReadUInt32();
|
||||
Width = reader.ReadUInt32();
|
||||
Height = reader.ReadUInt32();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
{
|
||||
var m_PixelAspecRatioNum = reader.ReadUInt32();
|
||||
var m_PixelAspecRatioDen = reader.ReadUInt32();
|
||||
}
|
||||
var m_FrameRate = reader.ReadDouble();
|
||||
m_FrameRate = reader.ReadDouble();
|
||||
var m_FrameCount = reader.ReadUInt64();
|
||||
var m_Format = reader.ReadInt32();
|
||||
m_Format = reader.ReadInt32();
|
||||
var m_AudioChannelCount = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
var m_AudioSampleRate = reader.ReadUInt32Array();
|
||||
@@ -51,7 +56,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
m_ExternalResources = new StreamedResource(reader);
|
||||
var m_HasSplitAlpha = reader.ReadBoolean();
|
||||
m_HasSplitAlpha = reader.ReadBoolean();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_sRGB = reader.ReadBoolean();
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum EndianType
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
|
||||
public class EndianBinaryReader : BinaryReader
|
||||
{
|
||||
public EndianType endian;
|
||||
private readonly byte[] buffer;
|
||||
|
||||
public EndianType Endian;
|
||||
|
||||
public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream)
|
||||
{
|
||||
this.endian = endian;
|
||||
Endian = endian;
|
||||
buffer = new byte[8];
|
||||
}
|
||||
|
||||
public long Position
|
||||
@@ -28,88 +24,82 @@ namespace AssetStudio
|
||||
|
||||
public override short ReadInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt16(buff, 0);
|
||||
Read(buffer, 0, 2);
|
||||
return BinaryPrimitives.ReadInt16BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt16();
|
||||
}
|
||||
|
||||
public override int ReadInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt32(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
return BinaryPrimitives.ReadInt32BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt32();
|
||||
}
|
||||
|
||||
public override long ReadInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
return BinaryPrimitives.ReadInt64BigEndian(buffer);
|
||||
}
|
||||
return base.ReadInt64();
|
||||
}
|
||||
|
||||
public override ushort ReadUInt16()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(2);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt16(buff, 0);
|
||||
Read(buffer, 0, 2);
|
||||
return BinaryPrimitives.ReadUInt16BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt16();
|
||||
}
|
||||
|
||||
public override uint ReadUInt32()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt32(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
return BinaryPrimitives.ReadUInt32BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt32();
|
||||
}
|
||||
|
||||
public override ulong ReadUInt64()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
return BinaryPrimitives.ReadUInt64BigEndian(buffer);
|
||||
}
|
||||
return base.ReadUInt64();
|
||||
}
|
||||
|
||||
public override float ReadSingle()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(4);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToSingle(buff, 0);
|
||||
Read(buffer, 0, 4);
|
||||
Array.Reverse(buffer, 0, 4);
|
||||
return BitConverter.ToSingle(buffer, 0);
|
||||
}
|
||||
return base.ReadSingle();
|
||||
}
|
||||
|
||||
public override double ReadDouble()
|
||||
{
|
||||
if (endian == EndianType.BigEndian)
|
||||
if (Endian == EndianType.BigEndian)
|
||||
{
|
||||
var buff = ReadBytes(8);
|
||||
Array.Reverse(buff);
|
||||
return BitConverter.ToUInt64(buff, 0);
|
||||
Read(buffer, 0, 8);
|
||||
Array.Reverse(buffer);
|
||||
return BitConverter.ToDouble(buffer, 0);
|
||||
}
|
||||
return base.ReadDouble();
|
||||
}
|
||||
|
||||
14
AssetStudio/EndianType.cs
Normal file
14
AssetStudio/EndianType.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum EndianType
|
||||
{
|
||||
LittleEndian,
|
||||
BigEndian
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ namespace AssetStudio
|
||||
|
||||
private static readonly byte[] gzipMagic = { 0x1f, 0x8b };
|
||||
private static readonly byte[] brotliMagic = { 0x62, 0x72, 0x6F, 0x74, 0x6C, 0x69 };
|
||||
private static readonly byte[] zipMagic = { 0x50, 0x4B, 0x03, 0x04 };
|
||||
private static readonly byte[] zipSpannedMagic = { 0x50, 0x4B, 0x07, 0x08 };
|
||||
|
||||
public FileReader(string path) : this(path, File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { }
|
||||
|
||||
@@ -36,7 +38,7 @@ namespace AssetStudio
|
||||
return FileType.WebFile;
|
||||
default:
|
||||
{
|
||||
var magic = ReadBytes(2);
|
||||
byte[] magic = ReadBytes(2);
|
||||
Position = 0;
|
||||
if (gzipMagic.SequenceEqual(magic))
|
||||
{
|
||||
@@ -53,10 +55,11 @@ namespace AssetStudio
|
||||
{
|
||||
return FileType.AssetsFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FileType.ResourceFile;
|
||||
}
|
||||
magic = ReadBytes(4);
|
||||
Position = 0;
|
||||
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
|
||||
return FileType.ZipFile;
|
||||
return FileType.ResourceFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace AssetStudio
|
||||
WebFile,
|
||||
ResourceFile,
|
||||
GZipFile,
|
||||
BrotliFile
|
||||
BrotliFile,
|
||||
ZipFile
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,28 @@ namespace AssetStudio
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImportedFrame FindRelativeFrameWithPath(string path)
|
||||
{
|
||||
var subs = path.Split(new[] { '/' }, 2);
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (child.Name == subs[0])
|
||||
{
|
||||
if (subs.Length == 1)
|
||||
{
|
||||
return child;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = child.FindRelativeFrameWithPath(subs[1]);
|
||||
if (result != null)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ImportedFrame FindFrame(string name)
|
||||
{
|
||||
if (Name == name)
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace AssetStudio
|
||||
|
||||
public interface ILogger
|
||||
{
|
||||
void Log(LoggerEvent loggerEvent, string message);
|
||||
void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel = false);
|
||||
}
|
||||
|
||||
public sealed class DummyLogger : ILogger
|
||||
{
|
||||
public void Log(LoggerEvent loggerEvent, string message) { }
|
||||
public void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public interface IProgress
|
||||
{
|
||||
void Report(int value);
|
||||
}
|
||||
|
||||
public sealed class DummyProgress : IProgress
|
||||
{
|
||||
public void Report(int value) { }
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ namespace AssetStudio
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine(message);
|
||||
sb.AppendLine();
|
||||
sb.AppendLine(e.ToString());
|
||||
Default.Log(LoggerEvent.Error, sb.ToString());
|
||||
}
|
||||
|
||||
@@ -1,540 +0,0 @@
|
||||
#define CHECK_ARGS
|
||||
#define CHECK_EOF
|
||||
//#define LOCAL_SHADOW
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Lz4
|
||||
{
|
||||
public class Lz4DecoderStream : Stream
|
||||
{
|
||||
public Lz4DecoderStream(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
Reset(input, inputLength);
|
||||
}
|
||||
|
||||
private void Reset(Stream input, long inputLength = long.MaxValue)
|
||||
{
|
||||
this.inputLength = inputLength;
|
||||
this.input = input;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
|
||||
decodeBufferPos = 0;
|
||||
|
||||
litLen = 0;
|
||||
matLen = 0;
|
||||
matDst = 0;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (disposing && input != null)
|
||||
{
|
||||
input.Close();
|
||||
}
|
||||
input = null;
|
||||
decodeBuffer = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
|
||||
private long inputLength;
|
||||
private Stream input;
|
||||
|
||||
//because we might not be able to match back across invocations,
|
||||
//we have to keep the last window's worth of bytes around for reuse
|
||||
//we use a circular buffer for this - every time we write into this
|
||||
//buffer, we also write the same into our output buffer
|
||||
|
||||
private const int DecBufLen = 0x10000;
|
||||
private const int DecBufMask = 0xFFFF;
|
||||
|
||||
private const int InBufLen = 128;
|
||||
|
||||
private byte[] decodeBuffer = new byte[DecBufLen + InBufLen];
|
||||
private int decodeBufferPos, inBufPos, inBufEnd;
|
||||
|
||||
//we keep track of which phase we're in so that we can jump right back
|
||||
//into the correct part of decoding
|
||||
|
||||
private DecodePhase phase;
|
||||
|
||||
private enum DecodePhase
|
||||
{
|
||||
ReadToken,
|
||||
ReadExLiteralLength,
|
||||
CopyLiteral,
|
||||
ReadOffset,
|
||||
ReadExMatchLength,
|
||||
CopyMatch,
|
||||
}
|
||||
|
||||
//state within interruptable phases and across phase boundaries is
|
||||
//kept here - again, so that we can punt out and restart freely
|
||||
|
||||
private int litLen, matLen, matDst;
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
#if CHECK_ARGS
|
||||
if (buffer == null)
|
||||
throw new ArgumentNullException("buffer");
|
||||
if (offset < 0 || count < 0 || buffer.Length - count < offset)
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
if (input == null)
|
||||
throw new InvalidOperationException();
|
||||
#endif
|
||||
int nRead, nToRead = count;
|
||||
|
||||
var decBuf = decodeBuffer;
|
||||
|
||||
//the stringy gotos are obnoxious, but their purpose is to
|
||||
//make it *blindingly* obvious how the state machine transitions
|
||||
//back and forth as it reads - remember, we can yield out of
|
||||
//this routine in several places, and we must be able to re-enter
|
||||
//and pick up where we left off!
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
var phase = this.phase;
|
||||
var inBufPos = this.inBufPos;
|
||||
var inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
switch (phase)
|
||||
{
|
||||
case DecodePhase.ReadToken:
|
||||
goto readToken;
|
||||
|
||||
case DecodePhase.ReadExLiteralLength:
|
||||
goto readExLiteralLength;
|
||||
|
||||
case DecodePhase.CopyLiteral:
|
||||
goto copyLiteral;
|
||||
|
||||
case DecodePhase.ReadOffset:
|
||||
goto readOffset;
|
||||
|
||||
case DecodePhase.ReadExMatchLength:
|
||||
goto readExMatchLength;
|
||||
|
||||
case DecodePhase.CopyMatch:
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readToken:
|
||||
int tok;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
tok = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
|
||||
tok = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (tok == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen = tok >> 4;
|
||||
matLen = (tok & 0xF) + 4;
|
||||
|
||||
switch (litLen)
|
||||
{
|
||||
case 0:
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
case 0xF:
|
||||
phase = DecodePhase.ReadExLiteralLength;
|
||||
goto readExLiteralLength;
|
||||
|
||||
default:
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
readExLiteralLength:
|
||||
int exLitLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exLitLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exLitLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
|
||||
#if CHECK_EOF
|
||||
if (exLitLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
litLen += exLitLen;
|
||||
if (exLitLen == 255)
|
||||
goto readExLiteralLength;
|
||||
|
||||
phase = DecodePhase.CopyLiteral;
|
||||
goto copyLiteral;
|
||||
|
||||
copyLiteral:
|
||||
int nReadLit = litLen < nToRead ? litLen : nToRead;
|
||||
if (nReadLit != 0)
|
||||
{
|
||||
if (inBufPos + nReadLit <= inBufEnd)
|
||||
{
|
||||
int ofs = offset;
|
||||
|
||||
for (int c = nReadLit; c-- != 0;)
|
||||
buffer[ofs++] = decBuf[inBufPos++];
|
||||
|
||||
nRead = nReadLit;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
nRead = ReadCore(buffer, offset, nReadLit);
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
offset += nRead;
|
||||
nToRead -= nRead;
|
||||
|
||||
litLen -= nRead;
|
||||
|
||||
if (litLen != 0)
|
||||
goto copyLiteral;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadOffset;
|
||||
goto readOffset;
|
||||
|
||||
readOffset:
|
||||
if (inBufPos + 1 < inBufEnd)
|
||||
{
|
||||
matDst = (decBuf[inBufPos + 1] << 8) | decBuf[inBufPos];
|
||||
inBufPos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
matDst = ReadOffsetCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (matDst == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (matLen == 15 + 4)
|
||||
{
|
||||
phase = DecodePhase.ReadExMatchLength;
|
||||
goto readExMatchLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
}
|
||||
|
||||
readExMatchLength:
|
||||
int exMatLen;
|
||||
if (inBufPos < inBufEnd)
|
||||
{
|
||||
exMatLen = decBuf[inBufPos++];
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOCAL_SHADOW
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
exMatLen = ReadByteCore();
|
||||
#if LOCAL_SHADOW
|
||||
inBufPos = this.inBufPos;
|
||||
inBufEnd = this.inBufEnd;
|
||||
#endif
|
||||
#if CHECK_EOF
|
||||
if (exMatLen == -1)
|
||||
goto finish;
|
||||
#endif
|
||||
}
|
||||
|
||||
matLen += exMatLen;
|
||||
if (exMatLen == 255)
|
||||
goto readExMatchLength;
|
||||
|
||||
phase = DecodePhase.CopyMatch;
|
||||
goto copyMatch;
|
||||
|
||||
copyMatch:
|
||||
int nCpyMat = matLen < nToRead ? matLen : nToRead;
|
||||
if (nCpyMat != 0)
|
||||
{
|
||||
nRead = count - nToRead;
|
||||
|
||||
int bufDst = matDst - nRead;
|
||||
if (bufDst > 0)
|
||||
{
|
||||
//offset is fairly far back, we need to pull from the buffer
|
||||
|
||||
int bufSrc = decodeBufferPos - bufDst;
|
||||
if (bufSrc < 0)
|
||||
bufSrc += DecBufLen;
|
||||
int bufCnt = bufDst < nCpyMat ? bufDst : nCpyMat;
|
||||
|
||||
for (int c = bufCnt; c-- != 0;)
|
||||
buffer[offset++] = decBuf[bufSrc++ & DecBufMask];
|
||||
}
|
||||
else
|
||||
{
|
||||
bufDst = 0;
|
||||
}
|
||||
|
||||
int sOfs = offset - matDst;
|
||||
for (int i = bufDst; i < nCpyMat; i++)
|
||||
buffer[offset++] = buffer[sOfs++];
|
||||
|
||||
nToRead -= nCpyMat;
|
||||
matLen -= nCpyMat;
|
||||
}
|
||||
|
||||
if (nToRead == 0)
|
||||
goto finish;
|
||||
|
||||
phase = DecodePhase.ReadToken;
|
||||
goto readToken;
|
||||
|
||||
finish:
|
||||
nRead = count - nToRead;
|
||||
|
||||
int nToBuf = nRead < DecBufLen ? nRead : DecBufLen;
|
||||
int repPos = offset - nToBuf;
|
||||
|
||||
if (nToBuf == DecBufLen)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, repPos, decBuf, 0, DecBufLen);
|
||||
decodeBufferPos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int decPos = decodeBufferPos;
|
||||
|
||||
while (nToBuf-- != 0)
|
||||
decBuf[decPos++ & DecBufMask] = buffer[repPos++];
|
||||
|
||||
decodeBufferPos = decPos & DecBufMask;
|
||||
}
|
||||
|
||||
#if LOCAL_SHADOW
|
||||
this.phase = phase;
|
||||
this.inBufPos = inBufPos;
|
||||
#endif
|
||||
return nRead;
|
||||
}
|
||||
|
||||
private int ReadByteCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
return buf[inBufPos++];
|
||||
}
|
||||
|
||||
private int ReadOffsetCore()
|
||||
{
|
||||
var buf = decodeBuffer;
|
||||
|
||||
if (inBufPos == inBufEnd)
|
||||
{
|
||||
int nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
}
|
||||
|
||||
if (inBufEnd - inBufPos == 1)
|
||||
{
|
||||
buf[DecBufLen] = buf[inBufPos];
|
||||
|
||||
int nRead = input.Read(buf, DecBufLen + 1,
|
||||
InBufLen - 1 < inputLength ? InBufLen - 1 : (int)inputLength);
|
||||
|
||||
#if CHECK_EOF
|
||||
if (nRead == 0)
|
||||
{
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
inputLength -= nRead;
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead + 1;
|
||||
}
|
||||
|
||||
int ret = (buf[inBufPos + 1] << 8) | buf[inBufPos];
|
||||
inBufPos += 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private int ReadCore(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int nToRead = count;
|
||||
|
||||
var buf = decodeBuffer;
|
||||
int inBufLen = inBufEnd - inBufPos;
|
||||
|
||||
int fromBuf = nToRead < inBufLen ? nToRead : inBufLen;
|
||||
if (fromBuf != 0)
|
||||
{
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
if (nToRead != 0)
|
||||
{
|
||||
int nRead;
|
||||
|
||||
if (nToRead >= InBufLen)
|
||||
{
|
||||
nRead = input.Read(buffer, offset,
|
||||
nToRead < inputLength ? nToRead : (int)inputLength);
|
||||
nToRead -= nRead;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRead = input.Read(buf, DecBufLen,
|
||||
InBufLen < inputLength ? InBufLen : (int)inputLength);
|
||||
|
||||
inBufPos = DecBufLen;
|
||||
inBufEnd = DecBufLen + nRead;
|
||||
|
||||
fromBuf = nToRead < nRead ? nToRead : nRead;
|
||||
|
||||
var bufPos = inBufPos;
|
||||
|
||||
for (int c = fromBuf; c-- != 0;)
|
||||
buffer[offset++] = buf[bufPos++];
|
||||
|
||||
inBufPos = bufPos;
|
||||
nToRead -= fromBuf;
|
||||
}
|
||||
|
||||
inputLength -= nRead;
|
||||
}
|
||||
|
||||
return count - nToRead;
|
||||
}
|
||||
|
||||
#region Stream internals
|
||||
|
||||
public override bool CanRead => true;
|
||||
|
||||
public override bool CanSeek => false;
|
||||
|
||||
public override bool CanWrite => false;
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override long Length => throw new NotSupportedException();
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
set => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace AssetStudio
|
||||
public int[] version => assetsFile.version;
|
||||
public BuildType buildType => assetsFile.buildType;
|
||||
|
||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.endian)
|
||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
|
||||
{
|
||||
this.assetsFile = assetsFile;
|
||||
m_PathID = objectInfo.m_PathID;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
namespace AssetStudio
|
||||
using System;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static class Progress
|
||||
{
|
||||
public static IProgress Default = new DummyProgress();
|
||||
public static IProgress<int> Default = new Progress<int>();
|
||||
private static int preValue;
|
||||
|
||||
public static void Reset()
|
||||
|
||||
@@ -11,6 +11,8 @@ namespace AssetStudio
|
||||
private long size;
|
||||
private BinaryReader reader;
|
||||
|
||||
public int Size { get => (int)size; }
|
||||
|
||||
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
|
||||
{
|
||||
needSearch = true;
|
||||
@@ -69,6 +71,13 @@ namespace AssetStudio
|
||||
return binaryReader.ReadBytes((int)size);
|
||||
}
|
||||
|
||||
public void GetData(byte[] buff)
|
||||
{
|
||||
var binaryReader = GetReader();
|
||||
binaryReader.BaseStream.Position = offset;
|
||||
binaryReader.Read(buff, 0, (int)size);
|
||||
}
|
||||
|
||||
public void WriteData(string path)
|
||||
{
|
||||
var binaryReader = GetReader();
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace AssetStudio
|
||||
header.m_Version = (SerializedFileFormatVersion)reader.ReadUInt32();
|
||||
header.m_DataOffset = reader.ReadUInt32();
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_9)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_9)
|
||||
{
|
||||
header.m_Endianess = reader.ReadByte();
|
||||
header.m_Reserved = reader.ReadBytes(3);
|
||||
@@ -57,7 +57,7 @@ namespace AssetStudio
|
||||
m_FileEndianess = reader.ReadByte();
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
|
||||
{
|
||||
header.m_MetadataSize = reader.ReadUInt32();
|
||||
header.m_FileSize = reader.ReadInt64();
|
||||
@@ -68,14 +68,14 @@ namespace AssetStudio
|
||||
// ReadMetadata
|
||||
if (m_FileEndianess == 0)
|
||||
{
|
||||
reader.endian = EndianType.LittleEndian;
|
||||
reader.Endian = EndianType.LittleEndian;
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
|
||||
{
|
||||
unityVersion = reader.ReadStringToNull();
|
||||
SetVersion(unityVersion);
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_8)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
|
||||
{
|
||||
m_TargetPlatform = (BuildTarget)reader.ReadInt32();
|
||||
if (!Enum.IsDefined(typeof(BuildTarget), m_TargetPlatform))
|
||||
@@ -83,7 +83,7 @@ namespace AssetStudio
|
||||
m_TargetPlatform = BuildTarget.UnknownPlatform;
|
||||
}
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
|
||||
{
|
||||
m_EnableTypeTree = reader.ReadBoolean();
|
||||
}
|
||||
@@ -96,7 +96,7 @@ namespace AssetStudio
|
||||
m_Types.Add(ReadSerializedType(false));
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_7 && header.m_Version < SerializedFileFormatVersion.kUnknown_14)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7 && header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||
{
|
||||
bigIDEnabled = reader.ReadInt32();
|
||||
}
|
||||
@@ -113,7 +113,7 @@ namespace AssetStudio
|
||||
{
|
||||
objectInfo.m_PathID = reader.ReadInt64();
|
||||
}
|
||||
else if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
|
||||
else if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||
{
|
||||
objectInfo.m_PathID = reader.ReadInt32();
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace AssetStudio
|
||||
objectInfo.m_PathID = reader.ReadInt64();
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kLargeFilesSupport)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.LargeFilesSupport)
|
||||
objectInfo.byteStart = reader.ReadInt64();
|
||||
else
|
||||
objectInfo.byteStart = reader.ReadUInt32();
|
||||
@@ -131,7 +131,7 @@ namespace AssetStudio
|
||||
objectInfo.byteStart += header.m_DataOffset;
|
||||
objectInfo.byteSize = reader.ReadUInt32();
|
||||
objectInfo.typeID = reader.ReadInt32();
|
||||
if (header.m_Version < SerializedFileFormatVersion.kRefactoredClassId)
|
||||
if (header.m_Version < SerializedFileFormatVersion.RefactoredClassId)
|
||||
{
|
||||
objectInfo.classID = reader.ReadUInt16();
|
||||
objectInfo.serializedType = m_Types.Find(x => x.classID == objectInfo.typeID);
|
||||
@@ -142,24 +142,24 @@ namespace AssetStudio
|
||||
objectInfo.serializedType = type;
|
||||
objectInfo.classID = type.classID;
|
||||
}
|
||||
if (header.m_Version < SerializedFileFormatVersion.kHasScriptTypeIndex)
|
||||
if (header.m_Version < SerializedFileFormatVersion.HasScriptTypeIndex)
|
||||
{
|
||||
objectInfo.isDestroyed = reader.ReadUInt16();
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.kRefactorTypeData)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex && header.m_Version < SerializedFileFormatVersion.RefactorTypeData)
|
||||
{
|
||||
var m_ScriptTypeIndex = reader.ReadInt16();
|
||||
if (objectInfo.serializedType != null)
|
||||
objectInfo.serializedType.m_ScriptTypeIndex = m_ScriptTypeIndex;
|
||||
}
|
||||
if (header.m_Version == SerializedFileFormatVersion.kSupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.kRefactoredClassId)
|
||||
if (header.m_Version == SerializedFileFormatVersion.SupportsStrippedObject || header.m_Version == SerializedFileFormatVersion.RefactoredClassId)
|
||||
{
|
||||
objectInfo.stripped = reader.ReadByte();
|
||||
}
|
||||
m_Objects.Add(objectInfo);
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kHasScriptTypeIndex)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.HasScriptTypeIndex)
|
||||
{
|
||||
int scriptCount = reader.ReadInt32();
|
||||
m_ScriptTypes = new List<LocalSerializedObjectIdentifier>(scriptCount);
|
||||
@@ -167,7 +167,7 @@ namespace AssetStudio
|
||||
{
|
||||
var m_ScriptType = new LocalSerializedObjectIdentifier();
|
||||
m_ScriptType.localSerializedFileIndex = reader.ReadInt32();
|
||||
if (header.m_Version < SerializedFileFormatVersion.kUnknown_14)
|
||||
if (header.m_Version < SerializedFileFormatVersion.Unknown_14)
|
||||
{
|
||||
m_ScriptType.localIdentifierInFile = reader.ReadInt32();
|
||||
}
|
||||
@@ -185,11 +185,11 @@ namespace AssetStudio
|
||||
for (int i = 0; i < externalsCount; i++)
|
||||
{
|
||||
var m_External = new FileIdentifier();
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_6)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_6)
|
||||
{
|
||||
var tempEmpty = reader.ReadStringToNull();
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
|
||||
{
|
||||
m_External.guid = new Guid(reader.ReadBytes(16));
|
||||
m_External.type = reader.ReadInt32();
|
||||
@@ -199,7 +199,7 @@ namespace AssetStudio
|
||||
m_Externals.Add(m_External);
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kSupportsRefObject)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.SupportsRefObject)
|
||||
{
|
||||
int refTypesCount = reader.ReadInt32();
|
||||
m_RefTypes = new List<SerializedType>(refTypesCount);
|
||||
@@ -209,7 +209,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_5)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_5)
|
||||
{
|
||||
userInformation = reader.ReadStringToNull();
|
||||
}
|
||||
@@ -223,6 +223,10 @@ namespace AssetStudio
|
||||
{
|
||||
unityVersion = stringVersion;
|
||||
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (buildSplit.Length == 0)
|
||||
throw new NotSupportedException("Specified Unity version is not in a correct format.\n" +
|
||||
"Specify full Unity version, including letters at the end.\n" +
|
||||
"Example: 2017.4.39f1");
|
||||
buildType = new BuildType(buildSplit[0]);
|
||||
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
version = versionSplit.Select(int.Parse).ToArray();
|
||||
@@ -235,23 +239,23 @@ namespace AssetStudio
|
||||
|
||||
type.classID = reader.ReadInt32();
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId)
|
||||
{
|
||||
type.m_IsStrippedType = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kRefactorTypeData)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.RefactorTypeData)
|
||||
{
|
||||
type.m_ScriptTypeIndex = reader.ReadInt16();
|
||||
}
|
||||
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kHasTypeTreeHashes)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.HasTypeTreeHashes)
|
||||
{
|
||||
if (isRefType && type.m_ScriptTypeIndex >= 0)
|
||||
{
|
||||
type.m_ScriptID = reader.ReadBytes(16);
|
||||
}
|
||||
else if ((header.m_Version < SerializedFileFormatVersion.kRefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.kRefactoredClassId && type.classID == 114))
|
||||
else if ((header.m_Version < SerializedFileFormatVersion.RefactoredClassId && type.classID < 0) || (header.m_Version >= SerializedFileFormatVersion.RefactoredClassId && type.classID == 114))
|
||||
{
|
||||
type.m_ScriptID = reader.ReadBytes(16);
|
||||
}
|
||||
@@ -262,7 +266,7 @@ namespace AssetStudio
|
||||
{
|
||||
type.m_Type = new TypeTree();
|
||||
type.m_Type.m_Nodes = new List<TypeTreeNode>();
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kUnknown_12 || header.m_Version == SerializedFileFormatVersion.kUnknown_10)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_12 || header.m_Version == SerializedFileFormatVersion.Unknown_10)
|
||||
{
|
||||
TypeTreeBlobRead(type.m_Type);
|
||||
}
|
||||
@@ -270,7 +274,7 @@ namespace AssetStudio
|
||||
{
|
||||
ReadTypeTree(type.m_Type);
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kStoresTypeDependencies)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.StoresTypeDependencies)
|
||||
{
|
||||
if (isRefType)
|
||||
{
|
||||
@@ -296,17 +300,17 @@ namespace AssetStudio
|
||||
typeTreeNode.m_Type = reader.ReadStringToNull();
|
||||
typeTreeNode.m_Name = reader.ReadStringToNull();
|
||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||
if (header.m_Version == SerializedFileFormatVersion.kUnknown_2)
|
||||
if (header.m_Version == SerializedFileFormatVersion.Unknown_2)
|
||||
{
|
||||
var variableCount = reader.ReadInt32();
|
||||
}
|
||||
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
|
||||
if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
|
||||
{
|
||||
typeTreeNode.m_Index = reader.ReadInt32();
|
||||
}
|
||||
typeTreeNode.m_TypeFlags = reader.ReadInt32();
|
||||
typeTreeNode.m_Version = reader.ReadInt32();
|
||||
if (header.m_Version != SerializedFileFormatVersion.kUnknown_3)
|
||||
if (header.m_Version != SerializedFileFormatVersion.Unknown_3)
|
||||
{
|
||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||
}
|
||||
@@ -334,7 +338,7 @@ namespace AssetStudio
|
||||
typeTreeNode.m_ByteSize = reader.ReadInt32();
|
||||
typeTreeNode.m_Index = reader.ReadInt32();
|
||||
typeTreeNode.m_MetaFlag = reader.ReadInt32();
|
||||
if (header.m_Version >= SerializedFileFormatVersion.kTypeTreeNodeWithTypeFlags)
|
||||
if (header.m_Version >= SerializedFileFormatVersion.TypeTreeNodeWithTypeFlags)
|
||||
{
|
||||
typeTreeNode.m_RefTypeHash = reader.ReadUInt64();
|
||||
}
|
||||
|
||||
@@ -8,80 +8,80 @@ namespace AssetStudio
|
||||
{
|
||||
public enum SerializedFileFormatVersion
|
||||
{
|
||||
kUnsupported = 1,
|
||||
kUnknown_2 = 2,
|
||||
kUnknown_3 = 3,
|
||||
Unsupported = 1,
|
||||
Unknown_2 = 2,
|
||||
Unknown_3 = 3,
|
||||
/// <summary>
|
||||
/// 1.2.0 to 2.0.0
|
||||
/// </summary>
|
||||
kUnknown_5 = 5,
|
||||
Unknown_5 = 5,
|
||||
/// <summary>
|
||||
/// 2.1.0 to 2.6.1
|
||||
/// </summary>
|
||||
kUnknown_6 = 6,
|
||||
Unknown_6 = 6,
|
||||
/// <summary>
|
||||
/// 3.0.0b
|
||||
/// </summary>
|
||||
kUnknown_7 = 7,
|
||||
Unknown_7 = 7,
|
||||
/// <summary>
|
||||
/// 3.0.0 to 3.4.2
|
||||
/// </summary>
|
||||
kUnknown_8 = 8,
|
||||
Unknown_8 = 8,
|
||||
/// <summary>
|
||||
/// 3.5.0 to 4.7.2
|
||||
/// </summary>
|
||||
kUnknown_9 = 9,
|
||||
Unknown_9 = 9,
|
||||
/// <summary>
|
||||
/// 5.0.0aunk1
|
||||
/// </summary>
|
||||
kUnknown_10 = 10,
|
||||
Unknown_10 = 10,
|
||||
/// <summary>
|
||||
/// 5.0.0aunk2
|
||||
/// </summary>
|
||||
kHasScriptTypeIndex = 11,
|
||||
HasScriptTypeIndex = 11,
|
||||
/// <summary>
|
||||
/// 5.0.0aunk3
|
||||
/// </summary>
|
||||
kUnknown_12 = 12,
|
||||
Unknown_12 = 12,
|
||||
/// <summary>
|
||||
/// 5.0.0aunk4
|
||||
/// </summary>
|
||||
kHasTypeTreeHashes = 13,
|
||||
HasTypeTreeHashes = 13,
|
||||
/// <summary>
|
||||
/// 5.0.0unk
|
||||
/// </summary>
|
||||
kUnknown_14 = 14,
|
||||
Unknown_14 = 14,
|
||||
/// <summary>
|
||||
/// 5.0.1 to 5.4.0
|
||||
/// </summary>
|
||||
kSupportsStrippedObject = 15,
|
||||
SupportsStrippedObject = 15,
|
||||
/// <summary>
|
||||
/// 5.5.0a
|
||||
/// </summary>
|
||||
kRefactoredClassId = 16,
|
||||
RefactoredClassId = 16,
|
||||
/// <summary>
|
||||
/// 5.5.0unk to 2018.4
|
||||
/// </summary>
|
||||
kRefactorTypeData = 17,
|
||||
RefactorTypeData = 17,
|
||||
/// <summary>
|
||||
/// 2019.1a
|
||||
/// </summary>
|
||||
kRefactorShareableTypeTreeData = 18,
|
||||
RefactorShareableTypeTreeData = 18,
|
||||
/// <summary>
|
||||
/// 2019.1unk
|
||||
/// </summary>
|
||||
kTypeTreeNodeWithTypeFlags = 19,
|
||||
TypeTreeNodeWithTypeFlags = 19,
|
||||
/// <summary>
|
||||
/// 2019.2
|
||||
/// </summary>
|
||||
kSupportsRefObject = 20,
|
||||
SupportsRefObject = 20,
|
||||
/// <summary>
|
||||
/// 2019.3 to 2019.4
|
||||
/// </summary>
|
||||
kStoresTypeDependencies = 21,
|
||||
StoresTypeDependencies = 21,
|
||||
/// <summary>
|
||||
/// 2020.1 to x
|
||||
/// </summary>
|
||||
kLargeFilesSupport = 22
|
||||
LargeFilesSupport = 22
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -39,9 +40,11 @@ namespace AssetStudio
|
||||
value = reader.ReadSByte();
|
||||
break;
|
||||
case "UInt8":
|
||||
case "char":
|
||||
value = reader.ReadByte();
|
||||
break;
|
||||
case "char":
|
||||
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
|
||||
break;
|
||||
case "short":
|
||||
case "SInt16":
|
||||
value = reader.ReadInt16();
|
||||
@@ -81,7 +84,8 @@ namespace AssetStudio
|
||||
append = false;
|
||||
var str = reader.ReadAlignedString();
|
||||
sb.AppendFormat("{0}{1} {2} = \"{3}\"\r\n", (new string('\t', level)), varTypeStr, varNameStr, str);
|
||||
i += 3;
|
||||
var toSkip = GetNodes(m_Nodes, i);
|
||||
i += toSkip.Count - 1;
|
||||
break;
|
||||
case "map":
|
||||
{
|
||||
@@ -190,9 +194,11 @@ namespace AssetStudio
|
||||
value = reader.ReadSByte();
|
||||
break;
|
||||
case "UInt8":
|
||||
case "char":
|
||||
value = reader.ReadByte();
|
||||
break;
|
||||
case "char":
|
||||
value = BitConverter.ToChar(reader.ReadBytes(2), 0);
|
||||
break;
|
||||
case "short":
|
||||
case "SInt16":
|
||||
value = reader.ReadInt16();
|
||||
@@ -230,7 +236,8 @@ namespace AssetStudio
|
||||
break;
|
||||
case "string":
|
||||
value = reader.ReadAlignedString();
|
||||
i += 3;
|
||||
var toSkip = GetNodes(m_Nodes, i);
|
||||
i += toSkip.Count - 1;
|
||||
break;
|
||||
case "map":
|
||||
{
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace AssetStudio
|
||||
|
||||
public WebFile(EndianBinaryReader reader)
|
||||
{
|
||||
reader.endian = EndianType.LittleEndian;
|
||||
reader.Endian = EndianType.LittleEndian;
|
||||
var signature = reader.ReadStringToNull();
|
||||
var headLength = reader.ReadInt32();
|
||||
var dataList = new List<WebData>();
|
||||
|
||||
114
AssetStudioCLI/AssetStudioCLI.csproj
Normal file
114
AssetStudioCLI/AssetStudioCLI.csproj
Normal file
@@ -0,0 +1,114 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||
<AssemblyTitle>ArknightsStudio by aelurum</AssemblyTitle>
|
||||
<AssemblyName>ArknightsStudioCLI</AssemblyName>
|
||||
<Version>1.0.0</Version>
|
||||
<Copyright>Copyright © Perfare; Copyright © aelurum 2023</Copyright>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</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 windows extra files for $(TargetFramework)... " Importance="high" />
|
||||
<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="$(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 other platforms extra files for $(TargetFramework)... " Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-arm64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||
<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>
|
||||
|
||||
<!-- 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.
|
||||
The dll is cross-platform while the executable isn't -->
|
||||
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||
<Message Text="Publishing windows extra files for Portable build ($(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-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 Name="PublishExtraFilesPortableNet" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||
<Message Text="Publishing other platforms extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-arm64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||
<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)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<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)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<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)\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>
|
||||
|
||||
<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\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<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)\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\libfmod.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyExtraFilesMac" AfterTargets="AfterBuild" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\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)\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\libfmod.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
118
AssetStudioCLI/CLILogger.cs
Normal file
118
AssetStudioCLI/CLILogger.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
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()
|
||||
{
|
||||
logOutput = CLIOptions.o_logOutput.Value;
|
||||
logMinLevel = CLIOptions.o_logLevel.Value;
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
||||
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
|
||||
LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" +
|
||||
$"CMD Args: {string.Join(" ", CLIOptions.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, bool ignoreLevel)
|
||||
{
|
||||
if ((logMsgLevel < logMinLevel && !ignoreLevel) || string.IsNullOrEmpty(message))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (logOutput != LogOutputMode.File)
|
||||
{
|
||||
LogToConsole(logMsgLevel, message);
|
||||
}
|
||||
if (logOutput != LogOutputMode.Console)
|
||||
{
|
||||
LogToFile(logMsgLevel, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
211
AssetStudioCLI/Components/Arknights/AkSpriteHelper.cs
Normal file
211
AssetStudioCLI/Components/Arknights/AkSpriteHelper.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using Arknights.PortraitSpriteMono;
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI;
|
||||
using AssetStudioCLI.Options;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal static class AkSpriteHelper
|
||||
{
|
||||
public static Texture2D TryFindAlphaTex(AssetItem assetItem, AvgSprite avgSprite, bool isAvgSprite)
|
||||
{
|
||||
Sprite m_Sprite = (Sprite)assetItem.Asset;
|
||||
var imgType = "arts/characters";
|
||||
if (m_Sprite.m_RD.alphaTexture.m_PathID == 0)
|
||||
{
|
||||
if (isAvgSprite)
|
||||
{
|
||||
if (avgSprite?.FullAlphaTexture != null)
|
||||
return avgSprite.FullAlphaTexture;
|
||||
|
||||
imgType = "avg/characters"; //since the avg hub was not found for some reason, let's try to find alpha tex by name
|
||||
}
|
||||
var spriteFullName = Path.GetFileNameWithoutExtension(assetItem.Container);
|
||||
foreach (var item in Studio.loadedAssetsList)
|
||||
{
|
||||
if (item.Type == ClassIDType.Texture2D)
|
||||
{
|
||||
if (item.Container.Contains(imgType) && item.Container.Contains($"illust_{m_Sprite.m_Name}_material") && item.Text.Contains("[alpha]"))
|
||||
return (Texture2D)item.Asset;
|
||||
else if (item.Container.Contains(imgType) && item.Container.Contains(spriteFullName) && item.Text == $"{m_Sprite.m_Name}[alpha]")
|
||||
return (Texture2D)item.Asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Image<Bgra32> AkGetImage(this Sprite m_Sprite, AvgSprite avgSprite = null, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On)
|
||||
{
|
||||
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off)
|
||||
{
|
||||
Image<Bgra32> tex;
|
||||
Image<Bgra32> alphaTex;
|
||||
|
||||
if (avgSprite != null && avgSprite.IsHubParsed)
|
||||
{
|
||||
alphaTex = m_AlphaTexture2D.ConvertToImage(true);
|
||||
if (avgSprite.IsFaceSprite)
|
||||
{
|
||||
var faceImage = m_Texture2D.ConvertToImage(true);
|
||||
var faceAlpha = avgSprite.FaceSpriteAlphaTexture.ConvertToImage(true);
|
||||
if (faceImage.Size() != avgSprite.FaceSize)
|
||||
{
|
||||
faceImage.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
|
||||
faceAlpha.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
|
||||
}
|
||||
tex = avgSprite.FullTexture.ConvertToImage(true);
|
||||
tex.Mutate(x => x.DrawImage(faceImage, location: avgSprite.FacePos, opacity: 1f));
|
||||
alphaTex.Mutate(x => x.DrawImage(faceAlpha, location: avgSprite.FacePos, opacity: 1f));
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = m_Texture2D.ConvertToImage(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
alphaTex = CutImage(m_AlphaTexture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
}
|
||||
tex.ApplyRGBMask(alphaTex);
|
||||
return tex;
|
||||
}
|
||||
else if (m_Sprite.m_RD.texture.TryGet(out m_Texture2D))
|
||||
{
|
||||
return CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Image<Bgra32> AkGetImage(this PortraitSprite portraitSprite, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On)
|
||||
{
|
||||
if (portraitSprite.Texture != null && portraitSprite.AlphaTexture != null)
|
||||
{
|
||||
var tex = CutImage(portraitSprite.Texture.ConvertToImage(false), portraitSprite.TextureRect, portraitSprite.DownscaleMultiplier, portraitSprite.Rotate);
|
||||
|
||||
if (spriteMaskMode == SpriteMaskMode.Off)
|
||||
{
|
||||
return tex;
|
||||
}
|
||||
else
|
||||
{
|
||||
var alphaTex = CutImage(portraitSprite.AlphaTexture.ConvertToImage(false), portraitSprite.TextureRect, portraitSprite.DownscaleMultiplier, portraitSprite.Rotate);
|
||||
tex.ApplyRGBMask(alphaTex);
|
||||
return tex;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<PortraitSprite> GeneratePortraits(AssetItem asset)
|
||||
{
|
||||
var portraits = new List<PortraitSprite>();
|
||||
|
||||
var portraitsDict = ((MonoBehaviour)asset.Asset).ToType();
|
||||
if (portraitsDict == null)
|
||||
{
|
||||
Logger.Warning("Portraits MonoBehaviour is not readable.");
|
||||
return portraits;
|
||||
}
|
||||
var portraitsJson = JsonConvert.SerializeObject(portraitsDict);
|
||||
var portraitsData = JsonConvert.DeserializeObject<PortraitSpriteConfig>(portraitsJson);
|
||||
|
||||
var atlasTex = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == portraitsData._atlas.Texture.m_PathID).Asset;
|
||||
var atlasAlpha = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == portraitsData._atlas.Alpha.m_PathID).Asset;
|
||||
|
||||
foreach (var portraitData in portraitsData._sprites)
|
||||
{
|
||||
var portraitSprite = new PortraitSprite()
|
||||
{
|
||||
Name = portraitData.Name,
|
||||
AssetsFile = atlasTex.assetsFile,
|
||||
Container = asset.Container,
|
||||
Texture = atlasTex,
|
||||
AlphaTexture = atlasAlpha,
|
||||
TextureRect = new Rectf(portraitData.Rect.X, portraitData.Rect.Y, portraitData.Rect.W, portraitData.Rect.H),
|
||||
Rotate = portraitData.Rotate,
|
||||
};
|
||||
portraits.Add(portraitSprite);
|
||||
}
|
||||
|
||||
return portraits;
|
||||
}
|
||||
|
||||
private static void ApplyRGBMask(this Image<Bgra32> tex, Image<Bgra32> texMask)
|
||||
{
|
||||
using (texMask)
|
||||
{
|
||||
bool resized = false;
|
||||
if (tex.Width != texMask.Width || tex.Height != texMask.Height)
|
||||
{
|
||||
texMask.Mutate(x => x.Resize(tex.Width, tex.Height, CLIOptions.o_akAlphaTexResampler.Value));
|
||||
resized = true;
|
||||
}
|
||||
|
||||
var invGamma = 1.0 / (1.0 + CLIOptions.o_akShadowGamma.Value / 10.0);
|
||||
if (CLIOptions.akResizedOnly && !resized)
|
||||
{
|
||||
invGamma = 1.0;
|
||||
}
|
||||
|
||||
tex.ProcessPixelRows(texMask, (sourceTex, targetTexMask) =>
|
||||
{
|
||||
for (int y = 0; y < texMask.Height; y++)
|
||||
{
|
||||
var texRow = sourceTex.GetRowSpan(y);
|
||||
var maskRow = targetTexMask.GetRowSpan(y);
|
||||
for (int x = 0; x < maskRow.Length; x++)
|
||||
{
|
||||
var grayscale = (maskRow[x].R + maskRow[x].G + maskRow[x].B) / 3.0;
|
||||
if (invGamma != 1.0)
|
||||
{
|
||||
grayscale = 255 - Math.Pow((255 - grayscale) / 255, invGamma) * 255;
|
||||
}
|
||||
texRow[x].A = (byte)grayscale;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static Image<Bgra32> CutImage(Image<Bgra32> originalImage, Rectf textureRect, float downscaleMultiplier, bool rotate = false)
|
||||
{
|
||||
if (originalImage != null)
|
||||
{
|
||||
if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
|
||||
{
|
||||
var newSize = (Size)(originalImage.Size() / downscaleMultiplier);
|
||||
originalImage.Mutate(x => x.Resize(newSize, KnownResamplers.Lanczos3, compand: true));
|
||||
}
|
||||
var rectX = (int)Math.Floor(textureRect.x);
|
||||
var rectY = (int)Math.Floor(textureRect.y);
|
||||
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
|
||||
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
|
||||
rectRight = Math.Min(rectRight, originalImage.Width);
|
||||
rectBottom = Math.Min(rectBottom, originalImage.Height);
|
||||
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
|
||||
var spriteImage = originalImage.Clone(x => x.Crop(rect));
|
||||
originalImage.Dispose();
|
||||
if (rotate)
|
||||
{
|
||||
spriteImage.Mutate(x => x.Rotate(RotateMode.Rotate270));
|
||||
}
|
||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||
|
||||
return spriteImage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
AssetStudioCLI/Components/Arknights/AvgSprite.cs
Normal file
125
AssetStudioCLI/Components/Arknights/AvgSprite.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using Arknights.AvgCharHubMono;
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal class AvgSprite
|
||||
{
|
||||
public Texture2D FaceSpriteAlphaTexture { get; }
|
||||
public Texture2D FullTexture { get; }
|
||||
public Texture2D FullAlphaTexture { get; }
|
||||
public Point FacePos { get; }
|
||||
public Size FaceSize { get; }
|
||||
public string Alias { get; }
|
||||
public bool IsWholeBodySprite { get; }
|
||||
public bool IsFaceSprite { get; }
|
||||
public bool IsHubParsed { get; }
|
||||
|
||||
private AvgSpriteConfig GetCurSpriteGroup(AvgSpriteConfigGroup spriteHubDataGrouped, long spriteItemID, string spriteName)
|
||||
{
|
||||
if (spriteHubDataGrouped.SpriteGroups.Length > 1)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(spriteName))
|
||||
{
|
||||
var groupFromName = int.TryParse(spriteName?.Substring(spriteName.IndexOf('$') + 1, 1), out int groupIndex);
|
||||
if (groupFromName)
|
||||
{
|
||||
return spriteHubDataGrouped.SpriteGroups[groupIndex - 1];
|
||||
}
|
||||
}
|
||||
return spriteHubDataGrouped.SpriteGroups.FirstOrDefault(x => x.Sprites.Any(y => y.Sprite.m_PathID == spriteItemID));
|
||||
}
|
||||
else
|
||||
{
|
||||
return spriteHubDataGrouped.SpriteGroups[0];
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetSpriteHub(AssetItem assetItem, out AvgSpriteConfig spriteHubData)
|
||||
{
|
||||
spriteHubData = null;
|
||||
var avgSpriteHubItem = Studio.loadedAssetsList.Find(x =>
|
||||
x.Type == ClassIDType.MonoBehaviour
|
||||
&& x.Container == assetItem.Container
|
||||
&& x.Text.IndexOf("AVGCharacterSpriteHub", StringComparison.OrdinalIgnoreCase) >= 0
|
||||
);
|
||||
if (avgSpriteHubItem == null)
|
||||
{
|
||||
Logger.Warning("AVGCharacterSpriteHub was not found.");
|
||||
return false;
|
||||
}
|
||||
var spriteHubDict = ((MonoBehaviour)avgSpriteHubItem.Asset).ToType();
|
||||
if (spriteHubDict == null)
|
||||
{
|
||||
Logger.Warning("AVGCharacterSpriteHub is not readable.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict);
|
||||
if (avgSpriteHubItem.Text.ToLower().Contains("hubgroup"))
|
||||
{
|
||||
var groupedSpriteHub = JsonConvert.DeserializeObject<AvgSpriteConfigGroup>(spriteHubJson);
|
||||
spriteHubData = GetCurSpriteGroup(groupedSpriteHub, assetItem.m_PathID, assetItem.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteHubData = JsonConvert.DeserializeObject<AvgSpriteConfig>(spriteHubJson);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public AvgSprite(AssetItem assetItem)
|
||||
{
|
||||
if (TryGetSpriteHub(assetItem, out var spriteHubData))
|
||||
{
|
||||
IsHubParsed = spriteHubData?.Sprites.Length > 0;
|
||||
}
|
||||
if (IsHubParsed)
|
||||
{
|
||||
var curSpriteData = spriteHubData.Sprites.FirstOrDefault(x => x.Sprite.m_PathID == assetItem.m_PathID);
|
||||
|
||||
if (curSpriteData == null)
|
||||
{
|
||||
Logger.Warning($"Sprite \"{assetItem.Text}\" was not found in the avg sprite hub");
|
||||
return;
|
||||
}
|
||||
|
||||
Alias = curSpriteData.Alias;
|
||||
IsWholeBodySprite = curSpriteData.IsWholeBody;
|
||||
|
||||
if (spriteHubData.FaceSize.X > 0 && spriteHubData.FaceSize.Y > 0)
|
||||
{
|
||||
var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture
|
||||
if (IsWholeBodySprite || curSpriteData.Equals(fullTexSpriteData))
|
||||
{
|
||||
fullTexSpriteData = curSpriteData;
|
||||
}
|
||||
else
|
||||
{
|
||||
var faceAlphaID = curSpriteData.AlphaTex.m_PathID;
|
||||
FaceSpriteAlphaTexture = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == faceAlphaID).Asset;
|
||||
}
|
||||
var fullTexSpriteID = fullTexSpriteData.Sprite.m_PathID;
|
||||
var fullTexAlphaID = fullTexSpriteData.AlphaTex.m_PathID;
|
||||
var fullTexSprite = (Sprite)Studio.loadedAssetsList.Find(x => x.m_PathID == fullTexSpriteID).Asset;
|
||||
|
||||
FullTexture = fullTexSprite.m_RD.texture.TryGet(out var fullTex) ? fullTex : null;
|
||||
FullAlphaTexture = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == fullTexAlphaID).Asset;
|
||||
FacePos = new Point((int)Math.Round(spriteHubData.FacePos.X), (int)Math.Round(spriteHubData.FacePos.Y));
|
||||
FaceSize = new Size((int)Math.Round(spriteHubData.FaceSize.X), (int)Math.Round(spriteHubData.FaceSize.Y));
|
||||
IsFaceSprite = assetItem.m_PathID != fullTexSpriteID;
|
||||
}
|
||||
else
|
||||
{
|
||||
FullAlphaTexture = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID).Asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
AssetStudioCLI/Components/Arknights/AvgSpriteConfig.cs
Normal file
30
AssetStudioCLI/Components/Arknights/AvgSpriteConfig.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using AssetStudio;
|
||||
|
||||
namespace Arknights.AvgCharHubMono
|
||||
{
|
||||
internal class AvgAssetIDs
|
||||
{
|
||||
public int m_FileID { get; set; }
|
||||
public long m_PathID { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteData
|
||||
{
|
||||
public AvgAssetIDs Sprite { get; set; }
|
||||
public AvgAssetIDs AlphaTex { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public bool IsWholeBody { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteConfig
|
||||
{
|
||||
public AvgSpriteData[] Sprites { get; set; }
|
||||
public Vector2 FaceSize { get; set; }
|
||||
public Vector3 FacePos { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteConfigGroup
|
||||
{
|
||||
public AvgSpriteConfig[] SpriteGroups { get; set; }
|
||||
}
|
||||
}
|
||||
24
AssetStudioCLI/Components/Arknights/PortraitSprite.cs
Normal file
24
AssetStudioCLI/Components/Arknights/PortraitSprite.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using AssetStudio;
|
||||
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal class PortraitSprite
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ClassIDType Type { get; }
|
||||
public SerializedFile AssetsFile { get; set; }
|
||||
public string Container { get; set; }
|
||||
public Texture2D Texture { get; set; }
|
||||
public Texture2D AlphaTexture { get; set; }
|
||||
public Rectf TextureRect { get; set; }
|
||||
public bool Rotate { get; set; }
|
||||
public float DownscaleMultiplier { get; }
|
||||
|
||||
public PortraitSprite()
|
||||
{
|
||||
Type = ClassIDType.AkPortraitSprite;
|
||||
DownscaleMultiplier = 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
AssetStudioCLI/Components/Arknights/PortraitSpriteConfig.cs
Normal file
41
AssetStudioCLI/Components/Arknights/PortraitSpriteConfig.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace Arknights.PortraitSpriteMono
|
||||
{
|
||||
internal class PortraitRect
|
||||
{
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float W { get; set; }
|
||||
public float H { get; set; }
|
||||
}
|
||||
|
||||
internal class AtlasSprite
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Guid { get; set; }
|
||||
public int Atlas { get; set; }
|
||||
public PortraitRect Rect { get; set; }
|
||||
public bool Rotate { get; set; }
|
||||
}
|
||||
|
||||
internal class TextureIDs
|
||||
{
|
||||
public int m_FileID { get; set; }
|
||||
public long m_PathID { get; set; }
|
||||
}
|
||||
|
||||
internal class AtlasInfo
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public TextureIDs Texture { get; set; }
|
||||
public TextureIDs Alpha { get; set; }
|
||||
public int Size { get; set; }
|
||||
}
|
||||
|
||||
internal class PortraitSpriteConfig
|
||||
{
|
||||
public string m_Name { get; set; }
|
||||
public AtlasSprite[] _sprites { get; set; }
|
||||
public AtlasInfo _atlas { get; set; }
|
||||
public int _index { get; set; }
|
||||
}
|
||||
}
|
||||
42
AssetStudioCLI/Components/AssetItem.cs
Normal file
42
AssetStudioCLI/Components/AssetItem.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Arknights;
|
||||
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 GameObjectNode Node;
|
||||
public PortraitSprite AkPortraitSprite;
|
||||
|
||||
public AssetItem(Object asset)
|
||||
{
|
||||
Asset = asset;
|
||||
SourceFile = asset.assetsFile;
|
||||
Type = asset.type;
|
||||
TypeString = Type.ToString();
|
||||
m_PathID = asset.m_PathID;
|
||||
FullSize = asset.byteSize;
|
||||
}
|
||||
|
||||
public AssetItem(PortraitSprite akPortraitSprite)
|
||||
{
|
||||
Asset = null;
|
||||
SourceFile = akPortraitSprite.AssetsFile;
|
||||
Container = akPortraitSprite.Container;
|
||||
Type = akPortraitSprite.Type;
|
||||
TypeString = Type.ToString();
|
||||
Text = akPortraitSprite.Name;
|
||||
m_PathID = -1;
|
||||
AkPortraitSprite = akPortraitSprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using AssetStudio;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal class BaseNode
|
||||
{
|
||||
public List<BaseNode> nodes = new List<BaseNode>();
|
||||
|
||||
public BaseNode()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
49
AssetStudioCLI/Components/CLIAnsiColors.cs
Normal file
49
AssetStudioCLI/Components/CLIAnsiColors.cs
Normal file
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
AssetStudioCLI/Components/CLIWinAnsiFix.cs
Normal file
62
AssetStudioCLI/Components/CLIWinAnsiFix.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
16
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using AssetStudio;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal class GameObjectNode : BaseNode
|
||||
{
|
||||
public GameObject gameObject;
|
||||
|
||||
public GameObjectNode(GameObject gameObject)
|
||||
{
|
||||
this.gameObject = gameObject;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
550
AssetStudioCLI/Exporter.cs
Normal file
550
AssetStudioCLI/Exporter.cs
Normal file
@@ -0,0 +1,550 @@
|
||||
using Arknights;
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal static class Exporter
|
||||
{
|
||||
public static bool ExportTexture2D(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_Texture2D = (Texture2D)item.Asset;
|
||||
if (CLIOptions.convertTexture)
|
||||
{
|
||||
var type = CLIOptions.o_imageFormat.Value;
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
|
||||
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"Converting \"{m_Texture2D.m_Name}\" to {type}..");
|
||||
sb.AppendLine($"Width: {m_Texture2D.m_Width}");
|
||||
sb.AppendLine($"Height: {m_Texture2D.m_Height}");
|
||||
sb.AppendLine($"Format: {m_Texture2D.m_TextureFormat}");
|
||||
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
||||
{
|
||||
case 0: sb.AppendLine("Filter Mode: Point "); break;
|
||||
case 1: sb.AppendLine("Filter Mode: Bilinear "); break;
|
||||
case 2: sb.AppendLine("Filter Mode: Trilinear "); break;
|
||||
}
|
||||
sb.AppendLine($"Anisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}");
|
||||
sb.AppendLine($"Mip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}");
|
||||
switch (m_Texture2D.m_TextureSettings.m_WrapMode)
|
||||
{
|
||||
case 0: sb.AppendLine($"Wrap mode: Repeat"); break;
|
||||
case 1: sb.AppendLine($"Wrap mode: Clamp"); break;
|
||||
}
|
||||
Logger.Debug(sb.ToString());
|
||||
}
|
||||
|
||||
var image = m_Texture2D.ConvertToImage(flip: true);
|
||||
if (image == null)
|
||||
{
|
||||
Logger.Error($"Export 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)
|
||||
{
|
||||
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($"Export error. \"{item.Text}\": AudioData was not found");
|
||||
return false;
|
||||
}
|
||||
var converter = new AudioClipConverter(m_AudioClip);
|
||||
if (CLIOptions.o_audioFormat.Value != AudioFormat.None && converter.IsSupport)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
|
||||
return false;
|
||||
|
||||
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"Converting \"{m_AudioClip.m_Name}\" to wav..");
|
||||
sb.AppendLine(m_AudioClip.version[0] < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}");
|
||||
sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}");
|
||||
sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}");
|
||||
sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}");
|
||||
Logger.Debug(sb.ToString());
|
||||
}
|
||||
|
||||
var buffer = converter.ConvertToWav(m_AudioData);
|
||||
if (buffer == null)
|
||||
{
|
||||
Logger.Error($"Export 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;
|
||||
|
||||
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"VideoClip format: {m_VideoClip.m_Format}");
|
||||
sb.AppendLine($"VideoClip width: {m_VideoClip.Width}");
|
||||
sb.AppendLine($"VideoClip height: {m_VideoClip.Height}");
|
||||
sb.AppendLine($"VideoClip frame rate: {m_VideoClip.m_FrameRate:.0##}");
|
||||
sb.AppendLine($"VideoClip split alpha: {m_VideoClip.m_HasSplitAlpha}");
|
||||
Logger.Debug(sb.ToString());
|
||||
}
|
||||
|
||||
m_VideoClip.m_VideoData.WriteData(exportFullPath);
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ExportMovieTexture(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_MovieTexture = (MovieTexture)item.Asset;
|
||||
if (!TryExportFile(exportPath, item, ".ogv", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, m_MovieTexture.m_MovieData);
|
||||
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
var m_TextAsset = (TextAsset)item.Asset;
|
||||
var extension = ".txt";
|
||||
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
|
||||
if (!CLIOptions.f_notRestoreExtensionName.Value)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(assetExtension))
|
||||
{
|
||||
extension = "";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(item.Container))
|
||||
{
|
||||
var ext = Path.GetExtension(item.Container);
|
||||
if (!string.IsNullOrEmpty(item.Container))
|
||||
{
|
||||
extension = ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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 = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
|
||||
type = m_MonoBehaviour.ToType(m_Type);
|
||||
}
|
||||
if (type != null)
|
||||
{
|
||||
var str = JsonConvert.SerializeObject(type, Formatting.Indented);
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Image<Bgra32> image;
|
||||
AvgSprite avgSprite = null;
|
||||
var alias = "";
|
||||
var m_Sprite = (Sprite)item.Asset;
|
||||
var type = CLIOptions.o_imageFormat.Value;
|
||||
var spriteMaskMode = CLIOptions.o_akSpriteAlphaMode.Value != AkSpriteAlphaMode.None ? SpriteMaskMode.Export : SpriteMaskMode.Off;
|
||||
var isCharAvgSprite = item.Container.Contains("avg/characters");
|
||||
var isCharArt = item.Container.Contains("arts/characters");
|
||||
|
||||
if (isCharAvgSprite)
|
||||
{
|
||||
avgSprite = new AvgSprite(item);
|
||||
|
||||
if (CLIOptions.f_akAddAliases.Value && !string.IsNullOrEmpty(avgSprite.Alias))
|
||||
{
|
||||
alias = $"_{avgSprite.Alias}";
|
||||
}
|
||||
|
||||
if (!CLIOptions.f_akOriginalAvgNames.Value)
|
||||
{
|
||||
var groupedPattern = new Regex(@"^\d{1,2}\$\d{1,2}$"); // "spriteIndex$groupIndex"
|
||||
var notGroupedPattern = new Regex(@"^\d{1,2}$"); // "spriteIndex"
|
||||
if (groupedPattern.IsMatch(m_Sprite.m_Name) || notGroupedPattern.IsMatch(m_Sprite.m_Name))
|
||||
{
|
||||
var fullName = Path.GetFileNameWithoutExtension(item.Container);
|
||||
item.Text = $"{fullName}#{m_Sprite.m_Name}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath, alias))
|
||||
return false;
|
||||
|
||||
if (CLIOptions.o_akSpriteAlphaMode.Value == AkSpriteAlphaMode.SearchExternal && (isCharAvgSprite || isCharArt))
|
||||
{
|
||||
if (m_Sprite.m_RD.alphaTexture.IsNull)
|
||||
{
|
||||
var charAlphaAtlas = AkSpriteHelper.TryFindAlphaTex(item, avgSprite, isCharAvgSprite);
|
||||
if (charAlphaAtlas != null)
|
||||
{
|
||||
m_Sprite.m_RD.alphaTexture.Set(charAlphaAtlas);
|
||||
m_Sprite.akSplitAlpha = true;
|
||||
}
|
||||
}
|
||||
image = m_Sprite.AkGetImage(avgSprite, spriteMaskMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = m_Sprite.GetImage(spriteMaskMode);
|
||||
}
|
||||
|
||||
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 ExportPortraitSprite(AssetItem item, string exportPath)
|
||||
{
|
||||
var type = CLIOptions.o_imageFormat.Value;
|
||||
var spriteMaskMode = CLIOptions.o_akSpriteAlphaMode.Value != AkSpriteAlphaMode.None ? SpriteMaskMode.Export : SpriteMaskMode.Off;
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
|
||||
var image = item.AkPortraitSprite.AkGetImage(spriteMaskMode: spriteMaskMode);
|
||||
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 (item.Asset == null)
|
||||
{
|
||||
Logger.Warning($"Raw export is not supported for \"{item.Text}\" ({item.TypeString}) file");
|
||||
return false;
|
||||
}
|
||||
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 void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
var convert = animationList != null
|
||||
? new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||
: new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value);
|
||||
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
||||
ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
private static void ExportFbx(IImported convert, string exportPath)
|
||||
{
|
||||
var eulerFilter = true;
|
||||
var filterPrecision = (float)0.25f;
|
||||
var exportAllNodes = true;
|
||||
var exportSkins = true;
|
||||
var exportAnimations = true;
|
||||
var exportBlendShape = true;
|
||||
var castToBone = false;
|
||||
var boneSize = CLIOptions.o_fbxBoneSize.Value;
|
||||
var exportAllUvsAsDiffuseMaps = false;
|
||||
var scaleFactor = CLIOptions.o_fbxScaleFactor.Value;
|
||||
var fbxVersion = 3;
|
||||
var fbxFormat = 0;
|
||||
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
|
||||
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
|
||||
}
|
||||
|
||||
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (item.Asset == null)
|
||||
{
|
||||
Logger.Warning($"Dump is not supported for \"{item.Text}\" ({item.TypeString}) file");
|
||||
return false;
|
||||
}
|
||||
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 = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
|
||||
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, string alias = "")
|
||||
{
|
||||
var fileName = FixFileName(item.Text) + alias;
|
||||
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;
|
||||
}
|
||||
|
||||
private static bool ExportMesh(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_Mesh = (Mesh)item.Asset;
|
||||
if (m_Mesh.m_VertexCount <= 0)
|
||||
return false;
|
||||
if (!TryExportFile(exportPath, item, ".obj", out var exportFullPath))
|
||||
return false;
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("g " + m_Mesh.m_Name);
|
||||
|
||||
#region Vertices
|
||||
|
||||
if (m_Mesh.m_Vertices == null || m_Mesh.m_Vertices.Length == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int c = 3;
|
||||
if (m_Mesh.m_Vertices.Length == m_Mesh.m_VertexCount * 4)
|
||||
{
|
||||
c = 4;
|
||||
}
|
||||
|
||||
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
|
||||
{
|
||||
sb.Append($"v {-m_Mesh.m_Vertices[v * c]} {m_Mesh.m_Vertices[v * c + 1]} {m_Mesh.m_Vertices[v * c + 2]}\r\n");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UV
|
||||
|
||||
if (m_Mesh.m_UV0?.Length > 0)
|
||||
{
|
||||
c = 4;
|
||||
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
|
||||
{
|
||||
c = 2;
|
||||
}
|
||||
else if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 3)
|
||||
{
|
||||
c = 3;
|
||||
}
|
||||
|
||||
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
|
||||
{
|
||||
sb.AppendFormat("vt {0} {1}\r\n", m_Mesh.m_UV0[v * c], m_Mesh.m_UV0[v * c + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normals
|
||||
|
||||
if (m_Mesh.m_Normals?.Length > 0)
|
||||
{
|
||||
if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 3)
|
||||
{
|
||||
c = 3;
|
||||
}
|
||||
else if (m_Mesh.m_Normals.Length == m_Mesh.m_VertexCount * 4)
|
||||
{
|
||||
c = 4;
|
||||
}
|
||||
|
||||
for (int v = 0; v < m_Mesh.m_VertexCount; v++)
|
||||
{
|
||||
sb.AppendFormat("vn {0} {1} {2}\r\n", -m_Mesh.m_Normals[v * c], m_Mesh.m_Normals[v * c + 1], m_Mesh.m_Normals[v * c + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Face
|
||||
|
||||
int sum = 0;
|
||||
for (var i = 0; i < m_Mesh.m_SubMeshes.Length; i++)
|
||||
{
|
||||
sb.AppendLine($"g {m_Mesh.m_Name}_{i}");
|
||||
int indexCount = (int)m_Mesh.m_SubMeshes[i].indexCount;
|
||||
var end = sum + indexCount / 3;
|
||||
for (int f = sum; f < end; f++)
|
||||
{
|
||||
sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\r\n", m_Mesh.m_Indices[f * 3 + 2] + 1, m_Mesh.m_Indices[f * 3 + 1] + 1, m_Mesh.m_Indices[f * 3] + 1);
|
||||
}
|
||||
|
||||
sum = end;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
sb.Replace("NaN", "0");
|
||||
File.WriteAllText(exportFullPath, sb.ToString());
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportConvertFile(AssetItem item, string exportPath)
|
||||
{
|
||||
switch (item.Type)
|
||||
{
|
||||
case ClassIDType.Texture2D:
|
||||
return ExportTexture2D(item, exportPath);
|
||||
case ClassIDType.AudioClip:
|
||||
return ExportAudioClip(item, exportPath);
|
||||
case ClassIDType.VideoClip:
|
||||
return ExportVideoClip(item, exportPath);
|
||||
case ClassIDType.MovieTexture:
|
||||
return ExportMovieTexture(item, exportPath);
|
||||
case ClassIDType.Shader:
|
||||
return ExportShader(item, exportPath);
|
||||
case ClassIDType.TextAsset:
|
||||
return ExportTextAsset(item, exportPath);
|
||||
case ClassIDType.MonoBehaviour:
|
||||
return ExportMonoBehaviour(item, exportPath);
|
||||
case ClassIDType.Font:
|
||||
return ExportFont(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
return ExportSprite(item, exportPath);
|
||||
case ClassIDType.AkPortraitSprite:
|
||||
return ExportPortraitSprite(item, exportPath);
|
||||
case ClassIDType.Mesh:
|
||||
return ExportMesh(item, exportPath);
|
||||
default:
|
||||
return ExportRawFile(item, exportPath);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FixFileName(string str)
|
||||
{
|
||||
if (str.Length >= 260) return Path.GetRandomFileName();
|
||||
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/linux-x64/libTexture2DDecoderNative.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x64/libTexture2DDecoderNative.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/linux-x64/libfmod.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x64/libfmod.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/linux-x86/libfmod.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x86/libfmod.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-arm64/libfmod.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-arm64/libfmod.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-x64/libTexture2DDecoderNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-x64/libTexture2DDecoderNative.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-x64/libfmod.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-x64/libfmod.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/win-x64/fmod.dll
Normal file
BIN
AssetStudioCLI/Libraries/win-x64/fmod.dll
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/win-x86/fmod.dll
Normal file
BIN
AssetStudioCLI/Libraries/win-x86/fmod.dll
Normal file
Binary file not shown.
1146
AssetStudioCLI/Options/CLIOptions.cs
Normal file
1146
AssetStudioCLI/Options/CLIOptions.cs
Normal file
File diff suppressed because it is too large
Load Diff
27
AssetStudioCLI/Options/Option.cs
Normal file
27
AssetStudioCLI/Options/Option.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
AssetStudioCLI/Options/OptionExtensions.cs
Normal file
17
AssetStudioCLI/Options/OptionExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
|
||||
namespace AssetStudioCLI.Options
|
||||
{
|
||||
internal static class OptionExtensions
|
||||
{
|
||||
public static Action<string, string, HelpGroups, bool> OptionGrouping = (name, desc, group, isFlag) => { };
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
OptionExtensions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
AssetStudioCLI/Program.cs
Normal file
73
AssetStudioCLI/Program.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using System;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CLIOptions.ParseArgs(args);
|
||||
if (CLIOptions.isParsed)
|
||||
{
|
||||
CLIRun();
|
||||
}
|
||||
else if (CLIOptions.showHelp)
|
||||
{
|
||||
CLIOptions.ShowHelp();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine();
|
||||
CLIOptions.ShowHelp(showUsageOnly: true);
|
||||
}
|
||||
}
|
||||
|
||||
private static void CLIRun()
|
||||
{
|
||||
var cliLogger = new CLILogger();
|
||||
Logger.Default = cliLogger;
|
||||
CLIOptions.ShowCurrentOptions();
|
||||
|
||||
try
|
||||
{
|
||||
if (Studio.LoadAssets())
|
||||
{
|
||||
Studio.ParseAssets();
|
||||
if (CLIOptions.filterBy != FilterBy.None)
|
||||
{
|
||||
Studio.Filter();
|
||||
}
|
||||
if (CLIOptions.o_exportAssetList.Value != ExportListType.None)
|
||||
{
|
||||
Studio.ExportAssetList();
|
||||
}
|
||||
switch (CLIOptions.o_workMode.Value)
|
||||
{
|
||||
case WorkMode.Info:
|
||||
Studio.ShowExportableAssetsInfo();
|
||||
break;
|
||||
case WorkMode.ExportLive2D:
|
||||
Studio.ExportLive2D();
|
||||
break;
|
||||
case WorkMode.SplitObjects:
|
||||
Studio.ExportSplitObjects();
|
||||
break;
|
||||
default:
|
||||
Studio.ExportAssets();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error(ex.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
cliLogger.LogToFile(LoggerEvent.Verbose, "---Program ended---");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
AssetStudioCLI/ReadMe.md
Normal file
147
AssetStudioCLI/ReadMe.md
Normal file
@@ -0,0 +1,147 @@
|
||||
## ArknightsStudioCLI
|
||||
CLI version of ArknightsStudio.
|
||||
- Supported asset types for export: `Texture2D`, `Sprite`, `AkPortraitSprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`.
|
||||
- *There are no plans to add support for `AnimationClip`, `Animator` for now.*
|
||||
|
||||
### Usage
|
||||
```
|
||||
ArknightsStudioCLI <input path to asset file/folder> [-m, --mode <value>]
|
||||
[-t, --asset-type <value(s)>] [-g, --group-option <value>]
|
||||
[-o, --output <path>] [-h, --help]
|
||||
[--log-level <value>] [--log-output <value>]
|
||||
[--image-format <value>] [--audio-format <value>]
|
||||
[--fbx-scale-factor <value>] [--fbx-bone-size <value>]
|
||||
[--filter-by-name <text>] [--filter-by-container <text>]
|
||||
[--filter-by-pathid <text>] [--filter-by-text <text>]
|
||||
[--spritealpha-mode <value>] [--alphatex-resampler <value>]
|
||||
[--shadow-gamma <value>] [--original-avg-names]
|
||||
[--add-aliases] [--export-asset-list <value>]
|
||||
[--assembly-folder <path>] [--unity-version <text>]
|
||||
[--not-restore-extension] [--load-all]
|
||||
|
||||
|
||||
General Options:
|
||||
-m, --mode <value> Specify working mode
|
||||
<Value: export(default) | exportRaw | dump | info | live2d | splitObjects>
|
||||
Export - Exports converted assets
|
||||
ExportRaw - Exports raw data
|
||||
Dump - Makes asset dumps
|
||||
Info - Loads file(s), shows the number of available for export assets and exits
|
||||
Live2D - Exports Live2D Cubism 3 models
|
||||
SplitObjects - Exports split objects (fbx)
|
||||
Example: "-m info"
|
||||
|
||||
-t, --asset-type <value(s)> Specify asset type(s) to export
|
||||
<Value(s): tex2d, sprite, akPortrait, textAsset, monoBehaviour, font, shader,
|
||||
movieTexture, audio, video, mesh | all(default)>
|
||||
All - export all asset types, which are listed in the values
|
||||
*To specify multiple asset types, write them separated by ',' or ';' without spaces
|
||||
Examples: "-t sprite" or "-t tex2d,sprite,audio" or "-t tex2d;sprite;font"
|
||||
|
||||
-g, --group-option <value> Specify the way in which exported assets should be grouped
|
||||
<Value: none | type | container(default) | containerFull | filename>
|
||||
None - Do not group exported assets
|
||||
Type - Group exported assets by type name
|
||||
Container - Group exported assets by container path
|
||||
ContainerFull - Group exported assets by full container path (e.g. with prefab name)
|
||||
Filename - Group exported assets by source file name
|
||||
Example: "-g container"
|
||||
|
||||
-o, --output <path> Specify path to the output folder
|
||||
If path isn't specifyed, 'ASExport' folder will be created in the program's work folder
|
||||
|
||||
-h, --help Display help and exit
|
||||
|
||||
Logger Options:
|
||||
--log-level <value> Specify the log level
|
||||
<Value: verbose | debug | info(default) | warning | error>
|
||||
Example: "--log-level warning"
|
||||
|
||||
--log-output <value> Specify the log output
|
||||
<Value: console(default) | file | both>
|
||||
Example: "--log-output both"
|
||||
|
||||
Convert Options:
|
||||
--image-format <value> Specify the format for converting image assets
|
||||
<Value: none | jpg | png(default) | bmp | tga | webp>
|
||||
None - Do not convert images and export them as texture data (.tex)
|
||||
Example: "--image-format jpg"
|
||||
|
||||
--audio-format <value> Specify the format for converting audio assets
|
||||
<Value: none | wav(default)>
|
||||
None - Do not convert audios and export them in their own format
|
||||
Example: "--audio-format wav"
|
||||
|
||||
FBX Options:
|
||||
--fbx-scale-factor <value> Specify the FBX Scale Factor
|
||||
<Value: float number from 0 to 100 (default=1)
|
||||
Example: "--fbx-scale-factor 50"
|
||||
|
||||
--fbx-bone-size <value> Specify the FBX Bone Size
|
||||
<Value: integer number from 0 to 100 (default=10)
|
||||
Example: "--fbx-bone-size 10"
|
||||
|
||||
Filter Options:
|
||||
--filter-by-name <text> Specify the name by which assets should be filtered
|
||||
*To specify multiple names write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-name char" or "--filter-by-name char,bg"
|
||||
|
||||
--filter-by-container <text> Specify the container by which assets should be filtered
|
||||
*To specify multiple containers write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-container arts" or "--filter-by-container arts,icons"
|
||||
|
||||
--filter-by-pathid <text> Specify the PathID by which assets should be filtered
|
||||
*To specify multiple PathIDs write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-pathid 7238605633795851352,-2430306240205277265"
|
||||
|
||||
--filter-by-text <text> Specify the text by which assets should be filtered
|
||||
Looks for assets that contain the specified text in their names or containers
|
||||
*To specify multiple values write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-text portrait" or "--filter-by-text portrait,art"
|
||||
|
||||
|
||||
Arknights Options:
|
||||
--spritealpha-mode <value> Specify the mode in which you want to export sprites with alpha texture
|
||||
<Value: none | internalOnly | searchExternal(default)>
|
||||
None - Export sprites without alpha texture applied
|
||||
InternalOnly - Export sprites with internal alpha texture applied (if exist)
|
||||
SearchExternal - Export sprites with internal alpha texture applied,
|
||||
and in case it doesn't exist, Studio will try to find an external alpha texture
|
||||
Example: "--spritealpha-mode internalOnly"
|
||||
|
||||
--alphatex-resampler <value> Specify the alpha texture upscale algorithm for 2048x2048 sprites
|
||||
<Value: nearest | bilinear | bicubic | mitchell(default) | spline | welch>
|
||||
Mitchell - Mitchell Netravali algorithm. Yields good equilibrium between
|
||||
sharpness and smoothness (produces less artifacts than bicubic in the current use case)
|
||||
Spline - Similar to Mitchell Netravali but yielding smoother results
|
||||
Welch - A high speed algorithm that delivers very sharpened results
|
||||
Example: "--alphatex-resampler bicubic"
|
||||
|
||||
--shadow-gamma <value> Specify the gamma correction of semi-transparent shadow for 2048x2048 sprites
|
||||
<Value: integer number from -5 to 5 (default=2)>
|
||||
<0 - Make the shadow darker
|
||||
0 - Do not change the brightness of the shadow
|
||||
>0 - Make the shadow lighter
|
||||
Example: "--shadow-gamma 0"
|
||||
|
||||
--original-avg-names (Flag) If specified, names of avg character sprites will not be fixed
|
||||
|
||||
--add-aliases (Flag) If specified, aliases will be added to avg character sprite names (if exist)
|
||||
|
||||
Advanced Options:
|
||||
--export-asset-list <value> Specify the format in which you want to export asset list
|
||||
<Value: none(default) | xml>
|
||||
None - Do not export asset list
|
||||
Example: "--export-asset-list xml"
|
||||
|
||||
--assembly-folder <path> Specify the path to the assembly folder
|
||||
|
||||
--unity-version <text> Specify Unity version
|
||||
Example: "--unity-version 2017.4.39f1"
|
||||
|
||||
--not-restore-extension (Flag) If specified, Studio will not try to use/restore original TextAsset
|
||||
extension name, and will just export all TextAssets with the ".txt" extension
|
||||
|
||||
--load-all (Flag) If specified, Studio will load assets of all types
|
||||
(Only for Dump, Info and ExportRaw modes)
|
||||
```
|
||||
690
AssetStudioCLI/Studio.cs
Normal file
690
AssetStudioCLI/Studio.cs
Normal file
@@ -0,0 +1,690 @@
|
||||
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 static CubismLive2DExtractor.Live2DExtractor;
|
||||
using Ansi = AssetStudioCLI.CLIAnsiColors;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal static class Studio
|
||||
{
|
||||
public static AssetsManager assetsManager = new AssetsManager();
|
||||
public static List<AssetItem> exportableAssetsList = new List<AssetItem>();
|
||||
public static List<AssetItem> loadedAssetsList = new List<AssetItem>();
|
||||
public static List<BaseNode> gameObjectTree = new List<BaseNode>();
|
||||
public static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
||||
private static Dictionary<AssetStudio.Object, string> containers = new Dictionary<AssetStudio.Object, string>();
|
||||
|
||||
static Studio()
|
||||
{
|
||||
Progress.Default = new Progress<int>(ShowCurProgressValue);
|
||||
}
|
||||
|
||||
private static void ShowCurProgressValue(int value)
|
||||
{
|
||||
Console.Write($"[{value:000}%]\r");
|
||||
}
|
||||
|
||||
public static bool LoadAssets()
|
||||
{
|
||||
var isLoaded = false;
|
||||
assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value;
|
||||
if (!CLIOptions.f_loadAllAssets.Value)
|
||||
{
|
||||
assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value);
|
||||
}
|
||||
assetsManager.LoadFilesAndFolders(CLIOptions.inputPath);
|
||||
if (assetsManager.assetsFileList.Count == 0)
|
||||
{
|
||||
Logger.Warning("No Unity file can be loaded.");
|
||||
}
|
||||
else
|
||||
{
|
||||
isLoaded = true;
|
||||
}
|
||||
|
||||
return isLoaded;
|
||||
}
|
||||
|
||||
public static void ParseAssets()
|
||||
{
|
||||
Logger.Info("Parse assets...");
|
||||
|
||||
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||
var objectAssetItemDic = new Dictionary<AssetStudio.Object, AssetItem>(objectCount);
|
||||
|
||||
Progress.Reset();
|
||||
var i = 0;
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
foreach (var asset in assetsFile.Objects)
|
||||
{
|
||||
var assetItem = new AssetItem(asset);
|
||||
objectAssetItemDic.Add(asset, assetItem);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
assetItem.Text = m_AssetBundle.m_Name;
|
||||
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 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;
|
||||
case GameObject m_GameObject:
|
||||
assetItem.Text = m_GameObject.m_Name;
|
||||
break;
|
||||
case Animator m_Animator:
|
||||
if (m_Animator.m_GameObject.TryGet(out var gameObject))
|
||||
{
|
||||
assetItem.Text = gameObject.m_Name;
|
||||
}
|
||||
break;
|
||||
case NamedObject m_NamedObject:
|
||||
assetItem.Text = m_NamedObject.m_Name;
|
||||
break;
|
||||
}
|
||||
if (string.IsNullOrEmpty(assetItem.Text))
|
||||
{
|
||||
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
||||
}
|
||||
|
||||
loadedAssetsList.Add(assetItem);
|
||||
isExportable = CLIOptions.o_exportAssetTypes.Value.Contains(asset.type);
|
||||
if (isExportable || (CLIOptions.f_loadAllAssets.Value && CLIOptions.o_exportAssetTypes.Value == CLIOptions.o_exportAssetTypes.DefaultValue))
|
||||
{
|
||||
exportableAssetsList.Add(assetItem);
|
||||
}
|
||||
|
||||
Progress.Report(++i, objectCount);
|
||||
}
|
||||
foreach (var asset in loadedAssetsList)
|
||||
{
|
||||
if (containers.ContainsKey(asset.Asset))
|
||||
{
|
||||
asset.Container = containers[asset.Asset];
|
||||
|
||||
if (asset.Type == ClassIDType.MonoBehaviour && asset.Container.Contains("/arts/charportraits/portraits"))
|
||||
{
|
||||
var portraitsList = Arknights.AkSpriteHelper.GeneratePortraits(asset);
|
||||
foreach (var portrait in portraitsList)
|
||||
{
|
||||
exportableAssetsList.Add(new AssetItem(portrait));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CLIOptions.o_workMode.Value != WorkMode.ExportLive2D)
|
||||
{
|
||||
containers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects)
|
||||
{
|
||||
BuildTreeStructure(objectAssetItemDic);
|
||||
}
|
||||
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {exportableAssetsList.Count} exportable assets";
|
||||
var unityVer = assetsManager.assetsFileList[0].version;
|
||||
long m_ObjectsCount;
|
||||
if (unityVer[0] > 2020)
|
||||
{
|
||||
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y =>
|
||||
y.classID != (int)ClassIDType.Shader
|
||||
&& CLIOptions.o_exportAssetTypes.Value.Any(k => (int)k == y.classID))
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => CLIOptions.o_exportAssetTypes.Value.Any(k => (int)k == y.classID)));
|
||||
}
|
||||
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.LongCount(y => CLIOptions.o_exportAssetTypes.Value.Any(k => k == y.type)));
|
||||
if (m_ObjectsCount != objectsCount)
|
||||
{
|
||||
log += $" and {m_ObjectsCount - objectsCount} assets failed to read";
|
||||
}
|
||||
Logger.Info(log);
|
||||
}
|
||||
|
||||
public static void BuildTreeStructure(Dictionary<AssetStudio.Object, AssetItem> objectAssetItemDic)
|
||||
{
|
||||
Logger.Info("Building tree structure...");
|
||||
|
||||
var treeNodeDictionary = new Dictionary<GameObject, GameObjectNode>();
|
||||
var assetsFileCount = assetsManager.assetsFileList.Count;
|
||||
int j = 0;
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
var fileNode = new BaseNode(); //RootNode
|
||||
|
||||
foreach (var obj in assetsFile.Objects)
|
||||
{
|
||||
if (obj is GameObject m_GameObject)
|
||||
{
|
||||
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
|
||||
{
|
||||
currentNode = new GameObjectNode(m_GameObject);
|
||||
treeNodeDictionary.Add(m_GameObject, currentNode);
|
||||
}
|
||||
|
||||
foreach (var pptr in m_GameObject.m_Components)
|
||||
{
|
||||
if (pptr.TryGet(out var m_Component))
|
||||
{
|
||||
objectAssetItemDic[m_Component].Node = currentNode;
|
||||
if (m_Component is MeshFilter m_MeshFilter)
|
||||
{
|
||||
if (m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
|
||||
{
|
||||
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||
}
|
||||
}
|
||||
else if (m_Component is SkinnedMeshRenderer m_SkinnedMeshRenderer)
|
||||
{
|
||||
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))
|
||||
{
|
||||
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var parentNode = fileNode;
|
||||
|
||||
if (m_GameObject.m_Transform != null)
|
||||
{
|
||||
if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
|
||||
{
|
||||
if (m_Father.m_GameObject.TryGet(out var parentGameObject))
|
||||
{
|
||||
if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))
|
||||
{
|
||||
parentGameObjectNode = new GameObjectNode(parentGameObject);
|
||||
treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
|
||||
}
|
||||
parentNode = parentGameObjectNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parentNode.nodes.Add(currentNode);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNode.nodes.Count > 0)
|
||||
{
|
||||
gameObjectTree.Add(fileNode);
|
||||
}
|
||||
|
||||
Progress.Report(++j, assetsFileCount);
|
||||
}
|
||||
|
||||
treeNodeDictionary.Clear();
|
||||
objectAssetItemDic.Clear();
|
||||
}
|
||||
|
||||
public static void ShowExportableAssetsInfo()
|
||||
{
|
||||
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
|
||||
string info = "";
|
||||
if (exportableAssetsList.Count > 0)
|
||||
{
|
||||
foreach (var asset in exportableAssetsList)
|
||||
{
|
||||
if (exportableAssetsCountDict.ContainsKey(asset.Type))
|
||||
{
|
||||
exportableAssetsCountDict[asset.Type] += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
exportableAssetsCountDict.Add(asset.Type, 1);
|
||||
}
|
||||
}
|
||||
|
||||
info += "\n[Exportable Assets Count]\n";
|
||||
foreach (var assetType in exportableAssetsCountDict.Keys)
|
||||
{
|
||||
info += $"# {assetType}: {exportableAssetsCountDict[assetType]}\n";
|
||||
}
|
||||
if (exportableAssetsCountDict.Count > 1)
|
||||
{
|
||||
info += $"#\n# Total: {exportableAssetsList.Count} assets";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
info += "No exportable assets found.";
|
||||
}
|
||||
|
||||
if (CLIOptions.o_logLevel.Value > LoggerEvent.Info)
|
||||
{
|
||||
Console.WriteLine(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Filter()
|
||||
{
|
||||
switch (CLIOptions.o_workMode.Value)
|
||||
{
|
||||
case WorkMode.ExportLive2D:
|
||||
case WorkMode.SplitObjects:
|
||||
break;
|
||||
default:
|
||||
FilterAssets();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FilterAssets()
|
||||
{
|
||||
var assetsCount = exportableAssetsList.Count;
|
||||
var filteredAssets = new List<AssetItem>();
|
||||
|
||||
switch(CLIOptions.filterBy)
|
||||
{
|
||||
case FilterBy.Name:
|
||||
filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||
);
|
||||
break;
|
||||
case FilterBy.Container:
|
||||
filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
|
||||
);
|
||||
break;
|
||||
case FilterBy.PathID:
|
||||
filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.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("\", \"", CLIOptions.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs."
|
||||
);
|
||||
break;
|
||||
case FilterBy.NameOrContainer:
|
||||
filteredAssets = exportableAssetsList.FindAll(x =>
|
||||
CLIOptions.o_filterByText.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
CLIOptions.o_filterByText.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
);
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByText.Value)}\"".Color(Ansi.BrightYellow)} in their Names or Contaniers."
|
||||
);
|
||||
break;
|
||||
case FilterBy.NameAndContainer:
|
||||
filteredAssets = exportableAssetsList.FindAll(x =>
|
||||
CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) &&
|
||||
CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
|
||||
);
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers " +
|
||||
$"and {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||
);
|
||||
break;
|
||||
}
|
||||
exportableAssetsList.Clear();
|
||||
exportableAssetsList = filteredAssets;
|
||||
}
|
||||
|
||||
public static void ExportAssets()
|
||||
{
|
||||
var savePath = CLIOptions.o_outputFolder.Value;
|
||||
var toExportCount = exportableAssetsList.Count;
|
||||
var exportedCount = 0;
|
||||
|
||||
var groupOption = CLIOptions.o_groupAssetsBy.Value;
|
||||
foreach (var asset in exportableAssetsList)
|
||||
{
|
||||
string exportPath;
|
||||
switch (groupOption)
|
||||
{
|
||||
case AssetGroupOption.TypeName:
|
||||
exportPath = Path.Combine(savePath, asset.TypeString);
|
||||
break;
|
||||
case AssetGroupOption.ContainerPath:
|
||||
case AssetGroupOption.ContainerPathFull:
|
||||
if (!string.IsNullOrEmpty(asset.Container))
|
||||
{
|
||||
exportPath = Path.Combine(savePath, Path.GetDirectoryName(asset.Container));
|
||||
if (groupOption == AssetGroupOption.ContainerPathFull)
|
||||
{
|
||||
exportPath = Path.Combine(exportPath, Path.GetFileNameWithoutExtension(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 (CLIOptions.o_workMode.Value)
|
||||
{
|
||||
case WorkMode.ExportRaw:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportRawFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
break;
|
||||
case WorkMode.Dump:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportDumpFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
break;
|
||||
case WorkMode.Export:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportConvertFile(asset, exportPath))
|
||||
{
|
||||
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.Default.Log(LoggerEvent.Info, "Nothing exported.", ignoreLevel: true);
|
||||
}
|
||||
else if (toExportCount > exportedCount)
|
||||
{
|
||||
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightYellow)}\".", ignoreLevel: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Default.Log(LoggerEvent.Info, $"Finished exporting {exportedCount} asset(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightGreen)}\".", ignoreLevel: true);
|
||||
}
|
||||
|
||||
if (toExportCount > exportedCount)
|
||||
{
|
||||
Logger.Default.Log(LoggerEvent.Info, $"{toExportCount - exportedCount} asset(s) skipped (not extractable or file(s) already exist).", ignoreLevel: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExportAssetList()
|
||||
{
|
||||
var savePath = CLIOptions.o_outputFolder.Value;
|
||||
|
||||
switch (CLIOptions.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")),
|
||||
exportableAssetsList.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 {exportableAssetsList.Count} items.");
|
||||
}
|
||||
|
||||
public static void ExportSplitObjects()
|
||||
{
|
||||
var savePath = CLIOptions.o_outputFolder.Value;
|
||||
var searchList = CLIOptions.o_filterByName.Value;
|
||||
var isFiltered = CLIOptions.filterBy == FilterBy.Name;
|
||||
|
||||
var exportableObjects = new List<GameObjectNode>();
|
||||
var exportedCount = 0;
|
||||
var k = 0;
|
||||
|
||||
Logger.Info($"Searching for objects to export..");
|
||||
Progress.Reset();
|
||||
var count = gameObjectTree.Sum(x => x.nodes.Count);
|
||||
foreach (var node in gameObjectTree)
|
||||
{
|
||||
foreach (GameObjectNode j in node.nodes)
|
||||
{
|
||||
if (isFiltered)
|
||||
{
|
||||
if (!searchList.Any(searchText => j.gameObject.m_Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
continue;
|
||||
}
|
||||
var gameObjects = new List<GameObject>();
|
||||
CollectNode(j, gameObjects);
|
||||
|
||||
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
|
||||
{
|
||||
Progress.Report(++k, count);
|
||||
continue;
|
||||
}
|
||||
exportableObjects.Add(j);
|
||||
}
|
||||
}
|
||||
gameObjectTree.Clear();
|
||||
var exportableCount = exportableObjects.Count;
|
||||
var log = $"Found {exportableCount} exportable object(s) ";
|
||||
if (isFiltered)
|
||||
{
|
||||
log += $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names";
|
||||
}
|
||||
Logger.Info(log);
|
||||
if (exportableCount > 0)
|
||||
{
|
||||
Progress.Reset();
|
||||
k = 0;
|
||||
|
||||
foreach (var gameObjectNode in exportableObjects)
|
||||
{
|
||||
var gameObject = gameObjectNode.gameObject;
|
||||
var filename = FixFileName(gameObject.m_Name);
|
||||
var targetPath = $"{savePath}{filename}{Path.DirectorySeparatorChar}";
|
||||
//重名文件处理
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
if (Directory.Exists(targetPath))
|
||||
{
|
||||
targetPath = $"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}";
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Directory.CreateDirectory(targetPath);
|
||||
//导出FBX
|
||||
Logger.Info($"Exporting {filename}.fbx");
|
||||
Progress.Report(k, exportableCount);
|
||||
try
|
||||
{
|
||||
ExportGameObject(gameObject, targetPath);
|
||||
Logger.Debug($"{gameObject.type} \"{filename}\" saved to \"{targetPath}\"");
|
||||
exportedCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Export GameObject:{gameObject.m_Name} error", ex);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
var status = exportedCount > 0
|
||||
? $"Finished exporting [{exportedCount}/{exportableCount}] object(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\""
|
||||
: "Nothing exported";
|
||||
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
||||
}
|
||||
|
||||
private static void CollectNode(GameObjectNode node, List<GameObject> gameObjects)
|
||||
{
|
||||
gameObjects.Add(node.gameObject);
|
||||
foreach (GameObjectNode i in node.nodes)
|
||||
{
|
||||
CollectNode(i, gameObjects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExportLive2D()
|
||||
{
|
||||
var baseDestPath = Path.Combine(CLIOptions.o_outputFolder.Value, "Live2DOutput");
|
||||
var useFullContainerPath = false;
|
||||
|
||||
Progress.Reset();
|
||||
Logger.Info($"Searching for Live2D files...");
|
||||
|
||||
var cubismMocs = exportableAssetsList.Where(x =>
|
||||
{
|
||||
if (x.Type == ClassIDType.MonoBehaviour)
|
||||
{
|
||||
((MonoBehaviour)x.Asset).m_Script.TryGet(out var m_Script);
|
||||
return m_Script?.m_ClassName == "CubismMoc";
|
||||
}
|
||||
return false;
|
||||
}).Select(x => x.Asset).ToArray();
|
||||
if (cubismMocs.Length == 0)
|
||||
{
|
||||
Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
|
||||
return;
|
||||
}
|
||||
if (cubismMocs.Length > 1)
|
||||
{
|
||||
var basePathSet = cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToHashSet();
|
||||
|
||||
if (basePathSet.Count != cubismMocs.Length)
|
||||
{
|
||||
useFullContainerPath = true;
|
||||
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
|
||||
}
|
||||
}
|
||||
var basePathList = useFullContainerPath ?
|
||||
cubismMocs.Select(x => containers[x]).ToList() :
|
||||
cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToList();
|
||||
var lookup = containers.ToLookup(
|
||||
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||
x => x.Key
|
||||
);
|
||||
|
||||
var totalModelCount = lookup.LongCount(x => x.Key != null);
|
||||
Logger.Info($"Found {totalModelCount} model(s).");
|
||||
var name = "";
|
||||
var modelCounter = 0;
|
||||
foreach (var assets in lookup)
|
||||
{
|
||||
var container = assets.Key;
|
||||
if (container == null)
|
||||
continue;
|
||||
name = container;
|
||||
|
||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{container.Color(Ansi.BrightCyan)}\"");
|
||||
try
|
||||
{
|
||||
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
||||
container = Path.HasExtension(container) ? container.Replace(Path.GetExtension(container), "") : container;
|
||||
var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar;
|
||||
|
||||
ExtractLive2D(assets, destPath, modelName, assemblyLoader);
|
||||
modelCounter++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Live2D model export error: \"{name}\"", ex);
|
||||
}
|
||||
Progress.Report(modelCounter, (int)totalModelCount);
|
||||
}
|
||||
var status = modelCounter > 0 ?
|
||||
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
||||
"Nothing exported.";
|
||||
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,26 +29,26 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
@@ -100,14 +100,14 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -119,7 +119,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
@@ -129,7 +129,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x86\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@@ -138,14 +138,14 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;wininet.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -157,7 +157,7 @@
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_AS_DLL;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
</ClCompile>
|
||||
@@ -167,7 +167,7 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>libfbxsdk-mt.lib;libxml2-mt.lib;zlib-mt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.0.1\lib\vs2017\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>C:\Program Files\Autodesk\FBX\FBX SDK\2020.2.1\lib\vs2019\x64\release;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
# Set the minimum version of CMake that can be used
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
# Set the project name
|
||||
project("AssetStudioFBXNative")
|
||||
|
||||
# Set the C++ standard to C++ 14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
# Generate the shared library from the library sources
|
||||
add_library(AssetStudioFBXNative SHARED
|
||||
asfbx_skin_context.cpp
|
||||
asfbx_morph_context.cpp
|
||||
api.cpp
|
||||
utils.cpp
|
||||
asfbx_context.cpp
|
||||
asfbx_anim_context.cpp)
|
||||
|
||||
# Add the given directories to those the compiler uses to search for include files
|
||||
target_include_directories(AssetStudioFBXNative PRIVATE .)
|
||||
|
||||
target_link_libraries(AssetStudioFBXNative PRIVATE fbxsdk xml2)
|
||||
@@ -1,17 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>0.16.8.1</Version>
|
||||
<AssemblyVersion>0.16.8.1</AssemblyVersion>
|
||||
<FileVersion>0.16.8.1</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2018-2021; Copyright © hozuki 2020</Copyright>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net472|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
<Version>1.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
using AssetStudio.FbxInterop;
|
||||
using AssetStudio.PInvoke;
|
||||
using System.IO;
|
||||
|
||||
#if NETFRAMEWORK
|
||||
using AssetStudio.PInvoke;
|
||||
#endif
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public static partial class Fbx
|
||||
{
|
||||
|
||||
#if NETFRAMEWORK
|
||||
static Fbx()
|
||||
{
|
||||
DllLoader.PreloadDll(FbxDll.DllName);
|
||||
}
|
||||
#endif
|
||||
|
||||
public static Vector3 QuaternionToEuler(Quaternion q)
|
||||
{
|
||||
|
||||
503
AssetStudioGUI/AboutForm.Designer.cs
generated
Normal file
503
AssetStudioGUI/AboutForm.Designer.cs
generated
Normal file
@@ -0,0 +1,503 @@
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
partial class AboutForm
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm));
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.label11 = new System.Windows.Forms.Label();
|
||||
this.label10 = new System.Windows.Forms.Label();
|
||||
this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label16 = new System.Windows.Forms.Label();
|
||||
this.label17 = new System.Windows.Forms.Label();
|
||||
this.gitPerfareLinkLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.label18 = new System.Windows.Forms.Label();
|
||||
this.label19 = new System.Windows.Forms.Label();
|
||||
this.gitAelurumLinkLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.productNamelabel = new System.Windows.Forms.Label();
|
||||
this.label7 = new System.Windows.Forms.Label();
|
||||
this.modVersionLabel = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.basedOnLabel = new System.Windows.Forms.Label();
|
||||
this.checkUpdatesLinkLabel = new System.Windows.Forms.LinkLabel();
|
||||
this.tabPage2 = new System.Windows.Forms.TabPage();
|
||||
this.licenseRichTextBox = new System.Windows.Forms.RichTextBox();
|
||||
this.pictureBox1 = new System.Windows.Forms.PictureBox();
|
||||
this.productTitleLabel = new System.Windows.Forms.Label();
|
||||
this.CloseButton = new System.Windows.Forms.Button();
|
||||
this.productVersionLabel = new System.Windows.Forms.Label();
|
||||
this.panel2 = new System.Windows.Forms.Panel();
|
||||
this.panel3 = new System.Windows.Forms.Panel();
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
this.tableLayoutPanel2.SuspendLayout();
|
||||
this.tableLayoutPanel1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
|
||||
this.panel2.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// tabControl1
|
||||
//
|
||||
this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tabControl1.Controls.Add(this.tabPage1);
|
||||
this.tabControl1.Controls.Add(this.tabPage2);
|
||||
this.tabControl1.Location = new System.Drawing.Point(8, 103);
|
||||
this.tabControl1.Name = "tabControl1";
|
||||
this.tabControl1.SelectedIndex = 0;
|
||||
this.tabControl1.Size = new System.Drawing.Size(370, 315);
|
||||
this.tabControl1.TabIndex = 0;
|
||||
//
|
||||
// tabPage1
|
||||
//
|
||||
this.tabPage1.BackColor = System.Drawing.Color.White;
|
||||
this.tabPage1.Controls.Add(this.panel1);
|
||||
this.tabPage1.Controls.Add(this.textBox2);
|
||||
this.tabPage1.Controls.Add(this.label11);
|
||||
this.tabPage1.Controls.Add(this.label10);
|
||||
this.tabPage1.Controls.Add(this.tableLayoutPanel2);
|
||||
this.tabPage1.Controls.Add(this.tableLayoutPanel1);
|
||||
this.tabPage1.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage1.Name = "tabPage1";
|
||||
this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage1.Size = new System.Drawing.Size(362, 289);
|
||||
this.tabPage1.TabIndex = 0;
|
||||
this.tabPage1.Text = "Info";
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.panel1.BackColor = System.Drawing.Color.White;
|
||||
this.panel1.Controls.Add(this.label2);
|
||||
this.panel1.Location = new System.Drawing.Point(9, 16);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(347, 46);
|
||||
this.panel1.TabIndex = 21;
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.label2.Location = new System.Drawing.Point(0, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(347, 46);
|
||||
this.label2.TabIndex = 0;
|
||||
this.label2.Text = "ArknightsStudio is a modified version of AssetStudio designed for Arknights.";
|
||||
this.label2.UseCompatibleTextRendering = true;
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.textBox2.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.textBox2.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.textBox2.Cursor = System.Windows.Forms.Cursors.Default;
|
||||
this.textBox2.Enabled = false;
|
||||
this.textBox2.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.textBox2.Location = new System.Drawing.Point(9, 232);
|
||||
this.textBox2.Multiline = true;
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.ReadOnly = true;
|
||||
this.textBox2.Size = new System.Drawing.Size(347, 51);
|
||||
this.textBox2.TabIndex = 20;
|
||||
this.textBox2.TabStop = false;
|
||||
this.textBox2.Text = "* Neither the repository, nor the tool, nor the author of the tool, nor the autho" +
|
||||
"r of the modification is affiliated with, sponsored, or authorized by Unity Tech" +
|
||||
"nologies or its affiliates.";
|
||||
//
|
||||
// label11
|
||||
//
|
||||
this.label11.AutoSize = true;
|
||||
this.label11.Location = new System.Drawing.Point(6, 150);
|
||||
this.label11.Name = "label11";
|
||||
this.label11.Size = new System.Drawing.Size(43, 13);
|
||||
this.label11.TabIndex = 17;
|
||||
this.label11.Text = "Authors";
|
||||
//
|
||||
// label10
|
||||
//
|
||||
this.label10.AutoSize = true;
|
||||
this.label10.Location = new System.Drawing.Point(8, 65);
|
||||
this.label10.Name = "label10";
|
||||
this.label10.Size = new System.Drawing.Size(42, 13);
|
||||
this.label10.TabIndex = 16;
|
||||
this.label10.Text = "Version";
|
||||
//
|
||||
// tableLayoutPanel2
|
||||
//
|
||||
this.tableLayoutPanel2.BackColor = System.Drawing.Color.WhiteSmoke;
|
||||
this.tableLayoutPanel2.ColumnCount = 3;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 41.37931F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 58.62069F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 113F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.label16, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label17, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.gitPerfareLinkLabel, 2, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label18, 0, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label19, 1, 1);
|
||||
this.tableLayoutPanel2.Controls.Add(this.gitAelurumLinkLabel, 2, 1);
|
||||
this.tableLayoutPanel2.Location = new System.Drawing.Point(6, 165);
|
||||
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||
this.tableLayoutPanel2.Padding = new System.Windows.Forms.Padding(2);
|
||||
this.tableLayoutPanel2.RowCount = 2;
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
|
||||
this.tableLayoutPanel2.Size = new System.Drawing.Size(350, 40);
|
||||
this.tableLayoutPanel2.TabIndex = 15;
|
||||
//
|
||||
// label16
|
||||
//
|
||||
this.label16.AutoSize = true;
|
||||
this.label16.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label16.Location = new System.Drawing.Point(5, 2);
|
||||
this.label16.Name = "label16";
|
||||
this.label16.Size = new System.Drawing.Size(78, 13);
|
||||
this.label16.TabIndex = 9;
|
||||
this.label16.Text = "Original author:";
|
||||
//
|
||||
// label17
|
||||
//
|
||||
this.label17.AutoSize = true;
|
||||
this.label17.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label17.Location = new System.Drawing.Point(101, 2);
|
||||
this.label17.Name = "label17";
|
||||
this.label17.Size = new System.Drawing.Size(110, 13);
|
||||
this.label17.TabIndex = 10;
|
||||
this.label17.Text = "Perfare (c) 2016-2022";
|
||||
//
|
||||
// gitPerfareLinkLabel
|
||||
//
|
||||
this.gitPerfareLinkLabel.AutoSize = true;
|
||||
this.gitPerfareLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.gitPerfareLinkLabel.Location = new System.Drawing.Point(237, 2);
|
||||
this.gitPerfareLinkLabel.Name = "gitPerfareLinkLabel";
|
||||
this.gitPerfareLinkLabel.Size = new System.Drawing.Size(67, 13);
|
||||
this.gitPerfareLinkLabel.TabIndex = 11;
|
||||
this.gitPerfareLinkLabel.TabStop = true;
|
||||
this.gitPerfareLinkLabel.Text = "GitHub page";
|
||||
this.gitPerfareLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.gitPerfareLinkLabel_LinkClicked);
|
||||
//
|
||||
// label18
|
||||
//
|
||||
this.label18.AutoSize = true;
|
||||
this.label18.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label18.Location = new System.Drawing.Point(5, 20);
|
||||
this.label18.Name = "label18";
|
||||
this.label18.Size = new System.Drawing.Size(76, 13);
|
||||
this.label18.TabIndex = 12;
|
||||
this.label18.Text = "Author of mod:";
|
||||
//
|
||||
// label19
|
||||
//
|
||||
this.label19.AutoSize = true;
|
||||
this.label19.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label19.Location = new System.Drawing.Point(101, 20);
|
||||
this.label19.Name = "label19";
|
||||
this.label19.Size = new System.Drawing.Size(113, 13);
|
||||
this.label19.TabIndex = 13;
|
||||
this.label19.Text = "aelurum (c) 2021-2023";
|
||||
//
|
||||
// gitAelurumLinkLabel
|
||||
//
|
||||
this.gitAelurumLinkLabel.AutoSize = true;
|
||||
this.gitAelurumLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.gitAelurumLinkLabel.Location = new System.Drawing.Point(237, 20);
|
||||
this.gitAelurumLinkLabel.Name = "gitAelurumLinkLabel";
|
||||
this.gitAelurumLinkLabel.Size = new System.Drawing.Size(67, 13);
|
||||
this.gitAelurumLinkLabel.TabIndex = 14;
|
||||
this.gitAelurumLinkLabel.TabStop = true;
|
||||
this.gitAelurumLinkLabel.Text = "GitHub page";
|
||||
this.gitAelurumLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.gitAelurumLinkLabel_LinkClicked);
|
||||
//
|
||||
// tableLayoutPanel1
|
||||
//
|
||||
this.tableLayoutPanel1.BackColor = System.Drawing.Color.WhiteSmoke;
|
||||
this.tableLayoutPanel1.ColumnCount = 3;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 41.37931F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 58.62069F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 113F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.label5, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.productNamelabel, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label7, 0, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.modVersionLabel, 1, 1);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label4, 0, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.basedOnLabel, 1, 2);
|
||||
this.tableLayoutPanel1.Controls.Add(this.checkUpdatesLinkLabel, 2, 1);
|
||||
this.tableLayoutPanel1.Location = new System.Drawing.Point(6, 80);
|
||||
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||
this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(2);
|
||||
this.tableLayoutPanel1.RowCount = 3;
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33334F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 33.33333F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F));
|
||||
this.tableLayoutPanel1.Size = new System.Drawing.Size(350, 60);
|
||||
this.tableLayoutPanel1.TabIndex = 5;
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label5.Location = new System.Drawing.Point(5, 2);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(76, 13);
|
||||
this.label5.TabIndex = 0;
|
||||
this.label5.Text = "Product name:";
|
||||
//
|
||||
// productNamelabel
|
||||
//
|
||||
this.productNamelabel.AutoSize = true;
|
||||
this.productNamelabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.productNamelabel.Location = new System.Drawing.Point(101, 2);
|
||||
this.productNamelabel.Name = "productNamelabel";
|
||||
this.productNamelabel.Size = new System.Drawing.Size(100, 13);
|
||||
this.productNamelabel.TabIndex = 1;
|
||||
this.productNamelabel.Text = "ArknightsStudioGUI";
|
||||
//
|
||||
// label7
|
||||
//
|
||||
this.label7.AutoSize = true;
|
||||
this.label7.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label7.Location = new System.Drawing.Point(5, 20);
|
||||
this.label7.Name = "label7";
|
||||
this.label7.Size = new System.Drawing.Size(45, 13);
|
||||
this.label7.TabIndex = 2;
|
||||
this.label7.Text = "Version:";
|
||||
//
|
||||
// modVersionLabel
|
||||
//
|
||||
this.modVersionLabel.AutoSize = true;
|
||||
this.modVersionLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.modVersionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.modVersionLabel.Location = new System.Drawing.Point(101, 20);
|
||||
this.modVersionLabel.Name = "modVersionLabel";
|
||||
this.modVersionLabel.Size = new System.Drawing.Size(52, 13);
|
||||
this.modVersionLabel.TabIndex = 3;
|
||||
this.modVersionLabel.Text = "0.16.48.1";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.label4.Location = new System.Drawing.Point(5, 38);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(55, 13);
|
||||
this.label4.TabIndex = 4;
|
||||
this.label4.Text = "Based on:";
|
||||
//
|
||||
// basedOnLabel
|
||||
//
|
||||
this.basedOnLabel.AutoSize = true;
|
||||
this.basedOnLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.basedOnLabel.Location = new System.Drawing.Point(101, 38);
|
||||
this.basedOnLabel.Name = "basedOnLabel";
|
||||
this.basedOnLabel.Size = new System.Drawing.Size(123, 13);
|
||||
this.basedOnLabel.TabIndex = 5;
|
||||
this.basedOnLabel.Text = "AssetStudioMod v0.17.0";
|
||||
//
|
||||
// checkUpdatesLinkLabel
|
||||
//
|
||||
this.checkUpdatesLinkLabel.AutoSize = true;
|
||||
this.checkUpdatesLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.checkUpdatesLinkLabel.Location = new System.Drawing.Point(237, 20);
|
||||
this.checkUpdatesLinkLabel.Name = "checkUpdatesLinkLabel";
|
||||
this.checkUpdatesLinkLabel.Size = new System.Drawing.Size(96, 13);
|
||||
this.checkUpdatesLinkLabel.TabIndex = 6;
|
||||
this.checkUpdatesLinkLabel.TabStop = true;
|
||||
this.checkUpdatesLinkLabel.Text = "Check for Updates";
|
||||
this.checkUpdatesLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.checkUpdatesLinkLabel_LinkClicked);
|
||||
//
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.licenseRichTextBox);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Padding = new System.Windows.Forms.Padding(3);
|
||||
this.tabPage2.Size = new System.Drawing.Size(362, 289);
|
||||
this.tabPage2.TabIndex = 1;
|
||||
this.tabPage2.Text = "License";
|
||||
this.tabPage2.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// licenseRichTextBox
|
||||
//
|
||||
this.licenseRichTextBox.BackColor = System.Drawing.Color.White;
|
||||
this.licenseRichTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.licenseRichTextBox.DetectUrls = false;
|
||||
this.licenseRichTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.licenseRichTextBox.Location = new System.Drawing.Point(3, 3);
|
||||
this.licenseRichTextBox.Name = "licenseRichTextBox";
|
||||
this.licenseRichTextBox.ReadOnly = true;
|
||||
this.licenseRichTextBox.Size = new System.Drawing.Size(356, 283);
|
||||
this.licenseRichTextBox.TabIndex = 0;
|
||||
this.licenseRichTextBox.Text = "MIT License";
|
||||
this.licenseRichTextBox.ZoomFactor = 1.1F;
|
||||
//
|
||||
// pictureBox1
|
||||
//
|
||||
this.pictureBox1.BackColor = System.Drawing.Color.Transparent;
|
||||
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.pictureBox1.Image = global::AssetStudioGUI.Properties.Resources.as_logo;
|
||||
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
|
||||
this.pictureBox1.Name = "pictureBox1";
|
||||
this.pictureBox1.Size = new System.Drawing.Size(384, 50);
|
||||
this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
|
||||
this.pictureBox1.TabIndex = 0;
|
||||
this.pictureBox1.TabStop = false;
|
||||
//
|
||||
// productTitleLabel
|
||||
//
|
||||
this.productTitleLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.productTitleLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.productTitleLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.productTitleLabel.Location = new System.Drawing.Point(0, 52);
|
||||
this.productTitleLabel.Name = "productTitleLabel";
|
||||
this.productTitleLabel.Size = new System.Drawing.Size(384, 30);
|
||||
this.productTitleLabel.TabIndex = 1;
|
||||
this.productTitleLabel.Text = "ArknightsStudioGUI";
|
||||
this.productTitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||
//
|
||||
// CloseButton
|
||||
//
|
||||
this.CloseButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.CloseButton.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.CloseButton.Location = new System.Drawing.Point(0, 422);
|
||||
this.CloseButton.Name = "CloseButton";
|
||||
this.CloseButton.Size = new System.Drawing.Size(384, 39);
|
||||
this.CloseButton.TabIndex = 1;
|
||||
this.CloseButton.Text = "Close";
|
||||
this.CloseButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// productVersionLabel
|
||||
//
|
||||
this.productVersionLabel.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||
this.productVersionLabel.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.productVersionLabel.Location = new System.Drawing.Point(0, 82);
|
||||
this.productVersionLabel.Name = "productVersionLabel";
|
||||
this.productVersionLabel.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0);
|
||||
this.productVersionLabel.Size = new System.Drawing.Size(384, 13);
|
||||
this.productVersionLabel.TabIndex = 2;
|
||||
this.productVersionLabel.Text = "v0.16.48.1 [x64]";
|
||||
this.productVersionLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
||||
//
|
||||
// panel2
|
||||
//
|
||||
this.panel2.Controls.Add(this.productTitleLabel);
|
||||
this.panel2.Controls.Add(this.pictureBox1);
|
||||
this.panel2.Controls.Add(this.productVersionLabel);
|
||||
this.panel2.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panel2.Location = new System.Drawing.Point(0, 5);
|
||||
this.panel2.Name = "panel2";
|
||||
this.panel2.Size = new System.Drawing.Size(384, 95);
|
||||
this.panel2.TabIndex = 3;
|
||||
//
|
||||
// panel3
|
||||
//
|
||||
this.panel3.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panel3.Location = new System.Drawing.Point(0, 0);
|
||||
this.panel3.Name = "panel3";
|
||||
this.panel3.Size = new System.Drawing.Size(384, 5);
|
||||
this.panel3.TabIndex = 3;
|
||||
//
|
||||
// AboutForm
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.CloseButton;
|
||||
this.ClientSize = new System.Drawing.Size(384, 461);
|
||||
this.Controls.Add(this.panel2);
|
||||
this.Controls.Add(this.panel3);
|
||||
this.Controls.Add(this.CloseButton);
|
||||
this.Controls.Add(this.tabControl1);
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "AboutForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "About";
|
||||
this.tabControl1.ResumeLayout(false);
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.ResumeLayout(false);
|
||||
this.tableLayoutPanel2.PerformLayout();
|
||||
this.tableLayoutPanel1.ResumeLayout(false);
|
||||
this.tableLayoutPanel1.PerformLayout();
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
|
||||
this.panel2.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.TabControl tabControl1;
|
||||
private System.Windows.Forms.PictureBox pictureBox1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.Label productTitleLabel;
|
||||
private System.Windows.Forms.Button CloseButton;
|
||||
private System.Windows.Forms.Label productVersionLabel;
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.Label label11;
|
||||
private System.Windows.Forms.Label label10;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
|
||||
private System.Windows.Forms.Label label16;
|
||||
private System.Windows.Forms.Label label17;
|
||||
private System.Windows.Forms.LinkLabel gitPerfareLinkLabel;
|
||||
private System.Windows.Forms.Label label18;
|
||||
private System.Windows.Forms.Label label19;
|
||||
private System.Windows.Forms.LinkLabel gitAelurumLinkLabel;
|
||||
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
|
||||
private System.Windows.Forms.Label label5;
|
||||
private System.Windows.Forms.Label productNamelabel;
|
||||
private System.Windows.Forms.Label label7;
|
||||
private System.Windows.Forms.Label modVersionLabel;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Label basedOnLabel;
|
||||
private System.Windows.Forms.LinkLabel checkUpdatesLinkLabel;
|
||||
private System.Windows.Forms.RichTextBox licenseRichTextBox;
|
||||
private System.Windows.Forms.TextBox textBox2;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Panel panel2;
|
||||
private System.Windows.Forms.Panel panel3;
|
||||
}
|
||||
}
|
||||
70
AssetStudioGUI/AboutForm.cs
Normal file
70
AssetStudioGUI/AboutForm.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
public partial class AboutForm : Form
|
||||
{
|
||||
public AboutForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
var productName = Application.ProductName;
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
Text += " " + productName;
|
||||
productTitleLabel.Text = productName;
|
||||
productVersionLabel.Text = $"v{Application.ProductVersion} [{arch}]";
|
||||
productNamelabel.Text = productName;
|
||||
modVersionLabel.Text = Application.ProductVersion;
|
||||
basedOnLabel.Text = "AssetStudioMod v0.17.3";
|
||||
|
||||
licenseRichTextBox.Text = GetLicenseText();
|
||||
}
|
||||
|
||||
private string GetLicenseText()
|
||||
{
|
||||
string license = "MIT License";
|
||||
|
||||
if (File.Exists("LICENSE"))
|
||||
{
|
||||
string text = File.ReadAllText("LICENSE");
|
||||
license = text.Replace("\r", "")
|
||||
.Replace("\n\n", "\r")
|
||||
.Replace("\nCopyright", "\tCopyright")
|
||||
.Replace("\n", " ")
|
||||
.Replace("\r", "\n\n")
|
||||
.Replace("\tCopyright", "\nCopyright");
|
||||
}
|
||||
|
||||
return license;
|
||||
}
|
||||
|
||||
private void checkUpdatesLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var ps = new ProcessStartInfo("https://github.com/aelurum/AssetStudio/tags")
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(ps);
|
||||
}
|
||||
|
||||
private void gitPerfareLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var ps = new ProcessStartInfo("https://github.com/Perfare")
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(ps);
|
||||
}
|
||||
|
||||
private void gitAelurumLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
var ps = new ProcessStartInfo("https://github.com/aelurum")
|
||||
{
|
||||
UseShellExecute = true
|
||||
};
|
||||
Process.Start(ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
754
AssetStudioGUI/AboutForm.resx
Normal file
754
AssetStudioGUI/AboutForm.resx
Normal file
@@ -0,0 +1,754 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>
|
||||
AAABAAoAEBAQAAEABAAoAQAApgAAABAQAAABAAgAaAUAAM4BAAAQEAAAAQAgAGgEAAA2BwAAICAQAAEA
|
||||
BADoAgAAngsAACAgAAABAAgAqAgAAIYOAAAgIAAAAQAgAKgQAAAuFwAAMDAQAAEABABoBgAA1icAADAw
|
||||
AAABAAgAqA4AAD4uAAAwMAAAAQAgAKglAADmPAAAAAAAAAEAIADMMAAAjmIAACgAAAAQAAAAIAAAAAEA
|
||||
BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAACAAACAAIAAgIAAAAAAgACAgIAAAICAAMDA
|
||||
wAAAAP8A////AP8A/wAAAAAAAAAAAAAAAAAAAAAAABcXAQQBcDABcQBgYFISFUUCVAACFRUhAEMVFlMj
|
||||
IDIGaGZqubk2ABAIiKiTlpMhBxaDppYzlgUBdoapY5aTQCMBiIk5aTIFEHCKaWllIwQHEGqWmWaTJQEj
|
||||
CJZWmWcBRRBxcBV3EBcAcQYBcQEGAAYGAEUGAjBxABAjAEBRIBCAAQAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAAKAAAABAAAAAgAAAAAQAIAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwKCYANzZSADI2ZQAwKSoAMCgsADInSAAxLlUAMDZeADAq
|
||||
LAAyKigAmqDgADpR/gA0M20AOiWTADk0vwA2VfwANVj+ADNQ1wAwKi4AXlZUAOfj7QBDSv0APzrTAEEj
|
||||
nAA+RewAPDvDAEArrAA6TPQAMzZvAJyUkQDz7egAdG33AEU99QBGIpgAQ0D0ADcwbAAyJzEAMis7ADEq
|
||||
MAAxKScA18/JANTH1QCuoe8ATDf/AEwmrgBKMdUARznrAEA1sgA2LV8AV05LAOTY1gCCXKUA4NfjAFMw
|
||||
/gBMKr8ARiNwAE8qwgBPMOMATDX6ADQqRwCSiIIAu6G7AFwjiQDm29oAfFT2AFMn6QA2J0QARCNbAFge
|
||||
hwBUKucAPiqAAMq+tQDdzssA1sTKAOfc1gCvjeoAXh7/AF0f/wBYH7sAXR2YAFoj8gA/J3QAUEdDAN/Q
|
||||
xgCRXpcAhF2FAJSKhQDbydoAZRb+AGMX8wBiGP4AYRn/AFcd2gAyKDAARDw4AF9TUQBAJD4AOCYzADkw
|
||||
LgBnXloARSdlAEEiXgBAI1IAPiNfADInLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAV9gYWJjZGVmZ2hpAQEBAQFTVFVWV1hZWltcXV4BAQEBAUhJSktMTU5PUFFS
|
||||
AQEBAQE9Pj9AQUJDREVGRwEBAQEBMjM0NTY3ODk6OzwBAQEBASgpKissLS4vMDEBAQEBAQEBHh8gISIj
|
||||
JCUmJwEBAQEBARQVFhcYGRobHB0BAQEBAQEKCwwNDg8QERITAQEBAQEBAQIDBAUGBwgJAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEAgAEAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAACgAAAAQAAAAIAAAAAEA
|
||||
IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwKCY3MCgm2DAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJtgwKCY3MCgm2DAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm2DAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/0Q8OP9fU1H/QCQ+/zgm
|
||||
M/85MC7/Z15a/0UnZf9BIl7/QCNS/z4jX/8yJy3/MCgm/zAoJv8wKCb/MCgm/zAoJv9QR0P/39DG/5Fe
|
||||
l/+EXYX/lIqF/9vJ2v9lFv7/Yxfz/2IY/v9hGf//Vx3a/zIoMP8wKCb/MCgm/zAoJv8wKCb/MCgm/8q+
|
||||
tf/dzsv/1sTK/+fc1v+vjer/Xh7//10f//9YH7v/XR2Y/1oj8v8/J3T/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv+SiIL/u6G7/1wjif/m29r/fFT2/1Mn6f82J0T/RCNb/1geh/9UKuf/PiqA/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/V05L/+TY1v+CXKX/4Nfj/1Mw/v9MKr//RiNw/08qwv9PMOP/TDX6/zQqR/8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zEpJ//Xz8n/1MfV/66h7/9MN///TCau/0ox1f9HOev/QDWy/zYtX/8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/nJSR//Pt6P90bff/RT31/0YimP9DQPT/NzBs/zInMf8yKzv/MSow/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/15WVP/n4+3/Q0r9/z860/9BI5z/PkXs/zw7w/9AK6z/Okz0/zM2
|
||||
b/8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8yKij/mqDg/zpR/v80M23/OiWT/zk0v/82Vfz/NVj+/zNQ
|
||||
1/8wKi7/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zc2Uv8yNmX/MCkq/zAoLP8yJ0j/MS5V/zA2
|
||||
Xv8wKiz/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJtgwKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJtgwKCY3MCgm2DAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJtgwKCY3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAgAAAAQAAAAAEABAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAgAAAAACAAACAAIAAgIAAAAAAgACAgIAAAICAAAAA/wDAwMAA////AAD/
|
||||
/wD/AP8AAAAAAAAAAAAAAAAAAAAwIVBFIVBAVAFFEhcDAAAXEjAGADISMEUCUGBQQCADIVBFQDIBUCMB
|
||||
cQQAQDAyBFAhUjAhUhcQcBcQVFEgRRUhVAECMEUBcQRQcSAXAwACFUUHFxcEUgRUBAMEUEBxAyAQQQAB
|
||||
BRAwUFFSMARRAgRRJmYWMjRpNzY3M3FxBUUVIVaZMzEJmYyDjIaDAjIQAjAjqZaWmanIbIaMjHEFIwMh
|
||||
UpmampqWjIaDOGg3EhAEBUVqmZmprIg4NlOGgQVFFSEBaaY1mpiMc0UzaMJUAAIwcQmmM6mYxwBTY4hl
|
||||
EHEVQBcJmTaqhoNzNoaGMCMFAjBwFpo5qYyGOGjIaGAyEgMgEGCaaamGg2hohoYBIDAEAyMCmpqoaGOG
|
||||
hlYFBgMgFSECMGmqmGhlhoQAEhAgMgIwcQIaqmhoNoaEVnNwMhADIBcVCZpoaGiGhlOGhAMHBFFwEjap
|
||||
hoZWhoaGhoIwIRUhAXBAqYaDU4aGi4ZUAjACFQYBUJhoYGVlhoaGADAjAyBAUEVlaCUVVldzUlQGEARR
|
||||
BxIwIXEEAXEBBgQBUHAwIyEDIDIAYFIVJUBQMgQBAjAFQAYBVAEjBAFUASMAMgMhcQcQJUUCMHAXBxJQ
|
||||
YSUEBQRRIwEBcQQDIQFRIQcBAGBgBFBgIwcQVFBFIwIwEAABAjAEBRIBUhAGABJRAgDAAAADgAAAAQAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABwAAAAygA
|
||||
AAAgAAAAQAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCgmAEhFVgA0Q6UAM0OlADAs
|
||||
NwAyJ0AANCdlADQmbgA0K3UAMT+UADBGogAwQYkAMC4/ALCsqwBHXvsAOFP+ADM5egA1JmkAOSWjADgy
|
||||
uQA1VfcANFn+ADNa/gAyWfYAMTluADYuLADt6eYAhI32ADtP/gA4RMEANSZUADwkoAA8KakAOFD4ADhU
|
||||
/gA3Vf4ANlb+ADVX/gA1VvgAMS9GAGxlYwD18e0AwcHwAD5K/gA9SvkAPSaVAD8jngA9OtAAPTrPAD4u
|
||||
sgA8OckAOVH8ADRBoACrpaEA9O/rAPHs7ABNT/sAQkX+AEFH/gBBMMAAQiObAD9B5gA5P7cAPyOKAD4+
|
||||
2AA4R9AANCwqAOXe2gDz7egAhYD0AEVB/gBEQv4ARTnfAEUimABCQO4AODeQADMnNgA0Jz0AMytJADMw
|
||||
VQAyL04AZl5bAPDp5ADx6+YAvrfsAEg9/gBHPv4ARz37AEgjmwBIIZYARTrlAD86wwCjm5cA7ubgAOLZ
|
||||
3ADx6uUA7ebnAFNB/ABKOf4ASTv+AEopuABLIZMASS/KAEc9/gA/NrIAODB1ADUtWQAwKCkAMysoAN3U
|
||||
zgDu5d8Ak3axAOrh4ACGc/UATTX/AE0v2wBOIJAATSKZAEs29ABLN/8ANSxPAGBXVADr4toA7OPcAGE1
|
||||
lQDArMgA8OjjALus6QBRL/8AUDH6AFAgjwBRH44AUCOgAE4x6QBJN+wAMik4AJ2TjQDq39gAzr3JAFQf
|
||||
iwCTcK0A6ODhAFoz/ABTLf8APSlyADkmQQA/JFEATyB+AFIjoQBSJrIAUC3bAE8z/wBONP8APy6WANXK
|
||||
wgDo3dQAooKwAFceiABoNZIA7eTeAIdl8QBWKf8ASSm0ADQnMgBVHoUAUivgAEou0ABaUU0A5trRAHlJ
|
||||
lgBZHYYA0sDMAO3k3QC5oecAWyL/AFkl/wBXJfQAOydhADYoQwBRIHIAViS8AFQr/wBQK+QAlImDAOXY
|
||||
zgDFrsEA3c/RAOTZ3QBhJf0AXCD/AE0ktQBZHnwAXB2DAFkizgBQJ9oAzcC2AOPWzADp3tYA6uDYAIpX
|
||||
8gBfG/8AXR37AF4evgBeHZwASiWrAFVLRwDi1MkAv6OzALeZrwC4mrEAsZ2lAKqgmgDc0ckAuJblAGMX
|
||||
/wBhGf8AOCZOAI2BegDh0cYA2snCAGkhfQBlG3sAQSRBAJmPigDo3tUA4NLXAGgX/QBlE/8AZRT/AGUX
|
||||
zwBkFfsAYBj5AEIjdgCCdm8AmIuDAIRwdwBQIFYAMicpAJ6UjgBhNKAAURqnAFEdgwBQH2YATxyVAE8c
|
||||
pgBJH4wANiZBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAerr7O3t7e4Bzonv8PHx8vP09fb3AWwBAQEBAQEB
|
||||
AQEB2tvc3d7e3wHg4eLj5OXm5+XX1+jpAQEBAQEBAQEBAQHOz8/Q0dLT1NWK1tfX19jJycnJysrZAQEB
|
||||
AQEBAQEBAQHExbmpqZzGx3vIycnJycrLzMu+r80BAQEBAQEBAQEBAbi5qbq6urt7vL2vvq+vv8DBwcKw
|
||||
wwEBAQEBAQEBAQEBqKmpqqurrK2ur7CxsrKztKurtba3AQEBAQEBAQEBAQEBm5ydnp+gXqGioqMBAaSl
|
||||
np6mkKcBAQEBAQEBAQEBAQGJiouMjV6Oj5CQkZKTlJWWl5iZmgEBAQEBAQEBAQEBAXp7fH1+f4CBgYKD
|
||||
hIWGc3N4eIeIAQEBAQEBAQEBAQEBbW5vcHFgcnNzdHV2d3hjZGRJeQEBAQEBAQEBAQEBAQEBXV5fYGFi
|
||||
Y2RlZmdWaGlqa2wBAQEBAQEBAQEBAQEBAQFSU1RFVVZXWFlaW0dcAQEBAQEBAQEBAQEBAQEBAQEBAUNE
|
||||
RTdGR0hJSkpLOkxNTk5PUFEBAQEBAQEBAQEBAQEBATY3ODk6Ozw9PT4sP0A9PUEdQgEBAQEBAQEBAQEB
|
||||
AQEBKSorLCwtLi8vMB0dMTIzNBA1AQEBAQEBAQEBAQEBAQEaGxwdHR4fICAhIiMkJCUmJygBAQEBAQEB
|
||||
AQEBAQEBAQEODxAQEQESExMUFRYXFxgZAQEBAQEBAQEBAQEBAQEBAQIDBAQFAQEGBwgJCgsMDQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAMAAAAOAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAHAAAADKAAAACAA
|
||||
AABAAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwKCYKMCgmgzAoJt8wKCb+MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv4wKCbfMCgmgzAoJgoAAAAAMCgmCjAoJsgwKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgmyDAoJgowKCaDMCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgmgzAo
|
||||
Jt8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCbfMCgm/jAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv4wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+Cdm//mIuD/4Rw
|
||||
d/9QIFb/UCBW/1AgVf8yJyn/MCgm/1JKRv+dk43/npSO/2E0oP9RGaf/URqn/1Edg/9QH2b/TxyV/08c
|
||||
pv9JH4z/NiZB/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/42B
|
||||
ev/g0MX/2snC/2khff9lG3v/ZRt7/0EkQf8wKCb/mY+K/+je1f/g0tf/aBf9/2UT//9lFP//ZRfP/2QV
|
||||
+/9jFv//Yxb//2IX//9gGPn/QiN2/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/VUtH/+HSx//i1Mn/v6Oz/7eZr/+4mrH/sZ2l/6qgmv/c0cn/6t/Y/7iW5f9jF///Yhf//2IY
|
||||
//9hGf7/YRn//2Aa//9gG///Xxz//14c//9dHfv/OCZO/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8xKSf/zcC2/+PWzP/k2M7/5tnQ/+fb0v/o3dT/6d7W/+rg2P/r4tr/ilfy/18b
|
||||
//9fHP//Xx3//14d//9eHv7/Xh2//14dnP9dHr3/WyH9/1si//9KJav/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+UiYP/5djO/+ba0P/Frb//xa3A/8Wuwv/dz9H/6+Lb/+TZ
|
||||
3f9hJf3/XCD//1wg//9bIf//WyH//00ktf9ZHnz/XB2D/1wdg/9ZIs7/WCb//1An2v8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/1pRTf/m2tH/59vT/3lJlv9ZHYb/WR2G/9LA
|
||||
zP/t5N3/uaHn/1oj//9ZJP//VyX0/zsnYf87J2H/NihD/1Egcv9ZHYb/WR2G/1YkvP9UK///UCvk/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MSkn/9XKwv/o3tX/ooKw/1ce
|
||||
iP9oNZL/7eTe/+7m4P+HZfH/Vij//1Yp//9JKbT/MCgm/zAoJv80JzL/VR6F/1ceiP9XHon/Uivg/1Ev
|
||||
//9KLtD/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/nJKN/+rf
|
||||
2P/Ovcn/VB+L/5Nwrf/u5uD/6ODh/1oz/P9TLP//Uy3//z0pcv85JkH/PyRR/08gfv9SI6H/Uiay/1At
|
||||
2/9PM///TjT//z8ulv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv9gV1T/6+La/+zj3P9hNZX/wKzI//Do4/+7rOn/UTD//1Ax//9QMfr/UCCP/1Efjv9QI6D/TjHp/001
|
||||
//9NNv//TDf//0s3//9JN+z/Mik4/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zMrKP/d1M7/7uXf/5N2sf/q4eD/8erl/4Zz9f9NNf//TTX//00v2/9OIJD/TSKZ/0s2
|
||||
9P9LOf7/Sjn+/0k6/v9JO/7/RTne/zUsT/8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/6Obl//v5+H/4tnc//Hq5f/t5uf/U0H8/0o5/v9KOv7/Sim4/0sh
|
||||
k/9JL8r/SDz+/0c9/v8/NrL/ODB1/zUtWf8wKCn/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/Zl5b//Dp5P/x6+b/8+3o/7637P9IPf7/Rz7+/0c9
|
||||
+/9II5v/SCGW/0U65f9FQf7/PzrD/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv80LCr/5d7a//Pt6P/07ur/hYD0/0RB
|
||||
/v9EQv7/RDnf/0UimP9FIpj/QkDu/0JF/v84N5D/Myc2/zQnPf80Jz3/MytJ/zMwVf8yL07/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+rpaH/9O/r//Hs
|
||||
7P9NT/v/QUb+/0FH/v9BMMD/QiOb/0Ijm/8/Qeb/Pkr+/zk/t/8/I4r/QiOb/0Ijm/8+Ptj/O0/+/zhH
|
||||
0P8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/2xl
|
||||
Y//18e3/wcHw/z9K/v8+Sv7/PUr5/z0mlf8/I57/PyOe/z060P87Tv7/O0/+/z06z/8+LrL/PDnJ/zlR
|
||||
/P84U/7/NEGg/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/Ni4s/+3p5v+Ejfb/O07+/ztP/v84RMH/NSZU/zwkoP88JKD/PCmp/zhQ+P84VP7/N1T+/zZV
|
||||
/v82Vv7/NVf+/zVW+P8xL0b/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/sKyr/0de+/84U/7/OFP+/zM5ev8wKCb/NSZp/zklov85JaP/ODK5/zVV
|
||||
9/80Wf7/M1r+/zNa/v8yWfb/MTlu/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv9IRVb/NEOl/zNDpf8zQ6X/MCw3/zAoJv8wKCb/MidA/zQn
|
||||
Zf80Jm7/NCt1/zE/lP8wRqL/MEGJ/zAuP/8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv4wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb+MCgm3zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJt8wKCaDMCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgmgzAoJgowKCbIMCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJsgwKCYKAAAAADAoJgowKCaDMCgm3zAo
|
||||
Jv4wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/jAoJt8wKCaDMCgmCgAAAACAAAABAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAASgA
|
||||
AAAwAAAAYAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAACAAACAAIAAgIAAAAAA
|
||||
gACAgIAAAICAAAAA/wDAwMAAAP//AP///wD/AP8AAAAAAAAAAAAAAAAAAAAAYAMhUhJRJRcBIVJRIyAS
|
||||
AyMhUgAAAARUAGBUBFBAVAFwFwEGABUjBAAwIVAAAABRcQIQUBcXECMBcBcQBgQBcBcSMEAAADISAyFU
|
||||
BgAQcVIXFxBxcQVFAyAwIwYAAyFRcVBFASMHEEUAEAcQBFQAQFQCMCBUEgUhAgYAYFIQRQEjJUAXFQBg
|
||||
MhBRIDBFBUAXAwEjAhFwMhcQBFFwBFQARQYEUSMABFFwEjJRIyUEADIGAwIQYAFUUEADBxBxAyEBcBBA
|
||||
UBIVBgAwIGBUBUUgFxVAIQcQElBxBgcDIXAyEHEEUQEjISEDIBJRBgEGBUAXAQESEAEgMhBFFxcAUDBg
|
||||
cXAXBFIwBAMgMpmWNjcVQGmZaDjGNoaDMAMgFQEgAyFUBpmZMzMyBZubPIyDjIyGhlQDIGBUElAhUGuZ
|
||||
YzYxYZuZhoaMhoyMjIRSMBIVBUAwIWmbmZmZmbm8jIyGjIaMhoMBIHFSBFElFSmZm5uZubm2hoaMiDOG
|
||||
jIYHFRIQAyFUAha5uZm5ubmYyMjIk1ZThoxxBAUjEgUhUXG5mZmZm5vIaGiDhjM2OGgwcGASBUAwIQeZ
|
||||
uTc1m5s4yGU2UDc1OMhxAQYFBFEgMlGZuTMzm5uGjIElBjM2hoY3FSASAyFUUEBpuWNWubmMhlcQRTVj
|
||||
jIZRIDIwElAhBFAZuZM5ubOGhlEjU2M4aGgXBgElBUAyUQYJm5N5m5hoyGU4aGhoaGhAEGBRBAMgFwEm
|
||||
ubM7u5jIaDY2jIaMhoFQRQBAAyEDJUUBm7lrm4aGhjg4aGhoaGAGAEUXElBxAQIymZmbm4yGgzaGhoho
|
||||
YBcQcVQABUASVFElS7ubuYaGhlhoaGIDAjAjAhBxBFFwECMBW5m5toaGg2hoZRAyBgYBIwcSAyEGAjAj
|
||||
Kbu7mGhoNzhoZSEgEAAjAhBREgUhUSMgBrm5mGhoY4aGhFNWVjcwcVQCBUAwIwAVRbu7aGhoNTaGhlNz
|
||||
hoZxASUVBFElEgMhAJubhoaGg3hoaGOGioZRcDAhFUBUBUAyUWu5hoaDc4OGioaGhoZSASMXAlEhcVIB
|
||||
Iyu2hoZzhlaGhomGhoYDIwIAFUBRAhVFBFm4qGgQc4VoaGhoqGUCEHFUAhVAcVIQYAaYaKNxU3OHhoqG
|
||||
hlIVRRBAAyADBAFSFUVoaGUCMlNzh4aHVAMhAlRQBFFxIDIDAhUjAhBgEBcQQGASFUAFRRAjBgIQVAVA
|
||||
cVISUXAGBwFSUQcDAlFxASUQEFFwRQRRAhAwQBVAEGBAFUASMEAXBxBgBxIVEjIBcVIGBSFSVAUGAlFw
|
||||
IwUhIVIQBAUSUQAyASMBIVQBAyEhUSEDBARRUEUHAwRQQFQFRQBgUhUlQFAyBxUgYFASBgEhBFAhVAMh
|
||||
AXEEAwQBVAEjAQRRBAMhUDIwAGAyFSAyBxcAYHAXBxJQYCUXAjJQQSAAAAQFBFEjAQFxBAMhAVEhBgEh
|
||||
UQEjAlEAAABgYARQYCMHEFRQRSMCMFQFRSFSMBAAAAABAjAEBRIBUhAGABJRAhUEADIBBwAA8AAAAAAP
|
||||
AADgAAAAAAcAAMAAAAAAAwAAgAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAQAAwAAAAAAD
|
||||
AADgAAAAAAcAAPAAAAAADwAAKAAAADAAAABgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAwKCYAQzw6AFZp3AA1UeQAMTBLADEoKQAzJ1sANSaBADYmjwA2JZMANieWADQ8tQAyTtEAMVXhADBU
|
||||
2AAwSq8AMDZeAIF7eQCapPMAOVL+ADZV/gA0PpMAMic9ADglkQA6JaIAOC6xADRR7wA0Wf4AM1r+ADJc
|
||||
/gAxSrIAMSktAMG8ugDX1+8APFH9ADtO/gA3StgAMSc1ADoklwA6K60AN1H1ADJJtwA+NjQA9O/rAPby
|
||||
8ABbZ/gAPE3+ADIuSgA5JX0APSSgAD8jngA6RuMAMjdtAHt0cQD18e0AmJvxAD5K/gA5OKYAPiyxADs/
|
||||
2AA8NLwAPDbDADpI6QA1SswAurSwANTR7ABASP4AP0LrAEEjnABDIpoAPzjOADw1sgBBJJ4APUbmADlR
|
||||
+QAyKjoAPTUzAO7m4QDz7ekAW1z3AEND/gBBRv4AQiepAEA+3gA1J0UAQDG9ADIwVAB1bWoA8OvoAJaS
|
||||
8QBEMcgAQzzmADw+wgA2JkgANStTADQ0bQCzq6cA8erlAM/J6QBHPv4ARUH+AEU66ABGIpcAPz7VADoy
|
||||
MADm3NoAXlP2AEgkoQBLIZMARTbUAEVA+wBvZ2MA7+jiAJWJ8ABKOv4ASizCAEwquQA3L2sAMio1AKyj
|
||||
ngDTxNIAwrDMAMzB6gBNNf4ASzLjAEo48wBGPPMAQznSADoxgwA2LiwA5trSAOzj3ACiiLcAk3WzAGFI
|
||||
+gBOIpwAVCGNAE0otABpYF0A6t/aAHRNngBmO5kAlH/vAFAx/wBQJ74AVB+LAKWblgDi1dYAyLrlAFMs
|
||||
/wBMLdMARCNjAE0gfgBSIpwAUCvNAE8w7gA9LogA3M/IAOne1gC1nLsAp4q4AGE7+QBJIm0AUCzbAGNa
|
||||
VwCJYqIAe0+eAJN17QBXJ/8APyl9AEwhcABbHYUAUivgADUpRACelI4A5NjPAGQujABbIokAxbLjAEwn
|
||||
wwA+JUUAVSOqADspYwA0LCoA1Mi/AMWvvwBmM/kAWiP/AEEmfgA8KWwANyY2AFcglwBeVVEA0r+9ALOV
|
||||
tgC0lrgAzrvGAJNr7gBeHf8AVCThAFgfpgCYjIYA4tXLAMOp4wBaIuIA0MK4AGoo+gBhGv8AXh3KAF8b
|
||||
qwBcH+cAVCPcAFlPSwDh0sYA39DEAN/RygCUYO4AZBX+AJGFfgB/R4oAZyN8AEAtPABNQ0EAv6HfAGQW
|
||||
9ABTH8QAx7muAGUbegBfHHAAbBv6AGUYqQBSHbsAMycyAMu8sQCgfpUAYBxtAE0hUQDUycEAhU3YAGIT
|
||||
6QBhE+cAYRmWAF8W1QBdF90AUhuzAD4jYgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAAAAAAABAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQYBAQEBAQEBAQEBAQEBAQEBAQYGBgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB3+rq
|
||||
6uvs7Ozl7QEBATa57u7v8PHw8PLl0vPx9PX2AQEBAQEBAQEBAQEBAQEBAQEBBuPX18Lk5OTk5QYGAUGf
|
||||
n5Tm2tra4efh2tra0Nra6OkBAQEBAQEBAQEBAQEBAQEBAdvWy9bc3d3d3d6C34OfjODa2tra4dra0NDa
|
||||
0NDQ0OIGAQEBAQEBAQEBAQEBAQEBAdXWy8vXntjW2NjLsJ+fn9na0NDQ0NDQ0MfHx8fHx8e9AQEBAQEB
|
||||
AQEBAQEBAQEBAQHOy7CwsIODn4OfaoyEas/Qx8fHx8fH0NHS0tPHvLzUAQEBAQEBAQEBAQEBAQEBAQHK
|
||||
y8uwsIODn5+fn4yEzMfHx8fHx7y8yaysrKzNvKmprgEBAQEBAQEBAQEBAQEBAQHBsLCDwsPDxMPFhISE
|
||||
xsfHvLy8x7zItaysrKzJqamptwEBAQEBAQEBAQEBAQEBAQG4uYODuqysrKyghISMu7y8vLyqvb2+v6ys
|
||||
rKzAqamWvgEBAQEBAQEBAQEBAQEBAQEBr4ODsLGyrLKUTk6zqampqbQBAQEBtayskqy2lpaQtwEBAQEB
|
||||
AQEBAQEBAQEBAQEBpZ+fn6aSkqeEhHGoqamWqaoBAQEGq5KskpKtkJaQrgEBAQEBAQEBAQEBAQEBAQEB
|
||||
gp6fn6CSiaFxTk6ilpaWlkwBICajkpKSmqSQfJB9AQEBAQEBAQEBAQEBAQEBAQEBAZOMhJSJiXlxcZWW
|
||||
lpCQl5iZkpKam5x8fJB8fHydAQEBAQEBAQEBAQEBAQEBAQEBAYuMhISNjoRxYo+QkJCQkZKSbYp8fHxz
|
||||
c3xzc24gAQEBAQEBAQEBAQEBAQEBAQEBAYKDhISFhmJicYd8fHx8iG2JinN8c3xzc3NzbhcBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQF4Tk55emJie3x8fHx9bW1nfnNzZHNkf4CBIAEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQFwTnFOTk9icnNzc3N0bW11ZGRkXHZ3IAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQFpamJiYk9Za2Rk
|
||||
ZGRsbWduZGRvXwEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBYWJPT09jZGRlZGZnZ2dcUlFoAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBWFlZLCxaUVFRUVtGRkZcUlJdBlVeXl5fYGBgTAEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBTU5PLDdQUVJSUlNGRkZUOUNKVUZGRkZWJCQkVwEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAUE3N0JDQ0M5REVGRUVHLy8kSEVGRUlKJBRLTAEBAQEBAQEBAQEBAQEBAQEBAQEBATY3Nzg5OTk5
|
||||
OjMzMzM7JCQUJDw9Pj8UFBVAAQEBAQEBAQEBAQEBAQEBAQEBAQEBASssLS4vLyQkMDEyMjMzNBQVFRUV
|
||||
FRUVFRU1AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEhIiMUFCQlASYnGRkZKCkVFRUVHBwcHSoBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQESExQUFRUWAQEXGBkZGRobHB0dHh4eHyABAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQECAwQEBAQFAQEBBgcICQoLDA0ODxARAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAAAABAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAQEBAQEBAQEBAQEBAQEBAQEB
|
||||
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQAAAADwAAAAAA8AAOAAAAAABwAAwAAAAAADAACAAAAAAAEAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAgAAAAAABAADAAAAAAAMAAOAAAAAABwAA8AAAAAAPAAAoAAAAMAAAAGAA
|
||||
AAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCgmLDAoJpkwKCbeMCgm/TAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb9MCgm3jAoJpkwKCYsAAAAAAAAAAAAAAAAAAAAADAoJgEwKCZ3MCgm+TAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb5MCgmdzAoJgEAAAAAAAAAADAo
|
||||
JncwKCb+MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/jAo
|
||||
JncAAAAAMCgmLDAoJvkwKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJvkwKCYsMCgmmTAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCaZMCgm3jAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCbeMCgm/TAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb9MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/05EQf/Lu7D/y7yx/8y9s/+gfpX/YBxt/2Acbf9gHG3/YBxt/00hUf8wKCb/MCgm/zAo
|
||||
Jv99dG//08jA/9TJwf/VysP/hU3Y/2IS5/9iEuf/YRPo/2IT6f9hGZb/YBt4/18Yrv9fFtX/YBXm/10X
|
||||
3f9SG7P/PiNi/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zIqKP/Hua7/39DE/+DRxf/Sv73/Zhx7/2Ybe/9mG3v/Zht7/18c
|
||||
cP8xKCf/MCgm/zAoJv+/tK3/6N3V/+ne1v/k2Nb/bBv6/2YS//9mEv//ZRP//2UU+P9lGKn/ZBX1/2QU
|
||||
//9kFf//YxX//2MW//9jFv//Yhf//1Idu/8zJzL/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+RhX7/4NHG/+HSx//h08j/f0eK/2cj
|
||||
fP9nI3z/ZyN8/2cjfP9ALTz/Ny8t/0tCQP/l2tL/6d7W/+rf2P+/od//ZBT//2QV//9kFf//Yxb//2MX
|
||||
8v9jF/v/Yhf//2IX//9iGP//YRj//2EZ//9hGv//YBr//2Ab//9TH8T/MSgp/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv9ZT0v/4dLH/+LT
|
||||
yf/i1Mr/39DI/93PyP/e0Mn/39HK/+DSzP/f08z/4NXM/+LYz//p3tf/6t/Y/+vh2f+UYO7/Yhf//2IY
|
||||
//9hGP//YRn//2EZ//9hGf//YBr//2Ab//9gG///Xxz//18c//9eHf//Xh3//14e//9dHv//QiR9/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8xKSf/0MK4/+PVyv/j1sz/5NfN/+XYzv/m2dD/5trR/+fb0//o3NT/6N7V/+nf1//q4Nj/6+HZ/+ba
|
||||
2/9qKPr/YBr//2Ab//9fG///Xxz//18c//9fHP//Xh3//14d/P9eHcr/Xh2o/10ds/9cH+f/XCD//1wh
|
||||
//9bIf//VCPc/zAoJ/8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/mIyG/+PWzP/k183/5djP/+bZ0P/m2tL/59zT/+jd1P/p3tb/6d/X/+rg
|
||||
2P/r4dr/7OLb/8Op4/9eHf//Xh3//14e//9dHv//XR///10f//9cH///XCD+/1gfpv9eHIL/XhyC/14c
|
||||
gv9dHYb/WiLi/1kk//9ZJP//WCX9/zUoQv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/XlVR/+TXzv/l2M//5trQ/8+8xP+zlLX/s5W2/7OV
|
||||
t/+0lrj/zbnH/+vh2v/s4tv/7OTd/5Nr7v9cIP//XCD//1sh//9bIf//WyL+/1si//9aIv//VCTh/z8k
|
||||
Rv9cHYT/XB2E/1wdhP9cHYT/WSCp/1cm//9XJ///Vyf//zsoYv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/NCwq/9TIv//m2tH/59vS/8Wv
|
||||
v/9aHYX/Wh2F/1odhf9aHYX/up++/+zj3P/t5N3/6d/e/2Yz+f9aI///WiP//1kk//9YJPv/QSZ+/0Em
|
||||
f/9BJ3//PCdo/zcmNv9aHYX/Wh2F/1odhf9aHYX/VyCX/1Up//9VKv//VCv//zwpbP8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/56U
|
||||
jv/n29L/6NzU/+TY0v9kLoz/WB6H/1geh/9bIon/49bX/+3k3f/u5d//xbLj/1gl//9YJv//WCb//1cn
|
||||
//9MJ8P/MCgm/zAoJv8wKCb/MCgm/zwlQ/9YHof/WB6H/1geh/9YHof/VSOq/1Mt//9TLf//Ui7//zoq
|
||||
Y/8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/2NaV//o3NT/6N7V/+nf1/+JYqL/Vh6J/1Yeif97T57/7eTe/+7l3//u5uD/k3Xt/1Yo
|
||||
//9WKf//VSn//1Uq//8/KX3/MCgm/zAoJv8wKCb/MSgo/0whcP9WHon/Vh6J/1Yeif9WHor/Uivg/1Ev
|
||||
//9RMP//UDD9/zUpRf8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zYuLP/az8j/6d/X/+rg2P+1nLv/VB+L/1Qfi/+nirj/7ubf/+/n
|
||||
4f/t5eH/YTv5/1Qr//9ULP//Uyz//1It+v8zKDv/MCgn/zEoKv82Jjn/SSJt/1Qfi/9UH4v/VCCP/1Mi
|
||||
nf9QLNv/TzL//08y//9PM///SjLg/zAoKP8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+lm5b/6uDZ/+vh2v/g1NT/VCKN/1Mg
|
||||
jP/UxdL/7+fh/+/o4v/IuuX/Ui7//1Iu//9SL///US///0wt0/9EI2P/TSB+/1EfiP9SH4z/USKb/1Ar
|
||||
zf9PMO7/TjP4/040//9ONP//TTX//002//9MNv//PS6I/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv9pYF3/6+La/+zj
|
||||
3P/t5N3/dE2e/2Y7mf/t5eD/8Ojj//Dp5P+Uf+//UDH//1Ax//9PMv//TzL//1Anvv9QH47/UB+O/1Af
|
||||
jv9OKLj/TTT6/001//9NNv//TDb//0w3//9LN///Szj//0s4/v9FNdX/MSgs/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv82Liz/4tnS/+3k3f/u5d//ooi3/5N1s//w6eP/8erk/+7n5f9hSPr/TjT//040//9NNf//TTX9/04i
|
||||
nP9OIJD/TiCQ/00otP9LN/7/Szj//0s4/v9KOf7/Sjn+/0o6/v9JOv7/STv+/0Q30/8zKj3/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/rKOe/+7l3//u5uD/0cPR/8KwzP/x6uT/8evm/8zB6v9NN///TDf//0w3
|
||||
//9LOP//SzLl/0wgkv9MIJL/TCKX/0o48/9JOv7/STv+/0k7/v9IPP7/SDz8/0Y88/9DOdL/OjGD/zEp
|
||||
Lf8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/b2dj/+/n4f/v6OL/7+fj/+7m4//y6+b/8uzo/5WJ
|
||||
8P9KOf7/Sjr+/0o6/v9JO/7/SizC/0ohk/9KIZP/SSy6/0g9/v9HPf7/Rz7+/0Q85/83L2v/Mio1/zEp
|
||||
Lv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/OjIw/+be2f/w6eT/8erl//Lr
|
||||
5//y7Oj/8Ovo/15T9v9IPP7/SD3+/0c9/v9HPv7/SCSh/0ghlf9IIZX/RjXV/0ZA/v9FQP7/RUD7/zQt
|
||||
VP8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/7Or
|
||||
p//x6uX/8uzn//Pt6P/z7ur/z8np/0Y//v9GP/7/RkD+/0VA/v9FOuj/RiKX/0Yil/9GIpf/RDvj/0ND
|
||||
/v9DQ/7/Pz7V/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/3Vtav/y7Of/8+3o//Pu6v/07+v/lpLx/0RC/v9EQv7/Q0P+/0ND/v9EMcj/RCKZ/0Qi
|
||||
mf9EIpn/Qj7n/0FG/v9BRv7/PD7C/zEoKv82Jkf/NiZI/zYmSP82Jkj/NilR/zQ0bf80NG3/NDRt/zEr
|
||||
Of8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/z01M//r5eH/9O7q//Tv6//18O3/W1z3/0JF/v9CRf7/QUb+/0FG
|
||||
/f9CJ6n/QyKa/0Mimv9DIpr/QD7e/z9J/v8/Sf7/PUbk/zQnQv9DIpr/QyKa/0Mimv9DIpr/QDG9/zxN
|
||||
/v88Tv7/O07+/zIwVP8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv+6tLD/9fDs//Xx7f/U0ez/QEf+/0BI
|
||||
/v9ASP7/P0n+/z9C6/9BI53/QSOc/0EjnP9BI5z/PzjO/z1M/v89TP7/PE3+/zw1sv9BI5z/QSOc/0Ej
|
||||
nP9BJJ7/PEbn/zpQ/v85Uf7/OVH5/zErOP8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv97dHH/9fHt//by
|
||||
7/+Ym/H/Pkr+/z5L/v89S/7/PUz+/zk4pv8/I53/PyOe/z8jnv8/I57/Piyx/ztP/v87T/7/OlD+/zpQ
|
||||
/P87P9j/PDS8/zw2w/86SOn/OFP+/zhT/v83VP7/NUrM/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8+NjT/8u7r//by8P9bZ/j/PE3+/zxO/v87Tv7/O078/zIuSv85JX3/PSSg/z0koP89JKD/PSSg/zpG
|
||||
4/84Uv7/OFP+/zhT/v83VP7/N1T+/zdV/v82Vf7/Nlb+/zZW/v81V/7/Mjdt/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/wby6/9fX7/88Uf3/OlD+/zpR/v85Uf7/N0rY/zAoJ/8xJzX/OiSX/zsk
|
||||
of87JKH/OySh/zorrf83UfX/Nlb+/zZW/v81V/7/NVf+/zVY/v80WP7/NFn+/zNZ/v8ySbf/MCgn/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/gXt5/5qk8/84U/7/OFP+/zdU/v83VP7/ND6T/zAo
|
||||
Jv8wKCb/Mic9/zglkf85JaP/OSWj/zklo/84LrH/NFHv/zRZ/v8zWv7/M1r+/zJb/v8yW/7/Mlz+/zFK
|
||||
sv8wKi7/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/Qzw6/1Zp3P81UOT/NVDk/zVR
|
||||
5P81UeT/MTBL/zAoJv8wKCb/MCgm/zAoK/8zJ1v/NSaB/zYmj/82JZP/NieW/zQ8tf8yTtH/MVXh/zBU
|
||||
2P8wSq//MDZe/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/TAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb9MCgm3jAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCbeMCgmmTAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCaZMCgmLDAoJvkwKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJvkwKCYsAAAAADAoJncwKCb+MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/jAoJncAAAAAAAAAADAoJgEwKCZ3MCgm+TAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb5MCgmdzAoJgEAAAAAAAAAAAAA
|
||||
AAAAAAAAMCgmLDAoJpkwKCbeMCgm/TAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAo
|
||||
Jv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb/MCgm/zAoJv8wKCb9MCgm3jAoJpkwKCYsAAAAAAAA
|
||||
AAAAAAAA4AAAAAAHAACAAAAAAAEAAIAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
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
|
||||
</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,72 +1,126 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net472</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||
<AssemblyTitle>AssetStudio Mod by VaDiM</AssemblyTitle>
|
||||
<Version>0.16.8.1</Version>
|
||||
<AssemblyVersion>0.16.8.1</AssemblyVersion>
|
||||
<FileVersion>0.16.8.1</FileVersion>
|
||||
<Copyright>Copyright © Perfare 2018-2021</Copyright>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFrameworks>net472;net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||
<AssemblyTitle>ArknightsStudio by aelurum</AssemblyTitle>
|
||||
<AssemblyName>ArknightsStudioGUI</AssemblyName>
|
||||
<Version>1.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2023</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<DebugType>none</DebugType>
|
||||
<DebugSymbols>false</DebugSymbols>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<IsPublishable>false</IsPublishable>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
|
||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AssetStudioUtility\AssetStudioUtility.csproj" />
|
||||
<ProjectReference Include="..\AssetStudio\AssetStudio.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Update="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ContentWithTargetPath Include="..\LICENSE">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE</TargetPath>
|
||||
</ContentWithTargetPath>
|
||||
</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>
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Core-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="OpenTK" Version="3.1.0" />
|
||||
<PackageReference Include="OpenTK.GLControl" Version="3.1.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.8.0" />
|
||||
<PackageReference Include="OpenTK.Windowing.Desktop" Version="4.8.0" />
|
||||
<Reference Include="OpenTK.WinForms">
|
||||
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CustomAfterBuild" AfterTargets="AfterBuild">
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x86" ContinueOnError="true" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)x64" ContinueOnError="true" />
|
||||
</Target>
|
||||
</Project>
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<PackageReference Include="OpenTK" Version="3.3.3" />
|
||||
<PackageReference Include="OpenTK.GLControl" Version="3.3.3" />
|
||||
</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)' == '' OR '$(TargetFramework)' == 'net472' ">
|
||||
<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="$(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>
|
||||
|
||||
<!-- 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.
|
||||
The dll is cross-platform while the executable isn't -->
|
||||
<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\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>
|
||||
|
||||
<!-- No need to publish net472 build of AssetStudioGUI -->
|
||||
<Target Name="PublishNet472" AfterTargets="Publish" Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<Message Text="%0a NOTE: Publishing net472 build of AssetStudioGUI was disabled." Importance="high" />
|
||||
<Message Text=" Instead, use the binaries created after the build.%0a" Importance="high" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" $(RuntimeIdentifier.Contains('-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' AND '$(TargetFramework)' != 'net472' ">
|
||||
<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')) 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>
|
||||
|
||||
304
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
304
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@@ -41,6 +41,11 @@
|
||||
this.displayAll = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.enablePreview = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.displayInfo = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.akSeparator1 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.akTitleMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.akUseExternalAlphaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.akSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();
|
||||
this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -66,6 +71,8 @@
|
||||
this.toolStripMenuItem7 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.allLive2DModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -76,6 +83,7 @@
|
||||
this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
this.tabControl1 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage1 = new System.Windows.Forms.TabPage();
|
||||
@@ -88,7 +96,10 @@
|
||||
this.columnHeaderType = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeaderPathID = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.columnHeaderSize = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
this.listSearch = new System.Windows.Forms.TextBox();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.listSearch = new System.Windows.Forms.RichTextBox();
|
||||
this.listSearchHistory = new System.Windows.Forms.ComboBox();
|
||||
this.listSearchFilterMode = new System.Windows.Forms.ComboBox();
|
||||
this.tabPage3 = new System.Windows.Forms.TabPage();
|
||||
this.classesListView = new System.Windows.Forms.ListView();
|
||||
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||
@@ -118,6 +129,14 @@
|
||||
this.dumpTextBox = new System.Windows.Forms.TextBox();
|
||||
this.statusStrip1 = new System.Windows.Forms.StatusStrip();
|
||||
this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel();
|
||||
this.contextMenuStrip2 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.showRelatedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.selectAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.clearSelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.expandAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.collapseAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.timer = new System.Windows.Forms.Timer(this.components);
|
||||
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
|
||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
@@ -135,6 +154,7 @@
|
||||
this.tabControl1.SuspendLayout();
|
||||
this.tabPage1.SuspendLayout();
|
||||
this.tabPage2.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
this.tabPage3.SuspendLayout();
|
||||
this.progressbarPanel.SuspendLayout();
|
||||
this.tabControl2.SuspendLayout();
|
||||
@@ -145,6 +165,7 @@
|
||||
((System.ComponentModel.ISupportInitialize)(this.FMODvolumeBar)).BeginInit();
|
||||
this.tabPage5.SuspendLayout();
|
||||
this.statusStrip1.SuspendLayout();
|
||||
this.contextMenuStrip2.SuspendLayout();
|
||||
this.contextMenuStrip1.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
@@ -156,7 +177,8 @@
|
||||
this.modelToolStripMenuItem,
|
||||
this.exportToolStripMenuItem,
|
||||
this.filterTypeToolStripMenuItem,
|
||||
this.debugMenuItem});
|
||||
this.debugMenuItem,
|
||||
this.aboutToolStripMenuItem});
|
||||
this.menuStrip1.Location = new System.Drawing.Point(0, 0);
|
||||
this.menuStrip1.Name = "menuStrip1";
|
||||
this.menuStrip1.Size = new System.Drawing.Size(1264, 24);
|
||||
@@ -214,6 +236,11 @@
|
||||
this.displayAll,
|
||||
this.enablePreview,
|
||||
this.displayInfo,
|
||||
this.akSeparator1,
|
||||
this.akTitleMenuItem,
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem,
|
||||
this.akUseExternalAlphaToolStripMenuItem,
|
||||
this.akSeparator2,
|
||||
this.toolStripMenuItem14,
|
||||
this.showExpOpt});
|
||||
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
@@ -224,7 +251,7 @@
|
||||
//
|
||||
this.displayAll.CheckOnClick = true;
|
||||
this.displayAll.Name = "displayAll";
|
||||
this.displayAll.Size = new System.Drawing.Size(207, 22);
|
||||
this.displayAll.Size = new System.Drawing.Size(265, 22);
|
||||
this.displayAll.Text = "Display all assets";
|
||||
this.displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can expor" +
|
||||
"t the RAW file.";
|
||||
@@ -236,7 +263,7 @@
|
||||
this.enablePreview.CheckOnClick = true;
|
||||
this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.enablePreview.Name = "enablePreview";
|
||||
this.enablePreview.Size = new System.Drawing.Size(207, 22);
|
||||
this.enablePreview.Size = new System.Drawing.Size(265, 22);
|
||||
this.enablePreview.Text = "Enable preview";
|
||||
this.enablePreview.ToolTipText = "Toggle the loading and preview of readable assets, such as images, sounds, text, " +
|
||||
"etc.\r\nDisable preview if you have performance or compatibility issues.";
|
||||
@@ -248,30 +275,74 @@
|
||||
this.displayInfo.CheckOnClick = true;
|
||||
this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.displayInfo.Name = "displayInfo";
|
||||
this.displayInfo.Size = new System.Drawing.Size(207, 22);
|
||||
this.displayInfo.Text = "Display asset infromation";
|
||||
this.displayInfo.Size = new System.Drawing.Size(265, 22);
|
||||
this.displayInfo.Text = "Display asset information";
|
||||
this.displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, forma" +
|
||||
"t, audio bitrate, etc.";
|
||||
this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check);
|
||||
//
|
||||
// akSeparator1
|
||||
//
|
||||
this.akSeparator1.Name = "akSeparator1";
|
||||
this.akSeparator1.Size = new System.Drawing.Size(262, 6);
|
||||
//
|
||||
// akTitleMenuItem
|
||||
//
|
||||
this.akTitleMenuItem.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
|
||||
this.akTitleMenuItem.Enabled = false;
|
||||
this.akTitleMenuItem.Name = "akTitleMenuItem";
|
||||
this.akTitleMenuItem.ShowShortcutKeys = false;
|
||||
this.akTitleMenuItem.Size = new System.Drawing.Size(265, 22);
|
||||
this.akTitleMenuItem.Text = "Arknights";
|
||||
//
|
||||
// akFixFaceSpriteNamesToolStripMenuItem
|
||||
//
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.Checked = true;
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.CheckOnClick = true;
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.Name = "akFixFaceSpriteNamesToolStripMenuItem";
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.Size = new System.Drawing.Size(265, 22);
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.Text = "Fix names of avg character sprites";
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.ToolTipText = "Rename face sprites with numeric names to correct ones";
|
||||
this.akFixFaceSpriteNamesToolStripMenuItem.CheckedChanged += new System.EventHandler(this.akFixFaceSpriteNamesToolStripMenuItem_Check);
|
||||
//
|
||||
// akUseExternalAlphaToolStripMenuItem
|
||||
//
|
||||
this.akUseExternalAlphaToolStripMenuItem.Checked = true;
|
||||
this.akUseExternalAlphaToolStripMenuItem.CheckOnClick = true;
|
||||
this.akUseExternalAlphaToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.akUseExternalAlphaToolStripMenuItem.Name = "akUseExternalAlphaToolStripMenuItem";
|
||||
this.akUseExternalAlphaToolStripMenuItem.Size = new System.Drawing.Size(265, 22);
|
||||
this.akUseExternalAlphaToolStripMenuItem.Text = "Use external alpha texture for sprites";
|
||||
this.akUseExternalAlphaToolStripMenuItem.ToolTipText = "Trying to find an external alpha texture for preview/export sprite assets (Skins," +
|
||||
" Char arts, Avg char arts, etc.)";
|
||||
this.akUseExternalAlphaToolStripMenuItem.CheckedChanged += new System.EventHandler(this.akUseExternalAlphaToolStripMenuItem_Check);
|
||||
//
|
||||
// akSeparator2
|
||||
//
|
||||
this.akSeparator2.Name = "akSeparator2";
|
||||
this.akSeparator2.Size = new System.Drawing.Size(262, 6);
|
||||
//
|
||||
// toolStripMenuItem14
|
||||
//
|
||||
this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.specifyUnityVersion});
|
||||
this.toolStripMenuItem14.Name = "toolStripMenuItem14";
|
||||
this.toolStripMenuItem14.Size = new System.Drawing.Size(207, 22);
|
||||
this.toolStripMenuItem14.Size = new System.Drawing.Size(265, 22);
|
||||
this.toolStripMenuItem14.Text = "Specify Unity version";
|
||||
//
|
||||
// specifyUnityVersion
|
||||
//
|
||||
this.specifyUnityVersion.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
this.specifyUnityVersion.Font = new System.Drawing.Font("Microsoft YaHei UI", 9F);
|
||||
this.specifyUnityVersion.Name = "specifyUnityVersion";
|
||||
this.specifyUnityVersion.Size = new System.Drawing.Size(100, 23);
|
||||
this.specifyUnityVersion.ToolTipText = "Specify full Unity version, including letters at the end\r\nExample: 2017.4.39f1";
|
||||
//
|
||||
// showExpOpt
|
||||
//
|
||||
this.showExpOpt.Name = "showExpOpt";
|
||||
this.showExpOpt.Size = new System.Drawing.Size(207, 22);
|
||||
this.showExpOpt.Size = new System.Drawing.Size(265, 22);
|
||||
this.showExpOpt.Text = "Export options";
|
||||
this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click);
|
||||
//
|
||||
@@ -339,6 +410,8 @@
|
||||
this.toolStripSeparator4,
|
||||
this.toolStripMenuItem2,
|
||||
this.toolStripMenuItem3,
|
||||
this.toolStripSeparator6,
|
||||
this.allLive2DModelsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.toolStripMenuItem10});
|
||||
this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
|
||||
@@ -445,6 +518,18 @@
|
||||
this.toolStripMenuItem9.Text = "Filtered assets";
|
||||
this.toolStripMenuItem9.Click += new System.EventHandler(this.toolStripMenuItem9_Click);
|
||||
//
|
||||
// toolStripSeparator6
|
||||
//
|
||||
this.toolStripSeparator6.Name = "toolStripSeparator6";
|
||||
this.toolStripSeparator6.Size = new System.Drawing.Size(263, 6);
|
||||
//
|
||||
// allLive2DModelsToolStripMenuItem
|
||||
//
|
||||
this.allLive2DModelsToolStripMenuItem.Name = "allLive2DModelsToolStripMenuItem";
|
||||
this.allLive2DModelsToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
|
||||
this.allLive2DModelsToolStripMenuItem.Text = "Live2D Cubism models";
|
||||
this.allLive2DModelsToolStripMenuItem.Click += new System.EventHandler(this.allLive2DModelsToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator2
|
||||
//
|
||||
this.toolStripSeparator2.Name = "toolStripSeparator2";
|
||||
@@ -523,6 +608,13 @@
|
||||
this.exportClassStructuresMenuItem.Text = "Export class structures";
|
||||
this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click);
|
||||
//
|
||||
// aboutToolStripMenuItem
|
||||
//
|
||||
this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem";
|
||||
this.aboutToolStripMenuItem.Size = new System.Drawing.Size(52, 20);
|
||||
this.aboutToolStripMenuItem.Text = "About";
|
||||
this.aboutToolStripMenuItem.Click += new System.EventHandler(this.aboutToolStripMenuItem_Click);
|
||||
//
|
||||
// splitContainer1
|
||||
//
|
||||
this.splitContainer1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
|
||||
@@ -582,6 +674,7 @@
|
||||
this.sceneTreeView.Size = new System.Drawing.Size(472, 587);
|
||||
this.sceneTreeView.TabIndex = 1;
|
||||
this.sceneTreeView.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.sceneTreeView_AfterCheck);
|
||||
this.sceneTreeView.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.sceneTreeView_NodeMouseClick);
|
||||
//
|
||||
// treeSearch
|
||||
//
|
||||
@@ -590,7 +683,7 @@
|
||||
this.treeSearch.Location = new System.Drawing.Point(0, 0);
|
||||
this.treeSearch.Name = "treeSearch";
|
||||
this.treeSearch.Size = new System.Drawing.Size(472, 20);
|
||||
this.treeSearch.TabIndex = 0;
|
||||
this.treeSearch.TabIndex = 2;
|
||||
this.treeSearch.Text = " Search ";
|
||||
this.treeSearch.TextChanged += new System.EventHandler(this.treeSearch_TextChanged);
|
||||
this.treeSearch.Enter += new System.EventHandler(this.treeSearch_Enter);
|
||||
@@ -600,7 +693,7 @@
|
||||
// tabPage2
|
||||
//
|
||||
this.tabPage2.Controls.Add(this.assetListView);
|
||||
this.tabPage2.Controls.Add(this.listSearch);
|
||||
this.tabPage2.Controls.Add(this.panel1);
|
||||
this.tabPage2.Location = new System.Drawing.Point(4, 22);
|
||||
this.tabPage2.Name = "tabPage2";
|
||||
this.tabPage2.Size = new System.Drawing.Size(472, 607);
|
||||
@@ -620,9 +713,9 @@
|
||||
this.assetListView.FullRowSelect = true;
|
||||
this.assetListView.GridLines = true;
|
||||
this.assetListView.HideSelection = false;
|
||||
this.assetListView.Location = new System.Drawing.Point(0, 20);
|
||||
this.assetListView.Location = new System.Drawing.Point(0, 23);
|
||||
this.assetListView.Name = "assetListView";
|
||||
this.assetListView.Size = new System.Drawing.Size(472, 587);
|
||||
this.assetListView.Size = new System.Drawing.Size(472, 584);
|
||||
this.assetListView.TabIndex = 1;
|
||||
this.assetListView.UseCompatibleStateImageBehavior = false;
|
||||
this.assetListView.View = System.Windows.Forms.View.Details;
|
||||
@@ -658,19 +751,68 @@
|
||||
this.columnHeaderSize.Text = "Size";
|
||||
this.columnHeaderSize.Width = 50;
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Controls.Add(this.listSearch);
|
||||
this.panel1.Controls.Add(this.listSearchHistory);
|
||||
this.panel1.Controls.Add(this.listSearchFilterMode);
|
||||
this.panel1.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.panel1.Location = new System.Drawing.Point(0, 0);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(472, 23);
|
||||
this.panel1.TabIndex = 2;
|
||||
//
|
||||
// listSearch
|
||||
//
|
||||
this.listSearch.Dock = System.Windows.Forms.DockStyle.Top;
|
||||
this.listSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.listSearch.BackColor = System.Drawing.Color.White;
|
||||
this.listSearch.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.listSearch.DetectUrls = false;
|
||||
this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.listSearch.Location = new System.Drawing.Point(0, 0);
|
||||
this.listSearch.Location = new System.Drawing.Point(3, 3);
|
||||
this.listSearch.Multiline = false;
|
||||
this.listSearch.Name = "listSearch";
|
||||
this.listSearch.Size = new System.Drawing.Size(472, 20);
|
||||
this.listSearch.TabIndex = 0;
|
||||
this.listSearch.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.None;
|
||||
this.listSearch.Size = new System.Drawing.Size(331, 16);
|
||||
this.listSearch.TabIndex = 3;
|
||||
this.listSearch.Text = " Filter ";
|
||||
this.listSearch.WordWrap = false;
|
||||
this.listSearch.TextChanged += new System.EventHandler(this.ListSearchTextChanged);
|
||||
this.listSearch.Enter += new System.EventHandler(this.listSearch_Enter);
|
||||
this.listSearch.Leave += new System.EventHandler(this.listSearch_Leave);
|
||||
//
|
||||
// listSearchHistory
|
||||
//
|
||||
this.listSearchHistory.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
|
||||
this.listSearchHistory.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
|
||||
this.listSearchHistory.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||
this.listSearchHistory.Location = new System.Drawing.Point(0, 0);
|
||||
this.listSearchHistory.Name = "listSearchHistory";
|
||||
this.listSearchHistory.Size = new System.Drawing.Size(351, 21);
|
||||
this.listSearchHistory.TabIndex = 2;
|
||||
this.listSearchHistory.TabStop = false;
|
||||
this.listSearchHistory.SelectedIndexChanged += new System.EventHandler(this.listSearchHistory_SelectedIndexChanged);
|
||||
this.listSearchHistory.Enter += new System.EventHandler(this.listSearch_Enter);
|
||||
this.listSearchHistory.Leave += new System.EventHandler(this.listSearch_Leave);
|
||||
//
|
||||
// listSearchFilterMode
|
||||
//
|
||||
this.listSearchFilterMode.Dock = System.Windows.Forms.DockStyle.Right;
|
||||
this.listSearchFilterMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.listSearchFilterMode.DropDownWidth = 150;
|
||||
this.listSearchFilterMode.Items.AddRange(new object[] {
|
||||
"Include",
|
||||
"Exclude",
|
||||
"Regex (Name)",
|
||||
"Regex (Container)"});
|
||||
this.listSearchFilterMode.Location = new System.Drawing.Point(351, 0);
|
||||
this.listSearchFilterMode.Name = "listSearchFilterMode";
|
||||
this.listSearchFilterMode.Size = new System.Drawing.Size(121, 21);
|
||||
this.listSearchFilterMode.TabIndex = 3;
|
||||
this.listSearchFilterMode.SelectedIndexChanged += new System.EventHandler(this.listSearchFilterMode_SelectedIndexChanged);
|
||||
//
|
||||
// tabPage3
|
||||
//
|
||||
this.tabPage3.Controls.Add(this.classesListView);
|
||||
@@ -723,6 +865,7 @@
|
||||
// progressBar1
|
||||
//
|
||||
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.Name = "progressBar1";
|
||||
this.progressBar1.Size = new System.Drawing.Size(478, 18);
|
||||
@@ -774,6 +917,7 @@
|
||||
this.assetInfoLabel.AutoSize = true;
|
||||
this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
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.Name = "assetInfoLabel";
|
||||
this.assetInfoLabel.Size = new System.Drawing.Size(0, 13);
|
||||
@@ -801,8 +945,10 @@
|
||||
//
|
||||
// FMODcopyright
|
||||
//
|
||||
this.FMODcopyright.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODcopyright.AutoSize = true;
|
||||
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.Name = "FMODcopyright";
|
||||
this.FMODcopyright.Size = new System.Drawing.Size(283, 13);
|
||||
@@ -811,35 +957,44 @@
|
||||
//
|
||||
// FMODinfoLabel
|
||||
//
|
||||
this.FMODinfoLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODinfoLabel.AutoSize = true;
|
||||
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODinfoLabel.Location = new System.Drawing.Point(269, 255);
|
||||
this.FMODinfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255);
|
||||
this.FMODinfoLabel.Name = "FMODinfoLabel";
|
||||
this.FMODinfoLabel.Size = new System.Drawing.Size(0, 13);
|
||||
this.FMODinfoLabel.TabIndex = 8;
|
||||
//
|
||||
// FMODtimerLabel
|
||||
//
|
||||
this.FMODtimerLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODtimerLabel.AutoSize = true;
|
||||
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODtimerLabel.Location = new System.Drawing.Point(404, 255);
|
||||
this.FMODtimerLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253);
|
||||
this.FMODtimerLabel.Name = "FMODtimerLabel";
|
||||
this.FMODtimerLabel.Size = new System.Drawing.Size(155, 13);
|
||||
this.FMODtimerLabel.Size = new System.Drawing.Size(102, 13);
|
||||
this.FMODtimerLabel.TabIndex = 7;
|
||||
this.FMODtimerLabel.Text = "0:00.0 / 0:00.0";
|
||||
this.FMODtimerLabel.TextAlign = System.Drawing.ContentAlignment.TopRight;
|
||||
this.FMODtimerLabel.Text = "00:00.00 / 00:00.00";
|
||||
//
|
||||
// FMODstatusLabel
|
||||
//
|
||||
this.FMODstatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODstatusLabel.AutoSize = true;
|
||||
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODstatusLabel.Location = new System.Drawing.Point(213, 255);
|
||||
this.FMODstatusLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255);
|
||||
this.FMODstatusLabel.Name = "FMODstatusLabel";
|
||||
this.FMODstatusLabel.Size = new System.Drawing.Size(50, 13);
|
||||
this.FMODstatusLabel.Size = new System.Drawing.Size(47, 13);
|
||||
this.FMODstatusLabel.TabIndex = 6;
|
||||
this.FMODstatusLabel.Text = "Stopped";
|
||||
//
|
||||
// FMODprogressBar
|
||||
//
|
||||
this.FMODprogressBar.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODprogressBar.AutoSize = false;
|
||||
this.FMODprogressBar.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODprogressBar.Location = new System.Drawing.Point(213, 274);
|
||||
this.FMODprogressBar.Maximum = 1000;
|
||||
this.FMODprogressBar.Name = "FMODprogressBar";
|
||||
@@ -852,6 +1007,8 @@
|
||||
//
|
||||
// FMODvolumeBar
|
||||
//
|
||||
this.FMODvolumeBar.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODvolumeBar.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODvolumeBar.LargeChange = 2;
|
||||
this.FMODvolumeBar.Location = new System.Drawing.Point(460, 303);
|
||||
this.FMODvolumeBar.Name = "FMODvolumeBar";
|
||||
@@ -863,7 +1020,9 @@
|
||||
//
|
||||
// FMODloopButton
|
||||
//
|
||||
this.FMODloopButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
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.Name = "FMODloopButton";
|
||||
this.FMODloopButton.Size = new System.Drawing.Size(55, 46);
|
||||
@@ -875,6 +1034,8 @@
|
||||
//
|
||||
// FMODstopButton
|
||||
//
|
||||
this.FMODstopButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODstopButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODstopButton.Location = new System.Drawing.Point(338, 303);
|
||||
this.FMODstopButton.Name = "FMODstopButton";
|
||||
this.FMODstopButton.Size = new System.Drawing.Size(55, 46);
|
||||
@@ -885,6 +1046,8 @@
|
||||
//
|
||||
// FMODpauseButton
|
||||
//
|
||||
this.FMODpauseButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODpauseButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODpauseButton.Location = new System.Drawing.Point(277, 303);
|
||||
this.FMODpauseButton.Name = "FMODpauseButton";
|
||||
this.FMODpauseButton.Size = new System.Drawing.Size(55, 46);
|
||||
@@ -895,6 +1058,8 @@
|
||||
//
|
||||
// FMODplayButton
|
||||
//
|
||||
this.FMODplayButton.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODplayButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODplayButton.Location = new System.Drawing.Point(216, 303);
|
||||
this.FMODplayButton.Name = "FMODplayButton";
|
||||
this.FMODplayButton.Size = new System.Drawing.Size(55, 46);
|
||||
@@ -936,7 +1101,7 @@
|
||||
// textPreviewBox
|
||||
//
|
||||
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.Multiline = true;
|
||||
this.textPreviewBox.Name = "textPreviewBox";
|
||||
@@ -1001,6 +1166,65 @@
|
||||
this.toolStripStatusLabel1.Text = "Ready to go";
|
||||
this.toolStripStatusLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// contextMenuStrip2
|
||||
//
|
||||
this.contextMenuStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.showRelatedAssetsToolStripMenuItem,
|
||||
this.toolStripSeparator7,
|
||||
this.selectAllToolStripMenuItem,
|
||||
this.clearSelectionToolStripMenuItem,
|
||||
this.toolStripSeparator5,
|
||||
this.expandAllToolStripMenuItem,
|
||||
this.collapseAllToolStripMenuItem});
|
||||
this.contextMenuStrip2.Name = "contextMenuStrip2";
|
||||
this.contextMenuStrip2.Size = new System.Drawing.Size(152, 126);
|
||||
this.contextMenuStrip2.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip2_Opening);
|
||||
//
|
||||
// showRelatedAssetsToolStripMenuItem
|
||||
//
|
||||
this.showRelatedAssetsToolStripMenuItem.Name = "showRelatedAssetsToolStripMenuItem";
|
||||
this.showRelatedAssetsToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.showRelatedAssetsToolStripMenuItem.Text = "Related assets";
|
||||
this.showRelatedAssetsToolStripMenuItem.Click += new System.EventHandler(this.showRelatedAssetsToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator7
|
||||
//
|
||||
this.toolStripSeparator7.Name = "toolStripSeparator7";
|
||||
this.toolStripSeparator7.Size = new System.Drawing.Size(148, 6);
|
||||
//
|
||||
// selectAllToolStripMenuItem
|
||||
//
|
||||
this.selectAllToolStripMenuItem.Name = "selectAllToolStripMenuItem";
|
||||
this.selectAllToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.selectAllToolStripMenuItem.Text = "Select all";
|
||||
this.selectAllToolStripMenuItem.Click += new System.EventHandler(this.selectAllToolStripMenuItem_Click);
|
||||
//
|
||||
// clearSelectionToolStripMenuItem
|
||||
//
|
||||
this.clearSelectionToolStripMenuItem.Name = "clearSelectionToolStripMenuItem";
|
||||
this.clearSelectionToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.clearSelectionToolStripMenuItem.Text = "Clear selection";
|
||||
this.clearSelectionToolStripMenuItem.Click += new System.EventHandler(this.clearSelectionToolStripMenuItem_Click);
|
||||
//
|
||||
// toolStripSeparator5
|
||||
//
|
||||
this.toolStripSeparator5.Name = "toolStripSeparator5";
|
||||
this.toolStripSeparator5.Size = new System.Drawing.Size(148, 6);
|
||||
//
|
||||
// expandAllToolStripMenuItem
|
||||
//
|
||||
this.expandAllToolStripMenuItem.Name = "expandAllToolStripMenuItem";
|
||||
this.expandAllToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.expandAllToolStripMenuItem.Text = "Expand all";
|
||||
this.expandAllToolStripMenuItem.Click += new System.EventHandler(this.expandAllToolStripMenuItem_Click);
|
||||
//
|
||||
// collapseAllToolStripMenuItem
|
||||
//
|
||||
this.collapseAllToolStripMenuItem.Name = "collapseAllToolStripMenuItem";
|
||||
this.collapseAllToolStripMenuItem.Size = new System.Drawing.Size(151, 22);
|
||||
this.collapseAllToolStripMenuItem.Text = "Collapse all";
|
||||
this.collapseAllToolStripMenuItem.Click += new System.EventHandler(this.collapseAllToolStripMenuItem_Click);
|
||||
//
|
||||
// timer
|
||||
//
|
||||
this.timer.Interval = 10;
|
||||
@@ -1024,7 +1248,7 @@
|
||||
this.goToSceneHierarchyToolStripMenuItem,
|
||||
this.showOriginalFileToolStripMenuItem});
|
||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
this.contextMenuStrip1.Size = new System.Drawing.Size(304, 158);
|
||||
this.contextMenuStrip1.Size = new System.Drawing.Size(304, 136);
|
||||
//
|
||||
// copyToolStripMenuItem
|
||||
//
|
||||
@@ -1074,8 +1298,6 @@
|
||||
// AssetStudioGUIForm
|
||||
//
|
||||
this.AllowDrop = true;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(1264, 681);
|
||||
this.Controls.Add(this.splitContainer1);
|
||||
this.Controls.Add(this.menuStrip1);
|
||||
@@ -1085,7 +1307,7 @@
|
||||
this.MinimumSize = new System.Drawing.Size(620, 400);
|
||||
this.Name = "AssetStudioGUIForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "AssetStudioGUI";
|
||||
this.Text = "AssetStudioModGUI";
|
||||
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragDrop);
|
||||
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragEnter);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
|
||||
@@ -1100,7 +1322,7 @@
|
||||
this.tabPage1.ResumeLayout(false);
|
||||
this.tabPage1.PerformLayout();
|
||||
this.tabPage2.ResumeLayout(false);
|
||||
this.tabPage2.PerformLayout();
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.tabPage3.ResumeLayout(false);
|
||||
this.progressbarPanel.ResumeLayout(false);
|
||||
this.tabControl2.ResumeLayout(false);
|
||||
@@ -1115,6 +1337,7 @@
|
||||
this.tabPage5.PerformLayout();
|
||||
this.statusStrip1.ResumeLayout(false);
|
||||
this.statusStrip1.PerformLayout();
|
||||
this.contextMenuStrip2.ResumeLayout(false);
|
||||
this.contextMenuStrip1.ResumeLayout(false);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
@@ -1130,10 +1353,8 @@
|
||||
private System.Windows.Forms.TabPage tabPage1;
|
||||
private System.Windows.Forms.TabPage tabPage2;
|
||||
private System.Windows.Forms.TextBox treeSearch;
|
||||
private System.Windows.Forms.TextBox listSearch;
|
||||
private System.Windows.Forms.ToolStripMenuItem loadFileToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem loadFolderToolStripMenuItem;
|
||||
private System.Windows.Forms.ListView assetListView;
|
||||
private System.Windows.Forms.ColumnHeader columnHeaderName;
|
||||
private System.Windows.Forms.ColumnHeader columnHeaderSize;
|
||||
private System.Windows.Forms.ColumnHeader columnHeaderType;
|
||||
@@ -1220,6 +1441,27 @@
|
||||
private System.Windows.Forms.ToolStripTextBox specifyUnityVersion;
|
||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem15;
|
||||
private System.Windows.Forms.ToolStripMenuItem dumpSelectedAssetsToolStripMenuItem;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip2;
|
||||
private System.Windows.Forms.ToolStripMenuItem selectAllToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem clearSelectionToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
||||
private System.Windows.Forms.ToolStripMenuItem collapseAllToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem expandAllToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
|
||||
private System.Windows.Forms.Panel panel1;
|
||||
private System.Windows.Forms.ComboBox listSearchFilterMode;
|
||||
private System.Windows.Forms.ComboBox listSearchHistory;
|
||||
private System.Windows.Forms.RichTextBox listSearch;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
||||
private System.Windows.Forms.ToolStripMenuItem allLive2DModelsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
|
||||
private System.Windows.Forms.ListView assetListView;
|
||||
private System.Windows.Forms.ToolStripMenuItem akFixFaceSpriteNamesToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem akUseExternalAlphaToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator akSeparator1;
|
||||
private System.Windows.Forms.ToolStripMenuItem akTitleMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator akSeparator2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -141,6 +141,9 @@ The quick brown fox jumps over the lazy dog. 1234567890</value>
|
||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>432, 17</value>
|
||||
</metadata>
|
||||
<metadata name="contextMenuStrip2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>775, 21</value>
|
||||
</metadata>
|
||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>553, 17</value>
|
||||
</metadata>
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
// This code developed by Dot Net Perls
|
||||
using System.Collections;
|
||||
// AlphanumComparatorFast mod by aelurum
|
||||
// Original code was developed by Dot Net Perls
|
||||
// For more detail visit: https://www.dotnetperls.com/alphanumeric-sorting
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
internal class AlphanumComparatorFast : IComparer
|
||||
internal class AlphanumComparatorFast : IComparer<string>
|
||||
{
|
||||
public int Compare(object x, object y)
|
||||
public int Compare(string s1, string s2)
|
||||
{
|
||||
if (!(x is string s1))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!(y is string s2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int len1 = s1.Length;
|
||||
int len2 = s2.Length;
|
||||
int marker1 = 0;
|
||||
@@ -69,20 +63,23 @@ namespace AssetStudioGUI
|
||||
|
||||
// If we have collected numbers, compare them numerically.
|
||||
// Otherwise, if we have strings, compare them alphabetically.
|
||||
string str1 = new string(space1);
|
||||
string str2 = new string(space2);
|
||||
|
||||
int result;
|
||||
|
||||
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
|
||||
{
|
||||
int thisNumericChunk = int.Parse(str1);
|
||||
int thatNumericChunk = int.Parse(str2);
|
||||
result = thisNumericChunk.CompareTo(thatNumericChunk);
|
||||
if (long.TryParse(new string(space1), out long thisNumericChunk) &&
|
||||
long.TryParse(new string(space2), out long thatNumericChunk))
|
||||
{
|
||||
result = thisNumericChunk.CompareTo(thatNumericChunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MemoryExtensions.CompareTo(space1, space2, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = str1.CompareTo(str2);
|
||||
result = MemoryExtensions.CompareTo(space1, space2, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
|
||||
99
AssetStudioGUI/Components/AlphanumComparatorFastNet.cs
Normal file
99
AssetStudioGUI/Components/AlphanumComparatorFastNet.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
// AlphanumComparatorFast mod by aelurum
|
||||
// Original code was developed by Dot Net Perls
|
||||
// For more detail visit: https://www.dotnetperls.com/alphanumeric-sorting
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
internal class AlphanumComparatorFastNet : IComparer<string>
|
||||
{
|
||||
public int Compare(string s1, string s2)
|
||||
{
|
||||
const int maxStackSize = 256;
|
||||
int len1 = s1.Length;
|
||||
int len2 = s2.Length;
|
||||
int marker1 = 0;
|
||||
int marker2 = 0;
|
||||
|
||||
// Some buffers we can build up characters in for each chunk.
|
||||
Span<char> space1 = len1 > maxStackSize ? new char[len1] : stackalloc char[len1];
|
||||
Span<char> space2 = len2 > maxStackSize ? new char[len2] : stackalloc char[len2];
|
||||
|
||||
// Walk through two the strings with two markers.
|
||||
while (marker1 < len1 && marker2 < len2)
|
||||
{
|
||||
char ch1 = s1[marker1];
|
||||
char ch2 = s2[marker2];
|
||||
|
||||
int loc1 = 0;
|
||||
int loc2 = 0;
|
||||
space1.Clear();
|
||||
space2.Clear();
|
||||
|
||||
// Walk through all following characters that are digits or
|
||||
// characters in BOTH strings starting at the appropriate marker.
|
||||
// Collect char arrays.
|
||||
do
|
||||
{
|
||||
space1[loc1++] = ch1;
|
||||
marker1++;
|
||||
|
||||
if (marker1 < len1)
|
||||
{
|
||||
ch1 = s1[marker1];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch1) == char.IsDigit(space1[0]));
|
||||
|
||||
do
|
||||
{
|
||||
space2[loc2++] = ch2;
|
||||
marker2++;
|
||||
|
||||
if (marker2 < len2)
|
||||
{
|
||||
ch2 = s2[marker2];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (char.IsDigit(ch2) == char.IsDigit(space2[0]));
|
||||
|
||||
// If we have collected numbers, compare them numerically.
|
||||
// Otherwise, if we have strings, compare them alphabetically.
|
||||
int result;
|
||||
|
||||
if (char.IsDigit(space1[0]) && char.IsDigit(space2[0]))
|
||||
{
|
||||
if (long.TryParse(space1, out long thisNumericChunk) &&
|
||||
long.TryParse(space2, out long thatNumericChunk))
|
||||
{
|
||||
result = thisNumericChunk.CompareTo(thatNumericChunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MemoryExtensions.CompareTo(space1, space2, StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = MemoryExtensions.CompareTo(space1, space2, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
274
AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs
Normal file
274
AssetStudioGUI/Components/Arknights/AkSpriteHelper.cs
Normal file
@@ -0,0 +1,274 @@
|
||||
using Arknights.PortraitSpriteMono;
|
||||
using AssetStudio;
|
||||
using AssetStudioGUI;
|
||||
using AssetStudioGUI.Properties;
|
||||
using Newtonsoft.Json;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp.Processing.Processors.Transforms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal static class AkSpriteHelper
|
||||
{
|
||||
public static Texture2D TryFindAlphaTex(AssetItem assetItem, AvgSprite avgSprite, bool isAvgSprite)
|
||||
{
|
||||
Sprite m_Sprite = (Sprite)assetItem.Asset;
|
||||
var imgType = "arts/characters";
|
||||
if (m_Sprite.m_RD.alphaTexture.m_PathID == 0)
|
||||
{
|
||||
if (isAvgSprite)
|
||||
{
|
||||
if (avgSprite?.FullAlphaTexture != null)
|
||||
return avgSprite.FullAlphaTexture;
|
||||
|
||||
imgType = "avg/characters"; //since the avg hub was not found for some reason, let's try to find alpha tex by name
|
||||
}
|
||||
var spriteFullName = Path.GetFileNameWithoutExtension(assetItem.Container);
|
||||
foreach (var item in Studio.exportableAssets)
|
||||
{
|
||||
if (item.Type == ClassIDType.Texture2D)
|
||||
{
|
||||
if (item.Container.Contains(imgType) && item.Container.Contains($"illust_{m_Sprite.m_Name}_material") && item.Text.Contains("[alpha]"))
|
||||
return (Texture2D)item.Asset;
|
||||
else if (item.Container.Contains(imgType) && item.Container.Contains(spriteFullName) && item.Text == $"{m_Sprite.m_Name}[alpha]")
|
||||
return (Texture2D)item.Asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Image<Bgra32> AkGetImage(this Sprite m_Sprite, AvgSprite avgSprite = null, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On)
|
||||
{
|
||||
if (m_Sprite.m_RD.texture.TryGet(out var m_Texture2D) && m_Sprite.m_RD.alphaTexture.TryGet(out var m_AlphaTexture2D) && spriteMaskMode != SpriteMaskMode.Off)
|
||||
{
|
||||
Image<Bgra32> tex = null;
|
||||
Image<Bgra32> alphaTex = null;
|
||||
|
||||
if (avgSprite != null && avgSprite.IsHubParsed)
|
||||
{
|
||||
alphaTex = m_AlphaTexture2D.ConvertToImage(true);
|
||||
if (avgSprite.IsFaceSprite)
|
||||
{
|
||||
var faceImage = m_Texture2D.ConvertToImage(true);
|
||||
var faceAlpha = avgSprite.FaceSpriteAlphaTexture.ConvertToImage(true);
|
||||
if (faceImage.Size() != avgSprite.FaceSize)
|
||||
{
|
||||
faceImage.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
|
||||
faceAlpha.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
|
||||
}
|
||||
tex = avgSprite.FullTexture.ConvertToImage(true);
|
||||
tex.Mutate(x => x.DrawImage(faceImage, location: avgSprite.FacePos, opacity: 1f));
|
||||
alphaTex.Mutate(x => x.DrawImage(faceAlpha, location: avgSprite.FacePos, opacity: 1f));
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = m_Texture2D.ConvertToImage(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spriteMaskMode != SpriteMaskMode.MaskOnly)
|
||||
{
|
||||
tex = CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
}
|
||||
alphaTex = CutImage(m_AlphaTexture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
}
|
||||
|
||||
return ImageRender(tex, alphaTex, spriteMaskMode);
|
||||
}
|
||||
else if (m_Sprite.m_RD.texture.TryGet(out m_Texture2D))
|
||||
{
|
||||
return CutImage(m_Texture2D.ConvertToImage(false), m_Sprite.m_RD.textureRect, m_Sprite.m_RD.downscaleMultiplier);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Image<Bgra32> AkGetImage(this PortraitSprite portraitSprite, SpriteMaskMode spriteMaskMode = SpriteMaskMode.On)
|
||||
{
|
||||
if (portraitSprite.Texture != null && portraitSprite.AlphaTexture != null)
|
||||
{
|
||||
Image<Bgra32> tex = null;
|
||||
Image<Bgra32> alphaTex = null;
|
||||
|
||||
if (spriteMaskMode != SpriteMaskMode.MaskOnly)
|
||||
{
|
||||
tex = CutImage(portraitSprite.Texture.ConvertToImage(false), portraitSprite.TextureRect, portraitSprite.DownscaleMultiplier, portraitSprite.Rotate);
|
||||
}
|
||||
if (spriteMaskMode != SpriteMaskMode.Off)
|
||||
{
|
||||
alphaTex = CutImage(portraitSprite.AlphaTexture.ConvertToImage(false), portraitSprite.TextureRect, portraitSprite.DownscaleMultiplier, portraitSprite.Rotate);
|
||||
}
|
||||
|
||||
return ImageRender(tex, alphaTex, spriteMaskMode);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<PortraitSprite> GeneratePortraits(AssetItem asset)
|
||||
{
|
||||
var portraits = new List<PortraitSprite>();
|
||||
|
||||
var portraitsDict = ((MonoBehaviour)asset.Asset).ToType();
|
||||
if (portraitsDict == null)
|
||||
{
|
||||
Logger.Warning("Portraits MonoBehaviour is not readable.");
|
||||
return portraits;
|
||||
}
|
||||
var portraitsJson = JsonConvert.SerializeObject(portraitsDict);
|
||||
var portraitsData = JsonConvert.DeserializeObject<PortraitSpriteConfig>(portraitsJson);
|
||||
|
||||
var atlasTex = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == portraitsData._atlas.Texture.m_PathID).Asset;
|
||||
var atlasAlpha = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == portraitsData._atlas.Alpha.m_PathID).Asset;
|
||||
|
||||
foreach (var portraitData in portraitsData._sprites)
|
||||
{
|
||||
var portraitSprite = new PortraitSprite()
|
||||
{
|
||||
Name = portraitData.Name,
|
||||
AssetsFile = atlasTex.assetsFile,
|
||||
Container = asset.Container,
|
||||
Texture = atlasTex,
|
||||
AlphaTexture = atlasAlpha,
|
||||
TextureRect = new Rectf(portraitData.Rect.X, portraitData.Rect.Y, portraitData.Rect.W, portraitData.Rect.H),
|
||||
Rotate = portraitData.Rotate,
|
||||
};
|
||||
portraits.Add(portraitSprite);
|
||||
}
|
||||
|
||||
return portraits;
|
||||
}
|
||||
|
||||
private static Image<Bgra32> ImageRender(Image<Bgra32> tex, Image<Bgra32> alpha, SpriteMaskMode maskMode)
|
||||
{
|
||||
switch (maskMode)
|
||||
{
|
||||
case SpriteMaskMode.On:
|
||||
tex.ApplyRGBMask(alpha, isPreview: true);
|
||||
return tex;
|
||||
case SpriteMaskMode.Off:
|
||||
alpha?.Dispose();
|
||||
return tex;
|
||||
case SpriteMaskMode.MaskOnly:
|
||||
tex?.Dispose();
|
||||
return alpha;
|
||||
case SpriteMaskMode.Export:
|
||||
tex.ApplyRGBMask(alpha);
|
||||
return tex;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IResampler GetResampler(bool isPreview)
|
||||
{
|
||||
IResampler resampler;
|
||||
if (isPreview)
|
||||
{
|
||||
resampler = KnownResamplers.NearestNeighbor;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Settings.Default.resamplerIndex)
|
||||
{
|
||||
case 0:
|
||||
resampler = KnownResamplers.NearestNeighbor;
|
||||
break;
|
||||
case 1: //Bilinear
|
||||
resampler = KnownResamplers.Triangle;
|
||||
break;
|
||||
case 2:
|
||||
resampler = KnownResamplers.Bicubic;
|
||||
break;
|
||||
case 3:
|
||||
resampler = KnownResamplers.MitchellNetravali;
|
||||
break;
|
||||
case 4:
|
||||
resampler = KnownResamplers.Spline;
|
||||
break;
|
||||
case 5:
|
||||
resampler = KnownResamplers.Welch;
|
||||
break;
|
||||
default:
|
||||
resampler = KnownResamplers.MitchellNetravali;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return resampler;
|
||||
}
|
||||
|
||||
private static void ApplyRGBMask(this Image<Bgra32> tex, Image<Bgra32> texMask, bool isPreview = false)
|
||||
{
|
||||
using (texMask)
|
||||
{
|
||||
bool resized = false;
|
||||
if (tex.Width != texMask.Width || tex.Height != texMask.Height)
|
||||
{
|
||||
texMask.Mutate(x => x.Resize(tex.Width, tex.Height, GetResampler(isPreview)));
|
||||
resized = true;
|
||||
}
|
||||
|
||||
var invGamma = 1.0 / (1.0 + Settings.Default.alphaMaskGamma / 10.0);
|
||||
if (Settings.Default.resizedOnly && !resized)
|
||||
{
|
||||
invGamma = 1.0;
|
||||
}
|
||||
|
||||
tex.ProcessPixelRows(texMask, (sourceTex, targetTexMask) =>
|
||||
{
|
||||
for (int y = 0; y < texMask.Height; y++)
|
||||
{
|
||||
var texRow = sourceTex.GetRowSpan(y);
|
||||
var maskRow = targetTexMask.GetRowSpan(y);
|
||||
for (int x = 0; x < maskRow.Length; x++)
|
||||
{
|
||||
var grayscale = (maskRow[x].R + maskRow[x].G + maskRow[x].B) / 3.0;
|
||||
if (invGamma != 1)
|
||||
{
|
||||
grayscale = 255 - Math.Pow((255 - grayscale) / 255, invGamma) * 255;
|
||||
}
|
||||
texRow[x].A = (byte)grayscale;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static Image<Bgra32> CutImage(Image<Bgra32> originalImage, Rectf textureRect, float downscaleMultiplier, bool rotate = false)
|
||||
{
|
||||
if (originalImage != null)
|
||||
{
|
||||
if (downscaleMultiplier > 0f && downscaleMultiplier != 1f)
|
||||
{
|
||||
var newSize = (Size)(originalImage.Size() / downscaleMultiplier);
|
||||
originalImage.Mutate(x => x.Resize(newSize, KnownResamplers.Lanczos3, compand: true));
|
||||
}
|
||||
var rectX = (int)Math.Floor(textureRect.x);
|
||||
var rectY = (int)Math.Floor(textureRect.y);
|
||||
var rectRight = (int)Math.Ceiling(textureRect.x + textureRect.width);
|
||||
var rectBottom = (int)Math.Ceiling(textureRect.y + textureRect.height);
|
||||
rectRight = Math.Min(rectRight, originalImage.Width);
|
||||
rectBottom = Math.Min(rectBottom, originalImage.Height);
|
||||
var rect = new Rectangle(rectX, rectY, rectRight - rectX, rectBottom - rectY);
|
||||
var spriteImage = originalImage.Clone(x => x.Crop(rect));
|
||||
originalImage.Dispose();
|
||||
if (rotate)
|
||||
{
|
||||
spriteImage.Mutate(x => x.Rotate(RotateMode.Rotate270));
|
||||
}
|
||||
spriteImage.Mutate(x => x.Flip(FlipMode.Vertical));
|
||||
|
||||
return spriteImage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
125
AssetStudioGUI/Components/Arknights/AvgSprite.cs
Normal file
125
AssetStudioGUI/Components/Arknights/AvgSprite.cs
Normal file
@@ -0,0 +1,125 @@
|
||||
using Arknights.AvgCharHubMono;
|
||||
using AssetStudio;
|
||||
using AssetStudioGUI;
|
||||
using SixLabors.ImageSharp;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal class AvgSprite
|
||||
{
|
||||
public Texture2D FaceSpriteAlphaTexture { get; }
|
||||
public Texture2D FullTexture { get; }
|
||||
public Texture2D FullAlphaTexture { get; }
|
||||
public Point FacePos { get; }
|
||||
public Size FaceSize { get; }
|
||||
public string Alias { get; }
|
||||
public bool IsWholeBodySprite { get; }
|
||||
public bool IsFaceSprite { get; }
|
||||
public bool IsHubParsed { get; }
|
||||
|
||||
private AvgSpriteConfig GetCurSpriteGroup(AvgSpriteConfigGroup spriteHubDataGrouped, long spriteItemID, string spriteName)
|
||||
{
|
||||
if (spriteHubDataGrouped.SpriteGroups.Length > 1)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(spriteName))
|
||||
{
|
||||
var groupFromName = int.TryParse(spriteName?.Substring(spriteName.IndexOf('$') + 1, 1), out int groupIndex);
|
||||
if (groupFromName)
|
||||
{
|
||||
return spriteHubDataGrouped.SpriteGroups[groupIndex - 1];
|
||||
}
|
||||
}
|
||||
return spriteHubDataGrouped.SpriteGroups.FirstOrDefault(x => x.Sprites.Any(y => y.Sprite.m_PathID == spriteItemID));
|
||||
}
|
||||
else
|
||||
{
|
||||
return spriteHubDataGrouped.SpriteGroups[0];
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetSpriteHub(AssetItem assetItem, out AvgSpriteConfig spriteHubData)
|
||||
{
|
||||
spriteHubData = null;
|
||||
var avgSpriteHubItem = Studio.exportableAssets.Find(x =>
|
||||
x.Type == ClassIDType.MonoBehaviour
|
||||
&& x.Container == assetItem.Container
|
||||
&& x.Text.IndexOf("AVGCharacterSpriteHub", StringComparison.OrdinalIgnoreCase) >= 0
|
||||
);
|
||||
if (avgSpriteHubItem == null)
|
||||
{
|
||||
Logger.Warning("AVGCharacterSpriteHub was not found.");
|
||||
return false;
|
||||
}
|
||||
var spriteHubDict = ((MonoBehaviour)avgSpriteHubItem.Asset).ToType();
|
||||
if (spriteHubDict == null)
|
||||
{
|
||||
Logger.Warning("AVGCharacterSpriteHub is not readable.");
|
||||
return false;
|
||||
}
|
||||
|
||||
var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict);
|
||||
if (avgSpriteHubItem.Text.ToLower().Contains("hubgroup"))
|
||||
{
|
||||
var groupedSpriteHub = JsonConvert.DeserializeObject<AvgSpriteConfigGroup>(spriteHubJson);
|
||||
spriteHubData = GetCurSpriteGroup(groupedSpriteHub, assetItem.m_PathID, assetItem.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
spriteHubData = JsonConvert.DeserializeObject<AvgSpriteConfig>(spriteHubJson);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public AvgSprite(AssetItem assetItem)
|
||||
{
|
||||
if (TryGetSpriteHub(assetItem, out var spriteHubData))
|
||||
{
|
||||
IsHubParsed = spriteHubData?.Sprites.Length > 0;
|
||||
}
|
||||
if (IsHubParsed)
|
||||
{
|
||||
var curSpriteData = spriteHubData.Sprites.FirstOrDefault(x => x.Sprite.m_PathID == assetItem.m_PathID);
|
||||
|
||||
if (curSpriteData == null)
|
||||
{
|
||||
Studio.StatusStripUpdate($"Sprite \"{assetItem.Text}\" was not found in the avg sprite hub.");
|
||||
return;
|
||||
}
|
||||
|
||||
Alias = curSpriteData.Alias;
|
||||
IsWholeBodySprite = curSpriteData.IsWholeBody;
|
||||
|
||||
if (spriteHubData.FaceSize.X > 0 && spriteHubData.FaceSize.Y > 0)
|
||||
{
|
||||
var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture
|
||||
if (IsWholeBodySprite || curSpriteData.Equals(fullTexSpriteData))
|
||||
{
|
||||
fullTexSpriteData = curSpriteData;
|
||||
}
|
||||
else
|
||||
{
|
||||
var faceAlphaID = curSpriteData.AlphaTex.m_PathID;
|
||||
FaceSpriteAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == faceAlphaID).Asset;
|
||||
}
|
||||
var fullTexSpriteID = fullTexSpriteData.Sprite.m_PathID;
|
||||
var fullTexAlphaID = fullTexSpriteData.AlphaTex.m_PathID;
|
||||
var fullTexSprite = (Sprite)Studio.exportableAssets.Find(x => x.m_PathID == fullTexSpriteID).Asset;
|
||||
|
||||
FullTexture = fullTexSprite.m_RD.texture.TryGet(out var fullTex) ? fullTex : null;
|
||||
FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == fullTexAlphaID).Asset;
|
||||
FacePos = new Point((int)Math.Round(spriteHubData.FacePos.X), (int)Math.Round(spriteHubData.FacePos.Y));
|
||||
FaceSize = new Size((int)Math.Round(spriteHubData.FaceSize.X), (int)Math.Round(spriteHubData.FaceSize.Y));
|
||||
IsFaceSprite = assetItem.m_PathID != fullTexSpriteID;
|
||||
}
|
||||
else
|
||||
{
|
||||
FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID).Asset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs
Normal file
30
AssetStudioGUI/Components/Arknights/AvgSpriteConfig.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using AssetStudio;
|
||||
|
||||
namespace Arknights.AvgCharHubMono
|
||||
{
|
||||
internal class AvgAssetIDs
|
||||
{
|
||||
public int m_FileID { get; set; }
|
||||
public long m_PathID { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteData
|
||||
{
|
||||
public AvgAssetIDs Sprite { get; set; }
|
||||
public AvgAssetIDs AlphaTex { get; set; }
|
||||
public string Alias { get; set; }
|
||||
public bool IsWholeBody { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteConfig
|
||||
{
|
||||
public AvgSpriteData[] Sprites { get; set; }
|
||||
public Vector2 FaceSize { get; set; }
|
||||
public Vector3 FacePos { get; set; }
|
||||
}
|
||||
|
||||
internal class AvgSpriteConfigGroup
|
||||
{
|
||||
public AvgSpriteConfig[] SpriteGroups { get; set; }
|
||||
}
|
||||
}
|
||||
24
AssetStudioGUI/Components/Arknights/PortraitSprite.cs
Normal file
24
AssetStudioGUI/Components/Arknights/PortraitSprite.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using AssetStudio;
|
||||
|
||||
|
||||
namespace Arknights
|
||||
{
|
||||
internal class PortraitSprite
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ClassIDType Type { get; }
|
||||
public SerializedFile AssetsFile { get; set; }
|
||||
public string Container { get; set; }
|
||||
public Texture2D Texture { get; set; }
|
||||
public Texture2D AlphaTexture { get; set; }
|
||||
public Rectf TextureRect { get; set; }
|
||||
public bool Rotate { get; set; }
|
||||
public float DownscaleMultiplier { get; }
|
||||
|
||||
public PortraitSprite()
|
||||
{
|
||||
Type = ClassIDType.AkPortraitSprite;
|
||||
DownscaleMultiplier = 1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
AssetStudioGUI/Components/Arknights/PortraitSpriteConfig.cs
Normal file
41
AssetStudioGUI/Components/Arknights/PortraitSpriteConfig.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
namespace Arknights.PortraitSpriteMono
|
||||
{
|
||||
internal class PortraitRect
|
||||
{
|
||||
public float X { get; set; }
|
||||
public float Y { get; set; }
|
||||
public float W { get; set; }
|
||||
public float H { get; set; }
|
||||
}
|
||||
|
||||
internal class AtlasSprite
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Guid { get; set; }
|
||||
public int Atlas { get; set; }
|
||||
public PortraitRect Rect { get; set; }
|
||||
public bool Rotate { get; set; }
|
||||
}
|
||||
|
||||
internal class TextureIDs
|
||||
{
|
||||
public int m_FileID { get; set; }
|
||||
public long m_PathID { get; set; }
|
||||
}
|
||||
|
||||
internal class AtlasInfo
|
||||
{
|
||||
public int Index { get; set; }
|
||||
public TextureIDs Texture { get; set; }
|
||||
public TextureIDs Alpha { get; set; }
|
||||
public int Size { get; set; }
|
||||
}
|
||||
|
||||
internal class PortraitSpriteConfig
|
||||
{
|
||||
public string m_Name { get; set; }
|
||||
public AtlasSprite[] _sprites { get; set; }
|
||||
public AtlasInfo _atlas { get; set; }
|
||||
public int _index { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Windows.Forms;
|
||||
using AssetStudio;
|
||||
using Arknights;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
@@ -15,6 +16,7 @@ namespace AssetStudioGUI
|
||||
public string InfoText;
|
||||
public string UniqueID;
|
||||
public GameObjectTreeNode TreeNode;
|
||||
public PortraitSprite AkPortraitSprite;
|
||||
|
||||
public AssetItem(Object asset)
|
||||
{
|
||||
@@ -26,6 +28,19 @@ namespace AssetStudioGUI
|
||||
FullSize = asset.byteSize;
|
||||
}
|
||||
|
||||
public AssetItem(PortraitSprite akPortraitSprite)
|
||||
{
|
||||
Asset = null;
|
||||
SourceFile = akPortraitSprite.AssetsFile;
|
||||
Container = akPortraitSprite.Container;
|
||||
Type = akPortraitSprite.Type;
|
||||
TypeString = Type.ToString();
|
||||
Text = akPortraitSprite.Name;
|
||||
m_PathID = -1;
|
||||
FullSize = (long)(akPortraitSprite.TextureRect.width * akPortraitSprite.TextureRect.height * 4);
|
||||
AkPortraitSprite = akPortraitSprite;
|
||||
}
|
||||
|
||||
public void SetSubItems()
|
||||
{
|
||||
SubItems.AddRange(new[]
|
||||
|
||||
@@ -7,11 +7,6 @@ namespace AssetStudioGUI
|
||||
{
|
||||
public GameObject gameObject;
|
||||
|
||||
public GameObjectTreeNode(string name)
|
||||
{
|
||||
Text = name;
|
||||
}
|
||||
|
||||
public GameObjectTreeNode(GameObject gameObject)
|
||||
{
|
||||
this.gameObject = gameObject;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
@@ -15,12 +14,13 @@ namespace AssetStudioGUI
|
||||
|
||||
internal DialogResult ShowDialog(IWin32Window owner = null)
|
||||
{
|
||||
//#if NETFRAMEWORK
|
||||
if (Environment.OSVersion.Version.Major >= 6)
|
||||
{
|
||||
return ShowVistaDialog(owner);
|
||||
}
|
||||
|
||||
return ShowLegacyDialog(owner);
|
||||
//#endif
|
||||
return ShowFolderBrowserDialog(owner);
|
||||
}
|
||||
|
||||
private DialogResult ShowVistaDialog(IWin32Window owner)
|
||||
@@ -74,7 +74,7 @@ namespace AssetStudioGUI
|
||||
return DialogResult.Cancel;
|
||||
}
|
||||
|
||||
private DialogResult ShowLegacyDialog(IWin32Window owner)
|
||||
private DialogResult ShowFolderBrowserDialog(IWin32Window owner)
|
||||
{
|
||||
using (var frm = new FolderBrowserDialog())
|
||||
{
|
||||
@@ -82,13 +82,20 @@ namespace AssetStudioGUI
|
||||
{
|
||||
frm.SelectedPath = InitialFolder;
|
||||
}
|
||||
if ((owner == null ? frm.ShowDialog() : frm.ShowDialog(owner)) == DialogResult.OK)
|
||||
#if !NETFRAMEWORK
|
||||
if (Title != null)
|
||||
{
|
||||
Folder = Path.GetDirectoryName(frm.SelectedPath);
|
||||
return DialogResult.OK;
|
||||
frm.Description = Title;
|
||||
frm.UseDescriptionForTitle = true;
|
||||
}
|
||||
|
||||
return DialogResult.Cancel;
|
||||
#endif
|
||||
var result = owner == null ? frm.ShowDialog() : frm.ShowDialog(owner);
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
Folder = frm.SelectedPath;
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
internal static class TreeViewExtensions
|
||||
{
|
||||
private const int TVIF_STATE = 0x8;
|
||||
private const int TVIS_STATEIMAGEMASK = 0xF000;
|
||||
private const int TV_FIRST = 0x1100;
|
||||
private const int TVM_SETITEM = TV_FIRST + 63;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 8, CharSet = CharSet.Auto)]
|
||||
private struct TVITEM
|
||||
{
|
||||
public int mask;
|
||||
public IntPtr hItem;
|
||||
public int state;
|
||||
public int stateMask;
|
||||
[MarshalAs(UnmanagedType.LPTStr)]
|
||||
public string lpszText;
|
||||
public int cchTextMax;
|
||||
public int iImage;
|
||||
public int iSelectedImage;
|
||||
public int cChildren;
|
||||
public IntPtr lParam;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref TVITEM lParam);
|
||||
|
||||
/// <summary>
|
||||
/// Hides the checkbox for the specified node on a TreeView control.
|
||||
/// </summary>
|
||||
public static void HideCheckBox(this TreeNode node)
|
||||
{
|
||||
var tvi = new TVITEM
|
||||
{
|
||||
hItem = node.Handle,
|
||||
mask = TVIF_STATE,
|
||||
stateMask = TVIS_STATEIMAGEMASK,
|
||||
state = TVIS_STATEIMAGEMASK //temp bugfix for an issue with getting stuck during the "Building tree structure" step
|
||||
};
|
||||
SendMessage(node.TreeView.Handle, TVM_SETITEM, IntPtr.Zero, ref tvi);
|
||||
}
|
||||
}
|
||||
}
|
||||
48
AssetStudioGUI/DirectBitmap.cs
Normal file
48
AssetStudioGUI/DirectBitmap.cs
Normal file
@@ -0,0 +1,48 @@
|
||||
using AssetStudio;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
public sealed class DirectBitmap : IDisposable
|
||||
{
|
||||
public DirectBitmap(Image<Bgra32> image)
|
||||
{
|
||||
Width = image.Width;
|
||||
Height = image.Height;
|
||||
Bits = BigArrayPool<byte>.Shared.Rent(Width * Height * 4);
|
||||
image.CopyPixelDataTo(Bits);
|
||||
m_handle = GCHandle.Alloc(Bits, GCHandleType.Pinned);
|
||||
m_bitmap = new Bitmap(Width, Height, Stride, PixelFormat.Format32bppArgb, m_handle.AddrOfPinnedObject());
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
m_bitmap.Dispose();
|
||||
m_handle.Free();
|
||||
BigArrayPool<byte>.Shared.Return(Bits);
|
||||
}
|
||||
m_bitmap = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
public int Height { get; }
|
||||
public int Width { get; }
|
||||
public int Stride => Width * 4;
|
||||
public byte[] Bits { get; }
|
||||
public Bitmap Bitmap => m_bitmap;
|
||||
|
||||
private Bitmap m_bitmap;
|
||||
private readonly GCHandle m_handle;
|
||||
}
|
||||
}
|
||||
214
AssetStudioGUI/ExportOptions.Designer.cs
generated
214
AssetStudioGUI/ExportOptions.Designer.cs
generated
@@ -32,12 +32,14 @@
|
||||
this.OKbutton = new System.Windows.Forms.Button();
|
||||
this.Cancel = new System.Windows.Forms.Button();
|
||||
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||
this.exportSpriteWithAlphaMask = new System.Windows.Forms.CheckBox();
|
||||
this.openAfterExport = new System.Windows.Forms.CheckBox();
|
||||
this.restoreExtensionName = new System.Windows.Forms.CheckBox();
|
||||
this.assetGroupOptions = new System.Windows.Forms.ComboBox();
|
||||
this.label6 = new System.Windows.Forms.Label();
|
||||
this.convertAudio = new System.Windows.Forms.CheckBox();
|
||||
this.panel1 = new System.Windows.Forms.Panel();
|
||||
this.towebp = new System.Windows.Forms.RadioButton();
|
||||
this.totga = new System.Windows.Forms.RadioButton();
|
||||
this.tojpg = new System.Windows.Forms.RadioButton();
|
||||
this.topng = new System.Windows.Forms.RadioButton();
|
||||
@@ -62,17 +64,31 @@
|
||||
this.exportAllNodes = new System.Windows.Forms.CheckBox();
|
||||
this.eulerFilter = new System.Windows.Forms.CheckBox();
|
||||
this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.akResamplerLabel = new System.Windows.Forms.Label();
|
||||
this.akResamplerComboBox = new System.Windows.Forms.ComboBox();
|
||||
this.akSpritesAlphaGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.akGammaNoteLabel = new System.Windows.Forms.Label();
|
||||
this.akResamplerDescLabel = new System.Windows.Forms.Label();
|
||||
this.akResizedOnlyCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.akGammaValueLabel = new System.Windows.Forms.Label();
|
||||
this.akGammaLabel = new System.Windows.Forms.Label();
|
||||
this.akAlphaMaskGammaTrackBar = new System.Windows.Forms.TrackBar();
|
||||
this.akSpritesExportGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.akAddAliasesCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox1.SuspendLayout();
|
||||
this.panel1.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit();
|
||||
this.akSpritesAlphaGroupBox.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.akAlphaMaskGammaTrackBar)).BeginInit();
|
||||
this.akSpritesExportGroupBox.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// OKbutton
|
||||
//
|
||||
this.OKbutton.Location = new System.Drawing.Point(318, 380);
|
||||
this.OKbutton.Location = new System.Drawing.Point(681, 381);
|
||||
this.OKbutton.Name = "OKbutton";
|
||||
this.OKbutton.Size = new System.Drawing.Size(75, 23);
|
||||
this.OKbutton.TabIndex = 6;
|
||||
@@ -83,7 +99,7 @@
|
||||
// Cancel
|
||||
//
|
||||
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.Cancel.Location = new System.Drawing.Point(399, 380);
|
||||
this.Cancel.Location = new System.Drawing.Point(762, 381);
|
||||
this.Cancel.Name = "Cancel";
|
||||
this.Cancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.Cancel.TabIndex = 7;
|
||||
@@ -94,6 +110,7 @@
|
||||
// groupBox1
|
||||
//
|
||||
this.groupBox1.AutoSize = true;
|
||||
this.groupBox1.Controls.Add(this.exportSpriteWithAlphaMask);
|
||||
this.groupBox1.Controls.Add(this.openAfterExport);
|
||||
this.groupBox1.Controls.Add(this.restoreExtensionName);
|
||||
this.groupBox1.Controls.Add(this.assetGroupOptions);
|
||||
@@ -103,17 +120,29 @@
|
||||
this.groupBox1.Controls.Add(this.converttexture);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 13);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(232, 362);
|
||||
this.groupBox1.Size = new System.Drawing.Size(301, 362);
|
||||
this.groupBox1.TabIndex = 9;
|
||||
this.groupBox1.TabStop = false;
|
||||
this.groupBox1.Text = "Export";
|
||||
//
|
||||
// exportSpriteWithAlphaMask
|
||||
//
|
||||
this.exportSpriteWithAlphaMask.AutoSize = true;
|
||||
this.exportSpriteWithAlphaMask.Checked = true;
|
||||
this.exportSpriteWithAlphaMask.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.exportSpriteWithAlphaMask.Location = new System.Drawing.Point(6, 150);
|
||||
this.exportSpriteWithAlphaMask.Name = "exportSpriteWithAlphaMask";
|
||||
this.exportSpriteWithAlphaMask.Size = new System.Drawing.Size(205, 17);
|
||||
this.exportSpriteWithAlphaMask.TabIndex = 11;
|
||||
this.exportSpriteWithAlphaMask.Text = "Export sprites with alpha mask applied";
|
||||
this.exportSpriteWithAlphaMask.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// openAfterExport
|
||||
//
|
||||
this.openAfterExport.AutoSize = true;
|
||||
this.openAfterExport.Checked = true;
|
||||
this.openAfterExport.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.openAfterExport.Location = new System.Drawing.Point(6, 173);
|
||||
this.openAfterExport.Location = new System.Drawing.Point(6, 196);
|
||||
this.openAfterExport.Name = "openAfterExport";
|
||||
this.openAfterExport.Size = new System.Drawing.Size(137, 17);
|
||||
this.openAfterExport.TabIndex = 10;
|
||||
@@ -127,9 +156,10 @@
|
||||
this.restoreExtensionName.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.restoreExtensionName.Location = new System.Drawing.Point(6, 63);
|
||||
this.restoreExtensionName.Name = "restoreExtensionName";
|
||||
this.restoreExtensionName.Size = new System.Drawing.Size(190, 17);
|
||||
this.restoreExtensionName.Size = new System.Drawing.Size(275, 17);
|
||||
this.restoreExtensionName.TabIndex = 9;
|
||||
this.restoreExtensionName.Text = "Restore TextAsset extension name";
|
||||
this.restoreExtensionName.Text = "Try to restore/Use original TextAsset extension name";
|
||||
this.exportUvsTooltip.SetToolTip(this.restoreExtensionName, "If not checked, AssetStudio will export all TextAssets with the \".txt\" extension");
|
||||
this.restoreExtensionName.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// assetGroupOptions
|
||||
@@ -139,11 +169,12 @@
|
||||
this.assetGroupOptions.Items.AddRange(new object[] {
|
||||
"type name",
|
||||
"container path",
|
||||
"container path full (with name)",
|
||||
"source file name",
|
||||
"do not group"});
|
||||
this.assetGroupOptions.Location = new System.Drawing.Point(6, 35);
|
||||
this.assetGroupOptions.Name = "assetGroupOptions";
|
||||
this.assetGroupOptions.Size = new System.Drawing.Size(149, 21);
|
||||
this.assetGroupOptions.Size = new System.Drawing.Size(165, 21);
|
||||
this.assetGroupOptions.TabIndex = 8;
|
||||
//
|
||||
// label6
|
||||
@@ -160,7 +191,7 @@
|
||||
this.convertAudio.AutoSize = true;
|
||||
this.convertAudio.Checked = true;
|
||||
this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.convertAudio.Location = new System.Drawing.Point(6, 150);
|
||||
this.convertAudio.Location = new System.Drawing.Point(6, 173);
|
||||
this.convertAudio.Name = "convertAudio";
|
||||
this.convertAudio.Size = new System.Drawing.Size(179, 17);
|
||||
this.convertAudio.TabIndex = 6;
|
||||
@@ -169,15 +200,27 @@
|
||||
//
|
||||
// panel1
|
||||
//
|
||||
this.panel1.Controls.Add(this.towebp);
|
||||
this.panel1.Controls.Add(this.totga);
|
||||
this.panel1.Controls.Add(this.tojpg);
|
||||
this.panel1.Controls.Add(this.topng);
|
||||
this.panel1.Controls.Add(this.tobmp);
|
||||
this.panel1.Location = new System.Drawing.Point(20, 111);
|
||||
this.panel1.Location = new System.Drawing.Point(18, 111);
|
||||
this.panel1.Name = "panel1";
|
||||
this.panel1.Size = new System.Drawing.Size(202, 33);
|
||||
this.panel1.Size = new System.Drawing.Size(260, 33);
|
||||
this.panel1.TabIndex = 5;
|
||||
//
|
||||
// towebp
|
||||
//
|
||||
this.towebp.AutoSize = true;
|
||||
this.towebp.Location = new System.Drawing.Point(201, 7);
|
||||
this.towebp.Name = "towebp";
|
||||
this.towebp.Size = new System.Drawing.Size(54, 17);
|
||||
this.towebp.TabIndex = 5;
|
||||
this.towebp.TabStop = true;
|
||||
this.towebp.Text = "Webp";
|
||||
this.towebp.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// totga
|
||||
//
|
||||
this.totga.AutoSize = true;
|
||||
@@ -252,7 +295,7 @@
|
||||
this.groupBox2.Controls.Add(this.castToBone);
|
||||
this.groupBox2.Controls.Add(this.exportAllNodes);
|
||||
this.groupBox2.Controls.Add(this.eulerFilter);
|
||||
this.groupBox2.Location = new System.Drawing.Point(250, 13);
|
||||
this.groupBox2.Location = new System.Drawing.Point(313, 13);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(224, 362);
|
||||
this.groupBox2.TabIndex = 11;
|
||||
@@ -464,13 +507,140 @@
|
||||
this.eulerFilter.Text = "EulerFilter";
|
||||
this.eulerFilter.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// akResamplerLabel
|
||||
//
|
||||
this.akResamplerLabel.AutoSize = true;
|
||||
this.akResamplerLabel.Location = new System.Drawing.Point(6, 21);
|
||||
this.akResamplerLabel.Name = "akResamplerLabel";
|
||||
this.akResamplerLabel.Size = new System.Drawing.Size(120, 13);
|
||||
this.akResamplerLabel.TabIndex = 5;
|
||||
this.akResamplerLabel.Text = "Alpha texture resampler:";
|
||||
this.exportUvsTooltip.SetToolTip(this.akResamplerLabel, "Only affects exported images");
|
||||
//
|
||||
// akResamplerComboBox
|
||||
//
|
||||
this.akResamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.akResamplerComboBox.FormattingEnabled = true;
|
||||
this.akResamplerComboBox.Items.AddRange(new object[] {
|
||||
"Nearest Neighbor",
|
||||
"Bilinear",
|
||||
"Bicubic",
|
||||
"Mitchell-Netravali",
|
||||
"Spline",
|
||||
"Welch"});
|
||||
this.akResamplerComboBox.Location = new System.Drawing.Point(132, 18);
|
||||
this.akResamplerComboBox.Name = "akResamplerComboBox";
|
||||
this.akResamplerComboBox.Size = new System.Drawing.Size(162, 21);
|
||||
this.akResamplerComboBox.TabIndex = 4;
|
||||
this.exportUvsTooltip.SetToolTip(this.akResamplerComboBox, "Only affects exported images");
|
||||
//
|
||||
// akSpritesAlphaGroupBox
|
||||
//
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaNoteLabel);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerDescLabel);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerLabel);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerComboBox);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akResizedOnlyCheckBox);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaValueLabel);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaLabel);
|
||||
this.akSpritesAlphaGroupBox.Controls.Add(this.akAlphaMaskGammaTrackBar);
|
||||
this.akSpritesAlphaGroupBox.Location = new System.Drawing.Point(537, 13);
|
||||
this.akSpritesAlphaGroupBox.Name = "akSpritesAlphaGroupBox";
|
||||
this.akSpritesAlphaGroupBox.Size = new System.Drawing.Size(300, 178);
|
||||
this.akSpritesAlphaGroupBox.TabIndex = 12;
|
||||
this.akSpritesAlphaGroupBox.TabStop = false;
|
||||
this.akSpritesAlphaGroupBox.Text = "Sprites: Alpha Texture [Arknights]";
|
||||
//
|
||||
// akGammaNoteLabel
|
||||
//
|
||||
this.akGammaNoteLabel.AutoSize = true;
|
||||
this.akGammaNoteLabel.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.akGammaNoteLabel.Location = new System.Drawing.Point(6, 138);
|
||||
this.akGammaNoteLabel.Name = "akGammaNoteLabel";
|
||||
this.akGammaNoteLabel.Size = new System.Drawing.Size(230, 13);
|
||||
this.akGammaNoteLabel.TabIndex = 7;
|
||||
this.akGammaNoteLabel.Text = "* Gamma settings also affect the preview image";
|
||||
//
|
||||
// akResamplerDescLabel
|
||||
//
|
||||
this.akResamplerDescLabel.AutoSize = true;
|
||||
this.akResamplerDescLabel.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.akResamplerDescLabel.Location = new System.Drawing.Point(6, 43);
|
||||
this.akResamplerDescLabel.Name = "akResamplerDescLabel";
|
||||
this.akResamplerDescLabel.Size = new System.Drawing.Size(251, 13);
|
||||
this.akResamplerDescLabel.TabIndex = 6;
|
||||
this.akResamplerDescLabel.Text = "Alpha texture upscale method for 2048x2048 sprites";
|
||||
//
|
||||
// akResizedOnlyCheckBox
|
||||
//
|
||||
this.akResizedOnlyCheckBox.AutoSize = true;
|
||||
this.akResizedOnlyCheckBox.Checked = true;
|
||||
this.akResizedOnlyCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.akResizedOnlyCheckBox.Location = new System.Drawing.Point(172, 85);
|
||||
this.akResizedOnlyCheckBox.Name = "akResizedOnlyCheckBox";
|
||||
this.akResizedOnlyCheckBox.Size = new System.Drawing.Size(122, 17);
|
||||
this.akResizedOnlyCheckBox.TabIndex = 3;
|
||||
this.akResizedOnlyCheckBox.Text = "Apply to resized only";
|
||||
this.akResizedOnlyCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// akGammaValueLabel
|
||||
//
|
||||
this.akGammaValueLabel.AutoSize = true;
|
||||
this.akGammaValueLabel.Location = new System.Drawing.Point(111, 86);
|
||||
this.akGammaValueLabel.Name = "akGammaValueLabel";
|
||||
this.akGammaValueLabel.Size = new System.Drawing.Size(41, 13);
|
||||
this.akGammaValueLabel.TabIndex = 2;
|
||||
this.akGammaValueLabel.Text = "Default";
|
||||
//
|
||||
// akGammaLabel
|
||||
//
|
||||
this.akGammaLabel.AutoSize = true;
|
||||
this.akGammaLabel.Location = new System.Drawing.Point(6, 86);
|
||||
this.akGammaLabel.Name = "akGammaLabel";
|
||||
this.akGammaLabel.Size = new System.Drawing.Size(86, 13);
|
||||
this.akGammaLabel.TabIndex = 1;
|
||||
this.akGammaLabel.Text = "Shadow gamma:";
|
||||
//
|
||||
// akAlphaMaskGammaTrackBar
|
||||
//
|
||||
this.akAlphaMaskGammaTrackBar.LargeChange = 2;
|
||||
this.akAlphaMaskGammaTrackBar.Location = new System.Drawing.Point(6, 102);
|
||||
this.akAlphaMaskGammaTrackBar.Maximum = 5;
|
||||
this.akAlphaMaskGammaTrackBar.Minimum = -5;
|
||||
this.akAlphaMaskGammaTrackBar.Name = "akAlphaMaskGammaTrackBar";
|
||||
this.akAlphaMaskGammaTrackBar.Size = new System.Drawing.Size(288, 45);
|
||||
this.akAlphaMaskGammaTrackBar.TabIndex = 0;
|
||||
this.akAlphaMaskGammaTrackBar.Scroll += new System.EventHandler(this.akAlphaMaskGammaTrackBar_Scroll);
|
||||
//
|
||||
// akSpritesExportGroupBox
|
||||
//
|
||||
this.akSpritesExportGroupBox.Controls.Add(this.akAddAliasesCheckBox);
|
||||
this.akSpritesExportGroupBox.Location = new System.Drawing.Point(537, 197);
|
||||
this.akSpritesExportGroupBox.Name = "akSpritesExportGroupBox";
|
||||
this.akSpritesExportGroupBox.Size = new System.Drawing.Size(300, 178);
|
||||
this.akSpritesExportGroupBox.TabIndex = 13;
|
||||
this.akSpritesExportGroupBox.TabStop = false;
|
||||
this.akSpritesExportGroupBox.Text = "Sprites: Export [Arknights]";
|
||||
//
|
||||
// akAddAliasesCheckBox
|
||||
//
|
||||
this.akAddAliasesCheckBox.AutoSize = true;
|
||||
this.akAddAliasesCheckBox.Location = new System.Drawing.Point(6, 28);
|
||||
this.akAddAliasesCheckBox.Name = "akAddAliasesCheckBox";
|
||||
this.akAddAliasesCheckBox.Size = new System.Drawing.Size(261, 17);
|
||||
this.akAddAliasesCheckBox.TabIndex = 0;
|
||||
this.akAddAliasesCheckBox.Text = "Add aliases to avg character sprite names (if exist)";
|
||||
this.akAddAliasesCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// ExportOptions
|
||||
//
|
||||
this.AcceptButton = this.OKbutton;
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.Cancel;
|
||||
this.ClientSize = new System.Drawing.Size(486, 416);
|
||||
this.ClientSize = new System.Drawing.Size(849, 416);
|
||||
this.Controls.Add(this.akSpritesExportGroupBox);
|
||||
this.Controls.Add(this.akSpritesAlphaGroupBox);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.Cancel);
|
||||
@@ -480,7 +650,7 @@
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "ExportOptions";
|
||||
this.ShowIcon = false;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||
this.Text = "Export options";
|
||||
this.TopMost = true;
|
||||
this.groupBox1.ResumeLayout(false);
|
||||
@@ -492,6 +662,11 @@
|
||||
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit();
|
||||
this.akSpritesAlphaGroupBox.ResumeLayout(false);
|
||||
this.akSpritesAlphaGroupBox.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.akAlphaMaskGammaTrackBar)).EndInit();
|
||||
this.akSpritesExportGroupBox.ResumeLayout(false);
|
||||
this.akSpritesExportGroupBox.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -531,5 +706,18 @@
|
||||
private System.Windows.Forms.CheckBox openAfterExport;
|
||||
private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;
|
||||
private System.Windows.Forms.ToolTip exportUvsTooltip;
|
||||
private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask;
|
||||
private System.Windows.Forms.RadioButton towebp;
|
||||
private System.Windows.Forms.GroupBox akSpritesAlphaGroupBox;
|
||||
private System.Windows.Forms.TrackBar akAlphaMaskGammaTrackBar;
|
||||
private System.Windows.Forms.Label akResamplerDescLabel;
|
||||
private System.Windows.Forms.Label akResamplerLabel;
|
||||
private System.Windows.Forms.ComboBox akResamplerComboBox;
|
||||
private System.Windows.Forms.CheckBox akResizedOnlyCheckBox;
|
||||
private System.Windows.Forms.Label akGammaValueLabel;
|
||||
private System.Windows.Forms.Label akGammaLabel;
|
||||
private System.Windows.Forms.GroupBox akSpritesExportGroupBox;
|
||||
private System.Windows.Forms.CheckBox akAddAliasesCheckBox;
|
||||
private System.Windows.Forms.Label akGammaNoteLabel;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ namespace AssetStudioGUI
|
||||
assetGroupOptions.SelectedIndex = Properties.Settings.Default.assetGroupOption;
|
||||
restoreExtensionName.Checked = Properties.Settings.Default.restoreExtensionName;
|
||||
converttexture.Checked = Properties.Settings.Default.convertTexture;
|
||||
exportSpriteWithAlphaMask.Checked = Properties.Settings.Default.exportSpriteWithMask;
|
||||
convertAudio.Checked = Properties.Settings.Default.convertAudio;
|
||||
var str = Properties.Settings.Default.convertType.ToString();
|
||||
foreach (Control c in panel1.Controls)
|
||||
@@ -36,6 +37,13 @@ namespace AssetStudioGUI
|
||||
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
|
||||
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
|
||||
|
||||
//Arknights
|
||||
akResamplerComboBox.SelectedIndex = Properties.Settings.Default.resamplerIndex;
|
||||
akAlphaMaskGammaTrackBar.Value = Properties.Settings.Default.alphaMaskGamma;
|
||||
akGammaValueLabel.Text = akAlphaMaskGammaTrackBar.Value == 0 ? "Default" : $"{akAlphaMaskGammaTrackBar.Value * 10:+#;-#;0}%";
|
||||
akResizedOnlyCheckBox.Checked = Properties.Settings.Default.resizedOnly;
|
||||
akAddAliasesCheckBox.Checked = Properties.Settings.Default.addAliases;
|
||||
|
||||
}
|
||||
|
||||
private void OKbutton_Click(object sender, EventArgs e)
|
||||
@@ -43,6 +51,7 @@ namespace AssetStudioGUI
|
||||
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
|
||||
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
|
||||
Properties.Settings.Default.convertTexture = converttexture.Checked;
|
||||
Properties.Settings.Default.exportSpriteWithMask = exportSpriteWithAlphaMask.Checked;
|
||||
Properties.Settings.Default.convertAudio = convertAudio.Checked;
|
||||
foreach (Control c in panel1.Controls)
|
||||
{
|
||||
@@ -65,16 +74,28 @@ namespace AssetStudioGUI
|
||||
Properties.Settings.Default.scaleFactor = scaleFactor.Value;
|
||||
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
|
||||
Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex;
|
||||
|
||||
//Arknights
|
||||
Properties.Settings.Default.resamplerIndex = akResamplerComboBox.SelectedIndex;
|
||||
Properties.Settings.Default.alphaMaskGamma = akAlphaMaskGammaTrackBar.Value;
|
||||
Properties.Settings.Default.resizedOnly = akResizedOnlyCheckBox.Checked;
|
||||
Properties.Settings.Default.addAliases = akAddAliasesCheckBox.Checked;
|
||||
|
||||
Properties.Settings.Default.Save();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
|
||||
//Arknights
|
||||
private void akAlphaMaskGammaTrackBar_Scroll(object sender, EventArgs e)
|
||||
{
|
||||
akGammaValueLabel.Text = akAlphaMaskGammaTrackBar.Value == 0 ? "Default" : $"{akAlphaMaskGammaTrackBar.Value * 10:+#;-#;0}%";
|
||||
}
|
||||
|
||||
private void Cancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,4 @@
|
||||
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<value>17, 17</value>
|
||||
</metadata>
|
||||
</root>
|
||||
@@ -1,4 +1,7 @@
|
||||
using AssetStudio;
|
||||
using Arknights;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using AssetStudio;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -17,12 +20,15 @@ namespace AssetStudioGUI
|
||||
var type = Properties.Settings.Default.convertType;
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
var stream = m_Texture2D.ConvertToStream(type, true);
|
||||
if (stream == null)
|
||||
var image = m_Texture2D.ConvertToImage(true);
|
||||
if (image == null)
|
||||
return false;
|
||||
using (stream)
|
||||
using (image)
|
||||
{
|
||||
File.WriteAllBytes(exportFullPath, stream.ToArray());
|
||||
using (var file = File.OpenWrite(exportFullPath))
|
||||
{
|
||||
image.WriteToStream(file, type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -46,7 +52,7 @@ namespace AssetStudioGUI
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".wav", out var exportFullPath))
|
||||
return false;
|
||||
var buffer = converter.ConvertToWav();
|
||||
var buffer = converter.ConvertToWav(m_AudioData);
|
||||
if (buffer == null)
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, buffer);
|
||||
@@ -72,13 +78,22 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportTextAsset(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_TextAsset = (TextAsset)(item.Asset);
|
||||
var m_TextAsset = (TextAsset)item.Asset;
|
||||
var extension = ".txt";
|
||||
var assetExtension = Path.GetExtension(m_TextAsset.m_Name);
|
||||
if (Properties.Settings.Default.restoreExtensionName)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Container))
|
||||
if (!string.IsNullOrEmpty(assetExtension))
|
||||
{
|
||||
extension = Path.GetExtension(item.Container);
|
||||
extension = "";
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(item.Container))
|
||||
{
|
||||
var ext = Path.GetExtension(item.Container);
|
||||
if (!string.IsNullOrEmpty(item.Container))
|
||||
{
|
||||
extension = ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!TryExportFile(exportPath, item, extension, out var exportFullPath))
|
||||
@@ -149,6 +164,7 @@ namespace AssetStudioGUI
|
||||
#region UV
|
||||
if (m_Mesh.m_UV0?.Length > 0)
|
||||
{
|
||||
c = 4;
|
||||
if (m_Mesh.m_UV0.Length == m_Mesh.m_VertexCount * 2)
|
||||
{
|
||||
c = 2;
|
||||
@@ -226,15 +242,76 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportSprite(AssetItem item, string exportPath)
|
||||
{
|
||||
Image<Bgra32> image;
|
||||
AvgSprite avgSprite = null;
|
||||
var alias = "";
|
||||
var m_Sprite = (Sprite)item.Asset;
|
||||
var spriteMaskMode = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.Export : SpriteMaskMode.Off;
|
||||
var type = Properties.Settings.Default.convertType;
|
||||
var isCharAvgSprite = item.Container.Contains("avg/characters");
|
||||
var isCharArt = item.Container.Contains("arts/characters");
|
||||
|
||||
if (isCharAvgSprite)
|
||||
{
|
||||
avgSprite = new AvgSprite(item);
|
||||
|
||||
if (Properties.Settings.Default.addAliases && !string.IsNullOrEmpty(avgSprite.Alias))
|
||||
{
|
||||
alias = $"_{avgSprite.Alias}";
|
||||
}
|
||||
}
|
||||
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath, alias))
|
||||
return false;
|
||||
|
||||
if (Properties.Settings.Default.useExternalAlpha && (isCharAvgSprite || isCharArt))
|
||||
{
|
||||
if (m_Sprite.m_RD.alphaTexture.IsNull)
|
||||
{
|
||||
var charAlphaAtlas = AkSpriteHelper.TryFindAlphaTex(item, avgSprite, isCharAvgSprite);
|
||||
if (charAlphaAtlas != null)
|
||||
{
|
||||
m_Sprite.m_RD.alphaTexture.Set(charAlphaAtlas);
|
||||
m_Sprite.akSplitAlpha = true;
|
||||
}
|
||||
}
|
||||
image = m_Sprite.AkGetImage(avgSprite, spriteMaskMode: spriteMaskMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
image = m_Sprite.GetImage(spriteMaskMode: spriteMaskMode);
|
||||
}
|
||||
|
||||
if (image != null)
|
||||
{
|
||||
using (image)
|
||||
{
|
||||
using (var file = File.OpenWrite(exportFullPath))
|
||||
{
|
||||
image.WriteToStream(file, type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ExportPortraitSprite(AssetItem item, string exportPath)
|
||||
{
|
||||
var type = Properties.Settings.Default.convertType;
|
||||
var spriteMaskMode = Properties.Settings.Default.exportSpriteWithMask ? SpriteMaskMode.Export : SpriteMaskMode.Off;
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
var stream = ((Sprite)item.Asset).GetImage(type);
|
||||
if (stream != null)
|
||||
|
||||
var image = item.AkPortraitSprite.AkGetImage(spriteMaskMode: spriteMaskMode);
|
||||
if (image != null)
|
||||
{
|
||||
using (stream)
|
||||
using (image)
|
||||
{
|
||||
File.WriteAllBytes(exportFullPath, stream.ToArray());
|
||||
using (var file = File.OpenWrite(exportFullPath))
|
||||
{
|
||||
image.WriteToStream(file, type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -243,15 +320,17 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportRawFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (item.Asset == null)
|
||||
return false;
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string alias = "")
|
||||
{
|
||||
var fileName = FixFileName(item.Text);
|
||||
var fileName = FixFileName(item.Text) + alias;
|
||||
fullPath = Path.Combine(dir, fileName + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
@@ -320,6 +399,8 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (item.Asset == null)
|
||||
return false;
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||
return false;
|
||||
var str = item.Asset.Dump();
|
||||
@@ -360,6 +441,8 @@ namespace AssetStudioGUI
|
||||
return ExportMovieTexture(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
return ExportSprite(item, exportPath);
|
||||
case ClassIDType.AkPortraitSprite:
|
||||
return ExportPortraitSprite(item, exportPath);
|
||||
case ClassIDType.Animator:
|
||||
return ExportAnimator(item, exportPath);
|
||||
case ClassIDType.AnimationClip:
|
||||
|
||||
@@ -14,21 +14,29 @@ namespace AssetStudioGUI
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public void Log(LoggerEvent loggerEvent, string message)
|
||||
public void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel)
|
||||
{
|
||||
switch (loggerEvent)
|
||||
{
|
||||
case LoggerEvent.Error:
|
||||
MessageBox.Show(message, "Error");
|
||||
break;
|
||||
case LoggerEvent.Warning:
|
||||
if (ShowErrorMessage)
|
||||
{
|
||||
MessageBox.Show(message);
|
||||
MessageBox.Show(message, "Warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
action("An error has occurred. Turn on \"Show all error messages\" to see details next time.");
|
||||
}
|
||||
break;
|
||||
case LoggerEvent.Debug:
|
||||
break;
|
||||
default:
|
||||
action(message);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AssetStudio;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
class GUIProgress : IProgress
|
||||
{
|
||||
private Action<int> action;
|
||||
|
||||
public GUIProgress(Action<int> action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public void Report(int value)
|
||||
{
|
||||
action(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
AssetStudioGUI/Libraries/OpenTK.WinForms.dll
Normal file
BIN
AssetStudioGUI/Libraries/OpenTK.WinForms.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user