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.

TypeSafeDictionary.cs 34KB

Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
Svelto.ECS 2.9 changes (random order of importance): New Serialization framework more thorough disposing of the EnginesRoot an EnginesRoot reference should never be held, unless it’s a weak reference. The code changed to stick to this rule IReactOnAddAndRemove callbacks are now guaranteed to be called after all the entity structs generated by the same entity have been added and before any is removed. both functions pass the EGID of the analysing entity by parameter now, so that the entity struct won’t need to implement INeedEGID for this sole purpose. The IReactOnSwap MovedFrom method has been removed, it is now redundant. Entities built or removed during the IReactOnAddAndRemove callbacks are now added and removed immediately and not on the next submission like used to happen. This avoid some awkward checks that were previously needed inside engines. EntityStreams can get (optionally) the EGID of the entity published, so that the EntityStruct won’t need an INeedEGID for this sole purpose. Groups are not trimmed anymore when they are emptied to avoid allocations. Removed a bunch of run-time allocations that weren’t supposed to happen in Release and/or when the Profile define is used in editor (for debugging reasons Svelto.ECS may need to use strings at run-time, but Svelto.ECS is allocation zero in Release and when the Profile keyword is used) A improved the DynamicEntityDescriptor and ExtendibleEntityDescriptor code and more notably, introduced the new method ExtendedWith<> to facilitate the writing of modular and reusable entity descriptors. Several minor code design improvements/optimisations
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  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. }