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.

800 linhas
34KB

  1. #if DEBUG && !PROFILE_SVELTO
  2. //#define PARANOID_CHECK
  3. #endif
  4. using System;
  5. using System.Runtime.CompilerServices;
  6. using DBC.ECS;
  7. using Svelto.Common;
  8. using Svelto.DataStructures;
  9. using Svelto.DataStructures.Native;
  10. using Svelto.ECS.DataStructures;
  11. using Svelto.ECS.Hybrid;
  12. namespace Svelto.ECS.Internal
  13. {
  14. public readonly struct NativeEntityIDs
  15. {
  16. public NativeEntityIDs(NB<SveltoDictionaryNode<uint>> native)
  17. {
  18. _native = native;
  19. }
  20. public uint this[uint index] => _native[index].key;
  21. public uint this[int index] => _native[index].key;
  22. readonly NB<SveltoDictionaryNode<uint>> _native;
  23. }
  24. public readonly struct ManagedEntityIDs
  25. {
  26. public ManagedEntityIDs(MB<SveltoDictionaryNode<uint>> managed)
  27. {
  28. _managed = managed;
  29. }
  30. public uint this[uint index] => _managed[index].key;
  31. public uint this[int index] => _managed[index].key;
  32. readonly MB<SveltoDictionaryNode<uint>> _managed;
  33. }
  34. public readonly struct EntityIDs
  35. {
  36. readonly NB<SveltoDictionaryNode<uint>> _native;
  37. readonly MB<SveltoDictionaryNode<uint>> _managed;
  38. public EntityIDs(NativeStrategy<SveltoDictionaryNode<uint>> unmanagedKeys) : this()
  39. {
  40. _native = unmanagedKeys.ToRealBuffer();
  41. }
  42. public EntityIDs(ManagedStrategy<SveltoDictionaryNode<uint>> managedKeys) : this()
  43. {
  44. _managed = managedKeys.ToRealBuffer();
  45. }
  46. public NativeEntityIDs nativeIDs => new NativeEntityIDs(_native);
  47. public ManagedEntityIDs managedIDs => new ManagedEntityIDs(_managed);
  48. }
  49. public sealed class TypeSafeDictionary<TValue> : ITypeSafeDictionary<TValue> where TValue : struct, IEntityComponent
  50. {
  51. static readonly Type _type = typeof(TValue);
  52. #if SLOW_SVELTO_SUBMISSION
  53. static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type);
  54. static readonly bool _hasReference = typeof(INeedEntityReference).IsAssignableFrom(_type);
  55. #endif
  56. internal static readonly bool isUnmanaged =
  57. _type.IsUnmanagedEx() && typeof(IEntityViewComponent).IsAssignableFrom(_type) == false;
  58. public TypeSafeDictionary(uint size)
  59. {
  60. if (isUnmanaged)
  61. implUnmgd =
  62. new SharedNative<SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>,
  63. NativeStrategy<TValue>, NativeStrategy<int>>>(
  64. new SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>,
  65. NativeStrategy<TValue>, NativeStrategy<int>>(size, Allocator.Persistent));
  66. else
  67. implMgd =
  68. new SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>,
  69. ManagedStrategy<TValue>, ManagedStrategy<int>>(size, Allocator.Managed);
  70. }
  71. public EntityIDs entityIDs
  72. {
  73. get
  74. {
  75. if (isUnmanaged)
  76. return new EntityIDs(implUnmgd.value.unsafeKeys);
  77. return new EntityIDs(implMgd.unsafeKeys);
  78. }
  79. }
  80. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  81. public bool ContainsKey(uint egidEntityId)
  82. {
  83. return isUnmanaged ? implUnmgd.value.ContainsKey(egidEntityId) : implMgd.ContainsKey(egidEntityId);
  84. }
  85. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  86. public uint GetIndex(uint valueEntityId)
  87. {
  88. return isUnmanaged ? implUnmgd.value.GetIndex(valueEntityId) : implMgd.GetIndex(valueEntityId);
  89. }
  90. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  91. public ref TValue GetOrAdd(uint idEntityId)
  92. {
  93. return ref isUnmanaged ? ref implUnmgd.value.GetOrAdd(idEntityId) : ref implMgd.GetOrAdd(idEntityId);
  94. }
  95. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  96. public IBuffer<TValue> GetValues(out uint count)
  97. {
  98. return isUnmanaged ? implUnmgd.value.UnsafeGetValues(out count) : implMgd.UnsafeGetValues(out count);
  99. }
  100. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  101. public ref TValue GetDirectValueByRef(uint key)
  102. {
  103. return ref isUnmanaged
  104. ? ref implUnmgd.value.GetDirectValueByRef(key)
  105. : ref implMgd.GetDirectValueByRef(key);
  106. }
  107. public ref TValue GetValueByRef(uint key)
  108. {
  109. return ref isUnmanaged ? ref implUnmgd.value.GetValueByRef(key) : ref implMgd.GetValueByRef(key);
  110. }
  111. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  112. public bool Has(uint key)
  113. {
  114. return isUnmanaged ? implUnmgd.value.ContainsKey(key) : implMgd.ContainsKey(key);
  115. }
  116. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  117. public bool TryFindIndex(uint entityId, out uint index)
  118. {
  119. return isUnmanaged
  120. ? implUnmgd.value.TryFindIndex(entityId, out index)
  121. : implMgd.TryFindIndex(entityId, out index);
  122. }
  123. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  124. public bool TryGetValue(uint entityId, out TValue item)
  125. {
  126. return isUnmanaged
  127. ? implUnmgd.value.TryGetValue(entityId, out item)
  128. : implMgd.TryGetValue(entityId, out item);
  129. }
  130. public int count
  131. {
  132. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  133. get => isUnmanaged ? implUnmgd.value.count : implMgd.count;
  134. }
  135. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  136. public ITypeSafeDictionary Create()
  137. {
  138. return TypeSafeDictionaryFactory<TValue>.Create(1);
  139. }
  140. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  141. public void Clear()
  142. {
  143. if (isUnmanaged)
  144. implUnmgd.value.FastClear();
  145. else
  146. implMgd.Clear();
  147. }
  148. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  149. public void EnsureCapacity(uint size)
  150. {
  151. if (isUnmanaged)
  152. implUnmgd.value.EnsureCapacity(size);
  153. else
  154. implMgd.EnsureCapacity(size);
  155. }
  156. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  157. public void IncreaseCapacityBy(uint size)
  158. {
  159. if (isUnmanaged)
  160. implUnmgd.value.IncreaseCapacityBy(size);
  161. else
  162. implMgd.IncreaseCapacityBy(size);
  163. }
  164. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  165. public void Trim()
  166. {
  167. if (isUnmanaged)
  168. implUnmgd.value.Trim();
  169. else
  170. implMgd.Trim();
  171. }
  172. public void KeysEvaluator(Action<uint> action)
  173. {
  174. if (isUnmanaged)
  175. foreach (var key in implUnmgd.value.keys)
  176. action(key);
  177. else
  178. foreach (var key in implMgd.keys)
  179. action(key);
  180. }
  181. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  182. public void Add(uint egidEntityId, in TValue entityComponent)
  183. {
  184. if (isUnmanaged)
  185. implUnmgd.value.Add(egidEntityId, entityComponent);
  186. else
  187. implMgd.Add(egidEntityId, entityComponent);
  188. }
  189. public void Dispose()
  190. {
  191. if (isUnmanaged)
  192. implUnmgd.Dispose();
  193. else
  194. implMgd.Dispose();
  195. GC.SuppressFinalize(this);
  196. }
  197. public void AddEntitiesToDictionary(ITypeSafeDictionary toDictionary, ExclusiveGroupStruct groupId,
  198. in EnginesRoot.EntityReferenceMap entityLocator)
  199. {
  200. void SharedAddEntitiesFromDictionary<Strategy1, Strategy2, Strategy3>(
  201. in SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  202. ITypeSafeDictionary<TValue> toDic, in EnginesRoot.EntityReferenceMap locator,
  203. ExclusiveGroupStruct toGroupID) where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  204. where Strategy2 : struct, IBufferStrategy<TValue>
  205. where Strategy3 : struct, IBufferStrategy<int>
  206. {
  207. foreach (var tuple in fromDictionary)
  208. {
  209. #if SLOW_SVELTO_SUBMISSION
  210. var egid = new EGID(tuple.key, toGroupID);
  211. if (_hasEgid)
  212. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref tuple.value, egid);
  213. //todo: temporary code that will eventually be removed
  214. if (_hasReference)
  215. SetEGIDWithoutBoxing<TValue>.SetRefWithoutBoxing(ref tuple.value,
  216. locator.GetEntityReference(egid));
  217. #endif
  218. try
  219. {
  220. toDic.Add(tuple.key, tuple.value);
  221. }
  222. catch (Exception e)
  223. {
  224. Console.LogException(e,
  225. "trying to add an EntityComponent with the same ID more than once Entity: "
  226. .FastConcat(typeof(TValue).ToString()).FastConcat(", group ")
  227. .FastConcat(toGroupID.ToName()).FastConcat(", id ").FastConcat(tuple.key));
  228. throw;
  229. }
  230. #if PARANOID_CHECK && SLOW_SVELTO_SUBMISSION
  231. DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)fromDictionary[egid.entityID]).ID == egid, "impossible situation happened during swap");
  232. #endif
  233. }
  234. }
  235. var destinationDictionary = toDictionary as ITypeSafeDictionary<TValue>;
  236. if (isUnmanaged)
  237. SharedAddEntitiesFromDictionary(implUnmgd.value, destinationDictionary, entityLocator, groupId);
  238. else
  239. SharedAddEntitiesFromDictionary(implMgd, destinationDictionary, entityLocator, groupId);
  240. }
  241. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  242. public void RemoveEntitiesFromDictionary(FasterList<(uint, string)> infosToProcess)
  243. {
  244. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  245. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary)
  246. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  247. where Strategy2 : struct, IBufferStrategy<TValue>
  248. where Strategy3 : struct, IBufferStrategy<int>
  249. {
  250. var iterations = infosToProcess.count;
  251. for (var i = 0; i < iterations; i++)
  252. {
  253. var (id, trace) = infosToProcess[i];
  254. try
  255. {
  256. if (fromDictionary.Remove(id, out var value))
  257. //Note I am doing this to be able to use a range of values even with the
  258. //remove Ex callbacks. Basically I am copying back the deleted value
  259. //at the end of the array, so I can use as range
  260. //count, count + number of deleted entities
  261. fromDictionary.GetDirectValueByRef((uint)fromDictionary.count) = value;
  262. }
  263. catch
  264. {
  265. var str = "Crash while executing Remove Entity operation on ".FastConcat(TypeCache<TValue>.name)
  266. .FastConcat(" from : ", trace);
  267. Console.LogError(str);
  268. throw;
  269. }
  270. }
  271. }
  272. if (isUnmanaged)
  273. AgnosticMethod(ref implUnmgd.value);
  274. else
  275. AgnosticMethod(ref implMgd);
  276. }
  277. public void SwapEntitiesBetweenDictionaries(FasterList<(uint, uint, string)> infosToProcess,
  278. ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup, ITypeSafeDictionary toComponentsDictionary)
  279. {
  280. void SharedSwapEntityInDictionary<Strategy1, Strategy2, Strategy3>(
  281. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  282. ITypeSafeDictionary<TValue> toDictionary)
  283. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  284. where Strategy2 : struct, IBufferStrategy<TValue>
  285. where Strategy3 : struct, IBufferStrategy<int>
  286. {
  287. var iterations = infosToProcess.count;
  288. for (var i = 0; i < iterations; i++)
  289. {
  290. var (fromID, toID, trace) = infosToProcess[i];
  291. try
  292. {
  293. var fromEntityGid = new EGID(fromID, fromGroup);
  294. var toEntityEgid = new EGID(toID, toGroup);
  295. Check.Require(toGroup.isInvalid == false, "Invalid To Group");
  296. var isFound = fromDictionary.Remove(fromEntityGid.entityID, out var entity);
  297. Check.Assert(isFound, "Swapping an entity that doesn't exist");
  298. #if SLOW_SVELTO_SUBMISSION
  299. if (_hasEgid)
  300. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityEgid);
  301. #endif
  302. toDictionary.Add(toEntityEgid.entityID, entity);
  303. #if PARANOID_CHECK
  304. DBC.ECS.Check.Ensure(_hasEgid == false || ((INeedEGID)toGroupCasted[toEntityEGID.entityID]).ID == toEntityEGID, "impossible situation happened during swap");
  305. #endif
  306. }
  307. catch
  308. {
  309. var str = "Crash while executing Swap Entity operation on ".FastConcat(TypeCache<TValue>.name)
  310. .FastConcat(" from : ", trace);
  311. Console.LogError(str);
  312. throw;
  313. }
  314. }
  315. }
  316. var toGroupCasted = toComponentsDictionary as ITypeSafeDictionary<TValue>;
  317. if (isUnmanaged)
  318. SharedSwapEntityInDictionary(ref implUnmgd.value, toGroupCasted);
  319. else
  320. SharedSwapEntityInDictionary(ref implMgd, toGroupCasted);
  321. }
  322. public void ExecuteEnginesAddCallbacks(
  323. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnAdd>>> entityComponentEnginesDB,
  324. ITypeSafeDictionary toDic, ExclusiveGroupStruct toGroup, in PlatformProfiler profiler)
  325. {
  326. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  327. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  328. ITypeSafeDictionary<TValue> todic, in PlatformProfiler sampler)
  329. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  330. where Strategy2 : struct, IBufferStrategy<TValue>
  331. where Strategy3 : struct, IBufferStrategy<int>
  332. {
  333. if (entityComponentEnginesDB.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  334. {
  335. if (entityComponentsEngines.count == 0) return;
  336. var dictionaryKeyEnumerator = fromDictionary.unsafeKeys;
  337. var count = fromDictionary.count;
  338. for (var i = 0; i < count; ++i)
  339. try
  340. {
  341. var key = dictionaryKeyEnumerator[i].key;
  342. ref var entity = ref todic.GetValueByRef(key);
  343. var egid = new EGID(key, toGroup);
  344. //get all the engines linked to TValue
  345. for (var j = 0; j < entityComponentsEngines.count; j++)
  346. using (sampler.Sample(entityComponentsEngines[j].name))
  347. {
  348. ((IReactOnAdd<TValue>)entityComponentsEngines[j].engine).Add(ref entity, egid);
  349. }
  350. }
  351. catch (Exception e)
  352. {
  353. Console.LogException(e,
  354. "Code crashed inside Add callback with Type ".FastConcat(TypeCache<TValue>.name));
  355. throw;
  356. }
  357. }
  358. }
  359. var toDictionary = (ITypeSafeDictionary<TValue>)toDic;
  360. if (isUnmanaged)
  361. AgnosticMethod(ref implUnmgd.value, toDictionary, in profiler);
  362. else
  363. AgnosticMethod(ref implMgd, toDictionary, in profiler);
  364. }
  365. public void ExecuteEnginesSwapCallbacks(FasterList<(uint, uint, string)> infosToProcess,
  366. FasterList<ReactEngineContainer<IReactOnSwap>> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup,
  367. ExclusiveGroupStruct toGroup, in PlatformProfiler profiler)
  368. {
  369. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  370. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  371. in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  372. where Strategy2 : struct, IBufferStrategy<TValue>
  373. where Strategy3 : struct, IBufferStrategy<int>
  374. {
  375. if (reactiveEnginesSwap.count == 0) return;
  376. var iterations = infosToProcess.count;
  377. for (var i = 0; i < iterations; i++)
  378. {
  379. var (fromEntityID, toEntityID, trace) = infosToProcess[i];
  380. try
  381. {
  382. ref var entityComponent = ref fromDictionary.GetValueByRef(fromEntityID);
  383. var newEgid = new EGID(toEntityID, toGroup);
  384. for (var j = 0; j < reactiveEnginesSwap.count; j++)
  385. using (sampler.Sample(reactiveEnginesSwap[j].name))
  386. {
  387. ((IReactOnSwap<TValue>)reactiveEnginesSwap[j].engine).MovedTo(ref entityComponent,
  388. fromGroup, newEgid);
  389. }
  390. }
  391. catch
  392. {
  393. var str = "Crash while executing Swap Entity callback on ".FastConcat(TypeCache<TValue>.name)
  394. .FastConcat(" from : ", trace);
  395. Console.LogError(str);
  396. throw;
  397. }
  398. }
  399. }
  400. if (isUnmanaged)
  401. AgnosticMethod(ref implUnmgd.value, in profiler);
  402. else
  403. AgnosticMethod(ref implMgd, in profiler);
  404. }
  405. public void ExecuteEnginesRemoveCallbacks(FasterList<(uint, string)> infosToProcess,
  406. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnRemove>>> reactiveEnginesRemove,
  407. ExclusiveGroupStruct fromGroup, in PlatformProfiler sampler)
  408. {
  409. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  410. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  411. in PlatformProfiler profiler) where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  412. where Strategy2 : struct, IBufferStrategy<TValue>
  413. where Strategy3 : struct, IBufferStrategy<int>
  414. {
  415. if (reactiveEnginesRemove.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  416. {
  417. if (entityComponentsEngines.count == 0) return;
  418. var iterations = infosToProcess.count;
  419. for (var i = 0; i < iterations; i++)
  420. {
  421. var (entityID, trace) = infosToProcess[i];
  422. try
  423. {
  424. ref var entity = ref fromDictionary.GetValueByRef(entityID);
  425. var egid = new EGID(entityID, fromGroup);
  426. for (var j = 0; j < entityComponentsEngines.count; j++)
  427. using (profiler.Sample(entityComponentsEngines[j].name))
  428. {
  429. ((IReactOnRemove<TValue>)entityComponentsEngines[j].engine).Remove(ref entity,
  430. egid);
  431. }
  432. }
  433. catch
  434. {
  435. var str = "Crash while executing Remove Entity callback on "
  436. .FastConcat(TypeCache<TValue>.name).FastConcat(" from : ", trace);
  437. Console.LogError(str);
  438. throw;
  439. }
  440. }
  441. }
  442. }
  443. if (isUnmanaged)
  444. AgnosticMethod(ref implUnmgd.value, in sampler);
  445. else
  446. AgnosticMethod(ref implMgd, in sampler);
  447. }
  448. public void ExecuteEnginesAddEntityCallbacksFast(
  449. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnAddEx>>> reactiveEnginesAdd,
  450. ExclusiveGroupStruct groupID, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler profiler)
  451. {
  452. //get all the engines linked to TValue
  453. if (!reactiveEnginesAdd.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  454. return;
  455. for (var i = 0; i < entityComponentsEngines.count; i++)
  456. try
  457. {
  458. using (profiler.Sample(entityComponentsEngines[i].name))
  459. {
  460. ((IReactOnAddEx<TValue>)entityComponentsEngines[i].engine).Add(rangeOfSubmittedEntitiesIndicies,
  461. new EntityCollection<TValue>(GetValues(out var count), count, entityIDs), groupID);
  462. }
  463. }
  464. catch (Exception e)
  465. {
  466. Console.LogException(e,
  467. "Code crashed inside Add callback ".FastConcat(entityComponentsEngines[i].name));
  468. throw;
  469. }
  470. }
  471. public void ExecuteEnginesSwapCallbacksFast(
  472. FasterList<ReactEngineContainer<IReactOnSwapEx>> reactiveEnginesSwap, ExclusiveGroupStruct fromGroup,
  473. ExclusiveGroupStruct toGroup, (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler)
  474. {
  475. for (var i = 0; i < reactiveEnginesSwap.count; i++)
  476. try
  477. {
  478. using (sampler.Sample(reactiveEnginesSwap[i].name))
  479. {
  480. ((IReactOnSwapEx<TValue>)reactiveEnginesSwap[i].engine).MovedTo(
  481. rangeOfSubmittedEntitiesIndicies,
  482. new EntityCollection<TValue>(GetValues(out var count), count, entityIDs), fromGroup,
  483. toGroup);
  484. }
  485. }
  486. catch (Exception e)
  487. {
  488. Console.LogException(e,
  489. "Code crashed inside Add callback ".FastConcat(reactiveEnginesSwap[i].name));
  490. throw;
  491. }
  492. }
  493. public void ExecuteEnginesRemoveCallbacksFast(
  494. FasterList<ReactEngineContainer<IReactOnRemoveEx>> reactiveEnginesRemoveEx, ExclusiveGroupStruct fromGroup,
  495. (uint, uint) rangeOfSubmittedEntitiesIndicies, in PlatformProfiler sampler)
  496. {
  497. for (var i = 0; i < reactiveEnginesRemoveEx.count; i++)
  498. try
  499. {
  500. using (sampler.Sample(reactiveEnginesRemoveEx[i].name))
  501. {
  502. ((IReactOnRemoveEx<TValue>)reactiveEnginesRemoveEx[i].engine).Remove(
  503. rangeOfSubmittedEntitiesIndicies,
  504. new EntityCollection<TValue>(GetValues(out var count), count, entityIDs), fromGroup);
  505. }
  506. }
  507. catch (Exception e)
  508. {
  509. Console.LogException(e,
  510. "Code crashed inside Add callback ".FastConcat(reactiveEnginesRemoveEx[i].name));
  511. throw;
  512. }
  513. }
  514. public void ExecuteEnginesSwapCallbacks_Group(
  515. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnSwap>>> reactiveEnginesSwap,
  516. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnSwapEx>>> reactiveEnginesSwapEx,
  517. ITypeSafeDictionary toDictionary, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup,
  518. in PlatformProfiler profiler)
  519. {
  520. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  521. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  522. ITypeSafeDictionary<TValue> toDic, in PlatformProfiler sampler)
  523. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  524. where Strategy2 : struct, IBufferStrategy<TValue>
  525. where Strategy3 : struct, IBufferStrategy<int>
  526. {
  527. //get all the engines linked to TValue
  528. if (!reactiveEnginesSwap.TryGetValue(new RefWrapperType(_type), out var reactiveEnginesSwapPerType))
  529. return;
  530. var componentsEnginesCount = reactiveEnginesSwapPerType.count;
  531. for (var i = 0; i < componentsEnginesCount; i++)
  532. try
  533. {
  534. foreach (var value in fromDictionary)
  535. {
  536. ref var entityComponent = ref toDic.GetValueByRef(value.key);
  537. var newEgid = new EGID(value.key, toGroup);
  538. using (sampler.Sample(reactiveEnginesSwapPerType[i].name))
  539. {
  540. ((IReactOnSwap<TValue>)reactiveEnginesSwapPerType[i].engine).MovedTo(
  541. ref entityComponent, fromGroup, newEgid);
  542. }
  543. }
  544. }
  545. catch (Exception)
  546. {
  547. Console.LogError(
  548. "Code crashed inside MoveTo callback ".FastConcat(reactiveEnginesSwapPerType[i].name));
  549. throw;
  550. }
  551. if (reactiveEnginesSwapEx.TryGetValue(new RefWrapperType(_type),
  552. out var reactiveEnginesRemoveExPerType))
  553. {
  554. var enginesCount = reactiveEnginesRemoveExPerType.count;
  555. for (var i = 0; i < enginesCount; i++)
  556. try
  557. {
  558. using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name))
  559. {
  560. ((IReactOnSwapEx<TValue>)reactiveEnginesRemoveExPerType[i].engine).MovedTo(
  561. (0, (uint)count),
  562. new EntityCollection<TValue>(GetValues(out _), (uint)count, entityIDs), fromGroup,
  563. toGroup);
  564. }
  565. }
  566. catch
  567. {
  568. Console.LogError(
  569. "Code crashed inside Remove callback ".FastConcat(
  570. reactiveEnginesRemoveExPerType[i].name));
  571. throw;
  572. }
  573. }
  574. }
  575. var toEntitiesDictionary = (ITypeSafeDictionary<TValue>)toDictionary;
  576. if (isUnmanaged)
  577. AgnosticMethod(ref implUnmgd.value, toEntitiesDictionary, in profiler);
  578. else
  579. AgnosticMethod(ref implMgd, toEntitiesDictionary, in profiler);
  580. }
  581. public void ExecuteEnginesRemoveCallbacks_Group(
  582. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnRemove>>> reactiveEnginesRemove,
  583. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnRemoveEx>>>
  584. reactiveEnginesRemoveEx, ExclusiveGroupStruct group, in PlatformProfiler profiler)
  585. {
  586. void AgnosticMethod<Strategy1, Strategy2, Strategy3>(
  587. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  588. in PlatformProfiler sampler) where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  589. where Strategy2 : struct, IBufferStrategy<TValue>
  590. where Strategy3 : struct, IBufferStrategy<int>
  591. {
  592. if (reactiveEnginesRemove.TryGetValue(new RefWrapperType(_type), out var reactiveEnginesRemovePerType))
  593. {
  594. var enginesCount = reactiveEnginesRemovePerType.count;
  595. for (var i = 0; i < enginesCount; i++)
  596. try
  597. {
  598. foreach (var value in fromDictionary)
  599. {
  600. ref var entity = ref value.value;
  601. var egid = new EGID(value.key, group);
  602. using (sampler.Sample(reactiveEnginesRemovePerType[i].name))
  603. {
  604. ((IReactOnRemove<TValue>)reactiveEnginesRemovePerType[i].engine).Remove(ref entity,
  605. egid);
  606. }
  607. }
  608. }
  609. catch
  610. {
  611. Console.LogError(
  612. "Code crashed inside Remove callback ".FastConcat(reactiveEnginesRemovePerType[i]
  613. .name));
  614. throw;
  615. }
  616. }
  617. if (reactiveEnginesRemoveEx.TryGetValue(new RefWrapperType(_type),
  618. out var reactiveEnginesRemoveExPerType))
  619. {
  620. var enginesCount = reactiveEnginesRemoveExPerType.count;
  621. for (var i = 0; i < enginesCount; i++)
  622. try
  623. {
  624. using (sampler.Sample(reactiveEnginesRemoveExPerType[i].name))
  625. {
  626. ((IReactOnRemoveEx<TValue>)reactiveEnginesRemoveExPerType[i].engine).Remove(
  627. (0, (uint)count),
  628. new EntityCollection<TValue>(GetValues(out _), (uint)count, entityIDs), group);
  629. }
  630. }
  631. catch
  632. {
  633. Console.LogError(
  634. "Code crashed inside Remove callback ".FastConcat(
  635. reactiveEnginesRemoveExPerType[i].name));
  636. throw;
  637. }
  638. }
  639. }
  640. if (isUnmanaged)
  641. AgnosticMethod(ref implUnmgd.value, in profiler);
  642. else
  643. AgnosticMethod(ref implMgd, in profiler);
  644. }
  645. public void ExecuteEnginesDisposeCallbacks_Group(
  646. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnDispose>>> engines,
  647. ExclusiveGroupStruct group, in PlatformProfiler profiler)
  648. {
  649. void ExecuteEnginesDisposeEntityCallback<Strategy1, Strategy2, Strategy3>(
  650. ref SveltoDictionary<uint, TValue, Strategy1, Strategy2, Strategy3> fromDictionary,
  651. FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer<IReactOnDispose>>> allEngines,
  652. in PlatformProfiler sampler, ExclusiveGroupStruct inGroup)
  653. where Strategy1 : struct, IBufferStrategy<SveltoDictionaryNode<uint>>
  654. where Strategy2 : struct, IBufferStrategy<TValue>
  655. where Strategy3 : struct, IBufferStrategy<int>
  656. {
  657. if (allEngines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines) == false)
  658. return;
  659. for (var i = 0; i < entityComponentsEngines.count; i++)
  660. try
  661. {
  662. using (sampler.Sample(entityComponentsEngines[i].name))
  663. {
  664. foreach (var value in fromDictionary)
  665. {
  666. ref var entity = ref value.value;
  667. var egid = new EGID(value.key, inGroup);
  668. var reactOnRemove = ((IReactOnDispose<TValue>)entityComponentsEngines[i].engine);
  669. reactOnRemove.Remove(ref entity, egid);
  670. }
  671. }
  672. }
  673. catch
  674. {
  675. Console.LogError(
  676. "Code crashed inside Remove callback ".FastConcat(entityComponentsEngines[i].name));
  677. throw;
  678. }
  679. }
  680. if (isUnmanaged)
  681. ExecuteEnginesDisposeEntityCallback(ref implUnmgd.value, engines, in profiler, @group);
  682. else
  683. ExecuteEnginesDisposeEntityCallback(ref implMgd, engines, in profiler, @group);
  684. }
  685. SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>, ManagedStrategy<TValue>,
  686. ManagedStrategy<int>> implMgd;
  687. internal SharedNative<SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>,
  688. NativeStrategy<TValue>, NativeStrategy<int>>> implUnmgd;
  689. }
  690. }