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);
            }
        }
Example #2
0
        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;
            }
        }
Example #3
0
        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);
        }
Example #5
0
        public static float EditPropertyHeight(object container, InspectedProperty property, fiGraphMetadataChild metadata)
        {
            object propertyValue = property.Read(container);

            return(EditPropertyHeightDirect(property, propertyValue, metadata));
        }
Example #6
0
        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);
            }
        }
Example #7
0
        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);
        }
Example #8
0
        /// <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);
        }