Mirror of Svelto.ECS because we're a fan of it
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

307 linhas
13KB

  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using Svelto.DataStructures;
  4. using Svelto.Utilities;
  5. namespace Svelto.ECS
  6. {
  7. class EntitiesOperations
  8. {
  9. /// <summary>
  10. /// Todo: need to go back here and add a ton of comments
  11. /// </summary>
  12. public EntitiesOperations()
  13. {
  14. _thisSubmissionInfo.Init();
  15. _lastSubmittedInfo.Init();
  16. _newGroupDictionary = NewGroupDictionary;
  17. _newGroupsDictionary = NewGroupsDictionary;
  18. _recycleDictionary = RecycleDictionary;
  19. _newList = NewList;
  20. _clearList = ClearList;
  21. _newGroupsDictionaryWithCaller = NewGroupsDictionaryWithCaller;
  22. _recycleGroupDictionaryWithCaller = RecycleGroupDictionaryWithCaller;
  23. _recycleDicitionaryWithCaller = RecycleDicitionaryWithCaller;
  24. _newListWithCaller = NewListWithCaller;
  25. _clearListWithCaller = ClearListWithCaller;
  26. }
  27. public void QueueRemoveGroupOperation(ExclusiveBuildGroup groupID, string caller)
  28. {
  29. _thisSubmissionInfo._groupsToRemove.Add((groupID, caller));
  30. }
  31. public void QueueRemoveOperation(EGID fromEgid, IComponentBuilder[] componentBuilders, string caller)
  32. {
  33. _thisSubmissionInfo._entitiesRemoved.Add(fromEgid);
  34. RevertSwapOperation(fromEgid);
  35. //todo: limit the number of dictionaries that can be cached
  36. //recycle or create dictionaries of components per group
  37. var removedComponentsPerType = _thisSubmissionInfo._currentRemoveEntitiesOperations.RecycleOrAdd(
  38. fromEgid.groupID, _newGroupsDictionary, _recycleDictionary);
  39. foreach (var operation in componentBuilders)
  40. {
  41. removedComponentsPerType //recycle or create dictionaries per component type
  42. .RecycleOrAdd(operation.getComponentID, _newList, _clearList)
  43. //add entity to remove
  44. .Add((fromEgid.entityID, caller));
  45. }
  46. void RevertSwapOperation(EGID fromEgid)
  47. {
  48. if (_thisSubmissionInfo._entitiesSwapped.Remove(fromEgid, out (EGID fromEgid, EGID toEgid) val)) //Remove supersedes swap, check comment in IEntityFunctions.cs
  49. {
  50. var swappedComponentsPerType = _thisSubmissionInfo._currentSwapEntitiesOperations[fromEgid.groupID];
  51. var componentBuildersLength = componentBuilders.Length - 1;
  52. for (var index = componentBuildersLength; index >= 0; index--)
  53. {
  54. var operation = componentBuilders[index];
  55. //todo: maybe the order of swappedComponentsPerType should be fromID, toGroupID, componentID
  56. swappedComponentsPerType[operation.getComponentID][val.toEgid.groupID].Remove(fromEgid.entityID);
  57. }
  58. }
  59. }
  60. }
  61. public void QueueSwapGroupOperation(ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID, string caller)
  62. {
  63. _thisSubmissionInfo._groupsToSwap.Add((fromGroupID, toGroupID, caller));
  64. }
  65. public void QueueSwapOperation(EGID fromEGID, EGID toEGID, IComponentBuilder[] componentBuilders, string caller)
  66. {
  67. _thisSubmissionInfo._entitiesSwapped.Add(fromEGID, (fromEGID, toEGID));
  68. //todo: limit the number of dictionaries that can be cached
  69. //Get (or create) the dictionary that holds the entities that are swapping from fromEGID group
  70. var swappedComponentsPerType = _thisSubmissionInfo._currentSwapEntitiesOperations.RecycleOrAdd(
  71. fromEGID.groupID, _newGroupsDictionaryWithCaller, _recycleGroupDictionaryWithCaller);
  72. var componentBuildersLength = componentBuilders.Length - 1;
  73. //for each component of the entity that is swapping
  74. for (var index = componentBuildersLength; index >= 0; index--)
  75. {
  76. var operation = componentBuilders[index];
  77. //Get the dictionary for each component that holds the list of entities to swap
  78. swappedComponentsPerType
  79. //recycle or create dictionaries per component type
  80. .RecycleOrAdd(operation.getComponentID, _newGroupDictionary, _recycleDicitionaryWithCaller)
  81. //recycle or create list of entities to swap
  82. .RecycleOrAdd(toEGID.groupID, _newListWithCaller, _clearListWithCaller)
  83. //add entity to swap
  84. .Add(fromEGID.entityID, new SwapInfo(fromEGID.entityID, toEGID.entityID, caller));
  85. }
  86. }
  87. [MethodImpl(MethodImplOptions.Synchronized)]
  88. public bool AnyOperationQueued()
  89. {
  90. return _thisSubmissionInfo.AnyOperationQueued();
  91. }
  92. public void ExecuteRemoveAndSwappingOperations(
  93. Action<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>>, FasterDictionary<EGID, (EGID, EGID)>, EnginesRoot> swapEntities, Action<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<ComponentID, FasterList<(uint, string)>>>,
  94. FasterList<EGID>, EnginesRoot> removeEntities, Action<ExclusiveGroupStruct, EnginesRoot> removeGroup,
  95. Action<ExclusiveGroupStruct, ExclusiveGroupStruct, EnginesRoot> swapGroup, EnginesRoot enginesRoot)
  96. {
  97. (_thisSubmissionInfo, _lastSubmittedInfo) = (_lastSubmittedInfo, _thisSubmissionInfo);
  98. /// todo: entity references should be updated before calling all the methods to avoid callbacks handling
  99. /// references that should be marked as invalid.
  100. foreach (var (group, caller) in _lastSubmittedInfo._groupsToRemove)
  101. try
  102. {
  103. removeGroup(group, enginesRoot);
  104. }
  105. catch
  106. {
  107. var str = "Crash while removing a whole group on ".FastConcat(group.ToString())
  108. .FastConcat(" from : ", caller);
  109. Console.LogError(str);
  110. throw;
  111. }
  112. foreach (var (fromGroup, toGroup, caller) in _lastSubmittedInfo._groupsToSwap)
  113. try
  114. {
  115. swapGroup(fromGroup, toGroup, enginesRoot);
  116. }
  117. catch
  118. {
  119. var str = "Crash while swapping a whole group on "
  120. .FastConcat(fromGroup.ToString(), " ", toGroup.ToString()).FastConcat(" from : ", caller);
  121. Console.LogError(str);
  122. throw;
  123. }
  124. if (_lastSubmittedInfo._entitiesSwapped.count > 0)
  125. swapEntities(_lastSubmittedInfo._currentSwapEntitiesOperations, _lastSubmittedInfo._entitiesSwapped, enginesRoot);
  126. if (_lastSubmittedInfo._entitiesRemoved.count > 0)
  127. removeEntities(
  128. _lastSubmittedInfo._currentRemoveEntitiesOperations, _lastSubmittedInfo._entitiesRemoved
  129. , enginesRoot);
  130. _lastSubmittedInfo.Clear();
  131. }
  132. static FasterDictionary<ComponentID, FasterList<(uint, string)>> NewGroupsDictionary()
  133. {
  134. return new FasterDictionary<ComponentID, FasterList<(uint, string)>>();
  135. }
  136. static void RecycleDictionary(ref FasterDictionary<ComponentID, FasterList<(uint, string)>> recycled)
  137. {
  138. recycled.Recycle();
  139. }
  140. static FasterList<(uint, string)> NewList()
  141. {
  142. return new FasterList<(uint, string)>();
  143. }
  144. static void ClearList(ref FasterList<(uint, string)> target)
  145. {
  146. target.Clear();
  147. }
  148. static void RecycleDicitionaryWithCaller(ref FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>> target)
  149. {
  150. target.Recycle();
  151. }
  152. static void ClearListWithCaller(ref FasterDictionary<uint, SwapInfo> target)
  153. {
  154. target.Clear();
  155. }
  156. static FasterDictionary<uint, SwapInfo> NewListWithCaller()
  157. {
  158. return new FasterDictionary<uint, SwapInfo>();
  159. }
  160. static FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>
  161. NewGroupsDictionaryWithCaller()
  162. {
  163. return new FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>();
  164. }
  165. static void RecycleGroupDictionaryWithCaller(
  166. ref FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>> recycled)
  167. {
  168. recycled.Recycle();
  169. }
  170. static FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>> NewGroupDictionary()
  171. {
  172. return new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>();
  173. }
  174. struct Info
  175. {
  176. //from group //actual component type
  177. internal FasterDictionary<ExclusiveGroupStruct, FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>> _currentSwapEntitiesOperations;
  178. internal FasterDictionary<ExclusiveGroupStruct,
  179. FasterDictionary<ComponentID, FasterList<(uint, string)>>> _currentRemoveEntitiesOperations;
  180. internal FasterDictionary<EGID, (EGID fromEgid, EGID toEgid)> _entitiesSwapped;
  181. internal FasterList<EGID> _entitiesRemoved;
  182. public FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)> _groupsToSwap;
  183. public FasterList<(ExclusiveBuildGroup, string)> _groupsToRemove;
  184. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  185. internal bool AnyOperationQueued()
  186. {
  187. return _entitiesSwapped.count > 0 || _entitiesRemoved.count > 0 || _groupsToSwap.count > 0
  188. || _groupsToRemove.count > 0;
  189. }
  190. internal void Clear()
  191. {
  192. _currentSwapEntitiesOperations.Recycle();
  193. _currentRemoveEntitiesOperations.Recycle();
  194. _entitiesSwapped.Clear();
  195. _entitiesRemoved.Clear();
  196. _groupsToRemove.Clear();
  197. _groupsToSwap.Clear();
  198. }
  199. internal void Init()
  200. {
  201. _entitiesSwapped = new FasterDictionary<EGID, (EGID fromEgid, EGID toEgid)>();
  202. _entitiesRemoved = new FasterList<EGID>();
  203. _groupsToRemove = new FasterList<(ExclusiveBuildGroup, string)>();
  204. _groupsToSwap = new FasterList<(ExclusiveBuildGroup, ExclusiveBuildGroup, string)>();
  205. _currentSwapEntitiesOperations =
  206. new FasterDictionary<ExclusiveGroupStruct, FasterDictionary<ComponentID,
  207. FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>>();
  208. _currentRemoveEntitiesOperations =
  209. new FasterDictionary<ExclusiveGroupStruct,
  210. FasterDictionary<ComponentID, FasterList<(uint, string)>>>();
  211. }
  212. }
  213. Info _lastSubmittedInfo;
  214. Info _thisSubmissionInfo;
  215. readonly Func<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>> _newGroupDictionary;
  216. readonly Func<FasterDictionary<ComponentID, FasterList<(uint, string)>>> _newGroupsDictionary;
  217. readonly ActionRef<FasterDictionary<ComponentID, FasterList<(uint, string)>>> _recycleDictionary;
  218. readonly Func<FasterList<(uint, string)>> _newList;
  219. readonly ActionRef<FasterList<(uint, string)>> _clearList;
  220. readonly Func<FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>>
  221. _newGroupsDictionaryWithCaller;
  222. readonly ActionRef<FasterDictionary<ComponentID, FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>>>
  223. _recycleGroupDictionaryWithCaller;
  224. readonly ActionRef<FasterDictionary<ExclusiveGroupStruct, FasterDictionary<uint, SwapInfo>>> _recycleDicitionaryWithCaller;
  225. readonly Func<FasterDictionary<uint, SwapInfo>> _newListWithCaller;
  226. readonly ActionRef<FasterDictionary<uint, SwapInfo>> _clearListWithCaller;
  227. }
  228. public struct SwapInfo
  229. {
  230. public uint fromID; //to do this information should be redundant, try to remove it
  231. public uint toID;
  232. public uint toIndex;
  233. public string trace;
  234. public SwapInfo(uint fromEgidEntityId, uint toEgidEntityId, string s)
  235. {
  236. fromID = fromEgidEntityId;
  237. toID = toEgidEntityId;
  238. toIndex = 0;
  239. trace = s;
  240. }
  241. public void Deconstruct(out uint fromID, out uint toID, out uint toIndex, out string caller)
  242. {
  243. fromID = this.fromID;
  244. toID = this.toID;
  245. toIndex = this.toIndex;
  246. caller = this.trace;
  247. }
  248. public void Deconstruct(out uint fromID, out uint toID, out string caller)
  249. {
  250. fromID = this.fromID;
  251. toID = this.toID;
  252. caller = this.trace;
  253. }
  254. }
  255. }