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)))); }
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()); }