Mirror of Svelto.ECS because we're a fan of it
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

191 рядки
9.2KB

  1. using System;
  2. using Svelto.DataStructures;
  3. namespace Svelto.ECS
  4. {
  5. class EntitiesOperations
  6. {
  7. public EntitiesOperations()
  8. {
  9. _thisSubmissionInfo.Init();
  10. _lastSubmittedInfo.Init();
  11. }
  12. public void AddSwapOperation(EGID fromID, EGID toID, IComponentBuilder[] componentBuilders, string caller)
  13. {
  14. _thisSubmissionInfo._entitiesSwapped.Add((fromID, toID));
  15. //todo: limit the number of dictionaries that can be cached
  16. //recycle or create dictionaries of components per group
  17. var swappedComponentsPerType = _thisSubmissionInfo._currentSwapEntitiesOperations.RecycleOrAdd(
  18. fromID.groupID,
  19. () => new FasterDictionary<RefWrapperType,
  20. FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>>(),
  21. (ref FasterDictionary<RefWrapperType, FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>> recycled) =>
  22. recycled.FastClear());
  23. foreach (IComponentBuilder operation in componentBuilders)
  24. {
  25. swappedComponentsPerType
  26. //recycle or create dictionaries per component type
  27. .RecycleOrAdd(new RefWrapperType(operation.GetEntityComponentType()),
  28. () => new FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>(),
  29. (ref FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>> target) =>
  30. target.FastClear())
  31. //recycle or create list of entities to swap
  32. .RecycleOrAdd(toID.groupID, () => new FasterList<(uint, uint, string)>(),
  33. (ref FasterList<(uint, uint, string)> target) => target.FastClear())
  34. //add entity to swap
  35. .Add((fromID.entityID, toID.entityID, caller));
  36. }
  37. }
  38. public void AddRemoveOperation(EGID entityEgid, IComponentBuilder[] componentBuilders, string caller)
  39. {
  40. _thisSubmissionInfo._entitiesRemoved.Add(entityEgid);
  41. //todo: limit the number of dictionaries that can be cached
  42. //recycle or create dictionaries of components per group
  43. var removedComponentsPerType = _thisSubmissionInfo._currentRemoveEntitiesOperations.RecycleOrAdd(
  44. entityEgid.groupID, () => new FasterDictionary<RefWrapperType, FasterList<(uint, string)>>(),
  45. (ref FasterDictionary<RefWrapperType, FasterList<(uint, string)>> recycled) => recycled.FastClear());
  46. foreach (IComponentBuilder operation in componentBuilders)
  47. {
  48. removedComponentsPerType
  49. //recycle or create dictionaries per component type
  50. .RecycleOrAdd(new RefWrapperType(operation.GetEntityComponentType()),
  51. () => new FasterList<(uint, string)>(),
  52. (ref FasterList<(uint, string)> target) => target.FastClear())
  53. //add entity to swap
  54. .Add((entityEgid.entityID, caller));
  55. }
  56. }
  57. public void AddRemoveGroupOperation(ExclusiveBuildGroup groupID, string caller)
  58. {
  59. _thisSubmissionInfo._groupsToRemove.Add((groupID, caller));
  60. }
  61. public void AddSwapGroupOperation(ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID, string caller)
  62. {
  63. _thisSubmissionInfo._groupsToSwap.Add((fromGroupID, toGroupID, caller));
  64. }
  65. public void ExecuteRemoveAndSwappingOperations(
  66. Action<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType,
  67. FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>>>, FasterList<(EGID, EGID)>
  68. ,
  69. EnginesRoot> swapEntities,
  70. Action<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType, FasterList<(uint, string)>>>,
  71. FasterList<EGID>, EnginesRoot> removeEntities, Action<ExclusiveGroupStruct, EnginesRoot> removeGroup,
  72. Action<ExclusiveGroupStruct, ExclusiveGroupStruct, EnginesRoot> swapGroup, EnginesRoot enginesRoot)
  73. {
  74. (_thisSubmissionInfo, _lastSubmittedInfo) = (_lastSubmittedInfo, _thisSubmissionInfo);
  75. ///todo: we found a case where entities with reference to other entities were removed
  76. /// in the same frame where the referenced entities are remove too.
  77. /// the callback of the referencing entities were assuming that the reference at that point
  78. /// would be invalid. However since the callbacks were called before the groups are removed
  79. /// the reference were still valid, which was not expected.
  80. /// If the referenced entities were removed one by one instead that with the group, by chance
  81. /// it instead worked because the entities were removed before the callbacks were called.
  82. /// this is why RemoveGroup is happeing before RemoveEntities, however the real fix
  83. /// should be to update all the references before removing the entities from the dictionaries
  84. /// and call the callbacks
  85. foreach (var (group, caller) in _lastSubmittedInfo._groupsToRemove)
  86. {
  87. try
  88. {
  89. removeGroup(group, enginesRoot);
  90. }
  91. catch
  92. {
  93. var str = "Crash while removing a whole group on ".FastConcat(group.ToString())
  94. .FastConcat(" from : ", caller);
  95. Console.LogError(str);
  96. throw;
  97. }
  98. }
  99. foreach (var (fromGroup, toGroup, caller) in _lastSubmittedInfo._groupsToSwap)
  100. {
  101. try
  102. {
  103. swapGroup(fromGroup, toGroup, enginesRoot);
  104. }
  105. catch
  106. {
  107. var str = "Crash while swapping a whole group on "
  108. .FastConcat(fromGroup.ToString(), " ", toGroup.ToString()).FastConcat(" from : ", caller);
  109. Console.LogError(str);
  110. throw;
  111. }
  112. }
  113. if (_lastSubmittedInfo._entitiesSwapped.count > 0)
  114. swapEntities(_lastSubmittedInfo._currentSwapEntitiesOperations, _lastSubmittedInfo._entitiesSwapped,
  115. enginesRoot);
  116. if (_lastSubmittedInfo._entitiesRemoved.count > 0)
  117. removeEntities(_lastSubmittedInfo._currentRemoveEntitiesOperations, _lastSubmittedInfo._entitiesRemoved,
  118. enginesRoot);
  119. _lastSubmittedInfo.Clear();
  120. }
  121. public bool AnyOperationQueued() => _thisSubmissionInfo.AnyOperationQueued();
  122. struct Info
  123. {
  124. //from group //actual component type
  125. internal FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType,
  126. // to group ID //entityIDs , debugInfo
  127. FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>>>
  128. _currentSwapEntitiesOperations;
  129. internal FasterDictionary<ExclusiveGroupStruct,
  130. FasterDictionary<RefWrapperType, FasterList<(uint, string)>>> _currentRemoveEntitiesOperations;
  131. internal FasterList<(EGID, EGID)> _entitiesSwapped;
  132. internal FasterList<EGID> _entitiesRemoved;
  133. public FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)> _groupsToSwap;
  134. public FasterList<(ExclusiveBuildGroup, string)> _groupsToRemove;
  135. internal bool AnyOperationQueued() =>
  136. _entitiesSwapped.count > 0 || _entitiesRemoved.count > 0 || _groupsToSwap.count > 0 ||
  137. _groupsToRemove.count > 0;
  138. internal void Clear()
  139. {
  140. _currentSwapEntitiesOperations.FastClear();
  141. _currentRemoveEntitiesOperations.FastClear();
  142. _entitiesSwapped.FastClear();
  143. _entitiesRemoved.FastClear();
  144. _groupsToRemove.FastClear();
  145. _groupsToSwap.FastClear();
  146. }
  147. internal void Init()
  148. {
  149. _entitiesSwapped = new FasterList<(EGID, EGID)>();
  150. _entitiesRemoved = new FasterList<EGID>();
  151. _groupsToRemove = new FasterList<(ExclusiveBuildGroup, string)>();
  152. _groupsToSwap = new FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)>();
  153. _currentSwapEntitiesOperations =
  154. new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType,
  155. FasterDictionary<ExclusiveGroupStruct, FasterList<(uint, uint, string)>>>>();
  156. _currentRemoveEntitiesOperations =
  157. new FasterDictionary<ExclusiveGroupStruct,
  158. FasterDictionary<RefWrapperType, FasterList<(uint, string)>>>();
  159. }
  160. }
  161. Info _thisSubmissionInfo;
  162. Info _lastSubmittedInfo;
  163. }
  164. }