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.

189 lines
9.8KB

  1. using Svelto.DataStructures;
  2. using Svelto.DataStructures.Native;
  3. using Svelto.ECS.DataStructures;
  4. using Svelto.ECS.Internal;
  5. namespace Svelto.ECS
  6. {
  7. public partial class EnginesRoot
  8. {
  9. void InitFilters()
  10. {
  11. _transientEntityFilters = new SharedSveltoDictionaryNative<long, EntityFilterCollection>(0);
  12. _persistentEntityFilters = new SharedSveltoDictionaryNative<long, EntityFilterCollection>(0);
  13. _indicesOfPersistentFiltersUsedByThisComponent =
  14. new SharedSveltoDictionaryNative<NativeRefWrapperType, NativeDynamicArrayCast<int>>(0);
  15. }
  16. void DisposeFilters()
  17. {
  18. foreach (var filter in _transientEntityFilters)
  19. {
  20. filter.value.Dispose();
  21. }
  22. foreach (var filter in _persistentEntityFilters)
  23. {
  24. filter.value.Dispose();
  25. }
  26. foreach (var filter in _indicesOfPersistentFiltersUsedByThisComponent)
  27. {
  28. filter.value.Dispose();
  29. }
  30. _transientEntityFilters.Dispose();
  31. _persistentEntityFilters.Dispose();
  32. _indicesOfPersistentFiltersUsedByThisComponent.Dispose();
  33. }
  34. void ClearTransientFilters()
  35. {
  36. foreach (var filter in _transientEntityFilters)
  37. {
  38. filter.value.Clear();
  39. }
  40. }
  41. void RemoveEntityFromPersistentFilters(FasterList<(uint, string)> entityIDs, ExclusiveGroupStruct fromGroup,
  42. RefWrapperType refWrapperType, ITypeSafeDictionary fromDic)
  43. {
  44. //is there any filter used by this component?
  45. if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue(new NativeRefWrapperType(refWrapperType),
  46. out NativeDynamicArrayCast<int> listOfFilters))
  47. {
  48. var numberOfFilters = listOfFilters.count;
  49. for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex)
  50. {
  51. //we are going to remove multiple entities, this means that the dictionary count would decrease
  52. //for each entity removed from each filter
  53. //we need to keep a copy to reset to the original count for each filter
  54. var currentLastIndex = (uint)fromDic.count - 1;
  55. var filters = _persistentEntityFilters.unsafeValues;
  56. var persistentFilter = filters[listOfFilters[filterIndex]]._filtersPerGroup;
  57. if (persistentFilter.TryGetValue(fromGroup, out var groupFilter))
  58. {
  59. var entitiesCount = entityIDs.count;
  60. _filtersSwapBackIndexByEntityID.FastClear();
  61. _filtersSwapBackEntityIDByIndex.FastClear();
  62. for (var entityIndex = 0; entityIndex < entitiesCount; ++entityIndex)
  63. {
  64. var index = fromDic.GetIndex(entityIDs[entityIndex].Item1);
  65. _filtersSwapBackIndexByEntityID.Add(entityIDs[entityIndex].Item1, index);
  66. _filtersSwapBackEntityIDByIndex.Add(index, entityIDs[entityIndex].Item1);
  67. }
  68. for (int entityIndex = 0; entityIndex < entitiesCount; ++entityIndex)
  69. {
  70. uint fromentityID = entityIDs[entityIndex].Item1;
  71. var fromIndex = _filtersSwapBackIndexByEntityID[fromentityID];
  72. if (_filtersSwapBackEntityIDByIndex.TryGetValue(currentLastIndex, out var lastEntityID))
  73. _filtersSwapBackIndexByEntityID[lastEntityID] = fromIndex;
  74. groupFilter.RemoveWithSwapBack(fromentityID, fromIndex, currentLastIndex--);
  75. }
  76. }
  77. }
  78. }
  79. }
  80. //this method is called by the framework only if listOfFilters.count > 0
  81. void SwapEntityBetweenPersistentFilters(FasterList<(uint, uint, string)> fromEntityToEntityIDs,
  82. FasterDictionary<uint, uint> beforeSubmissionFromIDs, ITypeSafeDictionary toComponentsDictionary,
  83. ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, uint fromDictionaryCount,
  84. NativeDynamicArrayCast<int> listOfFilters)
  85. {
  86. DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?");
  87. var numberOfFilters = listOfFilters.count;
  88. /// fromEntityToEntityIDs are the ID of the entities to swap from the from group to the to group.
  89. /// for this component type. for each component type, there is only one set of fromEntityToEntityIDs
  90. /// per from/to group.
  91. /// The complexity of this function is that the ToDictionary is already updated, so the toIndex
  92. /// is actually correct and guaranteed to be valid. However the beforeSubmissionFromIDs are the
  93. /// indices of the entities in the FromDictionary BEFORE the submission happens, so before the
  94. /// entities are actually removed from the dictionary.
  95. for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex)
  96. {
  97. //we are going to remove multiple entities, this means that the dictionary count would decrease
  98. //for each entity removed from each filter
  99. //we need to keep a copy to reset to the original count for each filter
  100. var currentLastIndex = fromDictionaryCount;
  101. //if the group has a filter linked:
  102. EntityFilterCollection persistentFilter =
  103. _persistentEntityFilters.unsafeValues[listOfFilters[filterIndex]];
  104. if (persistentFilter._filtersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter))
  105. {
  106. EntityFilterCollection.GroupFilters groupFilterTo = default;
  107. foreach (var (fromEntityID, toEntityID, _) in fromEntityToEntityIDs)
  108. {
  109. //if there is an entity, it must be moved to the to filter
  110. if (fromGroupFilter.Exists(fromEntityID) == true)
  111. {
  112. var toIndex = toComponentsDictionary.GetIndex(toEntityID);
  113. if (groupFilterTo.isValid == false)
  114. groupFilterTo = persistentFilter.GetGroupFilter(toGroup);
  115. groupFilterTo.Add(toEntityID, toIndex);
  116. }
  117. }
  118. _filtersSwapBackIndexByEntityID.FastClear();
  119. _filtersSwapBackEntityIDByIndex.FastClear();
  120. foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs)
  121. {
  122. uint fromIndex; //index in the from dictionary
  123. if (fromGroupFilter.Exists(fromEntityID))
  124. fromIndex = fromGroupFilter._entityIDToDenseIndex[fromEntityID];
  125. else
  126. fromIndex = beforeSubmissionFromIDs[fromEntityID];
  127. _filtersSwapBackIndexByEntityID.Add(fromEntityID, fromIndex);
  128. _filtersSwapBackEntityIDByIndex.Add(fromIndex, fromEntityID);
  129. }
  130. foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs)
  131. {
  132. //fromIndex is the same of the index in the filter if the entity is in the filter, but
  133. //we need to update the entity index of the last entity swapped from the dictionary even
  134. //in the case when the fromEntity is not present in the filter.
  135. uint fromIndex = _filtersSwapBackIndexByEntityID[fromEntityID]; //index in the from dictionary
  136. if (_filtersSwapBackEntityIDByIndex.TryGetValue(currentLastIndex, out var lastEntityID))
  137. _filtersSwapBackIndexByEntityID[lastEntityID] = fromIndex;
  138. //Removing an entity from the dictionary may affect the index of the last entity in the
  139. //values dictionary array, so we need to to update the indices of the affected entities.
  140. //must be outside because from may not be present in the filter, but last index is
  141. //for each entity removed from the from group, I have to update it's index in the
  142. //from filter. An entity removed from the DB is always swapped back, which means
  143. //it's current position is taken by the last entity in the dictionary array.
  144. //this means that the index of the last entity will change to the index of the
  145. //replaced entity
  146. fromGroupFilter.RemoveWithSwapBack(fromEntityID, fromIndex, currentLastIndex--);
  147. }
  148. }
  149. }
  150. }
  151. FasterDictionary<uint, uint> _filtersSwapBackIndexByEntityID = new FasterDictionary<uint, uint>();
  152. FasterDictionary<uint, uint> _filtersSwapBackEntityIDByIndex = new FasterDictionary<uint, uint>();
  153. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _transientEntityFilters;
  154. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _persistentEntityFilters;
  155. internal SharedSveltoDictionaryNative<NativeRefWrapperType, NativeDynamicArrayCast<int>>
  156. _indicesOfPersistentFiltersUsedByThisComponent;
  157. }
  158. }