From ca60dd98343b8a063c4575bbb54fa239e876a69c Mon Sep 17 00:00:00 2001 From: Perfare Date: Fri, 14 Aug 2020 15:45:48 +0800 Subject: [PATCH] Support exporting MonoBehaviour to json. Close #477 --- AssetStudio/AssetStudio.csproj | 1 - AssetStudio/Classes/Object.cs | 33 +++++- AssetStudio/TypeTreeHelper.cs | 13 ++- AssetStudio/UType.cs | 108 ------------------ AssetStudioGUI/AssetStudioGUI.csproj | 3 + AssetStudioGUI/AssetStudioGUIForm.cs | 10 +- AssetStudioGUI/Exporter.cs | 16 ++- AssetStudioGUI/Studio.cs | 11 +- AssetStudioGUI/packages.config | 1 + AssetStudioUtility/MonoBehaviourConverter.cs | 4 +- AssetStudioUtility/TypeDefinitionConverter.cs | 4 +- 11 files changed, 74 insertions(+), 130 deletions(-) delete mode 100644 AssetStudio/UType.cs diff --git a/AssetStudio/AssetStudio.csproj b/AssetStudio/AssetStudio.csproj index 85fe323..a457361 100644 --- a/AssetStudio/AssetStudio.csproj +++ b/AssetStudio/AssetStudio.csproj @@ -148,7 +148,6 @@ - diff --git a/AssetStudio/Classes/Object.cs b/AssetStudio/Classes/Object.cs index 835b5bf..a070013 100644 --- a/AssetStudio/Classes/Object.cs +++ b/AssetStudio/Classes/Object.cs @@ -1,5 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Collections.Specialized; using System.Linq; using System.Text; @@ -52,6 +52,35 @@ namespace AssetStudio return null; } + public string Dump(List m_Nodes) + { + if (m_Nodes != null) + { + var sb = new StringBuilder(); + TypeTreeHelper.ReadTypeString(sb, m_Nodes, reader); + return sb.ToString(); + } + return null; + } + + public OrderedDictionary ToType() + { + if (serializedType?.m_Nodes != null) + { + return TypeTreeHelper.ReadType(serializedType.m_Nodes, reader); + } + return null; + } + + public OrderedDictionary ToType(List m_Nodes) + { + if (m_Nodes != null) + { + return TypeTreeHelper.ReadType(m_Nodes, reader); + } + return null; + } + public byte[] GetRawData() { reader.Reset(); diff --git a/AssetStudio/TypeTreeHelper.cs b/AssetStudio/TypeTreeHelper.cs index 8b66325..52bb2ea 100644 --- a/AssetStudio/TypeTreeHelper.cs +++ b/AssetStudio/TypeTreeHelper.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Collections.Specialized; using System.IO; using System.Text; @@ -155,15 +156,21 @@ namespace AssetStudio reader.AlignStream(); } - public static UType ReadUType(List members, BinaryReader reader) + public static OrderedDictionary ReadType(List members, ObjectReader reader) { - var obj = new UType(); + reader.Reset(); + var obj = new OrderedDictionary(); for (int i = 1; i < members.Count; i++) { var member = members[i]; var varNameStr = member.m_Name; obj[varNameStr] = ReadValue(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"); + } return obj; } @@ -270,7 +277,7 @@ namespace AssetStudio { var @class = GetMembers(members, i); i += @class.Count - 1; - var obj = new UType(); + var obj = new OrderedDictionary(); for (int j = 1; j < @class.Count; j++) { var classmember = @class[j]; diff --git a/AssetStudio/UType.cs b/AssetStudio/UType.cs deleted file mode 100644 index 2b7902a..0000000 --- a/AssetStudio/UType.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace AssetStudio -{ - public class UType : IDictionary - { - private List keys; - private IDictionary values; - - public UType() - { - keys = new List(); - values = new Dictionary(); - } - - public object this[string key] - { - get - { - if (!values.ContainsKey(key)) - { - return null; - } - return values[key]; - } - set - { - if (!values.ContainsKey(key)) - { - keys.Add(key); - } - values[key] = value; - } - } - - public ICollection Keys => keys; - - public ICollection Values => values.Values; - - public int Count => keys.Count; - - public bool IsReadOnly => false; - - public void Add(string key, object value) - { - keys.Add(key); - values.Add(key, value); - } - - public void Add(KeyValuePair item) - { - keys.Add(item.Key); - values.Add(item); - } - - public void Clear() - { - keys.Clear(); - values.Clear(); - } - - public bool Contains(KeyValuePair item) - { - return values.Contains(item); - } - - public bool ContainsKey(string key) - { - return values.ContainsKey(key); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - values.CopyTo(array, arrayIndex); - } - - public IEnumerator> GetEnumerator() - { - return values.GetEnumerator(); - } - - public bool Remove(string key) - { - keys.Remove(key); - return values.Remove(key); - } - - public bool Remove(KeyValuePair item) - { - keys.Remove(item.Key); - return values.Remove(item); - } - - public bool TryGetValue(string key, out object value) - { - return values.TryGetValue(key, out value); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return values.GetEnumerator(); - } - } -} diff --git a/AssetStudioGUI/AssetStudioGUI.csproj b/AssetStudioGUI/AssetStudioGUI.csproj index b5e58c9..548402c 100644 --- a/AssetStudioGUI/AssetStudioGUI.csproj +++ b/AssetStudioGUI/AssetStudioGUI.csproj @@ -39,6 +39,9 @@ false + + ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll + ..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll diff --git a/AssetStudioGUI/AssetStudioGUIForm.cs b/AssetStudioGUI/AssetStudioGUIForm.cs index 89d624d..df1c993 100644 --- a/AssetStudioGUI/AssetStudioGUIForm.cs +++ b/AssetStudioGUI/AssetStudioGUIForm.cs @@ -1,4 +1,5 @@ using AssetStudio; +using Newtonsoft.Json; using OpenTK; using OpenTK.Graphics.OpenGL; using System; @@ -930,7 +931,14 @@ namespace AssetStudioGUI private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour) { - PreviewText(m_MonoBehaviour.Dump() ?? DeserializeMonoBehaviour(m_MonoBehaviour)); + var obj = m_MonoBehaviour.ToType(); + if (obj == null) + { + var nodes = MonoBehaviourToTypeTreeNodes(m_MonoBehaviour); + obj = m_MonoBehaviour.ToType(nodes); + } + var str = JsonConvert.SerializeObject(obj, Formatting.Indented); + PreviewText(str); } private void PreviewFont(Font m_Font) diff --git a/AssetStudioGUI/Exporter.cs b/AssetStudioGUI/Exporter.cs index fd7a9b1..66b58e4 100644 --- a/AssetStudioGUI/Exporter.cs +++ b/AssetStudioGUI/Exporter.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using AssetStudio; +using Newtonsoft.Json; using TGASharpLib; namespace AssetStudioGUI @@ -113,10 +114,16 @@ namespace AssetStudioGUI public static bool ExportMonoBehaviour(AssetItem item, string exportPath) { - if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath)) + if (!TryExportFile(exportPath, item, ".json", out var exportFullPath)) return false; var m_MonoBehaviour = (MonoBehaviour)item.Asset; - var str = m_MonoBehaviour.Dump() ?? Studio.DeserializeMonoBehaviour(m_MonoBehaviour); + var type = m_MonoBehaviour.ToType(); + if (type == null) + { + var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour); + type = m_MonoBehaviour.ToType(nodes); + } + var str = JsonConvert.SerializeObject(type, Formatting.Indented); File.WriteAllText(exportFullPath, str); return true; } @@ -358,6 +365,11 @@ namespace AssetStudioGUI if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath)) return false; var str = item.Asset.Dump(); + if (str == null && item.Asset is MonoBehaviour m_MonoBehaviour) + { + var nodes = Studio.MonoBehaviourToTypeTreeNodes(m_MonoBehaviour); + str = m_MonoBehaviour.Dump(nodes); + } if (str != null) { File.WriteAllText(exportFullPath, str); diff --git a/AssetStudioGUI/Studio.cs b/AssetStudioGUI/Studio.cs index ae5706c..9dbffad 100644 --- a/AssetStudioGUI/Studio.cs +++ b/AssetStudioGUI/Studio.cs @@ -615,7 +615,7 @@ namespace AssetStudioGUI } } - public static string DeserializeMonoBehaviour(MonoBehaviour m_MonoBehaviour) + public static List MonoBehaviourToTypeTreeNodes(MonoBehaviour m_MonoBehaviour) { if (!assemblyLoader.Loaded) { @@ -630,14 +630,7 @@ namespace AssetStudioGUI assemblyLoader.Loaded = true; } } - var nodes = m_MonoBehaviour.ConvertToTypeTreeNode(assemblyLoader); - if (nodes != null) - { - var sb = new StringBuilder(); - TypeTreeHelper.ReadTypeString(sb, nodes, m_MonoBehaviour.reader); - return sb.ToString(); - } - return null; + return m_MonoBehaviour.ConvertToTypeTreeNodes(assemblyLoader); } } } diff --git a/AssetStudioGUI/packages.config b/AssetStudioGUI/packages.config index ec75cf5..91b191f 100644 --- a/AssetStudioGUI/packages.config +++ b/AssetStudioGUI/packages.config @@ -1,5 +1,6 @@  + \ No newline at end of file diff --git a/AssetStudioUtility/MonoBehaviourConverter.cs b/AssetStudioUtility/MonoBehaviourConverter.cs index 34b9fdf..eb0b745 100644 --- a/AssetStudioUtility/MonoBehaviourConverter.cs +++ b/AssetStudioUtility/MonoBehaviourConverter.cs @@ -4,7 +4,7 @@ namespace AssetStudio { public static class MonoBehaviourConverter { - public static List ConvertToTypeTreeNode(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader) + public static List ConvertToTypeTreeNodes(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader) { var nodes = new List(); var helper = new SerializedTypeHelper(m_MonoBehaviour.version); @@ -15,7 +15,7 @@ namespace AssetStudio if (typeDef != null) { var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1); - nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNode()); + nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes()); } } return nodes; diff --git a/AssetStudioUtility/TypeDefinitionConverter.cs b/AssetStudioUtility/TypeDefinitionConverter.cs index 4041a7d..d796f0e 100644 --- a/AssetStudioUtility/TypeDefinitionConverter.cs +++ b/AssetStudioUtility/TypeDefinitionConverter.cs @@ -22,7 +22,7 @@ namespace AssetStudio Indent = indent; } - public List ConvertToTypeTreeNode() + public List ConvertToTypeTreeNodes() { var nodes = new List(); @@ -302,7 +302,7 @@ namespace AssetStudio 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()); + nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes()); } return nodes;