private static bool SaveStateForProperty(ISerializedObject obj, InspectedProperty property, BaseSerializer serializer, ISerializationOperator serializationOperator, out string serializedValue, ref bool success) { object currentValue = property.Read(obj); try { if (currentValue == null) { serializedValue = null; } else { serializedValue = serializer.Serialize(property.MemberInfo, currentValue, serializationOperator); } return(true); } catch (Exception e) { success = false; serializedValue = null; Debug.LogError("Exception caught when serializing property <" + property.Name + "> in <" + obj + "> with value " + currentValue + "\n" + e); return(false); } }
public static void EditProperty(Rect region, object container, InspectedProperty property, fiGraphMetadataChild metadata) { EditorGUI.BeginChangeCheck(); object propertyValue = property.Read(container); object updatedValue = EditPropertyDirect(region, property, propertyValue, metadata, container); if (EditorGUI.EndChangeCheck()) { property.Write(container, updatedValue); // Make sure we propagate the changes up the edit stack. For example, if this property // is on a struct on a struct, then the top-level struct will not get modified without // propagation of the change check. GUI.changed = true; } }
public bool Read(object obj, out object result) { if (byType != null) { result = obj; return(true); } // The property was potentially found on a different type. We need to // update it to associate with this type. It's very possible the // property will not even apply to context, in which case Write // becomes a no-op. InspectedProperty propertyToUse = byProperty; if (byProperty.MemberInfo.DeclaringType != obj.GetType()) { var childProp = InspectedType.Get(obj.GetType()).GetPropertyByName(byProperty.Name); if (childProp != null) { propertyToUse = childProp; } else { result = null; return(false); } } var read = propertyToUse.Read(obj); if (byListIndex >= 0) { result = ((IList)read)[byListIndex]; return(true); } if (byDictKey != null) { result = ((IDictionary)read)[byDictKey]; return(true); } result = read; return(true); }
private static bool TryToCopyValues(ISerializedObject newInstance) { if (string.IsNullOrEmpty(newInstance.SharedStateGuid)) { return(false); } ISerializedObject originalInstance = null; lock (_skipSerializationQueue) { if (!_skipSerializationQueue.TryGetValue(newInstance.SharedStateGuid, out originalInstance)) { return(false); } _skipSerializationQueue.Remove(newInstance.SharedStateGuid); } // After a prefab is instantiated Unity will call a full // serialize/deserialize cycle on the object. We don't need to copy // values if the object references are the same. if (ReferenceEquals(newInstance, originalInstance)) { return(true); } var inspectedType = InspectedType.Get(originalInstance.GetType()); for (int i = 0; i < originalInstance.SerializedStateKeys.Count; ++i) { InspectedProperty property = inspectedType.GetPropertyByName(originalInstance.SerializedStateKeys[i]) ?? inspectedType.GetPropertyByFormerlySerializedName(originalInstance.SerializedStateKeys[i]); property.Write(newInstance, property.Read(originalInstance)); } return(true); }
public static float EditPropertyHeight(object container, InspectedProperty property, fiGraphMetadataChild metadata) { object propertyValue = property.Read(container); return(EditPropertyHeightDirect(property, propertyValue, metadata)); }
public void Write(object context, object value) { if (byType != null) { if (value != s_RemoveObject) { value = InspectedType.Get((Type)value).CreateInstance(); } byType[byType.Length - 1].Write(context, value); return; } // The property was potentially found on a different type. We need to // update it to associate with this type. It's very possible the // property will not even apply to context, in which case Write // becomes a no-op. InspectedProperty propertyToUse = byProperty; if (byProperty.MemberInfo.DeclaringType != context.GetType()) { var childProp = InspectedType.Get(context.GetType()).GetPropertyByName(byProperty.Name); if (childProp != null) { propertyToUse = childProp; } else { return; } } if (byListIndex >= 0) { var read = propertyToUse.Read(context); var list = (IList)read; var elementType = InspectedType.Get(propertyToUse.StorageType).ElementType; if (value == s_RemoveObject) { fiListUtility.RemoveAt(ref list, elementType, byListIndex); } else { while (byListIndex >= list.Count) { fiListUtility.Add(ref list, elementType); } list[byListIndex] = value; } // Changing list will not update the actual array reference, so // we have to write back to the stored object. if (list is Array) { propertyToUse.Write(context, list); } return; } if (byDictKey != null) { var read = propertyToUse.Read(context); var dict = (IDictionary)read; // TODO: Have a separate Write/Remove command, since you might // want to set a dict field to null. if (value == s_RemoveObject) { dict.Remove(byDictKey); } else { dict[byDictKey] = value; } return; } if (value != s_RemoveObject) { propertyToUse.Write(context, value); } else { propertyToUse.Write(context, null); } }
public static Dictionary <ObjectDataPath[], object> Create(List <ObjectDataPath> toUs, object obj, HashSet <object> seenObjects) { /* * Debug.Log(string.Join(", ", toUs.Select(t => { * if (t.byProperty == null) return ""; * return t.byProperty.Name; * }).ToArray())); * Debug.Log("seenObjects.Count = " + seenObjects.Count); * Debug.Log("seenObjects.Contains " + obj + " = " + seenObjects.Contains(obj)); */ Dictionary <ObjectDataPath[], object> thisLevel = AllocateDict(); if (seenObjects.Add(obj) == false) { return(thisLevel); } // Write the type. thisLevel.Add(CreateNavigation(toUs, new ObjectDataPath(toUs.ToArray())), obj.GetType()); List <InspectedProperty> properties = InspectedType.Get(obj.GetType()).GetProperties(InspectedMemberFilters.InspectableMembers); for (int i = 0; i < properties.Count; ++i) { InspectedProperty property = properties[i]; object valueForProperty = property.Read(obj); if (IsPrimitiveValue(valueForProperty)) { thisLevel.Add(CreateNavigation(toUs, new ObjectDataPath(property)), valueForProperty); continue; } if (InspectedType.Get(property.StorageType).IsCollection) { if (valueForProperty is IList) { var listForProperty = (IList)valueForProperty; for (int j = 0; j < listForProperty.Count; ++j) { object listElement = listForProperty[j]; if (IsPrimitiveValue(listElement)) { thisLevel.Add(CreateNavigation(toUs, new ObjectDataPath(property, j)), listElement); continue; } var listChildValues = CreateWithPath(toUs, new ObjectDataPath(property, j), listElement, seenObjects); foreach (var entry in listChildValues) { thisLevel.Add(entry.Key, entry.Value); } } } else if (valueForProperty is IDictionary) { var dictForProperty = (IDictionary)valueForProperty; IDictionaryEnumerator enumerator = dictForProperty.GetEnumerator(); while (enumerator.MoveNext()) { object key = enumerator.Key; object value = enumerator.Value; if (value == null || value.GetType().IsPrimitive || value is string) { thisLevel.Add(CreateNavigation(toUs, new ObjectDataPath(property, key)), value); } else { toUs.Add(new ObjectDataPath(property, key)); var dictChildValues = Create(toUs, value, seenObjects); toUs.RemoveAt(toUs.Count - 1); foreach (var entry in dictChildValues) { thisLevel.Add(entry.Key, entry.Value); } } } } else { Debug.LogError("Please file a bug (with an example) requesting multiedit support for " + valueForProperty.GetType().CSharpName()); } continue; } // Navigate children. var childValues = CreateWithPath(toUs, new ObjectDataPath(property), valueForProperty, seenObjects); foreach (var entry in childValues) { thisLevel.Add(entry.Key, entry.Value); } } return(thisLevel); }
/// <summary> /// Serializes the current state of the given object. /// </summary> /// <typeparam name="TSerializer">The type of serializer to use for the serialization /// process.</typeparam> /// <param name="obj">The object that should be serialized.</param> /// <returns>True if serialization was entirely successful, false if something bad happened along the way.</returns> public static bool SaveState <TSerializer>(ISerializedObject obj) where TSerializer : BaseSerializer { bool success = true; // short-circuit for null serializer if (typeof(TSerializer) == typeof(NullSerializer)) { return(success); } var callbacks = obj as ISerializationCallbacks; if (callbacks != null) { callbacks.OnBeforeSerialize(); } // fetch the selected serializer var serializer = fiSingletons.Get <TSerializer>(); // setup the serialization operator var serializationOperator = fiSingletons.Get <ListSerializationOperator>(); serializationOperator.SerializedObjects = new List <UnityObject>(); // get the properties that we will be serializing var properties = InspectedType.Get(obj.GetType()).GetProperties(InspectedMemberFilters.FullInspectorSerializedProperties); var serializedKeys = new List <string>(); var serializedValues = new List <string>(); for (int i = 0; i < properties.Count; ++i) { InspectedProperty property = properties[i]; object currentValue = property.Read(obj); try { if (currentValue == null) { serializedKeys.Add(property.Name); serializedValues.Add(null); } else { var serializedState = serializer.Serialize(property.MemberInfo, currentValue, serializationOperator); serializedKeys.Add(property.Name); serializedValues.Add(serializedState); } } catch (Exception e) { success = false; Debug.LogError("Exception caught when serializing property <" + property.Name + "> in <" + obj + "> with value " + currentValue + "\n" + e); } } // Write the updated data out to the object. // Note that we only write data out to the object if our serialized state has // changed. Unity will blindly rewrite the data on disk which will cause some // source control systems to check-out the files. If we are just updating // the content to the same content, we do not want to cause an accidental // checkout. if (AreListsDifferent(obj.SerializedStateKeys, serializedKeys)) { obj.SerializedStateKeys = serializedKeys; } if (AreListsDifferent(obj.SerializedStateValues, serializedValues)) { obj.SerializedStateValues = serializedValues; } if (AreListsDifferent(obj.SerializedObjectReferences, serializationOperator.SerializedObjects)) { obj.SerializedObjectReferences = serializationOperator.SerializedObjects; } // Calling SetDirty seems cause prefab instances to have prefab differences after a script // reload, so we only call SetDirty on ScriptableObjects (it's only really necessary for those as well) if (obj is ScriptableObject) { fiLateBindings.EditorUtility.SetDirty((ScriptableObject)obj); } if (callbacks != null) { callbacks.OnAfterSerialize(); } fiEditorSerializationManager.MarkSerialized(obj); return(success); }