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.

147 lines
4.6KB

  1. using System;
  2. using System.Collections.Generic;
  3. #if DEBUG && !PROFILER
  4. using System.Reflection;
  5. #endif
  6. using Svelto.DataStructures;
  7. using Svelto.ECS.Internal;
  8. using Svelto.Utilities;
  9. namespace Svelto.ECS
  10. {
  11. public class EntityBuilder<T> : IEntityBuilder where T : IEntityStruct, new()
  12. {
  13. public EntityBuilder()
  14. {
  15. _initializer = default(T);
  16. #if DEBUG && !PROFILER
  17. if (needsReflection == false)
  18. {
  19. CheckFields(typeof(T));
  20. }
  21. #endif
  22. if (needsReflection == true)
  23. {
  24. EntityView<T>.InitCache();
  25. }
  26. }
  27. #if DEBUG && !PROFILER
  28. static void CheckFields(Type type)
  29. {
  30. var fields = type.GetFields(BindingFlags.Public |
  31. BindingFlags.Instance);
  32. for (int i = fields.Length - 1; i >= 0; --i)
  33. {
  34. var field = fields[i];
  35. var fieldFieldType = field.FieldType;
  36. SubCheckFields(fieldFieldType);
  37. }
  38. if (type.Assembly == Assembly.GetCallingAssembly())
  39. {
  40. var methods = type.GetMethods(BindingFlags.Public |
  41. BindingFlags.Instance | BindingFlags.DeclaredOnly);
  42. var properties = type.GetProperties(BindingFlags.Public |
  43. BindingFlags.Instance | BindingFlags.DeclaredOnly);
  44. if (methods.Length > properties.Length + 1)
  45. throw new EntityStructException(type);
  46. for (int i = properties.Length - 1; i >= 0; --i)
  47. {
  48. var propertyInfo = properties[i];
  49. var fieldFieldType = propertyInfo.PropertyType;
  50. SubCheckFields(fieldFieldType);
  51. }
  52. }
  53. }
  54. static void SubCheckFields(Type fieldFieldType)
  55. {
  56. if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true)
  57. {
  58. if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum && fieldFieldType.IsPrimitive == false)
  59. {
  60. CheckFields(fieldFieldType);
  61. }
  62. return;
  63. }
  64. throw new EntityStructException(fieldFieldType);
  65. }
  66. #endif
  67. public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors)
  68. {
  69. if (dictionary == null)
  70. dictionary = new TypeSafeDictionary<T>();
  71. var castedDic = dictionary as TypeSafeDictionary<T>;
  72. if (needsReflection == true)
  73. {
  74. DBC.ECS.Check.Require(implementors != null, "Implementors not found while building an EntityView");
  75. T lentityView;
  76. EntityView<T>.BuildEntityView(entityID, out lentityView);
  77. this.FillEntityView(ref lentityView
  78. , entityViewBlazingFastReflection
  79. , implementors
  80. , DESCRIPTOR_NAME);
  81. castedDic.Add(entityID.entityID, ref lentityView);
  82. }
  83. else
  84. {
  85. _initializer.ID = entityID;
  86. castedDic.Add(entityID.entityID, _initializer);
  87. }
  88. }
  89. ITypeSafeDictionary IEntityBuilder.Preallocate(ref ITypeSafeDictionary dictionary, int size)
  90. {
  91. return Preallocate(ref dictionary, size);
  92. }
  93. public static ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary dictionary, int size)
  94. {
  95. if (dictionary == null)
  96. dictionary = new TypeSafeDictionary<T>(size);
  97. else
  98. dictionary.AddCapacity(size);
  99. return dictionary;
  100. }
  101. public Type GetEntityType()
  102. {
  103. return ENTITY_VIEW_TYPE;
  104. }
  105. static FasterList<KeyValuePair<Type, ActionCast<T>>> entityViewBlazingFastReflection
  106. {
  107. get { return EntityView<T>.cachedFields; }
  108. }
  109. static readonly Type ENTITY_VIEW_TYPE = typeof(T);
  110. static readonly string DESCRIPTOR_NAME = ENTITY_VIEW_TYPE.ToString();
  111. static readonly bool needsReflection = typeof(IEntityViewStruct).IsAssignableFrom(typeof(T));
  112. internal T _initializer;
  113. }
  114. public class EntityStructException : Exception
  115. {
  116. public EntityStructException(Type fieldType):base("EntityStruct must contains only value types and no public methods! " + fieldType.ToString())
  117. {}
  118. }
  119. }