static bool IsArrayReorderable(SerializedProperty property)
        {
            FieldInfo      listInfo     = null;
            Queue <string> propertyName = new Queue <string>(property.propertyPath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));

            listInfo = property.serializedObject.targetObject.GetType().GetField(propertyName.Dequeue());

            if (listInfo == null)
            {
                return(false);
            }

            // If we have a nested property we need to find it via reflection in order to verify
            // if it has a non-reorderable attribute
            while (propertyName.Count > 0)
            {
                Type t = listInfo.FieldType;
                if (t.IsArray)
                {
                    t = t.GetElementType();
                }
                else if (t.IsArrayOrList())
                {
                    t = t.GetGenericArguments().Single();
                }
                FieldInfo f = t.GetField(propertyName.Dequeue());
                if (f != null)
                {
                    listInfo = f;
                }
            }

            return(TypeCache.GetFieldsWithAttribute(typeof(ReorderableAttribute)).Any(f => f.Equals(listInfo)) || property.IsReorderable());
        }
Example #2
0
        internal static bool IsArrayReorderable(SerializedProperty property)
        {
            const BindingFlags fieldFilter = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

            if (property == null || property.serializedObject == null || !property.serializedObject.targetObject)
            {
                return(false);
            }

            if (property.IsReorderable())
            {
                return(true);
            }

            FieldInfo      listInfo     = null;
            Queue <string> propertyName = new Queue <string>(property.propertyPath.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
            Type           type         = property.serializedObject.targetObject.GetType();
            var            name         = propertyName.Dequeue();

            listInfo = type.GetField(name, fieldFilter);

            if (listInfo == null)
            {
                // it may be private in any parent and still serializable
                type = type.BaseType;
                while (listInfo == null && type != null)
                {
                    listInfo = type.GetField(name, fieldFilter);
                    type     = type.BaseType;
                }
                if (listInfo == null)
                {
                    return(false);
                }
            }

            // If we have a nested property we need to find it via reflection in order to verify
            // if it has a non-reorderable attribute
            while (propertyName.Count > 0)
            {
                try
                {
                    // We should at least try to get the type from object instance
                    // in order to handle interfaces and abstractions correctly
                    type = listInfo.GetValue(property.serializedObject.targetObject).GetType();
                }
                catch
                {
                    type = listInfo.FieldType;
                }

                if (type.IsArray)
                {
                    type = type.GetElementType();
                }
                else if (type.IsArrayOrList())
                {
                    type = type.GetGenericArguments().Single();
                }

                FieldInfo field = type.GetField(propertyName.Dequeue(), fieldFilter);
                if (field != null)
                {
                    listInfo = field;
                }
            }

            // Since we're using TypeCache to find NonReorderableAttribute, we will need to manually check base fields
            List <FieldInfo> baseFields = new List <FieldInfo>();

            baseFields.Add(listInfo);
            while ((type = type.BaseType) != null)
            {
                var field = type.GetField(listInfo.Name, fieldFilter);
                if (field != null)
                {
                    baseFields.Add(field);
                }
            }

            return(!TypeCache.GetFieldsWithAttribute(typeof(NonReorderableAttribute)).Any(f => baseFields.Any(b => f.Equals(b))));
        }