Exemple #1
0
        /// <summary>
        /// Helper function that just ignores a few FI internal types for serialization since the
        /// backup solution serializes all inspected properties, not just those that are serialized
        /// </summary>
        private static bool ShouldIgnoreForPersist(InspectedProperty property) {
            string name = property.Name;

            return
                name.Contains("ISerializedObject.") ||
                name == "_objectReferences" ||
                name == "_serializedStateKeys" ||
                name == "_serializedStateValues" ||
                name == "_restored";
        }
Exemple #2
0
        /// <summary>
        /// Reverts the given property on the instance to the prefab value.
        /// </summary>
        /// <param name="instance">The prefab instance to revert the value on.</param>
        /// <param name="property">The property to revert.</param>
        public static void RevertValue(object instance, InspectedProperty property) {
            // We only want top-level components
            if (instance is MonoBehaviour == false) {
                return;
            }

            // Not a prefab
            var prefabGameObject = (GameObject)PrefabUtility.GetPrefabParent(((MonoBehaviour)instance).gameObject);
            if (prefabGameObject == null) {
                return;
            }

            // Get all of the property modifications on the object. If there are no property
            // modifications, then there is nothing to revert.
            PropertyModification[] mods = PrefabUtility.GetPropertyModifications((UnityObject)instance);
            if (mods == null) {
                return;
            }

            ISerializedObject serializedInstance = (ISerializedObject)instance;

            bool removed = false;

            for (int i = 0; i < mods.Length; ++i) {
                PropertyModification mod = mods[i];

                // A property modification can take one of two forms. It can either be modifying a
                // Unity serialized value or a Full Inspector serialized value.

                // Check to see if it's a Full Inspector serialized value. If it is, then we lookup
                // the key that the modification is associated with and, if we find said key, and
                // that the key is equal to the property we are checking for, then we return true.
                string serializedPropertyName;
                if (TryExtractPropertyName(serializedInstance, mod, out serializedPropertyName) &&
                    serializedPropertyName == property.Name) {

                    removed = true;
                }

                // Check to see if it is a Unity serialized value. We have to do a dotted comparison
                // because the propertyPath may be associated with, ie, an array, which in that case
                // the path is something like "values.Array._items[0]" while property.Name is just
                // "values".
                if (ContainsPropertyName(mod.propertyPath, property.Name)) {

                    removed = true;
                }

                if (removed) {
                    ArrayUtility.RemoveAt(ref mods, i);
                    PrefabUtility.SetPropertyModifications((UnityObject)instance, mods);
                    break;
                }
            }
        }
 private void EditProperty(ref Rect region, object element, InspectedProperty property)
 {
     if (!ReflectedPropertyEditor.ShowProperty(property))
     {
         return;
     }
     bool flag = ReflectedPropertyEditor.HasPrefabDiff(element, property);
     if (flag)
     {
         UnityInternalReflection.SetBoldDefaultFont(true);
     }
     TooltipAttribute attribute = property.MemberInfo.GetAttribute<TooltipAttribute>();
     GUIContent label = new GUIContent(DisplayNameMapper.Map(property.Name), (attribute != null) ? attribute.Tooltip : "");
     PropertyEditorChain propertyEditorChain = PropertyEditor.Get(property.StorageType, property.MemberInfo);
     IPropertyEditor firstEditor = propertyEditorChain.FirstEditor;
     object obj = property.Read(element);
     float elementHeight = firstEditor.GetElementHeight(label, obj);
     Rect rect = new Rect(region);
     rect.height = elementHeight;
     float num = 0f;
     ReflectedPropertyEditor.StateObject stateObject = ObjectMetadata<ReflectedPropertyEditor.StateObject>.Get(obj);
     if (elementHeight > 80f && ReflectedPropertyEditor.CanShowFoldout(property.StorageType))
     {
         GUIContent gUIContent = stateObject.Foldout ? GUIContent.none : firstEditor.GetFoldoutHeader(label, obj);
         Rect rect2 = rect;
         rect2.height = EditorStyles.foldout.CalcHeight(gUIContent, 100f);
         rect2.width = EditorStyles.foldout.CalcSize(gUIContent).x;
         stateObject.Foldout = EditorGUI.Foldout(rect2, stateObject.Foldout, gUIContent);
         num = EditorStyles.foldout.CalcHeight(gUIContent, 100f);
     }
     if (stateObject.Foldout)
     {
         object value = firstEditor.Edit(rect, label, obj);
         property.Write(element, value);
         num = elementHeight;
     }
     region.y = region.y + num;
     region.y = region.y + 2f;
     if (flag)
     {
         UnityInternalReflection.SetBoldDefaultFont(false);
     }
 }
 private static bool ShowProperty(InspectedProperty property)
 {
     return property.MemberInfo.GetAttribute<HideInInspector>() == null && (property.MemberInfo.GetAttribute<ShowInInspectorAttribute>() != null || (FullInspectorSettings.InspectorAutomaticallyShowPublicProperties && property.IsPublic));
 }
 private static bool HasPrefabDiff(object instance, InspectedProperty property)
 {
     if (!(instance is MonoBehaviour))
     {
         return false;
     }
     GameObject gameObject = (GameObject)PrefabUtility.GetPrefabParent(((MonoBehaviour)instance).gameObject);
     if (gameObject == null)
     {
         return false;
     }
     Component component = gameObject.GetComponent(instance.GetType());
     if (component == null)
     {
         return true;
     }
     PropertyModification[] propertyModifications = PrefabUtility.GetPropertyModifications((UnityEngine.Object)instance);
     if (propertyModifications == null)
     {
         return false;
     }
     ISerializedObject obj = (ISerializedObject)instance;
     PropertyModification[] array = propertyModifications;
     int i = 0;
     while (i < array.Length)
     {
         PropertyModification propertyModification = array[i];
         string a;
         bool result;
         if (ReflectedPropertyEditor.TryExtractPropertyName(obj, propertyModification, out a) && a == property.Name)
         {
             result = true;
         }
         else
         {
             if (!ReflectedPropertyEditor.ContainsPropertyName(propertyModification.propertyPath, property.Name))
             {
                 i++;
                 continue;
             }
             result = true;
         }
         return result;
     }
     return false;
 }
Exemple #6
0
        /// <summary>
        /// Returns true if the given property on the given object instance has a prefab override.
        /// </summary>
        /// <param name="instance">The object instance.</param>
        /// <param name="property">The property to check.</param>
        /// <returns>True if the property is prefab override, false otherwise.</returns>
        /// <remarks>
        /// Currently, this method only works for MonoBehavior targets.
        /// </remarks>
        public static bool HasPrefabDiff(object instance, InspectedProperty property) {
            // For prefab differences, we rely upon the internal Unity mechanisms for identifying
            // when an object has a prefab diff. We are able to do this because we only support
            // top-level prefab differences.
            //
            // One of the current issues with this mechanism is when an array is serialized by
            // Unity, and only part of the array tracks the prefab, then the inspector will show the
            // entire array in bold (when only the one part should be).

            // We only want top-level components
            if (instance is MonoBehaviour == false) {
                return false;
            }

            // If there is no prefab, then we don't show anything in bold.
            var prefabGameObject = (GameObject)PrefabUtility.GetPrefabParent(((MonoBehaviour)instance).gameObject);
            if (prefabGameObject == null) {
                return false;
            }

            // If the prefab doesn't have this component, then the entire component should be in
            // bold.
            var prefab = prefabGameObject.GetComponent(instance.GetType());
            if (prefab == null) {
                return true;
            }

            // Get all of the property modifications on the object. If there are no property
            // modifications, then nothing should be in bold.
            PropertyModification[] mods = PrefabUtility.GetPropertyModifications((UnityObject)instance);
            if (mods == null) {
                return false;
            }

            ISerializedObject serializedInstance = (ISerializedObject)instance;

            foreach (PropertyModification mod in mods) {
                // A property modification can take one of two forms. It can either be modifying a
                // Unity serialized value or a Full Inspector serialized value.

                // Check to see if it's a Full Inspector serialized value. If it is, then we lookup
                // the key that the modification is associated with and, if we find said key, and
                // that the key is equal to the property we are checking for, then we return true.
                string serializedPropertyName;
                if (TryExtractPropertyName(serializedInstance, mod, out serializedPropertyName) &&
                    serializedPropertyName == property.Name) {
                    return true;
                }

                // Check to see if it is a Unity serialized value. We have to do a dotted comparison
                // because the propertyPath may be associated with, ie, an array, which in that case
                // the path is something like "values.Array._items[0]" while property.Name is just
                // "values".
                if (ContainsPropertyName(mod.propertyPath, property.Name)) {
                    return true;
                }
            }

            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;
            }
        }
        private static void RevertPrefabContextMenu(Rect region, object context, InspectedProperty property)
        {
            if (Event.current.type == EventType.ContextClick &&
                region.Contains(Event.current.mousePosition) &&

                // This can be a relatively heavy function call, so we check it
                // last. If the rect bounds check ends up consuming lots of time,
                // then HasPrefabDiff has a small fast-path section that can
                // short-circuit the bounds check.
                fiPrefabTools.HasPrefabDiff(context, property)) {
                Event.current.Use();

                var content = new GUIContent("Revert " + property.DisplayName + " to Prefab Value");

                GenericMenu menu = new GenericMenu();
                menu.AddItem(content, /*on:*/false, () => {
                    fiPrefabTools.RevertValue(context, property);
                });
                menu.ShowAsContext();
            }
        }
        public static float EditPropertyHeightDirect(InspectedProperty property, object propertyValue, fiGraphMetadataChild metadataChild)
        {
            fiGraphMetadata metadata = metadataChild.Metadata;

            var editor = PropertyEditor.Get(property.StorageType, property.MemberInfo).FirstEditor;

            GUIContent propertyLabel = new GUIContent(property.DisplayName);

            // Either the foldout is active or we are not displaying a foldout.
            // Either way, we want to report the full height of the property.
            return editor.GetElementHeight(propertyLabel, propertyValue, metadata.Enter("EditProperty", metadata.Context));
        }
 public static float EditPropertyHeight(object container, InspectedProperty property, fiGraphMetadataChild metadata)
 {
     object propertyValue = property.Read(container);
     return EditPropertyHeightDirect(property, propertyValue, metadata);
 }
        /// <summary>
        /// Draws a GUI for editing the given property and returns the updated
        /// value. This does
        /// *not* write the updated value to a container.
        /// </summary>
        /// <param name="context">
        /// An optional context that the property value came from. If this is not
        /// given, then a prefab context menu will not be displayable.
        /// </param>
        public static object EditPropertyDirect(Rect region, InspectedProperty property, object propertyValue, fiGraphMetadataChild metadataChild, object context)
        {
            fiGraphMetadata metadata = metadataChild.Metadata;

            // Show a "revert to prefab" value context-menu if possible
            if (context != null) {
                RevertPrefabContextMenu(region, context, property);
            }

            // get the label / tooltip
            GUIContent label = new GUIContent(property.DisplayName,
                                              InspectorTooltipAttribute.GetTooltip(property.MemberInfo));

            var editorChain = PropertyEditor.Get(property.StorageType, property.MemberInfo);
            IPropertyEditor editor = editorChain.FirstEditor;

            EditorGUI.BeginDisabledGroup(property.CanWrite == false);
            propertyValue = editor.Edit(region, label, propertyValue, metadata.Enter("EditProperty", metadata.Context));
            EditorGUI.EndDisabledGroup();

            return propertyValue;
        }
 /// <summary>
 /// Draws a GUI for editing the given property and returns the updated
 /// value. This does
 /// *not* write the updated value to a container.
 /// </summary>
 public static object EditPropertyDirect(Rect region, InspectedProperty property, object propertyValue, fiGraphMetadataChild metadataChild)
 {
     return EditPropertyDirect(region, property, propertyValue, metadataChild, null);
 }
        /// <summary>
        /// A helper method that draws the inspector for a field/property at the given location.
        /// </summary>
        private void EditProperty(ref Rect region, object element, InspectedProperty property, fiGraphMetadata metadata) {
            bool hasPrefabDiff = fiPrefabTools.HasPrefabDiff(element, property);
            if (hasPrefabDiff) fiUnityInternalReflection.SetBoldDefaultFont(true);

            // edit the property
            {
                var childMetadata = metadata.Enter(property.Name);
                fiGraphMetadataCallbacks.PropertyMetadataCallback(childMetadata.Metadata, property);

                Rect propertyRect = region;
                float propertyHeight = fiEditorGUI.EditPropertyHeight(element, property, childMetadata);
                propertyRect.height = propertyHeight;

                fiEditorGUI.EditProperty(propertyRect, element, property, childMetadata);

                region.y += propertyHeight;
            }

            if (hasPrefabDiff) fiUnityInternalReflection.SetBoldDefaultFont(false);
        }
Exemple #14
0
 public bool Equals(InspectedProperty p)
 {
     return p != null && this.StorageType == p.StorageType && this.Name == p.Name;
 }