Mirror of Svelto.ECS because we're a fan of it
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

190 行
9.4KB

  1. using Svelto.DataStructures;
  2. using Svelto.DataStructures.Native;
  3. using Svelto.ECS.Internal;
  4. namespace Svelto.ECS
  5. {
  6. public partial class EnginesRoot
  7. {
  8. void InitFilters()
  9. {
  10. _transientEntityFilters = new SharedSveltoDictionaryNative<long, EntityFilterCollection>(0);
  11. _persistentEntityFilters = new SharedSveltoDictionaryNative<long, EntityFilterCollection>(0);
  12. _indicesOfPersistentFiltersUsedByThisComponent =
  13. new SharedSveltoDictionaryNative<NativeRefWrapperType, NativeDynamicArrayCast<int>>(0);
  14. }
  15. void DisposeFilters()
  16. {
  17. foreach (var filter in _transientEntityFilters)
  18. {
  19. filter.value.Dispose();
  20. }
  21. foreach (var filter in _persistentEntityFilters)
  22. {
  23. filter.value.Dispose();
  24. }
  25. foreach (var filter in _indicesOfPersistentFiltersUsedByThisComponent)
  26. {
  27. filter.value.Dispose();
  28. }
  29. _transientEntityFilters.Dispose();
  30. _persistentEntityFilters.Dispose();
  31. _indicesOfPersistentFiltersUsedByThisComponent.Dispose();
  32. }
  33. void ClearTransientFilters()
  34. {
  35. foreach (var filter in _transientEntityFilters)
  36. {
  37. filter.value.Clear();
  38. }
  39. }
  40. /// <summary>
  41. /// Persistent filters are automatically updated by the framework. If entities are removed from the database
  42. /// the filters are updated consequentially.
  43. /// </summary>
  44. /// <param name="entityIDsRemoved"></param>
  45. /// <param name="fromGroup"></param>
  46. /// <param name="refWrapperType"></param>
  47. /// <param name="fromDic"></param>
  48. /// <param name="entityIDsLeftAndAffectedByRemoval"></param>
  49. void RemoveEntitiesFromPersistentFilters
  50. (FasterList<(uint entityID, string)> entityIDsRemoved, ExclusiveGroupStruct fromGroup, RefWrapperType refWrapperType
  51. , ITypeSafeDictionary fromDic, FasterList<uint> entityIDsLeftAndAffectedByRemoval)
  52. {
  53. //is there any filter used by this component?
  54. if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue(
  55. new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast<int> listOfFilters) == true)
  56. {
  57. var numberOfFilters = listOfFilters.count;
  58. var filters = _persistentEntityFilters.unsafeValues;
  59. //remove duplicates
  60. _transientEntityIDsLeftWithoutDuplicates.Clear();
  61. var entityAffectedCount = entityIDsLeftAndAffectedByRemoval.count;
  62. for (int i = 0; i < entityAffectedCount; i++)
  63. {
  64. _transientEntityIDsLeftWithoutDuplicates[entityIDsLeftAndAffectedByRemoval[i]] = -1;
  65. }
  66. for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex)
  67. {
  68. //foreach filter linked to this component
  69. var persistentFiltersPerGroup = filters[listOfFilters[filterIndex]]._filtersPerGroup;
  70. //get the filter linked to this group
  71. if (persistentFiltersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter))
  72. {
  73. var entitiesCount = entityIDsRemoved.count;
  74. //foreach entity to remove, remove it from the filter (if present)
  75. for (int entityIndex = 0; entityIndex < entitiesCount; ++entityIndex)
  76. {
  77. //the current entity id to remove
  78. uint fromEntityID = entityIDsRemoved[entityIndex].entityID;
  79. fromGroupFilter.Remove(fromEntityID); //Remove works even if the ID is not found (just returns false)
  80. }
  81. //when a component is removed from a component array, a remove swap back happens. This means
  82. //that not only we have to remove the index of the component of the entity deleted from the array
  83. //but we need also to update the index of the component that has been swapped in the cell
  84. //of the deleted component
  85. //entityIDsAffectedByRemoval tracks all the entitiesID of the components that need to be updated
  86. //in the filters because their indices in the array changed.
  87. foreach (var entity in _transientEntityIDsLeftWithoutDuplicates)
  88. {
  89. var entityId = entity.key;
  90. if (fromGroupFilter.Exists(entityId)) //does the entityID that has been swapped exist in the filter?
  91. {
  92. if (entity.value == -1)
  93. entity.value = (int)fromDic.GetIndex(entityId); //let's find the index of the entityID in the dictionary only once
  94. fromGroupFilter._entityIDToDenseIndex[entityId] = (uint) entity.value; //update the index in the filter of the component that has been swapped
  95. }
  96. }
  97. }
  98. }
  99. }
  100. }
  101. //this method is called by the framework only if listOfFilters.count > 0
  102. void SwapEntityBetweenPersistentFilters
  103. (FasterList<(uint, uint, string)> fromEntityToEntityIDs, ITypeSafeDictionary fromDic
  104. , ITypeSafeDictionary toDic, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup
  105. , RefWrapperType refWrapperType, FasterList<uint> entityIDsLeftAndAffectedByRemoval)
  106. {
  107. //is there any filter used by this component?
  108. if (_indicesOfPersistentFiltersUsedByThisComponent.TryGetValue(
  109. new NativeRefWrapperType(refWrapperType), out NativeDynamicArrayCast<int> listOfFilters) == true)
  110. {
  111. DBC.ECS.Check.Require(listOfFilters.count > 0, "why are you calling this with an empty list?");
  112. var numberOfFilters = listOfFilters.count;
  113. //remove duplicates
  114. _transientEntityIDsLeftWithoutDuplicates.Clear();
  115. var entityAffectedCount = entityIDsLeftAndAffectedByRemoval.count;
  116. for (int i = 0; i < entityAffectedCount; i++)
  117. {
  118. _transientEntityIDsLeftWithoutDuplicates[entityIDsLeftAndAffectedByRemoval[i]] = -1;
  119. }
  120. /// fromEntityToEntityIDs are the IDs of the entities to swap from the from group to the to group.
  121. /// for this component type. for each component type, there is only one set of fromEntityToEntityIDs
  122. /// per from/to group.
  123. for (int filterIndex = 0; filterIndex < numberOfFilters; ++filterIndex)
  124. {
  125. //if the group has a filter linked:
  126. EntityFilterCollection persistentFilter =
  127. _persistentEntityFilters.unsafeValues[listOfFilters[filterIndex]];
  128. if (persistentFilter._filtersPerGroup.TryGetValue(fromGroup, out var fromGroupFilter))
  129. {
  130. EntityFilterCollection.GroupFilters groupFilterTo = default;
  131. foreach (var (fromEntityID, toEntityID, _) in fromEntityToEntityIDs)
  132. {
  133. var toIndex = toDic.GetIndex(toEntityID); //todo: optimize this should be calculated only once and not once per filter
  134. //if there is an entity, it must be moved to the to filter
  135. if (fromGroupFilter.Exists(fromEntityID) == true)
  136. {
  137. if (groupFilterTo.isValid == false)
  138. groupFilterTo = persistentFilter.GetOrCreateGroupFilter(toGroup);
  139. groupFilterTo.Add(toEntityID, toIndex);
  140. }
  141. }
  142. foreach (var (fromEntityID, _, _) in fromEntityToEntityIDs)
  143. {
  144. fromGroupFilter.Remove(fromEntityID); //Remove works even if the ID is not found (just returns false)
  145. }
  146. foreach (var entity in _transientEntityIDsLeftWithoutDuplicates)
  147. {
  148. var entityId = entity.key;
  149. if (fromGroupFilter.Exists(entityId))
  150. {
  151. if (entity.value == -1)
  152. entity.value = (int)fromDic.GetIndex(entityId);
  153. fromGroupFilter._entityIDToDenseIndex[entityId] = (uint) entity.value;
  154. }
  155. }
  156. }
  157. }
  158. }
  159. }
  160. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _transientEntityFilters;
  161. internal SharedSveltoDictionaryNative<long, EntityFilterCollection> _persistentEntityFilters;
  162. internal SharedSveltoDictionaryNative<NativeRefWrapperType, NativeDynamicArrayCast<int>>
  163. _indicesOfPersistentFiltersUsedByThisComponent;
  164. }
  165. }