UnityMemberDrawerHelper.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using Chronos.Controls.Editor;
  5. using Chronos.Reflection.Internal;
  6. using UnityEditor;
  7. namespace Chronos.Reflection.Editor
  8. {
  9. public static class UnityMemberDrawerHelper
  10. {
  11. public static bool ValidateMemberType(FilterAttribute filter, Type type)
  12. {
  13. bool validFamily = false;
  14. bool validType;
  15. // Allow type families based on the filter attribute
  16. TypeFamily families = filter.TypeFamilies;
  17. if (families.HasFlag(TypeFamily.Array)) validFamily |= type.IsArray;
  18. if (families.HasFlag(TypeFamily.Class)) validFamily |= type.IsClass;
  19. if (families.HasFlag(TypeFamily.Enum)) validFamily |= type.IsEnum;
  20. if (families.HasFlag(TypeFamily.Interface)) validFamily |= type.IsInterface;
  21. if (families.HasFlag(TypeFamily.Primitive)) validFamily |= type.IsPrimitive;
  22. if (families.HasFlag(TypeFamily.Reference)) validFamily |= !type.IsValueType;
  23. if (families.HasFlag(TypeFamily.Value)) validFamily |= (type.IsValueType && type != typeof(void));
  24. if (families.HasFlag(TypeFamily.Void)) validFamily |= type == typeof(void);
  25. // Allow types based on the filter attribute
  26. // If no filter types are specified, all types are allowed.
  27. if (filter.Types.Count > 0)
  28. {
  29. validType = false;
  30. foreach (Type allowedType in filter.Types)
  31. {
  32. if (allowedType.IsAssignableFrom(type))
  33. {
  34. validType = true;
  35. break;
  36. }
  37. }
  38. }
  39. else
  40. {
  41. validType = true;
  42. }
  43. return validFamily && validType;
  44. }
  45. public static bool ValidateField(FilterAttribute filter, FieldInfo field)
  46. {
  47. bool valid = true;
  48. // Validate type based on field type
  49. valid &= ValidateMemberType(filter, field.FieldType);
  50. // Exclude constants (literal) and readonly (init) fields if
  51. // the filter rejects read-only fields.
  52. if (!filter.ReadOnly) valid &= !field.IsLiteral || !field.IsInitOnly;
  53. return valid;
  54. }
  55. public static bool ValidateProperty(FilterAttribute filter, PropertyInfo property)
  56. {
  57. bool valid = true;
  58. // Validate type based on property type
  59. valid &= ValidateMemberType(filter, property.PropertyType);
  60. // Exclude read-only and write-only properties
  61. if (!filter.ReadOnly) valid &= property.CanWrite;
  62. if (!filter.WriteOnly) valid &= property.CanRead;
  63. return valid;
  64. }
  65. public static bool ValidateMethod(FilterAttribute filter, MethodInfo method)
  66. {
  67. bool valid = true;
  68. // Validate type based on return type
  69. valid &= ValidateMemberType(filter, method.ReturnType);
  70. // Exclude special compiler methods
  71. valid &= !method.IsSpecialName;
  72. // Exclude generic methods
  73. // TODO: Generic type (de)serialization
  74. valid &= !method.ContainsGenericParameters;
  75. // Exclude methods with parameters
  76. if (!filter.Parameters)
  77. {
  78. valid &= method.GetParameters().Length == 0;
  79. }
  80. return valid;
  81. }
  82. public static void SerializeParameterTypes(SerializedProperty parameterTypesProperty, Type[] parameterTypes)
  83. {
  84. // Assign the parameter types to their underlying properties
  85. if (parameterTypes == null)
  86. {
  87. parameterTypesProperty.arraySize = 0;
  88. }
  89. else
  90. {
  91. parameterTypesProperty.arraySize = parameterTypes.Length;
  92. for (int i = 0; i < parameterTypesProperty.arraySize; i++)
  93. {
  94. SerializedProperty parameterTypeProperty = parameterTypesProperty.GetArrayElementAtIndex(i);
  95. parameterTypeProperty.stringValue = TypeSerializer.Serialize(parameterTypes[i]);
  96. }
  97. }
  98. }
  99. public static Type[] DeserializeParameterTypes(SerializedProperty parameterTypesProperty)
  100. {
  101. // Fetch the parameter types from their underlying properties
  102. Type[] parameterTypes = new Type[parameterTypesProperty.arraySize];
  103. for (int i = 0; i < parameterTypesProperty.arraySize; i++)
  104. {
  105. SerializedProperty parameterTypeProperty = parameterTypesProperty.GetArrayElementAtIndex(i);
  106. parameterTypes[i] = TypeSerializer.Deserialize(parameterTypeProperty.stringValue);
  107. }
  108. return parameterTypes;
  109. }
  110. public static bool ParameterTypesHasMultipleValues(SerializedProperty parameterTypesProperty)
  111. {
  112. string[] last = null;
  113. foreach (SerializedProperty arrayProperty in parameterTypesProperty.Multiple())
  114. {
  115. string[] current = new string[arrayProperty.arraySize];
  116. for (int i = 0; i < arrayProperty.arraySize; i++)
  117. {
  118. SerializedProperty parameterTypeProperty = arrayProperty.GetArrayElementAtIndex(i);
  119. current[i] = parameterTypeProperty.stringValue;
  120. }
  121. if (last != null && !current.SequenceEqual(last))
  122. {
  123. return true;
  124. }
  125. last = current;
  126. }
  127. return false;
  128. }
  129. }
  130. }