private static void CheckForReset(ISerializedObject obj) { SerializedObjectSnapshot originalData = null; if (_deserializedObjects.TryGetValue(obj, out originalData)) { if (originalData.IsEmpty) { return; } if (obj.SerializedStateKeys == null || obj.SerializedStateKeys.Count == 0 || obj.SerializedStateValues == null || obj.SerializedStateValues.Count == 0) { // Note: we do not clear out the keys; if we did, then we would not actually deserialize "null" onto them // Note: we call SaveState() so we can fetch the keys we need to deserialize obj.SaveState(); obj.SerializedStateValues.Clear(); for (int i = 0; i < obj.SerializedStateKeys.Count; ++i) { obj.SerializedStateValues.Add(null); } obj.RestoreState(); fiRuntimeReflectionUtility.InvokeMethod(obj.GetType(), "Reset", obj, null); obj.SaveState(); _deserializedObjects[obj] = new SerializedObjectSnapshot(obj); } } }
/// <summary> /// Used internally to notify us that an object has been serialized. We update some metadata stored on the object /// upon each serialization so we can detect when prefab modifications are applied. /// </summary> public static void MarkSerialized(ISerializedObject obj) { if (fiUtility.IsEditor) { _deserializedObjects[obj] = new SerializedObjectSnapshot(obj); } }
public static void RunDeserializations() { // We never run deserializations outside of the editor if (fiUtility.IsEditor == false) { return; } // Serialization is disabled if (DisableAutomaticSerialization) { return; } // Do not deserialize in the middle of a level load that might be running on another thread // (asynchronous) which can lead to a race condition causing the following assert: // ms_IDToPointer->find (obj->GetInstanceID ()) == ms_IDToPointer->end () // // Very strange that the load is happening on another thread since RunDeserializations only // gets invoked from EditorApplication.update and EditorWindow.OnGUI. // // This method will get called again at a later point so there is no worries that we haven't // finished doing the deserializations. if (fiLateBindings.EditorApplication.isPlaying && Application.isLoadingLevel) { return; } while (_toDeserialize.Count > 0) { ISerializedObject item = _toDeserialize.Dequeue(); // If we're in play-mode, then we don't want to deserialize anything as that can wipe // user-data. We cannot do this in SubmitDeserializeRequest because // EditorApplication.isPlaying can only be called from the main thread. However, // we *do* want to restore prefabs and general disk-based resources which will not have // Awake called. if (fiLateBindings.EditorApplication.isPlaying) { // note: We do a null check against unityObj to also check for destroyed objects, // which we don't need to bother restoring. Doing a null check against an // ISerializedObject instance will *not* call the correct == method, so // we need to be explicit about calling it against UnityObject. var unityObj = item as UnityObject; if (unityObj == null || fiLateBindings.PrefabUtility.IsPrefab(unityObj) == false) { continue; } } CheckForReset(item); item.RestoreState(); _deserializedObjects[item] = new SerializedObjectSnapshot(item); } }
private static void DoSerialize(ISerializedObject obj) { SerializedObjectSnapshot originalData = null; _deserializedObjects.TryGetValue(obj, out originalData); var storedData = new SerializedObjectSnapshot(obj); if (originalData == null || originalData != storedData) { // Unity has gone behind our backs and changed the data stored inside of the serialized // object. This is likely due to prefab changes. We will simply deserialize the new data // so that we don't overwrite it. storedData.RestoreSnapshot(obj); _deserializedObjects[obj] = new SerializedObjectSnapshot(obj); } else { // Otherwise, serialize the existing object structure and update our deserialized state. obj.SaveState(); _deserializedObjects[obj] = new SerializedObjectSnapshot(obj); } }