[GUI] Rework some import options
- Added feature to load and export import options to a file (import options include unity version). - Added option to always decompress bundles to disk. (Related issue: #58 )
This commit is contained in:
@@ -7,6 +7,8 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json;
|
||||
using AssetStudio.CustomOptions;
|
||||
using AssetStudio.CustomOptions.Asmo;
|
||||
using static AssetStudio.ImportHelper;
|
||||
|
||||
namespace AssetStudio
|
||||
@@ -14,46 +16,22 @@ namespace AssetStudio
|
||||
public class AssetsManager
|
||||
{
|
||||
public bool LoadingViaTypeTreeEnabled = true;
|
||||
public CompressionType CustomBlockCompression = CompressionType.Auto;
|
||||
public CompressionType CustomBlockInfoCompression = CompressionType.Auto;
|
||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||
public ImportOptions Options = new ImportOptions();
|
||||
public readonly List<Action<OptionsFile>> OptionLoaders = new List<Action<OptionsFile>>();
|
||||
public readonly List<SerializedFile> AssetsFileList = new List<SerializedFile>();
|
||||
|
||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(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);
|
||||
private readonly List<string> importFiles = new List<string>();
|
||||
private readonly HashSet<ClassIDType> filteredAssetTypesList = new HashSet<ClassIDType>();
|
||||
private readonly HashSet<string> importFilesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public UnityVersion SpecifyUnityVersion
|
||||
public AssetsManager()
|
||||
{
|
||||
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}");
|
||||
}
|
||||
OptionLoaders.Add(LoadImportOptions);
|
||||
}
|
||||
|
||||
public void SetAssetFilter(params ClassIDType[] classIDTypes)
|
||||
@@ -102,16 +80,14 @@ namespace AssetStudio
|
||||
SetAssetFilter(classIDTypeList.ToArray());
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(params string[] path)
|
||||
public void LoadFilesAndFolders(params string[] paths)
|
||||
{
|
||||
LoadFilesAndFolders(out _, path);
|
||||
LoadFilesAndFolders(out _, paths.ToList());
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, params string[] path)
|
||||
public void LoadFilesAndFolders(out string parentPath, params string[] paths)
|
||||
{
|
||||
var pathList = new List<string>();
|
||||
pathList.AddRange(path);
|
||||
LoadFilesAndFolders(out parentPath, pathList);
|
||||
LoadFilesAndFolders(out parentPath, paths.ToList());
|
||||
}
|
||||
|
||||
public void LoadFilesAndFolders(out string parentPath, List<string> pathList)
|
||||
@@ -143,6 +119,8 @@ namespace AssetStudio
|
||||
{
|
||||
MergeSplitAssets(parentPath);
|
||||
}
|
||||
LoadOptionFiles(fileList);
|
||||
|
||||
var toReadFile = ProcessingSplitFiles(fileList);
|
||||
fileList.Clear();
|
||||
pathList.Clear();
|
||||
@@ -224,7 +202,7 @@ namespace AssetStudio
|
||||
var assetsFile = new SerializedFile(reader, this);
|
||||
var dirName = Path.GetDirectoryName(reader.FullPath);
|
||||
CheckStrippedVersion(assetsFile);
|
||||
assetsFileList.Add(assetsFile);
|
||||
AssetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
if (fromZip)
|
||||
return true;
|
||||
@@ -293,7 +271,7 @@ namespace AssetStudio
|
||||
assetsFile.version = assetBundleUnityVer;
|
||||
}
|
||||
CheckStrippedVersion(assetsFile, assetBundleUnityVer);
|
||||
assetsFileList.Add(assetsFile);
|
||||
AssetsFileList.Add(assetsFile);
|
||||
assetsFileListHash.Add(assetsFile.fileName);
|
||||
}
|
||||
catch (NotSupportedException e)
|
||||
@@ -325,7 +303,7 @@ namespace AssetStudio
|
||||
|
||||
try
|
||||
{
|
||||
var bundleFile = new BundleFile(bundleReader, CustomBlockInfoCompression, CustomBlockCompression, specifiedUnityVersion);
|
||||
var bundleFile = new BundleFile(bundleReader, Options.BundleOptions);
|
||||
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath);
|
||||
if (!isLoaded)
|
||||
return false;
|
||||
@@ -347,7 +325,7 @@ namespace AssetStudio
|
||||
bundleReader.FileName = $"{reader.FileName}_0x{bundleStream.Offset:X}";
|
||||
}
|
||||
Logger.Info($"[MultiBundle] Loading \"{reader.FileName}\" from offset: 0x{bundleStream.Offset:X}");
|
||||
bundleFile = new BundleFile(bundleReader, CustomBlockInfoCompression, CustomBlockCompression, specifiedUnityVersion, isMultiBundle: true);
|
||||
bundleFile = new BundleFile(bundleReader, Options.BundleOptions, isMultiBundle: true);
|
||||
isLoaded = LoadBundleFiles(bundleReader, bundleFile, originalPath ?? reader.FullPath);
|
||||
}
|
||||
return isLoaded;
|
||||
@@ -540,29 +518,92 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadOptionFiles(List<string> pathList)
|
||||
{
|
||||
if (pathList.Count == 0)
|
||||
return;
|
||||
|
||||
var optionFileIndexes = new List<int>();
|
||||
for (var i = 0; i < pathList.Count; i++)
|
||||
{
|
||||
var path = pathList[i];
|
||||
if (!path.EndsWith(OptionsFile.Extension, StringComparison.OrdinalIgnoreCase))
|
||||
continue;
|
||||
|
||||
optionFileIndexes.Add(i);
|
||||
var optionsFile = LoadOptionsFile(new FileReader(path));
|
||||
if (optionsFile == null)
|
||||
continue;
|
||||
|
||||
foreach (var optionsLoader in OptionLoaders)
|
||||
{
|
||||
optionsLoader(optionsFile);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < optionFileIndexes.Count; i++)
|
||||
{
|
||||
pathList.RemoveAt(optionFileIndexes[i] - i);
|
||||
}
|
||||
}
|
||||
|
||||
private static OptionsFile LoadOptionsFile(FileReader reader)
|
||||
{
|
||||
Logger.Info($"Loading options file \"{reader.FullPath}\"");
|
||||
try
|
||||
{
|
||||
return new OptionsFile(reader);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while loading options file \"{reader.FullPath}\"\n{e}");
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadImportOptions(OptionsFile optionsFile)
|
||||
{
|
||||
try
|
||||
{
|
||||
var importOptions = ImportOptions.FromOptionsFile(optionsFile);
|
||||
if (importOptions == null)
|
||||
return;
|
||||
Options = importOptions;
|
||||
Logger.Info("Import options successfully loaded.");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Warning($"Error while reading import options\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckStrippedVersion(SerializedFile assetsFile, UnityVersion bundleUnityVer = null)
|
||||
{
|
||||
if (assetsFile.version.IsStripped && specifiedUnityVersion == null)
|
||||
if (assetsFile.version.IsStripped && Options.CustomUnityVersion == null)
|
||||
{
|
||||
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 (specifiedUnityVersion != null)
|
||||
if (Options.CustomUnityVersion != null)
|
||||
{
|
||||
assetsFile.version = SpecifyUnityVersion;
|
||||
assetsFile.version = Options.CustomUnityVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
foreach (var assetsFile in AssetsFileList)
|
||||
{
|
||||
assetsFile.Objects.Clear();
|
||||
assetsFile.reader.Close();
|
||||
}
|
||||
assetsFileList.Clear();
|
||||
AssetsFileList.Clear();
|
||||
|
||||
foreach (var resourceFileReader in resourceFileReaders)
|
||||
{
|
||||
@@ -585,10 +626,10 @@ namespace AssetStudio
|
||||
IncludeFields = true,
|
||||
};
|
||||
|
||||
var progressCount = assetsFileList.Sum(x => x.m_Objects.Count);
|
||||
var progressCount = AssetsFileList.Sum(x => x.m_Objects.Count);
|
||||
var i = 0;
|
||||
Progress.Reset();
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
foreach (var assetsFile in AssetsFileList)
|
||||
{
|
||||
JsonConverterHelper.AssetsFile = assetsFile;
|
||||
foreach (var objectInfo in assetsFile.m_Objects)
|
||||
@@ -735,7 +776,7 @@ namespace AssetStudio
|
||||
{
|
||||
Logger.Info("Process assets...");
|
||||
|
||||
foreach (var assetsFile in assetsFileList)
|
||||
foreach (var assetsFile in AssetsFileList)
|
||||
{
|
||||
foreach (var obj in assetsFile.Objects)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using AssetStudio.CustomOptions;
|
||||
|
||||
namespace AssetStudio
|
||||
{
|
||||
@@ -44,6 +45,7 @@ namespace AssetStudio
|
||||
public class BundleFile
|
||||
{
|
||||
public readonly bool IsDataAfterBundle;
|
||||
private readonly CustomBundleOptions _bundleOptions;
|
||||
|
||||
public class Header
|
||||
{
|
||||
@@ -78,9 +80,10 @@ namespace AssetStudio
|
||||
|
||||
public List<StreamFile> fileList;
|
||||
|
||||
public BundleFile(FileReader reader, CompressionType customBlockInfoCompression, CompressionType customBlockCompression, UnityVersion specUnityVer = null, bool isMultiBundle = false)
|
||||
public BundleFile(FileReader reader, CustomBundleOptions bundleOptions, bool isMultiBundle = false)
|
||||
{
|
||||
Stream blocksStream;
|
||||
_bundleOptions = bundleOptions;
|
||||
m_Header = new Header();
|
||||
m_Header.signature = reader.ReadStringToNull();
|
||||
m_Header.version = reader.ReadUInt32();
|
||||
@@ -121,20 +124,21 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
var unityVer = m_Header.unityRevision;
|
||||
if (specUnityVer != null)
|
||||
var customUnityVer = _bundleOptions.Options.CustomUnityVersion;
|
||||
if (customUnityVer != null)
|
||||
{
|
||||
if (!unityVer.IsStripped && specUnityVer != unityVer)
|
||||
if (!unityVer.IsStripped && customUnityVer != unityVer)
|
||||
{
|
||||
Logger.Warning($"Detected Unity version is different from the specified one ({specUnityVer.FullVersion.Color(ColorConsole.BrightCyan)}).\n" +
|
||||
Logger.Warning($"Detected Unity version is different from the specified one ({customUnityVer.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;
|
||||
unityVer = customUnityVer;
|
||||
}
|
||||
|
||||
UnityCnCheck(reader, customBlockInfoCompression, unityVer);
|
||||
UnityCnCheck(reader, unityVer);
|
||||
|
||||
ReadBlocksInfoAndDirectory(reader, customBlockInfoCompression, unityVer);
|
||||
ReadBlocksInfoAndDirectory(reader, unityVer);
|
||||
|
||||
if (!isMultiBundle && IsUncompressedBundle)
|
||||
{
|
||||
@@ -142,7 +146,7 @@ namespace AssetStudio
|
||||
break;
|
||||
}
|
||||
|
||||
blocksStream = ReadBlocks(reader, customBlockCompression);
|
||||
blocksStream = ReadBlocks(reader);
|
||||
ReadFiles(blocksStream);
|
||||
|
||||
if (!IsDataAfterBundle)
|
||||
@@ -190,7 +194,7 @@ namespace AssetStudio
|
||||
private Stream CreateBlocksStream(string path)
|
||||
{
|
||||
var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize);
|
||||
return uncompressedSizeSum >= int.MaxValue
|
||||
return uncompressedSizeSum >= int.MaxValue || _bundleOptions.DecompressToDisk
|
||||
? new FileStream(path + ".temp", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096, FileOptions.DeleteOnClose)
|
||||
: (Stream) new MemoryStream((int)uncompressedSizeSum);
|
||||
}
|
||||
@@ -264,7 +268,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadBlocksInfoAndDirectory(FileReader reader, CompressionType customBlockInfoCompression, UnityVersion unityVer, bool silent = false)
|
||||
private void ReadBlocksInfoAndDirectory(FileReader reader, UnityVersion unityVer, bool silent = false)
|
||||
{
|
||||
byte[] blocksInfoBytes;
|
||||
|
||||
@@ -304,6 +308,7 @@ namespace AssetStudio
|
||||
blocksInfoBytes = reader.ReadBytes(compressedSize);
|
||||
}
|
||||
|
||||
var customBlockInfoCompression = _bundleOptions.CustomBlockInfoCompression;
|
||||
var compressionType = (CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask);
|
||||
if (customBlockInfoCompression == CompressionType.Auto)
|
||||
{
|
||||
@@ -402,8 +407,9 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
private Stream ReadBlocks(FileReader reader, CompressionType customBlockCompression)
|
||||
private Stream ReadBlocks(FileReader reader)
|
||||
{
|
||||
var customBlockCompression = _bundleOptions.CustomBlockCompression;
|
||||
var blocksStream = CreateBlocksStream(reader.FullPath);
|
||||
var blocksCompression = m_BlocksInfo.Max(x => (CompressionType)(x.flags & StorageBlockFlags.CompressionTypeMask));
|
||||
Logger.Debug($"BlockData compression: {blocksCompression}");
|
||||
@@ -503,7 +509,7 @@ namespace AssetStudio
|
||||
return blocksStream;
|
||||
}
|
||||
|
||||
private void UnityCnCheck(FileReader reader, CompressionType customBlockInfoCompression, UnityVersion unityVer)
|
||||
private void UnityCnCheck(FileReader reader, UnityVersion unityVer)
|
||||
{
|
||||
var hasUnityCnFlag = false;
|
||||
if (!unityVer.IsStripped)
|
||||
@@ -528,7 +534,7 @@ namespace AssetStudio
|
||||
reader.Position += 70;
|
||||
try
|
||||
{
|
||||
ReadBlocksInfoAndDirectory(reader, customBlockInfoCompression, unityVer, silent: true);
|
||||
ReadBlocksInfoAndDirectory(reader, unityVer, silent: true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace AssetStudio
|
||||
if (m_FileID > 0 && m_FileID - 1 < _assetsFile.m_Externals.Count)
|
||||
{
|
||||
var assetsManager = _assetsFile.assetsManager;
|
||||
var assetsFileList = assetsManager.assetsFileList;
|
||||
var assetsFileList = assetsManager.AssetsFileList;
|
||||
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
|
||||
|
||||
if (_index == -2)
|
||||
@@ -126,7 +126,7 @@ namespace AssetStudio
|
||||
}
|
||||
|
||||
var assetsManager = _assetsFile.assetsManager;
|
||||
var assetsFileList = assetsManager.assetsFileList;
|
||||
var assetsFileList = assetsManager.AssetsFileList;
|
||||
var assetsFileIndexCache = assetsManager.assetsFileIndexCache;
|
||||
|
||||
if (!assetsFileIndexCache.TryGetValue(name, out _index))
|
||||
|
||||
56
AssetStudio/CustomOptions/Asmo/OptionsFile.cs
Normal file
56
AssetStudio/CustomOptions/Asmo/OptionsFile.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
|
||||
namespace AssetStudio.CustomOptions.Asmo
|
||||
{
|
||||
public class OptionsFile
|
||||
{
|
||||
private static readonly byte[] OptionsFileSign = new byte[] { 0x41, 0x53, 0x4D, 0x4F }; //ASMO
|
||||
public static readonly string Extension = ".asmo";
|
||||
|
||||
public byte[] Signature { get; private set; } = OptionsFileSign;
|
||||
public short Version { get; private set; } = 1;
|
||||
public short Reserved { get; set; }
|
||||
public uint DataCrc { get; set; }
|
||||
public int DataSize { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
|
||||
public OptionsFile() { }
|
||||
|
||||
public OptionsFile(EndianBinaryReader reader)
|
||||
{
|
||||
Signature = reader.ReadBytes(4);
|
||||
Version = reader.ReadInt16();
|
||||
Reserved = reader.ReadInt16();
|
||||
DataCrc = reader.ReadUInt32();
|
||||
DataSize = reader.ReadInt32();
|
||||
CheckHeader(reader.BaseStream.Length);
|
||||
Data = reader.ReadBytes(DataSize);
|
||||
}
|
||||
|
||||
public void CheckHeader(long fileLength)
|
||||
{
|
||||
if (!Signature.AsSpan().SequenceEqual(OptionsFileSign))
|
||||
throw new NotSupportedException("Incorrect options file signature.");
|
||||
|
||||
if (Version != 1)
|
||||
throw new NotSupportedException("Incorrect options file version.");
|
||||
|
||||
if (DataSize <= 0 || DataSize > fileLength)
|
||||
throw new NotSupportedException("Incorrect data size.");
|
||||
}
|
||||
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
var buffer = new byte[16 + DataSize];
|
||||
OptionsFileSign.AsSpan().CopyTo(buffer);
|
||||
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(4), Version);
|
||||
BinaryPrimitives.WriteInt16BigEndian(buffer.AsSpan(6), Reserved);
|
||||
BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(8), DataCrc);
|
||||
BinaryPrimitives.WriteInt32BigEndian(buffer.AsSpan(12), DataSize);
|
||||
Data.AsSpan().CopyTo(buffer.AsSpan(16));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
40
AssetStudio/CustomOptions/CustomBundleOptions.cs
Normal file
40
AssetStudio/CustomOptions/CustomBundleOptions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
namespace AssetStudio.CustomOptions
|
||||
{
|
||||
public class CustomBundleOptions
|
||||
{
|
||||
private CompressionType _customBlockCompression = CompressionType.Auto;
|
||||
private CompressionType _customBlockInfoCompression = CompressionType.Auto;
|
||||
private bool _decompressToDisk;
|
||||
|
||||
public ImportOptions Options;
|
||||
|
||||
public CompressionType CustomBlockCompression
|
||||
{
|
||||
get => _customBlockCompression;
|
||||
set => _customBlockCompression = SetOption(nameof(CustomBlockCompression), value);
|
||||
}
|
||||
public CompressionType CustomBlockInfoCompression
|
||||
{
|
||||
get => _customBlockInfoCompression;
|
||||
set => _customBlockInfoCompression = SetOption(nameof(CustomBlockInfoCompression), value);
|
||||
}
|
||||
public bool DecompressToDisk
|
||||
{
|
||||
get => _decompressToDisk;
|
||||
set => _decompressToDisk = SetOption(nameof(DecompressToDisk), value);
|
||||
}
|
||||
|
||||
public CustomBundleOptions() { }
|
||||
|
||||
public CustomBundleOptions(ImportOptions importOptions)
|
||||
{
|
||||
Options = importOptions;
|
||||
}
|
||||
|
||||
private static T SetOption<T>(string option, T value)
|
||||
{
|
||||
Logger.Info($"- {option}: {value}");
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
94
AssetStudio/CustomOptions/ImportOptions.cs
Normal file
94
AssetStudio/CustomOptions/ImportOptions.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using AssetStudio.CustomOptions.Asmo;
|
||||
using SevenZip;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AssetStudio.CustomOptions
|
||||
{
|
||||
public class ImportOptions
|
||||
{
|
||||
private static JsonSerializerOptions jsonOptions;
|
||||
private static string fileName = "ImportOptions";
|
||||
private UnityVersion _customUnityVer;
|
||||
|
||||
public CustomBundleOptions BundleOptions { get; set; }
|
||||
public UnityVersion CustomUnityVersion { get => _customUnityVer; set => SetUnityVersion(value); }
|
||||
|
||||
static ImportOptions()
|
||||
{
|
||||
jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
ReferenceHandler = ReferenceHandler.Preserve,
|
||||
IncludeFields = true,
|
||||
};
|
||||
}
|
||||
|
||||
public ImportOptions()
|
||||
{
|
||||
BundleOptions = new CustomBundleOptions(this);
|
||||
CustomUnityVersion = null;
|
||||
}
|
||||
|
||||
public static ImportOptions FromOptionsFile(OptionsFile optionsFile)
|
||||
{
|
||||
if (optionsFile.Reserved != 0)
|
||||
{
|
||||
Logger.Debug("Skipped. Not an import options file.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var utf8Bytes = Convert.FromBase64String(Encoding.ASCII.GetString(optionsFile.Data));
|
||||
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
|
||||
if (optionsFile.DataCrc != dataCrc)
|
||||
throw new IOException("Options file data is corrupted.");
|
||||
|
||||
return JsonSerializer.Deserialize<ImportOptions>(utf8Bytes, jsonOptions);
|
||||
}
|
||||
|
||||
public void SaveToFile(string outputFolder)
|
||||
{
|
||||
var utf8Bytes = JsonSerializer.SerializeToUtf8Bytes(this, jsonOptions);
|
||||
var dataCrc = CRC.CalculateDigest(utf8Bytes, 0, (uint)utf8Bytes.Length);
|
||||
var base64String = Convert.ToBase64String(utf8Bytes);
|
||||
|
||||
var optionsFile = new OptionsFile
|
||||
{
|
||||
DataCrc = dataCrc,
|
||||
DataSize = base64String.Length,
|
||||
Data = Encoding.ASCII.GetBytes(base64String),
|
||||
};
|
||||
|
||||
var unityVer = _customUnityVer != null
|
||||
? $"_{_customUnityVer}"
|
||||
: "";
|
||||
var path = Path.Combine(outputFolder, $"{fileName}{unityVer}{OptionsFile.Extension}");
|
||||
File.WriteAllBytes(path, optionsFile.ToByteArray());
|
||||
|
||||
Logger.Info($"Options file saved to \"{path}\"");
|
||||
}
|
||||
|
||||
private void SetUnityVersion(UnityVersion value)
|
||||
{
|
||||
if (_customUnityVer == value)
|
||||
return;
|
||||
if (value == null)
|
||||
{
|
||||
_customUnityVer = 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");
|
||||
}
|
||||
_customUnityVer = value;
|
||||
|
||||
Logger.Info($"- Specified Unity version: {_customUnityVer}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace AssetStudio
|
||||
namespace AssetStudio
|
||||
{
|
||||
public enum FileType
|
||||
{
|
||||
|
||||
@@ -74,13 +74,13 @@ namespace AssetStudio
|
||||
var verStr = reader.ReadStringToNull();
|
||||
if (!UnityVersion.TryParse(verStr, out version))
|
||||
{
|
||||
if (assetsManager.SpecifyUnityVersion == null)
|
||||
if (assetsManager.Options.CustomUnityVersion == null)
|
||||
{
|
||||
Logger.Warning($"Failed to parse Unity version: \"{verStr}\"");
|
||||
version = new UnityVersion();
|
||||
return;
|
||||
}
|
||||
version = assetsManager.SpecifyUnityVersion;
|
||||
version = assetsManager.Options.CustomUnityVersion;
|
||||
reader.Position = versionPos;
|
||||
reader.ReadBytes(version.ToString().Length + 1);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AssetStudio
|
||||
@@ -54,6 +55,7 @@ namespace AssetStudio
|
||||
}
|
||||
}
|
||||
|
||||
[JsonConstructor]
|
||||
public UnityVersion(int major = 0, int minor = 0, int patch = 0)
|
||||
{
|
||||
(Major, Minor, Patch) = (major, minor, patch);
|
||||
|
||||
Reference in New Issue
Block a user