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.

108 lines
4.2KB

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