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.

582 lines
27KB

  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using DBC.ECS;
  4. using Svelto.Common;
  5. using Svelto.DataStructures;
  6. namespace Svelto.ECS.Internal
  7. {
  8. public static class TypeSafeDictionaryMethods
  9. {
  10. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  11. public static void AddEntitiesToDictionary<Strategy1, Strategy2, Strategy3, TValue>(
  12. in SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  13. , ITypeSafeDictionary<TValue> toDic
  14. #if SLOW_SVELTO_SUBMISSION
  15. , in EnginesRoot.EntityReferenceMap entityLocator
  16. #endif
  17. , ExclusiveGroupStruct toGroupID)
  18. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  19. where Strategy2 : struct, IBufferStrategy<TValue>
  20. where Strategy3 : struct, IBufferStrategy<int>
  21. where TValue : struct, _IInternalEntityComponent
  22. {
  23. foreach (var tuple in fromDictionary)
  24. {
  25. #if SLOW_SVELTO_SUBMISSION
  26. var egid = new EGID(tuple.key, toGroupID);
  27. if (SlowSubmissionInfo<TValue>.hasEgid)
  28. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref tuple.value, egid);
  29. if (SlowSubmissionInfo<TValue>.hasReference)
  30. SetEGIDWithoutBoxing<TValue>.SetRefWithoutBoxing(
  31. ref tuple.value,
  32. entityLocator.GetEntityReference(egid));
  33. #endif
  34. try
  35. {
  36. toDic.Add(tuple.key, tuple.value);
  37. }
  38. catch (Exception e)
  39. {
  40. Console.LogException(
  41. e,
  42. "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString())
  43. .FastConcat(", group ").FastConcat(toGroupID.ToName()).FastConcat(", id ").FastConcat(tuple.key));
  44. throw;
  45. }
  46. #if PARANOID_CHECK && SLOW_SVELTO_SUBMISSION
  47. DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)fromDictionary[egid.entityID]).ID == egid, "impossible situation happened during swap");
  48. #endif
  49. }
  50. }
  51. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  52. public static void ExecuteEnginesAddCallbacks<Strategy1, Strategy2, Strategy3, TValue>(
  53. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  54. , ITypeSafeDictionary<TValue> todic, ExclusiveGroupStruct togroup
  55. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnAdd>>> entitycomponentenginesdb
  56. , in PlatformProfiler sampler)
  57. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  58. where Strategy2 : struct, IBufferStrategy<TValue>
  59. where Strategy3 : struct, IBufferStrategy<int>
  60. where TValue : struct, _IInternalEntityComponent
  61. {
  62. if (entitycomponentenginesdb.TryGetValue(
  63. ComponentTypeID<TValue>.id
  64. , out var entityComponentsEngines))
  65. {
  66. if (entityComponentsEngines.count == 0)
  67. return;
  68. var dictionaryKeyEnumerator = fromDictionary.unsafeKeys;
  69. var count = fromDictionary.count;
  70. for (var i = 0; i < count; ++i)
  71. try
  72. {
  73. var key = dictionaryKeyEnumerator[i].key;
  74. ref var entity = ref todic.GetValueByRef(key);
  75. var egid = new EGID(key, togroup);
  76. //get all the engines linked to TValue
  77. for (var j = 0; j < entityComponentsEngines.count; j++)
  78. using (sampler.Sample(entityComponentsEngines[j].name))
  79. {
  80. #pragma warning disable CS0612
  81. ((IReactOnAdd<TValue>)entityComponentsEngines[j].engine).Add(ref entity, egid);
  82. #pragma warning restore CS0612
  83. }
  84. }
  85. catch (Exception e)
  86. {
  87. Console.LogException(e, "Code crashed inside Add callback with Type ".FastConcat(TypeCache<TValue>.name));
  88. throw;
  89. }
  90. }
  91. }
  92. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  93. public static void ExecuteEnginesDisposeCallbacks_Group<Strategy1, Strategy2, Strategy3, TValue>(
  94. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  95. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnDispose>>> reactiveEnginesDispose
  96. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnDisposeEx>>> reactiveEnginesDisposeEx
  97. , IEntityIDs entityids, ExclusiveGroupStruct group, in PlatformProfiler sampler)
  98. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  99. where Strategy2 : struct, IBufferStrategy<TValue>
  100. where Strategy3 : struct, IBufferStrategy<int>
  101. where TValue : struct, _IInternalEntityComponent
  102. {
  103. if (reactiveEnginesDispose.TryGetValue(ComponentTypeID<TValue>.id, out var entityComponentsEngines)
  104. == false)
  105. return;
  106. for (var i = 0; i < entityComponentsEngines.count; i++)
  107. try
  108. {
  109. using (sampler.Sample(entityComponentsEngines[i].name))
  110. {
  111. foreach (var value in fromDictionary)
  112. {
  113. ref var entity = ref value.value;
  114. var egid = new EGID(value.key, group);
  115. var reactOnRemove = (IReactOnDispose<TValue>)entityComponentsEngines[i].engine;
  116. reactOnRemove.Remove(ref entity, egid);
  117. }
  118. }
  119. }
  120. catch
  121. {
  122. Console.LogError("Code crashed inside Remove callback ".FastConcat(entityComponentsEngines[i].name));
  123. throw;
  124. }
  125. var count = fromDictionary.count;
  126. if (reactiveEnginesDisposeEx.TryGetValue(
  127. ComponentTypeID<TValue>.id
  128. , out var reactiveEnginesDisposeExPerType))
  129. {
  130. var enginesCount = reactiveEnginesDisposeExPerType.count;
  131. for (var i = 0; i < enginesCount; i++)
  132. try
  133. {
  134. using (sampler.Sample(reactiveEnginesDisposeExPerType[i].name))
  135. {
  136. ((IReactOnDisposeEx<TValue>)reactiveEnginesDisposeExPerType[i].engine).Remove(
  137. (0, (uint)count)
  138. , new EntityCollection<TValue>(
  139. fromDictionary.UnsafeGetValues(out _), entityids
  140. , (uint)count), group);
  141. }
  142. }
  143. catch
  144. {
  145. Console.LogError("Code crashed inside Remove callback ".FastConcat(reactiveEnginesDisposeExPerType[i].name));
  146. throw;
  147. }
  148. }
  149. }
  150. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  151. public static void ExecuteEnginesRemoveCallbacks<Strategy1, Strategy2, Strategy3, TValue>(FasterList<(uint, string)> infostoprocess
  152. , ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  153. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnRemove>>> reactiveenginesremove
  154. , ExclusiveGroupStruct fromgroup, in PlatformProfiler profiler)
  155. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  156. where Strategy2 : struct, IBufferStrategy<TValue>
  157. where Strategy3 : struct, IBufferStrategy<int>
  158. where TValue : struct, _IInternalEntityComponent
  159. {
  160. if (reactiveenginesremove.TryGetValue(
  161. ComponentTypeID<TValue>.id
  162. , out var entityComponentsEngines))
  163. {
  164. if (entityComponentsEngines.count == 0)
  165. return;
  166. var iterations = infostoprocess.count;
  167. for (var i = 0; i < iterations; i++)
  168. {
  169. var (entityID, trace) = infostoprocess[i];
  170. try
  171. {
  172. ref var entity = ref fromDictionary.GetValueByRef(entityID);
  173. var egid = new EGID(entityID, fromgroup);
  174. for (var j = 0; j < entityComponentsEngines.count; j++)
  175. using (profiler.Sample(entityComponentsEngines[j].name))
  176. {
  177. #pragma warning disable CS0612
  178. ((IReactOnRemove<TValue>)entityComponentsEngines[j].engine).Remove(ref entity, egid);
  179. #pragma warning restore CS0612
  180. }
  181. }
  182. catch
  183. {
  184. var str = "Crash while executing Remove Entity callback on ".FastConcat(TypeCache<TValue>.name)
  185. .FastConcat(" from : ", trace);
  186. Console.LogError(str);
  187. throw;
  188. }
  189. }
  190. }
  191. }
  192. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  193. public static void ExecuteEnginesRemoveCallbacks_Group<Strategy1, Strategy2, Strategy3, TValue>(
  194. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  195. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnRemove>>> reactiveenginesremove
  196. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnRemoveEx>>> reactiveenginesremoveex
  197. , IEntityIDs entityids, ExclusiveGroupStruct group, in PlatformProfiler sampler)
  198. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  199. where Strategy2 : struct, IBufferStrategy<TValue>
  200. where Strategy3 : struct, IBufferStrategy<int>
  201. where TValue : struct, _IInternalEntityComponent
  202. {
  203. if (reactiveenginesremove.TryGetValue(
  204. ComponentTypeID<TValue>.id
  205. , out var reactiveEnginesRemovePerType))
  206. {
  207. var enginesCount = reactiveEnginesRemovePerType.count;
  208. for (var i = 0; i < enginesCount; i++)
  209. try
  210. {
  211. foreach (var value in fromDictionary)
  212. {
  213. ref var entity = ref value.value;
  214. var egid = new EGID(value.key, group);
  215. using (sampler.Sample(reactiveEnginesRemovePerType[i].name))
  216. {
  217. #pragma warning disable CS0612
  218. ((IReactOnRemove<TValue>)reactiveEnginesRemovePerType[i].engine).Remove(
  219. #pragma warning restore CS0612
  220. ref entity, egid);
  221. }
  222. }
  223. }
  224. catch
  225. {
  226. Console.LogError("Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemovePerType[i].name));
  227. throw;
  228. }
  229. }
  230. if (reactiveenginesremoveex.TryGetValue(
  231. ComponentTypeID<TValue>.id
  232. , out var reactiveEnginesRemoveExPerType))
  233. {
  234. var count = fromDictionary.count;
  235. var enginesCount = reactiveEnginesRemoveExPerType.count;
  236. for (var i = 0; i < enginesCount; i++)
  237. try
  238. {
  239. using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name))
  240. {
  241. ((IReactOnRemoveEx<TValue>)reactiveEnginesRemoveExPerType[i].engine).Remove(
  242. (0, (uint)count)
  243. , new EntityCollection<TValue>(
  244. fromDictionary.UnsafeGetValues(out _), entityids
  245. , (uint)count), group);
  246. }
  247. }
  248. catch
  249. {
  250. Console.LogError("Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemoveExPerType[i].name));
  251. throw;
  252. }
  253. }
  254. }
  255. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  256. public static void ExecuteEnginesSwapCallbacks<Strategy1, Strategy2, Strategy3, TValue>(FasterList<(uint, uint, string)> infostoprocess
  257. , ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  258. , FasterList<ReactEngineContainer<IReactOnSwap>> reactiveenginesswap, ExclusiveGroupStruct togroup
  259. , ExclusiveGroupStruct fromgroup, in PlatformProfiler sampler)
  260. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  261. where Strategy2 : struct, IBufferStrategy<TValue>
  262. where Strategy3 : struct, IBufferStrategy<int>
  263. where TValue : struct, _IInternalEntityComponent
  264. {
  265. if (reactiveenginesswap.count == 0)
  266. return;
  267. var iterations = infostoprocess.count;
  268. for (var i = 0; i < iterations; i++)
  269. {
  270. var (fromEntityID, toEntityID, trace) = infostoprocess[i];
  271. try
  272. {
  273. ref var entityComponent = ref fromDictionary.GetValueByRef(fromEntityID);
  274. var newEgid = new EGID(toEntityID, togroup);
  275. for (var j = 0; j < reactiveenginesswap.count; j++)
  276. using (sampler.Sample(reactiveenginesswap[j].name))
  277. {
  278. #pragma warning disable CS0612
  279. ((IReactOnSwap<TValue>)reactiveenginesswap[j].engine).MovedTo(
  280. #pragma warning restore CS0612
  281. ref entityComponent, fromgroup, newEgid);
  282. }
  283. }
  284. catch
  285. {
  286. var str = "Crash while executing Swap Entity callback on ".FastConcat(TypeCache<TValue>.name)
  287. .FastConcat(" from : ", trace);
  288. Console.LogError(str);
  289. throw;
  290. }
  291. }
  292. }
  293. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  294. public static void ExecuteEnginesSwapCallbacks_Group<Strategy1, Strategy2, Strategy3, TValue>(
  295. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  296. , ITypeSafeDictionary<TValue> toDic, ExclusiveGroupStruct togroup, ExclusiveGroupStruct fromgroup
  297. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnSwap>>> reactiveenginesswap
  298. , FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnSwapEx>>> reactiveenginesswapex
  299. , IEntityIDs entityids, in PlatformProfiler sampler)
  300. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  301. where Strategy2 : struct, IBufferStrategy<TValue>
  302. where Strategy3 : struct, IBufferStrategy<int>
  303. where TValue : struct, _IInternalEntityComponent
  304. {
  305. //get all the engines linked to TValue
  306. if (!reactiveenginesswap.TryGetValue(
  307. ComponentTypeID<TValue>.id
  308. , out var reactiveEnginesSwapPerType))
  309. return;
  310. var componentsEnginesCount = reactiveEnginesSwapPerType.count;
  311. for (var i = 0; i < componentsEnginesCount; i++)
  312. try
  313. {
  314. foreach (var value in fromDictionary)
  315. {
  316. ref var entityComponent = ref toDic.GetValueByRef(value.key);
  317. var newEgid = new EGID(value.key, togroup);
  318. using (sampler.Sample(reactiveEnginesSwapPerType[i].name))
  319. {
  320. #pragma warning disable CS0612
  321. ((IReactOnSwap<TValue>)reactiveEnginesSwapPerType[i].engine).MovedTo(
  322. #pragma warning restore CS0612
  323. ref entityComponent, fromgroup, newEgid);
  324. }
  325. }
  326. }
  327. catch (Exception)
  328. {
  329. Console.LogError("Code crashed inside MoveTo callback ".FastConcat(reactiveEnginesSwapPerType[i].name));
  330. throw;
  331. }
  332. if (reactiveenginesswapex.TryGetValue(
  333. ComponentTypeID<TValue>.id
  334. , out var reactiveEnginesRemoveExPerType))
  335. {
  336. var enginesCount = reactiveEnginesRemoveExPerType.count;
  337. var count = fromDictionary.count;
  338. for (var i = 0; i < enginesCount; i++)
  339. try
  340. {
  341. using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name))
  342. {
  343. ((IReactOnSwapEx<TValue>)reactiveEnginesRemoveExPerType[i].engine).MovedTo(
  344. (0, (uint)count)
  345. , new EntityCollection<TValue>(
  346. fromDictionary.UnsafeGetValues(out _), entityids
  347. , (uint)count), fromgroup, togroup);
  348. }
  349. }
  350. catch
  351. {
  352. Console.LogError("Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemoveExPerType[i].name));
  353. throw;
  354. }
  355. }
  356. }
  357. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  358. public static void RemoveEntitiesFromDictionary<Strategy1, Strategy2, Strategy3, TValue>(FasterList<(uint, string)> infostoprocess
  359. , ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  360. , FasterList<uint> entityIDsAffectedByRemoval)
  361. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  362. where Strategy2 : struct, IBufferStrategy<TValue>
  363. where Strategy3 : struct, IBufferStrategy<int>
  364. where TValue : struct, _IInternalEntityComponent
  365. {
  366. var iterations = infostoprocess.count;
  367. for (var i = 0; i < iterations; i++)
  368. {
  369. var (id, trace) = infostoprocess[i];
  370. try
  371. {
  372. if (fromDictionary.Remove(id, out var index, out var value))
  373. {
  374. //Note I am doing this to be able to use a range of values even with the
  375. //remove Ex callbacks. Basically I am copying back the deleted value
  376. //at the end of the array, so I can use as range count, count + number of deleted entities
  377. //I need to swap the keys too to have matching EntityIDs
  378. fromDictionary.unsafeValues[(uint)fromDictionary.count] = value;
  379. fromDictionary.unsafeKeys[(uint)fromDictionary.count] = new SveltoDictionaryNode<uint>(ref id, 0);
  380. //when a component is removed from a component array, a remove swap back happens. This means
  381. //that not only we have to remove the index of the component of the entity deleted from the array
  382. //but we need also to update the index of the component that has been swapped in the cell
  383. //of the deleted component
  384. //entityIDsAffectedByRemoval tracks all the entitiesID of the components that need to be updated
  385. //in the filters because their indices in the array changed.
  386. entityIDsAffectedByRemoval.Add(fromDictionary.unsafeKeys[index].key);
  387. }
  388. }
  389. catch
  390. {
  391. var str = "Crash while executing Remove Entity operation on ".FastConcat(TypeCache<TValue>.name)
  392. .FastConcat(" from : ", trace);
  393. Console.LogError(str);
  394. throw;
  395. }
  396. }
  397. }
  398. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  399. public static void SwapEntitiesBetweenDictionaries<Strategy1, Strategy2, Strategy3, TValue>(FasterList<(uint, uint, string)> infostoprocess
  400. , ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary
  401. , ITypeSafeDictionary<TValue> toDictionary, ExclusiveGroupStruct fromgroup, ExclusiveGroupStruct togroup
  402. , FasterList<uint> entityIDsAffectedByRemoval)
  403. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  404. where Strategy2 : struct, IBufferStrategy<TValue>
  405. where Strategy3 : struct, IBufferStrategy<int>
  406. where TValue : struct, _IInternalEntityComponent
  407. {
  408. var iterations = infostoprocess.count;
  409. for (var i = 0; i < iterations; i++)
  410. {
  411. var (fromID, toID, trace) = infostoprocess[i];
  412. try
  413. {
  414. var fromEntityGid = new EGID(fromID, fromgroup);
  415. var toEntityEgid = new EGID(toID, togroup);
  416. Check.Require(togroup.isInvalid == false, "Invalid To Group");
  417. if (fromDictionary.Remove(fromEntityGid.entityID, out var index, out var value))
  418. entityIDsAffectedByRemoval.Add(fromDictionary.unsafeKeys[index].key);
  419. else
  420. Check.Assert(false, "Swapping an entity that doesn't exist");
  421. #if SLOW_SVELTO_SUBMISSION
  422. if (SlowSubmissionInfo<TValue>.hasEgid)
  423. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref value, toEntityEgid);
  424. #endif
  425. toDictionary.Add(toEntityEgid.entityID, value);
  426. #if PARANOID_CHECK
  427. DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)toGroupCasted[toEntityEGID.entityID]).ID == toEntityEGID, "impossible situation happened during swap");
  428. #endif
  429. }
  430. catch
  431. {
  432. var str = "Crash while executing Swap Entity operation on ".FastConcat(TypeCache<TValue>.name)
  433. .FastConcat(" from : ", trace);
  434. Console.LogError(str);
  435. throw;
  436. }
  437. }
  438. }
  439. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  440. public static void ExecuteEnginesAddEntityCallbacksFast<TValue>(
  441. FasterDictionary<ComponentID, FasterList<ReactEngineContainer<IReactOnAddEx>>> fasterDictionary
  442. , ExclusiveGroupStruct groupId, (uint, uint) rangeTuple, IEntityIDs entityids
  443. , ITypeSafeDictionary<TValue> typeSafeDictionary, PlatformProfiler profiler)
  444. where TValue : struct, _IInternalEntityComponent
  445. {
  446. //get all the engines linked to TValue
  447. if (!fasterDictionary.TryGetValue(
  448. ComponentTypeID<TValue>.id
  449. , out var entityComponentsEngines))
  450. return;
  451. for (var i = 0; i < entityComponentsEngines.count; i++)
  452. try
  453. {
  454. using (profiler.Sample(entityComponentsEngines[i].name))
  455. {
  456. ((IReactOnAddEx<TValue>)entityComponentsEngines[i].engine).Add(
  457. rangeTuple
  458. , new EntityCollection<TValue>(typeSafeDictionary.GetValues(out var count), entityids, count)
  459. , groupId);
  460. }
  461. }
  462. catch (Exception e)
  463. {
  464. Console.LogException(e, "Code crashed inside Add callback ".FastConcat(entityComponentsEngines[i].name));
  465. throw;
  466. }
  467. }
  468. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  469. public static void ExecuteEnginesSwapCallbacksFast<TValue>(FasterList<ReactEngineContainer<IReactOnSwapEx>> fasterList,
  470. ExclusiveGroupStruct fromGroup
  471. , ExclusiveGroupStruct toGroup, IEntityIDs entityids, ITypeSafeDictionary<TValue> typeSafeDictionary
  472. , (uint, uint) rangeofsubmittedentitiesindicies, PlatformProfiler sampler)
  473. where TValue : struct, _IInternalEntityComponent
  474. {
  475. for (var i = 0; i < fasterList.count; i++)
  476. try
  477. {
  478. using (sampler.Sample(fasterList[i].name))
  479. {
  480. ((IReactOnSwapEx<TValue>)fasterList[i].engine).MovedTo(
  481. rangeofsubmittedentitiesindicies
  482. , new EntityCollection<TValue>(typeSafeDictionary.GetValues(out var count), entityids, count)
  483. , fromGroup, toGroup);
  484. }
  485. }
  486. catch (Exception e)
  487. {
  488. Console.LogException(e, "Code crashed inside Add callback ".FastConcat(fasterList[i].name));
  489. throw;
  490. }
  491. }
  492. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  493. public static void ExecuteEnginesRemoveCallbacksFast<TValue>(FasterList<ReactEngineContainer<IReactOnRemoveEx>> fasterList,
  494. ExclusiveGroupStruct exclusiveGroupStruct
  495. , (uint, uint) valueTuple, IEntityIDs entityids, ITypeSafeDictionary<TValue> typeSafeDictionary
  496. , PlatformProfiler sampler)
  497. where TValue : struct, _IInternalEntityComponent
  498. {
  499. for (var i = 0; i < fasterList.count; i++)
  500. try
  501. {
  502. using (sampler.Sample(fasterList[i].name))
  503. {
  504. ((IReactOnRemoveEx<TValue>)fasterList[i].engine).Remove(
  505. valueTuple
  506. , new EntityCollection<TValue>(typeSafeDictionary.GetValues(out var count), entityids, count)
  507. , exclusiveGroupStruct);
  508. }
  509. }
  510. catch (Exception e)
  511. {
  512. Console.LogException(e, "Code crashed inside Add callback ".FastConcat(fasterList[i].name));
  513. throw;
  514. }
  515. }
  516. }
  517. }