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.

160 lines
7.9KB

  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. for (int entityIndex = 0; entityIndex < entitiesCount; ++entityIndex)
  61. {
  62. uint fromentityID = entityIDs[entityIndex].Item1;
  63. var fromIndex = fromDic.GetIndex(fromentityID);
  64. groupFilter.RemoveWithSwapBack(fromentityID, fromIndex, currentLastIndex--);
  65. }
  66. }
  67. }
  68. }
  69. }
  70. //this method is called by the framework only if listOfFilters.count > 0
  71. void SwapEntityBetweenPersistentFilters(FasterList<(uint, uint, string)> fromEntityToEntityIDs,
  72. FasterDictionary<uint, uint> beforeSubmissionFromIDs, ITypeSafeDictionary toComponentsDictionary,
  73. ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, uint fromDictionaryCount,
  74. NativeDynamicArrayCast<int> listOfFilters)
  75. {
  76. DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?");
  77. var numberOfFilters = listOfFilters.count;
  78. /// fromEntityToEntityIDs are the ID of the entities to swap from the from group to the to group.
  79. /// for this component type. for each component type, there is only one set of fromEntityToEntityIDs
  80. /// per from/to group.
  81. /// The complexity of this function is that the ToDictionary is already updated, so the toIndex
  82. /// is actually correct and guaranteed to be valid. However the beforeSubmissionFromIDs are the
  83. /// indices of the entities in the FromDictionary BEFORE the submission happens, so before the
  84. /// entities are actually removed from the dictionary.
  85. for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex)
  86. {
  87. //we are going to remove multiple entities, this means that the dictionary count would decrease
  88. //for each entity removed from each filter
  89. //we need to keep a copy to reset to the original count for each filter
  90. var currentLastIndex = fromDictionaryCount;
  91. //if the group has a filter linked:
  92. EntityFilterCollection persistentFilter =
  93. _persistentEntityFilters.unsafeValues[listOfFilters[filterIndex]];
  94. if (persistentFilter._filtersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter))
  95. {
  96. EntityFilterCollection.GroupFilters groupFilterTo = default;
  97. foreach (var (fromEntityID, toEntityID, _) in fromEntityToEntityIDs)
  98. {
  99. //if there is an entity, it must be moved to the to filter
  100. if (fromGroupFilter.Exists(fromEntityID) == true)
  101. {
  102. var toIndex = toComponentsDictionary.GetIndex(toEntityID);
  103. if (groupFilterTo.isValid == false)
  104. groupFilterTo = persistentFilter.GetGroupFilter(toGroup);
  105. groupFilterTo.Add(toEntityID, toIndex);
  106. }
  107. }
  108. foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs)
  109. {
  110. //fromIndex is the same of the index in the filter if the entity is in the filter, but
  111. //we need to update the entity index of the last entity swapped from the dictionary even
  112. //in the case when the fromEntity is not present in the filter.
  113. uint fromIndex; //index in the from dictionary
  114. if (fromGroupFilter.Exists(fromEntityID))
  115. fromIndex = fromGroupFilter._entityIDToDenseIndex[fromEntityID];
  116. else
  117. fromIndex = beforeSubmissionFromIDs[fromEntityID];
  118. //Removing an entity from the dictionary may affect the index of the last entity in the
  119. //values dictionary array, so we need to to update the indices of the affected entities.
  120. //must be outside because from may not be present in the filter, but last index is
  121. //for each entity removed from the from group, I have to update it's index in the
  122. //from filter. An entity removed from the DB is always swapped back, which means
  123. //it's current position is taken by the last entity in the dictionary array.
  124. //this means that the index of the last entity will change to the index of the
  125. //replaced entity
  126. fromGroupFilter.RemoveWithSwapBack(fromEntityID, fromIndex, currentLastIndex--);
  127. }
  128. }
  129. }
  130. }
  131. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _transientEntityFilters;
  132. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _persistentEntityFilters;
  133. internal SharedSveltoDictionaryNative<NativeRefWrapperType, NativeDynamicArrayCast<int>>
  134. _indicesOfPersistentFiltersUsedByThisComponent;
  135. }
  136. }