A PropertyMetadata describes a discovered property or field in a TypeMetadata.
コード例 #1
0
        /// <summary>
        /// Returns true if the property type itself is inspectable. This does not necessarily
        /// mean that the property should be displayed in the inspector -- just that the FI editing
        /// engine can handle it.
        /// </summary>
        private static bool IsPropertyTypeInspectable(InspectedProperty property)
        {
            // We never inspect delegates
            if (typeof(Delegate).IsAssignableFrom(property.StorageType))
            {
                return(false);
            }

            if (property.MemberInfo is FieldInfo)
            {
                // Don't inspect compiler generated fields (an example would be a backing field
                // for an automatically generated property).
                if (property.MemberInfo.IsDefined(typeof(CompilerGeneratedAttribute), /*inherit:*/ false))
                {
                    return(false);
                }
            }

            else if (property.MemberInfo is PropertyInfo)
            {
                var propertyInfo = (PropertyInfo)property.MemberInfo;

                // If we cannot read from the property, then there is no sense in displaying it --
                // we will have no value to display
                if (propertyInfo.CanRead == false)
                {
                    return(false);
                }

                // hack?: We only display r/w properties declared on Unity types
                // note: This may rely on the fact that we collect members locally per inheritance
                //       level (does DeclaringType change? I'm not sure).
                // note: We also check for UnityEditor since some users use FI in non-standard
                //       ways -- ie, potentially for types that are not available at runtime and
                //       hence may be in the UnityEditor namespace.
                var @namespace = propertyInfo.DeclaringType.Namespace;
                if (@namespace != null &&
                    (@namespace.StartsWith("UnityEngine") || @namespace.StartsWith("UnityEditor")))
                {
                    if (propertyInfo.CanWrite == false)
                    {
                        return(false);
                    }
                }

                // If the property is named "Item", it might be the this[int] indexer, which in that
                // case we don't serialize it We cannot just compare with "Item" because of explicit
                // interfaces, where the name of the property will be the full method name.
                if (propertyInfo.Name.EndsWith("Item"))
                {
                    ParameterInfo[] parameters = propertyInfo.GetIndexParameters();
                    if (parameters.Length > 0)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
コード例 #2
0
 public bool IsInterested(InspectedProperty property)
 {
     return
         (property.CanWrite &&
          InspectedType.IsSerializedByFullInspector(property) &&
          InspectedType.IsSerializedByUnity(property) == false);
 }
コード例 #3
0
        /// <summary>
        /// Returns true if the given property should be displayed in the inspector. This method
        /// assumes that the property type is inspectable.
        /// </summary>
        private static bool ShouldDisplayProperty(InspectedProperty property)
        {
            var memberInfo = property.MemberInfo;

            // note: we do opt-out before opt-in so that we can still serialize
            //       a field but not display it in the inspector (as the serialize
            //       annotations automatically cause a field to be displayed)
            if (memberInfo.IsDefined(typeof(HideInInspector), /*inherit:*/ true) ||
                memberInfo.IsDefined(typeof(NotSerializedAttribute), /*inherit:*/ true) ||
                fiInstalledSerializerManager.SerializationOptOutAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true)))
            {
                return(false);
            }

            if (memberInfo.IsDefined(typeof(ShowInInspectorAttribute), /*inherit:*/ true) ||
                (property.IsStatic == false && fiInstalledSerializerManager.SerializationOptInAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true))))
            {
                return(true);
            }

            if (property.MemberInfo is PropertyInfo && fiSettings.InspectorRequireShowInInspector)
            {
                return(false);
            }

            return
                (InspectedType.IsSerializedByFullInspector(property) ||
                 InspectedType.IsSerializedByUnity(property));
        }
コード例 #4
0
        /// <summary>
        /// Determines whether the specified object is equal to this one.
        /// </summary>
        public bool Equals(InspectedProperty p) {
            // If parameter is null return false:
            if ((object)p == null) {
                return false;
            }

            // Return true if the fields match:
            return (StorageType == p.StorageType) && (Name == p.Name);
        }
コード例 #5
0
        public override float GetElementHeight(GUIContent label, Facade <T> element, fiGraphMetadata metadata)
        {
            float height = 0;

            if (string.IsNullOrEmpty(label.text) == false || TypeOptions.Types.Length > 1)
            {
                height = LabelHeight;
            }

            var anim = metadata.GetMetadata <fiAnimationMetadata>();

            if (anim.IsAnimating)
            {
                return(height + anim.AnimationHeight);
            }

            if (element == null)
            {
                element = new Facade <T>();
            }


            if (element.InstanceType == null)
            {
                element.InstanceType = TypeOptions.Types[0];
            }

            InspectedType inspectedType = InspectedType.Get(element.InstanceType);

            var serializer        = (BaseSerializer)fiSingletons.Get(fiInstalledSerializerManager.DefaultMetadata.SerializerType);
            var deserializationOp = new ListSerializationOperator()
            {
                SerializedObjects = element.ObjectReferences
            };

            var properties = inspectedType.GetProperties(InspectedMemberFilters.InspectableMembers);

            for (int i = 0; i < properties.Count; ++i)
            {
                InspectedProperty property = properties[i];

                object propertyValue = DeserializeProperty(serializer, deserializationOp, property, element);

                height += fiEditorGUI.EditPropertyHeightDirect(property, propertyValue, metadata.Enter(property.Name));
                height += SplitterHeight;
            }

            return(height);
        }
コード例 #6
0
        /// <summary>
        /// Returns true if the given type can be serialized by Unity. This
        /// function is conservative and may not return true if the type can be
        /// serialized by unity. However, it will *not* return true if the type
        /// cannot be serialized by unity.
        /// </summary>
        public static bool IsSerializedByUnity(InspectedProperty property)
        {
            // Properties are *not* serialized by Unity
            if (property.MemberInfo is PropertyInfo)
            {
                return(false);
            }

            // statics are *not* serialized by Unity
            if (property.IsStatic)
            {
                return(false);
            }

            // readonly fields are *not* serialized by Unity
            FieldInfo fieldInfo = property.MemberInfo as FieldInfo;

            if (fieldInfo.IsInitOnly)
            {
                return(false);
            }

            // If the attribute is not public and doesn't have a [SerializeField]
            // attribute, then Unity will not serialize it, regardless of type.
            if (property.IsPublic == false &&
                property.MemberInfo.IsDefined(typeof(SerializeField), /*inherit:*/ true) == false)
            {
                return(false);
            }

            Type type = property.StorageType;

            return
                // Basic primitive types
                (IsSimpleTypeThatUnityCanSerialize(type) ||

                 // A non-generic UnityObject derived type
                 (typeof(UnityObject).IsAssignableFrom(type) && type.Resolve().IsGenericType == false) ||

                 // Array (but not a multidimensional one)
                 (type.IsArray && type.GetElementType().IsArray == false && IsSimpleTypeThatUnityCanSerialize(type.GetElementType())) ||

                 // Lists of already serializable types
                 (
                     type.Resolve().IsGenericType&&
                     type.GetGenericTypeDefinition() == typeof(List <>) &&
                     IsSimpleTypeThatUnityCanSerialize(type.GetGenericArguments()[0])
                 ));
        }
コード例 #7
0
        /// <summary>
        /// Determines whether the specified object is equal to this one.
        /// </summary>
        public override bool Equals(System.Object obj) {
            // If parameter is null return false.
            if (obj == null) {
                return false;
            }

            // If parameter cannot be cast to PropertyMetadata return false.
            InspectedProperty p = obj as InspectedProperty;
            if ((System.Object)p == null) {
                return false;
            }

            // Return true if the fields match:
            return (StorageType == p.StorageType) && (Name == p.Name);
        }
コード例 #8
0
        /// <summary>
        /// Returns true if the given property should be displayed in the
        /// inspector. This method assumes that the property type is inspectable.
        /// </summary>
        private static bool ShouldDisplayProperty(InspectedProperty property)
        {
            var memberInfo = property.MemberInfo;

            // If ShowInInspector is present, we will *always* display the
            // attribute.
            if (memberInfo.IsDefined(typeof(ShowInInspectorAttribute), /*inherit:*/ true))
            {
                return(true);
            }

            // note: we do opt-out serialization annotations before opt-in
            //       annotations so that we can still serialize a field but not
            //       display it in the inspector (as the serialize annotations
            //       automatically cause a field to be displayed)
            if (memberInfo.IsDefined(typeof(HideInInspector), /*inherit:*/ true) ||
                memberInfo.IsDefined(typeof(NotSerializedAttribute), /*inherit:*/ true) ||
                fiInstalledSerializerManager.SerializationOptOutAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true)))
            {
                return(false);
            }

            // Show the property if any of the opt-in annotations are present.
            if (property.IsStatic == false &&
                fiInstalledSerializerManager.SerializationOptInAnnotations.Any(t => memberInfo.IsDefined(t, /*inherit*/ true)))
            {
                return(true);
            }

            if (property.MemberInfo is PropertyInfo && fiSettings.InspectorRequireShowInInspector)
            {
                return(false);
            }

            return
                // IsSerializedByFullInspector will return false for BaseObject
                // types, so we want to special case support for them being
                // inspected.
                (typeof(BaseObject).Resolve().IsAssignableFrom(property.StorageType.Resolve()) ||
                 InspectedType.IsSerializedByFullInspector(property) ||
                 InspectedType.IsSerializedByUnity(property));
        }
コード例 #9
0
        /// <summary>
        /// Populate an pre-constructed instance with the data stored inside of the facade.
        /// </summary>
        /// <param name="instance">The object instance to populate.</param>
        public void PopulateInstance(ref T instance)
        {
            if (instance.GetType() != InstanceType)
            {
                Debug.LogWarning("PopulateInstance: Actual Facade type is different " +
                                 "(instance.GetType() = " + instance.GetType().CSharpName() +
                                 ", InstanceType = " + InstanceType.CSharpName() + ")");
            }

            Type defaultSerializer     = fiInstalledSerializerManager.DefaultMetadata.SerializerType;
            var  serializer            = (BaseSerializer)fiSingletons.Get(defaultSerializer);
            var  serializationOperator = new ListSerializationOperator()
            {
                SerializedObjects = ObjectReferences
            };

            InspectedType inspectedType = InspectedType.Get(instance.GetType());

            foreach (var tuple in FacadeMembers)
            {
                string name = tuple.Key;

                InspectedProperty property = inspectedType.GetPropertyByName(name);
                if (property != null)
                {
                    try {
                        object deserializedMember = serializer.Deserialize(
                            property.StorageType.Resolve(), tuple.Value, serializationOperator);
                        property.Write(instance, deserializedMember);
                    }
                    catch (Exception e) {
                        Debug.LogError("Skipping property " + name + " in facade due to " +
                                       "deserialization exception.\n" + e);
                    }
                }
            }
        }
コード例 #10
0
        public override Facade <T> Edit(Rect region, GUIContent label, Facade <T> element, fiGraphMetadata metadata)
        {
            if (element == null)
            {
                element = new Facade <T>();
            }

            if (element.InstanceType == null)
            {
                element.InstanceType = TypeOptions.Types[0];
            }

            bool changedTypes;

            DrawHeader(ref region, label, element, out changedTypes);

            var facadeMembers    = new Dictionary <string, string>();
            var facadeReferences = new List <UnityObject>();

            InspectedType inspectedType = InspectedType.Get(element.InstanceType);

            var serializer        = (BaseSerializer)fiSingletons.Get(fiInstalledSerializerManager.DefaultMetadata.SerializerType);
            var deserializationOp = new ListSerializationOperator()
            {
                SerializedObjects = element.ObjectReferences
            };
            var serializationOp = new ListSerializationOperator()
            {
                SerializedObjects = facadeReferences
            };

            float usedHeight = 0;

            var anim = metadata.GetMetadata <fiAnimationMetadata>();

            if (anim.IsAnimating)
            {
                fiEditorGUI.BeginFadeGroupHeight(LabelHeight, ref region, anim.AnimationHeight);
                fiEditorUtility.RepaintAllEditors();
            }

            var properties = inspectedType.GetProperties(InspectedMemberFilters.InspectableMembers);

            for (int i = 0; i < properties.Count; ++i)
            {
                InspectedProperty property = properties[i];

                object propertyValue = DeserializeProperty(serializer, deserializationOp, property, element);

                float height = fiEditorGUI.EditPropertyHeightDirect(property, propertyValue, metadata.Enter(property.Name));

                Rect propertyRect = region;
                propertyRect.height = height;
                region.y           += height;
                region.y           += SplitterHeight;

                usedHeight += height + SplitterHeight;

                object updatedValue = fiEditorGUI.EditPropertyDirect(propertyRect, property, propertyValue, metadata.Enter(property.Name));

                string data;
                if (TrySerializeProperty(serializer, serializationOp, property, updatedValue, out data))
                {
                    facadeMembers[property.Name] = data;
                }
            }

            if (anim.IsAnimating)
            {
                fiEditorGUI.EndFadeGroup();
            }

            element.FacadeMembers    = facadeMembers;
            element.ObjectReferences = facadeReferences;

            if (changedTypes && anim.UpdateHeight(usedHeight))
            {
                fiEditorUtility.RepaintAllEditors();
            }

            return(element);
        }
コード例 #11
0
        /// <summary>
        /// Returns true if the given property should be serialized.
        /// </summary>
        /// <remarks>This assumes that the property is r/w!</remarks>
        public static bool IsSerializedByFullInspector(InspectedProperty property)
        {
            if (property.IsStatic)
            {
                return(false);
            }

            // Do not bother serializing BaseObject derived types - they will
            // handle it properly themselves. Serializing them will only lead to
            // wasted storage space.
            if (typeof(BaseObject).Resolve().IsAssignableFrom(property.StorageType.Resolve()))
            {
                return(false);
            }

            MemberInfo member = property.MemberInfo;

            // if it has NonSerialized, then we *don't* serialize it
            if (fsPortableReflection.HasAttribute <NonSerializedAttribute>(member, /*shouldCache:*/ false) ||
                fsPortableReflection.HasAttribute <NotSerializedAttribute>(member, /*shouldCache:*/ false))
            {
                return(false);
            }

            // Don't serialize it if it has one of the custom opt-out annotations
            // either
            var optOut = fiInstalledSerializerManager.SerializationOptOutAnnotations;

            for (int i = 0; i < optOut.Length; ++i)
            {
                if (member.IsDefined(optOut[i], true))
                {
                    return(false);
                }
            }

            // if we have a [SerializeField] or [Serializable] attribute, then we
            // *do* serialize
            if (fsPortableReflection.HasAttribute <SerializeField>(member, /*shouldCache:*/ false) ||
                fsPortableReflection.HasAttribute <SerializableAttribute>(member, /*shouldCache:*/ false))
            {
                return(true);
            }

            // Serialize if we have a custom opt-in annotation
            var optIn = fiInstalledSerializerManager.SerializationOptInAnnotations;

            for (int i = 0; i < optIn.Length; ++i)
            {
                if (member.IsDefined(optIn[i], /*inherit:*/ true))
                {
                    return(true);
                }
            }

            if (property.MemberInfo is PropertyInfo)
            {
                // perf: property.IsAutoProperty is lazily computed, so if we
                //       have SerializeAutoProperties set to false we can avoid
                //       computing any auto-property checks by putting the
                //       SerializeAutoProperties check before the IsAutoProperty
                //       check

                // If we're not serializing auto-properties, then we will not
                // serialize any properties by default
                if (fiSettings.SerializeAutoProperties == false)
                {
                    return(false);
                }

                // If it's not an auto property, then we are not going to
                // serialize it by default
                if (property.IsAutoProperty == false)
                {
                    return(false);
                }
            }

            return(property.IsPublic);
        }
コード例 #12
0
 /// <summary>
 /// Construct an either containing a B value.
 /// </summary>
 public InspectedMember(InspectedMethod method)
 {
     _property = null;
     _method = method;
 }
コード例 #13
0
 /// <summary>
 /// Construct an either containing an A value.
 /// </summary>
 public InspectedMember(InspectedProperty property)
 {
     _property = property;
     _method = null;
 }
コード例 #14
0
 public bool IsInterested(InspectedProperty property)
 {
     return(false);
 }
コード例 #15
0
 /// <summary>
 /// Construct an either containing an A value.
 /// </summary>
 public InspectedMember(InspectedProperty property)
 {
     _property = property;
     _method   = null;
 }
コード例 #16
0
 public bool IsInterested(InspectedProperty property)
 {
     return(IsPropertyTypeInspectable(property) && ShouldDisplayProperty(property));
 }
コード例 #17
0
        /// <summary>
        /// Returns true if the given property should be serialized.
        /// </summary>
        /// <remarks>This assumes that the property is r/w!</remarks>
        public static bool IsSerializedByFullInspector(InspectedProperty property)
        {
            MemberInfo member = property.MemberInfo;

            if (property.IsStatic)
            {
                return(false);
            }

            // if it has NonSerialized, then we *don't* serialize it
            if (fsPortableReflection.HasAttribute <NonSerializedAttribute>(member) ||
                fsPortableReflection.HasAttribute <NotSerializedAttribute>(member))
            {
                return(false);
            }

            // Don't serialize it if it has one of the custom opt-out annotations either
            var optOut = fiInstalledSerializerManager.SerializationOptOutAnnotations;

            for (int i = 0; i < optOut.Length; ++i)
            {
                if (member.IsDefined(optOut[i], true))
                {
                    return(false);
                }
            }

            // if we have a [SerializeField] or [Serializable] attribute, then we *do* serialize
            if (fsPortableReflection.HasAttribute <SerializeField>(member) ||
                fsPortableReflection.HasAttribute <SerializableAttribute>(member))
            {
                return(true);
            }

            // Serialize if we have a custom opt-in annotation
            var optIn = fiInstalledSerializerManager.SerializationOptInAnnotations;

            for (int i = 0; i < optIn.Length; ++i)
            {
                if (member.IsDefined(optIn[i], /*inherit:*/ true))
                {
                    return(true);
                }
            }

            if (property.MemberInfo is PropertyInfo)
            {
                // perf: property.IsAutoProperty is lazily computed, so if we have SerializeAutoProperties set
                //       to false we can avoid computing any auto-property checks by putting the
                //       SerializeAutoProperties check before the IsAutoProperty check

                // If we're not serializing auto-properties, then we will not serialize any properties by default
                if (fiSettings.SerializeAutoProperties == false)
                {
                    return(false);
                }

                // If it's not an auto property, then we are not going to serialize it by default
                if (property.IsAutoProperty == false)
                {
                    return(false);
                }
            }

            return(property.IsPublic);
        }
コード例 #18
0
 public bool IsInterested(InspectedProperty property)
 {
     return(typeof(IEnumerable <tkIControl>).IsAssignableFrom(property.StorageType) ||
            typeof(tkIControl).IsAssignableFrom(property.StorageType));
 }
コード例 #19
0
        /// <summary>
        /// Deserializes a property on the facade.
        /// </summary>
        private static object DeserializeProperty(BaseSerializer serializer,
                                                  ISerializationOperator serializationOperator, InspectedProperty property,
                                                  Facade <T> facade)
        {
            string data;

            if (facade.FacadeMembers.TryGetValue(property.Name, out data))
            {
                try {
                    return(serializer.Deserialize(property.StorageType, data, serializationOperator));
                }
                catch {
                }
            }

            return(GetDefault(property.StorageType));
        }
コード例 #20
0
 /// <summary>
 /// Construct an either containing a B value.
 /// </summary>
 public InspectedMember(InspectedMethod method)
 {
     _property = null;
     _method   = method;
 }
コード例 #21
0
 /// <summary>
 /// Serializes a property that will be stored on the facade.
 /// </summary>
 public static bool TrySerializeProperty(BaseSerializer serializer,
                                         ISerializationOperator serializationOperator, InspectedProperty property, object value,
                                         out string data)
 {
     try {
         data = serializer.Serialize(property.StorageType, value, serializationOperator);
         return(true);
     }
     catch {
         data = string.Empty;
         return(false);
     }
 }
コード例 #22
0
 public bool IsInterested(InspectedProperty property)
 {
     return(property.IsStatic && IsPropertyTypeInspectable(property));
 }