diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index 1c5caba..93d89a3 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -181,6 +181,7 @@ + diff --git a/AssetStudio/AssetStudioForm.cs b/AssetStudio/AssetStudioForm.cs index 3e4cc37..1902876 100644 --- a/AssetStudio/AssetStudioForm.cs +++ b/AssetStudio/AssetStudioForm.cs @@ -76,7 +76,7 @@ namespace AssetStudio { if (openFileDialog1.ShowDialog() == DialogResult.OK) { - resetForm(); + ResetForm(); ThreadPool.QueueUserWorkItem(state => { mainPath = Path.GetDirectoryName(openFileDialog1.FileNames[0]); @@ -107,7 +107,7 @@ namespace AssetStudio var openFolderDialog1 = new OpenFolderDialog(); if (openFolderDialog1.ShowDialog(this) == DialogResult.OK) { - resetForm(); + ResetForm(); ThreadPool.QueueUserWorkItem(state => { mainPath = openFolderDialog1.Folder; @@ -180,7 +180,7 @@ namespace AssetStudio { Text = $"AssetStudio - {productName} - {assetsfileList[0].unityVersion} - {assetsfileList[0].platformStr}"; } - else if (assetsfileList.Count > 0) + else { Text = $"AssetStudio - no productName - {assetsfileList[0].unityVersion} - {assetsfileList[0].platformStr}"; } @@ -843,7 +843,7 @@ namespace AssetStudio } else { - textPreviewBox.Text = GetScriptString(reader); + textPreviewBox.Text = ScriptHelper.GetScriptString(reader); } textPreviewBox.Visible = true; @@ -1705,7 +1705,7 @@ namespace AssetStudio } } - private void resetForm() + private void ResetForm() { Text = "AssetStudio"; @@ -1723,7 +1723,7 @@ namespace AssetStudio } resourceFileReaders.Clear(); assetsFileIndexCache.Clear(); - productName = ""; + productName = string.Empty; sceneTreeView.Nodes.Clear(); @@ -1756,8 +1756,8 @@ namespace AssetStudio FMODreset(); - moduleLoaded = false; - LoadedModuleDic.Clear(); + ScriptHelper.moduleLoaded = false; + ScriptHelper.LoadedModuleDic.Clear(); treeNodeCollection.Clear(); treeNodeDictionary.Clear(); } diff --git a/AssetStudio/StudioClasses/Exporter.cs b/AssetStudio/StudioClasses/Exporter.cs index b7b5aac..1cff27e 100644 --- a/AssetStudio/StudioClasses/Exporter.cs +++ b/AssetStudio/StudioClasses/Exporter.cs @@ -113,7 +113,7 @@ namespace AssetStudio } else { - str = Studio.GetScriptString(reader); + str = ScriptHelper.GetScriptString(reader); } File.WriteAllText(exportFullName, str); return true; diff --git a/AssetStudio/StudioClasses/ModelConverter.cs b/AssetStudio/StudioClasses/ModelConverter.cs index adf7272..3cc7840 100644 --- a/AssetStudio/StudioClasses/ModelConverter.cs +++ b/AssetStudio/StudioClasses/ModelConverter.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Text; using SharpDX; -using static AssetStudio.Studio; namespace AssetStudio { @@ -1051,5 +1050,47 @@ namespace AssetStudio parentFrame.AddChild(frame); } } + + private static float[] QuatToEuler(float[] q) + { + double eax = 0; + double eay = 0; + double eaz = 0; + + float qx = q[0]; + float qy = q[1]; + float qz = q[2]; + float qw = q[3]; + + double[,] M = new double[4, 4]; + + double Nq = qx * qx + qy * qy + qz * qz + qw * qw; + double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; + double xs = qx * s, ys = qy * s, zs = qz * s; + double wx = qw * xs, wy = qw * ys, wz = qw * zs; + double xx = qx * xs, xy = qx * ys, xz = qx * zs; + double yy = qy * ys, yz = qy * zs, zz = qz * zs; + + M[0, 0] = 1.0 - (yy + zz); M[0, 1] = xy - wz; M[0, 2] = xz + wy; + M[1, 0] = xy + wz; M[1, 1] = 1.0 - (xx + zz); M[1, 2] = yz - wx; + M[2, 0] = xz - wy; M[2, 1] = yz + wx; M[2, 2] = 1.0 - (xx + yy); + M[3, 0] = M[3, 1] = M[3, 2] = M[0, 3] = M[1, 3] = M[2, 3] = 0.0; M[3, 3] = 1.0; + + double test = Math.Sqrt(M[0, 0] * M[0, 0] + M[1, 0] * M[1, 0]); + if (test > 16 * 1.19209290E-07F)//FLT_EPSILON + { + eax = Math.Atan2(M[2, 1], M[2, 2]); + eay = Math.Atan2(-M[2, 0], test); + eaz = Math.Atan2(M[1, 0], M[0, 0]); + } + else + { + eax = Math.Atan2(-M[1, 2], M[1, 1]); + eay = Math.Atan2(-M[2, 0], test); + eaz = 0; + } + + return new[] { (float)(eax * 180 / Math.PI), (float)(eay * 180 / Math.PI), (float)(eaz * 180 / Math.PI) }; + } } } diff --git a/AssetStudio/StudioClasses/ScriptHelper.cs b/AssetStudio/StudioClasses/ScriptHelper.cs new file mode 100644 index 0000000..a1958a1 --- /dev/null +++ b/AssetStudio/StudioClasses/ScriptHelper.cs @@ -0,0 +1,348 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using dnlib.DotNet; + +namespace AssetStudio +{ + //TODO unfinished + public static class ScriptHelper + { + public static bool moduleLoaded; + public static Dictionary LoadedModuleDic = new Dictionary(); + + public static string GetScriptString(ObjectReader reader) + { + if (!moduleLoaded) + { + var openFolderDialog = new OpenFolderDialog(); + openFolderDialog.Title = "Select Assembly Folder"; + if (openFolderDialog.ShowDialog() == DialogResult.OK) + { + var files = Directory.GetFiles(openFolderDialog.Folder, "*.dll"); + var moduleContext = new ModuleContext(); + var asmResolver = new AssemblyResolver(moduleContext, true); + var resolver = new Resolver(asmResolver); + moduleContext.AssemblyResolver = asmResolver; + moduleContext.Resolver = resolver; + try + { + foreach (var file in files) + { + var module = ModuleDefMD.Load(file, moduleContext); + LoadedModuleDic.Add(Path.GetFileName(file), module); + } + } + catch + { + // ignored + } + } + + moduleLoaded = true; + } + var m_MonoBehaviour = new MonoBehaviour(reader); + var sb = CreateMonoBehaviourHeader(m_MonoBehaviour); + if (m_MonoBehaviour.m_Script.TryGet(out var script)) + { + var m_Script = new MonoScript(script); + if (!LoadedModuleDic.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); + } + catch + { + sb = CreateMonoBehaviourHeader(m_MonoBehaviour); + } + } + } + return sb.ToString(); + } + + private static StringBuilder CreateMonoBehaviourHeader(MonoBehaviour m_MonoBehaviour) + { + var sb = new StringBuilder(); + sb.AppendLine("PPtr 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 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) + { + 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; + } + reader.AlignStream(4); + 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)}Array Array"); + 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 type = genericInstSig.GenericArguments[0].ToTypeDefOrRef().ResolveTypeDefThrow(); + if (!type.IsEnum && !IsBaseType(type) && !IsAssignFromUnityObject(type) && !IsEngineType(type) && !type.IsSerializable) + { + return; + } + var size = reader.ReadInt32(); + sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}"); + sb.AppendLine($"{new string('\t', indent + 1)}Array Array"); + 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); + } + } + return; + } + if (indent != -1 && IsAssignFromUnityObject(typeDef)) + { + var pptr = reader.ReadPPtr(); + 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 (indent != -1 && !IsEngineType(typeDef) && !typeDef.IsSerializable) + { + return; + } + if (typeDef.FullName == "UnityEngine.Rect") + { + sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); + var rect = reader.ReadSingleArray(4); + return; + } + if (typeDef.FullName == "UnityEngine.LayerMask") + { + sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); + var value = reader.ReadInt32(); + return; + } + if (typeDef.FullName == "UnityEngine.AnimationCurve") + { + sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); + var animationCurve = new AnimationCurve(reader, reader.ReadSingle); + return; + } + if (typeDef.FullName == "UnityEngine.Gradient") + { + sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); + 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.RectOffset") + { + sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); + var left = reader.ReadSingle(); + var right = reader.ReadSingle(); + var top = reader.ReadSingle(); + var bottom = reader.ReadSingle(); + return; + } + if (typeDef.FullName == "UnityEngine.GUIStyle") //TODO + { + throw new NotSupportedException(); + } + 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 access = fieldDef.Access & FieldAttributes.FieldAccessMask; + if (access != FieldAttributes.Public) + { + if (fieldDef.CustomAttributes.Any(x => x.TypeFullName.Contains("SerializeField"))) + { + DumpType(fieldDef.FieldType, sb, reader, fieldDef.Name, indent + 1); + } + } + else if ((fieldDef.Attributes & FieldAttributes.Static) == 0 && (fieldDef.Attributes & FieldAttributes.InitOnly) == 0 && (fieldDef.Attributes & FieldAttributes.NotSerialized) == 0) + { + 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.Vector2": + case "UnityEngine.Vector3": + case "UnityEngine.Vector4": + case "UnityEngine.Rect": + case "UnityEngine.Quaternion": + case "UnityEngine.Matrix4x4": + case "UnityEngine.Color": + case "UnityEngine.Color32": + case "UnityEngine.LayerMask": + case "UnityEngine.AnimationCurve": + case "UnityEngine.Gradient": + case "UnityEngine.RectOffset": + case "UnityEngine.GUIStyle": + return true; + default: + return false; + } + } + } +} diff --git a/AssetStudio/StudioClasses/Studio.cs b/AssetStudio/StudioClasses/Studio.cs index be58fb8..7d3deab 100644 --- a/AssetStudio/StudioClasses/Studio.cs +++ b/AssetStudio/StudioClasses/Studio.cs @@ -4,10 +4,8 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; -using System.Text; using System.Threading; using System.Windows.Forms; -using dnlib.DotNet; using static AssetStudio.Exporter; namespace AssetStudio @@ -21,12 +19,10 @@ namespace AssetStudio private static HashSet assetsNameHash = new HashSet(); //avoid the same name asset public static List visibleAssets = new List(); //used to build the ListView from all or filtered assets public static Dictionary> AllTypeMap = new Dictionary>(); - public static string mainPath; - public static string productName = ""; - public static bool moduleLoaded; - public static Dictionary LoadedModuleDic = new Dictionary(); public static List treeNodeCollection = new List(); public static Dictionary treeNodeDictionary = new Dictionary(); + public static string mainPath; + public static string productName = string.Empty; //UI public static Action SetProgressBarValue; @@ -748,400 +744,5 @@ namespace AssetStudio } } } - - public static float[] QuatToEuler(float[] q) - { - double eax = 0; - double eay = 0; - double eaz = 0; - - float qx = q[0]; - float qy = q[1]; - float qz = q[2]; - float qw = q[3]; - - double[,] M = new double[4, 4]; - - double Nq = qx * qx + qy * qy + qz * qz + qw * qw; - double s = (Nq > 0.0) ? (2.0 / Nq) : 0.0; - double xs = qx * s, ys = qy * s, zs = qz * s; - double wx = qw * xs, wy = qw * ys, wz = qw * zs; - double xx = qx * xs, xy = qx * ys, xz = qx * zs; - double yy = qy * ys, yz = qy * zs, zz = qz * zs; - - M[0, 0] = 1.0 - (yy + zz); M[0, 1] = xy - wz; M[0, 2] = xz + wy; - M[1, 0] = xy + wz; M[1, 1] = 1.0 - (xx + zz); M[1, 2] = yz - wx; - M[2, 0] = xz - wy; M[2, 1] = yz + wx; M[2, 2] = 1.0 - (xx + yy); - M[3, 0] = M[3, 1] = M[3, 2] = M[0, 3] = M[1, 3] = M[2, 3] = 0.0; M[3, 3] = 1.0; - - double test = Math.Sqrt(M[0, 0] * M[0, 0] + M[1, 0] * M[1, 0]); - if (test > 16 * 1.19209290E-07F)//FLT_EPSILON - { - eax = Math.Atan2(M[2, 1], M[2, 2]); - eay = Math.Atan2(-M[2, 0], test); - eaz = Math.Atan2(M[1, 0], M[0, 0]); - } - else - { - eax = Math.Atan2(-M[1, 2], M[1, 1]); - eay = Math.Atan2(-M[2, 0], test); - eaz = 0; - } - - return new[] { (float)(eax * 180 / Math.PI), (float)(eay * 180 / Math.PI), (float)(eaz * 180 / Math.PI) }; - } - - public static string GetScriptString(ObjectReader reader) - { - if (!moduleLoaded) - { - var openFolderDialog = new OpenFolderDialog(); - openFolderDialog.Title = "Select Assembly Folder"; - if (openFolderDialog.ShowDialog() == DialogResult.OK) - { - var files = Directory.GetFiles(openFolderDialog.Folder, "*.dll"); - var moduleContext = new ModuleContext(); - var asmResolver = new AssemblyResolver(moduleContext, true); - var resolver = new Resolver(asmResolver); - moduleContext.AssemblyResolver = asmResolver; - moduleContext.Resolver = resolver; - try - { - foreach (var file in files) - { - var module = ModuleDefMD.Load(file, moduleContext); - LoadedModuleDic.Add(Path.GetFileName(file), module); - } - } - catch - { - // ignored - } - } - - moduleLoaded = true; - } - var m_MonoBehaviour = new MonoBehaviour(reader); - var sb = new StringBuilder(); - sb.AppendLine("PPtr 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 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}\""); - if (m_MonoBehaviour.m_Script.TryGet(out var script)) - { - var m_Script = new MonoScript(script); - if (!LoadedModuleDic.TryGetValue(m_Script.m_AssemblyName, out var module)) - { - /*using (var openFileDialog = new OpenFileDialog()) - { - openFileDialog.Title = $"Select {m_Script.m_AssemblyName}"; - openFileDialog.FileName = m_Script.m_AssemblyName; - openFileDialog.Filter = $"{m_Script.m_AssemblyName}|{m_Script.m_AssemblyName}"; - if (openFileDialog.ShowDialog() == DialogResult.OK) - { - var moduleContext = new ModuleContext(); - var asmResolver = new AssemblyResolver(moduleContext, true); - var resolver = new Resolver(asmResolver); - moduleContext.AssemblyResolver = asmResolver; - moduleContext.Resolver = resolver; - module = ModuleDefMD.Load(openFileDialog.FileName, moduleContext); - LoadedModule.Add(m_Script.m_AssemblyName, module); - } - else - { - return sb.ToString(); - } - }*/ - 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); - } - catch - { - sb = new StringBuilder(); - sb.AppendLine("PPtr 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 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.ToString(); - } - - private static void DumpType(TypeSig typeSig, StringBuilder sb, ObjectReader reader, string name, int indent, bool isRoot = false) - { - 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; - } - reader.AlignStream(4); - 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)}Array Array"); - 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 type = genericInstSig.GenericArguments[0].ToTypeDefOrRef().ResolveTypeDefThrow(); - if (!type.IsEnum && !IsBaseType(type) && !IsAssignFromUnityObject(type) && !IsEngineType(type) && !type.IsSerializable) - { - return; - } - var size = reader.ReadInt32(); - sb.AppendLine($"{new string('\t', indent)}{typeSig.TypeName} {name}"); - sb.AppendLine($"{new string('\t', indent + 1)}Array Array"); - 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); - } - } - return; - } - if (indent != -1 && IsAssignFromUnityObject(typeDef)) - { - var pptr = reader.ReadPPtr(); - 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 (indent != -1 && !IsEngineType(typeDef) && !typeDef.IsSerializable) - { - return; - } - if (typeDef.FullName == "UnityEngine.Rect") - { - sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); - var rect = reader.ReadSingleArray(4); - return; - } - if (typeDef.FullName == "UnityEngine.LayerMask") - { - sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); - var value = reader.ReadInt32(); - return; - } - if (typeDef.FullName == "UnityEngine.AnimationCurve") - { - sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); - var animationCurve = new AnimationCurve(reader, reader.ReadSingle); - return; - } - if (typeDef.FullName == "UnityEngine.Gradient") - { - sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); - 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.RectOffset") - { - sb.AppendLine($"{new string('\t', indent)}{typeDef.Name} {name}"); - var left = reader.ReadSingle(); - var right = reader.ReadSingle(); - var top = reader.ReadSingle(); - var bottom = reader.ReadSingle(); - return; - } - if (typeDef.FullName == "UnityEngine.GUIStyle") //TODO - { - 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 access = fieldDef.Access & FieldAttributes.FieldAccessMask; - if (access != FieldAttributes.Public) - { - if (fieldDef.CustomAttributes.Any(x => x.TypeFullName.Contains("SerializeField"))) - { - DumpType(fieldDef.FieldType, sb, reader, fieldDef.Name, indent + 1); - } - } - else if ((fieldDef.Attributes & FieldAttributes.Static) == 0 && (fieldDef.Attributes & FieldAttributes.InitOnly) == 0 && (fieldDef.Attributes & FieldAttributes.NotSerialized) == 0) - { - 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.Vector2": - case "UnityEngine.Vector3": - case "UnityEngine.Vector4": - case "UnityEngine.Rect": - case "UnityEngine.Quaternion": - case "UnityEngine.Matrix4x4": - case "UnityEngine.Color": - case "UnityEngine.Color32": - case "UnityEngine.LayerMask": - case "UnityEngine.AnimationCurve": - case "UnityEngine.Gradient": - case "UnityEngine.RectOffset": - case "UnityEngine.GUIStyle": - return true; - default: - return false; - } - } } } diff --git a/AssetStudio/StudioClasses/WebFile.cs b/AssetStudio/StudioClasses/WebFile.cs index fc99791..b586548 100644 --- a/AssetStudio/StudioClasses/WebFile.cs +++ b/AssetStudio/StudioClasses/WebFile.cs @@ -35,9 +35,9 @@ namespace AssetStudio gs.CopyTo(stream); } stream.Position = 0; - using (reader = new EndianBinaryReader(stream, EndianType.LittleEndian)) + using (var binaryReader = new BinaryReader(stream)) { - ReadWebData(reader); + ReadWebData(binaryReader); } } else @@ -51,9 +51,9 @@ namespace AssetStudio var stream = new MemoryStream(); brotliStream.CopyTo(stream); stream.Position = 0; - using (reader = new EndianBinaryReader(stream, EndianType.LittleEndian)) + using (var binaryReader = new BinaryReader(stream)) { - ReadWebData(reader); + ReadWebData(binaryReader); } } else @@ -64,14 +64,14 @@ namespace AssetStudio } } - private void ReadWebData(EndianBinaryReader reader) + private void ReadWebData(BinaryReader reader) { var signature = reader.ReadStringToNull(); if (signature != "UnityWebData1.0") return; var headLength = reader.ReadInt32(); var dataList = new List(); - while (reader.Position < headLength) + while (reader.BaseStream.Position < headLength) { var data = new WebData(); data.dataOffset = reader.ReadInt32(); @@ -85,7 +85,7 @@ namespace AssetStudio { var file = new StreamFile(); file.fileName = Path.GetFileName(data.path); - reader.Position = data.dataOffset; + reader.BaseStream.Position = data.dataOffset; file.stream = new MemoryStream(reader.ReadBytes(data.dataLength)); fileList.Add(file); }