Support exporting MonoBehaviour to json. Close #477

This commit is contained in:
Perfare 2020-08-14 15:45:48 +08:00
parent 7aa35b5b8c
commit ca60dd9834
11 changed files with 74 additions and 130 deletions

View File

@ -148,7 +148,6 @@
<Compile Include="StreamFile.cs" /> <Compile Include="StreamFile.cs" />
<Compile Include="TypeTreeHelper.cs" /> <Compile Include="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" /> <Compile Include="TypeTreeNode.cs" />
<Compile Include="UType.cs" />
<Compile Include="WebFile.cs" /> <Compile Include="WebFile.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -1,5 +1,5 @@
using System; using System.Collections.Generic;
using System.Collections.Generic; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -52,6 +52,35 @@ namespace AssetStudio
return null; return null;
} }
public string Dump(List<TypeTreeNode> 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<TypeTreeNode> m_Nodes)
{
if (m_Nodes != null)
{
return TypeTreeHelper.ReadType(m_Nodes, reader);
}
return null;
}
public byte[] GetRawData() public byte[] GetRawData()
{ {
reader.Reset(); reader.Reset();

View File

@ -1,4 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO; using System.IO;
using System.Text; using System.Text;
@ -155,15 +156,21 @@ namespace AssetStudio
reader.AlignStream(); reader.AlignStream();
} }
public static UType ReadUType(List<TypeTreeNode> members, BinaryReader reader) public static OrderedDictionary ReadType(List<TypeTreeNode> members, ObjectReader reader)
{ {
var obj = new UType(); reader.Reset();
var obj = new OrderedDictionary();
for (int i = 1; i < members.Count; i++) for (int i = 1; i < members.Count; i++)
{ {
var member = members[i]; var member = members[i];
var varNameStr = member.m_Name; var varNameStr = member.m_Name;
obj[varNameStr] = ReadValue(members, reader, ref i); 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; return obj;
} }
@ -270,7 +277,7 @@ namespace AssetStudio
{ {
var @class = GetMembers(members, i); var @class = GetMembers(members, i);
i += @class.Count - 1; i += @class.Count - 1;
var obj = new UType(); var obj = new OrderedDictionary();
for (int j = 1; j < @class.Count; j++) for (int j = 1; j < @class.Count; j++)
{ {
var classmember = @class[j]; var classmember = @class[j];

View File

@ -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<string, object>
{
private List<string> keys;
private IDictionary<string, object> values;
public UType()
{
keys = new List<string>();
values = new Dictionary<string, object>();
}
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<string> Keys => keys;
public ICollection<object> 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<string, object> item)
{
keys.Add(item.Key);
values.Add(item);
}
public void Clear()
{
keys.Clear();
values.Clear();
}
public bool Contains(KeyValuePair<string, object> item)
{
return values.Contains(item);
}
public bool ContainsKey(string key)
{
return values.ContainsKey(key);
}
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
values.CopyTo(array, arrayIndex);
}
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
{
return values.GetEnumerator();
}
public bool Remove(string key)
{
keys.Remove(key);
return values.Remove(key);
}
public bool Remove(KeyValuePair<string, object> 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();
}
}
}

View File

@ -39,6 +39,9 @@
<Prefer32Bit>false</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> <Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath> <HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
</Reference> </Reference>

View File

@ -1,4 +1,5 @@
using AssetStudio; using AssetStudio;
using Newtonsoft.Json;
using OpenTK; using OpenTK;
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using System; using System;
@ -930,7 +931,14 @@ namespace AssetStudioGUI
private void PreviewMonoBehaviour(MonoBehaviour m_MonoBehaviour) 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) private void PreviewFont(Font m_Font)

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using AssetStudio; using AssetStudio;
using Newtonsoft.Json;
using TGASharpLib; using TGASharpLib;
namespace AssetStudioGUI namespace AssetStudioGUI
@ -113,10 +114,16 @@ namespace AssetStudioGUI
public static bool ExportMonoBehaviour(AssetItem item, string exportPath) 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; return false;
var m_MonoBehaviour = (MonoBehaviour)item.Asset; 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); File.WriteAllText(exportFullPath, str);
return true; return true;
} }
@ -358,6 +365,11 @@ namespace AssetStudioGUI
if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath)) if (!TryExportFile(exportPath, item, ".txt", out var exportFullPath))
return false; return false;
var str = item.Asset.Dump(); 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) if (str != null)
{ {
File.WriteAllText(exportFullPath, str); File.WriteAllText(exportFullPath, str);

View File

@ -615,7 +615,7 @@ namespace AssetStudioGUI
} }
} }
public static string DeserializeMonoBehaviour(MonoBehaviour m_MonoBehaviour) public static List<TypeTreeNode> MonoBehaviourToTypeTreeNodes(MonoBehaviour m_MonoBehaviour)
{ {
if (!assemblyLoader.Loaded) if (!assemblyLoader.Loaded)
{ {
@ -630,14 +630,7 @@ namespace AssetStudioGUI
assemblyLoader.Loaded = true; assemblyLoader.Loaded = true;
} }
} }
var nodes = m_MonoBehaviour.ConvertToTypeTreeNode(assemblyLoader); return m_MonoBehaviour.ConvertToTypeTreeNodes(assemblyLoader);
if (nodes != null)
{
var sb = new StringBuilder();
TypeTreeHelper.ReadTypeString(sb, nodes, m_MonoBehaviour.reader);
return sb.ToString();
}
return null;
} }
} }
} }

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="OpenTK" version="3.1.0" targetFramework="net472" /> <package id="OpenTK" version="3.1.0" targetFramework="net472" />
<package id="OpenTK.GLControl" version="3.1.0" targetFramework="net472" /> <package id="OpenTK.GLControl" version="3.1.0" targetFramework="net472" />
</packages> </packages>

View File

@ -4,7 +4,7 @@ namespace AssetStudio
{ {
public static class MonoBehaviourConverter public static class MonoBehaviourConverter
{ {
public static List<TypeTreeNode> ConvertToTypeTreeNode(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader) public static List<TypeTreeNode> ConvertToTypeTreeNodes(this MonoBehaviour m_MonoBehaviour, AssemblyLoader assemblyLoader)
{ {
var nodes = new List<TypeTreeNode>(); var nodes = new List<TypeTreeNode>();
var helper = new SerializedTypeHelper(m_MonoBehaviour.version); var helper = new SerializedTypeHelper(m_MonoBehaviour.version);
@ -15,7 +15,7 @@ namespace AssetStudio
if (typeDef != null) if (typeDef != null)
{ {
var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1); var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, helper, 1);
nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNode()); nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());
} }
} }
return nodes; return nodes;

View File

@ -22,7 +22,7 @@ namespace AssetStudio
Indent = indent; Indent = indent;
} }
public List<TypeTreeNode> ConvertToTypeTreeNode() public List<TypeTreeNode> ConvertToTypeTreeNodes()
{ {
var nodes = new List<TypeTreeNode>(); var nodes = new List<TypeTreeNode>();
@ -302,7 +302,7 @@ namespace AssetStudio
nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align)); nodes.Add(new TypeTreeNode(typeRef.Name, name, indent, align));
var typeDef = typeRef.Resolve(); var typeDef = typeRef.Resolve();
var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, Helper, indent + 1); var typeDefinitionConverter = new TypeDefinitionConverter(typeDef, Helper, indent + 1);
nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNode()); nodes.AddRange(typeDefinitionConverter.ConvertToTypeTreeNodes());
} }
return nodes; return nodes;