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.

110 lines
4.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. public static class EntityBuilderUtilities
  10. {
  11. #if DISABLE_CHECKS
  12. [Conditional("_CHECKS_DISABLED")]
  13. #endif
  14. public static void CheckFields(Type type, bool needsReflection)
  15. {
  16. if (type == ENTITY_STRUCT_INFO_VIEW || type == EGIDType || type == ECLUSIVEGROUPSTRUCTTYPE)
  17. return;
  18. if (needsReflection == false)
  19. {
  20. if (type.IsClass)
  21. throw new EntityStructException("EntityStructs must be structs.", ENTITY_VIEW_TYPE, type);
  22. var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
  23. for (int i = fields.Length - 1; i >= 0; --i)
  24. {
  25. var field = fields[i];
  26. var fieldFieldType = field.FieldType;
  27. if (fieldFieldType == STRINGTYPE) continue;
  28. SubCheckFields(fieldFieldType);
  29. }
  30. }
  31. else
  32. {
  33. var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
  34. if (fields.Length < 1)
  35. ProcessError("Entity View Structs must hold only entity components interfaces.", type);
  36. for (int i = fields.Length - 1; i >= 0; --i)
  37. {
  38. var field = fields[i];
  39. if (field.FieldType.IsInterfaceEx() == false)
  40. ProcessError("Entity View Structs must hold only entity components interfaces.", type);
  41. var properties = field.FieldType.GetProperties(BindingFlags.Public |
  42. BindingFlags.Instance | BindingFlags.DeclaredOnly);
  43. for (int j = properties.Length - 1; j >= 0; --j)
  44. {
  45. if (properties[j].PropertyType.IsGenericType == true)
  46. {
  47. var genericTypeDefinition = properties[j].PropertyType.GetGenericTypeDefinition();
  48. if (genericTypeDefinition == DISPATCHONSETTYPE ||
  49. genericTypeDefinition == DISPATCHONCHANGETYPE) continue;
  50. }
  51. var propertyType = properties[j].PropertyType;
  52. if (propertyType != STRINGTYPE)
  53. SubCheckFields(propertyType);
  54. }
  55. }
  56. }
  57. }
  58. static void SubCheckFields(Type fieldFieldType)
  59. {
  60. if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true)
  61. {
  62. if (fieldFieldType.IsValueType == true && !fieldFieldType.IsEnum && fieldFieldType.IsPrimitive == false)
  63. {
  64. CheckFields(fieldFieldType, false);
  65. }
  66. return;
  67. }
  68. ProcessError("Entity Structs field and Entity View Struct components must hold value types.",
  69. fieldFieldType);
  70. }
  71. static void ProcessError(string message, Type type)
  72. {
  73. #if !RELAXED_ECS
  74. Type ENTITY_VIEW_TYPE = typeof(Type);
  75. throw new EntityStructException(message, ENTITY_VIEW_TYPE, type);
  76. #endif
  77. }
  78. static readonly Type EGIDType = typeof(EGID);
  79. static readonly Type ECLUSIVEGROUPSTRUCTTYPE = typeof(ExclusiveGroup.ExclusiveGroupStruct);
  80. static readonly Type DISPATCHONSETTYPE = typeof(DispatchOnSet<>);
  81. static readonly Type DISPATCHONCHANGETYPE = typeof(DispatchOnChange<>);
  82. static readonly Type STRINGTYPE = typeof(String);
  83. static readonly Type ENTITY_VIEW_TYPE = typeof(Type);
  84. static readonly Type ENTITY_STRUCT_INFO_VIEW = typeof(EntityStructInfoView);
  85. }
  86. public class EntityStructException : Exception
  87. {
  88. public EntityStructException(string message, Type entityViewType, Type type):
  89. base(message.FastConcat(" entity view: ", entityViewType.ToString(), " field: ", type.ToString()))
  90. {}
  91. }
  92. }