mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
Refactor MonoBehaviour reading
This commit is contained in:
parent
efbab7c43a
commit
9b2c85bcae
@ -8,7 +8,7 @@ namespace AssetStudio
|
|||||||
public sealed class MonoScript : NamedObject
|
public sealed class MonoScript : NamedObject
|
||||||
{
|
{
|
||||||
public string m_ClassName;
|
public string m_ClassName;
|
||||||
public string m_Namespace = string.Empty;
|
public string m_Namespace;
|
||||||
public string m_AssemblyName;
|
public string m_AssemblyName;
|
||||||
|
|
||||||
public MonoScript(ObjectReader reader) : base(reader)
|
public MonoScript(ObjectReader reader) : base(reader)
|
||||||
|
@ -43,7 +43,6 @@ namespace AssetStudio
|
|||||||
|
|
||||||
public string Dump()
|
public string Dump()
|
||||||
{
|
{
|
||||||
reader.Reset();
|
|
||||||
if (serializedType?.m_Nodes != null)
|
if (serializedType?.m_Nodes != null)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
@ -1,19 +1,23 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public static class TypeTreeHelper
|
public static class TypeTreeHelper
|
||||||
{
|
{
|
||||||
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader)
|
public static void ReadTypeString(StringBuilder sb, List<TypeTreeNode> members, ObjectReader reader)
|
||||||
{
|
{
|
||||||
|
reader.Reset();
|
||||||
for (int i = 0; i < members.Count; i++)
|
for (int i = 0; i < members.Count; i++)
|
||||||
{
|
{
|
||||||
ReadStringValue(sb, members, reader, ref i);
|
ReadStringValue(sb, members, reader, ref i);
|
||||||
}
|
}
|
||||||
|
var readed = reader.Position - reader.byteStart;
|
||||||
|
if (readed != reader.byteSize)
|
||||||
|
{
|
||||||
|
Logger.Error($"Error while read type, read {readed} bytes but expected {reader.byteSize} bytes");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
private static void ReadStringValue(StringBuilder sb, List<TypeTreeNode> members, BinaryReader reader, ref int i)
|
||||||
|
@ -18,5 +18,15 @@ namespace AssetStudio
|
|||||||
public uint m_TypeStrOffset;
|
public uint m_TypeStrOffset;
|
||||||
public uint m_NameStrOffset;
|
public uint m_NameStrOffset;
|
||||||
public ulong m_RefTypeHash;
|
public ulong m_RefTypeHash;
|
||||||
|
|
||||||
|
public TypeTreeNode() { }
|
||||||
|
|
||||||
|
public TypeTreeNode(string type, string name, int level, bool align)
|
||||||
|
{
|
||||||
|
m_Type = type;
|
||||||
|
m_Name = name;
|
||||||
|
m_Level = level;
|
||||||
|
m_MetaFlag = align ? 0x4000 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -930,7 +930,7 @@ namespace AssetStudioGUI
|
|||||||
|
|
||||||
private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour)
|
private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour)
|
||||||
{
|
{
|
||||||
PreviewText(m_MonoBehaviour.Dump() ?? GetScriptString(m_MonoBehaviour.reader));
|
PreviewText(m_MonoBehaviour.Dump() ?? DeserializeMonoBehaviour(m_MonoBehaviour));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreviewFont(Font m_Font)
|
private void PreviewFont(Font m_Font)
|
||||||
@ -1192,6 +1192,7 @@ namespace AssetStudioGUI
|
|||||||
{
|
{
|
||||||
Text = $"AssetStudioGUI v{Application.ProductVersion}";
|
Text = $"AssetStudioGUI v{Application.ProductVersion}";
|
||||||
assetsManager.Clear();
|
assetsManager.Clear();
|
||||||
|
assemblyLoader.Clear();
|
||||||
exportableAssets.Clear();
|
exportableAssets.Clear();
|
||||||
visibleAssets.Clear();
|
visibleAssets.Clear();
|
||||||
sceneTreeView.Nodes.Clear();
|
sceneTreeView.Nodes.Clear();
|
||||||
@ -1221,12 +1222,6 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
FMODreset();
|
FMODreset();
|
||||||
|
|
||||||
if (scriptDumper != null)
|
|
||||||
{
|
|
||||||
scriptDumper.Dispose();
|
|
||||||
scriptDumper = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assetListView_MouseClick(object sender, MouseEventArgs e)
|
private void assetListView_MouseClick(object sender, MouseEventArgs e)
|
||||||
|
@ -116,7 +116,7 @@ namespace AssetStudioGUI
|
|||||||
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
|
||||||
return false;
|
return false;
|
||||||
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
|
var m_MonoBehaviour = (MonoBehaviour)item.Asset;
|
||||||
var str = m_MonoBehaviour.Dump() ?? Studio.GetScriptString(item.Asset.reader);
|
var str = m_MonoBehaviour.Dump() ?? Studio.DeserializeMonoBehaviour(m_MonoBehaviour);
|
||||||
File.WriteAllText(exportFullPath, str);
|
File.WriteAllText(exportFullPath, str);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ using System.Diagnostics;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using static AssetStudioGUI.Exporter;
|
using static AssetStudioGUI.Exporter;
|
||||||
@ -22,7 +23,7 @@ namespace AssetStudioGUI
|
|||||||
internal static class Studio
|
internal static class Studio
|
||||||
{
|
{
|
||||||
public static AssetsManager assetsManager = new AssetsManager();
|
public static AssetsManager assetsManager = new AssetsManager();
|
||||||
public static ScriptDumper scriptDumper = new ScriptDumper();
|
public static AssemblyLoader assemblyLoader = new AssemblyLoader();
|
||||||
public static List<AssetItem> exportableAssets = new List<AssetItem>();
|
public static List<AssetItem> exportableAssets = new List<AssetItem>();
|
||||||
public static List<AssetItem> visibleAssets = new List<AssetItem>();
|
public static List<AssetItem> visibleAssets = new List<AssetItem>();
|
||||||
internal static Action<string> StatusStripUpdate = x => { };
|
internal static Action<string> StatusStripUpdate = x => { };
|
||||||
@ -614,23 +615,29 @@ namespace AssetStudioGUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetScriptString(ObjectReader reader)
|
public static string DeserializeMonoBehaviour(MonoBehaviour m_MonoBehaviour)
|
||||||
{
|
{
|
||||||
if (scriptDumper == null)
|
if (!assemblyLoader.Loaded)
|
||||||
{
|
{
|
||||||
var openFolderDialog = new OpenFolderDialog();
|
var openFolderDialog = new OpenFolderDialog();
|
||||||
openFolderDialog.Title = "Select Assembly Folder";
|
openFolderDialog.Title = "Select Assembly Folder";
|
||||||
if (openFolderDialog.ShowDialog() == DialogResult.OK)
|
if (openFolderDialog.ShowDialog() == DialogResult.OK)
|
||||||
{
|
{
|
||||||
scriptDumper = new ScriptDumper(openFolderDialog.Folder);
|
assemblyLoader.Load(openFolderDialog.Folder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scriptDumper = new ScriptDumper();
|
assemblyLoader.Loaded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var nodes = m_MonoBehaviour.ConvertToTypeTreeNode(assemblyLoader);
|
||||||
return scriptDumper.DumpScript(reader);
|
if (nodes != null)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
TypeTreeHelper.ReadTypeString(sb, nodes, m_MonoBehaviour.reader);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
53
AssetStudioUtility/AssemblyLoader.cs
Normal file
53
AssetStudioUtility/AssemblyLoader.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using Mono.Cecil;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class AssemblyLoader
|
||||||
|
{
|
||||||
|
public bool Loaded;
|
||||||
|
private Dictionary<string, ModuleDefinition> moduleDic = new Dictionary<string, ModuleDefinition>();
|
||||||
|
|
||||||
|
public void Load(string path)
|
||||||
|
{
|
||||||
|
var files = Directory.GetFiles(path, "*.dll");
|
||||||
|
var resolver = new MyAssemblyResolver();
|
||||||
|
var readerParameters = new ReaderParameters();
|
||||||
|
readerParameters.AssemblyResolver = resolver;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var file in files)
|
||||||
|
{
|
||||||
|
var assembly = AssemblyDefinition.ReadAssembly(file, readerParameters);
|
||||||
|
resolver.Register(assembly);
|
||||||
|
moduleDic.Add(assembly.MainModule.Name, assembly.MainModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
Loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeDefinition GetTypeDefinition(string assemblyName, string fullName)
|
||||||
|
{
|
||||||
|
if (moduleDic.TryGetValue(assemblyName, out var module))
|
||||||
|
{
|
||||||
|
return module.GetType(fullName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
foreach (var pair in moduleDic)
|
||||||
|
{
|
||||||
|
pair.Value.Dispose();
|
||||||
|
}
|
||||||
|
moduleDic.Clear();
|
||||||
|
Loaded = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,9 +34,6 @@
|
|||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="dnlib, Version=3.3.2.0, Culture=neutral, PublicKeyToken=50e96378b6e77999, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\packages\dnlib.3.3.2\lib\net45\dnlib.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
@ -46,8 +43,18 @@
|
|||||||
<Reference Include="System.Data" />
|
<Reference Include="System.Data" />
|
||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="Unity.Cecil">
|
||||||
|
<HintPath>Libraries\Unity.Cecil.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Unity.CecilTools">
|
||||||
|
<HintPath>Libraries\Unity.CecilTools.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Unity.SerializationLogic">
|
||||||
|
<HintPath>Libraries\Unity.SerializationLogic.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="AssemblyLoader.cs" />
|
||||||
<Compile Include="AudioClipConverter.cs" />
|
<Compile Include="AudioClipConverter.cs" />
|
||||||
<Compile Include="CSspv\Disassembler.cs" />
|
<Compile Include="CSspv\Disassembler.cs" />
|
||||||
<Compile Include="CSspv\EnumValuesExtensions.cs" />
|
<Compile Include="CSspv\EnumValuesExtensions.cs" />
|
||||||
@ -64,8 +71,11 @@
|
|||||||
<Compile Include="FMOD Studio API\fmod_errors.cs" />
|
<Compile Include="FMOD Studio API\fmod_errors.cs" />
|
||||||
<Compile Include="ModelConverter.cs" />
|
<Compile Include="ModelConverter.cs" />
|
||||||
<Compile Include="ModelExporter.cs" />
|
<Compile Include="ModelExporter.cs" />
|
||||||
|
<Compile Include="MonoBehaviourConverter.cs" />
|
||||||
|
<Compile Include="SerializedTypeHelper.cs" />
|
||||||
|
<Compile Include="TypeDefinitionConverter.cs" />
|
||||||
|
<Compile Include="MyAssemblyResolver.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="ScriptDumper.cs" />
|
|
||||||
<Compile Include="ShaderConverter.cs" />
|
<Compile Include="ShaderConverter.cs" />
|
||||||
<Compile Include="Smolv\OpData.cs" />
|
<Compile Include="Smolv\OpData.cs" />
|
||||||
<Compile Include="Smolv\SmolvDecoder.cs" />
|
<Compile Include="Smolv\SmolvDecoder.cs" />
|
||||||
@ -93,8 +103,5 @@
|
|||||||
<Name>Texture2DDecoderWrapper</Name>
|
<Name>Texture2DDecoderWrapper</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<None Include="packages.config" />
|
|
||||||
</ItemGroup>
|
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
BIN
AssetStudioUtility/Libraries/Unity.Cecil.dll
Normal file
BIN
AssetStudioUtility/Libraries/Unity.Cecil.dll
Normal file
Binary file not shown.
BIN
AssetStudioUtility/Libraries/Unity.CecilTools.dll
Normal file
BIN
AssetStudioUtility/Libraries/Unity.CecilTools.dll
Normal file
Binary file not shown.
BIN
AssetStudioUtility/Libraries/Unity.SerializationLogic.dll
Normal file
BIN
AssetStudioUtility/Libraries/Unity.SerializationLogic.dll
Normal file
Binary file not shown.
24
AssetStudioUtility/MonoBehaviourConverter.cs
Normal file
24
AssetStudioUtility/MonoBehaviourConverter.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public static class MonoBehaviourConverter
|
||||||
|
{
|
||||||
|
public static List<TypeTreeNode> ConvertToTypeTreeNode(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader)
|
||||||
|
{
|
||||||
|
var nodes = new List<TypeTreeNode>();
|
||||||
|
var helper = new SerializedTypeHelper(m_MonoBehaviour.version);
|
||||||
|
helper.AddMonoBehaviour(nodes, 0);
|
||||||
|
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
||||||
|
{
|
||||||
|
var typeDef = assemblyLoader.GetTypeDefinition(m_Script.m_AssemblyName, string.IsNullOrEmpty(m_Script.m_Namespace) ? m_Script.m_ClassName : $"{m_Script.m_Namespace}.{m_Script.m_ClassName}");
|
||||||
|
if (typeDef != null)
|
||||||
|
{
|
||||||
|
var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1);
|
||||||
|
nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
AssetStudioUtility/MyAssemblyResolver.cs
Normal file
12
AssetStudioUtility/MyAssemblyResolver.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Mono.Cecil;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class MyAssemblyResolver : DefaultAssemblyResolver
|
||||||
|
{
|
||||||
|
public void Register(AssemblyDefinition assembly)
|
||||||
|
{
|
||||||
|
RegisterAssembly(assembly);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,492 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using dnlib.DotNet;
|
|
||||||
|
|
||||||
namespace AssetStudio
|
|
||||||
{
|
|
||||||
//TODO to json file
|
|
||||||
public sealed class ScriptDumper : IDisposable
|
|
||||||
{
|
|
||||||
private Dictionary<string, ModuleDef> moduleDic = new Dictionary<string, ModuleDef>();
|
|
||||||
|
|
||||||
public ScriptDumper() { }
|
|
||||||
|
|
||||||
public ScriptDumper(string path)
|
|
||||||
{
|
|
||||||
var files = Directory.GetFiles(path, "*.dll");
|
|
||||||
var moduleContext = new ModuleContext();
|
|
||||||
var asmResolver = new AssemblyResolver(moduleContext);
|
|
||||||
var resolver = new Resolver(asmResolver);
|
|
||||||
moduleContext.AssemblyResolver = asmResolver;
|
|
||||||
moduleContext.Resolver = resolver;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
var module = ModuleDefMD.Load(file, moduleContext);
|
|
||||||
asmResolver.AddToCache(module);
|
|
||||||
moduleDic.Add(Path.GetFileName(file), module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DumpScript(ObjectReader reader)
|
|
||||||
{
|
|
||||||
var m_MonoBehaviour = new MonoBehaviour(reader);
|
|
||||||
var sb = CreateMonoBehaviourHeader(m_MonoBehaviour);
|
|
||||||
if (m_MonoBehaviour.m_Script.TryGet(out var m_Script))
|
|
||||||
{
|
|
||||||
if (!moduleDic.TryGetValue(m_Script.m_AssemblyName, out var module))
|
|
||||||
{
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
var typeDef = module.Assembly.Find(m_Script.m_Namespace != "" ? $"{m_Script.m_Namespace}.{m_Script.m_ClassName}" : m_Script.m_ClassName, false);
|
|
||||||
if (typeDef != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DumpType(typeDef.ToTypeSig(), sb, reader, null, -1, true);
|
|
||||||
var readed = reader.Position - reader.byteStart;
|
|
||||||
if (readed != reader.byteSize)
|
|
||||||
{
|
|
||||||
Logger.Error($"Error while dump type, read {readed} bytes but expected {reader.byteSize} bytes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
sb = CreateMonoBehaviourHeader(m_MonoBehaviour);
|
|
||||||
Logger.Error("Error while dump type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (moduleDic != null)
|
|
||||||
{
|
|
||||||
foreach (var pair in moduleDic)
|
|
||||||
{
|
|
||||||
pair.Value.Dispose();
|
|
||||||
}
|
|
||||||
moduleDic.Clear();
|
|
||||||
moduleDic = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuilder CreateMonoBehaviourHeader(MonoBehaviour m_MonoBehaviour)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine("PPtr<GameObject> m_GameObject");
|
|
||||||
sb.AppendLine($"\tint m_FileID = {m_MonoBehaviour.m_GameObject.m_FileID}");
|
|
||||||
sb.AppendLine($"\tint64 m_PathID = {m_MonoBehaviour.m_GameObject.m_PathID}");
|
|
||||||
sb.AppendLine($"UInt8 m_Enabled = {m_MonoBehaviour.m_Enabled}");
|
|
||||||
sb.AppendLine("PPtr<MonoScript> m_Script");
|
|
||||||
sb.AppendLine($"\tint m_FileID = {m_MonoBehaviour.m_Script.m_FileID}");
|
|
||||||
sb.AppendLine($"\tint64 m_PathID = {m_MonoBehaviour.m_Script.m_PathID}");
|
|
||||||
sb.AppendLine($"string m_Name = \"{m_MonoBehaviour.m_Name}\"");
|
|
||||||
return sb;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DumpType(TypeSig typeSig, StringBuilder sb, ObjectReader reader, string name, int indent, bool isRoot = false, bool align = true)
|
|
||||||
{
|
|
||||||
var typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (typeSig.IsPrimitive)
|
|
||||||
{
|
|
||||||
object value = null;
|
|
||||||
switch (typeSig.TypeName)
|
|
||||||
{
|
|
||||||
case "Boolean":
|
|
||||||
value = reader.ReadBoolean();
|
|
||||||
break;
|
|
||||||
case "Byte":
|
|
||||||
value = reader.ReadByte();
|
|
||||||
break;
|
|
||||||
case "SByte":
|
|
||||||
value = reader.ReadSByte();
|
|
||||||
break;
|
|
||||||
case "Int16":
|
|
||||||
value = reader.ReadInt16();
|
|
||||||
break;
|
|
||||||
case "UInt16":
|
|
||||||
value = reader.ReadUInt16();
|
|
||||||
break;
|
|
||||||
case "Int32":
|
|
||||||
value = reader.ReadInt32();
|
|
||||||
break;
|
|
||||||
case "UInt32":
|
|
||||||
value = reader.ReadUInt32();
|
|
||||||
break;
|
|
||||||
case "Int64":
|
|
||||||
value = reader.ReadInt64();
|
|
||||||
break;
|
|
||||||
case "UInt64":
|
|
||||||
value = reader.ReadUInt64();
|
|
||||||
break;
|
|
||||||
case "Single":
|
|
||||||
value = reader.ReadSingle();
|
|
||||||
break;
|
|
||||||
case "Double":
|
|
||||||
value = reader.ReadDouble();
|
|
||||||
break;
|
|
||||||
case "Char":
|
|
||||||
value = reader.ReadChar();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (align)
|
|
||||||
reader.AlignStream();
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name} = {value}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeSig.FullName == "System.String")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name} = \"{reader.ReadAlignedString()}\"");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeSig.FullName == "System.Object")
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.IsDelegate)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeSig is ArraySigBase)
|
|
||||||
{
|
|
||||||
if (!typeDef.IsEnum && !IsBaseType(typeDef) && !IsAssignFromUnityObject(typeDef) && !IsEngineType(typeDef) && !typeDef.IsSerializable)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var size = reader.ReadInt32();
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}int size = {size}");
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 2)}[{i}]");
|
|
||||||
DumpType(typeDef.ToTypeSig(), sb, reader, "data", indent + 2);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isRoot && typeSig is GenericInstSig genericInstSig)
|
|
||||||
{
|
|
||||||
if (genericInstSig.GenericArguments.Count == 1)
|
|
||||||
{
|
|
||||||
var genericType = genericInstSig.GenericType.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
var type = genericInstSig.GenericArguments[0].ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (genericInstSig.GenericArguments[0] is ArraySigBase)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!type.IsEnum && !IsBaseType(type) && !IsAssignFromUnityObject(type) && !IsEngineType(type) && !type.IsSerializable)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}");
|
|
||||||
if (genericType.Interfaces.Any(x => x.Interface.FullName == "System.Collections.Generic.ICollection`1<T>")) //System.Collections.Generic.IEnumerable`1<T>
|
|
||||||
{
|
|
||||||
var size = reader.ReadInt32();
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}int size = {size}");
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 2)}[{i}]");
|
|
||||||
DumpType(genericInstSig.GenericArguments[0], sb, reader, "data", indent + 2, false, false);
|
|
||||||
}
|
|
||||||
reader.AlignStream();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DumpType(genericType.ToTypeSig(), sb, reader, "data", indent + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (indent != -1 && IsAssignFromUnityObject(typeDef))
|
|
||||||
{
|
|
||||||
var pptr = new PPtr<Object>(reader);
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}PPtr<{typeDef.Name}> {name} = {{fileID: {pptr.m_FileID}, pathID: {pptr.m_PathID}}}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.IsEnum)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name} = {reader.ReadUInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isRoot && !IsEngineType(typeDef) && !typeDef.IsSerializable)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.AnimationCurve")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}<truncated>");
|
|
||||||
var animationCurve = new AnimationCurve<float>(reader, reader.ReadSingle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Bounds")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}<truncated>");
|
|
||||||
new AABB(reader);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.BoundsInt")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}<truncated>");
|
|
||||||
reader.Position += 24;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Color32")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}byte r = {reader.ReadByte()}");
|
|
||||||
sb.AppendLine($"{prefix}byte g = {reader.ReadByte()}");
|
|
||||||
sb.AppendLine($"{prefix}byte b = {reader.ReadByte()}");
|
|
||||||
sb.AppendLine($"{prefix}byte a = {reader.ReadByte()}");
|
|
||||||
reader.AlignStream();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Gradient")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}<truncated>");
|
|
||||||
if (reader.version[0] == 5 && reader.version[1] < 5)
|
|
||||||
reader.Position += 68;
|
|
||||||
else if (reader.version[0] == 5 && reader.version[1] < 6)
|
|
||||||
reader.Position += 72;
|
|
||||||
else
|
|
||||||
reader.Position += 168;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.GUIStyle") //TODO
|
|
||||||
{
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.LayerMask")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}uint m_Bits = {reader.ReadUInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.PropertyName")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}int id = {reader.ReadInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Rect")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}float x = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float y = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float width = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float height = {reader.ReadSingle()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.RectInt")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}int x = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int y = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int width = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int height = {reader.ReadInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.RectOffset")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}float left = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float right = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float top = {reader.ReadSingle()}");
|
|
||||||
sb.AppendLine($"{prefix}float bottom = {reader.ReadSingle()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Vector2Int")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}int x = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int y = {reader.ReadInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.FullName == "UnityEngine.Vector3Int")
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
var prefix = new string('\t', indent + 1);
|
|
||||||
sb.AppendLine($"{prefix}int x = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int y = {reader.ReadInt32()}");
|
|
||||||
sb.AppendLine($"{prefix}int z = {reader.ReadInt32()}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeDef.IsClass || typeDef.IsValueType)
|
|
||||||
{
|
|
||||||
if (name != null && indent != -1)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}");
|
|
||||||
}
|
|
||||||
if (indent == -1 && typeDef.BaseType.FullName != "UnityEngine.Object")
|
|
||||||
{
|
|
||||||
DumpType(typeDef.BaseType.ToTypeSig(), sb, reader, null, indent, true);
|
|
||||||
}
|
|
||||||
if (indent != -1 && typeDef.BaseType.FullName != "System.Object")
|
|
||||||
{
|
|
||||||
DumpType(typeDef.BaseType.ToTypeSig(), sb, reader, null, indent, true);
|
|
||||||
}
|
|
||||||
foreach (var fieldDef in typeDef.Fields)
|
|
||||||
{
|
|
||||||
var flag = false;
|
|
||||||
var access = fieldDef.Access & FieldAttributes.FieldAccessMask;
|
|
||||||
if (access != FieldAttributes.Public)
|
|
||||||
{
|
|
||||||
if (fieldDef.CustomAttributes.Any(x => x.TypeFullName == "UnityEngine.SerializeField"))
|
|
||||||
{
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((fieldDef.Attributes & FieldAttributes.Static) == 0 && (fieldDef.Attributes & FieldAttributes.InitOnly) == 0 && (fieldDef.Attributes & FieldAttributes.NotSerialized) == 0)
|
|
||||||
{
|
|
||||||
flag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag)
|
|
||||||
{
|
|
||||||
if (fieldDef.FieldType.IsGenericParameter)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < typeDef.GenericParameters.Count; i++)
|
|
||||||
{
|
|
||||||
var g = typeDef.GenericParameters[i];
|
|
||||||
if (g.FullName == fieldDef.FieldType.FullName)
|
|
||||||
{
|
|
||||||
var type = ((GenericInstSig)typeSig).GenericArguments[i];
|
|
||||||
DumpType(type, sb, reader, fieldDef.Name, indent + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (fieldDef.FieldType is GenericInstSig genericSig && genericSig.GenericArguments.Count == 1 && genericSig.GenericArguments[0].IsGenericParameter)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < typeDef.GenericParameters.Count; i++)
|
|
||||||
{
|
|
||||||
var g = typeDef.GenericParameters[i];
|
|
||||||
if (g.FullName == genericSig.GenericArguments[0].FullName)
|
|
||||||
{
|
|
||||||
var type = ((GenericInstSig)typeSig).GenericArguments[i];
|
|
||||||
var fieldTypeDef = fieldDef.FieldType.ToTypeDefOrRef().ResolveTypeDefThrow();
|
|
||||||
if (fieldTypeDef.Interfaces.Any(x => x.Interface.FullName == "System.Collections.Generic.ICollection`1<T>")) //System.Collections.Generic.IEnumerable`1<T>
|
|
||||||
{
|
|
||||||
var size = reader.ReadInt32();
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 1)}int size = {size}");
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{new string('\t', indent + 2)}[{i}]");
|
|
||||||
DumpType(type, sb, reader, "data", indent + 2, false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DumpType(fieldDef.FieldType, sb, reader, fieldDef.Name, indent + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DumpType(fieldDef.FieldType, sb, reader, fieldDef.Name, indent + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsAssignFromUnityObject(TypeDef typeDef)
|
|
||||||
{
|
|
||||||
if (typeDef.FullName == "UnityEngine.Object")
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (typeDef.BaseType != null)
|
|
||||||
{
|
|
||||||
if (typeDef.BaseType.FullName == "UnityEngine.Object")
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
typeDef = typeDef.BaseType.ResolveTypeDefThrow();
|
|
||||||
if (typeDef.BaseType == null)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (typeDef.BaseType.FullName == "UnityEngine.Object")
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsBaseType(IFullName typeDef)
|
|
||||||
{
|
|
||||||
switch (typeDef.FullName)
|
|
||||||
{
|
|
||||||
case "System.Boolean":
|
|
||||||
case "System.Byte":
|
|
||||||
case "System.SByte":
|
|
||||||
case "System.Int16":
|
|
||||||
case "System.UInt16":
|
|
||||||
case "System.Int32":
|
|
||||||
case "System.UInt32":
|
|
||||||
case "System.Int64":
|
|
||||||
case "System.UInt64":
|
|
||||||
case "System.Single":
|
|
||||||
case "System.Double":
|
|
||||||
case "System.String":
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsEngineType(IFullName typeDef)
|
|
||||||
{
|
|
||||||
switch (typeDef.FullName)
|
|
||||||
{
|
|
||||||
case "UnityEngine.AnimationCurve":
|
|
||||||
case "UnityEngine.Bounds":
|
|
||||||
case "UnityEngine.BoundsInt":
|
|
||||||
case "UnityEngine.Color":
|
|
||||||
case "UnityEngine.Color32":
|
|
||||||
case "UnityEngine.Gradient":
|
|
||||||
case "UnityEngine.GUIStyle":
|
|
||||||
case "UnityEngine.LayerMask":
|
|
||||||
case "UnityEngine.Matrix4x4":
|
|
||||||
case "UnityEngine.PropertyName":
|
|
||||||
case "UnityEngine.Quaternion":
|
|
||||||
case "UnityEngine.Rect":
|
|
||||||
case "UnityEngine.RectInt":
|
|
||||||
case "UnityEngine.RectOffset":
|
|
||||||
case "UnityEngine.Vector2":
|
|
||||||
case "UnityEngine.Vector2Int":
|
|
||||||
case "UnityEngine.Vector3":
|
|
||||||
case "UnityEngine.Vector3Int":
|
|
||||||
case "UnityEngine.Vector4":
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
281
AssetStudioUtility/SerializedTypeHelper.cs
Normal file
281
AssetStudioUtility/SerializedTypeHelper.cs
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class SerializedTypeHelper
|
||||||
|
{
|
||||||
|
private readonly int[] version;
|
||||||
|
|
||||||
|
public SerializedTypeHelper(int[] version)
|
||||||
|
{
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMonoBehaviour(List<TypeTreeNode> nodes, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("MonoBehaviour", "Base", indent, false));
|
||||||
|
AddPPtr(nodes, "GameObject", "m_GameObject", indent + 1);
|
||||||
|
nodes.Add(new TypeTreeNode("UInt8", "m_Enabled", indent + 1, true));
|
||||||
|
AddPPtr(nodes, "MonoScript", "m_Script", indent + 1);
|
||||||
|
AddString(nodes, "m_Name", indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPPtr(List<TypeTreeNode> nodes, string type, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode($"PPtr<{type}>", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_FileID", indent + 1, false));
|
||||||
|
if (version[0] >= 5) //5.0 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("SInt64", "m_PathID", indent + 1, false));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_PathID", indent + 1, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddString(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("string", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("Array", "Array", indent + 1, true));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "size", indent + 2, false));
|
||||||
|
nodes.Add(new TypeTreeNode("char", "data", indent + 2, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddArray(List<TypeTreeNode> nodes, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("Array", "Array", indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "size", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddAnimationCurve(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("AnimationCurve", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("vector", "m_Curve", indent + 1, false));
|
||||||
|
AddArray(nodes, indent + 2); //TODO 2017 and up Array align but no effect
|
||||||
|
nodes.Add(new TypeTreeNode("Keyframe", "data", indent + 3, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "time", indent + 4, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "value", indent + 4, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "inSlope", indent + 4, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "outSlope", indent + 4, false));
|
||||||
|
if (version[0] >= 2018) //2018 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "weightedMode", indent + 4, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "inWeight", indent + 4, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "outWeight", indent + 4, false));
|
||||||
|
}
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_PreInfinity", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_PostInfinity", indent + 1, false));
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 3)) //5.3 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_RotationOrder", indent + 1, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddGradient(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("Gradient", name, indent, false));
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 6)) //5.6 and up
|
||||||
|
{
|
||||||
|
AddColorRGBA(nodes, "key0", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key1", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key2", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key3", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key4", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key5", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key6", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "key7", indent + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddColor32(nodes, "key0", indent + 1);
|
||||||
|
AddColor32(nodes, "key1", indent + 1);
|
||||||
|
AddColor32(nodes, "key2", indent + 1);
|
||||||
|
AddColor32(nodes, "key3", indent + 1);
|
||||||
|
AddColor32(nodes, "key4", indent + 1);
|
||||||
|
AddColor32(nodes, "key5", indent + 1);
|
||||||
|
AddColor32(nodes, "key6", indent + 1);
|
||||||
|
AddColor32(nodes, "key7", indent + 1);
|
||||||
|
}
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime0", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime1", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime2", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime3", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime4", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime5", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime6", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "ctime7", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime0", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime1", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime2", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime3", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime4", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime5", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime6", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt16", "atime7", indent + 1, false));
|
||||||
|
if (version[0] > 5 || (version[0] == 5 && version[1] >= 5)) //5.5 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Mode", indent + 1, false));
|
||||||
|
}
|
||||||
|
nodes.Add(new TypeTreeNode("UInt8", "m_NumColorKeys", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("UInt8", "m_NumAlphaKeys", indent + 1, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddGUIStyle(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("GUIStyle", name, indent, false));
|
||||||
|
AddString(nodes, "m_Name", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_Normal", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_Hover", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_Active", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_Focused", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_OnNormal", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_OnHover", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_OnActive", indent + 1);
|
||||||
|
AddGUIStyleState(nodes, "m_OnFocused", indent + 1);
|
||||||
|
AddRectOffset(nodes, "m_Border", indent + 1);
|
||||||
|
if (version[0] >= 4) //4 and up
|
||||||
|
{
|
||||||
|
AddRectOffset(nodes, "m_Margin", indent + 1);
|
||||||
|
AddRectOffset(nodes, "m_Padding", indent + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddRectOffset(nodes, "m_Padding", indent + 1);
|
||||||
|
AddRectOffset(nodes, "m_Margin", indent + 1);
|
||||||
|
}
|
||||||
|
AddRectOffset(nodes, "m_Overflow", indent + 1);
|
||||||
|
AddPPtr(nodes, "Font", "m_Font", indent + 1);
|
||||||
|
if (version[0] >= 4) //4 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Alignment", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_WordWrap", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_RichText", indent + 1, true));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_TextClipping", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_ImagePosition", indent + 1, false));
|
||||||
|
AddVector2f(nodes, "m_ContentOffset", indent + 1);
|
||||||
|
nodes.Add(new TypeTreeNode("float", "m_FixedWidth", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "m_FixedHeight", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_StretchWidth", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_StretchHeight", indent + 1, true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_ImagePosition", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Alignment", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_WordWrap", indent + 1, true));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_TextClipping", indent + 1, false));
|
||||||
|
AddVector2f(nodes, "m_ContentOffset", indent + 1);
|
||||||
|
AddVector2f(nodes, "m_ClipOffset", indent + 1);
|
||||||
|
nodes.Add(new TypeTreeNode("float", "m_FixedWidth", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "m_FixedHeight", indent + 1, false));
|
||||||
|
if (version[0] >= 3) //3 and up
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_FontSize", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_FontStyle", indent + 1, false));
|
||||||
|
}
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_StretchWidth", indent + 1, true));
|
||||||
|
nodes.Add(new TypeTreeNode("bool", "m_StretchHeight", indent + 1, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddGUIStyleState(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("GUIStyleState", name, indent, false));
|
||||||
|
AddPPtr(nodes, "Texture2D", "m_Background", indent + 1);
|
||||||
|
AddColorRGBA(nodes, "m_TextColor", indent + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddVector2f(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("Vector2f", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "x", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "y", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRectOffset(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("RectOffset", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Left", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Right", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Top", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("int", "m_Bottom", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddColorRGBA(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("ColorRGBA", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "r", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "g", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "b", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "a", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddColor32(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("ColorRGBA", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("unsigned int", "rgba", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMatrix4x4(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("Matrix4x4f", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e00", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e01", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e02", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e03", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e10", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e11", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e12", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e13", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e20", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e21", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e22", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e23", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e30", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e31", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e32", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "e33", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddSphericalHarmonicsL2(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("SphericalHarmonicsL2", name, indent, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 0]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 1]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 2]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 3]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 4]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 5]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 6]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 7]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 8]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[ 9]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[10]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[11]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[12]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[13]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[14]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[15]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[16]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[17]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[18]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[19]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[20]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[21]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[22]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[23]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[24]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[25]", indent + 1, false));
|
||||||
|
nodes.Add(new TypeTreeNode("float", "sh[26]", indent + 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddPropertyName(List<TypeTreeNode> nodes, string name, int indent)
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("PropertyName", name, indent, false));
|
||||||
|
AddString(nodes, "id", indent + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
307
AssetStudioUtility/TypeDefinitionConverter.cs
Normal file
307
AssetStudioUtility/TypeDefinitionConverter.cs
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
using Mono.Cecil;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Unity.CecilTools;
|
||||||
|
using Unity.SerializationLogic;
|
||||||
|
|
||||||
|
namespace AssetStudio
|
||||||
|
{
|
||||||
|
public class TypeDefinitionConverter
|
||||||
|
{
|
||||||
|
private readonly TypeDefinition TypeDef;
|
||||||
|
private readonly TypeResolver TypeResolver;
|
||||||
|
private readonly SerializedTypeHelper Helper;
|
||||||
|
private readonly int Indent;
|
||||||
|
|
||||||
|
public TypeDefinitionConverter(TypeDefinition typeDef, SerializedTypeHelper helper, int indent)
|
||||||
|
{
|
||||||
|
TypeDef = typeDef;
|
||||||
|
TypeResolver = new TypeResolver(null);
|
||||||
|
Helper = helper;
|
||||||
|
Indent = indent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TypeTreeNode> ConvertToTypeTreeNode()
|
||||||
|
{
|
||||||
|
var nodes = new List<TypeTreeNode>();
|
||||||
|
|
||||||
|
Stack<TypeReference> baseTypes = new Stack<TypeReference>();
|
||||||
|
TypeReference baseType = TypeDef.BaseType;
|
||||||
|
while (!UnitySerializationLogic.IsNonSerialized(baseType))
|
||||||
|
{
|
||||||
|
GenericInstanceType genericInstanceType = baseType as GenericInstanceType;
|
||||||
|
if (genericInstanceType != null)
|
||||||
|
{
|
||||||
|
TypeResolver.Add(genericInstanceType);
|
||||||
|
}
|
||||||
|
baseTypes.Push(baseType);
|
||||||
|
baseType = baseType.Resolve().BaseType;
|
||||||
|
}
|
||||||
|
while (baseTypes.Count > 0)
|
||||||
|
{
|
||||||
|
TypeReference typeReference = baseTypes.Pop();
|
||||||
|
TypeDefinition typeDefinition = typeReference.Resolve();
|
||||||
|
foreach (var fieldDefinition in typeDefinition.Fields.Where(WillUnitySerialize))
|
||||||
|
{
|
||||||
|
if (!IsHiddenByParentClass(baseTypes, fieldDefinition, TypeDef))
|
||||||
|
{
|
||||||
|
nodes.AddRange(ProcessingFieldRef(ResolveGenericFieldReference(fieldDefinition)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var genericInstanceType2 = typeReference as GenericInstanceType;
|
||||||
|
if (genericInstanceType2 != null)
|
||||||
|
{
|
||||||
|
TypeResolver.Remove(genericInstanceType2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (FieldDefinition fieldDefinition2 in FilteredFields())
|
||||||
|
{
|
||||||
|
nodes.AddRange(ProcessingFieldRef(fieldDefinition2));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool WillUnitySerialize(FieldDefinition fieldDefinition)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TypeReference typeReference = TypeResolver.Resolve(fieldDefinition.FieldType);
|
||||||
|
if (UnitySerializationLogic.ShouldNotTryToResolve(typeReference))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!UnityEngineTypePredicates.IsUnityEngineObject(typeReference))
|
||||||
|
{
|
||||||
|
if (typeReference.FullName == fieldDefinition.DeclaringType.FullName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = UnitySerializationLogic.WillUnitySerialize(fieldDefinition, TypeResolver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new Exception(string.Format("Exception while processing {0} {1}, error {2}", fieldDefinition.FieldType.FullName, fieldDefinition.FullName, ex.Message));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsHiddenByParentClass(IEnumerable<TypeReference> parentTypes, FieldDefinition fieldDefinition, TypeDefinition processingType)
|
||||||
|
{
|
||||||
|
return processingType.Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name) || parentTypes.Any((TypeReference t) => t.Resolve().Fields.Any((FieldDefinition f) => f.Name == fieldDefinition.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<FieldDefinition> FilteredFields()
|
||||||
|
{
|
||||||
|
foreach (var f in TypeDef.Fields.Where(WillUnitySerialize))
|
||||||
|
{
|
||||||
|
if (UnitySerializationLogic.IsSupportedCollection(f.FieldType) || !f.FieldType.IsGenericInstance || UnitySerializationLogic.ShouldImplementIDeserializable(f.FieldType.Resolve()))
|
||||||
|
{
|
||||||
|
yield return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldReference ResolveGenericFieldReference(FieldReference fieldRef)
|
||||||
|
{
|
||||||
|
FieldReference field = new FieldReference(fieldRef.Name, fieldRef.FieldType, ResolveDeclaringType(fieldRef.DeclaringType));
|
||||||
|
return TypeDef.Module.ImportReference(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeReference ResolveDeclaringType(TypeReference declaringType)
|
||||||
|
{
|
||||||
|
TypeDefinition typeDefinition = declaringType.Resolve();
|
||||||
|
TypeReference result;
|
||||||
|
if (typeDefinition == null || !typeDefinition.HasGenericParameters)
|
||||||
|
{
|
||||||
|
result = typeDefinition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GenericInstanceType genericInstanceType = new GenericInstanceType(typeDefinition);
|
||||||
|
foreach (GenericParameter item in typeDefinition.GenericParameters)
|
||||||
|
{
|
||||||
|
genericInstanceType.GenericArguments.Add(item);
|
||||||
|
}
|
||||||
|
result = TypeResolver.Resolve(genericInstanceType);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TypeTreeNode> ProcessingFieldRef(FieldReference fieldDef)
|
||||||
|
{
|
||||||
|
var typeRef = TypeResolver.Resolve(fieldDef.FieldType);
|
||||||
|
return TypeRefToTypeTreeNodes(typeRef, fieldDef.Name, Indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsStruct(TypeReference typeRef)
|
||||||
|
{
|
||||||
|
return typeRef.IsValueType && !IsEnum(typeRef) && !typeRef.IsPrimitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsEnum(TypeReference typeRef)
|
||||||
|
{
|
||||||
|
return !typeRef.IsArray && typeRef.Resolve().IsEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool RequiresAlignment(TypeReference typeRef)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
switch (typeRef.MetadataType)
|
||||||
|
{
|
||||||
|
case MetadataType.Boolean:
|
||||||
|
case MetadataType.Char:
|
||||||
|
case MetadataType.SByte:
|
||||||
|
case MetadataType.Byte:
|
||||||
|
case MetadataType.Int16:
|
||||||
|
case MetadataType.UInt16:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = (UnitySerializationLogic.IsSupportedCollection(typeRef) && RequiresAlignment(CecilUtils.ElementTypeOfCollection(typeRef)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsSystemString(TypeReference typeRef)
|
||||||
|
{
|
||||||
|
return typeRef.FullName == "System.String";
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TypeTreeNode> TypeRefToTypeTreeNodes(TypeReference typeRef, string name, int indent)
|
||||||
|
{
|
||||||
|
var align = false;
|
||||||
|
|
||||||
|
if (!IsStruct(TypeDef) || !UnityEngineTypePredicates.IsUnityEngineValueType(TypeDef))
|
||||||
|
{
|
||||||
|
if (IsStruct(typeRef) || RequiresAlignment(typeRef))
|
||||||
|
{
|
||||||
|
align = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodes = new List<TypeTreeNode>();
|
||||||
|
if (typeRef.IsPrimitive)
|
||||||
|
{
|
||||||
|
var primitiveName = typeRef.Name;
|
||||||
|
switch (primitiveName)
|
||||||
|
{
|
||||||
|
case "Boolean":
|
||||||
|
primitiveName = "bool";
|
||||||
|
break;
|
||||||
|
case "Byte":
|
||||||
|
primitiveName = "UInt8";
|
||||||
|
break;
|
||||||
|
case "SByte":
|
||||||
|
primitiveName = "SInt8";
|
||||||
|
break;
|
||||||
|
case "Int16":
|
||||||
|
primitiveName = "SInt16";
|
||||||
|
break;
|
||||||
|
case "UInt16":
|
||||||
|
primitiveName = "UInt16";
|
||||||
|
break;
|
||||||
|
case "Int32":
|
||||||
|
primitiveName = "SInt32";
|
||||||
|
break;
|
||||||
|
case "UInt32":
|
||||||
|
primitiveName = "UInt32";
|
||||||
|
break;
|
||||||
|
case "Int64":
|
||||||
|
primitiveName = "SInt64";
|
||||||
|
break;
|
||||||
|
case "UInt64":
|
||||||
|
primitiveName = "UInt64";
|
||||||
|
break;
|
||||||
|
case "Char":
|
||||||
|
primitiveName = "char";
|
||||||
|
break;
|
||||||
|
case "Double":
|
||||||
|
primitiveName = "double";
|
||||||
|
break;
|
||||||
|
case "Single":
|
||||||
|
primitiveName = "float";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
nodes.Add(new TypeTreeNode(primitiveName, name, indent, align));
|
||||||
|
}
|
||||||
|
else if (IsSystemString(typeRef))
|
||||||
|
{
|
||||||
|
Helper.AddString(nodes, name, indent);
|
||||||
|
}
|
||||||
|
else if (IsEnum(typeRef))
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode("SInt32", name, indent, align));
|
||||||
|
}
|
||||||
|
else if (CecilUtils.IsGenericList(typeRef))
|
||||||
|
{
|
||||||
|
var elementRef = CecilUtils.ElementTypeOfCollection(typeRef);
|
||||||
|
nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));
|
||||||
|
Helper.AddArray(nodes, indent + 1);
|
||||||
|
nodes.AddRange(TypeRefToTypeTreeNodes(elementRef, "data", indent + 2));
|
||||||
|
}
|
||||||
|
else if (typeRef.IsArray)
|
||||||
|
{
|
||||||
|
var elementRef = typeRef.GetElementType();
|
||||||
|
nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));
|
||||||
|
Helper.AddArray(nodes, indent + 1);
|
||||||
|
nodes.AddRange(TypeRefToTypeTreeNodes(elementRef, "data", indent + 2));
|
||||||
|
}
|
||||||
|
else if (UnityEngineTypePredicates.IsUnityEngineObject(typeRef))
|
||||||
|
{
|
||||||
|
Helper.AddPPtr(nodes, typeRef.Name, name, indent);
|
||||||
|
}
|
||||||
|
else if (UnityEngineTypePredicates.IsSerializableUnityClass(typeRef) || UnityEngineTypePredicates.IsSerializableUnityStruct(typeRef))
|
||||||
|
{
|
||||||
|
switch (typeRef.FullName)
|
||||||
|
{
|
||||||
|
case "UnityEngine.AnimationCurve":
|
||||||
|
Helper.AddAnimationCurve(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.Gradient":
|
||||||
|
Helper.AddGradient(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.GUIStyle":
|
||||||
|
Helper.AddGUIStyle(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.RectOffset":
|
||||||
|
Helper.AddRectOffset(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.Color32":
|
||||||
|
Helper.AddColor32(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.Matrix4x4":
|
||||||
|
Helper.AddMatrix4x4(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.Rendering.SphericalHarmonicsL2":
|
||||||
|
Helper.AddSphericalHarmonicsL2(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
case "UnityEngine.PropertyName":
|
||||||
|
Helper.AddPropertyName(nodes, name, indent + 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));
|
||||||
|
var typeDef = typeRef.Resolve();
|
||||||
|
var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, Helper, indent + 1);
|
||||||
|
nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<packages>
|
|
||||||
<package id="dnlib" version="3.3.2" targetFramework="net472" />
|
|
||||||
</packages>
|
|
Loading…
Reference in New Issue
Block a user