Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

138 lines
5.3KB

  1. #if !DEBUG || PROFILER
  2. #define DISABLE_CHECKS
  3. using System.Diagnostics;
  4. #endif
  5. using System;
  6. using System.Reflection;
  7. namespace Svelto.ECS
  8. {
  9. internal static class EntityBuilderUtilities
  10. {
  11. const string MSG = "Entity Structs field and Entity View Struct components must hold value types.";
  12. #if DISABLE_CHECKS
  13. [Conditional("_CHECKS_DISABLED")]
  14. #endif
  15. public static void CheckFields(Type entityStructType, bool needsReflection, bool isStringAllowed = false)
  16. {
  17. if (entityStructType == ENTITY_STRUCT_INFO_VIEW ||
  18. entityStructType == EGIDType ||
  19. entityStructType == EXCLUSIVEGROUPSTRUCTTYPE ||
  20. entityStructType == SERIALIZABLE_ENTITY_STRUCT)
  21. {
  22. return;
  23. }
  24. if (needsReflection == false)
  25. {
  26. if (entityStructType.IsClass)
  27. {
  28. throw new EntityStructException("EntityStructs must be structs.", entityStructType);
  29. }
  30. FieldInfo[] fields = entityStructType.GetFields(BindingFlags.Public | BindingFlags.Instance);
  31. for (var i = fields.Length - 1; i >= 0; --i)
  32. {
  33. FieldInfo fieldInfo = fields[i];
  34. Type fieldType = fieldInfo.FieldType;
  35. SubCheckFields(fieldType, entityStructType, isStringAllowed);
  36. }
  37. }
  38. else
  39. {
  40. FieldInfo[] fields = entityStructType.GetFields(BindingFlags.Public | BindingFlags.Instance);
  41. if (fields.Length < 1)
  42. {
  43. ProcessError("Entity View Structs must hold only entity components interfaces.", entityStructType);
  44. }
  45. for (int i = fields.Length - 1; i >= 0; --i)
  46. {
  47. FieldInfo fieldInfo = fields[i];
  48. if (fieldInfo.FieldType.IsInterfaceEx() == false)
  49. {
  50. ProcessError("Entity View Structs must hold only entity components interfaces.",
  51. entityStructType);
  52. }
  53. PropertyInfo[] properties = fieldInfo.FieldType.GetProperties(
  54. BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
  55. for (int j = properties.Length - 1; j >= 0; --j)
  56. {
  57. if (properties[j].PropertyType.IsGenericType)
  58. {
  59. Type genericTypeDefinition = properties[j].PropertyType.GetGenericTypeDefinition();
  60. if (genericTypeDefinition == DISPATCHONSETTYPE ||
  61. genericTypeDefinition == DISPATCHONCHANGETYPE)
  62. {
  63. continue;
  64. }
  65. }
  66. Type propertyType = properties[j].PropertyType;
  67. if (propertyType != STRINGTYPE)
  68. {
  69. //for EntityViewStructs, component fields that are structs that hold strings
  70. //are allowed
  71. SubCheckFields(propertyType, entityStructType, isStringAllowed: true);
  72. }
  73. }
  74. }
  75. }
  76. }
  77. static void SubCheckFields(Type fieldType, Type entityStructType, bool isStringAllowed = false)
  78. {
  79. if (fieldType.IsPrimitive || fieldType.IsValueType || (isStringAllowed == true && fieldType == STRINGTYPE))
  80. {
  81. if (fieldType.IsValueType && !fieldType.IsEnum && fieldType.IsPrimitive == false)
  82. {
  83. CheckFields(fieldType, false, isStringAllowed);
  84. }
  85. return;
  86. }
  87. ProcessError(MSG, entityStructType, fieldType);
  88. }
  89. static void ProcessError(string message, Type entityViewType, Type fieldType = null)
  90. {
  91. if (fieldType != null)
  92. {
  93. throw new EntityStructException(message, entityViewType, fieldType);
  94. }
  95. throw new EntityStructException(message, entityViewType);
  96. }
  97. static readonly Type DISPATCHONCHANGETYPE = typeof(DispatchOnChange<>);
  98. static readonly Type DISPATCHONSETTYPE = typeof(DispatchOnSet<>);
  99. static readonly Type EGIDType = typeof(EGID);
  100. static readonly Type EXCLUSIVEGROUPSTRUCTTYPE = typeof(ExclusiveGroup.ExclusiveGroupStruct);
  101. static readonly Type SERIALIZABLE_ENTITY_STRUCT = typeof(SerializableEntityStruct);
  102. static readonly Type STRINGTYPE = typeof(string);
  103. internal static readonly Type ENTITY_STRUCT_INFO_VIEW = typeof(EntityStructInfoView);
  104. }
  105. public class EntityStructException : Exception
  106. {
  107. public EntityStructException(string message, Type entityViewType, Type type) :
  108. base(message.FastConcat(" entity view: '", entityViewType.ToString(), "', field: '", type.ToString()))
  109. {
  110. }
  111. public EntityStructException(string message, Type entityViewType) :
  112. base(message.FastConcat(" entity view: ", entityViewType.ToString()))
  113. {
  114. }
  115. }
  116. }