A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Reflection;
5using UnityEditor.ShaderGraph.Serialization;
6using UnityEngine;
7
8namespace UnityEditor.Graphing
9{
10 static class SerializationHelper
11 {
12 [Serializable]
13 public struct TypeSerializationInfo
14 {
15 [SerializeField]
16 public string fullName;
17
18 public bool IsValid()
19 {
20 return !string.IsNullOrEmpty(fullName);
21 }
22 }
23
24 [Serializable]
25 public struct JSONSerializedElement
26 {
27 [SerializeField]
28 public TypeSerializationInfo typeInfo;
29
30 [SerializeField]
31 public string JSONnodeData;
32 }
33
34 public static JSONSerializedElement nullElement
35 {
36 get
37 {
38 return new JSONSerializedElement();
39 }
40 }
41
42 public static TypeSerializationInfo GetTypeSerializableAsString(Type type)
43 {
44 return new TypeSerializationInfo
45 {
46 fullName = type.FullName
47 };
48 }
49
50 static Type GetTypeFromSerializedString(TypeSerializationInfo typeInfo)
51 {
52 if (!typeInfo.IsValid())
53 return null;
54
55 var assemblies = AppDomain.CurrentDomain.GetAssemblies();
56 foreach (var assembly in assemblies)
57 {
58 var type = assembly.GetType(typeInfo.fullName);
59 if (type != null)
60 return type;
61 }
62
63 return null;
64 }
65
66 public static JSONSerializedElement Serialize<T>(T item)
67 {
68 if (item is JsonObject jsonObject)
69 return new JSONSerializedElement() { JSONnodeData = jsonObject.Serialize() };
70
71 if (item == null)
72 throw new ArgumentNullException("item", "Can not serialize null element");
73
74 //check if unknownnode type - if so, return saved metadata
75 //unknown node type will need onbeforeserialize to set guid and edges and all the things
76 var typeInfo = GetTypeSerializableAsString(item.GetType());
77 var data = JsonUtility.ToJson(item, true);
78
79 if (string.IsNullOrEmpty(data))
80 throw new ArgumentException(string.Format("Can not serialize {0}", item));
81
82
83 return new JSONSerializedElement
84 {
85 typeInfo = typeInfo,
86 JSONnodeData = data
87 };
88 }
89
90 static TypeSerializationInfo DoTypeRemap(TypeSerializationInfo info, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper)
91 {
92 TypeSerializationInfo foundInfo;
93 if (remapper.TryGetValue(info, out foundInfo))
94 return foundInfo;
95 return info;
96 }
97
98 public static T Deserialize<T>(JSONSerializedElement item, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper, params object[] constructorArgs) where T : class
99 {
100 T instance;
101 if (typeof(T) == typeof(JsonObject) || typeof(T).IsSubclassOf(typeof(JsonObject)))
102 {
103 try
104 {
105 var culture = CultureInfo.CurrentCulture;
106 var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
107 instance = Activator.CreateInstance(typeof(T), flags, null, constructorArgs, culture) as T;
108 }
109 catch (Exception e)
110 {
111 throw new Exception(string.Format("Could not construct instance of: {0}", typeof(T)), e);
112 }
113
114 MultiJson.Deserialize(instance as JsonObject, item.JSONnodeData);
115 return instance;
116 }
117
118 if (!item.typeInfo.IsValid() || string.IsNullOrEmpty(item.JSONnodeData))
119 throw new ArgumentException(string.Format("Can not deserialize {0}, it is invalid", item));
120
121 TypeSerializationInfo info = item.typeInfo;
122 info.fullName = info.fullName.Replace("UnityEngine.MaterialGraph", "UnityEditor.ShaderGraph");
123 info.fullName = info.fullName.Replace("UnityEngine.Graphing", "UnityEditor.Graphing");
124 if (remapper != null)
125 info = DoTypeRemap(info, remapper);
126
127 var type = GetTypeFromSerializedString(info);
128 //if type is null but T is an abstract material node, instead we create an unknowntype node
129 if (type == null)
130 {
131 throw new ArgumentException(string.Format("Can not deserialize ({0}), type is invalid", info.fullName));
132 }
133
134 try
135 {
136 var culture = CultureInfo.CurrentCulture;
137 var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
138 instance = Activator.CreateInstance(type, flags, null, constructorArgs, culture) as T;
139 }
140 catch (Exception e)
141 {
142 throw new Exception(string.Format("Could not construct instance of: {0}", type), e);
143 }
144
145 if (instance != null)
146 {
147 JsonUtility.FromJsonOverwrite(item.JSONnodeData, instance);
148 return instance;
149 }
150 Debug.Log("UhOh");
151 return null;
152 }
153
154 public static List<JSONSerializedElement> Serialize<T>(IEnumerable<T> list)
155 {
156 var result = new List<JSONSerializedElement>();
157 if (list == null)
158 return result;
159
160 foreach (var element in list)
161 {
162 try
163 {
164 result.Add(Serialize(element));
165 }
166 catch (Exception e)
167 {
168 Debug.LogException(e);
169 }
170 }
171 return result;
172 }
173
174 public static List<T> Deserialize<T>(IEnumerable<JSONSerializedElement> list, Dictionary<TypeSerializationInfo, TypeSerializationInfo> remapper, params object[] constructorArgs) where T : class
175 {
176 var result = new List<T>();
177 if (list == null)
178 return result;
179
180 foreach (var element in list)
181 {
182 try
183 {
184 result.Add(Deserialize<T>(element, remapper));
185 }
186 catch (Exception e)
187 {
188 Debug.LogException(e);
189 Debug.LogError(element.JSONnodeData);
190 }
191 }
192 return result;
193 }
194 }
195}