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.

221 lines
10KB

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