public void AfterDeserialize()
 {
     // resolve references
     foreach (var cmp in components)
     {
         System.Type type = cmp.GetType();
         foreach (var pair in refs)
         {
             string fieldName = pair.Key.Substring(1);
             System.Reflection.FieldInfo fi = type.GetField(fieldName);
             if (fi == null)
             {
                 continue;
             }
             SerializedComponent resolvedComponent = ResolveComponentFromId(pair.Value);
             if (resolvedComponent != null)
             {
                 if (fi.FieldType != resolvedComponent.GetType())
                 {
                     Debug.LogWarning("deserialize type mismatch", cmp);
                 }
                 else
                 {
                     fi.SetValue(cmp, resolvedComponent);
                 }
             }
             else
             {
                 // TODO resolve gameobject references
                 // this is probably not needed when there are component references
             }
         }
         cmp.AfterDeserialize();
     }
 }
 public static T ResolveComponentFromId <T>(int id) where T : SerializedComponent
 {
     if (serializedComponents.ContainsKey(id))
     {
         SerializedComponent sc = serializedComponents[id];
         if (sc.GetType() != typeof(T))
         {
             Debug.LogWarning("resolvecomponent type mismatch: " + sc.GetType().ToString() + " " + typeof(T).ToString());
             return(default(T));
         }
         return((T)sc);
     }
     //    if( idMap.ContainsKey( id ) && serializedComponents.ContainsKey( idMap[ id ] ) )
     //      return serializedComponents[ idMap[ id ] ];
     Debug.LogWarning("failed to resolve component: " + id);
     return(null);
 }
        public static GameObject Deserialize(JsonData data)
        {
            string  resourceName = data["resource"].GetString();
            Vector3 position     = JsonUtil.ReadVector(data["position"]);
            Vector3 rotation     = Vector3.zero;

            if (data.Keys.Contains("rotation"))
            {
                rotation = JsonUtil.ReadVector(data["rotation"]);
            }

            GameObject go;

            if (Application.isEditor && !Application.isPlaying)
            {
                go = GameObject.Instantiate(Resources.Load <GameObject>("serialized/" + resourceName), position, Quaternion.Euler(rotation), null);
            }
            else
            {
                go = Global.instance.Spawn(resourceName, position, Quaternion.Euler(rotation), null, false, false);
            }
            if (go != null)
            {
                SerializedObject so = go.GetComponent <SerializedObject>();
                if (so == null)
                {
                    // This can happen after name changes or removing the SerializedObject component from a prefab.
                    Destroy(go);
                    return(null);
                }

                serializedObjects.Remove(so.id);
                so.id = (int)data["id"].GetNatural();
                serializedObjects.Add(so.id, so);

                if (data.Keys.Contains("components"))
                {
                    JsonData cmps = data["components"];
                    foreach (JsonData cmpData in cmps)
                    {
                        string      t          = cmpData["type"].ToString();
                        System.Type stringType = System.Type.GetType(t);
                        if (stringType == null)
                        {
                            continue;
                        }
                        Component component = go.GetComponentInChildren(stringType);
                        if (component == null)
                        {
                            Debug.LogWarning("Cannot find component of type: " + stringType, go);
                            continue;
                        }

                        System.Type compType = component.GetType();
                        if (!typeof(SerializedComponent).IsAssignableFrom(compType))
                        {
                            // if component types change (different parent class, or field type changes)
                            Debug.Log("component is not serializedcomponent: " + stringType, go);
                            continue;
                        }
                        SerializedComponent comp = (SerializedComponent)component;
                        if (comp == null)
                        {
                            continue;
                        }

                        // this is hacky, but prevents the waste of many ids.
                        serializedComponents.Remove(comp.id);
                        comp.id = (int)cmpData["id"].GetNatural();
                        serializedComponents.Add(comp.id, comp);

                        foreach (var key in cmpData.Keys)
                        {
                            if (key == "type" || key == "id" || key == "position" || key == "rotation")
                            {
                                continue;
                            }
                            if (key.StartsWith("@"))
                            {
                                if (cmpData[key].IsArray)
                                {
                                    Debug.LogWarning("Cannot deserialize an array of references. Not implemented.");
                                }
                                else
                                {
                                    int refId = (int)cmpData[key].GetNatural();
                                    if (so.refs.ContainsKey(key))
                                    {
                                        Debug.LogWarning("Duplicate serialized field: " + key + " (Click for object)", go);
                                    }
                                    else
                                    {
                                        so.refs.Add(key, refId);
                                    }
                                }
                            }
                            else
                            {
                                System.Reflection.FieldInfo fi = compType.GetField(key);
                                if (fi == null)
                                {
                                    continue;
                                }
                                if (cmpData[key] == null)
                                {
                                    continue;
                                }
                                if (cmpData[key].IsNatural)
                                {
                                    fi.SetValue(comp, (int)cmpData[key].GetNatural());
                                }
                                if (cmpData[key].IsReal)
                                {
                                    fi.SetValue(comp, (float)cmpData[key].GetReal());
                                }
                                if (cmpData[key].IsBoolean)
                                {
                                    fi.SetValue(comp, cmpData[key].GetBoolean());
                                }
                                if (cmpData[key].IsString)
                                {
                                    fi.SetValue(comp, cmpData[key].GetString());
                                }
                                if (cmpData[key].IsArray && cmpData[key].Count > 0)
                                {
                                    if (cmpData[key][0] == null)
                                    {
                                        continue;
                                    }
                                    object   obj      = fi.GetValue(comp);
                                    JsonType jsonType = cmpData[key][0].GetJsonType();
                                    switch (jsonType)
                                    {
                                    case JsonType.String:
                                        foreach (JsonData element in cmpData[key])
                                        {
                                            (obj as List <string>).Add(element.GetString());
                                        }
                                        break;

                                    case JsonType.Natural:
                                        foreach (JsonData element in cmpData[key])
                                        {
                                            (obj as List <int>).Add((int)element.GetNatural());
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                return(go);
            }
            return(null);
        }
        public void Serialize(JsonWriter writer)
        {
            writer.WritePropertyName("id");
            writer.Write(id);
            writer.WritePropertyName("resource");
            writer.Write(gameObject.name);
            writer.WritePropertyName("position");
            JsonUtil.WriteVector(writer, transform.position);
            if (transform.rotation != Quaternion.identity)
            {
                writer.WritePropertyName("rotation");
                JsonUtil.WriteVector(writer, transform.rotation.eulerAngles);
            }

            // NOTE only one SerializedComponent of a given type per GameObject is supported.
            // TODO check for multiple components of a given type and print warning

            GetComponentsInChildren <SerializedComponent>(components);
            if (components.Count > 0)
            {
                writer.WritePropertyName("components");
                writer.WriteArrayStart();
                foreach (var cmp in components)
                {
                    System.Type cmpType = cmp.GetType();
                    writer.WriteObjectStart();
                    writer.WritePropertyName("type");
                    writer.Write(cmpType.Name);
                    writer.WritePropertyName("id");
                    writer.Write(cmp.id);

                    System.Reflection.FieldInfo[] fis = cmpType.GetFields();
                    foreach (var fi in fis)
                    {
                        if (fi.IsDefined(typeof(SerializeAttribute), true))
                        {
                            object value = fi.GetValue(cmp);
                            if (value == null)
                            {
                                continue;
                            }
                            if (fi.FieldType.IsSubclassOf(typeof(SerializedComponent)))
                            {
                                SerializedComponent sc = (SerializedComponent)value;
                                if (sc == null)
                                {
                                    continue;
                                }
                                SerializedObject so = sc.GetComponentInParent <SerializedObject>();
                                if (so != null)
                                {
                                    writer.WritePropertyName("@" + fi.Name);
                                    writer.Write(sc.id);
                                }
                            }
                            else
                            if (value is IList)
                            {
                                IList list = value as IList;
                                if (list.Count > 0)
                                {
                                    bool        isListOfReferences = false;
                                    string      propName           = fi.Name;
                                    System.Type type        = value.GetType();
                                    System.Type elementType = null;

                                    if (fi.FieldType.IsGenericType)
                                    {
                                        elementType = type.GetGenericArguments()[0];
                                        if (elementType.IsSubclassOf(typeof(SerializedComponent)))
                                        {
                                            // collection of serialized components
                                            propName           = "@" + propName;
                                            isListOfReferences = true;
                                        }
                                    }
                                    if (fi.FieldType.IsArray)
                                    {
                                        elementType = list.GetType().GetElementType();
                                    }

                                    if (isListOfReferences)
                                    {
                                        Debug.LogError("Serializing an array of references is not implemented.");

                                        /*writer.WritePropertyName( propName );
                                         * writer.WriteArrayStart();
                                         * foreach( SerializedComponent obj in value as IEnumerable )
                                         * writer.Write( obj.GetInstanceID() );
                                         * writer.WriteArrayEnd();*/
                                    }
                                    else
                                    {
                                        writer.WritePropertyName(propName);
                                        writer.WriteArrayStart();
                                        foreach (var obj in list)
                                        {
                                            JsonUtil.SerializeValue(writer, elementType, obj);
                                        }
                                        writer.WriteArrayEnd();
                                    }
                                }
                            }
                            else
                            {
                                writer.WritePropertyName(fi.Name);
                                JsonUtil.SerializeValue(writer, fi.FieldType, value);
                            }
                        }
                    }
                    writer.WriteObjectEnd();
                }
                writer.WriteArrayEnd();
            }
        }