v0.80.65
This commit is contained in:
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2020-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace AssetStudio
|
|||||||
public static CancellationTokenSource tokenSource = new CancellationTokenSource();
|
public static CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
private static string BaseFolder = "";
|
private static string BaseFolder = "";
|
||||||
private static Dictionary<string, Entry> Map = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
|
private static Dictionary<string, Entry> CABMap = new Dictionary<string, Entry>(StringComparer.OrdinalIgnoreCase);
|
||||||
private static Dictionary<string, HashSet<long>> Offsets = new Dictionary<string, HashSet<long>>();
|
private static Dictionary<string, HashSet<long>> Offsets = new Dictionary<string, HashSet<long>>();
|
||||||
private static AssetsManager assetsManager = new AssetsManager() { Silent = true, SkipProcess = true, ResolveDependencies = false };
|
private static AssetsManager assetsManager = new AssetsManager() { Silent = true, SkipProcess = true, ResolveDependencies = false };
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static void Clear()
|
public static void Clear()
|
||||||
{
|
{
|
||||||
Map.Clear();
|
CABMap.Clear();
|
||||||
Offsets.Clear();
|
Offsets.Clear();
|
||||||
BaseFolder = string.Empty;
|
BaseFolder = string.Empty;
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static bool TryAdd(string name, out string path)
|
public static bool TryAdd(string name, out string path)
|
||||||
{
|
{
|
||||||
if (Map.TryGetValue(name, out var entry))
|
if (CABMap.TryGetValue(name, out var entry))
|
||||||
{
|
{
|
||||||
path = Path.Combine(BaseFolder, entry.Path);
|
path = Path.Combine(BaseFolder, entry.Path);
|
||||||
if (!Offsets.ContainsKey(path))
|
if (!Offsets.ContainsKey(path))
|
||||||
@@ -81,269 +81,326 @@ namespace AssetStudio
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BuildMap(string[] files, string mapName, string baseFolder, Game game)
|
public static void BuildCABMap(string[] files, string mapName, string baseFolder, Game game)
|
||||||
{
|
{
|
||||||
Logger.Info($"Building Map...");
|
Logger.Info("Building CABMap...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Map.Clear();
|
CABMap.Clear();
|
||||||
Progress.Reset();
|
Progress.Reset();
|
||||||
var collision = 0;
|
var collision = 0;
|
||||||
BaseFolder = baseFolder;
|
BaseFolder = baseFolder;
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
for (int i = 0; i < files.Length; i++)
|
foreach (var file in LoadFiles(files))
|
||||||
{
|
{
|
||||||
var file = files[i];
|
BuildCABMap(file, ref collision);
|
||||||
assetsManager.LoadFiles(file);
|
|
||||||
if (assetsManager.assetsFileList.Count > 0)
|
|
||||||
{
|
|
||||||
var relativePath = Path.GetRelativePath(BaseFolder, file);
|
|
||||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
|
||||||
{
|
|
||||||
if (tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
Logger.Info("Building Map has been aborted !!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var dependencies = assetsFile.m_Externals.Select(x => x.fileName).ToArray();
|
|
||||||
var entry = new Entry()
|
|
||||||
{
|
|
||||||
Path = relativePath,
|
|
||||||
Offset = assetsFile.offset,
|
|
||||||
Dependencies = dependencies
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Map.ContainsKey(assetsFile.fileName))
|
|
||||||
{
|
|
||||||
collision++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Map.Add(assetsFile.fileName, entry);
|
|
||||||
}
|
|
||||||
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
|
||||||
Progress.Report(i + 1, files.Length);
|
|
||||||
}
|
|
||||||
assetsManager.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map = Map.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
DumpCABMap(mapName);
|
||||||
var outputFile = Path.Combine(MapName, $"{mapName}.bin");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
|
Logger.Info($"CABMap build successfully !! {collision} collisions found");
|
||||||
|
|
||||||
using (var binaryFile = File.OpenWrite(outputFile))
|
|
||||||
using (var writer = new BinaryWriter(binaryFile))
|
|
||||||
{
|
|
||||||
writer.Write(BaseFolder);
|
|
||||||
writer.Write(Map.Count);
|
|
||||||
foreach (var kv in Map)
|
|
||||||
{
|
|
||||||
writer.Write(kv.Key);
|
|
||||||
writer.Write(kv.Value.Path);
|
|
||||||
writer.Write(kv.Value.Offset);
|
|
||||||
writer.Write(kv.Value.Dependencies.Length);
|
|
||||||
foreach (var cab in kv.Value.Dependencies)
|
|
||||||
{
|
|
||||||
writer.Write(cab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info($"Map build successfully !! {collision} collisions found");
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warning($"Map was not build, {e}");
|
Logger.Warning($"CABMap was not build, {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BuildBoth(string[] files, string mapName, string baseFolder, Game game, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
private static IEnumerable<string> LoadFiles(string[] files)
|
||||||
{
|
{
|
||||||
Logger.Info($"Building Both...");
|
|
||||||
Map.Clear();
|
|
||||||
Progress.Reset();
|
|
||||||
var collision = 0;
|
|
||||||
BaseFolder = baseFolder;
|
|
||||||
assetsManager.Game = game;
|
|
||||||
var assets = new List<AssetEntry>();
|
|
||||||
for (int i = 0; i < files.Length; i++)
|
for (int i = 0; i < files.Length; i++)
|
||||||
{
|
{
|
||||||
var file = files[i];
|
var file = files[i];
|
||||||
assetsManager.LoadFiles(file);
|
assetsManager.LoadFiles(file);
|
||||||
if (assetsManager.assetsFileList.Count > 0)
|
if (assetsManager.assetsFileList.Count > 0)
|
||||||
{
|
{
|
||||||
var relativePath = Path.GetRelativePath(BaseFolder, file);
|
yield return file;
|
||||||
var containers = new List<(PPtr<Object>, string)>();
|
|
||||||
var mihoyoBinDataNames = new List<(PPtr<Object>, string)>();
|
|
||||||
var objectAssetItemDic = new Dictionary<Object, AssetEntry>();
|
|
||||||
var animators = new List<(PPtr<Object>, AssetEntry)>();
|
|
||||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
|
||||||
{
|
|
||||||
if (tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
Logger.Info("Building Map has been aborted !!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var dependencies = assetsFile.m_Externals.Select(x => x.fileName).ToArray();
|
|
||||||
var entry = new Entry()
|
|
||||||
{
|
|
||||||
Path = relativePath,
|
|
||||||
Offset = assetsFile.offset,
|
|
||||||
Dependencies = dependencies
|
|
||||||
};
|
|
||||||
|
|
||||||
if (Map.ContainsKey(assetsFile.fileName))
|
|
||||||
{
|
|
||||||
collision++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Map.Add(assetsFile.fileName, entry);
|
|
||||||
|
|
||||||
foreach (var objInfo in assetsFile.m_Objects)
|
|
||||||
{
|
|
||||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo, game);
|
|
||||||
var obj = new Object(objectReader);
|
|
||||||
var asset = new AssetEntry()
|
|
||||||
{
|
|
||||||
Source = file,
|
|
||||||
PathID = objectReader.m_PathID,
|
|
||||||
Type = objectReader.type,
|
|
||||||
Container = string.Empty,
|
|
||||||
Name = string.Empty
|
|
||||||
};
|
|
||||||
|
|
||||||
var exportable = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (objectReader.type)
|
|
||||||
{
|
|
||||||
case ClassIDType.AssetBundle:
|
|
||||||
var assetBundle = new AssetBundle(objectReader);
|
|
||||||
foreach (var m_Container in assetBundle.m_Container)
|
|
||||||
{
|
|
||||||
var preloadIndex = m_Container.Value.preloadIndex;
|
|
||||||
var preloadSize = m_Container.Value.preloadSize;
|
|
||||||
var preloadEnd = preloadIndex + preloadSize;
|
|
||||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
|
||||||
{
|
|
||||||
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj = null;
|
|
||||||
asset.Name = assetBundle.m_Name;
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
case ClassIDType.GameObject:
|
|
||||||
var gameObject = new GameObject(objectReader);
|
|
||||||
obj = gameObject;
|
|
||||||
asset.Name = gameObject.m_Name;
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
case ClassIDType.Shader:
|
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
|
||||||
if (string.IsNullOrEmpty(asset.Name))
|
|
||||||
{
|
|
||||||
var m_parsedForm = new SerializedShader(objectReader);
|
|
||||||
asset.Name = m_parsedForm.m_Name;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ClassIDType.Animator:
|
|
||||||
var component = new PPtr<Object>(objectReader);
|
|
||||||
animators.Add((component, asset));
|
|
||||||
break;
|
|
||||||
case ClassIDType.MiHoYoBinData:
|
|
||||||
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
|
||||||
obj = MiHoYoBinData;
|
|
||||||
exportable = true;
|
|
||||||
break;
|
|
||||||
case ClassIDType.IndexObject:
|
|
||||||
var indexObject = new IndexObject(objectReader);
|
|
||||||
obj = null;
|
|
||||||
foreach (var index in indexObject.AssetMap)
|
|
||||||
{
|
|
||||||
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
|
||||||
}
|
|
||||||
asset.Name = "IndexObject";
|
|
||||||
break;
|
|
||||||
case ClassIDType.Font:
|
|
||||||
case ClassIDType.Material:
|
|
||||||
case ClassIDType.Texture:
|
|
||||||
case ClassIDType.Mesh:
|
|
||||||
case ClassIDType.Sprite:
|
|
||||||
case ClassIDType.TextAsset:
|
|
||||||
case ClassIDType.Texture2D:
|
|
||||||
case ClassIDType.VideoClip:
|
|
||||||
case ClassIDType.AudioClip:
|
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine("Unable to load object")
|
|
||||||
.AppendLine($"Assets {assetsFile.fileName}")
|
|
||||||
.AppendLine($"Path {assetsFile.originalPath}")
|
|
||||||
.AppendLine($"Type {objectReader.type}")
|
|
||||||
.AppendLine($"PathID {objectReader.m_PathID}")
|
|
||||||
.Append(e);
|
|
||||||
Logger.Error(sb.ToString());
|
|
||||||
}
|
|
||||||
if (obj != null)
|
|
||||||
{
|
|
||||||
objectAssetItemDic.Add(obj, asset);
|
|
||||||
assetsFile.AddObject(obj);
|
|
||||||
}
|
|
||||||
var isMatchRegex = nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(asset.Name) || asset.Type == ClassIDType.Animator);
|
|
||||||
if (isMatchRegex && exportable)
|
|
||||||
{
|
|
||||||
assets.Add(asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ((var pptr, var asset) in animators)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet<GameObject>(out var gameObject) && (nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(gameObject.m_Name))))
|
|
||||||
{
|
|
||||||
asset.Name = gameObject.m_Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ((var pptr, var name) in mihoyoBinDataNames)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet<MiHoYoBinData>(out var miHoYoBinData))
|
|
||||||
{
|
|
||||||
var asset = objectAssetItemDic[miHoYoBinData];
|
|
||||||
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash))
|
|
||||||
{
|
|
||||||
asset.Name = name;
|
|
||||||
asset.Container = hash.ToString();
|
|
||||||
}
|
|
||||||
else asset.Name = $"BinFile #{asset.PathID}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ((var pptr, var container) in containers)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet(out var obj))
|
|
||||||
{
|
|
||||||
var item = objectAssetItemDic[obj];
|
|
||||||
if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container)))
|
|
||||||
{
|
|
||||||
item.Container = container;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assets.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
||||||
Progress.Report(i + 1, files.Length);
|
Progress.Report(i + 1, files.Length);
|
||||||
}
|
}
|
||||||
assetsManager.Clear();
|
assetsManager.Clear();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildCABMap(string file, ref int collision)
|
||||||
|
{
|
||||||
|
var relativePath = Path.GetRelativePath(BaseFolder, file);
|
||||||
|
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||||
|
{
|
||||||
|
if (tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Building CABMap has been cancelled !!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var dependencies = assetsFile.m_Externals.Select(x => x.fileName).ToArray();
|
||||||
|
var entry = new Entry()
|
||||||
|
{
|
||||||
|
Path = relativePath,
|
||||||
|
Offset = assetsFile.offset,
|
||||||
|
Dependencies = dependencies
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CABMap.ContainsKey(assetsFile.fileName))
|
||||||
|
{
|
||||||
|
collision++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CABMap.Add(assetsFile.fileName, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DumpCABMap(string mapName)
|
||||||
|
{
|
||||||
|
CABMap = CABMap.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var outputFile = Path.Combine(MapName, $"{mapName}.bin");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
|
||||||
|
|
||||||
|
using (var binaryFile = File.OpenWrite(outputFile))
|
||||||
|
using (var writer = new BinaryWriter(binaryFile))
|
||||||
|
{
|
||||||
|
writer.Write(BaseFolder);
|
||||||
|
writer.Write(CABMap.Count);
|
||||||
|
foreach (var kv in CABMap)
|
||||||
|
{
|
||||||
|
writer.Write(kv.Key);
|
||||||
|
writer.Write(kv.Value.Path);
|
||||||
|
writer.Write(kv.Value.Offset);
|
||||||
|
writer.Write(kv.Value.Dependencies.Length);
|
||||||
|
foreach (var cab in kv.Value.Dependencies)
|
||||||
|
{
|
||||||
|
writer.Write(cab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void LoadCABMap(string mapName)
|
||||||
|
{
|
||||||
|
Logger.Info($"Loading {mapName}");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CABMap.Clear();
|
||||||
|
using (var fs = File.OpenRead(Path.Combine(MapName, $"{mapName}.bin")))
|
||||||
|
using (var reader = new BinaryReader(fs))
|
||||||
|
{
|
||||||
|
BaseFolder = reader.ReadString();
|
||||||
|
var count = reader.ReadInt32();
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var cab = reader.ReadString();
|
||||||
|
var path = reader.ReadString();
|
||||||
|
var offset = reader.ReadInt64();
|
||||||
|
var depCount = reader.ReadInt32();
|
||||||
|
var dependencies = new List<string>();
|
||||||
|
for (int j = 0; j < depCount; j++)
|
||||||
|
{
|
||||||
|
var dependancy = reader.ReadString();
|
||||||
|
dependencies.Add(dependancy);
|
||||||
|
}
|
||||||
|
var entry = new Entry()
|
||||||
|
{
|
||||||
|
Path = path,
|
||||||
|
Offset = offset,
|
||||||
|
Dependencies = dependencies.ToArray()
|
||||||
|
};
|
||||||
|
CABMap.Add(cab, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Logger.Info($"Loaded {mapName} !!");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.Warning($"{mapName} was not loaded, {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void BuildAssetMap(string[] files, string mapName, Game game, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null, ClassIDType[] typeFilters = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
||||||
|
{
|
||||||
|
Logger.Info("Building AssetMap...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Progress.Reset();
|
||||||
|
assetsManager.Game = game;
|
||||||
|
var assets = new List<AssetEntry>();
|
||||||
|
foreach (var file in LoadFiles(files))
|
||||||
|
{
|
||||||
|
BuildAssetMap(file, assets, typeFilters, nameFilters, containerFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateContainers(assets, game);
|
||||||
|
|
||||||
|
ExportAssetsMap(assets.ToArray(), mapName, savePath, exportListType, resetEvent);
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Logger.Warning($"AssetMap was not build, {e}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildAssetMap(string file, List<AssetEntry> assets, ClassIDType[] typeFilters = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
||||||
|
{
|
||||||
|
var containers = new List<(PPtr<Object>, string)>();
|
||||||
|
var mihoyoBinDataNames = new List<(PPtr<Object>, string)>();
|
||||||
|
var objectAssetItemDic = new Dictionary<Object, AssetEntry>();
|
||||||
|
var animators = new List<(PPtr<Object>, AssetEntry)>();
|
||||||
|
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||||
|
{
|
||||||
|
foreach (var objInfo in assetsFile.m_Objects)
|
||||||
|
{
|
||||||
|
if (tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Building AssetMap has been cancelled !!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo, assetsManager.Game);
|
||||||
|
var obj = new Object(objectReader);
|
||||||
|
var asset = new AssetEntry()
|
||||||
|
{
|
||||||
|
Source = file,
|
||||||
|
PathID = objectReader.m_PathID,
|
||||||
|
Type = objectReader.type,
|
||||||
|
Container = ""
|
||||||
|
};
|
||||||
|
|
||||||
|
var exportable = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (objectReader.type)
|
||||||
|
{
|
||||||
|
case ClassIDType.AssetBundle:
|
||||||
|
var assetBundle = new AssetBundle(objectReader);
|
||||||
|
foreach (var m_Container in assetBundle.m_Container)
|
||||||
|
{
|
||||||
|
var preloadIndex = m_Container.Value.preloadIndex;
|
||||||
|
var preloadSize = m_Container.Value.preloadSize;
|
||||||
|
var preloadEnd = preloadIndex + preloadSize;
|
||||||
|
for (int k = preloadIndex; k < preloadEnd; k++)
|
||||||
|
{
|
||||||
|
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj = null;
|
||||||
|
asset.Name = assetBundle.m_Name;
|
||||||
|
exportable = false;
|
||||||
|
break;
|
||||||
|
case ClassIDType.GameObject:
|
||||||
|
var gameObject = new GameObject(objectReader);
|
||||||
|
obj = gameObject;
|
||||||
|
asset.Name = gameObject.m_Name;
|
||||||
|
exportable = false;
|
||||||
|
break;
|
||||||
|
case ClassIDType.Shader when Shader.Parsable:
|
||||||
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
|
if (string.IsNullOrEmpty(asset.Name))
|
||||||
|
{
|
||||||
|
var m_parsedForm = new SerializedShader(objectReader);
|
||||||
|
asset.Name = m_parsedForm.m_Name;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ClassIDType.Animator:
|
||||||
|
var component = new PPtr<Object>(objectReader);
|
||||||
|
animators.Add((component, asset));
|
||||||
|
break;
|
||||||
|
case ClassIDType.MiHoYoBinData:
|
||||||
|
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
||||||
|
obj = MiHoYoBinData;
|
||||||
|
exportable = true;
|
||||||
|
break;
|
||||||
|
case ClassIDType.IndexObject:
|
||||||
|
var indexObject = new IndexObject(objectReader);
|
||||||
|
obj = null;
|
||||||
|
foreach (var index in indexObject.AssetMap)
|
||||||
|
{
|
||||||
|
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
||||||
|
}
|
||||||
|
asset.Name = "IndexObject";
|
||||||
|
break;
|
||||||
|
case ClassIDType.Font:
|
||||||
|
case ClassIDType.Material:
|
||||||
|
case ClassIDType.Texture:
|
||||||
|
case ClassIDType.Mesh:
|
||||||
|
case ClassIDType.Sprite:
|
||||||
|
case ClassIDType.TextAsset:
|
||||||
|
case ClassIDType.Texture2D:
|
||||||
|
case ClassIDType.VideoClip:
|
||||||
|
case ClassIDType.AudioClip:
|
||||||
|
asset.Name = objectReader.ReadAlignedString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exportable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
sb.AppendLine("Unable to load object")
|
||||||
|
.AppendLine($"Assets {assetsFile.fileName}")
|
||||||
|
.AppendLine($"Path {assetsFile.originalPath}")
|
||||||
|
.AppendLine($"Type {objectReader.type}")
|
||||||
|
.AppendLine($"PathID {objectReader.m_PathID}")
|
||||||
|
.Append(e);
|
||||||
|
Logger.Error(sb.ToString());
|
||||||
|
}
|
||||||
|
if (obj != null)
|
||||||
|
{
|
||||||
|
objectAssetItemDic.Add(obj, asset);
|
||||||
|
assetsFile.AddObject(obj);
|
||||||
|
}
|
||||||
|
var isMatchRegex = nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(asset.Name) || asset.Type == ClassIDType.Animator);
|
||||||
|
var isFilteredType = typeFilters.IsNullOrEmpty() || typeFilters.Contains(asset.Type) || asset.Type == ClassIDType.Animator;
|
||||||
|
if (isMatchRegex && isFilteredType && exportable)
|
||||||
|
{
|
||||||
|
assets.Add(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ((var pptr, var asset) in animators)
|
||||||
|
{
|
||||||
|
if (pptr.TryGet<GameObject>(out var gameObject) && (nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(gameObject.m_Name))) && (typeFilters.IsNullOrEmpty() || typeFilters.Contains(asset.Type)))
|
||||||
|
{
|
||||||
|
asset.Name = gameObject.m_Name;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assets.Remove(asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
foreach ((var pptr, var name) in mihoyoBinDataNames)
|
||||||
|
{
|
||||||
|
if (pptr.TryGet<MiHoYoBinData>(out var miHoYoBinData))
|
||||||
|
{
|
||||||
|
var asset = objectAssetItemDic[miHoYoBinData];
|
||||||
|
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash))
|
||||||
|
{
|
||||||
|
asset.Name = name;
|
||||||
|
asset.Container = hash.ToString();
|
||||||
|
}
|
||||||
|
else asset.Name = $"BinFile #{asset.PathID}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ((var pptr, var container) in containers)
|
||||||
|
{
|
||||||
|
if (pptr.TryGet(out var obj))
|
||||||
|
{
|
||||||
|
var item = objectAssetItemDic[obj];
|
||||||
|
if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container)))
|
||||||
|
{
|
||||||
|
item.Container = container;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assets.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UpdateContainers(List<AssetEntry> assets, Game game)
|
||||||
|
{
|
||||||
if (game.Type.IsGISubGroup() && assets.Count > 0)
|
if (game.Type.IsGISubGroup() && assets.Count > 0)
|
||||||
{
|
{
|
||||||
Logger.Info("Updating Containers...");
|
Logger.Info("Updating Containers...");
|
||||||
@@ -369,267 +426,9 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
Logger.Info("Updated !!");
|
Logger.Info("Updated !!");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map = Map.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);
|
|
||||||
var outputFile = Path.Combine(MapName, $"{mapName}.bin");
|
|
||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(outputFile));
|
|
||||||
|
|
||||||
using (var binaryFile = File.OpenWrite(outputFile))
|
|
||||||
using (var writer = new BinaryWriter(binaryFile))
|
|
||||||
{
|
|
||||||
writer.Write(BaseFolder);
|
|
||||||
writer.Write(Map.Count);
|
|
||||||
foreach (var kv in Map)
|
|
||||||
{
|
|
||||||
writer.Write(kv.Key);
|
|
||||||
writer.Write(kv.Value.Path);
|
|
||||||
writer.Write(kv.Value.Offset);
|
|
||||||
writer.Write(kv.Value.Dependencies.Length);
|
|
||||||
foreach (var cab in kv.Value.Dependencies)
|
|
||||||
{
|
|
||||||
writer.Write(cab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.Info($"Map build successfully !! {collision} collisions found");
|
|
||||||
ExportAssetsMap(assets.ToArray(), mapName, savePath, exportListType, resetEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool LoadMap(string mapName)
|
private static void ExportAssetsMap(AssetEntry[] toExportAssets, string name, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null)
|
||||||
{
|
|
||||||
Logger.Info($"Loading {mapName}");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Map.Clear();
|
|
||||||
using (var fs = File.OpenRead(Path.Combine(MapName, $"{mapName}.bin")))
|
|
||||||
using (var reader = new BinaryReader(fs))
|
|
||||||
{
|
|
||||||
BaseFolder = reader.ReadString();
|
|
||||||
var count = reader.ReadInt32();
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
var cab = reader.ReadString();
|
|
||||||
var path = reader.ReadString();
|
|
||||||
var offset = reader.ReadInt64();
|
|
||||||
var depCount = reader.ReadInt32();
|
|
||||||
var dependencies = new List<string>();
|
|
||||||
for (int j = 0; j < depCount; j++)
|
|
||||||
{
|
|
||||||
var dependancy = reader.ReadString();
|
|
||||||
dependencies.Add(dependancy);
|
|
||||||
}
|
|
||||||
var entry = new Entry()
|
|
||||||
{
|
|
||||||
Path = path,
|
|
||||||
Offset = offset,
|
|
||||||
Dependencies = dependencies.ToArray()
|
|
||||||
};
|
|
||||||
Map.Add(cab, entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.Info($"Loaded {mapName} !!");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logger.Warning($"{mapName} was not loaded, {e}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AssetEntry[] BuildAssetMap(string[] files, Game game, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
|
||||||
{
|
|
||||||
Progress.Reset();
|
|
||||||
assetsManager.Game = game;
|
|
||||||
var assets = new List<AssetEntry>();
|
|
||||||
for (int i = 0; i < files.Length; i++)
|
|
||||||
{
|
|
||||||
var file = files[i];
|
|
||||||
assetsManager.LoadFiles(file);
|
|
||||||
if (assetsManager.assetsFileList.Count > 0)
|
|
||||||
{
|
|
||||||
var containers = new List<(PPtr<Object>, string)>();
|
|
||||||
var mihoyoBinDataNames = new List<(PPtr<Object>, string)>();
|
|
||||||
var objectAssetItemDic = new Dictionary<Object, AssetEntry>();
|
|
||||||
var animators = new List<(PPtr<Object>, AssetEntry)>();
|
|
||||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
|
||||||
{
|
|
||||||
foreach (var objInfo in assetsFile.m_Objects)
|
|
||||||
{
|
|
||||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objInfo, game);
|
|
||||||
var obj = new Object(objectReader);
|
|
||||||
var asset = new AssetEntry()
|
|
||||||
{
|
|
||||||
Source = file,
|
|
||||||
PathID = objectReader.m_PathID,
|
|
||||||
Type = objectReader.type,
|
|
||||||
Container = ""
|
|
||||||
};
|
|
||||||
|
|
||||||
var exportable = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
switch (objectReader.type)
|
|
||||||
{
|
|
||||||
case ClassIDType.AssetBundle:
|
|
||||||
var assetBundle = new AssetBundle(objectReader);
|
|
||||||
foreach (var m_Container in assetBundle.m_Container)
|
|
||||||
{
|
|
||||||
var preloadIndex = m_Container.Value.preloadIndex;
|
|
||||||
var preloadSize = m_Container.Value.preloadSize;
|
|
||||||
var preloadEnd = preloadIndex + preloadSize;
|
|
||||||
for (int k = preloadIndex; k < preloadEnd; k++)
|
|
||||||
{
|
|
||||||
containers.Add((assetBundle.m_PreloadTable[k], m_Container.Key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj = null;
|
|
||||||
asset.Name = assetBundle.m_Name;
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
case ClassIDType.GameObject:
|
|
||||||
var gameObject = new GameObject(objectReader);
|
|
||||||
obj = gameObject;
|
|
||||||
asset.Name = gameObject.m_Name;
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
case ClassIDType.Shader:
|
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
|
||||||
if (string.IsNullOrEmpty(asset.Name))
|
|
||||||
{
|
|
||||||
var m_parsedForm = new SerializedShader(objectReader);
|
|
||||||
asset.Name = m_parsedForm.m_Name;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ClassIDType.Animator:
|
|
||||||
var component = new PPtr<Object>(objectReader);
|
|
||||||
animators.Add((component, asset));
|
|
||||||
break;
|
|
||||||
case ClassIDType.MiHoYoBinData:
|
|
||||||
var MiHoYoBinData = new MiHoYoBinData(objectReader);
|
|
||||||
obj = MiHoYoBinData;
|
|
||||||
exportable = true;
|
|
||||||
break;
|
|
||||||
case ClassIDType.IndexObject:
|
|
||||||
var indexObject = new IndexObject(objectReader);
|
|
||||||
obj = null;
|
|
||||||
foreach (var index in indexObject.AssetMap)
|
|
||||||
{
|
|
||||||
mihoyoBinDataNames.Add((index.Value.Object, index.Key));
|
|
||||||
}
|
|
||||||
asset.Name = "IndexObject";
|
|
||||||
break;
|
|
||||||
case ClassIDType.Font:
|
|
||||||
case ClassIDType.Material:
|
|
||||||
case ClassIDType.Texture:
|
|
||||||
case ClassIDType.Mesh:
|
|
||||||
case ClassIDType.Sprite:
|
|
||||||
case ClassIDType.TextAsset:
|
|
||||||
case ClassIDType.Texture2D:
|
|
||||||
case ClassIDType.VideoClip:
|
|
||||||
case ClassIDType.AudioClip:
|
|
||||||
asset.Name = objectReader.ReadAlignedString();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
exportable = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine("Unable to load object")
|
|
||||||
.AppendLine($"Assets {assetsFile.fileName}")
|
|
||||||
.AppendLine($"Path {assetsFile.originalPath}")
|
|
||||||
.AppendLine($"Type {objectReader.type}")
|
|
||||||
.AppendLine($"PathID {objectReader.m_PathID}")
|
|
||||||
.Append(e);
|
|
||||||
Logger.Error(sb.ToString());
|
|
||||||
}
|
|
||||||
if (obj != null)
|
|
||||||
{
|
|
||||||
objectAssetItemDic.Add(obj, asset);
|
|
||||||
assetsFile.AddObject(obj);
|
|
||||||
}
|
|
||||||
var isMatchRegex = nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(asset.Name) || asset.Type == ClassIDType.Animator);
|
|
||||||
if (isMatchRegex && exportable)
|
|
||||||
{
|
|
||||||
assets.Add(asset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ((var pptr, var asset) in animators)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet<GameObject>(out var gameObject) && (nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(gameObject.m_Name))))
|
|
||||||
{
|
|
||||||
asset.Name = gameObject.m_Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach((var pptr, var name) in mihoyoBinDataNames)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet<MiHoYoBinData>(out var miHoYoBinData))
|
|
||||||
{
|
|
||||||
var asset = objectAssetItemDic[miHoYoBinData];
|
|
||||||
if (int.TryParse(name, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var hash))
|
|
||||||
{
|
|
||||||
asset.Name = name;
|
|
||||||
asset.Container = hash.ToString();
|
|
||||||
}
|
|
||||||
else asset.Name = $"BinFile #{asset.PathID}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach ((var pptr, var container) in containers)
|
|
||||||
{
|
|
||||||
if (pptr.TryGet(out var obj))
|
|
||||||
{
|
|
||||||
var item = objectAssetItemDic[obj];
|
|
||||||
if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container)))
|
|
||||||
{
|
|
||||||
item.Container = container;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assets.Remove(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.Info($"[{i + 1}/{files.Length}] Processed {Path.GetFileName(file)}");
|
|
||||||
Progress.Report(i + 1, files.Length);
|
|
||||||
}
|
|
||||||
assetsManager.Clear();
|
|
||||||
}
|
|
||||||
if (game.Type.IsGISubGroup() && assets.Count > 0)
|
|
||||||
{
|
|
||||||
Logger.Info("Updating Containers...");
|
|
||||||
foreach (var asset in assets)
|
|
||||||
{
|
|
||||||
if (int.TryParse(asset.Container, out var value))
|
|
||||||
{
|
|
||||||
var last = unchecked((uint)value);
|
|
||||||
var name = Path.GetFileNameWithoutExtension(asset.Source);
|
|
||||||
if (uint.TryParse(name, out var id))
|
|
||||||
{
|
|
||||||
var path = ResourceIndex.GetContainer(id, last);
|
|
||||||
if (!string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
asset.Container = path;
|
|
||||||
if (asset.Type == ClassIDType.MiHoYoBinData)
|
|
||||||
{
|
|
||||||
asset.Name = Path.GetFileNameWithoutExtension(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Logger.Info("Updated !!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return assets.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ExportAssetsMap(AssetEntry[] toExportAssets, string name, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null)
|
|
||||||
{
|
{
|
||||||
ThreadPool.QueueUserWorkItem(state =>
|
ThreadPool.QueueUserWorkItem(state =>
|
||||||
{
|
{
|
||||||
@@ -683,5 +482,26 @@ namespace AssetStudio
|
|||||||
resetEvent?.Set();
|
resetEvent?.Set();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public static void BuildBoth(string[] files, string mapName, string baseFolder, Game game, string savePath, ExportListType exportListType, ManualResetEvent resetEvent = null, ClassIDType[] typeFilters = null, Regex[] nameFilters = null, Regex[] containerFilters = null)
|
||||||
|
{
|
||||||
|
Logger.Info($"Building Both...");
|
||||||
|
CABMap.Clear();
|
||||||
|
Progress.Reset();
|
||||||
|
var collision = 0;
|
||||||
|
BaseFolder = baseFolder;
|
||||||
|
assetsManager.Game = game;
|
||||||
|
var assets = new List<AssetEntry>();
|
||||||
|
foreach(var file in LoadFiles(files))
|
||||||
|
{
|
||||||
|
BuildCABMap(file, ref collision);
|
||||||
|
BuildAssetMap(file, assets, typeFilters, nameFilters, containerFilters);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateContainers(assets, game);
|
||||||
|
DumpCABMap(mapName);
|
||||||
|
|
||||||
|
Logger.Info($"Map build successfully !! {collision} collisions found");
|
||||||
|
ExportAssetsMap(assets.ToArray(), mapName, savePath, exportListType, resetEvent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ namespace AssetStudio
|
|||||||
public string SpecifyUnityVersion;
|
public string SpecifyUnityVersion;
|
||||||
public CancellationTokenSource tokenSource = new CancellationTokenSource();
|
public CancellationTokenSource tokenSource = new CancellationTokenSource();
|
||||||
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
public List<SerializedFile> assetsFileList = new List<SerializedFile>();
|
||||||
public Dictionary<ClassIDType, bool> ExportableTypes = new Dictionary<ClassIDType, bool>();
|
|
||||||
|
|
||||||
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
internal Dictionary<string, int> assetsFileIndexCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
internal Dictionary<string, BinaryReader> resourceFileReaders = new Dictionary<string, BinaryReader>(StringComparer.OrdinalIgnoreCase);
|
||||||
@@ -29,25 +28,6 @@ namespace AssetStudio
|
|||||||
internal HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
internal HashSet<string> noexistFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
internal HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
internal HashSet<string> assetsFileListHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public AssetsManager()
|
|
||||||
{
|
|
||||||
ExportableTypes.Add(ClassIDType.GameObject, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Material, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Texture2D, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.AudioClip, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.VideoClip, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Mesh, false);
|
|
||||||
ExportableTypes.Add(ClassIDType.Renderer, false);
|
|
||||||
ExportableTypes.Add(ClassIDType.Shader, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.TextAsset, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.AnimationClip, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.MonoBehaviour, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Font, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Sprite, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.Animator, true);
|
|
||||||
ExportableTypes.Add(ClassIDType.MiHoYoBinData, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadFiles(params string[] files)
|
public void LoadFiles(params string[] files)
|
||||||
{
|
{
|
||||||
if (Silent)
|
if (Silent)
|
||||||
@@ -115,7 +95,7 @@ namespace AssetStudio
|
|||||||
assetsFileListHash.Clear();
|
assetsFileListHash.Clear();
|
||||||
AssetsHelper.ClearOffsets();
|
AssetsHelper.ClearOffsets();
|
||||||
|
|
||||||
if (!SkipProcess && !tokenSource.IsCancellationRequested)
|
if (!SkipProcess)
|
||||||
{
|
{
|
||||||
ReadAssets();
|
ReadAssets();
|
||||||
ProcessAssets();
|
ProcessAssets();
|
||||||
@@ -457,7 +437,7 @@ namespace AssetStudio
|
|||||||
Logger.Info("Loading " + reader.FullPath);
|
Logger.Info("Loading " + reader.FullPath);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var stream = new SubStream(reader.BaseStream, 0);
|
using var stream = new OffsetStream(reader.BaseStream, 0);
|
||||||
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
if (AssetsHelper.TryGet(reader.FullPath, out var offsets))
|
||||||
{
|
{
|
||||||
foreach (var offset in offsets)
|
foreach (var offset in offsets)
|
||||||
@@ -527,7 +507,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
var name = stream.Position.ToString("X8");
|
var name = stream.AbsolutePosition.ToString("X8");
|
||||||
Logger.Info($"Loading Block {name}");
|
Logger.Info($"Loading Block {name}");
|
||||||
|
|
||||||
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
var dummyPath = Path.Combine(Path.GetDirectoryName(reader.FullPath), name);
|
||||||
@@ -535,14 +515,14 @@ namespace AssetStudio
|
|||||||
switch (subReader.FileType)
|
switch (subReader.FileType)
|
||||||
{
|
{
|
||||||
case FileType.BundleFile:
|
case FileType.BundleFile:
|
||||||
LoadBundleFile(subReader, reader.FullPath, stream.Position, false);
|
LoadBundleFile(subReader, reader.FullPath, stream.AbsolutePosition, false);
|
||||||
break;
|
break;
|
||||||
case FileType.Mhy0File:
|
case FileType.Mhy0File:
|
||||||
LoadMhy0File(subReader, reader.FullPath, stream.Position, false);
|
LoadMhy0File(subReader, reader.FullPath, stream.AbsolutePosition, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.Offset += stream.Position;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
} while (stream.Remaining > 0);
|
} while (stream.Remaining > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -650,13 +630,9 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (tokenSource.IsCancellationRequested)
|
if (tokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Logger.Info("Reading assets has been aborted !!");
|
Logger.Info("Reading assets has been cancelled !!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (assetsFile.IsLoaded(objectInfo))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo, Game);
|
var objectReader = new ObjectReader(assetsFile.reader, assetsFile, objectInfo, Game);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -666,10 +642,10 @@ namespace AssetStudio
|
|||||||
case ClassIDType.Animation:
|
case ClassIDType.Animation:
|
||||||
obj = new Animation(objectReader);
|
obj = new Animation(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AnimationClip when ExportableTypes[ClassIDType.AnimationClip]:
|
case ClassIDType.AnimationClip:
|
||||||
obj = new AnimationClip(objectReader);
|
obj = new AnimationClip(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Animator when ExportableTypes[ClassIDType.Animator]:
|
case ClassIDType.Animator:
|
||||||
obj = new Animator(objectReader);
|
obj = new Animator(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AnimatorController:
|
case ClassIDType.AnimatorController:
|
||||||
@@ -681,37 +657,37 @@ namespace AssetStudio
|
|||||||
case ClassIDType.AssetBundle:
|
case ClassIDType.AssetBundle:
|
||||||
obj = new AssetBundle(objectReader);
|
obj = new AssetBundle(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.AudioClip when ExportableTypes[ClassIDType.AudioClip]:
|
case ClassIDType.AudioClip:
|
||||||
obj = new AudioClip(objectReader);
|
obj = new AudioClip(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Avatar:
|
case ClassIDType.Avatar:
|
||||||
obj = new Avatar(objectReader);
|
obj = new Avatar(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Font when ExportableTypes[ClassIDType.Font]:
|
case ClassIDType.Font:
|
||||||
obj = new Font(objectReader);
|
obj = new Font(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.GameObject when ExportableTypes[ClassIDType.GameObject]:
|
case ClassIDType.GameObject:
|
||||||
obj = new GameObject(objectReader);
|
obj = new GameObject(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.IndexObject when ExportableTypes[ClassIDType.MiHoYoBinData]:
|
case ClassIDType.IndexObject:
|
||||||
obj = new IndexObject(objectReader);
|
obj = new IndexObject(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Material when ExportableTypes[ClassIDType.Material]:
|
case ClassIDType.Material:
|
||||||
obj = new Material(objectReader);
|
obj = new Material(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Mesh when ExportableTypes[ClassIDType.Mesh]:
|
case ClassIDType.Mesh:
|
||||||
obj = new Mesh(objectReader);
|
obj = new Mesh(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MeshFilter:
|
case ClassIDType.MeshFilter:
|
||||||
obj = new MeshFilter(objectReader);
|
obj = new MeshFilter(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MeshRenderer when ExportableTypes[ClassIDType.Renderer]:
|
case ClassIDType.MeshRenderer when Renderer.Parsable:
|
||||||
obj = new MeshRenderer(objectReader);
|
obj = new MeshRenderer(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MiHoYoBinData when ExportableTypes[ClassIDType.MiHoYoBinData]:
|
case ClassIDType.MiHoYoBinData:
|
||||||
obj = new MiHoYoBinData(objectReader);
|
obj = new MiHoYoBinData(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MonoBehaviour when ExportableTypes[ClassIDType.MonoBehaviour]:
|
case ClassIDType.MonoBehaviour:
|
||||||
obj = new MonoBehaviour(objectReader);
|
obj = new MonoBehaviour(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.MonoScript:
|
case ClassIDType.MonoScript:
|
||||||
@@ -726,28 +702,28 @@ namespace AssetStudio
|
|||||||
case ClassIDType.RectTransform:
|
case ClassIDType.RectTransform:
|
||||||
obj = new RectTransform(objectReader);
|
obj = new RectTransform(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Shader when ExportableTypes[ClassIDType.Shader]:
|
case ClassIDType.Shader when Shader.Parsable:
|
||||||
obj = new Shader(objectReader);
|
obj = new Shader(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.SkinnedMeshRenderer when ExportableTypes[ClassIDType.Renderer]:
|
case ClassIDType.SkinnedMeshRenderer when Renderer.Parsable:
|
||||||
obj = new SkinnedMeshRenderer(objectReader);
|
obj = new SkinnedMeshRenderer(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Sprite when ExportableTypes[ClassIDType.Sprite]:
|
case ClassIDType.Sprite:
|
||||||
obj = new Sprite(objectReader);
|
obj = new Sprite(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.SpriteAtlas:
|
case ClassIDType.SpriteAtlas:
|
||||||
obj = new SpriteAtlas(objectReader);
|
obj = new SpriteAtlas(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.TextAsset when ExportableTypes[ClassIDType.TextAsset]:
|
case ClassIDType.TextAsset:
|
||||||
obj = new TextAsset(objectReader);
|
obj = new TextAsset(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Texture2D when ExportableTypes[ClassIDType.Texture2D]:
|
case ClassIDType.Texture2D:
|
||||||
obj = new Texture2D(objectReader);
|
obj = new Texture2D(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.Transform:
|
case ClassIDType.Transform:
|
||||||
obj = new Transform(objectReader);
|
obj = new Transform(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.VideoClip when ExportableTypes[ClassIDType.VideoClip]:
|
case ClassIDType.VideoClip:
|
||||||
obj = new VideoClip(objectReader);
|
obj = new VideoClip(objectReader);
|
||||||
break;
|
break;
|
||||||
case ClassIDType.ResourceManager:
|
case ClassIDType.ResourceManager:
|
||||||
@@ -778,9 +754,6 @@ namespace AssetStudio
|
|||||||
|
|
||||||
private void ProcessAssets()
|
private void ProcessAssets()
|
||||||
{
|
{
|
||||||
if (tokenSource.IsCancellationRequested)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Logger.Info("Process Assets...");
|
Logger.Info("Process Assets...");
|
||||||
|
|
||||||
foreach (var assetsFile in assetsFileList)
|
foreach (var assetsFile in assetsFileList)
|
||||||
@@ -789,62 +762,62 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
if (tokenSource.IsCancellationRequested)
|
if (tokenSource.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Logger.Info("Processing assets has been aborted !!");
|
Logger.Info("Processing assets has been cancelled !!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (obj is GameObject m_GameObject)
|
if (obj is GameObject m_GameObject)
|
||||||
{
|
{
|
||||||
foreach (var pptr in m_GameObject.m_Components)
|
foreach (var pptr in m_GameObject.m_Components)
|
||||||
{
|
|
||||||
if (pptr.TryGet(out var m_Component))
|
|
||||||
{
|
{
|
||||||
switch (m_Component)
|
if (pptr.TryGet(out var m_Component))
|
||||||
{
|
{
|
||||||
|
switch (m_Component)
|
||||||
|
{
|
||||||
case Transform m_Transform:
|
case Transform m_Transform:
|
||||||
m_GameObject.m_Transform = m_Transform;
|
m_GameObject.m_Transform = m_Transform;
|
||||||
break;
|
break;
|
||||||
case MeshRenderer m_MeshRenderer:
|
case MeshRenderer m_MeshRenderer:
|
||||||
m_GameObject.m_MeshRenderer = m_MeshRenderer;
|
m_GameObject.m_MeshRenderer = m_MeshRenderer;
|
||||||
break;
|
break;
|
||||||
case MeshFilter m_MeshFilter:
|
case MeshFilter m_MeshFilter:
|
||||||
m_GameObject.m_MeshFilter = m_MeshFilter;
|
m_GameObject.m_MeshFilter = m_MeshFilter;
|
||||||
break;
|
break;
|
||||||
case SkinnedMeshRenderer m_SkinnedMeshRenderer:
|
case SkinnedMeshRenderer m_SkinnedMeshRenderer:
|
||||||
m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;
|
m_GameObject.m_SkinnedMeshRenderer = m_SkinnedMeshRenderer;
|
||||||
break;
|
break;
|
||||||
case Animator m_Animator:
|
case Animator m_Animator:
|
||||||
m_GameObject.m_Animator = m_Animator;
|
m_GameObject.m_Animator = m_Animator;
|
||||||
break;
|
break;
|
||||||
case Animation m_Animation:
|
case Animation m_Animation:
|
||||||
m_GameObject.m_Animation = m_Animation;
|
m_GameObject.m_Animation = m_Animation;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (obj is SpriteAtlas m_SpriteAtlas)
|
else if (obj is SpriteAtlas m_SpriteAtlas)
|
||||||
{
|
{
|
||||||
if (m_SpriteAtlas.m_RenderDataMap.Count > 0)
|
if (m_SpriteAtlas.m_RenderDataMap.Count > 0)
|
||||||
{
|
|
||||||
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
|
|
||||||
{
|
{
|
||||||
if (m_PackedSprite.TryGet(out var m_Sprite))
|
foreach (var m_PackedSprite in m_SpriteAtlas.m_PackedSprites)
|
||||||
{
|
{
|
||||||
if (m_Sprite.m_SpriteAtlas.IsNull)
|
if (m_PackedSprite.TryGet(out var m_Sprite))
|
||||||
{
|
{
|
||||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
if (m_Sprite.m_SpriteAtlas.IsNull)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
|
|
||||||
if (m_SpriteAtlaOld.m_IsVariant)
|
|
||||||
{
|
{
|
||||||
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_Sprite.m_SpriteAtlas.TryGet(out var m_SpriteAtlaOld);
|
||||||
|
if (m_SpriteAtlaOld.m_IsVariant)
|
||||||
|
{
|
||||||
|
m_Sprite.m_SpriteAtlas.Set(m_SpriteAtlas);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
var m_UpdateMode = reader.ReadInt32();
|
var m_UpdateMode = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reader.Game.Type.IsSR())
|
||||||
|
{
|
||||||
|
var m_MotionSkeletonMode = reader.ReadInt32();
|
||||||
|
}
|
||||||
|
|
||||||
var m_ApplyRootMotion = reader.ReadBoolean();
|
var m_ApplyRootMotion = reader.ReadBoolean();
|
||||||
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
|
if (version[0] == 4 && version[1] >= 5) //4.5 and up - 5.0 down
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public abstract class Renderer : Component
|
public abstract class Renderer : Component
|
||||||
{
|
{
|
||||||
|
public static bool Parsable;
|
||||||
|
|
||||||
public PPtr<Material>[] m_Materials;
|
public PPtr<Material>[] m_Materials;
|
||||||
public StaticBatchInfo m_StaticBatchInfo;
|
public StaticBatchInfo m_StaticBatchInfo;
|
||||||
public uint[] m_SubsetIndices;
|
public uint[] m_SubsetIndices;
|
||||||
@@ -218,7 +220,7 @@ namespace AssetStudio
|
|||||||
var m_UseHighestMip = reader.ReadBoolean();
|
var m_UseHighestMip = reader.ReadBoolean();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
}
|
}
|
||||||
if (reader.Game.Type.IsSRCB3())
|
if (reader.Game.Type.IsSR())
|
||||||
{
|
{
|
||||||
var RenderFlag = reader.ReadUInt32();
|
var RenderFlag = reader.ReadUInt32();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
|
|||||||
@@ -578,6 +578,9 @@ namespace AssetStudio
|
|||||||
public UAVParameter[] m_UAVParams;
|
public UAVParameter[] m_UAVParams;
|
||||||
public SamplerParameter[] m_Samplers;
|
public SamplerParameter[] m_Samplers;
|
||||||
|
|
||||||
|
private static bool HasGlobalLocalKeywordIndices(ObjectReader reader) => reader.serializedType.Match("E99740711222CD922E9A6F92FF1EB07A") || reader.serializedType.Match("450A058C218DAF000647948F2F59DA6D");
|
||||||
|
private static bool HasInstancedStructuredBuffers(ObjectReader reader) => reader.serializedType.Match("E99740711222CD922E9A6F92FF1EB07A");
|
||||||
|
|
||||||
public SerializedSubProgram(ObjectReader reader)
|
public SerializedSubProgram(ObjectReader reader)
|
||||||
{
|
{
|
||||||
var version = reader.version;
|
var version = reader.version;
|
||||||
@@ -585,7 +588,7 @@ namespace AssetStudio
|
|||||||
m_BlobIndex = reader.ReadUInt32();
|
m_BlobIndex = reader.ReadUInt32();
|
||||||
m_Channels = new ParserBindChannels(reader);
|
m_Channels = new ParserBindChannels(reader);
|
||||||
|
|
||||||
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2) || reader.Match("E99740711222CD922E9A6F92FF1EB07A") || reader.Match("450A058C218DAF000647948F2F59DA6D")) //2019 ~2021.1
|
if ((version[0] >= 2019 && version[0] < 2021) || (version[0] == 2021 && version[1] < 2) || HasGlobalLocalKeywordIndices(reader)) //2019 ~2021.1
|
||||||
{
|
{
|
||||||
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
var m_GlobalKeywordIndices = reader.ReadUInt16Array();
|
||||||
reader.AlignStream();
|
reader.AlignStream();
|
||||||
@@ -687,7 +690,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.Match("E99740711222CD922E9A6F92FF1EB07A"))
|
if (HasInstancedStructuredBuffers(reader))
|
||||||
{
|
{
|
||||||
int numInstancedStructuredBuffers = reader.ReadInt32();
|
int numInstancedStructuredBuffers = reader.ReadInt32();
|
||||||
var m_InstancedStructuredBuffers = new ConstantBuffer[numInstancedStructuredBuffers];
|
var m_InstancedStructuredBuffers = new ConstantBuffer[numInstancedStructuredBuffers];
|
||||||
@@ -974,6 +977,8 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public class Shader : NamedObject
|
public class Shader : NamedObject
|
||||||
{
|
{
|
||||||
|
public static bool Parsable;
|
||||||
|
|
||||||
public byte[] m_Script;
|
public byte[] m_Script;
|
||||||
//5.3 - 5.4
|
//5.3 - 5.4
|
||||||
public uint decompressedSize;
|
public uint decompressedSize;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using static AssetStudio.ImportHelper;
|
using static AssetStudio.ImportHelper;
|
||||||
|
|
||||||
@@ -172,7 +173,20 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
if (reader.FileType == FileType.BundleFile && game.Type.IsBlockFile())
|
if (reader.FileType == FileType.BundleFile && game.Type.IsBlockFile())
|
||||||
{
|
{
|
||||||
reader.FileType = FileType.BlockFile;
|
try
|
||||||
|
{
|
||||||
|
var signature = reader.ReadStringToNull();
|
||||||
|
reader.ReadInt32();
|
||||||
|
reader.ReadStringToNull();
|
||||||
|
reader.ReadStringToNull();
|
||||||
|
var size = reader.ReadInt64();
|
||||||
|
if (!(signature == "UnityFS" && size == reader.BaseStream.Length))
|
||||||
|
{
|
||||||
|
reader.FileType = FileType.BlockFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception) { }
|
||||||
|
reader.Position = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return reader;
|
return reader;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace AssetStudio
|
|||||||
Games.Add(index++, new Mr0k(GameType.BH3, BH3ExpansionKey, BH3SBox, BH3InitVector, BH3BlockKey));
|
Games.Add(index++, new Mr0k(GameType.BH3, BH3ExpansionKey, BH3SBox, BH3InitVector, BH3BlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.BH3_Pre, PackExpansionKey, blockKey: PackBlockKey));
|
Games.Add(index++, new Mr0k(GameType.BH3_Pre, PackExpansionKey, blockKey: PackBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.SR_CB2, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.SR_CB2, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.SR_CB3, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.SR, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.ZZZ_CB1, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
Games.Add(index++, new Mr0k(GameType.ZZZ_CB1, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey));
|
||||||
Games.Add(index++, new Mr0k(GameType.TOT, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey, postKey: ToTKey));
|
Games.Add(index++, new Mr0k(GameType.TOT, Mr0kExpansionKey, initVector: Mr0kInitVector, blockKey: Mr0kBlockKey, postKey: ToTKey));
|
||||||
Games.Add(index++, new Game(GameType.Naraka));
|
Games.Add(index++, new Game(GameType.Naraka));
|
||||||
@@ -124,7 +124,7 @@ namespace AssetStudio
|
|||||||
BH3_Pre,
|
BH3_Pre,
|
||||||
ZZZ_CB1,
|
ZZZ_CB1,
|
||||||
SR_CB2,
|
SR_CB2,
|
||||||
SR_CB3,
|
SR,
|
||||||
TOT,
|
TOT,
|
||||||
Naraka,
|
Naraka,
|
||||||
EnsembleStars,
|
EnsembleStars,
|
||||||
@@ -148,7 +148,7 @@ namespace AssetStudio
|
|||||||
public static bool IsBH3Pre(this GameType type) => type == GameType.BH3_Pre;
|
public static bool IsBH3Pre(this GameType type) => type == GameType.BH3_Pre;
|
||||||
public static bool IsZZZCB1(this GameType type) => type == GameType.ZZZ_CB1;
|
public static bool IsZZZCB1(this GameType type) => type == GameType.ZZZ_CB1;
|
||||||
public static bool IsSRCB2(this GameType type) => type == GameType.SR_CB2;
|
public static bool IsSRCB2(this GameType type) => type == GameType.SR_CB2;
|
||||||
public static bool IsSRCB3(this GameType type) => type == GameType.SR_CB3;
|
public static bool IsSR(this GameType type) => type == GameType.SR;
|
||||||
public static bool IsTOT(this GameType type) => type == GameType.TOT;
|
public static bool IsTOT(this GameType type) => type == GameType.TOT;
|
||||||
public static bool IsNaraka(this GameType type) => type == GameType.Naraka;
|
public static bool IsNaraka(this GameType type) => type == GameType.Naraka;
|
||||||
public static bool IsOPFP(this GameType type) => type == GameType.OPFP;
|
public static bool IsOPFP(this GameType type) => type == GameType.OPFP;
|
||||||
@@ -172,19 +172,19 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public static bool IsSRGroup(this GameType type) => type switch
|
public static bool IsSRGroup(this GameType type) => type switch
|
||||||
{
|
{
|
||||||
GameType.SR_CB2 or GameType.SR_CB3 => true,
|
GameType.SR_CB2 or GameType.SR => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static bool IsBlockFile(this GameType type) => type switch
|
public static bool IsBlockFile(this GameType type) => type switch
|
||||||
{
|
{
|
||||||
GameType.BH3 or GameType.BH3_Pre or GameType.SR_CB3 or GameType.GI_Pack or GameType.TOT => true,
|
GameType.BH3 or GameType.BH3_Pre or GameType.SR or GameType.GI_Pack or GameType.TOT => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static bool IsMhyGroup(this GameType type) => type switch
|
public static bool IsMhyGroup(this GameType type) => type switch
|
||||||
{
|
{
|
||||||
GameType.GI or GameType.GI_Pack or GameType.GI_CB1 or GameType.GI_CB2 or GameType.GI_CB3 or GameType.GI_CB3Pre or GameType.BH3 or GameType.SR_CB2 or GameType.SR_CB3 or GameType.TOT => true,
|
GameType.GI or GameType.GI_Pack or GameType.GI_CB1 or GameType.GI_CB2 or GameType.GI_CB3 or GameType.GI_CB3Pre or GameType.BH3 or GameType.SR_CB2 or GameType.SR or GameType.TOT => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ namespace AssetStudio
|
|||||||
var idx = data.Search("UnityFS");
|
var idx = data.Search("UnityFS");
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
stream = new SubStream(stream, idx);
|
stream = new OffsetStream(stream, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FileReader(reader.FullPath, stream);
|
return new FileReader(reader.FullPath, stream);
|
||||||
@@ -295,11 +295,11 @@ namespace AssetStudio
|
|||||||
var idx2 = data[(idx + 1)..].Search("UnityFS");
|
var idx2 = data[(idx + 1)..].Search("UnityFS");
|
||||||
if (idx2 != -1)
|
if (idx2 != -1)
|
||||||
{
|
{
|
||||||
stream = new SubStream(stream, idx + idx2 + 1);
|
stream = new OffsetStream(stream, idx + idx2 + 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stream = new SubStream(stream, idx);
|
stream = new OffsetStream(stream, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +371,7 @@ namespace AssetStudio
|
|||||||
reader.Position = 0;
|
reader.Position = 0;
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
var stream = new SubStream(reader.BaseStream, idx);
|
var stream = new OffsetStream(reader.BaseStream, idx);
|
||||||
return new FileReader(reader.FullPath, stream);
|
return new FileReader(reader.FullPath, stream);
|
||||||
}
|
}
|
||||||
public static FileReader ParseHelixWaltz2(FileReader reader)
|
public static FileReader ParseHelixWaltz2(FileReader reader)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace AssetStudio
|
|||||||
public int[] version => assetsFile.version;
|
public int[] version => assetsFile.version;
|
||||||
public BuildType buildType => assetsFile.buildType;
|
public BuildType buildType => assetsFile.buildType;
|
||||||
|
|
||||||
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo, Game game) : base(new SubStream(reader.BaseStream, objectInfo.byteStart, objectInfo.byteSize), reader.Endian)
|
public ObjectReader(EndianBinaryReader reader, SerializedFile assetsFile, ObjectInfo objectInfo, Game game) : base(reader.BaseStream, reader.Endian)
|
||||||
{
|
{
|
||||||
this.assetsFile = assetsFile;
|
this.assetsFile = assetsFile;
|
||||||
Game = game;
|
Game = game;
|
||||||
@@ -41,11 +41,9 @@ namespace AssetStudio
|
|||||||
m_Version = assetsFile.header.m_Version;
|
m_Version = assetsFile.header.m_Version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Match(string hash) => Convert.ToHexString(serializedType.m_OldTypeHash) == hash;
|
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
Position = 0;
|
Position = byteStart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,29 +3,15 @@ using System.IO;
|
|||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class SubStream : Stream
|
public class OffsetStream : Stream
|
||||||
{
|
{
|
||||||
private readonly Stream _baseStream;
|
private readonly Stream _baseStream;
|
||||||
private long _offset;
|
private long _offset;
|
||||||
private long _size;
|
|
||||||
|
|
||||||
public override bool CanRead => _baseStream.CanRead;
|
public override bool CanRead => _baseStream.CanRead;
|
||||||
public override bool CanSeek => _baseStream.CanSeek;
|
public override bool CanSeek => _baseStream.CanSeek;
|
||||||
public override bool CanWrite => false;
|
public override bool CanWrite => false;
|
||||||
|
|
||||||
public long Size
|
|
||||||
{
|
|
||||||
get => _size;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value < 0 || value > _baseStream.Length || value + _offset > _baseStream.Length)
|
|
||||||
{
|
|
||||||
throw new IOException($"{nameof(Size)} is out of stream bound");
|
|
||||||
}
|
|
||||||
_size = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public long Offset
|
public long Offset
|
||||||
{
|
{
|
||||||
get => _offset;
|
get => _offset;
|
||||||
@@ -35,44 +21,30 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
throw new IOException($"{nameof(Offset)} is out of stream bound");
|
throw new IOException($"{nameof(Offset)} is out of stream bound");
|
||||||
}
|
}
|
||||||
if (value + _size > _baseStream.Length)
|
|
||||||
{
|
|
||||||
_size = _baseStream.Length - value;
|
|
||||||
}
|
|
||||||
_offset = value;
|
_offset = value;
|
||||||
|
Seek(0, SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public long AbsolutePosition => _baseStream.Position;
|
public long AbsolutePosition => _baseStream.Position;
|
||||||
public long Remaining => Length - Position;
|
public long Remaining => Length - Position;
|
||||||
|
|
||||||
public override long Length => Size;
|
public override long Length => _baseStream.Length - _offset;
|
||||||
public override long Position
|
public override long Position
|
||||||
{
|
{
|
||||||
get => _baseStream.Position - _offset;
|
get => _baseStream.Position - _offset;
|
||||||
set => Seek(value, SeekOrigin.Begin);
|
set => Seek(value, SeekOrigin.Begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SubStream(Stream stream, long offset)
|
public OffsetStream(Stream stream, long offset)
|
||||||
{
|
{
|
||||||
_baseStream = stream;
|
_baseStream = stream;
|
||||||
|
|
||||||
Offset = offset;
|
Offset = offset;
|
||||||
Size = _baseStream.Length - _offset;
|
|
||||||
Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubStream(Stream stream, long offset, long size)
|
|
||||||
{
|
|
||||||
_baseStream = stream;
|
|
||||||
|
|
||||||
Offset = offset;
|
|
||||||
Size = size;
|
|
||||||
Seek(0, SeekOrigin.Begin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override long Seek(long offset, SeekOrigin origin)
|
public override long Seek(long offset, SeekOrigin origin)
|
||||||
{
|
{
|
||||||
if (offset > _size)
|
if (offset > _baseStream.Length)
|
||||||
{
|
{
|
||||||
throw new IOException("Unable to seek beyond stream bound");
|
throw new IOException("Unable to seek beyond stream bound");
|
||||||
}
|
}
|
||||||
@@ -81,7 +53,7 @@ namespace AssetStudio
|
|||||||
{
|
{
|
||||||
SeekOrigin.Begin => offset + _offset,
|
SeekOrigin.Begin => offset + _offset,
|
||||||
SeekOrigin.Current => offset + Position,
|
SeekOrigin.Current => offset + Position,
|
||||||
SeekOrigin.End => offset + _size,
|
SeekOrigin.End => offset + _baseStream.Length,
|
||||||
_ => throw new NotSupportedException()
|
_ => throw new NotSupportedException()
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,7 +62,7 @@ namespace AssetStudio
|
|||||||
}
|
}
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
if (offset > _size || Position + count > _size)
|
if (offset > _baseStream.Length || Position + count > _baseStream.Length)
|
||||||
{
|
{
|
||||||
throw new IOException("Unable to read beyond stream bound");
|
throw new IOException("Unable to read beyond stream bound");
|
||||||
}
|
}
|
||||||
@@ -387,11 +387,6 @@ namespace AssetStudio
|
|||||||
ObjectsDic.Add(obj.m_PathID, obj);
|
ObjectsDic.Add(obj.m_PathID, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsLoaded(ObjectInfo objInfo)
|
|
||||||
{
|
|
||||||
return ObjectsDic.TryGetValue(objInfo.m_PathID, out var obj) && obj.type == (ClassIDType)objInfo.classID;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int DecodeClassID(int value)
|
private static int DecodeClassID(int value)
|
||||||
{
|
{
|
||||||
var bytes = BitConverter.GetBytes(value);
|
var bytes = BitConverter.GetBytes(value);
|
||||||
|
|||||||
@@ -17,5 +17,7 @@ namespace AssetStudio
|
|||||||
public string m_KlassName;
|
public string m_KlassName;
|
||||||
public string m_NameSpace;
|
public string m_NameSpace;
|
||||||
public string m_AsmName;
|
public string m_AsmName;
|
||||||
|
|
||||||
|
public bool Match(string hash) => Convert.ToHexString(m_OldTypeHash) == hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,13 @@
|
|||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public class XORStream : SubStream
|
public class XORStream : OffsetStream
|
||||||
{
|
{
|
||||||
private readonly byte[] _xorpad;
|
private readonly byte[] _xorpad;
|
||||||
private readonly long _offset;
|
private readonly long _offset;
|
||||||
|
|
||||||
|
private long Index => AbsolutePosition - _offset;
|
||||||
|
|
||||||
public XORStream(Stream stream, long offset, byte[] xorpad) : base(stream, offset)
|
public XORStream(Stream stream, long offset, byte[] xorpad) : base(stream, offset)
|
||||||
{
|
{
|
||||||
_xorpad = xorpad;
|
_xorpad = xorpad;
|
||||||
@@ -15,11 +17,14 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
var pos = AbsolutePosition - _offset;
|
var pos = Index;
|
||||||
var read = base.Read(buffer, offset, count);
|
var read = base.Read(buffer, offset, count);
|
||||||
for (int i = 0; i < count; i++)
|
if (pos >= 0)
|
||||||
{
|
{
|
||||||
buffer[i] ^= _xorpad[pos++ % _xorpad.Length];
|
for (int i = offset; i < count; i++)
|
||||||
|
{
|
||||||
|
buffer[i] ^= _xorpad[pos++ % _xorpad.Length];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,5 +20,7 @@
|
|||||||
<add key="castToBone" value="False" />
|
<add key="castToBone" value="False" />
|
||||||
<add key="restoreExtensionName" value="True" />
|
<add key="restoreExtensionName" value="True" />
|
||||||
<add key="exportAllUvsAsDiffuseMaps" value="False" />
|
<add key="exportAllUvsAsDiffuseMaps" value="False" />
|
||||||
|
<add key="disableShader" value="False" />
|
||||||
|
<add key="disableRenderer" value="False" />
|
||||||
</appSettings>
|
</appSettings>
|
||||||
</configuration>
|
</configuration>
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net6.0-windows;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
||||||
<BaseOutputPath>..\AssetStudioGUI\bin</BaseOutputPath>
|
<BaseOutputPath>..\AssetStudioGUI\bin</BaseOutputPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -334,26 +334,24 @@ namespace AssetStudioCLI
|
|||||||
public static bool ExportGameObject(AssetItem item, string exportPath, List <AssetItem> animationList = null)
|
public static bool ExportGameObject(AssetItem item, string exportPath, List <AssetItem> animationList = null)
|
||||||
{
|
{
|
||||||
var m_GameObject = (GameObject)item.Asset;
|
var m_GameObject = (GameObject)item.Asset;
|
||||||
ExportGameObject(m_GameObject, exportPath, animationList);
|
exportPath = Path.Combine(exportPath, m_GameObject.m_Name) + Path.DirectorySeparatorChar;
|
||||||
return true;
|
return ExportGameObject(m_GameObject, exportPath, animationList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
public static bool ExportGameObject(GameObject gameObject, string exportPath, List<AssetItem> animationList = null)
|
||||||
{
|
{
|
||||||
var convert = animationList != null
|
var convert = animationList != null
|
||||||
? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
? new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
||||||
: new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations);
|
: new ModelConverter(gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations);
|
||||||
|
|
||||||
|
if (convert.MeshList.Count == 0)
|
||||||
|
{
|
||||||
|
Logger.Info($"GameObject {gameObject.m_Name} has no mesh, skipping...");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
exportPath = exportPath + FixFileName(gameObject.m_Name) + ".fbx";
|
||||||
ExportFbx(convert, exportPath);
|
ExportFbx(convert, exportPath);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
public static void ExportGameObjectMerge(List<GameObject> gameObject, string exportPath, List<AssetItem> animationList = null)
|
|
||||||
{
|
|
||||||
var rootName = Path.GetFileNameWithoutExtension(exportPath);
|
|
||||||
var convert = animationList != null
|
|
||||||
? new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations, animationList.Select(x => (AnimationClip)x.Asset).ToArray())
|
|
||||||
: new ModelConverter(rootName, gameObject, Properties.Settings.Default.convertType, Studio.Game, Properties.Settings.Default.collectAnimations);
|
|
||||||
ExportFbx(convert, exportPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ExportFbx(IImported convert, string exportPath)
|
private static void ExportFbx(IImported convert, string exportPath)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AssetStudio;
|
using AssetStudio;
|
||||||
|
using AssetStudioCLI.Properties;
|
||||||
using static AssetStudioCLI.Studio;
|
using static AssetStudioCLI.Studio;
|
||||||
|
|
||||||
namespace AssetStudioCLI
|
namespace AssetStudioCLI
|
||||||
@@ -26,47 +27,16 @@ namespace AssetStudioCLI
|
|||||||
|
|
||||||
Studio.Game = game;
|
Studio.Game = game;
|
||||||
Logger.Default = new ConsoleLogger();
|
Logger.Default = new ConsoleLogger();
|
||||||
|
Shader.Parsable = !Settings.Default.disableShader;
|
||||||
|
Renderer.Parsable = !Settings.Default.disableRenderer;
|
||||||
assetsManager.Silent = o.Silent;
|
assetsManager.Silent = o.Silent;
|
||||||
assetsManager.Game = game;
|
assetsManager.Game = game;
|
||||||
|
ModelOnly = o.Model;
|
||||||
|
|
||||||
if (!o.TypeFilter.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
foreach (var kv in assetsManager.ExportableTypes)
|
|
||||||
{
|
|
||||||
assetsManager.ExportableTypes[kv.Key] = o.TypeFilter.Contains(kv.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.Model)
|
|
||||||
{
|
|
||||||
foreach (var kv in assetsManager.ExportableTypes)
|
|
||||||
{
|
|
||||||
assetsManager.ExportableTypes[kv.Key] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.Animator] = true;
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.GameObject] = true;
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.Texture2D] = true;
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.Material] = true;
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.Renderer] = true;
|
|
||||||
assetsManager.ExportableTypes[ClassIDType.Mesh] = true;
|
|
||||||
|
|
||||||
ModelOnly = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (o.Key != default)
|
if (o.Key != default)
|
||||||
{
|
{
|
||||||
if (!assetsManager.ExportableTypes[ClassIDType.MiHoYoBinData])
|
MiHoYoBinData.Encrypted = true;
|
||||||
{
|
MiHoYoBinData.Key = o.Key;
|
||||||
Logger.Warning("Key is set but MiHoYoBinData is skipped, ignoring key...");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MiHoYoBinData.Encrypted = true;
|
|
||||||
MiHoYoBinData.Key = o.Key;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o.AIFile != null && game.Type.IsGISubGroup())
|
if (o.AIFile != null && game.Type.IsGISubGroup())
|
||||||
@@ -82,36 +52,35 @@ namespace AssetStudioCLI
|
|||||||
Logger.Info("Scanning for files...");
|
Logger.Info("Scanning for files...");
|
||||||
var files = o.Input.Attributes.HasFlag(FileAttributes.Directory) ? Directory.GetFiles(o.Input.FullName, "*.*", SearchOption.AllDirectories).OrderBy(x => x.Length).ToArray() : new string[] { o.Input.FullName };
|
var files = o.Input.Attributes.HasFlag(FileAttributes.Directory) ? Directory.GetFiles(o.Input.FullName, "*.*", SearchOption.AllDirectories).OrderBy(x => x.Length).ToArray() : new string[] { o.Input.FullName };
|
||||||
files = files.Where(x => FileReader.IsReadable(x, game)).ToArray();
|
files = files.Where(x => FileReader.IsReadable(x, game)).ToArray();
|
||||||
Logger.Info(string.Format("Found {0} file(s)", files.Length));
|
Logger.Info($"Found {files.Length} files");
|
||||||
|
|
||||||
if (o.MapOp.HasFlag(MapOpType.Build))
|
if (o.MapOp.HasFlag(MapOpType.CABMap))
|
||||||
{
|
{
|
||||||
AssetsHelper.BuildMap(files, o.MapName, o.Input.FullName, game);
|
AssetsHelper.BuildCABMap(files, o.MapName, o.Input.FullName, game);
|
||||||
}
|
}
|
||||||
if (o.MapOp.HasFlag(MapOpType.Load))
|
if (o.MapOp.HasFlag(MapOpType.Load))
|
||||||
{
|
{
|
||||||
AssetsHelper.LoadMap(o.MapName);
|
AssetsHelper.LoadCABMap(o.MapName);
|
||||||
assetsManager.ResolveDependencies = true;
|
assetsManager.ResolveDependencies = true;
|
||||||
}
|
}
|
||||||
if (o.MapOp.HasFlag(MapOpType.List))
|
if (o.MapOp.HasFlag(MapOpType.AssetMap))
|
||||||
{
|
{
|
||||||
if (files.Length == 1)
|
if (files.Length == 1)
|
||||||
{
|
{
|
||||||
throw new Exception("Unable to build AssetMap with input_path as a file !!");
|
throw new Exception("Unable to build AssetMap with input_path as a file !!");
|
||||||
}
|
}
|
||||||
var assets = AssetsHelper.BuildAssetMap(files, game, o.NameFilter, o.ContainerFilter);
|
|
||||||
if (!o.Output.Exists)
|
if (!o.Output.Exists)
|
||||||
{
|
{
|
||||||
o.Output.Create();
|
o.Output.Create();
|
||||||
}
|
}
|
||||||
var resetEvent = new ManualResetEvent(false);
|
var resetEvent = new ManualResetEvent(false);
|
||||||
AssetsHelper.ExportAssetsMap(assets, o.MapName, o.Output.FullName, o.MapType, resetEvent);
|
AssetsHelper.BuildAssetMap(files, o.MapName, game, o.Output.FullName, o.MapType, resetEvent, o.TypeFilter, o.NameFilter, o.ContainerFilter);
|
||||||
resetEvent.WaitOne();
|
resetEvent.WaitOne();
|
||||||
}
|
}
|
||||||
if (o.MapOp.HasFlag(MapOpType.Both))
|
if (o.MapOp.HasFlag(MapOpType.Both))
|
||||||
{
|
{
|
||||||
var resetEvent = new ManualResetEvent(false);
|
var resetEvent = new ManualResetEvent(false);
|
||||||
AssetsHelper.BuildBoth(files, o.MapName, o.Input.FullName, game, o.Output.FullName, o.MapType, resetEvent, o.NameFilter, o.ContainerFilter);
|
AssetsHelper.BuildBoth(files, o.MapName, o.Input.FullName, game, o.Output.FullName, o.MapType, resetEvent, o.TypeFilter, o.NameFilter, o.ContainerFilter);
|
||||||
resetEvent.WaitOne();
|
resetEvent.WaitOne();
|
||||||
}
|
}
|
||||||
if (o.MapOp.Equals(MapOpType.None) || o.MapOp.HasFlag(MapOpType.Load))
|
if (o.MapOp.Equals(MapOpType.None) || o.MapOp.HasFlag(MapOpType.Load))
|
||||||
@@ -122,7 +91,7 @@ namespace AssetStudioCLI
|
|||||||
assetsManager.LoadFiles(file);
|
assetsManager.LoadFiles(file);
|
||||||
if (assetsManager.assetsFileList.Count > 0)
|
if (assetsManager.assetsFileList.Count > 0)
|
||||||
{
|
{
|
||||||
BuildAssetData(o.NameFilter, o.ContainerFilter, ref i);
|
BuildAssetData(o.TypeFilter, o.NameFilter, o.ContainerFilter, ref i);
|
||||||
ExportAssets(o.Output.FullName, exportableAssets, o.GroupAssetsType);
|
ExportAssets(o.Output.FullName, exportableAssets, o.GroupAssetsType);
|
||||||
}
|
}
|
||||||
exportableAssets.Clear();
|
exportableAssets.Clear();
|
||||||
|
|||||||
@@ -62,11 +62,13 @@ namespace AssetStudioCLI.Properties {
|
|||||||
public bool exportUV0UV1 => AppSettings.Get("exportUV0UV1", false);
|
public bool exportUV0UV1 => AppSettings.Get("exportUV0UV1", false);
|
||||||
public bool encrypted => AppSettings.Get("encrypted", true);
|
public bool encrypted => AppSettings.Get("encrypted", true);
|
||||||
public byte key => AppSettings.Get("key", (byte)0x93);
|
public byte key => AppSettings.Get("key", (byte)0x93);
|
||||||
public bool skipRenderer => AppSettings.Get("skipRenderer", false);
|
|
||||||
public int selectedGame => AppSettings.Get("selectedGame", 0);
|
public int selectedGame => AppSettings.Get("selectedGame", 0);
|
||||||
public bool enableResolveDependencies => AppSettings.Get("enableResolveDependencies", true);
|
public bool enableResolveDependencies => AppSettings.Get("enableResolveDependencies", true);
|
||||||
public int selectedCNUnityKey => AppSettings.Get("selectedCNUnityKey", 0);
|
public int selectedCNUnityKey => AppSettings.Get("selectedCNUnityKey", 0);
|
||||||
public int selectedAssetMapType => AppSettings.Get("selectedAssetMapType", 0);
|
public int selectedAssetMapType => AppSettings.Get("selectedAssetMapType", 0);
|
||||||
public bool exportMiHoYoBinData => AppSettings.Get("exportMiHoYoBinData", true);
|
public bool exportMiHoYoBinData => AppSettings.Get("exportMiHoYoBinData", true);
|
||||||
|
public bool disableShader => AppSettings.Get("disableShader", false);
|
||||||
|
public bool disableRenderer => AppSettings.Get("disableRenderer", false);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
None,
|
None,
|
||||||
Load,
|
Load,
|
||||||
Build,
|
CABMap,
|
||||||
List = 4,
|
AssetMap = 4,
|
||||||
Both = 8,
|
Both = 8,
|
||||||
All = Both | Load,
|
All = Both | Load,
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
Logger.Info($"Decompressing {reader.FileName} ...");
|
Logger.Info($"Decompressing {reader.FileName} ...");
|
||||||
using var stream = new SubStream(reader.BaseStream, 0);
|
using var stream = new OffsetStream(reader.BaseStream, 0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.AbsolutePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
@@ -238,7 +238,7 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void BuildAssetData(Regex[] nameFilters, Regex[] containerFilters, ref int i)
|
public static void BuildAssetData(ClassIDType[] typeFilters, Regex[] nameFilters, Regex[] containerFilters, ref int i)
|
||||||
{
|
{
|
||||||
var objectAssetItemDic = new Dictionary<Object, AssetItem>();
|
var objectAssetItemDic = new Dictionary<Object, AssetItem>();
|
||||||
var mihoyoBinDataNames = new List<(PPtr<Object>, string)>();
|
var mihoyoBinDataNames = new List<(PPtr<Object>, string)>();
|
||||||
@@ -247,7 +247,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
foreach (var asset in assetsFile.Objects)
|
foreach (var asset in assetsFile.Objects)
|
||||||
{
|
{
|
||||||
ProcessAssetData(asset, nameFilters, objectAssetItemDic, mihoyoBinDataNames, containers, ref i);
|
ProcessAssetData(asset, typeFilters, nameFilters, objectAssetItemDic, mihoyoBinDataNames, containers, ref i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ((var pptr, var name) in mihoyoBinDataNames)
|
foreach ((var pptr, var name) in mihoyoBinDataNames)
|
||||||
@@ -269,11 +269,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
if (pptr.TryGet(out var obj))
|
if (pptr.TryGet(out var obj))
|
||||||
{
|
{
|
||||||
if (!objectAssetItemDic.TryGetValue(obj, out var item))
|
var item = objectAssetItemDic[obj];
|
||||||
{
|
|
||||||
ProcessAssetData(obj, nameFilters, objectAssetItemDic, mihoyoBinDataNames, containers, ref i);
|
|
||||||
item = objectAssetItemDic[obj];
|
|
||||||
}
|
|
||||||
if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container)))
|
if (containerFilters.IsNullOrEmpty() || containerFilters.Any(x => x.IsMatch(container)))
|
||||||
{
|
{
|
||||||
item.Container = container;
|
item.Container = container;
|
||||||
@@ -292,7 +288,7 @@ namespace AssetStudioCLI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ProcessAssetData(Object asset, Regex[] nameFilters, Dictionary<Object, AssetItem> objectAssetItemDic, List<(PPtr<Object>, string)> mihoyoBinDataNames, List<(PPtr<Object>, string)> containers, ref int i)
|
public static void ProcessAssetData(Object asset, ClassIDType[] typeFilters, Regex[] nameFilters, Dictionary<Object, AssetItem> objectAssetItemDic, List<(PPtr<Object>, string)> mihoyoBinDataNames, List<(PPtr<Object>, string)> containers, ref int i)
|
||||||
{
|
{
|
||||||
var assetItem = new AssetItem(asset);
|
var assetItem = new AssetItem(asset);
|
||||||
objectAssetItemDic.Add(asset, assetItem);
|
objectAssetItemDic.Add(asset, assetItem);
|
||||||
@@ -322,7 +318,7 @@ namespace AssetStudioCLI
|
|||||||
assetItem.Text = m_VideoClip.m_Name;
|
assetItem.Text = m_VideoClip.m_Name;
|
||||||
exportable = !ModelOnly;
|
exportable = !ModelOnly;
|
||||||
break;
|
break;
|
||||||
case Shader m_Shader:
|
case Shader m_Shader when Shader.Parsable:
|
||||||
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
assetItem.Text = m_Shader.m_ParsedForm?.m_Name ?? m_Shader.m_Name;
|
||||||
exportable = !ModelOnly;
|
exportable = !ModelOnly;
|
||||||
break;
|
break;
|
||||||
@@ -351,7 +347,7 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
assetItem.Text = m_MonoBehaviour.m_Name;
|
assetItem.Text = m_MonoBehaviour.m_Name;
|
||||||
}
|
}
|
||||||
exportable = !ModelOnly;
|
exportable = !ModelOnly && assemblyLoader.Loaded;
|
||||||
break;
|
break;
|
||||||
case AssetBundle m_AssetBundle:
|
case AssetBundle m_AssetBundle:
|
||||||
foreach (var m_Container in m_AssetBundle.m_Container)
|
foreach (var m_Container in m_AssetBundle.m_Container)
|
||||||
@@ -390,8 +386,10 @@ namespace AssetStudioCLI
|
|||||||
{
|
{
|
||||||
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
assetItem.Text = assetItem.TypeString + assetItem.UniqueID;
|
||||||
}
|
}
|
||||||
var isMatchRegex = nameFilters.Length == 0 || nameFilters.Any(x => x.IsMatch(assetItem.Text));
|
|
||||||
if (isMatchRegex && exportable)
|
var isMatchRegex = nameFilters.IsNullOrEmpty() || nameFilters.Any(x => x.IsMatch(assetItem.Text));
|
||||||
|
var isFilteredType = typeFilters.IsNullOrEmpty() || typeFilters.Contains(assetItem.Type);
|
||||||
|
if (isMatchRegex && isFilteredType && exportable)
|
||||||
{
|
{
|
||||||
exportableAssets.Add(assetItem);
|
exportableAssets.Add(assetItem);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022; Copyright © hozuki 2020</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -94,8 +94,11 @@
|
|||||||
<setting name="exportUV0UV1" serializeAs="String">
|
<setting name="exportUV0UV1" serializeAs="String">
|
||||||
<value>False</value>
|
<value>False</value>
|
||||||
</setting>
|
</setting>
|
||||||
<setting name="exportableTypes" serializeAs="String">
|
<setting name="disableShader" serializeAs="String">
|
||||||
<value>{"GameObject":true,"Material":true,"Texture2D":true,"Mesh":true,"Renderer":true,"Shader":true,"TextAsset":true,"AnimationClip":true,"Font":true,"Sprite":true,"Animator":true,"MiHoYoBinData":true,"AssetBundle":true}</value>
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="disableRenderer" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
</setting>
|
</setting>
|
||||||
</AssetStudioGUI.Properties.Settings>
|
</AssetStudioGUI.Properties.Settings>
|
||||||
</userSettings>
|
</userSettings>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
<TargetFrameworks>net6.0-windows;net7.0-windows</TargetFrameworks>
|
<TargetFrameworks>net6.0-windows;net7.0-windows</TargetFrameworks>
|
||||||
<UseWindowsForms>true</UseWindowsForms>
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
<ApplicationIcon>Resources\as.ico</ApplicationIcon>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Razmoth 2022; Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
111
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
111
AssetStudioGUI/AssetStudioGUIForm.Designer.cs
generated
@@ -92,16 +92,18 @@ namespace AssetStudioGUI
|
|||||||
enableConsole = new System.Windows.Forms.ToolStripMenuItem();
|
enableConsole = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
clearConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
clearConsoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
miscToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
miscToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
MapNameComboBox = new System.Windows.Forms.ToolStripComboBox();
|
||||||
|
buildBothToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
clearMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
|
assetMapNameTextBox = new System.Windows.Forms.ToolStripTextBox();
|
||||||
|
buildAssetMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
assetMapTypeComboBox = new System.Windows.Forms.ToolStripComboBox();
|
||||||
|
toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
|
loadAIToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
assetHelpersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
assetHelpersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
MapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
MapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
MapNameComboBox = new System.Windows.Forms.ToolStripComboBox();
|
|
||||||
toolStripMenuItem20 = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
toolStripMenuItem21 = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
assetMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
assetMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
assetMapNameTextBox = new System.Windows.Forms.ToolStripTextBox();
|
|
||||||
toolStripMenuItem22 = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
assetMapTypeComboBox = new System.Windows.Forms.ToolStripComboBox();
|
|
||||||
loadAIToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
|
||||||
toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
|
||||||
splitContainer1 = new System.Windows.Forms.SplitContainer();
|
splitContainer1 = new System.Windows.Forms.SplitContainer();
|
||||||
tabControl1 = new System.Windows.Forms.TabControl();
|
tabControl1 = new System.Windows.Forms.TabControl();
|
||||||
@@ -153,6 +155,7 @@ namespace AssetStudioGUI
|
|||||||
exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
exportAnimatorwithselectedAnimationClipMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
goToSceneHierarchyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
showOriginalFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
|
buildMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
menuStrip1.SuspendLayout();
|
menuStrip1.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
|
((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit();
|
||||||
splitContainer1.Panel1.SuspendLayout();
|
splitContainer1.Panel1.SuspendLayout();
|
||||||
@@ -597,25 +600,11 @@ namespace AssetStudioGUI
|
|||||||
//
|
//
|
||||||
// miscToolStripMenuItem
|
// miscToolStripMenuItem
|
||||||
//
|
//
|
||||||
miscToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { assetHelpersToolStripMenuItem, loadAIToolStripMenuItem });
|
miscToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { MapNameComboBox, buildMapToolStripMenuItem, buildBothToolStripMenuItem, clearMapToolStripMenuItem, toolStripSeparator7, assetMapNameTextBox, buildAssetMapToolStripMenuItem, assetMapTypeComboBox, toolStripSeparator8, loadAIToolStripMenuItem });
|
||||||
miscToolStripMenuItem.Name = "miscToolStripMenuItem";
|
miscToolStripMenuItem.Name = "miscToolStripMenuItem";
|
||||||
miscToolStripMenuItem.Size = new System.Drawing.Size(47, 20);
|
miscToolStripMenuItem.Size = new System.Drawing.Size(47, 20);
|
||||||
miscToolStripMenuItem.Text = "Misc.";
|
miscToolStripMenuItem.Text = "Misc.";
|
||||||
//
|
miscToolStripMenuItem.DropDownOpening += miscToolStripMenuItem_DropDownOpening;
|
||||||
// assetHelpersToolStripMenuItem
|
|
||||||
//
|
|
||||||
assetHelpersToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { MapToolStripMenuItem, assetMapToolStripMenuItem });
|
|
||||||
assetHelpersToolStripMenuItem.Name = "assetHelpersToolStripMenuItem";
|
|
||||||
assetHelpersToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
|
|
||||||
assetHelpersToolStripMenuItem.Text = "Asset Helpers";
|
|
||||||
assetHelpersToolStripMenuItem.DropDownOpening += assetHelpersToolStripMenuItem_DropDownOpening;
|
|
||||||
//
|
|
||||||
// MapToolStripMenuItem
|
|
||||||
//
|
|
||||||
MapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { MapNameComboBox, toolStripMenuItem20, toolStripMenuItem21 });
|
|
||||||
MapToolStripMenuItem.Name = "MapToolStripMenuItem";
|
|
||||||
MapToolStripMenuItem.Size = new System.Drawing.Size(126, 22);
|
|
||||||
MapToolStripMenuItem.Text = "Map";
|
|
||||||
//
|
//
|
||||||
// MapNameComboBox
|
// MapNameComboBox
|
||||||
//
|
//
|
||||||
@@ -623,26 +612,31 @@ namespace AssetStudioGUI
|
|||||||
MapNameComboBox.Size = new System.Drawing.Size(121, 23);
|
MapNameComboBox.Size = new System.Drawing.Size(121, 23);
|
||||||
MapNameComboBox.ToolTipText = "Enter name of Map here";
|
MapNameComboBox.ToolTipText = "Enter name of Map here";
|
||||||
//
|
//
|
||||||
// toolStripMenuItem20
|
// buildMapToolStripMenuItem
|
||||||
//
|
//
|
||||||
toolStripMenuItem20.Name = "toolStripMenuItem20";
|
buildMapToolStripMenuItem.Name = "buildMapToolStripMenuItem";
|
||||||
toolStripMenuItem20.Size = new System.Drawing.Size(181, 22);
|
buildMapToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
|
||||||
toolStripMenuItem20.Text = "Build Map";
|
buildMapToolStripMenuItem.Text = "Build Map";
|
||||||
toolStripMenuItem20.Click += toolStripMenuItem20_Click;
|
buildMapToolStripMenuItem.Click += buildMapToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// toolStripMenuItem21
|
// buildBothToolStripMenuItem
|
||||||
//
|
//
|
||||||
toolStripMenuItem21.Name = "toolStripMenuItem21";
|
buildBothToolStripMenuItem.Name = "buildBothToolStripMenuItem";
|
||||||
toolStripMenuItem21.Size = new System.Drawing.Size(181, 22);
|
buildBothToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
|
||||||
toolStripMenuItem21.Text = "Clear Map";
|
buildBothToolStripMenuItem.Text = "Build Both";
|
||||||
toolStripMenuItem21.Click += toolStripMenuItem21_Click;
|
buildBothToolStripMenuItem.Click += buildBothToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// assetMapToolStripMenuItem
|
// clearMapToolStripMenuItem
|
||||||
//
|
//
|
||||||
assetMapToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { assetMapNameTextBox, toolStripMenuItem22, assetMapTypeComboBox });
|
clearMapToolStripMenuItem.Name = "clearMapToolStripMenuItem";
|
||||||
assetMapToolStripMenuItem.Name = "assetMapToolStripMenuItem";
|
clearMapToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
|
||||||
assetMapToolStripMenuItem.Size = new System.Drawing.Size(126, 22);
|
clearMapToolStripMenuItem.Text = "Clear Map";
|
||||||
assetMapToolStripMenuItem.Text = "AssetMap";
|
clearMapToolStripMenuItem.Click += clearMapToolStripMenuItem_Click;
|
||||||
|
//
|
||||||
|
// toolStripSeparator7
|
||||||
|
//
|
||||||
|
toolStripSeparator7.Name = "toolStripSeparator7";
|
||||||
|
toolStripSeparator7.Size = new System.Drawing.Size(178, 6);
|
||||||
//
|
//
|
||||||
// assetMapNameTextBox
|
// assetMapNameTextBox
|
||||||
//
|
//
|
||||||
@@ -650,12 +644,12 @@ namespace AssetStudioGUI
|
|||||||
assetMapNameTextBox.Size = new System.Drawing.Size(100, 23);
|
assetMapNameTextBox.Size = new System.Drawing.Size(100, 23);
|
||||||
assetMapNameTextBox.ToolTipText = "Enter name of AssetMap here";
|
assetMapNameTextBox.ToolTipText = "Enter name of AssetMap here";
|
||||||
//
|
//
|
||||||
// toolStripMenuItem22
|
// buildAssetMapToolStripMenuItem
|
||||||
//
|
//
|
||||||
toolStripMenuItem22.Name = "toolStripMenuItem22";
|
buildAssetMapToolStripMenuItem.Name = "buildAssetMapToolStripMenuItem";
|
||||||
toolStripMenuItem22.Size = new System.Drawing.Size(181, 22);
|
buildAssetMapToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
|
||||||
toolStripMenuItem22.Text = "Build AssetMap";
|
buildAssetMapToolStripMenuItem.Text = "Build AssetMap";
|
||||||
toolStripMenuItem22.Click += toolStripMenuItem22_Click;
|
buildAssetMapToolStripMenuItem.Click += buildAssetMapToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// assetMapTypeComboBox
|
// assetMapTypeComboBox
|
||||||
//
|
//
|
||||||
@@ -664,13 +658,33 @@ namespace AssetStudioGUI
|
|||||||
assetMapTypeComboBox.Size = new System.Drawing.Size(121, 23);
|
assetMapTypeComboBox.Size = new System.Drawing.Size(121, 23);
|
||||||
assetMapTypeComboBox.SelectedIndexChanged += assetMapTypeComboBox_SelectedIndexChanged;
|
assetMapTypeComboBox.SelectedIndexChanged += assetMapTypeComboBox_SelectedIndexChanged;
|
||||||
//
|
//
|
||||||
|
// toolStripSeparator8
|
||||||
|
//
|
||||||
|
toolStripSeparator8.Name = "toolStripSeparator8";
|
||||||
|
toolStripSeparator8.Size = new System.Drawing.Size(178, 6);
|
||||||
|
//
|
||||||
// loadAIToolStripMenuItem
|
// loadAIToolStripMenuItem
|
||||||
//
|
//
|
||||||
loadAIToolStripMenuItem.Name = "loadAIToolStripMenuItem";
|
loadAIToolStripMenuItem.Name = "loadAIToolStripMenuItem";
|
||||||
loadAIToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
|
loadAIToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
|
||||||
loadAIToolStripMenuItem.Text = "Load AI";
|
loadAIToolStripMenuItem.Text = "Load AI";
|
||||||
loadAIToolStripMenuItem.Click += loadAIToolStripMenuItem_Click;
|
loadAIToolStripMenuItem.Click += loadAIToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
|
// assetHelpersToolStripMenuItem
|
||||||
|
//
|
||||||
|
assetHelpersToolStripMenuItem.Name = "assetHelpersToolStripMenuItem";
|
||||||
|
assetHelpersToolStripMenuItem.Size = new System.Drawing.Size(32, 19);
|
||||||
|
//
|
||||||
|
// MapToolStripMenuItem
|
||||||
|
//
|
||||||
|
MapToolStripMenuItem.Name = "MapToolStripMenuItem";
|
||||||
|
MapToolStripMenuItem.Size = new System.Drawing.Size(32, 19);
|
||||||
|
//
|
||||||
|
// assetMapToolStripMenuItem
|
||||||
|
//
|
||||||
|
assetMapToolStripMenuItem.Name = "assetMapToolStripMenuItem";
|
||||||
|
assetMapToolStripMenuItem.Size = new System.Drawing.Size(32, 19);
|
||||||
|
//
|
||||||
// toolStripSeparator5
|
// toolStripSeparator5
|
||||||
//
|
//
|
||||||
toolStripSeparator5.Name = "toolStripSeparator5";
|
toolStripSeparator5.Name = "toolStripSeparator5";
|
||||||
@@ -1360,20 +1374,23 @@ namespace AssetStudioGUI
|
|||||||
private System.Windows.Forms.ToolStripMenuItem enableConsole;
|
private System.Windows.Forms.ToolStripMenuItem enableConsole;
|
||||||
private System.Windows.Forms.ToolStripMenuItem miscToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem miscToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem assetHelpersToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem assetHelpersToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem20;
|
private System.Windows.Forms.ToolStripMenuItem buildBothToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem22;
|
private System.Windows.Forms.ToolStripMenuItem buildAssetMapToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripComboBox MapNameComboBox;
|
private System.Windows.Forms.ToolStripComboBox MapNameComboBox;
|
||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator5;
|
||||||
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator6;
|
||||||
private System.Windows.Forms.ToolStripMenuItem resetToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem resetToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem abortStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem abortStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem21;
|
private System.Windows.Forms.ToolStripMenuItem clearMapToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem MapToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem MapToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem assetMapToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem assetMapToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem loadAIToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem loadAIToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripMenuItem clearConsoleToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem clearConsoleToolStripMenuItem;
|
||||||
private System.Windows.Forms.ToolStripTextBox assetMapNameTextBox;
|
private System.Windows.Forms.ToolStripTextBox assetMapNameTextBox;
|
||||||
private System.Windows.Forms.ToolStripComboBox assetMapTypeComboBox;
|
private System.Windows.Forms.ToolStripComboBox assetMapTypeComboBox;
|
||||||
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator7;
|
||||||
|
private System.Windows.Forms.ToolStripSeparator toolStripSeparator8;
|
||||||
|
private System.Windows.Forms.ToolStripMenuItem buildMapToolStripMenuItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,13 +110,8 @@ namespace AssetStudioGUI
|
|||||||
assetsManager.ResolveDependencies = Properties.Settings.Default.enableResolveDependencies;
|
assetsManager.ResolveDependencies = Properties.Settings.Default.enableResolveDependencies;
|
||||||
MiHoYoBinData.Encrypted = Properties.Settings.Default.encrypted;
|
MiHoYoBinData.Encrypted = Properties.Settings.Default.encrypted;
|
||||||
MiHoYoBinData.Key = Properties.Settings.Default.key;
|
MiHoYoBinData.Key = Properties.Settings.Default.key;
|
||||||
|
Renderer.Parsable = !Properties.Settings.Default.disableRenderer;
|
||||||
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
|
Shader.Parsable = !Properties.Settings.Default.disableShader;
|
||||||
foreach (var exportable in types)
|
|
||||||
{
|
|
||||||
if (assetsManager.ExportableTypes.ContainsKey(exportable.Key))
|
|
||||||
assetsManager.ExportableTypes[exportable.Key] = exportable.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeLogger()
|
private void InitializeLogger()
|
||||||
@@ -515,12 +510,6 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
var exportOpt = new ExportOptions();
|
var exportOpt = new ExportOptions();
|
||||||
exportOpt.ShowDialog(this);
|
exportOpt.ShowDialog(this);
|
||||||
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
|
|
||||||
foreach (var exportable in types)
|
|
||||||
{
|
|
||||||
if (assetsManager.ExportableTypes.ContainsKey(exportable.Key))
|
|
||||||
assetsManager.ExportableTypes[exportable.Key] = exportable.Value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
|
private void assetListView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
|
||||||
@@ -763,6 +752,9 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
switch (assetItem.Asset)
|
switch (assetItem.Asset)
|
||||||
{
|
{
|
||||||
|
case GameObject m_GameObject:
|
||||||
|
PreviewGameObject(m_GameObject);
|
||||||
|
break;
|
||||||
case Texture2D m_Texture2D:
|
case Texture2D m_Texture2D:
|
||||||
PreviewTexture2D(assetItem, m_Texture2D);
|
PreviewTexture2D(assetItem, m_Texture2D);
|
||||||
break;
|
break;
|
||||||
@@ -791,8 +783,9 @@ namespace AssetStudioGUI
|
|||||||
case Sprite m_Sprite:
|
case Sprite m_Sprite:
|
||||||
PreviewSprite(assetItem, m_Sprite);
|
PreviewSprite(assetItem, m_Sprite);
|
||||||
break;
|
break;
|
||||||
case Animator _:
|
case Animator m_Animator:
|
||||||
StatusStripUpdate("Can be exported to FBX file.");
|
//StatusStripUpdate("Can be exported to FBX file.");
|
||||||
|
PreviewAnimator(m_Animator);
|
||||||
break;
|
break;
|
||||||
case AnimationClip _:
|
case AnimationClip _:
|
||||||
StatusStripUpdate("Can be exported with Animator or Objects");
|
StatusStripUpdate("Can be exported with Animator or Objects");
|
||||||
@@ -1237,6 +1230,163 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PreviewGameObject(GameObject m_GameObject)
|
||||||
|
{
|
||||||
|
var model = new ModelConverter(m_GameObject, Properties.Settings.Default.convertType, Studio.Game, false, Array.Empty<AnimationClip>());
|
||||||
|
if (model.MeshList.Count > 0)
|
||||||
|
{
|
||||||
|
viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);
|
||||||
|
#region Vertices
|
||||||
|
vertexData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector3(x.Vertex.X, x.Vertex.Y, x.Vertex.Z)).ToArray();
|
||||||
|
// Calculate Bounding
|
||||||
|
Vector3 min = vertexData.Aggregate(Vector3.ComponentMin);
|
||||||
|
Vector3 max = vertexData.Aggregate(Vector3.ComponentMax);
|
||||||
|
|
||||||
|
// Calculate modelMatrix
|
||||||
|
Vector3 dist = max - min;
|
||||||
|
Vector3 offset = (max - min) / 2;
|
||||||
|
float d = Math.Max(1e-5f, dist.Length);
|
||||||
|
modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d);
|
||||||
|
#endregion
|
||||||
|
#region Indicies
|
||||||
|
int meshOffset = 0;
|
||||||
|
var indices = new List<int>();
|
||||||
|
foreach (var mesh in model.MeshList)
|
||||||
|
{
|
||||||
|
foreach (var submesh in mesh.SubmeshList)
|
||||||
|
{
|
||||||
|
foreach (var face in submesh.FaceList)
|
||||||
|
{
|
||||||
|
foreach (var index in face.VertexIndices)
|
||||||
|
{
|
||||||
|
indices.Add(submesh.BaseVertex + index + meshOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
meshOffset += mesh.VertexList.Count;
|
||||||
|
}
|
||||||
|
indiceData = indices.ToArray();
|
||||||
|
#endregion
|
||||||
|
#region Normals
|
||||||
|
normalData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector3(x.Normal.X, x.Normal.Y, x.Normal.Z)).ToArray();
|
||||||
|
// calculate normal by ourself
|
||||||
|
normal2Data = new Vector3[vertexData.Length];
|
||||||
|
int[] normalCalculatedCount = new int[vertexData.Length];
|
||||||
|
Array.Fill(normal2Data, Vector3.Zero);
|
||||||
|
Array.Fill(normalCalculatedCount, 0);
|
||||||
|
for (int j = 0; j < indiceData.Length; j += 3)
|
||||||
|
{
|
||||||
|
Vector3 dir1 = vertexData[indiceData[j + 1]] - vertexData[indiceData[j]];
|
||||||
|
Vector3 dir2 = vertexData[indiceData[j + 2]] - vertexData[indiceData[j]];
|
||||||
|
Vector3 normal = Vector3.Cross(dir1, dir2);
|
||||||
|
normal.Normalize();
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
{
|
||||||
|
normal2Data[indiceData[j + k]] += normal;
|
||||||
|
normalCalculatedCount[indiceData[j + k]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < vertexData.Length; j++)
|
||||||
|
{
|
||||||
|
if (normalCalculatedCount[j] == 0)
|
||||||
|
normal2Data[j] = new Vector3(0, 1, 0);
|
||||||
|
else
|
||||||
|
normal2Data[j] /= normalCalculatedCount[j];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Colors
|
||||||
|
colorData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector4(x.Color.R, x.Color.G, x.Color.B, x.Color.A)).ToArray();
|
||||||
|
#endregion
|
||||||
|
glControl.Visible = true;
|
||||||
|
CreateVAO();
|
||||||
|
StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + "\n"
|
||||||
|
+ "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n"
|
||||||
|
+ "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StatusStripUpdate("Unable to preview this model");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void PreviewAnimator(Animator m_Animator)
|
||||||
|
{
|
||||||
|
var model = new ModelConverter(m_Animator, Properties.Settings.Default.convertType, Studio.Game, false, Array.Empty<AnimationClip>());
|
||||||
|
if (model.MeshList.Count > 0)
|
||||||
|
{
|
||||||
|
viewMatrixData = Matrix4.CreateRotationY(-(float)Math.PI / 4) * Matrix4.CreateRotationX(-(float)Math.PI / 6);
|
||||||
|
#region Vertices
|
||||||
|
vertexData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector3(x.Vertex.X, x.Vertex.Y, x.Vertex.Z)).ToArray();
|
||||||
|
// Calculate Bounding
|
||||||
|
Vector3 min = vertexData.Aggregate(Vector3.ComponentMin);
|
||||||
|
Vector3 max = vertexData.Aggregate(Vector3.ComponentMax);
|
||||||
|
|
||||||
|
// Calculate modelMatrix
|
||||||
|
Vector3 dist = max - min;
|
||||||
|
Vector3 offset = (max - min) / 2;
|
||||||
|
float d = Math.Max(1e-5f, dist.Length);
|
||||||
|
modelMatrixData = Matrix4.CreateTranslation(-offset) * Matrix4.CreateScale(2f / d);
|
||||||
|
#endregion
|
||||||
|
#region Indicies
|
||||||
|
int meshOffset = 0;
|
||||||
|
var indices = new List<int>();
|
||||||
|
foreach (var mesh in model.MeshList)
|
||||||
|
{
|
||||||
|
foreach (var submesh in mesh.SubmeshList)
|
||||||
|
{
|
||||||
|
foreach (var face in submesh.FaceList)
|
||||||
|
{
|
||||||
|
foreach (var index in face.VertexIndices)
|
||||||
|
{
|
||||||
|
indices.Add(submesh.BaseVertex + index + meshOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
meshOffset += mesh.VertexList.Count;
|
||||||
|
}
|
||||||
|
indiceData = indices.ToArray();
|
||||||
|
#endregion
|
||||||
|
#region Normals
|
||||||
|
normalData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector3(x.Normal.X, x.Normal.Y, x.Normal.Z)).ToArray();
|
||||||
|
// calculate normal by ourself
|
||||||
|
normal2Data = new Vector3[vertexData.Length];
|
||||||
|
int[] normalCalculatedCount = new int[vertexData.Length];
|
||||||
|
Array.Fill(normal2Data, Vector3.Zero);
|
||||||
|
Array.Fill(normalCalculatedCount, 0);
|
||||||
|
for (int j = 0; j < indiceData.Length; j += 3)
|
||||||
|
{
|
||||||
|
Vector3 dir1 = vertexData[indiceData[j + 1]] - vertexData[indiceData[j]];
|
||||||
|
Vector3 dir2 = vertexData[indiceData[j + 2]] - vertexData[indiceData[j]];
|
||||||
|
Vector3 normal = Vector3.Cross(dir1, dir2);
|
||||||
|
normal.Normalize();
|
||||||
|
for (int k = 0; k < 3; k++)
|
||||||
|
{
|
||||||
|
normal2Data[indiceData[j + k]] += normal;
|
||||||
|
normalCalculatedCount[indiceData[j + k]]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int j = 0; j < vertexData.Length; j++)
|
||||||
|
{
|
||||||
|
if (normalCalculatedCount[j] == 0)
|
||||||
|
normal2Data[j] = new Vector3(0, 1, 0);
|
||||||
|
else
|
||||||
|
normal2Data[j] /= normalCalculatedCount[j];
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#region Colors
|
||||||
|
colorData = model.MeshList.SelectMany(x => x.VertexList).Select(x => new Vector4(x.Color.R, x.Color.G, x.Color.B, x.Color.A)).ToArray();
|
||||||
|
#endregion
|
||||||
|
glControl.Visible = true;
|
||||||
|
CreateVAO();
|
||||||
|
StatusStripUpdate("Using OpenGL Version: " + GL.GetString(StringName.Version) + "\n"
|
||||||
|
+ "'Mouse Left'=Rotate | 'Mouse Right'=Move | 'Mouse Wheel'=Zoom \n"
|
||||||
|
+ "'Ctrl W'=Wireframe | 'Ctrl S'=Shade | 'Ctrl N'=ReNormal ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StatusStripUpdate("Unable to preview this model");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
private void PreviewSprite(AssetItem assetItem, Sprite m_Sprite)
|
||||||
{
|
{
|
||||||
var image = m_Sprite.GetImage();
|
var image = m_Sprite.GetImage();
|
||||||
@@ -1714,9 +1864,9 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assetHelpersToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
|
private void miscToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (assetHelpersToolStripMenuItem.Enabled)
|
if (miscToolStripMenuItem.Enabled)
|
||||||
{
|
{
|
||||||
MapNameComboBox.Items.Clear();
|
MapNameComboBox.Items.Clear();
|
||||||
MapNameComboBox.Items.AddRange(AssetsHelper.GetMaps());
|
MapNameComboBox.Items.AddRange(AssetsHelper.GetMaps());
|
||||||
@@ -1831,10 +1981,11 @@ namespace AssetStudioGUI
|
|||||||
Properties.Settings.Default.selectedGame = specifyGame.SelectedIndex;
|
Properties.Settings.Default.selectedGame = specifyGame.SelectedIndex;
|
||||||
Properties.Settings.Default.Save();
|
Properties.Settings.Default.Save();
|
||||||
|
|
||||||
|
ResetForm();
|
||||||
|
|
||||||
Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame);
|
Studio.Game = GameManager.GetGame(Properties.Settings.Default.selectedGame);
|
||||||
Logger.Info($"Target Game is {Studio.Game.Name}");
|
Logger.Info($"Target Game is {Studio.Game.Name}");
|
||||||
|
|
||||||
ResetForm();
|
|
||||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||||
assetsManager.Game = Studio.Game;
|
assetsManager.Game = Studio.Game;
|
||||||
}
|
}
|
||||||
@@ -1844,17 +1995,18 @@ namespace AssetStudioGUI
|
|||||||
miscToolStripMenuItem.DropDown.Visible = false;
|
miscToolStripMenuItem.DropDown.Visible = false;
|
||||||
InvokeUpdate(miscToolStripMenuItem, false);
|
InvokeUpdate(miscToolStripMenuItem, false);
|
||||||
|
|
||||||
var name = MapNameComboBox.SelectedItem.ToString();
|
|
||||||
await Task.Run(() => AssetsHelper.LoadMap(name));
|
|
||||||
|
|
||||||
ResetForm();
|
ResetForm();
|
||||||
|
|
||||||
|
var name = MapNameComboBox.SelectedItem.ToString();
|
||||||
|
await Task.Run(() => AssetsHelper.LoadCABMap(name));
|
||||||
|
|
||||||
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
assetsManager.SpecifyUnityVersion = specifyUnityVersion.Text;
|
||||||
assetsManager.Game = Studio.Game;
|
assetsManager.Game = Studio.Game;
|
||||||
|
|
||||||
InvokeUpdate(miscToolStripMenuItem, true);
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void toolStripMenuItem20_Click(object sender, EventArgs e)
|
private async void buildMapToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
miscToolStripMenuItem.DropDown.Visible = false;
|
miscToolStripMenuItem.DropDown.Visible = false;
|
||||||
InvokeUpdate(miscToolStripMenuItem, false);
|
InvokeUpdate(miscToolStripMenuItem, false);
|
||||||
@@ -1903,12 +2055,83 @@ namespace AssetStudioGUI
|
|||||||
var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray();
|
var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray();
|
||||||
files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray();
|
files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray();
|
||||||
Logger.Info($"Found {files.Length} files");
|
Logger.Info($"Found {files.Length} files");
|
||||||
await Task.Run(() => AssetsHelper.BuildMap(files, name, openFolderDialog.Folder, Studio.Game));
|
await Task.Run(() => AssetsHelper.BuildCABMap(files, name, openFolderDialog.Folder, Studio.Game));
|
||||||
}
|
}
|
||||||
InvokeUpdate(miscToolStripMenuItem, true);
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toolStripMenuItem21_Click(object sender, EventArgs e)
|
private async void buildBothToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
miscToolStripMenuItem.DropDown.Visible = false;
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, false);
|
||||||
|
|
||||||
|
var input = MapNameComboBox.Text;
|
||||||
|
var selectedText = MapNameComboBox.SelectedText;
|
||||||
|
var exportListType = (ExportListType)assetMapTypeComboBox.SelectedItem;
|
||||||
|
var name = "";
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(selectedText))
|
||||||
|
{
|
||||||
|
name = selectedText;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
if (input.IndexOfAny(Path.GetInvalidFileNameChars()) != -1)
|
||||||
|
{
|
||||||
|
Logger.Warning("Name has invalid characters !!");
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = input;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Error("Map name is empty, please enter any name in ComboBox above");
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(Path.Combine(AssetsHelper.MapName, $"{name}.bin")))
|
||||||
|
{
|
||||||
|
var acceptOverride = MessageBox.Show("Map already exist, Do you want to override it ?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||||
|
if (acceptOverride != DialogResult.Yes)
|
||||||
|
{
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var openFolderDialog = new OpenFolderDialog();
|
||||||
|
openFolderDialog.Title = "Select Game Folder";
|
||||||
|
if (openFolderDialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
var saveFolderDialog = new OpenFolderDialog();
|
||||||
|
saveFolderDialog.InitialFolder = saveDirectoryBackup;
|
||||||
|
saveFolderDialog.Title = "Select Output Folder";
|
||||||
|
if (saveFolderDialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
if (File.Exists(Path.Combine(saveFolderDialog.Folder, $"{name}{exportListType.GetExtension()}")))
|
||||||
|
{
|
||||||
|
var acceptOverride = MessageBox.Show("AssetMap already exist, Do you want to override it ?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
|
||||||
|
if (acceptOverride != DialogResult.Yes)
|
||||||
|
{
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveDirectoryBackup = saveFolderDialog.Folder;
|
||||||
|
Logger.Info("Scanning for files...");
|
||||||
|
var files = Directory.GetFiles(openFolderDialog.Folder, "*.*", SearchOption.AllDirectories).ToArray();
|
||||||
|
files = files.Where(x => FileReader.IsReadable(x, Studio.Game)).ToArray();
|
||||||
|
Logger.Info($"Found {files.Length} files");
|
||||||
|
await Task.Run(() => AssetsHelper.BuildBoth(files, name, openFolderDialog.Folder, Studio.Game, saveFolderDialog.Folder, exportListType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearMapToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
miscToolStripMenuItem.DropDown.Visible = false;
|
miscToolStripMenuItem.DropDown.Visible = false;
|
||||||
InvokeUpdate(miscToolStripMenuItem, false);
|
InvokeUpdate(miscToolStripMenuItem, false);
|
||||||
@@ -1993,7 +2216,7 @@ namespace AssetStudioGUI
|
|||||||
Console.Clear();
|
Console.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void toolStripMenuItem22_Click(object sender, EventArgs e)
|
private async void buildAssetMapToolStripMenuItem_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
miscToolStripMenuItem.DropDown.Visible = false;
|
miscToolStripMenuItem.DropDown.Visible = false;
|
||||||
InvokeUpdate(miscToolStripMenuItem, false);
|
InvokeUpdate(miscToolStripMenuItem, false);
|
||||||
@@ -2038,8 +2261,7 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveDirectoryBackup = saveFolderDialog.Folder;
|
saveDirectoryBackup = saveFolderDialog.Folder;
|
||||||
var toExportAssets = await Task.Run(() => AssetsHelper.BuildAssetMap(files, Studio.Game));
|
await Task.Run(() => AssetsHelper.BuildAssetMap(files, name, Studio.Game, saveFolderDialog.Folder, exportListType));
|
||||||
AssetsHelper.ExportAssetsMap(toExportAssets, name, saveFolderDialog.Folder, exportListType);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InvokeUpdate(miscToolStripMenuItem, true);
|
InvokeUpdate(miscToolStripMenuItem, true);
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>312, 17</value>
|
<value>312, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>432, 17</value>
|
||||||
|
</metadata>
|
||||||
<data name="fontPreviewBox.Text" xml:space="preserve">
|
<data name="fontPreviewBox.Text" xml:space="preserve">
|
||||||
<value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ
|
<value>abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWYZ
|
||||||
1234567890.:,;'\"(!?)+-*/=
|
1234567890.:,;'\"(!?)+-*/=
|
||||||
@@ -78,9 +81,6 @@ The quick brown fox jumps over the lazy dog. 1234567890
|
|||||||
|
|
||||||
The quick brown fox jumps over the lazy dog. 1234567890</value>
|
The quick brown fox jumps over the lazy dog. 1234567890</value>
|
||||||
</data>
|
</data>
|
||||||
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
|
||||||
<value>432, 17</value>
|
|
||||||
</metadata>
|
|
||||||
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="timer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>553, 17</value>
|
<value>553, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|||||||
54
AssetStudioGUI/ExportOptions.Designer.cs
generated
54
AssetStudioGUI/ExportOptions.Designer.cs
generated
@@ -71,12 +71,12 @@ namespace AssetStudioGUI
|
|||||||
key = new System.Windows.Forms.NumericUpDown();
|
key = new System.Windows.Forms.NumericUpDown();
|
||||||
keyToolTip = new System.Windows.Forms.ToolTip(components);
|
keyToolTip = new System.Windows.Forms.ToolTip(components);
|
||||||
groupBox4 = new System.Windows.Forms.GroupBox();
|
groupBox4 = new System.Windows.Forms.GroupBox();
|
||||||
label7 = new System.Windows.Forms.Label();
|
|
||||||
exportableTypes = new System.Windows.Forms.CheckedListBox();
|
|
||||||
skipContainer = new System.Windows.Forms.CheckBox();
|
skipContainer = new System.Windows.Forms.CheckBox();
|
||||||
enableResolveDependencies = new System.Windows.Forms.CheckBox();
|
enableResolveDependencies = new System.Windows.Forms.CheckBox();
|
||||||
resolveToolTip = new System.Windows.Forms.ToolTip(components);
|
resolveToolTip = new System.Windows.Forms.ToolTip(components);
|
||||||
skipToolTip = new System.Windows.Forms.ToolTip(components);
|
skipToolTip = new System.Windows.Forms.ToolTip(components);
|
||||||
|
disableRenderer = new System.Windows.Forms.CheckBox();
|
||||||
|
disableShader = new System.Windows.Forms.CheckBox();
|
||||||
groupBox1.SuspendLayout();
|
groupBox1.SuspendLayout();
|
||||||
panel1.SuspendLayout();
|
panel1.SuspendLayout();
|
||||||
groupBox2.SuspendLayout();
|
groupBox2.SuspendLayout();
|
||||||
@@ -537,8 +537,8 @@ namespace AssetStudioGUI
|
|||||||
// groupBox4
|
// groupBox4
|
||||||
//
|
//
|
||||||
groupBox4.AutoSize = true;
|
groupBox4.AutoSize = true;
|
||||||
groupBox4.Controls.Add(label7);
|
groupBox4.Controls.Add(disableShader);
|
||||||
groupBox4.Controls.Add(exportableTypes);
|
groupBox4.Controls.Add(disableRenderer);
|
||||||
groupBox4.Controls.Add(skipContainer);
|
groupBox4.Controls.Add(skipContainer);
|
||||||
groupBox4.Controls.Add(key);
|
groupBox4.Controls.Add(key);
|
||||||
groupBox4.Controls.Add(encrypted);
|
groupBox4.Controls.Add(encrypted);
|
||||||
@@ -552,24 +552,6 @@ namespace AssetStudioGUI
|
|||||||
groupBox4.TabStop = false;
|
groupBox4.TabStop = false;
|
||||||
groupBox4.Text = "Options";
|
groupBox4.Text = "Options";
|
||||||
//
|
//
|
||||||
// label7
|
|
||||||
//
|
|
||||||
label7.AutoSize = true;
|
|
||||||
label7.Location = new System.Drawing.Point(7, 94);
|
|
||||||
label7.Name = "label7";
|
|
||||||
label7.Size = new System.Drawing.Size(95, 15);
|
|
||||||
label7.TabIndex = 16;
|
|
||||||
label7.Text = "Exportable Types";
|
|
||||||
//
|
|
||||||
// exportableTypes
|
|
||||||
//
|
|
||||||
exportableTypes.CheckOnClick = true;
|
|
||||||
exportableTypes.FormattingEnabled = true;
|
|
||||||
exportableTypes.Location = new System.Drawing.Point(102, 94);
|
|
||||||
exportableTypes.Name = "exportableTypes";
|
|
||||||
exportableTypes.Size = new System.Drawing.Size(152, 58);
|
|
||||||
exportableTypes.TabIndex = 15;
|
|
||||||
//
|
|
||||||
// skipContainer
|
// skipContainer
|
||||||
//
|
//
|
||||||
skipContainer.AutoSize = true;
|
skipContainer.AutoSize = true;
|
||||||
@@ -598,6 +580,30 @@ namespace AssetStudioGUI
|
|||||||
resolveToolTip.SetToolTip(enableResolveDependencies, "Toggle the behaviour of loading assets.\r\nDisable to load file(s) without its dependencies.");
|
resolveToolTip.SetToolTip(enableResolveDependencies, "Toggle the behaviour of loading assets.\r\nDisable to load file(s) without its dependencies.");
|
||||||
enableResolveDependencies.UseVisualStyleBackColor = true;
|
enableResolveDependencies.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
|
// disableRenderer
|
||||||
|
//
|
||||||
|
disableRenderer.AutoSize = true;
|
||||||
|
disableRenderer.Location = new System.Drawing.Point(8, 96);
|
||||||
|
disableRenderer.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
|
disableRenderer.Name = "disableRenderer";
|
||||||
|
disableRenderer.Size = new System.Drawing.Size(114, 19);
|
||||||
|
disableRenderer.TabIndex = 15;
|
||||||
|
disableRenderer.Text = "Disable Renderer";
|
||||||
|
skipToolTip.SetToolTip(disableRenderer, "Skips the container recovery step.\nImproves loading when dealing with a large number of files.");
|
||||||
|
disableRenderer.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// disableShader
|
||||||
|
//
|
||||||
|
disableShader.AutoSize = true;
|
||||||
|
disableShader.Location = new System.Drawing.Point(8, 121);
|
||||||
|
disableShader.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
|
||||||
|
disableShader.Name = "disableShader";
|
||||||
|
disableShader.Size = new System.Drawing.Size(103, 19);
|
||||||
|
disableShader.TabIndex = 16;
|
||||||
|
disableShader.Text = "Disable Shader";
|
||||||
|
skipToolTip.SetToolTip(disableShader, "Skips the container recovery step.\nImproves loading when dealing with a large number of files.");
|
||||||
|
disableShader.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
// ExportOptions
|
// ExportOptions
|
||||||
//
|
//
|
||||||
AcceptButton = OKbutton;
|
AcceptButton = OKbutton;
|
||||||
@@ -679,7 +685,7 @@ namespace AssetStudioGUI
|
|||||||
private System.Windows.Forms.CheckBox skipContainer;
|
private System.Windows.Forms.CheckBox skipContainer;
|
||||||
private System.Windows.Forms.ToolTip resolveToolTip;
|
private System.Windows.Forms.ToolTip resolveToolTip;
|
||||||
private System.Windows.Forms.ToolTip skipToolTip;
|
private System.Windows.Forms.ToolTip skipToolTip;
|
||||||
private System.Windows.Forms.CheckedListBox exportableTypes;
|
private System.Windows.Forms.CheckBox disableShader;
|
||||||
private System.Windows.Forms.Label label7;
|
private System.Windows.Forms.CheckBox disableRenderer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,27 +42,12 @@ namespace AssetStudioGUI
|
|||||||
collectAnimations.Checked = Properties.Settings.Default.collectAnimations;
|
collectAnimations.Checked = Properties.Settings.Default.collectAnimations;
|
||||||
encrypted.Checked = Properties.Settings.Default.encrypted;
|
encrypted.Checked = Properties.Settings.Default.encrypted;
|
||||||
key.Value = Properties.Settings.Default.key;
|
key.Value = Properties.Settings.Default.key;
|
||||||
|
disableRenderer.Checked = Properties.Settings.Default.disableRenderer;
|
||||||
exportableTypes.Items.AddRange(Studio.assetsManager.ExportableTypes.Keys.Select(x => x.ToString()).ToArray());
|
disableShader.Checked = Properties.Settings.Default.disableShader;
|
||||||
var types = JsonConvert.DeserializeObject<Dictionary<ClassIDType, bool>>(Properties.Settings.Default.exportableTypes);
|
|
||||||
foreach (var exportable in types)
|
|
||||||
{
|
|
||||||
var idx = exportableTypes.Items.IndexOf(exportable.Key.ToString());
|
|
||||||
if (idx != -1)
|
|
||||||
exportableTypes.SetItemChecked(idx, exportable.Value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OKbutton_Click(object sender, EventArgs e)
|
private void OKbutton_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var types = new Dictionary<ClassIDType, bool>();
|
|
||||||
for (int i = 0; i < exportableTypes.Items.Count; i++)
|
|
||||||
{
|
|
||||||
var type = Enum.Parse<ClassIDType>(exportableTypes.Items[i].ToString());
|
|
||||||
var state = exportableTypes.GetItemChecked(i);
|
|
||||||
types.Add(type, state);
|
|
||||||
}
|
|
||||||
Properties.Settings.Default.exportableTypes = JsonConvert.SerializeObject(types);
|
|
||||||
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
|
Properties.Settings.Default.assetGroupOption = assetGroupOptions.SelectedIndex;
|
||||||
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
|
Properties.Settings.Default.restoreExtensionName = restoreExtensionName.Checked;
|
||||||
Properties.Settings.Default.convertTexture = converttexture.Checked;
|
Properties.Settings.Default.convertTexture = converttexture.Checked;
|
||||||
@@ -92,9 +77,13 @@ namespace AssetStudioGUI
|
|||||||
Properties.Settings.Default.collectAnimations = collectAnimations.Checked;
|
Properties.Settings.Default.collectAnimations = collectAnimations.Checked;
|
||||||
Properties.Settings.Default.encrypted = encrypted.Checked;
|
Properties.Settings.Default.encrypted = encrypted.Checked;
|
||||||
Properties.Settings.Default.key = (byte)key.Value;
|
Properties.Settings.Default.key = (byte)key.Value;
|
||||||
|
Properties.Settings.Default.disableRenderer = disableRenderer.Checked;
|
||||||
|
Properties.Settings.Default.disableShader = disableShader.Checked;
|
||||||
Properties.Settings.Default.Save();
|
Properties.Settings.Default.Save();
|
||||||
MiHoYoBinData.Key = (byte)key.Value;
|
MiHoYoBinData.Key = (byte)key.Value;
|
||||||
MiHoYoBinData.Encrypted = encrypted.Checked;
|
MiHoYoBinData.Encrypted = encrypted.Checked;
|
||||||
|
Renderer.Parsable = !Properties.Settings.Default.disableRenderer;
|
||||||
|
Shader.Parsable = !Properties.Settings.Default.disableShader;
|
||||||
DialogResult = DialogResult.OK;
|
DialogResult = DialogResult.OK;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,12 @@
|
|||||||
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="exportUvsTooltip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
|
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>162, 17</value>
|
||||||
|
</metadata>
|
||||||
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="keyToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>162, 17</value>
|
<value>162, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
@@ -69,6 +75,9 @@
|
|||||||
<metadata name="resolveToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="resolveToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>273, 17</value>
|
<value>273, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
<metadata name="resolveToolTip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>273, 17</value>
|
||||||
|
</metadata>
|
||||||
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||||
<value>57</value>
|
<value>57</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
|
|||||||
22
AssetStudioGUI/Properties/Settings.Designer.cs
generated
22
AssetStudioGUI/Properties/Settings.Designer.cs
generated
@@ -385,15 +385,25 @@ namespace AssetStudioGUI.Properties {
|
|||||||
|
|
||||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
[global::System.Configuration.DefaultSettingValueAttribute("{\"GameObject\":true,\"Material\":true,\"Texture2D\":true,\"Mesh\":true,\"Renderer\":true,\"" +
|
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||||
"Shader\":true,\"TextAsset\":true,\"AnimationClip\":true,\"Font\":true,\"Sprite\":true,\"An" +
|
public bool disableShader {
|
||||||
"imator\":true,\"MiHoYoBinData\":true,\"AssetBundle\":true}")]
|
|
||||||
public string exportableTypes {
|
|
||||||
get {
|
get {
|
||||||
return ((string)(this["exportableTypes"]));
|
return ((bool)(this["disableShader"]));
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
this["exportableTypes"] = value;
|
this["disableShader"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||||
|
public bool disableRenderer {
|
||||||
|
get {
|
||||||
|
return ((bool)(this["disableRenderer"]));
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
this["disableRenderer"] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,11 @@
|
|||||||
<Setting Name="exportUV0UV1" Type="System.Boolean" Scope="User">
|
<Setting Name="exportUV0UV1" Type="System.Boolean" Scope="User">
|
||||||
<Value Profile="(Default)">False</Value>
|
<Value Profile="(Default)">False</Value>
|
||||||
</Setting>
|
</Setting>
|
||||||
<Setting Name="exportableTypes" Type="System.String" Scope="User">
|
<Setting Name="disableShader" Type="System.Boolean" Scope="User">
|
||||||
<Value Profile="(Default)">{"GameObject":true,"Material":true,"Texture2D":true,"Mesh":true,"Renderer":true,"Shader":true,"TextAsset":true,"AnimationClip":true,"Font":true,"Sprite":true,"Animator":true,"MiHoYoBinData":true,"AssetBundle":true}</Value>
|
<Value Profile="(Default)">False</Value>
|
||||||
|
</Setting>
|
||||||
|
<Setting Name="disableRenderer" Type="System.Boolean" Scope="User">
|
||||||
|
<Value Profile="(Default)">False</Value>
|
||||||
</Setting>
|
</Setting>
|
||||||
</Settings>
|
</Settings>
|
||||||
</SettingsFile>
|
</SettingsFile>
|
||||||
@@ -154,7 +154,7 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
int total = 0;
|
int total = 0;
|
||||||
StatusStripUpdate($"Decompressing {reader.FileName} ...");
|
StatusStripUpdate($"Decompressing {reader.FileName} ...");
|
||||||
using var stream = new SubStream(reader.BaseStream, 0);
|
using var stream = new OffsetStream(reader.BaseStream, 0);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
stream.Offset = stream.AbsolutePosition;
|
stream.Offset = stream.AbsolutePosition;
|
||||||
@@ -224,17 +224,17 @@ namespace AssetStudioGUI
|
|||||||
if (uint.TryParse(name, out var id))
|
if (uint.TryParse(name, out var id))
|
||||||
{
|
{
|
||||||
var path = ResourceIndex.GetContainer(id, last);
|
var path = ResourceIndex.GetContainer(id, last);
|
||||||
if (!string.IsNullOrEmpty(path))
|
if (!string.IsNullOrEmpty(path))
|
||||||
{
|
|
||||||
asset.Container = path;
|
|
||||||
if (asset.Type == ClassIDType.MiHoYoBinData)
|
|
||||||
{
|
{
|
||||||
asset.Text = Path.GetFileNameWithoutExtension(path);
|
asset.Container = path;
|
||||||
|
if (asset.Type == ClassIDType.MiHoYoBinData)
|
||||||
|
{
|
||||||
|
asset.Text = Path.GetFileNameWithoutExtension(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Logger.Info("Updated !!");
|
Logger.Info("Updated !!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,10 +347,10 @@ namespace AssetStudioGUI
|
|||||||
exportable = true;
|
exportable = true;
|
||||||
break;
|
break;
|
||||||
case ResourceManager m_ResourceManager:
|
case ResourceManager m_ResourceManager:
|
||||||
foreach (var m_Container in m_ResourceManager.m_Container)
|
foreach (var m_Container in m_ResourceManager.m_Container)
|
||||||
{
|
{
|
||||||
containers.Add((m_Container.Value, m_Container.Key));
|
containers.Add((m_Container.Value, m_Container.Key));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NamedObject m_NamedObject:
|
case NamedObject m_NamedObject:
|
||||||
assetItem.Text = m_NamedObject.m_Name;
|
assetItem.Text = m_NamedObject.m_Name;
|
||||||
@@ -369,6 +369,11 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
foreach((var pptr, var name) in mihoyoBinDataNames)
|
foreach((var pptr, var name) in mihoyoBinDataNames)
|
||||||
{
|
{
|
||||||
|
if (assetsManager.tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Processing asset namnes has been cancelled !!");
|
||||||
|
return (string.Empty, Array.Empty<TreeNode>().ToList());
|
||||||
|
}
|
||||||
if (pptr.TryGet<MiHoYoBinData>(out var obj))
|
if (pptr.TryGet<MiHoYoBinData>(out var obj))
|
||||||
{
|
{
|
||||||
var assetItem = objectAssetItemDic[obj];
|
var assetItem = objectAssetItemDic[obj];
|
||||||
@@ -384,6 +389,11 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
foreach ((var pptr, var container) in containers)
|
foreach ((var pptr, var container) in containers)
|
||||||
{
|
{
|
||||||
|
if (assetsManager.tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Processing containers been cancelled !!");
|
||||||
|
return (string.Empty, Array.Empty<TreeNode>().ToList());
|
||||||
|
}
|
||||||
if (pptr.TryGet(out var obj))
|
if (pptr.TryGet(out var obj))
|
||||||
{
|
{
|
||||||
objectAssetItemDic[obj].Container = container;
|
objectAssetItemDic[obj].Container = container;
|
||||||
@@ -397,6 +407,11 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
foreach (var tmp in exportableAssets)
|
foreach (var tmp in exportableAssets)
|
||||||
{
|
{
|
||||||
|
if (assetsManager.tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Processing subitems been cancelled !!");
|
||||||
|
return (string.Empty, Array.Empty<TreeNode>().ToList());
|
||||||
|
}
|
||||||
tmp.SetSubItems();
|
tmp.SetSubItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,6 +507,11 @@ namespace AssetStudioGUI
|
|||||||
var typeMap = new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();
|
var typeMap = new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();
|
||||||
foreach (var assetsFile in assetsManager.assetsFileList)
|
foreach (var assetsFile in assetsManager.assetsFileList)
|
||||||
{
|
{
|
||||||
|
if (assetsManager.tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Logger.Info("Processing class structure been cancelled !!");
|
||||||
|
return new Dictionary<string, SortedDictionary<int, TypeTreeItem>>();
|
||||||
|
}
|
||||||
if (typeMap.TryGetValue(assetsFile.unityVersion, out var curVer))
|
if (typeMap.TryGetValue(assetsFile.unityVersion, out var curVer))
|
||||||
{
|
{
|
||||||
foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))
|
foreach (var type in assetsFile.m_Types.Where(x => x.m_Type != null))
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
|
||||||
<Version>0.80.30</Version>
|
<Version>0.80.65</Version>
|
||||||
<AssemblyVersion>0.80.30</AssemblyVersion>
|
<AssemblyVersion>0.80.65</AssemblyVersion>
|
||||||
<FileVersion>0.80.30</FileVersion>
|
<FileVersion>0.80.65</FileVersion>
|
||||||
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
<Copyright>Copyright © Perfare 2018-2022</Copyright>
|
||||||
<DebugType>embedded</DebugType>
|
<DebugType>embedded</DebugType>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
|
|||||||
Reference in New Issue
Block a user