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="TypeTreeHelper.cs" />
<Compile Include="TypeTreeNode.cs" />
<Compile Include="UType.cs" />
<Compile Include="WebFile.cs" />
</ItemGroup>
<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.Text;
@ -52,6 +52,35 @@ namespace AssetStudio
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()
{
reader.Reset();

View File

@ -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<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++)
{
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];

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>
</PropertyGroup>
<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">
<HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath>
</Reference>

View File

@ -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)

View File

@ -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);

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)
{
@ -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);
}
}
}

View File

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

View File

@ -4,7 +4,7 @@ namespace AssetStudio
{
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 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;

View File

@ -22,7 +22,7 @@ namespace AssetStudio
Indent = indent;
}
public List<TypeTreeNode> ConvertToTypeTreeNode()
public List<TypeTreeNode> ConvertToTypeTreeNodes()
{
var nodes = new List<TypeTreeNode>();
@ -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;