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.

209 lines
7.2KB

  1. using System.Runtime.CompilerServices;
  2. using Svelto.Common;
  3. using Svelto.DataStructures.Native;
  4. using Svelto.ECS.Native;
  5. namespace Svelto.ECS
  6. {
  7. public readonly struct EntityFilterCollection
  8. {
  9. internal EntityFilterCollection(CombinedFilterID combinedFilterId,
  10. Allocator allocatorStrategy = Allocator.Persistent)
  11. {
  12. _filtersPerGroup =
  13. SharedSveltoDictionaryNative<ExclusiveGroupStruct, GroupFilters>.Create(allocatorStrategy);
  14. combinedFilterID = combinedFilterId;
  15. }
  16. public CombinedFilterID combinedFilterID { get; }
  17. public EntityFilterIterator GetEnumerator() => new EntityFilterIterator(this);
  18. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  19. public bool Add<T>(EGID egid, NativeEGIDMapper<T> mmap) where T : unmanaged, IEntityComponent
  20. {
  21. DBC.ECS.Check.Require(mmap.groupID == egid.groupID, "not compatible NativeEgidMapper used");
  22. return Add(egid, mmap.GetIndex(egid.entityID));
  23. }
  24. public bool Add<T>(EGID egid, NativeEGIDMultiMapper<T> mmap) where T : unmanaged, IEntityComponent
  25. {
  26. return Add(egid, mmap.GetIndex(egid));
  27. }
  28. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  29. public bool Add(EGID egid, uint toIndex)
  30. {
  31. return GetOrCreateGroupFilter(egid.groupID).Add(egid.entityID, toIndex);
  32. }
  33. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  34. public void Add(uint entityID, ExclusiveGroupStruct groupId, uint index)
  35. {
  36. Add(new EGID(entityID, groupId), index);
  37. }
  38. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  39. public void Remove(EGID egid)
  40. {
  41. _filtersPerGroup[egid.groupID].Remove(egid.entityID);
  42. }
  43. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  44. public bool Exists(EGID egid)
  45. {
  46. if (TryGetGroupFilter(egid.groupID, out var groupFilter))
  47. {
  48. return groupFilter.Exists(egid.entityID);
  49. }
  50. return false;
  51. }
  52. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  53. public bool TryGetGroupFilter(ExclusiveGroupStruct group, out GroupFilters groupFilter)
  54. {
  55. return _filtersPerGroup.TryGetValue(group, out groupFilter);
  56. }
  57. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  58. public GroupFilters GetOrCreateGroupFilter(ExclusiveGroupStruct group)
  59. {
  60. if (_filtersPerGroup.TryGetValue(group, out var groupFilter) == false)
  61. {
  62. groupFilter = new GroupFilters(group);
  63. _filtersPerGroup.Add(group, groupFilter);
  64. }
  65. return groupFilter;
  66. }
  67. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  68. public void Clear()
  69. {
  70. var filterSets = _filtersPerGroup.GetValues(out var count);
  71. for (var i = 0; i < count; i++)
  72. {
  73. filterSets[i].Clear();
  74. }
  75. }
  76. internal int groupCount => _filtersPerGroup.count;
  77. public void ComputeFinalCount(out int count)
  78. {
  79. count = 0;
  80. for (int i = 0; i < _filtersPerGroup.count; i++)
  81. {
  82. count += (int)GetGroup(i).count;
  83. }
  84. }
  85. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  86. internal GroupFilters GetGroup(int indexGroup)
  87. {
  88. DBC.ECS.Check.Require(indexGroup < _filtersPerGroup.count);
  89. return _filtersPerGroup.GetValues(out _)[indexGroup];
  90. }
  91. public void Dispose()
  92. {
  93. var filterSets = _filtersPerGroup.GetValues(out var count);
  94. for (var i = 0; i < count; i++)
  95. {
  96. filterSets[i].Dispose();
  97. }
  98. _filtersPerGroup.Dispose();
  99. }
  100. internal readonly SharedSveltoDictionaryNative<ExclusiveGroupStruct, GroupFilters> _filtersPerGroup;
  101. public struct GroupFilters
  102. {
  103. internal GroupFilters(ExclusiveGroupStruct group) : this()
  104. {
  105. _entityIDToDenseIndex = new SharedSveltoDictionaryNative<uint, uint>(1);
  106. _indexToEntityId = new SharedSveltoDictionaryNative<uint, uint>(1);
  107. _group = group;
  108. }
  109. public bool Add(uint entityId, uint entityIndex)
  110. {
  111. //TODO: when sentinels are finished, we need to add AsWriter here
  112. if (_entityIDToDenseIndex.TryAdd(entityId, entityIndex, out _))
  113. {
  114. _indexToEntityId[entityIndex] = entityId;
  115. return true;
  116. }
  117. return false;
  118. }
  119. public bool Exists(uint entityId) => _entityIDToDenseIndex.ContainsKey(entityId);
  120. public void Remove(uint entityId)
  121. {
  122. _indexToEntityId.Remove(_entityIDToDenseIndex[entityId]);
  123. _entityIDToDenseIndex.Remove(entityId);
  124. }
  125. public EntityFilterIndices indices
  126. {
  127. get
  128. {
  129. var values = _entityIDToDenseIndex.GetValues(out var count);
  130. return new EntityFilterIndices(values, count);
  131. }
  132. }
  133. public int count => _entityIDToDenseIndex.count;
  134. public bool isValid => _entityIDToDenseIndex.isValid;
  135. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  136. internal void RemoveWithSwapBack(uint entityId, uint entityIndex, uint lastIndex)
  137. {
  138. // Check if the last index is part of the filter as an entity, in that case
  139. //we need to update the filter
  140. if (entityIndex != lastIndex && _indexToEntityId.TryGetValue(lastIndex, out var lastEntityID))
  141. {
  142. _entityIDToDenseIndex[lastEntityID] = entityIndex;
  143. _indexToEntityId[entityIndex] = lastEntityID;
  144. _indexToEntityId.Remove(lastIndex);
  145. }
  146. else
  147. {
  148. // We don't need to check if the entityIndex is a part of the dictionary.
  149. // The Remove function will check for us.
  150. _indexToEntityId.Remove(entityIndex);
  151. }
  152. // We don't need to check if the entityID is part of the dictionary.
  153. // The Remove function will check for us.
  154. _entityIDToDenseIndex.Remove(entityId);
  155. }
  156. internal void Clear()
  157. {
  158. _indexToEntityId.FastClear();
  159. _entityIDToDenseIndex.FastClear();
  160. }
  161. internal void Dispose()
  162. {
  163. _entityIDToDenseIndex.Dispose();
  164. _indexToEntityId.Dispose();
  165. }
  166. internal ExclusiveGroupStruct group => _group;
  167. SharedSveltoDictionaryNative<uint, uint> _indexToEntityId;
  168. internal SharedSveltoDictionaryNative<uint, uint> _entityIDToDenseIndex;
  169. readonly ExclusiveGroupStruct _group;
  170. }
  171. }
  172. }