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.

223 lines
10.0KB

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