Mirror of Svelto.ECS because we're a fan of it
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

228 lignes
11KB

  1. using System;
  2. using System.Threading;
  3. using Svelto.DataStructures;
  4. using Svelto.ECS.Internal;
  5. namespace Svelto.ECS
  6. {
  7. public partial class EntitiesDB
  8. {
  9. /// <summary>
  10. /// Return all the groups where the entity component is found. It's a linear operation, but usually the number of groups are very low
  11. /// By default Groups marked as disabled are not returned, however this can be overridden using the ignoreDisabledBit parameter
  12. /// </summary>
  13. public LocalFasterReadOnlyList<ExclusiveGroupStruct> FindGroups<T1>(bool ignoreDisabledBit = false) where T1 : struct, _IInternalEntityComponent
  14. {
  15. FasterList<ExclusiveGroupStruct> result = localgroups.Value.groupArray;
  16. result.Clear();
  17. if (groupsPerComponent.TryGetValue(ComponentTypeID<T1>.id
  18. , out FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> result1)
  19. == false)
  20. return result;
  21. var result1Count = result1.count;
  22. var fasterDictionaryNodes1 = result1.unsafeKeys;
  23. for (int j = 0; j < result1Count; j++)
  24. {
  25. var group = fasterDictionaryNodes1[j].key;
  26. if (ignoreDisabledBit == false && group.IsEnabled() == false) continue;
  27. result.Add(group);
  28. }
  29. return result;
  30. }
  31. public LocalFasterReadOnlyList<ExclusiveGroupStruct> FindGroups<T1, T2>(bool ignoreDisabledBit = false)
  32. where T1 : struct, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent
  33. {
  34. FasterList<ExclusiveGroupStruct> result = localgroups.Value.groupArray;
  35. result.Clear();
  36. if (groupsPerComponent.TryGetValue(ComponentTypeID<T1>.id
  37. , out FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> result1)
  38. == false)
  39. return result;
  40. if (groupsPerComponent.TryGetValue(ComponentTypeID<T2>.id
  41. , out FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> result2)
  42. == false)
  43. return result;
  44. var result1Count = result1.count;
  45. var result2Count = result2.count;
  46. var fasterDictionaryNodes1 = result1.unsafeKeys;
  47. var fasterDictionaryNodes2 = result2.unsafeKeys;
  48. for (int i = 0; i < result1Count; i++)
  49. {
  50. var groupID = fasterDictionaryNodes1[i].key;
  51. if (ignoreDisabledBit == false && groupID.IsEnabled() == false) continue;
  52. for (int j = 0; j < result2Count; j++)
  53. {
  54. //if the same group is found used with both T1 and T2
  55. if (groupID == fasterDictionaryNodes2[j].key)
  56. {
  57. result.Add(groupID);
  58. break;
  59. }
  60. }
  61. }
  62. return result;
  63. }
  64. /// <summary>
  65. /// Remember that this operation os O(N*M*P) where N,M,P are the number of groups where each component
  66. /// is found.
  67. /// TODO: I have to find once for ever a solution to be sure that the entities in the groups match
  68. /// Currently this returns group where the entities are found, but the entities may not match in these
  69. /// groups.
  70. /// Checking the size of the entities is an early check, needed, but not sufficient, as entities components may
  71. /// coincidentally match in number but not from which entities they are generated
  72. /// </summary>
  73. /// <typeparam name="T1"></typeparam>
  74. /// <typeparam name="T2"></typeparam>
  75. /// <typeparam name="T3"></typeparam>
  76. /// <returns></returns>
  77. public LocalFasterReadOnlyList<ExclusiveGroupStruct> FindGroups<T1, T2, T3>(bool ignoreDisabledBit = false)
  78. where T1 : struct, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent where T3 : struct, _IInternalEntityComponent
  79. {
  80. FasterList<FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>> localArray =
  81. localgroups.Value.listOfGroups;
  82. if (groupsPerComponent.TryGetValue(ComponentTypeID<T1>.id, out localArray[0]) == false || localArray[0].count == 0)
  83. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  84. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  85. if (groupsPerComponent.TryGetValue(ComponentTypeID<T2>.id, out localArray[1]) == false || localArray[1].count == 0)
  86. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  87. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  88. if (groupsPerComponent.TryGetValue(ComponentTypeID<T3>.id, out localArray[2]) == false || localArray[2].count == 0)
  89. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  90. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  91. localgroups.Value.groups.Clear();
  92. FasterDictionary<ExclusiveGroupStruct, ExclusiveGroupStruct> localGroups = localgroups.Value.groups;
  93. int startIndex = 0;
  94. int min = int.MaxValue;
  95. for (int i = 0; i < 3; i++)
  96. if (localArray[i].count < min)
  97. {
  98. min = localArray[i].count;
  99. startIndex = i;
  100. }
  101. foreach (var value in localArray[startIndex])
  102. {
  103. if (ignoreDisabledBit == false && value.key.IsEnabled() == false) continue;
  104. localGroups.Add(value.key, value.key);
  105. }
  106. var groupData = localArray[++startIndex % 3];
  107. localGroups.Intersect(groupData);
  108. if (localGroups.count == 0)
  109. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  110. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  111. groupData = localArray[++startIndex % 3];
  112. localGroups.Intersect(groupData);
  113. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(localGroups.unsafeValues
  114. , (uint) localGroups.count);
  115. }
  116. public LocalFasterReadOnlyList<ExclusiveGroupStruct> FindGroups<T1, T2, T3, T4>(bool ignoreDisabledBit = false)
  117. where T1 : struct, _IInternalEntityComponent
  118. where T2 : struct, _IInternalEntityComponent
  119. where T3 : struct, _IInternalEntityComponent
  120. where T4 : struct, _IInternalEntityComponent
  121. {
  122. FasterList<FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>> localArray =
  123. localgroups.Value.listOfGroups;
  124. if (groupsPerComponent.TryGetValue(ComponentTypeID<T1>.id, out localArray[0]) == false || localArray[0].count == 0)
  125. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  126. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  127. if (groupsPerComponent.TryGetValue(ComponentTypeID<T2>.id, out localArray[1]) == false || localArray[1].count == 0)
  128. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  129. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  130. if (groupsPerComponent.TryGetValue(ComponentTypeID<T3>.id, out localArray[2]) == false || localArray[2].count == 0)
  131. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  132. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  133. if (groupsPerComponent.TryGetValue(ComponentTypeID<T4>.id, out localArray[3]) == false || localArray[3].count == 0)
  134. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  135. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  136. localgroups.Value.groups.Clear();
  137. var localGroups = localgroups.Value.groups;
  138. int startIndex = 0;
  139. int min = int.MaxValue;
  140. for (int i = 0; i < 4; i++)
  141. {
  142. var fasterDictionary = localArray[i];
  143. if (fasterDictionary.count < min)
  144. {
  145. min = fasterDictionary.count;
  146. startIndex = i;
  147. }
  148. }
  149. foreach (var value in localArray[startIndex])
  150. {
  151. if (ignoreDisabledBit == false && value.key.IsEnabled() == false) continue;
  152. localGroups.Add(value.key, value.key);
  153. }
  154. var groupData = localArray[++startIndex & 3]; //&3 == %4
  155. localGroups.Intersect(groupData);
  156. if (localGroups.count == 0)
  157. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  158. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  159. groupData = localArray[++startIndex & 3];
  160. localGroups.Intersect(groupData);
  161. if (localGroups.count == 0)
  162. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(
  163. FasterReadOnlyList<ExclusiveGroupStruct>.DefaultEmptyList);
  164. groupData = localArray[++startIndex & 3];
  165. localGroups.Intersect(groupData);
  166. return new LocalFasterReadOnlyList<ExclusiveGroupStruct>(localGroups.unsafeValues
  167. , (uint) localGroups.count);
  168. }
  169. internal FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> FindGroups_INTERNAL(ComponentID type)
  170. {
  171. if (groupsPerComponent.ContainsKey(type) == false)
  172. return _emptyDictionary;
  173. return groupsPerComponent[type];
  174. }
  175. struct GroupsList
  176. {
  177. internal FasterDictionary<ExclusiveGroupStruct, ExclusiveGroupStruct> groups;
  178. internal FasterList<FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>> listOfGroups;
  179. public FasterList<ExclusiveGroupStruct> groupArray;
  180. }
  181. static readonly ThreadLocal<GroupsList> localgroups = new ThreadLocal<GroupsList>(() =>
  182. {
  183. GroupsList gl = default;
  184. gl.groups = new FasterDictionary<ExclusiveGroupStruct, ExclusiveGroupStruct>();
  185. gl.listOfGroups = FasterList<FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>>.PreInit(4);
  186. gl.groupArray = new FasterList<ExclusiveGroupStruct>(1);
  187. return gl;
  188. });
  189. }
  190. }