Compare commits
81 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb7accd04d | ||
|
|
5120999026 | ||
|
|
1fc504e587 | ||
|
|
4e991d85fb | ||
|
|
29b4bb59a0 | ||
|
|
9750f486d5 | ||
|
|
97bbfe8fbb | ||
|
|
684bf5a874 | ||
|
|
3cc6bed844 | ||
|
|
c9e9bc840c | ||
|
|
cadcf0b492 | ||
|
|
1e8085da2d | ||
|
|
770d7e7532 | ||
|
|
d0d8a35f67 | ||
|
|
3f004f74d1 | ||
|
|
3effd06e64 | ||
|
|
4f0afffeba | ||
|
|
9b69b5607c | ||
|
|
9b16ea8d41 | ||
|
|
ae4548f1c3 | ||
|
|
4cd246592b | ||
|
|
f54cc004bd | ||
|
|
afdc81bca8 | ||
|
|
045f6c0ff4 | ||
|
|
bc9380b8be | ||
|
|
46f8023756 | ||
|
|
0f9afa60d7 | ||
|
|
ec7f2c393d | ||
|
|
3ec8169b08 | ||
|
|
5c24183d18 | ||
|
|
c68eaa5e3c | ||
|
|
8460ecef8d | ||
|
|
f90c0ecc00 | ||
|
|
535153be6b | ||
|
|
d4162161be | ||
|
|
6fe12d274f | ||
|
|
70213e3012 | ||
|
|
2f6d9ec77f | ||
|
|
0d2aebc1f4 | ||
|
|
115074fdc0 | ||
|
|
c2d3b8c5f9 | ||
|
|
67a74fd395 | ||
|
|
a00c857ac3 | ||
|
|
5333757843 | ||
|
|
4747687bec | ||
|
|
5c2ac1a5e8 | ||
|
|
e2eae53ac0 | ||
|
|
87347e8b60 | ||
|
|
0fdbddea55 | ||
|
|
823190abb7 | ||
|
|
60aef1b8ed | ||
|
|
f82a73f018 | ||
|
|
d42a1879ab | ||
|
|
632e5f8d08 | ||
|
|
51d259464b | ||
|
|
efd06648ad | ||
|
|
b27482e22b | ||
|
|
d572bd0e64 | ||
|
|
e415740373 | ||
|
|
45bf9251c9 | ||
|
|
75ebe67713 | ||
|
|
ed7b0a2415 | ||
|
|
22ab5c0633 | ||
|
|
a2bc935850 | ||
|
|
cb84c137e5 | ||
|
|
25c611fb9e | ||
|
|
6d3875cb2c | ||
|
|
be4ced77ea | ||
|
|
2bd762e8f4 | ||
|
|
a926644ff6 | ||
|
|
a4cdff5934 | ||
|
|
2e10e627b0 | ||
|
|
e216abd6be | ||
|
|
93c7e617d8 | ||
|
|
000916913e | ||
|
|
28f9744497 | ||
|
|
c3f99216b6 | ||
|
|
19c4835ea3 | ||
|
|
6b321da695 | ||
|
|
7cca301f7a | ||
|
|
5ac597c935 |
@@ -1,9 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -22,26 +22,26 @@ namespace SevenZip
|
||||
}
|
||||
}
|
||||
|
||||
uint _value = 0xFFFFFFFF;
|
||||
private uint _value = 0xFFFFFFFF;
|
||||
|
||||
public void Init() { _value = 0xFFFFFFFF; }
|
||||
|
||||
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)
|
||||
{
|
||||
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; }
|
||||
|
||||
static uint CalculateDigest(byte[] data, uint offset, uint size)
|
||||
public static uint CalculateDigest(byte[] data, uint offset, uint size)
|
||||
{
|
||||
CRC crc = new CRC();
|
||||
var crc = new CRC();
|
||||
// crc.Init();
|
||||
crc.Update(data, offset, size);
|
||||
return crc.GetDigest();
|
||||
@@ -49,7 +49,7 @@ namespace SevenZip
|
||||
|
||||
static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
|
||||
{
|
||||
return (CalculateDigest(data, offset, size) == digest);
|
||||
return CalculateDigest(data, offset, size) == digest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,26 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023-2024</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
|
||||
<PackageReference Include="K4os.Compression.LZ4" Version="1.3.8" />
|
||||
<PackageReference Include="ZstdSharp.Port" Version="0.7.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
<PackageReference Include="System.Memory" Version="4.5.4" />
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.0.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>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
@@ -10,18 +11,48 @@ namespace AssetStudio
|
||||
{
|
||||
public class AssetsManager
|
||||
{
|
||||
public string SpecifyUnityVersion;
|
||||
public bool ZstdEnabled = true;
|
||||
public bool LoadingViaTypeTreeEnabled = true;
|
||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||
private HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
|
||||
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||
internal ConcurrentDictionary<string, BinaryReader> resourceFileReaders = new ConcurrentDictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private UnityVersion specifiedUnityVersion;
|
||||
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> noexistFiles = 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)
|
||||
{
|
||||
if (filteredAssetTypesList.Count == 0)
|
||||
@@ -30,6 +61,8 @@ namespace AssetStudio
|
||||
{
|
||||
ClassIDType.AssetBundle,
|
||||
ClassIDType.ResourceManager,
|
||||
ClassIDType.GameObject,
|
||||
ClassIDType.Transform,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,8 +73,9 @@ namespace AssetStudio
|
||||
if (classIDTypes.Contains(ClassIDType.Sprite))
|
||||
{
|
||||
filteredAssetTypesList.Add(ClassIDType.Texture2D);
|
||||
filteredAssetTypesList.Add(ClassIDType.SpriteAtlas);
|
||||
}
|
||||
|
||||
|
||||
filteredAssetTypesList.UnionWith(classIDTypes);
|
||||
}
|
||||
|
||||
@@ -52,21 +86,21 @@ namespace AssetStudio
|
||||
|
||||
public void LoadFilesAndFolders(params string[] path)
|
||||
{
|
||||
List<string> pathList = new List<string>();
|
||||
var pathList = new List<string>();
|
||||
pathList.AddRange(path);
|
||||
LoadFilesAndFolders(out _, pathList);
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, params string[] path)
|
||||
{
|
||||
List<string> pathList = new List<string>();
|
||||
var pathList = new List<string>();
|
||||
pathList.AddRange(path);
|
||||
LoadFilesAndFolders(out parentPath, pathList);
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
|
||||
{
|
||||
List<string> fileList = new List<string>();
|
||||
var fileList = new List<string>();
|
||||
bool filesInPath = false;
|
||||
parentPath = "";
|
||||
foreach (var path in pathList)
|
||||
@@ -82,7 +116,7 @@ namespace AssetStudio
|
||||
MergeSplitAssets(fullPath, true);
|
||||
fileList.AddRange(Directory.GetFiles(fullPath, "*.*", SearchOption.AllDirectories));
|
||||
}
|
||||
else
|
||||
else if (File.Exists(fullPath))
|
||||
{
|
||||
parentPath = Path.GetDirectoryName(fullPath);
|
||||
fileList.Add(fullPath);
|
||||
@@ -112,8 +146,14 @@ namespace AssetStudio
|
||||
//use a for loop because list size can change
|
||||
for (var i = 0; i < importFiles.Count; i++)
|
||||
{
|
||||
LoadFile(importFiles[i]);
|
||||
Progress.Report(i + 1, importFiles.Count);
|
||||
if (LoadFile(importFiles[i]))
|
||||
{
|
||||
Progress.Report(i + 1, importFiles.Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
importFiles.Clear();
|
||||
@@ -125,22 +165,20 @@ namespace AssetStudio
|
||||
ProcessAssets();
|
||||
}
|
||||
|
||||
private void LoadFile(string fullName)
|
||||
private bool LoadFile(string fullName)
|
||||
{
|
||||
var reader = new FileReader(fullName);
|
||||
LoadFile(reader);
|
||||
return LoadFile(reader);
|
||||
}
|
||||
|
||||
private void LoadFile(FileReader reader)
|
||||
private bool LoadFile(FileReader reader)
|
||||
{
|
||||
switch (reader.FileType)
|
||||
switch (reader?.FileType)
|
||||
{
|
||||
case FileType.AssetsFile:
|
||||
LoadAssetsFile(reader);
|
||||
break;
|
||||
return LoadAssetsFile(reader);
|
||||
case FileType.BundleFile:
|
||||
LoadBundleFile(reader);
|
||||
break;
|
||||
return LoadBundleFile(reader);
|
||||
case FileType.WebFile:
|
||||
LoadWebFile(reader);
|
||||
break;
|
||||
@@ -154,9 +192,10 @@ namespace AssetStudio
|
||||
LoadZipFile(reader);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadAssetsFile(FileReader reader)
|
||||
private bool LoadAssetsFile(FileReader reader)
|
||||
{
|
||||
if (!assetsFileListHash.Contains(reader.FileName))
|
||||
{
|
||||
@@ -164,6 +203,7 @@ namespace AssetStudio
|
||||
try
|
||||
{
|
||||
var assetsFile = new SerializedFile(reader, this);
|
||||
var dirName = Path.GetDirectoryName(reader.FullPath);
|
||||
CheckStrippedVersion(assetsFile);
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
@@ -174,12 +214,12 @@ namespace AssetStudio
|
||||
|
||||
if (!importFilesHash.Contains(sharedFileName))
|
||||
{
|
||||
var sharedFilePath = Path.Combine(Path.GetDirectoryName(reader.FullPath), sharedFileName);
|
||||
var sharedFilePath = Path.Combine(dirName, sharedFileName);
|
||||
if (!noexistFiles.Contains(sharedFilePath))
|
||||
{
|
||||
if (!File.Exists(sharedFilePath))
|
||||
{
|
||||
var findFiles = Directory.GetFiles(Path.GetDirectoryName(reader.FullPath), sharedFileName, SearchOption.AllDirectories);
|
||||
var findFiles = Directory.GetFiles(dirName, sharedFileName, SearchOption.AllDirectories);
|
||||
if (findFiles.Length > 0)
|
||||
{
|
||||
sharedFilePath = findFiles[0];
|
||||
@@ -202,10 +242,11 @@ namespace AssetStudio
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
reader.Dispose();
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while reading assets file {reader.FullPath}\r\n{e}");
|
||||
Logger.Warning($"Failed to read assets file {reader.FullPath}\r\n{e}");
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -214,9 +255,10 @@ namespace AssetStudio
|
||||
Logger.Info($"Skipping {reader.FullPath}");
|
||||
reader.Dispose();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadAssetsFromMemory(FileReader reader, string originalPath, string unityVersion = null)
|
||||
private bool LoadAssetsFromMemory(FileReader reader, string originalPath, UnityVersion assetBundleUnityVer = null)
|
||||
{
|
||||
if (!assetsFileListHash.Contains(reader.FileName))
|
||||
{
|
||||
@@ -224,52 +266,59 @@ namespace AssetStudio
|
||||
{
|
||||
var assetsFile = new SerializedFile(reader, this);
|
||||
assetsFile.originalPath = originalPath;
|
||||
if (!string.IsNullOrEmpty(unityVersion) && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
|
||||
if (assetBundleUnityVer != null && assetsFile.header.m_Version < SerializedFileFormatVersion.Unknown_7)
|
||||
{
|
||||
assetsFile.SetVersion(unityVersion);
|
||||
assetsFile.SetVersion(assetBundleUnityVer);
|
||||
}
|
||||
CheckStrippedVersion(assetsFile);
|
||||
CheckStrippedVersion(assetsFile, assetBundleUnityVer);
|
||||
assetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
resourceFileReaders.Add(reader.FileName, reader);
|
||||
resourceFileReaders.TryAdd(reader.FileName, reader);
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while reading assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}");
|
||||
resourceFileReaders.Add(reader.FileName, reader);
|
||||
Logger.Warning($"Failed to read assets file {reader.FullPath} from {Path.GetFileName(originalPath)}\r\n{e}");
|
||||
resourceFileReaders.TryAdd(reader.FileName, reader);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"Skipping {originalPath} ({reader.FileName})");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void LoadBundleFile(FileReader reader, string originalPath = null)
|
||||
private bool LoadBundleFile(FileReader reader, string originalPath = null)
|
||||
{
|
||||
Logger.Info("Loading " + reader.FullPath);
|
||||
try
|
||||
{
|
||||
var bundleFile = new BundleFile(reader, SpecifyUnityVersion);
|
||||
var bundleFile = new BundleFile(reader, ZstdEnabled, specifiedUnityVersion);
|
||||
foreach (var file in bundleFile.fileList)
|
||||
{
|
||||
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), file.fileName);
|
||||
var subReader = new FileReader(dummyPath, file.stream);
|
||||
if (subReader.FileType == FileType.AssetsFile)
|
||||
{
|
||||
LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision);
|
||||
if (!LoadAssetsFromMemory(subReader, originalPath ?? reader.FullPath, bundleFile.m_Header.unityRevision))
|
||||
return false;
|
||||
}
|
||||
else if (!resourceFileReaders.ContainsKey(file.fileName))
|
||||
else
|
||||
{
|
||||
resourceFileReaders.Add(file.fileName, subReader);
|
||||
resourceFileReaders.TryAdd(file.fileName, subReader);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
{
|
||||
Logger.Error(e.Message);
|
||||
return false;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -279,6 +328,7 @@ namespace AssetStudio
|
||||
str += $" from {Path.GetFileName(originalPath)}";
|
||||
}
|
||||
Logger.Warning($"{str}\r\n{e}");
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -403,10 +453,7 @@ namespace AssetStudio
|
||||
if (entryReader.FileType == FileType.ResourceFile)
|
||||
{
|
||||
entryReader.Position = 0;
|
||||
if (!resourceFileReaders.ContainsKey(entry.Name))
|
||||
{
|
||||
resourceFileReaders.Add(entry.Name, entryReader);
|
||||
}
|
||||
resourceFileReaders.TryAdd(entry.Name, entryReader);
|
||||
}
|
||||
Progress.Report(++k, progressCount);
|
||||
}
|
||||
@@ -427,13 +474,16 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckStrippedVersion(SerializedFile assetsFile)
|
||||
public void CheckStrippedVersion(SerializedFile assetsFile, UnityVersion bundleUnityVer = null)
|
||||
{
|
||||
if (assetsFile.IsVersionStripped && string.IsNullOrEmpty(SpecifyUnityVersion))
|
||||
if (assetsFile.version.IsStripped && specifiedUnityVersion == null)
|
||||
{
|
||||
throw new NotSupportedException("The Unity version has been stripped, please set the version in the options");
|
||||
var msg = "The asset's 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 (!string.IsNullOrEmpty(SpecifyUnityVersion))
|
||||
if (specifiedUnityVersion != null)
|
||||
{
|
||||
assetsFile.SetVersion(SpecifyUnityVersion);
|
||||
}
|
||||
@@ -482,7 +532,9 @@ namespace AssetStudio
|
||||
obj = new Animation(objectReader);
|
||||
break;
|
||||
case ClassIDType.AnimationClip:
|
||||
obj = new AnimationClip(objectReader);
|
||||
obj = objectReader.serializedType?.m_Type != null && LoadingViaTypeTreeEnabled
|
||||
? new AnimationClip(objectReader, TypeTreeHelper.ReadType(objectReader.serializedType.m_Type, objectReader))
|
||||
: new AnimationClip(objectReader);
|
||||
break;
|
||||
case ClassIDType.Animator:
|
||||
obj = new Animator(objectReader);
|
||||
@@ -532,11 +584,14 @@ namespace AssetStudio
|
||||
case ClassIDType.PlayerSettings:
|
||||
obj = new PlayerSettings(objectReader);
|
||||
break;
|
||||
case ClassIDType.PreloadData:
|
||||
obj = new PreloadData(objectReader);
|
||||
break;
|
||||
case ClassIDType.RectTransform:
|
||||
obj = new RectTransform(objectReader);
|
||||
break;
|
||||
case ClassIDType.Shader:
|
||||
if (objectReader.version[0] < 2021)
|
||||
if (objectReader.version < 2021)
|
||||
obj = new Shader(objectReader);
|
||||
break;
|
||||
case ClassIDType.SkinnedMeshRenderer:
|
||||
@@ -552,7 +607,14 @@ namespace AssetStudio
|
||||
obj = new TextAsset(objectReader);
|
||||
break;
|
||||
case ClassIDType.Texture2D:
|
||||
obj = new Texture2D(objectReader);
|
||||
obj = objectReader.serializedType?.m_Type != null && LoadingViaTypeTreeEnabled
|
||||
? 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;
|
||||
case ClassIDType.Transform:
|
||||
obj = new Transform(objectReader);
|
||||
@@ -568,7 +630,9 @@ namespace AssetStudio
|
||||
break;
|
||||
}
|
||||
if (obj != null)
|
||||
{
|
||||
assetsFile.AddObject(obj);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -635,14 +699,17 @@ namespace AssetStudio
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
else
|
||||
else if (m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld))
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
|
||||
if (m_SpriteAtlaOld.m_IsVariant)
|
||||
{
|
||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warning($"\"{m_Sprite.m_Name}\": Sprite loading error. SpriteAtlas with PathID: \"{m_Sprite.m_SpriteAtlas.m_PathID}\" was not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,11 @@ namespace AssetStudio
|
||||
{
|
||||
public static class BigArrayPool<T>
|
||||
{
|
||||
private static readonly ArrayPool<T> s_shared = ArrayPool<T>.Create(64 * 1024 * 1024, 3);
|
||||
public static ArrayPool<T> Shared => s_shared;
|
||||
public static ArrayPool<T> Shared { get; }
|
||||
|
||||
static BigArrayPool()
|
||||
{
|
||||
Shared = ArrayPool<T>.Create(256 * 1024 * 1024, 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using K4os.Compression.LZ4;
|
||||
using ZstdSharp;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -35,7 +36,8 @@ namespace AssetStudio
|
||||
Lzma,
|
||||
Lz4,
|
||||
Lz4HC,
|
||||
Lzham
|
||||
Lzham,
|
||||
Custom,
|
||||
}
|
||||
|
||||
public class BundleFile
|
||||
@@ -45,7 +47,7 @@ namespace AssetStudio
|
||||
public string signature;
|
||||
public uint version;
|
||||
public string unityVersion;
|
||||
public string unityRevision;
|
||||
public UnityVersion unityRevision;
|
||||
public long size;
|
||||
public uint compressedBlocksInfoSize;
|
||||
public uint uncompressedBlocksInfoSize;
|
||||
@@ -73,13 +75,13 @@ namespace AssetStudio
|
||||
|
||||
public StreamFile[] fileList;
|
||||
|
||||
public BundleFile(FileReader reader, string specUnityVer = "")
|
||||
public BundleFile(FileReader reader, bool useZstd, UnityVersion specUnityVer = null)
|
||||
{
|
||||
m_Header = new Header();
|
||||
m_Header.signature = reader.ReadStringToNull();
|
||||
m_Header.version = reader.ReadUInt32();
|
||||
m_Header.unityVersion = reader.ReadStringToNull();
|
||||
m_Header.unityRevision = reader.ReadStringToNull();
|
||||
m_Header.unityRevision = new UnityVersion(reader.ReadStringToNull());
|
||||
switch (m_Header.signature)
|
||||
{
|
||||
case "UnityArchive":
|
||||
@@ -100,40 +102,54 @@ namespace AssetStudio
|
||||
case "UnityFS":
|
||||
ReadHeader(reader);
|
||||
|
||||
bool isUnityCnEnc = false;
|
||||
string unityVer = string.IsNullOrEmpty(specUnityVer) ? m_Header.unityRevision : specUnityVer;
|
||||
int[] ver = new string(unityVer.SkipWhile(x => !char.IsDigit(x)).TakeWhile(x => char.IsDigit(x) || x == '.').ToArray()).Split('.').Select(x => int.Parse(x)).ToArray();
|
||||
if (ver[0] != 0)
|
||||
var isUnityCnEnc = false;
|
||||
var unityVer = m_Header.unityRevision;
|
||||
if (specUnityVer != null)
|
||||
{
|
||||
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
|
||||
if (ver[0] < 2020 ||
|
||||
(ver[0] == 2020 && ver[1] <= 3 && ver[2] < 34) ||
|
||||
(ver[0] == 2021 && ver[1] <= 3 && ver[2] < 2) ||
|
||||
(ver[0] == 2022 && ver[1] <= 1 && ver[2] < 1))
|
||||
if (unityVer < 2020
|
||||
|| unityVer.IsInRange(2020, (2020, 3, 34))
|
||||
|| unityVer.IsInRange(2021, (2021, 3, 2))
|
||||
|| unityVer.IsInRange(2022, (2022, 1, 1)))
|
||||
{
|
||||
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.OldFlag) != 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0;
|
||||
isUnityCnEnc = ((CnEncryptionFlags)m_Header.flags & CnEncryptionFlags.NewFlag) != 0;
|
||||
}
|
||||
}
|
||||
if (isUnityCnEnc)
|
||||
{
|
||||
throw new NotSupportedException("Unsupported bundle file. UnityCN encryption was detected.");
|
||||
var msg = "Unsupported bundle file. ";
|
||||
msg += specUnityVer != null
|
||||
? "UnityCN encryption was detected or the specified Unity version is incorrect."
|
||||
: "UnityCN encryption was detected.";
|
||||
throw new NotSupportedException(msg);
|
||||
}
|
||||
|
||||
ReadBlocksInfoAndDirectory(reader, ver);
|
||||
ReadBlocksInfoAndDirectory(reader, unityVer);
|
||||
using (var blocksStream = CreateBlocksStream(reader.FullPath))
|
||||
{
|
||||
ReadBlocks(reader, blocksStream);
|
||||
ReadBlocks(reader, blocksStream, useZstd);
|
||||
ReadFiles(blocksStream, reader.FullPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadHeaderAndBlocksInfo(EndianBinaryReader reader)
|
||||
private void ReadHeaderAndBlocksInfo(FileReader reader)
|
||||
{
|
||||
if (m_Header.version >= 4)
|
||||
{
|
||||
@@ -185,7 +201,7 @@ namespace AssetStudio
|
||||
return blocksStream;
|
||||
}
|
||||
|
||||
private void ReadBlocksAndDirectory(EndianBinaryReader reader, Stream blocksStream)
|
||||
private void ReadBlocksAndDirectory(FileReader reader, Stream blocksStream)
|
||||
{
|
||||
var isCompressed = m_Header.signature == "UnityWeb";
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
@@ -246,7 +262,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadHeader(EndianBinaryReader reader)
|
||||
private void ReadHeader(FileReader reader)
|
||||
{
|
||||
m_Header.size = reader.ReadInt64();
|
||||
m_Header.compressedBlocksInfoSize = reader.ReadUInt32();
|
||||
@@ -258,7 +274,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(EndianBinaryReader reader, int[] unityVer)
|
||||
private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer)
|
||||
{
|
||||
byte[] blocksInfoBytes;
|
||||
|
||||
@@ -266,7 +282,7 @@ namespace AssetStudio
|
||||
{
|
||||
reader.AlignStream(16);
|
||||
}
|
||||
else if (unityVer[0] >= 2019 && unityVer[1] >= 4)
|
||||
else if (unityVer >= (2019, 4) && m_Header.flags != ArchiveFlags.BlocksAndDirectoryInfoCombined)
|
||||
{
|
||||
//check if we need to align the reader
|
||||
//- align to 16 bytes and check if all are 0
|
||||
@@ -290,42 +306,44 @@ namespace AssetStudio
|
||||
{
|
||||
blocksInfoBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize);
|
||||
}
|
||||
MemoryStream blocksInfoUncompresseddStream;
|
||||
MemoryStream blocksInfoUncompressedStream;
|
||||
var uncompressedSize = m_Header.uncompressedBlocksInfoSize;
|
||||
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
case CompressionType.None:
|
||||
{
|
||||
blocksInfoUncompresseddStream = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
{
|
||||
blocksInfoUncompressedStream = new MemoryStream(blocksInfoBytes);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
blocksInfoUncompressedStream = new MemoryStream((int) (uncompressedSize));
|
||||
using (var blocksInfoCompressedStream = new MemoryStream(blocksInfoBytes))
|
||||
{
|
||||
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;
|
||||
SevenZipHelper.StreamDecompress(blocksInfoCompressedStream, blocksInfoUncompressedStream,
|
||||
m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize);
|
||||
}
|
||||
blocksInfoUncompressedStream.Position = 0;
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
{
|
||||
var uncompressedBytes = new byte[uncompressedSize];
|
||||
var numWrite = LZ4Codec.Decode(blocksInfoBytes, uncompressedBytes);
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
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;
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksInfoUncompressedStream = new MemoryStream(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
throw new IOException($"Unsupported block info compression type {compressionType}");
|
||||
}
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompresseddStream))
|
||||
|
||||
using (var blocksInfoReader = new EndianBinaryReader(blocksInfoUncompressedStream))
|
||||
{
|
||||
var uncompressedDataHash = blocksInfoReader.ReadBytes(16);
|
||||
var blocksInfoCount = blocksInfoReader.ReadInt32();
|
||||
@@ -359,43 +377,72 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream)
|
||||
private void ReadBlocks(FileReader reader, Stream blocksStream, bool useZstd)
|
||||
{
|
||||
var zstdCodec = new Decompressor();
|
||||
var i = 0;
|
||||
foreach (var blockInfo in m_BlocksInfo)
|
||||
{
|
||||
var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask);
|
||||
switch (compressionType)
|
||||
{
|
||||
case CompressionType.None:
|
||||
{
|
||||
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
{
|
||||
reader.BaseStream.CopyTo(blocksStream, blockInfo.compressedSize);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lzma:
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
{
|
||||
SevenZipHelper.StreamDecompress(reader.BaseStream, blocksStream, blockInfo.compressedSize, blockInfo.uncompressedSize);
|
||||
break;
|
||||
}
|
||||
case CompressionType.Lz4:
|
||||
case CompressionType.Lz4HC:
|
||||
case CompressionType.Custom:
|
||||
{
|
||||
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 compressedSize = (int)blockInfo.compressedSize;
|
||||
var compressedBytes = BigArrayPool<byte>.Shared.Rent(compressedSize);
|
||||
reader.Read(compressedBytes, 0, compressedSize);
|
||||
var uncompressedSize = (int)blockInfo.uncompressedSize;
|
||||
var uncompressedBytes = BigArrayPool<byte>.Shared.Rent(uncompressedSize);
|
||||
var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
var compTypeStr = compressionType.ToString();
|
||||
if (compressionType == CompressionType.Custom)
|
||||
{
|
||||
compTypeStr = useZstd ? "Zstd" : "Lz4";
|
||||
if (i == 0)
|
||||
{
|
||||
Logger.Debug($"Custom block compression type was detected. Trying to decompress as {compTypeStr} archive..");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int numWrite;
|
||||
if (compressionType == CompressionType.Custom && useZstd)
|
||||
{
|
||||
numWrite = zstdCodec.Unwrap(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedSize, uncompressedBytes, 0, uncompressedSize);
|
||||
}
|
||||
|
||||
if (numWrite != uncompressedSize)
|
||||
{
|
||||
throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
throw new IOException($"{compTypeStr} block decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes");
|
||||
}
|
||||
blocksStream.Write(uncompressedBytes, 0, uncompressedSize);
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes);
|
||||
break;
|
||||
}
|
||||
finally
|
||||
{
|
||||
BigArrayPool<byte>.Shared.Return(compressedBytes, clearArray: true);
|
||||
BigArrayPool<byte>.Shared.Return(uncompressedBytes, clearArray: true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new IOException($"Unsupported compression type {compressionType}");
|
||||
throw new IOException($"Unsupported block compression type {compressionType}");
|
||||
}
|
||||
}
|
||||
blocksStream.Position = 0;
|
||||
|
||||
@@ -145,6 +145,7 @@ namespace AssetStudio
|
||||
ProceduralMaterial = 185,
|
||||
ProceduralTexture = 186,
|
||||
Texture2DArray = 187,
|
||||
Texture2DArrayImage = -187, //fake type
|
||||
CubemapArray = 188,
|
||||
OffMeshLink = 191,
|
||||
OcclusionArea = 192,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -15,6 +17,7 @@ namespace AssetStudio
|
||||
public T inWeight;
|
||||
public T outWeight;
|
||||
|
||||
public Keyframe() { }
|
||||
|
||||
public Keyframe(ObjectReader reader, Func<T> readerFunc)
|
||||
{
|
||||
@@ -22,7 +25,7 @@ namespace AssetStudio
|
||||
value = readerFunc();
|
||||
inSlope = readerFunc();
|
||||
outSlope = readerFunc();
|
||||
if (reader.version[0] >= 2018) //2018 and up
|
||||
if (reader.version >= 2018) //2018 and up
|
||||
{
|
||||
weightedMode = reader.ReadInt32();
|
||||
inWeight = readerFunc();
|
||||
@@ -38,6 +41,8 @@ namespace AssetStudio
|
||||
public int m_PostInfinity;
|
||||
public int m_RotationOrder;
|
||||
|
||||
public AnimationCurve() { }
|
||||
|
||||
public AnimationCurve(ObjectReader reader, Func<T> readerFunc)
|
||||
{
|
||||
var version = reader.version;
|
||||
@@ -50,7 +55,7 @@ namespace AssetStudio
|
||||
|
||||
m_PreInfinity = reader.ReadInt32();
|
||||
m_PostInfinity = reader.ReadInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
if (version >= (5, 3)) //5.3 and up
|
||||
{
|
||||
m_RotationOrder = reader.ReadInt32();
|
||||
}
|
||||
@@ -62,6 +67,8 @@ namespace AssetStudio
|
||||
public AnimationCurve<Quaternion> curve;
|
||||
public string path;
|
||||
|
||||
public QuaternionCurve() { }
|
||||
|
||||
public QuaternionCurve(ObjectReader reader)
|
||||
{
|
||||
curve = new AnimationCurve<Quaternion>(reader, reader.ReadQuaternion);
|
||||
@@ -77,6 +84,8 @@ namespace AssetStudio
|
||||
public byte[] m_Data;
|
||||
public byte m_BitSize;
|
||||
|
||||
public PackedFloatVector() { }
|
||||
|
||||
public PackedFloatVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
@@ -136,6 +145,8 @@ namespace AssetStudio
|
||||
public byte[] m_Data;
|
||||
public byte m_BitSize;
|
||||
|
||||
public PackedIntVector() { }
|
||||
|
||||
public PackedIntVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
@@ -180,6 +191,8 @@ namespace AssetStudio
|
||||
public uint m_NumItems;
|
||||
public byte[] m_Data;
|
||||
|
||||
public PackedQuatVector() { }
|
||||
|
||||
public PackedQuatVector(ObjectReader reader)
|
||||
{
|
||||
m_NumItems = reader.ReadUInt32();
|
||||
@@ -264,6 +277,8 @@ namespace AssetStudio
|
||||
public int m_PreInfinity;
|
||||
public int m_PostInfinity;
|
||||
|
||||
public CompressedAnimationCurve() { }
|
||||
|
||||
public CompressedAnimationCurve(ObjectReader reader)
|
||||
{
|
||||
m_Path = reader.ReadAlignedString();
|
||||
@@ -280,6 +295,8 @@ namespace AssetStudio
|
||||
public AnimationCurve<Vector3> curve;
|
||||
public string path;
|
||||
|
||||
public Vector3Curve() { }
|
||||
|
||||
public Vector3Curve(ObjectReader reader)
|
||||
{
|
||||
curve = new AnimationCurve<Vector3>(reader, reader.ReadVector3);
|
||||
@@ -294,15 +311,22 @@ namespace AssetStudio
|
||||
public string path;
|
||||
public ClassIDType classID;
|
||||
public PPtr<MonoScript> script;
|
||||
public int flags;
|
||||
|
||||
public FloatCurve() { }
|
||||
|
||||
public FloatCurve(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
curve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
||||
attribute = reader.ReadAlignedString();
|
||||
path = reader.ReadAlignedString();
|
||||
classID = (ClassIDType)reader.ReadInt32();
|
||||
script = new PPtr<MonoScript>(reader);
|
||||
if (version >= (2022, 2)) //2022.2 and up
|
||||
{
|
||||
flags = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,6 +335,7 @@ namespace AssetStudio
|
||||
public float time;
|
||||
public PPtr<Object> value;
|
||||
|
||||
public PPtrKeyframe() { }
|
||||
|
||||
public PPtrKeyframe(ObjectReader reader)
|
||||
{
|
||||
@@ -326,10 +351,13 @@ namespace AssetStudio
|
||||
public string path;
|
||||
public int classID;
|
||||
public PPtr<MonoScript> script;
|
||||
public int flags;
|
||||
|
||||
public PPtrCurve() { }
|
||||
|
||||
public PPtrCurve(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
int numCurves = reader.ReadInt32();
|
||||
curve = new PPtrKeyframe[numCurves];
|
||||
for (int i = 0; i < numCurves; i++)
|
||||
@@ -341,6 +369,10 @@ namespace AssetStudio
|
||||
path = reader.ReadAlignedString();
|
||||
classID = reader.ReadInt32();
|
||||
script = new PPtr<MonoScript>(reader);
|
||||
if (version >= (2022, 2)) //2022.2 and up
|
||||
{
|
||||
flags = reader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -349,6 +381,8 @@ namespace AssetStudio
|
||||
public Vector3 m_Center;
|
||||
public Vector3 m_Extent;
|
||||
|
||||
public AABB() { }
|
||||
|
||||
public AABB(ObjectReader reader)
|
||||
{
|
||||
m_Center = reader.ReadVector3();
|
||||
@@ -362,12 +396,14 @@ namespace AssetStudio
|
||||
public Quaternion q;
|
||||
public Vector3 s;
|
||||
|
||||
public xform() { }
|
||||
|
||||
public xform(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
t = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
t = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
q = reader.ReadQuaternion();
|
||||
s = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
s = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,6 +416,8 @@ namespace AssetStudio
|
||||
public float m_InOut;
|
||||
public float m_Grab;
|
||||
|
||||
public HandPose() { }
|
||||
|
||||
public HandPose(ObjectReader reader)
|
||||
{
|
||||
m_GrabX = new xform(reader);
|
||||
@@ -399,15 +437,17 @@ namespace AssetStudio
|
||||
public Vector3 m_HintT;
|
||||
public float m_HintWeightT;
|
||||
|
||||
public HumanGoal() { }
|
||||
|
||||
public HumanGoal(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_X = new xform(reader);
|
||||
m_WeightT = reader.ReadSingle();
|
||||
m_WeightR = reader.ReadSingle();
|
||||
if (version[0] >= 5)//5.0 and up
|
||||
if (version >= 5)//5.0 and up
|
||||
{
|
||||
m_HintT = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_HintT = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_HintWeightT = reader.ReadSingle();
|
||||
}
|
||||
}
|
||||
@@ -424,11 +464,13 @@ namespace AssetStudio
|
||||
public float[] m_DoFArray;
|
||||
public Vector3[] m_TDoFArray;
|
||||
|
||||
public HumanPose() { }
|
||||
|
||||
public HumanPose(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_RootX = new xform(reader);
|
||||
m_LookAtPosition = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_LookAtPosition = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_LookAtWeight = reader.ReadVector4();
|
||||
|
||||
int numGoals = reader.ReadInt32();
|
||||
@@ -443,13 +485,13 @@ namespace AssetStudio
|
||||
|
||||
m_DoFArray = reader.ReadSingleArray();
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2))//5.2 and up
|
||||
if (version >= (5, 2))//5.2 and up
|
||||
{
|
||||
int numTDof = reader.ReadInt32();
|
||||
m_TDoFArray = new Vector3[numTDof];
|
||||
for (int i = 0; i < numTDof; i++)
|
||||
{
|
||||
m_TDoFArray[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_TDoFArray[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -460,6 +502,8 @@ namespace AssetStudio
|
||||
public uint[] data;
|
||||
public uint curveCount;
|
||||
|
||||
public StreamedClip() { }
|
||||
|
||||
public StreamedClip(ObjectReader reader)
|
||||
{
|
||||
data = reader.ReadUInt32Array();
|
||||
@@ -475,6 +519,8 @@ namespace AssetStudio
|
||||
public float outSlope;
|
||||
public float inSlope;
|
||||
|
||||
public StreamedCurveKey() { }
|
||||
|
||||
public StreamedCurveKey(BinaryReader reader)
|
||||
{
|
||||
index = reader.ReadInt32();
|
||||
@@ -506,6 +552,8 @@ namespace AssetStudio
|
||||
public float time;
|
||||
public StreamedCurveKey[] keyList;
|
||||
|
||||
public StreamedFrame() { }
|
||||
|
||||
public StreamedFrame(BinaryReader reader)
|
||||
{
|
||||
time = reader.ReadSingle();
|
||||
@@ -561,6 +609,8 @@ namespace AssetStudio
|
||||
public float m_BeginTime;
|
||||
public float[] m_SampleArray;
|
||||
|
||||
public DenseClip() { }
|
||||
|
||||
public DenseClip(ObjectReader reader)
|
||||
{
|
||||
m_FrameCount = reader.ReadInt32();
|
||||
@@ -575,6 +625,8 @@ namespace AssetStudio
|
||||
{
|
||||
public float[] data;
|
||||
|
||||
public ConstantClip() { }
|
||||
|
||||
public ConstantClip(ObjectReader reader)
|
||||
{
|
||||
data = reader.ReadSingleArray();
|
||||
@@ -588,11 +640,13 @@ namespace AssetStudio
|
||||
public uint m_Type;
|
||||
public uint m_Index;
|
||||
|
||||
public ValueConstant() { }
|
||||
|
||||
public ValueConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_ID = reader.ReadUInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 5))//5.5 down
|
||||
if (version < (5, 5)) //5.5 down
|
||||
{
|
||||
m_TypeID = reader.ReadUInt32();
|
||||
}
|
||||
@@ -605,6 +659,8 @@ namespace AssetStudio
|
||||
{
|
||||
public ValueConstant[] m_ValueArray;
|
||||
|
||||
public ValueArrayConstant() { }
|
||||
|
||||
public ValueArrayConstant(ObjectReader reader)
|
||||
{
|
||||
int numVals = reader.ReadInt32();
|
||||
@@ -616,6 +672,18 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public class OffsetPtr
|
||||
{
|
||||
public Clip data;
|
||||
|
||||
public OffsetPtr() { }
|
||||
|
||||
public OffsetPtr(ObjectReader reader)
|
||||
{
|
||||
data = new Clip(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public class Clip
|
||||
{
|
||||
public StreamedClip m_StreamedClip;
|
||||
@@ -623,16 +691,18 @@ namespace AssetStudio
|
||||
public ConstantClip m_ConstantClip;
|
||||
public ValueArrayConstant m_Binding;
|
||||
|
||||
public Clip() { }
|
||||
|
||||
public Clip(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_StreamedClip = new StreamedClip(reader);
|
||||
m_DenseClip = new DenseClip(reader);
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_ConstantClip = new ConstantClip(reader);
|
||||
}
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 3)) //2018.3 down
|
||||
if (version < (2018, 3)) //2018.3 down
|
||||
{
|
||||
m_Binding = new ValueArrayConstant(reader);
|
||||
}
|
||||
@@ -688,6 +758,8 @@ namespace AssetStudio
|
||||
public float m_Start;
|
||||
public float m_Stop;
|
||||
|
||||
public ValueDelta() { }
|
||||
|
||||
public ValueDelta(ObjectReader reader)
|
||||
{
|
||||
m_Start = reader.ReadSingle();
|
||||
@@ -705,7 +777,7 @@ namespace AssetStudio
|
||||
public xform m_MotionStartX;
|
||||
public xform m_MotionStopX;
|
||||
public Vector3 m_AverageSpeed;
|
||||
public Clip m_Clip;
|
||||
public OffsetPtr m_Clip;
|
||||
public float m_StartTime;
|
||||
public float m_StopTime;
|
||||
public float m_OrientationOffsetY;
|
||||
@@ -727,24 +799,26 @@ namespace AssetStudio
|
||||
public bool m_KeepOriginalPositionXZ;
|
||||
public bool m_HeightFromFeet;
|
||||
|
||||
public ClipMuscleConstant() { }
|
||||
|
||||
public ClipMuscleConstant(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
m_DeltaPose = new HumanPose(reader);
|
||||
m_StartX = new xform(reader);
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
|
||||
if (version >= (5, 5)) //5.5 and up
|
||||
{
|
||||
m_StopX = new xform(reader);
|
||||
}
|
||||
m_LeftFootStartX = new xform(reader);
|
||||
m_RightFootStartX = new xform(reader);
|
||||
if (version[0] < 5)//5.0 down
|
||||
if (version < 5)//5.0 down
|
||||
{
|
||||
m_MotionStartX = new xform(reader);
|
||||
m_MotionStopX = new xform(reader);
|
||||
}
|
||||
m_AverageSpeed = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_Clip = new Clip(reader);
|
||||
m_AverageSpeed = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4();//5.4 and up
|
||||
m_Clip = new OffsetPtr(reader);
|
||||
m_StartTime = reader.ReadSingle();
|
||||
m_StopTime = reader.ReadSingle();
|
||||
m_OrientationOffsetY = reader.ReadSingle();
|
||||
@@ -753,7 +827,7 @@ namespace AssetStudio
|
||||
m_AverageAngularSpeed = reader.ReadSingle();
|
||||
|
||||
m_IndexArray = reader.ReadInt32Array();
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
|
||||
if (version < (4, 3)) //4.3 down
|
||||
{
|
||||
var m_AdditionalCurveIndexArray = reader.ReadInt32Array();
|
||||
}
|
||||
@@ -763,13 +837,13 @@ namespace AssetStudio
|
||||
{
|
||||
m_ValueArrayDelta[i] = new ValueDelta(reader);
|
||||
}
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
if (version >= (5, 3))//5.3 and up
|
||||
{
|
||||
m_ValueArrayReferencePose = reader.ReadSingleArray();
|
||||
}
|
||||
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_LoopTime = reader.ReadBoolean();
|
||||
}
|
||||
@@ -777,7 +851,7 @@ namespace AssetStudio
|
||||
m_LoopBlendOrientation = reader.ReadBoolean();
|
||||
m_LoopBlendPositionY = reader.ReadBoolean();
|
||||
m_LoopBlendPositionXZ = reader.ReadBoolean();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5))//5.5 and up
|
||||
if (version >= (5, 5))//5.5 and up
|
||||
{
|
||||
m_StartAtOrigin = reader.ReadBoolean();
|
||||
}
|
||||
@@ -807,7 +881,7 @@ namespace AssetStudio
|
||||
path = reader.ReadUInt32();
|
||||
attribute = reader.ReadUInt32();
|
||||
script = new PPtr<Object>(reader);
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
typeID = (ClassIDType)reader.ReadInt32();
|
||||
}
|
||||
@@ -817,7 +891,7 @@ namespace AssetStudio
|
||||
}
|
||||
customType = reader.ReadByte();
|
||||
isPPtrCurve = reader.ReadByte();
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
if (version >= (2022, 1)) //2022.1 and up
|
||||
{
|
||||
isIntCurve = reader.ReadByte();
|
||||
}
|
||||
@@ -895,6 +969,8 @@ namespace AssetStudio
|
||||
public int intParameter;
|
||||
public int messageOptions;
|
||||
|
||||
public AnimationEvent() { }
|
||||
|
||||
public AnimationEvent(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
@@ -904,7 +980,7 @@ namespace AssetStudio
|
||||
data = reader.ReadAlignedString();
|
||||
objectReferenceParameter = new PPtr<Object>(reader);
|
||||
floatParameter = reader.ReadSingle();
|
||||
if (version[0] >= 3) //3 and up
|
||||
if (version >= 3) //3 and up
|
||||
{
|
||||
intParameter = reader.ReadInt32();
|
||||
}
|
||||
@@ -940,14 +1016,40 @@ namespace AssetStudio
|
||||
public AnimationClipBindingConstant m_ClipBindingConstant;
|
||||
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)
|
||||
{
|
||||
if (version[0] >= 5)//5.0 and up
|
||||
if (version >= 5)//5.0 and up
|
||||
{
|
||||
m_Legacy = reader.ReadBoolean();
|
||||
}
|
||||
else if (version[0] >= 4)//4.0 and up
|
||||
else if (version >= 4)//4.0 and up
|
||||
{
|
||||
m_AnimationType = (AnimationType)reader.ReadInt32();
|
||||
if (m_AnimationType == AnimationType.Legacy)
|
||||
@@ -958,7 +1060,7 @@ namespace AssetStudio
|
||||
m_Legacy = true;
|
||||
}
|
||||
m_Compressed = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3))//4.3 and up
|
||||
if (version >= (4, 3))//4.3 and up
|
||||
{
|
||||
m_UseHighQualityCurve = reader.ReadBoolean();
|
||||
}
|
||||
@@ -977,7 +1079,7 @@ namespace AssetStudio
|
||||
m_CompressedRotationCurves[i] = new CompressedAnimationCurve(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3))//5.3 and up
|
||||
if (version >= (5, 3))//5.3 and up
|
||||
{
|
||||
int numEulerCurves = reader.ReadInt32();
|
||||
m_EulerCurves = new Vector3Curve[numEulerCurves];
|
||||
@@ -1008,7 +1110,7 @@ namespace AssetStudio
|
||||
m_FloatCurves[i] = new FloatCurve(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
int numPtrCurves = reader.ReadInt32();
|
||||
m_PPtrCurves = new PPtrCurve[numPtrCurves];
|
||||
@@ -1020,20 +1122,20 @@ namespace AssetStudio
|
||||
|
||||
m_SampleRate = reader.ReadSingle();
|
||||
m_WrapMode = reader.ReadInt32();
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
|
||||
if (version >= (3, 4)) //3.4 and up
|
||||
{
|
||||
m_Bounds = new AABB(reader);
|
||||
}
|
||||
if (version[0] >= 4)//4.0 and up
|
||||
if (version >= 4)//4.0 and up
|
||||
{
|
||||
m_MuscleClipSize = reader.ReadUInt32();
|
||||
m_MuscleClip = new ClipMuscleConstant(reader);
|
||||
}
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_ClipBindingConstant = new AnimationClipBindingConstant(reader);
|
||||
}
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
|
||||
if (version >= (2018, 3)) //2018.3 and up
|
||||
{
|
||||
var m_HasGenericRootTransform = reader.ReadBoolean();
|
||||
var m_HasMotionFloatCurves = reader.ReadBoolean();
|
||||
@@ -1045,7 +1147,7 @@ namespace AssetStudio
|
||||
{
|
||||
m_Events[i] = new AnimationEvent(reader);
|
||||
}
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
@@ -17,47 +17,47 @@ namespace AssetStudio
|
||||
m_Controller = new PPtr<RuntimeAnimatorController>(reader);
|
||||
var m_CullingMode = reader.ReadInt32();
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
if (version >= (4, 5)) //4.5 and up
|
||||
{
|
||||
var m_UpdateMode = reader.ReadInt32();
|
||||
}
|
||||
|
||||
var m_ApplyRootMotion = reader.ReadBoolean();
|
||||
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
|
||||
if (version == 4 && version.Minor >= 5) //4.5 and up - 5.0 down
|
||||
{
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
var m_LinearVelocityBlending = reader.ReadBoolean();
|
||||
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
|
||||
if (version >= (2021, 2)) //2021.2 and up
|
||||
{
|
||||
var m_StabilizeFeet = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
|
||||
if (version < (4, 5)) //4.5 down
|
||||
{
|
||||
var m_AnimatePhysics = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_HasTransformHierarchy = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
if (version >= (4, 5)) //4.5 and up
|
||||
{
|
||||
var m_AllowConstantClipSamplingOptimization = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 5 && version[0] < 2018) //5.0 and up - 2018 down
|
||||
if (version.IsInRange(5, 2018)) //5.0 and up - 2018 down
|
||||
{
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
if (version >= 2018) //2018 and up
|
||||
{
|
||||
var m_KeepAnimatorControllerStateOnDisable = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace AssetStudio
|
||||
|
||||
word0 = reader.ReadUInt32();
|
||||
word1 = reader.ReadUInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||
if (version >= (5, 2)) //5.2 and up
|
||||
{
|
||||
word2 = reader.ReadUInt32();
|
||||
}
|
||||
@@ -73,12 +73,12 @@ namespace AssetStudio
|
||||
m_SkeletonMask = new SkeletonMask(reader);
|
||||
m_Binding = reader.ReadUInt32();
|
||||
m_LayerBlendingMode = reader.ReadInt32();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
|
||||
if (version >= (4, 2)) //4.2 and up
|
||||
{
|
||||
m_DefaultWeight = reader.ReadSingle();
|
||||
}
|
||||
m_IKPass = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 2)) //4.2 and up
|
||||
if (version >= (4, 2)) //4.2 and up
|
||||
{
|
||||
m_SyncedLayerAffectsTiming = reader.ReadBoolean();
|
||||
}
|
||||
@@ -131,7 +131,7 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
m_DestinationState = reader.ReadUInt32();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_FullPathID = reader.ReadUInt32();
|
||||
}
|
||||
@@ -140,7 +140,7 @@ namespace AssetStudio
|
||||
m_UserID = reader.ReadUInt32();
|
||||
m_TransitionDuration = reader.ReadSingle();
|
||||
m_TransitionOffset = reader.ReadSingle();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_ExitTime = reader.ReadSingle();
|
||||
m_HasExitTime = reader.ReadBoolean();
|
||||
@@ -154,7 +154,7 @@ namespace AssetStudio
|
||||
m_Atomic = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
if (version >= (4, 5)) //4.5 and up
|
||||
{
|
||||
m_CanTransitionToSelf = reader.ReadBoolean();
|
||||
}
|
||||
@@ -252,43 +252,41 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_BlendType = reader.ReadUInt32();
|
||||
}
|
||||
m_BlendEventID = reader.ReadUInt32();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_BlendEventYID = reader.ReadUInt32();
|
||||
}
|
||||
m_ChildIndices = reader.ReadUInt32Array();
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 1)) //4.1 down
|
||||
if (version < (4, 1)) //4.1 down
|
||||
{
|
||||
m_ChildThresholdArray = reader.ReadSingleArray();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_Blend1dData = new Blend1dDataConstant(reader);
|
||||
m_Blend2dData = new Blend2dDataConstant(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_BlendDirectData = new BlendDirectDataConstant(reader);
|
||||
}
|
||||
|
||||
m_ClipID = reader.ReadUInt32();
|
||||
if (version[0] == 4 && version[1] >= 5) //4.5 - 5.0
|
||||
if (version == 4 && version.Minor >= 5) //4.5 - 5.0
|
||||
{
|
||||
m_ClipIndex = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_Duration = reader.ReadSingle();
|
||||
|
||||
if (version[0] > 4
|
||||
|| (version[0] == 4 && version[1] > 1)
|
||||
|| (version[0] == 4 && version[1] == 1 && version[2] >= 3)) //4.1.3 and up
|
||||
if (version >= (4, 1, 3)) //4.1.3 and up
|
||||
{
|
||||
m_CycleOffset = reader.ReadSingle();
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
@@ -313,7 +311,7 @@ namespace AssetStudio
|
||||
m_NodeArray[i] = new BlendTreeNodeConstant(reader);
|
||||
}
|
||||
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 5)) //4.5 down
|
||||
if (version < (4, 5)) //4.5 down
|
||||
{
|
||||
m_BlendEventArrayConstant = new ValueArrayConstant(reader);
|
||||
}
|
||||
@@ -354,7 +352,7 @@ namespace AssetStudio
|
||||
|
||||
m_BlendTreeConstantIndexArray = reader.ReadInt32Array();
|
||||
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
||||
if (version < (5, 2)) //5.2 down
|
||||
{
|
||||
int numInfos = reader.ReadInt32();
|
||||
m_LeafInfoArray = new LeafInfoConstant[numInfos];
|
||||
@@ -372,41 +370,41 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
m_NameID = reader.ReadUInt32();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_PathID = reader.ReadUInt32();
|
||||
}
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_FullPathID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_TagID = reader.ReadUInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
|
||||
if (version >= (5, 1)) //5.1 and up
|
||||
{
|
||||
m_SpeedParamID = reader.ReadUInt32();
|
||||
m_MirrorParamID = reader.ReadUInt32();
|
||||
m_CycleOffsetParamID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
var m_TimeParamID = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_Speed = reader.ReadSingle();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_CycleOffset = reader.ReadSingle();
|
||||
}
|
||||
m_IKOnFeet = reader.ReadBoolean();
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_WriteDefaultValues = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
m_Loop = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_Mirror = reader.ReadBoolean();
|
||||
}
|
||||
@@ -480,7 +478,7 @@ namespace AssetStudio
|
||||
m_AnyStateTransitionConstantArray[i] = new TransitionConstant(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
int numSelectors = reader.ReadInt32();
|
||||
m_SelectorStateConstantArray = new SelectorStateConstant[numSelectors];
|
||||
@@ -509,7 +507,7 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 5)) //5.5 down
|
||||
if (version < (5, 5)) //5.5 down
|
||||
{
|
||||
m_BoolValues = reader.ReadBooleanArray();
|
||||
reader.AlignStream();
|
||||
@@ -517,7 +515,7 @@ namespace AssetStudio
|
||||
m_FloatValues = reader.ReadSingleArray();
|
||||
}
|
||||
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] < 3)) //4.3 down
|
||||
if (version < (4, 3)) //4.3 down
|
||||
{
|
||||
m_VectorValues = reader.ReadVector4Array();
|
||||
}
|
||||
@@ -527,7 +525,7 @@ namespace AssetStudio
|
||||
m_PositionValues = new Vector3[numPosValues];
|
||||
for (int i = 0; i < numPosValues; i++)
|
||||
{
|
||||
m_PositionValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||
m_PositionValues[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||
}
|
||||
|
||||
m_QuaternionValues = reader.ReadVector4Array();
|
||||
@@ -536,10 +534,10 @@ namespace AssetStudio
|
||||
m_ScaleValues = new Vector3[numScaleValues];
|
||||
for (int i = 0; i < numScaleValues; i++)
|
||||
{
|
||||
m_ScaleValues[i] = version[0] > 5 || (version[0] == 5 && version[1] >= 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||
m_ScaleValues[i] = version >= (5, 4) ? reader.ReadVector3() : (Vector3)reader.ReadVector4(); //5.4 and up
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||
if (version >= (5, 5)) //5.5 and up
|
||||
{
|
||||
m_FloatValues = reader.ReadSingleArray();
|
||||
m_IntValues = reader.ReadInt32Array();
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@@ -23,22 +20,57 @@ namespace AssetStudio
|
||||
{
|
||||
public PPtr<Object>[] m_PreloadTable;
|
||||
public KeyValuePair<string, AssetInfo>[] m_Container;
|
||||
public string m_AssetBundleName;
|
||||
public string[] m_Dependencies;
|
||||
public bool m_IsStreamedSceneAssetBundle;
|
||||
|
||||
public AssetBundle(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_PreloadTableSize = reader.ReadInt32();
|
||||
m_PreloadTable = new PPtr<Object>[m_PreloadTableSize];
|
||||
for (int i = 0; i < m_PreloadTableSize; i++)
|
||||
for (var i = 0; i < m_PreloadTableSize; i++)
|
||||
{
|
||||
m_PreloadTable[i] = new PPtr<Object>(reader);
|
||||
}
|
||||
|
||||
var m_ContainerSize = reader.ReadInt32();
|
||||
m_Container = new KeyValuePair<string, AssetInfo>[m_ContainerSize];
|
||||
for (int i = 0; i < m_ContainerSize; i++)
|
||||
for (var i = 0; i < m_ContainerSize; i++)
|
||||
{
|
||||
m_Container[i] = new KeyValuePair<string, AssetInfo>(reader.ReadAlignedString(), new AssetInfo(reader));
|
||||
}
|
||||
|
||||
var m_MainAsset = new AssetInfo(reader);
|
||||
|
||||
if (version == (5, 4)) //5.4.x
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
m_AssetBundleName = reader.ReadAlignedString();
|
||||
|
||||
var m_DependenciesSize = reader.ReadInt32();
|
||||
m_Dependencies = new string[m_DependenciesSize];
|
||||
|
||||
for (var i = 0; i < m_DependenciesSize; i++)
|
||||
{
|
||||
m_Dependencies[i] = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
m_IsStreamedSceneAssetBundle = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace AssetStudio
|
||||
|
||||
public AudioClip(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] < 5)
|
||||
if (version < 5)
|
||||
{
|
||||
m_Format = reader.ReadInt32();
|
||||
m_Type = (FMODSoundType)reader.ReadInt32();
|
||||
@@ -41,7 +41,7 @@ namespace AssetStudio
|
||||
m_UseHardware = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
|
||||
if (version[0] >= 4 || (version[0] == 3 && version[1] >= 2)) //3.2.0 to 5
|
||||
if (version >= (3, 2)) //3.2.0 to 5
|
||||
{
|
||||
int m_Stream = reader.ReadInt32();
|
||||
m_Size = reader.ReadInt32();
|
||||
@@ -95,7 +95,7 @@ namespace AssetStudio
|
||||
public enum FMODSoundType
|
||||
{
|
||||
UNKNOWN = 0,
|
||||
ACC = 1,
|
||||
AAC = 1,
|
||||
AIFF = 2,
|
||||
ASF = 3,
|
||||
AT3 = 4,
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace AssetStudio
|
||||
public Limit(ObjectReader reader)
|
||||
{
|
||||
var version = reader.version;
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4))//5.4 and up
|
||||
if (version >= (5, 4))//5.4 and up
|
||||
{
|
||||
m_Min = reader.ReadVector3();
|
||||
m_Max = reader.ReadVector3();
|
||||
@@ -50,7 +50,7 @@ namespace AssetStudio
|
||||
var version = reader.version;
|
||||
m_PreQ = reader.ReadVector4();
|
||||
m_PostQ = reader.ReadVector4();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||
if (version >= (5, 4)) //5.4 and up
|
||||
{
|
||||
m_Sgn = reader.ReadVector3();
|
||||
}
|
||||
@@ -189,7 +189,7 @@ namespace AssetStudio
|
||||
m_LeftHand = new Hand(reader);
|
||||
m_RightHand = new Hand(reader);
|
||||
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
if (version < (2018, 2)) //2018.2 down
|
||||
{
|
||||
int numHandles = reader.ReadInt32();
|
||||
m_Handles = new Handle[numHandles];
|
||||
@@ -210,7 +210,7 @@ namespace AssetStudio
|
||||
|
||||
m_HumanBoneMass = reader.ReadSingleArray();
|
||||
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
if (version < (2018, 2)) //2018.2 down
|
||||
{
|
||||
m_ColliderIndex = reader.ReadInt32Array();
|
||||
}
|
||||
@@ -225,7 +225,7 @@ namespace AssetStudio
|
||||
m_FeetSpacing = reader.ReadSingle();
|
||||
m_HasLeftHand = reader.ReadBoolean();
|
||||
m_HasRightHand = reader.ReadBoolean();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||
if (version >= (5, 2)) //5.2 and up
|
||||
{
|
||||
m_HasTDoF = reader.ReadBoolean();
|
||||
}
|
||||
@@ -254,7 +254,7 @@ namespace AssetStudio
|
||||
m_AvatarSkeleton = new Skeleton(reader);
|
||||
m_AvatarSkeletonPose = new SkeletonPose(reader);
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_DefaultPose = new SkeletonPose(reader);
|
||||
|
||||
@@ -265,7 +265,7 @@ namespace AssetStudio
|
||||
|
||||
m_HumanSkeletonIndexArray = reader.ReadInt32Array();
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_HumanSkeletonReverseIndexArray = reader.ReadInt32Array();
|
||||
}
|
||||
@@ -273,7 +273,7 @@ namespace AssetStudio
|
||||
m_RootMotionBoneIndex = reader.ReadInt32();
|
||||
m_RootMotionBoneX = new xform(reader);
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_RootMotionSkeleton = new Skeleton(reader);
|
||||
m_RootMotionSkeletonPose = new SkeletonPose(reader);
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace AssetStudio
|
||||
{
|
||||
public abstract class EditorExtension : Object
|
||||
{
|
||||
protected EditorExtension() { }
|
||||
|
||||
protected EditorExtension(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (platform == BuildTarget.NoTarget)
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace AssetStudio
|
||||
|
||||
public Font(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if ((version[0] == 5 && version[1] >= 5) || version[0] > 5)//5.5 and up
|
||||
if (version >= (5, 5))//5.5 and up
|
||||
{
|
||||
var m_LineSpacing = reader.ReadSingle();
|
||||
var m_DefaultMaterial = new PPtr<Material>(reader);
|
||||
@@ -43,7 +43,7 @@ namespace AssetStudio
|
||||
{
|
||||
int m_AsciiStartOffset = reader.ReadInt32();
|
||||
|
||||
if (version[0] <= 3)
|
||||
if (version <= 3)
|
||||
{
|
||||
int m_FontCountX = reader.ReadInt32();
|
||||
int m_FontCountY = reader.ReadInt32();
|
||||
@@ -52,7 +52,7 @@ namespace AssetStudio
|
||||
float m_Kerning = reader.ReadSingle();
|
||||
float m_LineSpacing = reader.ReadSingle();
|
||||
|
||||
if (version[0] <= 3)
|
||||
if (version <= 3)
|
||||
{
|
||||
int m_PerCharacterKerning_size = reader.ReadInt32();
|
||||
for (int i = 0; i < m_PerCharacterKerning_size; i++)
|
||||
@@ -86,7 +86,7 @@ namespace AssetStudio
|
||||
float vertheight = reader.ReadSingle();
|
||||
float width = reader.ReadSingle();
|
||||
|
||||
if (version[0] >= 4)
|
||||
if (version >= 4)
|
||||
{
|
||||
var flipped = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
@@ -103,7 +103,7 @@ namespace AssetStudio
|
||||
float second = reader.ReadSingle();
|
||||
}
|
||||
|
||||
if (version[0] <= 3)
|
||||
if (version <= 3)
|
||||
{
|
||||
var m_GridFont = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
|
||||
31
AssetStudio/Classes/GLTextureSettings.cs
Normal file
31
AssetStudio/Classes/GLTextureSettings.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace AssetStudio
|
||||
m_Components = new PPtr<Component>[m_Component_size];
|
||||
for (int i = 0; i < m_Component_size; i++)
|
||||
{
|
||||
if ((version[0] == 5 && version[1] < 5) || version[0] < 5) //5.5 down
|
||||
if (version < (5, 5)) //5.5 down
|
||||
{
|
||||
int first = reader.ReadInt32();
|
||||
}
|
||||
|
||||
711
AssetStudio/Classes/GraphicsFormat.cs
Normal file
711
AssetStudio/Classes/GraphicsFormat.cs
Normal file
@@ -0,0 +1,711 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace AssetStudio
|
||||
m_TexEnvs[i] = new KeyValuePair<string, UnityTexEnv>(reader.ReadAlignedString(), new UnityTexEnv(reader));
|
||||
}
|
||||
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
if (version >= 2021) //2021.1 and up
|
||||
{
|
||||
int m_IntsSize = reader.ReadInt32();
|
||||
m_Ints = new KeyValuePair<string, int>[m_IntsSize];
|
||||
@@ -69,39 +69,39 @@ namespace AssetStudio
|
||||
{
|
||||
m_Shader = new PPtr<Shader>(reader);
|
||||
|
||||
if (version[0] == 4 && version[1] >= 1) //4.x
|
||||
if (version == 4 && version.Minor >= 1) //4.x
|
||||
{
|
||||
var m_ShaderKeywords = reader.ReadStringArray();
|
||||
}
|
||||
|
||||
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 3)) //2021.3 and up
|
||||
if (version >= (2021, 3)) //2021.3 and up
|
||||
{
|
||||
var m_ValidKeywords = reader.ReadStringArray();
|
||||
var m_InvalidKeywords = reader.ReadStringArray();
|
||||
}
|
||||
else if (version[0] >= 5) //5.0 ~ 2021.2
|
||||
else if (version >= 5) //5.0 ~ 2021.2
|
||||
{
|
||||
var m_ShaderKeywords = reader.ReadAlignedString();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
var m_LightmapFlags = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
var m_EnableInstancingVariants = reader.ReadBoolean();
|
||||
//var m_DoubleSidedGI = a_Stream.ReadBoolean(); //2017 and up
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
var m_CustomRenderQueue = reader.ReadInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 1)) //5.1 and up
|
||||
if (version >= (5, 1)) //5.1 and up
|
||||
{
|
||||
var stringTagMapSize = reader.ReadInt32();
|
||||
for (int i = 0; i < stringTagMapSize; i++)
|
||||
@@ -111,7 +111,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
var disabledShaderPasses = reader.ReadStringArray();
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace AssetStudio
|
||||
|
||||
m_Vertices = new PackedFloatVector(reader);
|
||||
m_UV = new PackedFloatVector(reader);
|
||||
if (version[0] < 5)
|
||||
if (version < 5)
|
||||
{
|
||||
m_BindPoses = new PackedFloatVector(reader);
|
||||
}
|
||||
@@ -49,15 +49,15 @@ namespace AssetStudio
|
||||
m_Weights = new PackedIntVector(reader);
|
||||
m_NormalSigns = new PackedIntVector(reader);
|
||||
m_TangentSigns = new PackedIntVector(reader);
|
||||
if (version[0] >= 5)
|
||||
if (version >= 5)
|
||||
{
|
||||
m_FloatColors = new PackedFloatVector(reader);
|
||||
}
|
||||
m_BoneIndices = new PackedIntVector(reader);
|
||||
m_Triangles = new PackedIntVector(reader);
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
|
||||
if (version >= (3, 5)) //3.5 and up
|
||||
{
|
||||
if (version[0] < 5)
|
||||
if (version < 5)
|
||||
{
|
||||
m_Colors = new PackedIntVector(reader);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ namespace AssetStudio
|
||||
channelMask = reader.ReadUInt32();
|
||||
offset = reader.ReadUInt32();
|
||||
|
||||
if (version[0] < 4) //4.0 down
|
||||
if (version < 4) //4.0 down
|
||||
{
|
||||
stride = reader.ReadUInt32();
|
||||
align = reader.ReadUInt32();
|
||||
@@ -131,14 +131,14 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] < 2018)//2018 down
|
||||
if (version < 2018)//2018 down
|
||||
{
|
||||
m_CurrentChannels = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
m_VertexCount = reader.ReadUInt32();
|
||||
|
||||
if (version[0] >= 4) //4.0 and up
|
||||
if (version >= 4) //4.0 and up
|
||||
{
|
||||
var m_ChannelsSize = reader.ReadInt32();
|
||||
m_Channels = new ChannelInfo[m_ChannelsSize];
|
||||
@@ -148,9 +148,9 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] < 5) //5.0 down
|
||||
if (version < 5) //5.0 down
|
||||
{
|
||||
if (version[0] < 4)
|
||||
if (version < 4)
|
||||
{
|
||||
m_Streams = new StreamInfo[4];
|
||||
}
|
||||
@@ -164,7 +164,7 @@ namespace AssetStudio
|
||||
m_Streams[i] = new StreamInfo(reader);
|
||||
}
|
||||
|
||||
if (version[0] < 4) //4.0 down
|
||||
if (version < 4) //4.0 down
|
||||
{
|
||||
GetChannels(version);
|
||||
}
|
||||
@@ -178,7 +178,7 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
private void GetStreams(int[] version)
|
||||
private void GetStreams(UnityVersion version)
|
||||
{
|
||||
var streamCount = m_Channels.Max(x => x.stream) + 1;
|
||||
m_Streams = new StreamInfo[streamCount];
|
||||
@@ -213,7 +213,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void GetChannels(int[] version)
|
||||
private void GetChannels(UnityVersion version)
|
||||
{
|
||||
m_Channels = new ChannelInfo[6];
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -305,20 +305,20 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] == 4 && version[1] < 3) //4.3 down
|
||||
if (version < (4, 3)) //4.3 down
|
||||
{
|
||||
var name = reader.ReadAlignedString();
|
||||
}
|
||||
firstVertex = reader.ReadUInt32();
|
||||
vertexCount = reader.ReadUInt32();
|
||||
if (version[0] == 4 && version[1] < 3) //4.3 down
|
||||
if (version < (4, 3)) //4.3 down
|
||||
{
|
||||
var aabbMinDelta = reader.ReadVector3();
|
||||
var aabbMaxDelta = reader.ReadVector3();
|
||||
}
|
||||
hasNormals = reader.ReadBoolean();
|
||||
hasTangents = reader.ReadBoolean();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
reader.AlignStream();
|
||||
}
|
||||
@@ -352,7 +352,7 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
int numVerts = reader.ReadInt32();
|
||||
vertices = new BlendShapeVertex[numVerts];
|
||||
@@ -425,17 +425,17 @@ namespace AssetStudio
|
||||
indexCount = reader.ReadUInt32();
|
||||
topology = (GfxPrimitiveType)reader.ReadInt32();
|
||||
|
||||
if (version[0] < 4) //4.0 down
|
||||
if (version < 4) //4.0 down
|
||||
{
|
||||
triangleCount = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
if (version >= (2017, 3)) //2017.3 and up
|
||||
{
|
||||
baseVertex = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] >= 3) //3.0 and up
|
||||
if (version >= 3) //3.0 and up
|
||||
{
|
||||
firstVertex = reader.ReadUInt32();
|
||||
vertexCount = reader.ReadUInt32();
|
||||
@@ -474,12 +474,12 @@ namespace AssetStudio
|
||||
|
||||
public Mesh(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.5 down
|
||||
if (version < (3, 5)) //3.5 down
|
||||
{
|
||||
m_Use16BitIndices = reader.ReadInt32() > 0;
|
||||
}
|
||||
|
||||
if (version[0] == 2 && version[1] <= 5) //2.5 and down
|
||||
if (version <= (2, 5)) //2.5 and down
|
||||
{
|
||||
int m_IndexBuffer_size = reader.ReadInt32();
|
||||
|
||||
@@ -505,21 +505,21 @@ namespace AssetStudio
|
||||
m_SubMeshes[i] = new SubMesh(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 1)) //4.1 and up
|
||||
if (version >= (4, 1)) //4.1 and up
|
||||
{
|
||||
m_Shapes = new BlendShapeData(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_BindPose = reader.ReadMatrixArray();
|
||||
m_BoneNameHashes = reader.ReadUInt32Array();
|
||||
var m_RootBoneNameHash = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
|
||||
if (version >= (2, 6)) //2.6.0 and up
|
||||
{
|
||||
if (version[0] >= 2019) //2019 and up
|
||||
if (version >= 2019) //2019 and up
|
||||
{
|
||||
var m_BonesAABBSize = reader.ReadInt32();
|
||||
var m_BonesAABB = new MinMaxAABB[m_BonesAABBSize];
|
||||
@@ -532,9 +532,9 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
var m_MeshCompression = reader.ReadByte();
|
||||
if (version[0] >= 4)
|
||||
if (version >= 4)
|
||||
{
|
||||
if (version[0] < 5)
|
||||
if (version < 5)
|
||||
{
|
||||
var m_StreamCompression = reader.ReadByte();
|
||||
}
|
||||
@@ -545,9 +545,9 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
|
||||
//Unity fixed it in 2017.3.1p1 and later versions
|
||||
if ((version[0] > 2017 || (version[0] == 2017 && version[1] >= 4)) || //2017.4
|
||||
((version[0] == 2017 && version[1] == 3 && version[2] == 1) && buildType.IsPatch) || //fixed after 2017.3.1px
|
||||
((version[0] == 2017 && version[1] == 3) && m_MeshCompression == 0))//2017.3.xfx with no compression
|
||||
if (version >= (2017, 4) //2017.4
|
||||
|| version == (2017, 3, 1) && buildType.IsPatch //fixed after 2017.3.1px
|
||||
|| version == (2017, 3) && m_MeshCompression == 0)//2017.3.xfx with no compression
|
||||
{
|
||||
var m_IndexFormat = reader.ReadInt32();
|
||||
m_Use16BitIndices = m_IndexFormat == 0;
|
||||
@@ -569,7 +569,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] < 3 || (version[0] == 3 && version[1] < 5)) //3.4.2 and earlier
|
||||
if (version < (3, 5)) //3.4.2 and earlier
|
||||
{
|
||||
m_VertexCount = reader.ReadInt32();
|
||||
m_Vertices = reader.ReadSingleArray(m_VertexCount * 3); //Vector3
|
||||
@@ -586,7 +586,7 @@ namespace AssetStudio
|
||||
|
||||
m_UV1 = reader.ReadSingleArray(reader.ReadInt32() * 2); //Vector2
|
||||
|
||||
if (version[0] == 2 && version[1] <= 5) //2.5 and down
|
||||
if (version <= (2, 5)) //2.5 and down
|
||||
{
|
||||
int m_TangentSpace_size = reader.ReadInt32();
|
||||
m_Normals = new float[m_TangentSpace_size * 3];
|
||||
@@ -611,7 +611,7 @@ namespace AssetStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
if (version < (2018, 2)) //2018.2 down
|
||||
{
|
||||
m_Skin = new BoneWeights4[reader.ReadInt32()];
|
||||
for (int s = 0; s < m_Skin.Length; s++)
|
||||
@@ -620,7 +620,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] == 3 || (version[0] == 4 && version[1] <= 2)) //4.2 and down
|
||||
if (version <= (4, 2)) //4.2 and down
|
||||
{
|
||||
m_BindPose = reader.ReadMatrixArray();
|
||||
}
|
||||
@@ -628,14 +628,14 @@ namespace AssetStudio
|
||||
m_VertexData = new VertexData(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later
|
||||
if (version >= (2, 6)) //2.6.0 and later
|
||||
{
|
||||
m_CompressedMesh = new CompressedMesh(reader);
|
||||
}
|
||||
|
||||
reader.Position += 24; //AABB m_LocalAABB
|
||||
|
||||
if (version[0] < 3 || (version[0] == 3 && version[1] <= 4)) //3.4.2 and earlier
|
||||
if (version <= (3, 4)) //3.4.2 and earlier
|
||||
{
|
||||
int m_Colors_size = reader.ReadInt32();
|
||||
m_Colors = new float[m_Colors_size * 4];
|
||||
@@ -651,12 +651,12 @@ namespace AssetStudio
|
||||
|
||||
int m_MeshUsageFlags = reader.ReadInt32();
|
||||
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
if (version >= (2022, 1)) //2022.1 and up
|
||||
{
|
||||
int m_CookingOptions = reader.ReadInt32();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
var m_BakedConvexCollisionMesh = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
@@ -664,14 +664,14 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
if (version >= (2018, 2)) //2018.2 and up
|
||||
{
|
||||
var m_MeshMetrics = new float[2];
|
||||
m_MeshMetrics[0] = reader.ReadSingle();
|
||||
m_MeshMetrics[1] = reader.ReadSingle();
|
||||
}
|
||||
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
|
||||
if (version >= (2018, 3)) //2018.3 and up
|
||||
{
|
||||
reader.AlignStream();
|
||||
m_StreamData = new StreamingInfo(reader);
|
||||
@@ -690,12 +690,12 @@ namespace AssetStudio
|
||||
m_VertexData.m_DataSize = resourceReader.GetData();
|
||||
}
|
||||
}
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
|
||||
if (version >= (3, 5)) //3.5 and up
|
||||
{
|
||||
ReadVertexData();
|
||||
}
|
||||
|
||||
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and later
|
||||
if (version >= (2, 6)) //2.6.0 and later
|
||||
{
|
||||
DecompressCompressedMesh();
|
||||
}
|
||||
@@ -716,7 +716,7 @@ namespace AssetStudio
|
||||
var channelMask = new BitArray(new[] { (int)m_Stream.channelMask });
|
||||
if (channelMask.Get(chn))
|
||||
{
|
||||
if (version[0] < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
|
||||
if (version < 2018 && chn == 2 && m_Channel.format == 2) //kShaderChannelColor && kChannelFormatColor
|
||||
{
|
||||
m_Channel.dimension = 4;
|
||||
}
|
||||
@@ -752,7 +752,7 @@ namespace AssetStudio
|
||||
else
|
||||
componentsFloatArray = MeshHelper.BytesToFloatArray(componentBytes, vertexFormat);
|
||||
|
||||
if (version[0] >= 2018)
|
||||
if (version >= 2018)
|
||||
{
|
||||
switch (chn)
|
||||
{
|
||||
@@ -841,7 +841,7 @@ namespace AssetStudio
|
||||
m_UV1 = componentsFloatArray;
|
||||
break;
|
||||
case 5:
|
||||
if (version[0] >= 5) //kShaderChannelTexCoord2
|
||||
if (version >= 5) //kShaderChannelTexCoord2
|
||||
{
|
||||
m_UV2 = componentsFloatArray;
|
||||
}
|
||||
@@ -906,7 +906,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
//BindPose
|
||||
if (version[0] < 5)
|
||||
if (version < 5)
|
||||
{
|
||||
if (m_CompressedMesh.m_BindPoses.m_NumItems > 0)
|
||||
{
|
||||
@@ -983,7 +983,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
//FloatColor
|
||||
if (version[0] >= 5)
|
||||
if (version >= 5)
|
||||
{
|
||||
if (m_CompressedMesh.m_FloatColors.m_NumItems > 0)
|
||||
{
|
||||
@@ -1074,7 +1074,7 @@ namespace AssetStudio
|
||||
m_Indices.Add(m_IndexBuffer[firstIndex + i + 2]);
|
||||
}
|
||||
}
|
||||
else if (version[0] < 4 || topology == GfxPrimitiveType.TriangleStrip)
|
||||
else if (version < 4 || topology == GfxPrimitiveType.TriangleStrip)
|
||||
{
|
||||
// de-stripify :
|
||||
uint triIndex = 0;
|
||||
@@ -1238,9 +1238,9 @@ namespace AssetStudio
|
||||
SInt32
|
||||
}
|
||||
|
||||
public static VertexFormat ToVertexFormat(int format, int[] version)
|
||||
public static VertexFormat ToVertexFormat(int format, UnityVersion version)
|
||||
{
|
||||
if (version[0] < 2017)
|
||||
if (version < 2017)
|
||||
{
|
||||
switch ((VertexChannelFormat)format)
|
||||
{
|
||||
@@ -1258,7 +1258,7 @@ namespace AssetStudio
|
||||
throw new ArgumentOutOfRangeException(nameof(format), format, null);
|
||||
}
|
||||
}
|
||||
else if (version[0] < 2019)
|
||||
else if (version < 2019)
|
||||
{
|
||||
switch ((VertexFormat2017)format)
|
||||
{
|
||||
|
||||
@@ -13,11 +13,11 @@ namespace AssetStudio
|
||||
|
||||
public MonoScript(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 4)) //3.4 and up
|
||||
if (version >= (3, 4)) //3.4 and up
|
||||
{
|
||||
var m_ExecutionOrder = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] < 5) //5.0 down
|
||||
if (version < 5) //5.0 down
|
||||
{
|
||||
var m_PropertiesHash = reader.ReadUInt32();
|
||||
}
|
||||
@@ -25,17 +25,17 @@ namespace AssetStudio
|
||||
{
|
||||
var m_PropertiesHash = reader.ReadBytes(16);
|
||||
}
|
||||
if (version[0] < 3) //3.0 down
|
||||
if (version < 3) //3.0 down
|
||||
{
|
||||
var m_PathName = reader.ReadAlignedString();
|
||||
}
|
||||
m_ClassName = reader.ReadAlignedString();
|
||||
if (version[0] >= 3) //3.0 and up
|
||||
if (version >= 3) //3.0 and up
|
||||
{
|
||||
m_Namespace = reader.ReadAlignedString();
|
||||
}
|
||||
m_AssemblyName = reader.ReadAlignedString();
|
||||
if (version[0] < 2018 || (version[0] == 2018 && version[1] < 2)) //2018.2 down
|
||||
if (version < (2018, 2)) //2018.2 down
|
||||
{
|
||||
var m_IsEditorScript = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ namespace AssetStudio
|
||||
{
|
||||
public string m_Name;
|
||||
|
||||
protected NamedObject() { }
|
||||
|
||||
protected NamedObject(ObjectReader reader) : base(reader)
|
||||
{
|
||||
m_Name = reader.ReadAlignedString();
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
using System.Collections.Specialized;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
public class Object
|
||||
{
|
||||
[JsonIgnore]
|
||||
public SerializedFile assetsFile;
|
||||
[JsonIgnore]
|
||||
public ObjectReader reader;
|
||||
public long m_PathID;
|
||||
public int[] version;
|
||||
[JsonIgnore]
|
||||
public UnityVersion version;
|
||||
protected BuildType buildType;
|
||||
[JsonIgnore]
|
||||
public BuildTarget platform;
|
||||
public ClassIDType type;
|
||||
[JsonIgnore]
|
||||
public SerializedType serializedType;
|
||||
public uint byteSize;
|
||||
|
||||
public Object() { }
|
||||
|
||||
public Object(ObjectReader reader)
|
||||
{
|
||||
this.reader = reader;
|
||||
@@ -51,6 +59,24 @@ namespace AssetStudio
|
||||
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()
|
||||
{
|
||||
if (serializedType?.m_Type != null)
|
||||
|
||||
@@ -7,45 +7,47 @@ namespace AssetStudio
|
||||
public int m_FileID;
|
||||
public long m_PathID;
|
||||
|
||||
private SerializedFile assetsFile;
|
||||
private int index = -2; //-2 - Prepare, -1 - Missing
|
||||
private SerializedFile _assetsFile;
|
||||
private int _index = -2; //-2 - Prepare, -1 - Missing
|
||||
|
||||
public PPtr(ObjectReader reader)
|
||||
{
|
||||
m_FileID = reader.ReadInt32();
|
||||
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)
|
||||
{
|
||||
result = null;
|
||||
if (m_FileID == 0)
|
||||
{
|
||||
result = assetsFile;
|
||||
result = _assetsFile;
|
||||
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 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;
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out index))
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out _index))
|
||||
{
|
||||
index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
assetsFileIndexCache.Add(name, index);
|
||||
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
assetsFileIndexCache.Add(name, _index);
|
||||
}
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
if (_index >= 0)
|
||||
{
|
||||
result = assetsFileList[index];
|
||||
result = assetsFileList[_index];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -53,8 +55,9 @@ namespace AssetStudio
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGet(out T result)
|
||||
public bool TryGet(out T result, SerializedFile assetsFile = null)
|
||||
{
|
||||
_assetsFile = _assetsFile ?? assetsFile;
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||
@@ -71,8 +74,9 @@ namespace AssetStudio
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGet<T2>(out T2 result) where T2 : Object
|
||||
public bool TryGet<T2>(out T2 result, SerializedFile assetsFile = null) where T2 : Object
|
||||
{
|
||||
_assetsFile = _assetsFile ?? assetsFile;
|
||||
if (TryGetAssetsFile(out var sourceFile))
|
||||
{
|
||||
if (sourceFile.ObjectsDic.TryGetValue(m_PathID, out var obj))
|
||||
@@ -92,20 +96,20 @@ namespace AssetStudio
|
||||
public void Set(T m_Object)
|
||||
{
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
assetsFile.m_Externals.Add(new FileIdentifier
|
||||
_assetsFile.m_Externals.Add(new FileIdentifier
|
||||
{
|
||||
fileName = m_Object.assetsFile.fileName
|
||||
});
|
||||
m_FileID = assetsFile.m_Externals.Count;
|
||||
m_FileID = _assetsFile.m_Externals.Count;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,14 +117,14 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
var assetsManager = assetsFile.assetsManager;
|
||||
var assetsManager = _assetsFile.assetsManager;
|
||||
var assetsFileList = assetsManager.assetsFileList;
|
||||
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));
|
||||
assetsFileIndexCache.Add(name, index);
|
||||
_index = assetsFileList.FindIndex(x => x.fileName.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
assetsFileIndexCache.Add(name, _index);
|
||||
}
|
||||
|
||||
m_PathID = m_Object.m_PathID;
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
|
||||
public PlayerSettings(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4.0 nad up
|
||||
if (version >= (5, 4)) //5.4.0 and up
|
||||
{
|
||||
var productGUID = reader.ReadBytes(16);
|
||||
}
|
||||
@@ -23,12 +23,12 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
int defaultScreenOrientation = reader.ReadInt32();
|
||||
int targetDevice = reader.ReadInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 3)) //5.3 down
|
||||
if (version < (5, 3)) //5.3 down
|
||||
{
|
||||
if (version[0] < 5) //5.0 down
|
||||
if (version < 5) //5.0 down
|
||||
{
|
||||
int targetPlatform = reader.ReadInt32(); //4.0 and up targetGlesGraphics
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 6)) //4.6 and up
|
||||
if (version >= (4, 6)) //4.6 and up
|
||||
{
|
||||
var targetIOSGraphics = reader.ReadInt32();
|
||||
}
|
||||
@@ -40,7 +40,7 @@ namespace AssetStudio
|
||||
var useOnDemandResources = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 and up
|
||||
if (version >= (3, 5)) //3.5 and up
|
||||
{
|
||||
var accelerometerFrequency = reader.ReadInt32();
|
||||
}
|
||||
|
||||
35
AssetStudio/Classes/PreloadData.cs
Normal file
35
AssetStudio/Classes/PreloadData.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
namespace AssetStudio
|
||||
{
|
||||
public sealed class PreloadData : NamedObject
|
||||
{
|
||||
public PPtr<Object>[] m_Assets;
|
||||
|
||||
public PreloadData(ObjectReader reader) : base(reader)
|
||||
{
|
||||
var m_PreloadTableSize = reader.ReadInt32();
|
||||
m_Assets = new PPtr<Object>[m_PreloadTableSize];
|
||||
for (var i = 0; i < m_PreloadTableSize; i++)
|
||||
{
|
||||
m_Assets[i] = new PPtr<Object>(reader);
|
||||
}
|
||||
|
||||
/*
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
{
|
||||
var m_DependenciesSize = reader.ReadInt32();
|
||||
var m_Dependencies = new string[m_DependenciesSize];
|
||||
|
||||
for (var i = 0; i < m_DependenciesSize; i++)
|
||||
{
|
||||
m_Dependencies[i] = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
{
|
||||
var m_ExplicitDataLayout = reader.ReadBoolean();
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace AssetStudio
|
||||
|
||||
protected Renderer(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] < 5) //5.0 down
|
||||
if (version < 5) //5.0 down
|
||||
{
|
||||
var m_Enabled = reader.ReadBoolean();
|
||||
var m_CastShadows = reader.ReadBoolean();
|
||||
@@ -34,27 +34,27 @@ namespace AssetStudio
|
||||
}
|
||||
else //5.0 and up
|
||||
{
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||
if (version >= (5, 4)) //5.4 and up
|
||||
{
|
||||
var m_Enabled = reader.ReadBoolean();
|
||||
var m_CastShadows = reader.ReadByte();
|
||||
var m_ReceiveShadows = reader.ReadByte();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
var m_DynamicOccludee = reader.ReadByte();
|
||||
}
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
if (version >= 2021) //2021.1 and up
|
||||
{
|
||||
var m_StaticShadowCaster = reader.ReadByte();
|
||||
}
|
||||
var m_MotionVectors = reader.ReadByte();
|
||||
var m_LightProbeUsage = reader.ReadByte();
|
||||
var m_ReflectionProbeUsage = reader.ReadByte();
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
if (version >= (2019, 3)) //2019.3 and up
|
||||
{
|
||||
var m_RayTracingMode = reader.ReadByte();
|
||||
}
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_RayTraceProcedural = reader.ReadByte();
|
||||
}
|
||||
@@ -69,12 +69,12 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
if (version >= 2018) //2018 and up
|
||||
{
|
||||
var m_RenderingLayerMask = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 3)) //2018.3 and up
|
||||
if (version >= (2018, 3)) //2018.3 and up
|
||||
{
|
||||
var m_RendererPriority = reader.ReadInt32();
|
||||
}
|
||||
@@ -83,12 +83,12 @@ namespace AssetStudio
|
||||
var m_LightmapIndexDynamic = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
if (version[0] >= 3) //3.0 and up
|
||||
if (version >= 3) //3.0 and up
|
||||
{
|
||||
var m_LightmapTilingOffset = reader.ReadVector4();
|
||||
}
|
||||
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
var m_LightmapTilingOffsetDynamic = reader.ReadVector4();
|
||||
}
|
||||
@@ -100,13 +100,13 @@ namespace AssetStudio
|
||||
m_Materials[i] = new PPtr<Material>(reader);
|
||||
}
|
||||
|
||||
if (version[0] < 3) //3.0 down
|
||||
if (version < 3) //3.0 down
|
||||
{
|
||||
var m_LightmapTilingOffset = reader.ReadVector4();
|
||||
}
|
||||
else //3.0 and up
|
||||
{
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||
if (version >= (5, 5)) //5.5 and up
|
||||
{
|
||||
m_StaticBatchInfo = new StaticBatchInfo(reader);
|
||||
}
|
||||
@@ -118,17 +118,17 @@ namespace AssetStudio
|
||||
var m_StaticBatchRoot = new PPtr<Transform>(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 4)) //5.4 and up
|
||||
if (version >= (5, 4)) //5.4 and up
|
||||
{
|
||||
var m_ProbeAnchor = new PPtr<Transform>(reader);
|
||||
var m_LightProbeVolumeOverride = new PPtr<GameObject>(reader);
|
||||
}
|
||||
else if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5 - 5.3
|
||||
else if (version >= (3, 5)) //3.5 - 5.3
|
||||
{
|
||||
var m_UseLightProbes = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
|
||||
if (version[0] >= 5)//5.0 and up
|
||||
if (version >= 5)//5.0 and up
|
||||
{
|
||||
var m_ReflectionProbeUsage = reader.ReadInt32();
|
||||
}
|
||||
@@ -136,9 +136,9 @@ namespace AssetStudio
|
||||
var m_LightProbeAnchor = new PPtr<Transform>(reader); //5.0 and up m_ProbeAnchor
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
if (version[0] == 4 && version[1] == 3) //4.3
|
||||
if (version == (4, 3)) //4.3
|
||||
{
|
||||
var m_SortingLayer = reader.ReadInt16();
|
||||
}
|
||||
|
||||
@@ -243,14 +243,14 @@ namespace AssetStudio
|
||||
}
|
||||
rtSeparateBlend = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
zClip = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
zTest = new SerializedShaderFloatValue(reader);
|
||||
zWrite = new SerializedShaderFloatValue(reader);
|
||||
culling = new SerializedShaderFloatValue(reader);
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
conservative = new SerializedShaderFloatValue(reader);
|
||||
}
|
||||
@@ -359,7 +359,7 @@ namespace AssetStudio
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
m_SamplerIndex = reader.ReadInt32();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
if (version >= (2017, 3)) //2017.3 and up
|
||||
{
|
||||
var m_MultiSampled = reader.ReadBoolean();
|
||||
}
|
||||
@@ -380,7 +380,7 @@ namespace AssetStudio
|
||||
|
||||
m_NameIndex = reader.ReadInt32();
|
||||
m_Index = reader.ReadInt32();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
m_ArraySize = reader.ReadInt32();
|
||||
}
|
||||
@@ -415,7 +415,7 @@ namespace AssetStudio
|
||||
{
|
||||
m_VectorParams[i] = new VectorParameter(reader);
|
||||
}
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
if (version >= (2017, 3)) //2017.3 and up
|
||||
{
|
||||
int numStructParams = reader.ReadInt32();
|
||||
m_StructParams = new StructParameter[numStructParams];
|
||||
@@ -426,11 +426,8 @@ namespace AssetStudio
|
||||
}
|
||||
m_Size = reader.ReadInt32();
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 4)) //2021.1.4f1 and up
|
||||
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|
||||
|| version >= (2021, 1, 4)) //2021.1.4f1 and up
|
||||
{
|
||||
m_IsPartialCB = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
@@ -584,7 +581,7 @@ namespace AssetStudio
|
||||
m_BlobIndex = reader.ReadUInt32();
|
||||
m_Channels = new ParserBindChannels(reader);
|
||||
|
||||
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2)) //2019 ~2021.1
|
||||
if (version.IsInRange(2019, (2021, 2))) //2019 ~2021.1
|
||||
{
|
||||
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -594,7 +591,7 @@ namespace AssetStudio
|
||||
else
|
||||
{
|
||||
m_KeywordIndices = reader.ReadUInt16Array();
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
reader.AlignStream();
|
||||
}
|
||||
@@ -604,11 +601,8 @@ namespace AssetStudio
|
||||
m_GpuProgramType = (ShaderGpuProgramType)reader.ReadSByte();
|
||||
reader.AlignStream();
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|
||||
|| version >= (2021, 1, 1)) //2021.1.1f1 and up
|
||||
{
|
||||
m_Parameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
@@ -663,7 +657,7 @@ namespace AssetStudio
|
||||
m_UAVParams[i] = new UAVParameter(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
int numSamplers = reader.ReadInt32();
|
||||
m_Samplers = new SamplerParameter[numSamplers];
|
||||
@@ -674,9 +668,9 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
if (version >= 2021) //2021.1 and up
|
||||
{
|
||||
var m_ShaderRequirements = reader.ReadInt64();
|
||||
}
|
||||
@@ -705,16 +699,13 @@ namespace AssetStudio
|
||||
m_SubPrograms[i] = new SerializedSubProgram(reader);
|
||||
}
|
||||
|
||||
if ((version[0] == 2020 && version[1] > 3) ||
|
||||
(version[0] == 2020 && version[1] == 3 && version[2] >= 2) || //2020.3.2f1 and up
|
||||
(version[0] > 2021) ||
|
||||
(version[0] == 2021 && version[1] > 1) ||
|
||||
(version[0] == 2021 && version[1] == 1 && version[2] >= 1)) //2021.1.1f1 and up
|
||||
if (version.IsInRange((2020, 3, 2), 2021) //2020.3.2f1 and up
|
||||
|| version >= (2021, 1, 1)) //2021.1.1f1 and up
|
||||
{
|
||||
m_CommonParameters = new SerializedProgramParameters(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 2022 || (version[0] == 2022 && version[1] >= 1)) //2022.1 and up
|
||||
if (version >= (2022, 1)) //2022.1 and up
|
||||
{
|
||||
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -756,7 +747,7 @@ namespace AssetStudio
|
||||
{
|
||||
var version = reader.version;
|
||||
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
if (version >= (2020, 2)) //2020.2 and up
|
||||
{
|
||||
int numEditorDataHash = reader.ReadInt32();
|
||||
m_EditorDataHash = new Hash128[numEditorDataHash];
|
||||
@@ -767,7 +758,7 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
m_Platforms = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
if (version[0] < 2021 || (version[0] == 2021 && version[1] < 2)) //2021.1 and down
|
||||
if (version <= (2021, 1)) //2021.1 and down
|
||||
{
|
||||
m_LocalKeywordMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -791,12 +782,12 @@ namespace AssetStudio
|
||||
progGeometry = new SerializedProgram(reader);
|
||||
progHull = new SerializedProgram(reader);
|
||||
progDomain = new SerializedProgram(reader);
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
if (version >= (2019, 3)) //2019.3 and up
|
||||
{
|
||||
progRayTracing = new SerializedProgram(reader);
|
||||
}
|
||||
m_HasInstancingVariant = reader.ReadBoolean();
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
if (version >= 2018) //2018 and up
|
||||
{
|
||||
var m_HasProceduralInstancingVariant = reader.ReadBoolean();
|
||||
}
|
||||
@@ -805,7 +796,7 @@ namespace AssetStudio
|
||||
m_Name = reader.ReadAlignedString();
|
||||
m_TextureName = reader.ReadAlignedString();
|
||||
m_Tags = new SerializedTagMap(reader);
|
||||
if (version[0] == 2021 && version[1] >= 2) //2021.2 ~2021.x
|
||||
if (version == 2021 && version.Minor >= 2) //2021.2 ~2021.x
|
||||
{
|
||||
m_SerializedKeywordStateMask = reader.ReadUInt16Array();
|
||||
reader.AlignStream();
|
||||
@@ -898,7 +889,7 @@ namespace AssetStudio
|
||||
m_SubShaders[i] = new SerializedSubShader(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 2021 || (version[0] == 2021 && version[1] >= 2)) //2021.2 and up
|
||||
if (version >= (2021, 2)) //2021.2 and up
|
||||
{
|
||||
m_KeywordNames = reader.ReadStringArray();
|
||||
m_KeywordFlags = reader.ReadUInt8Array();
|
||||
@@ -916,7 +907,7 @@ namespace AssetStudio
|
||||
m_Dependencies[i] = new SerializedShaderDependency(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 2021) //2021.1 and up
|
||||
if (version >= 2021) //2021.1 and up
|
||||
{
|
||||
int m_CustomEditorForRenderPipelinesSize = reader.ReadInt32();
|
||||
m_CustomEditorForRenderPipelines = new SerializedCustomEditorForRenderPipeline[m_CustomEditorForRenderPipelinesSize];
|
||||
@@ -977,11 +968,11 @@ namespace AssetStudio
|
||||
|
||||
public Shader(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] == 5 && version[1] >= 5 || version[0] > 5) //5.5 and up
|
||||
if (version >= (5, 5)) //5.5 and up
|
||||
{
|
||||
m_ParsedForm = new SerializedShader(reader);
|
||||
platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray();
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
if (version >= (2019, 3)) //2019.3 and up
|
||||
{
|
||||
offsets = reader.ReadUInt32ArrayArray();
|
||||
compressedLengths = reader.ReadUInt32ArrayArray();
|
||||
@@ -1002,7 +993,7 @@ namespace AssetStudio
|
||||
new PPtr<Shader>(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 2018)
|
||||
if (version >= 2018)
|
||||
{
|
||||
var m_NonModifiableTexturesCount = reader.ReadInt32();
|
||||
for (int i = 0; i < m_NonModifiableTexturesCount; i++)
|
||||
@@ -1020,7 +1011,7 @@ namespace AssetStudio
|
||||
m_Script = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
var m_PathName = reader.ReadAlignedString();
|
||||
if (version[0] == 5 && version[1] >= 3) //5.3 - 5.4
|
||||
if (version == 5 && version.Minor >= 3) //5.3 - 5.4
|
||||
{
|
||||
decompressedSize = reader.ReadUInt32();
|
||||
m_SubProgramBlob = reader.ReadUInt8Array();
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace AssetStudio
|
||||
var m_SkinNormals = reader.ReadBoolean(); //3.1.0 and below
|
||||
reader.AlignStream();
|
||||
|
||||
if (version[0] == 2 && version[1] < 6) //2.6 down
|
||||
if (version < (2, 6)) //2.6 down
|
||||
{
|
||||
var m_DisableAnimationWhenOffscreen = new PPtr<Animation>(reader);
|
||||
}
|
||||
@@ -31,7 +31,7 @@ namespace AssetStudio
|
||||
m_Bones[b] = new PPtr<Transform>(reader);
|
||||
}
|
||||
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 3)) //4.3 and up
|
||||
if (version >= (4, 3)) //4.3 and up
|
||||
{
|
||||
m_BlendShapeWeights = reader.ReadSingleArray();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace AssetStudio
|
||||
public SecondarySpriteTexture(ObjectReader reader)
|
||||
{
|
||||
texture = new PPtr<Texture2D>(reader);
|
||||
name = reader.ReadStringToNull();
|
||||
name = reader.ReadAlignedString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ namespace AssetStudio
|
||||
var version = reader.version;
|
||||
|
||||
pos = reader.ReadVector3();
|
||||
if (version[0] < 4 || (version[0] == 4 && version[1] <= 3)) //4.3 and down
|
||||
if (version <= (4, 3)) //4.3 and down
|
||||
{
|
||||
uv = reader.ReadVector2();
|
||||
}
|
||||
@@ -99,12 +99,12 @@ namespace AssetStudio
|
||||
var version = reader.version;
|
||||
|
||||
texture = new PPtr<Texture2D>(reader);
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 2)) //5.2 and up
|
||||
if (version >= (5, 2)) //5.2 and up
|
||||
{
|
||||
alphaTexture = new PPtr<Texture2D>(reader);
|
||||
}
|
||||
|
||||
if (version[0] >= 2019) //2019 and up
|
||||
if (version >= 2019) //2019 and up
|
||||
{
|
||||
var secondaryTexturesSize = reader.ReadInt32();
|
||||
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
|
||||
@@ -114,7 +114,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
var m_SubMeshesSize = reader.ReadInt32();
|
||||
m_SubMeshes = new SubMesh[m_SubMeshesSize];
|
||||
@@ -141,11 +141,11 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
if (version >= 2018) //2018 and up
|
||||
{
|
||||
m_Bindpose = reader.ReadMatrixArray();
|
||||
|
||||
if (version[0] == 2018 && version[1] < 2) //2018.2 down
|
||||
if (version < (2018, 2)) //2018.2 down
|
||||
{
|
||||
var m_SourceSkinSize = reader.ReadInt32();
|
||||
for (int i = 0; i < m_SourceSkinSize; i++)
|
||||
@@ -157,18 +157,18 @@ namespace AssetStudio
|
||||
|
||||
textureRect = new Rectf(reader);
|
||||
textureRectOffset = reader.ReadVector2();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
atlasRectOffset = reader.ReadVector2();
|
||||
}
|
||||
|
||||
settingsRaw = new SpriteSettings(reader);
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
if (version >= (4, 5)) //4.5 and up
|
||||
{
|
||||
uvTransform = reader.ReadVector4();
|
||||
}
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
downscaleMultiplier = reader.ReadSingle();
|
||||
}
|
||||
@@ -210,28 +210,26 @@ namespace AssetStudio
|
||||
{
|
||||
m_Rect = new Rectf(reader);
|
||||
m_Offset = reader.ReadVector2();
|
||||
if (version[0] > 4 || (version[0] == 4 && version[1] >= 5)) //4.5 and up
|
||||
if (version >= (4, 5)) //4.5 and up
|
||||
{
|
||||
m_Border = reader.ReadVector4();
|
||||
}
|
||||
|
||||
m_PixelsToUnits = reader.ReadSingle();
|
||||
if (version[0] > 5
|
||||
|| (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
|
||||
if (version >= (5, 4, 2)
|
||||
|| version == (5, 4, 1) && buildType.IsPatch && version.Build >= 3) //5.4.1p3 and up
|
||||
{
|
||||
m_Pivot = reader.ReadVector2();
|
||||
}
|
||||
|
||||
m_Extrude = reader.ReadUInt32();
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
|
||||
if (version >= (5, 3)) //5.3 and up
|
||||
{
|
||||
m_IsPolygon = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
var first = new Guid(reader.ReadBytes(16));
|
||||
var second = reader.ReadInt64();
|
||||
@@ -244,7 +242,7 @@ namespace AssetStudio
|
||||
|
||||
m_RD = new SpriteRenderData(reader);
|
||||
|
||||
if (version[0] >= 2017) //2017 and up
|
||||
if (version >= 2017) //2017 and up
|
||||
{
|
||||
var m_PhysicsShapeSize = reader.ReadInt32();
|
||||
m_PhysicsShape = new Vector2[m_PhysicsShapeSize][];
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace AssetStudio
|
||||
alphaTexture = new PPtr<Texture2D>(reader);
|
||||
textureRect = new Rectf(reader);
|
||||
textureRectOffset = reader.ReadVector2();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
atlasRectOffset = reader.ReadVector2();
|
||||
}
|
||||
uvTransform = reader.ReadVector4();
|
||||
downscaleMultiplier = reader.ReadSingle();
|
||||
settingsRaw = new SpriteSettings(reader);
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
if (version >= (2020, 2)) //2020.2 and up
|
||||
{
|
||||
var secondaryTexturesSize = reader.ReadInt32();
|
||||
secondaryTextures = new SecondarySpriteTexture[secondaryTexturesSize];
|
||||
|
||||
27
AssetStudio/Classes/StreamingInfo.cs
Normal file
27
AssetStudio/Classes/StreamingInfo.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudio
|
||||
namespace AssetStudio
|
||||
{
|
||||
public abstract class Texture : NamedObject
|
||||
{
|
||||
protected Texture() { }
|
||||
|
||||
protected Texture(ObjectReader reader) : base(reader)
|
||||
{
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 3)) //2017.3 and up
|
||||
if (version >= (2017, 3)) //2017.3 and up
|
||||
{
|
||||
var m_ForcedFallbackFormat = reader.ReadInt32();
|
||||
var m_DownscaleFallback = reader.ReadBoolean();
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
if (version < (2023, 2)) //2023.2 down
|
||||
{
|
||||
var m_ForcedFallbackFormat = reader.ReadInt32();
|
||||
var m_DownscaleFallback = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
if (version >= (2020, 2)) //2020.2 and up
|
||||
{
|
||||
var m_IsAlphaChannelOptional = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
@@ -1,79 +1,89 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
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 int m_Width;
|
||||
public int m_Height;
|
||||
public int m_CompleteImageSize;
|
||||
public TextureFormat m_TextureFormat;
|
||||
public bool m_MipMap;
|
||||
public int m_MipCount;
|
||||
public GLTextureSettings m_TextureSettings;
|
||||
public int m_ImageCount;
|
||||
public byte[] m_PlatformBlob;
|
||||
public ResourceReader image_data;
|
||||
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)
|
||||
{
|
||||
m_Width = reader.ReadInt32();
|
||||
m_Height = reader.ReadInt32();
|
||||
var m_CompleteImageSize = reader.ReadInt32();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
m_CompleteImageSize = reader.ReadInt32();
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_MipsStripped = reader.ReadInt32();
|
||||
}
|
||||
m_TextureFormat = (TextureFormat)reader.ReadInt32();
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] < 2)) //5.2 down
|
||||
if (version < (5, 2)) //5.2 down
|
||||
{
|
||||
m_MipMap = reader.ReadBoolean();
|
||||
}
|
||||
@@ -81,140 +91,132 @@ namespace AssetStudio
|
||||
{
|
||||
m_MipCount = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] > 2 || (version[0] == 2 && version[1] >= 6)) //2.6.0 and up
|
||||
if (version >= (2, 6)) //2.6.0 and up
|
||||
{
|
||||
var m_IsReadable = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_IsPreProcessed = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up
|
||||
if (version >= (2019, 3)) //2019.3 and up
|
||||
{
|
||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||
}
|
||||
if (version[0] >= 3) //3.0.0 - 5.4
|
||||
{
|
||||
if (version[0] < 5 || (version[0] == 5 && version[1] <= 4))
|
||||
if (version >= (2022, 2)) //2022.2 and up
|
||||
{
|
||||
var m_ReadAllowed = reader.ReadBoolean();
|
||||
var m_IgnoreMipmapLimit = reader.ReadBoolean();
|
||||
reader.AlignStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_IgnoreMasterTextureLimit = reader.ReadBoolean();
|
||||
}
|
||||
}
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
if (version.IsInRange(3, (5, 5))) //3.0.0 - 5.4
|
||||
{
|
||||
var m_ReadAllowed = reader.ReadBoolean();
|
||||
}
|
||||
if (version >= (2022, 2)) //2022.2 and up
|
||||
{
|
||||
var m_MipmapLimitGroupName = reader.ReadAlignedString();
|
||||
}
|
||||
if (version >= (2018, 2)) //2018.2 and up
|
||||
{
|
||||
var m_StreamingMipmaps = reader.ReadBoolean();
|
||||
}
|
||||
reader.AlignStream();
|
||||
if (version[0] > 2018 || (version[0] == 2018 && version[1] >= 2)) //2018.2 and up
|
||||
if (version >= (2018, 2)) //2018.2 and up
|
||||
{
|
||||
var m_StreamingMipmapsPriority = reader.ReadInt32();
|
||||
}
|
||||
var m_ImageCount = reader.ReadInt32();
|
||||
m_ImageCount = reader.ReadInt32();
|
||||
var m_TextureDimension = reader.ReadInt32();
|
||||
m_TextureSettings = new GLTextureSettings(reader);
|
||||
if (version[0] >= 3) //3.0 and up
|
||||
if (version >= 3) //3.0 and up
|
||||
{
|
||||
var m_LightmapFormat = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] > 3 || (version[0] == 3 && version[1] >= 5)) //3.5.0 and up
|
||||
if (version >= (3, 5)) //3.5.0 and up
|
||||
{
|
||||
var m_ColorSpace = reader.ReadInt32();
|
||||
}
|
||||
if (version[0] > 2020 || (version[0] == 2020 && version[1] >= 2)) //2020.2 and up
|
||||
if (version >= (2020, 2)) //2020.2 and up
|
||||
{
|
||||
var m_PlatformBlob = reader.ReadUInt8Array();
|
||||
m_PlatformBlob = reader.ReadUInt8Array();
|
||||
reader.AlignStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlatformBlob = Array.Empty<byte>();
|
||||
}
|
||||
var image_data_size = reader.ReadInt32();
|
||||
if (image_data_size == 0 && ((version[0] == 5 && version[1] >= 3) || version[0] > 5))//5.3.0 and up
|
||||
if (image_data_size == 0 && version >= (5, 3))//5.3.0 and up
|
||||
{
|
||||
m_StreamData = new StreamingInfo(reader);
|
||||
}
|
||||
|
||||
ResourceReader resourceReader;
|
||||
if (!string.IsNullOrEmpty(m_StreamData?.path))
|
||||
image_data = !string.IsNullOrEmpty(m_StreamData?.path)
|
||||
? new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size)
|
||||
: 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)
|
||||
{
|
||||
resourceReader = new ResourceReader(m_StreamData.path, assetsFile, m_StreamData.offset, m_StreamData.size);
|
||||
case TextureFormat.ASTC_RGBA_5x5:
|
||||
// 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;
|
||||
}
|
||||
else
|
||||
{
|
||||
resourceReader = new ResourceReader(reader, reader.BaseStream.Position, image_data_size);
|
||||
}
|
||||
image_data = resourceReader;
|
||||
return imgDataSize;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
73
AssetStudio/Classes/Texture2DArray.cs
Normal file
73
AssetStudio/Classes/Texture2DArray.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
282
AssetStudio/Classes/TextureFormat.cs
Normal file
282
AssetStudio/Classes/TextureFormat.cs
Normal file
@@ -0,0 +1,282 @@
|
||||
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,
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace AssetStudio
|
||||
var m_ProxyHeight = reader.ReadUInt32();
|
||||
Width = reader.ReadUInt32();
|
||||
Height = reader.ReadUInt32();
|
||||
if (version[0] > 2017 || (version[0] == 2017 && version[1] >= 2)) //2017.2 and up
|
||||
if (version >= (2017, 2)) //2017.2 and up
|
||||
{
|
||||
var m_PixelAspecRatioNum = reader.ReadUInt32();
|
||||
var m_PixelAspecRatioDen = reader.ReadUInt32();
|
||||
@@ -46,7 +46,7 @@ namespace AssetStudio
|
||||
reader.AlignStream();
|
||||
var m_AudioSampleRate = reader.ReadUInt32Array();
|
||||
var m_AudioLanguage = reader.ReadStringArray();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_VideoShadersSize = reader.ReadInt32();
|
||||
var m_VideoShaders = new PPtr<Shader>[m_VideoShadersSize];
|
||||
@@ -57,7 +57,7 @@ namespace AssetStudio
|
||||
}
|
||||
m_ExternalResources = new StreamedResource(reader);
|
||||
m_HasSplitAlpha = reader.ReadBoolean();
|
||||
if (version[0] >= 2020) //2020.1 and up
|
||||
if (version >= 2020) //2020.1 and up
|
||||
{
|
||||
var m_sRGB = reader.ReadBoolean();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
namespace AssetStudio
|
||||
{
|
||||
// Represents set with 16 base colors using ANSI escape codes, which should be supported in most terminals
|
||||
// (well, except for windows editions before windows 10)
|
||||
public static class CLIAnsiColors
|
||||
public static class ColorConsole
|
||||
{
|
||||
public static readonly string
|
||||
Black = "\u001b[30m",
|
||||
@@ -27,7 +27,7 @@ namespace AssetStudioCLI
|
||||
|
||||
public static string Color(this string str, string ansiColor)
|
||||
{
|
||||
if (!CLIWinAnsiFix.isAnsiSupported)
|
||||
if (!ColorConsoleHelper.isAnsiCodesSupported)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
@@ -35,10 +35,10 @@ namespace AssetStudioCLI
|
||||
return $"{ansiColor}{str}{Reset}";
|
||||
}
|
||||
|
||||
public static void ANSICodesTest()
|
||||
public static void AnsiCodesTest()
|
||||
{
|
||||
Console.WriteLine("ANSI escape codes test");
|
||||
Console.WriteLine($"Supported: {CLIWinAnsiFix.isAnsiSupported}");
|
||||
Console.WriteLine($"Supported: {ColorConsoleHelper.isAnsiCodesSupported}");
|
||||
Console.WriteLine("\u001b[30m A \u001b[31m B \u001b[32m C \u001b[33m D \u001b[0m");
|
||||
Console.WriteLine("\u001b[34m E \u001b[35m F \u001b[36m G \u001b[37m H \u001b[0m");
|
||||
Console.WriteLine("\u001b[30;1m A \u001b[31;1m B \u001b[32;1m C \u001b[33;1m D \u001b[0m");
|
||||
@@ -2,11 +2,11 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
namespace AssetStudio
|
||||
{
|
||||
static class CLIWinAnsiFix
|
||||
internal static class ColorConsoleHelper
|
||||
{
|
||||
public static readonly bool isAnsiSupported;
|
||||
public static readonly bool isAnsiCodesSupported;
|
||||
private const int STD_OUTPUT_HANDLE = -11;
|
||||
private const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
|
||||
|
||||
@@ -19,21 +19,21 @@ namespace AssetStudioCLI
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr GetStdHandle(int nStdHandle);
|
||||
|
||||
static CLIWinAnsiFix()
|
||||
static ColorConsoleHelper()
|
||||
{
|
||||
bool isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
var isWin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
if (isWin)
|
||||
{
|
||||
isAnsiSupported = TryEnableVTMode();
|
||||
if (!isAnsiSupported)
|
||||
isAnsiCodesSupported = TryEnableVTMode();
|
||||
if (!isAnsiCodesSupported)
|
||||
{
|
||||
//Check for bash terminal emulator. E.g., Git Bash, Cmder
|
||||
isAnsiSupported = Environment.GetEnvironmentVariable("TERM") != null;
|
||||
isAnsiCodesSupported = Environment.GetEnvironmentVariable("TERM") != null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
isAnsiSupported = true;
|
||||
isAnsiCodesSupported = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,7 @@ namespace AssetStudioCLI
|
||||
|
||||
outConsoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
|
||||
if (!SetConsoleMode(iStdOut, outConsoleMode))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return SetConsoleMode(iStdOut, outConsoleMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
149
AssetStudio/CubismModel.cs
Normal file
149
AssetStudio/CubismModel.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
AssetStudio/EndianSpanReader.cs
Normal file
29
AssetStudio/EndianSpanReader.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,10 +35,13 @@ namespace AssetStudio
|
||||
return "";
|
||||
}
|
||||
|
||||
public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767)
|
||||
public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767, Encoding encoding = null)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
int count = 0;
|
||||
if (encoding?.CodePage == 1200) //Unicode (UTF-16LE)
|
||||
return reader.ReadUnicodeStringToNull(maxLength * 2);
|
||||
|
||||
Span<byte> bytes = stackalloc byte[maxLength];
|
||||
var count = 0;
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
|
||||
{
|
||||
var b = reader.ReadByte();
|
||||
@@ -46,10 +49,28 @@ namespace AssetStudio
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes.Add(b);
|
||||
bytes[count] = b;
|
||||
count++;
|
||||
}
|
||||
return Encoding.UTF8.GetString(bytes.ToArray());
|
||||
bytes = bytes.Slice(0, count);
|
||||
return encoding?.GetString(bytes.ToArray()) ?? Encoding.UTF8.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
private static string ReadUnicodeStringToNull(this BinaryReader reader, int maxLength)
|
||||
{
|
||||
var bytes = new List<byte>();
|
||||
var count = 0;
|
||||
while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength)
|
||||
{
|
||||
var b = reader.ReadBytes(2);
|
||||
if (b.Length < 2 || (b[0] == 0 && b[1] == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
bytes.AddRange(b);
|
||||
count += 2;
|
||||
}
|
||||
return Encoding.Unicode.GetString(bytes.ToArray());
|
||||
}
|
||||
|
||||
public static Quaternion ReadQuaternion(this BinaryReader reader)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.IO;
|
||||
using static AssetStudio.EndianSpanReader;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@@ -37,66 +38,69 @@ namespace AssetStudio
|
||||
case "UnityWebData1.0":
|
||||
return FileType.WebFile;
|
||||
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))
|
||||
{
|
||||
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;
|
||||
return FileType.GZipFile;
|
||||
}
|
||||
|
||||
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()
|
||||
private bool IsSerializedFile(Span<byte> buff)
|
||||
{
|
||||
var fileSize = BaseStream.Length;
|
||||
if (fileSize < 20)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var m_MetadataSize = ReadUInt32();
|
||||
long m_FileSize = ReadUInt32();
|
||||
var m_Version = ReadUInt32();
|
||||
long m_DataOffset = ReadUInt32();
|
||||
var m_Endianess = ReadByte();
|
||||
var m_Reserved = ReadBytes(3);
|
||||
var isBigEndian = Endian == EndianType.BigEndian;
|
||||
|
||||
//var m_MetadataSize = SpanToUint32(buff, 0, isBigEndian);
|
||||
long m_FileSize = SpanToUint32(buff, 4, isBigEndian);
|
||||
var m_Version = SpanToUint32(buff, 8, isBigEndian);
|
||||
long m_DataOffset = SpanToUint32(buff, 12, isBigEndian);
|
||||
//var m_Endianess = buff[16];
|
||||
//var m_Reserved = buff.Slice(17, 3);
|
||||
if (m_Version >= 22)
|
||||
{
|
||||
if (fileSize < 48)
|
||||
{
|
||||
Position = 0;
|
||||
return false;
|
||||
}
|
||||
m_MetadataSize = ReadUInt32();
|
||||
m_FileSize = ReadInt64();
|
||||
m_DataOffset = ReadInt64();
|
||||
//m_MetadataSize = SpanToUint32(buff, 20, isBigEndian);
|
||||
m_FileSize = SpanToInt64(buff, 24, isBigEndian);
|
||||
m_DataOffset = SpanToInt64(buff, 32, isBigEndian);
|
||||
}
|
||||
Position = 0;
|
||||
if (m_FileSize != fileSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (m_DataOffset > fileSize)
|
||||
if (m_FileSize != fileSize || m_DataOffset > fileSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,15 +53,24 @@ namespace AssetStudio
|
||||
|
||||
public static FileReader DecompressGZip(FileReader reader)
|
||||
{
|
||||
using (reader)
|
||||
try
|
||||
{
|
||||
var stream = new MemoryStream();
|
||||
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
|
||||
using (reader)
|
||||
{
|
||||
gs.CopyTo(stream);
|
||||
var stream = new MemoryStream();
|
||||
using (var gs = new GZipStream(reader.BaseStream, CompressionMode.Decompress))
|
||||
{
|
||||
gs.CopyTo(stream);
|
||||
}
|
||||
stream.Position = 0;
|
||||
return new FileReader(reader.FullPath, stream);
|
||||
}
|
||||
stream.Position = 0;
|
||||
return new FileReader(reader.FullPath, stream);
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while decompressing gzip file {reader.FullPath}\r\n{e}");
|
||||
reader.Dispose();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace AssetStudio
|
||||
public BuildTarget platform;
|
||||
public SerializedFileFormatVersion m_Version;
|
||||
|
||||
public int[] version => assetsFile.version;
|
||||
public UnityVersion version => assetsFile.version;
|
||||
public BuildType buildType => assetsFile.buildType;
|
||||
|
||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo) : base(reader.BaseStream, reader.Endian)
|
||||
|
||||
@@ -7,25 +7,31 @@ namespace AssetStudio
|
||||
private bool needSearch;
|
||||
private string path;
|
||||
private SerializedFile assetsFile;
|
||||
private long offset;
|
||||
private long size;
|
||||
private BinaryReader reader;
|
||||
|
||||
public int Size { get => (int)size; }
|
||||
public 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)
|
||||
{
|
||||
needSearch = true;
|
||||
this.path = path;
|
||||
this.assetsFile = assetsFile;
|
||||
this.offset = offset;
|
||||
this.Offset = offset;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public ResourceReader(BinaryReader reader, long offset, long size)
|
||||
{
|
||||
this.reader = reader;
|
||||
this.offset = offset;
|
||||
this.Offset = offset;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@@ -52,8 +58,12 @@ namespace AssetStudio
|
||||
if (File.Exists(resourceFilePath))
|
||||
{
|
||||
needSearch = false;
|
||||
if (assetsFile.assetsManager.resourceFileReaders.TryGetValue(resourceFileName, out reader))
|
||||
{
|
||||
return reader;
|
||||
}
|
||||
reader = new BinaryReader(File.OpenRead(resourceFilePath));
|
||||
assetsFile.assetsManager.resourceFileReaders.Add(resourceFileName, reader);
|
||||
assetsFile.assetsManager.resourceFileReaders.TryAdd(resourceFileName, reader);
|
||||
return reader;
|
||||
}
|
||||
throw new FileNotFoundException($"Can't find the resource file {resourceFileName}");
|
||||
@@ -67,21 +77,27 @@ namespace AssetStudio
|
||||
public byte[] GetData()
|
||||
{
|
||||
var binaryReader = GetReader();
|
||||
binaryReader.BaseStream.Position = offset;
|
||||
return binaryReader.ReadBytes((int)size);
|
||||
lock (binaryReader)
|
||||
{
|
||||
binaryReader.BaseStream.Position = Offset;
|
||||
return binaryReader.ReadBytes((int) size);
|
||||
}
|
||||
}
|
||||
|
||||
public void GetData(byte[] buff)
|
||||
{
|
||||
var binaryReader = GetReader();
|
||||
binaryReader.BaseStream.Position = offset;
|
||||
binaryReader.Read(buff, 0, (int)size);
|
||||
lock (binaryReader)
|
||||
{
|
||||
binaryReader.BaseStream.Position = Offset;
|
||||
binaryReader.Read(buff, 0, (int) size);
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteData(string path)
|
||||
{
|
||||
var binaryReader = GetReader();
|
||||
binaryReader.BaseStream.Position = offset;
|
||||
binaryReader.BaseStream.Position = Offset;
|
||||
using (var writer = File.OpenWrite(path))
|
||||
{
|
||||
binaryReader.BaseStream.CopyTo(writer, size);
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace AssetStudio
|
||||
public string fullName;
|
||||
public string originalPath;
|
||||
public string fileName;
|
||||
public int[] version = { 0, 0, 0, 0 };
|
||||
public UnityVersion version = new UnityVersion();
|
||||
public BuildType buildType;
|
||||
public List<Object> Objects;
|
||||
public Dictionary<long, Object> ObjectsDic;
|
||||
@@ -73,7 +73,7 @@ namespace AssetStudio
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_7)
|
||||
{
|
||||
unityVersion = reader.ReadStringToNull();
|
||||
SetVersion(unityVersion);
|
||||
SetVersion(new UnityVersion(unityVersion));
|
||||
}
|
||||
if (header.m_Version >= SerializedFileFormatVersion.Unknown_8)
|
||||
{
|
||||
@@ -217,19 +217,13 @@ namespace AssetStudio
|
||||
//reader.AlignStream(16);
|
||||
}
|
||||
|
||||
public void SetVersion(string stringVersion)
|
||||
public void SetVersion(UnityVersion unityVer)
|
||||
{
|
||||
if (stringVersion != strippedVersion)
|
||||
if (unityVer != null && !unityVer.IsStripped)
|
||||
{
|
||||
unityVersion = stringVersion;
|
||||
var buildSplit = Regex.Replace(stringVersion, @"\d", "").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (buildSplit.Length == 0)
|
||||
throw new NotSupportedException("Specified Unity version is not in a correct format.\n" +
|
||||
"Specify full Unity version, including letters at the end.\n" +
|
||||
"Example: 2017.4.39f1");
|
||||
buildType = new BuildType(buildSplit[0]);
|
||||
var versionSplit = Regex.Replace(stringVersion, @"\D", ".").Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries);
|
||||
version = versionSplit.Select(int.Parse).ToArray();
|
||||
unityVersion = unityVer.FullVersion;
|
||||
buildType = new BuildType(unityVer.BuildType);
|
||||
version = unityVer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,9 +371,5 @@ namespace AssetStudio
|
||||
Objects.Add(obj);
|
||||
ObjectsDic.Add(obj.m_PathID, obj);
|
||||
}
|
||||
|
||||
public bool IsVersionStripped => unityVersion == strippedVersion;
|
||||
|
||||
private const string strippedVersion = "0.0.0";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace AssetStudio
|
||||
var readed = reader.Position - reader.byteStart;
|
||||
if (readed != reader.byteSize)
|
||||
{
|
||||
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
Logger.Info($"Failed to read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -116,7 +116,7 @@ namespace AssetStudio
|
||||
{
|
||||
append = false;
|
||||
var size = reader.ReadInt32();
|
||||
reader.ReadBytes(size);
|
||||
reader.BaseStream.Position += size;
|
||||
i += 2;
|
||||
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);
|
||||
@@ -171,13 +171,13 @@ namespace AssetStudio
|
||||
for (int i = 1; i < m_Nodes.Count; i++)
|
||||
{
|
||||
var m_Node = m_Nodes[i];
|
||||
var varNameStr = m_Node.m_Name;
|
||||
var varNameStr = m_Node.m_Name.Replace("image data", "image_data");
|
||||
obj[varNameStr] = ReadValue(m_Nodes, reader, ref i);
|
||||
}
|
||||
var readed = reader.Position - reader.byteStart;
|
||||
if (readed != reader.byteSize)
|
||||
{
|
||||
Logger.Info($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
Logger.Info($"Failed to read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
@@ -262,7 +262,13 @@ namespace AssetStudio
|
||||
case "TypelessData":
|
||||
{
|
||||
var size = reader.ReadInt32();
|
||||
value = reader.ReadBytes(size);
|
||||
var dic = new OrderedDictionary
|
||||
{
|
||||
{ "Offset", reader.BaseStream.Position },
|
||||
{ "Size", size }
|
||||
};
|
||||
value = dic;
|
||||
reader.BaseStream.Position += size;
|
||||
i += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
449
AssetStudio/UnityVersion.cs
Normal file
449
AssetStudio/UnityVersion.cs
Normal file
@@ -0,0 +1,449 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>net472;net6.0;net7.0</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0;net7.0;net8.0</TargetFrameworks>
|
||||
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
||||
<AssemblyName>AssetStudioModCLI</AssemblyName>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © Perfare; Copyright © aelurum 2023</Copyright>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare; Copyright © aelurum 2023-2024</Copyright>
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
<Target Name="CopyExtraFilesPortable" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||
<Message Text="Copying windows extra files for $(TargetFramework)... " Importance="high" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
@@ -32,6 +34,9 @@
|
||||
|
||||
<Target Name="CopyExtraFilesPortableNet" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||
<Message Text="Copying other platforms extra files for $(TargetFramework)... " Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-arm64\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x86\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\osx-x64\libfmod.dylib" DestinationFolder="$(TargetDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
@@ -42,6 +47,8 @@
|
||||
The dll is cross-platform while the executable isn't -->
|
||||
<Target Name="PublishExtraFilesPortable" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' ">
|
||||
<Message Text="Publishing windows extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x64\native\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)runtimes\win-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\win-x86\native\fmod.dll" DestinationFolder="$(PublishDir)runtimes\win-x86\native" ContinueOnError="false" />
|
||||
@@ -50,6 +57,9 @@
|
||||
|
||||
<Target Name="PublishExtraFilesPortableNet" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == '' AND '$(TargetFramework)' != 'net472' ">
|
||||
<Message Text="Publishing other platforms extra files for Portable build ($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-arm64\native\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)runtimes\osx-arm64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x86\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x86\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\linux-x64\native\libfmod.so" DestinationFolder="$(PublishDir)runtimes\linux-x64\native" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)runtimes\osx-x64\native\libfmod.dylib" DestinationFolder="$(PublishDir)runtimes\osx-x64\native" ContinueOnError="false" />
|
||||
@@ -58,39 +68,46 @@
|
||||
|
||||
<Target Name="CopyExtraFilesWin86" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x86' ">
|
||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\Win32\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\Win32\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x86\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyExtraFilesWin64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'win-x64' ">
|
||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(SolutionDir)AssetStudioFBXNative\bin\x64\$(Configuration)\AssetStudioFBXNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(SolutionDir)Texture2DDecoderNative\bin\x64\$(Configuration)\Texture2DDecoderNative.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\win-x64\fmod.dll" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishExtraFilesWin" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('win-x')) ">
|
||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)\AssetStudioFBXNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\Texture2DDecoderNative.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\fmod.dll" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyExtraFilesLinux64" AfterTargets="AfterBuild" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libAssetStudioFBXNative.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\linux-x64\libfmod.so" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishExtraFilesLinux64" AfterTargets="Publish" Condition=" '$(RuntimeIdentifier)' == 'linux-x64' ">
|
||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)\libAssetStudioFBXNative.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\libfmod.so" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CopyExtraFilesMac" AfterTargets="AfterBuild" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||
<Message Text="Copying extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libAssetStudioFBXNative.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(ProjectDir)Libraries\$(RuntimeIdentifier)\libfmod.dylib" DestinationFolder="$(TargetDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishExtraFilesMac" AfterTargets="Publish" Condition=" $(RuntimeIdentifier.Contains('osx-')) ">
|
||||
<Message Text="Publishing extra files for $(RuntimeIdentifier)($(TargetFramework))... " Importance="high" />
|
||||
<Copy SourceFiles="$(TargetDir)\libAssetStudioFBXNative.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
<Copy SourceFiles="$(TargetDir)\libfmod.dylib" DestinationFolder="$(PublishDir)" ContinueOnError="false" />
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
@@ -16,19 +17,28 @@ namespace AssetStudioCLI
|
||||
|
||||
internal class CLILogger : ILogger
|
||||
{
|
||||
private readonly LogOutputMode logOutput;
|
||||
private readonly LoggerEvent logMinLevel;
|
||||
public string LogName;
|
||||
public string LogPath;
|
||||
|
||||
private static BlockingCollection<string> logMessageCollection = new BlockingCollection<string>();
|
||||
private readonly LogOutputMode logOutput;
|
||||
private readonly LoggerEvent logMinLevel;
|
||||
|
||||
public CLILogger()
|
||||
{
|
||||
logOutput = CLIOptions.o_logOutput.Value;
|
||||
logMinLevel = CLIOptions.o_logLevel.Value;
|
||||
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
LogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
||||
LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LogName);
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||
|
||||
if (logOutput != LogOutputMode.Console)
|
||||
{
|
||||
ConcurrentFileWriter();
|
||||
}
|
||||
|
||||
LogToFile(LoggerEvent.Verbose, $"---{appAssembly.Name} v{appAssembly.Version} [{arch}] | Logger launched---\n" +
|
||||
$"CMD Args: {string.Join(" ", CLIOptions.cliArgs)}");
|
||||
@@ -36,15 +46,15 @@ namespace AssetStudioCLI
|
||||
|
||||
private static string ColorLogLevel(LoggerEvent logLevel)
|
||||
{
|
||||
string formattedLevel = $"[{logLevel}]";
|
||||
var formattedLevel = $"[{logLevel}]";
|
||||
switch (logLevel)
|
||||
{
|
||||
case LoggerEvent.Info:
|
||||
return $"{formattedLevel.Color(CLIAnsiColors.BrightCyan)}";
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightCyan)}";
|
||||
case LoggerEvent.Warning:
|
||||
return $"{formattedLevel.Color(CLIAnsiColors.BrightYellow)}";
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightYellow)}";
|
||||
case LoggerEvent.Error:
|
||||
return $"{formattedLevel.Color(CLIAnsiColors.BrightRed)}";
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightRed)}";
|
||||
default:
|
||||
return formattedLevel;
|
||||
}
|
||||
@@ -54,16 +64,16 @@ namespace AssetStudioCLI
|
||||
{
|
||||
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
message = message.TrimEnd();
|
||||
var multiLine = message.Contains('\n');
|
||||
var multiLine = message.Contains("\n");
|
||||
|
||||
string formattedMessage;
|
||||
if (consoleMode)
|
||||
{
|
||||
string colorLogLevel = ColorLogLevel(logMsgLevel);
|
||||
var colorLogLevel = ColorLogLevel(logMsgLevel);
|
||||
formattedMessage = $"{colorLogLevel} {message}";
|
||||
if (multiLine)
|
||||
{
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ");
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ") + $"\n{colorLogLevel}";
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -73,7 +83,7 @@ namespace AssetStudioCLI
|
||||
formattedMessage = $"{curTime} | {logLevel} | {message}";
|
||||
if (multiLine)
|
||||
{
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ");
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ") + $"\n{curTime} | {logLevel} |";
|
||||
}
|
||||
}
|
||||
return formattedMessage;
|
||||
@@ -87,15 +97,27 @@ namespace AssetStudioCLI
|
||||
}
|
||||
}
|
||||
|
||||
public async void LogToFile(LoggerEvent logMsgLevel, string message)
|
||||
public void LogToFile(LoggerEvent logMsgLevel, string message)
|
||||
{
|
||||
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))
|
||||
{
|
||||
await sw.WriteLineAsync(FormatMessage(logMsgLevel, message));
|
||||
sw.AutoFlush = true;
|
||||
foreach (var msg in logMessageCollection.GetConsumingEnumerable())
|
||||
{
|
||||
sw.WriteLine(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Log(LoggerEvent logMsgLevel, string message, bool ignoreLevel)
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace AssetStudioCLI
|
||||
public ClassIDType Type;
|
||||
public string Text;
|
||||
public string UniqueID;
|
||||
public GameObjectNode Node;
|
||||
|
||||
public AssetItem(Object asset)
|
||||
{
|
||||
|
||||
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
16
AssetStudioCLI/Components/BaseNode.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal class BaseNode
|
||||
{
|
||||
public List<BaseNode> nodes = new List<BaseNode>();
|
||||
public string FullPath = "";
|
||||
public readonly string Text;
|
||||
|
||||
public BaseNode(string name)
|
||||
{
|
||||
Text = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
14
AssetStudioCLI/Components/GameObjectNode.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using AssetStudio;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
internal class GameObjectNode : BaseNode
|
||||
{
|
||||
public GameObject gameObject;
|
||||
|
||||
public GameObjectNode(GameObject gameObject) : base(gameObject.m_Name)
|
||||
{
|
||||
this.gameObject = gameObject;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -9,110 +10,6 @@ namespace AssetStudioCLI
|
||||
{
|
||||
internal static class Exporter
|
||||
{
|
||||
public static bool ExportTexture2D(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_Texture2D = (Texture2D)item.Asset;
|
||||
if (CLIOptions.convertTexture)
|
||||
{
|
||||
var type = CLIOptions.o_imageFormat.Value;
|
||||
if (!TryExportFile(exportPath, item, "." + type.ToString().ToLower(), out var exportFullPath))
|
||||
return false;
|
||||
|
||||
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"Converting \"{m_Texture2D.m_Name}\" to {type}..");
|
||||
sb.AppendLine($"Width: {m_Texture2D.m_Width}");
|
||||
sb.AppendLine($"Height: {m_Texture2D.m_Height}");
|
||||
sb.AppendLine($"Format: {m_Texture2D.m_TextureFormat}");
|
||||
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
||||
{
|
||||
case 0: sb.AppendLine("Filter Mode: Point "); break;
|
||||
case 1: sb.AppendLine("Filter Mode: Bilinear "); break;
|
||||
case 2: sb.AppendLine("Filter Mode: Trilinear "); break;
|
||||
}
|
||||
sb.AppendLine($"Anisotropic level: {m_Texture2D.m_TextureSettings.m_Aniso}");
|
||||
sb.AppendLine($"Mip map bias: {m_Texture2D.m_TextureSettings.m_MipBias}");
|
||||
switch (m_Texture2D.m_TextureSettings.m_WrapMode)
|
||||
{
|
||||
case 0: sb.AppendLine($"Wrap mode: Repeat"); break;
|
||||
case 1: sb.AppendLine($"Wrap mode: Clamp"); break;
|
||||
}
|
||||
Logger.Debug(sb.ToString());
|
||||
}
|
||||
|
||||
var image = m_Texture2D.ConvertToImage(flip: true);
|
||||
if (image == null)
|
||||
{
|
||||
Logger.Error($"Export error. Failed to convert texture \"{m_Texture2D.m_Name}\" into image");
|
||||
return false;
|
||||
}
|
||||
using (image)
|
||||
{
|
||||
using (var file = File.OpenWrite(exportFullPath))
|
||||
{
|
||||
image.WriteToStream(file, type);
|
||||
}
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".tex", out var exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, m_Texture2D.image_data.GetData());
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ExportAudioClip(AssetItem item, string exportPath)
|
||||
{
|
||||
string exportFullPath;
|
||||
var m_AudioClip = (AudioClip)item.Asset;
|
||||
var m_AudioData = m_AudioClip.m_AudioData.GetData();
|
||||
if (m_AudioData == null || m_AudioData.Length == 0)
|
||||
{
|
||||
Logger.Error($"Export error. \"{item.Text}\": AudioData was not found");
|
||||
return false;
|
||||
}
|
||||
var converter = new AudioClipConverter(m_AudioClip);
|
||||
if (CLIOptions.o_audioFormat.Value != AudioFormat.None && converter.IsSupport)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".wav", out exportFullPath))
|
||||
return false;
|
||||
|
||||
if (CLIOptions.o_logLevel.Value <= LoggerEvent.Debug)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine($"Converting \"{m_AudioClip.m_Name}\" to wav..");
|
||||
sb.AppendLine(m_AudioClip.version[0] < 5 ? $"AudioClip type: {m_AudioClip.m_Type}" : $"AudioClip compression format: {m_AudioClip.m_CompressionFormat}");
|
||||
sb.AppendLine($"AudioClip channel count: {m_AudioClip.m_Channels}");
|
||||
sb.AppendLine($"AudioClip sample rate: {m_AudioClip.m_Frequency}");
|
||||
sb.AppendLine($"AudioClip bit depth: {m_AudioClip.m_BitsPerSample}");
|
||||
Logger.Debug(sb.ToString());
|
||||
}
|
||||
|
||||
var buffer = converter.ConvertToWav(m_AudioData);
|
||||
if (buffer == null)
|
||||
{
|
||||
Logger.Error($"Export error. \"{item.Text}\": Failed to convert to Wav");
|
||||
return false;
|
||||
}
|
||||
File.WriteAllBytes(exportFullPath, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, converter.GetExtensionName(), out exportFullPath))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, m_AudioData);
|
||||
}
|
||||
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportVideoClip(AssetItem item, string exportPath)
|
||||
{
|
||||
var m_VideoClip = (VideoClip)item.Asset;
|
||||
@@ -232,31 +129,36 @@ namespace AssetStudioCLI
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool ExportSprite(AssetItem item, string exportPath)
|
||||
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||
{
|
||||
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);
|
||||
}
|
||||
Logger.Debug($"{item.TypeString} \"{item.Text}\" exported to \"{exportFullPath}\"");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
var convert = animationList != null
|
||||
? new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||
: new ModelConverter(gameObject, CLIOptions.o_imageFormat.Value);
|
||||
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
||||
ExportFbx(convert, exportPath);
|
||||
}
|
||||
|
||||
private static void ExportFbx(IImported convert, string exportPath)
|
||||
{
|
||||
var eulerFilter = true;
|
||||
var filterPrecision = 0.25f;
|
||||
var exportAllNodes = true;
|
||||
var exportSkins = true;
|
||||
var exportAnimations = true;
|
||||
var exportBlendShape = true;
|
||||
var castToBone = false;
|
||||
var boneSize = CLIOptions.o_fbxBoneSize.Value;
|
||||
var exportAllUvsAsDiffuseMaps = false;
|
||||
var scaleFactor = CLIOptions.o_fbxScaleFactor.Value;
|
||||
var fbxVersion = 3;
|
||||
var fbxFormat = 0;
|
||||
ModelExporter.ExportFbx(exportPath, convert, eulerFilter, filterPrecision,
|
||||
exportAllNodes, exportSkins, exportAnimations, exportBlendShape, castToBone, boneSize, exportAllUvsAsDiffuseMaps, scaleFactor, fbxVersion, fbxFormat == 1);
|
||||
}
|
||||
|
||||
public static bool ExportRawFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw"))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||
|
||||
@@ -266,7 +168,7 @@ namespace AssetStudioCLI
|
||||
|
||||
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump"))
|
||||
return false;
|
||||
var str = item.Asset.Dump();
|
||||
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
||||
@@ -274,6 +176,10 @@ namespace AssetStudioCLI
|
||||
var m_Type = m_MonoBehaviour.ConvertToTypeTree(Studio.assemblyLoader);
|
||||
str = m_MonoBehaviour.Dump(m_Type);
|
||||
}
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
str = item.Asset.DumpObject();
|
||||
}
|
||||
if (str != null)
|
||||
{
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
@@ -283,22 +189,35 @@ namespace AssetStudioCLI
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string mode = "Export")
|
||||
{
|
||||
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 (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
if (filenameFormat == FilenameFormat.AssetName)
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Logger.Error($"Export error. File \"{fullPath.Color(CLIAnsiColors.BrightRed)}\" already exist");
|
||||
Logger.Error($"{mode} error. File \"{fullPath.Color(ColorConsole.BrightRed)}\" already exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -404,9 +323,10 @@ namespace AssetStudioCLI
|
||||
switch (item.Type)
|
||||
{
|
||||
case ClassIDType.Texture2D:
|
||||
return ExportTexture2D(item, exportPath);
|
||||
case ClassIDType.Texture2DArray:
|
||||
case ClassIDType.Sprite:
|
||||
case ClassIDType.AudioClip:
|
||||
return ExportAudioClip(item, exportPath);
|
||||
throw new System.NotImplementedException();
|
||||
case ClassIDType.VideoClip:
|
||||
return ExportVideoClip(item, exportPath);
|
||||
case ClassIDType.MovieTexture:
|
||||
@@ -419,8 +339,6 @@ namespace AssetStudioCLI
|
||||
return ExportMonoBehaviour(item, exportPath);
|
||||
case ClassIDType.Font:
|
||||
return ExportFont(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
return ExportSprite(item, exportPath);
|
||||
case ClassIDType.Mesh:
|
||||
return ExportMesh(item, exportPath);
|
||||
default:
|
||||
@@ -430,8 +348,9 @@ namespace AssetStudioCLI
|
||||
|
||||
public static string FixFileName(string str)
|
||||
{
|
||||
if (str.Length >= 260) return Path.GetRandomFileName();
|
||||
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
return str.Length >= 260
|
||||
? Path.GetRandomFileName()
|
||||
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
BIN
AssetStudioCLI/Libraries/linux-x64/libAssetStudioFBXNative.so
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-arm64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
BIN
AssetStudioCLI/Libraries/osx-x64/libAssetStudioFBXNative.dylib
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -4,15 +4,17 @@
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public string Example { get; }
|
||||
public T Value { get; set; }
|
||||
public T DefaultValue { get; }
|
||||
public HelpGroups HelpGroup { get; }
|
||||
public bool IsFlag { get; }
|
||||
|
||||
public Option(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag)
|
||||
public Option(T optionDefaultValue, string optionName, string optionDescription, string optionExample, HelpGroups optionHelpGroup, bool isFlag)
|
||||
{
|
||||
Name = optionName;
|
||||
Description = optionDescription;
|
||||
Example = optionExample;
|
||||
DefaultValue = optionDefaultValue;
|
||||
Value = DefaultValue;
|
||||
HelpGroup = optionHelpGroup;
|
||||
|
||||
@@ -4,14 +4,14 @@ namespace AssetStudioCLI.Options
|
||||
{
|
||||
internal static class OptionExtensions
|
||||
{
|
||||
public static Action<string, string, HelpGroups, bool> OptionGrouping = (name, desc, group, isFlag) => { };
|
||||
public static Action<string, string, string, HelpGroups, bool> OptionGrouping = (name, desc, example, group, isFlag) => { };
|
||||
}
|
||||
|
||||
internal class GroupedOption<T> : Option<T>
|
||||
{
|
||||
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionHelpGroup, isFlag)
|
||||
public GroupedOption(T optionDefaultValue, string optionName, string optionDescription, string optionExample, HelpGroups optionHelpGroup, bool isFlag = false) : base(optionDefaultValue, optionName, optionDescription, optionExample, optionHelpGroup, isFlag)
|
||||
{
|
||||
OptionExtensions.OptionGrouping(optionName, optionDescription, optionHelpGroup, isFlag);
|
||||
OptionExtensions.OptionGrouping(optionName, optionDescription, optionExample, optionHelpGroup, isFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
223
AssetStudioCLI/ParallelExporter.cs
Normal file
223
AssetStudioCLI/ParallelExporter.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,9 +35,9 @@ namespace AssetStudioCLI
|
||||
if (Studio.LoadAssets())
|
||||
{
|
||||
Studio.ParseAssets();
|
||||
if (CLIOptions.filterBy != FilterBy.None && CLIOptions.o_workMode.Value != WorkMode.ExportLive2D)
|
||||
if (CLIOptions.filterBy != FilterBy.None)
|
||||
{
|
||||
Studio.FilterAssets();
|
||||
Studio.Filter();
|
||||
}
|
||||
if (CLIOptions.o_exportAssetList.Value != ExportListType.None)
|
||||
{
|
||||
@@ -48,9 +48,12 @@ namespace AssetStudioCLI
|
||||
case WorkMode.Info:
|
||||
Studio.ShowExportableAssetsInfo();
|
||||
break;
|
||||
case WorkMode.ExportLive2D:
|
||||
case WorkMode.Live2D:
|
||||
Studio.ExportLive2D();
|
||||
break;
|
||||
case WorkMode.SplitObjects:
|
||||
Studio.ExportSplitObjects();
|
||||
break;
|
||||
default:
|
||||
Studio.ExportAssets();
|
||||
break;
|
||||
|
||||
@@ -1,49 +1,62 @@
|
||||
## AssetStudioModCLI
|
||||
CLI version of AssetStudioMod.
|
||||
- Supported asset types: `Texture2D`, `Sprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`.
|
||||
- Supported asset types for export: `Texture2D`, `Sprite`, `TextAsset`, `MonoBehaviour`, `Font`, `Shader`, `MovieTexture`, `AudioClip`, `VideoClip`, `Mesh`.
|
||||
- *There are no plans to add support for `AnimationClip`, `Animator` for now.*
|
||||
|
||||
### Usage
|
||||
```
|
||||
AssetStudioModCLI <input path to asset file/folder> [-m, --mode <value>]
|
||||
[-t, --asset-type <value(s)>] [-g, --group-option <value>]
|
||||
[-o, --output <path>] [-h, --help]
|
||||
[--log-level <value>] [--log-output <value>]
|
||||
[--image-format <value>] [--audio-format <value>]
|
||||
[--export-asset-list <value>] [--filter-by-name <text>]
|
||||
[-f, --filename-format <value>] [-o, --output <path>]
|
||||
[-h, --help] [--log-level <value>]
|
||||
[--log-output <value>] [--image-format <value>]
|
||||
[--audio-format <value>] [--l2d-motion-mode <value>]
|
||||
[--l2d-force-bezier] [--fbx-scale-factor <value>]
|
||||
[--fbx-bone-size <value>] [--filter-by-name <text>]
|
||||
[--filter-by-container <text>] [--filter-by-pathid <text>]
|
||||
[--filter-by-text <text>] [--assembly-folder <path>]
|
||||
[--unity-version <text>] [--not-restore-extension]
|
||||
|
||||
[--filter-by-text <text>] [--custom-compression <value>]
|
||||
[--max-export-tasks <value>] [--export-asset-list <value>]
|
||||
[--assembly-folder <path>] [--unity-version <text>]
|
||||
[--not-restore-extension] [--avoid-typetree-loading]
|
||||
[--load-all]
|
||||
|
||||
General Options:
|
||||
-m, --mode <value> Specify working mode
|
||||
<Value: export(default) | exportRaw | dump | info | live2d>
|
||||
<Value: export(default) | exportRaw | dump | info | live2d | splitObjects>
|
||||
Export - Exports converted assets
|
||||
ExportRaw - Exports raw data
|
||||
Dump - Makes asset dumps
|
||||
Info - Loads file(s), shows the number of available for export assets and exits
|
||||
Live2D - Exports Live2D Cubism 3 models
|
||||
Live2D - Exports Live2D Cubism models
|
||||
SplitObjects - Exports split objects (fbx)
|
||||
Example: "-m info"
|
||||
|
||||
-t, --asset-type <value(s)> Specify asset type(s) to export
|
||||
<Value(s): tex2d, sprite, textAsset, monoBehaviour, font, shader, movieTexture,
|
||||
audio, video, mesh | all(default)>
|
||||
<Value(s): tex2d, tex2dArray, sprite, textAsset, monoBehaviour, font, shader
|
||||
movieTexture, audio, video, mesh | all(default)>
|
||||
All - export all asset types, which are listed in the values
|
||||
*To specify multiple asset types, write them separated by ',' or ';' without spaces
|
||||
Examples: "-t sprite" or "-t tex2d,sprite,audio" or "-t tex2d;sprite;font"
|
||||
|
||||
-g, --group-option <value> Specify the way in which exported assets should be grouped
|
||||
<Value: none | type | container(default) | containerFull | filename>
|
||||
<Value: none | type | container(default) | containerFull | filename | sceneHierarchy>
|
||||
None - Do not group exported assets
|
||||
Type - Group exported assets by type name
|
||||
Container - Group exported assets by container path
|
||||
ContainerFull - Group exported assets by full container path (e.g. with prefab name)
|
||||
SceneHierarchy - Group exported assets by their node path in scene hierarchy
|
||||
Filename - Group exported assets by source file name
|
||||
Example: "-g container"
|
||||
Example: "-g containerFull"
|
||||
|
||||
-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
|
||||
If path isn't specifyed, '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
|
||||
|
||||
-h, --help Display help and exit
|
||||
|
||||
@@ -62,17 +75,32 @@ Convert Options:
|
||||
None - Do not convert images and export them as texture data (.tex)
|
||||
Example: "--image-format jpg"
|
||||
|
||||
--audio-format <value> Specify the format for converting audio assets
|
||||
--audio-format <value> Specify the format for converting FMOD audio assets
|
||||
<Value: none | wav(default)>
|
||||
None - Do not convert audios and export them in their own format
|
||||
None - Do not convert fmod audios and export them in their own format
|
||||
Example: "--audio-format wav"
|
||||
|
||||
Advanced Options:
|
||||
--export-asset-list <value> Specify the format in which you want to export asset list
|
||||
<Value: none(default) | xml>
|
||||
None - Do not export asset list
|
||||
Example: "--export-asset-list xml"
|
||||
Live2D Options:
|
||||
--l2d-motion-mode <value> Specify Live2D motion export mode
|
||||
<Value: monoBehaviour(default) | animationClip>
|
||||
MonoBehaviour - Try to export motions from MonoBehaviour Fade motions
|
||||
If no Fade motions are found, the AnimationClip method will be used
|
||||
AnimationClip - Try to export motions using AnimationClip assets
|
||||
Example: "--l2d-motion-mode animationClip"
|
||||
|
||||
--l2d-force-bezier (Flag) If specified, Linear motion segments will be calculated as Bezier segments
|
||||
(May help if the exported motions look jerky/not smooth enough)
|
||||
|
||||
FBX Options:
|
||||
--fbx-scale-factor <value> Specify the FBX Scale Factor
|
||||
<Value: float number from 0 to 100 (default=1)>
|
||||
Example: "--fbx-scale-factor 50"
|
||||
|
||||
--fbx-bone-size <value> Specify the FBX Bone Size
|
||||
<Value: integer number from 0 to 100 (default=10)>
|
||||
Example: "--fbx-bone-size 10"
|
||||
|
||||
Filter Options:
|
||||
--filter-by-name <text> Specify the name by which assets should be filtered
|
||||
*To specify multiple names write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-name char" or "--filter-by-name char,bg"
|
||||
@@ -90,8 +118,35 @@ Advanced Options:
|
||||
*To specify multiple values write them separated by ',' or ';' without spaces
|
||||
Example: "--filter-by-text portrait" or "--filter-by-text portrait,art"
|
||||
|
||||
|
||||
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
|
||||
<Value: none(default) | xml>
|
||||
None - Do not export asset list
|
||||
Example: "--export-asset-list xml"
|
||||
|
||||
--assembly-folder <path> Specify the path to the assembly folder
|
||||
--unity-version <text> Specify Unity version. Example: "--unity-version 2017.4.39f1"
|
||||
|
||||
--unity-version <text> Specify Unity version
|
||||
Example: "--unity-version 2017.4.39f1"
|
||||
|
||||
--not-restore-extension (Flag) If specified, AssetStudio will not try to use/restore original TextAsset
|
||||
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
|
||||
using their type tree
|
||||
|
||||
--load-all (Flag) If specified, AssetStudio will load assets of all types
|
||||
(Only for Dump, Info and ExportRaw modes)
|
||||
```
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
using AssetStudio;
|
||||
using AssetStudioCLI.Options;
|
||||
using CubismLive2DExtractor;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using static AssetStudioCLI.Exporter;
|
||||
using static CubismLive2DExtractor.Live2DExtractor;
|
||||
using Ansi = AssetStudioCLI.CLIAnsiColors;
|
||||
using Ansi = AssetStudio.ColorConsole;
|
||||
|
||||
namespace AssetStudioCLI
|
||||
{
|
||||
@@ -15,7 +18,9 @@ namespace AssetStudioCLI
|
||||
{
|
||||
public static AssetsManager assetsManager = new AssetsManager();
|
||||
public static List<AssetItem> parsedAssetsList = new List<AssetItem>();
|
||||
public static List<BaseNode> gameObjectTree = new List<BaseNode>();
|
||||
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>();
|
||||
|
||||
static Studio()
|
||||
@@ -32,8 +37,12 @@ namespace AssetStudioCLI
|
||||
{
|
||||
var isLoaded = false;
|
||||
assetsManager.SpecifyUnityVersion = CLIOptions.o_unityVersion.Value;
|
||||
assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value);
|
||||
|
||||
assetsManager.ZstdEnabled = CLIOptions.o_customCompressionType.Value == CustomCompressionType.Zstd;
|
||||
assetsManager.LoadingViaTypeTreeEnabled = !CLIOptions.f_avoidLoadingViaTypetree.Value;
|
||||
if (!CLIOptions.f_loadAllAssets.Value)
|
||||
{
|
||||
assetsManager.SetAssetFilter(CLIOptions.o_exportAssetTypes.Value);
|
||||
}
|
||||
assetsManager.LoadFilesAndFolders(CLIOptions.inputPath);
|
||||
if (assetsManager.assetsFileList.Count == 0)
|
||||
{
|
||||
@@ -52,28 +61,42 @@ namespace AssetStudioCLI
|
||||
Logger.Info("Parse assets...");
|
||||
|
||||
var fileAssetsList = new List<AssetItem>();
|
||||
var tex2dArrayAssetList = new List<AssetItem>();
|
||||
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||
var objectAssetItemDic = new Dictionary<AssetStudio.Object, AssetItem>(objectCount);
|
||||
|
||||
Progress.Reset();
|
||||
var i = 0;
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
var preloadTable = Array.Empty<PPtr<AssetStudio.Object>>();
|
||||
foreach (var asset in assetsFile.Objects)
|
||||
{
|
||||
var assetItem = new AssetItem(asset);
|
||||
objectAssetItemDic.Add(asset, assetItem);
|
||||
assetItem.UniqueID = "_#" + i;
|
||||
var isExportable = false;
|
||||
switch (asset)
|
||||
{
|
||||
case PreloadData m_PreloadData:
|
||||
preloadTable = m_PreloadData.m_Assets;
|
||||
break;
|
||||
case AssetBundle m_AssetBundle:
|
||||
var isStreamedSceneAssetBundle = m_AssetBundle.m_IsStreamedSceneAssetBundle;
|
||||
if (!isStreamedSceneAssetBundle)
|
||||
{
|
||||
preloadTable = m_AssetBundle.m_PreloadTable;
|
||||
}
|
||||
assetItem.Text = string.IsNullOrEmpty(m_AssetBundle.m_AssetBundleName) ? m_AssetBundle.m_Name : m_AssetBundle.m_AssetBundleName;
|
||||
|
||||
foreach (var m_Container in m_AssetBundle.m_Container)
|
||||
{
|
||||
var preloadIndex = m_Container.Value.preloadIndex;
|
||||
var preloadSize = m_Container.Value.preloadSize;
|
||||
var preloadSize = isStreamedSceneAssetBundle ? preloadTable.Length : m_Container.Value.preloadSize;
|
||||
var preloadEnd = preloadIndex + preloadSize;
|
||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||
for (var k = preloadIndex; k < preloadEnd; k++)
|
||||
{
|
||||
var pptr = m_AssetBundle.m_PreloadTable[k];
|
||||
var pptr = preloadTable[k];
|
||||
if (pptr.TryGet(out var obj))
|
||||
{
|
||||
containers[obj] = m_Container.Key;
|
||||
@@ -95,6 +118,12 @@ namespace AssetStudioCLI
|
||||
assetItem.FullSize = asset.byteSize + m_Texture2D.m_StreamData.size;
|
||||
assetItem.Text = m_Texture2D.m_Name;
|
||||
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:
|
||||
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
|
||||
assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
|
||||
@@ -105,34 +134,41 @@ namespace AssetStudioCLI
|
||||
assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size;
|
||||
assetItem.Text = m_VideoClip.m_Name;
|
||||
break;
|
||||
case Mesh _:
|
||||
case MovieTexture _:
|
||||
case TextAsset _:
|
||||
case Font _:
|
||||
case Sprite _:
|
||||
assetItem.Text = ((NamedObject)asset).m_Name;
|
||||
break;
|
||||
case Shader m_Shader:
|
||||
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
||||
break;
|
||||
case MonoBehaviour m_MonoBehaviour:
|
||||
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||
var assetName = m_MonoBehaviour.m_Name;
|
||||
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||
{
|
||||
assetItem.Text = m_Script.m_ClassName;
|
||||
assetName = assetName == "" ? m_Script.m_ClassName : assetName;
|
||||
if (m_Script.m_ClassName == "CubismMoc")
|
||||
{
|
||||
cubismMocList.Add(m_MonoBehaviour);
|
||||
}
|
||||
}
|
||||
else
|
||||
assetItem.Text = assetName;
|
||||
break;
|
||||
case GameObject m_GameObject:
|
||||
assetItem.Text = m_GameObject.m_Name;
|
||||
break;
|
||||
case Animator m_Animator:
|
||||
if (m_Animator.m_GameObject.TryGet(out var gameObject))
|
||||
{
|
||||
assetItem.Text = m_MonoBehaviour.m_Name;
|
||||
assetItem.Text = gameObject.m_Name;
|
||||
}
|
||||
break;
|
||||
case NamedObject m_NamedObject:
|
||||
assetItem.Text = m_NamedObject.m_Name;
|
||||
break;
|
||||
}
|
||||
if (assetItem.Text == "")
|
||||
if (string.IsNullOrEmpty(assetItem.Text))
|
||||
{
|
||||
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
||||
}
|
||||
|
||||
isExportable = CLIOptions.o_exportAssetTypes.Value.Contains(asset.type);
|
||||
if (isExportable)
|
||||
if (isExportable || (CLIOptions.f_loadAllAssets.Value && CLIOptions.o_exportAssetTypes.Value == CLIOptions.o_exportAssetTypes.DefaultValue))
|
||||
{
|
||||
fileAssetsList.Add(assetItem);
|
||||
}
|
||||
@@ -141,22 +177,38 @@ namespace AssetStudioCLI
|
||||
}
|
||||
foreach (var asset in fileAssetsList)
|
||||
{
|
||||
if (containers.ContainsKey(asset.Asset))
|
||||
if (containers.TryGetValue(asset.Asset, out var container))
|
||||
{
|
||||
asset.Container = containers[asset.Asset];
|
||||
asset.Container = container;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
parsedAssetsList.AddRange(fileAssetsList);
|
||||
fileAssetsList.Clear();
|
||||
if (CLIOptions.o_workMode.Value != WorkMode.ExportLive2D)
|
||||
tex2dArrayAssetList.Clear();
|
||||
if (CLIOptions.o_workMode.Value != WorkMode.Live2D)
|
||||
{
|
||||
containers.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (CLIOptions.o_workMode.Value == WorkMode.SplitObjects || CLIOptions.o_groupAssetsBy.Value == AssetGroupOption.SceneHierarchy)
|
||||
{
|
||||
BuildTreeStructure(objectAssetItemDic);
|
||||
}
|
||||
|
||||
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {parsedAssetsList.Count} exportable assets";
|
||||
var unityVer = assetsManager.assetsFileList[0].version;
|
||||
long m_ObjectsCount;
|
||||
if (unityVer[0] > 2020)
|
||||
if (unityVer > 2020)
|
||||
{
|
||||
m_ObjectsCount = assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y =>
|
||||
y.classID != (int)ClassIDType.Shader
|
||||
@@ -175,6 +227,99 @@ namespace AssetStudioCLI
|
||||
Logger.Info(log);
|
||||
}
|
||||
|
||||
public static void BuildTreeStructure(Dictionary<AssetStudio.Object, AssetItem> objectAssetItemDic)
|
||||
{
|
||||
Logger.Info("Building tree structure...");
|
||||
|
||||
var treeNodeDictionary = new Dictionary<GameObject, GameObjectNode>();
|
||||
var assetsFileCount = assetsManager.assetsFileList.Count;
|
||||
int j = 0;
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
var fileNode = new BaseNode(assetsFile.fileName); //RootNode
|
||||
|
||||
foreach (var obj in assetsFile.Objects)
|
||||
{
|
||||
if (obj is GameObject m_GameObject)
|
||||
{
|
||||
if (!treeNodeDictionary.TryGetValue(m_GameObject, out var currentNode))
|
||||
{
|
||||
currentNode = new GameObjectNode(m_GameObject);
|
||||
treeNodeDictionary.Add(m_GameObject, currentNode);
|
||||
}
|
||||
|
||||
foreach (var pptr in m_GameObject.m_Components)
|
||||
{
|
||||
if (pptr.TryGet(out var m_Component))
|
||||
{
|
||||
objectAssetItemDic[m_Component].Node = currentNode;
|
||||
if (m_Component is MeshFilter m_MeshFilter)
|
||||
{
|
||||
if (m_MeshFilter.m_Mesh.TryGet(out var m_Mesh))
|
||||
{
|
||||
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||
}
|
||||
}
|
||||
else if (m_Component is SkinnedMeshRenderer m_SkinnedMeshRenderer)
|
||||
{
|
||||
if (m_SkinnedMeshRenderer.m_Mesh.TryGet(out var m_Mesh))
|
||||
{
|
||||
objectAssetItemDic[m_Mesh].Node = currentNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var parentNode = fileNode;
|
||||
if (m_GameObject.m_Transform != null)
|
||||
{
|
||||
if (m_GameObject.m_Transform.m_Father.TryGet(out var m_Father))
|
||||
{
|
||||
if (m_Father.m_GameObject.TryGet(out var parentGameObject))
|
||||
{
|
||||
if (!treeNodeDictionary.TryGetValue(parentGameObject, out var parentGameObjectNode))
|
||||
{
|
||||
parentGameObjectNode = new GameObjectNode(parentGameObject);
|
||||
treeNodeDictionary.Add(parentGameObject, parentGameObjectNode);
|
||||
}
|
||||
parentNode = parentGameObjectNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
parentNode.nodes.Add(currentNode);
|
||||
}
|
||||
}
|
||||
|
||||
if (fileNode.nodes.Count > 0)
|
||||
{
|
||||
GenerateFullPath(fileNode, fileNode.Text);
|
||||
gameObjectTree.Add(fileNode);
|
||||
}
|
||||
|
||||
Progress.Report(++j, assetsFileCount);
|
||||
}
|
||||
|
||||
treeNodeDictionary.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()
|
||||
{
|
||||
var exportableAssetsCountDict = new Dictionary<ClassIDType, int>();
|
||||
@@ -218,7 +363,20 @@ namespace AssetStudioCLI
|
||||
}
|
||||
}
|
||||
|
||||
public static void FilterAssets()
|
||||
public static void Filter()
|
||||
{
|
||||
switch (CLIOptions.o_workMode.Value)
|
||||
{
|
||||
case WorkMode.Live2D:
|
||||
case WorkMode.SplitObjects:
|
||||
break;
|
||||
default:
|
||||
FilterAssets();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void FilterAssets()
|
||||
{
|
||||
var assetsCount = parsedAssetsList.Count;
|
||||
var filteredAssets = new List<AssetItem>();
|
||||
@@ -226,14 +384,14 @@ namespace AssetStudioCLI
|
||||
switch(CLIOptions.filterBy)
|
||||
{
|
||||
case FilterBy.Name:
|
||||
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByName.Value.Any(y => x.Text.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names."
|
||||
);
|
||||
break;
|
||||
case FilterBy.Container:
|
||||
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
filteredAssets = parsedAssetsList.FindAll(x => CLIOptions.o_filterByContainer.Value.Any(y => x.Container.IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0));
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
$"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByContainer.Value)}\"".Color(Ansi.BrightYellow)} in their Containers."
|
||||
@@ -248,8 +406,8 @@ namespace AssetStudioCLI
|
||||
break;
|
||||
case FilterBy.NameOrContainer:
|
||||
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||
CLIOptions.o_filterByText.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) ||
|
||||
CLIOptions.o_filterByText.Value.Any(y => x.Container.ToString().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)
|
||||
);
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
@@ -258,8 +416,8 @@ namespace AssetStudioCLI
|
||||
break;
|
||||
case FilterBy.NameAndContainer:
|
||||
filteredAssets = parsedAssetsList.FindAll(x =>
|
||||
CLIOptions.o_filterByName.Value.Any(y => x.Text.ToString().IndexOf(y, StringComparison.OrdinalIgnoreCase) >= 0) &&
|
||||
CLIOptions.o_filterByContainer.Value.Any(y => x.Container.ToString().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)
|
||||
);
|
||||
Logger.Info(
|
||||
$"Found [{filteredAssets.Count}/{assetsCount}] asset(s) " +
|
||||
@@ -279,7 +437,10 @@ namespace AssetStudioCLI
|
||||
var exportedCount = 0;
|
||||
|
||||
var groupOption = CLIOptions.o_groupAssetsBy.Value;
|
||||
foreach (var asset in parsedAssetsList)
|
||||
var parallelExportCount = CLIOptions.o_maxParallelExportTasks.Value;
|
||||
var toExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
|
||||
var toParallelExportAssetDict = new ConcurrentDictionary<AssetItem, string>();
|
||||
Parallel.ForEach(parsedAssetsList, asset =>
|
||||
{
|
||||
string exportPath;
|
||||
switch (groupOption)
|
||||
@@ -312,36 +473,75 @@ namespace AssetStudioCLI
|
||||
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
|
||||
}
|
||||
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:
|
||||
exportPath = savePath;
|
||||
break;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
switch (CLIOptions.o_workMode.Value)
|
||||
{
|
||||
case WorkMode.ExportRaw:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportRawFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportRawFile(asset, exportPath);
|
||||
break;
|
||||
case WorkMode.Dump:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportDumpFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportDumpFile(asset, exportPath);
|
||||
break;
|
||||
case WorkMode.Export:
|
||||
Logger.Debug($"{CLIOptions.o_workMode}: {asset.Type} : {asset.Container} : {asset.Text}");
|
||||
if (ExportConvertFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportConvertFile(asset, exportPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -349,8 +549,33 @@ namespace AssetStudioCLI
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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("");
|
||||
|
||||
if (exportedCount == 0)
|
||||
@@ -391,6 +616,7 @@ namespace AssetStudioCLI
|
||||
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
|
||||
new XElement("PathID", asset.m_PathID),
|
||||
new XElement("Source", asset.SourceFile.fullName),
|
||||
new XElement("TreeNode", asset.Node != null ? asset.Node.FullPath : ""),
|
||||
new XElement("Size", asset.FullSize)
|
||||
)
|
||||
)
|
||||
@@ -403,73 +629,188 @@ namespace AssetStudioCLI
|
||||
Logger.Info($"Finished exporting asset list with {parsedAssetsList.Count} items.");
|
||||
}
|
||||
|
||||
public static void ExportSplitObjects()
|
||||
{
|
||||
var savePath = CLIOptions.o_outputFolder.Value;
|
||||
var searchList = CLIOptions.o_filterByName.Value;
|
||||
var isFiltered = CLIOptions.filterBy == FilterBy.Name;
|
||||
|
||||
var exportableObjects = new List<GameObjectNode>();
|
||||
var exportedCount = 0;
|
||||
var k = 0;
|
||||
|
||||
Logger.Info($"Searching for objects to export..");
|
||||
Progress.Reset();
|
||||
var count = gameObjectTree.Sum(x => x.nodes.Count);
|
||||
foreach (var node in gameObjectTree)
|
||||
{
|
||||
foreach (GameObjectNode j in node.nodes)
|
||||
{
|
||||
if (isFiltered)
|
||||
{
|
||||
if (!searchList.Any(searchText => j.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0))
|
||||
continue;
|
||||
}
|
||||
var gameObjects = new List<GameObject>();
|
||||
CollectNode(j, gameObjects);
|
||||
|
||||
if (gameObjects.All(x => x.m_SkinnedMeshRenderer == null && x.m_MeshFilter == null))
|
||||
{
|
||||
Progress.Report(++k, count);
|
||||
continue;
|
||||
}
|
||||
exportableObjects.Add(j);
|
||||
}
|
||||
}
|
||||
gameObjectTree.Clear();
|
||||
var exportableCount = exportableObjects.Count;
|
||||
var log = $"Found {exportableCount} exportable object(s) ";
|
||||
if (isFiltered)
|
||||
{
|
||||
log += $"that contain {$"\"{string.Join("\", \"", CLIOptions.o_filterByName.Value)}\"".Color(Ansi.BrightYellow)} in their Names";
|
||||
}
|
||||
Logger.Info(log);
|
||||
if (exportableCount > 0)
|
||||
{
|
||||
Progress.Reset();
|
||||
k = 0;
|
||||
|
||||
foreach (var gameObjectNode in exportableObjects)
|
||||
{
|
||||
var gameObject = gameObjectNode.gameObject;
|
||||
var filename = FixFileName(gameObject.m_Name);
|
||||
var targetPath = $"{savePath}{filename}{Path.DirectorySeparatorChar}";
|
||||
//重名文件处理
|
||||
for (int i = 1; ; i++)
|
||||
{
|
||||
if (Directory.Exists(targetPath))
|
||||
{
|
||||
targetPath = $"{savePath}{filename} ({i}){Path.DirectorySeparatorChar}";
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Directory.CreateDirectory(targetPath);
|
||||
//导出FBX
|
||||
Logger.Info($"Exporting {filename}.fbx");
|
||||
Progress.Report(k, exportableCount);
|
||||
try
|
||||
{
|
||||
ExportGameObject(gameObject, targetPath);
|
||||
Logger.Debug($"{gameObject.type} \"{filename}\" saved to \"{targetPath}\"");
|
||||
exportedCount++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Export GameObject:{gameObject.m_Name} error", ex);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
var status = exportedCount > 0
|
||||
? $"Finished exporting [{exportedCount}/{exportableCount}] object(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\""
|
||||
: "Nothing exported";
|
||||
Logger.Default.Log(LoggerEvent.Info, status, ignoreLevel: true);
|
||||
}
|
||||
|
||||
private static void CollectNode(GameObjectNode node, List<GameObject> gameObjects)
|
||||
{
|
||||
gameObjects.Add(node.gameObject);
|
||||
foreach (GameObjectNode i in node.nodes)
|
||||
{
|
||||
CollectNode(i, gameObjects);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ExportLive2D()
|
||||
{
|
||||
var baseDestPath = Path.Combine(CLIOptions.o_outputFolder.Value, "Live2DOutput");
|
||||
var useFullContainerPath = false;
|
||||
var useFullContainerPath = true;
|
||||
var mocPathList = new List<string>();
|
||||
var basePathSet = new HashSet<string>();
|
||||
var motionMode = CLIOptions.o_l2dMotionMode.Value;
|
||||
var forceBezier = CLIOptions.f_l2dForceBezier.Value;
|
||||
|
||||
Progress.Reset();
|
||||
Logger.Info($"Searching for Live2D files...");
|
||||
|
||||
var cubismMocs = parsedAssetsList.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)
|
||||
if (cubismMocList.Count == 0)
|
||||
{
|
||||
Logger.Default.Log(LoggerEvent.Info, "Live2D Cubism models were not found.", ignoreLevel: true);
|
||||
return;
|
||||
}
|
||||
if (cubismMocs.Length > 1)
|
||||
{
|
||||
var basePathSet = cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToHashSet();
|
||||
|
||||
if (basePathSet.Count != cubismMocs.Length)
|
||||
{
|
||||
useFullContainerPath = true;
|
||||
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
|
||||
}
|
||||
Progress.Reset();
|
||||
Logger.Info($"Searching for Live2D files...");
|
||||
|
||||
foreach (var mocMonoBehaviour in cubismMocList)
|
||||
{
|
||||
if (!containers.TryGetValue(mocMonoBehaviour, out var fullContainerPath))
|
||||
continue;
|
||||
|
||||
var pathSepIndex = fullContainerPath.LastIndexOf('/');
|
||||
var basePath = pathSepIndex > 0
|
||||
? fullContainerPath.Substring(0, pathSepIndex)
|
||||
: fullContainerPath;
|
||||
basePathSet.Add(basePath);
|
||||
mocPathList.Add(fullContainerPath);
|
||||
}
|
||||
var basePathList = useFullContainerPath ?
|
||||
cubismMocs.Select(x => containers[x]).ToList() :
|
||||
cubismMocs.Select(x => containers[x].Substring(0, containers[x].LastIndexOf("/"))).ToList();
|
||||
var lookup = containers.ToLookup(
|
||||
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||
|
||||
if (mocPathList.Count == 0)
|
||||
{
|
||||
Logger.Error("Live2D Cubism export error: Cannot find any model related files.");
|
||||
return;
|
||||
}
|
||||
if (basePathSet.Count == mocPathList.Count)
|
||||
{
|
||||
mocPathList = basePathSet.ToList();
|
||||
useFullContainerPath = false;
|
||||
Logger.Debug($"useFullContainerPath: {useFullContainerPath}");
|
||||
}
|
||||
basePathSet.Clear();
|
||||
|
||||
var lookup = containers.AsParallel().ToLookup(
|
||||
x => mocPathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||
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);
|
||||
Logger.Info($"Found {totalModelCount} model(s).");
|
||||
var name = "";
|
||||
var parallelTaskCount = CLIOptions.o_maxParallelExportTasks.Value;
|
||||
var modelCounter = 0;
|
||||
foreach (var assets in lookup)
|
||||
{
|
||||
var container = assets.Key;
|
||||
if (container == null)
|
||||
var srcContainer = assets.Key;
|
||||
if (srcContainer == null)
|
||||
continue;
|
||||
name = container;
|
||||
var container = srcContainer;
|
||||
|
||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{container.Color(Ansi.BrightCyan)}\"");
|
||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer.Color(Ansi.BrightCyan)}\"");
|
||||
try
|
||||
{
|
||||
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
||||
container = Path.HasExtension(container) ? container.Replace(Path.GetExtension(container), "") : container;
|
||||
var modelName = useFullContainerPath
|
||||
? Path.GetFileNameWithoutExtension(container)
|
||||
: container.Substring(container.LastIndexOf('/') + 1);
|
||||
container = Path.HasExtension(container)
|
||||
? container.Replace(Path.GetExtension(container), "")
|
||||
: container;
|
||||
var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar;
|
||||
|
||||
ExtractLive2D(assets, destPath, modelName, assemblyLoader);
|
||||
var modelExtractor = new Live2DExtractor(assets);
|
||||
modelExtractor.ExtractCubismModel(destPath, modelName, motionMode, assemblyLoader, forceBezier, parallelTaskCount);
|
||||
modelCounter++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Live2D model export error: \"{name}\"", ex);
|
||||
Logger.Error($"Live2D model export error: \"{srcContainer}\"", ex);
|
||||
}
|
||||
Progress.Report(modelCounter, (int)totalModelCount);
|
||||
}
|
||||
|
||||
var status = modelCounter > 0 ?
|
||||
$"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s) to \"{CLIOptions.o_outputFolder.Value.Color(Ansi.BrightCyan)}\"" :
|
||||
"Nothing exported.";
|
||||
|
||||
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
22
AssetStudioFBXNative/CMakeLists.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
# Set the minimum version of CMake that can be used
|
||||
cmake_minimum_required (VERSION 3.8)
|
||||
|
||||
# Set the project name
|
||||
project("AssetStudioFBXNative")
|
||||
|
||||
# Set the C++ standard to C++ 14
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
# Generate the shared library from the library sources
|
||||
add_library(AssetStudioFBXNative SHARED
|
||||
asfbx_skin_context.cpp
|
||||
asfbx_morph_context.cpp
|
||||
api.cpp
|
||||
utils.cpp
|
||||
asfbx_context.cpp
|
||||
asfbx_anim_context.cpp)
|
||||
|
||||
# Add the given directories to those the compiler uses to search for include files
|
||||
target_include_directories(AssetStudioFBXNative PRIVATE .)
|
||||
|
||||
target_link_libraries(AssetStudioFBXNative PRIVATE fbxsdk xml2)
|
||||
@@ -1,9 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
28
AssetStudioGUI/AboutForm.Designer.cs
generated
28
AssetStudioGUI/AboutForm.Designer.cs
generated
@@ -164,7 +164,7 @@
|
||||
this.tableLayoutPanel2.ColumnCount = 3;
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 41.37931F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 58.62069F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 111F));
|
||||
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 112F));
|
||||
this.tableLayoutPanel2.Controls.Add(this.label16, 0, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.label17, 1, 0);
|
||||
this.tableLayoutPanel2.Controls.Add(this.gitPerfareLinkLabel, 2, 0);
|
||||
@@ -194,7 +194,7 @@
|
||||
//
|
||||
this.label17.AutoSize = true;
|
||||
this.label17.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label17.Location = new System.Drawing.Point(102, 2);
|
||||
this.label17.Location = new System.Drawing.Point(101, 2);
|
||||
this.label17.Name = "label17";
|
||||
this.label17.Size = new System.Drawing.Size(110, 13);
|
||||
this.label17.TabIndex = 10;
|
||||
@@ -204,7 +204,7 @@
|
||||
//
|
||||
this.gitPerfareLinkLabel.AutoSize = true;
|
||||
this.gitPerfareLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.gitPerfareLinkLabel.Location = new System.Drawing.Point(239, 2);
|
||||
this.gitPerfareLinkLabel.Location = new System.Drawing.Point(238, 2);
|
||||
this.gitPerfareLinkLabel.Name = "gitPerfareLinkLabel";
|
||||
this.gitPerfareLinkLabel.Size = new System.Drawing.Size(67, 13);
|
||||
this.gitPerfareLinkLabel.TabIndex = 11;
|
||||
@@ -226,17 +226,17 @@
|
||||
//
|
||||
this.label19.AutoSize = true;
|
||||
this.label19.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label19.Location = new System.Drawing.Point(102, 20);
|
||||
this.label19.Location = new System.Drawing.Point(101, 20);
|
||||
this.label19.Name = "label19";
|
||||
this.label19.Size = new System.Drawing.Size(113, 13);
|
||||
this.label19.TabIndex = 13;
|
||||
this.label19.Text = "aelurum (c) 2021-2023";
|
||||
this.label19.Text = "aelurum (c) 2021-2024";
|
||||
//
|
||||
// gitAelurumLinkLabel
|
||||
//
|
||||
this.gitAelurumLinkLabel.AutoSize = true;
|
||||
this.gitAelurumLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.gitAelurumLinkLabel.Location = new System.Drawing.Point(239, 20);
|
||||
this.gitAelurumLinkLabel.Location = new System.Drawing.Point(238, 20);
|
||||
this.gitAelurumLinkLabel.Name = "gitAelurumLinkLabel";
|
||||
this.gitAelurumLinkLabel.Size = new System.Drawing.Size(67, 13);
|
||||
this.gitAelurumLinkLabel.TabIndex = 14;
|
||||
@@ -250,7 +250,7 @@
|
||||
this.tableLayoutPanel1.ColumnCount = 3;
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 41.37931F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 58.62069F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 111F));
|
||||
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 112F));
|
||||
this.tableLayoutPanel1.Controls.Add(this.label5, 0, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.productNamelabel, 1, 0);
|
||||
this.tableLayoutPanel1.Controls.Add(this.label7, 0, 1);
|
||||
@@ -285,7 +285,7 @@
|
||||
//
|
||||
this.productNamelabel.AutoSize = true;
|
||||
this.productNamelabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.productNamelabel.Location = new System.Drawing.Point(102, 2);
|
||||
this.productNamelabel.Location = new System.Drawing.Point(101, 2);
|
||||
this.productNamelabel.Name = "productNamelabel";
|
||||
this.productNamelabel.Size = new System.Drawing.Size(103, 13);
|
||||
this.productNamelabel.TabIndex = 1;
|
||||
@@ -306,11 +306,11 @@
|
||||
this.modVersionLabel.AutoSize = true;
|
||||
this.modVersionLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.modVersionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
|
||||
this.modVersionLabel.Location = new System.Drawing.Point(102, 20);
|
||||
this.modVersionLabel.Location = new System.Drawing.Point(101, 20);
|
||||
this.modVersionLabel.Name = "modVersionLabel";
|
||||
this.modVersionLabel.Size = new System.Drawing.Size(52, 13);
|
||||
this.modVersionLabel.Size = new System.Drawing.Size(46, 13);
|
||||
this.modVersionLabel.TabIndex = 3;
|
||||
this.modVersionLabel.Text = "0.16.48.1";
|
||||
this.modVersionLabel.Text = "0.18.0.0";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
@@ -327,7 +327,7 @@
|
||||
//
|
||||
this.label8.AutoSize = true;
|
||||
this.label8.BackColor = System.Drawing.Color.Transparent;
|
||||
this.label8.Location = new System.Drawing.Point(102, 38);
|
||||
this.label8.Location = new System.Drawing.Point(101, 38);
|
||||
this.label8.Name = "label8";
|
||||
this.label8.Size = new System.Drawing.Size(108, 13);
|
||||
this.label8.TabIndex = 5;
|
||||
@@ -337,7 +337,7 @@
|
||||
//
|
||||
this.checkUpdatesLinkLabel.AutoSize = true;
|
||||
this.checkUpdatesLinkLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.checkUpdatesLinkLabel.Location = new System.Drawing.Point(239, 20);
|
||||
this.checkUpdatesLinkLabel.Location = new System.Drawing.Point(238, 20);
|
||||
this.checkUpdatesLinkLabel.Name = "checkUpdatesLinkLabel";
|
||||
this.checkUpdatesLinkLabel.Size = new System.Drawing.Size(96, 13);
|
||||
this.checkUpdatesLinkLabel.TabIndex = 6;
|
||||
@@ -414,7 +414,7 @@
|
||||
this.productVersionLabel.Padding = new System.Windows.Forms.Padding(0, 0, 5, 0);
|
||||
this.productVersionLabel.Size = new System.Drawing.Size(384, 13);
|
||||
this.productVersionLabel.TabIndex = 2;
|
||||
this.productVersionLabel.Text = "v0.16.48.1 [x64]";
|
||||
this.productVersionLabel.Text = "v0.18.0.0 [x64]";
|
||||
this.productVersionLabel.TextAlign = System.Drawing.ContentAlignment.BottomCenter;
|
||||
//
|
||||
// panel2
|
||||
|
||||
@@ -10,13 +10,15 @@ namespace AssetStudioGUI
|
||||
public AboutForm()
|
||||
{
|
||||
InitializeComponent();
|
||||
var productName = Application.ProductName;
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
var productName = appAssembly.Name;
|
||||
var productVer = appAssembly.Version.ToString();
|
||||
Text += " " + productName;
|
||||
productTitleLabel.Text = productName;
|
||||
productVersionLabel.Text = $"v{Application.ProductVersion} [{arch}]";
|
||||
productVersionLabel.Text = $"v{productVer} [{arch}]";
|
||||
productNamelabel.Text = productName;
|
||||
modVersionLabel.Text = Application.ProductVersion;
|
||||
modVersionLabel.Text = productVer;
|
||||
|
||||
licenseRichTextBox.Text = GetLicenseText();
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFrameworks>net472;net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||
<TargetFrameworks>net472;net6.0-windows;net7.0-windows;net8.0-windows</TargetFrameworks>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||
<AssemblyTitle>AssetStudioMod by aelurum</AssemblyTitle>
|
||||
<AssemblyName>AssetStudioModGUI</AssemblyName>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2023</Copyright>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2021-2024</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -54,14 +54,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Core-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell-6.0" Version="1.1.6-preview.2.24bd88f" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Core-6.0" Version="1.1.6" />
|
||||
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell-6.0" Version="1.1.6" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' != 'net472' ">
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.8.0" />
|
||||
<PackageReference Include="OpenTK.Windowing.Desktop" Version="4.8.0" />
|
||||
<PackageReference Include="OpenTK.Graphics" Version="4.8.2" />
|
||||
<PackageReference Include="OpenTK.Windowing.Desktop" Version="4.8.2" />
|
||||
<Reference Include="OpenTK.WinForms">
|
||||
<HintPath>Libraries\OpenTK.WinForms.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
292
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
292
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@@ -39,8 +39,14 @@
|
||||
this.extractFolderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.optionsToolStripMenuItem = 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.displayInfo = 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.specifyUnityVersion = new System.Windows.Forms.ToolStripTextBox();
|
||||
this.showExpOpt = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -67,7 +73,12 @@
|
||||
this.toolStripMenuItem8 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem9 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
|
||||
this.allLive2DModelsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.live2DCubismModelsToolStripMenuItem = 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.toolStripMenuItem10 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.toolStripMenuItem11 = new System.Windows.Forms.ToolStripMenuItem();
|
||||
@@ -76,7 +87,9 @@
|
||||
this.filterTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.allToolStripMenuItem = 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.writeLogToFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.exportClassStructuresMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||
@@ -103,7 +116,7 @@
|
||||
this.progressBar1 = new System.Windows.Forms.ProgressBar();
|
||||
this.tabControl2 = new System.Windows.Forms.TabControl();
|
||||
this.tabPage4 = new System.Windows.Forms.TabPage();
|
||||
this.previewPanel = new System.Windows.Forms.Panel();
|
||||
this.previewPanel = new System.Windows.Forms.PictureBox();
|
||||
this.assetInfoLabel = new System.Windows.Forms.Label();
|
||||
this.FMODpanel = new System.Windows.Forms.Panel();
|
||||
this.FMODcopyright = new System.Windows.Forms.Label();
|
||||
@@ -137,8 +150,12 @@
|
||||
this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
|
||||
this.copyToolStripMenuItem = 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.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.showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||
this.menuStrip1.SuspendLayout();
|
||||
@@ -154,6 +171,7 @@
|
||||
this.progressbarPanel.SuspendLayout();
|
||||
this.tabControl2.SuspendLayout();
|
||||
this.tabPage4.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.previewPanel)).BeginInit();
|
||||
this.previewPanel.SuspendLayout();
|
||||
this.FMODpanel.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.FMODprogressBar)).BeginInit();
|
||||
@@ -229,8 +247,12 @@
|
||||
//
|
||||
this.optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.displayAll,
|
||||
this.useAssetLoadingViaTypetreeToolStripMenuItem,
|
||||
this.assetLoadingToolStripSeparator,
|
||||
this.enablePreview,
|
||||
this.displayInfo,
|
||||
this.buildTreeStructureToolStripMenuItem,
|
||||
this.customCompressionTypeToolStripMenuItem,
|
||||
this.toolStripMenuItem14,
|
||||
this.showExpOpt});
|
||||
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
|
||||
@@ -241,19 +263,36 @@
|
||||
//
|
||||
this.displayAll.CheckOnClick = true;
|
||||
this.displayAll.Name = "displayAll";
|
||||
this.displayAll.Size = new System.Drawing.Size(207, 22);
|
||||
this.displayAll.Size = new System.Drawing.Size(241, 22);
|
||||
this.displayAll.Text = "Display all assets";
|
||||
this.displayAll.ToolTipText = "Check this option will display all types assets. Not extractable assets can expor" +
|
||||
"t the RAW file.";
|
||||
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
|
||||
//
|
||||
this.enablePreview.Checked = true;
|
||||
this.enablePreview.CheckOnClick = true;
|
||||
this.enablePreview.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.enablePreview.Name = "enablePreview";
|
||||
this.enablePreview.Size = new System.Drawing.Size(207, 22);
|
||||
this.enablePreview.Size = new System.Drawing.Size(241, 22);
|
||||
this.enablePreview.Text = "Enable preview";
|
||||
this.enablePreview.ToolTipText = "Toggle the loading and preview of readable assets, such as images, sounds, text, " +
|
||||
"etc.\r\nDisable preview if you have performance or compatibility issues.";
|
||||
@@ -265,19 +304,62 @@
|
||||
this.displayInfo.CheckOnClick = true;
|
||||
this.displayInfo.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.displayInfo.Name = "displayInfo";
|
||||
this.displayInfo.Size = new System.Drawing.Size(207, 22);
|
||||
this.displayInfo.Size = new System.Drawing.Size(241, 22);
|
||||
this.displayInfo.Text = "Display asset information";
|
||||
this.displayInfo.ToolTipText = "Toggle the overlay that shows information about each asset, eg. image size, forma" +
|
||||
"t, audio bitrate, etc.";
|
||||
this.displayInfo.CheckedChanged += new System.EventHandler(this.displayAssetInfo_Check);
|
||||
//
|
||||
// buildTreeStructureToolStripMenuItem
|
||||
//
|
||||
this.buildTreeStructureToolStripMenuItem.Checked = true;
|
||||
this.buildTreeStructureToolStripMenuItem.CheckOnClick = true;
|
||||
this.buildTreeStructureToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.buildTreeStructureToolStripMenuItem.Name = "buildTreeStructureToolStripMenuItem";
|
||||
this.buildTreeStructureToolStripMenuItem.Size = new System.Drawing.Size(241, 22);
|
||||
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.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
|
||||
//
|
||||
this.toolStripMenuItem14.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.specifyUnityVersion});
|
||||
this.toolStripMenuItem14.Name = "toolStripMenuItem14";
|
||||
this.toolStripMenuItem14.Size = new System.Drawing.Size(207, 22);
|
||||
this.toolStripMenuItem14.Size = new System.Drawing.Size(241, 22);
|
||||
this.toolStripMenuItem14.Text = "Specify Unity version";
|
||||
this.toolStripMenuItem14.DropDownClosed += new System.EventHandler(this.specifyUnityVersion_Close);
|
||||
//
|
||||
// specifyUnityVersion
|
||||
//
|
||||
@@ -290,7 +372,7 @@
|
||||
// showExpOpt
|
||||
//
|
||||
this.showExpOpt.Name = "showExpOpt";
|
||||
this.showExpOpt.Size = new System.Drawing.Size(207, 22);
|
||||
this.showExpOpt.Size = new System.Drawing.Size(241, 22);
|
||||
this.showExpOpt.Text = "Export options";
|
||||
this.showExpOpt.Click += new System.EventHandler(this.showExpOpt_Click);
|
||||
//
|
||||
@@ -312,7 +394,7 @@
|
||||
this.exportAllObjectssplitToolStripMenuItem1.Name = "exportAllObjectssplitToolStripMenuItem1";
|
||||
this.exportAllObjectssplitToolStripMenuItem1.Size = new System.Drawing.Size(382, 22);
|
||||
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
|
||||
//
|
||||
@@ -326,7 +408,7 @@
|
||||
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsWithAnimationClipToolStripMenuItem";
|
||||
this.exportSelectedObjectsWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
|
||||
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
|
||||
//
|
||||
@@ -338,14 +420,14 @@
|
||||
this.exportSelectedObjectsmergeToolStripMenuItem.Name = "exportSelectedObjectsmergeToolStripMenuItem";
|
||||
this.exportSelectedObjectsmergeToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
|
||||
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
|
||||
//
|
||||
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Name = "exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem";
|
||||
this.exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(382, 22);
|
||||
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
|
||||
//
|
||||
@@ -359,7 +441,7 @@
|
||||
this.toolStripMenuItem2,
|
||||
this.toolStripMenuItem3,
|
||||
this.toolStripSeparator6,
|
||||
this.allLive2DModelsToolStripMenuItem,
|
||||
this.live2DCubismModelsToolStripMenuItem,
|
||||
this.toolStripSeparator2,
|
||||
this.toolStripMenuItem10});
|
||||
this.exportToolStripMenuItem.Name = "exportToolStripMenuItem";
|
||||
@@ -397,7 +479,7 @@
|
||||
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Name = "exportAnimatorWithSelectedAnimationClipToolStripMenuItem";
|
||||
this.exportAnimatorWithSelectedAnimationClipToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
|
||||
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
|
||||
//
|
||||
@@ -471,12 +553,52 @@
|
||||
this.toolStripSeparator6.Name = "toolStripSeparator6";
|
||||
this.toolStripSeparator6.Size = new System.Drawing.Size(263, 6);
|
||||
//
|
||||
// allLive2DModelsToolStripMenuItem
|
||||
// live2DCubismModelsToolStripMenuItem
|
||||
//
|
||||
this.allLive2DModelsToolStripMenuItem.Name = "allLive2DModelsToolStripMenuItem";
|
||||
this.allLive2DModelsToolStripMenuItem.Size = new System.Drawing.Size(266, 22);
|
||||
this.allLive2DModelsToolStripMenuItem.Text = "Live2D Cubism models";
|
||||
this.allLive2DModelsToolStripMenuItem.Click += new System.EventHandler(this.allLive2DModelsToolStripMenuItem_Click);
|
||||
this.live2DCubismModelsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.allL2DModelsToolStripMenuItem,
|
||||
this.selectedL2DModelsToolStripMenuItem,
|
||||
this.l2DModelWithFadeListToolStripMenuItem,
|
||||
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
|
||||
//
|
||||
@@ -535,24 +657,44 @@
|
||||
// debugMenuItem
|
||||
//
|
||||
this.debugMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.showConsoleToolStripMenuItem,
|
||||
this.toolStripMenuItem15,
|
||||
this.writeLogToFileToolStripMenuItem,
|
||||
this.exportClassStructuresMenuItem});
|
||||
this.debugMenuItem.Name = "debugMenuItem";
|
||||
this.debugMenuItem.Size = new System.Drawing.Size(54, 20);
|
||||
this.debugMenuItem.Text = "Debug";
|
||||
//
|
||||
// showConsoleToolStripMenuItem
|
||||
//
|
||||
this.showConsoleToolStripMenuItem.Checked = true;
|
||||
this.showConsoleToolStripMenuItem.CheckOnClick = true;
|
||||
this.showConsoleToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.showConsoleToolStripMenuItem.Name = "showConsoleToolStripMenuItem";
|
||||
this.showConsoleToolStripMenuItem.Size = new System.Drawing.Size(288, 22);
|
||||
this.showConsoleToolStripMenuItem.Text = "Show console logger";
|
||||
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(200, 22);
|
||||
this.toolStripMenuItem15.Text = "Show all error messages";
|
||||
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
|
||||
//
|
||||
this.writeLogToFileToolStripMenuItem.CheckOnClick = true;
|
||||
this.writeLogToFileToolStripMenuItem.Name = "writeLogToFileToolStripMenuItem";
|
||||
this.writeLogToFileToolStripMenuItem.Size = new System.Drawing.Size(288, 22);
|
||||
this.writeLogToFileToolStripMenuItem.Text = "Write log to file";
|
||||
this.writeLogToFileToolStripMenuItem.CheckedChanged += new System.EventHandler(this.writeLogToFileToolStripMenuItem_CheckedChanged);
|
||||
//
|
||||
// exportClassStructuresMenuItem
|
||||
//
|
||||
this.exportClassStructuresMenuItem.Name = "exportClassStructuresMenuItem";
|
||||
this.exportClassStructuresMenuItem.Size = new System.Drawing.Size(200, 22);
|
||||
this.exportClassStructuresMenuItem.Size = new System.Drawing.Size(288, 22);
|
||||
this.exportClassStructuresMenuItem.Text = "Export class structures";
|
||||
this.exportClassStructuresMenuItem.Click += new System.EventHandler(this.exportClassStructuresMenuItem_Click);
|
||||
//
|
||||
@@ -715,7 +857,7 @@
|
||||
this.listSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.listSearch.BackColor = System.Drawing.Color.White;
|
||||
this.listSearch.BackColor = System.Drawing.SystemColors.Window;
|
||||
this.listSearch.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||
this.listSearch.DetectUrls = false;
|
||||
this.listSearch.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
@@ -845,8 +987,6 @@
|
||||
// previewPanel
|
||||
//
|
||||
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.FMODpanel);
|
||||
this.previewPanel.Controls.Add(this.fontPreviewBox);
|
||||
@@ -854,17 +994,20 @@
|
||||
this.previewPanel.Controls.Add(this.textPreviewBox);
|
||||
this.previewPanel.Controls.Add(this.classTextBox);
|
||||
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.Name = "previewPanel";
|
||||
this.previewPanel.Size = new System.Drawing.Size(768, 607);
|
||||
this.previewPanel.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
|
||||
this.previewPanel.TabIndex = 1;
|
||||
this.previewPanel.TabStop = false;
|
||||
this.previewPanel.Resize += new System.EventHandler(this.preview_Resize);
|
||||
//
|
||||
// assetInfoLabel
|
||||
//
|
||||
this.assetInfoLabel.AutoSize = true;
|
||||
this.assetInfoLabel.BackColor = System.Drawing.Color.Transparent;
|
||||
this.assetInfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.assetInfoLabel.ForeColor = System.Drawing.Color.White;
|
||||
this.assetInfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.assetInfoLabel.Location = new System.Drawing.Point(4, 8);
|
||||
this.assetInfoLabel.Name = "assetInfoLabel";
|
||||
@@ -907,7 +1050,7 @@
|
||||
//
|
||||
this.FMODinfoLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODinfoLabel.AutoSize = true;
|
||||
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODinfoLabel.ForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.FMODinfoLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODinfoLabel.Location = new System.Drawing.Point(275, 255);
|
||||
this.FMODinfoLabel.Name = "FMODinfoLabel";
|
||||
@@ -918,7 +1061,7 @@
|
||||
//
|
||||
this.FMODtimerLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODtimerLabel.AutoSize = true;
|
||||
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODtimerLabel.ForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.FMODtimerLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODtimerLabel.Location = new System.Drawing.Point(457, 253);
|
||||
this.FMODtimerLabel.Name = "FMODtimerLabel";
|
||||
@@ -930,7 +1073,7 @@
|
||||
//
|
||||
this.FMODstatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
|
||||
this.FMODstatusLabel.AutoSize = true;
|
||||
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight;
|
||||
this.FMODstatusLabel.ForeColor = System.Drawing.SystemColors.HighlightText;
|
||||
this.FMODstatusLabel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
|
||||
this.FMODstatusLabel.Location = new System.Drawing.Point(214, 255);
|
||||
this.FMODstatusLabel.Name = "FMODstatusLabel";
|
||||
@@ -1191,46 +1334,82 @@
|
||||
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||
this.copyToolStripMenuItem,
|
||||
this.exportSelectedAssetsToolStripMenuItem,
|
||||
this.exportAnimatorwithselectedAnimationClipMenuItem,
|
||||
this.dumpSelectedAssetsToolStripMenuItem,
|
||||
this.exportAnimatorWithSelectedAnimationClipMenuItem,
|
||||
this.exportAsLive2DModelToolStripMenuItem,
|
||||
this.exportL2DWithFadeLstToolStripMenuItem,
|
||||
this.exportL2DWithFadeToolStripMenuItem,
|
||||
this.exportL2DWithClipsToolStripMenuItem,
|
||||
this.goToSceneHierarchyToolStripMenuItem,
|
||||
this.showOriginalFileToolStripMenuItem});
|
||||
this.contextMenuStrip1.Name = "contextMenuStrip1";
|
||||
this.contextMenuStrip1.Size = new System.Drawing.Size(304, 136);
|
||||
this.contextMenuStrip1.Size = new System.Drawing.Size(332, 224);
|
||||
//
|
||||
// copyToolStripMenuItem
|
||||
//
|
||||
this.copyToolStripMenuItem.Name = "copyToolStripMenuItem";
|
||||
this.copyToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
|
||||
this.copyToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
|
||||
this.copyToolStripMenuItem.Text = "Copy text";
|
||||
this.copyToolStripMenuItem.Click += new System.EventHandler(this.copyToolStripMenuItem_Click);
|
||||
//
|
||||
// exportSelectedAssetsToolStripMenuItem
|
||||
//
|
||||
this.exportSelectedAssetsToolStripMenuItem.Name = "exportSelectedAssetsToolStripMenuItem";
|
||||
this.exportSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
|
||||
this.exportSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
|
||||
this.exportSelectedAssetsToolStripMenuItem.Text = "Export selected assets";
|
||||
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
|
||||
//
|
||||
this.dumpSelectedAssetsToolStripMenuItem.Name = "dumpSelectedAssetsToolStripMenuItem";
|
||||
this.dumpSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
|
||||
this.dumpSelectedAssetsToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
|
||||
this.dumpSelectedAssetsToolStripMenuItem.Text = "Dump selected assets";
|
||||
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
|
||||
//
|
||||
this.goToSceneHierarchyToolStripMenuItem.Name = "goToSceneHierarchyToolStripMenuItem";
|
||||
this.goToSceneHierarchyToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
|
||||
this.goToSceneHierarchyToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
|
||||
this.goToSceneHierarchyToolStripMenuItem.Text = "Go to scene hierarchy";
|
||||
this.goToSceneHierarchyToolStripMenuItem.Visible = false;
|
||||
this.goToSceneHierarchyToolStripMenuItem.Click += new System.EventHandler(this.goToSceneHierarchyToolStripMenuItem_Click);
|
||||
@@ -1238,7 +1417,7 @@
|
||||
// showOriginalFileToolStripMenuItem
|
||||
//
|
||||
this.showOriginalFileToolStripMenuItem.Name = "showOriginalFileToolStripMenuItem";
|
||||
this.showOriginalFileToolStripMenuItem.Size = new System.Drawing.Size(303, 22);
|
||||
this.showOriginalFileToolStripMenuItem.Size = new System.Drawing.Size(331, 22);
|
||||
this.showOriginalFileToolStripMenuItem.Text = "Show original file";
|
||||
this.showOriginalFileToolStripMenuItem.Visible = false;
|
||||
this.showOriginalFileToolStripMenuItem.Click += new System.EventHandler(this.showOriginalFileToolStripMenuItem_Click);
|
||||
@@ -1256,6 +1435,7 @@
|
||||
this.Name = "AssetStudioGUIForm";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "AssetStudioModGUI";
|
||||
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.AssetStudioGUIForm_FormClosing);
|
||||
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragDrop);
|
||||
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.AssetStudioGUIForm_DragEnter);
|
||||
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.AssetStudioForm_KeyDown);
|
||||
@@ -1275,6 +1455,7 @@
|
||||
this.progressbarPanel.ResumeLayout(false);
|
||||
this.tabControl2.ResumeLayout(false);
|
||||
this.tabPage4.ResumeLayout(false);
|
||||
((System.ComponentModel.ISupportInitialize)(this.previewPanel)).EndInit();
|
||||
this.previewPanel.ResumeLayout(false);
|
||||
this.previewPanel.PerformLayout();
|
||||
this.FMODpanel.ResumeLayout(false);
|
||||
@@ -1309,7 +1490,7 @@
|
||||
private System.Windows.Forms.ToolStripMenuItem exportToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem exportAllAssetsMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem exportSelectedAssetsMenuItem;
|
||||
private System.Windows.Forms.Panel previewPanel;
|
||||
private System.Windows.Forms.PictureBox previewPanel;
|
||||
private System.Windows.Forms.ProgressBar progressBar1;
|
||||
private System.Windows.Forms.StatusStrip statusStrip1;
|
||||
private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1;
|
||||
@@ -1351,7 +1532,7 @@
|
||||
private OpenTK.GLControl glControl1;
|
||||
private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
|
||||
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 filterTypeToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem allToolStripMenuItem;
|
||||
@@ -1401,10 +1582,27 @@
|
||||
private System.Windows.Forms.ComboBox listSearchHistory;
|
||||
private System.Windows.Forms.RichTextBox listSearch;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
||||
private System.Windows.Forms.ToolStripMenuItem allLive2DModelsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem showRelatedAssetsToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
|
||||
private System.Windows.Forms.ListView assetListView;
|
||||
private System.Windows.Forms.ToolStripMenuItem showConsoleToolStripMenuItem;
|
||||
private System.Windows.Forms.ToolStripMenuItem writeLogToFileToolStripMenuItem;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,10 @@ namespace AssetStudioGUI
|
||||
private AlphanumComparatorFast alphanumComparator = new AlphanumComparatorFast();
|
||||
#endif
|
||||
|
||||
//asset list selection
|
||||
private List<int> selectedIndicesPrevList = new List<int>();
|
||||
private List<AssetItem> selectedAnimationAssetsList = new List<AssetItem>();
|
||||
|
||||
//asset list filter
|
||||
private System.Timers.Timer delayTimer;
|
||||
private bool enableFiltering;
|
||||
@@ -112,21 +116,33 @@ namespace AssetStudioGUI
|
||||
[DllImport("gdi32.dll")]
|
||||
private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);
|
||||
|
||||
private string guiTitle = string.Empty;
|
||||
|
||||
public AssetStudioGUIForm()
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
||||
ConsoleWindow.RunConsole(Properties.Settings.Default.showConsole);
|
||||
InitializeComponent();
|
||||
Text = $"{Application.ProductName} v{Application.ProductVersion}";
|
||||
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
guiTitle = $"{appAssembly.Name} v{appAssembly.Version}";
|
||||
Text = guiTitle;
|
||||
|
||||
delayTimer = new System.Timers.Timer(800);
|
||||
delayTimer.Elapsed += new ElapsedEventHandler(delayTimer_Elapsed);
|
||||
delayTimer.Elapsed += delayTimer_Elapsed;
|
||||
displayAll.Checked = Properties.Settings.Default.displayAll;
|
||||
displayInfo.Checked = Properties.Settings.Default.displayInfo;
|
||||
enablePreview.Checked = Properties.Settings.Default.enablePreview;
|
||||
showConsoleToolStripMenuItem.Checked = Properties.Settings.Default.showConsole;
|
||||
buildTreeStructureToolStripMenuItem.Checked = Properties.Settings.Default.buildTreeStructure;
|
||||
useAssetLoadingViaTypetreeToolStripMenuItem.Checked = Properties.Settings.Default.useTypetreeLoading;
|
||||
FMODinit();
|
||||
listSearchFilterMode.SelectedIndex = 0;
|
||||
|
||||
logger = new GUILogger(StatusStripUpdate);
|
||||
Logger.Default = logger;
|
||||
writeLogToFileToolStripMenuItem.Checked = Properties.Settings.Default.useFileLogger;
|
||||
|
||||
Progress.Default = new Progress<int>(SetProgressBarValue);
|
||||
Studio.StatusStripUpdate = StatusStripUpdate;
|
||||
}
|
||||
@@ -135,21 +151,31 @@ namespace AssetStudioGUI
|
||||
{
|
||||
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
||||
{
|
||||
e.Effect = DragDropEffects.Move;
|
||||
e.Effect = DragDropEffects.Copy;
|
||||
}
|
||||
}
|
||||
|
||||
private async void AssetStudioGUIForm_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
var paths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (paths.Length > 0)
|
||||
if (paths.Length == 0)
|
||||
return;
|
||||
|
||||
ResetForm();
|
||||
for (var i = 0; i < paths.Length; i++)
|
||||
{
|
||||
ResetForm();
|
||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, paths));
|
||||
saveDirectoryBackup = openDirectoryBackup;
|
||||
BuildAssetStructures();
|
||||
if (paths[i].ToLower().EndsWith(".lnk"))
|
||||
{
|
||||
var targetPath = LnkReader.GetLnkTarget(paths[i]);
|
||||
if (!string.IsNullOrEmpty(targetPath))
|
||||
{
|
||||
paths[i] = targetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, paths));
|
||||
saveDirectoryBackup = openDirectoryBackup;
|
||||
BuildAssetStructures();
|
||||
}
|
||||
|
||||
private async void loadFile_Click(object sender, EventArgs e)
|
||||
@@ -158,7 +184,6 @@ namespace AssetStudioGUI
|
||||
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
ResetForm();
|
||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFileDialog1.FileNames));
|
||||
BuildAssetStructures();
|
||||
}
|
||||
@@ -171,12 +196,29 @@ namespace AssetStudioGUI
|
||||
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
||||
{
|
||||
ResetForm();
|
||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||
await Task.Run(() => assetsManager.LoadFilesAndFolders(out openDirectoryBackup, openFolderDialog.Folder));
|
||||
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)
|
||||
{
|
||||
if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
|
||||
@@ -218,17 +260,11 @@ namespace AssetStudioGUI
|
||||
return;
|
||||
}
|
||||
|
||||
(var productName, var treeNodeCollection) = await Task.Run(() => BuildAssetData());
|
||||
var (productName, treeNodeCollection) = await Task.Run(() => BuildAssetData());
|
||||
var typeMap = await Task.Run(() => BuildClassStructure());
|
||||
productName = string.IsNullOrEmpty(productName) ? "no productName" : productName;
|
||||
|
||||
if (!string.IsNullOrEmpty(productName))
|
||||
{
|
||||
Text = $"{Application.ProductName} v{Application.ProductVersion} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = $"{Application.ProductName} v{Application.ProductVersion} - no productName - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
|
||||
}
|
||||
Text = $"{guiTitle} - {productName} - {assetsManager.assetsFileList[0].unityVersion} - {assetsManager.assetsFileList[0].m_TargetPlatform}";
|
||||
|
||||
assetListView.VirtualListSize = visibleAssets.Count;
|
||||
|
||||
@@ -266,9 +302,9 @@ namespace AssetStudioGUI
|
||||
filterTypeToolStripMenuItem.DropDownItems.Add(typeItem);
|
||||
}
|
||||
allToolStripMenuItem.Checked = true;
|
||||
var log = $"Finished loading {assetsManager.assetsFileList.Count} files with {assetListView.Items.Count} exportable assets";
|
||||
var log = $"Finished loading {assetsManager.assetsFileList.Count} file(s) with {assetListView.Items.Count} exportable assets";
|
||||
var unityVer = assetsManager.assetsFileList[0].version;
|
||||
var m_ObjectsCount = unityVer[0] > 2020 ?
|
||||
var m_ObjectsCount = unityVer > 2020 ?
|
||||
assetsManager.assetsFileList.Sum(x => x.m_Objects.LongCount(y => y.classID != (int)ClassIDType.Shader)) :
|
||||
assetsManager.assetsFileList.Sum(x => x.m_Objects.Count);
|
||||
var objectsCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||
@@ -329,7 +365,7 @@ namespace AssetStudioGUI
|
||||
if (e.Control)
|
||||
{
|
||||
var need = false;
|
||||
if (lastSelectedItem?.Type == ClassIDType.Texture2D)
|
||||
if (lastSelectedItem?.Type == ClassIDType.Texture2D || lastSelectedItem?.Type == ClassIDType.Texture2DArrayImage)
|
||||
{
|
||||
switch (e.KeyCode)
|
||||
{
|
||||
@@ -421,12 +457,12 @@ namespace AssetStudioGUI
|
||||
{
|
||||
if (enablePreview.Checked && imageTexture != null)
|
||||
{
|
||||
previewPanel.BackgroundImage = imageTexture.Bitmap;
|
||||
previewPanel.Image = imageTexture.Bitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
previewPanel.BackgroundImage = Properties.Resources.preview;
|
||||
previewPanel.BackgroundImageLayout = ImageLayout.Center;
|
||||
previewPanel.Image = Properties.Resources.preview;
|
||||
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -624,7 +660,7 @@ namespace AssetStudioGUI
|
||||
enableFiltering = false;
|
||||
listSearch.Text = " Filter ";
|
||||
listSearch.ForeColor = SystemColors.GrayText;
|
||||
listSearch.BackColor = System.Drawing.Color.White;
|
||||
listSearch.BackColor = SystemColors.Window;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,6 +715,8 @@ namespace AssetStudioGUI
|
||||
sortColumn = e.Column;
|
||||
assetListView.BeginUpdate();
|
||||
assetListView.SelectedIndices.Clear();
|
||||
selectedIndicesPrevList.Clear();
|
||||
selectedAnimationAssetsList.Clear();
|
||||
if (sortColumn == 4) //FullSize
|
||||
{
|
||||
visibleAssets.Sort((a, b) =>
|
||||
@@ -721,8 +759,8 @@ namespace AssetStudioGUI
|
||||
|
||||
private void selectAsset(object sender, ListViewItemSelectionChangedEventArgs e)
|
||||
{
|
||||
previewPanel.BackgroundImage = Properties.Resources.preview;
|
||||
previewPanel.BackgroundImageLayout = ImageLayout.Center;
|
||||
previewPanel.Image = Properties.Resources.preview;
|
||||
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage;
|
||||
classTextBox.Visible = false;
|
||||
assetInfoLabel.Visible = false;
|
||||
assetInfoLabel.Text = null;
|
||||
@@ -788,8 +826,12 @@ namespace AssetStudioGUI
|
||||
switch (assetItem.Type)
|
||||
{
|
||||
case ClassIDType.Texture2D:
|
||||
case ClassIDType.Texture2DArrayImage:
|
||||
PreviewTexture2D(assetItem, assetItem.Asset as Texture2D);
|
||||
break;
|
||||
case ClassIDType.Texture2DArray:
|
||||
PreviewTexture2DArray(assetItem, assetItem.Asset as Texture2DArray);
|
||||
break;
|
||||
case ClassIDType.AudioClip:
|
||||
PreviewAudioClip(assetItem, assetItem.Asset as AudioClip);
|
||||
break;
|
||||
@@ -800,7 +842,16 @@ namespace AssetStudioGUI
|
||||
PreviewTextAsset(assetItem.Asset as TextAsset);
|
||||
break;
|
||||
case ClassIDType.MonoBehaviour:
|
||||
PreviewMonoBehaviour(assetItem.Asset as MonoBehaviour);
|
||||
var m_MonoBehaviour = (MonoBehaviour)assetItem.Asset;
|
||||
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;
|
||||
case ClassIDType.Font:
|
||||
PreviewFont(assetItem.Asset as Font);
|
||||
@@ -839,6 +890,16 @@ 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)
|
||||
{
|
||||
var image = m_Texture2D.ConvertToImage(true);
|
||||
@@ -849,9 +910,9 @@ namespace AssetStudioGUI
|
||||
assetItem.InfoText = $"Width: {m_Texture2D.m_Width}\nHeight: {m_Texture2D.m_Height}\nFormat: {m_Texture2D.m_TextureFormat}";
|
||||
switch (m_Texture2D.m_TextureSettings.m_FilterMode)
|
||||
{
|
||||
case 0: assetItem.InfoText += "\nFilter Mode: Point "; break;
|
||||
case 1: assetItem.InfoText += "\nFilter Mode: Bilinear "; break;
|
||||
case 2: assetItem.InfoText += "\nFilter Mode: Trilinear "; break;
|
||||
case 0: assetItem.InfoText += "\nFilter mode: Point "; break;
|
||||
case 1: assetItem.InfoText += "\nFilter mode: Bilinear "; 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}";
|
||||
switch (m_Texture2D.m_TextureSettings.m_WrapMode)
|
||||
@@ -887,6 +948,8 @@ namespace AssetStudioGUI
|
||||
}
|
||||
}
|
||||
}
|
||||
var switchSwizzled = m_Texture2D.m_PlatformBlob.Length != 0;
|
||||
assetItem.InfoText += assetItem.Asset.platform == BuildTarget.Switch ? $"\nUses texture swizzling: {switchSwizzled}" : "";
|
||||
PreviewTexture(bitmap);
|
||||
|
||||
StatusStripUpdate("'Ctrl'+'R'/'G'/'B'/'A' for Channel Toggle");
|
||||
@@ -901,12 +964,12 @@ namespace AssetStudioGUI
|
||||
{
|
||||
//Info
|
||||
assetItem.InfoText = "Compression format: ";
|
||||
if (m_AudioClip.version[0] < 5)
|
||||
if (m_AudioClip.version < 5)
|
||||
{
|
||||
switch (m_AudioClip.m_Type)
|
||||
{
|
||||
case FMODSoundType.ACC:
|
||||
assetItem.InfoText += "Acc";
|
||||
case FMODSoundType.AAC:
|
||||
assetItem.InfoText += "AAC";
|
||||
break;
|
||||
case FMODSoundType.AIFF:
|
||||
assetItem.InfoText += "AIFF";
|
||||
@@ -989,6 +1052,18 @@ namespace AssetStudioGUI
|
||||
var m_AudioData = m_AudioClip.m_AudioData.GetData();
|
||||
if (m_AudioData == null || m_AudioData.Length == 0)
|
||||
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();
|
||||
|
||||
exinfo.cbsize = Marshal.SizeOf(exinfo);
|
||||
@@ -1061,6 +1136,27 @@ namespace AssetStudioGUI
|
||||
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)
|
||||
{
|
||||
if (m_Font.m_FontData != null)
|
||||
@@ -1286,11 +1382,11 @@ namespace AssetStudioGUI
|
||||
{
|
||||
imageTexture?.Dispose();
|
||||
imageTexture = bitmap;
|
||||
previewPanel.BackgroundImage = imageTexture.Bitmap;
|
||||
previewPanel.Image = imageTexture.Bitmap;
|
||||
if (imageTexture.Width > previewPanel.Width || imageTexture.Height > previewPanel.Height)
|
||||
previewPanel.BackgroundImageLayout = ImageLayout.Zoom;
|
||||
previewPanel.SizeMode = PictureBoxSizeMode.Zoom;
|
||||
else
|
||||
previewPanel.BackgroundImageLayout = ImageLayout.Center;
|
||||
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage;
|
||||
}
|
||||
|
||||
private void PreviewText(string text)
|
||||
@@ -1340,7 +1436,7 @@ namespace AssetStudioGUI
|
||||
|
||||
private void ResetForm()
|
||||
{
|
||||
Text = $"{Application.ProductName} v{Application.ProductVersion}";
|
||||
Text = guiTitle;
|
||||
assetsManager.Clear();
|
||||
assemblyLoader.Clear();
|
||||
exportableAssets.Clear();
|
||||
@@ -1350,10 +1446,13 @@ namespace AssetStudioGUI
|
||||
assetListView.Items.Clear();
|
||||
classesListView.Items.Clear();
|
||||
classesListView.Groups.Clear();
|
||||
previewPanel.BackgroundImage = Properties.Resources.preview;
|
||||
selectedAnimationAssetsList.Clear();
|
||||
selectedIndicesPrevList.Clear();
|
||||
cubismMocList.Clear();
|
||||
previewPanel.Image = Properties.Resources.preview;
|
||||
previewPanel.SizeMode = PictureBoxSizeMode.CenterImage;
|
||||
imageTexture?.Dispose();
|
||||
imageTexture = null;
|
||||
previewPanel.BackgroundImageLayout = ImageLayout.Center;
|
||||
assetInfoLabel.Visible = false;
|
||||
assetInfoLabel.Text = null;
|
||||
textPreviewBox.Visible = false;
|
||||
@@ -1365,7 +1464,7 @@ namespace AssetStudioGUI
|
||||
enableFiltering = false;
|
||||
listSearch.Text = " Filter ";
|
||||
listSearch.ForeColor = SystemColors.GrayText;
|
||||
listSearch.BackColor = System.Drawing.Color.White;
|
||||
listSearch.BackColor = SystemColors.Window;
|
||||
if (tabControl1.SelectedIndex == 1)
|
||||
assetListView.Select();
|
||||
|
||||
@@ -1393,7 +1492,11 @@ namespace AssetStudioGUI
|
||||
{
|
||||
goToSceneHierarchyToolStripMenuItem.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)
|
||||
{
|
||||
@@ -1403,10 +1506,42 @@ namespace AssetStudioGUI
|
||||
if (assetListView.SelectedIndices.Count >= 1)
|
||||
{
|
||||
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)
|
||||
{
|
||||
exportAnimatorwithselectedAnimationClipMenuItem.Visible = true;
|
||||
switch (asset.Asset)
|
||||
{
|
||||
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));
|
||||
@@ -1434,16 +1569,15 @@ namespace AssetStudioGUI
|
||||
|
||||
private void showOriginalFileToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
|
||||
var args = $"/select, \"{selectasset.SourceFile.originalPath ?? selectasset.SourceFile.fullName}\"";
|
||||
var selectAsset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
|
||||
var args = $"/select, \"{selectAsset.SourceFile.originalPath ?? selectAsset.SourceFile.fullName}\"";
|
||||
var pfi = new ProcessStartInfo("explorer.exe", args);
|
||||
Process.Start(pfi);
|
||||
}
|
||||
|
||||
private void exportAnimatorwithAnimationClipMenuItem_Click(object sender, EventArgs e)
|
||||
private void exportAnimatorWithAnimationClipMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
AssetItem animator = null;
|
||||
List<AssetItem> animationList = new List<AssetItem>();
|
||||
var selectedAssets = GetSelectedAssets();
|
||||
foreach (var assetPreloadData in selectedAssets)
|
||||
{
|
||||
@@ -1451,10 +1585,6 @@ namespace AssetStudioGUI
|
||||
{
|
||||
animator = assetPreloadData;
|
||||
}
|
||||
else if (assetPreloadData.Type == ClassIDType.AnimationClip)
|
||||
{
|
||||
animationList.Add(assetPreloadData);
|
||||
}
|
||||
}
|
||||
|
||||
if (animator != null)
|
||||
@@ -1465,7 +1595,7 @@ namespace AssetStudioGUI
|
||||
{
|
||||
saveDirectoryBackup = saveFolderDialog.Folder;
|
||||
var exportPath = Path.Combine(saveFolderDialog.Folder, "Animator") + Path.DirectorySeparatorChar;
|
||||
ExportAnimatorWithAnimationClip(animator, animationList, exportPath);
|
||||
ExportAnimatorWithAnimationClip(animator, selectedAnimationAssetsList, exportPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1475,7 +1605,7 @@ namespace AssetStudioGUI
|
||||
ExportObjects(false);
|
||||
}
|
||||
|
||||
private void exportObjectswithAnimationClipMenuItem_Click(object sender, EventArgs e)
|
||||
private void exportObjectsWithAnimationClipMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
ExportObjects(true);
|
||||
}
|
||||
@@ -1508,12 +1638,12 @@ namespace AssetStudioGUI
|
||||
}
|
||||
}
|
||||
|
||||
private void exportSelectedObjectsmergeToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
private void exportSelectedObjectsMergeToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
ExportMergeObjects(false);
|
||||
}
|
||||
|
||||
private void exportSelectedObjectsmergeWithAnimationClipToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
private void exportSelectedObjectsMergeWithAnimationClipToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
ExportMergeObjects(true);
|
||||
}
|
||||
@@ -1556,10 +1686,10 @@ namespace AssetStudioGUI
|
||||
|
||||
private void goToSceneHierarchyToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var selectasset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
|
||||
if (selectasset.TreeNode != null)
|
||||
var selectAsset = (AssetItem)assetListView.Items[assetListView.SelectedIndices[0]];
|
||||
if (selectAsset.TreeNode != null)
|
||||
{
|
||||
sceneTreeView.SelectedNode = selectasset.TreeNode;
|
||||
sceneTreeView.SelectedNode = selectAsset.TreeNode;
|
||||
tabControl1.SelectedTab = tabPage1;
|
||||
}
|
||||
}
|
||||
@@ -1624,7 +1754,7 @@ namespace AssetStudioGUI
|
||||
ExportAssetsList(ExportFilter.Filtered);
|
||||
}
|
||||
|
||||
private void exportAllObjectssplitToolStripMenuItem1_Click(object sender, EventArgs e)
|
||||
private void exportAllObjectsSplitToolStripMenuItem1_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (sceneTreeView.Nodes.Count > 0)
|
||||
{
|
||||
@@ -1645,14 +1775,44 @@ namespace AssetStudioGUI
|
||||
|
||||
private void assetListView_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (assetListView.SelectedIndices.Count > 1)
|
||||
StatusStripUpdate($"Selected {assetListView.SelectedIndices.Count} assets.");
|
||||
ProcessSelectedItems();
|
||||
}
|
||||
|
||||
private void assetListView_VirtualItemsSelectionRangeChanged(object sender, ListViewVirtualItemsSelectionRangeChangedEventArgs e)
|
||||
{
|
||||
ProcessSelectedItems();
|
||||
}
|
||||
|
||||
private void ProcessSelectedItems()
|
||||
{
|
||||
if (assetListView.SelectedIndices.Count > 1)
|
||||
{
|
||||
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()
|
||||
@@ -1722,16 +1882,16 @@ namespace AssetStudioGUI
|
||||
{
|
||||
visibleAssets = visibleAssets.FindAll(x => Regex.IsMatch(x.SubItems[1].Text, pattern, regexOptions));
|
||||
}
|
||||
listSearch.BackColor = System.Drawing.Color.PaleGreen;
|
||||
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.PaleGreen;
|
||||
}
|
||||
catch (ArgumentException e)
|
||||
{
|
||||
listSearch.BackColor = System.Drawing.Color.FromArgb(255, 160, 160);
|
||||
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.FromArgb(255, 160, 160);
|
||||
StatusStripUpdate($"Regex error: {e.Message}");
|
||||
}
|
||||
catch (RegexMatchTimeoutException)
|
||||
{
|
||||
listSearch.BackColor = System.Drawing.Color.FromArgb(255, 160, 160);
|
||||
listSearch.BackColor = SystemInformation.HighContrast ? listSearch.BackColor : System.Drawing.Color.FromArgb(255, 160, 160);
|
||||
StatusStripUpdate($"Timeout error");
|
||||
}
|
||||
break;
|
||||
@@ -1764,6 +1924,19 @@ namespace AssetStudioGUI
|
||||
toExportAssets = visibleAssets;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1809,7 +1982,7 @@ namespace AssetStudioGUI
|
||||
|
||||
private void toolStripMenuItem15_Click(object sender, EventArgs e)
|
||||
{
|
||||
logger.ShowErrorMessage = toolStripMenuItem15.Checked;
|
||||
GUILogger.ShowDebugMessage = toolStripMenuItem15.Checked;
|
||||
}
|
||||
|
||||
private void sceneTreeView_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
|
||||
@@ -1832,7 +2005,7 @@ namespace AssetStudioGUI
|
||||
private void clearSelectionToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
treeRecursionEnabled = false;
|
||||
for(var i = 0; i < treeNodeSelectedList.Count; i++)
|
||||
for (var i = 0; i < treeNodeSelectedList.Count; i++)
|
||||
{
|
||||
treeNodeSelectedList[i].Checked = false;
|
||||
}
|
||||
@@ -1875,7 +2048,7 @@ namespace AssetStudioGUI
|
||||
|
||||
private void listSearchFilterMode_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
listSearch.BackColor = System.Drawing.Color.White;
|
||||
listSearch.BackColor = SystemColors.Window;
|
||||
if (listSearch.Text != " Filter ")
|
||||
{
|
||||
FilterAssetList();
|
||||
@@ -1889,42 +2062,6 @@ namespace AssetStudioGUI
|
||||
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)
|
||||
{
|
||||
var selectedItem = (ToolStripMenuItem)sender;
|
||||
@@ -1996,6 +2133,190 @@ namespace AssetStudioGUI
|
||||
}
|
||||
}
|
||||
|
||||
private void showConsoleToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var showConsole = showConsoleToolStripMenuItem.Checked;
|
||||
if (showConsole)
|
||||
ConsoleWindow.ShowConsoleWindow();
|
||||
else
|
||||
ConsoleWindow.HideConsoleWindow();
|
||||
|
||||
Properties.Settings.Default.showConsole = showConsole;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void writeLogToFileToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
var useFileLogger = writeLogToFileToolStripMenuItem.Checked;
|
||||
logger.UseFileLogger = useFileLogger;
|
||||
|
||||
Properties.Settings.Default.useFileLogger = useFileLogger;
|
||||
Properties.Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void AssetStudioGUIForm_FormClosing(object sender, FormClosingEventArgs e)
|
||||
{
|
||||
Logger.Verbose("Closing AssetStudio");
|
||||
}
|
||||
|
||||
private void buildTreeStructureToolStripMenuItem_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
Properties.Settings.Default.buildTreeStructure = buildTreeStructureToolStripMenuItem.Checked;
|
||||
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
|
||||
private void FMODinit()
|
||||
{
|
||||
@@ -2008,7 +2329,7 @@ namespace AssetStudioGUI
|
||||
ERRCHECK(result);
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
67
AssetStudioGUI/Components/ConsoleWindow.cs
Normal file
67
AssetStudioGUI/Components/ConsoleWindow.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using AssetStudio;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
internal static class ConsoleWindow
|
||||
{
|
||||
private enum CtrlSignalType
|
||||
{
|
||||
CTRL_C_EVENT,
|
||||
CTRL_BREAK_EVENT,
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool AllocConsole();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern IntPtr GetConsoleWindow();
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);
|
||||
|
||||
private delegate bool EventHandler(CtrlSignalType ctrlSignal);
|
||||
private static EventHandler eventHandler;
|
||||
private static IntPtr ConsoleWindowHandle;
|
||||
private static readonly int SW_HIDE = 0;
|
||||
private static readonly int SW_SHOW = 5;
|
||||
|
||||
private static bool CloseEventHandler(CtrlSignalType ctrlSignal)
|
||||
{
|
||||
switch (ctrlSignal)
|
||||
{
|
||||
case CtrlSignalType.CTRL_C_EVENT:
|
||||
case CtrlSignalType.CTRL_BREAK_EVENT:
|
||||
return true;
|
||||
default:
|
||||
Logger.Verbose("Closing AssetStudio");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunConsole(bool showConsole)
|
||||
{
|
||||
AllocConsole();
|
||||
ConsoleWindowHandle = GetConsoleWindow();
|
||||
eventHandler += CloseEventHandler;
|
||||
SetConsoleCtrlHandler(eventHandler, true);
|
||||
|
||||
if (!showConsole)
|
||||
HideConsoleWindow();
|
||||
}
|
||||
|
||||
public static void ShowConsoleWindow()
|
||||
{
|
||||
ShowWindow(ConsoleWindowHandle, SW_SHOW);
|
||||
}
|
||||
|
||||
public static void HideConsoleWindow()
|
||||
{
|
||||
ShowWindow(ConsoleWindowHandle, SW_HIDE);
|
||||
}
|
||||
}
|
||||
}
|
||||
164
AssetStudioGUI/Components/LnkReader.cs
Normal file
164
AssetStudioGUI/Components/LnkReader.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
// Shortcut (.lnk) file reader
|
||||
// by aelurum
|
||||
// Based on https://github.com/libyal/liblnk/blob/main/documentation/Windows%20Shortcut%20File%20(LNK)%20format.asciidoc
|
||||
|
||||
using AssetStudio;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
public static class LnkReader
|
||||
{
|
||||
[Flags]
|
||||
private enum LnkDataFlags
|
||||
{
|
||||
//The LNK file contains a link target identifier
|
||||
HasTargetIDList = 0x00000001,
|
||||
//The LNK file contains location information
|
||||
HasLinkInfo = 0x00000002,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum LnkLocFlags
|
||||
{
|
||||
//The linked file is on a volume
|
||||
//If set the volume information and the local path contain data
|
||||
VolumeIDAndLocalBasePath = 0x0001,
|
||||
//The linked file is on a network share
|
||||
//If set the network share information and common path contain data
|
||||
CommonNetworkRelativeLinkAndPathSuffix = 0x0002
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum PathTypeFlags
|
||||
{
|
||||
IsUnicodeLocalPath = 0x01,
|
||||
IsUnicodeNetShareName = 0x02,
|
||||
IsUnicodeCommonPath = 0x04
|
||||
}
|
||||
|
||||
public static string GetLnkTarget(string filePath)
|
||||
{
|
||||
var targetPath = string.Empty;
|
||||
var pathType = (PathTypeFlags)0;
|
||||
Encoding sysEncoding;
|
||||
try
|
||||
{
|
||||
sysEncoding = GetSysEncoding();
|
||||
Logger.Debug($"System default text encoding: {sysEncoding.CodePage}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error("Text encoding error", ex);
|
||||
return null;
|
||||
}
|
||||
|
||||
using (var reader = new FileReader(filePath))
|
||||
{
|
||||
reader.Endian = EndianType.LittleEndian;
|
||||
|
||||
var headerSize = reader.ReadUInt32(); //76 bytes
|
||||
reader.Position = 20; //skip LNK class identifier (GUID)
|
||||
var dataFlags = (LnkDataFlags)reader.ReadUInt32();
|
||||
if ((dataFlags & LnkDataFlags.HasLinkInfo) == 0)
|
||||
{
|
||||
Logger.Warning("Unsupported type of .lnk file. Link info was not found.");
|
||||
return null;
|
||||
}
|
||||
reader.Position = headerSize;
|
||||
|
||||
//Skip the shell item ID list
|
||||
if ((dataFlags & LnkDataFlags.HasTargetIDList) != 0)
|
||||
{
|
||||
var itemIDListSize = reader.ReadUInt16();
|
||||
reader.Position += itemIDListSize;
|
||||
}
|
||||
|
||||
//The offsets is relative to the start of the location information block
|
||||
var locInfoPos = reader.Position;
|
||||
var locInfoFullSize = reader.ReadUInt32();
|
||||
if (locInfoFullSize == 0)
|
||||
{
|
||||
Logger.Warning("Unsupported type of .lnk file. Link info was not found.");
|
||||
return null;
|
||||
}
|
||||
var locInfoHeaderSize = reader.ReadUInt32();
|
||||
var locFlags = (LnkLocFlags)reader.ReadUInt32();
|
||||
//Offset to the volume information block
|
||||
var offsetVolumeInfo = reader.ReadUInt32();
|
||||
//Offset to the ANSI local path
|
||||
var offsetLocalPath = reader.ReadUInt32();
|
||||
//Offset to the network share information block
|
||||
var offsetNetInfo = reader.ReadUInt32();
|
||||
//Offset to the ANSI common path. 0 if not available
|
||||
var offsetCommonPath = reader.ReadUInt32();
|
||||
if (locInfoHeaderSize > 28)
|
||||
{
|
||||
//Offset to the Unicode local path
|
||||
offsetLocalPath = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeLocalPath;
|
||||
}
|
||||
if (locInfoHeaderSize > 32)
|
||||
{
|
||||
//Offset to the Unicode common path
|
||||
offsetCommonPath = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeCommonPath;
|
||||
}
|
||||
|
||||
//Read local path, if exist
|
||||
if (offsetLocalPath > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetLocalPath;
|
||||
targetPath = (pathType & PathTypeFlags.IsUnicodeLocalPath) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
}
|
||||
|
||||
//Read network path, if exist
|
||||
if (locFlags == LnkLocFlags.CommonNetworkRelativeLinkAndPathSuffix)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo;
|
||||
var netInfoSize = reader.ReadUInt32();
|
||||
var netInfoFlags = reader.ReadUInt32();
|
||||
//Offset to the ANSI network share name. The offset is relative to the start of the network share information block
|
||||
var offsetNetShareName = reader.ReadUInt32();
|
||||
if (offsetNetShareName > 20)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo + 20;
|
||||
//Offset to the Unicode network share name
|
||||
offsetNetShareName = reader.ReadUInt32();
|
||||
pathType |= PathTypeFlags.IsUnicodeNetShareName;
|
||||
}
|
||||
if (offsetNetShareName > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetNetInfo + offsetNetShareName;
|
||||
targetPath = (pathType & PathTypeFlags.IsUnicodeNetShareName) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
//Read common path, if exist
|
||||
if (offsetCommonPath > 0)
|
||||
{
|
||||
reader.Position = locInfoPos + offsetCommonPath;
|
||||
var commonPath = (pathType & PathTypeFlags.IsUnicodeCommonPath) != 0
|
||||
? reader.ReadStringToNull(encoding: Encoding.Unicode)
|
||||
: reader.ReadStringToNull(encoding: sysEncoding);
|
||||
targetPath = Path.Combine(targetPath, commonPath);
|
||||
}
|
||||
}
|
||||
return targetPath;
|
||||
}
|
||||
|
||||
private static Encoding GetSysEncoding()
|
||||
{
|
||||
#if !NETFRAMEWORK
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
#endif
|
||||
return Encoding.GetEncoding(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,6 @@ namespace AssetStudioGUI
|
||||
public Bitmap Bitmap => m_bitmap;
|
||||
|
||||
private Bitmap m_bitmap;
|
||||
private readonly GCHandle m_handle;
|
||||
private GCHandle m_handle;
|
||||
}
|
||||
}
|
||||
|
||||
247
AssetStudioGUI/ExportOptions.Designer.cs
generated
247
AssetStudioGUI/ExportOptions.Designer.cs
generated
@@ -32,6 +32,8 @@
|
||||
this.OKbutton = new System.Windows.Forms.Button();
|
||||
this.Cancel = new System.Windows.Forms.Button();
|
||||
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.openAfterExport = new System.Windows.Forms.CheckBox();
|
||||
this.restoreExtensionName = new System.Windows.Forms.CheckBox();
|
||||
@@ -45,6 +47,12 @@
|
||||
this.topng = new System.Windows.Forms.RadioButton();
|
||||
this.tobmp = new System.Windows.Forms.RadioButton();
|
||||
this.converttexture = new System.Windows.Forms.CheckBox();
|
||||
this.l2dGroupBox = new System.Windows.Forms.GroupBox();
|
||||
this.l2dMotionExportMethodPanel = new System.Windows.Forms.Panel();
|
||||
this.l2dMonoBehaviourRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.l2dAnimationClipRadioButton = new System.Windows.Forms.RadioButton();
|
||||
this.l2dMotionExportMethodLabel = new System.Windows.Forms.Label();
|
||||
this.l2dForceBezierCheckBox = new System.Windows.Forms.CheckBox();
|
||||
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||
this.exportAllUvsAsDiffuseMaps = new System.Windows.Forms.CheckBox();
|
||||
this.exportBlendShape = new System.Windows.Forms.CheckBox();
|
||||
@@ -63,13 +71,19 @@
|
||||
this.castToBone = new System.Windows.Forms.CheckBox();
|
||||
this.exportAllNodes = new System.Windows.Forms.CheckBox();
|
||||
this.eulerFilter = new System.Windows.Forms.CheckBox();
|
||||
this.exportUvsTooltip = new System.Windows.Forms.ToolTip(this.components);
|
||||
this.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.panel1.SuspendLayout();
|
||||
this.l2dGroupBox.SuspendLayout();
|
||||
this.l2dMotionExportMethodPanel.SuspendLayout();
|
||||
this.groupBox2.SuspendLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.boneSize)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).BeginInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.parallelExportUpDown)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// OKbutton
|
||||
@@ -77,7 +91,7 @@
|
||||
this.OKbutton.Location = new System.Drawing.Point(381, 380);
|
||||
this.OKbutton.Name = "OKbutton";
|
||||
this.OKbutton.Size = new System.Drawing.Size(75, 23);
|
||||
this.OKbutton.TabIndex = 6;
|
||||
this.OKbutton.TabIndex = 4;
|
||||
this.OKbutton.Text = "OK";
|
||||
this.OKbutton.UseVisualStyleBackColor = true;
|
||||
this.OKbutton.Click += new System.EventHandler(this.OKbutton_Click);
|
||||
@@ -88,7 +102,7 @@
|
||||
this.Cancel.Location = new System.Drawing.Point(462, 380);
|
||||
this.Cancel.Name = "Cancel";
|
||||
this.Cancel.Size = new System.Drawing.Size(75, 23);
|
||||
this.Cancel.TabIndex = 7;
|
||||
this.Cancel.TabIndex = 5;
|
||||
this.Cancel.Text = "Cancel";
|
||||
this.Cancel.UseVisualStyleBackColor = true;
|
||||
this.Cancel.Click += new System.EventHandler(this.Cancel_Click);
|
||||
@@ -96,6 +110,11 @@
|
||||
// groupBox1
|
||||
//
|
||||
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.openAfterExport);
|
||||
this.groupBox1.Controls.Add(this.restoreExtensionName);
|
||||
@@ -106,11 +125,33 @@
|
||||
this.groupBox1.Controls.Add(this.converttexture);
|
||||
this.groupBox1.Location = new System.Drawing.Point(12, 13);
|
||||
this.groupBox1.Name = "groupBox1";
|
||||
this.groupBox1.Size = new System.Drawing.Size(301, 362);
|
||||
this.groupBox1.TabIndex = 9;
|
||||
this.groupBox1.Size = new System.Drawing.Size(301, 272);
|
||||
this.groupBox1.TabIndex = 1;
|
||||
this.groupBox1.TabStop = false;
|
||||
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
|
||||
//
|
||||
this.exportSpriteWithAlphaMask.AutoSize = true;
|
||||
@@ -119,7 +160,7 @@
|
||||
this.exportSpriteWithAlphaMask.Location = new System.Drawing.Point(6, 150);
|
||||
this.exportSpriteWithAlphaMask.Name = "exportSpriteWithAlphaMask";
|
||||
this.exportSpriteWithAlphaMask.Size = new System.Drawing.Size(205, 17);
|
||||
this.exportSpriteWithAlphaMask.TabIndex = 11;
|
||||
this.exportSpriteWithAlphaMask.TabIndex = 6;
|
||||
this.exportSpriteWithAlphaMask.Text = "Export sprites with alpha mask applied";
|
||||
this.exportSpriteWithAlphaMask.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -131,7 +172,7 @@
|
||||
this.openAfterExport.Location = new System.Drawing.Point(6, 196);
|
||||
this.openAfterExport.Name = "openAfterExport";
|
||||
this.openAfterExport.Size = new System.Drawing.Size(137, 17);
|
||||
this.openAfterExport.TabIndex = 10;
|
||||
this.openAfterExport.TabIndex = 8;
|
||||
this.openAfterExport.Text = "Open folder after export";
|
||||
this.openAfterExport.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -143,9 +184,9 @@
|
||||
this.restoreExtensionName.Location = new System.Drawing.Point(6, 63);
|
||||
this.restoreExtensionName.Name = "restoreExtensionName";
|
||||
this.restoreExtensionName.Size = new System.Drawing.Size(275, 17);
|
||||
this.restoreExtensionName.TabIndex = 9;
|
||||
this.restoreExtensionName.TabIndex = 3;
|
||||
this.restoreExtensionName.Text = "Try to restore/Use original TextAsset extension name";
|
||||
this.exportUvsTooltip.SetToolTip(this.restoreExtensionName, "If not checked, AssetStudio will export all TextAssets with the \".txt\" extension");
|
||||
this.optionTooltip.SetToolTip(this.restoreExtensionName, "If not checked, AssetStudio will export all TextAssets with the \".txt\" extension");
|
||||
this.restoreExtensionName.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// assetGroupOptions
|
||||
@@ -157,11 +198,12 @@
|
||||
"container path",
|
||||
"container path full (with name)",
|
||||
"source file name",
|
||||
"scene hierarchy",
|
||||
"do not group"});
|
||||
this.assetGroupOptions.Location = new System.Drawing.Point(6, 35);
|
||||
this.assetGroupOptions.Name = "assetGroupOptions";
|
||||
this.assetGroupOptions.Size = new System.Drawing.Size(165, 21);
|
||||
this.assetGroupOptions.TabIndex = 8;
|
||||
this.assetGroupOptions.TabIndex = 2;
|
||||
//
|
||||
// label6
|
||||
//
|
||||
@@ -169,7 +211,7 @@
|
||||
this.label6.Location = new System.Drawing.Point(6, 18);
|
||||
this.label6.Name = "label6";
|
||||
this.label6.Size = new System.Drawing.Size(127, 13);
|
||||
this.label6.TabIndex = 7;
|
||||
this.label6.TabIndex = 1;
|
||||
this.label6.Text = "Group exported assets by";
|
||||
//
|
||||
// convertAudio
|
||||
@@ -179,9 +221,9 @@
|
||||
this.convertAudio.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.convertAudio.Location = new System.Drawing.Point(6, 173);
|
||||
this.convertAudio.Name = "convertAudio";
|
||||
this.convertAudio.Size = new System.Drawing.Size(179, 17);
|
||||
this.convertAudio.TabIndex = 6;
|
||||
this.convertAudio.Text = "Convert AudioClip to WAV(PCM)";
|
||||
this.convertAudio.Size = new System.Drawing.Size(213, 17);
|
||||
this.convertAudio.TabIndex = 7;
|
||||
this.convertAudio.Text = "Convert FMOD AudioClip to WAV(PCM)";
|
||||
this.convertAudio.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// panel1
|
||||
@@ -202,8 +244,7 @@
|
||||
this.towebp.Location = new System.Drawing.Point(201, 7);
|
||||
this.towebp.Name = "towebp";
|
||||
this.towebp.Size = new System.Drawing.Size(54, 17);
|
||||
this.towebp.TabIndex = 5;
|
||||
this.towebp.TabStop = true;
|
||||
this.towebp.TabIndex = 4;
|
||||
this.towebp.Text = "Webp";
|
||||
this.towebp.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -213,7 +254,7 @@
|
||||
this.totga.Location = new System.Drawing.Point(150, 7);
|
||||
this.totga.Name = "totga";
|
||||
this.totga.Size = new System.Drawing.Size(44, 17);
|
||||
this.totga.TabIndex = 2;
|
||||
this.totga.TabIndex = 3;
|
||||
this.totga.Text = "Tga";
|
||||
this.totga.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -223,7 +264,7 @@
|
||||
this.tojpg.Location = new System.Drawing.Point(97, 7);
|
||||
this.tojpg.Name = "tojpg";
|
||||
this.tojpg.Size = new System.Drawing.Size(48, 17);
|
||||
this.tojpg.TabIndex = 4;
|
||||
this.tojpg.TabIndex = 2;
|
||||
this.tojpg.Text = "Jpeg";
|
||||
this.tojpg.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -234,7 +275,7 @@
|
||||
this.topng.Location = new System.Drawing.Point(50, 7);
|
||||
this.topng.Name = "topng";
|
||||
this.topng.Size = new System.Drawing.Size(44, 17);
|
||||
this.topng.TabIndex = 3;
|
||||
this.topng.TabIndex = 1;
|
||||
this.topng.TabStop = true;
|
||||
this.topng.Text = "Png";
|
||||
this.topng.UseVisualStyleBackColor = true;
|
||||
@@ -245,7 +286,7 @@
|
||||
this.tobmp.Location = new System.Drawing.Point(3, 7);
|
||||
this.tobmp.Name = "tobmp";
|
||||
this.tobmp.Size = new System.Drawing.Size(46, 17);
|
||||
this.tobmp.TabIndex = 2;
|
||||
this.tobmp.TabIndex = 0;
|
||||
this.tobmp.Text = "Bmp";
|
||||
this.tobmp.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -257,10 +298,76 @@
|
||||
this.converttexture.Location = new System.Drawing.Point(6, 87);
|
||||
this.converttexture.Name = "converttexture";
|
||||
this.converttexture.Size = new System.Drawing.Size(116, 17);
|
||||
this.converttexture.TabIndex = 1;
|
||||
this.converttexture.TabIndex = 4;
|
||||
this.converttexture.Text = "Convert Texture2D";
|
||||
this.converttexture.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// l2dGroupBox
|
||||
//
|
||||
this.l2dGroupBox.Controls.Add(this.l2dMotionExportMethodPanel);
|
||||
this.l2dGroupBox.Controls.Add(this.l2dMotionExportMethodLabel);
|
||||
this.l2dGroupBox.Controls.Add(this.l2dForceBezierCheckBox);
|
||||
this.l2dGroupBox.Location = new System.Drawing.Point(12, 275);
|
||||
this.l2dGroupBox.Name = "l2dGroupBox";
|
||||
this.l2dGroupBox.Size = new System.Drawing.Size(301, 100);
|
||||
this.l2dGroupBox.TabIndex = 2;
|
||||
this.l2dGroupBox.TabStop = false;
|
||||
this.l2dGroupBox.Text = "Cubism Live2D";
|
||||
//
|
||||
// l2dMotionExportMethodPanel
|
||||
//
|
||||
this.l2dMotionExportMethodPanel.Controls.Add(this.l2dMonoBehaviourRadioButton);
|
||||
this.l2dMotionExportMethodPanel.Controls.Add(this.l2dAnimationClipRadioButton);
|
||||
this.l2dMotionExportMethodPanel.Location = new System.Drawing.Point(18, 40);
|
||||
this.l2dMotionExportMethodPanel.Name = "l2dMotionExportMethodPanel";
|
||||
this.l2dMotionExportMethodPanel.Size = new System.Drawing.Size(263, 27);
|
||||
this.l2dMotionExportMethodPanel.TabIndex = 2;
|
||||
//
|
||||
// l2dMonoBehaviourRadioButton
|
||||
//
|
||||
this.l2dMonoBehaviourRadioButton.AccessibleName = "MonoBehaviour";
|
||||
this.l2dMonoBehaviourRadioButton.AutoSize = true;
|
||||
this.l2dMonoBehaviourRadioButton.Checked = true;
|
||||
this.l2dMonoBehaviourRadioButton.Location = new System.Drawing.Point(3, 5);
|
||||
this.l2dMonoBehaviourRadioButton.Name = "l2dMonoBehaviourRadioButton";
|
||||
this.l2dMonoBehaviourRadioButton.Size = new System.Drawing.Size(167, 17);
|
||||
this.l2dMonoBehaviourRadioButton.TabIndex = 0;
|
||||
this.l2dMonoBehaviourRadioButton.TabStop = true;
|
||||
this.l2dMonoBehaviourRadioButton.Text = "MonoBehaviour (Fade motion)";
|
||||
this.optionTooltip.SetToolTip(this.l2dMonoBehaviourRadioButton, "If no Fade motions are found, the AnimationClip method will be used");
|
||||
this.l2dMonoBehaviourRadioButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// l2dAnimationClipRadioButton
|
||||
//
|
||||
this.l2dAnimationClipRadioButton.AccessibleName = "AnimationClipV2";
|
||||
this.l2dAnimationClipRadioButton.AutoSize = true;
|
||||
this.l2dAnimationClipRadioButton.Location = new System.Drawing.Point(172, 5);
|
||||
this.l2dAnimationClipRadioButton.Name = "l2dAnimationClipRadioButton";
|
||||
this.l2dAnimationClipRadioButton.Size = new System.Drawing.Size(88, 17);
|
||||
this.l2dAnimationClipRadioButton.TabIndex = 1;
|
||||
this.l2dAnimationClipRadioButton.Text = "AnimationClip";
|
||||
this.l2dAnimationClipRadioButton.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// l2dMotionExportMethodLabel
|
||||
//
|
||||
this.l2dMotionExportMethodLabel.AutoSize = true;
|
||||
this.l2dMotionExportMethodLabel.Location = new System.Drawing.Point(6, 21);
|
||||
this.l2dMotionExportMethodLabel.Name = "l2dMotionExportMethodLabel";
|
||||
this.l2dMotionExportMethodLabel.Size = new System.Drawing.Size(109, 13);
|
||||
this.l2dMotionExportMethodLabel.TabIndex = 1;
|
||||
this.l2dMotionExportMethodLabel.Text = "Motion export method";
|
||||
//
|
||||
// l2dForceBezierCheckBox
|
||||
//
|
||||
this.l2dForceBezierCheckBox.AutoSize = true;
|
||||
this.l2dForceBezierCheckBox.Location = new System.Drawing.Point(6, 77);
|
||||
this.l2dForceBezierCheckBox.Name = "l2dForceBezierCheckBox";
|
||||
this.l2dForceBezierCheckBox.Size = new System.Drawing.Size(278, 17);
|
||||
this.l2dForceBezierCheckBox.TabIndex = 3;
|
||||
this.l2dForceBezierCheckBox.Text = "Calculate Linear motion segments as Bezier segments";
|
||||
this.optionTooltip.SetToolTip(this.l2dForceBezierCheckBox, "May help if the exported motions look jerky/not smooth enough");
|
||||
this.l2dForceBezierCheckBox.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// groupBox2
|
||||
//
|
||||
this.groupBox2.AutoSize = true;
|
||||
@@ -284,7 +391,7 @@
|
||||
this.groupBox2.Location = new System.Drawing.Point(313, 13);
|
||||
this.groupBox2.Name = "groupBox2";
|
||||
this.groupBox2.Size = new System.Drawing.Size(224, 362);
|
||||
this.groupBox2.TabIndex = 11;
|
||||
this.groupBox2.TabIndex = 3;
|
||||
this.groupBox2.TabStop = false;
|
||||
this.groupBox2.Text = "Fbx";
|
||||
//
|
||||
@@ -295,9 +402,9 @@
|
||||
this.exportAllUvsAsDiffuseMaps.Location = new System.Drawing.Point(6, 185);
|
||||
this.exportAllUvsAsDiffuseMaps.Name = "exportAllUvsAsDiffuseMaps";
|
||||
this.exportAllUvsAsDiffuseMaps.Size = new System.Drawing.Size(168, 17);
|
||||
this.exportAllUvsAsDiffuseMaps.TabIndex = 23;
|
||||
this.exportAllUvsAsDiffuseMaps.TabIndex = 9;
|
||||
this.exportAllUvsAsDiffuseMaps.Text = "Export all UVs as diffuse maps";
|
||||
this.exportUvsTooltip.SetToolTip(this.exportAllUvsAsDiffuseMaps, "Unchecked: UV1 exported as normal map. Check this if your export is missing a UV " +
|
||||
this.optionTooltip.SetToolTip(this.exportAllUvsAsDiffuseMaps, "Unchecked: UV1 exported as normal map. Check this if your export is missing a UV " +
|
||||
"map.");
|
||||
this.exportAllUvsAsDiffuseMaps.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -309,7 +416,7 @@
|
||||
this.exportBlendShape.Location = new System.Drawing.Point(6, 138);
|
||||
this.exportBlendShape.Name = "exportBlendShape";
|
||||
this.exportBlendShape.Size = new System.Drawing.Size(114, 17);
|
||||
this.exportBlendShape.TabIndex = 22;
|
||||
this.exportBlendShape.TabIndex = 7;
|
||||
this.exportBlendShape.Text = "Export blendshape";
|
||||
this.exportBlendShape.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -321,7 +428,7 @@
|
||||
this.exportAnimations.Location = new System.Drawing.Point(6, 114);
|
||||
this.exportAnimations.Name = "exportAnimations";
|
||||
this.exportAnimations.Size = new System.Drawing.Size(109, 17);
|
||||
this.exportAnimations.TabIndex = 21;
|
||||
this.exportAnimations.TabIndex = 6;
|
||||
this.exportAnimations.Text = "Export animations";
|
||||
this.exportAnimations.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -336,7 +443,7 @@
|
||||
this.scaleFactor.Location = new System.Drawing.Point(83, 243);
|
||||
this.scaleFactor.Name = "scaleFactor";
|
||||
this.scaleFactor.Size = new System.Drawing.Size(60, 20);
|
||||
this.scaleFactor.TabIndex = 20;
|
||||
this.scaleFactor.TabIndex = 13;
|
||||
this.scaleFactor.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
|
||||
this.scaleFactor.Value = new decimal(new int[] {
|
||||
1,
|
||||
@@ -350,7 +457,7 @@
|
||||
this.label5.Location = new System.Drawing.Point(6, 245);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(64, 13);
|
||||
this.label5.TabIndex = 19;
|
||||
this.label5.TabIndex = 12;
|
||||
this.label5.Text = "ScaleFactor";
|
||||
//
|
||||
// fbxFormat
|
||||
@@ -363,7 +470,7 @@
|
||||
this.fbxFormat.Location = new System.Drawing.Point(77, 275);
|
||||
this.fbxFormat.Name = "fbxFormat";
|
||||
this.fbxFormat.Size = new System.Drawing.Size(61, 21);
|
||||
this.fbxFormat.TabIndex = 18;
|
||||
this.fbxFormat.TabIndex = 15;
|
||||
//
|
||||
// label4
|
||||
//
|
||||
@@ -371,7 +478,7 @@
|
||||
this.label4.Location = new System.Drawing.Point(6, 280);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(59, 13);
|
||||
this.label4.TabIndex = 17;
|
||||
this.label4.TabIndex = 14;
|
||||
this.label4.Text = "FBXFormat";
|
||||
//
|
||||
// fbxVersion
|
||||
@@ -388,7 +495,7 @@
|
||||
this.fbxVersion.Location = new System.Drawing.Point(77, 308);
|
||||
this.fbxVersion.Name = "fbxVersion";
|
||||
this.fbxVersion.Size = new System.Drawing.Size(47, 21);
|
||||
this.fbxVersion.TabIndex = 16;
|
||||
this.fbxVersion.TabIndex = 17;
|
||||
//
|
||||
// label3
|
||||
//
|
||||
@@ -396,7 +503,7 @@
|
||||
this.label3.Location = new System.Drawing.Point(6, 311);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(62, 13);
|
||||
this.label3.TabIndex = 15;
|
||||
this.label3.TabIndex = 16;
|
||||
this.label3.Text = "FBXVersion";
|
||||
//
|
||||
// boneSize
|
||||
@@ -428,7 +535,7 @@
|
||||
this.exportSkins.Location = new System.Drawing.Point(6, 90);
|
||||
this.exportSkins.Name = "exportSkins";
|
||||
this.exportSkins.Size = new System.Drawing.Size(83, 17);
|
||||
this.exportSkins.TabIndex = 8;
|
||||
this.exportSkins.TabIndex = 5;
|
||||
this.exportSkins.Text = "Export skins";
|
||||
this.exportSkins.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -438,7 +545,7 @@
|
||||
this.label1.Location = new System.Drawing.Point(26, 42);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(72, 13);
|
||||
this.label1.TabIndex = 7;
|
||||
this.label1.TabIndex = 2;
|
||||
this.label1.Text = "FilterPrecision";
|
||||
//
|
||||
// filterPrecision
|
||||
@@ -452,7 +559,7 @@
|
||||
this.filterPrecision.Location = new System.Drawing.Point(127, 40);
|
||||
this.filterPrecision.Name = "filterPrecision";
|
||||
this.filterPrecision.Size = new System.Drawing.Size(51, 20);
|
||||
this.filterPrecision.TabIndex = 6;
|
||||
this.filterPrecision.TabIndex = 3;
|
||||
this.filterPrecision.Value = new decimal(new int[] {
|
||||
25,
|
||||
0,
|
||||
@@ -465,7 +572,7 @@
|
||||
this.castToBone.Location = new System.Drawing.Point(6, 161);
|
||||
this.castToBone.Name = "castToBone";
|
||||
this.castToBone.Size = new System.Drawing.Size(131, 17);
|
||||
this.castToBone.TabIndex = 5;
|
||||
this.castToBone.TabIndex = 8;
|
||||
this.castToBone.Text = "All nodes cast to bone";
|
||||
this.castToBone.UseVisualStyleBackColor = true;
|
||||
//
|
||||
@@ -489,10 +596,57 @@
|
||||
this.eulerFilter.Location = new System.Drawing.Point(6, 22);
|
||||
this.eulerFilter.Name = "eulerFilter";
|
||||
this.eulerFilter.Size = new System.Drawing.Size(72, 17);
|
||||
this.eulerFilter.TabIndex = 3;
|
||||
this.eulerFilter.TabIndex = 1;
|
||||
this.eulerFilter.Text = "EulerFilter";
|
||||
this.eulerFilter.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// parallelExportUpDown
|
||||
//
|
||||
this.parallelExportUpDown.Location = new System.Drawing.Point(209, 218);
|
||||
this.parallelExportUpDown.Maximum = new decimal(new int[] {
|
||||
8,
|
||||
0,
|
||||
0,
|
||||
0});
|
||||
this.parallelExportUpDown.Minimum = new decimal(new int[] {
|
||||
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
|
||||
//
|
||||
this.parallelExportCheckBox.AutoSize = true;
|
||||
this.parallelExportCheckBox.Checked = true;
|
||||
this.parallelExportCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
this.parallelExportCheckBox.Location = new System.Drawing.Point(6, 219);
|
||||
this.parallelExportCheckBox.Name = "parallelExportCheckBox";
|
||||
this.parallelExportCheckBox.Size = new System.Drawing.Size(203, 17);
|
||||
this.parallelExportCheckBox.TabIndex = 15;
|
||||
this.parallelExportCheckBox.Text = "Export in parallel with number of tasks";
|
||||
this.optionTooltip.SetToolTip(this.parallelExportCheckBox, "*Requires slightly more RAM than in single-task mode");
|
||||
this.parallelExportCheckBox.UseVisualStyleBackColor = true;
|
||||
this.parallelExportCheckBox.CheckedChanged += new System.EventHandler(this.parallelExportCheckBox_CheckedChanged);
|
||||
//
|
||||
// parallelExportMaxLabel
|
||||
//
|
||||
this.parallelExportMaxLabel.AutoSize = true;
|
||||
this.parallelExportMaxLabel.ForeColor = System.Drawing.SystemColors.ControlDark;
|
||||
this.parallelExportMaxLabel.Location = new System.Drawing.Point(256, 221);
|
||||
this.parallelExportMaxLabel.Name = "parallelExportMaxLabel";
|
||||
this.parallelExportMaxLabel.Size = new System.Drawing.Size(33, 13);
|
||||
this.parallelExportMaxLabel.TabIndex = 16;
|
||||
this.parallelExportMaxLabel.Text = "Max: ";
|
||||
this.optionTooltip.SetToolTip(this.parallelExportMaxLabel, "*The maximum number matches the number of CPU cores");
|
||||
//
|
||||
// ExportOptions
|
||||
//
|
||||
this.AcceptButton = this.OKbutton;
|
||||
@@ -500,6 +654,7 @@
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.CancelButton = this.Cancel;
|
||||
this.ClientSize = new System.Drawing.Size(549, 416);
|
||||
this.Controls.Add(this.l2dGroupBox);
|
||||
this.Controls.Add(this.groupBox2);
|
||||
this.Controls.Add(this.groupBox1);
|
||||
this.Controls.Add(this.Cancel);
|
||||
@@ -516,11 +671,16 @@
|
||||
this.groupBox1.PerformLayout();
|
||||
this.panel1.ResumeLayout(false);
|
||||
this.panel1.PerformLayout();
|
||||
this.l2dGroupBox.ResumeLayout(false);
|
||||
this.l2dGroupBox.PerformLayout();
|
||||
this.l2dMotionExportMethodPanel.ResumeLayout(false);
|
||||
this.l2dMotionExportMethodPanel.PerformLayout();
|
||||
this.groupBox2.ResumeLayout(false);
|
||||
this.groupBox2.PerformLayout();
|
||||
((System.ComponentModel.ISupportInitialize)(this.scaleFactor)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.boneSize)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.filterPrecision)).EndInit();
|
||||
((System.ComponentModel.ISupportInitialize)(this.parallelExportUpDown)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
@@ -559,8 +719,19 @@
|
||||
private System.Windows.Forms.CheckBox restoreExtensionName;
|
||||
private System.Windows.Forms.CheckBox openAfterExport;
|
||||
private System.Windows.Forms.CheckBox exportAllUvsAsDiffuseMaps;
|
||||
private System.Windows.Forms.ToolTip exportUvsTooltip;
|
||||
private System.Windows.Forms.ToolTip optionTooltip;
|
||||
private System.Windows.Forms.CheckBox exportSpriteWithAlphaMask;
|
||||
private System.Windows.Forms.RadioButton towebp;
|
||||
private System.Windows.Forms.GroupBox l2dGroupBox;
|
||||
private System.Windows.Forms.CheckBox l2dForceBezierCheckBox;
|
||||
private System.Windows.Forms.Label l2dMotionExportMethodLabel;
|
||||
private System.Windows.Forms.RadioButton l2dAnimationClipRadioButton;
|
||||
private System.Windows.Forms.RadioButton l2dMonoBehaviourRadioButton;
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using AssetStudio;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
@@ -14,15 +15,8 @@ namespace AssetStudioGUI
|
||||
converttexture.Checked = Properties.Settings.Default.convertTexture;
|
||||
exportSpriteWithAlphaMask.Checked = Properties.Settings.Default.exportSpriteWithMask;
|
||||
convertAudio.Checked = Properties.Settings.Default.convertAudio;
|
||||
var str = Properties.Settings.Default.convertType.ToString();
|
||||
foreach (Control c in panel1.Controls)
|
||||
{
|
||||
if (c.Text == str)
|
||||
{
|
||||
((RadioButton)c).Checked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var defaultImageType = Properties.Settings.Default.convertType.ToString();
|
||||
((RadioButton)panel1.Controls.Cast<Control>().First(x => x.Text == defaultImageType)).Checked = true;
|
||||
openAfterExport.Checked = Properties.Settings.Default.openAfterExport;
|
||||
eulerFilter.Checked = Properties.Settings.Default.eulerFilter;
|
||||
filterPrecision.Value = Properties.Settings.Default.filterPrecision;
|
||||
@@ -36,7 +30,16 @@ namespace AssetStudioGUI
|
||||
scaleFactor.Value = Properties.Settings.Default.scaleFactor;
|
||||
fbxVersion.SelectedIndex = Properties.Settings.Default.fbxVersion;
|
||||
fbxFormat.SelectedIndex = Properties.Settings.Default.fbxFormat;
|
||||
|
||||
var defaultMotionMode = Properties.Settings.Default.l2dMotionMode.ToString();
|
||||
((RadioButton)l2dMotionExportMethodPanel.Controls.Cast<Control>().First(x => x.AccessibleName == defaultMotionMode)).Checked = true;
|
||||
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)
|
||||
@@ -46,14 +49,8 @@ namespace AssetStudioGUI
|
||||
Properties.Settings.Default.convertTexture = converttexture.Checked;
|
||||
Properties.Settings.Default.exportSpriteWithMask = exportSpriteWithAlphaMask.Checked;
|
||||
Properties.Settings.Default.convertAudio = convertAudio.Checked;
|
||||
foreach (Control c in panel1.Controls)
|
||||
{
|
||||
if (((RadioButton)c).Checked)
|
||||
{
|
||||
Properties.Settings.Default.convertType = (ImageFormat)Enum.Parse(typeof(ImageFormat), c.Text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
var checkedImageType = (RadioButton)panel1.Controls.Cast<Control>().First(x => ((RadioButton)x).Checked);
|
||||
Properties.Settings.Default.convertType = (ImageFormat)Enum.Parse(typeof(ImageFormat), checkedImageType.Text);
|
||||
Properties.Settings.Default.openAfterExport = openAfterExport.Checked;
|
||||
Properties.Settings.Default.eulerFilter = eulerFilter.Checked;
|
||||
Properties.Settings.Default.filterPrecision = filterPrecision.Value;
|
||||
@@ -67,6 +64,12 @@ namespace AssetStudioGUI
|
||||
Properties.Settings.Default.scaleFactor = scaleFactor.Value;
|
||||
Properties.Settings.Default.fbxVersion = fbxVersion.SelectedIndex;
|
||||
Properties.Settings.Default.fbxFormat = fbxFormat.SelectedIndex;
|
||||
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.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();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
@@ -77,5 +80,10 @@ namespace AssetStudioGUI
|
||||
DialogResult = DialogResult.Cancel;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void parallelExportCheckBox_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
parallelExportUpDown.Enabled = parallelExportCheckBox.Checked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,13 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||
<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>
|
||||
<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>
|
||||
@@ -9,60 +9,6 @@ namespace AssetStudioGUI
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".shader", out var exportFullPath))
|
||||
@@ -237,50 +183,43 @@ namespace AssetStudioGUI
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ExportSprite(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 = ((Sprite)item.Asset).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 ExportRawFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath))
|
||||
if (!TryExportFile(exportPath, item, ".dat", out var exportFullPath, mode: "ExportRaw"))
|
||||
return false;
|
||||
File.WriteAllBytes(exportFullPath, item.Asset.GetRawData());
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath)
|
||||
private static bool TryExportFile(string dir, AssetItem item, string extension, out string fullPath, string mode = "Export")
|
||||
{
|
||||
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 (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
if (filenameFormatIndex == 0) //assetName
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
fullPath = Path.Combine(dir, fileName + item.UniqueID + extension);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Logger.Warning($"{mode} failed. File \"{fullPath.Color(ColorConsole.BrightYellow)}\" already exist");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -337,7 +276,7 @@ namespace AssetStudioGUI
|
||||
|
||||
public static bool ExportDumpFile(AssetItem item, string exportPath)
|
||||
{
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath, mode: "Dump"))
|
||||
return false;
|
||||
var str = item.Asset.Dump();
|
||||
if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour)
|
||||
@@ -345,6 +284,10 @@ namespace AssetStudioGUI
|
||||
var m_Type = Studio.MonoBehaviourToTypeTree(m_MonoBehaviour);
|
||||
str = m_MonoBehaviour.Dump(m_Type);
|
||||
}
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
str = item.Asset.DumpObject();
|
||||
}
|
||||
if (str != null)
|
||||
{
|
||||
File.WriteAllText(exportFullPath, str);
|
||||
@@ -358,9 +301,11 @@ namespace AssetStudioGUI
|
||||
switch (item.Type)
|
||||
{
|
||||
case ClassIDType.Texture2D:
|
||||
return ExportTexture2D(item, exportPath);
|
||||
case ClassIDType.Texture2DArrayImage:
|
||||
case ClassIDType.Texture2DArray:
|
||||
case ClassIDType.AudioClip:
|
||||
return ExportAudioClip(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
throw new System.NotImplementedException();
|
||||
case ClassIDType.Shader:
|
||||
return ExportShader(item, exportPath);
|
||||
case ClassIDType.TextAsset:
|
||||
@@ -375,8 +320,6 @@ namespace AssetStudioGUI
|
||||
return ExportVideoClip(item, exportPath);
|
||||
case ClassIDType.MovieTexture:
|
||||
return ExportMovieTexture(item, exportPath);
|
||||
case ClassIDType.Sprite:
|
||||
return ExportSprite(item, exportPath);
|
||||
case ClassIDType.Animator:
|
||||
return ExportAnimator(item, exportPath);
|
||||
case ClassIDType.AnimationClip:
|
||||
@@ -388,8 +331,9 @@ namespace AssetStudioGUI
|
||||
|
||||
public static string FixFileName(string str)
|
||||
{
|
||||
if (str.Length >= 260) return Path.GetRandomFileName();
|
||||
return Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
return str.Length >= 260
|
||||
? Path.GetRandomFileName()
|
||||
: Path.GetInvalidFileNameChars().Aggregate(str, (current, c) => current.Replace(c, '_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,181 @@
|
||||
using AssetStudio;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
{
|
||||
class GUILogger : ILogger
|
||||
{
|
||||
public bool ShowErrorMessage = false;
|
||||
public static bool ShowDebugMessage = false;
|
||||
|
||||
private bool isFileLoggerRunning = false;
|
||||
private string loggerInitString;
|
||||
private string fileLogName;
|
||||
private string fileLogPath;
|
||||
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;
|
||||
public bool UseFileLogger
|
||||
{
|
||||
get => _useFileLogger;
|
||||
set
|
||||
{
|
||||
_useFileLogger = value;
|
||||
if (_useFileLogger && !isFileLoggerRunning)
|
||||
{
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
fileLogName = $"{appAssembly.Name}_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log";
|
||||
fileLogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileLogName);
|
||||
tokenSource = new CancellationTokenSource();
|
||||
isFileLoggerRunning = true;
|
||||
|
||||
ConcurrentFileWriter(tokenSource.Token);
|
||||
LogToFile(LoggerEvent.Verbose, $"# {loggerInitString} - Logger launched #");
|
||||
}
|
||||
else if (!_useFileLogger && isFileLoggerRunning)
|
||||
{
|
||||
LogToFile(LoggerEvent.Verbose, "# Logger closed #");
|
||||
isFileLoggerRunning = false;
|
||||
tokenSource.Cancel();
|
||||
tokenSource.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GUILogger(Action<string> action)
|
||||
{
|
||||
this.action = action;
|
||||
|
||||
var appAssembly = typeof(Program).Assembly.GetName();
|
||||
var arch = Environment.Is64BitProcess ? "x64" : "x32";
|
||||
var frameworkName = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
|
||||
loggerInitString = $"{appAssembly.Name} v{appAssembly.Version} [{arch}] [{frameworkName}]";
|
||||
try
|
||||
{
|
||||
Console.Title = $"Console Logger - {appAssembly.Name} v{appAssembly.Version}";
|
||||
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
ConcurrentConsoleWriter();
|
||||
Console.WriteLine($"# {loggerInitString}");
|
||||
}
|
||||
|
||||
private static string ColorLogLevel(LoggerEvent logLevel)
|
||||
{
|
||||
var formattedLevel = $"[{logLevel}]";
|
||||
switch (logLevel)
|
||||
{
|
||||
case LoggerEvent.Info:
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightCyan)}";
|
||||
case LoggerEvent.Warning:
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightYellow)}";
|
||||
case LoggerEvent.Error:
|
||||
return $"{formattedLevel.Color(ColorConsole.BrightRed)}";
|
||||
default:
|
||||
return formattedLevel;
|
||||
}
|
||||
}
|
||||
|
||||
private static string FormatMessage(LoggerEvent logMsgLevel, string message, bool toConsole)
|
||||
{
|
||||
message = message.TrimEnd();
|
||||
var multiLine = message.Contains("\n");
|
||||
|
||||
string formattedMessage;
|
||||
if (toConsole)
|
||||
{
|
||||
var colorLogLevel = ColorLogLevel(logMsgLevel);
|
||||
formattedMessage = $"{colorLogLevel} {message}";
|
||||
if (multiLine)
|
||||
{
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{colorLogLevel} ") + $"\n{colorLogLevel}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var curTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
message = Regex.Replace(message, @"\e\[[0-9;]*m(?:\e\[K)?", ""); //Delete ANSI colors
|
||||
var logLevel = $"{logMsgLevel.ToString().ToUpper(),-7}";
|
||||
formattedMessage = $"{curTime} | {logLevel} | {message}";
|
||||
if (multiLine)
|
||||
{
|
||||
formattedMessage = formattedMessage.Replace("\n", $"\n{curTime} | {logLevel} | ") + $"\n{curTime} | {logLevel} |";
|
||||
}
|
||||
}
|
||||
return formattedMessage;
|
||||
}
|
||||
|
||||
private void ConcurrentFileWriter(CancellationToken token)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
using (var sw = new StreamWriter(fileLogPath, append: true, System.Text.Encoding.UTF8))
|
||||
{
|
||||
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)
|
||||
{
|
||||
//File logger
|
||||
if (_useFileLogger)
|
||||
{
|
||||
LogToFile(loggerEvent, message);
|
||||
}
|
||||
|
||||
//Console logger
|
||||
if (!ShowDebugMessage && loggerEvent == LoggerEvent.Debug)
|
||||
return;
|
||||
LogToConsole(loggerEvent, message);
|
||||
|
||||
//GUI logger
|
||||
switch (loggerEvent)
|
||||
{
|
||||
case LoggerEvent.Error:
|
||||
MessageBox.Show(message, "Error");
|
||||
break;
|
||||
case LoggerEvent.Warning:
|
||||
if (ShowErrorMessage)
|
||||
{
|
||||
MessageBox.Show(message, "Warning");
|
||||
}
|
||||
else
|
||||
{
|
||||
action("An error has occurred. Turn on \"Show all error messages\" to see details next time.");
|
||||
}
|
||||
action("Some warnings occurred. See Console Logger for details.");
|
||||
break;
|
||||
case LoggerEvent.Debug:
|
||||
break;
|
||||
|
||||
226
AssetStudioGUI/ParallelExport.cs
Normal file
226
AssetStudioGUI/ParallelExport.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
110
AssetStudioGUI/Properties/Settings.Designer.cs
generated
110
AssetStudioGUI/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace AssetStudioGUI.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -286,5 +286,113 @@ namespace AssetStudioGUI.Properties {
|
||||
this["exportSpriteWithMask"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("MonoBehaviour")]
|
||||
public global::CubismLive2DExtractor.Live2DMotionMode l2dMotionMode {
|
||||
get {
|
||||
return ((global::CubismLive2DExtractor.Live2DMotionMode)(this["l2dMotionMode"]));
|
||||
}
|
||||
set {
|
||||
this["l2dMotionMode"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool l2dForceBezier {
|
||||
get {
|
||||
return ((bool)(this["l2dForceBezier"]));
|
||||
}
|
||||
set {
|
||||
this["l2dForceBezier"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool showConsole {
|
||||
get {
|
||||
return ((bool)(this["showConsole"]));
|
||||
}
|
||||
set {
|
||||
this["showConsole"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool useFileLogger {
|
||||
get {
|
||||
return ((bool)(this["useFileLogger"]));
|
||||
}
|
||||
set {
|
||||
this["useFileLogger"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("True")]
|
||||
public bool buildTreeStructure {
|
||||
get {
|
||||
return ((bool)(this["buildTreeStructure"]));
|
||||
}
|
||||
set {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,5 +68,32 @@
|
||||
<Setting Name="exportSpriteWithMask" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="l2dMotionMode" Type="CubismLive2DExtractor.Live2DMotionMode" Scope="User">
|
||||
<Value Profile="(Default)">MonoBehaviour</Value>
|
||||
</Setting>
|
||||
<Setting Name="l2dForceBezier" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="showConsole" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</Setting>
|
||||
<Setting Name="useFileLogger" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="buildTreeStructure" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">True</Value>
|
||||
</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>
|
||||
</SettingsFile>
|
||||
@@ -1,15 +1,17 @@
|
||||
using AssetStudio;
|
||||
using CubismLive2DExtractor;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using System.Xml.Linq;
|
||||
using static AssetStudioGUI.Exporter;
|
||||
using static CubismLive2DExtractor.Live2DExtractor;
|
||||
using Object = AssetStudio.Object;
|
||||
|
||||
namespace AssetStudioGUI
|
||||
@@ -28,6 +30,15 @@ namespace AssetStudioGUI
|
||||
Filtered
|
||||
}
|
||||
|
||||
internal enum ExportL2DFilter
|
||||
{
|
||||
All,
|
||||
Selected,
|
||||
SelectedWithFadeList,
|
||||
SelectedWithFade,
|
||||
SelectedWithClips,
|
||||
}
|
||||
|
||||
internal enum ExportListType
|
||||
{
|
||||
XML
|
||||
@@ -38,7 +49,8 @@ namespace AssetStudioGUI
|
||||
TypeName,
|
||||
ContainerPath,
|
||||
ContainerPathFull,
|
||||
SourceFileName
|
||||
SourceFileName,
|
||||
SceneHierarchy,
|
||||
}
|
||||
|
||||
internal enum ListSearchFilterMode
|
||||
@@ -49,13 +61,24 @@ namespace AssetStudioGUI
|
||||
RegexContainer,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
internal enum SelectedAssetType
|
||||
{
|
||||
Animator = 0x01,
|
||||
AnimationClip = 0x02,
|
||||
MonoBehaviourMoc = 0x04,
|
||||
MonoBehaviourFade = 0x08,
|
||||
MonoBehaviourFadeLst = 0x10
|
||||
}
|
||||
|
||||
internal static class Studio
|
||||
{
|
||||
public static AssetsManager assetsManager = new AssetsManager();
|
||||
public static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
||||
public static List<AssetItem> exportableAssets = new List<AssetItem>();
|
||||
public static List<AssetItem> visibleAssets = new List<AssetItem>();
|
||||
private static Dictionary<Object, string> allContainers = new Dictionary<Object, string>();
|
||||
public static List<MonoBehaviour> cubismMocList = new List<MonoBehaviour>();
|
||||
private static Dictionary<Object, string> l2dResourceContainers = new Dictionary<Object, string>();
|
||||
internal static Action<string> StatusStripUpdate = x => { };
|
||||
|
||||
public static int ExtractFolder(string path, string savePath)
|
||||
@@ -103,7 +126,7 @@ namespace AssetStudioGUI
|
||||
private static int ExtractBundleFile(FileReader reader, string savePath)
|
||||
{
|
||||
Logger.Info($"Decompressing {reader.FileName} ...");
|
||||
var bundleFile = new BundleFile(reader, assetsManager.SpecifyUnityVersion);
|
||||
var bundleFile = new BundleFile(reader, assetsManager.ZstdEnabled, assetsManager.SpecifyUnityVersion);
|
||||
reader.Dispose();
|
||||
if (bundleFile.fileList.Length > 0)
|
||||
{
|
||||
@@ -158,10 +181,14 @@ namespace AssetStudioGUI
|
||||
var objectCount = assetsManager.assetsFileList.Sum(x => x.Objects.Count);
|
||||
var objectAssetItemDic = new Dictionary<Object, AssetItem>(objectCount);
|
||||
var containers = new List<(PPtr<Object>, string)>();
|
||||
int i = 0;
|
||||
var tex2dArrayAssetList = new List<AssetItem>();
|
||||
l2dResourceContainers.Clear();
|
||||
var i = 0;
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
var preloadTable = Array.Empty<PPtr<Object>>();
|
||||
|
||||
foreach (var asset in assetsFile.Objects)
|
||||
{
|
||||
var assetItem = new AssetItem(asset);
|
||||
@@ -170,6 +197,9 @@ namespace AssetStudioGUI
|
||||
var exportable = false;
|
||||
switch (asset)
|
||||
{
|
||||
case PreloadData m_PreloadData:
|
||||
preloadTable = m_PreloadData.m_Assets;
|
||||
break;
|
||||
case GameObject m_GameObject:
|
||||
assetItem.Text = m_GameObject.m_Name;
|
||||
break;
|
||||
@@ -179,6 +209,13 @@ namespace AssetStudioGUI
|
||||
assetItem.Text = m_Texture2D.m_Name;
|
||||
exportable = true;
|
||||
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:
|
||||
if (!string.IsNullOrEmpty(m_AudioClip.m_Source))
|
||||
assetItem.FullSize = asset.byteSize + m_AudioClip.m_Size;
|
||||
@@ -187,7 +224,7 @@ namespace AssetStudioGUI
|
||||
break;
|
||||
case VideoClip m_VideoClip:
|
||||
if (!string.IsNullOrEmpty(m_VideoClip.m_OriginalPath))
|
||||
assetItem.FullSize = asset.byteSize + (long)m_VideoClip.m_ExternalResources.m_Size;
|
||||
assetItem.FullSize = asset.byteSize + m_VideoClip.m_ExternalResources.m_Size;
|
||||
assetItem.Text = m_VideoClip.m_Name;
|
||||
exportable = true;
|
||||
break;
|
||||
@@ -212,31 +249,39 @@ namespace AssetStudioGUI
|
||||
exportable = true;
|
||||
break;
|
||||
case MonoBehaviour m_MonoBehaviour:
|
||||
if (m_MonoBehaviour.m_Name == "" && m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||
var assetName = m_MonoBehaviour.m_Name;
|
||||
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||
{
|
||||
assetItem.Text = m_Script.m_ClassName;
|
||||
}
|
||||
else
|
||||
{
|
||||
assetItem.Text = m_MonoBehaviour.m_Name;
|
||||
assetName = assetName == "" ? m_Script.m_ClassName : assetName;
|
||||
if (m_Script.m_ClassName == "CubismMoc")
|
||||
{
|
||||
cubismMocList.Add(m_MonoBehaviour);
|
||||
}
|
||||
}
|
||||
assetItem.Text = assetName;
|
||||
exportable = true;
|
||||
break;
|
||||
case PlayerSettings m_PlayerSettings:
|
||||
productName = m_PlayerSettings.productName;
|
||||
break;
|
||||
case AssetBundle m_AssetBundle:
|
||||
var isStreamedSceneAssetBundle = m_AssetBundle.m_IsStreamedSceneAssetBundle;
|
||||
if (!isStreamedSceneAssetBundle)
|
||||
{
|
||||
preloadTable = m_AssetBundle.m_PreloadTable;
|
||||
}
|
||||
assetItem.Text = string.IsNullOrEmpty(m_AssetBundle.m_AssetBundleName) ? m_AssetBundle.m_Name : m_AssetBundle.m_AssetBundleName;
|
||||
|
||||
foreach (var m_Container in m_AssetBundle.m_Container)
|
||||
{
|
||||
var preloadIndex = m_Container.Value.preloadIndex;
|
||||
var preloadSize = m_Container.Value.preloadSize;
|
||||
var preloadSize = isStreamedSceneAssetBundle ? preloadTable.Length : m_Container.Value.preloadSize;
|
||||
var preloadEnd = preloadIndex + preloadSize;
|
||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||
for (var k = preloadIndex; k < preloadEnd; k++)
|
||||
{
|
||||
containers.Add((m_AssetBundle.m_PreloadTable[k], m_Container.Key));
|
||||
containers.Add((preloadTable[k], m_Container.Key));
|
||||
}
|
||||
}
|
||||
assetItem.Text = m_AssetBundle.m_Name;
|
||||
break;
|
||||
case ResourceManager m_ResourceManager:
|
||||
foreach (var m_Container in m_ResourceManager.m_Container)
|
||||
@@ -259,12 +304,36 @@ namespace AssetStudioGUI
|
||||
Progress.Report(++i, objectCount);
|
||||
}
|
||||
}
|
||||
foreach ((var pptr, var container) in containers)
|
||||
foreach (var (pptr, container) in containers)
|
||||
{
|
||||
if (pptr.TryGet(out var obj))
|
||||
{
|
||||
objectAssetItemDic[obj].Container = container;
|
||||
allContainers[obj] = container;
|
||||
switch (obj)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Text = fakeObj.m_Name,
|
||||
Container = tex2dAssetItem.Container
|
||||
};
|
||||
exportableAssets.Add(fakeItem);
|
||||
}
|
||||
}
|
||||
foreach (var tmp in exportableAssets)
|
||||
@@ -272,15 +341,23 @@ namespace AssetStudioGUI
|
||||
tmp.SetSubItems();
|
||||
}
|
||||
containers.Clear();
|
||||
tex2dArrayAssetList.Clear();
|
||||
|
||||
visibleAssets = exportableAssets;
|
||||
|
||||
if (!Properties.Settings.Default.buildTreeStructure)
|
||||
{
|
||||
Logger.Info("Building tree structure step is skipped");
|
||||
objectAssetItemDic.Clear();
|
||||
return (productName, new List<TreeNode>());
|
||||
}
|
||||
|
||||
Logger.Info("Building tree structure...");
|
||||
|
||||
var treeNodeCollection = new List<TreeNode>();
|
||||
var treeNodeDictionary = new Dictionary<GameObject, GameObjectTreeNode>();
|
||||
var assetsFileCount = assetsManager.assetsFileList.Count;
|
||||
int j = 0;
|
||||
var j = 0;
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||
{
|
||||
@@ -335,7 +412,6 @@ namespace AssetStudioGUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parentNode.Nodes.Add(currentNode);
|
||||
}
|
||||
}
|
||||
@@ -348,7 +424,6 @@ namespace AssetStudioGUI
|
||||
Progress.Report(++j, assetsFileCount);
|
||||
}
|
||||
treeNodeDictionary.Clear();
|
||||
|
||||
objectAssetItemDic.Clear();
|
||||
|
||||
return (productName, treeNodeCollection);
|
||||
@@ -386,7 +461,6 @@ namespace AssetStudioGUI
|
||||
typeMap.Add(assetsFile.unityVersion, items);
|
||||
}
|
||||
}
|
||||
|
||||
return typeMap;
|
||||
}
|
||||
|
||||
@@ -396,12 +470,21 @@ namespace AssetStudioGUI
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
|
||||
|
||||
int toExportCount = toExportAssets.Count;
|
||||
int exportedCount = 0;
|
||||
int i = 0;
|
||||
Progress.Reset();
|
||||
var groupOption = (AssetGroupOption)Properties.Settings.Default.assetGroupOption;
|
||||
foreach (var asset in toExportAssets)
|
||||
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;
|
||||
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();
|
||||
|
||||
Parallel.ForEach(toExportAssets, asset =>
|
||||
{
|
||||
string exportPath;
|
||||
switch (groupOption)
|
||||
@@ -434,52 +517,146 @@ namespace AssetStudioGUI
|
||||
exportPath = Path.Combine(savePath, Path.GetFileName(asset.SourceFile.originalPath) + "_export", asset.SourceFile.fileName);
|
||||
}
|
||||
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:
|
||||
exportPath = savePath;
|
||||
break;
|
||||
}
|
||||
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
|
||||
{
|
||||
Logger.Info($"[{exportedCount + 1}/{toExportCount}] {mode}ing {asset.TypeString}: {asset.Text}");
|
||||
switch (exportType)
|
||||
{
|
||||
case ExportType.Raw:
|
||||
if (ExportRawFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportRawFile(asset, exportPath);
|
||||
break;
|
||||
case ExportType.Dump:
|
||||
if (ExportDumpFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportDumpFile(asset, exportPath);
|
||||
break;
|
||||
case ExportType.Convert:
|
||||
if (ExportConvertFile(asset, exportPath))
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
isExported = ExportConvertFile(asset, exportPath);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Export {asset.Type}:{asset.Text} error", ex);
|
||||
Logger.Error($"{mode} {asset.TypeString}: {asset.Text} error", ex);
|
||||
}
|
||||
|
||||
if (isExported)
|
||||
{
|
||||
exportedCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Warning($"Unable to {mode.ToLower()} {asset.TypeString}: {asset.Text}");
|
||||
}
|
||||
|
||||
Progress.Report(++i, toExportCount);
|
||||
}
|
||||
|
||||
var statusText = exportedCount == 0 ? "Nothing exported." : $"Finished exporting {exportedCount} assets.";
|
||||
|
||||
if (toExportCount > exportedCount)
|
||||
Parallel.ForEach(toParallelExportAssetDict, new ParallelOptions { MaxDegreeOfParallelism = parallelExportCount }, (toExportAsset, loopState) =>
|
||||
{
|
||||
statusText += $" {toExportCount - exportedCount} assets skipped (not extractable or files already exist)";
|
||||
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)
|
||||
{
|
||||
statusText += exceptionMsgs.IsEmpty
|
||||
? $" {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);
|
||||
exceptionMsgs.Clear();
|
||||
|
||||
if (Properties.Settings.Default.openAfterExport && exportedCount > 0)
|
||||
{
|
||||
@@ -511,6 +688,7 @@ namespace AssetStudioGUI
|
||||
new XElement("Type", new XAttribute("id", (int)asset.Type), asset.TypeString),
|
||||
new XElement("PathID", asset.m_PathID),
|
||||
new XElement("Source", asset.SourceFile.fullName),
|
||||
new XElement("TreeNode", asset.TreeNode != null ? asset.TreeNode.FullPath : ""),
|
||||
new XElement("Size", asset.FullSize)
|
||||
)
|
||||
)
|
||||
@@ -522,11 +700,11 @@ namespace AssetStudioGUI
|
||||
break;
|
||||
}
|
||||
|
||||
var statusText = $"Finished exporting asset list with {toExportAssets.Count()} items.";
|
||||
var statusText = $"Finished exporting asset list with {toExportAssets.Count} items.";
|
||||
|
||||
Logger.Info(statusText);
|
||||
|
||||
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count() > 0)
|
||||
if (Properties.Settings.Default.openAfterExport && toExportAssets.Count > 0)
|
||||
{
|
||||
OpenFolderInExplorer(savePath);
|
||||
}
|
||||
@@ -609,6 +787,7 @@ namespace AssetStudioGUI
|
||||
{
|
||||
Progress.Reset();
|
||||
Logger.Info($"Exporting {animator.Text}");
|
||||
Logger.Debug($"Selected AnimationClip(s):\n\"{string.Join("\"\n\"", animationList.Select(x => x.Text))}\"");
|
||||
try
|
||||
{
|
||||
ExportAnimator(animator, exportPath, animationList);
|
||||
@@ -707,6 +886,12 @@ namespace AssetStudioGUI
|
||||
}
|
||||
|
||||
public static TypeTree MonoBehaviourToTypeTree(MonoBehaviour m_MonoBehaviour)
|
||||
{
|
||||
SelectAssemblyFolder();
|
||||
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
|
||||
}
|
||||
|
||||
private static void SelectAssemblyFolder()
|
||||
{
|
||||
if (!assemblyLoader.Loaded)
|
||||
{
|
||||
@@ -721,7 +906,6 @@ namespace AssetStudioGUI
|
||||
assemblyLoader.Loaded = true;
|
||||
}
|
||||
}
|
||||
return m_MonoBehaviour.ConvertToTypeTree(assemblyLoader);
|
||||
}
|
||||
|
||||
public static string DumpAsset(Object obj)
|
||||
@@ -732,6 +916,10 @@ namespace AssetStudioGUI
|
||||
var type = MonoBehaviourToTypeTree(m_MonoBehaviour);
|
||||
str = m_MonoBehaviour.Dump(type);
|
||||
}
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
str = obj.DumpObject();
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
@@ -742,59 +930,105 @@ namespace AssetStudioGUI
|
||||
Process.Start(info);
|
||||
}
|
||||
|
||||
public static void ExportLive2D(Object[] cubismMocs, string exportPath)
|
||||
public static void ExportLive2D(string exportPath, List<MonoBehaviour> selMocs = null, List<AnimationClip> selClipMotions = null, List<MonoBehaviour> selFadeMotions = null, MonoBehaviour selFadeLst = null)
|
||||
{
|
||||
var baseDestPath = Path.Combine(exportPath, "Live2DOutput");
|
||||
var forceBezier = Properties.Settings.Default.l2dForceBezier;
|
||||
var mocList = selMocs ?? cubismMocList;
|
||||
var motionMode = Properties.Settings.Default.l2dMotionMode;
|
||||
if (selClipMotions != null)
|
||||
motionMode = Live2DMotionMode.AnimationClipV2;
|
||||
else if (selFadeMotions != null || selFadeLst != null)
|
||||
motionMode = Live2DMotionMode.MonoBehaviour;
|
||||
|
||||
ThreadPool.QueueUserWorkItem(state =>
|
||||
{
|
||||
Logger.Info($"Searching for Live2D files...");
|
||||
|
||||
var useFullContainerPath = false;
|
||||
if (cubismMocs.Length > 1)
|
||||
var mocPathDict = new Dictionary<MonoBehaviour, (string, string)>();
|
||||
var mocPathList = new List<string>();
|
||||
foreach (var mocMonoBehaviour in cubismMocList)
|
||||
{
|
||||
var basePathSet = cubismMocs.Select(x => allContainers[x].Substring(0, allContainers[x].LastIndexOf("/"))).ToHashSet();
|
||||
if (!l2dResourceContainers.TryGetValue(mocMonoBehaviour, out var fullContainerPath))
|
||||
continue;
|
||||
|
||||
if (basePathSet.Count != cubismMocs.Length)
|
||||
{
|
||||
useFullContainerPath = true;
|
||||
}
|
||||
var pathSepIndex = fullContainerPath.LastIndexOf('/');
|
||||
var basePath = pathSepIndex > 0
|
||||
? fullContainerPath.Substring(0, pathSepIndex)
|
||||
: fullContainerPath;
|
||||
mocPathDict.Add(mocMonoBehaviour, (fullContainerPath, basePath));
|
||||
}
|
||||
var basePathList = useFullContainerPath ?
|
||||
cubismMocs.Select(x => allContainers[x]).ToList() :
|
||||
cubismMocs.Select(x => allContainers[x].Substring(0, allContainers[x].LastIndexOf("/"))).ToList();
|
||||
var lookup = allContainers.ToLookup(
|
||||
x => basePathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||
if (mocPathDict.Count == 0)
|
||||
{
|
||||
Logger.Error("Live2D Cubism export error\r\nCannot find any model related files");
|
||||
StatusStripUpdate("Live2D export canceled");
|
||||
Progress.Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
var basePathSet = mocPathDict.Values.Select(x => x.Item2).ToHashSet();
|
||||
var useFullContainerPath = mocPathDict.Count != basePathSet.Count;
|
||||
foreach (var moc in mocList)
|
||||
{
|
||||
var mocPath = useFullContainerPath
|
||||
? mocPathDict[moc].Item1 //fullContainerPath
|
||||
: mocPathDict[moc].Item2; //basePath
|
||||
mocPathList.Add(mocPath);
|
||||
}
|
||||
mocPathDict.Clear();
|
||||
|
||||
var lookup = l2dResourceContainers.AsParallel().ToLookup(
|
||||
x => mocPathList.Find(b => x.Value.Contains(b) && x.Value.Split('/').Any(y => y == b.Substring(b.LastIndexOf("/") + 1))),
|
||||
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 name = "";
|
||||
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)
|
||||
{
|
||||
var container = assets.Key;
|
||||
if (container == null)
|
||||
var srcContainer = assets.Key;
|
||||
if (srcContainer == null)
|
||||
continue;
|
||||
name = container;
|
||||
var container = srcContainer;
|
||||
|
||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{container}\"...");
|
||||
Logger.Info($"[{modelCounter + 1}/{totalModelCount}] Exporting Live2D: \"{srcContainer}\"...");
|
||||
try
|
||||
{
|
||||
var modelName = useFullContainerPath ? Path.GetFileNameWithoutExtension(container) : container.Substring(container.LastIndexOf('/') + 1);
|
||||
container = Path.HasExtension(container) ? container.Replace(Path.GetExtension(container), "") : container;
|
||||
var modelName = useFullContainerPath
|
||||
? Path.GetFileNameWithoutExtension(container)
|
||||
: container.Substring(container.LastIndexOf('/') + 1);
|
||||
container = Path.HasExtension(container)
|
||||
? container.Replace(Path.GetExtension(container), "")
|
||||
: container;
|
||||
var destPath = Path.Combine(baseDestPath, container) + Path.DirectorySeparatorChar;
|
||||
|
||||
ExtractLive2D(assets, destPath, modelName, assemblyLoader);
|
||||
var modelExtractor = new Live2DExtractor(assets, selClipMotions, selFadeMotions, selFadeLst);
|
||||
modelExtractor.ExtractCubismModel(destPath, modelName, motionMode, assemblyLoader, forceBezier, parallelExportCount);
|
||||
modelCounter++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error($"Live2D model export error: \"{name}\"", ex);
|
||||
Logger.Error($"Live2D model export error: \"{srcContainer}\"", ex);
|
||||
}
|
||||
Progress.Report(modelCounter, (int)totalModelCount);
|
||||
}
|
||||
|
||||
Logger.Info($"Finished exporting [{modelCounter}/{totalModelCount}] Live2D model(s).");
|
||||
if (modelCounter < totalModelCount)
|
||||
{
|
||||
var total = (int)totalModelCount;
|
||||
Progress.Report(total, total);
|
||||
}
|
||||
if (Properties.Settings.Default.openAfterExport && modelCounter > 0)
|
||||
{
|
||||
OpenFolderInExplorer(exportPath);
|
||||
|
||||
@@ -33,7 +33,12 @@ namespace AssetStudio
|
||||
|
||||
public TypeDefinition GetTypeDefinition(string assemblyName, string fullName)
|
||||
{
|
||||
if (moduleDic.TryGetValue(assemblyName, out var module))
|
||||
moduleDic.TryGetValue(assemblyName, out var module);
|
||||
if (module == null && !assemblyName.Contains(".dll"))
|
||||
{
|
||||
moduleDic.TryGetValue(assemblyName + ".dll", out module);
|
||||
}
|
||||
if (module != null)
|
||||
{
|
||||
var typeDef = module.GetType(fullName);
|
||||
if (typeDef == null && assemblyName == "UnityEngine.dll")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows</TargetFrameworks>
|
||||
<Version>0.17.2.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023</Copyright>
|
||||
<TargetFrameworks>net472;net6.0;net6.0-windows;net7.0;net7.0-windows;net8.0;net8.0-windows</TargetFrameworks>
|
||||
<Version>0.18.0.0</Version>
|
||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © aelurum 2023-2024</Copyright>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<PackageReference Include="Kyaru.Texture2DDecoder">
|
||||
<Version>0.17.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="2.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
|
||||
|
||||
@@ -7,25 +7,37 @@ namespace AssetStudio
|
||||
{
|
||||
public class AudioClipConverter
|
||||
{
|
||||
public bool IsSupport => m_AudioClip.IsConvertSupport();
|
||||
|
||||
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)
|
||||
{
|
||||
m_AudioClip = audioClip;
|
||||
}
|
||||
|
||||
public byte[] ConvertToWav(byte[] m_AudioData)
|
||||
public byte[] ConvertToWav(byte[] m_AudioData, out string debugLog)
|
||||
{
|
||||
debugLog = "";
|
||||
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.length = (uint)m_AudioClip.m_Size;
|
||||
result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound);
|
||||
var result = system.createSound(m_AudioData, MODE.OPENMEMORY, ref exinfo, out var sound);
|
||||
if (result != RESULT.OK)
|
||||
return null;
|
||||
result = sound.getNumSubSounds(out var numsubsounds);
|
||||
@@ -37,28 +49,29 @@ namespace AssetStudio
|
||||
result = sound.getSubSound(0, out var subsound);
|
||||
if (result != RESULT.OK)
|
||||
return null;
|
||||
buff = SoundToWav(subsound);
|
||||
buff = SoundToWav(subsound, out debugLog);
|
||||
subsound.release();
|
||||
subsound.clearHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
buff = SoundToWav(sound);
|
||||
buff = SoundToWav(sound, out debugLog);
|
||||
}
|
||||
sound.release();
|
||||
system.release();
|
||||
sound.clearHandle();
|
||||
return buff;
|
||||
}
|
||||
|
||||
public byte[] SoundToWav(Sound sound)
|
||||
public byte[] SoundToWav(Sound sound, out string debugLog)
|
||||
{
|
||||
Logger.Debug($"[Fmod] Detecting sound format..\n");
|
||||
debugLog = "[Fmod] Detecting sound format..\n";
|
||||
var result = sound.getFormat(out SOUND_TYPE soundType, out SOUND_FORMAT soundFormat, out int channels, out int bits);
|
||||
if (result != RESULT.OK)
|
||||
return null;
|
||||
Logger.Debug($"Detected sound type: {soundType}\n" +
|
||||
$"Detected sound format: {soundFormat}\n" +
|
||||
$"Detected channels: {channels}\n" +
|
||||
$"Detected bit depth: {bits}");
|
||||
debugLog += $"Detected sound type: {soundType}\n" +
|
||||
$"Detected sound format: {soundFormat}\n" +
|
||||
$"Detected channels: {channels}\n" +
|
||||
$"Detected bit depth: {bits}\n";
|
||||
result = sound.getDefaults(out var frequency, out _);
|
||||
if (result != RESULT.OK)
|
||||
return null;
|
||||
@@ -69,11 +82,11 @@ namespace AssetStudio
|
||||
result = sound.@lock(0, length, out var ptr1, out var ptr2, out var len1, out var len2);
|
||||
if (result != RESULT.OK)
|
||||
return null;
|
||||
byte[] buffer = new byte[len1 + 44];
|
||||
var buffer = new byte[len1 + 44];
|
||||
//添加wav头
|
||||
Encoding.UTF8.GetBytes("RIFF").CopyTo(buffer, 0);
|
||||
Encoding.ASCII.GetBytes("RIFF").CopyTo(buffer, 0);
|
||||
BitConverter.GetBytes(len1 + 36).CopyTo(buffer, 4);
|
||||
Encoding.UTF8.GetBytes("WAVEfmt ").CopyTo(buffer, 8);
|
||||
Encoding.ASCII.GetBytes("WAVEfmt ").CopyTo(buffer, 8);
|
||||
BitConverter.GetBytes(16).CopyTo(buffer, 16);
|
||||
BitConverter.GetBytes((short)1).CopyTo(buffer, 20);
|
||||
BitConverter.GetBytes((short)channels).CopyTo(buffer, 22);
|
||||
@@ -81,7 +94,7 @@ namespace AssetStudio
|
||||
BitConverter.GetBytes(sampleRate * channels * bits / 8).CopyTo(buffer, 28);
|
||||
BitConverter.GetBytes((short)(channels * bits / 8)).CopyTo(buffer, 32);
|
||||
BitConverter.GetBytes((short)bits).CopyTo(buffer, 34);
|
||||
Encoding.UTF8.GetBytes("data").CopyTo(buffer, 36);
|
||||
Encoding.ASCII.GetBytes("data").CopyTo(buffer, 36);
|
||||
BitConverter.GetBytes(len1).CopyTo(buffer, 40);
|
||||
Marshal.Copy(ptr1, buffer, 44, (int)len1);
|
||||
result = sound.unlock(ptr1, ptr2, len1, len2);
|
||||
@@ -92,11 +105,11 @@ namespace AssetStudio
|
||||
|
||||
public string GetExtensionName()
|
||||
{
|
||||
if (m_AudioClip.version[0] < 5)
|
||||
if (m_AudioClip.version < 5)
|
||||
{
|
||||
switch (m_AudioClip.m_Type)
|
||||
{
|
||||
case FMODSoundType.ACC:
|
||||
case FMODSoundType.AAC:
|
||||
return ".m4a";
|
||||
case FMODSoundType.AIFF:
|
||||
return ".aif";
|
||||
@@ -149,43 +162,42 @@ namespace AssetStudio
|
||||
return ".fsb";
|
||||
}
|
||||
}
|
||||
|
||||
return ".AudioClip";
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSupport
|
||||
public static class AudioClipExtension
|
||||
{
|
||||
public static bool IsConvertSupport(this AudioClip m_AudioClip)
|
||||
{
|
||||
get
|
||||
if (m_AudioClip.version < 5)
|
||||
{
|
||||
if (m_AudioClip.version[0] < 5)
|
||||
switch (m_AudioClip.m_Type)
|
||||
{
|
||||
switch (m_AudioClip.m_Type)
|
||||
{
|
||||
case FMODSoundType.AIFF:
|
||||
case FMODSoundType.IT:
|
||||
case FMODSoundType.MOD:
|
||||
case FMODSoundType.S3M:
|
||||
case FMODSoundType.XM:
|
||||
case FMODSoundType.XMA:
|
||||
case FMODSoundType.AUDIOQUEUE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case FMODSoundType.AIFF:
|
||||
case FMODSoundType.IT:
|
||||
case FMODSoundType.MOD:
|
||||
case FMODSoundType.S3M:
|
||||
case FMODSoundType.XM:
|
||||
case FMODSoundType.XMA:
|
||||
case FMODSoundType.AUDIOQUEUE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_AudioClip.m_CompressionFormat)
|
||||
{
|
||||
switch (m_AudioClip.m_CompressionFormat)
|
||||
{
|
||||
case AudioCompressionFormat.PCM:
|
||||
case AudioCompressionFormat.Vorbis:
|
||||
case AudioCompressionFormat.ADPCM:
|
||||
case AudioCompressionFormat.MP3:
|
||||
case AudioCompressionFormat.XMA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case AudioCompressionFormat.PCM:
|
||||
case AudioCompressionFormat.Vorbis:
|
||||
case AudioCompressionFormat.ADPCM:
|
||||
case AudioCompressionFormat.MP3:
|
||||
case AudioCompressionFormat.XMA:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs
Normal file
35
AssetStudioUtility/CubismLive2DExtractor/CubismCdi3Json.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,12 @@
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
public enum BlendType
|
||||
{
|
||||
Add,
|
||||
Multiply,
|
||||
Overwrite,
|
||||
}
|
||||
|
||||
public class CubismExpression3Json
|
||||
{
|
||||
public string Type;
|
||||
@@ -11,7 +18,7 @@
|
||||
{
|
||||
public string Id;
|
||||
public float Value;
|
||||
public int Blend;
|
||||
public BlendType Blend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
30
AssetStudioUtility/CubismLive2DExtractor/CubismFadeMotion.cs
Normal file
30
AssetStudioUtility/CubismLive2DExtractor/CubismFadeMotion.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
public sealed class AnimationCurve
|
||||
{
|
||||
public CubismKeyframeData[] m_Curve { get; set; }
|
||||
public int m_PreInfinity { get; set; }
|
||||
public int m_PostInfinity { get; set; }
|
||||
public int m_RotationOrder { get; set; }
|
||||
}
|
||||
|
||||
public sealed class CubismFadeMotion
|
||||
{
|
||||
public string m_Name { get; set; }
|
||||
public string MotionName { get; set; }
|
||||
public float FadeInTime { get; set; }
|
||||
public float FadeOutTime { get; set; }
|
||||
public string[] ParameterIds { get; set; }
|
||||
public AnimationCurve[] ParameterCurves { get; set; }
|
||||
public float[] ParameterFadeInTimes { get; set; }
|
||||
public float[] ParameterFadeOutTimes { get; set; }
|
||||
public float MotionLength { get; set; }
|
||||
|
||||
public CubismFadeMotion()
|
||||
{
|
||||
ParameterIds = Array.Empty<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
public class CubismKeyframeData
|
||||
{
|
||||
public float time { get; set; }
|
||||
public float value { get; set; }
|
||||
public float inSlope { get; set; }
|
||||
public float outSlope { get; set; }
|
||||
public int weightedMode { get; set; }
|
||||
public float inWeight { get; set; }
|
||||
public float outWeight { get; set; }
|
||||
|
||||
public CubismKeyframeData() { }
|
||||
|
||||
public CubismKeyframeData(ImportedKeyframe<float> keyframe)
|
||||
{
|
||||
time = keyframe.time;
|
||||
value = keyframe.value;
|
||||
inSlope = keyframe.inSlope;
|
||||
outSlope = keyframe.outSlope;
|
||||
weightedMode = 0;
|
||||
inWeight = 0;
|
||||
outWeight = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ namespace CubismLive2DExtractor
|
||||
{
|
||||
public string Moc;
|
||||
public string[] Textures;
|
||||
public string DisplayInfo;
|
||||
public string Physics;
|
||||
public JObject Motions;
|
||||
public JArray Expressions;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using AssetStudio;
|
||||
|
||||
@@ -8,26 +7,35 @@ namespace CubismLive2DExtractor
|
||||
{
|
||||
class CubismMotion3Converter
|
||||
{
|
||||
private SerializedFile assetsFile;
|
||||
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
|
||||
public List<ImportedKeyframedAnimation> AnimationList { get; protected set; } = new List<ImportedKeyframedAnimation>();
|
||||
|
||||
public CubismMotion3Converter(GameObject rootGameObject, AnimationClip[] animationClips)
|
||||
public CubismMotion3Converter(GameObject rootGameObject, List<AnimationClip> animationClips)
|
||||
{
|
||||
var rootTransform = GetTransform(rootGameObject);
|
||||
CreateBonePathHash(rootTransform);
|
||||
ConvertAnimations(animationClips);
|
||||
}
|
||||
|
||||
private void ConvertAnimations(AnimationClip[] animationClips)
|
||||
public CubismMotion3Converter(List<AnimationClip> animationClips, HashSet<string> partIds, HashSet<string> parameterIds)
|
||||
{
|
||||
CreateBonePathHash(partIds, pathType: "Parts/");
|
||||
CreateBonePathHash(parameterIds, pathType: "Parameters/");
|
||||
ConvertAnimations(animationClips);
|
||||
}
|
||||
|
||||
private void ConvertAnimations(List<AnimationClip> animationClips)
|
||||
{
|
||||
foreach (var animationClip in animationClips)
|
||||
{
|
||||
var iAnim = new ImportedKeyframedAnimation();
|
||||
assetsFile = animationClip.assetsFile;
|
||||
AnimationList.Add(iAnim);
|
||||
iAnim.Name = animationClip.m_Name;
|
||||
iAnim.SampleRate = animationClip.m_SampleRate;
|
||||
iAnim.Duration = animationClip.m_MuscleClip.m_StopTime;
|
||||
var m_Clip = animationClip.m_MuscleClip.m_Clip;
|
||||
var m_Clip = animationClip.m_MuscleClip.m_Clip.data;
|
||||
var streamedFrames = m_Clip.m_StreamedClip.ReadData();
|
||||
var m_ClipBindingConstant = animationClip.m_ClipBindingConstant;
|
||||
for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
|
||||
@@ -73,7 +81,7 @@ namespace CubismLive2DExtractor
|
||||
|
||||
if (iAnim.TrackList.Count == 0 || iAnim.Events.Count == 0)
|
||||
{
|
||||
Logger.Warning($"[Motion Converter] {iAnim.Name} has {iAnim.TrackList.Count} tracks and {iAnim.Events.Count} event!.");
|
||||
Logger.Warning($"[Motion Converter] \"{iAnim.Name}\" has {iAnim.TrackList.Count} tracks and {iAnim.Events.Count} event!.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,7 +92,7 @@ namespace CubismLive2DExtractor
|
||||
GetLive2dPath(binding, out var target, out var boneName);
|
||||
if (string.IsNullOrEmpty(boneName))
|
||||
{
|
||||
Logger.Warning($"[Motion Converter] {iAnim.Name} read fail on binding {Array.IndexOf(m_ClipBindingConstant.genericBindings, binding)}");
|
||||
Logger.Warning($"[Motion Converter] \"{iAnim.Name}\" read fail on binding {Array.IndexOf(m_ClipBindingConstant.genericBindings, binding)}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -99,7 +107,7 @@ namespace CubismLive2DExtractor
|
||||
GetLive2dPath(binding, out var target, out var boneName);
|
||||
if (string.IsNullOrEmpty(boneName))
|
||||
{
|
||||
Logger.Warning($"[Motion Converter] {iAnim.Name} read fail on binding {Array.IndexOf(m_ClipBindingConstant.genericBindings, binding)}");
|
||||
Logger.Warning($"[Motion Converter] \"{iAnim.Name}\" read fail on binding {Array.IndexOf(m_ClipBindingConstant.genericBindings, binding)}");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,7 +136,7 @@ namespace CubismLive2DExtractor
|
||||
target = "PartOpacity";
|
||||
}
|
||||
}
|
||||
else if (binding.script.TryGet(out MonoScript script))
|
||||
else if (binding.script.TryGet(out MonoScript script, assetsFile))
|
||||
{
|
||||
switch (script.m_ClassName)
|
||||
{
|
||||
@@ -161,21 +169,30 @@ namespace CubismLive2DExtractor
|
||||
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)
|
||||
{
|
||||
var name = GetTransformPath(m_Transform);
|
||||
var crc = new SevenZip.CRC();
|
||||
var bytes = Encoding.UTF8.GetBytes(name);
|
||||
crc.Update(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc.GetDigest()] = name;
|
||||
bonePathHash[GetCRC(name)] = name;
|
||||
int index;
|
||||
while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0)
|
||||
{
|
||||
name = name.Substring(index + 1);
|
||||
crc = new SevenZip.CRC();
|
||||
bytes = Encoding.UTF8.GetBytes(name);
|
||||
crc.Update(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc.GetDigest()] = name;
|
||||
bonePathHash[GetCRC(name)] = name;
|
||||
}
|
||||
foreach (var pptr in m_Transform.m_Children)
|
||||
{
|
||||
@@ -184,7 +201,13 @@ namespace CubismLive2DExtractor
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTransformPath(Transform transform)
|
||||
private static uint GetCRC(string name)
|
||||
{
|
||||
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);
|
||||
if (transform.m_Father.TryGet(out var father))
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
// File Format Specifications
|
||||
// https://github.com/Live2D/CubismSpecs/blob/master/FileFormats/motion3.json.md
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
@@ -18,24 +20,238 @@ namespace CubismLive2DExtractor
|
||||
public float Fps;
|
||||
public bool Loop;
|
||||
public bool AreBeziersRestricted;
|
||||
public float FadeInTime;
|
||||
public float FadeOutTime;
|
||||
public int CurveCount;
|
||||
public int TotalSegmentCount;
|
||||
public int TotalPointCount;
|
||||
public int UserDataCount;
|
||||
public int TotalUserDataSize;
|
||||
};
|
||||
}
|
||||
|
||||
public class SerializableCurve
|
||||
{
|
||||
public string Target;
|
||||
public string Id;
|
||||
public float FadeInTime;
|
||||
public float FadeOutTime;
|
||||
public List<float> Segments;
|
||||
};
|
||||
}
|
||||
|
||||
public class SerializableUserData
|
||||
{
|
||||
public float Time;
|
||||
public string Value;
|
||||
}
|
||||
|
||||
private static void AddSegments(
|
||||
CubismKeyframeData curve,
|
||||
CubismKeyframeData preCurve,
|
||||
CubismKeyframeData nextCurve,
|
||||
SerializableCurve cubismCurve,
|
||||
bool forceBezier,
|
||||
ref int totalPointCount,
|
||||
ref int totalSegmentCount,
|
||||
ref int j
|
||||
)
|
||||
{
|
||||
if (Math.Abs(curve.time - preCurve.time - 0.01f) < 0.0001f) // InverseSteppedSegment
|
||||
{
|
||||
if (nextCurve.value == curve.value)
|
||||
{
|
||||
cubismCurve.Segments.Add(3f); // Segment ID
|
||||
cubismCurve.Segments.Add(nextCurve.time);
|
||||
cubismCurve.Segments.Add(nextCurve.value);
|
||||
j += 1;
|
||||
totalPointCount += 1;
|
||||
totalSegmentCount++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (float.IsPositiveInfinity(curve.inSlope)) // SteppedSegment
|
||||
{
|
||||
cubismCurve.Segments.Add(2f); // Segment ID
|
||||
cubismCurve.Segments.Add(curve.time);
|
||||
cubismCurve.Segments.Add(curve.value);
|
||||
totalPointCount += 1;
|
||||
}
|
||||
else if (preCurve.outSlope == 0f && Math.Abs(curve.inSlope) < 0.0001f && !forceBezier) // LinearSegment
|
||||
{
|
||||
cubismCurve.Segments.Add(0f); // Segment ID
|
||||
cubismCurve.Segments.Add(curve.time);
|
||||
cubismCurve.Segments.Add(curve.value);
|
||||
totalPointCount += 1;
|
||||
}
|
||||
else // BezierSegment
|
||||
{
|
||||
var tangentLength = (curve.time - preCurve.time) / 3f;
|
||||
cubismCurve.Segments.Add(1f); // Segment ID
|
||||
cubismCurve.Segments.Add(preCurve.time + tangentLength);
|
||||
cubismCurve.Segments.Add(preCurve.outSlope * tangentLength + preCurve.value);
|
||||
cubismCurve.Segments.Add(curve.time - tangentLength);
|
||||
cubismCurve.Segments.Add(curve.value - curve.inSlope * tangentLength);
|
||||
cubismCurve.Segments.Add(curve.time);
|
||||
cubismCurve.Segments.Add(curve.value);
|
||||
totalPointCount += 3;
|
||||
}
|
||||
totalSegmentCount++;
|
||||
}
|
||||
|
||||
public CubismMotion3Json(CubismFadeMotion fadeMotion, HashSet<string> paramNames, HashSet<string> partNames, bool forceBezier)
|
||||
{
|
||||
Version = 3;
|
||||
Meta = new SerializableMeta
|
||||
{
|
||||
// Duration of the motion in seconds.
|
||||
Duration = fadeMotion.MotionLength,
|
||||
// Framerate of the motion in seconds.
|
||||
Fps = 30,
|
||||
// [Optional] Status of the looping of the motion.
|
||||
Loop = true,
|
||||
// [Optional] Status of the restriction of Bezier handles'X translations.
|
||||
AreBeziersRestricted = true,
|
||||
// [Optional] Time of the overall Fade-In for easing in seconds.
|
||||
FadeInTime = fadeMotion.FadeInTime,
|
||||
// [Optional] Time of the overall Fade-Out for easing in seconds.
|
||||
FadeOutTime = fadeMotion.FadeOutTime,
|
||||
// The total number of curves.
|
||||
CurveCount = (int)fadeMotion.ParameterCurves.LongCount(x => x.m_Curve.Length > 0),
|
||||
// [Optional] The total number of UserData.
|
||||
UserDataCount = 0
|
||||
};
|
||||
// Motion curves.
|
||||
Curves = new SerializableCurve[Meta.CurveCount];
|
||||
|
||||
var totalSegmentCount = 1;
|
||||
var totalPointCount = 1;
|
||||
var actualCurveCount = 0;
|
||||
for (var i = 0; i < fadeMotion.ParameterCurves.Length; i++)
|
||||
{
|
||||
if (fadeMotion.ParameterCurves[i].m_Curve.Length == 0)
|
||||
continue;
|
||||
|
||||
string target;
|
||||
string paramId = fadeMotion.ParameterIds[i];
|
||||
switch (paramId)
|
||||
{
|
||||
case "Opacity":
|
||||
case "EyeBlink":
|
||||
case "LipSync":
|
||||
target = "Model";
|
||||
break;
|
||||
default:
|
||||
if (paramNames.Contains(paramId))
|
||||
{
|
||||
target = "Parameter";
|
||||
}
|
||||
else if (partNames.Contains(paramId))
|
||||
{
|
||||
target = "PartOpacity";
|
||||
}
|
||||
else
|
||||
{
|
||||
target = paramId.ToLower().Contains("part") ? "PartOpacity" : "Parameter";
|
||||
AssetStudio.Logger.Warning($"[{fadeMotion.m_Name}] Binding error: Unable to find \"{paramId}\" among the model parts/parameters");
|
||||
}
|
||||
break;
|
||||
}
|
||||
Curves[actualCurveCount] = new SerializableCurve
|
||||
{
|
||||
// Target type.
|
||||
Target = target,
|
||||
// Identifier for mapping curve to target.
|
||||
Id = paramId,
|
||||
// [Optional] Time of the Fade - In for easing in seconds.
|
||||
FadeInTime = fadeMotion.ParameterFadeInTimes[i],
|
||||
// [Optional] Time of the Fade - Out for easing in seconds.
|
||||
FadeOutTime = fadeMotion.ParameterFadeOutTimes[i],
|
||||
// Flattened segments.
|
||||
Segments = new List<float>
|
||||
{
|
||||
// First point
|
||||
fadeMotion.ParameterCurves[i].m_Curve[0].time,
|
||||
fadeMotion.ParameterCurves[i].m_Curve[0].value
|
||||
}
|
||||
};
|
||||
for (var j = 1; j < fadeMotion.ParameterCurves[i].m_Curve.Length; j++)
|
||||
{
|
||||
var curve = fadeMotion.ParameterCurves[i].m_Curve[j];
|
||||
var preCurve = fadeMotion.ParameterCurves[i].m_Curve[j - 1];
|
||||
var next = fadeMotion.ParameterCurves[i].m_Curve.ElementAtOrDefault(j + 1);
|
||||
var nextCurve = next ?? new CubismKeyframeData();
|
||||
AddSegments(curve, preCurve, nextCurve, Curves[actualCurveCount], forceBezier, ref totalPointCount, ref totalSegmentCount, ref j);
|
||||
}
|
||||
actualCurveCount++;
|
||||
}
|
||||
|
||||
// The total number of segments (from all curves).
|
||||
Meta.TotalSegmentCount = totalSegmentCount;
|
||||
// The total number of points (from all segments of all curves).
|
||||
Meta.TotalPointCount = totalPointCount;
|
||||
|
||||
UserData = Array.Empty<SerializableUserData>();
|
||||
// [Optional] The total size of UserData in bytes.
|
||||
Meta.TotalUserDataSize = 0;
|
||||
}
|
||||
|
||||
public CubismMotion3Json(ImportedKeyframedAnimation animation, bool forceBezier)
|
||||
{
|
||||
Version = 3;
|
||||
Meta = new SerializableMeta
|
||||
{
|
||||
Duration = animation.Duration,
|
||||
Fps = animation.SampleRate,
|
||||
Loop = true,
|
||||
AreBeziersRestricted = true,
|
||||
FadeInTime = 0,
|
||||
FadeOutTime = 0,
|
||||
CurveCount = animation.TrackList.Count,
|
||||
UserDataCount = animation.Events.Count
|
||||
};
|
||||
Curves = new SerializableCurve[Meta.CurveCount];
|
||||
|
||||
var totalSegmentCount = 1;
|
||||
var totalPointCount = 1;
|
||||
for (var i = 0; i < Meta.CurveCount; i++)
|
||||
{
|
||||
var track = animation.TrackList[i];
|
||||
Curves[i] = new SerializableCurve
|
||||
{
|
||||
Target = track.Target,
|
||||
Id = track.Name,
|
||||
FadeInTime = -1,
|
||||
FadeOutTime = -1,
|
||||
Segments = new List<float>
|
||||
{
|
||||
0f,
|
||||
track.Curve[0].value
|
||||
}
|
||||
};
|
||||
for (var j = 1; j < track.Curve.Count; j++)
|
||||
{
|
||||
var curve = new CubismKeyframeData(track.Curve[j]);
|
||||
var preCurve = new CubismKeyframeData(track.Curve[j - 1]);
|
||||
var next = track.Curve.ElementAtOrDefault(j + 1);
|
||||
var nextCurve = next != null ? new CubismKeyframeData(next) : new CubismKeyframeData();
|
||||
AddSegments(curve, preCurve, nextCurve, Curves[i], forceBezier, ref totalPointCount, ref totalSegmentCount, ref j);
|
||||
}
|
||||
}
|
||||
Meta.TotalSegmentCount = totalSegmentCount;
|
||||
Meta.TotalPointCount = totalPointCount;
|
||||
|
||||
UserData = new SerializableUserData[Meta.UserDataCount];
|
||||
var totalUserDataSize = 0;
|
||||
for (var i = 0; i < Meta.UserDataCount; i++)
|
||||
{
|
||||
var @event = animation.Events[i];
|
||||
UserData[i] = new SerializableUserData
|
||||
{
|
||||
Time = @event.time,
|
||||
Value = @event.value
|
||||
};
|
||||
totalUserDataSize += @event.value.Length;
|
||||
}
|
||||
Meta.TotalUserDataSize = totalUserDataSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
62
AssetStudioUtility/CubismLive2DExtractor/CubismObjectList.cs
Normal file
62
AssetStudioUtility/CubismLive2DExtractor/CubismObjectList.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
163
AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs
Normal file
163
AssetStudioUtility/CubismLive2DExtractor/CubismParsers.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,301 +1,405 @@
|
||||
////
|
||||
// Based on UnityLive2DExtractorMod by aelurum
|
||||
// https://github.com/aelurum/UnityLive2DExtractor
|
||||
//
|
||||
// Original version - by Perfare
|
||||
// Based on UnityLive2DExtractor by Perfare
|
||||
// https://github.com/Perfare/UnityLive2DExtractor
|
||||
////
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AssetStudio;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using static CubismLive2DExtractor.CubismParsers;
|
||||
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
public static class Live2DExtractor
|
||||
public sealed class Live2DExtractor
|
||||
{
|
||||
public static void ExtractLive2D(IGrouping<string, AssetStudio.Object> assets, string destPath, string modelName, AssemblyLoader assemblyLoader)
|
||||
{
|
||||
var destTexturePath = Path.Combine(destPath, "textures") + Path.DirectorySeparatorChar;
|
||||
var destMotionPath = Path.Combine(destPath, "motions") + Path.DirectorySeparatorChar;
|
||||
var destExpressionPath = Path.Combine(destPath, "expressions") + Path.DirectorySeparatorChar;
|
||||
Directory.CreateDirectory(destPath);
|
||||
Directory.CreateDirectory(destTexturePath);
|
||||
private List<MonoBehaviour> Expressions { get; set; }
|
||||
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; }
|
||||
|
||||
var monoBehaviours = new List<MonoBehaviour>();
|
||||
var texture2Ds = new List<Texture2D>();
|
||||
var gameObjects = new List<GameObject>();
|
||||
var animationClips = new List<AnimationClip>();
|
||||
public Live2DExtractor(IGrouping<string, AssetStudio.Object> assets, List<AnimationClip> inClipMotions = null, List<MonoBehaviour> inFadeMotions = null, MonoBehaviour inFadeMotionLst = null)
|
||||
{
|
||||
Expressions = new List<MonoBehaviour>();
|
||||
FadeMotions = inFadeMotions ?? new List<MonoBehaviour>();
|
||||
AnimationClips = inClipMotions ?? new List<AnimationClip>();
|
||||
GameObjects = new List<GameObject>();
|
||||
Texture2Ds = new List<Texture2D>();
|
||||
EyeBlinkParameters = new HashSet<string>();
|
||||
LipSyncParameters = new HashSet<string>();
|
||||
ParameterNames = new HashSet<string>();
|
||||
PartNames = new HashSet<string>();
|
||||
FadeMotionLst = inFadeMotionLst;
|
||||
ParametersCdi = new List<MonoBehaviour>();
|
||||
PartsCdi = new List<MonoBehaviour>();
|
||||
|
||||
Logger.Debug("Sorting model assets..");
|
||||
foreach (var asset in assets)
|
||||
{
|
||||
switch (asset)
|
||||
{
|
||||
case MonoBehaviour m_MonoBehaviour:
|
||||
monoBehaviours.Add(m_MonoBehaviour);
|
||||
break;
|
||||
case Texture2D m_Texture2D:
|
||||
texture2Ds.Add(m_Texture2D);
|
||||
break;
|
||||
case GameObject m_GameObject:
|
||||
gameObjects.Add(m_GameObject);
|
||||
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||
{
|
||||
switch (m_Script.m_ClassName)
|
||||
{
|
||||
case "CubismMoc":
|
||||
MocMono = m_MonoBehaviour;
|
||||
break;
|
||||
case "CubismPhysicsController":
|
||||
PhysicsMono = m_MonoBehaviour;
|
||||
break;
|
||||
case "CubismExpressionData":
|
||||
Expressions.Add(m_MonoBehaviour);
|
||||
break;
|
||||
case "CubismFadeMotionData":
|
||||
if (inFadeMotions == null && inFadeMotionLst == null)
|
||||
{
|
||||
FadeMotions.Add(m_MonoBehaviour);
|
||||
}
|
||||
break;
|
||||
case "CubismFadeMotionList":
|
||||
if (inFadeMotions == null && inFadeMotionLst == null)
|
||||
{
|
||||
FadeMotionLst = m_MonoBehaviour;
|
||||
}
|
||||
break;
|
||||
case "CubismEyeBlinkParameter":
|
||||
if (m_MonoBehaviour.m_GameObject.TryGet(out var blinkGameObject))
|
||||
{
|
||||
EyeBlinkParameters.Add(blinkGameObject.m_Name);
|
||||
}
|
||||
break;
|
||||
case "CubismMouthParameter":
|
||||
if (m_MonoBehaviour.m_GameObject.TryGet(out var mouthGameObject))
|
||||
{
|
||||
LipSyncParameters.Add(mouthGameObject.m_Name);
|
||||
}
|
||||
break;
|
||||
case "CubismParameter":
|
||||
if (m_MonoBehaviour.m_GameObject.TryGet(out var paramGameObject))
|
||||
{
|
||||
ParameterNames.Add(paramGameObject.m_Name);
|
||||
}
|
||||
break;
|
||||
case "CubismPart":
|
||||
if (m_MonoBehaviour.m_GameObject.TryGet(out var partGameObject))
|
||||
{
|
||||
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;
|
||||
case AnimationClip m_AnimationClip:
|
||||
animationClips.Add(m_AnimationClip);
|
||||
if (inClipMotions == null)
|
||||
{
|
||||
AnimationClips.Add(m_AnimationClip);
|
||||
}
|
||||
break;
|
||||
case GameObject m_GameObject:
|
||||
GameObjects.Add(m_GameObject);
|
||||
break;
|
||||
case Texture2D m_Texture2D:
|
||||
Texture2Ds.Add(m_Texture2D);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//physics
|
||||
var physics = monoBehaviours.FirstOrDefault(x =>
|
||||
public void ExtractCubismModel(string destPath, string modelName, Live2DMotionMode motionMode, AssemblyLoader assemblyLoader, bool forceBezier = false, int parallelTaskCount = 1)
|
||||
{
|
||||
Directory.CreateDirectory(destPath);
|
||||
|
||||
#region moc3
|
||||
using (var cubismModel = new CubismModel(MocMono))
|
||||
{
|
||||
if (x.m_Script.TryGet(out var m_Script))
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("Model Stats:");
|
||||
sb.AppendLine($"SDK Version: {cubismModel.VersionDescription}");
|
||||
if (cubismModel.Version > 0)
|
||||
{
|
||||
return m_Script.m_ClassName == "CubismPhysicsController";
|
||||
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;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (physics != null)
|
||||
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)
|
||||
{
|
||||
try
|
||||
{
|
||||
var buff = ParsePhysics(physics, assemblyLoader);
|
||||
File.WriteAllText($"{destPath}{modelName}.physics3.json", buff);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error in parsing physics data: {e.Message}");
|
||||
physics = null;
|
||||
}
|
||||
Logger.Warning($"No textures found for \"{modelName}\" model");
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.CreateDirectory(destTexturePath);
|
||||
}
|
||||
|
||||
//moc
|
||||
var moc = monoBehaviours.First(x =>
|
||||
var textureBag = new ConcurrentBag<string>();
|
||||
var savePathHash = new ConcurrentDictionary<string, bool>();
|
||||
Parallel.ForEach(Texture2Ds, new ParallelOptions { MaxDegreeOfParallelism = parallelTaskCount }, texture2D =>
|
||||
{
|
||||
if (x.m_Script.TryGet(out var m_Script))
|
||||
{
|
||||
return m_Script.m_ClassName == "CubismMoc";
|
||||
}
|
||||
return false;
|
||||
});
|
||||
File.WriteAllBytes($"{destPath}{modelName}.moc3", ParseMoc(moc));
|
||||
var savePath = $"{destTexturePath}{texture2D.m_Name}.png";
|
||||
if (!savePathHash.TryAdd(savePath, true))
|
||||
return;
|
||||
|
||||
//texture
|
||||
var textures = new SortedSet<string>();
|
||||
foreach (var texture2D in texture2Ds)
|
||||
{
|
||||
using (var image = texture2D.ConvertToImage(flip: true))
|
||||
{
|
||||
textures.Add($"textures/{texture2D.m_Name}.png");
|
||||
using (var file = File.OpenWrite($"{destTexturePath}{texture2D.m_Name}.png"))
|
||||
using (var file = File.OpenWrite(savePath))
|
||||
{
|
||||
image.WriteToStream(file, ImageFormat.Png);
|
||||
}
|
||||
textureBag.Add($"textures/{texture2D.m_Name}.png");
|
||||
}
|
||||
}
|
||||
});
|
||||
textures.UnionWith(textureBag);
|
||||
#endregion
|
||||
|
||||
//motion
|
||||
var motions = new SortedDictionary<string, JArray>();
|
||||
|
||||
if (gameObjects.Count > 0)
|
||||
#region physics3.json
|
||||
if (PhysicsMono != null)
|
||||
{
|
||||
var rootTransform = gameObjects[0].m_Transform;
|
||||
while (rootTransform.m_Father.TryGet(out var m_Father))
|
||||
var physicsDict = ParseMonoBehaviour(PhysicsMono, CubismMonoBehaviourType.Physics, assemblyLoader);
|
||||
if (physicsDict != null)
|
||||
{
|
||||
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 (ImportedKeyframedAnimation animation in converter.AnimationList)
|
||||
{
|
||||
var json = new CubismMotion3Json
|
||||
try
|
||||
{
|
||||
Version = 3,
|
||||
Meta = new CubismMotion3Json.SerializableMeta
|
||||
{
|
||||
Duration = animation.Duration,
|
||||
Fps = animation.SampleRate,
|
||||
Loop = true,
|
||||
AreBeziersRestricted = true,
|
||||
CurveCount = animation.TrackList.Count,
|
||||
UserDataCount = animation.Events.Count
|
||||
},
|
||||
Curves = new CubismMotion3Json.SerializableCurve[animation.TrackList.Count]
|
||||
};
|
||||
int totalSegmentCount = 1;
|
||||
int totalPointCount = 1;
|
||||
for (int i = 0; i < animation.TrackList.Count; i++)
|
||||
{
|
||||
var track = animation.TrackList[i];
|
||||
json.Curves[i] = new CubismMotion3Json.SerializableCurve
|
||||
{
|
||||
Target = track.Target,
|
||||
Id = track.Name,
|
||||
Segments = new List<float> { 0f, track.Curve[0].value }
|
||||
};
|
||||
for (var j = 1; j < track.Curve.Count; j++)
|
||||
{
|
||||
var curve = track.Curve[j];
|
||||
var preCurve = track.Curve[j - 1];
|
||||
if (Math.Abs(curve.time - preCurve.time - 0.01f) < 0.0001f) //InverseSteppedSegment
|
||||
{
|
||||
var nextCurve = track.Curve[j + 1];
|
||||
if (nextCurve.value == curve.value)
|
||||
{
|
||||
json.Curves[i].Segments.Add(3f);
|
||||
json.Curves[i].Segments.Add(nextCurve.time);
|
||||
json.Curves[i].Segments.Add(nextCurve.value);
|
||||
j += 1;
|
||||
totalPointCount += 1;
|
||||
totalSegmentCount++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (float.IsPositiveInfinity(curve.inSlope)) //SteppedSegment
|
||||
{
|
||||
json.Curves[i].Segments.Add(2f);
|
||||
json.Curves[i].Segments.Add(curve.time);
|
||||
json.Curves[i].Segments.Add(curve.value);
|
||||
totalPointCount += 1;
|
||||
}
|
||||
else if (preCurve.outSlope == 0f && Math.Abs(curve.inSlope) < 0.0001f) //LinearSegment
|
||||
{
|
||||
json.Curves[i].Segments.Add(0f);
|
||||
json.Curves[i].Segments.Add(curve.time);
|
||||
json.Curves[i].Segments.Add(curve.value);
|
||||
totalPointCount += 1;
|
||||
}
|
||||
else //BezierSegment
|
||||
{
|
||||
var tangentLength = (curve.time - preCurve.time) / 3f;
|
||||
json.Curves[i].Segments.Add(1f);
|
||||
json.Curves[i].Segments.Add(preCurve.time + tangentLength);
|
||||
json.Curves[i].Segments.Add(preCurve.outSlope * tangentLength + preCurve.value);
|
||||
json.Curves[i].Segments.Add(curve.time - tangentLength);
|
||||
json.Curves[i].Segments.Add(curve.value - curve.inSlope * tangentLength);
|
||||
json.Curves[i].Segments.Add(curve.time);
|
||||
json.Curves[i].Segments.Add(curve.value);
|
||||
totalPointCount += 3;
|
||||
}
|
||||
totalSegmentCount++;
|
||||
}
|
||||
var buff = ParsePhysics(physicsDict);
|
||||
File.WriteAllText($"{destPath}{modelName}.physics3.json", buff);
|
||||
}
|
||||
json.Meta.TotalSegmentCount = totalSegmentCount;
|
||||
json.Meta.TotalPointCount = totalPointCount;
|
||||
|
||||
json.UserData = new CubismMotion3Json.SerializableUserData[animation.Events.Count];
|
||||
var totalUserDataSize = 0;
|
||||
for (var i = 0; i < animation.Events.Count; i++)
|
||||
catch (Exception e)
|
||||
{
|
||||
var @event = animation.Events[i];
|
||||
json.UserData[i] = new CubismMotion3Json.SerializableUserData
|
||||
{
|
||||
Time = @event.time,
|
||||
Value = @event.value
|
||||
};
|
||||
totalUserDataSize += @event.value.Length;
|
||||
Logger.Warning($"Error in parsing physics data: {e.Message}");
|
||||
PhysicsMono = null;
|
||||
}
|
||||
json.Meta.TotalUserDataSize = totalUserDataSize;
|
||||
|
||||
var motionPath = new JObject(new JProperty("File", $"motions/{animation.Name}.motion3.json"));
|
||||
motions.Add(animation.Name, new JArray(motionPath));
|
||||
File.WriteAllText($"{destMotionPath}{animation.Name}.motion3.json", JsonConvert.SerializeObject(json, Formatting.Indented, new MyJsonConverter()));
|
||||
}
|
||||
else
|
||||
{
|
||||
PhysicsMono = null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
//expression
|
||||
#region cdi3.json
|
||||
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 destMotionPath = Path.Combine(destPath, "motions") + Path.DirectorySeparatorChar;
|
||||
|
||||
if (motionMode == Live2DMotionMode.MonoBehaviour && FadeMotionLst != null) //Fade motions from Fade Motion List
|
||||
{
|
||||
Logger.Debug("Motion export method: MonoBehaviour (Fade motion)");
|
||||
var fadeMotionLstDict = ParseMonoBehaviour(FadeMotionLst, CubismMonoBehaviourType.FadeMotionList, assemblyLoader);
|
||||
if (fadeMotionLstDict != null)
|
||||
{
|
||||
CubismObjectList.AssetsFile = FadeMotionLst.assetsFile;
|
||||
var fadeMotionAssetList = JsonConvert.DeserializeObject<CubismObjectList>(JsonConvert.SerializeObject(fadeMotionLstDict)).GetFadeMotionAssetList();
|
||||
if (fadeMotionAssetList?.Count > 0)
|
||||
{
|
||||
FadeMotions = fadeMotionAssetList;
|
||||
Logger.Debug($"\"{FadeMotionLst.m_Name}\": found {fadeMotionAssetList.Count} motion(s)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (motionMode == Live2DMotionMode.MonoBehaviour && FadeMotions.Count > 0) //motion from MonoBehaviour
|
||||
{
|
||||
ExportFadeMotions(destMotionPath, assemblyLoader, forceBezier, motions);
|
||||
}
|
||||
|
||||
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}");
|
||||
|
||||
ExportClipMotions(destMotionPath, converter, forceBezier, motions);
|
||||
}
|
||||
|
||||
if (motions.Count == 0)
|
||||
{
|
||||
Logger.Warning($"No exportable motions found for \"{modelName}\" model");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"Exported {motions.Count} motion(s)");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region exp3.json
|
||||
var expressions = new JArray();
|
||||
var monoBehaviourArray = monoBehaviours.Where(x => x.m_Name.EndsWith(".exp3")).ToArray();
|
||||
if (monoBehaviourArray.Length > 0)
|
||||
var destExpressionPath = Path.Combine(destPath, "expressions") + Path.DirectorySeparatorChar;
|
||||
|
||||
if (Expressions.Count > 0)
|
||||
{
|
||||
Directory.CreateDirectory(destExpressionPath);
|
||||
}
|
||||
foreach (var monoBehaviour in monoBehaviourArray)
|
||||
foreach (var monoBehaviour in Expressions)
|
||||
{
|
||||
var fullName = monoBehaviour.m_Name;
|
||||
var expressionName = fullName.Replace(".exp3", "");
|
||||
var expressionObj = monoBehaviour.ToType();
|
||||
if (expressionObj == null)
|
||||
{
|
||||
var m_Type = monoBehaviour.ConvertToTypeTree(assemblyLoader);
|
||||
expressionObj = monoBehaviour.ToType(m_Type);
|
||||
if (expressionObj == null)
|
||||
{
|
||||
Logger.Warning($"Expression \"{expressionName}\" is not readable.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var expression = JsonConvert.DeserializeObject<CubismExpression3Json>(JsonConvert.SerializeObject(expressionObj));
|
||||
var expressionName = monoBehaviour.m_Name.Replace(".exp3", "");
|
||||
var expressionDict = ParseMonoBehaviour(monoBehaviour, CubismMonoBehaviourType.Expression, assemblyLoader);
|
||||
if (expressionDict == null)
|
||||
continue;
|
||||
|
||||
var expression = JsonConvert.DeserializeObject<CubismExpression3Json>(JsonConvert.SerializeObject(expressionDict));
|
||||
|
||||
expressions.Add(new JObject
|
||||
{
|
||||
{ "Name", expressionName },
|
||||
{ "File", $"expressions/{fullName}.json" }
|
||||
});
|
||||
File.WriteAllText($"{destExpressionPath}{fullName}.json", JsonConvert.SerializeObject(expression, Formatting.Indented));
|
||||
{
|
||||
{ "Name", expressionName },
|
||||
{ "File", $"expressions/{expressionName}.exp3.json" }
|
||||
});
|
||||
File.WriteAllText($"{destExpressionPath}{expressionName}.exp3.json", JsonConvert.SerializeObject(expression, Formatting.Indented));
|
||||
}
|
||||
#endregion
|
||||
|
||||
//model
|
||||
#region model3.json
|
||||
var groups = new List<CubismModel3Json.SerializableGroup>();
|
||||
|
||||
var eyeBlinkParameters = monoBehaviours.Where(x =>
|
||||
//Try looking for group IDs among the parameter names manually
|
||||
if (EyeBlinkParameters.Count == 0)
|
||||
{
|
||||
x.m_Script.TryGet(out var m_Script);
|
||||
return m_Script?.m_ClassName == "CubismEyeBlinkParameter";
|
||||
}).Select(x =>
|
||||
{
|
||||
x.m_GameObject.TryGet(out var m_GameObject);
|
||||
return m_GameObject?.m_Name;
|
||||
}).ToHashSet();
|
||||
if (eyeBlinkParameters.Count == 0)
|
||||
{
|
||||
eyeBlinkParameters = gameObjects.Where(x =>
|
||||
{
|
||||
return x.m_Name.ToLower().Contains("eye")
|
||||
&& x.m_Name.ToLower().Contains("open")
|
||||
&& (x.m_Name.ToLower().Contains('l') || x.m_Name.ToLower().Contains('r'));
|
||||
}).Select(x => x.m_Name).ToHashSet();
|
||||
EyeBlinkParameters = ParameterNames.Where(x =>
|
||||
x.ToLower().Contains("eye")
|
||||
&& x.ToLower().Contains("open")
|
||||
&& (x.ToLower().Contains('l') || x.ToLower().Contains('r'))
|
||||
).ToHashSet();
|
||||
}
|
||||
if (LipSyncParameters.Count == 0)
|
||||
{
|
||||
LipSyncParameters = ParameterNames.Where(x =>
|
||||
x.ToLower().Contains("mouth")
|
||||
&& x.ToLower().Contains("open")
|
||||
&& x.ToLower().Contains('y')
|
||||
).ToHashSet();
|
||||
}
|
||||
|
||||
groups.Add(new CubismModel3Json.SerializableGroup
|
||||
{
|
||||
Target = "Parameter",
|
||||
Name = "EyeBlink",
|
||||
Ids = eyeBlinkParameters.ToArray()
|
||||
Ids = EyeBlinkParameters.ToArray()
|
||||
});
|
||||
|
||||
var lipSyncParameters = monoBehaviours.Where(x =>
|
||||
{
|
||||
x.m_Script.TryGet(out var m_Script);
|
||||
return m_Script?.m_ClassName == "CubismMouthParameter";
|
||||
}).Select(x =>
|
||||
{
|
||||
x.m_GameObject.TryGet(out var m_GameObject);
|
||||
return m_GameObject?.m_Name;
|
||||
}).ToHashSet();
|
||||
if (lipSyncParameters.Count == 0)
|
||||
{
|
||||
lipSyncParameters = gameObjects.Where(x =>
|
||||
{
|
||||
return x.m_Name.ToLower().Contains("mouth")
|
||||
&& x.m_Name.ToLower().Contains("open")
|
||||
&& x.m_Name.ToLower().Contains('y');
|
||||
}).Select(x => x.m_Name).ToHashSet();
|
||||
}
|
||||
groups.Add(new CubismModel3Json.SerializableGroup
|
||||
{
|
||||
Target = "Parameter",
|
||||
Name = "LipSync",
|
||||
Ids = lipSyncParameters.ToArray()
|
||||
Ids = LipSyncParameters.ToArray()
|
||||
});
|
||||
|
||||
|
||||
var model3 = new CubismModel3Json
|
||||
{
|
||||
Version = 3,
|
||||
@@ -304,140 +408,90 @@ namespace CubismLive2DExtractor
|
||||
{
|
||||
Moc = $"{modelName}.moc3",
|
||||
Textures = textures.ToArray(),
|
||||
DisplayInfo = isCdiParsed ? $"{modelName}.cdi3.json" : null,
|
||||
Physics = PhysicsMono != null ? $"{modelName}.physics3.json" : null,
|
||||
Motions = JObject.FromObject(motions),
|
||||
Expressions = expressions,
|
||||
},
|
||||
Groups = groups.ToArray()
|
||||
};
|
||||
if (physics != null)
|
||||
{
|
||||
model3.FileReferences.Physics = $"{modelName}.physics3.json";
|
||||
}
|
||||
File.WriteAllText($"{destPath}{modelName}.model3.json", JsonConvert.SerializeObject(model3, Formatting.Indented));
|
||||
#endregion
|
||||
}
|
||||
|
||||
private static string ParsePhysics(MonoBehaviour physics, AssemblyLoader assemblyLoader)
|
||||
private void ExportFadeMotions(string destMotionPath, AssemblyLoader assemblyLoader, bool forceBezier, SortedDictionary<string, JArray> motions)
|
||||
{
|
||||
var physicsObj = physics.ToType();
|
||||
if (physicsObj == null)
|
||||
Directory.CreateDirectory(destMotionPath);
|
||||
foreach (var fadeMotionMono in FadeMotions)
|
||||
{
|
||||
var m_Type = physics.ConvertToTypeTree(assemblyLoader);
|
||||
physicsObj = physics.ToType(m_Type);
|
||||
if (physicsObj == null)
|
||||
{
|
||||
throw new Exception("MonoBehaviour is not readable.");
|
||||
}
|
||||
}
|
||||
var cubismPhysicsRig = JsonConvert.DeserializeObject<CubismPhysics>(JsonConvert.SerializeObject(physicsObj))._rig;
|
||||
var fadeMotionDict = ParseMonoBehaviour(fadeMotionMono, CubismMonoBehaviourType.FadeMotion, assemblyLoader);
|
||||
if (fadeMotionDict == null)
|
||||
continue;
|
||||
|
||||
var fadeMotion = JsonConvert.DeserializeObject<CubismFadeMotion>(JsonConvert.SerializeObject(fadeMotionDict));
|
||||
if (fadeMotion.ParameterIds.Length == 0)
|
||||
continue;
|
||||
|
||||
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
|
||||
var motionJson = new CubismMotion3Json(fadeMotion, ParameterNames, PartNames, forceBezier);
|
||||
|
||||
var animName = Path.GetFileNameWithoutExtension(fadeMotion.m_Name);
|
||||
if (motions.ContainsKey(animName))
|
||||
{
|
||||
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
|
||||
};
|
||||
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()));
|
||||
}
|
||||
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 byte[] ParseMoc(MonoBehaviour moc)
|
||||
private static void ExportClipMotions(string destMotionPath, CubismMotion3Converter converter, bool forceBezier, SortedDictionary<string, JArray> motions)
|
||||
{
|
||||
var reader = moc.reader;
|
||||
reader.Reset();
|
||||
reader.Position += 28; //PPtr<GameObject> m_GameObject, m_Enabled, PPtr<MonoScript>
|
||||
reader.ReadAlignedString(); //m_Name
|
||||
return reader.ReadBytes(reader.ReadInt32());
|
||||
if (converter == null)
|
||||
return;
|
||||
|
||||
if (converter.AnimationList.Count > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace CubismLive2DExtractor
|
||||
{
|
||||
public enum Live2DMotionMode
|
||||
{
|
||||
MonoBehaviour,
|
||||
AnimationClipV1,
|
||||
AnimationClipV2,
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace AssetStudio
|
||||
|
||||
private ImageFormat imageFormat;
|
||||
private Avatar avatar;
|
||||
private HashSet<AnimationClip> animationClipHashSet = new HashSet<AnimationClip>();
|
||||
private AnimationClip[] animationClipUniqArray = Array.Empty<AnimationClip>(); //TODO: a proper AnimationClip equality comparer
|
||||
private Dictionary<AnimationClip, string> boundAnimationPathDic = new Dictionary<AnimationClip, string>();
|
||||
private Dictionary<uint, string> bonePathHash = new Dictionary<uint, string>();
|
||||
private Dictionary<Texture2D, string> textureNameDictionary = new Dictionary<Texture2D, string>();
|
||||
@@ -40,10 +40,7 @@ namespace AssetStudio
|
||||
}
|
||||
if (animationList != null)
|
||||
{
|
||||
foreach (var animationClip in animationList)
|
||||
{
|
||||
animationClipHashSet.Add(animationClip);
|
||||
}
|
||||
animationClipUniqArray = animationList.Distinct().ToArray();
|
||||
}
|
||||
ConvertAnimations();
|
||||
}
|
||||
@@ -70,10 +67,7 @@ namespace AssetStudio
|
||||
}
|
||||
if (animationList != null)
|
||||
{
|
||||
foreach (var animationClip in animationList)
|
||||
{
|
||||
animationClipHashSet.Add(animationClip);
|
||||
}
|
||||
animationClipUniqArray = animationList.Distinct().ToArray();
|
||||
}
|
||||
ConvertAnimations();
|
||||
}
|
||||
@@ -88,10 +82,7 @@ namespace AssetStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var animationClip in animationList)
|
||||
{
|
||||
animationClipHashSet.Add(animationClip);
|
||||
}
|
||||
animationClipUniqArray = animationList.Distinct().ToArray();
|
||||
}
|
||||
ConvertAnimations();
|
||||
}
|
||||
@@ -160,6 +151,7 @@ namespace AssetStudio
|
||||
|
||||
if (m_GameObject.m_Animation != null)
|
||||
{
|
||||
var animationList = new List<AnimationClip>();
|
||||
foreach (var animation in m_GameObject.m_Animation.m_Animations)
|
||||
{
|
||||
if (animation.TryGet(out var animationClip))
|
||||
@@ -168,9 +160,10 @@ namespace AssetStudio
|
||||
{
|
||||
boundAnimationPathDic.Add(animationClip, GetTransformPath(m_Transform));
|
||||
}
|
||||
animationClipHashSet.Add(animationClip);
|
||||
animationList.Add(animationClip);
|
||||
}
|
||||
}
|
||||
animationClipUniqArray = animationList.Distinct().ToArray();
|
||||
}
|
||||
|
||||
foreach (var pptr in m_Transform.m_Children)
|
||||
@@ -184,6 +177,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (m_Animator.m_Controller.TryGet(out var m_Controller))
|
||||
{
|
||||
var animationList = new List<AnimationClip>();
|
||||
switch (m_Controller)
|
||||
{
|
||||
case AnimatorOverrideController m_AnimatorOverrideController:
|
||||
@@ -194,7 +188,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (pptr.TryGet(out var m_AnimationClip))
|
||||
{
|
||||
animationClipHashSet.Add(m_AnimationClip);
|
||||
animationList.Add(m_AnimationClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,12 +201,13 @@ namespace AssetStudio
|
||||
{
|
||||
if (pptr.TryGet(out var m_AnimationClip))
|
||||
{
|
||||
animationClipHashSet.Add(m_AnimationClip);
|
||||
animationList.Add(m_AnimationClip);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
animationClipUniqArray = animationList.Distinct().ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +366,7 @@ namespace AssetStudio
|
||||
{
|
||||
if (iMesh.hasUV[uv])
|
||||
{
|
||||
c = 4;
|
||||
var m_UV = mesh.GetUV(uv);
|
||||
if (m_UV.Length == mesh.m_VertexCount * 2)
|
||||
{
|
||||
@@ -769,7 +765,7 @@ namespace AssetStudio
|
||||
|
||||
private void ConvertAnimations()
|
||||
{
|
||||
foreach (var animationClip in animationClipHashSet)
|
||||
foreach (var animationClip in animationClipUniqArray)
|
||||
{
|
||||
var iAnim = new ImportedKeyframedAnimation();
|
||||
var name = animationClip.m_Name;
|
||||
@@ -877,7 +873,7 @@ namespace AssetStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
var m_Clip = animationClip.m_MuscleClip.m_Clip;
|
||||
var m_Clip = animationClip.m_MuscleClip.m_Clip.data;
|
||||
var streamedFrames = m_Clip.m_StreamedClip.ReadData();
|
||||
var m_ClipBindingConstant = animationClip.m_ClipBindingConstant ?? m_Clip.ConvertValueArrayToGenericBinding();
|
||||
for (int frameIndex = 1; frameIndex < streamedFrames.Count - 1; frameIndex++)
|
||||
@@ -1016,18 +1012,16 @@ namespace AssetStudio
|
||||
private void CreateBonePathHash(Transform m_Transform)
|
||||
{
|
||||
var name = GetTransformPathByFather(m_Transform);
|
||||
var crc = new SevenZip.CRC();
|
||||
var bytes = Encoding.UTF8.GetBytes(name);
|
||||
crc.Update(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc.GetDigest()] = name;
|
||||
var crc = SevenZip.CRC.CalculateDigest(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc] = name;
|
||||
int index;
|
||||
while ((index = name.IndexOf("/", StringComparison.Ordinal)) >= 0)
|
||||
{
|
||||
name = name.Substring(index + 1);
|
||||
crc = new SevenZip.CRC();
|
||||
bytes = Encoding.UTF8.GetBytes(name);
|
||||
crc.Update(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc.GetDigest()] = name;
|
||||
crc = SevenZip.CRC.CalculateDigest(bytes, 0, (uint)bytes.Length);
|
||||
bonePathHash[crc] = name;
|
||||
}
|
||||
foreach (var pptr in m_Transform.m_Children)
|
||||
{
|
||||
@@ -1102,10 +1096,7 @@ namespace AssetStudio
|
||||
{
|
||||
return name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace AssetStudio
|
||||
{
|
||||
public class SerializedTypeHelper
|
||||
{
|
||||
private readonly int[] version;
|
||||
private readonly UnityVersion version;
|
||||
|
||||
public SerializedTypeHelper(int[] version)
|
||||
public SerializedTypeHelper(UnityVersion version)
|
||||
{
|
||||
this.version = version;
|
||||
}
|
||||
@@ -24,7 +24,7 @@ namespace AssetStudio
|
||||
{
|
||||
nodes.Add(new TypeTreeNode($"PPtr<{type}>", name, indent, false));
|
||||
nodes.Add(new TypeTreeNode("int", "m_FileID", indent + 1, false));
|
||||
if (version[0] >= 5) //5.0 and up
|
||||
if (version >= 5) //5.0 and up
|
||||
{
|
||||
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", "inSlope", indent + 4, false));
|
||||
nodes.Add(new TypeTreeNode("float", "outSlope", indent + 4, false));
|
||||
if (version[0] >= 2018) //2018 and up
|
||||
if (version >= 2018) //2018 and up
|
||||
{
|
||||
nodes.Add(new TypeTreeNode("int", "weightedMode", 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_PostInfinity", indent + 1, false));
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
|
||||
if (version >= (5, 3)) //5.3 and up
|
||||
{
|
||||
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)
|
||||
{
|
||||
nodes.Add(new TypeTreeNode("Gradient", name, indent, false));
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||
if (version >= (5, 6)) //5.6 and up
|
||||
{
|
||||
AddColorRGBA(nodes, "key0", 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", "atime6", indent + 1, false));
|
||||
nodes.Add(new TypeTreeNode("UInt16", "atime7", indent + 1, false));
|
||||
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||
if (version >= (5, 5)) //5.5 and up
|
||||
{
|
||||
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_OnFocused", indent + 1);
|
||||
AddRectOffset(nodes, "m_Border", indent + 1);
|
||||
if (version[0] >= 4) //4 and up
|
||||
if (version >= 4) //4 and up
|
||||
{
|
||||
AddRectOffset(nodes, "m_Margin", indent + 1);
|
||||
AddRectOffset(nodes, "m_Padding", indent + 1);
|
||||
@@ -146,7 +146,7 @@ namespace AssetStudio
|
||||
}
|
||||
AddRectOffset(nodes, "m_Overflow", indent + 1);
|
||||
AddPPtr(nodes, "Font", "m_Font", indent + 1);
|
||||
if (version[0] >= 4) //4 and up
|
||||
if (version >= 4) //4 and up
|
||||
{
|
||||
nodes.Add(new TypeTreeNode("int", "m_FontSize", 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);
|
||||
nodes.Add(new TypeTreeNode("float", "m_FixedWidth", indent + 1, false));
|
||||
nodes.Add(new TypeTreeNode("float", "m_FixedHeight", indent + 1, false));
|
||||
if (version[0] >= 3) //3 and up
|
||||
if (version >= 3) //3 and up
|
||||
{
|
||||
nodes.Add(new TypeTreeNode("int", "m_FontSize", 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
Reference in New Issue
Block a user