20 Commits

Author SHA1 Message Date
VaDiM
d07fc6d6f5 Fix for avg sprites 2025-04-07 16:03:20 +03:00
VaDiM
ee2976aaf1 Update version & dependencies 2025-04-07 13:32:17 +03:00
VaDiM
f144037bc0 Fix for new compression type 2025-04-07 13:23:04 +03:00
VaDiM
0e097bda04 Update README.md 2024-05-01 14:25:55 +03:00
VaDiM
9686eee3b7 Fix for 512x512 avg sprites
temporarily?
2024-04-11 22:30:42 +03:00
VaDiM
b6318e6d9b Fix for empty alpha tex 2024-01-09 11:18:06 +03:00
VaDiM
e0d90d1b1e Update AssetStudioGUI.csproj 2023-12-16 23:17:56 +03:00
VaDiM
dd727758a8 Update ver to v1.1.0 2023-12-16 23:11:27 +03:00
VaDiM
d44ed315e3 Merge branch 'AssetStudioMod' into ArknightsStudio 2023-12-16 22:57:32 +03:00
VaDiM
e30b9e9e89 Fix bug with some avg sprites
- Changed face sprite detection method. We can't rely on the "IsWholeBody" flag
2023-11-08 13:57:57 +03:00
VaDiM
9632e88115 Update version to v1.0.1 2023-11-01 06:49:36 +03:00
VaDiM
bb19dd5019 Add support for avg sprite without separate alpha tex 2023-11-01 06:49:36 +03:00
VaDiM
b6c6ceba1c Update CHANGELOG.md 2023-09-24 15:41:47 +03:00
VaDiM
7c0a6375b1 Update readme files 2023-09-24 15:41:21 +03:00
VaDiM
5c489c5f83 Merge branch 'AssetStudioMod' into ArknightsStudio 2023-09-24 15:40:23 +03:00
VaDiM
e90af43459 Merge branch 'AssetStudioMod' into ArknightsStudio 2023-08-28 02:28:14 +03:00
VaDiM
381a7d89ae [AK][CLI] Add support for portrait sprites 2023-08-25 01:15:46 +03:00
VaDiM
572e3bf0d6 [AK][GUI] Add support for portrait sprites 2023-08-24 05:50:50 +03:00
VaDiM
3d7d51b54f [AK][CLI] Add support for sprites with an external alpha texture
- Added support for Arknights chararts sprites
- Added support for Arknights avg sprites
2023-08-17 01:22:16 +03:00
VaDiM
abbd27fde7 [AK][GUI] Add support for sprites with an external alpha texture
- Added support for Arknights chararts sprites
- Added support for Arknights avg sprites
2023-08-14 20:25:48 +03:00
109 changed files with 4090 additions and 6259 deletions

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright> <Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>

View File

@@ -22,26 +22,26 @@ namespace SevenZip
} }
} }
private uint _value = 0xFFFFFFFF; uint _value = 0xFFFFFFFF;
public void Init() { _value = 0xFFFFFFFF; } public void Init() { _value = 0xFFFFFFFF; }
public void UpdateByte(byte b) public void UpdateByte(byte b)
{ {
_value = Table[(byte)_value ^ b] ^ (_value >> 8); _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
} }
public void Update(byte[] data, uint offset, uint size) public void Update(byte[] data, uint offset, uint size)
{ {
for (uint i = 0; i < size; i++) for (uint i = 0; i < size; i++)
_value = Table[(byte)_value ^ data[offset + i]] ^ (_value >> 8); _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
} }
public uint GetDigest() { return _value ^ 0xFFFFFFFF; } public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
public static uint CalculateDigest(byte[] data, uint offset, uint size) static uint CalculateDigest(byte[] data, uint offset, uint size)
{ {
var crc = new CRC(); CRC crc = new CRC();
// crc.Init(); // crc.Init();
crc.Update(data, offset, size); crc.Update(data, offset, size);
return crc.GetDigest(); return crc.GetDigest();
@@ -49,7 +49,7 @@ namespace SevenZip
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
{ {
return CalculateDigest(data, offset, size) == digest; return (CalculateDigest(data, offset, size) == digest);
} }
} }
} }

View File

@@ -2,25 +2,18 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023-2024</Copyright> <Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2025</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' "> <ItemGroup>
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" /> <PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
<PackageReference Include="ZstdSharp.Port" Version="0.7.6" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
<PackageReference Include="System.Memory" Version="4.5.5" /> <PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="System.IO.Compression" Version="4.0.0" /> <PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="K4os.Compression.LZ4" Version="1.1.11" />
<PackageReference Include="ZstdSharp.Port" Version="0.6.5" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
@@ -11,48 +10,18 @@ namespace AssetStudio
{ {
public class AssetsManager public class AssetsManager
{ {
public bool ZstdEnabled = true; public string SpecifyUnityVersion;
public bool LoadingViaTypeTreeEnabled = true;
public List<SerializedFile> assetsFileList = new List<SerializedFile>(); 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, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
internal ConcurrentDictionary<string, BinaryReader> resourceFileReaders = new ConcurrentDictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase); internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
private UnityVersion specifiedUnityVersion;
private List<string> importFiles = new List<string>(); private List<string> importFiles = new List<string>();
private HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
public UnityVersion SpecifyUnityVersion
{
get => specifiedUnityVersion;
set
{
if (specifiedUnityVersion == value)
{
return;
}
if (value == null)
{
specifiedUnityVersion = null;
Logger.Info("Specified Unity version: None");
return;
}
if (string.IsNullOrEmpty(value.BuildType))
{
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");
}
specifiedUnityVersion = value;
Logger.Info($"Specified Unity version: {specifiedUnityVersion}");
}
}
public void SetAssetFilter(params ClassIDType[] classIDTypes) public void SetAssetFilter(params ClassIDType[] classIDTypes)
{ {
if (filteredAssetTypesList.Count == 0) if (filteredAssetTypesList.Count == 0)
@@ -61,8 +30,6 @@ namespace AssetStudio
{ {
ClassIDType.AssetBundle, ClassIDType.AssetBundle,
ClassIDType.ResourceManager, ClassIDType.ResourceManager,
ClassIDType.GameObject,
ClassIDType.Transform,
}); });
} }
@@ -70,10 +37,15 @@ namespace AssetStudio
{ {
filteredAssetTypesList.Add(ClassIDType.MonoScript); filteredAssetTypesList.Add(ClassIDType.MonoScript);
} }
if (classIDTypes.Contains(ClassIDType.Sprite)) if (classIDTypes.Contains(ClassIDType.Sprite) || classIDTypes.Contains(ClassIDType.AkPortraitSprite))
{ {
filteredAssetTypesList.Add(ClassIDType.Texture2D); filteredAssetTypesList.UnionWith(new HashSet<ClassIDType>
filteredAssetTypesList.Add(ClassIDType.SpriteAtlas); {
ClassIDType.Texture2D,
ClassIDType.SpriteAtlas,
ClassIDType.MonoBehaviour,
ClassIDType.MonoScript
});
} }
filteredAssetTypesList.UnionWith(classIDTypes); filteredAssetTypesList.UnionWith(classIDTypes);
@@ -86,21 +58,21 @@ namespace AssetStudio
public void LoadFilesAndFolders(params string[] path) public void LoadFilesAndFolders(params string[] path)
{ {
var pathList = new List<string>(); List<string> pathList = new List<string>();
pathList.AddRange(path); pathList.AddRange(path);
LoadFilesAndFolders(out _, pathList); LoadFilesAndFolders(out _, pathList);
} }
public void LoadFilesAndFolders(out string parentPath, params string[] path) public void LoadFilesAndFolders(out string parentPath, params string[] path)
{ {
var pathList = new List<string>(); List<string> pathList = new List<string>();
pathList.AddRange(path); pathList.AddRange(path);
LoadFilesAndFolders(out parentPath, pathList); LoadFilesAndFolders(out parentPath, pathList);
} }
public void LoadFilesAndFolders(out string parentPath, List<string> pathList) public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
{ {
var fileList = new List<string>(); List<string> fileList = new List<string>();
bool filesInPath = false; bool filesInPath = false;
parentPath = ""; parentPath = "";
foreach (var path in pathList) foreach (var path in pathList)
@@ -146,14 +118,8 @@ namespace AssetStudio
//use a for loop because list size can change //use a for loop because list size can change
for (var i = 0; i < importFiles.Count; i++) for (var i = 0; i < importFiles.Count; i++)
{ {
if (LoadFile(importFiles[i])) LoadFile(importFiles[i]);
{ Progress.Report(i + 1, importFiles.Count);
Progress.Report(i + 1, importFiles.Count);
}
else
{
break;
}
} }
importFiles.Clear(); importFiles.Clear();
@@ -165,20 +131,22 @@ namespace AssetStudio
ProcessAssets(); ProcessAssets();
} }
private bool LoadFile(string fullName) private void LoadFile(string fullName)
{ {
var reader = new FileReader(fullName); var reader = new FileReader(fullName);
return LoadFile(reader); LoadFile(reader);
} }
private bool LoadFile(FileReader reader) private void LoadFile(FileReader reader)
{ {
switch (reader?.FileType) switch (reader?.FileType)
{ {
case FileType.AssetsFile: case FileType.AssetsFile:
return LoadAssetsFile(reader); LoadAssetsFile(reader);
break;
case FileType.BundleFile: case FileType.BundleFile:
return LoadBundleFile(reader); LoadBundleFile(reader);
break;
case FileType.WebFile: case FileType.WebFile:
LoadWebFile(reader); LoadWebFile(reader);
break; break;
@@ -192,10 +160,9 @@ namespace AssetStudio
LoadZipFile(reader); LoadZipFile(reader);
break; break;
} }
return true;
} }
private bool LoadAssetsFile(FileReader reader) private void LoadAssetsFile(FileReader reader)
{ {
if (!assetsFileListHash.Contains(reader.FileName)) if (!assetsFileListHash.Contains(reader.FileName))
{ {
@@ -203,7 +170,6 @@ namespace AssetStudio
try try
{ {
var assetsFile = new SerializedFile(reader, this); var assetsFile = new SerializedFile(reader, this);
var dirName = Path.GetDirectoryName(reader.FullPath);
CheckStrippedVersion(assetsFile); CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile); assetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName); assetsFileListHash.Add(assetsFile.fileName);
@@ -214,12 +180,12 @@ namespace AssetStudio
if (!importFilesHash.Contains(sharedFileName)) if (!importFilesHash.Contains(sharedFileName))
{ {
var sharedFilePath = Path.Combine(dirName, sharedFileName); var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
if (!noexistFiles.Contains(sharedFilePath)) if (!noexistFiles.Contains(sharedFilePath))
{ {
if (!File.Exists(sharedFilePath)) if (!File.Exists(sharedFilePath))
{ {
var findFiles = Directory.GetFiles(dirName, sharedFileName, SearchOption.AllDirectories); var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
if (findFiles.Length > 0) if (findFiles.Length > 0)
{ {
sharedFilePath = findFiles[0]; sharedFilePath = findFiles[0];
@@ -242,11 +208,10 @@ namespace AssetStudio
{ {
Logger.Error(e.Message); Logger.Error(e.Message);
reader.Dispose(); reader.Dispose();
return false;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Warning($"Failed to read assets file {reader.FullPath}\r\n{e}"); Logger.Warning($"Error while reading assets file {reader.FullPath}\r\n{e}");
reader.Dispose(); reader.Dispose();
} }
} }
@@ -255,10 +220,9 @@ namespace AssetStudio
Logger.Info($"Skipping {reader.FullPath}"); Logger.Info($"Skipping {reader.FullPath}");
reader.Dispose(); reader.Dispose();
} }
return true;
} }
private bool LoadAssetsFromMemory(FileReader reader, string originalPath, UnityVersion assetBundleUnityVer = null) private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
{ {
if (!assetsFileListHash.Contains(reader.FileName)) if (!assetsFileListHash.Contains(reader.FileName))
{ {
@@ -266,59 +230,52 @@ namespace AssetStudio
{ {
var assetsFile = new SerializedFile(reader, this); var assetsFile = new SerializedFile(reader, this);
assetsFile.originalPath = originalPath; assetsFile.originalPath = originalPath;
if (assetBundleUnityVer != null && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7) if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
{ {
assetsFile.SetVersion(assetBundleUnityVer); assetsFile.SetVersion(unityVersion);
} }
CheckStrippedVersion(assetsFile, assetBundleUnityVer); CheckStrippedVersion(assetsFile);
assetsFileList.Add(assetsFile); assetsFileList.Add(assetsFile);
assetsFileListHash.Add(assetsFile.fileName); assetsFileListHash.Add(assetsFile.fileName);
} }
catch (NotSupportedException e) catch (NotSupportedException e)
{ {
Logger.Error(e.Message); Logger.Error(e.Message);
resourceFileReaders.TryAdd(reader.FileName, reader); resourceFileReaders.Add(reader.FileName, reader);
return false;
} }
catch (Exception e) catch (Exception e)
{ {
Logger.Warning($"Failed to read assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}"); Logger.Warning($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}");
resourceFileReaders.TryAdd(reader.FileName, reader); resourceFileReaders.Add(reader.FileName, reader);
} }
} }
else else
{
Logger.Info($"Skipping {originalPath} ({reader.FileName})"); Logger.Info($"Skipping {originalPath} ({reader.FileName})");
}
return true;
} }
private bool LoadBundleFile(FileReader reader, string originalPath = null) private void LoadBundleFile(FileReader reader, string originalPath = null)
{ {
Logger.Info("Loading " + reader.FullPath); Logger.Info("Loading " + reader.FullPath);
try try
{ {
var bundleFile = new BundleFile(reader, ZstdEnabled, specifiedUnityVersion); var bundleFile = new BundleFile(reader, SpecifyUnityVersion);
foreach (var file in bundleFile.fileList) foreach (var file in bundleFile.fileList)
{ {
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName); var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
var subReader = new FileReader(dummyPath, file.stream); var subReader = new FileReader(dummyPath, file.stream);
if (subReader.FileType == FileType.AssetsFile) if (subReader.FileType == FileType.AssetsFile)
{ {
if (!LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision)) LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
return false;
} }
else else if (!resourceFileReaders.ContainsKey(file.fileName))
{ {
resourceFileReaders.TryAdd(file.fileName, subReader); resourceFileReaders.Add(file.fileName, subReader);
} }
} }
return true;
} }
catch (NotSupportedException e) catch (NotSupportedException e)
{ {
Logger.Error(e.Message); Logger.Error(e.Message);
return false;
} }
catch (Exception e) catch (Exception e)
{ {
@@ -328,7 +285,6 @@ namespace AssetStudio
str += $" from {Path.GetFileName(originalPath)}"; str += $" from {Path.GetFileName(originalPath)}";
} }
Logger.Warning($"{str}\r\n{e}"); Logger.Warning($"{str}\r\n{e}");
return true;
} }
finally finally
{ {
@@ -453,7 +409,10 @@ namespace AssetStudio
if (entryReader.FileType == FileType.ResourceFile) if (entryReader.FileType == FileType.ResourceFile)
{ {
entryReader.Position = 0; entryReader.Position = 0;
resourceFileReaders.TryAdd(entry.Name, entryReader); if (!resourceFileReaders.ContainsKey(entry.Name))
{
resourceFileReaders.Add(entry.Name, entryReader);
}
} }
Progress.Report(++k, progressCount); Progress.Report(++k, progressCount);
} }
@@ -474,16 +433,13 @@ namespace AssetStudio
} }
} }
public void CheckStrippedVersion(SerializedFile assetsFile, UnityVersion bundleUnityVer = null) public void CheckStrippedVersion(SerializedFile assetsFile)
{ {
if (assetsFile.version.IsStripped && specifiedUnityVersion == null) if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
{ {
var msg = "The asset's 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 (bundleUnityVer != null && !bundleUnityVer.IsStripped)
msg += $"\n\nAssumed Unity version based on asset bundle: {bundleUnityVer}";
throw new NotSupportedException(msg);
} }
if (specifiedUnityVersion != null) if (!string.IsNullOrEmpty(SpecifyUnityVersion))
{ {
assetsFile.SetVersion(SpecifyUnityVersion); assetsFile.SetVersion(SpecifyUnityVersion);
} }
@@ -532,9 +488,7 @@ namespace AssetStudio
obj = new Animation(objectReader); obj = new Animation(objectReader);
break; break;
case ClassIDType.AnimationClip: case ClassIDType.AnimationClip:
obj = objectReader.serializedType?.m_Type != null && LoadingViaTypeTreeEnabled obj = new AnimationClip(objectReader);
? new AnimationClip(objectReader, TypeTreeHelper.ReadType(objectReader.serializedType.m_Type, objectReader))
: new AnimationClip(objectReader);
break; break;
case ClassIDType.Animator: case ClassIDType.Animator:
obj = new Animator(objectReader); obj = new Animator(objectReader);
@@ -591,7 +545,7 @@ namespace AssetStudio
obj = new RectTransform(objectReader); obj = new RectTransform(objectReader);
break; break;
case ClassIDType.Shader: case ClassIDType.Shader:
if (objectReader.version < 2021) if (objectReader.version[0] < 2021)
obj = new Shader(objectReader); obj = new Shader(objectReader);
break; break;
case ClassIDType.SkinnedMeshRenderer: case ClassIDType.SkinnedMeshRenderer:
@@ -607,14 +561,7 @@ namespace AssetStudio
obj = new TextAsset(objectReader); obj = new TextAsset(objectReader);
break; break;
case ClassIDType.Texture2D: case ClassIDType.Texture2D:
obj = objectReader.serializedType?.m_Type != null && LoadingViaTypeTreeEnabled obj = new Texture2D(objectReader);
? new Texture2D(objectReader, TypeTreeHelper.ReadType(objectReader.serializedType.m_Type, objectReader))
: new Texture2D(objectReader);
break;
case ClassIDType.Texture2DArray:
obj = objectReader.serializedType?.m_Type != null && LoadingViaTypeTreeEnabled
? new Texture2DArray(objectReader, TypeTreeHelper.ReadType(objectReader.serializedType.m_Type, objectReader))
: new Texture2DArray(objectReader);
break; break;
case ClassIDType.Transform: case ClassIDType.Transform:
obj = new Transform(objectReader); obj = new Transform(objectReader);
@@ -630,9 +577,7 @@ namespace AssetStudio
break; break;
} }
if (obj != null) if (obj != null)
{
assetsFile.AddObject(obj); assetsFile.AddObject(obj);
}
} }
catch (Exception e) catch (Exception e)
{ {

View File

@@ -4,11 +4,7 @@ namespace AssetStudio
{ {
public static class BigArrayPool<T> public static class BigArrayPool<T>
{ {
public static ArrayPool<T> Shared { get; } private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
public static ArrayPool<T> Shared => s_shared;
static BigArrayPool()
{
Shared = ArrayPool<T>.Create(256 * 1024 * 1024, 5);
}
} }
} }

View File

@@ -1,5 +1,4 @@
using K4os.Compression.LZ4; using K4os.Compression.LZ4;
using ZstdSharp;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -36,8 +35,7 @@ namespace AssetStudio
Lzma, Lzma,
Lz4, Lz4,
Lz4HC, Lz4HC,
Lzham, Lz4Inv,
Custom,
} }
public class BundleFile public class BundleFile
@@ -47,7 +45,7 @@ namespace AssetStudio
public string signature; public string signature;
public uint version; public uint version;
public string unityVersion; public string unityVersion;
public UnityVersion unityRevision; public string unityRevision;
public long size; public long size;
public uint compressedBlocksInfoSize; public uint compressedBlocksInfoSize;
public uint uncompressedBlocksInfoSize; public uint uncompressedBlocksInfoSize;
@@ -75,13 +73,13 @@ namespace AssetStudio
public StreamFile[] fileList; public StreamFile[] fileList;
public BundleFile(FileReader reader, bool useZstd, UnityVersion specUnityVer = null) public BundleFile(FileReader reader, string specUnityVer = "")
{ {
m_Header = new Header(); m_Header = new Header();
m_Header.signature = reader.ReadStringToNull(); m_Header.signature = reader.ReadStringToNull();
m_Header.version = reader.ReadUInt32(); m_Header.version = reader.ReadUInt32();
m_Header.unityVersion = reader.ReadStringToNull(); m_Header.unityVersion = reader.ReadStringToNull();
m_Header.unityRevision = new UnityVersion(reader.ReadStringToNull()); m_Header.unityRevision = reader.ReadStringToNull();
switch (m_Header.signature) switch (m_Header.signature)
{ {
case "UnityArchive": case "UnityArchive":
@@ -102,26 +100,16 @@ namespace AssetStudio
case "UnityFS": case "UnityFS":
ReadHeader(reader); ReadHeader(reader);
var isUnityCnEnc = false; bool isUnityCnEnc = false;
var unityVer = m_Header.unityRevision; string unityVer = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer;
if (specUnityVer != null) 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)
if (!unityVer.IsStripped && specUnityVer != unityVer)
{
Logger.Warning($"Detected Unity version is different from the specified one ({specUnityVer.FullVersion.Color(ColorConsole.BrightCyan)}).\n" +
$"Assets may load with errors.\n" +
$"It is recommended to specify the detected Unity version: {unityVer.FullVersion.Color(ColorConsole.BrightCyan)}");
}
unityVer = specUnityVer;
}
if (!unityVer.IsStripped)
{ {
// https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch // https://issuetracker.unity3d.com/issues/files-within-assetbundles-do-not-start-on-aligned-boundaries-breaking-patching-on-nintendo-switch
if (unityVer < 2020 if (ver[0] < 2020 ||
|| unityVer.IsInRange(2020, (2020, 3, 34)) (ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) ||
|| unityVer.IsInRange(2021, (2021, 3, 2)) (ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) ||
|| unityVer.IsInRange(2022, (2022, 1, 1))) (ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1))
{ {
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0; isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0;
} }
@@ -132,24 +120,20 @@ namespace AssetStudio
} }
if (isUnityCnEnc) if (isUnityCnEnc)
{ {
var msg = "Unsupported bundle file. "; throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
msg += specUnityVer != null
? "UnityCN encryption was detected or the specified Unity version is incorrect."
: "UnityCN encryption was detected.";
throw new NotSupportedException(msg);
} }
ReadBlocksInfoAndDirectory(reader, unityVer); ReadBlocksInfoAndDirectory(reader, ver);
using (var blocksStream = CreateBlocksStream(reader.FullPath)) using (var blocksStream = CreateBlocksStream(reader.FullPath))
{ {
ReadBlocks(reader, blocksStream, useZstd); ReadBlocks(reader, blocksStream);
ReadFiles(blocksStream, reader.FullPath); ReadFiles(blocksStream, reader.FullPath);
} }
break; break;
} }
} }
private void ReadHeaderAndBlocksInfo(FileReader reader) private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
{ {
if (m_Header.version >= 4) if (m_Header.version >= 4)
{ {
@@ -201,7 +185,7 @@ namespace AssetStudio
return blocksStream; return blocksStream;
} }
private void ReadBlocksAndDirectory(FileReader reader, Stream blocksStream) private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
{ {
var isCompressed = m_Header.signature == "UnityWeb"; var isCompressed = m_Header.signature == "UnityWeb";
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
@@ -262,7 +246,7 @@ namespace AssetStudio
} }
} }
private void ReadHeader(FileReader reader) private void ReadHeader(EndianBinaryReader reader)
{ {
m_Header.size = reader.ReadInt64(); m_Header.size = reader.ReadInt64();
m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
@@ -274,7 +258,7 @@ namespace AssetStudio
} }
} }
private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer) private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader, int[] unityVer)
{ {
byte[] blocksInfoBytes; byte[] blocksInfoBytes;
@@ -282,7 +266,7 @@ namespace AssetStudio
{ {
reader.AlignStream(16); reader.AlignStream(16);
} }
else if (unityVer >= (2019, 4) && m_Header.flags != ArchiveFlags.BlocksAndDirectoryInfoCombined) else if (unityVer[0] >= 2019 && unityVer[1] >= 4)
{ {
//check if we need to align the reader //check if we need to align the reader
//- align to 16 bytes and check if all are 0 //- align to 16 bytes and check if all are 0
@@ -306,44 +290,42 @@ namespace AssetStudio
{ {
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
} }
MemoryStream blocksInfoUncompressedStream; MemoryStream blocksInfoUncompresseddStream;
var uncompressedSize = m_Header.uncompressedBlocksInfoSize; var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask); var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
switch (compressionType) switch (compressionType)
{ {
case CompressionType.None: case CompressionType.None:
{
blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes);
break;
}
case CompressionType.Lzma:
{
blocksInfoUncompressedStream = new MemoryStream((int) (uncompressedSize));
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{ {
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompressedStream, blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); break;
}
case CompressionType.Lzma:
{
blocksInfoUncompresseddStream = new MemoryStream((int)(uncompressedSize));
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
{
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompresseddStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
}
blocksInfoUncompresseddStream.Position = 0;
break;
} }
blocksInfoUncompressedStream.Position = 0;
break;
}
case CompressionType.Lz4: case CompressionType.Lz4:
case CompressionType.Lz4HC: 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"); 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;
} }
blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes);
break;
}
default: default:
throw new IOException($"Unsupported block info compression type {compressionType}"); throw new IOException($"Unsupported compression type {compressionType}");
} }
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream))
{ {
var uncompressedDataHash = blocksInfoReader.ReadBytes(16); var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
var blocksInfoCount = blocksInfoReader.ReadInt32(); var blocksInfoCount = blocksInfoReader.ReadInt32();
@@ -377,72 +359,54 @@ namespace AssetStudio
} }
} }
private void ReadBlocks(FileReader reader, Stream blocksStream, bool useZstd) private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
{ {
var zstdCodec = new Decompressor();
var i = 0;
foreach (var blockInfo in m_BlocksInfo) foreach (var blockInfo in m_BlocksInfo)
{ {
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask); var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
switch (compressionType) switch (compressionType)
{ {
case CompressionType.None: case CompressionType.None:
{ {
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize); reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
break; break;
} }
case CompressionType.Lzma: case CompressionType.Lzma:
{ {
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize); SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
break; break;
} }
case CompressionType.Lz4: case CompressionType.Lz4:
case CompressionType.Lz4HC: case CompressionType.Lz4HC:
case CompressionType.Custom: case CompressionType.Lz4Inv:
{
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);
try
{ {
var compTypeStr = compressionType.ToString(); var compressedSize = (int)blockInfo.compressedSize;
if (compressionType == CompressionType.Custom) var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
_ = reader.Read(compressedBytes, 0, compressedSize);
var uncompressedSize = (int)blockInfo.uncompressedSize;
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
try
{ {
compTypeStr = useZstd ? "Zstd" : "Lz4"; var compressedSpan = compressedBytes.AsSpan(0, compressedSize);
if (i == 0) var uncompressedSpan = uncompressedBytes.AsSpan(0, uncompressedSize);
var numWrite = compressionType == CompressionType.Lz4Inv
? LZ4Inv.Instance.Decompress(compressedSpan, uncompressedSpan)
: LZ4Codec.Decode(compressedSpan, uncompressedSpan);
if (numWrite != uncompressedSize)
{ {
Logger.Debug($"Custom block compression type was detected. Trying to decompress as {compTypeStr} archive.."); throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
i++;
} }
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
} }
finally
int numWrite;
if (compressionType == CompressionType.Custom && useZstd)
{ {
numWrite = zstdCodec.Unwrap(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize); BigArrayPool<byte>.Shared.Return(compressedBytes);
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
} }
else break;
{
numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
}
if (numWrite != uncompressedSize)
{
throw new IOException($"{compTypeStr} block decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
}
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
} }
finally
{
BigArrayPool<byte>.Shared.Return(compressedBytes, clearArray: true);
BigArrayPool<byte>.Shared.Return(uncompressedBytes, clearArray: true);
}
break;
}
default: default:
throw new IOException($"Unsupported block compression type {compressionType}"); throw new IOException($"Unsupported compression type {compressionType}");
} }
} }
blocksStream.Position = 0; blocksStream.Position = 0;

View File

@@ -3,6 +3,7 @@ namespace AssetStudio
{ {
public enum ClassIDType public enum ClassIDType
{ {
AkPortraitSprite = -2,
UnknownType = -1, UnknownType = -1,
Object = 0, Object = 0,
GameObject = 1, GameObject = 1,
@@ -145,7 +146,6 @@ namespace AssetStudio
ProceduralMaterial = 185, ProceduralMaterial = 185,
ProceduralTexture = 186, ProceduralTexture = 186,
Texture2DArray = 187, Texture2DArray = 187,
Texture2DArrayImage = -187, //fake type
CubemapArray = 188, CubemapArray = 188,
OffMeshLink = 191, OffMeshLink = 191,
OcclusionArea = 192, OcclusionArea = 192,

View File

@@ -1,6 +1,4 @@
using Newtonsoft.Json; using System;
using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -17,15 +15,13 @@ namespace AssetStudio
public T inWeight; public T inWeight;
public T outWeight; public T outWeight;
public Keyframe() { }
public Keyframe(ObjectReader reader, Func<T> readerFunc) public Keyframe(ObjectReader reader, Func<T> readerFunc)
{ {
time = reader.ReadSingle(); time = reader.ReadSingle();
value = readerFunc(); value = readerFunc();
inSlope = readerFunc(); inSlope = readerFunc();
outSlope = readerFunc(); outSlope = readerFunc();
if (reader.version >= 2018) //2018 and up if (reader.version[0] >= 2018) //2018 and up
{ {
weightedMode = reader.ReadInt32(); weightedMode = reader.ReadInt32();
inWeight = readerFunc(); inWeight = readerFunc();
@@ -41,8 +37,6 @@ namespace AssetStudio
public int m_PostInfinity; public int m_PostInfinity;
public int m_RotationOrder; public int m_RotationOrder;
public AnimationCurve() { }
public AnimationCurve(ObjectReader reader, Func<T> readerFunc) public AnimationCurve(ObjectReader reader, Func<T> readerFunc)
{ {
var version = reader.version; var version = reader.version;
@@ -55,7 +49,7 @@ namespace AssetStudio
m_PreInfinity = reader.ReadInt32(); m_PreInfinity = reader.ReadInt32();
m_PostInfinity = reader.ReadInt32(); m_PostInfinity = reader.ReadInt32();
if (version >= (5, 3)) //5.3 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
{ {
m_RotationOrder = reader.ReadInt32(); m_RotationOrder = reader.ReadInt32();
} }
@@ -67,8 +61,6 @@ namespace AssetStudio
public AnimationCurve<Quaternion> curve; public AnimationCurve<Quaternion> curve;
public string path; public string path;
public QuaternionCurve() { }
public QuaternionCurve(ObjectReader reader) public QuaternionCurve(ObjectReader reader)
{ {
curve = new AnimationCurve<Quaternion>(reader, reader.ReadQuaternion); curve = new AnimationCurve<Quaternion>(reader, reader.ReadQuaternion);
@@ -84,8 +76,6 @@ namespace AssetStudio
public byte[] m_Data; public byte[] m_Data;
public byte m_BitSize; public byte m_BitSize;
public PackedFloatVector() { }
public PackedFloatVector(ObjectReader reader) public PackedFloatVector(ObjectReader reader)
{ {
m_NumItems = reader.ReadUInt32(); m_NumItems = reader.ReadUInt32();
@@ -145,8 +135,6 @@ namespace AssetStudio
public byte[] m_Data; public byte[] m_Data;
public byte m_BitSize; public byte m_BitSize;
public PackedIntVector() { }
public PackedIntVector(ObjectReader reader) public PackedIntVector(ObjectReader reader)
{ {
m_NumItems = reader.ReadUInt32(); m_NumItems = reader.ReadUInt32();
@@ -191,8 +179,6 @@ namespace AssetStudio
public uint m_NumItems; public uint m_NumItems;
public byte[] m_Data; public byte[] m_Data;
public PackedQuatVector() { }
public PackedQuatVector(ObjectReader reader) public PackedQuatVector(ObjectReader reader)
{ {
m_NumItems = reader.ReadUInt32(); m_NumItems = reader.ReadUInt32();
@@ -277,8 +263,6 @@ namespace AssetStudio
public int m_PreInfinity; public int m_PreInfinity;
public int m_PostInfinity; public int m_PostInfinity;
public CompressedAnimationCurve() { }
public CompressedAnimationCurve(ObjectReader reader) public CompressedAnimationCurve(ObjectReader reader)
{ {
m_Path = reader.ReadAlignedString(); m_Path = reader.ReadAlignedString();
@@ -295,8 +279,6 @@ namespace AssetStudio
public AnimationCurve<Vector3> curve; public AnimationCurve<Vector3> curve;
public string path; public string path;
public Vector3Curve() { }
public Vector3Curve(ObjectReader reader) public Vector3Curve(ObjectReader reader)
{ {
curve = new AnimationCurve<Vector3>(reader, reader.ReadVector3); curve = new AnimationCurve<Vector3>(reader, reader.ReadVector3);
@@ -313,8 +295,6 @@ namespace AssetStudio
public PPtr<MonoScript> script; public PPtr<MonoScript> script;
public int flags; public int flags;
public FloatCurve() { }
public FloatCurve(ObjectReader reader) public FloatCurve(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
@@ -323,7 +303,7 @@ namespace AssetStudio
path = reader.ReadAlignedString(); path = reader.ReadAlignedString();
classID = (ClassIDType)reader.ReadInt32(); classID = (ClassIDType)reader.ReadInt32();
script = new PPtr<MonoScript>(reader); script = new PPtr<MonoScript>(reader);
if (version >= (2022, 2)) //2022.2 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
{ {
flags = reader.ReadInt32(); flags = reader.ReadInt32();
} }
@@ -335,8 +315,6 @@ namespace AssetStudio
public float time; public float time;
public PPtr<Object> value; public PPtr<Object> value;
public PPtrKeyframe() { }
public PPtrKeyframe(ObjectReader reader) public PPtrKeyframe(ObjectReader reader)
{ {
time = reader.ReadSingle(); time = reader.ReadSingle();
@@ -353,8 +331,6 @@ namespace AssetStudio
public PPtr<MonoScript> script; public PPtr<MonoScript> script;
public int flags; public int flags;
public PPtrCurve() { }
public PPtrCurve(ObjectReader reader) public PPtrCurve(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
@@ -369,7 +345,7 @@ namespace AssetStudio
path = reader.ReadAlignedString(); path = reader.ReadAlignedString();
classID = reader.ReadInt32(); classID = reader.ReadInt32();
script = new PPtr<MonoScript>(reader); script = new PPtr<MonoScript>(reader);
if (version >= (2022, 2)) //2022.2 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
{ {
flags = reader.ReadInt32(); flags = reader.ReadInt32();
} }
@@ -381,8 +357,6 @@ namespace AssetStudio
public Vector3 m_Center; public Vector3 m_Center;
public Vector3 m_Extent; public Vector3 m_Extent;
public AABB() { }
public AABB(ObjectReader reader) public AABB(ObjectReader reader)
{ {
m_Center = reader.ReadVector3(); m_Center = reader.ReadVector3();
@@ -396,14 +370,12 @@ namespace AssetStudio
public Quaternion q; public Quaternion q;
public Vector3 s; public Vector3 s;
public xform() { }
public xform(ObjectReader reader) public xform(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
t = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
q = reader.ReadQuaternion(); q = reader.ReadQuaternion();
s = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
} }
} }
@@ -416,8 +388,6 @@ namespace AssetStudio
public float m_InOut; public float m_InOut;
public float m_Grab; public float m_Grab;
public HandPose() { }
public HandPose(ObjectReader reader) public HandPose(ObjectReader reader)
{ {
m_GrabX = new xform(reader); m_GrabX = new xform(reader);
@@ -437,17 +407,15 @@ namespace AssetStudio
public Vector3 m_HintT; public Vector3 m_HintT;
public float m_HintWeightT; public float m_HintWeightT;
public HumanGoal() { }
public HumanGoal(ObjectReader reader) public HumanGoal(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
m_X = new xform(reader); m_X = new xform(reader);
m_WeightT = reader.ReadSingle(); m_WeightT = reader.ReadSingle();
m_WeightR = reader.ReadSingle(); m_WeightR = reader.ReadSingle();
if (version >= 5)//5.0 and up if (version[0] >= 5)//5.0 and up
{ {
m_HintT = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_HintWeightT = reader.ReadSingle(); m_HintWeightT = reader.ReadSingle();
} }
} }
@@ -464,13 +432,11 @@ namespace AssetStudio
public float[] m_DoFArray; public float[] m_DoFArray;
public Vector3[] m_TDoFArray; public Vector3[] m_TDoFArray;
public HumanPose() { }
public HumanPose(ObjectReader reader) public HumanPose(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
m_RootX = new xform(reader); m_RootX = new xform(reader);
m_LookAtPosition = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_LookAtWeight = reader.ReadVector4(); m_LookAtWeight = reader.ReadVector4();
int numGoals = reader.ReadInt32(); int numGoals = reader.ReadInt32();
@@ -485,13 +451,13 @@ namespace AssetStudio
m_DoFArray = reader.ReadSingleArray(); m_DoFArray = reader.ReadSingleArray();
if (version >= (5, 2))//5.2 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 2))//5.2 and up
{ {
int numTDof = reader.ReadInt32(); int numTDof = reader.ReadInt32();
m_TDoFArray = new Vector3[numTDof]; m_TDoFArray = new Vector3[numTDof];
for (int i = 0; i < numTDof; i++) for (int i = 0; i < numTDof; i++)
{ {
m_TDoFArray[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
} }
} }
} }
@@ -502,8 +468,6 @@ namespace AssetStudio
public uint[] data; public uint[] data;
public uint curveCount; public uint curveCount;
public StreamedClip() { }
public StreamedClip(ObjectReader reader) public StreamedClip(ObjectReader reader)
{ {
data = reader.ReadUInt32Array(); data = reader.ReadUInt32Array();
@@ -519,8 +483,6 @@ namespace AssetStudio
public float outSlope; public float outSlope;
public float inSlope; public float inSlope;
public StreamedCurveKey() { }
public StreamedCurveKey(BinaryReader reader) public StreamedCurveKey(BinaryReader reader)
{ {
index = reader.ReadInt32(); index = reader.ReadInt32();
@@ -552,8 +514,6 @@ namespace AssetStudio
public float time; public float time;
public StreamedCurveKey[] keyList; public StreamedCurveKey[] keyList;
public StreamedFrame() { }
public StreamedFrame(BinaryReader reader) public StreamedFrame(BinaryReader reader)
{ {
time = reader.ReadSingle(); time = reader.ReadSingle();
@@ -609,8 +569,6 @@ namespace AssetStudio
public float m_BeginTime; public float m_BeginTime;
public float[] m_SampleArray; public float[] m_SampleArray;
public DenseClip() { }
public DenseClip(ObjectReader reader) public DenseClip(ObjectReader reader)
{ {
m_FrameCount = reader.ReadInt32(); m_FrameCount = reader.ReadInt32();
@@ -625,8 +583,6 @@ namespace AssetStudio
{ {
public float[] data; public float[] data;
public ConstantClip() { }
public ConstantClip(ObjectReader reader) public ConstantClip(ObjectReader reader)
{ {
data = reader.ReadSingleArray(); data = reader.ReadSingleArray();
@@ -640,13 +596,11 @@ namespace AssetStudio
public uint m_Type; public uint m_Type;
public uint m_Index; public uint m_Index;
public ValueConstant() { }
public ValueConstant(ObjectReader reader) public ValueConstant(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
m_ID = reader.ReadUInt32(); m_ID = reader.ReadUInt32();
if (version < (5, 5)) //5.5 down if (version[0] < 5 || (version[0] == 5 && version[1] < 5))//5.5 down
{ {
m_TypeID = reader.ReadUInt32(); m_TypeID = reader.ReadUInt32();
} }
@@ -659,8 +613,6 @@ namespace AssetStudio
{ {
public ValueConstant[] m_ValueArray; public ValueConstant[] m_ValueArray;
public ValueArrayConstant() { }
public ValueArrayConstant(ObjectReader reader) public ValueArrayConstant(ObjectReader reader)
{ {
int numVals = reader.ReadInt32(); int numVals = reader.ReadInt32();
@@ -672,18 +624,6 @@ namespace AssetStudio
} }
} }
public class OffsetPtr
{
public Clip data;
public OffsetPtr() { }
public OffsetPtr(ObjectReader reader)
{
data = new Clip(reader);
}
}
public class Clip public class Clip
{ {
public StreamedClip m_StreamedClip; public StreamedClip m_StreamedClip;
@@ -691,18 +631,16 @@ namespace AssetStudio
public ConstantClip m_ConstantClip; public ConstantClip m_ConstantClip;
public ValueArrayConstant m_Binding; public ValueArrayConstant m_Binding;
public Clip() { }
public Clip(ObjectReader reader) public Clip(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
m_StreamedClip = new StreamedClip(reader); m_StreamedClip = new StreamedClip(reader);
m_DenseClip = new DenseClip(reader); m_DenseClip = new DenseClip(reader);
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_ConstantClip = new ConstantClip(reader); m_ConstantClip = new ConstantClip(reader);
} }
if (version < (2018, 3)) //2018.3 down if (version[0] < 2018 || (version[0] == 2018 && version[1] < 3)) //2018.3 down
{ {
m_Binding = new ValueArrayConstant(reader); m_Binding = new ValueArrayConstant(reader);
} }
@@ -758,8 +696,6 @@ namespace AssetStudio
public float m_Start; public float m_Start;
public float m_Stop; public float m_Stop;
public ValueDelta() { }
public ValueDelta(ObjectReader reader) public ValueDelta(ObjectReader reader)
{ {
m_Start = reader.ReadSingle(); m_Start = reader.ReadSingle();
@@ -777,7 +713,7 @@ namespace AssetStudio
public xform m_MotionStartX; public xform m_MotionStartX;
public xform m_MotionStopX; public xform m_MotionStopX;
public Vector3 m_AverageSpeed; public Vector3 m_AverageSpeed;
public OffsetPtr m_Clip; public Clip m_Clip;
public float m_StartTime; public float m_StartTime;
public float m_StopTime; public float m_StopTime;
public float m_OrientationOffsetY; public float m_OrientationOffsetY;
@@ -799,26 +735,24 @@ namespace AssetStudio
public bool m_KeepOriginalPositionXZ; public bool m_KeepOriginalPositionXZ;
public bool m_HeightFromFeet; public bool m_HeightFromFeet;
public ClipMuscleConstant() { }
public ClipMuscleConstant(ObjectReader reader) public ClipMuscleConstant(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
m_DeltaPose = new HumanPose(reader); m_DeltaPose = new HumanPose(reader);
m_StartX = new xform(reader); m_StartX = new xform(reader);
if (version >= (5, 5)) //5.5 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
{ {
m_StopX = new xform(reader); m_StopX = new xform(reader);
} }
m_LeftFootStartX = new xform(reader); m_LeftFootStartX = new xform(reader);
m_RightFootStartX = new xform(reader); m_RightFootStartX = new xform(reader);
if (version < 5)//5.0 down if (version[0] < 5)//5.0 down
{ {
m_MotionStartX = new xform(reader); m_MotionStartX = new xform(reader);
m_MotionStopX = new xform(reader); m_MotionStopX = new xform(reader);
} }
m_AverageSpeed = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
m_Clip = new OffsetPtr(reader); m_Clip = new Clip(reader);
m_StartTime = reader.ReadSingle(); m_StartTime = reader.ReadSingle();
m_StopTime = reader.ReadSingle(); m_StopTime = reader.ReadSingle();
m_OrientationOffsetY = reader.ReadSingle(); m_OrientationOffsetY = reader.ReadSingle();
@@ -827,7 +761,7 @@ namespace AssetStudio
m_AverageAngularSpeed = reader.ReadSingle(); m_AverageAngularSpeed = reader.ReadSingle();
m_IndexArray = reader.ReadInt32Array(); m_IndexArray = reader.ReadInt32Array();
if (version < (4, 3)) //4.3 down if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
{ {
var m_AdditionalCurveIndexArray = reader.ReadInt32Array(); var m_AdditionalCurveIndexArray = reader.ReadInt32Array();
} }
@@ -837,13 +771,13 @@ namespace AssetStudio
{ {
m_ValueArrayDelta[i] = new ValueDelta(reader); m_ValueArrayDelta[i] = new ValueDelta(reader);
} }
if (version >= (5, 3))//5.3 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
{ {
m_ValueArrayReferencePose = reader.ReadSingleArray(); m_ValueArrayReferencePose = reader.ReadSingleArray();
} }
m_Mirror = reader.ReadBoolean(); m_Mirror = reader.ReadBoolean();
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_LoopTime = reader.ReadBoolean(); m_LoopTime = reader.ReadBoolean();
} }
@@ -851,7 +785,7 @@ namespace AssetStudio
m_LoopBlendOrientation = reader.ReadBoolean(); m_LoopBlendOrientation = reader.ReadBoolean();
m_LoopBlendPositionY = reader.ReadBoolean(); m_LoopBlendPositionY = reader.ReadBoolean();
m_LoopBlendPositionXZ = reader.ReadBoolean(); m_LoopBlendPositionXZ = reader.ReadBoolean();
if (version >= (5, 5))//5.5 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
{ {
m_StartAtOrigin = reader.ReadBoolean(); m_StartAtOrigin = reader.ReadBoolean();
} }
@@ -881,7 +815,7 @@ namespace AssetStudio
path = reader.ReadUInt32(); path = reader.ReadUInt32();
attribute = reader.ReadUInt32(); attribute = reader.ReadUInt32();
script = new PPtr<Object>(reader); script = new PPtr<Object>(reader);
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
typeID = (ClassIDType)reader.ReadInt32(); typeID = (ClassIDType)reader.ReadInt32();
} }
@@ -891,7 +825,7 @@ namespace AssetStudio
} }
customType = reader.ReadByte(); customType = reader.ReadByte();
isPPtrCurve = reader.ReadByte(); isPPtrCurve = reader.ReadByte();
if (version >= (2022, 1)) //2022.1 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{ {
isIntCurve = reader.ReadByte(); isIntCurve = reader.ReadByte();
} }
@@ -969,8 +903,6 @@ namespace AssetStudio
public int intParameter; public int intParameter;
public int messageOptions; public int messageOptions;
public AnimationEvent() { }
public AnimationEvent(ObjectReader reader) public AnimationEvent(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
@@ -980,7 +912,7 @@ namespace AssetStudio
data = reader.ReadAlignedString(); data = reader.ReadAlignedString();
objectReferenceParameter = new PPtr<Object>(reader); objectReferenceParameter = new PPtr<Object>(reader);
floatParameter = reader.ReadSingle(); floatParameter = reader.ReadSingle();
if (version >= 3) //3 and up if (version[0] >= 3) //3 and up
{ {
intParameter = reader.ReadInt32(); intParameter = reader.ReadInt32();
} }
@@ -1016,40 +948,13 @@ namespace AssetStudio
public AnimationClipBindingConstant m_ClipBindingConstant; public AnimationClipBindingConstant m_ClipBindingConstant;
public AnimationEvent[] m_Events; public AnimationEvent[] m_Events;
public AnimationClip() { }
public AnimationClip(ObjectReader reader, IDictionary typeDict) : base(reader)
{
var parsedAnimClip = JsonConvert.DeserializeObject<AnimationClip>(JsonConvert.SerializeObject(typeDict));
m_AnimationType = parsedAnimClip.m_AnimationType;
m_Legacy = parsedAnimClip.m_Legacy;
m_Compressed = parsedAnimClip.m_Compressed;
m_UseHighQualityCurve = parsedAnimClip.m_UseHighQualityCurve;
m_RotationCurves = parsedAnimClip.m_RotationCurves;
m_CompressedRotationCurves = parsedAnimClip.m_CompressedRotationCurves;
m_EulerCurves = parsedAnimClip.m_EulerCurves;
m_PositionCurves = parsedAnimClip.m_PositionCurves;
m_ScaleCurves = parsedAnimClip.m_ScaleCurves;
m_FloatCurves = parsedAnimClip.m_FloatCurves;
m_PPtrCurves = parsedAnimClip.m_PPtrCurves;
m_SampleRate = parsedAnimClip.m_SampleRate;
m_WrapMode = parsedAnimClip.m_WrapMode;
m_Bounds = parsedAnimClip.m_Bounds;
m_MuscleClipSize = parsedAnimClip.m_MuscleClipSize;
m_MuscleClip = parsedAnimClip.m_MuscleClip;
m_ClipBindingConstant = parsedAnimClip.m_ClipBindingConstant;
m_Events = parsedAnimClip.m_Events;
typeDict.Clear();
}
public AnimationClip(ObjectReader reader) : base(reader) public AnimationClip(ObjectReader reader) : base(reader)
{ {
if (version >= 5)//5.0 and up if (version[0] >= 5)//5.0 and up
{ {
m_Legacy = reader.ReadBoolean(); m_Legacy = reader.ReadBoolean();
} }
else if (version >= 4)//4.0 and up else if (version[0] >= 4)//4.0 and up
{ {
m_AnimationType = (AnimationType)reader.ReadInt32(); m_AnimationType = (AnimationType)reader.ReadInt32();
if (m_AnimationType == AnimationType.Legacy) if (m_AnimationType == AnimationType.Legacy)
@@ -1060,7 +965,7 @@ namespace AssetStudio
m_Legacy = true; m_Legacy = true;
} }
m_Compressed = reader.ReadBoolean(); m_Compressed = reader.ReadBoolean();
if (version >= (4, 3))//4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up
{ {
m_UseHighQualityCurve = reader.ReadBoolean(); m_UseHighQualityCurve = reader.ReadBoolean();
} }
@@ -1079,7 +984,7 @@ namespace AssetStudio
m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader); m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader);
} }
if (version >= (5, 3))//5.3 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
{ {
int numEulerCurves = reader.ReadInt32(); int numEulerCurves = reader.ReadInt32();
m_EulerCurves = new Vector3Curve[numEulerCurves]; m_EulerCurves = new Vector3Curve[numEulerCurves];
@@ -1110,7 +1015,7 @@ namespace AssetStudio
m_FloatCurves[i] = new FloatCurve(reader); m_FloatCurves[i] = new FloatCurve(reader);
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
int numPtrCurves = reader.ReadInt32(); int numPtrCurves = reader.ReadInt32();
m_PPtrCurves = new PPtrCurve[numPtrCurves]; m_PPtrCurves = new PPtrCurve[numPtrCurves];
@@ -1122,20 +1027,20 @@ namespace AssetStudio
m_SampleRate = reader.ReadSingle(); m_SampleRate = reader.ReadSingle();
m_WrapMode = reader.ReadInt32(); m_WrapMode = reader.ReadInt32();
if (version >= (3, 4)) //3.4 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
{ {
m_Bounds = new AABB(reader); m_Bounds = new AABB(reader);
} }
if (version >= 4)//4.0 and up if (version[0] >= 4)//4.0 and up
{ {
m_MuscleClipSize = reader.ReadUInt32(); m_MuscleClipSize = reader.ReadUInt32();
m_MuscleClip = new ClipMuscleConstant(reader); m_MuscleClip = new ClipMuscleConstant(reader);
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_ClipBindingConstant = new AnimationClipBindingConstant(reader); m_ClipBindingConstant = new AnimationClipBindingConstant(reader);
} }
if (version >= (2018, 3)) //2018.3 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
{ {
var m_HasGenericRootTransform = reader.ReadBoolean(); var m_HasGenericRootTransform = reader.ReadBoolean();
var m_HasMotionFloatCurves = reader.ReadBoolean(); var m_HasMotionFloatCurves = reader.ReadBoolean();
@@ -1147,7 +1052,7 @@ namespace AssetStudio
{ {
m_Events[i] = new AnimationEvent(reader); m_Events[i] = new AnimationEvent(reader);
} }
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
reader.AlignStream(); reader.AlignStream();
} }

View File

@@ -17,47 +17,47 @@ namespace AssetStudio
m_Controller = new PPtr<RuntimeAnimatorController>(reader); m_Controller = new PPtr<RuntimeAnimatorController>(reader);
var m_CullingMode = reader.ReadInt32(); var m_CullingMode = reader.ReadInt32();
if (version >= (4, 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{ {
var m_UpdateMode = reader.ReadInt32(); var m_UpdateMode = reader.ReadInt32();
} }
var m_ApplyRootMotion = reader.ReadBoolean(); var m_ApplyRootMotion = reader.ReadBoolean();
if (version == 4 && version.Minor >= 5) //4.5 and up - 5.0 down if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
{ {
reader.AlignStream(); reader.AlignStream();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
var m_LinearVelocityBlending = reader.ReadBoolean(); var m_LinearVelocityBlending = reader.ReadBoolean();
if (version >= (2021, 2)) //2021.2 and up if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{ {
var m_StabilizeFeet = reader.ReadBoolean(); var m_StabilizeFeet = reader.ReadBoolean();
} }
reader.AlignStream(); reader.AlignStream();
} }
if (version < (4, 5)) //4.5 down if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
{ {
var m_AnimatePhysics = reader.ReadBoolean(); var m_AnimatePhysics = reader.ReadBoolean();
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_HasTransformHierarchy = reader.ReadBoolean(); m_HasTransformHierarchy = reader.ReadBoolean();
} }
if (version >= (4, 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{ {
var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean(); var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();
} }
if (version.IsInRange(5, 2018)) //5.0 and up - 2018 down if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down
{ {
reader.AlignStream(); reader.AlignStream();
} }
if (version >= 2018) //2018 and up if (version[0] >= 2018) //2018 and up
{ {
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean(); var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();

View File

@@ -17,7 +17,7 @@ namespace AssetStudio
word0 = reader.ReadUInt32(); word0 = reader.ReadUInt32();
word1 = reader.ReadUInt32(); word1 = reader.ReadUInt32();
if (version >= (5, 2)) //5.2 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{ {
word2 = reader.ReadUInt32(); word2 = reader.ReadUInt32();
} }
@@ -73,12 +73,12 @@ namespace AssetStudio
m_SkeletonMask = new SkeletonMask(reader); m_SkeletonMask = new SkeletonMask(reader);
m_Binding = reader.ReadUInt32(); m_Binding = reader.ReadUInt32();
m_LayerBlendingMode = reader.ReadInt32(); m_LayerBlendingMode = reader.ReadInt32();
if (version >= (4, 2)) //4.2 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
{ {
m_DefaultWeight = reader.ReadSingle(); m_DefaultWeight = reader.ReadSingle();
} }
m_IKPass = reader.ReadBoolean(); m_IKPass = reader.ReadBoolean();
if (version >= (4, 2)) //4.2 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
{ {
m_SyncedLayerAffectsTiming = reader.ReadBoolean(); m_SyncedLayerAffectsTiming = reader.ReadBoolean();
} }
@@ -131,7 +131,7 @@ namespace AssetStudio
} }
m_DestinationState = reader.ReadUInt32(); m_DestinationState = reader.ReadUInt32();
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_FullPathID = reader.ReadUInt32(); m_FullPathID = reader.ReadUInt32();
} }
@@ -140,7 +140,7 @@ namespace AssetStudio
m_UserID = reader.ReadUInt32(); m_UserID = reader.ReadUInt32();
m_TransitionDuration = reader.ReadSingle(); m_TransitionDuration = reader.ReadSingle();
m_TransitionOffset = reader.ReadSingle(); m_TransitionOffset = reader.ReadSingle();
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_ExitTime = reader.ReadSingle(); m_ExitTime = reader.ReadSingle();
m_HasExitTime = reader.ReadBoolean(); m_HasExitTime = reader.ReadBoolean();
@@ -154,7 +154,7 @@ namespace AssetStudio
m_Atomic = reader.ReadBoolean(); m_Atomic = reader.ReadBoolean();
} }
if (version >= (4, 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{ {
m_CanTransitionToSelf = reader.ReadBoolean(); m_CanTransitionToSelf = reader.ReadBoolean();
} }
@@ -252,41 +252,43 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_BlendType = reader.ReadUInt32(); m_BlendType = reader.ReadUInt32();
} }
m_BlendEventID = reader.ReadUInt32(); m_BlendEventID = reader.ReadUInt32();
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_BlendEventYID = reader.ReadUInt32(); m_BlendEventYID = reader.ReadUInt32();
} }
m_ChildIndices = reader.ReadUInt32Array(); m_ChildIndices = reader.ReadUInt32Array();
if (version < (4, 1)) //4.1 down if (version[0] < 4 || (version[0] == 4 && version[1] < 1)) //4.1 down
{ {
m_ChildThresholdArray = reader.ReadSingleArray(); m_ChildThresholdArray = reader.ReadSingleArray();
} }
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_Blend1dData = new Blend1dDataConstant(reader); m_Blend1dData = new Blend1dDataConstant(reader);
m_Blend2dData = new Blend2dDataConstant(reader); m_Blend2dData = new Blend2dDataConstant(reader);
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_BlendDirectData = new BlendDirectDataConstant(reader); m_BlendDirectData = new BlendDirectDataConstant(reader);
} }
m_ClipID = reader.ReadUInt32(); m_ClipID = reader.ReadUInt32();
if (version == 4 && version.Minor >= 5) //4.5 - 5.0 if (version[0] == 4 && version[1] >= 5) //4.5 - 5.0
{ {
m_ClipIndex = reader.ReadUInt32(); m_ClipIndex = reader.ReadUInt32();
} }
m_Duration = reader.ReadSingle(); m_Duration = reader.ReadSingle();
if (version >= (4, 1, 3)) //4.1.3 and up if (version[0] > 4
|| (version[0] == 4 && version[1] > 1)
|| (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up
{ {
m_CycleOffset = reader.ReadSingle(); m_CycleOffset = reader.ReadSingle();
m_Mirror = reader.ReadBoolean(); m_Mirror = reader.ReadBoolean();
@@ -311,7 +313,7 @@ namespace AssetStudio
m_NodeArray[i] = new BlendTreeNodeConstant(reader); m_NodeArray[i] = new BlendTreeNodeConstant(reader);
} }
if (version < (4, 5)) //4.5 down if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
{ {
m_BlendEventArrayConstant = new ValueArrayConstant(reader); m_BlendEventArrayConstant = new ValueArrayConstant(reader);
} }
@@ -352,7 +354,7 @@ namespace AssetStudio
m_BlendTreeConstantIndexArray = reader.ReadInt32Array(); m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
if (version < (5, 2)) //5.2 down if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
{ {
int numInfos = reader.ReadInt32(); int numInfos = reader.ReadInt32();
m_LeafInfoArray = new LeafInfoConstant[numInfos]; m_LeafInfoArray = new LeafInfoConstant[numInfos];
@@ -370,41 +372,41 @@ namespace AssetStudio
} }
m_NameID = reader.ReadUInt32(); m_NameID = reader.ReadUInt32();
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_PathID = reader.ReadUInt32(); m_PathID = reader.ReadUInt32();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_FullPathID = reader.ReadUInt32(); m_FullPathID = reader.ReadUInt32();
} }
m_TagID = reader.ReadUInt32(); m_TagID = reader.ReadUInt32();
if (version >= (5, 1)) //5.1 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
{ {
m_SpeedParamID = reader.ReadUInt32(); m_SpeedParamID = reader.ReadUInt32();
m_MirrorParamID = reader.ReadUInt32(); m_MirrorParamID = reader.ReadUInt32();
m_CycleOffsetParamID = reader.ReadUInt32(); m_CycleOffsetParamID = reader.ReadUInt32();
} }
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
var m_TimeParamID = reader.ReadUInt32(); var m_TimeParamID = reader.ReadUInt32();
} }
m_Speed = reader.ReadSingle(); m_Speed = reader.ReadSingle();
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_CycleOffset = reader.ReadSingle(); m_CycleOffset = reader.ReadSingle();
} }
m_IKOnFeet = reader.ReadBoolean(); m_IKOnFeet = reader.ReadBoolean();
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_WriteDefaultValues = reader.ReadBoolean(); m_WriteDefaultValues = reader.ReadBoolean();
} }
m_Loop = reader.ReadBoolean(); m_Loop = reader.ReadBoolean();
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_Mirror = reader.ReadBoolean(); m_Mirror = reader.ReadBoolean();
} }
@@ -478,7 +480,7 @@ namespace AssetStudio
m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader); m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader);
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
int numSelectors = reader.ReadInt32(); int numSelectors = reader.ReadInt32();
m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors]; m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors];
@@ -507,7 +509,7 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version < (5, 5)) //5.5 down if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
{ {
m_BoolValues = reader.ReadBooleanArray(); m_BoolValues = reader.ReadBooleanArray();
reader.AlignStream(); reader.AlignStream();
@@ -515,7 +517,7 @@ namespace AssetStudio
m_FloatValues = reader.ReadSingleArray(); m_FloatValues = reader.ReadSingleArray();
} }
if (version < (4, 3)) //4.3 down if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
{ {
m_VectorValues = reader.ReadVector4Array(); m_VectorValues = reader.ReadVector4Array();
} }
@@ -525,7 +527,7 @@ namespace AssetStudio
m_PositionValues = new Vector3[numPosValues]; m_PositionValues = new Vector3[numPosValues];
for (int i = 0; i < numPosValues; i++) for (int i = 0; i < numPosValues; i++)
{ {
m_PositionValues[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
} }
m_QuaternionValues = reader.ReadVector4Array(); m_QuaternionValues = reader.ReadVector4Array();
@@ -534,10 +536,10 @@ namespace AssetStudio
m_ScaleValues = new Vector3[numScaleValues]; m_ScaleValues = new Vector3[numScaleValues];
for (int i = 0; i < numScaleValues; i++) for (int i = 0; i < numScaleValues; i++)
{ {
m_ScaleValues[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
} }
if (version >= (5, 5)) //5.5 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{ {
m_FloatValues = reader.ReadSingleArray(); m_FloatValues = reader.ReadSingleArray();
m_IntValues = reader.ReadInt32Array(); m_IntValues = reader.ReadInt32Array();

View File

@@ -42,22 +42,12 @@ namespace AssetStudio
var m_MainAsset = new AssetInfo(reader); var m_MainAsset = new AssetInfo(reader);
if (version == (5, 4)) //5.4.x if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
{
var m_ClassVersionMapSize = reader.ReadInt32();
for (var i = 0; i < m_ClassVersionMapSize; i++)
{
var first = reader.ReadInt32();
var second = reader.ReadInt32();
}
}
if (version >= (4, 2)) //4.2 and up
{ {
var m_RuntimeCompatibility = reader.ReadUInt32(); var m_RuntimeCompatibility = reader.ReadUInt32();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
m_AssetBundleName = reader.ReadAlignedString(); m_AssetBundleName = reader.ReadAlignedString();

View File

@@ -33,7 +33,7 @@ namespace AssetStudio
public AudioClip(ObjectReader reader) : base(reader) public AudioClip(ObjectReader reader) : base(reader)
{ {
if (version < 5) if (version[0] < 5)
{ {
m_Format = reader.ReadInt32(); m_Format = reader.ReadInt32();
m_Type = (FMODSoundType)reader.ReadInt32(); m_Type = (FMODSoundType)reader.ReadInt32();
@@ -41,7 +41,7 @@ namespace AssetStudio
m_UseHardware = reader.ReadBoolean(); m_UseHardware = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
if (version >= (3, 2)) //3.2.0 to 5 if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5
{ {
int m_Stream = reader.ReadInt32(); int m_Stream = reader.ReadInt32();
m_Size = reader.ReadInt32(); m_Size = reader.ReadInt32();
@@ -95,7 +95,7 @@ namespace AssetStudio
public enum FMODSoundType public enum FMODSoundType
{ {
UNKNOWN = 0, UNKNOWN = 0,
AAC = 1, ACC = 1,
AIFF = 2, AIFF = 2,
ASF = 3, ASF = 3,
AT3 = 4, AT3 = 4,

View File

@@ -23,7 +23,7 @@ namespace AssetStudio
public Limit(ObjectReader reader) public Limit(ObjectReader reader)
{ {
var version = reader.version; var version = reader.version;
if (version >= (5, 4))//5.4 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up
{ {
m_Min = reader.ReadVector3(); m_Min = reader.ReadVector3();
m_Max = reader.ReadVector3(); m_Max = reader.ReadVector3();
@@ -50,7 +50,7 @@ namespace AssetStudio
var version = reader.version; var version = reader.version;
m_PreQ = reader.ReadVector4(); m_PreQ = reader.ReadVector4();
m_PostQ = reader.ReadVector4(); m_PostQ = reader.ReadVector4();
if (version >= (5, 4)) //5.4 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
{ {
m_Sgn = reader.ReadVector3(); m_Sgn = reader.ReadVector3();
} }
@@ -189,7 +189,7 @@ namespace AssetStudio
m_LeftHand = new Hand(reader); m_LeftHand = new Hand(reader);
m_RightHand = new Hand(reader); m_RightHand = new Hand(reader);
if (version < (2018, 2)) //2018.2 down if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{ {
int numHandles = reader.ReadInt32(); int numHandles = reader.ReadInt32();
m_Handles = new Handle[numHandles]; m_Handles = new Handle[numHandles];
@@ -210,7 +210,7 @@ namespace AssetStudio
m_HumanBoneMass = reader.ReadSingleArray(); m_HumanBoneMass = reader.ReadSingleArray();
if (version < (2018, 2)) //2018.2 down if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{ {
m_ColliderIndex = reader.ReadInt32Array(); m_ColliderIndex = reader.ReadInt32Array();
} }
@@ -225,7 +225,7 @@ namespace AssetStudio
m_FeetSpacing = reader.ReadSingle(); m_FeetSpacing = reader.ReadSingle();
m_HasLeftHand = reader.ReadBoolean(); m_HasLeftHand = reader.ReadBoolean();
m_HasRightHand = reader.ReadBoolean(); m_HasRightHand = reader.ReadBoolean();
if (version >= (5, 2)) //5.2 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{ {
m_HasTDoF = reader.ReadBoolean(); m_HasTDoF = reader.ReadBoolean();
} }
@@ -254,7 +254,7 @@ namespace AssetStudio
m_AvatarSkeleton = new Skeleton(reader); m_AvatarSkeleton = new Skeleton(reader);
m_AvatarSkeletonPose = new SkeletonPose(reader); m_AvatarSkeletonPose = new SkeletonPose(reader);
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_DefaultPose = new SkeletonPose(reader); m_DefaultPose = new SkeletonPose(reader);
@@ -265,7 +265,7 @@ namespace AssetStudio
m_HumanSkeletonIndexArray = reader.ReadInt32Array(); m_HumanSkeletonIndexArray = reader.ReadInt32Array();
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array(); m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
} }
@@ -273,7 +273,7 @@ namespace AssetStudio
m_RootMotionBoneIndex = reader.ReadInt32(); m_RootMotionBoneIndex = reader.ReadInt32();
m_RootMotionBoneX = new xform(reader); m_RootMotionBoneX = new xform(reader);
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_RootMotionSkeleton = new Skeleton(reader); m_RootMotionSkeleton = new Skeleton(reader);
m_RootMotionSkeletonPose = new SkeletonPose(reader); m_RootMotionSkeletonPose = new SkeletonPose(reader);

View File

@@ -7,8 +7,6 @@ namespace AssetStudio
{ {
public abstract class EditorExtension : Object public abstract class EditorExtension : Object
{ {
protected EditorExtension() { }
protected EditorExtension(ObjectReader reader) : base(reader) protected EditorExtension(ObjectReader reader) : base(reader)
{ {
if (platform == BuildTarget.NoTarget) if (platform == BuildTarget.NoTarget)

View File

@@ -11,7 +11,7 @@ namespace AssetStudio
public Font(ObjectReader reader) : base(reader) public Font(ObjectReader reader) : base(reader)
{ {
if (version >= (5, 5))//5.5 and up if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
{ {
var m_LineSpacing = reader.ReadSingle(); var m_LineSpacing = reader.ReadSingle();
var m_DefaultMaterial = new PPtr<Material>(reader); var m_DefaultMaterial = new PPtr<Material>(reader);
@@ -43,7 +43,7 @@ namespace AssetStudio
{ {
int m_AsciiStartOffset = reader.ReadInt32(); int m_AsciiStartOffset = reader.ReadInt32();
if (version <= 3) if (version[0] <= 3)
{ {
int m_FontCountX = reader.ReadInt32(); int m_FontCountX = reader.ReadInt32();
int m_FontCountY = reader.ReadInt32(); int m_FontCountY = reader.ReadInt32();
@@ -52,7 +52,7 @@ namespace AssetStudio
float m_Kerning = reader.ReadSingle(); float m_Kerning = reader.ReadSingle();
float m_LineSpacing = reader.ReadSingle(); float m_LineSpacing = reader.ReadSingle();
if (version <= 3) if (version[0] <= 3)
{ {
int m_PerCharacterKerning_size = reader.ReadInt32(); int m_PerCharacterKerning_size = reader.ReadInt32();
for (int i = 0; i < m_PerCharacterKerning_size; i++) for (int i = 0; i < m_PerCharacterKerning_size; i++)
@@ -86,7 +86,7 @@ namespace AssetStudio
float vertheight = reader.ReadSingle(); float vertheight = reader.ReadSingle();
float width = reader.ReadSingle(); float width = reader.ReadSingle();
if (version >= 4) if (version[0] >= 4)
{ {
var flipped = reader.ReadBoolean(); var flipped = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
@@ -103,7 +103,7 @@ namespace AssetStudio
float second = reader.ReadSingle(); float second = reader.ReadSingle();
} }
if (version <= 3) if (version[0] <= 3)
{ {
var m_GridFont = reader.ReadBoolean(); var m_GridFont = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();

View File

@@ -1,31 +0,0 @@
namespace AssetStudio
{
public class GLTextureSettings
{
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
public GLTextureSettings() { }
public GLTextureSettings(ObjectReader reader)
{
var version = reader.version;
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version >= 2017)//2017.x and up
{
m_WrapMode = reader.ReadInt32(); //m_WrapU
int m_WrapV = reader.ReadInt32();
int m_WrapW = reader.ReadInt32();
}
else
{
m_WrapMode = reader.ReadInt32();
}
}
}
}

View File

@@ -23,7 +23,7 @@ namespace AssetStudio
m_Components = new PPtr<Component>[m_Component_size]; m_Components = new PPtr<Component>[m_Component_size];
for (int i = 0; i < m_Component_size; i++) for (int i = 0; i < m_Component_size; i++)
{ {
if (version < (5, 5)) //5.5 down if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down
{ {
int first = reader.ReadInt32(); int first = reader.ReadInt32();
} }

View File

@@ -1,711 +0,0 @@
namespace AssetStudio
{
public enum GraphicsFormat
{
/// <summary>
/// The format is not specified.
/// </summary>
None,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component stored with sRGB nonlinear encoding.
/// </summary>
R8_SRGB,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit B component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
R8G8B8_SRGB,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit B component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SRGB,
/// <summary>
/// A one-component, 8-bit unsigned normalized format that has a single 8-bit R component.
/// </summary>
R8_UNorm,
/// <summary>
/// A two-component, 16-bit unsigned normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_UNorm,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UNorm,
/// <summary>
/// A one-component, 8-bit signed normalized format that has a single 8-bit R component.
/// </summary>
R8_SNorm,
/// <summary>
/// A two-component, 16-bit signed normalized format that has an 8-bit R component stored with sRGB nonlinear encoding in byte 0, and an 8-bit G component stored with sRGB nonlinear encoding in byte 1.
/// </summary>
R8G8_SNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SNorm,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has a single 8-bit R component.
/// </summary>
R8_UInt,
/// <summary>
/// A two-component, 16-bit unsigned integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_UInt,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_UInt,
/// <summary>
/// A one-component, 8-bit signed integer format that has a single 8-bit R component.
/// </summary>
R8_SInt,
/// <summary>
/// A two-component, 16-bit signed integer format that has an 8-bit R component in byte 0, and an 8-bit G component in byte 1.
/// </summary>
R8G8_SInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, and an 8-bit B component in byte 2.
/// </summary>
R8G8B8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit R component in byte 0, an 8-bit G component in byte 1, an 8-bit B component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
R8G8B8A8_SInt,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit R component.
/// </summary>
R16_UNorm,
/// <summary>
/// A two-component, 32-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UNorm,
/// <summary>
/// A three-component, 48-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UNorm,
/// <summary>
/// A four-component, 64-bit unsigned normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UNorm,
/// <summary>
/// A one-component, 16-bit signed normalized format that has a single 16-bit R component.
/// </summary>
R16_SNorm,
/// <summary>
/// A two-component, 32-bit signed normalized format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SNorm,
/// <summary>
/// A three-component, 48-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SNorm,
/// <summary>
/// A four-component, 64-bit signed normalized format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SNorm,
/// <summary>
/// A one-component, 16-bit unsigned integer format that has a single 16-bit R component.
/// </summary>
R16_UInt,
/// <summary>
/// A two-component, 32-bit unsigned integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_UInt,
/// <summary>
/// A three-component, 48-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_UInt,
/// <summary>
/// A four-component, 64-bit unsigned integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_UInt,
/// <summary>
/// A one-component, 16-bit signed integer format that has a single 16-bit R component.
/// </summary>
R16_SInt,
/// <summary>
/// A two-component, 32-bit signed integer format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SInt,
/// <summary>
/// A three-component, 48-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SInt,
/// <summary>
/// A four-component, 64-bit signed integer format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SInt,
/// <summary>
/// A one-component, 32-bit unsigned integer format that has a single 32-bit R component.
/// </summary>
R32_UInt,
/// <summary>
/// A two-component, 64-bit unsigned integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_UInt,
/// <summary>
/// A three-component, 96-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_UInt,
/// <summary>
/// A four-component, 128-bit unsigned integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_UInt,
/// <summary>
/// A one-component, 32-bit signed integer format that has a single 32-bit R component.
/// </summary>
R32_SInt,
/// <summary>
/// A two-component, 64-bit signed integer format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SInt,
/// <summary>
/// A three-component, 96-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SInt,
/// <summary>
/// A four-component, 128-bit signed integer format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SInt,
/// <summary>
/// A one-component, 16-bit signed floating-point format that has a single 16-bit R component.
/// </summary>
R16_SFloat,
/// <summary>
/// A two-component, 32-bit signed floating-point format that has a 16-bit R component in bytes 0..1, and a 16-bit G component in bytes 2..3.
/// </summary>
R16G16_SFloat,
/// <summary>
/// A three-component, 48-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, and a 16-bit B component in bytes 4..5.
/// </summary>
R16G16B16_SFloat,
/// <summary>
/// A four-component, 64-bit signed floating-point format that has a 16-bit R component in bytes 0..1, a 16-bit G component in bytes 2..3, a 16-bit B component in bytes 4..5, and a 16-bit A component in bytes 6..7.
/// </summary>
R16G16B16A16_SFloat,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has a single 32-bit R component.
/// </summary>
R32_SFloat,
/// <summary>
/// A two-component, 64-bit signed floating-point format that has a 32-bit R component in bytes 0..3, and a 32-bit G component in bytes 4..7.
/// </summary>
R32G32_SFloat,
/// <summary>
/// A three-component, 96-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, and a 32-bit B component in bytes 8..11.
/// </summary>
R32G32B32_SFloat,
/// <summary>
/// A four-component, 128-bit signed floating-point format that has a 32-bit R component in bytes 0..3, a 32-bit G component in bytes 4..7, a 32-bit B component in bytes 8..11, and a 32-bit A component in bytes 12..15.
/// </summary>
R32G32B32A32_SFloat,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, and an 8-bit R component stored with sRGB nonlinear encoding in byte 2.
/// </summary>
B8G8R8_SRGB = 56,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component stored with sRGB nonlinear encoding in byte 0, an 8-bit G component stored with sRGB nonlinear encoding in byte 1, an 8-bit R component stored with sRGB nonlinear encoding in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SRGB,
/// <summary>
/// A three-component, 24-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_UNorm,
/// <summary>
/// A four-component, 32-bit unsigned normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UNorm,
/// <summary>
/// A three-component, 24-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SNorm,
/// <summary>
/// A four-component, 32-bit signed normalized format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SNorm,
/// <summary>
/// A three-component, 24-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2
/// </summary>
B8G8R8_UInt,
/// <summary>
/// A four-component, 32-bit unsigned integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_UInt,
/// <summary>
/// A three-component, 24-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, and an 8-bit R component in byte 2.
/// </summary>
B8G8R8_SInt,
/// <summary>
/// A four-component, 32-bit signed integer format that has an 8-bit B component in byte 0, an 8-bit G component in byte 1, an 8-bit R component in byte 2, and an 8-bit A component in byte 3.
/// </summary>
B8G8R8A8_SInt,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit R component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit B component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
R4G4B4A4_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 4-bit B component in bits 12..15, a 4-bit G component in bits 8..11, a 4-bit R component in bits 4..7, and a 4-bit A component in bits 0..3.
/// </summary>
B4G4R4A4_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit B component in bits 0..4.
/// </summary>
R5G6B5_UNormPack16,
/// <summary>
/// A three-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 6-bit G component in bits 5..10, and a 5-bit R component in bits 0..4.
/// </summary>
B5G6R5_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit R component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit B component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
R5G5B5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 5-bit B component in bits 11..15, a 5-bit G component in bits 6..10, a 5-bit R component in bits 1..5, and a 1-bit A component in bit 0.
/// </summary>
B5G5R5A1_UNormPack16,
/// <summary>
/// A four-component, 16-bit packed unsigned normalized format that has a 1-bit A component in bit 15, a 5-bit R component in bits 10..14, a 5-bit G component in bits 5..9, and a 5-bit B component in bits 0..4.
/// </summary>
A1R5G5B5_UNormPack16,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 5-bit shared exponent in bits 27..31, a 9-bit B component mantissa in bits 18..26, a 9-bit G component mantissa in bits 9..17, and a 9-bit R component mantissa in bits 0..8.
/// </summary>
E5B9G9R9_UFloatPack32,
/// <summary>
/// A three-component, 32-bit packed unsigned floating-point format that has a 10-bit B component in bits 22..31, an 11-bit G component in bits 11..21, an 11-bit R component in bits 0..10.
/// </summary>
B10G11R11_UFloatPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit B component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit R component in bits 0..9.
/// </summary>
A2B10G10R10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_UIntPack32,
/// <summary>
/// A four-component, 32-bit packed signed integer format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9.
/// </summary>
A2R10G10B10_SIntPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 2-bit A component in bits 30..31, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A2R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 32-bit packed unsigned normalized format that has a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion).
/// </summary>
R10G10B10_XRUNormPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are gamma encoded and their values range from -0.5271 to 1.66894. The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRSRGBPack32,
/// <summary>
/// A four-component, 64-bit packed unsigned normalized format that has a 10-bit A component in bits 30..39, a 10-bit R component in bits 20..29, a 10-bit G component in bits 10..19, and a 10-bit B component in bits 0..9. The components are linearly encoded and their values range from -0.752941 to 1.25098 (pre-expansion). The alpha component is clamped to either 0.0 or 1.0 on sampling, rendering, and writing operations.
/// </summary>
A10R10G10B10_XRUNormPack32,
/// <summary>
/// A one-component, 16-bit unsigned normalized format that has a single 16-bit depth component.
/// </summary>
D16_UNorm = 90,
/// <summary>
/// A two-component, 32-bit format that has 24 unsigned normalized bits in the depth component and, optionally: 8 bits that are unused.
/// </summary>
D24_UNorm,
/// <summary>
/// A two-component, 32-bit packed format that has 8 unsigned integer bits in the stencil component, and 24 unsigned normalized bits in the depth component.
/// </summary>
D24_UNorm_S8_UInt,
/// <summary>
/// A one-component, 32-bit signed floating-point format that has 32-bits in the depth component.
/// </summary>
D32_SFloat,
/// <summary>
/// A two-component format that has 32 signed float bits in the depth component and 8 unsigned integer bits in the stencil component. There are optionally: 24-bits that are unused.
/// </summary>
D32_SFloat_S8_UInt,
/// <summary>
/// A one-component, 8-bit unsigned integer format that has 8-bits in the stencil component.
/// </summary>
S8_UInt,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_SRGB,
/// <summary>
/// A three-component, block-compressed format (also known as BC1). Each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has a 1 bit alpha channel.
/// </summary>
RGBA_DXT1_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT3_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC2) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT3_UNorm,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding.
/// </summary>
RGBA_DXT5_SRGB,
/// <summary>
/// A four-component, block-compressed format (also known as BC3) where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_DXT5_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_BC4_UNorm,
/// <summary>
/// A one-component, block-compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_BC4_SNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_UNorm,
/// <summary>
/// A two-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_BC5_SNorm,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned floating-point RGB texel data.
/// </summary>
RGB_BC6H_UFloat,
/// <summary>
/// A three-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed floating-point RGB texel data.
/// </summary>
RGB_BC6H_SFloat,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_BC7_SRGB,
/// <summary>
/// A four-component, block-compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_BC7_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_2Bpp_UNorm,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_SRGB,
/// <summary>
/// A three-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_PVRTC_4Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_2Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 8×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_2Bpp_UNorm,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_PVRTC_4Bpp_SRGB,
/// <summary>
/// A four-component, PVRTC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 32 bits encoding alpha values followed by 32 bits encoding RGB values.
/// </summary>
RGBA_PVRTC_4Bpp_UNorm,
/// <summary>
/// A three-component, ETC compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC_UNorm,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_SRGB,
/// <summary>
/// A three-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data. This format has no alpha and is considered opaque.
/// </summary>
RGB_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data with sRGB nonlinear encoding, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGB texel data, and provides 1 bit of alpha.
/// </summary>
RGB_A1_ETC2_UNorm,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values with sRGB nonlinear encoding applied.
/// </summary>
RGBA_ETC2_SRGB,
/// <summary>
/// A four-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with the first 64 bits encoding alpha values followed by 64 bits encoding RGB values.
/// </summary>
RGBA_ETC2_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized red texel data.
/// </summary>
R_EAC_UNorm,
/// <summary>
/// A one-component, ETC2 compressed format where each 64-bit compressed texel block encodes a 4×4 rectangle of signed normalized red texel data.
/// </summary>
R_EAC_SNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_UNorm,
/// <summary>
/// A two-component, ETC2 compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of signed normalized RG texel data with the first 64 bits encoding red values followed by 64 bits encoding green values.
/// </summary>
RG_EAC_SNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC4X4_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC5X5_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC6X6_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC8X8_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC10X10_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UNorm,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data with sRGB nonlinear encoding applied to the RGB components.
/// </summary>
RGBA_ASTC12X12_SRGB,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of unsigned normalized RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UNorm,
/// <summary>
/// YUV 4:2:2 Video resource format.
/// </summary>
YUV2,
/// <summary>
/// GraphicsFormat.YUV2.
/// </summary>
VideoAuto = 144,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 4×4 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC4X4_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 5×5 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC5X5_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 6×6 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC6X6_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes an 8×8 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC8X8_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 10×10 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC10X10_UFloat,
/// <summary>
/// A four-component, ASTC compressed format where each 128-bit compressed texel block encodes a 12×12 rectangle of float RGBA texel data.
/// </summary>
RGBA_ASTC12X12_UFloat,
/// <summary>
/// A two-component, 24-bit format that has 16 unsigned normalized bits in the depth component and 8 unsigned integer bits in the stencil component. Most platforms do not support this format.
/// </summary>
D16_UNorm_S8_UInt,
}
public static class GraphicsFormatExtension
{
public static TextureFormat ToTextureFormat(this GraphicsFormat graphicsFormat)
{
switch (graphicsFormat)
{
case GraphicsFormat.R8_SRGB:
case GraphicsFormat.R8_UInt:
case GraphicsFormat.R8_UNorm:
return TextureFormat.R8;
case GraphicsFormat.R8G8_SRGB:
case GraphicsFormat.R8G8_UInt:
case GraphicsFormat.R8G8_UNorm:
return TextureFormat.RG16;
case GraphicsFormat.R8G8B8_SRGB:
case GraphicsFormat.R8G8B8_UInt:
case GraphicsFormat.R8G8B8_UNorm:
return TextureFormat.RGB24;
case GraphicsFormat.R8G8B8A8_SRGB:
case GraphicsFormat.R8G8B8A8_UInt:
case GraphicsFormat.R8G8B8A8_UNorm:
return TextureFormat.RGBA32;
case GraphicsFormat.R16_UInt:
case GraphicsFormat.R16_UNorm:
return TextureFormat.R16;
case GraphicsFormat.R16G16_UInt:
case GraphicsFormat.R16G16_UNorm:
return TextureFormat.RG32;
case GraphicsFormat.R16G16B16_UInt:
case GraphicsFormat.R16G16B16_UNorm:
return TextureFormat.RGB48;
case GraphicsFormat.R16G16B16A16_UInt:
case GraphicsFormat.R16G16B16A16_UNorm:
return TextureFormat.RGBA64;
case GraphicsFormat.R16_SFloat:
return TextureFormat.RHalf;
case GraphicsFormat.R16G16_SFloat:
return TextureFormat.RGHalf;
case GraphicsFormat.R16G16B16_SFloat: //?
case GraphicsFormat.R16G16B16A16_SFloat:
return TextureFormat.RGBAHalf;
case GraphicsFormat.R32_SFloat:
return TextureFormat.RFloat;
case GraphicsFormat.R32G32_SFloat:
return TextureFormat.RGFloat;
case GraphicsFormat.R32G32B32_SFloat: //?
case GraphicsFormat.R32G32B32A32_SFloat:
return TextureFormat.RGBAFloat;
case GraphicsFormat.B8G8R8A8_SRGB:
case GraphicsFormat.B8G8R8A8_UInt:
case GraphicsFormat.B8G8R8A8_UNorm:
return TextureFormat.BGRA32;
case GraphicsFormat.E5B9G9R9_UFloatPack32:
return TextureFormat.RGB9e5Float;
case GraphicsFormat.RGBA_DXT1_SRGB:
case GraphicsFormat.RGBA_DXT1_UNorm:
return TextureFormat.DXT1;
case GraphicsFormat.RGBA_DXT3_SRGB:
case GraphicsFormat.RGBA_DXT3_UNorm:
return TextureFormat.DXT3;
case GraphicsFormat.RGBA_DXT5_SRGB:
case GraphicsFormat.RGBA_DXT5_UNorm:
return TextureFormat.DXT5;
case GraphicsFormat.R_BC4_UNorm:
return TextureFormat.BC4;
case GraphicsFormat.RG_BC5_UNorm:
return TextureFormat.BC5;
case GraphicsFormat.RGB_BC6H_SFloat:
case GraphicsFormat.RGB_BC6H_UFloat:
return TextureFormat.BC6H;
case GraphicsFormat.RGBA_BC7_SRGB:
case GraphicsFormat.RGBA_BC7_UNorm:
return TextureFormat.BC7;
case GraphicsFormat.RGB_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_2Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_2Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_2Bpp_UNorm:
return TextureFormat.PVRTC_RGBA2;
case GraphicsFormat.RGB_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGB_PVRTC_4Bpp_UNorm:
case GraphicsFormat.RGBA_PVRTC_4Bpp_SRGB:
case GraphicsFormat.RGBA_PVRTC_4Bpp_UNorm:
return TextureFormat.PVRTC_RGBA4;
case GraphicsFormat.RGB_ETC_UNorm:
return TextureFormat.ETC_RGB4;
case GraphicsFormat.RGB_ETC2_SRGB:
case GraphicsFormat.RGB_ETC2_UNorm:
return TextureFormat.ETC2_RGB;
case GraphicsFormat.RGB_A1_ETC2_SRGB:
case GraphicsFormat.RGB_A1_ETC2_UNorm:
return TextureFormat.ETC2_RGBA1;
case GraphicsFormat.RGBA_ETC2_SRGB:
case GraphicsFormat.RGBA_ETC2_UNorm:
return TextureFormat.ETC2_RGBA8;
case GraphicsFormat.R_EAC_UNorm:
return TextureFormat.EAC_R;
case GraphicsFormat.R_EAC_SNorm:
return TextureFormat.EAC_R_SIGNED;
case GraphicsFormat.RG_EAC_UNorm:
return TextureFormat.EAC_RG;
case GraphicsFormat.RG_EAC_SNorm:
return TextureFormat.EAC_RG_SIGNED;
case GraphicsFormat.RGBA_ASTC4X4_SRGB:
case GraphicsFormat.RGBA_ASTC4X4_UNorm:
return TextureFormat.ASTC_RGBA_4x4;
case GraphicsFormat.RGBA_ASTC5X5_SRGB:
case GraphicsFormat.RGBA_ASTC5X5_UNorm:
return TextureFormat.ASTC_RGBA_5x5;
case GraphicsFormat.RGBA_ASTC6X6_SRGB:
case GraphicsFormat.RGBA_ASTC6X6_UNorm:
return TextureFormat.ASTC_RGBA_6x6;
case GraphicsFormat.RGBA_ASTC8X8_SRGB:
case GraphicsFormat.RGBA_ASTC8X8_UNorm:
return TextureFormat.ASTC_RGBA_8x8;
case GraphicsFormat.RGBA_ASTC10X10_SRGB:
case GraphicsFormat.RGBA_ASTC10X10_UNorm:
return TextureFormat.ASTC_RGBA_10x10;
case GraphicsFormat.RGBA_ASTC12X12_SRGB:
case GraphicsFormat.RGBA_ASTC12X12_UNorm:
return TextureFormat.ASTC_RGBA_12x12;
case GraphicsFormat.YUV2:
case GraphicsFormat.VideoAuto:
return TextureFormat.YUY2;
default:
return 0;
}
}
}
}

View File

@@ -34,7 +34,7 @@ namespace AssetStudio
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader)); m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
} }
if (version >= 2021) //2021.1 and up if (version[0] >= 2021) //2021.1 and up
{ {
int m_IntsSize = reader.ReadInt32(); int m_IntsSize = reader.ReadInt32();
m_Ints = new KeyValuePair<string, int>[m_IntsSize]; m_Ints = new KeyValuePair<string, int>[m_IntsSize];
@@ -69,39 +69,39 @@ namespace AssetStudio
{ {
m_Shader = new PPtr<Shader>(reader); m_Shader = new PPtr<Shader>(reader);
if (version == 4 && version.Minor >= 1) //4.x if (version[0] == 4 && version[1] >= 1) //4.x
{ {
var m_ShaderKeywords = reader.ReadStringArray(); var m_ShaderKeywords = reader.ReadStringArray();
} }
if (version >= (2021, 3)) //2021.3 and up if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up
{ {
var m_ValidKeywords = reader.ReadStringArray(); var m_ValidKeywords = reader.ReadStringArray();
var m_InvalidKeywords = reader.ReadStringArray(); var m_InvalidKeywords = reader.ReadStringArray();
} }
else if (version >= 5) //5.0 ~ 2021.2 else if (version[0] >= 5) //5.0 ~ 2021.2
{ {
var m_ShaderKeywords = reader.ReadAlignedString(); var m_ShaderKeywords = reader.ReadAlignedString();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
var m_LightmapFlags = reader.ReadUInt32(); var m_LightmapFlags = reader.ReadUInt32();
} }
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
var m_EnableInstancingVariants = reader.ReadBoolean(); var m_EnableInstancingVariants = reader.ReadBoolean();
//var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up //var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up
reader.AlignStream(); reader.AlignStream();
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
var m_CustomRenderQueue = reader.ReadInt32(); var m_CustomRenderQueue = reader.ReadInt32();
} }
if (version >= (5, 1)) //5.1 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
{ {
var stringTagMapSize = reader.ReadInt32(); var stringTagMapSize = reader.ReadInt32();
for (int i = 0; i < stringTagMapSize; i++) for (int i = 0; i < stringTagMapSize; i++)
@@ -111,7 +111,7 @@ namespace AssetStudio
} }
} }
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
var disabledShaderPasses = reader.ReadStringArray(); var disabledShaderPasses = reader.ReadStringArray();
} }

View File

@@ -40,7 +40,7 @@ namespace AssetStudio
m_Vertices = new PackedFloatVector(reader); m_Vertices = new PackedFloatVector(reader);
m_UV = new PackedFloatVector(reader); m_UV = new PackedFloatVector(reader);
if (version < 5) if (version[0] < 5)
{ {
m_BindPoses = new PackedFloatVector(reader); m_BindPoses = new PackedFloatVector(reader);
} }
@@ -49,15 +49,15 @@ namespace AssetStudio
m_Weights = new PackedIntVector(reader); m_Weights = new PackedIntVector(reader);
m_NormalSigns = new PackedIntVector(reader); m_NormalSigns = new PackedIntVector(reader);
m_TangentSigns = new PackedIntVector(reader); m_TangentSigns = new PackedIntVector(reader);
if (version >= 5) if (version[0] >= 5)
{ {
m_FloatColors = new PackedFloatVector(reader); m_FloatColors = new PackedFloatVector(reader);
} }
m_BoneIndices = new PackedIntVector(reader); m_BoneIndices = new PackedIntVector(reader);
m_Triangles = new PackedIntVector(reader); m_Triangles = new PackedIntVector(reader);
if (version >= (3, 5)) //3.5 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
{ {
if (version < 5) if (version[0] < 5)
{ {
m_Colors = new PackedIntVector(reader); m_Colors = new PackedIntVector(reader);
} }
@@ -87,7 +87,7 @@ namespace AssetStudio
channelMask = reader.ReadUInt32(); channelMask = reader.ReadUInt32();
offset = reader.ReadUInt32(); offset = reader.ReadUInt32();
if (version < 4) //4.0 down if (version[0] < 4) //4.0 down
{ {
stride = reader.ReadUInt32(); stride = reader.ReadUInt32();
align = reader.ReadUInt32(); align = reader.ReadUInt32();
@@ -131,14 +131,14 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version < 2018)//2018 down if (version[0] < 2018)//2018 down
{ {
m_CurrentChannels = reader.ReadUInt32(); m_CurrentChannels = reader.ReadUInt32();
} }
m_VertexCount = reader.ReadUInt32(); m_VertexCount = reader.ReadUInt32();
if (version >= 4) //4.0 and up if (version[0] >= 4) //4.0 and up
{ {
var m_ChannelsSize = reader.ReadInt32(); var m_ChannelsSize = reader.ReadInt32();
m_Channels = new ChannelInfo[m_ChannelsSize]; m_Channels = new ChannelInfo[m_ChannelsSize];
@@ -148,9 +148,9 @@ namespace AssetStudio
} }
} }
if (version < 5) //5.0 down if (version[0] < 5) //5.0 down
{ {
if (version < 4) if (version[0] < 4)
{ {
m_Streams = new StreamInfo[4]; m_Streams = new StreamInfo[4];
} }
@@ -164,7 +164,7 @@ namespace AssetStudio
m_Streams[i] = new StreamInfo(reader); m_Streams[i] = new StreamInfo(reader);
} }
if (version < 4) //4.0 down if (version[0] < 4) //4.0 down
{ {
GetChannels(version); GetChannels(version);
} }
@@ -178,7 +178,7 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
} }
private void GetStreams(UnityVersion version) private void GetStreams(int[] version)
{ {
var streamCount = m_Channels.Max(x => x.stream) + 1; var streamCount = m_Channels.Max(x => x.stream) + 1;
m_Streams = new StreamInfo[streamCount]; m_Streams = new StreamInfo[streamCount];
@@ -213,7 +213,7 @@ namespace AssetStudio
} }
} }
private void GetChannels(UnityVersion version) private void GetChannels(int[] version)
{ {
m_Channels = new ChannelInfo[6]; m_Channels = new ChannelInfo[6];
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
@@ -305,20 +305,20 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version < (4, 3)) //4.3 down if (version[0] == 4 && version[1] < 3) //4.3 down
{ {
var name = reader.ReadAlignedString(); var name = reader.ReadAlignedString();
} }
firstVertex = reader.ReadUInt32(); firstVertex = reader.ReadUInt32();
vertexCount = reader.ReadUInt32(); vertexCount = reader.ReadUInt32();
if (version < (4, 3)) //4.3 down if (version[0] == 4 && version[1] < 3) //4.3 down
{ {
var aabbMinDelta = reader.ReadVector3(); var aabbMinDelta = reader.ReadVector3();
var aabbMaxDelta = reader.ReadVector3(); var aabbMaxDelta = reader.ReadVector3();
} }
hasNormals = reader.ReadBoolean(); hasNormals = reader.ReadBoolean();
hasTangents = reader.ReadBoolean(); hasTangents = reader.ReadBoolean();
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
reader.AlignStream(); reader.AlignStream();
} }
@@ -352,7 +352,7 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
int numVerts = reader.ReadInt32(); int numVerts = reader.ReadInt32();
vertices = new BlendShapeVertex[numVerts]; vertices = new BlendShapeVertex[numVerts];
@@ -425,17 +425,17 @@ namespace AssetStudio
indexCount = reader.ReadUInt32(); indexCount = reader.ReadUInt32();
topology = (GfxPrimitiveType)reader.ReadInt32(); topology = (GfxPrimitiveType)reader.ReadInt32();
if (version < 4) //4.0 down if (version[0] < 4) //4.0 down
{ {
triangleCount = reader.ReadUInt32(); triangleCount = reader.ReadUInt32();
} }
if (version >= (2017, 3)) //2017.3 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{ {
baseVertex = reader.ReadUInt32(); baseVertex = reader.ReadUInt32();
} }
if (version >= 3) //3.0 and up if (version[0] >= 3) //3.0 and up
{ {
firstVertex = reader.ReadUInt32(); firstVertex = reader.ReadUInt32();
vertexCount = reader.ReadUInt32(); vertexCount = reader.ReadUInt32();
@@ -474,12 +474,12 @@ namespace AssetStudio
public Mesh(ObjectReader reader) : base(reader) public Mesh(ObjectReader reader) : base(reader)
{ {
if (version < (3, 5)) //3.5 down if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.5 down
{ {
m_Use16BitIndices = reader.ReadInt32() > 0; m_Use16BitIndices = reader.ReadInt32() > 0;
} }
if (version <= (2, 5)) //2.5 and down if (version[0] == 2 && version[1] <= 5) //2.5 and down
{ {
int m_IndexBuffer_size = reader.ReadInt32(); int m_IndexBuffer_size = reader.ReadInt32();
@@ -505,21 +505,21 @@ namespace AssetStudio
m_SubMeshes[i] = new SubMesh(reader); m_SubMeshes[i] = new SubMesh(reader);
} }
if (version >= (4, 1)) //4.1 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
{ {
m_Shapes = new BlendShapeData(reader); m_Shapes = new BlendShapeData(reader);
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_BindPose = reader.ReadMatrixArray(); m_BindPose = reader.ReadMatrixArray();
m_BoneNameHashes = reader.ReadUInt32Array(); m_BoneNameHashes = reader.ReadUInt32Array();
var m_RootBoneNameHash = reader.ReadUInt32(); var m_RootBoneNameHash = reader.ReadUInt32();
} }
if (version >= (2, 6)) //2.6.0 and up if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
{ {
if (version >= 2019) //2019 and up if (version[0] >= 2019) //2019 and up
{ {
var m_BonesAABBSize = reader.ReadInt32(); var m_BonesAABBSize = reader.ReadInt32();
var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize]; var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize];
@@ -532,9 +532,9 @@ namespace AssetStudio
} }
var m_MeshCompression = reader.ReadByte(); var m_MeshCompression = reader.ReadByte();
if (version >= 4) if (version[0] >= 4)
{ {
if (version < 5) if (version[0] < 5)
{ {
var m_StreamCompression = reader.ReadByte(); var m_StreamCompression = reader.ReadByte();
} }
@@ -545,9 +545,9 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
//Unity fixed it in 2017.3.1p1 and later versions //Unity fixed it in 2017.3.1p1 and later versions
if (version >= (2017, 4) //2017.4 if ((version[0] > 2017 || (version[0] == 2017 && version[1] >= 4)) || //2017.4
|| version == (2017, 3, 1) && buildType.IsPatch //fixed after 2017.3.1px ((version[0] == 2017 && version[1] == 3 && version[2] == 1) && buildType.IsPatch) || //fixed after 2017.3.1px
|| version == (2017, 3) && m_MeshCompression == 0)//2017.3.xfx with no compression ((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
{ {
var m_IndexFormat = reader.ReadInt32(); var m_IndexFormat = reader.ReadInt32();
m_Use16BitIndices = m_IndexFormat == 0; m_Use16BitIndices = m_IndexFormat == 0;
@@ -569,7 +569,7 @@ namespace AssetStudio
} }
} }
if (version < (3, 5)) //3.4.2 and earlier if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.4.2 and earlier
{ {
m_VertexCount = reader.ReadInt32(); m_VertexCount = reader.ReadInt32();
m_Vertices = reader.ReadSingleArray(m_VertexCount * 3); //Vector3 m_Vertices = reader.ReadSingleArray(m_VertexCount * 3); //Vector3
@@ -586,7 +586,7 @@ namespace AssetStudio
m_UV1 = reader.ReadSingleArray(reader.ReadInt32() * 2); //Vector2 m_UV1 = reader.ReadSingleArray(reader.ReadInt32() * 2); //Vector2
if (version <= (2, 5)) //2.5 and down if (version[0] == 2 && version[1] <= 5) //2.5 and down
{ {
int m_TangentSpace_size = reader.ReadInt32(); int m_TangentSpace_size = reader.ReadInt32();
m_Normals = new float[m_TangentSpace_size * 3]; m_Normals = new float[m_TangentSpace_size * 3];
@@ -611,7 +611,7 @@ namespace AssetStudio
} }
else else
{ {
if (version < (2018, 2)) //2018.2 down if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{ {
m_Skin = new BoneWeights4[reader.ReadInt32()]; m_Skin = new BoneWeights4[reader.ReadInt32()];
for (int s = 0; s < m_Skin.Length; s++) for (int s = 0; s < m_Skin.Length; s++)
@@ -620,7 +620,7 @@ namespace AssetStudio
} }
} }
if (version <= (4, 2)) //4.2 and down if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) //4.2 and down
{ {
m_BindPose = reader.ReadMatrixArray(); m_BindPose = reader.ReadMatrixArray();
} }
@@ -628,14 +628,14 @@ namespace AssetStudio
m_VertexData = new VertexData(reader); m_VertexData = new VertexData(reader);
} }
if (version >= (2, 6)) //2.6.0 and later if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later
{ {
m_CompressedMesh = new CompressedMesh(reader); m_CompressedMesh = new CompressedMesh(reader);
} }
reader.Position += 24; //AABB m_LocalAABB reader.Position += 24; //AABB m_LocalAABB
if (version <= (3, 4)) //3.4.2 and earlier if (version[0] < 3 || (version[0] == 3 && version[1] <= 4)) //3.4.2 and earlier
{ {
int m_Colors_size = reader.ReadInt32(); int m_Colors_size = reader.ReadInt32();
m_Colors = new float[m_Colors_size * 4]; m_Colors = new float[m_Colors_size * 4];
@@ -651,12 +651,12 @@ namespace AssetStudio
int m_MeshUsageFlags = reader.ReadInt32(); int m_MeshUsageFlags = reader.ReadInt32();
if (version >= (2022, 1)) //2022.1 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{ {
int m_CookingOptions = reader.ReadInt32(); int m_CookingOptions = reader.ReadInt32();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array(); var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
@@ -664,14 +664,14 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
} }
if (version >= (2018, 2)) //2018.2 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
{ {
var m_MeshMetrics = new float[2]; var m_MeshMetrics = new float[2];
m_MeshMetrics[0] = reader.ReadSingle(); m_MeshMetrics[0] = reader.ReadSingle();
m_MeshMetrics[1] = reader.ReadSingle(); m_MeshMetrics[1] = reader.ReadSingle();
} }
if (version >= (2018, 3)) //2018.3 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
{ {
reader.AlignStream(); reader.AlignStream();
m_StreamData = new StreamingInfo(reader); m_StreamData = new StreamingInfo(reader);
@@ -690,12 +690,12 @@ namespace AssetStudio
m_VertexData.m_DataSize = resourceReader.GetData(); m_VertexData.m_DataSize = resourceReader.GetData();
} }
} }
if (version >= (3, 5)) //3.5 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
{ {
ReadVertexData(); ReadVertexData();
} }
if (version >= (2, 6)) //2.6.0 and later if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later
{ {
DecompressCompressedMesh(); DecompressCompressedMesh();
} }
@@ -716,7 +716,7 @@ namespace AssetStudio
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask }); var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
if (channelMask.Get(chn)) if (channelMask.Get(chn))
{ {
if (version < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
{ {
m_Channel.dimension = 4; m_Channel.dimension = 4;
} }
@@ -752,7 +752,7 @@ namespace AssetStudio
else else
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat); componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
if (version >= 2018) if (version[0] >= 2018)
{ {
switch (chn) switch (chn)
{ {
@@ -841,7 +841,7 @@ namespace AssetStudio
m_UV1 = componentsFloatArray; m_UV1 = componentsFloatArray;
break; break;
case 5: case 5:
if (version >= 5) //kShaderChannelTexCoord2 if (version[0] >= 5) //kShaderChannelTexCoord2
{ {
m_UV2 = componentsFloatArray; m_UV2 = componentsFloatArray;
} }
@@ -906,7 +906,7 @@ namespace AssetStudio
} }
} }
//BindPose //BindPose
if (version < 5) if (version[0] < 5)
{ {
if (m_CompressedMesh.m_BindPoses.m_NumItems > 0) if (m_CompressedMesh.m_BindPoses.m_NumItems > 0)
{ {
@@ -983,7 +983,7 @@ namespace AssetStudio
} }
} }
//FloatColor //FloatColor
if (version >= 5) if (version[0] >= 5)
{ {
if (m_CompressedMesh.m_FloatColors.m_NumItems > 0) if (m_CompressedMesh.m_FloatColors.m_NumItems > 0)
{ {
@@ -1074,7 +1074,7 @@ namespace AssetStudio
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]); m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
} }
} }
else if (version < 4 || topology == GfxPrimitiveType.TriangleStrip) else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
{ {
// de-stripify : // de-stripify :
uint triIndex = 0; uint triIndex = 0;
@@ -1238,9 +1238,9 @@ namespace AssetStudio
SInt32 SInt32
} }
public static VertexFormat ToVertexFormat(int format, UnityVersion version) public static VertexFormat ToVertexFormat(int format, int[] version)
{ {
if (version < 2017) if (version[0] < 2017)
{ {
switch ((VertexChannelFormat)format) switch ((VertexChannelFormat)format)
{ {
@@ -1258,7 +1258,7 @@ namespace AssetStudio
throw new ArgumentOutOfRangeException(nameof(format), format, null); throw new ArgumentOutOfRangeException(nameof(format), format, null);
} }
} }
else if (version < 2019) else if (version[0] < 2019)
{ {
switch ((VertexFormat2017)format) switch ((VertexFormat2017)format)
{ {

View File

@@ -13,11 +13,11 @@ namespace AssetStudio
public MonoScript(ObjectReader reader) : base(reader) public MonoScript(ObjectReader reader) : base(reader)
{ {
if (version >= (3, 4)) //3.4 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
{ {
var m_ExecutionOrder = reader.ReadInt32(); var m_ExecutionOrder = reader.ReadInt32();
} }
if (version < 5) //5.0 down if (version[0] < 5) //5.0 down
{ {
var m_PropertiesHash = reader.ReadUInt32(); var m_PropertiesHash = reader.ReadUInt32();
} }
@@ -25,17 +25,17 @@ namespace AssetStudio
{ {
var m_PropertiesHash = reader.ReadBytes(16); var m_PropertiesHash = reader.ReadBytes(16);
} }
if (version < 3) //3.0 down if (version[0] < 3) //3.0 down
{ {
var m_PathName = reader.ReadAlignedString(); var m_PathName = reader.ReadAlignedString();
} }
m_ClassName = reader.ReadAlignedString(); m_ClassName = reader.ReadAlignedString();
if (version >= 3) //3.0 and up if (version[0] >= 3) //3.0 and up
{ {
m_Namespace = reader.ReadAlignedString(); m_Namespace = reader.ReadAlignedString();
} }
m_AssemblyName = reader.ReadAlignedString(); m_AssemblyName = reader.ReadAlignedString();
if (version < (2018, 2)) //2018.2 down if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
{ {
var m_IsEditorScript = reader.ReadBoolean(); var m_IsEditorScript = reader.ReadBoolean();
} }

View File

@@ -9,8 +9,6 @@ namespace AssetStudio
{ {
public string m_Name; public string m_Name;
protected NamedObject() { }
protected NamedObject(ObjectReader reader) : base(reader) protected NamedObject(ObjectReader reader) : base(reader)
{ {
m_Name = reader.ReadAlignedString(); m_Name = reader.ReadAlignedString();

View File

@@ -1,27 +1,19 @@
using Newtonsoft.Json; using System.Collections.Specialized;
using System.Collections.Specialized;
namespace AssetStudio namespace AssetStudio
{ {
public class Object public class Object
{ {
[JsonIgnore]
public SerializedFile assetsFile; public SerializedFile assetsFile;
[JsonIgnore]
public ObjectReader reader; public ObjectReader reader;
public long m_PathID; public long m_PathID;
[JsonIgnore] public int[] version;
public UnityVersion version;
protected BuildType buildType; protected BuildType buildType;
[JsonIgnore]
public BuildTarget platform; public BuildTarget platform;
public ClassIDType type; public ClassIDType type;
[JsonIgnore]
public SerializedType serializedType; public SerializedType serializedType;
public uint byteSize; public uint byteSize;
public Object() { }
public Object(ObjectReader reader) public Object(ObjectReader reader)
{ {
this.reader = reader; this.reader = reader;
@@ -59,24 +51,6 @@ namespace AssetStudio
return null; return null;
} }
public string DumpObject()
{
string str = null;
try
{
str = JsonConvert.SerializeObject(this, new JsonSerializerSettings
{
Formatting = Formatting.Indented,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
}).Replace(" ", " ");
}
catch
{
//ignore
}
return str;
}
public OrderedDictionary ToType() public OrderedDictionary ToType()
{ {
if (serializedType?.m_Type != null) if (serializedType?.m_Type != null)

View File

@@ -7,47 +7,45 @@ namespace AssetStudio
public int m_FileID; public int m_FileID;
public long m_PathID; public long m_PathID;
private SerializedFile _assetsFile; private SerializedFile assetsFile;
private int _index = -2; //-2 - Prepare, -1 - Missing private int index = -2; //-2 - Prepare, -1 - Missing
public PPtr(ObjectReader reader) public PPtr(ObjectReader reader)
{ {
m_FileID = reader.ReadInt32(); m_FileID = reader.ReadInt32();
m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64(); m_PathID = reader.m_Version < SerializedFileFormatVersion.Unknown_14 ? reader.ReadInt32() : reader.ReadInt64();
_assetsFile = reader.assetsFile; assetsFile = reader.assetsFile;
} }
public PPtr() { }
private bool TryGetAssetsFile(out SerializedFile result) private bool TryGetAssetsFile(out SerializedFile result)
{ {
result = null; result = null;
if (m_FileID == 0) if (m_FileID == 0)
{ {
result = _assetsFile; result = assetsFile;
return true; return true;
} }
if (m_FileID > 0 && m_FileID - 1 < _assetsFile.m_Externals.Count) if (m_FileID > 0 && m_FileID - 1 < assetsFile.m_Externals.Count)
{ {
var assetsManager = _assetsFile.assetsManager; var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList; var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache; var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (_index == -2) if (index == -2)
{ {
var m_External = _assetsFile.m_Externals[m_FileID - 1]; var m_External = assetsFile.m_Externals[m_FileID - 1];
var name = m_External.fileName; var name = m_External.fileName;
if (!assetsFileIndexCache.TryGetValue(name, out _index)) if (!assetsFileIndexCache.TryGetValue(name, out index))
{ {
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase)); index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, _index); assetsFileIndexCache.Add(name, index);
} }
} }
if (_index >= 0) if (index >= 0)
{ {
result = assetsFileList[_index]; result = assetsFileList[index];
return true; return true;
} }
} }
@@ -55,9 +53,8 @@ namespace AssetStudio
return false; return false;
} }
public bool TryGet(out T result, SerializedFile assetsFile = null) public bool TryGet(out T result)
{ {
_assetsFile = _assetsFile ?? assetsFile;
if (TryGetAssetsFile(out var sourceFile)) if (TryGetAssetsFile(out var sourceFile))
{ {
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj)) if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
@@ -74,9 +71,8 @@ namespace AssetStudio
return false; return false;
} }
public bool TryGet<T2>(out T2 result, SerializedFile assetsFile = null) where T2 : Object public bool TryGet<T2>(out T2 result) where T2 : Object
{ {
_assetsFile = _assetsFile ?? assetsFile;
if (TryGetAssetsFile(out var sourceFile)) if (TryGetAssetsFile(out var sourceFile))
{ {
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj)) if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
@@ -96,20 +92,20 @@ namespace AssetStudio
public void Set(T m_Object) public void Set(T m_Object)
{ {
var name = m_Object.assetsFile.fileName; var name = m_Object.assetsFile.fileName;
if (string.Equals(_assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase)) if (string.Equals(assetsFile.fileName, name, StringComparison.OrdinalIgnoreCase))
{ {
m_FileID = 0; m_FileID = 0;
} }
else else
{ {
m_FileID = _assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase)); m_FileID = assetsFile.m_Externals.FindIndex(x => string.Equals(x.fileName, name, StringComparison.OrdinalIgnoreCase));
if (m_FileID == -1) if (m_FileID == -1)
{ {
_assetsFile.m_Externals.Add(new FileIdentifier assetsFile.m_Externals.Add(new FileIdentifier
{ {
fileName = m_Object.assetsFile.fileName fileName = m_Object.assetsFile.fileName
}); });
m_FileID = _assetsFile.m_Externals.Count; m_FileID = assetsFile.m_Externals.Count;
} }
else else
{ {
@@ -117,14 +113,14 @@ namespace AssetStudio
} }
} }
var assetsManager = _assetsFile.assetsManager; var assetsManager = assetsFile.assetsManager;
var assetsFileList = assetsManager.assetsFileList; var assetsFileList = assetsManager.assetsFileList;
var assetsFileIndexCache = assetsManager.assetsFileIndexCache; var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
if (!assetsFileIndexCache.TryGetValue(name, out _index)) if (!assetsFileIndexCache.TryGetValue(name, out index))
{ {
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase)); index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
assetsFileIndexCache.Add(name, _index); assetsFileIndexCache.Add(name, index);
} }
m_PathID = m_Object.m_PathID; m_PathID = m_Object.m_PathID;

View File

@@ -12,7 +12,7 @@ namespace AssetStudio
public PlayerSettings(ObjectReader reader) : base(reader) public PlayerSettings(ObjectReader reader) : base(reader)
{ {
if (version >= (5, 4)) //5.4.0 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4.0 nad up
{ {
var productGUID = reader.ReadBytes(16); var productGUID = reader.ReadBytes(16);
} }
@@ -23,12 +23,12 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
int defaultScreenOrientation = reader.ReadInt32(); int defaultScreenOrientation = reader.ReadInt32();
int targetDevice = reader.ReadInt32(); int targetDevice = reader.ReadInt32();
if (version < (5, 3)) //5.3 down if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down
{ {
if (version < 5) //5.0 down if (version[0] < 5) //5.0 down
{ {
int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics
if (version >= (4, 6)) //4.6 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 6)) //4.6 and up
{ {
var targetIOSGraphics = reader.ReadInt32(); var targetIOSGraphics = reader.ReadInt32();
} }
@@ -40,7 +40,7 @@ namespace AssetStudio
var useOnDemandResources = reader.ReadBoolean(); var useOnDemandResources = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
} }
if (version >= (3, 5)) //3.5 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
{ {
var accelerometerFrequency = reader.ReadInt32(); var accelerometerFrequency = reader.ReadInt32();
} }

View File

@@ -25,7 +25,7 @@ namespace AssetStudio
protected Renderer(ObjectReader reader) : base(reader) protected Renderer(ObjectReader reader) : base(reader)
{ {
if (version < 5) //5.0 down if (version[0] < 5) //5.0 down
{ {
var m_Enabled = reader.ReadBoolean(); var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadBoolean(); var m_CastShadows = reader.ReadBoolean();
@@ -34,27 +34,27 @@ namespace AssetStudio
} }
else //5.0 and up else //5.0 and up
{ {
if (version >= (5, 4)) //5.4 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
{ {
var m_Enabled = reader.ReadBoolean(); var m_Enabled = reader.ReadBoolean();
var m_CastShadows = reader.ReadByte(); var m_CastShadows = reader.ReadByte();
var m_ReceiveShadows = reader.ReadByte(); var m_ReceiveShadows = reader.ReadByte();
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
var m_DynamicOccludee = reader.ReadByte(); var m_DynamicOccludee = reader.ReadByte();
} }
if (version >= 2021) //2021.1 and up if (version[0] >= 2021) //2021.1 and up
{ {
var m_StaticShadowCaster = reader.ReadByte(); var m_StaticShadowCaster = reader.ReadByte();
} }
var m_MotionVectors = reader.ReadByte(); var m_MotionVectors = reader.ReadByte();
var m_LightProbeUsage = reader.ReadByte(); var m_LightProbeUsage = reader.ReadByte();
var m_ReflectionProbeUsage = reader.ReadByte(); var m_ReflectionProbeUsage = reader.ReadByte();
if (version >= (2019, 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
var m_RayTracingMode = reader.ReadByte(); var m_RayTracingMode = reader.ReadByte();
} }
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
var m_RayTraceProcedural = reader.ReadByte(); var m_RayTraceProcedural = reader.ReadByte();
} }
@@ -69,12 +69,12 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
} }
if (version >= 2018) //2018 and up if (version[0] >= 2018) //2018 and up
{ {
var m_RenderingLayerMask = reader.ReadUInt32(); var m_RenderingLayerMask = reader.ReadUInt32();
} }
if (version >= (2018, 3)) //2018.3 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
{ {
var m_RendererPriority = reader.ReadInt32(); var m_RendererPriority = reader.ReadInt32();
} }
@@ -83,12 +83,12 @@ namespace AssetStudio
var m_LightmapIndexDynamic = reader.ReadUInt16(); var m_LightmapIndexDynamic = reader.ReadUInt16();
} }
if (version >= 3) //3.0 and up if (version[0] >= 3) //3.0 and up
{ {
var m_LightmapTilingOffset = reader.ReadVector4(); var m_LightmapTilingOffset = reader.ReadVector4();
} }
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
var m_LightmapTilingOffsetDynamic = reader.ReadVector4(); var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
} }
@@ -100,13 +100,13 @@ namespace AssetStudio
m_Materials[i] = new PPtr<Material>(reader); m_Materials[i] = new PPtr<Material>(reader);
} }
if (version < 3) //3.0 down if (version[0] < 3) //3.0 down
{ {
var m_LightmapTilingOffset = reader.ReadVector4(); var m_LightmapTilingOffset = reader.ReadVector4();
} }
else //3.0 and up else //3.0 and up
{ {
if (version >= (5, 5)) //5.5 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{ {
m_StaticBatchInfo = new StaticBatchInfo(reader); m_StaticBatchInfo = new StaticBatchInfo(reader);
} }
@@ -118,17 +118,17 @@ namespace AssetStudio
var m_StaticBatchRoot = new PPtr<Transform>(reader); var m_StaticBatchRoot = new PPtr<Transform>(reader);
} }
if (version >= (5, 4)) //5.4 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
{ {
var m_ProbeAnchor = new PPtr<Transform>(reader); var m_ProbeAnchor = new PPtr<Transform>(reader);
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader); var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
} }
else if (version >= (3, 5)) //3.5 - 5.3 else if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 - 5.3
{ {
var m_UseLightProbes = reader.ReadBoolean(); var m_UseLightProbes = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
if (version >= 5)//5.0 and up if (version[0] >= 5)//5.0 and up
{ {
var m_ReflectionProbeUsage = reader.ReadInt32(); var m_ReflectionProbeUsage = reader.ReadInt32();
} }
@@ -136,9 +136,9 @@ namespace AssetStudio
var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
if (version == (4, 3)) //4.3 if (version[0] == 4 && version[1] == 3) //4.3
{ {
var m_SortingLayer = reader.ReadInt16(); var m_SortingLayer = reader.ReadInt16();
} }

View File

@@ -243,14 +243,14 @@ namespace AssetStudio
} }
rtSeparateBlend = reader.ReadBoolean(); rtSeparateBlend = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
zClip = new SerializedShaderFloatValue(reader); zClip = new SerializedShaderFloatValue(reader);
} }
zTest = new SerializedShaderFloatValue(reader); zTest = new SerializedShaderFloatValue(reader);
zWrite = new SerializedShaderFloatValue(reader); zWrite = new SerializedShaderFloatValue(reader);
culling = new SerializedShaderFloatValue(reader); culling = new SerializedShaderFloatValue(reader);
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
conservative = new SerializedShaderFloatValue(reader); conservative = new SerializedShaderFloatValue(reader);
} }
@@ -359,7 +359,7 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32(); m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32(); m_Index = reader.ReadInt32();
m_SamplerIndex = reader.ReadInt32(); m_SamplerIndex = reader.ReadInt32();
if (version >= (2017, 3)) //2017.3 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{ {
var m_MultiSampled = reader.ReadBoolean(); var m_MultiSampled = reader.ReadBoolean();
} }
@@ -380,7 +380,7 @@ namespace AssetStudio
m_NameIndex = reader.ReadInt32(); m_NameIndex = reader.ReadInt32();
m_Index = reader.ReadInt32(); m_Index = reader.ReadInt32();
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
m_ArraySize = reader.ReadInt32(); m_ArraySize = reader.ReadInt32();
} }
@@ -415,7 +415,7 @@ namespace AssetStudio
{ {
m_VectorParams[i] = new VectorParameter(reader); m_VectorParams[i] = new VectorParameter(reader);
} }
if (version >= (2017, 3)) //2017.3 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{ {
int numStructParams = reader.ReadInt32(); int numStructParams = reader.ReadInt32();
m_StructParams = new StructParameter[numStructParams]; m_StructParams = new StructParameter[numStructParams];
@@ -426,8 +426,11 @@ namespace AssetStudio
} }
m_Size = reader.ReadInt32(); m_Size = reader.ReadInt32();
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up if ((version[0] == 2020 && version[1] > 3) ||
|| version >= (2021, 1, 4)) //2021.1.4f1 and up (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
{ {
m_IsPartialCB = reader.ReadBoolean(); m_IsPartialCB = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
@@ -581,7 +584,7 @@ namespace AssetStudio
m_BlobIndex = reader.ReadUInt32(); m_BlobIndex = reader.ReadUInt32();
m_Channels = new ParserBindChannels(reader); m_Channels = new ParserBindChannels(reader);
if (version.IsInRange(2019, (2021, 2))) //2019 ~2021.1 if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
{ {
var m_GlobalKeywordIndices = reader.ReadUInt16Array(); var m_GlobalKeywordIndices = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -591,7 +594,7 @@ namespace AssetStudio
else else
{ {
m_KeywordIndices = reader.ReadUInt16Array(); m_KeywordIndices = reader.ReadUInt16Array();
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
reader.AlignStream(); reader.AlignStream();
} }
@@ -601,8 +604,11 @@ namespace AssetStudio
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte(); m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
reader.AlignStream(); reader.AlignStream();
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up if ((version[0] == 2020 && version[1] > 3) ||
|| version >= (2021, 1, 1)) //2021.1.1f1 and up (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] >= 1)) //2021.1.1f1 and up
{ {
m_Parameters = new SerializedProgramParameters(reader); m_Parameters = new SerializedProgramParameters(reader);
} }
@@ -657,7 +663,7 @@ namespace AssetStudio
m_UAVParams[i] = new UAVParameter(reader); m_UAVParams[i] = new UAVParameter(reader);
} }
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
int numSamplers = reader.ReadInt32(); int numSamplers = reader.ReadInt32();
m_Samplers = new SamplerParameter[numSamplers]; m_Samplers = new SamplerParameter[numSamplers];
@@ -668,9 +674,9 @@ namespace AssetStudio
} }
} }
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
if (version >= 2021) //2021.1 and up if (version[0] >= 2021) //2021.1 and up
{ {
var m_ShaderRequirements = reader.ReadInt64(); var m_ShaderRequirements = reader.ReadInt64();
} }
@@ -699,13 +705,16 @@ namespace AssetStudio
m_SubPrograms[i] = new SerializedSubProgram(reader); m_SubPrograms[i] = new SerializedSubProgram(reader);
} }
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up if ((version[0] == 2020 && version[1] > 3) ||
|| version >= (2021, 1, 1)) //2021.1.1f1 and up (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] >= 1)) //2021.1.1f1 and up
{ {
m_CommonParameters = new SerializedProgramParameters(reader); m_CommonParameters = new SerializedProgramParameters(reader);
} }
if (version >= (2022, 1)) //2022.1 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
{ {
m_SerializedKeywordStateMask = reader.ReadUInt16Array(); m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -747,7 +756,7 @@ namespace AssetStudio
{ {
var version = reader.version; var version = reader.version;
if (version >= (2020, 2)) //2020.2 and up if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{ {
int numEditorDataHash = reader.ReadInt32(); int numEditorDataHash = reader.ReadInt32();
m_EditorDataHash = new Hash128[numEditorDataHash]; m_EditorDataHash = new Hash128[numEditorDataHash];
@@ -758,7 +767,7 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
m_Platforms = reader.ReadUInt8Array(); m_Platforms = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
if (version <= (2021, 1)) //2021.1 and down if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
{ {
m_LocalKeywordMask = reader.ReadUInt16Array(); m_LocalKeywordMask = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -782,12 +791,12 @@ namespace AssetStudio
progGeometry = new SerializedProgram(reader); progGeometry = new SerializedProgram(reader);
progHull = new SerializedProgram(reader); progHull = new SerializedProgram(reader);
progDomain = new SerializedProgram(reader); progDomain = new SerializedProgram(reader);
if (version >= (2019, 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
progRayTracing = new SerializedProgram(reader); progRayTracing = new SerializedProgram(reader);
} }
m_HasInstancingVariant = reader.ReadBoolean(); m_HasInstancingVariant = reader.ReadBoolean();
if (version >= 2018) //2018 and up if (version[0] >= 2018) //2018 and up
{ {
var m_HasProceduralInstancingVariant = reader.ReadBoolean(); var m_HasProceduralInstancingVariant = reader.ReadBoolean();
} }
@@ -796,7 +805,7 @@ namespace AssetStudio
m_Name = reader.ReadAlignedString(); m_Name = reader.ReadAlignedString();
m_TextureName = reader.ReadAlignedString(); m_TextureName = reader.ReadAlignedString();
m_Tags = new SerializedTagMap(reader); m_Tags = new SerializedTagMap(reader);
if (version == 2021 && version.Minor >= 2) //2021.2 ~2021.x if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
{ {
m_SerializedKeywordStateMask = reader.ReadUInt16Array(); m_SerializedKeywordStateMask = reader.ReadUInt16Array();
reader.AlignStream(); reader.AlignStream();
@@ -889,7 +898,7 @@ namespace AssetStudio
m_SubShaders[i] = new SerializedSubShader(reader); m_SubShaders[i] = new SerializedSubShader(reader);
} }
if (version >= (2021, 2)) //2021.2 and up if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
{ {
m_KeywordNames = reader.ReadStringArray(); m_KeywordNames = reader.ReadStringArray();
m_KeywordFlags = reader.ReadUInt8Array(); m_KeywordFlags = reader.ReadUInt8Array();
@@ -907,7 +916,7 @@ namespace AssetStudio
m_Dependencies[i] = new SerializedShaderDependency(reader); m_Dependencies[i] = new SerializedShaderDependency(reader);
} }
if (version >= 2021) //2021.1 and up if (version[0] >= 2021) //2021.1 and up
{ {
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32(); int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize]; m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];
@@ -968,11 +977,11 @@ namespace AssetStudio
public Shader(ObjectReader reader) : base(reader) public Shader(ObjectReader reader) : base(reader)
{ {
if (version >= (5, 5)) //5.5 and up if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
{ {
m_ParsedForm = new SerializedShader(reader); m_ParsedForm = new SerializedShader(reader);
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray(); platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
if (version >= (2019, 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
offsets = reader.ReadUInt32ArrayArray(); offsets = reader.ReadUInt32ArrayArray();
compressedLengths = reader.ReadUInt32ArrayArray(); compressedLengths = reader.ReadUInt32ArrayArray();
@@ -993,7 +1002,7 @@ namespace AssetStudio
new PPtr<Shader>(reader); new PPtr<Shader>(reader);
} }
if (version >= 2018) if (version[0] >= 2018)
{ {
var m_NonModifiableTexturesCount = reader.ReadInt32(); var m_NonModifiableTexturesCount = reader.ReadInt32();
for (int i = 0; i < m_NonModifiableTexturesCount; i++) for (int i = 0; i < m_NonModifiableTexturesCount; i++)
@@ -1011,7 +1020,7 @@ namespace AssetStudio
m_Script = reader.ReadUInt8Array(); m_Script = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
var m_PathName = reader.ReadAlignedString(); var m_PathName = reader.ReadAlignedString();
if (version == 5 && version.Minor >= 3) //5.3 - 5.4 if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
{ {
decompressedSize = reader.ReadUInt32(); decompressedSize = reader.ReadUInt32();
m_SubProgramBlob = reader.ReadUInt8Array(); m_SubProgramBlob = reader.ReadUInt8Array();

View File

@@ -18,7 +18,7 @@ namespace AssetStudio
var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below
reader.AlignStream(); reader.AlignStream();
if (version < (2, 6)) //2.6 down if (version[0] == 2 && version[1] < 6) //2.6 down
{ {
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader); var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
} }
@@ -31,7 +31,7 @@ namespace AssetStudio
m_Bones[b] = new PPtr<Transform>(reader); m_Bones[b] = new PPtr<Transform>(reader);
} }
if (version >= (4, 3)) //4.3 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
{ {
m_BlendShapeWeights = reader.ReadSingleArray(); m_BlendShapeWeights = reader.ReadSingleArray();
} }

View File

@@ -68,7 +68,7 @@ namespace AssetStudio
var version = reader.version; var version = reader.version;
pos = reader.ReadVector3(); pos = reader.ReadVector3();
if (version <= (4, 3)) //4.3 and down if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
{ {
uv = reader.ReadVector2(); uv = reader.ReadVector2();
} }
@@ -99,12 +99,12 @@ namespace AssetStudio
var version = reader.version; var version = reader.version;
texture = new PPtr<Texture2D>(reader); texture = new PPtr<Texture2D>(reader);
if (version >= (5, 2)) //5.2 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
{ {
alphaTexture = new PPtr<Texture2D>(reader); alphaTexture = new PPtr<Texture2D>(reader);
} }
if (version >= 2019) //2019 and up if (version[0] >= 2019) //2019 and up
{ {
var secondaryTexturesSize = reader.ReadInt32(); var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize]; secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
@@ -114,7 +114,7 @@ namespace AssetStudio
} }
} }
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
var m_SubMeshesSize = reader.ReadInt32(); var m_SubMeshesSize = reader.ReadInt32();
m_SubMeshes = new SubMesh[m_SubMeshesSize]; m_SubMeshes = new SubMesh[m_SubMeshesSize];
@@ -141,11 +141,11 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
} }
if (version >= 2018) //2018 and up if (version[0] >= 2018) //2018 and up
{ {
m_Bindpose = reader.ReadMatrixArray(); m_Bindpose = reader.ReadMatrixArray();
if (version < (2018, 2)) //2018.2 down if (version[0] == 2018 && version[1] < 2) //2018.2 down
{ {
var m_SourceSkinSize = reader.ReadInt32(); var m_SourceSkinSize = reader.ReadInt32();
for (int i = 0; i < m_SourceSkinSize; i++) for (int i = 0; i < m_SourceSkinSize; i++)
@@ -157,18 +157,18 @@ namespace AssetStudio
textureRect = new Rectf(reader); textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2(); textureRectOffset = reader.ReadVector2();
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
atlasRectOffset = reader.ReadVector2(); atlasRectOffset = reader.ReadVector2();
} }
settingsRaw = new SpriteSettings(reader); settingsRaw = new SpriteSettings(reader);
if (version >= (4, 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{ {
uvTransform = reader.ReadVector4(); uvTransform = reader.ReadVector4();
} }
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
downscaleMultiplier = reader.ReadSingle(); downscaleMultiplier = reader.ReadSingle();
} }
@@ -182,6 +182,13 @@ namespace AssetStudio
public float width; public float width;
public float height; 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) public Rectf(BinaryReader reader)
{ {
x = reader.ReadSingle(); x = reader.ReadSingle();
@@ -205,31 +212,34 @@ namespace AssetStudio
public PPtr<SpriteAtlas> m_SpriteAtlas; public PPtr<SpriteAtlas> m_SpriteAtlas;
public SpriteRenderData m_RD; public SpriteRenderData m_RD;
public Vector2[][] m_PhysicsShape; public Vector2[][] m_PhysicsShape;
public bool akSplitAlpha;
public Sprite(ObjectReader reader) : base(reader) public Sprite(ObjectReader reader) : base(reader)
{ {
m_Rect = new Rectf(reader); m_Rect = new Rectf(reader);
m_Offset = reader.ReadVector2(); m_Offset = reader.ReadVector2();
if (version >= (4, 5)) //4.5 and up if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
{ {
m_Border = reader.ReadVector4(); m_Border = reader.ReadVector4();
} }
m_PixelsToUnits = reader.ReadSingle(); m_PixelsToUnits = reader.ReadSingle();
if (version >= (5, 4, 2) if (version[0] > 5
|| version == (5, 4, 1) && buildType.IsPatch && version.Build >= 3) //5.4.1p3 and up || (version[0] == 5 && version[1] > 4)
|| (version[0] == 5 && version[1] == 4 && version[2] >= 2)
|| (version[0] == 5 && version[1] == 4 && version[2] == 1 && buildType.IsPatch && version[3] >= 3)) //5.4.1p3 and up
{ {
m_Pivot = reader.ReadVector2(); m_Pivot = reader.ReadVector2();
} }
m_Extrude = reader.ReadUInt32(); m_Extrude = reader.ReadUInt32();
if (version >= (5, 3)) //5.3 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
{ {
m_IsPolygon = reader.ReadBoolean(); m_IsPolygon = reader.ReadBoolean();
reader.AlignStream(); reader.AlignStream();
} }
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
var first = new Guid(reader.ReadBytes(16)); var first = new Guid(reader.ReadBytes(16));
var second = reader.ReadInt64(); var second = reader.ReadInt64();
@@ -242,7 +252,7 @@ namespace AssetStudio
m_RD = new SpriteRenderData(reader); m_RD = new SpriteRenderData(reader);
if (version >= 2017) //2017 and up if (version[0] >= 2017) //2017 and up
{ {
var m_PhysicsShapeSize = reader.ReadInt32(); var m_PhysicsShapeSize = reader.ReadInt32();
m_PhysicsShape = new Vector2[m_PhysicsShapeSize][]; m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];
@@ -252,6 +262,8 @@ namespace AssetStudio
} }
} }
akSplitAlpha = false;
//vector m_Bones 2018 and up //vector m_Bones 2018 and up
} }
} }

View File

@@ -22,14 +22,14 @@ namespace AssetStudio
alphaTexture = new PPtr<Texture2D>(reader); alphaTexture = new PPtr<Texture2D>(reader);
textureRect = new Rectf(reader); textureRect = new Rectf(reader);
textureRectOffset = reader.ReadVector2(); textureRectOffset = reader.ReadVector2();
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
atlasRectOffset = reader.ReadVector2(); atlasRectOffset = reader.ReadVector2();
} }
uvTransform = reader.ReadVector4(); uvTransform = reader.ReadVector4();
downscaleMultiplier = reader.ReadSingle(); downscaleMultiplier = reader.ReadSingle();
settingsRaw = new SpriteSettings(reader); settingsRaw = new SpriteSettings(reader);
if (version >= (2020, 2)) //2020.2 and up if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{ {
var secondaryTexturesSize = reader.ReadInt32(); var secondaryTexturesSize = reader.ReadInt32();
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize]; secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];

View File

@@ -1,27 +0,0 @@
namespace AssetStudio
{
public class StreamingInfo
{
public long offset; //ulong
public uint size;
public string path;
public StreamingInfo() { }
public StreamingInfo(ObjectReader reader)
{
var version = reader.version;
if (version >= 2020) //2020.1 and up
{
offset = reader.ReadInt64();
}
else
{
offset = reader.ReadUInt32();
}
size = reader.ReadUInt32();
path = reader.ReadAlignedString();
}
}
}

View File

@@ -1,20 +1,19 @@
namespace AssetStudio using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AssetStudio
{ {
public abstract class Texture : NamedObject public abstract class Texture : NamedObject
{ {
protected Texture() { }
protected Texture(ObjectReader reader) : base(reader) protected Texture(ObjectReader reader) : base(reader)
{ {
if (version >= (2017, 3)) //2017.3 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
{ {
if (version < (2023, 2)) //2023.2 down var m_ForcedFallbackFormat = reader.ReadInt32();
{ var m_DownscaleFallback = reader.ReadBoolean();
var m_ForcedFallbackFormat = reader.ReadInt32(); if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
var m_DownscaleFallback = reader.ReadBoolean();
}
if (version >= (2020, 2)) //2020.2 and up
{ {
var m_IsAlphaChannelOptional = reader.ReadBoolean(); var m_IsAlphaChannelOptional = reader.ReadBoolean();
} }

View File

@@ -1,89 +1,79 @@
using System; using System;
using System.Collections;
using Newtonsoft.Json;
namespace AssetStudio namespace AssetStudio
{ {
public class StreamingInfo
{
public long offset; //ulong
public uint size;
public string path;
public StreamingInfo(ObjectReader reader)
{
var version = reader.version;
if (version[0] >= 2020) //2020.1 and up
{
offset = reader.ReadInt64();
}
else
{
offset = reader.ReadUInt32();
}
size = reader.ReadUInt32();
path = reader.ReadAlignedString();
}
}
public class GLTextureSettings
{
public int m_FilterMode;
public int m_Aniso;
public float m_MipBias;
public int m_WrapMode;
public GLTextureSettings(ObjectReader reader)
{
var version = reader.version;
m_FilterMode = reader.ReadInt32();
m_Aniso = reader.ReadInt32();
m_MipBias = reader.ReadSingle();
if (version[0] >= 2017)//2017.x and up
{
m_WrapMode = reader.ReadInt32(); //m_WrapU
int m_WrapV = reader.ReadInt32();
int m_WrapW = reader.ReadInt32();
}
else
{
m_WrapMode = reader.ReadInt32();
}
}
}
public sealed class Texture2D : Texture public sealed class Texture2D : Texture
{ {
public int m_Width; public int m_Width;
public int m_Height; public int m_Height;
public int m_CompleteImageSize;
public TextureFormat m_TextureFormat; public TextureFormat m_TextureFormat;
public bool m_MipMap; public bool m_MipMap;
public int m_MipCount; public int m_MipCount;
public GLTextureSettings m_TextureSettings; public GLTextureSettings m_TextureSettings;
public int m_ImageCount;
public byte[] m_PlatformBlob;
public ResourceReader image_data; public ResourceReader image_data;
public StreamingInfo m_StreamData; public StreamingInfo m_StreamData;
public Texture2D() { }
public Texture2D(Texture2DArray m_Texture2DArray, int layer) // Texture2DArrayImage
{
reader = m_Texture2DArray.reader;
assetsFile = m_Texture2DArray.assetsFile;
version = m_Texture2DArray.version;
platform = m_Texture2DArray.platform;
m_Name = $"{m_Texture2DArray.m_Name}_{layer + 1}";
type = ClassIDType.Texture2DArrayImage;
m_PathID = m_Texture2DArray.m_PathID;
m_Width = m_Texture2DArray.m_Width;
m_Height = m_Texture2DArray.m_Height;
m_TextureFormat = m_Texture2DArray.m_Format.ToTextureFormat();
m_MipCount = m_Texture2DArray.m_MipCount;
m_TextureSettings = m_Texture2DArray.m_TextureSettings;
m_StreamData = m_Texture2DArray.m_StreamData;
m_PlatformBlob = Array.Empty<byte>();
m_MipMap = m_MipCount > 1;
m_ImageCount = 1;
//var imgActualDataSize = GetImageDataSize(m_TextureFormat);
//var mipmapSize = (int)(m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth - imgActualDataSize);
m_CompleteImageSize = (int)m_Texture2DArray.m_DataSize / m_Texture2DArray.m_Depth;
var offset = layer * m_CompleteImageSize + m_Texture2DArray.image_data.Offset;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, offset, m_CompleteImageSize)
: new ResourceReader(reader, offset, m_CompleteImageSize);
byteSize = (uint)(m_Width * m_Height) * 4;
}
public Texture2D(ObjectReader reader, IDictionary typeDict) : base(reader)
{
var parsedTex2d = JsonConvert.DeserializeObject<Texture2D>(JsonConvert.SerializeObject(typeDict));
m_Width = parsedTex2d.m_Width;
m_Height = parsedTex2d.m_Height;
m_CompleteImageSize = parsedTex2d.m_CompleteImageSize;
m_TextureFormat = parsedTex2d.m_TextureFormat;
m_MipMap = parsedTex2d.m_MipMap;
m_MipCount = parsedTex2d.m_MipCount;
m_ImageCount = parsedTex2d.m_ImageCount;
m_TextureSettings = parsedTex2d.m_TextureSettings;
m_StreamData = parsedTex2d.m_StreamData;
m_PlatformBlob = parsedTex2d.m_PlatformBlob ?? Array.Empty<byte>();
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2d.image_data.Offset, parsedTex2d.image_data.Size);
typeDict.Clear();
}
public Texture2D(ObjectReader reader) : base(reader) public Texture2D(ObjectReader reader) : base(reader)
{ {
m_Width = reader.ReadInt32(); m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32(); m_Height = reader.ReadInt32();
m_CompleteImageSize = reader.ReadInt32(); var m_CompleteImageSize = reader.ReadInt32();
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
var m_MipsStripped = reader.ReadInt32(); var m_MipsStripped = reader.ReadInt32();
} }
m_TextureFormat = (TextureFormat)reader.ReadInt32(); m_TextureFormat = (TextureFormat)reader.ReadInt32();
if (version < (5, 2)) //5.2 down if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
{ {
m_MipMap = reader.ReadBoolean(); m_MipMap = reader.ReadBoolean();
} }
@@ -91,132 +81,152 @@ namespace AssetStudio
{ {
m_MipCount = reader.ReadInt32(); m_MipCount = reader.ReadInt32();
} }
if (version >= (2, 6)) //2.6.0 and up if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
{ {
var m_IsReadable = reader.ReadBoolean(); var m_IsReadable = reader.ReadBoolean();
} }
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
var m_IsPreProcessed = reader.ReadBoolean(); var m_IsPreProcessed = reader.ReadBoolean();
} }
if (version >= (2019, 3)) //2019.3 and up if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
{ {
if (version >= (2022, 2)) //2022.2 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
{ {
var m_IgnoreMipmapLimit = reader.ReadBoolean(); var m_IgnoreMipmapLimit = reader.ReadBoolean();
reader.AlignStream();
} }
else else
{ {
var m_IgnoreMasterTextureLimit = reader.ReadBoolean(); var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
} }
} }
if (version.IsInRange(3, (5, 5))) //3.0.0 - 5.4 if (version[0] >= 3) //3.0.0 - 5.4
{ {
var m_ReadAllowed = reader.ReadBoolean(); if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))
{
var m_ReadAllowed = reader.ReadBoolean();
}
} }
if (version >= (2022, 2)) //2022.2 and up if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 2)) //2022.2 and up
{ {
var m_MipmapLimitGroupName = reader.ReadAlignedString(); var m_MipmapLimitGroupName = reader.ReadAlignedString();
reader.AlignStream();
} }
if (version >= (2018, 2)) //2018.2 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
{ {
var m_StreamingMipmaps = reader.ReadBoolean(); var m_StreamingMipmaps = reader.ReadBoolean();
} }
reader.AlignStream(); reader.AlignStream();
if (version >= (2018, 2)) //2018.2 and up if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
{ {
var m_StreamingMipmapsPriority = reader.ReadInt32(); var m_StreamingMipmapsPriority = reader.ReadInt32();
} }
m_ImageCount = reader.ReadInt32(); var m_ImageCount = reader.ReadInt32();
var m_TextureDimension = reader.ReadInt32(); var m_TextureDimension = reader.ReadInt32();
m_TextureSettings = new GLTextureSettings(reader); m_TextureSettings = new GLTextureSettings(reader);
if (version >= 3) //3.0 and up if (version[0] >= 3) //3.0 and up
{ {
var m_LightmapFormat = reader.ReadInt32(); var m_LightmapFormat = reader.ReadInt32();
} }
if (version >= (3, 5)) //3.5.0 and up if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5.0 and up
{ {
var m_ColorSpace = reader.ReadInt32(); var m_ColorSpace = reader.ReadInt32();
} }
if (version >= (2020, 2)) //2020.2 and up if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
{ {
m_PlatformBlob = reader.ReadUInt8Array(); var m_PlatformBlob = reader.ReadUInt8Array();
reader.AlignStream(); reader.AlignStream();
} }
else
{
m_PlatformBlob = Array.Empty<byte>();
}
var image_data_size = reader.ReadInt32(); var image_data_size = reader.ReadInt32();
if (image_data_size == 0 && version >= (5, 3))//5.3.0 and up if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
{ {
m_StreamData = new StreamingInfo(reader); m_StreamData = new StreamingInfo(reader);
} }
image_data = !string.IsNullOrEmpty(m_StreamData?.path) ResourceReader resourceReader;
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size) if (!string.IsNullOrEmpty(m_StreamData?.path))
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
// https://docs.unity3d.com/2023.3/Documentation/Manual/class-TextureImporterOverride.html
private int GetImageDataSize(TextureFormat textureFormat)
{
var imgDataSize = m_Width * m_Height;
switch (textureFormat)
{ {
case TextureFormat.ASTC_RGBA_5x5: resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
// https://registry.khronos.org/webgl/extensions/WEBGL_compressed_texture_astc/
imgDataSize = (int)(Math.Floor((m_Width + 4) / 5f) * Math.Floor((m_Height + 4) / 5f) * 16);
break;
case TextureFormat.ASTC_RGBA_6x6:
imgDataSize = (int)(Math.Floor((m_Width + 5) / 6f) * Math.Floor((m_Height + 5) / 6f) * 16);
break;
case TextureFormat.ASTC_RGBA_8x8:
imgDataSize = (int)(Math.Floor((m_Width + 7) / 8f) * Math.Floor((m_Height + 7) / 8f) * 16);
break;
case TextureFormat.ASTC_RGBA_10x10:
imgDataSize = (int)(Math.Floor((m_Width + 9) / 10f) * Math.Floor((m_Height + 9) / 10f) * 16);
break;
case TextureFormat.ASTC_RGBA_12x12:
imgDataSize = (int)(Math.Floor((m_Width + 11) / 12f) * Math.Floor((m_Height + 11) / 12f) * 16);
break;
case TextureFormat.DXT1:
case TextureFormat.EAC_R:
case TextureFormat.EAC_R_SIGNED:
case TextureFormat.ATC_RGB4:
case TextureFormat.ETC_RGB4:
case TextureFormat.ETC2_RGB:
case TextureFormat.ETC2_RGBA1:
case TextureFormat.PVRTC_RGBA4:
imgDataSize /= 2;
break;
case TextureFormat.PVRTC_RGBA2:
imgDataSize /= 4;
break;
case TextureFormat.R16:
case TextureFormat.RGB565:
imgDataSize *= 2;
break;
case TextureFormat.RGB24:
imgDataSize *= 3;
break;
case TextureFormat.RG32:
case TextureFormat.RGBA32:
case TextureFormat.ARGB32:
case TextureFormat.BGRA32:
case TextureFormat.RGB9e5Float:
imgDataSize *= 4;
break;
case TextureFormat.RGB48:
imgDataSize *= 6;
break;
case TextureFormat.RGBAHalf:
case TextureFormat.RGBA64:
imgDataSize *= 8;
break;
} }
return imgDataSize; else
{
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
}
image_data = resourceReader;
} }
} }
public enum TextureFormat
{
Alpha8 = 1,
ARGB4444,
RGB24,
RGBA32,
ARGB32,
ARGBFloat,
RGB565,
BGR24,
R16,
DXT1,
DXT3,
DXT5,
RGBA4444,
BGRA32,
RHalf,
RGHalf,
RGBAHalf,
RFloat,
RGFloat,
RGBAFloat,
YUY2,
RGB9e5Float,
RGBFloat,
BC6H,
BC7,
BC4,
BC5,
DXT1Crunched,
DXT5Crunched,
PVRTC_RGB2,
PVRTC_RGBA2,
PVRTC_RGB4,
PVRTC_RGBA4,
ETC_RGB4,
ATC_RGB4,
ATC_RGBA8,
EAC_R = 41,
EAC_R_SIGNED,
EAC_RG,
EAC_RG_SIGNED,
ETC2_RGB,
ETC2_RGBA1,
ETC2_RGBA8,
ASTC_RGB_4x4,
ASTC_RGB_5x5,
ASTC_RGB_6x6,
ASTC_RGB_8x8,
ASTC_RGB_10x10,
ASTC_RGB_12x12,
ASTC_RGBA_4x4,
ASTC_RGBA_5x5,
ASTC_RGBA_6x6,
ASTC_RGBA_8x8,
ASTC_RGBA_10x10,
ASTC_RGBA_12x12,
ETC_RGB4_3DS,
ETC_RGBA8_3DS,
RG16,
R8,
ETC_RGB4Crunched,
ETC2_RGBA8Crunched,
ASTC_HDR_4x4,
ASTC_HDR_5x5,
ASTC_HDR_6x6,
ASTC_HDR_8x8,
ASTC_HDR_10x10,
ASTC_HDR_12x12,
RG32,
RGB48,
RGBA64
}
} }

View File

@@ -1,73 +0,0 @@
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
namespace AssetStudio
{
public sealed class Texture2DArray : Texture
{
public int m_Width;
public int m_Height;
public int m_Depth;
public GraphicsFormat m_Format;
public int m_MipCount;
public uint m_DataSize;
public GLTextureSettings m_TextureSettings;
public int m_ColorSpace;
public ResourceReader image_data;
public StreamingInfo m_StreamData;
public List<Texture2D> TextureList;
public Texture2DArray() { }
public Texture2DArray(ObjectReader reader) : base(reader)
{
m_ColorSpace = reader.ReadInt32();
m_Format = (GraphicsFormat)reader.ReadInt32();
m_Width = reader.ReadInt32();
m_Height = reader.ReadInt32();
m_Depth = reader.ReadInt32();
m_MipCount = reader.ReadInt32();
m_DataSize = reader.ReadUInt32();
m_TextureSettings = new GLTextureSettings(reader);
if (version >= (2020, 2)) //2020.2 and up
{
var m_UsageMode = reader.ReadInt32();
}
var m_IsReadable = reader.ReadBoolean();
reader.AlignStream();
var image_data_size = reader.ReadInt32();
if (image_data_size == 0)
{
m_StreamData = new StreamingInfo(reader);
}
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, (int)m_StreamData.size)
: new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
TextureList = new List<Texture2D>();
}
public Texture2DArray(ObjectReader reader, IDictionary typeDict) : base(reader)
{
var parsedTex2dArray = JsonConvert.DeserializeObject<Texture2DArray>(JsonConvert.SerializeObject(typeDict));
m_Width = parsedTex2dArray.m_Width;
m_Height = parsedTex2dArray.m_Height;
m_Depth = parsedTex2dArray.m_Depth;
m_Format = parsedTex2dArray.m_Format;
m_MipCount = parsedTex2dArray.m_MipCount;
m_DataSize = parsedTex2dArray.m_DataSize;
m_TextureSettings = parsedTex2dArray.m_TextureSettings;
m_StreamData = parsedTex2dArray.m_StreamData;
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
: new ResourceReader(reader, parsedTex2dArray.image_data.Offset, parsedTex2dArray.image_data.Size);
typeDict.Clear();
TextureList = new List<Texture2D>();
}
}
}

View File

@@ -1,282 +0,0 @@
namespace AssetStudio
{
public enum TextureFormat
{
/// <summary>
/// Alpha-only texture format, 8 bit integer.
/// </summary>
Alpha8 = 1,
/// <summary>
/// A 16 bits/pixel texture format. Texture stores color with an alpha channel.
/// </summary>
ARGB4444,
/// <summary>
/// Three channel (RGB) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGB24,
/// <summary>
/// Four channel (RGBA) texture format, 8-bits unsigned integer per channel.
/// </summary>
RGBA32,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
ARGB32,
/// <summary>
/// </summary>
ARGBFloat,
/// <summary>
/// A 16 bit color texture format.
/// </summary>
RGB565,
/// <summary>
/// </summary>
BGR24,
/// <summary>
/// Single channel (R) texture format, 16 bit integer.
/// </summary>
R16,
/// <summary>
/// Compressed color texture format.
/// </summary>
DXT1,
/// <summary>
/// </summary>
DXT3,
/// <summary>
/// Compressed color with alpha channel texture format.
/// </summary>
DXT5,
/// <summary>
/// Color and alpha texture format, 4 bit per channel.
/// </summary>
RGBA4444,
/// <summary>
/// Color with alpha texture format, 8-bits per channel.
/// </summary>
BGRA32,
/// <summary>
/// Scalar (R) texture format, 16 bit floating point.
/// </summary>
RHalf,
/// <summary>
/// Two color (RG) texture format, 16 bit floating point per channel.
/// </summary>
RGHalf,
/// <summary>
/// RGB color and alpha texture format, 16 bit floating point per channel.
/// </summary>
RGBAHalf,
/// <summary>
/// Scalar (R) texture format, 32 bit floating point.
/// </summary>
RFloat,
/// <summary>
/// Two color (RG) texture format, 32 bit floating point per channel.
/// </summary>
RGFloat,
/// <summary>
/// RGB color and alpha texture format, 32-bit floats per channel.
/// </summary>
RGBAFloat,
/// <summary>
/// A format that uses the YUV color space and is often used for video encoding or playback.
/// </summary>
YUY2,
/// <summary>
/// RGB HDR format, with 9 bit mantissa per channel and a 5 bit shared exponent.
/// </summary>
RGB9e5Float,
/// <summary>
/// </summary>
RGBFloat,
/// <summary>
/// HDR compressed color texture format.
/// </summary>
BC6H,
/// <summary>
/// High quality compressed color texture format.
/// </summary>
BC7,
/// <summary>
/// Compressed one channel (R) texture format.
/// </summary>
BC4,
/// <summary>
/// Compressed two-channel (RG) texture format.
/// </summary>
BC5,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT1Crunched,
/// <summary>
/// Compressed color with alpha channel texture format with Crunch compression for smaller storage sizes.
/// </summary>
DXT5Crunched,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB2,
/// <summary>
/// PowerVR (iOS) 2 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA2,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed color texture format.
/// </summary>
PVRTC_RGB4,
/// <summary>
/// PowerVR (iOS) 4 bits/pixel compressed with alpha channel texture format.
/// </summary>
PVRTC_RGBA4,
/// <summary>
/// ETC (GLES2.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4,
/// <summary>
/// ATC (ATITC) 4 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGB4,
/// <summary>
/// ATC (ATITC) 8 bits/pixel compressed RGB texture format.
/// </summary>
ATC_RGBA8,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed unsigned single-channel texture format.
/// </summary>
EAC_R = 41,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 4 bits/pixel compressed signed single-channel texture format.
/// </summary>
EAC_R_SIGNED,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed unsigned dual-channel (RG) texture format.
/// </summary>
EAC_RG,
/// <summary>
/// ETC2 / EAC (GL ES 3.0) 8 bits/pixel compressed signed dual-channel (RG) texture format.
/// </summary>
EAC_RG_SIGNED,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC2_RGB,
/// <summary>
/// ETC2 (GL ES 3.0) 4 bits/pixel RGB+1-bit alpha texture format.
/// </summary>
ETC2_RGBA1,
/// <summary>
/// ETC2 (GL ES 3.0) 8 bits/pixel compressed RGBA texture format.
/// </summary>
ETC2_RGBA8,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB texture format.
/// </summary>
ASTC_RGB_12x12,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGBA texture format.
/// </summary>
ASTC_RGBA_12x12,
/// <summary>
/// ETC 4 bits/pixel compressed RGB texture format.
/// </summary>
ETC_RGB4_3DS,
/// <summary>
/// ETC 4 bits/pixel RGB + 4 bits/pixel Alpha compressed texture format.
/// </summary>
ETC_RGBA8_3DS,
/// <summary>
/// Two color (RG) texture format, 8-bits per channel.
/// </summary>
RG16,
/// <summary>
/// Single channel (R) texture format, 8 bit integer.
/// </summary>
R8,
/// <summary>
/// Compressed color texture format with Crunch compression for smaller storage sizes.
/// </summary>
ETC_RGB4Crunched,
/// <summary>
/// Compressed color with alpha channel texture format using Crunch compression for smaller storage sizes.
/// </summary>
ETC2_RGBA8Crunched,
/// <summary>
/// ASTC (4x4 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_4x4,
/// <summary>
/// ASTC (5x5 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_5x5,
/// <summary>
/// ASTC (6x6 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_6x6,
/// <summary>
/// ASTC (8x8 pixel block in 128 bits) compressed RGB(A) texture format.
/// </summary>
ASTC_HDR_8x8,
/// <summary>
/// ASTC (10x10 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_10x10,
/// <summary>
/// ASTC (12x12 pixel block in 128 bits) compressed RGB(A) HDR texture format.
/// </summary>
ASTC_HDR_12x12,
/// <summary>
/// Two channel (RG) texture format, 16-bits unsigned integer per channel.
/// </summary>
RG32,
/// <summary>
/// Three channel (RGB) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGB48,
/// <summary>
/// Four channel (RGBA) texture format, 16-bits unsigned integer per channel.
/// </summary>
RGBA64,
}
}

View File

@@ -34,7 +34,7 @@ namespace AssetStudio
var m_ProxyHeight = reader.ReadUInt32(); var m_ProxyHeight = reader.ReadUInt32();
Width = reader.ReadUInt32(); Width = reader.ReadUInt32();
Height = reader.ReadUInt32(); Height = reader.ReadUInt32();
if (version >= (2017, 2)) //2017.2 and up if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
{ {
var m_PixelAspecRatioNum = reader.ReadUInt32(); var m_PixelAspecRatioNum = reader.ReadUInt32();
var m_PixelAspecRatioDen = reader.ReadUInt32(); var m_PixelAspecRatioDen = reader.ReadUInt32();
@@ -46,7 +46,7 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
var m_AudioSampleRate = reader.ReadUInt32Array(); var m_AudioSampleRate = reader.ReadUInt32Array();
var m_AudioLanguage = reader.ReadStringArray(); var m_AudioLanguage = reader.ReadStringArray();
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
var m_VideoShadersSize = reader.ReadInt32(); var m_VideoShadersSize = reader.ReadInt32();
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize]; var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
@@ -57,7 +57,7 @@ namespace AssetStudio
} }
m_ExternalResources = new StreamedResource(reader); m_ExternalResources = new StreamedResource(reader);
m_HasSplitAlpha = reader.ReadBoolean(); m_HasSplitAlpha = reader.ReadBoolean();
if (version >= 2020) //2020.1 and up if (version[0] >= 2020) //2020.1 and up
{ {
var m_sRGB = reader.ReadBoolean(); var m_sRGB = reader.ReadBoolean();
} }

View File

@@ -1,149 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using static AssetStudio.EndianSpanReader;
namespace AssetStudio
{
public enum CubismSDKVersion : byte
{
V30 = 1,
V33,
V40,
V42,
V50
}
public sealed class CubismModel : IDisposable
{
public CubismSDKVersion Version { get; }
public string VersionDescription { get; }
public float CanvasWidth { get; }
public float CanvasHeight { get; }
public float CentralPosX { get; }
public float CentralPosY { get; }
public float PixelPerUnit { get; }
public uint PartCount { get; }
public uint ParamCount { get; }
public HashSet<string> PartNames { get; }
public HashSet<string> ParamNames { get; }
private byte[] modelData;
private int modelDataSize;
private bool isBigEndian;
public CubismModel(MonoBehaviour moc)
{
var reader = moc.reader;
reader.Reset();
reader.Position += 28; //PPtr<GameObject> m_GameObject, m_Enabled, PPtr<MonoScript>
reader.ReadAlignedString(); //m_Name
modelDataSize = (int)reader.ReadUInt32();
modelData = BigArrayPool<byte>.Shared.Rent(modelDataSize);
_ = reader.Read(modelData, 0, modelDataSize);
var sdkVer = modelData[4];
if (Enum.IsDefined(typeof(CubismSDKVersion), sdkVer))
{
Version = (CubismSDKVersion)sdkVer;
VersionDescription = ParseVersion();
}
else
{
var msg = $"Unknown SDK version ({sdkVer})";
VersionDescription = msg;
Version = 0;
Logger.Warning($"Live2D model \"{moc.m_Name}\": " + msg);
return;
}
isBigEndian = BitConverter.ToBoolean(modelData, 5);
//offsets
var countInfoTableOffset = (int)SpanToUint32(modelData, 64, isBigEndian);
var canvasInfoOffset = (int)SpanToUint32(modelData, 68, isBigEndian);
var partIdsOffset = SpanToUint32(modelData, 76, isBigEndian);
var parameterIdsOffset = SpanToUint32(modelData, 264, isBigEndian);
//canvas
PixelPerUnit = ToSingle(modelData, canvasInfoOffset, isBigEndian);
CentralPosX = ToSingle(modelData, canvasInfoOffset + 4, isBigEndian);
CentralPosY = ToSingle(modelData, canvasInfoOffset + 8, isBigEndian);
CanvasWidth = ToSingle(modelData, canvasInfoOffset + 12, isBigEndian);
CanvasHeight = ToSingle(modelData, canvasInfoOffset + 16, isBigEndian);
//model
PartCount = SpanToUint32(modelData, countInfoTableOffset, isBigEndian);
ParamCount = SpanToUint32(modelData, countInfoTableOffset + 20, isBigEndian);
PartNames = ReadMocStringHashSet(modelData, (int)partIdsOffset, (int)PartCount);
ParamNames = ReadMocStringHashSet(modelData, (int)parameterIdsOffset, (int)ParamCount);
}
public void SaveMoc3(string savePath)
{
if (!savePath.EndsWith(".moc3"))
savePath += ".moc3";
using (var file = File.OpenWrite(savePath))
{
file.Write(modelData, 0, modelDataSize);
}
}
private string ParseVersion()
{
switch (Version)
{
case CubismSDKVersion.V30:
return "SDK3.0/Cubism3.0(3.2)";
case CubismSDKVersion.V33:
return "SDK3.3/Cubism3.3";
case CubismSDKVersion.V40:
return "SDK4.0/Cubism4.0";
case CubismSDKVersion.V42:
return "SDK4.2/Cubism4.2";
case CubismSDKVersion.V50:
return "SDK5.0/Cubism5.0";
default:
return "";
}
}
private static float ToSingle(ReadOnlySpan<byte> data, int index, bool isBigEndian) //net framework ver
{
var bytes = data.Slice(index, index + 4).ToArray();
if ((isBigEndian && BitConverter.IsLittleEndian) || (!isBigEndian && !BitConverter.IsLittleEndian))
(bytes[0], bytes[1], bytes[2], bytes[3]) = (bytes[3], bytes[2], bytes[1], bytes[0]);
return BitConverter.ToSingle(bytes, 0);
}
private static HashSet<string> ReadMocStringHashSet(ReadOnlySpan<byte> data, int index, int count)
{
const int strLen = 64;
var strHashSet = new HashSet<string>();
for (var i = 0; i < count; i++)
{
if (index + i * strLen <= data.Length)
{
var buff = data.Slice(index + i * strLen, strLen);
strHashSet.Add(Encoding.UTF8.GetString(buff.ToArray()).TrimEnd('\0'));
}
}
return strHashSet;
}
private void Dispose(bool disposing)
{
if (disposing)
{
BigArrayPool<byte>.Shared.Return(modelData, clearArray: true);
}
}
public void Dispose()
{
Dispose(true);
}
}
}

View File

@@ -1,29 +0,0 @@
using System;
using System.Buffers.Binary;
namespace AssetStudio
{
public static class EndianSpanReader
{
public static uint SpanToUint32(Span<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt32BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(start));
}
public static uint SpanToUint16(Span<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadUInt16BigEndian(data.Slice(start))
: BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(start));
}
public static long SpanToInt64(Span<byte> data, int start, bool isBigEndian)
{
return isBigEndian
? BinaryPrimitives.ReadInt64BigEndian(data.Slice(start))
: BinaryPrimitives.ReadInt64LittleEndian(data.Slice(start));
}
}
}

View File

@@ -40,7 +40,7 @@ namespace AssetStudio
if (encoding?.CodePage == 1200) //Unicode (UTF-16LE) if (encoding?.CodePage == 1200) //Unicode (UTF-16LE)
return reader.ReadUnicodeStringToNull(maxLength * 2); return reader.ReadUnicodeStringToNull(maxLength * 2);
Span<byte> bytes = stackalloc byte[maxLength]; var bytes = new List<byte>();
var count = 0; var count = 0;
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength) while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
{ {
@@ -49,10 +49,9 @@ namespace AssetStudio
{ {
break; break;
} }
bytes[count] = b; bytes.Add(b);
count++; count++;
} }
bytes = bytes.Slice(0, count);
return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray()); return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray());
} }

View File

@@ -1,6 +1,5 @@
using System; using System.IO;
using System.IO; using System.Linq;
using static AssetStudio.EndianSpanReader;
namespace AssetStudio namespace AssetStudio
{ {
@@ -38,69 +37,66 @@ namespace AssetStudio
case "UnityWebData1.0": case "UnityWebData1.0":
return FileType.WebFile; return FileType.WebFile;
default: default:
{
var buff = ReadBytes(40).AsSpan();
var magic = Span<byte>.Empty;
Position = 0;
magic = buff.Length > 2 ? buff.Slice(0, 2) : magic;
if (magic.SequenceEqual(gzipMagic))
{ {
return FileType.GZipFile; byte[] magic = ReadBytes(2);
Position = 0;
if (gzipMagic.SequenceEqual(magic))
{
return FileType.GZipFile;
}
Position = 0x20;
magic = ReadBytes(6);
Position = 0;
if (brotliMagic.SequenceEqual(magic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile())
{
return FileType.AssetsFile;
}
magic = ReadBytes(4);
Position = 0;
if (zipMagic.SequenceEqual(magic) || zipSpannedMagic.SequenceEqual(magic))
return FileType.ZipFile;
return FileType.ResourceFile;
} }
magic = buff.Length > 38 ? buff.Slice(32, 6) : magic;
if (magic.SequenceEqual(brotliMagic))
{
return FileType.BrotliFile;
}
if (IsSerializedFile(buff))
{
return FileType.AssetsFile;
}
magic = buff.Length > 4 ? buff.Slice(0, 4): magic;
if (magic.SequenceEqual(zipMagic) || magic.SequenceEqual(zipSpannedMagic))
{
return FileType.ZipFile;
}
return FileType.ResourceFile;
}
} }
} }
private bool IsSerializedFile(Span<byte> buff) private bool IsSerializedFile()
{ {
var fileSize = BaseStream.Length; var fileSize = BaseStream.Length;
if (fileSize < 20) if (fileSize < 20)
{ {
return false; return false;
} }
var isBigEndian = Endian == EndianType.BigEndian; var m_MetadataSize = ReadUInt32();
long m_FileSize = ReadUInt32();
//var m_MetadataSize = SpanToUint32(buff, 0, isBigEndian); var m_Version = ReadUInt32();
long m_FileSize = SpanToUint32(buff, 4, isBigEndian); long m_DataOffset = ReadUInt32();
var m_Version = SpanToUint32(buff, 8, isBigEndian); var m_Endianess = ReadByte();
long m_DataOffset = SpanToUint32(buff, 12, isBigEndian); var m_Reserved = ReadBytes(3);
//var m_Endianess = buff[16];
//var m_Reserved = buff.Slice(17, 3);
if (m_Version >= 22) if (m_Version >= 22)
{ {
if (fileSize < 48) if (fileSize < 48)
{ {
Position = 0;
return false; return false;
} }
//m_MetadataSize = SpanToUint32(buff, 20, isBigEndian); m_MetadataSize = ReadUInt32();
m_FileSize = SpanToInt64(buff, 24, isBigEndian); m_FileSize = ReadInt64();
m_DataOffset = SpanToInt64(buff, 32, isBigEndian); m_DataOffset = ReadInt64();
} }
if (m_FileSize != fileSize || m_DataOffset > fileSize) Position = 0;
if (m_FileSize != fileSize)
{
return false;
}
if (m_DataOffset > fileSize)
{ {
return false; return false;
} }
return true; return true;
} }
} }

75
AssetStudio/LZ4/LZ4.cs Normal file
View File

@@ -0,0 +1,75 @@
using System;
namespace AssetStudio
{
public class LZ4
{
public static LZ4 Instance => new LZ4();
public virtual int Decompress(ReadOnlySpan<byte> cmp, Span<byte> dec)
{
int cmpPos = 0;
int decPos = 0;
do
{
var (encCount, litCount) = GetLiteralToken(cmp, ref cmpPos);
//Copy literal chunk
litCount = GetLength(litCount, cmp, ref cmpPos);
cmp.Slice(cmpPos, litCount).CopyTo(dec.Slice(decPos));
cmpPos += litCount;
decPos += litCount;
if (cmpPos >= cmp.Length)
{
break;
}
//Copy compressed chunk
int back = GetChunkEnd(cmp, ref cmpPos);
encCount = GetLength(encCount, cmp, ref cmpPos) + 4;
int encPos = decPos - back;
if (encCount <= back)
{
dec.Slice(encPos, encCount).CopyTo(dec.Slice(decPos));
decPos += encCount;
}
else
{
while (encCount-- > 0)
{
dec[decPos++] = dec[encPos++];
}
}
} while (cmpPos < cmp.Length && decPos < dec.Length);
return decPos;
}
protected virtual (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
((cmp[cmpPos] >> 0) & 0xf, (cmp[cmpPos++] >> 4) & 0xf);
protected virtual int GetChunkEnd(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
cmp[cmpPos++] << 0 | cmp[cmpPos++] << 8;
protected virtual int GetLength(int length, ReadOnlySpan<byte> cmp, ref int cmpPos)
{
byte sum;
if (length == 0xf)
{
do
{
length += sum = cmp[cmpPos++];
} while (sum == 0xff);
}
return length;
}
}
}

15
AssetStudio/LZ4/LZ4Inv.cs Normal file
View File

@@ -0,0 +1,15 @@
using System;
namespace AssetStudio
{
public class LZ4Inv : LZ4
{
public new static LZ4Inv Instance => new LZ4Inv();
protected override (int encCount, int litCount) GetLiteralToken(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
((cmp[cmpPos] >> 4) & 0xf, (cmp[cmpPos++] >> 0) & 0xf);
protected override int GetChunkEnd(ReadOnlySpan<byte> cmp, ref int cmpPos) =>
cmp[cmpPos++] << 8 | cmp[cmpPos++] << 0;
}
}

View File

@@ -17,7 +17,7 @@ namespace AssetStudio
public BuildTarget platform; public BuildTarget platform;
public SerializedFileFormatVersion m_Version; public SerializedFileFormatVersion m_Version;
public UnityVersion version => assetsFile.version; public int[] version => assetsFile.version;
public BuildType buildType => assetsFile.buildType; 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)

View File

@@ -7,31 +7,25 @@ namespace AssetStudio
private bool needSearch; private bool needSearch;
private string path; private string path;
private SerializedFile assetsFile; private SerializedFile assetsFile;
private long offset;
private long size; private long size;
private BinaryReader reader; private BinaryReader reader;
public int Size public int Size { get => (int)size; }
{
get => (int)size;
set => size = value;
}
public long Offset { get; set; }
public ResourceReader() { }
public ResourceReader(string path, SerializedFile assetsFile, long offset, long size) public ResourceReader(string path, SerializedFile assetsFile, long offset, long size)
{ {
needSearch = true; needSearch = true;
this.path = path; this.path = path;
this.assetsFile = assetsFile; this.assetsFile = assetsFile;
this.Offset = offset; this.offset = offset;
this.size = size; this.size = size;
} }
public ResourceReader(BinaryReader reader, long offset, long size) public ResourceReader(BinaryReader reader, long offset, long size)
{ {
this.reader = reader; this.reader = reader;
this.Offset = offset; this.offset = offset;
this.size = size; this.size = size;
} }
@@ -58,12 +52,8 @@ namespace AssetStudio
if (File.Exists(resourceFilePath)) if (File.Exists(resourceFilePath))
{ {
needSearch = false; needSearch = false;
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
{
return reader;
}
reader = new BinaryReader(File.OpenRead(resourceFilePath)); reader = new BinaryReader(File.OpenRead(resourceFilePath));
assetsFile.assetsManager.resourceFileReaders.TryAdd(resourceFileName, reader); assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
return reader; return reader;
} }
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}"); throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
@@ -77,27 +67,21 @@ namespace AssetStudio
public byte[] GetData() public byte[] GetData()
{ {
var binaryReader = GetReader(); var binaryReader = GetReader();
lock (binaryReader) binaryReader.BaseStream.Position = offset;
{ return binaryReader.ReadBytes((int)size);
binaryReader.BaseStream.Position = Offset;
return binaryReader.ReadBytes((int) size);
}
} }
public void GetData(byte[] buff) public void GetData(byte[] buff)
{ {
var binaryReader = GetReader(); var binaryReader = GetReader();
lock (binaryReader) binaryReader.BaseStream.Position = offset;
{ binaryReader.Read(buff, 0, (int)size);
binaryReader.BaseStream.Position = Offset;
binaryReader.Read(buff, 0, (int) size);
}
} }
public void WriteData(string path) public void WriteData(string path)
{ {
var binaryReader = GetReader(); var binaryReader = GetReader();
binaryReader.BaseStream.Position = Offset; binaryReader.BaseStream.Position = offset;
using (var writer = File.OpenWrite(path)) using (var writer = File.OpenWrite(path))
{ {
binaryReader.BaseStream.CopyTo(writer, size); binaryReader.BaseStream.CopyTo(writer, size);

View File

@@ -13,7 +13,7 @@ namespace AssetStudio
public string fullName; public string fullName;
public string originalPath; public string originalPath;
public string fileName; public string fileName;
public UnityVersion version = new UnityVersion(); public int[] version = { 0, 0, 0, 0 };
public BuildType buildType; public BuildType buildType;
public List<Object> Objects; public List<Object> Objects;
public Dictionary<long, Object> ObjectsDic; public Dictionary<long, Object> ObjectsDic;
@@ -73,7 +73,7 @@ namespace AssetStudio
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7) if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
{ {
unityVersion = reader.ReadStringToNull(); unityVersion = reader.ReadStringToNull();
SetVersion(new UnityVersion(unityVersion)); SetVersion(unityVersion);
} }
if (header.m_Version >= SerializedFileFormatVersion.Unknown_8) if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
{ {
@@ -217,13 +217,19 @@ namespace AssetStudio
//reader.AlignStream(16); //reader.AlignStream(16);
} }
public void SetVersion(UnityVersion unityVer) public void SetVersion(string stringVersion)
{ {
if (unityVer != null && !unityVer.IsStripped) if (stringVersion != strippedVersion)
{ {
unityVersion = unityVer.FullVersion; unityVersion = stringVersion;
buildType = new BuildType(unityVer.BuildType); var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
version = unityVer; 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();
} }
} }
@@ -371,5 +377,9 @@ namespace AssetStudio
Objects.Add(obj); Objects.Add(obj);
ObjectsDic.Add(obj.m_PathID, obj); ObjectsDic.Add(obj.m_PathID, obj);
} }
public bool IsVersionStripped => unityVersion == strippedVersion;
private const string strippedVersion = "0.0.0";
} }
} }

View File

@@ -20,7 +20,7 @@ namespace AssetStudio
var readed = reader.Position - reader.byteStart; var readed = reader.Position - reader.byteStart;
if (readed != reader.byteSize) if (readed != reader.byteSize)
{ {
Logger.Info($"Failed to read type, read {readed} bytes but expected {reader.byteSize} bytes"); Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
} }
return sb.ToString(); return sb.ToString();
} }
@@ -116,7 +116,7 @@ namespace AssetStudio
{ {
append = false; append = false;
var size = reader.ReadInt32(); var size = reader.ReadInt32();
reader.BaseStream.Position += size; reader.ReadBytes(size);
i += 2; i += 2;
sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr); sb.AppendFormat("{0}{1} {2}\r\n", (new string('\t', level)), varTypeStr, varNameStr);
sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size); sb.AppendFormat("{0}{1} {2} = {3}\r\n", (new string('\t', level)), "int", "size", size);
@@ -171,13 +171,13 @@ namespace AssetStudio
for (int i = 1; i < m_Nodes.Count; i++) for (int i = 1; i < m_Nodes.Count; i++)
{ {
var m_Node = m_Nodes[i]; var m_Node = m_Nodes[i];
var varNameStr = m_Node.m_Name.Replace("image data", "image_data"); var varNameStr = m_Node.m_Name;
obj[varNameStr] = ReadValue(m_Nodes, reader, ref i); obj[varNameStr] = ReadValue(m_Nodes, reader, ref i);
} }
var readed = reader.Position - reader.byteStart; var readed = reader.Position - reader.byteStart;
if (readed != reader.byteSize) if (readed != reader.byteSize)
{ {
Logger.Info($"Failed to read type, read {readed} bytes but expected {reader.byteSize} bytes"); Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
} }
return obj; return obj;
} }
@@ -262,13 +262,7 @@ namespace AssetStudio
case "TypelessData": case "TypelessData":
{ {
var size = reader.ReadInt32(); var size = reader.ReadInt32();
var dic = new OrderedDictionary value = reader.ReadBytes(size);
{
{ "Offset", reader.BaseStream.Position },
{ "Size", size }
};
value = dic;
reader.BaseStream.Position += size;
i += 2; i += 2;
break; break;
} }

View File

@@ -1,449 +0,0 @@
using System;
using System.Linq;
using System.Text.RegularExpressions;
namespace AssetStudio
{
public class UnityVersion : IComparable
{
public int Major { get; }
public int Minor { get; }
public int Patch { get; }
public int Build { get; }
public string BuildType { get; }
public string FullVersion { get; }
public bool IsStripped => this == (0, 0, 0);
public UnityVersion(string version)
{
if (string.IsNullOrEmpty(version))
throw new ArgumentException("Unity version cannot be empty.");
try
{
int[] ver = Regex.Matches(version, @"\d+").Cast<Match>().Select(x => int.Parse(x.Value)).ToArray();
(Major, Minor, Patch) = (ver[0], ver[1], ver[2]);
if (ver.Length == 4)
Build = ver[3];
FullVersion = version;
}
catch (Exception)
{
throw new NotSupportedException($"Failed to parse Unity version: \"{version}\".");
}
string[] build = Regex.Matches(version, @"\D+").Cast<Match>().Select(x => x.Value).ToArray();
if (build.Length > 2)
{
BuildType = build[2];
}
}
public UnityVersion(int major = 0, int minor = 0, int patch = 0)
{
(Major, Minor, Patch) = (major, minor, patch);
FullVersion = $"{Major}.{Minor}.{Patch}";
if (!IsStripped)
{
Build = 1;
BuildType = "f";
FullVersion += $"{BuildType}{Build}";
}
}
#region UnityVer, UnityVer
public static bool operator ==(UnityVersion left, UnityVersion right)
{
return Equals(left, right);
}
public static bool operator !=(UnityVersion left, UnityVersion right)
{
return !Equals(left, right);
}
public static bool operator >(UnityVersion left, UnityVersion right)
{
return left?.CompareTo(right) > 0;
}
public static bool operator <(UnityVersion left, UnityVersion right)
{
return left?.CompareTo(right) < 0;
}
public static bool operator >=(UnityVersion left, UnityVersion right)
{
return left == right || left > right;
}
public static bool operator <=(UnityVersion left, UnityVersion right)
{
return left == right || left < right;
}
#endregion
#region UnityVer, int
public static bool operator ==(UnityVersion left, int right)
{
return left?.Major == right;
}
public static bool operator !=(UnityVersion left, int right)
{
return left?.Major != right;
}
public static bool operator >(UnityVersion left, int right)
{
return left?.Major > right;
}
public static bool operator <(UnityVersion left, int right)
{
return left?.Major < right;
}
public static bool operator >=(UnityVersion left, int right)
{
return left?.Major >= right;
}
public static bool operator <=(UnityVersion left, int right)
{
return left?.Major <= right;
}
#endregion
#region UnityVer, (int, int)
public static bool operator ==(UnityVersion left, (int, int) right)
{
return (left?.Major, left?.Minor) == (right.Item1, right.Item2);
}
public static bool operator !=(UnityVersion left, (int, int) right)
{
return (left?.Major, left?.Minor) != (right.Item1, right.Item2);
}
public static bool operator >(UnityVersion left, (int, int) right)
{
return left?.CompareTo(right) > 0;
}
public static bool operator <(UnityVersion left, (int, int) right)
{
return left?.CompareTo(right) < 0;
}
public static bool operator >=(UnityVersion left, (int, int) right)
{
return left == right || left > right;
}
public static bool operator <=(UnityVersion left, (int, int) right)
{
return left == right || left < right;
}
#endregion
#region UnityVer, (int, int, int)
public static bool operator ==(UnityVersion left, (int, int, int) right)
{
return (left?.Major, left?.Minor, left?.Patch) == (right.Item1, right.Item2, right.Item3);
}
public static bool operator !=(UnityVersion left, (int, int, int) right)
{
return (left?.Major, left?.Minor, left?.Patch) != (right.Item1, right.Item2, right.Item3);
}
public static bool operator >(UnityVersion left, (int, int, int) right)
{
return left?.CompareTo(right) > 0;
}
public static bool operator <(UnityVersion left, (int, int, int) right)
{
return left?.CompareTo(right) < 0;
}
public static bool operator >=(UnityVersion left, (int, int, int) right)
{
return left == right || left > right;
}
public static bool operator <=(UnityVersion left, (int, int, int) right)
{
return left == right || left < right;
}
#endregion
#region int, UnityVer
public static bool operator ==(int left, UnityVersion right)
{
return left == right?.Major;
}
public static bool operator !=(int left, UnityVersion right)
{
return left != right?.Major;
}
public static bool operator >(int left, UnityVersion right)
{
return left > right?.Major;
}
public static bool operator <(int left, UnityVersion right)
{
return left < right?.Major;
}
public static bool operator >=(int left, UnityVersion right)
{
return left >= right?.Major;
}
public static bool operator <=(int left, UnityVersion right)
{
return left <= right?.Major;
}
#endregion
#region (int, int), UnityVer
public static bool operator ==((int, int) left, UnityVersion right)
{
return (left.Item1, left.Item2) == (right?.Major, right?.Minor);
}
public static bool operator !=((int, int) left, UnityVersion right)
{
return (left.Item1, left.Item2) != (right?.Major, right?.Minor);
}
public static bool operator >((int, int) left, UnityVersion right)
{
return right?.CompareTo(left) < 0;
}
public static bool operator <((int, int) left, UnityVersion right)
{
return right?.CompareTo(left) > 0;
}
public static bool operator >=((int, int) left, UnityVersion right)
{
return left == right || left > right;
}
public static bool operator <=((int, int) left, UnityVersion right)
{
return left == right || left < right;
}
#endregion
#region (int, int, int), UnityVer
public static bool operator ==((int, int, int) left, UnityVersion right)
{
return (left.Item1, left.Item2, left.Item3) == (right?.Major, right?.Minor, right?.Patch);
}
public static bool operator !=((int, int, int) left, UnityVersion right)
{
return (left.Item1, left.Item2, left.Item3) != (right?.Major, right?.Minor, right?.Patch);
}
public static bool operator >((int, int, int) left, UnityVersion right)
{
return right?.CompareTo(left) < 0;
}
public static bool operator <((int, int, int) left, UnityVersion right)
{
return right?.CompareTo(left) > 0;
}
public static bool operator >=((int, int, int) left, UnityVersion right)
{
return left == right || left > right;
}
public static bool operator <=((int, int, int) left, UnityVersion right)
{
return left == right || left < right;
}
#endregion
private int CompareTo((int, int) other)
{
var result = Major.CompareTo(other.Item1);
if (result != 0)
{
return result;
}
result = Minor.CompareTo(other.Item2);
if (result != 0)
{
return result;
}
return 0;
}
private int CompareTo((int, int, int) other)
{
var result = CompareTo((other.Item1, other.Item2));
if (result != 0)
{
return result;
}
result = Patch.CompareTo(other.Item3);
if (result != 0)
{
return result;
}
return 0;
}
private int CompareTo(UnityVersion other)
{
return CompareTo((other.Major, other.Minor, other.Patch));
}
private bool Equals(UnityVersion other)
{
return (Major, Minor, Patch) == (other.Major, other.Minor, other.Patch);
}
public override bool Equals(object other)
{
return other is UnityVersion otherUnityVer && Equals(otherUnityVer);
}
public override int GetHashCode()
{
var result = Major * 31;
result = result * 31 + Minor;
result = result * 31 + Patch;
result = result * 31 + Build;
return result.GetHashCode();
}
public int CompareTo(object obj)
{
return CompareTo((UnityVersion)obj);
}
public sealed override string ToString()
{
return FullVersion;
}
public Tuple<int, int, int> ToTuple()
{
return new Tuple<int, int, int>(Major, Minor, Patch);
}
public int[] ToArray()
{
return new[] {Major, Minor, Patch};
}
}
public static class UnityVersionExtensions
{
/// <summary>
/// Checks if the Unity version is within the range limits specified by the "lowerLimit" and "upperLimit" attributes.
/// </summary>
/// <param name="ver"></param>
/// <param name="lowerLimit">Minimal version. Included in the range.</param>
/// <param name="upperLimit">Maximal version. Not included in the range.</param>
/// <returns><see langword="true"/> if the Unity version is within the specified range; otherwise <see langword="false"/>.</returns>
/// <remarks>[lowerLimit, upperLimit)</remarks>
public static bool IsInRange(this UnityVersion ver, UnityVersion lowerLimit, UnityVersion upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, int lowerLimit, UnityVersion upperLimit)
{
return ver.Major >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int) lowerLimit, UnityVersion upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int, int) lowerLimit, UnityVersion upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, UnityVersion lowerLimit, int upperLimit)
{
return ver >= lowerLimit && ver.Major < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, UnityVersion lowerLimit, (int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, UnityVersion lowerLimit, (int, int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, int lowerLimit, int upperLimit)
{
return ver.Major >= lowerLimit && ver.Major < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, int lowerLimit, (int, int) upperLimit)
{
return ver.Major >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, int lowerLimit, (int, int, int) upperLimit)
{
return ver.Major >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int) lowerLimit, int upperLimit)
{
return ver >= lowerLimit && ver.Major < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int, int) lowerLimit, int upperLimit)
{
return ver >= lowerLimit && ver.Major < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int) lowerLimit, (int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int) lowerLimit, (int, int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int, int) lowerLimit, (int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
public static bool IsInRange(this UnityVersion ver, (int, int, int) lowerLimit, (int, int, int) upperLimit)
{
return ver >= lowerLimit && ver < upperLimit;
}
}
}

View File

@@ -3,10 +3,10 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks> <TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks>
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle> <AssemblyTitle>ArknightsStudio by aelurum</AssemblyTitle>
<AssemblyName>AssetStudioModCLI</AssemblyName> <AssemblyName>ArknightsStudioCLI</AssemblyName>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare; Copyright © aelurum 2023-2024</Copyright> <Copyright>Copyright © Perfare; Copyright © aelurum 2025</Copyright>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>

View File

@@ -1,10 +1,9 @@
using AssetStudio; using AssetStudio;
using AssetStudioCLI.Options; using AssetStudioCLI.Options;
using System; using System;
using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace AssetStudioCLI namespace AssetStudioCLI
{ {
@@ -17,29 +16,21 @@ namespace AssetStudioCLI
internal class CLILogger : ILogger internal class CLILogger : ILogger
{ {
public string LogName;
public string LogPath;
private static BlockingCollection<string> logMessageCollection = new BlockingCollection<string>();
private readonly LogOutputMode logOutput; private readonly LogOutputMode logOutput;
private readonly LoggerEvent logMinLevel; private readonly LoggerEvent logMinLevel;
public string LogName;
public string LogPath;
public CLILogger() public CLILogger()
{ {
logOutput = CLIOptions.o_logOutput.Value; logOutput = CLIOptions.o_logOutput.Value;
logMinLevel = CLIOptions.o_logLevel.Value; logMinLevel = CLIOptions.o_logLevel.Value;
var appAssembly = typeof(Program).Assembly.GetName(); var appAssembly = typeof(Program).Assembly.GetName();
var arch = Environment.Is64BitProcess ? "x64" : "x32";
LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"; LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName); LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
var arch = Environment.Is64BitProcess ? "x64" : "x32";
Console.OutputEncoding = System.Text.Encoding.UTF8; Console.OutputEncoding = System.Text.Encoding.UTF8;
if (logOutput != LogOutputMode.Console)
{
ConcurrentFileWriter();
}
LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" + LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" +
$"CMD Args: {string.Join(" ", CLIOptions.cliArgs)}"); $"CMD Args: {string.Join(" ", CLIOptions.cliArgs)}");
} }
@@ -64,7 +55,7 @@ namespace AssetStudioCLI
{ {
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"); var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
message = message.TrimEnd(); message = message.TrimEnd();
var multiLine = message.Contains("\n"); var multiLine = message.Contains('\n');
string formattedMessage; string formattedMessage;
if (consoleMode) if (consoleMode)
@@ -73,7 +64,7 @@ namespace AssetStudioCLI
formattedMessage = $"{colorLogLevel} {message}"; formattedMessage = $"{colorLogLevel} {message}";
if (multiLine) if (multiLine)
{ {
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ") + $"\n{colorLogLevel}"; formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ");
} }
} }
else else
@@ -83,7 +74,7 @@ namespace AssetStudioCLI
formattedMessage = $"{curTime} | {logLevel} | {message}"; formattedMessage = $"{curTime} | {logLevel} | {message}";
if (multiLine) if (multiLine)
{ {
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ") + $"\n{curTime} | {logLevel} |"; formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ");
} }
} }
return formattedMessage; return formattedMessage;
@@ -97,27 +88,15 @@ namespace AssetStudioCLI
} }
} }
public void LogToFile(LoggerEvent logMsgLevel, string message) public async void LogToFile(LoggerEvent logMsgLevel, string message)
{ {
if (logOutput != LogOutputMode.Console) if (logOutput != LogOutputMode.Console)
{
logMessageCollection.Add(FormatMessage(logMsgLevel, message));
}
}
private void ConcurrentFileWriter()
{
Task.Run(() =>
{ {
using (var sw = new StreamWriter(LogPath, append: true, System.Text.Encoding.UTF8)) using (var sw = new StreamWriter(LogPath, append: true, System.Text.Encoding.UTF8))
{ {
sw.AutoFlush = true; await sw.WriteLineAsync(FormatMessage(logMsgLevel, message));
foreach (var msg in logMessageCollection.GetConsumingEnumerable())
{
sw.WriteLine(msg);
}
} }
}); }
} }
public void Log(LoggerEvent logMsgLevel, string message, bool ignoreLevel) public void Log(LoggerEvent logMsgLevel, string message, bool ignoreLevel)

View File

@@ -0,0 +1,228 @@
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;
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 (new Size(faceImage.Width, faceImage.Height) != 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, avgSprite.FacePos, opacity: 1f));
alphaTex.Mutate(x => x.DrawImage(faceAlpha, 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) && avgSprite != null && avgSprite.IsHubParsed)
{
if (!avgSprite.IsFaceSprite)
{
return m_Texture2D.ConvertToImage(true);
}
var faceImage = m_Texture2D.ConvertToImage(true);
var tex = avgSprite.FullTexture.ConvertToImage(true);
if (new Size(faceImage.Width, faceImage.Height) != avgSprite.FaceSize)
{
faceImage.Mutate(x => x.Resize(new ResizeOptions { Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
}
tex.Mutate(x => x.DrawImage(faceImage, avgSprite.FacePos, opacity: 1f));
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)(new Size(originalImage.Width, originalImage.Height) / 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;
}
}
}

View File

@@ -0,0 +1,149 @@
using Arknights.AvgCharHubMono;
using AssetStudio;
using AssetStudioCLI;
using SixLabors.ImageSharp;
using System.Linq;
using System;
using System.Collections.Specialized;
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 scriptAssets = Studio.loadedAssetsList.FindAll(x =>
x.Type == ClassIDType.MonoBehaviour
&& x.Container == assetItem.Container);
if (scriptAssets.Count == 0)
{
Logger.Warning("No MonoBehaviours were found.");
return false;
}
OrderedDictionary spriteHubDict = null;
var isGrouped = false;
foreach (var scriptAsset in scriptAssets)
{
var scriptAssetDict = ((MonoBehaviour)scriptAsset.Asset).ToType();
if (scriptAssetDict == null)
{
Logger.Warning("MonoBehaviour is not readable.");
return false;
}
if (scriptAssetDict.Contains("spriteGroups"))
{
spriteHubDict = scriptAssetDict;
isGrouped = true;
break;
}
if (scriptAssetDict.Contains("sprites"))
{
spriteHubDict = scriptAssetDict;
break;
}
}
if (spriteHubDict == null)
{
Logger.Warning("AVGCharacterSpriteHub is not readable.");
return false;
}
var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict);
if (isGrouped)
{
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) //If face data exist
{
var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture
var curSprite = (Sprite)assetItem.Asset;
IsFaceSprite = curSprite.m_Rect.width <= 256 && curSprite.m_Rect.height <= 256 && curSprite.m_PathID != fullTexSpriteData.Sprite.m_PathID;
var curSpriteAlphaID = curSpriteData.AlphaTex.m_PathID;
var curSpriteAlphaTex = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == curSpriteAlphaID)?.Asset;
if (curSpriteAlphaTex != null)
{
FaceSpriteAlphaTexture = IsFaceSprite ? curSpriteAlphaTex : null;
fullTexSpriteData = IsFaceSprite ? fullTexSpriteData : curSpriteData;
}
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));
}
else
{
FullAlphaTexture = (Texture2D)Studio.loadedAssetsList.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID).Asset;
}
}
}
}
}

View 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; }
}
}

View 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;
}
}
}

View 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; }
}
}

View File

@@ -1,4 +1,5 @@
using AssetStudio; using Arknights;
using AssetStudio;
namespace AssetStudioCLI namespace AssetStudioCLI
{ {
@@ -14,6 +15,7 @@ namespace AssetStudioCLI
public string Text; public string Text;
public string UniqueID; public string UniqueID;
public GameObjectNode Node; public GameObjectNode Node;
public PortraitSprite AkPortraitSprite;
public AssetItem(Object asset) public AssetItem(Object asset)
{ {
@@ -24,5 +26,17 @@ namespace AssetStudioCLI
m_PathID = asset.m_PathID; m_PathID = asset.m_PathID;
FullSize = asset.byteSize; 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;
}
} }
} }

View File

@@ -1,3 +1,4 @@
using AssetStudio;
using System.Collections.Generic; using System.Collections.Generic;
namespace AssetStudioCLI namespace AssetStudioCLI
@@ -5,12 +6,11 @@ namespace AssetStudioCLI
internal class BaseNode internal class BaseNode
{ {
public List<BaseNode> nodes = new List<BaseNode>(); public List<BaseNode> nodes = new List<BaseNode>();
public string FullPath = "";
public readonly string Text;
public BaseNode(string name) public BaseNode()
{ {
Text = name;
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using AssetStudio; using AssetStudio;
using System.Collections.Generic;
namespace AssetStudioCLI namespace AssetStudioCLI
{ {
@@ -6,9 +7,10 @@ namespace AssetStudioCLI
{ {
public GameObject gameObject; public GameObject gameObject;
public GameObjectNode(GameObject gameObject) : base(gameObject.m_Name) public GameObjectNode(GameObject gameObject)
{ {
this.gameObject = gameObject; this.gameObject = gameObject;
} }
} }
} }

View File

@@ -1,15 +1,123 @@
using AssetStudio; using Arknights;
using AssetStudio;
using AssetStudioCLI.Options; using AssetStudioCLI.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
namespace AssetStudioCLI namespace AssetStudioCLI
{ {
internal static class Exporter 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) public static bool ExportVideoClip(AssetItem item, string exportPath)
{ {
var m_VideoClip = (VideoClip)item.Asset; var m_VideoClip = (VideoClip)item.Asset;
@@ -129,6 +237,112 @@ namespace AssetStudioCLI
return false; 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) public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
{ {
var convert = animationList != null var convert = animationList != null
@@ -141,7 +355,7 @@ namespace AssetStudioCLI
private static void ExportFbx(IImported convert, string exportPath) private static void ExportFbx(IImported convert, string exportPath)
{ {
var eulerFilter = true; var eulerFilter = true;
var filterPrecision = 0.25f; var filterPrecision = (float)0.25f;
var exportAllNodes = true; var exportAllNodes = true;
var exportSkins = true; var exportSkins = true;
var exportAnimations = true; var exportAnimations = true;
@@ -156,19 +370,14 @@ namespace AssetStudioCLI
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1); exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
} }
public static bool ExportRawFile(AssetItem item, string exportPath)
{
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw"))
return false;
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
return true;
}
public static bool ExportDumpFile(AssetItem item, string exportPath) public static bool ExportDumpFile(AssetItem item, string exportPath)
{ {
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump")) 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; return false;
var str = item.Asset.Dump(); var str = item.Asset.Dump();
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour) if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
@@ -176,10 +385,6 @@ namespace AssetStudioCLI
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader); var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
str = m_MonoBehaviour.Dump(m_Type); str = m_MonoBehaviour.Dump(m_Type);
} }
if (string.IsNullOrEmpty(str))
{
str = item.Asset.DumpObject();
}
if (str != null) if (str != null)
{ {
File.WriteAllText(exportFullPath, str); File.WriteAllText(exportFullPath, str);
@@ -189,35 +394,22 @@ namespace AssetStudioCLI
return false; return false;
} }
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string mode = "Export") 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;
var filenameFormat = CLIOptions.o_filenameFormat.Value;
switch (filenameFormat)
{
case FilenameFormat.AssetName_PathID:
fileName = $"{fileName} @{item.m_PathID}";
break;
case FilenameFormat.PathID:
fileName = item.m_PathID.ToString();
break;
}
fullPath = Path.Combine(dir, fileName + extension); fullPath = Path.Combine(dir, fileName + extension);
if (!File.Exists(fullPath)) if (!File.Exists(fullPath))
{ {
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
return true; return true;
} }
if (filenameFormat == FilenameFormat.AssetName) fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
if (!File.Exists(fullPath))
{ {
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension); Directory.CreateDirectory(dir);
if (!File.Exists(fullPath)) return true;
{
Directory.CreateDirectory(dir);
return true;
}
} }
Logger.Error($"{mode} error. File \"{fullPath.Color(ColorConsole.BrightRed)}\" already exist"); Logger.Error($"Export error. File \"{fullPath.Color(ColorConsole.BrightRed)}\" already exist");
return false; return false;
} }
@@ -323,10 +515,9 @@ namespace AssetStudioCLI
switch (item.Type) switch (item.Type)
{ {
case ClassIDType.Texture2D: case ClassIDType.Texture2D:
case ClassIDType.Texture2DArray: return ExportTexture2D(item, exportPath);
case ClassIDType.Sprite:
case ClassIDType.AudioClip: case ClassIDType.AudioClip:
throw new System.NotImplementedException(); return ExportAudioClip(item, exportPath);
case ClassIDType.VideoClip: case ClassIDType.VideoClip:
return ExportVideoClip(item, exportPath); return ExportVideoClip(item, exportPath);
case ClassIDType.MovieTexture: case ClassIDType.MovieTexture:
@@ -339,6 +530,10 @@ namespace AssetStudioCLI
return ExportMonoBehaviour(item, exportPath); return ExportMonoBehaviour(item, exportPath);
case ClassIDType.Font: case ClassIDType.Font:
return ExportFont(item, exportPath); return ExportFont(item, exportPath);
case ClassIDType.Sprite:
return ExportSprite(item, exportPath);
case ClassIDType.AkPortraitSprite:
return ExportPortraitSprite(item, exportPath);
case ClassIDType.Mesh: case ClassIDType.Mesh:
return ExportMesh(item, exportPath); return ExportMesh(item, exportPath);
default: default:
@@ -348,9 +543,8 @@ namespace AssetStudioCLI
public static string FixFileName(string str) public static string FixFileName(string str)
{ {
return str.Length >= 260 if (str.Length >= 260) return Path.GetRandomFileName();
? Path.GetRandomFileName() return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -4,17 +4,15 @@
{ {
public string Name { get; } public string Name { get; }
public string Description { get; } public string Description { get; }
public string Example { get; }
public T Value { get; set; } public T Value { get; set; }
public T DefaultValue { get; } public T DefaultValue { get; }
public HelpGroups HelpGroup { get; } public HelpGroups HelpGroup { get; }
public bool IsFlag { get; } public bool IsFlag { get; }
public Option(T optionDefaultValue, string optionName, string optionDescription, string optionExample, HelpGroups optionHelpGroup, bool isFlag) public Option(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag)
{ {
Name = optionName; Name = optionName;
Description = optionDescription; Description = optionDescription;
Example = optionExample;
DefaultValue = optionDefaultValue; DefaultValue = optionDefaultValue;
Value = DefaultValue; Value = DefaultValue;
HelpGroup = optionHelpGroup; HelpGroup = optionHelpGroup;

View File

@@ -4,14 +4,14 @@ namespace AssetStudioCLI.Options
{ {
internal static class OptionExtensions internal static class OptionExtensions
{ {
public static Action<string, string, string, HelpGroups, bool> OptionGrouping = (name, desc, example, group, isFlag) => { }; public static Action<string, string, HelpGroups, bool> OptionGrouping = (name, desc, group, isFlag) => { };
} }
internal class GroupedOption<T> : Option<T> internal class GroupedOption<T> : Option<T>
{ {
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, string optionExample, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionExample, optionHelpGroup, isFlag) public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionHelpGroup, isFlag)
{ {
OptionExtensions.OptionGrouping(optionName, optionDescription, optionExample, optionHelpGroup, isFlag); OptionExtensions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
} }
} }
} }

View File

@@ -1,223 +0,0 @@
using AssetStudio;
using AssetStudioCLI.Options;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudioCLI
{
internal static class ParallelExporter
{
private static ConcurrentDictionary<string, bool> savePathHash = new ConcurrentDictionary<string, bool>();
public static bool ExportTexture2D(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
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 {item.TypeString} \"{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;
}
debugLog += sb.ToString();
}
var image = m_Texture2D.ConvertToImage(flip: true);
if (image == null)
{
Logger.Error($"{debugLog}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);
}
debugLog += $"{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());
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
}
public static bool ExportSprite(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
var type = CLIOptions.o_imageFormat.Value;
var alphaMask = SpriteMaskMode.On;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
var image = ((Sprite)item.Asset).GetImage(alphaMask);
if (image != null)
{
using (image)
{
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
}
return false;
}
public static bool ExportAudioClip(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
string exportFullPath;
var m_AudioClip = (AudioClip)item.Asset;
var m_AudioData = BigArrayPool<byte>.Shared.Rent(m_AudioClip.m_AudioData.Size);
try
{
m_AudioClip.m_AudioData.GetData(m_AudioData);
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 {item.TypeString} \"{m_AudioClip.m_Name}\" to wav..");
sb.AppendLine(m_AudioClip.version < 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}");
debugLog += sb.ToString();
}
var buffer = converter.ConvertToWav(m_AudioData, out var debugLogConverter);
debugLog += debugLogConverter;
if (buffer == null)
{
Logger.Error($"{debugLog}Export error. \"{item.Text}\": Failed to convert fmod audio to Wav");
return false;
}
File.WriteAllBytes(exportFullPath, buffer);
}
else
{
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out exportFullPath))
return false;
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
{
var sb = new StringBuilder();
sb.AppendLine($"Exporting non-fmod {item.TypeString} \"{m_AudioClip.m_Name}\"..");
sb.AppendLine(m_AudioClip.version < 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}");
debugLog += sb.ToString();
}
File.WriteAllBytes(exportFullPath, m_AudioData);
}
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
finally
{
BigArrayPool<byte>.Shared.Return(m_AudioData, clearArray: true);
}
}
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
{
var fileName = FixFileName(item.Text);
var filenameFormat = CLIOptions.o_filenameFormat.Value;
switch (filenameFormat)
{
case FilenameFormat.AssetName_PathID:
fileName = $"{fileName} @{item.m_PathID}";
break;
case FilenameFormat.PathID:
fileName = item.m_PathID.ToString();
break;
}
fullPath = Path.Combine(dir, fileName + extension);
if (savePathHash.TryAdd(fullPath.ToLower(), true) && !File.Exists(fullPath))
{
Directory.CreateDirectory(dir);
return true;
}
if (filenameFormat == FilenameFormat.AssetName)
{
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
if (!File.Exists(fullPath))
{
Directory.CreateDirectory(dir);
return true;
}
}
Logger.Error($"Export error. File \"{fullPath.Color(ColorConsole.BrightRed)}\" already exist");
return false;
}
public static bool ParallelExportConvertFile(AssetItem item, string exportPath, out string debugLog)
{
switch (item.Type)
{
case ClassIDType.Texture2D:
case ClassIDType.Texture2DArrayImage:
return ExportTexture2D(item, exportPath, out debugLog);
case ClassIDType.Sprite:
return ExportSprite(item, exportPath, out debugLog);
case ClassIDType.AudioClip:
return ExportAudioClip(item, exportPath, out debugLog);
default:
throw new NotImplementedException();
}
}
private static string FixFileName(string str)
{
return str.Length >= 260
? Path.GetRandomFileName()
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
}
public static void ClearHash()
{
savePathHash.Clear();
}
}
}

View File

@@ -48,7 +48,7 @@ namespace AssetStudioCLI
case WorkMode.Info: case WorkMode.Info:
Studio.ShowExportableAssetsInfo(); Studio.ShowExportableAssetsInfo();
break; break;
case WorkMode.Live2D: case WorkMode.ExportLive2D:
Studio.ExportLive2D(); Studio.ExportLive2D();
break; break;
case WorkMode.SplitObjects: case WorkMode.SplitObjects:

View File

@@ -1,24 +1,25 @@
## AssetStudioModCLI ## ArknightsStudioCLI
CLI version of AssetStudioMod. CLI version of ArknightsStudio.
- Supported asset types for export: `Texture2D`, `Sprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`. - 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.* - *There are no plans to add support for `AnimationClip`, `Animator` for now.*
### Usage ### Usage
``` ```
AssetStudioModCLI <input path to asset file/folder> [-m, --mode <value>] ArknightsStudioCLI <input path to asset file/folder> [-m, --mode <value>]
[-t, --asset-type <value(s)>] [-g, --group-option <value>] [-t, --asset-type <value(s)>] [-g, --group-option <value>]
[-f, --filename-format <value>] [-o, --output <path>] [-o, --output <path>] [-h, --help]
[-h, --help] [--log-level <value>] [--log-level <value>] [--log-output <value>]
[--log-output <value>] [--image-format <value>] [--image-format <value>] [--audio-format <value>]
[--audio-format <value>] [--l2d-motion-mode <value>] [--l2d-motion-mode <value>] [--l2d-force-bezier]
[--l2d-force-bezier] [--fbx-scale-factor <value>] [--fbx-scale-factor <value>] [--fbx-bone-size <value>]
[--fbx-bone-size <value>] [--filter-by-name <text>] [--filter-by-name <text>] [--filter-by-container <text>]
[--filter-by-container <text>] [--filter-by-pathid <text>] [--filter-by-pathid <text>] [--filter-by-text <text>]
[--filter-by-text <text>] [--custom-compression <value>] [--spritealpha-mode <value>] [--alphatex-resampler <value>]
[--max-export-tasks <value>] [--export-asset-list <value>] [--shadow-gamma <value>] [--original-avg-names]
[--add-aliases] [--export-asset-list <value>]
[--assembly-folder <path>] [--unity-version <text>] [--assembly-folder <path>] [--unity-version <text>]
[--not-restore-extension] [--avoid-typetree-loading] [--not-restore-extension] [--load-all]
[--load-all]
General Options: General Options:
-m, --mode <value> Specify working mode -m, --mode <value> Specify working mode
@@ -27,33 +28,25 @@ General Options:
ExportRaw - Exports raw data ExportRaw - Exports raw data
Dump - Makes asset dumps Dump - Makes asset dumps
Info - Loads file(s), shows the number of available for export assets and exits Info - Loads file(s), shows the number of available for export assets and exits
Live2D - Exports Live2D Cubism models Live2D - Exports Live2D Cubism 3 models
SplitObjects - Exports split objects (fbx) SplitObjects - Exports split objects (fbx)
Example: "-m info" Example: "-m info"
-t, --asset-type <value(s)> Specify asset type(s) to export -t, --asset-type <value(s)> Specify asset type(s) to export
<Value(s): tex2d, tex2dArray, sprite, textAsset, monoBehaviour, font, shader <Value(s): tex2d, sprite, akPortrait, textAsset, monoBehaviour, font, shader,
movieTexture, audio, video, mesh | all(default)> movieTexture, audio, video, mesh | all(default)>
All - export all asset types, which are listed in the values All - export all asset types, which are listed in the values
*To specify multiple asset types, write them separated by ',' or ';' without spaces *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" 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 -g, --group-option <value> Specify the way in which exported assets should be grouped
<Value: none | type | container(default) | containerFull | filename | sceneHierarchy> <Value: none | type | container(default) | containerFull | filename>
None - Do not group exported assets None - Do not group exported assets
Type - Group exported assets by type name Type - Group exported assets by type name
Container - Group exported assets by container path Container - Group exported assets by container path
ContainerFull - Group exported assets by full container path (e.g. with prefab name) ContainerFull - Group exported assets by full container path (e.g. with prefab name)
SceneHierarchy - Group exported assets by their node path in scene hierarchy
Filename - Group exported assets by source file name Filename - Group exported assets by source file name
Example: "-g containerFull" Example: "-g container"
-f, --filename-format <value> Specify the file name format for exported assets
<Value: assetName(default) | assetName_pathID | pathID>
AssetName - Asset file names will look like "assetName.extension"
AssetName_pathID - Asset file names will look like "assetName @pathID.extension"
PathID - Asset file names will look like "pathID.extension"
Example: "-f assetName_pathID"
-o, --output <path> Specify path to the output folder -o, --output <path> Specify path to the output folder
If path isn't specified, 'ASExport' folder will be created in the program's work folder If path isn't specified, 'ASExport' folder will be created in the program's work folder
@@ -75,9 +68,9 @@ Convert Options:
None - Do not convert images and export them as texture data (.tex) None - Do not convert images and export them as texture data (.tex)
Example: "--image-format jpg" Example: "--image-format jpg"
--audio-format <value> Specify the format for converting FMOD audio assets --audio-format <value> Specify the format for converting audio assets
<Value: none | wav(default)> <Value: none | wav(default)>
None - Do not convert fmod audios and export them in their own format None - Do not convert audios and export them in their own format
Example: "--audio-format wav" Example: "--audio-format wav"
Live2D Options: Live2D Options:
@@ -93,11 +86,11 @@ Live2D Options:
FBX Options: FBX Options:
--fbx-scale-factor <value> Specify the FBX Scale Factor --fbx-scale-factor <value> Specify the FBX Scale Factor
<Value: float number from 0 to 100 (default=1)> <Value: float number from 0 to 100 (default=1)
Example: "--fbx-scale-factor 50" Example: "--fbx-scale-factor 50"
--fbx-bone-size <value> Specify the FBX Bone Size --fbx-bone-size <value> Specify the FBX Bone Size
<Value: integer number from 0 to 100 (default=10)> <Value: integer number from 0 to 100 (default=10)
Example: "--fbx-bone-size 10" Example: "--fbx-bone-size 10"
Filter Options: Filter Options:
@@ -119,18 +112,35 @@ Filter Options:
Example: "--filter-by-text portrait" or "--filter-by-text portrait,art" 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 restored
--add-aliases (Flag) If specified, aliases will be added to avg character sprite names (if exist)
Advanced Options: Advanced Options:
--custom-compression <value> Specify the compression type for assets that use custom compression
<Value: zstd(default) | lz4>
Zstd - Try to decompress as zstd archive
Lz4 - Try to decompress as lz4 archive
Example: "--custom-compression lz4"
--max-export-tasks <value> Specify the number of parallel tasks for asset export
<Value: integer number from 1 to max number of cores (default=max)>
Max - Number of cores in your CPU
Example: "--max-export-tasks 8"
--export-asset-list <value> Specify the format in which you want to export asset list --export-asset-list <value> Specify the format in which you want to export asset list
<Value: none(default) | xml> <Value: none(default) | xml>
None - Do not export asset list None - Do not export asset list
@@ -141,12 +151,9 @@ Advanced Options:
--unity-version <text> Specify Unity version --unity-version <text> Specify Unity version
Example: "--unity-version 2017.4.39f1" Example: "--unity-version 2017.4.39f1"
--not-restore-extension (Flag) If specified, AssetStudio will not try to use/restore original TextAsset --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 extension name, and will just export all TextAssets with the ".txt" extension
--avoid-typetree-loading (Flag) If specified, AssetStudio will not try to parse assets at load time --load-all (Flag) If specified, Studio will load assets of all types
using their type tree
--load-all (Flag) If specified, AssetStudio will load assets of all types
(Only for Dump, Info and ExportRaw modes) (Only for Dump, Info and ExportRaw modes)
``` ```

View File

@@ -1,15 +1,12 @@
using AssetStudio; using AssetStudio;
using AssetStudioCLI.Options; using AssetStudioCLI.Options;
using CubismLive2DExtractor;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq; using System.Xml.Linq;
using static AssetStudioCLI.Exporter; using static AssetStudioCLI.Exporter;
using static CubismLive2DExtractor.Live2DExtractor;
using Ansi = AssetStudio.ColorConsole; using Ansi = AssetStudio.ColorConsole;
namespace AssetStudioCLI namespace AssetStudioCLI
@@ -17,10 +14,10 @@ namespace AssetStudioCLI
internal static class Studio internal static class Studio
{ {
public static AssetsManager assetsManager = new AssetsManager(); public static AssetsManager assetsManager = new AssetsManager();
public static List<AssetItem> parsedAssetsList = new List<AssetItem>(); 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 List<BaseNode> gameObjectTree = new List<BaseNode>();
public static AssemblyLoader assemblyLoader = new AssemblyLoader(); public static AssemblyLoader assemblyLoader = new AssemblyLoader();
public static List<MonoBehaviour> cubismMocList = new List<MonoBehaviour>();
private static Dictionary<AssetStudio.Object, string> containers = new Dictionary<AssetStudio.Object, string>(); private static Dictionary<AssetStudio.Object, string> containers = new Dictionary<AssetStudio.Object, string>();
static Studio() static Studio()
@@ -37,8 +34,6 @@ namespace AssetStudioCLI
{ {
var isLoaded = false; var isLoaded = false;
assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value; assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value;
assetsManager.ZstdEnabled = CLIOptions.o_customCompressionType.Value == CustomCompressionType.Zstd;
assetsManager.LoadingViaTypeTreeEnabled = !CLIOptions.f_avoidLoadingViaTypetree.Value;
if (!CLIOptions.f_loadAllAssets.Value) if (!CLIOptions.f_loadAllAssets.Value)
{ {
assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value); assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value);
@@ -60,8 +55,6 @@ namespace AssetStudioCLI
{ {
Logger.Info("Parse assets..."); Logger.Info("Parse assets...");
var fileAssetsList = new List<AssetItem>();
var tex2dArrayAssetList = new List<AssetItem>();
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count); var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
var objectAssetItemDic = new Dictionary<AssetStudio.Object, AssetItem>(objectCount); var objectAssetItemDic = new Dictionary<AssetStudio.Object, AssetItem>(objectCount);
@@ -118,12 +111,6 @@ namespace AssetStudioCLI
assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size; assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size;
assetItem.Text = m_Texture2D.m_Name; assetItem.Text = m_Texture2D.m_Name;
break; break;
case Texture2DArray m_Texture2DArray:
if (!string.IsNullOrEmpty(m_Texture2DArray.m_StreamData?.path))
assetItem.FullSize = asset.byteSize + m_Texture2DArray.m_StreamData.size;
assetItem.Text = m_Texture2DArray.m_Name;
tex2dArrayAssetList.Add(assetItem);
break;
case AudioClip m_AudioClip: case AudioClip m_AudioClip:
if (!string.IsNullOrEmpty(m_AudioClip.m_Source)) if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size; assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
@@ -138,16 +125,14 @@ namespace AssetStudioCLI
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name; assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
break; break;
case MonoBehaviour m_MonoBehaviour: case MonoBehaviour m_MonoBehaviour:
var assetName = m_MonoBehaviour.m_Name; if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{ {
assetName = assetName == "" ? m_Script.m_ClassName : assetName; assetItem.Text = m_Script.m_ClassName;
if (m_Script.m_ClassName == "CubismMoc") }
{ else
cubismMocList.Add(m_MonoBehaviour); {
} assetItem.Text = m_MonoBehaviour.m_Name;
} }
assetItem.Text = assetName;
break; break;
case GameObject m_GameObject: case GameObject m_GameObject:
assetItem.Text = m_GameObject.m_Name; assetItem.Text = m_GameObject.m_Name;
@@ -167,48 +152,45 @@ namespace AssetStudioCLI
assetItem.Text = assetItem.TypeString + assetItem.UniqueID; assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
} }
loadedAssetsList.Add(assetItem);
isExportable = CLIOptions.o_exportAssetTypes.Value.Contains(asset.type); isExportable = CLIOptions.o_exportAssetTypes.Value.Contains(asset.type);
if (isExportable || (CLIOptions.f_loadAllAssets.Value && CLIOptions.o_exportAssetTypes.Value == CLIOptions.o_exportAssetTypes.DefaultValue)) if (isExportable || (CLIOptions.f_loadAllAssets.Value && CLIOptions.o_exportAssetTypes.Value == CLIOptions.o_exportAssetTypes.DefaultValue))
{ {
fileAssetsList.Add(assetItem); exportableAssetsList.Add(assetItem);
} }
Progress.Report(++i, objectCount); Progress.Report(++i, objectCount);
} }
foreach (var asset in fileAssetsList) foreach (var asset in loadedAssetsList)
{ {
if (containers.TryGetValue(asset.Asset, out var container)) if (containers.TryGetValue(asset.Asset, out var container))
{ {
asset.Container = container; asset.Container = container;
if (asset.Type == ClassIDType.MonoBehaviour && container.Contains("/arts/charportraits/portraits"))
{
var portraitsList = Arknights.AkSpriteHelper.GeneratePortraits(asset);
foreach (var portrait in portraitsList)
{
exportableAssetsList.Add(new AssetItem(portrait));
}
}
} }
} }
foreach (var tex2dAssetItem in tex2dArrayAssetList) if (CLIOptions.o_workMode.Value != WorkMode.ExportLive2D)
{
var m_Texture2DArray = (Texture2DArray)tex2dAssetItem.Asset;
for (var layer = 0; layer < m_Texture2DArray.m_Depth; layer++)
{
var fakeObj = new Texture2D(m_Texture2DArray, layer);
m_Texture2DArray.TextureList.Add(fakeObj);
}
}
parsedAssetsList.AddRange(fileAssetsList);
fileAssetsList.Clear();
tex2dArrayAssetList.Clear();
if (CLIOptions.o_workMode.Value != WorkMode.Live2D)
{ {
containers.Clear(); containers.Clear();
} }
} }
if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects || CLIOptions.o_groupAssetsBy.Value == AssetGroupOption.SceneHierarchy) if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects)
{ {
BuildTreeStructure(objectAssetItemDic); BuildTreeStructure(objectAssetItemDic);
} }
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {exportableAssetsList.Count} exportable assets";
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {parsedAssetsList.Count} exportable assets";
var unityVer = assetsManager.assetsFileList[0].version; var unityVer = assetsManager.assetsFileList[0].version;
long m_ObjectsCount; long m_ObjectsCount;
if (unityVer > 2020) if (unityVer[0] > 2020)
{ {
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y =>
y.classID != (int)ClassIDType.Shader y.classID != (int)ClassIDType.Shader
@@ -237,7 +219,7 @@ namespace AssetStudioCLI
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
{ {
var fileNode = new BaseNode(assetsFile.fileName); //RootNode var fileNode = new BaseNode(); //RootNode
foreach (var obj in assetsFile.Objects) foreach (var obj in assetsFile.Objects)
{ {
@@ -272,6 +254,7 @@ namespace AssetStudioCLI
} }
var parentNode = fileNode; var parentNode = fileNode;
if (m_GameObject.m_Transform != null) if (m_GameObject.m_Transform != null)
{ {
if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father)) if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
@@ -287,13 +270,14 @@ namespace AssetStudioCLI
} }
} }
} }
parentNode.nodes.Add(currentNode); parentNode.nodes.Add(currentNode);
} }
} }
if (fileNode.nodes.Count > 0) if (fileNode.nodes.Count > 0)
{ {
GenerateFullPath(fileNode, fileNode.Text);
gameObjectTree.Add(fileNode); gameObjectTree.Add(fileNode);
} }
@@ -304,29 +288,13 @@ namespace AssetStudioCLI
objectAssetItemDic.Clear(); objectAssetItemDic.Clear();
} }
private static void GenerateFullPath(BaseNode treeNode, string path)
{
treeNode.FullPath = path;
foreach (var node in treeNode.nodes)
{
if (node.nodes.Count > 0)
{
GenerateFullPath(node, Path.Combine(path, node.Text));
}
else
{
node.FullPath = Path.Combine(path, node.Text);
}
}
}
public static void ShowExportableAssetsInfo() public static void ShowExportableAssetsInfo()
{ {
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>(); var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
string info = ""; string info = "";
if (parsedAssetsList.Count > 0) if (exportableAssetsList.Count > 0)
{ {
foreach (var asset in parsedAssetsList) foreach (var asset in exportableAssetsList)
{ {
if (exportableAssetsCountDict.ContainsKey(asset.Type)) if (exportableAssetsCountDict.ContainsKey(asset.Type))
{ {
@@ -345,7 +313,7 @@ namespace AssetStudioCLI
} }
if (exportableAssetsCountDict.Count > 1) if (exportableAssetsCountDict.Count > 1)
{ {
info += $"#\n# Total: {parsedAssetsList.Count} assets"; info += $"#\n# Total: {exportableAssetsList.Count} assets";
} }
} }
else else
@@ -367,7 +335,7 @@ namespace AssetStudioCLI
{ {
switch (CLIOptions.o_workMode.Value) switch (CLIOptions.o_workMode.Value)
{ {
case WorkMode.Live2D: case WorkMode.ExportLive2D:
case WorkMode.SplitObjects: case WorkMode.SplitObjects:
break; break;
default: default:
@@ -378,34 +346,34 @@ namespace AssetStudioCLI
private static void FilterAssets() private static void FilterAssets()
{ {
var assetsCount = parsedAssetsList.Count; var assetsCount = exportableAssetsList.Count;
var filteredAssets = new List<AssetItem>(); var filteredAssets = new List<AssetItem>();
switch(CLIOptions.filterBy) switch(CLIOptions.filterBy)
{ {
case FilterBy.Name: case FilterBy.Name:
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)); filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
Logger.Info( Logger.Info(
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " + $"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names." $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
); );
break; break;
case FilterBy.Container: case FilterBy.Container:
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)); filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
Logger.Info( Logger.Info(
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " + $"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers." $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
); );
break; break;
case FilterBy.PathID: case FilterBy.PathID:
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByPathID.Value.Any(y => x.m_PathID.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)); filteredAssets = exportableAssetsList.FindAll(x => CLIOptions.o_filterByPathID.Value.Any(y => x.m_PathID.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
Logger.Info( Logger.Info(
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " + $"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs." $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByPathID.Value)}\"".Color(Ansi.BrightYellow)} in their PathIDs."
); );
break; break;
case FilterBy.NameOrContainer: case FilterBy.NameOrContainer:
filteredAssets = parsedAssetsList.FindAll(x => filteredAssets = exportableAssetsList.FindAll(x =>
CLIOptions.o_filterByText.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) || 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) CLIOptions.o_filterByText.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
); );
@@ -415,7 +383,7 @@ namespace AssetStudioCLI
); );
break; break;
case FilterBy.NameAndContainer: case FilterBy.NameAndContainer:
filteredAssets = parsedAssetsList.FindAll(x => filteredAssets = exportableAssetsList.FindAll(x =>
CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) && 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) CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0)
); );
@@ -426,21 +394,18 @@ namespace AssetStudioCLI
); );
break; break;
} }
parsedAssetsList.Clear(); exportableAssetsList.Clear();
parsedAssetsList = filteredAssets; exportableAssetsList = filteredAssets;
} }
public static void ExportAssets() public static void ExportAssets()
{ {
var savePath = CLIOptions.o_outputFolder.Value; var savePath = CLIOptions.o_outputFolder.Value;
var toExportCount = parsedAssetsList.Count; var toExportCount = exportableAssetsList.Count;
var exportedCount = 0; var exportedCount = 0;
var groupOption = CLIOptions.o_groupAssetsBy.Value; var groupOption = CLIOptions.o_groupAssetsBy.Value;
var parallelExportCount = CLIOptions.o_maxParallelExportTasks.Value; foreach (var asset in exportableAssetsList)
var toExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
var toParallelExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
Parallel.ForEach(parsedAssetsList, asset =>
{ {
string exportPath; string exportPath;
switch (groupOption) switch (groupOption)
@@ -473,75 +438,36 @@ namespace AssetStudioCLI
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName); exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
} }
break; break;
case AssetGroupOption.SceneHierarchy:
if (asset.Node != null)
{
exportPath = Path.Combine(savePath, asset.Node.FullPath);
}
else
{
exportPath = Path.Combine(savePath, "_sceneRoot", asset.TypeString);
}
break;
default: default:
exportPath = savePath; exportPath = savePath;
break; break;
} }
exportPath += Path.DirectorySeparatorChar; exportPath += Path.DirectorySeparatorChar;
if (CLIOptions.o_workMode.Value == WorkMode.Export)
{
switch (asset.Type)
{
case ClassIDType.Texture2D:
case ClassIDType.Sprite:
case ClassIDType.AudioClip:
toParallelExportAssetDict.TryAdd(asset, exportPath);
break;
case ClassIDType.Texture2DArray:
var m_Texture2DArray = (Texture2DArray)asset.Asset;
toExportCount += m_Texture2DArray.TextureList.Count - 1;
foreach (var texture in m_Texture2DArray.TextureList)
{
var fakeItem = new AssetItem(texture)
{
Text = texture.m_Name,
Container = asset.Container,
};
toParallelExportAssetDict.TryAdd(fakeItem, exportPath);
}
break;
default:
toExportAssetDict.TryAdd(asset, exportPath);
break;
}
}
else
{
toExportAssetDict.TryAdd(asset, exportPath);
}
});
foreach (var toExportAsset in toExportAssetDict)
{
var asset = toExportAsset.Key;
var exportPath = toExportAsset.Value;
var isExported = false;
try try
{ {
switch (CLIOptions.o_workMode.Value) switch (CLIOptions.o_workMode.Value)
{ {
case WorkMode.ExportRaw: case WorkMode.ExportRaw:
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}"); Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
isExported = ExportRawFile(asset, exportPath); if (ExportRawFile(asset, exportPath))
{
exportedCount++;
}
break; break;
case WorkMode.Dump: case WorkMode.Dump:
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}"); Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
isExported = ExportDumpFile(asset, exportPath); if (ExportDumpFile(asset, exportPath))
{
exportedCount++;
}
break; break;
case WorkMode.Export: case WorkMode.Export:
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}"); Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
isExported = ExportConvertFile(asset, exportPath); if (ExportConvertFile(asset, exportPath))
{
exportedCount++;
}
break; break;
} }
} }
@@ -549,33 +475,8 @@ namespace AssetStudioCLI
{ {
Logger.Error($"{asset.SourceFile.originalPath}: [{$"{asset.Type}: {asset.Text}".Color(Ansi.BrightRed)}] : Export error\n{ex}"); Logger.Error($"{asset.SourceFile.originalPath}: [{$"{asset.Type}: {asset.Text}".Color(Ansi.BrightRed)}] : Export error\n{ex}");
} }
if (isExported)
{
exportedCount++;
}
Console.Write($"Exported [{exportedCount}/{toExportCount}]\r"); Console.Write($"Exported [{exportedCount}/{toExportCount}]\r");
} }
Parallel.ForEach(toParallelExportAssetDict, new ParallelOptions { MaxDegreeOfParallelism = parallelExportCount }, toExportAsset =>
{
var asset = toExportAsset.Key;
var exportPath = toExportAsset.Value;
try
{
if (ParallelExporter.ParallelExportConvertFile(asset, exportPath, out var debugLog))
{
Interlocked.Increment(ref exportedCount);
Logger.Debug(debugLog);
Console.Write($"Exported [{exportedCount}/{toExportCount}]\r");
}
}
catch (Exception ex)
{
Logger.Error($"{asset.SourceFile.originalPath}: [{$"{asset.Type}: {asset.Text}".Color(Ansi.BrightRed)}] : Export error\n{ex}");
}
});
ParallelExporter.ClearHash();
Console.WriteLine(""); Console.WriteLine("");
if (exportedCount == 0) if (exportedCount == 0)
@@ -609,14 +510,13 @@ namespace AssetStudioCLI
new XElement("Assets", new XElement("Assets",
new XAttribute("filename", filename), new XAttribute("filename", filename),
new XAttribute("createdAt", DateTime.UtcNow.ToString("s")), new XAttribute("createdAt", DateTime.UtcNow.ToString("s")),
parsedAssetsList.Select( exportableAssetsList.Select(
asset => new XElement("Asset", asset => new XElement("Asset",
new XElement("Name", asset.Text), new XElement("Name", asset.Text),
new XElement("Container", asset.Container), new XElement("Container", asset.Container),
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString), new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
new XElement("PathID", asset.m_PathID), new XElement("PathID", asset.m_PathID),
new XElement("Source", asset.SourceFile.fullName), new XElement("Source", asset.SourceFile.fullName),
new XElement("TreeNode", asset.Node != null ? asset.Node.FullPath : ""),
new XElement("Size", asset.FullSize) new XElement("Size", asset.FullSize)
) )
) )
@@ -626,7 +526,7 @@ namespace AssetStudioCLI
break; break;
} }
Logger.Info($"Finished exporting asset list with {parsedAssetsList.Count} items."); Logger.Info($"Finished exporting asset list with {exportableAssetsList.Count} items.");
} }
public static void ExportSplitObjects() public static void ExportSplitObjects()
@@ -648,7 +548,7 @@ namespace AssetStudioCLI
{ {
if (isFiltered) if (isFiltered)
{ {
if (!searchList.Any(searchText => j.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0)) if (!searchList.Any(searchText => j.gameObject.m_Name.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
continue; continue;
} }
var gameObjects = new List<GameObject>(); var gameObjects = new List<GameObject>();
@@ -727,60 +627,66 @@ namespace AssetStudioCLI
public static void ExportLive2D() public static void ExportLive2D()
{ {
var baseDestPath = Path.Combine(CLIOptions.o_outputFolder.Value, "Live2DOutput"); var baseDestPath = Path.Combine(CLIOptions.o_outputFolder.Value, "Live2DOutput");
var useFullContainerPath = true; var useFullContainerPath = false;
var mocPathList = new List<string>();
var basePathSet = new HashSet<string>();
var motionMode = CLIOptions.o_l2dMotionMode.Value; var motionMode = CLIOptions.o_l2dMotionMode.Value;
var forceBezier = CLIOptions.f_l2dForceBezier.Value; var forceBezier = CLIOptions.f_l2dForceBezier.Value;
if (cubismMocList.Count == 0)
{
Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
return;
}
Progress.Reset(); Progress.Reset();
Logger.Info($"Searching for Live2D files..."); Logger.Info($"Searching for Live2D files...");
foreach (var mocMonoBehaviour in cubismMocList) var cubismMocs = exportableAssetsList.Where(x =>
{ {
if (!containers.TryGetValue(mocMonoBehaviour, out var fullContainerPath)) if (x.Type == ClassIDType.MonoBehaviour)
continue; {
((MonoBehaviour)x.Asset).m_Script.TryGet(out var m_Script);
return m_Script?.m_ClassName == "CubismMoc";
}
return false;
}).Select(x => x.Asset).ToArray();
var pathSepIndex = fullContainerPath.LastIndexOf('/'); if (cubismMocs.Length == 0)
var basePath = pathSepIndex > 0
? fullContainerPath.Substring(0, pathSepIndex)
: fullContainerPath;
basePathSet.Add(basePath);
mocPathList.Add(fullContainerPath);
}
if (mocPathList.Count == 0)
{ {
Logger.Error("Live2D Cubism export error: Cannot find any model related files."); Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
return; return;
} }
if (basePathSet.Count == mocPathList.Count) if (cubismMocs.Length > 1)
{ {
mocPathList = basePathSet.ToList(); var basePathSet = cubismMocs.Select(x =>
useFullContainerPath = false; {
Logger.Debug($"useFullContainerPath: {useFullContainerPath}"); var pathLen = containers.TryGetValue(x, out var itemContainer) ? itemContainer.LastIndexOf("/") : 0;
} pathLen = pathLen < 0 ? containers[x].Length : pathLen;
basePathSet.Clear(); return itemContainer?.Substring(0, pathLen);
}).ToHashSet();
var lookup = containers.AsParallel().ToLookup( if (basePathSet.All(x => x == null))
x => mocPathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))), {
Logger.Error($"Live2D Cubism export error: Cannot find any model related files.");
return;
}
if (basePathSet.Count != cubismMocs.Length)
{
useFullContainerPath = true;
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
}
}
var basePathList = cubismMocs.Select(x =>
{
containers.TryGetValue(x, out var container);
container = useFullContainerPath
? container
: container?.Substring(0, container.LastIndexOf("/"));
return container;
}).Where(x => x != null).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 x => x.Key
); );
if (cubismMocList[0].serializedType?.m_Type == null && CLIOptions.o_assemblyPath.Value == "")
{
Logger.Warning("Specifying the assembly folder may be needed for proper extraction");
}
var totalModelCount = lookup.LongCount(x => x.Key != null); var totalModelCount = lookup.LongCount(x => x.Key != null);
Logger.Info($"Found {totalModelCount} model(s)."); Logger.Info($"Found {totalModelCount} model(s).");
var parallelTaskCount = CLIOptions.o_maxParallelExportTasks.Value;
var modelCounter = 0; var modelCounter = 0;
foreach (var assets in lookup) foreach (var assets in lookup)
{ {
@@ -792,16 +698,11 @@ namespace AssetStudioCLI
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer.Color(Ansi.BrightCyan)}\""); Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer.Color(Ansi.BrightCyan)}\"");
try try
{ {
var modelName = useFullContainerPath var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
? Path.GetFileNameWithoutExtension(container) container = Path.HasExtension(container) ? container.Replace(Path.GetExtension(container), "") : container;
: container.Substring(container.LastIndexOf('/') + 1);
container = Path.HasExtension(container)
? container.Replace(Path.GetExtension(container), "")
: container;
var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar; var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar;
var modelExtractor = new Live2DExtractor(assets); ExtractLive2D(assets, destPath, modelName, assemblyLoader, motionMode, forceBezier);
modelExtractor.ExtractCubismModel(destPath, modelName, motionMode, assemblyLoader, forceBezier, parallelTaskCount);
modelCounter++; modelCounter++;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright> <Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>

View File

@@ -49,7 +49,7 @@
this.label7 = new System.Windows.Forms.Label(); this.label7 = new System.Windows.Forms.Label();
this.modVersionLabel = new System.Windows.Forms.Label(); this.modVersionLabel = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label(); this.label4 = new System.Windows.Forms.Label();
this.label8 = new System.Windows.Forms.Label(); this.basedOnLabel = new System.Windows.Forms.Label();
this.checkUpdatesLinkLabel = new System.Windows.Forms.LinkLabel(); this.checkUpdatesLinkLabel = new System.Windows.Forms.LinkLabel();
this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabPage2 = new System.Windows.Forms.TabPage();
this.licenseRichTextBox = new System.Windows.Forms.RichTextBox(); this.licenseRichTextBox = new System.Windows.Forms.RichTextBox();
@@ -116,8 +116,7 @@
this.label2.Name = "label2"; this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(347, 46); this.label2.Size = new System.Drawing.Size(347, 46);
this.label2.TabIndex = 0; this.label2.TabIndex = 0;
this.label2.Text = "AssetStudio is a tool for exploring, extracting, and exporting assets and asset b" + this.label2.Text = "ArknightsStudio is a modified version of AssetStudio designed for Arknights.";
"undles.";
this.label2.UseCompatibleTextRendering = true; this.label2.UseCompatibleTextRendering = true;
// //
// textBox2 // textBox2
@@ -164,7 +163,7 @@
this.tableLayoutPanel2.ColumnCount = 3; 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, 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.Percent, 58.62069F));
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 112F)); 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.label16, 0, 0);
this.tableLayoutPanel2.Controls.Add(this.label17, 1, 0); this.tableLayoutPanel2.Controls.Add(this.label17, 1, 0);
this.tableLayoutPanel2.Controls.Add(this.gitPerfareLinkLabel, 2, 0); this.tableLayoutPanel2.Controls.Add(this.gitPerfareLinkLabel, 2, 0);
@@ -204,7 +203,7 @@
// //
this.gitPerfareLinkLabel.AutoSize = true; this.gitPerfareLinkLabel.AutoSize = true;
this.gitPerfareLinkLabel.BackColor = System.Drawing.Color.Transparent; this.gitPerfareLinkLabel.BackColor = System.Drawing.Color.Transparent;
this.gitPerfareLinkLabel.Location = new System.Drawing.Point(238, 2); this.gitPerfareLinkLabel.Location = new System.Drawing.Point(237, 2);
this.gitPerfareLinkLabel.Name = "gitPerfareLinkLabel"; this.gitPerfareLinkLabel.Name = "gitPerfareLinkLabel";
this.gitPerfareLinkLabel.Size = new System.Drawing.Size(67, 13); this.gitPerfareLinkLabel.Size = new System.Drawing.Size(67, 13);
this.gitPerfareLinkLabel.TabIndex = 11; this.gitPerfareLinkLabel.TabIndex = 11;
@@ -230,13 +229,13 @@
this.label19.Name = "label19"; this.label19.Name = "label19";
this.label19.Size = new System.Drawing.Size(113, 13); this.label19.Size = new System.Drawing.Size(113, 13);
this.label19.TabIndex = 13; this.label19.TabIndex = 13;
this.label19.Text = "aelurum (c) 2021-2024"; this.label19.Text = "aelurum (c) 2021-2023";
// //
// gitAelurumLinkLabel // gitAelurumLinkLabel
// //
this.gitAelurumLinkLabel.AutoSize = true; this.gitAelurumLinkLabel.AutoSize = true;
this.gitAelurumLinkLabel.BackColor = System.Drawing.Color.Transparent; this.gitAelurumLinkLabel.BackColor = System.Drawing.Color.Transparent;
this.gitAelurumLinkLabel.Location = new System.Drawing.Point(238, 20); this.gitAelurumLinkLabel.Location = new System.Drawing.Point(237, 20);
this.gitAelurumLinkLabel.Name = "gitAelurumLinkLabel"; this.gitAelurumLinkLabel.Name = "gitAelurumLinkLabel";
this.gitAelurumLinkLabel.Size = new System.Drawing.Size(67, 13); this.gitAelurumLinkLabel.Size = new System.Drawing.Size(67, 13);
this.gitAelurumLinkLabel.TabIndex = 14; this.gitAelurumLinkLabel.TabIndex = 14;
@@ -250,13 +249,13 @@
this.tableLayoutPanel1.ColumnCount = 3; 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, 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.Percent, 58.62069F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 112F)); 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.label5, 0, 0);
this.tableLayoutPanel1.Controls.Add(this.productNamelabel, 1, 0); this.tableLayoutPanel1.Controls.Add(this.productNamelabel, 1, 0);
this.tableLayoutPanel1.Controls.Add(this.label7, 0, 1); this.tableLayoutPanel1.Controls.Add(this.label7, 0, 1);
this.tableLayoutPanel1.Controls.Add(this.modVersionLabel, 1, 1); this.tableLayoutPanel1.Controls.Add(this.modVersionLabel, 1, 1);
this.tableLayoutPanel1.Controls.Add(this.label4, 0, 2); this.tableLayoutPanel1.Controls.Add(this.label4, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.label8, 1, 2); this.tableLayoutPanel1.Controls.Add(this.basedOnLabel, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.checkUpdatesLinkLabel, 2, 1); this.tableLayoutPanel1.Controls.Add(this.checkUpdatesLinkLabel, 2, 1);
this.tableLayoutPanel1.Location = new System.Drawing.Point(6, 80); this.tableLayoutPanel1.Location = new System.Drawing.Point(6, 80);
this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Name = "tableLayoutPanel1";
@@ -287,9 +286,9 @@
this.productNamelabel.BackColor = System.Drawing.Color.Transparent; this.productNamelabel.BackColor = System.Drawing.Color.Transparent;
this.productNamelabel.Location = new System.Drawing.Point(101, 2); this.productNamelabel.Location = new System.Drawing.Point(101, 2);
this.productNamelabel.Name = "productNamelabel"; this.productNamelabel.Name = "productNamelabel";
this.productNamelabel.Size = new System.Drawing.Size(103, 13); this.productNamelabel.Size = new System.Drawing.Size(100, 13);
this.productNamelabel.TabIndex = 1; this.productNamelabel.TabIndex = 1;
this.productNamelabel.Text = "AssetStudioModGUI"; this.productNamelabel.Text = "ArknightsStudioGUI";
// //
// label7 // label7
// //
@@ -297,9 +296,9 @@
this.label7.BackColor = System.Drawing.Color.Transparent; this.label7.BackColor = System.Drawing.Color.Transparent;
this.label7.Location = new System.Drawing.Point(5, 20); this.label7.Location = new System.Drawing.Point(5, 20);
this.label7.Name = "label7"; this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(68, 13); this.label7.Size = new System.Drawing.Size(45, 13);
this.label7.TabIndex = 2; this.label7.TabIndex = 2;
this.label7.Text = "Mod version:"; this.label7.Text = "Version:";
// //
// modVersionLabel // modVersionLabel
// //
@@ -308,9 +307,9 @@
this.modVersionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 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.Location = new System.Drawing.Point(101, 20);
this.modVersionLabel.Name = "modVersionLabel"; this.modVersionLabel.Name = "modVersionLabel";
this.modVersionLabel.Size = new System.Drawing.Size(46, 13); this.modVersionLabel.Size = new System.Drawing.Size(52, 13);
this.modVersionLabel.TabIndex = 3; this.modVersionLabel.TabIndex = 3;
this.modVersionLabel.Text = "0.18.0.0"; this.modVersionLabel.Text = "0.16.48.1";
// //
// label4 // label4
// //
@@ -323,21 +322,21 @@
this.label4.TabIndex = 4; this.label4.TabIndex = 4;
this.label4.Text = "Based on:"; this.label4.Text = "Based on:";
// //
// label8 // basedOnLabel
// //
this.label8.AutoSize = true; this.basedOnLabel.AutoSize = true;
this.label8.BackColor = System.Drawing.Color.Transparent; this.basedOnLabel.BackColor = System.Drawing.Color.Transparent;
this.label8.Location = new System.Drawing.Point(101, 38); this.basedOnLabel.Location = new System.Drawing.Point(101, 38);
this.label8.Name = "label8"; this.basedOnLabel.Name = "basedOnLabel";
this.label8.Size = new System.Drawing.Size(108, 13); this.basedOnLabel.Size = new System.Drawing.Size(123, 13);
this.label8.TabIndex = 5; this.basedOnLabel.TabIndex = 5;
this.label8.Text = "AssetStudio v0.16.47"; this.basedOnLabel.Text = "AssetStudioMod v0.17.0";
// //
// checkUpdatesLinkLabel // checkUpdatesLinkLabel
// //
this.checkUpdatesLinkLabel.AutoSize = true; this.checkUpdatesLinkLabel.AutoSize = true;
this.checkUpdatesLinkLabel.BackColor = System.Drawing.Color.Transparent; this.checkUpdatesLinkLabel.BackColor = System.Drawing.Color.Transparent;
this.checkUpdatesLinkLabel.Location = new System.Drawing.Point(238, 20); this.checkUpdatesLinkLabel.Location = new System.Drawing.Point(237, 20);
this.checkUpdatesLinkLabel.Name = "checkUpdatesLinkLabel"; this.checkUpdatesLinkLabel.Name = "checkUpdatesLinkLabel";
this.checkUpdatesLinkLabel.Size = new System.Drawing.Size(96, 13); this.checkUpdatesLinkLabel.Size = new System.Drawing.Size(96, 13);
this.checkUpdatesLinkLabel.TabIndex = 6; this.checkUpdatesLinkLabel.TabIndex = 6;
@@ -391,7 +390,7 @@
this.productTitleLabel.Name = "productTitleLabel"; this.productTitleLabel.Name = "productTitleLabel";
this.productTitleLabel.Size = new System.Drawing.Size(384, 30); this.productTitleLabel.Size = new System.Drawing.Size(384, 30);
this.productTitleLabel.TabIndex = 1; this.productTitleLabel.TabIndex = 1;
this.productTitleLabel.Text = "AssetStudioModGUI"; this.productTitleLabel.Text = "ArknightsStudioGUI";
this.productTitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; this.productTitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
// //
// CloseButton // CloseButton
@@ -414,7 +413,7 @@
this.productVersionLabel.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0); this.productVersionLabel.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0);
this.productVersionLabel.Size = new System.Drawing.Size(384, 13); this.productVersionLabel.Size = new System.Drawing.Size(384, 13);
this.productVersionLabel.TabIndex = 2; this.productVersionLabel.TabIndex = 2;
this.productVersionLabel.Text = "v0.18.0.0 [x64]"; this.productVersionLabel.Text = "v0.16.48.1 [x64]";
this.productVersionLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter; this.productVersionLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
// //
// panel2 // panel2
@@ -492,7 +491,7 @@
private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label modVersionLabel; private System.Windows.Forms.Label modVersionLabel;
private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label8; private System.Windows.Forms.Label basedOnLabel;
private System.Windows.Forms.LinkLabel checkUpdatesLinkLabel; private System.Windows.Forms.LinkLabel checkUpdatesLinkLabel;
private System.Windows.Forms.RichTextBox licenseRichTextBox; private System.Windows.Forms.RichTextBox licenseRichTextBox;
private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.TextBox textBox2;

View File

@@ -19,6 +19,7 @@ namespace AssetStudioGUI
productVersionLabel.Text = $"v{productVer} [{arch}]"; productVersionLabel.Text = $"v{productVer} [{arch}]";
productNamelabel.Text = productName; productNamelabel.Text = productName;
modVersionLabel.Text = productVer; modVersionLabel.Text = productVer;
basedOnLabel.Text = "AssetStudioMod v0.17.4";
licenseRichTextBox.Text = GetLicenseText(); licenseRichTextBox.Text = GetLicenseText();
} }
@@ -43,7 +44,7 @@ namespace AssetStudioGUI
private void checkUpdatesLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) private void checkUpdatesLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{ {
var ps = new ProcessStartInfo("https://github.com/aelurum/AssetStudio/releases") var ps = new ProcessStartInfo("https://github.com/aelurum/AssetStudio/tags")
{ {
UseShellExecute = true UseShellExecute = true
}; };

View File

@@ -5,10 +5,10 @@
<TargetFrameworks>net472;net6.0-windows;net7.0-windows;net8.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0-windows;net7.0-windows;net8.0-windows</TargetFrameworks>
<UseWindowsForms>true</UseWindowsForms> <UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>Resources\as.ico</ApplicationIcon> <ApplicationIcon>Resources\as.ico</ApplicationIcon>
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle> <AssemblyTitle>ArknightsStudio by aelurum</AssemblyTitle>
<AssemblyName>AssetStudioModGUI</AssemblyName> <AssemblyName>ArknightsStudioGUI</AssemblyName>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2024</Copyright> <Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2025</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>

View File

@@ -39,14 +39,14 @@
this.extractFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.extractFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.displayAll = new System.Windows.Forms.ToolStripMenuItem(); this.displayAll = new System.Windows.Forms.ToolStripMenuItem();
this.useAssetLoadingViaTypetreeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.assetLoadingToolStripSeparator = new System.Windows.Forms.ToolStripSeparator();
this.enablePreview = new System.Windows.Forms.ToolStripMenuItem(); this.enablePreview = new System.Windows.Forms.ToolStripMenuItem();
this.displayInfo = 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.buildTreeStructureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.buildTreeStructureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.customCompressionTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.customCompressionZstdToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.customCompressionLZ4ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem14 = new System.Windows.Forms.ToolStripMenuItem();
this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox(); this.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();
this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem(); this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem();
@@ -73,12 +73,7 @@
this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
this.live2DCubismModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.allLive2DModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.allL2DModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.selectedL2DModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.l2DModelWithFadeListToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.l2DModelWithFadeMotionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.l2DModelWithClipsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem();
@@ -87,8 +82,8 @@
this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.allToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.debugMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.showConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem15 = new System.Windows.Forms.ToolStripMenuItem();
this.showConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.writeLogToFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.writeLogToFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -116,7 +111,7 @@
this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.progressBar1 = new System.Windows.Forms.ProgressBar();
this.tabControl2 = new System.Windows.Forms.TabControl(); this.tabControl2 = new System.Windows.Forms.TabControl();
this.tabPage4 = new System.Windows.Forms.TabPage(); this.tabPage4 = new System.Windows.Forms.TabPage();
this.previewPanel = new System.Windows.Forms.PictureBox(); this.previewPanel = new System.Windows.Forms.Panel();
this.assetInfoLabel = new System.Windows.Forms.Label(); this.assetInfoLabel = new System.Windows.Forms.Label();
this.FMODpanel = new System.Windows.Forms.Panel(); this.FMODpanel = new System.Windows.Forms.Panel();
this.FMODcopyright = new System.Windows.Forms.Label(); this.FMODcopyright = new System.Windows.Forms.Label();
@@ -150,12 +145,8 @@
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exportSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.dumpSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.dumpSelectedAssetsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAnimatorWithSelectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportAsLive2DModelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportL2DWithFadeLstToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportL2DWithFadeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exportL2DWithClipsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuStrip1.SuspendLayout(); this.menuStrip1.SuspendLayout();
@@ -171,7 +162,6 @@
this.progressbarPanel.SuspendLayout(); this.progressbarPanel.SuspendLayout();
this.tabControl2.SuspendLayout(); this.tabControl2.SuspendLayout();
this.tabPage4.SuspendLayout(); this.tabPage4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.previewPanel)).BeginInit();
this.previewPanel.SuspendLayout(); this.previewPanel.SuspendLayout();
this.FMODpanel.SuspendLayout(); this.FMODpanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.FMODprogressBar)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.FMODprogressBar)).BeginInit();
@@ -247,12 +237,14 @@
// //
this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.displayAll, this.displayAll,
this.useAssetLoadingViaTypetreeToolStripMenuItem,
this.assetLoadingToolStripSeparator,
this.enablePreview, this.enablePreview,
this.displayInfo, this.displayInfo,
this.akSeparator1,
this.akTitleMenuItem,
this.akFixFaceSpriteNamesToolStripMenuItem,
this.akUseExternalAlphaToolStripMenuItem,
this.akSeparator2,
this.buildTreeStructureToolStripMenuItem, this.buildTreeStructureToolStripMenuItem,
this.customCompressionTypeToolStripMenuItem,
this.toolStripMenuItem14, this.toolStripMenuItem14,
this.showExpOpt}); this.showExpOpt});
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem"; this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
@@ -263,36 +255,19 @@
// //
this.displayAll.CheckOnClick = true; this.displayAll.CheckOnClick = true;
this.displayAll.Name = "displayAll"; this.displayAll.Name = "displayAll";
this.displayAll.Size = new System.Drawing.Size(241, 22); this.displayAll.Size = new System.Drawing.Size(276, 22);
this.displayAll.Text = "Display all assets"; this.displayAll.Text = "Display all assets";
this.displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can expor" + this.displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can expor" +
"t the RAW file."; "t the RAW file.";
this.displayAll.CheckedChanged += new System.EventHandler(this.displayAll_CheckedChanged); this.displayAll.CheckedChanged += new System.EventHandler(this.displayAll_CheckedChanged);
// //
// useAssetLoadingViaTypetreeToolStripMenuItem
//
this.useAssetLoadingViaTypetreeToolStripMenuItem.Checked = true;
this.useAssetLoadingViaTypetreeToolStripMenuItem.CheckOnClick = true;
this.useAssetLoadingViaTypetreeToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.useAssetLoadingViaTypetreeToolStripMenuItem.Name = "useAssetLoadingViaTypetreeToolStripMenuItem";
this.useAssetLoadingViaTypetreeToolStripMenuItem.Size = new System.Drawing.Size(241, 22);
this.useAssetLoadingViaTypetreeToolStripMenuItem.Text = "Parse assets using their typetree";
this.useAssetLoadingViaTypetreeToolStripMenuItem.ToolTipText = "(Applies to assets with typetree included). Slower but more correct parsing. Only" +
" for Texture2D and AnimationClip assets for now.";
this.useAssetLoadingViaTypetreeToolStripMenuItem.CheckedChanged += new System.EventHandler(this.useAssetLoadingViaTypetreeToolStripMenuItem_CheckedChanged);
//
// assetLoadingToolStripSeparator
//
this.assetLoadingToolStripSeparator.Name = "assetLoadingToolStripSeparator";
this.assetLoadingToolStripSeparator.Size = new System.Drawing.Size(238, 6);
//
// enablePreview // enablePreview
// //
this.enablePreview.Checked = true; this.enablePreview.Checked = true;
this.enablePreview.CheckOnClick = true; this.enablePreview.CheckOnClick = true;
this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked; this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked;
this.enablePreview.Name = "enablePreview"; this.enablePreview.Name = "enablePreview";
this.enablePreview.Size = new System.Drawing.Size(241, 22); this.enablePreview.Size = new System.Drawing.Size(276, 22);
this.enablePreview.Text = "Enable preview"; this.enablePreview.Text = "Enable preview";
this.enablePreview.ToolTipText = "Toggle the loading and preview of readable assets, such as images, sounds, text, " + 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."; "etc.\r\nDisable preview if you have performance or compatibility issues.";
@@ -304,62 +279,72 @@
this.displayInfo.CheckOnClick = true; this.displayInfo.CheckOnClick = true;
this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked; this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;
this.displayInfo.Name = "displayInfo"; this.displayInfo.Name = "displayInfo";
this.displayInfo.Size = new System.Drawing.Size(241, 22); this.displayInfo.Size = new System.Drawing.Size(276, 22);
this.displayInfo.Text = "Display asset information"; this.displayInfo.Text = "Display asset information";
this.displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, forma" + this.displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, forma" +
"t, audio bitrate, etc."; "t, audio bitrate, etc.";
this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check); this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check);
// //
// akSeparator1
//
this.akSeparator1.Name = "akSeparator1";
this.akSeparator1.Size = new System.Drawing.Size(273, 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(276, 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(276, 22);
this.akFixFaceSpriteNamesToolStripMenuItem.Text = "Restore 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(276, 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(273, 6);
//
// buildTreeStructureToolStripMenuItem // buildTreeStructureToolStripMenuItem
// //
this.buildTreeStructureToolStripMenuItem.Checked = true; this.buildTreeStructureToolStripMenuItem.Checked = true;
this.buildTreeStructureToolStripMenuItem.CheckOnClick = true; this.buildTreeStructureToolStripMenuItem.CheckOnClick = true;
this.buildTreeStructureToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.buildTreeStructureToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.buildTreeStructureToolStripMenuItem.Name = "buildTreeStructureToolStripMenuItem"; this.buildTreeStructureToolStripMenuItem.Name = "buildTreeStructureToolStripMenuItem";
this.buildTreeStructureToolStripMenuItem.Size = new System.Drawing.Size(241, 22); this.buildTreeStructureToolStripMenuItem.Size = new System.Drawing.Size(276, 22);
this.buildTreeStructureToolStripMenuItem.Text = "Build tree structure"; this.buildTreeStructureToolStripMenuItem.Text = "Build tree structure";
this.buildTreeStructureToolStripMenuItem.ToolTipText = "You can disable tree structure building if you don\'t use the Scene Hierarchy tab"; this.buildTreeStructureToolStripMenuItem.ToolTipText = "You can disable tree structure building if you don\'t use the Scene Hierarchy tab";
this.buildTreeStructureToolStripMenuItem.CheckedChanged += new System.EventHandler(this.buildTreeStructureToolStripMenuItem_CheckedChanged); this.buildTreeStructureToolStripMenuItem.CheckedChanged += new System.EventHandler(this.buildTreeStructureToolStripMenuItem_CheckedChanged);
// //
// customCompressionTypeToolStripMenuItem
//
this.customCompressionTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.customCompressionZstdToolStripMenuItem,
this.customCompressionLZ4ToolStripMenuItem});
this.customCompressionTypeToolStripMenuItem.Name = "customCompressionTypeToolStripMenuItem";
this.customCompressionTypeToolStripMenuItem.Size = new System.Drawing.Size(241, 22);
this.customCompressionTypeToolStripMenuItem.Text = "Custom compression type";
//
// customCompressionZstdToolStripMenuItem
//
this.customCompressionZstdToolStripMenuItem.Checked = true;
this.customCompressionZstdToolStripMenuItem.CheckOnClick = true;
this.customCompressionZstdToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.customCompressionZstdToolStripMenuItem.Name = "customCompressionZstdToolStripMenuItem";
this.customCompressionZstdToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
this.customCompressionZstdToolStripMenuItem.Text = "Zstd";
this.customCompressionZstdToolStripMenuItem.ToolTipText = "If selected, Zstd-decompression will be used for assets with custom compression t" +
"ype";
this.customCompressionZstdToolStripMenuItem.CheckedChanged += new System.EventHandler(this.customCompressionZstd_CheckedChanged);
//
// customCompressionLZ4ToolStripMenuItem
//
this.customCompressionLZ4ToolStripMenuItem.CheckOnClick = true;
this.customCompressionLZ4ToolStripMenuItem.Name = "customCompressionLZ4ToolStripMenuItem";
this.customCompressionLZ4ToolStripMenuItem.Size = new System.Drawing.Size(130, 22);
this.customCompressionLZ4ToolStripMenuItem.Text = "Lz4/Lz4HC";
this.customCompressionLZ4ToolStripMenuItem.ToolTipText = "If selected, Lz4-decompression will be used for assets with custom compression ty" +
"pe";
this.customCompressionLZ4ToolStripMenuItem.CheckedChanged += new System.EventHandler(this.customCompressionLZ4_CheckedChanged);
//
// toolStripMenuItem14 // toolStripMenuItem14
// //
this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.specifyUnityVersion}); this.specifyUnityVersion});
this.toolStripMenuItem14.Name = "toolStripMenuItem14"; this.toolStripMenuItem14.Name = "toolStripMenuItem14";
this.toolStripMenuItem14.Size = new System.Drawing.Size(241, 22); this.toolStripMenuItem14.Size = new System.Drawing.Size(276, 22);
this.toolStripMenuItem14.Text = "Specify Unity version"; this.toolStripMenuItem14.Text = "Specify Unity version";
this.toolStripMenuItem14.DropDownClosed += new System.EventHandler(this.specifyUnityVersion_Close);
// //
// specifyUnityVersion // specifyUnityVersion
// //
@@ -372,7 +357,7 @@
// showExpOpt // showExpOpt
// //
this.showExpOpt.Name = "showExpOpt"; this.showExpOpt.Name = "showExpOpt";
this.showExpOpt.Size = new System.Drawing.Size(241, 22); this.showExpOpt.Size = new System.Drawing.Size(276, 22);
this.showExpOpt.Text = "Export options"; this.showExpOpt.Text = "Export options";
this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click); this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click);
// //
@@ -394,7 +379,7 @@
this.exportAllObjectssplitToolStripMenuItem1.Name = "exportAllObjectssplitToolStripMenuItem1"; this.exportAllObjectssplitToolStripMenuItem1.Name = "exportAllObjectssplitToolStripMenuItem1";
this.exportAllObjectssplitToolStripMenuItem1.Size = new System.Drawing.Size(382, 22); this.exportAllObjectssplitToolStripMenuItem1.Size = new System.Drawing.Size(382, 22);
this.exportAllObjectssplitToolStripMenuItem1.Text = "Export all objects (split)"; this.exportAllObjectssplitToolStripMenuItem1.Text = "Export all objects (split)";
this.exportAllObjectssplitToolStripMenuItem1.Click += new System.EventHandler(this.exportAllObjectsSplitToolStripMenuItem1_Click); this.exportAllObjectssplitToolStripMenuItem1.Click += new System.EventHandler(this.exportAllObjectssplitToolStripMenuItem1_Click);
// //
// exportSelectedObjectsToolStripMenuItem // exportSelectedObjectsToolStripMenuItem
// //
@@ -408,7 +393,7 @@
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsWithAnimationClipToolStripMenuItem"; this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsWithAnimationClipToolStripMenuItem";
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22); this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Text = "Export selected objects (split) + selected AnimationClips"; this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Text = "Export selected objects (split) + selected AnimationClips";
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportObjectsWithAnimationClipMenuItem_Click); this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportObjectswithAnimationClipMenuItem_Click);
// //
// toolStripSeparator1 // toolStripSeparator1
// //
@@ -420,14 +405,14 @@
this.exportSelectedObjectsmergeToolStripMenuItem.Name = "exportSelectedObjectsmergeToolStripMenuItem"; this.exportSelectedObjectsmergeToolStripMenuItem.Name = "exportSelectedObjectsmergeToolStripMenuItem";
this.exportSelectedObjectsmergeToolStripMenuItem.Size = new System.Drawing.Size(382, 22); this.exportSelectedObjectsmergeToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
this.exportSelectedObjectsmergeToolStripMenuItem.Text = "Export selected objects (merge)"; this.exportSelectedObjectsmergeToolStripMenuItem.Text = "Export selected objects (merge)";
this.exportSelectedObjectsmergeToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsMergeToolStripMenuItem_Click); this.exportSelectedObjectsmergeToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsmergeToolStripMenuItem_Click);
// //
// exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem // exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem
// //
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem"; this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem";
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22); this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Text = "Export selected objects (merge) + selected AnimationClips"; this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Text = "Export selected objects (merge) + selected AnimationClips";
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsMergeWithAnimationClipToolStripMenuItem_Click); this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem_Click);
// //
// exportToolStripMenuItem // exportToolStripMenuItem
// //
@@ -441,7 +426,7 @@
this.toolStripMenuItem2, this.toolStripMenuItem2,
this.toolStripMenuItem3, this.toolStripMenuItem3,
this.toolStripSeparator6, this.toolStripSeparator6,
this.live2DCubismModelsToolStripMenuItem, this.allLive2DModelsToolStripMenuItem,
this.toolStripSeparator2, this.toolStripSeparator2,
this.toolStripMenuItem10}); this.toolStripMenuItem10});
this.exportToolStripMenuItem.Name = "exportToolStripMenuItem"; this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
@@ -479,7 +464,7 @@
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Name = "exportAnimatorWithSelectedAnimationClipToolStripMenuItem"; this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Name = "exportAnimatorWithSelectedAnimationClipToolStripMenuItem";
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(266, 22); this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Text = "Animator + selected AnimationClips"; this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Text = "Animator + selected AnimationClips";
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportAnimatorWithAnimationClipMenuItem_Click); this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Click += new System.EventHandler(this.exportAnimatorwithAnimationClipMenuItem_Click);
// //
// toolStripSeparator4 // toolStripSeparator4
// //
@@ -553,52 +538,12 @@
this.toolStripSeparator6.Name = "toolStripSeparator6"; this.toolStripSeparator6.Name = "toolStripSeparator6";
this.toolStripSeparator6.Size = new System.Drawing.Size(263, 6); this.toolStripSeparator6.Size = new System.Drawing.Size(263, 6);
// //
// live2DCubismModelsToolStripMenuItem // allLive2DModelsToolStripMenuItem
// //
this.live2DCubismModelsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.allLive2DModelsToolStripMenuItem.Name = "allLive2DModelsToolStripMenuItem";
this.allL2DModelsToolStripMenuItem, this.allLive2DModelsToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
this.selectedL2DModelsToolStripMenuItem, this.allLive2DModelsToolStripMenuItem.Text = "Live2D Cubism models";
this.l2DModelWithFadeListToolStripMenuItem, this.allLive2DModelsToolStripMenuItem.Click += new System.EventHandler(this.allLive2DModelsToolStripMenuItem_Click);
this.l2DModelWithFadeMotionsToolStripMenuItem,
this.l2DModelWithClipsToolStripMenuItem});
this.live2DCubismModelsToolStripMenuItem.Name = "live2DCubismModelsToolStripMenuItem";
this.live2DCubismModelsToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
this.live2DCubismModelsToolStripMenuItem.Text = "Live2D Cubism models";
//
// allL2DModelsToolStripMenuItem
//
this.allL2DModelsToolStripMenuItem.Name = "allL2DModelsToolStripMenuItem";
this.allL2DModelsToolStripMenuItem.Size = new System.Drawing.Size(292, 22);
this.allL2DModelsToolStripMenuItem.Text = "All models";
this.allL2DModelsToolStripMenuItem.Click += new System.EventHandler(this.exportAllL2D_Click);
//
// selectedL2DModelsToolStripMenuItem
//
this.selectedL2DModelsToolStripMenuItem.Name = "selectedL2DModelsToolStripMenuItem";
this.selectedL2DModelsToolStripMenuItem.Size = new System.Drawing.Size(292, 22);
this.selectedL2DModelsToolStripMenuItem.Text = "Selected models";
this.selectedL2DModelsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2D_Click);
//
// l2DModelWithFadeListToolStripMenuItem
//
this.l2DModelWithFadeListToolStripMenuItem.Name = "l2DModelWithFadeListToolStripMenuItem";
this.l2DModelWithFadeListToolStripMenuItem.Size = new System.Drawing.Size(292, 22);
this.l2DModelWithFadeListToolStripMenuItem.Text = "Model + selected Fade Motion List";
this.l2DModelWithFadeListToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithFadeList_Click);
//
// l2DModelWithFadeMotionsToolStripMenuItem
//
this.l2DModelWithFadeMotionsToolStripMenuItem.Name = "l2DModelWithFadeMotionsToolStripMenuItem";
this.l2DModelWithFadeMotionsToolStripMenuItem.Size = new System.Drawing.Size(292, 22);
this.l2DModelWithFadeMotionsToolStripMenuItem.Text = "Model + selected Fade motions";
this.l2DModelWithFadeMotionsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithFadeMotions_Click);
//
// l2DModelWithClipsToolStripMenuItem
//
this.l2DModelWithClipsToolStripMenuItem.Name = "l2DModelWithClipsToolStripMenuItem";
this.l2DModelWithClipsToolStripMenuItem.Size = new System.Drawing.Size(292, 22);
this.l2DModelWithClipsToolStripMenuItem.Text = "Model + selected AnimationClip motions";
this.l2DModelWithClipsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithClips_Click);
// //
// toolStripSeparator2 // toolStripSeparator2
// //
@@ -657,44 +602,44 @@
// debugMenuItem // debugMenuItem
// //
this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.showConsoleToolStripMenuItem,
this.toolStripMenuItem15, this.toolStripMenuItem15,
this.showConsoleToolStripMenuItem,
this.writeLogToFileToolStripMenuItem, this.writeLogToFileToolStripMenuItem,
this.exportClassStructuresMenuItem}); this.exportClassStructuresMenuItem});
this.debugMenuItem.Name = "debugMenuItem"; this.debugMenuItem.Name = "debugMenuItem";
this.debugMenuItem.Size = new System.Drawing.Size(54, 20); this.debugMenuItem.Size = new System.Drawing.Size(54, 20);
this.debugMenuItem.Text = "Debug"; this.debugMenuItem.Text = "Debug";
// //
// toolStripMenuItem15
//
this.toolStripMenuItem15.CheckOnClick = true;
this.toolStripMenuItem15.Name = "toolStripMenuItem15";
this.toolStripMenuItem15.Size = new System.Drawing.Size(200, 22);
this.toolStripMenuItem15.Text = "Show all error messages";
this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click);
//
// showConsoleToolStripMenuItem // showConsoleToolStripMenuItem
// //
this.showConsoleToolStripMenuItem.Checked = true; this.showConsoleToolStripMenuItem.Checked = true;
this.showConsoleToolStripMenuItem.CheckOnClick = true; this.showConsoleToolStripMenuItem.CheckOnClick = true;
this.showConsoleToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.showConsoleToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this.showConsoleToolStripMenuItem.Name = "showConsoleToolStripMenuItem"; this.showConsoleToolStripMenuItem.Name = "showConsoleToolStripMenuItem";
this.showConsoleToolStripMenuItem.Size = new System.Drawing.Size(288, 22); this.showConsoleToolStripMenuItem.Size = new System.Drawing.Size(200, 22);
this.showConsoleToolStripMenuItem.Text = "Show console logger"; this.showConsoleToolStripMenuItem.Text = "Show console logger";
this.showConsoleToolStripMenuItem.Click += new System.EventHandler(this.showConsoleToolStripMenuItem_Click); this.showConsoleToolStripMenuItem.Click += new System.EventHandler(this.showConsoleToolStripMenuItem_Click);
// //
// toolStripMenuItem15
//
this.toolStripMenuItem15.CheckOnClick = true;
this.toolStripMenuItem15.Name = "toolStripMenuItem15";
this.toolStripMenuItem15.Size = new System.Drawing.Size(288, 22);
this.toolStripMenuItem15.Text = "Show debug messages in console logger";
this.toolStripMenuItem15.Click += new System.EventHandler(this.toolStripMenuItem15_Click);
//
// writeLogToFileToolStripMenuItem // writeLogToFileToolStripMenuItem
// //
this.writeLogToFileToolStripMenuItem.CheckOnClick = true; this.writeLogToFileToolStripMenuItem.CheckOnClick = true;
this.writeLogToFileToolStripMenuItem.Name = "writeLogToFileToolStripMenuItem"; this.writeLogToFileToolStripMenuItem.Name = "writeLogToFileToolStripMenuItem";
this.writeLogToFileToolStripMenuItem.Size = new System.Drawing.Size(288, 22); this.writeLogToFileToolStripMenuItem.Size = new System.Drawing.Size(200, 22);
this.writeLogToFileToolStripMenuItem.Text = "Write log to file"; this.writeLogToFileToolStripMenuItem.Text = "Write log to file";
this.writeLogToFileToolStripMenuItem.CheckedChanged += new System.EventHandler(this.writeLogToFileToolStripMenuItem_CheckedChanged); this.writeLogToFileToolStripMenuItem.CheckedChanged += new System.EventHandler(this.writeLogToFileToolStripMenuItem_CheckedChanged);
// //
// exportClassStructuresMenuItem // exportClassStructuresMenuItem
// //
this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem"; this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem";
this.exportClassStructuresMenuItem.Size = new System.Drawing.Size(288, 22); this.exportClassStructuresMenuItem.Size = new System.Drawing.Size(200, 22);
this.exportClassStructuresMenuItem.Text = "Export class structures"; this.exportClassStructuresMenuItem.Text = "Export class structures";
this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click); this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click);
// //
@@ -857,7 +802,7 @@
this.listSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 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.Left)
| System.Windows.Forms.AnchorStyles.Right))); | System.Windows.Forms.AnchorStyles.Right)));
this.listSearch.BackColor = System.Drawing.SystemColors.Window; this.listSearch.BackColor = System.Drawing.Color.White;
this.listSearch.BorderStyle = System.Windows.Forms.BorderStyle.None; this.listSearch.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.listSearch.DetectUrls = false; this.listSearch.DetectUrls = false;
this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText; this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText;
@@ -987,6 +932,8 @@
// previewPanel // previewPanel
// //
this.previewPanel.BackColor = System.Drawing.SystemColors.ControlDark; this.previewPanel.BackColor = System.Drawing.SystemColors.ControlDark;
this.previewPanel.BackgroundImage = global::AssetStudioGUI.Properties.Resources.preview;
this.previewPanel.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.previewPanel.Controls.Add(this.assetInfoLabel); this.previewPanel.Controls.Add(this.assetInfoLabel);
this.previewPanel.Controls.Add(this.FMODpanel); this.previewPanel.Controls.Add(this.FMODpanel);
this.previewPanel.Controls.Add(this.fontPreviewBox); this.previewPanel.Controls.Add(this.fontPreviewBox);
@@ -994,20 +941,17 @@
this.previewPanel.Controls.Add(this.textPreviewBox); this.previewPanel.Controls.Add(this.textPreviewBox);
this.previewPanel.Controls.Add(this.classTextBox); this.previewPanel.Controls.Add(this.classTextBox);
this.previewPanel.Dock = System.Windows.Forms.DockStyle.Fill; this.previewPanel.Dock = System.Windows.Forms.DockStyle.Fill;
this.previewPanel.Image = global::AssetStudioGUI.Properties.Resources.preview;
this.previewPanel.Location = new System.Drawing.Point(0, 0); this.previewPanel.Location = new System.Drawing.Point(0, 0);
this.previewPanel.Name = "previewPanel"; this.previewPanel.Name = "previewPanel";
this.previewPanel.Size = new System.Drawing.Size(768, 607); this.previewPanel.Size = new System.Drawing.Size(768, 607);
this.previewPanel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
this.previewPanel.TabIndex = 1; this.previewPanel.TabIndex = 1;
this.previewPanel.TabStop = false;
this.previewPanel.Resize += new System.EventHandler(this.preview_Resize); this.previewPanel.Resize += new System.EventHandler(this.preview_Resize);
// //
// assetInfoLabel // assetInfoLabel
// //
this.assetInfoLabel.AutoSize = true; this.assetInfoLabel.AutoSize = true;
this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent; this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;
this.assetInfoLabel.ForeColor = System.Drawing.Color.White; this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.assetInfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.assetInfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.assetInfoLabel.Location = new System.Drawing.Point(4, 8); this.assetInfoLabel.Location = new System.Drawing.Point(4, 8);
this.assetInfoLabel.Name = "assetInfoLabel"; this.assetInfoLabel.Name = "assetInfoLabel";
@@ -1050,7 +994,7 @@
// //
this.FMODinfoLabel.Anchor = System.Windows.Forms.AnchorStyles.Top; this.FMODinfoLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.FMODinfoLabel.AutoSize = true; this.FMODinfoLabel.AutoSize = true;
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.HighlightText; this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODinfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.FMODinfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255); this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255);
this.FMODinfoLabel.Name = "FMODinfoLabel"; this.FMODinfoLabel.Name = "FMODinfoLabel";
@@ -1061,7 +1005,7 @@
// //
this.FMODtimerLabel.Anchor = System.Windows.Forms.AnchorStyles.Top; this.FMODtimerLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.FMODtimerLabel.AutoSize = true; this.FMODtimerLabel.AutoSize = true;
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.HighlightText; this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODtimerLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.FMODtimerLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253); this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253);
this.FMODtimerLabel.Name = "FMODtimerLabel"; this.FMODtimerLabel.Name = "FMODtimerLabel";
@@ -1073,7 +1017,7 @@
// //
this.FMODstatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top; this.FMODstatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.FMODstatusLabel.AutoSize = true; this.FMODstatusLabel.AutoSize = true;
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.HighlightText; this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
this.FMODstatusLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl; this.FMODstatusLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255); this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255);
this.FMODstatusLabel.Name = "FMODstatusLabel"; this.FMODstatusLabel.Name = "FMODstatusLabel";
@@ -1334,82 +1278,46 @@
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.copyToolStripMenuItem, this.copyToolStripMenuItem,
this.exportSelectedAssetsToolStripMenuItem, this.exportSelectedAssetsToolStripMenuItem,
this.exportAnimatorwithselectedAnimationClipMenuItem,
this.dumpSelectedAssetsToolStripMenuItem, this.dumpSelectedAssetsToolStripMenuItem,
this.exportAnimatorWithSelectedAnimationClipMenuItem,
this.exportAsLive2DModelToolStripMenuItem,
this.exportL2DWithFadeLstToolStripMenuItem,
this.exportL2DWithFadeToolStripMenuItem,
this.exportL2DWithClipsToolStripMenuItem,
this.goToSceneHierarchyToolStripMenuItem, this.goToSceneHierarchyToolStripMenuItem,
this.showOriginalFileToolStripMenuItem}); this.showOriginalFileToolStripMenuItem});
this.contextMenuStrip1.Name = "contextMenuStrip1"; this.contextMenuStrip1.Name = "contextMenuStrip1";
this.contextMenuStrip1.Size = new System.Drawing.Size(332, 224); this.contextMenuStrip1.Size = new System.Drawing.Size(304, 136);
// //
// copyToolStripMenuItem // copyToolStripMenuItem
// //
this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
this.copyToolStripMenuItem.Size = new System.Drawing.Size(331, 22); this.copyToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
this.copyToolStripMenuItem.Text = "Copy text"; this.copyToolStripMenuItem.Text = "Copy text";
this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click); this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
// //
// exportSelectedAssetsToolStripMenuItem // exportSelectedAssetsToolStripMenuItem
// //
this.exportSelectedAssetsToolStripMenuItem.Name = "exportSelectedAssetsToolStripMenuItem"; this.exportSelectedAssetsToolStripMenuItem.Name = "exportSelectedAssetsToolStripMenuItem";
this.exportSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(331, 22); this.exportSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
this.exportSelectedAssetsToolStripMenuItem.Text = "Export selected assets"; this.exportSelectedAssetsToolStripMenuItem.Text = "Export selected assets";
this.exportSelectedAssetsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedAssetsToolStripMenuItem_Click); this.exportSelectedAssetsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedAssetsToolStripMenuItem_Click);
// //
// exportAnimatorwithselectedAnimationClipMenuItem
//
this.exportAnimatorwithselectedAnimationClipMenuItem.Name = "exportAnimatorwithselectedAnimationClipMenuItem";
this.exportAnimatorwithselectedAnimationClipMenuItem.Size = new System.Drawing.Size(303, 22);
this.exportAnimatorwithselectedAnimationClipMenuItem.Text = "Export Animator + selected AnimationClips";
this.exportAnimatorwithselectedAnimationClipMenuItem.Visible = false;
this.exportAnimatorwithselectedAnimationClipMenuItem.Click += new System.EventHandler(this.exportAnimatorwithAnimationClipMenuItem_Click);
//
// dumpSelectedAssetsToolStripMenuItem // dumpSelectedAssetsToolStripMenuItem
// //
this.dumpSelectedAssetsToolStripMenuItem.Name = "dumpSelectedAssetsToolStripMenuItem"; this.dumpSelectedAssetsToolStripMenuItem.Name = "dumpSelectedAssetsToolStripMenuItem";
this.dumpSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(331, 22); this.dumpSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
this.dumpSelectedAssetsToolStripMenuItem.Text = "Dump selected assets"; this.dumpSelectedAssetsToolStripMenuItem.Text = "Dump selected assets";
this.dumpSelectedAssetsToolStripMenuItem.Click += new System.EventHandler(this.dumpSelectedAssetsToolStripMenuItem_Click); this.dumpSelectedAssetsToolStripMenuItem.Click += new System.EventHandler(this.dumpSelectedAssetsToolStripMenuItem_Click);
// //
// exportAnimatorWithSelectedAnimationClipMenuItem
//
this.exportAnimatorWithSelectedAnimationClipMenuItem.Name = "exportAnimatorWithSelectedAnimationClipMenuItem";
this.exportAnimatorWithSelectedAnimationClipMenuItem.Size = new System.Drawing.Size(331, 22);
this.exportAnimatorWithSelectedAnimationClipMenuItem.Text = "Export Animator + selected AnimationClips";
this.exportAnimatorWithSelectedAnimationClipMenuItem.Visible = false;
this.exportAnimatorWithSelectedAnimationClipMenuItem.Click += new System.EventHandler(this.exportAnimatorWithAnimationClipMenuItem_Click);
//
// exportAsLive2DModelToolStripMenuItem
//
this.exportAsLive2DModelToolStripMenuItem.Name = "exportAsLive2DModelToolStripMenuItem";
this.exportAsLive2DModelToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
this.exportAsLive2DModelToolStripMenuItem.Text = "Export as Live2D model(s)";
this.exportAsLive2DModelToolStripMenuItem.Visible = false;
this.exportAsLive2DModelToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2D_Click);
//
// exportL2DWithFadeLstToolStripMenuItem
//
this.exportL2DWithFadeLstToolStripMenuItem.Name = "exportL2DWithFadeLstToolStripMenuItem";
this.exportL2DWithFadeLstToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
this.exportL2DWithFadeLstToolStripMenuItem.Text = "Export Live2D model + selected Fade Motion List";
this.exportL2DWithFadeLstToolStripMenuItem.Visible = false;
this.exportL2DWithFadeLstToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithFadeList_Click);
//
// exportL2DWithFadeToolStripMenuItem
//
this.exportL2DWithFadeToolStripMenuItem.Name = "exportL2DWithFadeToolStripMenuItem";
this.exportL2DWithFadeToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
this.exportL2DWithFadeToolStripMenuItem.Text = "Export Live2D model + selected Fade motions";
this.exportL2DWithFadeToolStripMenuItem.Visible = false;
this.exportL2DWithFadeToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithFadeMotions_Click);
//
// exportL2DWithClipsToolStripMenuItem
//
this.exportL2DWithClipsToolStripMenuItem.Name = "exportL2DWithClipsToolStripMenuItem";
this.exportL2DWithClipsToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
this.exportL2DWithClipsToolStripMenuItem.Text = "Export Live2D model + selected AnimationClips";
this.exportL2DWithClipsToolStripMenuItem.Visible = false;
this.exportL2DWithClipsToolStripMenuItem.Click += new System.EventHandler(this.exportSelectedL2DWithClips_Click);
//
// goToSceneHierarchyToolStripMenuItem // goToSceneHierarchyToolStripMenuItem
// //
this.goToSceneHierarchyToolStripMenuItem.Name = "goToSceneHierarchyToolStripMenuItem"; this.goToSceneHierarchyToolStripMenuItem.Name = "goToSceneHierarchyToolStripMenuItem";
this.goToSceneHierarchyToolStripMenuItem.Size = new System.Drawing.Size(331, 22); this.goToSceneHierarchyToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
this.goToSceneHierarchyToolStripMenuItem.Text = "Go to scene hierarchy"; this.goToSceneHierarchyToolStripMenuItem.Text = "Go to scene hierarchy";
this.goToSceneHierarchyToolStripMenuItem.Visible = false; this.goToSceneHierarchyToolStripMenuItem.Visible = false;
this.goToSceneHierarchyToolStripMenuItem.Click += new System.EventHandler(this.goToSceneHierarchyToolStripMenuItem_Click); this.goToSceneHierarchyToolStripMenuItem.Click += new System.EventHandler(this.goToSceneHierarchyToolStripMenuItem_Click);
@@ -1417,7 +1325,7 @@
// showOriginalFileToolStripMenuItem // showOriginalFileToolStripMenuItem
// //
this.showOriginalFileToolStripMenuItem.Name = "showOriginalFileToolStripMenuItem"; this.showOriginalFileToolStripMenuItem.Name = "showOriginalFileToolStripMenuItem";
this.showOriginalFileToolStripMenuItem.Size = new System.Drawing.Size(331, 22); this.showOriginalFileToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
this.showOriginalFileToolStripMenuItem.Text = "Show original file"; this.showOriginalFileToolStripMenuItem.Text = "Show original file";
this.showOriginalFileToolStripMenuItem.Visible = false; this.showOriginalFileToolStripMenuItem.Visible = false;
this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click); this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);
@@ -1455,7 +1363,6 @@
this.progressbarPanel.ResumeLayout(false); this.progressbarPanel.ResumeLayout(false);
this.tabControl2.ResumeLayout(false); this.tabControl2.ResumeLayout(false);
this.tabPage4.ResumeLayout(false); this.tabPage4.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.previewPanel)).EndInit();
this.previewPanel.ResumeLayout(false); this.previewPanel.ResumeLayout(false);
this.previewPanel.PerformLayout(); this.previewPanel.PerformLayout();
this.FMODpanel.ResumeLayout(false); this.FMODpanel.ResumeLayout(false);
@@ -1490,7 +1397,7 @@
private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportAllAssetsMenuItem; private System.Windows.Forms.ToolStripMenuItem exportAllAssetsMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsMenuItem; private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsMenuItem;
private System.Windows.Forms.PictureBox previewPanel; private System.Windows.Forms.Panel previewPanel;
private System.Windows.Forms.ProgressBar progressBar1; private System.Windows.Forms.ProgressBar progressBar1;
private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.StatusStrip statusStrip1;
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
@@ -1532,7 +1439,7 @@
private OpenTK.GLControl glControl1; private OpenTK.GLControl glControl1;
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
private System.Windows.Forms.ToolStripMenuItem showOriginalFileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem showOriginalFileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportAnimatorWithSelectedAnimationClipMenuItem; private System.Windows.Forms.ToolStripMenuItem exportAnimatorwithselectedAnimationClipMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem filterTypeToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem filterTypeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem allToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem allToolStripMenuItem;
@@ -1582,27 +1489,18 @@
private System.Windows.Forms.ComboBox listSearchHistory; private System.Windows.Forms.ComboBox listSearchHistory;
private System.Windows.Forms.RichTextBox listSearch; private System.Windows.Forms.RichTextBox listSearch;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
private System.Windows.Forms.ToolStripMenuItem allLive2DModelsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
private System.Windows.Forms.ListView assetListView; 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;
private System.Windows.Forms.ToolStripMenuItem showConsoleToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem showConsoleToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem writeLogToFileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem writeLogToFileToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem buildTreeStructureToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem buildTreeStructureToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportL2DWithClipsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportAsLive2DModelToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem live2DCubismModelsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem allL2DModelsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem selectedL2DModelsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem l2DModelWithClipsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem l2DModelWithFadeMotionsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportL2DWithFadeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem l2DModelWithFadeListToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem exportL2DWithFadeLstToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem customCompressionTypeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem customCompressionZstdToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem customCompressionLZ4ToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem useAssetLoadingViaTypetreeToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator assetLoadingToolStripSeparator;
} }
} }

View File

@@ -1,4 +1,5 @@
using AssetStudio; using Arknights;
using AssetStudio;
using Newtonsoft.Json; using Newtonsoft.Json;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using System; using System;
@@ -18,6 +19,8 @@ using System.Timers;
using System.Windows.Forms; using System.Windows.Forms;
using static AssetStudioGUI.Studio; using static AssetStudioGUI.Studio;
using Font = AssetStudio.Font; using Font = AssetStudio.Font;
using SharpImage = SixLabors.ImageSharp;
using SharpImageFormat = SixLabors.ImageSharp.PixelFormats;
using Microsoft.WindowsAPICodePack.Taskbar; using Microsoft.WindowsAPICodePack.Taskbar;
#if NET472 #if NET472
using OpenTK; using OpenTK;
@@ -47,6 +50,7 @@ namespace AssetStudioGUI
#region SpriteControl #region SpriteControl
private SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On; private SpriteMaskMode spriteMaskVisibleMode = SpriteMaskMode.On;
private bool showDebugInfo = false;
#endregion #endregion
#region TexControl #region TexControl
@@ -89,10 +93,6 @@ namespace AssetStudioGUI
private AlphanumComparatorFast alphanumComparator = new AlphanumComparatorFast(); private AlphanumComparatorFast alphanumComparator = new AlphanumComparatorFast();
#endif #endif
//asset list selection
private List<int> selectedIndicesPrevList = new List<int>();
private List<AssetItem> selectedAnimationAssetsList = new List<AssetItem>();
//asset list filter //asset list filter
private System.Timers.Timer delayTimer; private System.Timers.Timer delayTimer;
private bool enableFiltering; private bool enableFiltering;
@@ -133,9 +133,10 @@ namespace AssetStudioGUI
displayAll.Checked = Properties.Settings.Default.displayAll; displayAll.Checked = Properties.Settings.Default.displayAll;
displayInfo.Checked = Properties.Settings.Default.displayInfo; displayInfo.Checked = Properties.Settings.Default.displayInfo;
enablePreview.Checked = Properties.Settings.Default.enablePreview; enablePreview.Checked = Properties.Settings.Default.enablePreview;
akFixFaceSpriteNamesToolStripMenuItem.Checked = Properties.Settings.Default.fixFaceSpriteNames;
akUseExternalAlphaToolStripMenuItem.Checked = Properties.Settings.Default.useExternalAlpha;
showConsoleToolStripMenuItem.Checked = Properties.Settings.Default.showConsole; showConsoleToolStripMenuItem.Checked = Properties.Settings.Default.showConsole;
buildTreeStructureToolStripMenuItem.Checked = Properties.Settings.Default.buildTreeStructure; buildTreeStructureToolStripMenuItem.Checked = Properties.Settings.Default.buildTreeStructure;
useAssetLoadingViaTypetreeToolStripMenuItem.Checked = Properties.Settings.Default.useTypetreeLoading;
FMODinit(); FMODinit();
listSearchFilterMode.SelectedIndex = 0; listSearchFilterMode.SelectedIndex = 0;
@@ -173,6 +174,7 @@ namespace AssetStudioGUI
} }
} }
} }
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, paths)); await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, paths));
saveDirectoryBackup = openDirectoryBackup; saveDirectoryBackup = openDirectoryBackup;
BuildAssetStructures(); BuildAssetStructures();
@@ -184,6 +186,7 @@ namespace AssetStudioGUI
if (openFileDialog1.ShowDialog(this) == DialogResult.OK) if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
{ {
ResetForm(); ResetForm();
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFileDialog1.FileNames)); await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFileDialog1.FileNames));
BuildAssetStructures(); BuildAssetStructures();
} }
@@ -196,29 +199,12 @@ namespace AssetStudioGUI
if (openFolderDialog.ShowDialog(this) == DialogResult.OK) if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
{ {
ResetForm(); ResetForm();
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFolderDialog.Folder)); await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFolderDialog.Folder));
BuildAssetStructures(); BuildAssetStructures();
} }
} }
private void specifyUnityVersion_Close(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(specifyUnityVersion.Text))
{
assetsManager.SpecifyUnityVersion = null;
return;
}
try
{
assetsManager.SpecifyUnityVersion = new UnityVersion(specifyUnityVersion.Text);
}
catch (Exception ex)
{
Logger.Error(ex.Message);
}
}
private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e) private async void extractFileToolStripMenuItem_Click(object sender, EventArgs e)
{ {
if (openFileDialog1.ShowDialog(this) == DialogResult.OK) if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
@@ -288,6 +274,9 @@ namespace AssetStudioGUI
typeMap.Clear(); typeMap.Clear();
classesListView.EndUpdate(); classesListView.EndUpdate();
if (akFixFaceSpriteNamesToolStripMenuItem.Checked)
FixFaceSpriteNames();
var types = exportableAssets.Select(x => x.Type).Distinct().OrderBy(x => x.ToString()).ToArray(); var types = exportableAssets.Select(x => x.Type).Distinct().OrderBy(x => x.ToString()).ToArray();
foreach (var type in types) foreach (var type in types)
{ {
@@ -302,9 +291,9 @@ namespace AssetStudioGUI
filterTypeToolStripMenuItem.DropDownItems.Add(typeItem); filterTypeToolStripMenuItem.DropDownItems.Add(typeItem);
} }
allToolStripMenuItem.Checked = true; allToolStripMenuItem.Checked = true;
var log = $"Finished loading {assetsManager.assetsFileList.Count} file(s) with {assetListView.Items.Count} exportable assets"; var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {assetListView.Items.Count} exportable assets";
var unityVer = assetsManager.assetsFileList[0].version; var unityVer = assetsManager.assetsFileList[0].version;
var m_ObjectsCount = unityVer > 2020 ? var m_ObjectsCount = unityVer[0] > 2020 ?
assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => y.classID != (int)ClassIDType.Shader)) : assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => y.classID != (int)ClassIDType.Shader)) :
assetsManager.assetsFileList.Sum(x => x.m_Objects.Count); assetsManager.assetsFileList.Sum(x => x.m_Objects.Count);
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count); var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
@@ -365,7 +354,7 @@ namespace AssetStudioGUI
if (e.Control) if (e.Control)
{ {
var need = false; var need = false;
if (lastSelectedItem?.Type == ClassIDType.Texture2D || lastSelectedItem?.Type == ClassIDType.Texture2DArrayImage) if (lastSelectedItem?.Type == ClassIDType.Texture2D)
{ {
switch (e.KeyCode) switch (e.KeyCode)
{ {
@@ -387,7 +376,7 @@ namespace AssetStudioGUI
break; break;
} }
} }
else if (lastSelectedItem?.Type == ClassIDType.Sprite && !((Sprite)lastSelectedItem.Asset).m_RD.alphaTexture.IsNull) else if ((lastSelectedItem?.Type == ClassIDType.Sprite && !((Sprite)lastSelectedItem.Asset).m_RD.alphaTexture.IsNull) || lastSelectedItem?.Type == ClassIDType.AkPortraitSprite)
{ {
switch (e.KeyCode) switch (e.KeyCode)
{ {
@@ -399,6 +388,10 @@ namespace AssetStudioGUI
spriteMaskVisibleMode = spriteMaskVisibleMode == SpriteMaskMode.MaskOnly ? SpriteMaskMode.On : SpriteMaskMode.MaskOnly; spriteMaskVisibleMode = spriteMaskVisibleMode == SpriteMaskMode.MaskOnly ? SpriteMaskMode.On : SpriteMaskMode.MaskOnly;
need = true; need = true;
break; break;
case Keys.D:
showDebugInfo = !showDebugInfo;
need = true;
break;
} }
} }
if (need) if (need)
@@ -453,16 +446,17 @@ namespace AssetStudioGUI
switch (lastSelectedItem.Type) switch (lastSelectedItem.Type)
{ {
case ClassIDType.Texture2D: case ClassIDType.Texture2D:
case ClassIDType.AkPortraitSprite:
case ClassIDType.Sprite: case ClassIDType.Sprite:
{ {
if (enablePreview.Checked && imageTexture != null) if (enablePreview.Checked && imageTexture != null)
{ {
previewPanel.Image = imageTexture.Bitmap; previewPanel.BackgroundImage = imageTexture.Bitmap;
} }
else else
{ {
previewPanel.Image = Properties.Resources.preview; previewPanel.BackgroundImage = Properties.Resources.preview;
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage; previewPanel.BackgroundImageLayout = ImageLayout.Center;
} }
} }
break; break;
@@ -660,7 +654,7 @@ namespace AssetStudioGUI
enableFiltering = false; enableFiltering = false;
listSearch.Text = " Filter "; listSearch.Text = " Filter ";
listSearch.ForeColor = SystemColors.GrayText; listSearch.ForeColor = SystemColors.GrayText;
listSearch.BackColor = SystemColors.Window; listSearch.BackColor = System.Drawing.Color.White;
} }
} }
@@ -715,8 +709,6 @@ namespace AssetStudioGUI
sortColumn = e.Column; sortColumn = e.Column;
assetListView.BeginUpdate(); assetListView.BeginUpdate();
assetListView.SelectedIndices.Clear(); assetListView.SelectedIndices.Clear();
selectedIndicesPrevList.Clear();
selectedAnimationAssetsList.Clear();
if (sortColumn == 4) //FullSize if (sortColumn == 4) //FullSize
{ {
visibleAssets.Sort((a, b) => visibleAssets.Sort((a, b) =>
@@ -759,8 +751,8 @@ namespace AssetStudioGUI
private void selectAsset(object sender, ListViewItemSelectionChangedEventArgs e) private void selectAsset(object sender, ListViewItemSelectionChangedEventArgs e)
{ {
previewPanel.Image = Properties.Resources.preview; previewPanel.BackgroundImage = Properties.Resources.preview;
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage; previewPanel.BackgroundImageLayout = ImageLayout.Center;
classTextBox.Visible = false; classTextBox.Visible = false;
assetInfoLabel.Visible = false; assetInfoLabel.Visible = false;
assetInfoLabel.Text = null; assetInfoLabel.Text = null;
@@ -826,12 +818,8 @@ namespace AssetStudioGUI
switch (assetItem.Type) switch (assetItem.Type)
{ {
case ClassIDType.Texture2D: case ClassIDType.Texture2D:
case ClassIDType.Texture2DArrayImage:
PreviewTexture2D(assetItem, assetItem.Asset as Texture2D); PreviewTexture2D(assetItem, assetItem.Asset as Texture2D);
break; break;
case ClassIDType.Texture2DArray:
PreviewTexture2DArray(assetItem, assetItem.Asset as Texture2DArray);
break;
case ClassIDType.AudioClip: case ClassIDType.AudioClip:
PreviewAudioClip(assetItem, assetItem.Asset as AudioClip); PreviewAudioClip(assetItem, assetItem.Asset as AudioClip);
break; break;
@@ -842,16 +830,7 @@ namespace AssetStudioGUI
PreviewTextAsset(assetItem.Asset as TextAsset); PreviewTextAsset(assetItem.Asset as TextAsset);
break; break;
case ClassIDType.MonoBehaviour: case ClassIDType.MonoBehaviour:
var m_MonoBehaviour = (MonoBehaviour)assetItem.Asset; PreviewMonoBehaviour(assetItem.Asset as MonoBehaviour);
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
if (m_Script.m_ClassName == "CubismMoc")
{
PreviewMoc(assetItem, m_MonoBehaviour);
break;
}
}
PreviewMonoBehaviour(m_MonoBehaviour);
break; break;
case ClassIDType.Font: case ClassIDType.Font:
PreviewFont(assetItem.Asset as Font); PreviewFont(assetItem.Asset as Font);
@@ -868,6 +847,9 @@ namespace AssetStudioGUI
case ClassIDType.Sprite: case ClassIDType.Sprite:
PreviewSprite(assetItem, assetItem.Asset as Sprite); PreviewSprite(assetItem, assetItem.Asset as Sprite);
break; break;
case ClassIDType.AkPortraitSprite:
PreviewAkPortraitSprite(assetItem);
break;
case ClassIDType.Animator: case ClassIDType.Animator:
StatusStripUpdate("Can be exported to FBX file."); StatusStripUpdate("Can be exported to FBX file.");
break; break;
@@ -890,16 +872,6 @@ namespace AssetStudioGUI
} }
} }
private void PreviewTexture2DArray(AssetItem assetItem, Texture2DArray m_Texture2DArray)
{
assetItem.InfoText =
$"Width: {m_Texture2DArray.m_Width}\n" +
$"Height: {m_Texture2DArray.m_Height}\n" +
$"Graphics format: {m_Texture2DArray.m_Format}\n" +
$"Texture format: {m_Texture2DArray.m_Format.ToTextureFormat()}\n" +
$"Texture count: {m_Texture2DArray.m_Depth}";
}
private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D) private void PreviewTexture2D(AssetItem assetItem, Texture2D m_Texture2D)
{ {
var image = m_Texture2D.ConvertToImage(true); var image = m_Texture2D.ConvertToImage(true);
@@ -910,9 +882,9 @@ namespace AssetStudioGUI
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}"; assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
switch (m_Texture2D.m_TextureSettings.m_FilterMode) switch (m_Texture2D.m_TextureSettings.m_FilterMode)
{ {
case 0: assetItem.InfoText += "\nFilter mode: Point "; break; case 0: assetItem.InfoText += "\nFilter Mode: Point "; break;
case 1: assetItem.InfoText += "\nFilter mode: Bilinear "; break; case 1: assetItem.InfoText += "\nFilter Mode: Bilinear "; break;
case 2: assetItem.InfoText += "\nFilter mode: Trilinear "; break; case 2: assetItem.InfoText += "\nFilter Mode: Trilinear "; break;
} }
assetItem.InfoText += $"\nAnisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}\nMip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}"; assetItem.InfoText += $"\nAnisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}\nMip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}";
switch (m_Texture2D.m_TextureSettings.m_WrapMode) switch (m_Texture2D.m_TextureSettings.m_WrapMode)
@@ -948,8 +920,6 @@ namespace AssetStudioGUI
} }
} }
} }
var switchSwizzled = m_Texture2D.m_PlatformBlob.Length != 0;
assetItem.InfoText += assetItem.Asset.platform == BuildTarget.Switch ? $"\nUses texture swizzling: {switchSwizzled}" : "";
PreviewTexture(bitmap); PreviewTexture(bitmap);
StatusStripUpdate("'Ctrl'+'R'/'G'/'B'/'A' for Channel Toggle"); StatusStripUpdate("'Ctrl'+'R'/'G'/'B'/'A' for Channel Toggle");
@@ -964,12 +934,12 @@ namespace AssetStudioGUI
{ {
//Info //Info
assetItem.InfoText = "Compression format: "; assetItem.InfoText = "Compression format: ";
if (m_AudioClip.version < 5) if (m_AudioClip.version[0] < 5)
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case FMODSoundType.AAC: case FMODSoundType.ACC:
assetItem.InfoText += "AAC"; assetItem.InfoText += "Acc";
break; break;
case FMODSoundType.AIFF: case FMODSoundType.AIFF:
assetItem.InfoText += "AIFF"; assetItem.InfoText += "AIFF";
@@ -1052,18 +1022,6 @@ namespace AssetStudioGUI
var m_AudioData = m_AudioClip.m_AudioData.GetData(); var m_AudioData = m_AudioClip.m_AudioData.GetData();
if (m_AudioData == null || m_AudioData.Length == 0) if (m_AudioData == null || m_AudioData.Length == 0)
return; return;
if (!m_AudioClip.IsConvertSupport())
{
assetItem.InfoText +=
$"\nLength: {m_AudioClip.m_Length:.0##}\n" +
$"Channel count: {m_AudioClip.m_Channels}\n" +
$"Sample rate: {m_AudioClip.m_Frequency}\n" +
$"Bit depth: {m_AudioClip.m_BitsPerSample}";
StatusStripUpdate("Preview is not available for non-fmod sounds. Try to export instead.");
return;
}
var exinfo = new FMOD.CREATESOUNDEXINFO(); var exinfo = new FMOD.CREATESOUNDEXINFO();
exinfo.cbsize = Marshal.SizeOf(exinfo); exinfo.cbsize = Marshal.SizeOf(exinfo);
@@ -1136,27 +1094,6 @@ namespace AssetStudioGUI
PreviewText(str); PreviewText(str);
} }
private void PreviewMoc(AssetItem assetItem, MonoBehaviour m_MonoBehaviour)
{
using (var cubismModel = new CubismModel(m_MonoBehaviour))
{
var sb = new StringBuilder();
sb.AppendLine($"SDK Version: {cubismModel.VersionDescription}");
if (cubismModel.Version > 0)
{
sb.AppendLine($"Canvas Width: {cubismModel.CanvasWidth}");
sb.AppendLine($"Canvas Height: {cubismModel.CanvasHeight}");
sb.AppendLine($"Center X: {cubismModel.CentralPosX}");
sb.AppendLine($"Center Y: {cubismModel.CentralPosY}");
sb.AppendLine($"Pixel Per Unit: {cubismModel.PixelPerUnit}");
sb.AppendLine($"Parameter Count: {cubismModel.ParamCount}");
sb.AppendLine($"Part Count: {cubismModel.PartCount}");
}
assetItem.InfoText = sb.ToString();
}
StatusStripUpdate("Can be exported as Live2D Cubism model.");
}
private void PreviewFont(Font m_Font) private void PreviewFont(Font m_Font)
{ {
if (m_Font.m_FontData != null) if (m_Font.m_FontData != null)
@@ -1358,7 +1295,31 @@ namespace AssetStudioGUI
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite) private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
{ {
var image = m_Sprite.GetImage(spriteMaskMode: spriteMaskVisibleMode); SharpImage.Image<SharpImageFormat.Bgra32> image;
AvgSprite avgSprite = null;
bool isCharAvgSprite = assetItem.Container.Contains("avg/characters");
bool isCharArt = assetItem.Container.Contains("arts/characters");
if (akUseExternalAlphaToolStripMenuItem.Checked && (isCharAvgSprite || isCharArt))
{
avgSprite = isCharAvgSprite ? new AvgSprite(assetItem) : null;
if (m_Sprite.m_RD.alphaTexture.IsNull)
{
var charAlphaTex = AkSpriteHelper.TryFindAlphaTex(assetItem, avgSprite, isCharAvgSprite);
if (charAlphaTex != null)
{
m_Sprite.m_RD.alphaTexture.Set(charAlphaTex);
m_Sprite.akSplitAlpha = true;
}
}
image = m_Sprite.AkGetImage(avgSprite, spriteMaskMode: spriteMaskVisibleMode);
}
else
{
image = m_Sprite.GetImage(spriteMaskMode: spriteMaskVisibleMode);
}
if (image != null) if (image != null)
{ {
var bitmap = new DirectBitmap(image); var bitmap = new DirectBitmap(image);
@@ -1366,10 +1327,33 @@ namespace AssetStudioGUI
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n"; assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
PreviewTexture(bitmap); PreviewTexture(bitmap);
if (!m_Sprite.m_RD.alphaTexture.IsNull) if (!m_Sprite.m_RD.alphaTexture.IsNull && (akUseExternalAlphaToolStripMenuItem.Checked || !m_Sprite.akSplitAlpha))
{ {
assetItem.InfoText += $"Alpha Mask: {spriteMaskVisibleMode}\n"; var sb = new StringBuilder();
StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only.");
sb.AppendLine($"Alpha mask: {spriteMaskVisibleMode}");
sb.Append(spriteMaskVisibleMode != SpriteMaskMode.Off ? $"Is external mask: {m_Sprite.akSplitAlpha}\n" : "");
if (avgSprite != null)
{
sb.AppendLine($"Alias: \"{avgSprite.Alias}\"");
if (showDebugInfo)
{
sb.AppendLine($"[Debug]");
sb.AppendLine($"Is avg hub parsed: {avgSprite.IsHubParsed}");
if (avgSprite.IsHubParsed)
{
sb.AppendLine($"Is face data exist: {avgSprite.FaceSize.Width > 0}");
sb.AppendLine($"Is face sprite: {avgSprite.IsFaceSprite}");
sb.AppendLine($"Is whole body sprite: {avgSprite.IsWholeBodySprite}");
}
}
StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only. 'Ctrl'+'D' - Show debug info.");
}
else
{
StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only.");
}
assetItem.InfoText += sb.ToString();
} }
} }
else else
@@ -1378,15 +1362,34 @@ namespace AssetStudioGUI
} }
} }
private void PreviewAkPortraitSprite(AssetItem assetItem)
{
var image = assetItem.AkPortraitSprite.AkGetImage(spriteMaskMode: spriteMaskVisibleMode);
if (image != null)
{
var bitmap = new DirectBitmap(image);
image.Dispose();
assetItem.InfoText = $"Width: {bitmap.Width}\nHeight: {bitmap.Height}\n";
assetItem.InfoText += $"Alpha mask: {spriteMaskVisibleMode}";
PreviewTexture(bitmap);
StatusStripUpdate("'Ctrl'+'A' - Enable/Disable alpha mask usage. 'Ctrl'+'M' - Show alpha mask only.");
}
else
{
StatusStripUpdate("Unsupported sprite for preview.");
}
}
private void PreviewTexture(DirectBitmap bitmap) private void PreviewTexture(DirectBitmap bitmap)
{ {
imageTexture?.Dispose(); imageTexture?.Dispose();
imageTexture = bitmap; imageTexture = bitmap;
previewPanel.Image = imageTexture.Bitmap; previewPanel.BackgroundImage = imageTexture.Bitmap;
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height) if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
previewPanel.SizeMode = PictureBoxSizeMode.Zoom; previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
else else
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage; previewPanel.BackgroundImageLayout = ImageLayout.Center;
} }
private void PreviewText(string text) private void PreviewText(string text)
@@ -1446,13 +1449,10 @@ namespace AssetStudioGUI
assetListView.Items.Clear(); assetListView.Items.Clear();
classesListView.Items.Clear(); classesListView.Items.Clear();
classesListView.Groups.Clear(); classesListView.Groups.Clear();
selectedAnimationAssetsList.Clear(); previewPanel.BackgroundImage = Properties.Resources.preview;
selectedIndicesPrevList.Clear();
cubismMocList.Clear();
previewPanel.Image = Properties.Resources.preview;
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage;
imageTexture?.Dispose(); imageTexture?.Dispose();
imageTexture = null; imageTexture = null;
previewPanel.BackgroundImageLayout = ImageLayout.Center;
assetInfoLabel.Visible = false; assetInfoLabel.Visible = false;
assetInfoLabel.Text = null; assetInfoLabel.Text = null;
textPreviewBox.Visible = false; textPreviewBox.Visible = false;
@@ -1464,7 +1464,7 @@ namespace AssetStudioGUI
enableFiltering = false; enableFiltering = false;
listSearch.Text = " Filter "; listSearch.Text = " Filter ";
listSearch.ForeColor = SystemColors.GrayText; listSearch.ForeColor = SystemColors.GrayText;
listSearch.BackColor = SystemColors.Window; listSearch.BackColor = System.Drawing.Color.White;
if (tabControl1.SelectedIndex == 1) if (tabControl1.SelectedIndex == 1)
assetListView.Select(); assetListView.Select();
@@ -1478,6 +1478,34 @@ namespace AssetStudioGUI
FMODreset(); FMODreset();
} }
private void FixFaceSpriteNames()
{
assetListView.BeginUpdate();
for (int i = 0; i < assetListView.Items.Count; i++)
{
var assetItem = (AssetItem)assetListView.Items[i];
if (assetItem.Type == ClassIDType.Sprite)
{
var m_Sprite = (Sprite)assetItem.Asset;
if (akFixFaceSpriteNamesToolStripMenuItem.Checked)
{
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(assetItem.Container);
assetItem.Text = $"{fullName}#{m_Sprite.m_Name}";
}
}
else if (assetItem.Text != m_Sprite.m_Name)
{
assetItem.Text = m_Sprite.m_Name;
}
}
}
assetListView.EndUpdate();
}
private void tabControl2_SelectedIndexChanged(object sender, EventArgs e) private void tabControl2_SelectedIndexChanged(object sender, EventArgs e)
{ {
if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null) if (tabControl2.SelectedIndex == 1 && lastSelectedItem != null)
@@ -1492,11 +1520,7 @@ namespace AssetStudioGUI
{ {
goToSceneHierarchyToolStripMenuItem.Visible = false; goToSceneHierarchyToolStripMenuItem.Visible = false;
showOriginalFileToolStripMenuItem.Visible = false; showOriginalFileToolStripMenuItem.Visible = false;
exportAnimatorWithSelectedAnimationClipMenuItem.Visible = false; exportAnimatorwithselectedAnimationClipMenuItem.Visible = false;
exportAsLive2DModelToolStripMenuItem.Visible = false;
exportL2DWithFadeLstToolStripMenuItem.Visible = false;
exportL2DWithFadeToolStripMenuItem.Visible = false;
exportL2DWithClipsToolStripMenuItem.Visible = false;
if (assetListView.SelectedIndices.Count == 1) if (assetListView.SelectedIndices.Count == 1)
{ {
@@ -1506,42 +1530,10 @@ namespace AssetStudioGUI
if (assetListView.SelectedIndices.Count >= 1) if (assetListView.SelectedIndices.Count >= 1)
{ {
var selectedAssets = GetSelectedAssets(); var selectedAssets = GetSelectedAssets();
if (selectedAssets.Any(x => x.Type == ClassIDType.Animator) && selectedAssets.Any(x => x.Type == ClassIDType.AnimationClip))
var selectedTypes = (SelectedAssetType)0;
foreach (var asset in selectedAssets)
{ {
switch (asset.Asset) exportAnimatorwithselectedAnimationClipMenuItem.Visible = true;
{
case MonoBehaviour m_MonoBehaviour:
if (Studio.cubismMocList.Count > 0 && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
if (m_Script.m_ClassName == "CubismMoc")
{
selectedTypes |= SelectedAssetType.MonoBehaviourMoc;
}
else if (m_Script.m_ClassName == "CubismFadeMotionData")
{
selectedTypes |= SelectedAssetType.MonoBehaviourFade;
}
else if (m_Script.m_ClassName == "CubismFadeMotionList")
{
selectedTypes |= SelectedAssetType.MonoBehaviourFadeLst;
}
}
break;
case AnimationClip _:
selectedTypes |= SelectedAssetType.AnimationClip;
break;
case Animator _:
selectedTypes |= SelectedAssetType.Animator;
break;
}
} }
exportAnimatorWithSelectedAnimationClipMenuItem.Visible = (selectedTypes & SelectedAssetType.Animator) !=0 && (selectedTypes & SelectedAssetType.AnimationClip) != 0;
exportAsLive2DModelToolStripMenuItem.Visible = (selectedTypes & SelectedAssetType.MonoBehaviourMoc) != 0;
exportL2DWithFadeLstToolStripMenuItem.Visible = (selectedTypes & SelectedAssetType.MonoBehaviourMoc) !=0 && (selectedTypes & SelectedAssetType.MonoBehaviourFadeLst) != 0;
exportL2DWithFadeToolStripMenuItem.Visible = (selectedTypes & SelectedAssetType.MonoBehaviourMoc) != 0 && (selectedTypes & SelectedAssetType.MonoBehaviourFade) !=0;
exportL2DWithClipsToolStripMenuItem.Visible = (selectedTypes & SelectedAssetType.MonoBehaviourMoc) !=0 && (selectedTypes & SelectedAssetType.AnimationClip) != 0;
} }
var selectedElement = assetListView.HitTest(new Point(e.X, e.Y)); var selectedElement = assetListView.HitTest(new Point(e.X, e.Y));
@@ -1569,15 +1561,16 @@ namespace AssetStudioGUI
private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e) private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e)
{ {
var selectAsset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]]; var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
var args = $"/select, \"{selectAsset.SourceFile.originalPath ?? selectAsset.SourceFile.fullName}\""; var args = $"/select, \"{selectasset.SourceFile.originalPath ?? selectasset.SourceFile.fullName}\"";
var pfi = new ProcessStartInfo("explorer.exe", args); var pfi = new ProcessStartInfo("explorer.exe", args);
Process.Start(pfi); Process.Start(pfi);
} }
private void exportAnimatorWithAnimationClipMenuItem_Click(object sender, EventArgs e) private void exportAnimatorwithAnimationClipMenuItem_Click(object sender, EventArgs e)
{ {
AssetItem animator = null; AssetItem animator = null;
List<AssetItem> animationList = new List<AssetItem>();
var selectedAssets = GetSelectedAssets(); var selectedAssets = GetSelectedAssets();
foreach (var assetPreloadData in selectedAssets) foreach (var assetPreloadData in selectedAssets)
{ {
@@ -1585,6 +1578,10 @@ namespace AssetStudioGUI
{ {
animator = assetPreloadData; animator = assetPreloadData;
} }
else if (assetPreloadData.Type == ClassIDType.AnimationClip)
{
animationList.Add(assetPreloadData);
}
} }
if (animator != null) if (animator != null)
@@ -1595,7 +1592,7 @@ namespace AssetStudioGUI
{ {
saveDirectoryBackup = saveFolderDialog.Folder; saveDirectoryBackup = saveFolderDialog.Folder;
var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar; var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar;
ExportAnimatorWithAnimationClip(animator, selectedAnimationAssetsList, exportPath); ExportAnimatorWithAnimationClip(animator, animationList, exportPath);
} }
} }
} }
@@ -1605,7 +1602,7 @@ namespace AssetStudioGUI
ExportObjects(false); ExportObjects(false);
} }
private void exportObjectsWithAnimationClipMenuItem_Click(object sender, EventArgs e) private void exportObjectswithAnimationClipMenuItem_Click(object sender, EventArgs e)
{ {
ExportObjects(true); ExportObjects(true);
} }
@@ -1638,12 +1635,12 @@ namespace AssetStudioGUI
} }
} }
private void exportSelectedObjectsMergeToolStripMenuItem_Click(object sender, EventArgs e) private void exportSelectedObjectsmergeToolStripMenuItem_Click(object sender, EventArgs e)
{ {
ExportMergeObjects(false); ExportMergeObjects(false);
} }
private void exportSelectedObjectsMergeWithAnimationClipToolStripMenuItem_Click(object sender, EventArgs e) private void exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem_Click(object sender, EventArgs e)
{ {
ExportMergeObjects(true); ExportMergeObjects(true);
} }
@@ -1686,10 +1683,10 @@ namespace AssetStudioGUI
private void goToSceneHierarchyToolStripMenuItem_Click(object sender, EventArgs e) private void goToSceneHierarchyToolStripMenuItem_Click(object sender, EventArgs e)
{ {
var selectAsset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]]; var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
if (selectAsset.TreeNode != null) if (selectasset.TreeNode != null)
{ {
sceneTreeView.SelectedNode = selectAsset.TreeNode; sceneTreeView.SelectedNode = selectasset.TreeNode;
tabControl1.SelectedTab = tabPage1; tabControl1.SelectedTab = tabPage1;
} }
} }
@@ -1754,7 +1751,7 @@ namespace AssetStudioGUI
ExportAssetsList(ExportFilter.Filtered); ExportAssetsList(ExportFilter.Filtered);
} }
private void exportAllObjectsSplitToolStripMenuItem1_Click(object sender, EventArgs e) private void exportAllObjectssplitToolStripMenuItem1_Click(object sender, EventArgs e)
{ {
if (sceneTreeView.Nodes.Count > 0) if (sceneTreeView.Nodes.Count > 0)
{ {
@@ -1775,44 +1772,14 @@ namespace AssetStudioGUI
private void assetListView_SelectedIndexChanged(object sender, EventArgs e) private void assetListView_SelectedIndexChanged(object sender, EventArgs e)
{ {
ProcessSelectedItems(); if (assetListView.SelectedIndices.Count > 1)
StatusStripUpdate($"Selected {assetListView.SelectedIndices.Count} assets.");
} }
private void assetListView_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e) private void assetListView_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
{
ProcessSelectedItems();
}
private void ProcessSelectedItems()
{ {
if (assetListView.SelectedIndices.Count > 1) if (assetListView.SelectedIndices.Count > 1)
{
StatusStripUpdate($"Selected {assetListView.SelectedIndices.Count} assets."); StatusStripUpdate($"Selected {assetListView.SelectedIndices.Count} assets.");
}
var selectedIndicesList = assetListView.SelectedIndices.Cast<int>().ToList();
var addedIndices = selectedIndicesList.Except(selectedIndicesPrevList).ToArray();
foreach (var itemIndex in addedIndices)
{
selectedIndicesPrevList.Add(itemIndex);
var selectedItem = (AssetItem)assetListView.Items[itemIndex];
if (selectedItem.Type == ClassIDType.AnimationClip)
{
selectedAnimationAssetsList.Add(selectedItem);
}
}
var removedIndices = selectedIndicesPrevList.Except(selectedIndicesList).ToArray();
foreach (var itemIndex in removedIndices)
{
selectedIndicesPrevList.Remove(itemIndex);
var unselectedItem = (AssetItem)assetListView.Items[itemIndex];
if (unselectedItem.Type == ClassIDType.AnimationClip)
{
selectedAnimationAssetsList.Remove(unselectedItem);
}
}
} }
private List<AssetItem> GetSelectedAssets() private List<AssetItem> GetSelectedAssets()
@@ -1882,16 +1849,16 @@ namespace AssetStudioGUI
{ {
visibleAssets = visibleAssets.FindAll(x => Regex.IsMatch(x.SubItems[1].Text, pattern, regexOptions)); visibleAssets = visibleAssets.FindAll(x => Regex.IsMatch(x.SubItems[1].Text, pattern, regexOptions));
} }
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.PaleGreen; listSearch.BackColor = System.Drawing.Color.PaleGreen;
} }
catch (ArgumentException e) catch (ArgumentException e)
{ {
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.FromArgb(255, 160, 160); listSearch.BackColor = System.Drawing.Color.FromArgb(255, 160, 160);
StatusStripUpdate($"Regex error: {e.Message}"); StatusStripUpdate($"Regex error: {e.Message}");
} }
catch (RegexMatchTimeoutException) catch (RegexMatchTimeoutException)
{ {
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.FromArgb(255, 160, 160); listSearch.BackColor = System.Drawing.Color.FromArgb(255, 160, 160);
StatusStripUpdate($"Timeout error"); StatusStripUpdate($"Timeout error");
} }
break; break;
@@ -1924,19 +1891,6 @@ namespace AssetStudioGUI
toExportAssets = visibleAssets; toExportAssets = visibleAssets;
break; break;
} }
if (toExportAssets != null && filterTypeToolStripMenuItem.DropDownItems.ContainsKey("Texture2DArray"))
{
var tex2dArrayImgPathIdSet = toExportAssets.FindAll(x => x.Type == ClassIDType.Texture2DArrayImage).Select(x => x.m_PathID).ToHashSet();
foreach (var pathId in tex2dArrayImgPathIdSet)
{
toExportAssets = toExportAssets.Where(x =>
x.Type != ClassIDType.Texture2DArray
|| (x.Type == ClassIDType.Texture2DArray && x.m_PathID != pathId))
.ToList();
}
}
Studio.ExportAssets(saveFolderDialog.Folder, toExportAssets, exportType); Studio.ExportAssets(saveFolderDialog.Folder, toExportAssets, exportType);
} }
} }
@@ -1982,7 +1936,7 @@ namespace AssetStudioGUI
private void toolStripMenuItem15_Click(object sender, EventArgs e) private void toolStripMenuItem15_Click(object sender, EventArgs e)
{ {
GUILogger.ShowDebugMessage = toolStripMenuItem15.Checked; logger.ShowErrorMessage = toolStripMenuItem15.Checked;
} }
private void sceneTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) private void sceneTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
@@ -2005,7 +1959,7 @@ namespace AssetStudioGUI
private void clearSelectionToolStripMenuItem_Click(object sender, EventArgs e) private void clearSelectionToolStripMenuItem_Click(object sender, EventArgs e)
{ {
treeRecursionEnabled = false; treeRecursionEnabled = false;
for (var i = 0; i < treeNodeSelectedList.Count; i++) for(var i = 0; i < treeNodeSelectedList.Count; i++)
{ {
treeNodeSelectedList[i].Checked = false; treeNodeSelectedList[i].Checked = false;
} }
@@ -2040,6 +1994,26 @@ namespace AssetStudioGUI
sceneTreeView.EndUpdate(); sceneTreeView.EndUpdate();
} }
private void akFixFaceSpriteNamesToolStripMenuItem_Check(object sender, EventArgs e)
{
Properties.Settings.Default.fixFaceSpriteNames = akFixFaceSpriteNamesToolStripMenuItem.Checked;
Properties.Settings.Default.Save();
FixFaceSpriteNames();
}
private void akUseExternalAlphaToolStripMenuItem_Check(object sender, EventArgs e)
{
Properties.Settings.Default.useExternalAlpha = akUseExternalAlphaToolStripMenuItem.Checked;
Properties.Settings.Default.Save();
if (lastSelectedItem?.Type == ClassIDType.Sprite)
{
StatusStripUpdate("");
PreviewAsset(lastSelectedItem);
assetInfoLabel.Text = lastSelectedItem.InfoText;
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e) private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{ {
var aboutForm = new AboutForm(); var aboutForm = new AboutForm();
@@ -2048,7 +2022,7 @@ namespace AssetStudioGUI
private void listSearchFilterMode_SelectedIndexChanged(object sender, EventArgs e) private void listSearchFilterMode_SelectedIndexChanged(object sender, EventArgs e)
{ {
listSearch.BackColor = SystemColors.Window; listSearch.BackColor = System.Drawing.Color.White;
if (listSearch.Text != " Filter ") if (listSearch.Text != " Filter ")
{ {
FilterAssetList(); FilterAssetList();
@@ -2062,6 +2036,42 @@ namespace AssetStudioGUI
listSearch.SelectionStart = listSearch.Text.Length; listSearch.SelectionStart = listSearch.Text.Length;
} }
private void allLive2DModelsToolStripMenuItem_Click(object sender, EventArgs e)
{
if (exportableAssets.Count > 0)
{
var cubismMocs = exportableAssets.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.Info("Live2D Cubism models were not found.");
return;
}
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
Progress.Reset();
BeginInvoke(new Action(() => { progressBar1.Style = ProgressBarStyle.Marquee; }));
Studio.ExportLive2D(cubismMocs, saveFolderDialog.Folder);
}
}
else
{
Logger.Info("No exportable assets loaded");
}
}
private void selectRelatedAsset(object sender, EventArgs e) private void selectRelatedAsset(object sender, EventArgs e)
{ {
var selectedItem = (ToolStripMenuItem)sender; var selectedItem = (ToolStripMenuItem)sender;
@@ -2165,158 +2175,6 @@ namespace AssetStudioGUI
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
} }
private void exportAllL2D_Click(object sender, EventArgs e)
{
if (exportableAssets.Count > 0)
{
if (Studio.cubismMocList.Count == 0)
{
Logger.Info("Live2D Cubism models were not found.");
return;
}
Live2DExporter();
}
else
{
Logger.Info("No exportable assets loaded");
}
}
private void exportSelectedL2D_Click(object sender, EventArgs e)
{
ExportSelectedL2DModels(ExportL2DFilter.Selected);
}
private void exportSelectedL2DWithClips_Click(object sender, EventArgs e)
{
ExportSelectedL2DModels(ExportL2DFilter.SelectedWithClips);
}
private void exportSelectedL2DWithFadeMotions_Click(object sender, EventArgs e)
{
ExportSelectedL2DModels(ExportL2DFilter.SelectedWithFade);
}
private void exportSelectedL2DWithFadeList_Click(object sender, EventArgs e)
{
ExportSelectedL2DModels(ExportL2DFilter.SelectedWithFadeList);
}
private void ExportSelectedL2DModels(ExportL2DFilter l2dExportMode)
{
if (exportableAssets.Count == 0)
{
Logger.Info("No exportable assets loaded");
return;
}
if (Studio.cubismMocList.Count == 0)
{
Logger.Info("Live2D Cubism models were not found.");
return;
}
var selectedAssets = GetSelectedAssets();
if (selectedAssets.Count == 0)
return;
MonoBehaviour selectedFadeLst = null;
var selectedMocs = new List<MonoBehaviour>();
var selectedFadeMotions = new List<MonoBehaviour>();
var selectedClips = new List<AnimationClip>();
foreach (var assetItem in selectedAssets)
{
if (assetItem.Asset is MonoBehaviour m_MonoBehaviour && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{
if (m_Script.m_ClassName == "CubismMoc")
{
selectedMocs.Add(m_MonoBehaviour);
}
else if (m_Script.m_ClassName == "CubismFadeMotionData")
{
selectedFadeMotions.Add(m_MonoBehaviour);
}
else if (m_Script.m_ClassName == "CubismFadeMotionList")
{
selectedFadeLst = m_MonoBehaviour;
}
}
else if (assetItem.Asset is AnimationClip m_AnimationClip)
{
selectedClips.Add(m_AnimationClip);
}
}
if (selectedMocs.Count == 0)
{
Logger.Info("Live2D Cubism models were not selected.");
return;
}
switch (l2dExportMode)
{
case ExportL2DFilter.Selected:
Live2DExporter(selectedMocs);
break;
case ExportL2DFilter.SelectedWithFadeList:
if (selectedFadeLst == null)
{
Logger.Info("Fade Motion List was not selected.");
return;
}
Live2DExporter(selectedMocs, selFadeLst: selectedFadeLst);
break;
case ExportL2DFilter.SelectedWithFade:
if (selectedFadeMotions.Count == 0)
{
Logger.Info("No Fade motions were selected.");
return;
}
Live2DExporter(selectedMocs, selFadeMotions: selectedFadeMotions);
break;
case ExportL2DFilter.SelectedWithClips:
if (selectedClips.Count == 0)
{
Logger.Info("No AnimationClips were selected.");
return;
}
Live2DExporter(selectedMocs, selectedClips);
break;
}
}
private void Live2DExporter(List<MonoBehaviour> selMocs = null, List<AnimationClip> selClipMotions = null, List<MonoBehaviour> selFadeMotions = null, MonoBehaviour selFadeLst = null)
{
var saveFolderDialog = new OpenFolderDialog();
saveFolderDialog.InitialFolder = saveDirectoryBackup;
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
{
timer.Stop();
saveDirectoryBackup = saveFolderDialog.Folder;
Progress.Reset();
BeginInvoke(new Action(() => { progressBar1.Style = ProgressBarStyle.Marquee; }));
Studio.ExportLive2D(saveFolderDialog.Folder, selMocs, selClipMotions, selFadeMotions, selFadeLst);
}
}
private void customCompressionZstd_CheckedChanged(object sender, EventArgs e)
{
customCompressionLZ4ToolStripMenuItem.Checked = !customCompressionZstdToolStripMenuItem.Checked;
assetsManager.ZstdEnabled = customCompressionZstdToolStripMenuItem.Checked;
}
private void customCompressionLZ4_CheckedChanged(object sender, EventArgs e)
{
customCompressionZstdToolStripMenuItem.Checked = !customCompressionLZ4ToolStripMenuItem.Checked;
assetsManager.ZstdEnabled = customCompressionZstdToolStripMenuItem.Checked;
}
private void useAssetLoadingViaTypetreeToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
{
var isEnabled = useAssetLoadingViaTypetreeToolStripMenuItem.Checked;
assetsManager.LoadingViaTypeTreeEnabled = isEnabled;
Properties.Settings.Default.useTypetreeLoading = isEnabled;
Properties.Settings.Default.Save();
}
#region FMOD #region FMOD
private void FMODinit() private void FMODinit()
{ {
@@ -2329,7 +2187,7 @@ namespace AssetStudioGUI
ERRCHECK(result); ERRCHECK(result);
if (version < FMOD.VERSION.number) if (version < FMOD.VERSION.number)
{ {
Logger.Error($"Error! You are using an old version of FMOD {version:X}. This program requires {FMOD.VERSION.number:X}."); Logger.Error($"Error! You are using an old version of FMOD {version:X}. This program requires {FMOD.VERSION.number:X}.");
Application.Exit(); Application.Exit();
} }

View File

@@ -0,0 +1,296 @@
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;
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);
tex = avgSprite.FullTexture.ConvertToImage(true);
var facePos = tex.Width == 512 ? avgSprite.FacePos / 2 : avgSprite.FacePos; // ?
var faceSize = tex.Width == 512 ? avgSprite.FaceSize / 2 : avgSprite.FaceSize;
if (new Size(faceImage.Width, faceImage.Height) != avgSprite.FaceSize)
{
faceImage.Mutate(x => x.Resize(new ResizeOptions { Size = faceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
faceAlpha.Mutate(x => x.Resize(new ResizeOptions { Size = faceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch }));
}
tex.Mutate(x => x.DrawImage(faceImage, facePos, opacity: 1f));
alphaTex.Mutate(x => x.DrawImage(faceAlpha, 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) && avgSprite != null && avgSprite.IsHubParsed)
{
if (!avgSprite.IsFaceSprite)
{
return m_Texture2D.ConvertToImage(true);
}
var faceImage = m_Texture2D.ConvertToImage(true);
var tex = avgSprite.FullTexture.ConvertToImage(true);
if (new Size(faceImage.Width, faceImage.Height) != avgSprite.FaceSize)
{
faceImage.Mutate(x => x.Resize(new ResizeOptions {Size = avgSprite.FaceSize, Sampler = KnownResamplers.Lanczos3, Mode = ResizeMode.Stretch}));
}
tex.Mutate(x => x.DrawImage(faceImage, avgSprite.FacePos, opacity: 1f));
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)
{
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)(new Size(originalImage.Width, originalImage.Height) / 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;
}
}
}

View File

@@ -0,0 +1,149 @@
using Arknights.AvgCharHubMono;
using AssetStudio;
using AssetStudioGUI;
using SixLabors.ImageSharp;
using System.Linq;
using System;
using System.Collections.Specialized;
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 scriptAssets = Studio.exportableAssets.FindAll(x =>
x.Type == ClassIDType.MonoBehaviour
&& x.Container == assetItem.Container);
if (scriptAssets.Count == 0)
{
Logger.Warning("No MonoBehaviours were found.");
return false;
}
OrderedDictionary spriteHubDict = null;
var isGrouped = false;
foreach (var scriptAsset in scriptAssets)
{
var scriptAssetDict = ((MonoBehaviour)scriptAsset.Asset).ToType();
if (scriptAssetDict == null)
{
Logger.Warning("MonoBehaviour is not readable.");
return false;
}
if (scriptAssetDict.Contains("spriteGroups"))
{
spriteHubDict = scriptAssetDict;
isGrouped = true;
break;
}
if (scriptAssetDict.Contains("sprites"))
{
spriteHubDict = scriptAssetDict;
break;
}
}
if (spriteHubDict == null)
{
Logger.Warning("AVGCharacterSpriteHub is not readable.");
return false;
}
var spriteHubJson = JsonConvert.SerializeObject(spriteHubDict);
if (isGrouped)
{
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) //If face data exist
{
var fullTexSpriteData = spriteHubData.Sprites.Last(); //Last sprite item in the list usually contains PathID of Sprite with full texture
var curSprite = (Sprite)assetItem.Asset;
IsFaceSprite = curSprite.m_Rect.width <= 256 && curSprite.m_Rect.height <= 256 && curSprite.m_PathID != fullTexSpriteData.Sprite.m_PathID;
var curSpriteAlphaID = curSpriteData.AlphaTex.m_PathID;
var curSpriteAlphaTex = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteAlphaID)?.Asset;
if (curSpriteAlphaTex != null)
{
FaceSpriteAlphaTexture = IsFaceSprite ? curSpriteAlphaTex : null;
fullTexSpriteData = IsFaceSprite ? fullTexSpriteData : curSpriteData;
}
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));
}
else
{
FullAlphaTexture = (Texture2D)Studio.exportableAssets.Find(x => x.m_PathID == curSpriteData.AlphaTex.m_PathID)?.Asset;
}
}
}
}
}

View 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; }
}
}

View 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;
}
}
}

View 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; }
}
}

View File

@@ -1,5 +1,6 @@
using System.Windows.Forms; using System.Windows.Forms;
using AssetStudio; using AssetStudio;
using Arknights;
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
@@ -15,6 +16,7 @@ namespace AssetStudioGUI
public string InfoText; public string InfoText;
public string UniqueID; public string UniqueID;
public GameObjectTreeNode TreeNode; public GameObjectTreeNode TreeNode;
public PortraitSprite AkPortraitSprite;
public AssetItem(Object asset) public AssetItem(Object asset)
{ {
@@ -26,6 +28,19 @@ namespace AssetStudioGUI
FullSize = asset.byteSize; 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() public void SetSubItems()
{ {
SubItems.AddRange(new[] SubItems.AddRange(new[]

View File

@@ -43,6 +43,6 @@ namespace AssetStudioGUI
public Bitmap Bitmap => m_bitmap; public Bitmap Bitmap => m_bitmap;
private Bitmap m_bitmap; private Bitmap m_bitmap;
private GCHandle m_handle; private readonly GCHandle m_handle;
} }
} }

View File

@@ -32,8 +32,6 @@
this.OKbutton = new System.Windows.Forms.Button(); this.OKbutton = new System.Windows.Forms.Button();
this.Cancel = new System.Windows.Forms.Button(); this.Cancel = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox(); this.groupBox1 = new System.Windows.Forms.GroupBox();
this.filenameFormatLabel = new System.Windows.Forms.Label();
this.filenameFormatComboBox = new System.Windows.Forms.ComboBox();
this.exportSpriteWithAlphaMask = new System.Windows.Forms.CheckBox(); this.exportSpriteWithAlphaMask = new System.Windows.Forms.CheckBox();
this.openAfterExport = new System.Windows.Forms.CheckBox(); this.openAfterExport = new System.Windows.Forms.CheckBox();
this.restoreExtensionName = new System.Windows.Forms.CheckBox(); this.restoreExtensionName = new System.Windows.Forms.CheckBox();
@@ -71,10 +69,18 @@
this.castToBone = new System.Windows.Forms.CheckBox(); this.castToBone = new System.Windows.Forms.CheckBox();
this.exportAllNodes = new System.Windows.Forms.CheckBox(); this.exportAllNodes = new System.Windows.Forms.CheckBox();
this.eulerFilter = new System.Windows.Forms.CheckBox(); this.eulerFilter = new System.Windows.Forms.CheckBox();
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.optionTooltip = new System.Windows.Forms.ToolTip(this.components); this.optionTooltip = new System.Windows.Forms.ToolTip(this.components);
this.parallelExportUpDown = new System.Windows.Forms.NumericUpDown();
this.parallelExportCheckBox = new System.Windows.Forms.CheckBox();
this.parallelExportMaxLabel = new System.Windows.Forms.Label();
this.groupBox1.SuspendLayout(); this.groupBox1.SuspendLayout();
this.panel1.SuspendLayout(); this.panel1.SuspendLayout();
this.l2dGroupBox.SuspendLayout(); this.l2dGroupBox.SuspendLayout();
@@ -83,15 +89,17 @@
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.parallelExportUpDown)).BeginInit(); this.akSpritesAlphaGroupBox.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.akAlphaMaskGammaTrackBar)).BeginInit();
this.akSpritesExportGroupBox.SuspendLayout();
this.SuspendLayout(); this.SuspendLayout();
// //
// OKbutton // OKbutton
// //
this.OKbutton.Location = new System.Drawing.Point(381, 380); this.OKbutton.Location = new System.Drawing.Point(681, 381);
this.OKbutton.Name = "OKbutton"; this.OKbutton.Name = "OKbutton";
this.OKbutton.Size = new System.Drawing.Size(75, 23); this.OKbutton.Size = new System.Drawing.Size(75, 23);
this.OKbutton.TabIndex = 4; this.OKbutton.TabIndex = 6;
this.OKbutton.Text = "OK"; this.OKbutton.Text = "OK";
this.OKbutton.UseVisualStyleBackColor = true; this.OKbutton.UseVisualStyleBackColor = true;
this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click); this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click);
@@ -99,10 +107,10 @@
// Cancel // Cancel
// //
this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.Cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Cancel.Location = new System.Drawing.Point(462, 380); this.Cancel.Location = new System.Drawing.Point(762, 381);
this.Cancel.Name = "Cancel"; this.Cancel.Name = "Cancel";
this.Cancel.Size = new System.Drawing.Size(75, 23); this.Cancel.Size = new System.Drawing.Size(75, 23);
this.Cancel.TabIndex = 5; this.Cancel.TabIndex = 7;
this.Cancel.Text = "Cancel"; this.Cancel.Text = "Cancel";
this.Cancel.UseVisualStyleBackColor = true; this.Cancel.UseVisualStyleBackColor = true;
this.Cancel.Click += new System.EventHandler(this.Cancel_Click); this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
@@ -110,11 +118,6 @@
// groupBox1 // groupBox1
// //
this.groupBox1.AutoSize = true; this.groupBox1.AutoSize = true;
this.groupBox1.Controls.Add(this.parallelExportMaxLabel);
this.groupBox1.Controls.Add(this.parallelExportCheckBox);
this.groupBox1.Controls.Add(this.parallelExportUpDown);
this.groupBox1.Controls.Add(this.filenameFormatLabel);
this.groupBox1.Controls.Add(this.filenameFormatComboBox);
this.groupBox1.Controls.Add(this.exportSpriteWithAlphaMask); this.groupBox1.Controls.Add(this.exportSpriteWithAlphaMask);
this.groupBox1.Controls.Add(this.openAfterExport); this.groupBox1.Controls.Add(this.openAfterExport);
this.groupBox1.Controls.Add(this.restoreExtensionName); this.groupBox1.Controls.Add(this.restoreExtensionName);
@@ -130,28 +133,6 @@
this.groupBox1.TabStop = false; this.groupBox1.TabStop = false;
this.groupBox1.Text = "Export"; this.groupBox1.Text = "Export";
// //
// filenameFormatLabel
//
this.filenameFormatLabel.AutoSize = true;
this.filenameFormatLabel.Location = new System.Drawing.Point(177, 18);
this.filenameFormatLabel.Name = "filenameFormatLabel";
this.filenameFormatLabel.Size = new System.Drawing.Size(84, 13);
this.filenameFormatLabel.TabIndex = 10;
this.filenameFormatLabel.Text = "File name format";
//
// filenameFormatComboBox
//
this.filenameFormatComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.filenameFormatComboBox.FormattingEnabled = true;
this.filenameFormatComboBox.Items.AddRange(new object[] {
"assetName",
"assetName@pathID",
"pathID"});
this.filenameFormatComboBox.Location = new System.Drawing.Point(177, 35);
this.filenameFormatComboBox.Name = "filenameFormatComboBox";
this.filenameFormatComboBox.Size = new System.Drawing.Size(118, 21);
this.filenameFormatComboBox.TabIndex = 9;
//
// exportSpriteWithAlphaMask // exportSpriteWithAlphaMask
// //
this.exportSpriteWithAlphaMask.AutoSize = true; this.exportSpriteWithAlphaMask.AutoSize = true;
@@ -198,7 +179,6 @@
"container path", "container path",
"container path full (with name)", "container path full (with name)",
"source file name", "source file name",
"scene hierarchy",
"do not group"}); "do not group"});
this.assetGroupOptions.Location = new System.Drawing.Point(6, 35); this.assetGroupOptions.Location = new System.Drawing.Point(6, 35);
this.assetGroupOptions.Name = "assetGroupOptions"; this.assetGroupOptions.Name = "assetGroupOptions";
@@ -221,9 +201,9 @@
this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked; this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;
this.convertAudio.Location = new System.Drawing.Point(6, 173); this.convertAudio.Location = new System.Drawing.Point(6, 173);
this.convertAudio.Name = "convertAudio"; this.convertAudio.Name = "convertAudio";
this.convertAudio.Size = new System.Drawing.Size(213, 17); this.convertAudio.Size = new System.Drawing.Size(179, 17);
this.convertAudio.TabIndex = 7; this.convertAudio.TabIndex = 7;
this.convertAudio.Text = "Convert FMOD AudioClip to WAV(PCM)"; this.convertAudio.Text = "Convert AudioClip to WAV(PCM)";
this.convertAudio.UseVisualStyleBackColor = true; this.convertAudio.UseVisualStyleBackColor = true;
// //
// panel1 // panel1
@@ -339,7 +319,7 @@
// //
// l2dAnimationClipRadioButton // l2dAnimationClipRadioButton
// //
this.l2dAnimationClipRadioButton.AccessibleName = "AnimationClipV2"; this.l2dAnimationClipRadioButton.AccessibleName = "AnimationClip";
this.l2dAnimationClipRadioButton.AutoSize = true; this.l2dAnimationClipRadioButton.AutoSize = true;
this.l2dAnimationClipRadioButton.Location = new System.Drawing.Point(172, 5); this.l2dAnimationClipRadioButton.Location = new System.Drawing.Point(172, 5);
this.l2dAnimationClipRadioButton.Name = "l2dAnimationClipRadioButton"; this.l2dAnimationClipRadioButton.Name = "l2dAnimationClipRadioButton";
@@ -600,52 +580,130 @@
this.eulerFilter.Text = "EulerFilter"; this.eulerFilter.Text = "EulerFilter";
this.eulerFilter.UseVisualStyleBackColor = true; this.eulerFilter.UseVisualStyleBackColor = true;
// //
// parallelExportUpDown // akResamplerLabel
// //
this.parallelExportUpDown.Location = new System.Drawing.Point(209, 218); this.akResamplerLabel.AutoSize = true;
this.parallelExportUpDown.Maximum = new decimal(new int[] { this.akResamplerLabel.Location = new System.Drawing.Point(6, 21);
8, this.akResamplerLabel.Name = "akResamplerLabel";
0, this.akResamplerLabel.Size = new System.Drawing.Size(120, 13);
0, this.akResamplerLabel.TabIndex = 1;
0}); this.akResamplerLabel.Text = "Alpha texture resampler:";
this.parallelExportUpDown.Minimum = new decimal(new int[] { this.optionTooltip.SetToolTip(this.akResamplerLabel, "Only affects exported images");
1,
0,
0,
0});
this.parallelExportUpDown.Name = "parallelExportUpDown";
this.parallelExportUpDown.Size = new System.Drawing.Size(42, 20);
this.parallelExportUpDown.TabIndex = 13;
this.parallelExportUpDown.Value = new decimal(new int[] {
1,
0,
0,
0});
// //
// parallelExportCheckBox // akResamplerComboBox
// //
this.parallelExportCheckBox.AutoSize = true; this.akResamplerComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.parallelExportCheckBox.Checked = true; this.akResamplerComboBox.FormattingEnabled = true;
this.parallelExportCheckBox.CheckState = System.Windows.Forms.CheckState.Checked; this.akResamplerComboBox.Items.AddRange(new object[] {
this.parallelExportCheckBox.Location = new System.Drawing.Point(6, 219); "Nearest Neighbor",
this.parallelExportCheckBox.Name = "parallelExportCheckBox"; "Bilinear",
this.parallelExportCheckBox.Size = new System.Drawing.Size(203, 17); "Bicubic",
this.parallelExportCheckBox.TabIndex = 15; "Mitchell-Netravali",
this.parallelExportCheckBox.Text = "Export in parallel with number of tasks"; "Spline",
this.optionTooltip.SetToolTip(this.parallelExportCheckBox, "*Requires slightly more RAM than in single-task mode"); "Welch"});
this.parallelExportCheckBox.UseVisualStyleBackColor = true; this.akResamplerComboBox.Location = new System.Drawing.Point(132, 18);
this.parallelExportCheckBox.CheckedChanged += new System.EventHandler(this.parallelExportCheckBox_CheckedChanged); this.akResamplerComboBox.Name = "akResamplerComboBox";
this.akResamplerComboBox.Size = new System.Drawing.Size(162, 21);
this.akResamplerComboBox.TabIndex = 2;
this.optionTooltip.SetToolTip(this.akResamplerComboBox, "Only affects exported images");
// //
// parallelExportMaxLabel // akSpritesAlphaGroupBox
// //
this.parallelExportMaxLabel.AutoSize = true; this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaNoteLabel);
this.parallelExportMaxLabel.ForeColor = System.Drawing.SystemColors.ControlDark; this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerDescLabel);
this.parallelExportMaxLabel.Location = new System.Drawing.Point(256, 221); this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerLabel);
this.parallelExportMaxLabel.Name = "parallelExportMaxLabel"; this.akSpritesAlphaGroupBox.Controls.Add(this.akResamplerComboBox);
this.parallelExportMaxLabel.Size = new System.Drawing.Size(33, 13); this.akSpritesAlphaGroupBox.Controls.Add(this.akResizedOnlyCheckBox);
this.parallelExportMaxLabel.TabIndex = 16; this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaValueLabel);
this.parallelExportMaxLabel.Text = "Max: "; this.akSpritesAlphaGroupBox.Controls.Add(this.akGammaLabel);
this.optionTooltip.SetToolTip(this.parallelExportMaxLabel, "*The maximum number matches the number of CPU cores"); 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 = 4;
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 = 8;
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 = 3;
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 = 6;
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 = 5;
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 = 4;
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 = 7;
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 = 5;
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 = 1;
this.akAddAliasesCheckBox.Text = "Add aliases to avg character sprite names (if exist)";
this.akAddAliasesCheckBox.UseVisualStyleBackColor = true;
// //
// ExportOptions // ExportOptions
// //
@@ -653,8 +711,10 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.Cancel; this.CancelButton = this.Cancel;
this.ClientSize = new System.Drawing.Size(549, 416); this.ClientSize = new System.Drawing.Size(849, 416);
this.Controls.Add(this.l2dGroupBox); this.Controls.Add(this.l2dGroupBox);
this.Controls.Add(this.akSpritesExportGroupBox);
this.Controls.Add(this.akSpritesAlphaGroupBox);
this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox2);
this.Controls.Add(this.groupBox1); this.Controls.Add(this.groupBox1);
this.Controls.Add(this.Cancel); this.Controls.Add(this.Cancel);
@@ -680,7 +740,11 @@
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.parallelExportUpDown)).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.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@@ -722,16 +786,22 @@
private System.Windows.Forms.ToolTip optionTooltip; private System.Windows.Forms.ToolTip optionTooltip;
private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask; private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask;
private System.Windows.Forms.RadioButton towebp; 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;
private System.Windows.Forms.GroupBox l2dGroupBox; private System.Windows.Forms.GroupBox l2dGroupBox;
private System.Windows.Forms.CheckBox l2dForceBezierCheckBox; private System.Windows.Forms.CheckBox l2dForceBezierCheckBox;
private System.Windows.Forms.Label l2dMotionExportMethodLabel; private System.Windows.Forms.Label l2dMotionExportMethodLabel;
private System.Windows.Forms.RadioButton l2dAnimationClipRadioButton; private System.Windows.Forms.RadioButton l2dAnimationClipRadioButton;
private System.Windows.Forms.RadioButton l2dMonoBehaviourRadioButton; private System.Windows.Forms.RadioButton l2dMonoBehaviourRadioButton;
private System.Windows.Forms.Panel l2dMotionExportMethodPanel; private System.Windows.Forms.Panel l2dMotionExportMethodPanel;
private System.Windows.Forms.ComboBox filenameFormatComboBox;
private System.Windows.Forms.Label filenameFormatLabel;
private System.Windows.Forms.NumericUpDown parallelExportUpDown;
private System.Windows.Forms.CheckBox parallelExportCheckBox;
private System.Windows.Forms.Label parallelExportMaxLabel;
} }
} }

View File

@@ -30,16 +30,17 @@ namespace AssetStudioGUI
scaleFactor.Value = Properties.Settings.Default.scaleFactor; scaleFactor.Value = Properties.Settings.Default.scaleFactor;
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion; fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat; 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;
var defaultMotionMode = Properties.Settings.Default.l2dMotionMode.ToString(); var defaultMotionMode = Properties.Settings.Default.l2dMotionMode.ToString();
((RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => x.AccessibleName == defaultMotionMode)).Checked = true; ((RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => x.AccessibleName == defaultMotionMode)).Checked = true;
l2dForceBezierCheckBox.Checked = Properties.Settings.Default.l2dForceBezier; l2dForceBezierCheckBox.Checked = Properties.Settings.Default.l2dForceBezier;
filenameFormatComboBox.SelectedIndex = Properties.Settings.Default.filenameFormat;
var maxParallelTasks = Environment.ProcessorCount;
var taskCount = Properties.Settings.Default.parallelExportCount;
parallelExportUpDown.Maximum = maxParallelTasks;
parallelExportUpDown.Value = taskCount <= 0 ? maxParallelTasks : Math.Min(taskCount, maxParallelTasks);
parallelExportMaxLabel.Text += maxParallelTasks;
parallelExportCheckBox.Checked = Properties.Settings.Default.parallelExport;
} }
private void OKbutton_Click(object sender, EventArgs e) private void OKbutton_Click(object sender, EventArgs e)
@@ -64,26 +65,31 @@ namespace AssetStudioGUI
Properties.Settings.Default.scaleFactor = scaleFactor.Value; Properties.Settings.Default.scaleFactor = scaleFactor.Value;
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex; Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
Properties.Settings.Default.fbxFormat = fbxFormat.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;
var checkedMotionMode = (RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => ((RadioButton)x).Checked); var checkedMotionMode = (RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => ((RadioButton)x).Checked);
Properties.Settings.Default.l2dMotionMode = (CubismLive2DExtractor.Live2DMotionMode)Enum.Parse(typeof(CubismLive2DExtractor.Live2DMotionMode), checkedMotionMode.AccessibleName); Properties.Settings.Default.l2dMotionMode = (CubismLive2DExtractor.Live2DMotionMode)Enum.Parse(typeof(CubismLive2DExtractor.Live2DMotionMode), checkedMotionMode.AccessibleName);
Properties.Settings.Default.l2dForceBezier = l2dForceBezierCheckBox.Checked; Properties.Settings.Default.l2dForceBezier = l2dForceBezierCheckBox.Checked;
Properties.Settings.Default.filenameFormat = filenameFormatComboBox.SelectedIndex;
Properties.Settings.Default.parallelExport = parallelExportCheckBox.Checked;
Properties.Settings.Default.parallelExportCount = (int)parallelExportUpDown.Value;
Properties.Settings.Default.Save(); Properties.Settings.Default.Save();
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); 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) private void Cancel_Click(object sender, EventArgs e)
{ {
DialogResult = DialogResult.Cancel; DialogResult = DialogResult.Cancel;
Close(); Close();
} }
private void parallelExportCheckBox_CheckedChanged(object sender, EventArgs e)
{
parallelExportUpDown.Enabled = parallelExportCheckBox.Checked;
}
} }
} }

View File

@@ -120,10 +120,4 @@
<metadata name="optionTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="optionTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value> <value>17, 17</value>
</metadata> </metadata>
<metadata name="optionTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="optionTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root> </root>

View File

@@ -1,4 +1,7 @@
using AssetStudio; using Arknights;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using AssetStudio;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
@@ -9,6 +12,60 @@ namespace AssetStudioGUI
{ {
internal static class Exporter internal static class Exporter
{ {
public static bool ExportTexture2D(AssetItem item, string exportPath)
{
var m_Texture2D = (Texture2D)item.Asset;
if (Properties.Settings.Default.convertTexture)
{
var type = Properties.Settings.Default.convertType;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
var image = m_Texture2D.ConvertToImage(true);
if (image == null)
return false;
using (image)
{
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
}
else
{
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
return true;
}
}
public static bool ExportAudioClip(AssetItem item, string exportPath)
{
var m_AudioClip = (AudioClip)item.Asset;
var m_AudioData = m_AudioClip.m_AudioData.GetData();
if (m_AudioData == null || m_AudioData.Length == 0)
return false;
var converter = new AudioClipConverter(m_AudioClip);
if (Properties.Settings.Default.convertAudio && converter.IsSupport)
{
if (!TryExportFile(exportPath, item, ".wav", out var exportFullPath))
return false;
var buffer = converter.ConvertToWav(m_AudioData);
if (buffer == null)
return false;
File.WriteAllBytes(exportFullPath, buffer);
}
else
{
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out var exportFullPath))
return false;
File.WriteAllBytes(exportFullPath, m_AudioData);
}
return true;
}
public static bool ExportShader(AssetItem item, string exportPath) public static bool ExportShader(AssetItem item, string exportPath)
{ {
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath)) if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
@@ -183,43 +240,109 @@ namespace AssetStudioGUI
return true; return true;
} }
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 image = item.AkPortraitSprite.AkGetImage(spriteMaskMode: spriteMaskMode);
if (image != null)
{
using (image)
{
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
return true;
}
}
return false;
}
public static bool ExportRawFile(AssetItem item, string exportPath) public static bool ExportRawFile(AssetItem item, string exportPath)
{ {
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw")) if (item.Asset == null)
return false;
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
return false; return false;
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData()); File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
return true; return true;
} }
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string mode = "Export") 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;
var filenameFormatIndex = Properties.Settings.Default.filenameFormat;
switch (filenameFormatIndex)
{
case 1: //assetName@pathID
fileName = $"{fileName} @{item.m_PathID}";
break;
case 2: //pathID
fileName = item.m_PathID.ToString();
break;
}
fullPath = Path.Combine(dir, fileName + extension); fullPath = Path.Combine(dir, fileName + extension);
if (!File.Exists(fullPath)) if (!File.Exists(fullPath))
{ {
Directory.CreateDirectory(dir); Directory.CreateDirectory(dir);
return true; return true;
} }
if (filenameFormatIndex == 0) //assetName fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
if (!File.Exists(fullPath))
{ {
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension); Directory.CreateDirectory(dir);
if (!File.Exists(fullPath)) return true;
{
Directory.CreateDirectory(dir);
return true;
}
} }
Logger.Warning($"{mode} failed. File \"{fullPath.Color(ColorConsole.BrightYellow)}\" already exist");
return false; return false;
} }
@@ -276,7 +399,9 @@ namespace AssetStudioGUI
public static bool ExportDumpFile(AssetItem item, string exportPath) public static bool ExportDumpFile(AssetItem item, string exportPath)
{ {
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump")) if (item.Asset == null)
return false;
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
return false; return false;
var str = item.Asset.Dump(); var str = item.Asset.Dump();
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour) if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
@@ -284,10 +409,6 @@ namespace AssetStudioGUI
var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour); var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(m_Type); str = m_MonoBehaviour.Dump(m_Type);
} }
if (string.IsNullOrEmpty(str))
{
str = item.Asset.DumpObject();
}
if (str != null) if (str != null)
{ {
File.WriteAllText(exportFullPath, str); File.WriteAllText(exportFullPath, str);
@@ -301,11 +422,9 @@ namespace AssetStudioGUI
switch (item.Type) switch (item.Type)
{ {
case ClassIDType.Texture2D: case ClassIDType.Texture2D:
case ClassIDType.Texture2DArrayImage: return ExportTexture2D(item, exportPath);
case ClassIDType.Texture2DArray:
case ClassIDType.AudioClip: case ClassIDType.AudioClip:
case ClassIDType.Sprite: return ExportAudioClip(item, exportPath);
throw new System.NotImplementedException();
case ClassIDType.Shader: case ClassIDType.Shader:
return ExportShader(item, exportPath); return ExportShader(item, exportPath);
case ClassIDType.TextAsset: case ClassIDType.TextAsset:
@@ -320,6 +439,10 @@ namespace AssetStudioGUI
return ExportVideoClip(item, exportPath); return ExportVideoClip(item, exportPath);
case ClassIDType.MovieTexture: case ClassIDType.MovieTexture:
return ExportMovieTexture(item, exportPath); return ExportMovieTexture(item, exportPath);
case ClassIDType.Sprite:
return ExportSprite(item, exportPath);
case ClassIDType.AkPortraitSprite:
return ExportPortraitSprite(item, exportPath);
case ClassIDType.Animator: case ClassIDType.Animator:
return ExportAnimator(item, exportPath); return ExportAnimator(item, exportPath);
case ClassIDType.AnimationClip: case ClassIDType.AnimationClip:
@@ -331,9 +454,8 @@ namespace AssetStudioGUI
public static string FixFileName(string str) public static string FixFileName(string str)
{ {
return str.Length >= 260 if (str.Length >= 260) return Path.GetRandomFileName();
? Path.GetRandomFileName() return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
} }
} }
} }

View File

@@ -1,26 +1,20 @@
using AssetStudio; using AssetStudio;
using System; using System;
using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
namespace AssetStudioGUI namespace AssetStudioGUI
{ {
class GUILogger : ILogger class GUILogger : ILogger
{ {
public static bool ShowDebugMessage = false; public bool ShowErrorMessage = false;
private bool IsFileLoggerRunning = false;
private bool isFileLoggerRunning = false; private string LoggerInitString;
private string loggerInitString; private string FileLogName;
private string fileLogName; private string FileLogPath;
private string fileLogPath;
private Action<string> action; private Action<string> action;
private CancellationTokenSource tokenSource;
private BlockingCollection<string> consoleLogMessageCollection = new BlockingCollection<string>();
private BlockingCollection<string> fileLogMessageCollection = new BlockingCollection<string>();
private bool _useFileLogger = false; private bool _useFileLogger = false;
public bool UseFileLogger public bool UseFileLogger
@@ -29,23 +23,19 @@ namespace AssetStudioGUI
set set
{ {
_useFileLogger = value; _useFileLogger = value;
if (_useFileLogger && !isFileLoggerRunning) if (_useFileLogger && !IsFileLoggerRunning)
{ {
var appAssembly = typeof(Program).Assembly.GetName(); var appAssembly = typeof(Program).Assembly.GetName();
fileLogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"; FileLogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
fileLogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileLogName); FileLogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, FileLogName);
tokenSource = new CancellationTokenSource();
isFileLoggerRunning = true;
ConcurrentFileWriter(tokenSource.Token); LogToFile(LoggerEvent.Verbose, $"# {LoggerInitString} - Logger launched #");
LogToFile(LoggerEvent.Verbose, $"# {loggerInitString} - Logger launched #"); IsFileLoggerRunning = true;
} }
else if (!_useFileLogger && isFileLoggerRunning) else if (!_useFileLogger && IsFileLoggerRunning)
{ {
LogToFile(LoggerEvent.Verbose, "# Logger closed #"); LogToFile(LoggerEvent.Verbose, "# Logger closed #");
isFileLoggerRunning = false; IsFileLoggerRunning = false;
tokenSource.Cancel();
tokenSource.Dispose();
} }
} }
} }
@@ -57,7 +47,7 @@ namespace AssetStudioGUI
var appAssembly = typeof(Program).Assembly.GetName(); var appAssembly = typeof(Program).Assembly.GetName();
var arch = Environment.Is64BitProcess ? "x64" : "x32"; var arch = Environment.Is64BitProcess ? "x64" : "x32";
var frameworkName = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName; var frameworkName = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
loggerInitString = $"{appAssembly.Name} v{appAssembly.Version} [{arch}] [{frameworkName}]"; LoggerInitString = $"{appAssembly.Name} v{appAssembly.Version} [{arch}] [{frameworkName}]";
try try
{ {
Console.Title = $"Console Logger - {appAssembly.Name} v{appAssembly.Version}"; Console.Title = $"Console Logger - {appAssembly.Name} v{appAssembly.Version}";
@@ -67,9 +57,7 @@ namespace AssetStudioGUI
{ {
// ignored // ignored
} }
Console.WriteLine($"# {LoggerInitString}");
ConcurrentConsoleWriter();
Console.WriteLine($"# {loggerInitString}");
} }
private static string ColorLogLevel(LoggerEvent logLevel) private static string ColorLogLevel(LoggerEvent logLevel)
@@ -91,7 +79,7 @@ namespace AssetStudioGUI
private static string FormatMessage(LoggerEvent logMsgLevel, string message, bool toConsole) private static string FormatMessage(LoggerEvent logMsgLevel, string message, bool toConsole)
{ {
message = message.TrimEnd(); message = message.TrimEnd();
var multiLine = message.Contains("\n"); var multiLine = message.Contains('\n');
string formattedMessage; string formattedMessage;
if (toConsole) if (toConsole)
@@ -100,7 +88,7 @@ namespace AssetStudioGUI
formattedMessage = $"{colorLogLevel} {message}"; formattedMessage = $"{colorLogLevel} {message}";
if (multiLine) if (multiLine)
{ {
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ") + $"\n{colorLogLevel}"; formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ");
} }
} }
else else
@@ -111,48 +99,19 @@ namespace AssetStudioGUI
formattedMessage = $"{curTime} | {logLevel} | {message}"; formattedMessage = $"{curTime} | {logLevel} | {message}";
if (multiLine) if (multiLine)
{ {
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ") + $"\n{curTime} | {logLevel} |"; formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ");
} }
} }
return formattedMessage; return formattedMessage;
} }
private void ConcurrentFileWriter(CancellationToken token) private async void LogToFile(LoggerEvent logMsgLevel, string message)
{ {
Task.Run(() => using (var sw = new StreamWriter(FileLogPath, append: true, System.Text.Encoding.UTF8))
{ {
using (var sw = new StreamWriter(fileLogPath, append: true, System.Text.Encoding.UTF8)) await sw.WriteLineAsync(FormatMessage(logMsgLevel, message, toConsole: false));
{ }
sw.AutoFlush = true;
foreach (var msg in fileLogMessageCollection.GetConsumingEnumerable())
{
sw.WriteLine(msg);
if (token.IsCancellationRequested)
break;
}
}
}, token);
}
private void ConcurrentConsoleWriter()
{
Task.Run(() =>
{
foreach (var msg in consoleLogMessageCollection.GetConsumingEnumerable())
{
Console.WriteLine(msg);
}
});
}
private void LogToFile(LoggerEvent logMsgLevel, string message)
{
fileLogMessageCollection.Add(FormatMessage(logMsgLevel, message, toConsole: false));
}
private void LogToConsole(LoggerEvent logMsgLevel, string message)
{
consoleLogMessageCollection.Add(FormatMessage(logMsgLevel, message, toConsole: true));
} }
public void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel) public void Log(LoggerEvent loggerEvent, string message, bool ignoreLevel)
@@ -164,9 +123,7 @@ namespace AssetStudioGUI
} }
//Console logger //Console logger
if (!ShowDebugMessage && loggerEvent == LoggerEvent.Debug) Console.WriteLine(FormatMessage(loggerEvent, message, toConsole: true));
return;
LogToConsole(loggerEvent, message);
//GUI logger //GUI logger
switch (loggerEvent) switch (loggerEvent)
@@ -175,7 +132,14 @@ namespace AssetStudioGUI
MessageBox.Show(message, "Error"); MessageBox.Show(message, "Error");
break; break;
case LoggerEvent.Warning: case LoggerEvent.Warning:
action("Some warnings occurred. See Console Logger for details."); if (ShowErrorMessage)
{
MessageBox.Show(message, "Warning");
}
else
{
action("An error has occurred. Turn on \"Show all error messages\" to see details next time.");
}
break; break;
case LoggerEvent.Debug: case LoggerEvent.Debug:
break; break;

View File

@@ -1,226 +0,0 @@
using AssetStudio;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Text;
namespace AssetStudioGUI
{
internal static class ParallelExporter
{
private static ConcurrentDictionary<string, bool> savePathHash = new ConcurrentDictionary<string, bool>();
public static bool ExportTexture2D(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
var m_Texture2D = (Texture2D)item.Asset;
if (Properties.Settings.Default.convertTexture)
{
var type = Properties.Settings.Default.convertType;
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
return false;
if (GUILogger.ShowDebugMessage)
{
var sb = new StringBuilder();
sb.AppendLine($"Converting {item.TypeString} \"{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;
}
debugLog += sb.ToString();
}
var image = m_Texture2D.ConvertToImage(flip: true);
if (image == null)
{
Logger.Warning($"Failed to convert texture \"{m_Texture2D.m_Name}\" into image");
return false;
}
using (image)
{
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
debugLog += $"{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());
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
}
public static bool ExportSprite(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
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 image = ((Sprite)item.Asset).GetImage(spriteMaskMode: spriteMaskMode);
if (image != null)
{
using (image)
{
using (var file = File.OpenWrite(exportFullPath))
{
image.WriteToStream(file, type);
}
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
}
return false;
}
public static bool ExportAudioClip(AssetItem item, string exportPath, out string debugLog)
{
debugLog = "";
string exportFullPath;
var m_AudioClip = (AudioClip)item.Asset;
var m_AudioData = BigArrayPool<byte>.Shared.Rent(m_AudioClip.m_AudioData.Size);
try
{
m_AudioClip.m_AudioData.GetData(m_AudioData);
if (m_AudioData == null || m_AudioData.Length == 0)
{
Logger.Warning($"Failed to export \"{item.Text}\": AudioData was not found");
return false;
}
var converter = new AudioClipConverter(m_AudioClip);
if (Properties.Settings.Default.convertAudio && converter.IsSupport)
{
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
return false;
if (GUILogger.ShowDebugMessage)
{
var sb = new StringBuilder();
sb.AppendLine($"Converting {item.TypeString} \"{m_AudioClip.m_Name}\" to wav..");
sb.AppendLine(m_AudioClip.version < 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}");
debugLog += sb.ToString();
}
var buffer = converter.ConvertToWav(m_AudioData, out var debugLogConverter);
debugLog += debugLogConverter;
if (buffer == null)
{
Logger.Warning($"{debugLog}Failed to export \"{item.Text}\": Failed to convert fmod audio to Wav");
return false;
}
File.WriteAllBytes(exportFullPath, buffer);
}
else
{
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out exportFullPath))
return false;
if (GUILogger.ShowDebugMessage)
{
var sb = new StringBuilder();
sb.AppendLine($"Exporting non-fmod {item.TypeString} \"{m_AudioClip.m_Name}\"..");
sb.AppendLine(m_AudioClip.version < 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}");
debugLog += sb.ToString();
}
File.WriteAllBytes(exportFullPath, m_AudioData);
}
debugLog += $"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"";
return true;
}
finally
{
BigArrayPool<byte>.Shared.Return(m_AudioData, clearArray: true);
}
}
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
{
var fileName = FixFileName(item.Text);
var filenameFormatIndex = Properties.Settings.Default.filenameFormat;
switch (filenameFormatIndex)
{
case 1: //assetName@pathID
fileName = $"{fileName} @{item.m_PathID}";
break;
case 2: //pathID
fileName = item.m_PathID.ToString();
break;
}
fullPath = Path.Combine(dir, fileName + extension);
if (savePathHash.TryAdd(fullPath.ToLower(), true) && !File.Exists(fullPath))
{
Directory.CreateDirectory(dir);
return true;
}
if (filenameFormatIndex == 0) //assetName
{
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
if (!File.Exists(fullPath))
{
Directory.CreateDirectory(dir);
return true;
}
}
Logger.Warning($"Export failed. File \"{fullPath.Color(ColorConsole.BrightYellow)}\" already exist");
return false;
}
public static bool ParallelExportConvertFile(AssetItem item, string exportPath, out string debugLog)
{
switch (item.Type)
{
case ClassIDType.Texture2D:
case ClassIDType.Texture2DArrayImage:
return ExportTexture2D(item, exportPath, out debugLog);
case ClassIDType.Sprite:
return ExportSprite(item, exportPath, out debugLog);
case ClassIDType.AudioClip:
return ExportAudioClip(item, exportPath, out debugLog);
default:
throw new NotImplementedException();
}
}
private static string FixFileName(string str)
{
return str.Length >= 260
? Path.GetRandomFileName()
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
}
public static void ClearHash()
{
savePathHash.Clear();
}
}
}

View File

@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.8.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -287,6 +287,78 @@ namespace AssetStudioGUI.Properties {
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool fixFaceSpriteNames {
get {
return ((bool)(this["fixFaceSpriteNames"]));
}
set {
this["fixFaceSpriteNames"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool useExternalAlpha {
get {
return ((bool)(this["useExternalAlpha"]));
}
set {
this["useExternalAlpha"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool addAliases {
get {
return ((bool)(this["addAliases"]));
}
set {
this["addAliases"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3")]
public int resamplerIndex {
get {
return ((int)(this["resamplerIndex"]));
}
set {
this["resamplerIndex"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool resizedOnly {
get {
return ((bool)(this["resizedOnly"]));
}
set {
this["resizedOnly"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("2")]
public int alphaMaskGamma {
get {
return ((int)(this["alphaMaskGamma"]));
}
set {
this["alphaMaskGamma"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()] [global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("MonoBehaviour")] [global::System.Configuration.DefaultSettingValueAttribute("MonoBehaviour")]
@@ -346,53 +418,5 @@ namespace AssetStudioGUI.Properties {
this["buildTreeStructure"] = value; this["buildTreeStructure"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public int filenameFormat {
get {
return ((int)(this["filenameFormat"]));
}
set {
this["filenameFormat"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool parallelExport {
get {
return ((bool)(this["parallelExport"]));
}
set {
this["parallelExport"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("-1")]
public int parallelExportCount {
get {
return ((int)(this["parallelExportCount"]));
}
set {
this["parallelExportCount"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool useTypetreeLoading {
get {
return ((bool)(this["useTypetreeLoading"]));
}
set {
this["useTypetreeLoading"] = value;
}
}
} }
} }

View File

@@ -68,6 +68,24 @@
<Setting Name="exportSpriteWithMask" Type="System.Boolean" Scope="User"> <Setting Name="exportSpriteWithMask" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="fixFaceSpriteNames" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="useExternalAlpha" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="addAliases" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="resamplerIndex" Type="System.Int32" Scope="User">
<Value Profile="(Default)">3</Value>
</Setting>
<Setting Name="resizedOnly" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="alphaMaskGamma" Type="System.Int32" Scope="User">
<Value Profile="(Default)">2</Value>
</Setting>
<Setting Name="l2dMotionMode" Type="CubismLive2DExtractor.Live2DMotionMode" Scope="User"> <Setting Name="l2dMotionMode" Type="CubismLive2DExtractor.Live2DMotionMode" Scope="User">
<Value Profile="(Default)">MonoBehaviour</Value> <Value Profile="(Default)">MonoBehaviour</Value>
</Setting> </Setting>
@@ -83,17 +101,5 @@
<Setting Name="buildTreeStructure" Type="System.Boolean" Scope="User"> <Setting Name="buildTreeStructure" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="filenameFormat" Type="System.Int32" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="parallelExport" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="parallelExportCount" Type="System.Int32" Scope="User">
<Value Profile="(Default)">-1</Value>
</Setting>
<Setting Name="useTypetreeLoading" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>

View File

@@ -1,17 +1,15 @@
using AssetStudio; using AssetStudio;
using CubismLive2DExtractor;
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using System.Xml.Linq; using System.Xml.Linq;
using static AssetStudioGUI.Exporter; using static AssetStudioGUI.Exporter;
using static CubismLive2DExtractor.Live2DExtractor;
using Object = AssetStudio.Object; using Object = AssetStudio.Object;
namespace AssetStudioGUI namespace AssetStudioGUI
@@ -30,15 +28,6 @@ namespace AssetStudioGUI
Filtered Filtered
} }
internal enum ExportL2DFilter
{
All,
Selected,
SelectedWithFadeList,
SelectedWithFade,
SelectedWithClips,
}
internal enum ExportListType internal enum ExportListType
{ {
XML XML
@@ -49,8 +38,7 @@ namespace AssetStudioGUI
TypeName, TypeName,
ContainerPath, ContainerPath,
ContainerPathFull, ContainerPathFull,
SourceFileName, SourceFileName
SceneHierarchy,
} }
internal enum ListSearchFilterMode internal enum ListSearchFilterMode
@@ -61,24 +49,13 @@ namespace AssetStudioGUI
RegexContainer, RegexContainer,
} }
[Flags]
internal enum SelectedAssetType
{
Animator = 0x01,
AnimationClip = 0x02,
MonoBehaviourMoc = 0x04,
MonoBehaviourFade = 0x08,
MonoBehaviourFadeLst = 0x10
}
internal static class Studio internal static class Studio
{ {
public static AssetsManager assetsManager = new AssetsManager(); public static AssetsManager assetsManager = new AssetsManager();
public static AssemblyLoader assemblyLoader = new AssemblyLoader(); public static AssemblyLoader assemblyLoader = new AssemblyLoader();
public static List<AssetItem> exportableAssets = new List<AssetItem>(); public static List<AssetItem> exportableAssets = new List<AssetItem>();
public static List<AssetItem> visibleAssets = new List<AssetItem>(); public static List<AssetItem> visibleAssets = new List<AssetItem>();
public static List<MonoBehaviour> cubismMocList = new List<MonoBehaviour>(); private static Dictionary<Object, string> allContainers = new Dictionary<Object, string>();
private static Dictionary<Object, string> l2dResourceContainers = new Dictionary<Object, string>();
internal static Action<string> StatusStripUpdate = x => { }; internal static Action<string> StatusStripUpdate = x => { };
public static int ExtractFolder(string path, string savePath) public static int ExtractFolder(string path, string savePath)
@@ -126,7 +103,7 @@ namespace AssetStudioGUI
private static int ExtractBundleFile(FileReader reader, string savePath) private static int ExtractBundleFile(FileReader reader, string savePath)
{ {
Logger.Info($"Decompressing {reader.FileName} ..."); Logger.Info($"Decompressing {reader.FileName} ...");
var bundleFile = new BundleFile(reader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion); var bundleFile = new BundleFile(reader, assetsManager.SpecifyUnityVersion);
reader.Dispose(); reader.Dispose();
if (bundleFile.fileList.Length > 0) if (bundleFile.fileList.Length > 0)
{ {
@@ -181,8 +158,7 @@ namespace AssetStudioGUI
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count); var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
var objectAssetItemDic = new Dictionary<Object, AssetItem>(objectCount); var objectAssetItemDic = new Dictionary<Object, AssetItem>(objectCount);
var containers = new List<(PPtr<Object>, string)>(); var containers = new List<(PPtr<Object>, string)>();
var tex2dArrayAssetList = new List<AssetItem>(); allContainers.Clear();
l2dResourceContainers.Clear();
var i = 0; var i = 0;
Progress.Reset(); Progress.Reset();
foreach (var assetsFile in assetsManager.assetsFileList) foreach (var assetsFile in assetsManager.assetsFileList)
@@ -209,13 +185,6 @@ namespace AssetStudioGUI
assetItem.Text = m_Texture2D.m_Name; assetItem.Text = m_Texture2D.m_Name;
exportable = true; exportable = true;
break; break;
case Texture2DArray m_Texture2DArray:
if (!string.IsNullOrEmpty(m_Texture2DArray.m_StreamData?.path))
assetItem.FullSize = asset.byteSize + m_Texture2DArray.m_StreamData.size;
assetItem.Text = m_Texture2DArray.m_Name;
tex2dArrayAssetList.Add(assetItem);
exportable = true;
break;
case AudioClip m_AudioClip: case AudioClip m_AudioClip:
if (!string.IsNullOrEmpty(m_AudioClip.m_Source)) if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size; assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
@@ -249,16 +218,14 @@ namespace AssetStudioGUI
exportable = true; exportable = true;
break; break;
case MonoBehaviour m_MonoBehaviour: case MonoBehaviour m_MonoBehaviour:
var assetName = m_MonoBehaviour.m_Name; if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
{ {
assetName = assetName == "" ? m_Script.m_ClassName : assetName; assetItem.Text = m_Script.m_ClassName;
if (m_Script.m_ClassName == "CubismMoc") }
{ else
cubismMocList.Add(m_MonoBehaviour); {
} assetItem.Text = m_MonoBehaviour.m_Name;
} }
assetItem.Text = assetName;
exportable = true; exportable = true;
break; break;
case PlayerSettings m_PlayerSettings: case PlayerSettings m_PlayerSettings:
@@ -308,32 +275,18 @@ namespace AssetStudioGUI
{ {
if (pptr.TryGet(out var obj)) if (pptr.TryGet(out var obj))
{ {
objectAssetItemDic[obj].Container = container; var asset = objectAssetItemDic[obj];
switch (obj) asset.Container = container;
{ allContainers[obj] = container;
case AnimationClip _:
case GameObject _:
case Texture2D _:
case MonoBehaviour _:
l2dResourceContainers[obj] = container;
break;
}
}
}
foreach (var tex2dAssetItem in tex2dArrayAssetList)
{
var m_Texture2DArray = (Texture2DArray)tex2dAssetItem.Asset;
for (var layer = 0; layer < m_Texture2DArray.m_Depth; layer++)
{
var fakeObj = new Texture2D(m_Texture2DArray, layer);
m_Texture2DArray.TextureList.Add(fakeObj);
var fakeItem = new AssetItem(fakeObj) if (asset.Type == ClassIDType.MonoBehaviour && container.Contains("/arts/charportraits/portraits"))
{ {
Text = fakeObj.m_Name, var portraitsList = Arknights.AkSpriteHelper.GeneratePortraits(asset);
Container = tex2dAssetItem.Container foreach (var portrait in portraitsList)
}; {
exportableAssets.Add(fakeItem); exportableAssets.Add(new AssetItem(portrait));
}
}
} }
} }
foreach (var tmp in exportableAssets) foreach (var tmp in exportableAssets)
@@ -341,7 +294,6 @@ namespace AssetStudioGUI
tmp.SetSubItems(); tmp.SetSubItems();
} }
containers.Clear(); containers.Clear();
tex2dArrayAssetList.Clear();
visibleAssets = exportableAssets; visibleAssets = exportableAssets;
@@ -412,6 +364,7 @@ namespace AssetStudioGUI
} }
} }
} }
parentNode.Nodes.Add(currentNode); parentNode.Nodes.Add(currentNode);
} }
} }
@@ -470,21 +423,12 @@ namespace AssetStudioGUI
{ {
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
var groupOption = (AssetGroupOption)Properties.Settings.Default.assetGroupOption; int toExportCount = toExportAssets.Count;
var parallelExportCount = Properties.Settings.Default.parallelExportCount <= 0 int exportedCount = 0;
? Environment.ProcessorCount - 1 int i = 0;
: Math.Min(Properties.Settings.Default.parallelExportCount, Environment.ProcessorCount - 1);
parallelExportCount = Properties.Settings.Default.parallelExport ? parallelExportCount : 1;
var toExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
var toParallelExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
var exceptionMsgs = new ConcurrentDictionary<Exception, string>();
var mode = exportType == ExportType.Dump ? "Dump" : "Export";
var toExportCount = toExportAssets.Count;
var exportedCount = 0;
var i = 0;
Progress.Reset(); Progress.Reset();
var groupOption = (AssetGroupOption)Properties.Settings.Default.assetGroupOption;
Parallel.ForEach(toExportAssets, asset => foreach (var asset in toExportAssets)
{ {
string exportPath; string exportPath;
switch (groupOption) switch (groupOption)
@@ -517,146 +461,52 @@ namespace AssetStudioGUI
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName); exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
} }
break; break;
case AssetGroupOption.SceneHierarchy:
if (asset.TreeNode != null)
{
exportPath = Path.Combine(savePath, asset.TreeNode.FullPath);
}
else
{
exportPath = Path.Combine(savePath, "_sceneRoot", asset.TypeString);
}
break;
default: default:
exportPath = savePath; exportPath = savePath;
break; break;
} }
exportPath += Path.DirectorySeparatorChar; exportPath += Path.DirectorySeparatorChar;
Logger.Info($"[{exportedCount + 1}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
if (exportType == ExportType.Convert)
{
switch (asset.Type)
{
case ClassIDType.Texture2D:
case ClassIDType.Texture2DArrayImage:
case ClassIDType.Sprite:
case ClassIDType.AudioClip:
toParallelExportAssetDict.TryAdd(asset, exportPath);
break;
case ClassIDType.Texture2DArray:
var m_Texture2DArray = (Texture2DArray)asset.Asset;
toExportCount += m_Texture2DArray.TextureList.Count - 1;
foreach (var texture in m_Texture2DArray.TextureList)
{
var fakeItem = new AssetItem(texture)
{
Text = texture.m_Name,
Container = asset.Container,
};
toParallelExportAssetDict.TryAdd(fakeItem, exportPath);
}
break;
default:
toExportAssetDict.TryAdd(asset, exportPath);
break;
}
}
else
{
toExportAssetDict.TryAdd(asset, exportPath);
}
});
foreach (var toExportAsset in toExportAssetDict)
{
var asset = toExportAsset.Key;
var exportPath = toExportAsset.Value;
var isExported = false;
try try
{ {
Logger.Info($"[{exportedCount + 1}/{toExportCount}] {mode}ing {asset.TypeString}: {asset.Text}");
switch (exportType) switch (exportType)
{ {
case ExportType.Raw: case ExportType.Raw:
isExported = ExportRawFile(asset, exportPath); if (ExportRawFile(asset, exportPath))
{
exportedCount++;
}
break; break;
case ExportType.Dump: case ExportType.Dump:
isExported = ExportDumpFile(asset, exportPath); if (ExportDumpFile(asset, exportPath))
{
exportedCount++;
}
break; break;
case ExportType.Convert: case ExportType.Convert:
isExported = ExportConvertFile(asset, exportPath); if (ExportConvertFile(asset, exportPath))
{
exportedCount++;
}
break; break;
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error($"{mode} {asset.TypeString}: {asset.Text} error", ex); Logger.Error($"Export {asset.Type}:{asset.Text} error", ex);
}
if (isExported)
{
exportedCount++;
}
else
{
Logger.Warning($"Unable to {mode.ToLower()} {asset.TypeString}: {asset.Text}");
} }
Progress.Report(++i, toExportCount); Progress.Report(++i, toExportCount);
} }
Parallel.ForEach(toParallelExportAssetDict, new ParallelOptions { MaxDegreeOfParallelism = parallelExportCount }, (toExportAsset, loopState) => var statusText = exportedCount == 0 ? "Nothing exported." : $"Finished exporting {exportedCount} assets.";
{
var asset = toExportAsset.Key;
var exportPath = toExportAsset.Value;
try
{
if (ParallelExporter.ParallelExportConvertFile(asset, exportPath, out var debugLog))
{
Interlocked.Increment(ref exportedCount);
if (GUILogger.ShowDebugMessage)
{
Logger.Debug(debugLog);
StatusStripUpdate($"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
}
else
{
Logger.Info($"[{exportedCount}/{toExportCount}] Exporting {asset.TypeString}: {asset.Text}");
}
}
Interlocked.Increment(ref i);
Progress.Report(i, toExportCount);
}
catch (Exception ex)
{
if (parallelExportCount == 1)
{
Logger.Error($"{mode} {asset.TypeString}: {asset.Text} error", ex);
}
else
{
loopState.Break();
exceptionMsgs.TryAdd(ex, $"Exception occurred when exporting {asset.TypeString}: {asset.Text}\n{ex}\n");
}
}
});
ParallelExporter.ClearHash();
foreach (var ex in exceptionMsgs)
{
Logger.Error(ex.Value);
}
var statusText = exportedCount == 0 ? "Nothing exported." : $"Finished {mode.ToLower()}ing [{exportedCount}/{toExportCount}] assets.";
if (toExportCount > exportedCount) if (toExportCount > exportedCount)
{ {
statusText += exceptionMsgs.IsEmpty statusText += $" {toExportCount - exportedCount} assets skipped (not extractable or files already exist)";
? $" {toExportCount - exportedCount} assets skipped (not extractable or files already exist)."
: " Export process was stopped because one or more exceptions occurred.";
Progress.Report(toExportCount, toExportCount);
} }
Logger.Info(statusText); Logger.Info(statusText);
exceptionMsgs.Clear();
if (Properties.Settings.Default.openAfterExport && exportedCount > 0) if (Properties.Settings.Default.openAfterExport && exportedCount > 0)
{ {
@@ -688,7 +538,6 @@ namespace AssetStudioGUI
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString), new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
new XElement("PathID", asset.m_PathID), new XElement("PathID", asset.m_PathID),
new XElement("Source", asset.SourceFile.fullName), new XElement("Source", asset.SourceFile.fullName),
new XElement("TreeNode", asset.TreeNode != null ? asset.TreeNode.FullPath : ""),
new XElement("Size", asset.FullSize) new XElement("Size", asset.FullSize)
) )
) )
@@ -700,11 +549,11 @@ namespace AssetStudioGUI
break; break;
} }
var statusText = $"Finished exporting asset list with {toExportAssets.Count} items."; var statusText = $"Finished exporting asset list with {toExportAssets.Count()} items.";
Logger.Info(statusText); Logger.Info(statusText);
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count > 0) if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)
{ {
OpenFolderInExplorer(savePath); OpenFolderInExplorer(savePath);
} }
@@ -787,7 +636,6 @@ namespace AssetStudioGUI
{ {
Progress.Reset(); Progress.Reset();
Logger.Info($"Exporting {animator.Text}"); Logger.Info($"Exporting {animator.Text}");
Logger.Debug($"Selected AnimationClip(s):\n\"{string.Join("\"\n\"", animationList.Select(x => x.Text))}\"");
try try
{ {
ExportAnimator(animator, exportPath, animationList); ExportAnimator(animator, exportPath, animationList);
@@ -886,12 +734,6 @@ namespace AssetStudioGUI
} }
public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour) public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour)
{
SelectAssemblyFolder();
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
}
private static void SelectAssemblyFolder()
{ {
if (!assemblyLoader.Loaded) if (!assemblyLoader.Loaded)
{ {
@@ -906,20 +748,17 @@ namespace AssetStudioGUI
assemblyLoader.Loaded = true; assemblyLoader.Loaded = true;
} }
} }
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
} }
public static string DumpAsset(Object obj) public static string DumpAsset(Object obj)
{ {
var str = obj.Dump(); var str = obj?.Dump();
if (str == null && obj is MonoBehaviour m_MonoBehaviour) if (str == null && obj is MonoBehaviour m_MonoBehaviour)
{ {
var type = MonoBehaviourToTypeTree(m_MonoBehaviour); var type = MonoBehaviourToTypeTree(m_MonoBehaviour);
str = m_MonoBehaviour.Dump(type); str = m_MonoBehaviour.Dump(type);
} }
if (string.IsNullOrEmpty(str))
{
str = obj.DumpObject();
}
return str; return str;
} }
@@ -930,70 +769,56 @@ namespace AssetStudioGUI
Process.Start(info); Process.Start(info);
} }
public static void ExportLive2D(string exportPath, List<MonoBehaviour> selMocs = null, List<AnimationClip> selClipMotions = null, List<MonoBehaviour> selFadeMotions = null, MonoBehaviour selFadeLst = null) public static void ExportLive2D(Object[] cubismMocs, string exportPath)
{ {
var baseDestPath = Path.Combine(exportPath, "Live2DOutput"); var baseDestPath = Path.Combine(exportPath, "Live2DOutput");
var forceBezier = Properties.Settings.Default.l2dForceBezier;
var mocList = selMocs ?? cubismMocList;
var motionMode = Properties.Settings.Default.l2dMotionMode; var motionMode = Properties.Settings.Default.l2dMotionMode;
if (selClipMotions != null) var forceBezier = Properties.Settings.Default.l2dForceBezier;
motionMode = Live2DMotionMode.AnimationClipV2;
else if (selFadeMotions != null || selFadeLst != null)
motionMode = Live2DMotionMode.MonoBehaviour;
ThreadPool.QueueUserWorkItem(state => ThreadPool.QueueUserWorkItem(state =>
{ {
Logger.Info($"Searching for Live2D files..."); Logger.Info($"Searching for Live2D files...");
var mocPathDict = new Dictionary<MonoBehaviour, (string, string)>(); var useFullContainerPath = false;
var mocPathList = new List<string>(); if (cubismMocs.Length > 1)
foreach (var mocMonoBehaviour in cubismMocList)
{ {
if (!l2dResourceContainers.TryGetValue(mocMonoBehaviour, out var fullContainerPath)) var basePathSet = cubismMocs.Select(x =>
continue; {
var pathLen = allContainers.TryGetValue(x, out var itemContainer) ? itemContainer.LastIndexOf("/") : 0;
pathLen = pathLen < 0 ? allContainers[x].Length : pathLen;
return itemContainer?.Substring(0, pathLen);
}).ToHashSet();
var pathSepIndex = fullContainerPath.LastIndexOf('/'); if (basePathSet.All(x => x == null))
var basePath = pathSepIndex > 0 {
? fullContainerPath.Substring(0, pathSepIndex) Logger.Error($"Live2D Cubism export error\r\nCannot find any model related files");
: fullContainerPath; StatusStripUpdate("Live2D export canceled");
mocPathDict.Add(mocMonoBehaviour, (fullContainerPath, basePath)); Progress.Reset();
} return;
if (mocPathDict.Count == 0) }
{
Logger.Error("Live2D Cubism export error\r\nCannot find any model related files"); if (basePathSet.Count != cubismMocs.Length)
StatusStripUpdate("Live2D export canceled"); {
Progress.Reset(); useFullContainerPath = true;
return; }
} }
var basePathSet = mocPathDict.Values.Select(x => x.Item2).ToHashSet(); var basePathList = cubismMocs.Select(x =>
var useFullContainerPath = mocPathDict.Count != basePathSet.Count;
foreach (var moc in mocList)
{ {
var mocPath = useFullContainerPath allContainers.TryGetValue(x, out var container);
? mocPathDict[moc].Item1 //fullContainerPath container = useFullContainerPath
: mocPathDict[moc].Item2; //basePath ? container
mocPathList.Add(mocPath); : container?.Substring(0, container.LastIndexOf("/"));
} return container;
mocPathDict.Clear(); }).Where(x => x != null).ToList();
var lookup = l2dResourceContainers.AsParallel().ToLookup( var lookup = allContainers.ToLookup(
x => mocPathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))), x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
x => x.Key x => x.Key
); );
if (mocList[0].serializedType?.m_Type == null && !assemblyLoader.Loaded)
{
Logger.Warning("Specifying the assembly folder may be needed for proper extraction");
SelectAssemblyFolder();
}
var totalModelCount = lookup.LongCount(x => x.Key != null); var totalModelCount = lookup.LongCount(x => x.Key != null);
var modelCounter = 0; var modelCounter = 0;
var parallelExportCount = Properties.Settings.Default.parallelExportCount <= 0
? Environment.ProcessorCount - 1
: Math.Min(Properties.Settings.Default.parallelExportCount, Environment.ProcessorCount - 1);
parallelExportCount = Properties.Settings.Default.parallelExport ? parallelExportCount : 1;
foreach (var assets in lookup) foreach (var assets in lookup)
{ {
var srcContainer = assets.Key; var srcContainer = assets.Key;
@@ -1004,16 +829,11 @@ namespace AssetStudioGUI
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer}\"..."); Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer}\"...");
try try
{ {
var modelName = useFullContainerPath var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
? Path.GetFileNameWithoutExtension(container) container = Path.HasExtension(container) ? container.Replace(Path.GetExtension(container), "") : container;
: container.Substring(container.LastIndexOf('/') + 1);
container = Path.HasExtension(container)
? container.Replace(Path.GetExtension(container), "")
: container;
var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar; var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar;
var modelExtractor = new Live2DExtractor(assets, selClipMotions, selFadeMotions, selFadeLst); ExtractLive2D(assets, destPath, modelName, assemblyLoader, motionMode, forceBezier);
modelExtractor.ExtractCubismModel(destPath, modelName, motionMode, assemblyLoader, forceBezier, parallelExportCount);
modelCounter++; modelCounter++;
} }
catch (Exception ex) catch (Exception ex)

View File

@@ -2,8 +2,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks> <TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
<Version>0.18.0.0</Version> <Version>1.2.0</Version>
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023-2024</Copyright> <Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2025</Copyright>
<DebugType>embedded</DebugType> <DebugType>embedded</DebugType>
</PropertyGroup> </PropertyGroup>
@@ -22,7 +22,7 @@
<PackageReference Include="Kyaru.Texture2DDecoder"> <PackageReference Include="Kyaru.Texture2DDecoder">
<Version>0.17.0</Version> <Version>0.17.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.2" /> <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">

View File

@@ -7,37 +7,25 @@ namespace AssetStudio
{ {
public class AudioClipConverter public class AudioClipConverter
{ {
public bool IsSupport => m_AudioClip.IsConvertSupport();
private AudioClip m_AudioClip; private AudioClip m_AudioClip;
private static FMOD.System system;
static AudioClipConverter()
{
var result = Factory.System_Create(out system);
if (result != RESULT.OK)
{
Logger.Error($"FMOD error! {result} - {Error.String(result)}");
}
result = system.init(1, INITFLAGS.NORMAL, IntPtr.Zero);
if (result != RESULT.OK)
{
Logger.Error($"FMOD error! {result} - {Error.String(result)}");
}
}
public AudioClipConverter(AudioClip audioClip) public AudioClipConverter(AudioClip audioClip)
{ {
m_AudioClip = audioClip; m_AudioClip = audioClip;
} }
public byte[] ConvertToWav(byte[] m_AudioData, out string debugLog) public byte[] ConvertToWav(byte[] m_AudioData)
{ {
debugLog = "";
var exinfo = new CREATESOUNDEXINFO(); var exinfo = new CREATESOUNDEXINFO();
var result = Factory.System_Create(out var system);
if (result != RESULT.OK)
return null;
result = system.init(1, INITFLAGS.NORMAL, IntPtr.Zero);
if (result != RESULT.OK)
return null;
exinfo.cbsize = Marshal.SizeOf(exinfo); exinfo.cbsize = Marshal.SizeOf(exinfo);
exinfo.length = (uint)m_AudioClip.m_Size; exinfo.length = (uint)m_AudioClip.m_Size;
var result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound); result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound);
if (result != RESULT.OK) if (result != RESULT.OK)
return null; return null;
result = sound.getNumSubSounds(out var numsubsounds); result = sound.getNumSubSounds(out var numsubsounds);
@@ -49,29 +37,28 @@ namespace AssetStudio
result = sound.getSubSound(0, out var subsound); result = sound.getSubSound(0, out var subsound);
if (result != RESULT.OK) if (result != RESULT.OK)
return null; return null;
buff = SoundToWav(subsound, out debugLog); buff = SoundToWav(subsound);
subsound.release(); subsound.release();
subsound.clearHandle();
} }
else else
{ {
buff = SoundToWav(sound, out debugLog); buff = SoundToWav(sound);
} }
sound.release(); sound.release();
sound.clearHandle(); system.release();
return buff; return buff;
} }
public byte[] SoundToWav(Sound sound, out string debugLog) public byte[] SoundToWav(Sound sound)
{ {
debugLog = "[Fmod] Detecting sound format..\n"; Logger.Debug($"[Fmod] Detecting sound format..\n");
var result = sound.getFormat(out SOUND_TYPE soundType, out SOUND_FORMAT soundFormat, out int channels, out int bits); var result = sound.getFormat(out SOUND_TYPE soundType, out SOUND_FORMAT soundFormat, out int channels, out int bits);
if (result != RESULT.OK) if (result != RESULT.OK)
return null; return null;
debugLog += $"Detected sound type: {soundType}\n" + Logger.Debug($"Detected sound type: {soundType}\n" +
$"Detected sound format: {soundFormat}\n" + $"Detected sound format: {soundFormat}\n" +
$"Detected channels: {channels}\n" + $"Detected channels: {channels}\n" +
$"Detected bit depth: {bits}\n"; $"Detected bit depth: {bits}");
result = sound.getDefaults(out var frequency, out _); result = sound.getDefaults(out var frequency, out _);
if (result != RESULT.OK) if (result != RESULT.OK)
return null; return null;
@@ -82,11 +69,11 @@ namespace AssetStudio
result = sound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2); result = sound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2);
if (result != RESULT.OK) if (result != RESULT.OK)
return null; return null;
var buffer = new byte[len1 + 44]; byte[] buffer = new byte[len1 + 44];
//添加wav头 //添加wav头
Encoding.ASCII.GetBytes("RIFF").CopyTo(buffer, 0); Encoding.UTF8.GetBytes("RIFF").CopyTo(buffer, 0);
BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4); BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4);
Encoding.ASCII.GetBytes("WAVEfmt ").CopyTo(buffer, 8); Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8);
BitConverter.GetBytes(16).CopyTo(buffer, 16); BitConverter.GetBytes(16).CopyTo(buffer, 16);
BitConverter.GetBytes((short)1).CopyTo(buffer, 20); BitConverter.GetBytes((short)1).CopyTo(buffer, 20);
BitConverter.GetBytes((short)channels).CopyTo(buffer, 22); BitConverter.GetBytes((short)channels).CopyTo(buffer, 22);
@@ -94,7 +81,7 @@ namespace AssetStudio
BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28); BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28);
BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32); BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32);
BitConverter.GetBytes((short)bits).CopyTo(buffer, 34); BitConverter.GetBytes((short)bits).CopyTo(buffer, 34);
Encoding.ASCII.GetBytes("data").CopyTo(buffer, 36); Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36);
BitConverter.GetBytes(len1).CopyTo(buffer, 40); BitConverter.GetBytes(len1).CopyTo(buffer, 40);
Marshal.Copy(ptr1, buffer, 44, (int)len1); Marshal.Copy(ptr1, buffer, 44, (int)len1);
result = sound.unlock(ptr1, ptr2, len1, len2); result = sound.unlock(ptr1, ptr2, len1, len2);
@@ -105,11 +92,11 @@ namespace AssetStudio
public string GetExtensionName() public string GetExtensionName()
{ {
if (m_AudioClip.version < 5) if (m_AudioClip.version[0] < 5)
{ {
switch (m_AudioClip.m_Type) switch (m_AudioClip.m_Type)
{ {
case FMODSoundType.AAC: case FMODSoundType.ACC:
return ".m4a"; return ".m4a";
case FMODSoundType.AIFF: case FMODSoundType.AIFF:
return ".aif"; return ".aif";
@@ -162,42 +149,43 @@ namespace AssetStudio
return ".fsb"; return ".fsb";
} }
} }
return ".AudioClip"; return ".AudioClip";
} }
}
public static class AudioClipExtension public bool IsSupport
{
public static bool IsConvertSupport(this AudioClip m_AudioClip)
{ {
if (m_AudioClip.version < 5) get
{ {
switch (m_AudioClip.m_Type) if (m_AudioClip.version[0] < 5)
{ {
case FMODSoundType.AIFF: switch (m_AudioClip.m_Type)
case FMODSoundType.IT: {
case FMODSoundType.MOD: case FMODSoundType.AIFF:
case FMODSoundType.S3M: case FMODSoundType.IT:
case FMODSoundType.XM: case FMODSoundType.MOD:
case FMODSoundType.XMA: case FMODSoundType.S3M:
case FMODSoundType.AUDIOQUEUE: case FMODSoundType.XM:
return true; case FMODSoundType.XMA:
default: case FMODSoundType.AUDIOQUEUE:
return false; return true;
default:
return false;
}
} }
} else
else
{
switch (m_AudioClip.m_CompressionFormat)
{ {
case AudioCompressionFormat.PCM: switch (m_AudioClip.m_CompressionFormat)
case AudioCompressionFormat.Vorbis: {
case AudioCompressionFormat.ADPCM: case AudioCompressionFormat.PCM:
case AudioCompressionFormat.MP3: case AudioCompressionFormat.Vorbis:
case AudioCompressionFormat.XMA: case AudioCompressionFormat.ADPCM:
return true; case AudioCompressionFormat.MP3:
default: case AudioCompressionFormat.XMA:
return false; return true;
default:
return false;
}
} }
} }
} }

View File

@@ -1,35 +0,0 @@
using System;
namespace CubismLive2DExtractor
{
public class CubismCdi3Json
{
public int Version { get; set; }
public ParamGroupArray[] Parameters { get; set; }
public ParamGroupArray[] ParameterGroups { get; set; }
public PartArray[] Parts { get; set; }
public class ParamGroupArray : IComparable
{
public string Id { get; set; }
public string GroupId { get; set; }
public string Name { get; set; }
public int CompareTo(object obj)
{
return string.Compare(Id, ((ParamGroupArray)obj).Id, StringComparison.OrdinalIgnoreCase);
}
}
public class PartArray : IComparable
{
public string Id { get; set; }
public string Name { get; set; }
public int CompareTo(object obj)
{
return string.Compare(Id, ((PartArray)obj).Id, StringComparison.OrdinalIgnoreCase);
}
}
}
}

View File

@@ -1,12 +1,5 @@
namespace CubismLive2DExtractor namespace CubismLive2DExtractor
{ {
public enum BlendType
{
Add,
Multiply,
Overwrite,
}
public class CubismExpression3Json public class CubismExpression3Json
{ {
public string Type; public string Type;
@@ -18,7 +11,7 @@
{ {
public string Id; public string Id;
public float Value; public float Value;
public BlendType Blend; public int Blend;
} }
} }
} }

View File

@@ -2,7 +2,7 @@
namespace CubismLive2DExtractor namespace CubismLive2DExtractor
{ {
public sealed class AnimationCurve public class AnimationCurve
{ {
public CubismKeyframeData[] m_Curve { get; set; } public CubismKeyframeData[] m_Curve { get; set; }
public int m_PreInfinity { get; set; } public int m_PreInfinity { get; set; }
@@ -10,7 +10,7 @@ namespace CubismLive2DExtractor
public int m_RotationOrder { get; set; } public int m_RotationOrder { get; set; }
} }
public sealed class CubismFadeMotion public class CubismFadeMotion
{ {
public string m_Name { get; set; } public string m_Name { get; set; }
public string MotionName { get; set; } public string MotionName { get; set; }

View File

@@ -13,7 +13,6 @@ namespace CubismLive2DExtractor
{ {
public string Moc; public string Moc;
public string[] Textures; public string[] Textures;
public string DisplayInfo;
public string Physics; public string Physics;
public JObject Motions; public JObject Motions;
public JArray Expressions; public JArray Expressions;

View File

@@ -7,35 +7,26 @@ namespace CubismLive2DExtractor
{ {
class CubismMotion3Converter class CubismMotion3Converter
{ {
private SerializedFile assetsFile;
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>(); private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>(); public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>();
public CubismMotion3Converter(GameObject rootGameObject, List<AnimationClip> animationClips) public CubismMotion3Converter(GameObject rootGameObject, AnimationClip[] animationClips)
{ {
var rootTransform = GetTransform(rootGameObject); var rootTransform = GetTransform(rootGameObject);
CreateBonePathHash(rootTransform); CreateBonePathHash(rootTransform);
ConvertAnimations(animationClips); ConvertAnimations(animationClips);
} }
public CubismMotion3Converter(List<AnimationClip> animationClips, HashSet<string> partIds, HashSet<string> parameterIds) private void ConvertAnimations(AnimationClip[] animationClips)
{
CreateBonePathHash(partIds, pathType: "Parts/");
CreateBonePathHash(parameterIds, pathType: "Parameters/");
ConvertAnimations(animationClips);
}
private void ConvertAnimations(List<AnimationClip> animationClips)
{ {
foreach (var animationClip in animationClips) foreach (var animationClip in animationClips)
{ {
var iAnim = new ImportedKeyframedAnimation(); var iAnim = new ImportedKeyframedAnimation();
assetsFile = animationClip.assetsFile;
AnimationList.Add(iAnim); AnimationList.Add(iAnim);
iAnim.Name = animationClip.m_Name; iAnim.Name = animationClip.m_Name;
iAnim.SampleRate = animationClip.m_SampleRate; iAnim.SampleRate = animationClip.m_SampleRate;
iAnim.Duration = animationClip.m_MuscleClip.m_StopTime; iAnim.Duration = animationClip.m_MuscleClip.m_StopTime;
var m_Clip = animationClip.m_MuscleClip.m_Clip.data; var m_Clip = animationClip.m_MuscleClip.m_Clip;
var streamedFrames = m_Clip.m_StreamedClip.ReadData(); var streamedFrames = m_Clip.m_StreamedClip.ReadData();
var m_ClipBindingConstant = animationClip.m_ClipBindingConstant; var m_ClipBindingConstant = animationClip.m_ClipBindingConstant;
for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++) for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
@@ -136,7 +127,7 @@ namespace CubismLive2DExtractor
target = "PartOpacity"; target = "PartOpacity";
} }
} }
else if (binding.script.TryGet(out MonoScript script, assetsFile)) else if (binding.script.TryGet(out MonoScript script))
{ {
switch (script.m_ClassName) switch (script.m_ClassName)
{ {
@@ -169,30 +160,21 @@ namespace CubismLive2DExtractor
return null; return null;
} }
private void CreateBonePathHash(HashSet<string> ids, string pathType)
{
foreach (var id in ids)
{
var name = pathType + id;;
bonePathHash[GetCRC(name)] = name;
int index;
while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0)
{
name = name.Substring(index + 1);
bonePathHash[GetCRC(name)] = name;
}
}
}
private void CreateBonePathHash(Transform m_Transform) private void CreateBonePathHash(Transform m_Transform)
{ {
var name = GetTransformPath(m_Transform); var name = GetTransformPath(m_Transform);
bonePathHash[GetCRC(name)] = name; var crc = new SevenZip.CRC();
var bytes = Encoding.UTF8.GetBytes(name);
crc.Update(bytes, 0, (uint)bytes.Length);
bonePathHash[crc.GetDigest()] = name;
int index; int index;
while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0) while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0)
{ {
name = name.Substring(index + 1); name = name.Substring(index + 1);
bonePathHash[GetCRC(name)] = name; crc = new SevenZip.CRC();
bytes = Encoding.UTF8.GetBytes(name);
crc.Update(bytes, 0, (uint)bytes.Length);
bonePathHash[crc.GetDigest()] = name;
} }
foreach (var pptr in m_Transform.m_Children) foreach (var pptr in m_Transform.m_Children)
{ {
@@ -201,13 +183,7 @@ namespace CubismLive2DExtractor
} }
} }
private static uint GetCRC(string name) private string GetTransformPath(Transform transform)
{
var bytes = Encoding.UTF8.GetBytes(name);
return SevenZip.CRC.CalculateDigest(bytes, 0, (uint)bytes.Length);
}
private static string GetTransformPath(Transform transform)
{ {
transform.m_GameObject.TryGet(out var m_GameObject); transform.m_GameObject.TryGet(out var m_GameObject);
if (transform.m_Father.TryGet(out var father)) if (transform.m_Father.TryGet(out var father))

View File

@@ -1,62 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using AssetStudio;
namespace CubismLive2DExtractor
{
public sealed class CubismObjectList
{
public static SerializedFile AssetsFile { get; set; }
public HashSet<ObjectData> CubismExpressionObjects { get; set; }
public HashSet<ObjectData> CubismFadeMotionObjects { get; set; }
public class ObjectData
{
private long _pathID;
public Object Asset { get; set; }
public int m_FileID { get; set; }
public long m_PathID
{
get => _pathID;
set
{
_pathID = value;
Asset = GetObjByPathID(_pathID);
}
}
public override bool Equals(object obj)
{
return obj is ObjectData objectData && _pathID == objectData.m_PathID;
}
public override int GetHashCode()
{
return _pathID.GetHashCode();
}
}
public List<MonoBehaviour> GetFadeMotionAssetList()
{
return CubismFadeMotionObjects?.Where(x => x.Asset != null).Select(x => (MonoBehaviour)x.Asset).ToList();
}
public List<MonoBehaviour> GetExpressionList()
{
return CubismExpressionObjects?.Where(x => x.Asset != null).Select(x => (MonoBehaviour)x.Asset).ToList();
}
private static Object GetObjByPathID(long pathID)
{
var assetFileList = AssetsFile.assetsManager.assetsFileList;
foreach (var assetFile in assetFileList)
{
if (assetFile.ObjectsDic.TryGetValue(pathID, out var obj))
{
return obj;
}
}
return null;
}
}
}

View File

@@ -1,163 +0,0 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using AssetStudio;
using Newtonsoft.Json;
namespace CubismLive2DExtractor
{
public static class CubismParsers
{
public enum CubismMonoBehaviourType
{
FadeMotionList,
FadeMotion,
Expression,
Physics,
DisplayInfo,
}
public static string ParsePhysics(OrderedDictionary physicsDict)
{
var cubismPhysicsRig = JsonConvert.DeserializeObject<CubismPhysics>(JsonConvert.SerializeObject(physicsDict))._rig;
var physicsSettings = new CubismPhysics3Json.SerializablePhysicsSettings[cubismPhysicsRig.SubRigs.Length];
for (int i = 0; i < physicsSettings.Length; i++)
{
var subRigs = cubismPhysicsRig.SubRigs[i];
physicsSettings[i] = new CubismPhysics3Json.SerializablePhysicsSettings
{
Id = $"PhysicsSetting{i + 1}",
Input = new CubismPhysics3Json.SerializableInput[subRigs.Input.Length],
Output = new CubismPhysics3Json.SerializableOutput[subRigs.Output.Length],
Vertices = new CubismPhysics3Json.SerializableVertex[subRigs.Particles.Length],
Normalization = new CubismPhysics3Json.SerializableNormalization
{
Position = new CubismPhysics3Json.SerializableNormalizationValue
{
Minimum = subRigs.Normalization.Position.Minimum,
Default = subRigs.Normalization.Position.Default,
Maximum = subRigs.Normalization.Position.Maximum
},
Angle = new CubismPhysics3Json.SerializableNormalizationValue
{
Minimum = subRigs.Normalization.Angle.Minimum,
Default = subRigs.Normalization.Angle.Default,
Maximum = subRigs.Normalization.Angle.Maximum
}
}
};
for (int j = 0; j < subRigs.Input.Length; j++)
{
var input = subRigs.Input[j];
physicsSettings[i].Input[j] = new CubismPhysics3Json.SerializableInput
{
Source = new CubismPhysics3Json.SerializableParameter
{
Target = "Parameter", //同名GameObject父节点的名称
Id = input.SourceId
},
Weight = input.Weight,
Type = Enum.GetName(typeof(CubismPhysicsSourceComponent), input.SourceComponent),
Reflect = input.IsInverted
};
}
for (int j = 0; j < subRigs.Output.Length; j++)
{
var output = subRigs.Output[j];
physicsSettings[i].Output[j] = new CubismPhysics3Json.SerializableOutput
{
Destination = new CubismPhysics3Json.SerializableParameter
{
Target = "Parameter", //同名GameObject父节点的名称
Id = output.DestinationId
},
VertexIndex = output.ParticleIndex,
Scale = output.AngleScale,
Weight = output.Weight,
Type = Enum.GetName(typeof(CubismPhysicsSourceComponent), output.SourceComponent),
Reflect = output.IsInverted
};
}
for (int j = 0; j < subRigs.Particles.Length; j++)
{
var particles = subRigs.Particles[j];
physicsSettings[i].Vertices[j] = new CubismPhysics3Json.SerializableVertex
{
Position = particles.InitialPosition,
Mobility = particles.Mobility,
Delay = particles.Delay,
Acceleration = particles.Acceleration,
Radius = particles.Radius
};
}
}
var physicsDictionary = new CubismPhysics3Json.SerializablePhysicsDictionary[physicsSettings.Length];
for (int i = 0; i < physicsSettings.Length; i++)
{
physicsDictionary[i] = new CubismPhysics3Json.SerializablePhysicsDictionary
{
Id = $"PhysicsSetting{i + 1}",
Name = $"Dummy{i + 1}"
};
}
var physicsJson = new CubismPhysics3Json
{
Version = 3,
Meta = new CubismPhysics3Json.SerializableMeta
{
PhysicsSettingCount = cubismPhysicsRig.SubRigs.Length,
TotalInputCount = cubismPhysicsRig.SubRigs.Sum(x => x.Input.Length),
TotalOutputCount = cubismPhysicsRig.SubRigs.Sum(x => x.Output.Length),
VertexCount = cubismPhysicsRig.SubRigs.Sum(x => x.Particles.Length),
EffectiveForces = new CubismPhysics3Json.SerializableEffectiveForces
{
Gravity = cubismPhysicsRig.Gravity,
Wind = cubismPhysicsRig.Wind
},
PhysicsDictionary = physicsDictionary
},
PhysicsSettings = physicsSettings
};
return JsonConvert.SerializeObject(physicsJson, Formatting.Indented, new MyJsonConverter2());
}
public static OrderedDictionary ParseMonoBehaviour(MonoBehaviour m_MonoBehaviour, CubismMonoBehaviourType cubismMonoBehaviourType, AssemblyLoader assemblyLoader)
{
var orderedDict = m_MonoBehaviour.ToType();
if (orderedDict != null)
return orderedDict;
var fieldName = "";
var m_Type = m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
switch (cubismMonoBehaviourType)
{
case CubismMonoBehaviourType.FadeMotionList:
fieldName = "cubismfademotionobjects";
break;
case CubismMonoBehaviourType.FadeMotion:
fieldName = "parameterids";
break;
case CubismMonoBehaviourType.Expression:
fieldName = "parameters";
break;
case CubismMonoBehaviourType.Physics:
fieldName = "_rig";
break;
case CubismMonoBehaviourType.DisplayInfo:
fieldName = "name";
break;
}
if (m_Type.m_Nodes.FindIndex(x => x.m_Name.ToLower() == fieldName) < 0)
{
m_MonoBehaviour.m_Script.TryGet(out var m_MonoScript);
var assetName = m_MonoBehaviour.m_Name != "" ? m_MonoBehaviour.m_Name : m_MonoScript.m_ClassName;
Logger.Warning($"{cubismMonoBehaviourType} asset \"{assetName}\" is not readable");
return null;
}
orderedDict = m_MonoBehaviour.ToType(m_Type);
return orderedDict;
}
}
}

View File

@@ -1,55 +1,43 @@
//// ////
// Based on UnityLive2DExtractor by Perfare // Based on UnityLive2DExtractorMod by aelurum
// https://github.com/aelurum/UnityLive2DExtractor
//
// Original version - by Perfare
// https://github.com/Perfare/UnityLive2DExtractor // https://github.com/Perfare/UnityLive2DExtractor
//// ////
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AssetStudio; using AssetStudio;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using static CubismLive2DExtractor.CubismParsers;
namespace CubismLive2DExtractor namespace CubismLive2DExtractor
{ {
public sealed class Live2DExtractor public static class Live2DExtractor
{ {
private List<MonoBehaviour> Expressions { get; set; } public static void ExtractLive2D(IGrouping<string, AssetStudio.Object> assets, string destPath, string modelName, AssemblyLoader assemblyLoader, Live2DMotionMode motionMode, bool forceBezier = false)
private List<MonoBehaviour> FadeMotions { get; set; }
private List<GameObject> GameObjects { get; set; }
private List<AnimationClip> AnimationClips { get; set; }
private List<Texture2D> Texture2Ds { get; set; }
private HashSet<string> EyeBlinkParameters { get; set; }
private HashSet<string> LipSyncParameters { get; set; }
private HashSet<string> ParameterNames { get; set; }
private HashSet<string> PartNames { get; set; }
private MonoBehaviour MocMono { get; set; }
private MonoBehaviour PhysicsMono { get; set; }
private MonoBehaviour FadeMotionLst { get; set; }
private List<MonoBehaviour> ParametersCdi { get; set; }
private List<MonoBehaviour> PartsCdi { get; set; }
public Live2DExtractor(IGrouping<string, AssetStudio.Object> assets, List<AnimationClip> inClipMotions = null, List<MonoBehaviour> inFadeMotions = null, MonoBehaviour inFadeMotionLst = null)
{ {
Expressions = new List<MonoBehaviour>(); var destTexturePath = Path.Combine(destPath, "textures") + Path.DirectorySeparatorChar;
FadeMotions = inFadeMotions ?? new List<MonoBehaviour>(); var destMotionPath = Path.Combine(destPath, "motions") + Path.DirectorySeparatorChar;
AnimationClips = inClipMotions ?? new List<AnimationClip>(); var destExpressionPath = Path.Combine(destPath, "expressions") + Path.DirectorySeparatorChar;
GameObjects = new List<GameObject>(); Directory.CreateDirectory(destPath);
Texture2Ds = new List<Texture2D>(); Directory.CreateDirectory(destTexturePath);
EyeBlinkParameters = new HashSet<string>();
LipSyncParameters = new HashSet<string>(); var expressionList = new List<MonoBehaviour>();
ParameterNames = new HashSet<string>(); var fadeMotionList = new List<MonoBehaviour>();
PartNames = new HashSet<string>(); var gameObjects = new List<GameObject>();
FadeMotionLst = inFadeMotionLst; var animationClips = new List<AnimationClip>();
ParametersCdi = new List<MonoBehaviour>();
PartsCdi = new List<MonoBehaviour>(); var textures = new SortedSet<string>();
var eyeBlinkParameters = new HashSet<string>();
var lipSyncParameters = new HashSet<string>();
var parameterNames = new HashSet<string>();
var partNames = new HashSet<string>();
MonoBehaviour physics = null;
Logger.Debug("Sorting model assets..");
foreach (var asset in assets) foreach (var asset in assets)
{ {
switch (asset) switch (asset)
@@ -60,346 +48,226 @@ namespace CubismLive2DExtractor
switch (m_Script.m_ClassName) switch (m_Script.m_ClassName)
{ {
case "CubismMoc": case "CubismMoc":
MocMono = m_MonoBehaviour; File.WriteAllBytes($"{destPath}{modelName}.moc3", ParseMoc(m_MonoBehaviour)); //moc
break; break;
case "CubismPhysicsController": case "CubismPhysicsController":
PhysicsMono = m_MonoBehaviour; physics = physics ?? m_MonoBehaviour;
break; break;
case "CubismExpressionData": case "CubismExpressionData":
Expressions.Add(m_MonoBehaviour); expressionList.Add(m_MonoBehaviour);
break; break;
case "CubismFadeMotionData": case "CubismFadeMotionData":
if (inFadeMotions == null && inFadeMotionLst == null) fadeMotionList.Add(m_MonoBehaviour);
{
FadeMotions.Add(m_MonoBehaviour);
}
break;
case "CubismFadeMotionList":
if (inFadeMotions == null && inFadeMotionLst == null)
{
FadeMotionLst = m_MonoBehaviour;
}
break; break;
case "CubismEyeBlinkParameter": case "CubismEyeBlinkParameter":
if (m_MonoBehaviour.m_GameObject.TryGet(out var blinkGameObject)) if (m_MonoBehaviour.m_GameObject.TryGet(out var blinkGameObject))
{ {
EyeBlinkParameters.Add(blinkGameObject.m_Name); eyeBlinkParameters.Add(blinkGameObject.m_Name);
} }
break; break;
case "CubismMouthParameter": case "CubismMouthParameter":
if (m_MonoBehaviour.m_GameObject.TryGet(out var mouthGameObject)) if (m_MonoBehaviour.m_GameObject.TryGet(out var mouthGameObject))
{ {
LipSyncParameters.Add(mouthGameObject.m_Name); lipSyncParameters.Add(mouthGameObject.m_Name);
} }
break; break;
case "CubismParameter": case "CubismParameter":
if (m_MonoBehaviour.m_GameObject.TryGet(out var paramGameObject)) if (m_MonoBehaviour.m_GameObject.TryGet(out var paramGameObject))
{ {
ParameterNames.Add(paramGameObject.m_Name); parameterNames.Add(paramGameObject.m_Name);
} }
break; break;
case "CubismPart": case "CubismPart":
if (m_MonoBehaviour.m_GameObject.TryGet(out var partGameObject)) if (m_MonoBehaviour.m_GameObject.TryGet(out var partGameObject))
{ {
PartNames.Add(partGameObject.m_Name); partNames.Add(partGameObject.m_Name);
}
break;
case "CubismDisplayInfoParameterName":
if (m_MonoBehaviour.m_GameObject.TryGet(out _))
{
ParametersCdi.Add(m_MonoBehaviour);
}
break;
case "CubismDisplayInfoPartName":
if (m_MonoBehaviour.m_GameObject.TryGet(out _))
{
PartsCdi.Add(m_MonoBehaviour);
} }
break; break;
} }
} }
break; break;
case AnimationClip m_AnimationClip: case Texture2D m_Texture2D:
if (inClipMotions == null) using (var image = m_Texture2D.ConvertToImage(flip: true))
{ {
AnimationClips.Add(m_AnimationClip); using (var file = File.OpenWrite($"{destTexturePath}{m_Texture2D.m_Name}.png"))
{
image.WriteToStream(file, ImageFormat.Png);
}
textures.Add($"textures/{m_Texture2D.m_Name}.png"); //texture
} }
break; break;
case GameObject m_GameObject: case GameObject m_GameObject:
GameObjects.Add(m_GameObject); gameObjects.Add(m_GameObject);
break; break;
case Texture2D m_Texture2D: case AnimationClip m_AnimationClip:
Texture2Ds.Add(m_Texture2D); animationClips.Add(m_AnimationClip);
break; break;
} }
} }
}
public void ExtractCubismModel(string destPath, string modelName, Live2DMotionMode motionMode, AssemblyLoader assemblyLoader, bool forceBezier = false, int parallelTaskCount = 1) if (textures.Count == 0)
{
Directory.CreateDirectory(destPath);
#region moc3
using (var cubismModel = new CubismModel(MocMono))
{ {
var sb = new StringBuilder(); Logger.Warning($"No textures found for \"{modelName}\" model.");
sb.AppendLine("Model Stats:");
sb.AppendLine($"SDK Version: {cubismModel.VersionDescription}");
if (cubismModel.Version > 0)
{
sb.AppendLine($"Canvas Width: {cubismModel.CanvasWidth}");
sb.AppendLine($"Canvas Height: {cubismModel.CanvasHeight}");
sb.AppendLine($"Center X: {cubismModel.CentralPosX}");
sb.AppendLine($"Center Y: {cubismModel.CentralPosY}");
sb.AppendLine($"Pixel Per Unit: {cubismModel.PixelPerUnit}");
sb.AppendLine($"Part Count: {cubismModel.PartCount}");
sb.AppendLine($"Parameter Count: {cubismModel.ParamCount}");
Logger.Debug(sb.ToString());
ParameterNames = cubismModel.ParamNames;
PartNames = cubismModel.PartNames;
}
cubismModel.SaveMoc3($"{destPath}{modelName}.moc3");
}
#endregion
#region textures
var textures = new SortedSet<string>();
var destTexturePath = Path.Combine(destPath, "textures") + Path.DirectorySeparatorChar;
if (Texture2Ds.Count == 0)
{
Logger.Warning($"No textures found for \"{modelName}\" model");
}
else
{
Directory.CreateDirectory(destTexturePath);
} }
var textureBag = new ConcurrentBag<string>(); //physics
var savePathHash = new ConcurrentDictionary<string, bool>(); if (physics != null)
Parallel.ForEach(Texture2Ds, new ParallelOptions { MaxDegreeOfParallelism = parallelTaskCount }, texture2D =>
{ {
var savePath = $"{destTexturePath}{texture2D.m_Name}.png"; try
if (!savePathHash.TryAdd(savePath, true))
return;
using (var image = texture2D.ConvertToImage(flip: true))
{ {
using (var file = File.OpenWrite(savePath)) var buff = ParsePhysics(physics, assemblyLoader);
{ File.WriteAllText($"{destPath}{modelName}.physics3.json", buff);
image.WriteToStream(file, ImageFormat.Png);
}
textureBag.Add($"textures/{texture2D.m_Name}.png");
} }
}); catch (Exception e)
textures.UnionWith(textureBag);
#endregion
#region physics3.json
if (PhysicsMono != null)
{
var physicsDict = ParseMonoBehaviour(PhysicsMono, CubismMonoBehaviourType.Physics, assemblyLoader);
if (physicsDict != null)
{ {
try Logger.Warning($"Error in parsing physics data: {e.Message}");
{ physics = null;
var buff = ParsePhysics(physicsDict);
File.WriteAllText($"{destPath}{modelName}.physics3.json", buff);
}
catch (Exception e)
{
Logger.Warning($"Error in parsing physics data: {e.Message}");
PhysicsMono = null;
}
}
else
{
PhysicsMono = null;
} }
} }
#endregion
#region cdi3.json //motion
var isCdiParsed = false;
if (ParametersCdi.Count > 0 || PartsCdi.Count > 0)
{
var cdiJson = new CubismCdi3Json
{
Version = 3,
ParameterGroups = Array.Empty<CubismCdi3Json.ParamGroupArray>()
};
var parameters = new SortedSet<CubismCdi3Json.ParamGroupArray>();
foreach (var paramMono in ParametersCdi)
{
var displayName = GetDisplayName(paramMono, assemblyLoader);
if (displayName == null)
break;
paramMono.m_GameObject.TryGet(out var paramGameObject);
var paramId = paramGameObject.m_Name;
parameters.Add(new CubismCdi3Json.ParamGroupArray
{
Id = paramId,
GroupId = "",
Name = displayName
});
}
cdiJson.Parameters = parameters.ToArray();
var parts = new SortedSet<CubismCdi3Json.PartArray>();
foreach (var partMono in PartsCdi)
{
var displayName = GetDisplayName(partMono, assemblyLoader);
if (displayName == null)
break;
partMono.m_GameObject.TryGet(out var partGameObject);
var paramId = partGameObject.m_Name;
parts.Add(new CubismCdi3Json.PartArray
{
Id = paramId,
Name = displayName
});
}
cdiJson.Parts = parts.ToArray();
if (parts.Count > 0 || parameters.Count > 0)
{
File.WriteAllText($"{destPath}{modelName}.cdi3.json", JsonConvert.SerializeObject(cdiJson, Formatting.Indented));
isCdiParsed = true;
}
}
#endregion
#region motion3.json
var motions = new SortedDictionary<string, JArray>(); var motions = new SortedDictionary<string, JArray>();
var destMotionPath = Path.Combine(destPath, "motions") + Path.DirectorySeparatorChar;
if (motionMode == Live2DMotionMode.MonoBehaviour && FadeMotionLst != null) //Fade motions from Fade Motion List if (motionMode == Live2DMotionMode.MonoBehaviour && fadeMotionList.Count > 0) //motion from MonoBehaviour
{ {
Logger.Debug("Motion export method: MonoBehaviour (Fade motion)"); Logger.Debug("Motion export method: MonoBehaviour (Fade motion)");
var fadeMotionLstDict = ParseMonoBehaviour(FadeMotionLst, CubismMonoBehaviourType.FadeMotionList, assemblyLoader); Directory.CreateDirectory(destMotionPath);
if (fadeMotionLstDict != null) foreach (var fadeMotionMono in fadeMotionList)
{ {
CubismObjectList.AssetsFile = FadeMotionLst.assetsFile; var fadeMotionObj = fadeMotionMono.ToType();
var fadeMotionAssetList = JsonConvert.DeserializeObject<CubismObjectList>(JsonConvert.SerializeObject(fadeMotionLstDict)).GetFadeMotionAssetList(); if (fadeMotionObj == null)
if (fadeMotionAssetList?.Count > 0)
{ {
FadeMotions = fadeMotionAssetList; var m_Type = fadeMotionMono.ConvertToTypeTree(assemblyLoader);
Logger.Debug($"\"{FadeMotionLst.m_Name}\": found {fadeMotionAssetList.Count} motion(s)"); fadeMotionObj = fadeMotionMono.ToType(m_Type);
if (fadeMotionObj == null)
{
Logger.Warning($"Fade motion \"{fadeMotionMono.m_Name}\" is not readable.");
continue;
}
} }
var fadeMotion = JsonConvert.DeserializeObject<CubismFadeMotion>(JsonConvert.SerializeObject(fadeMotionObj));
if (fadeMotion.ParameterIds.Length == 0)
continue;
var motionJson = new CubismMotion3Json(fadeMotion, parameterNames, partNames, forceBezier);
var animName = Path.GetFileNameWithoutExtension(fadeMotion.m_Name);
if (motions.ContainsKey(animName))
{
animName = $"{animName}_{fadeMotion.GetHashCode()}";
if (motions.ContainsKey(animName))
continue;
}
var motionPath = new JObject(new JProperty("File", $"motions/{animName}.motion3.json"));
motions.Add(animName, new JArray(motionPath));
File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(motionJson, Formatting.Indented, new MyJsonConverter()));
} }
} }
else if (gameObjects.Count > 0) //motion from AnimationClip
if (motionMode == Live2DMotionMode.MonoBehaviour && FadeMotions.Count > 0) //motion from MonoBehaviour
{ {
ExportFadeMotions(destMotionPath, assemblyLoader, forceBezier, motions); var exportMethod = motionMode == Live2DMotionMode.AnimationClip
} ? "AnimationClip"
: "AnimationClip (no Fade motions found)";
if (motions.Count == 0) //motion from AnimationClip
{
CubismMotion3Converter converter = null;
var exportMethod = "AnimationClip";
if (motionMode != Live2DMotionMode.AnimationClipV1) //AnimationClipV2
{
exportMethod += "V2";
converter = new CubismMotion3Converter(AnimationClips, PartNames, ParameterNames);
}
else if (GameObjects.Count > 0) //AnimationClipV1
{
exportMethod += "V1";
var rootTransform = GameObjects[0].m_Transform;
while (rootTransform.m_Father.TryGet(out var m_Father))
{
rootTransform = m_Father;
}
rootTransform.m_GameObject.TryGet(out var rootGameObject);
converter = new CubismMotion3Converter(rootGameObject, AnimationClips);
}
if (motionMode == Live2DMotionMode.MonoBehaviour)
{
exportMethod = FadeMotions.Count > 0
? exportMethod + " (unable to export motions using Fade motion method)"
: exportMethod + " (no Fade motions found)";
}
Logger.Debug($"Motion export method: {exportMethod}"); Logger.Debug($"Motion export method: {exportMethod}");
var rootTransform = gameObjects[0].m_Transform;
while (rootTransform.m_Father.TryGet(out var m_Father))
{
rootTransform = m_Father;
}
rootTransform.m_GameObject.TryGet(out var rootGameObject);
var converter = new CubismMotion3Converter(rootGameObject, animationClips.ToArray());
if (converter.AnimationList.Count > 0)
{
Directory.CreateDirectory(destMotionPath);
}
foreach (var animation in converter.AnimationList)
{
var motionJson = new CubismMotion3Json(animation, forceBezier);
ExportClipMotions(destMotionPath, converter, forceBezier, motions); var animName = animation.Name;
if (motions.ContainsKey(animName))
{
animName = $"{animName}_{animation.GetHashCode()}";
if (motions.ContainsKey(animName))
continue;
}
var motionPath = new JObject(new JProperty("File", $"motions/{animName}.motion3.json"));
motions.Add(animName, new JArray(motionPath));
File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(motionJson, Formatting.Indented, new MyJsonConverter()));
}
} }
if (motions.Count == 0) if (motions.Count == 0)
{ {
Logger.Warning($"No exportable motions found for \"{modelName}\" model"); Logger.Warning($"No motions found for \"{modelName}\" model.");
} }
else
{
Logger.Info($"Exported {motions.Count} motion(s)");
}
#endregion
#region exp3.json //expression
var expressions = new JArray(); var expressions = new JArray();
var destExpressionPath = Path.Combine(destPath, "expressions") + Path.DirectorySeparatorChar; if (expressionList.Count > 0)
if (Expressions.Count > 0)
{ {
Directory.CreateDirectory(destExpressionPath); Directory.CreateDirectory(destExpressionPath);
} }
foreach (var monoBehaviour in Expressions) foreach (var monoBehaviour in expressionList)
{ {
var expressionName = monoBehaviour.m_Name.Replace(".exp3", ""); var expressionName = monoBehaviour.m_Name.Replace(".exp3", "");
var expressionDict = ParseMonoBehaviour(monoBehaviour, CubismMonoBehaviourType.Expression, assemblyLoader); var expressionObj = monoBehaviour.ToType();
if (expressionDict == null) if (expressionObj == null)
continue; {
var m_Type = monoBehaviour.ConvertToTypeTree(assemblyLoader);
var expression = JsonConvert.DeserializeObject<CubismExpression3Json>(JsonConvert.SerializeObject(expressionDict)); expressionObj = monoBehaviour.ToType(m_Type);
if (expressionObj == null)
{
Logger.Warning($"Expression \"{expressionName}\" is not readable.");
continue;
}
}
var expression = JsonConvert.DeserializeObject<CubismExpression3Json>(JsonConvert.SerializeObject(expressionObj));
expressions.Add(new JObject expressions.Add(new JObject
{ {
{ "Name", expressionName }, { "Name", expressionName },
{ "File", $"expressions/{expressionName}.exp3.json" } { "File", $"expressions/{expressionName}.exp3.json" }
}); });
File.WriteAllText($"{destExpressionPath}{expressionName}.exp3.json", JsonConvert.SerializeObject(expression, Formatting.Indented)); File.WriteAllText($"{destExpressionPath}{expressionName}.exp3.json", JsonConvert.SerializeObject(expression, Formatting.Indented));
} }
#endregion
#region model3.json //group
var groups = new List<CubismModel3Json.SerializableGroup>(); var groups = new List<CubismModel3Json.SerializableGroup>();
//Try looking for group IDs among the parameter names manually //Try looking for group IDs among the gameObjects
if (EyeBlinkParameters.Count == 0) if (eyeBlinkParameters.Count == 0)
{ {
EyeBlinkParameters = ParameterNames.Where(x => eyeBlinkParameters = gameObjects.Where(x =>
x.ToLower().Contains("eye") x.m_Name.ToLower().Contains("eye")
&& x.ToLower().Contains("open") && x.m_Name.ToLower().Contains("open")
&& (x.ToLower().Contains('l') || x.ToLower().Contains('r')) && (x.m_Name.ToLower().Contains('l') || x.m_Name.ToLower().Contains('r'))
).ToHashSet(); ).Select(x => x.m_Name).ToHashSet();
} }
if (LipSyncParameters.Count == 0) if (lipSyncParameters.Count == 0)
{ {
LipSyncParameters = ParameterNames.Where(x => lipSyncParameters = gameObjects.Where(x =>
x.ToLower().Contains("mouth") x.m_Name.ToLower().Contains("mouth")
&& x.ToLower().Contains("open") && x.m_Name.ToLower().Contains("open")
&& x.ToLower().Contains('y') && x.m_Name.ToLower().Contains('y')
).ToHashSet(); ).Select(x => x.m_Name).ToHashSet();
} }
groups.Add(new CubismModel3Json.SerializableGroup groups.Add(new CubismModel3Json.SerializableGroup
{ {
Target = "Parameter", Target = "Parameter",
Name = "EyeBlink", Name = "EyeBlink",
Ids = EyeBlinkParameters.ToArray() Ids = eyeBlinkParameters.ToArray()
}); });
groups.Add(new CubismModel3Json.SerializableGroup groups.Add(new CubismModel3Json.SerializableGroup
{ {
Target = "Parameter", Target = "Parameter",
Name = "LipSync", Name = "LipSync",
Ids = LipSyncParameters.ToArray() Ids = lipSyncParameters.ToArray()
}); });
//model
var model3 = new CubismModel3Json var model3 = new CubismModel3Json
{ {
Version = 3, Version = 3,
@@ -408,90 +276,140 @@ namespace CubismLive2DExtractor
{ {
Moc = $"{modelName}.moc3", Moc = $"{modelName}.moc3",
Textures = textures.ToArray(), Textures = textures.ToArray(),
DisplayInfo = isCdiParsed ? $"{modelName}.cdi3.json" : null,
Physics = PhysicsMono != null ? $"{modelName}.physics3.json" : null,
Motions = JObject.FromObject(motions), Motions = JObject.FromObject(motions),
Expressions = expressions, Expressions = expressions,
}, },
Groups = groups.ToArray() Groups = groups.ToArray()
}; };
if (physics != null)
{
model3.FileReferences.Physics = $"{modelName}.physics3.json";
}
File.WriteAllText($"{destPath}{modelName}.model3.json", JsonConvert.SerializeObject(model3, Formatting.Indented)); File.WriteAllText($"{destPath}{modelName}.model3.json", JsonConvert.SerializeObject(model3, Formatting.Indented));
#endregion
} }
private void ExportFadeMotions(string destMotionPath, AssemblyLoader assemblyLoader, bool forceBezier, SortedDictionary<string, JArray> motions) private static string ParsePhysics(MonoBehaviour physics, AssemblyLoader assemblyLoader)
{ {
Directory.CreateDirectory(destMotionPath); var physicsObj = physics.ToType();
foreach (var fadeMotionMono in FadeMotions) if (physicsObj == null)
{ {
var fadeMotionDict = ParseMonoBehaviour(fadeMotionMono, CubismMonoBehaviourType.FadeMotion, assemblyLoader); var m_Type = physics.ConvertToTypeTree(assemblyLoader);
if (fadeMotionDict == null) physicsObj = physics.ToType(m_Type);
continue; if (physicsObj == null)
var fadeMotion = JsonConvert.DeserializeObject<CubismFadeMotion>(JsonConvert.SerializeObject(fadeMotionDict));
if (fadeMotion.ParameterIds.Length == 0)
continue;
var motionJson = new CubismMotion3Json(fadeMotion, ParameterNames, PartNames, forceBezier);
var animName = Path.GetFileNameWithoutExtension(fadeMotion.m_Name);
if (motions.ContainsKey(animName))
{ {
animName = $"{animName}_{fadeMotion.GetHashCode()}"; throw new Exception("MonoBehaviour is not readable.");
if (motions.ContainsKey(animName))
continue;
} }
var motionPath = new JObject(new JProperty("File", $"motions/{animName}.motion3.json"));
motions.Add(animName, new JArray(motionPath));
File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(motionJson, Formatting.Indented, new MyJsonConverter()));
} }
var cubismPhysicsRig = JsonConvert.DeserializeObject<CubismPhysics>(JsonConvert.SerializeObject(physicsObj))._rig;
var physicsSettings = new CubismPhysics3Json.SerializablePhysicsSettings[cubismPhysicsRig.SubRigs.Length];
for (int i = 0; i < physicsSettings.Length; i++)
{
var subRigs = cubismPhysicsRig.SubRigs[i];
physicsSettings[i] = new CubismPhysics3Json.SerializablePhysicsSettings
{
Id = $"PhysicsSetting{i + 1}",
Input = new CubismPhysics3Json.SerializableInput[subRigs.Input.Length],
Output = new CubismPhysics3Json.SerializableOutput[subRigs.Output.Length],
Vertices = new CubismPhysics3Json.SerializableVertex[subRigs.Particles.Length],
Normalization = new CubismPhysics3Json.SerializableNormalization
{
Position = new CubismPhysics3Json.SerializableNormalizationValue
{
Minimum = subRigs.Normalization.Position.Minimum,
Default = subRigs.Normalization.Position.Default,
Maximum = subRigs.Normalization.Position.Maximum
},
Angle = new CubismPhysics3Json.SerializableNormalizationValue
{
Minimum = subRigs.Normalization.Angle.Minimum,
Default = subRigs.Normalization.Angle.Default,
Maximum = subRigs.Normalization.Angle.Maximum
}
}
};
for (int j = 0; j < subRigs.Input.Length; j++)
{
var input = subRigs.Input[j];
physicsSettings[i].Input[j] = new CubismPhysics3Json.SerializableInput
{
Source = new CubismPhysics3Json.SerializableParameter
{
Target = "Parameter", //同名GameObject父节点的名称
Id = input.SourceId
},
Weight = input.Weight,
Type = Enum.GetName(typeof(CubismPhysicsSourceComponent), input.SourceComponent),
Reflect = input.IsInverted
};
}
for (int j = 0; j < subRigs.Output.Length; j++)
{
var output = subRigs.Output[j];
physicsSettings[i].Output[j] = new CubismPhysics3Json.SerializableOutput
{
Destination = new CubismPhysics3Json.SerializableParameter
{
Target = "Parameter", //同名GameObject父节点的名称
Id = output.DestinationId
},
VertexIndex = output.ParticleIndex,
Scale = output.AngleScale,
Weight = output.Weight,
Type = Enum.GetName(typeof(CubismPhysicsSourceComponent), output.SourceComponent),
Reflect = output.IsInverted
};
}
for (int j = 0; j < subRigs.Particles.Length; j++)
{
var particles = subRigs.Particles[j];
physicsSettings[i].Vertices[j] = new CubismPhysics3Json.SerializableVertex
{
Position = particles.InitialPosition,
Mobility = particles.Mobility,
Delay = particles.Delay,
Acceleration = particles.Acceleration,
Radius = particles.Radius
};
}
}
var physicsDictionary = new CubismPhysics3Json.SerializablePhysicsDictionary[physicsSettings.Length];
for (int i = 0; i < physicsSettings.Length; i++)
{
physicsDictionary[i] = new CubismPhysics3Json.SerializablePhysicsDictionary
{
Id = $"PhysicsSetting{i + 1}",
Name = $"Dummy{i + 1}"
};
}
var physicsJson = new CubismPhysics3Json
{
Version = 3,
Meta = new CubismPhysics3Json.SerializableMeta
{
PhysicsSettingCount = cubismPhysicsRig.SubRigs.Length,
TotalInputCount = cubismPhysicsRig.SubRigs.Sum(x => x.Input.Length),
TotalOutputCount = cubismPhysicsRig.SubRigs.Sum(x => x.Output.Length),
VertexCount = cubismPhysicsRig.SubRigs.Sum(x => x.Particles.Length),
EffectiveForces = new CubismPhysics3Json.SerializableEffectiveForces
{
Gravity = cubismPhysicsRig.Gravity,
Wind = cubismPhysicsRig.Wind
},
PhysicsDictionary = physicsDictionary
},
PhysicsSettings = physicsSettings
};
return JsonConvert.SerializeObject(physicsJson, Formatting.Indented, new MyJsonConverter2());
} }
private static void ExportClipMotions(string destMotionPath, CubismMotion3Converter converter, bool forceBezier, SortedDictionary<string, JArray> motions) private static byte[] ParseMoc(MonoBehaviour moc)
{ {
if (converter == null) var reader = moc.reader;
return; reader.Reset();
reader.Position += 28; //PPtr<GameObject> m_GameObject, m_Enabled, PPtr<MonoScript>
if (converter.AnimationList.Count > 0) reader.ReadAlignedString(); //m_Name
{ return reader.ReadBytes(reader.ReadInt32());
Directory.CreateDirectory(destMotionPath);
}
foreach (var animation in converter.AnimationList)
{
var animName = animation.Name;
if (animation.TrackList.Count == 0)
{
Logger.Warning($"Motion \"{animName}\" is empty. Export skipped");
continue;
}
var motionJson = new CubismMotion3Json(animation, forceBezier);
if (motions.ContainsKey(animName))
{
animName = $"{animName}_{animation.GetHashCode()}";
if (motions.ContainsKey(animName))
continue;
}
var motionPath = new JObject(new JProperty("File", $"motions/{animName}.motion3.json"));
motions.Add(animName, new JArray(motionPath));
File.WriteAllText($"{destMotionPath}{animName}.motion3.json", JsonConvert.SerializeObject(motionJson, Formatting.Indented, new MyJsonConverter()));
}
}
private static string GetDisplayName(MonoBehaviour cdiMono, AssemblyLoader assemblyLoader)
{
var dict = ParseMonoBehaviour(cdiMono, CubismMonoBehaviourType.DisplayInfo, assemblyLoader);
if (dict == null)
return null;
var name = (string)dict["Name"];
if (dict.Contains("DisplayName"))
{
var displayName = (string)dict["DisplayName"];
name = displayName != "" ? displayName : name;
}
return name;
} }
} }
} }

View File

@@ -3,7 +3,6 @@
public enum Live2DMotionMode public enum Live2DMotionMode
{ {
MonoBehaviour, MonoBehaviour,
AnimationClipV1, AnimationClip
AnimationClipV2,
} }
} }

View File

@@ -16,7 +16,7 @@ namespace AssetStudio
private ImageFormat imageFormat; private ImageFormat imageFormat;
private Avatar avatar; private Avatar avatar;
private AnimationClip[] animationClipUniqArray = Array.Empty<AnimationClip>(); //TODO: a proper AnimationClip equality comparer private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
private Dictionary<AnimationClip, string> boundAnimationPathDic = new Dictionary<AnimationClip, string>(); private Dictionary<AnimationClip, string> boundAnimationPathDic = new Dictionary<AnimationClip, string>();
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>(); private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>(); private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
@@ -40,7 +40,10 @@ namespace AssetStudio
} }
if (animationList != null) if (animationList != null)
{ {
animationClipUniqArray = animationList.Distinct().ToArray(); foreach (var animationClip in animationList)
{
animationClipHashSet.Add(animationClip);
}
} }
ConvertAnimations(); ConvertAnimations();
} }
@@ -67,7 +70,10 @@ namespace AssetStudio
} }
if (animationList != null) if (animationList != null)
{ {
animationClipUniqArray = animationList.Distinct().ToArray(); foreach (var animationClip in animationList)
{
animationClipHashSet.Add(animationClip);
}
} }
ConvertAnimations(); ConvertAnimations();
} }
@@ -82,7 +88,10 @@ namespace AssetStudio
} }
else else
{ {
animationClipUniqArray = animationList.Distinct().ToArray(); foreach (var animationClip in animationList)
{
animationClipHashSet.Add(animationClip);
}
} }
ConvertAnimations(); ConvertAnimations();
} }
@@ -151,7 +160,6 @@ namespace AssetStudio
if (m_GameObject.m_Animation != null) if (m_GameObject.m_Animation != null)
{ {
var animationList = new List<AnimationClip>();
foreach (var animation in m_GameObject.m_Animation.m_Animations) foreach (var animation in m_GameObject.m_Animation.m_Animations)
{ {
if (animation.TryGet(out var animationClip)) if (animation.TryGet(out var animationClip))
@@ -160,10 +168,9 @@ namespace AssetStudio
{ {
boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform)); boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform));
} }
animationList.Add(animationClip); animationClipHashSet.Add(animationClip);
} }
} }
animationClipUniqArray = animationList.Distinct().ToArray();
} }
foreach (var pptr in m_Transform.m_Children) foreach (var pptr in m_Transform.m_Children)
@@ -177,7 +184,6 @@ namespace AssetStudio
{ {
if (m_Animator.m_Controller.TryGet(out var m_Controller)) if (m_Animator.m_Controller.TryGet(out var m_Controller))
{ {
var animationList = new List<AnimationClip>();
switch (m_Controller) switch (m_Controller)
{ {
case AnimatorOverrideController m_AnimatorOverrideController: case AnimatorOverrideController m_AnimatorOverrideController:
@@ -188,7 +194,7 @@ namespace AssetStudio
{ {
if (pptr.TryGet(out var m_AnimationClip)) if (pptr.TryGet(out var m_AnimationClip))
{ {
animationList.Add(m_AnimationClip); animationClipHashSet.Add(m_AnimationClip);
} }
} }
} }
@@ -201,13 +207,12 @@ namespace AssetStudio
{ {
if (pptr.TryGet(out var m_AnimationClip)) if (pptr.TryGet(out var m_AnimationClip))
{ {
animationList.Add(m_AnimationClip); animationClipHashSet.Add(m_AnimationClip);
} }
} }
break; break;
} }
} }
animationClipUniqArray = animationList.Distinct().ToArray();
} }
} }
@@ -366,7 +371,6 @@ namespace AssetStudio
{ {
if (iMesh.hasUV[uv]) if (iMesh.hasUV[uv])
{ {
c = 4;
var m_UV = mesh.GetUV(uv); var m_UV = mesh.GetUV(uv);
if (m_UV.Length == mesh.m_VertexCount * 2) if (m_UV.Length == mesh.m_VertexCount * 2)
{ {
@@ -765,7 +769,7 @@ namespace AssetStudio
private void ConvertAnimations() private void ConvertAnimations()
{ {
foreach (var animationClip in animationClipUniqArray) foreach (var animationClip in animationClipHashSet)
{ {
var iAnim = new ImportedKeyframedAnimation(); var iAnim = new ImportedKeyframedAnimation();
var name = animationClip.m_Name; var name = animationClip.m_Name;
@@ -873,7 +877,7 @@ namespace AssetStudio
} }
else else
{ {
var m_Clip = animationClip.m_MuscleClip.m_Clip.data; var m_Clip = animationClip.m_MuscleClip.m_Clip;
var streamedFrames = m_Clip.m_StreamedClip.ReadData(); var streamedFrames = m_Clip.m_StreamedClip.ReadData();
var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding(); var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding();
for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++) for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
@@ -1012,16 +1016,18 @@ namespace AssetStudio
private void CreateBonePathHash(Transform m_Transform) private void CreateBonePathHash(Transform m_Transform)
{ {
var name = GetTransformPathByFather(m_Transform); var name = GetTransformPathByFather(m_Transform);
var crc = new SevenZip.CRC();
var bytes = Encoding.UTF8.GetBytes(name); var bytes = Encoding.UTF8.GetBytes(name);
var crc = SevenZip.CRC.CalculateDigest(bytes, 0, (uint)bytes.Length); crc.Update(bytes, 0, (uint)bytes.Length);
bonePathHash[crc] = name; bonePathHash[crc.GetDigest()] = name;
int index; int index;
while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0) while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0)
{ {
name = name.Substring(index + 1); name = name.Substring(index + 1);
crc = new SevenZip.CRC();
bytes = Encoding.UTF8.GetBytes(name); bytes = Encoding.UTF8.GetBytes(name);
crc = SevenZip.CRC.CalculateDigest(bytes, 0, (uint)bytes.Length); crc.Update(bytes, 0, (uint)bytes.Length);
bonePathHash[crc] = name; bonePathHash[crc.GetDigest()] = name;
} }
foreach (var pptr in m_Transform.m_Children) foreach (var pptr in m_Transform.m_Children)
{ {
@@ -1096,7 +1102,10 @@ namespace AssetStudio
{ {
return name; return name;
} }
return null; else
{
return null;
}
} }
} }
} }

View File

@@ -4,9 +4,9 @@ namespace AssetStudio
{ {
public class SerializedTypeHelper public class SerializedTypeHelper
{ {
private readonly UnityVersion version; private readonly int[] version;
public SerializedTypeHelper(UnityVersion version) public SerializedTypeHelper(int[] version)
{ {
this.version = version; this.version = version;
} }
@@ -24,7 +24,7 @@ namespace AssetStudio
{ {
nodes.Add(new TypeTreeNode($"PPtr<{type}>", name, indent, false)); nodes.Add(new TypeTreeNode($"PPtr<{type}>", name, indent, false));
nodes.Add(new TypeTreeNode("int", "m_FileID", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_FileID", indent + 1, false));
if (version >= 5) //5.0 and up if (version[0] >= 5) //5.0 and up
{ {
nodes.Add(new TypeTreeNode("SInt64", "m_PathID", indent + 1, false)); nodes.Add(new TypeTreeNode("SInt64", "m_PathID", indent + 1, false));
} }
@@ -58,7 +58,7 @@ namespace AssetStudio
nodes.Add(new TypeTreeNode("float", "value", indent + 4, false)); nodes.Add(new TypeTreeNode("float", "value", indent + 4, false));
nodes.Add(new TypeTreeNode("float", "inSlope", indent + 4, false)); nodes.Add(new TypeTreeNode("float", "inSlope", indent + 4, false));
nodes.Add(new TypeTreeNode("float", "outSlope", indent + 4, false)); nodes.Add(new TypeTreeNode("float", "outSlope", indent + 4, false));
if (version >= 2018) //2018 and up if (version[0] >= 2018) //2018 and up
{ {
nodes.Add(new TypeTreeNode("int", "weightedMode", indent + 4, false)); nodes.Add(new TypeTreeNode("int", "weightedMode", indent + 4, false));
nodes.Add(new TypeTreeNode("float", "inWeight", indent + 4, false)); nodes.Add(new TypeTreeNode("float", "inWeight", indent + 4, false));
@@ -66,7 +66,7 @@ namespace AssetStudio
} }
nodes.Add(new TypeTreeNode("int", "m_PreInfinity", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_PreInfinity", indent + 1, false));
nodes.Add(new TypeTreeNode("int", "m_PostInfinity", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_PostInfinity", indent + 1, false));
if (version >= (5, 3)) //5.3 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
{ {
nodes.Add(new TypeTreeNode("int", "m_RotationOrder", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_RotationOrder", indent + 1, false));
} }
@@ -75,7 +75,7 @@ namespace AssetStudio
public void AddGradient(List<TypeTreeNode> nodes, string name, int indent) public void AddGradient(List<TypeTreeNode> nodes, string name, int indent)
{ {
nodes.Add(new TypeTreeNode("Gradient", name, indent, false)); nodes.Add(new TypeTreeNode("Gradient", name, indent, false));
if (version >= (5, 6)) //5.6 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
{ {
AddColorRGBA(nodes, "key0", indent + 1); AddColorRGBA(nodes, "key0", indent + 1);
AddColorRGBA(nodes, "key1", indent + 1); AddColorRGBA(nodes, "key1", indent + 1);
@@ -113,7 +113,7 @@ namespace AssetStudio
nodes.Add(new TypeTreeNode("UInt16", "atime5", indent + 1, false)); nodes.Add(new TypeTreeNode("UInt16", "atime5", indent + 1, false));
nodes.Add(new TypeTreeNode("UInt16", "atime6", indent + 1, false)); nodes.Add(new TypeTreeNode("UInt16", "atime6", indent + 1, false));
nodes.Add(new TypeTreeNode("UInt16", "atime7", indent + 1, false)); nodes.Add(new TypeTreeNode("UInt16", "atime7", indent + 1, false));
if (version >= (5, 5)) //5.5 and up if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
{ {
nodes.Add(new TypeTreeNode("int", "m_Mode", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_Mode", indent + 1, false));
} }
@@ -134,7 +134,7 @@ namespace AssetStudio
AddGUIStyleState(nodes, "m_OnActive", indent + 1); AddGUIStyleState(nodes, "m_OnActive", indent + 1);
AddGUIStyleState(nodes, "m_OnFocused", indent + 1); AddGUIStyleState(nodes, "m_OnFocused", indent + 1);
AddRectOffset(nodes, "m_Border", indent + 1); AddRectOffset(nodes, "m_Border", indent + 1);
if (version >= 4) //4 and up if (version[0] >= 4) //4 and up
{ {
AddRectOffset(nodes, "m_Margin", indent + 1); AddRectOffset(nodes, "m_Margin", indent + 1);
AddRectOffset(nodes, "m_Padding", indent + 1); AddRectOffset(nodes, "m_Padding", indent + 1);
@@ -146,7 +146,7 @@ namespace AssetStudio
} }
AddRectOffset(nodes, "m_Overflow", indent + 1); AddRectOffset(nodes, "m_Overflow", indent + 1);
AddPPtr(nodes, "Font", "m_Font", indent + 1); AddPPtr(nodes, "Font", "m_Font", indent + 1);
if (version >= 4) //4 and up if (version[0] >= 4) //4 and up
{ {
nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false));
nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false));
@@ -171,7 +171,7 @@ namespace AssetStudio
AddVector2f(nodes, "m_ClipOffset", indent + 1); AddVector2f(nodes, "m_ClipOffset", indent + 1);
nodes.Add(new TypeTreeNode("float", "m_FixedWidth", indent + 1, false)); nodes.Add(new TypeTreeNode("float", "m_FixedWidth", indent + 1, false));
nodes.Add(new TypeTreeNode("float", "m_FixedHeight", indent + 1, false)); nodes.Add(new TypeTreeNode("float", "m_FixedHeight", indent + 1, false));
if (version >= 3) //3 and up if (version[0] >= 3) //3 and up
{ {
nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false));
nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false)); nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false));

Some files were not shown because too many files have changed in this diff Show More