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.

EntitiesDB.cs 16KB

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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. #if DEBUG && !PROFILE_SVELTO
  2. #define ENABLE_DEBUG_FUNC
  3. #endif
  4. using System;
  5. using System.Runtime.CompilerServices;
  6. using Svelto.Common;
  7. using Svelto.DataStructures;
  8. using Svelto.ECS.Internal;
  9. namespace Svelto.ECS
  10. {
  11. public partial class EntitiesDB
  12. {
  13. internal EntitiesDB(EnginesRoot enginesRoot, EnginesRoot.EntityReferenceMap entityReferencesMap)
  14. {
  15. _enginesRoot = enginesRoot;
  16. _entityReferencesMap = entityReferencesMap;
  17. }
  18. EntityCollection<T> InternalQueryEntities<T>
  19. (FasterDictionary<RefWrapperType, ITypeSafeDictionary> entitiesInGroupPerType)
  20. where T : struct, IBaseEntityComponent
  21. {
  22. uint count = 0;
  23. IBuffer<T> buffer;
  24. IEntityIDs ids = default;
  25. if (SafeQueryEntityDictionary<T>(out var typeSafeDictionary, entitiesInGroupPerType) == false)
  26. buffer = default;
  27. else
  28. {
  29. ITypeSafeDictionary<T> safeDictionary = (typeSafeDictionary as ITypeSafeDictionary<T>);
  30. buffer = safeDictionary.GetValues(out count);
  31. ids = safeDictionary.entityIDs;
  32. }
  33. return new EntityCollection<T>(buffer, ids, count);
  34. }
  35. /// <summary>
  36. /// The QueryEntities<T> follows the rule that entities could always be iterated regardless if they
  37. /// are 0, 1 or N. In case of 0 it returns an empty array. This allows to use the same for iteration
  38. /// regardless the number of entities built.
  39. /// </summary>
  40. /// <param name="groupStructId"></param>
  41. /// <typeparam name="T"></typeparam>
  42. /// <returns></returns>
  43. public EntityCollection<T> QueryEntities<T>(ExclusiveGroupStruct groupStructId)
  44. where T : struct, IBaseEntityComponent
  45. {
  46. if (groupEntityComponentsDB.TryGetValue(groupStructId, out var entitiesInGroupPerType) == false)
  47. {
  48. return new EntityCollection<T>(default, default, 0);
  49. }
  50. return InternalQueryEntities<T>(entitiesInGroupPerType);
  51. }
  52. public EntityCollection<T1, T2> QueryEntities<T1, T2>(ExclusiveGroupStruct groupStruct)
  53. where T1 : struct, IBaseEntityComponent where T2 : struct, IBaseEntityComponent
  54. {
  55. if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false)
  56. {
  57. return new EntityCollection<T1, T2>(
  58. new EntityCollection<T1>(default, default, 0)
  59. , new EntityCollection<T2>(default, default, 0));
  60. }
  61. var T1entities = InternalQueryEntities<T1>(entitiesInGroupPerType);
  62. var T2entities = InternalQueryEntities<T2>(entitiesInGroupPerType);
  63. #if DEBUG && !PROFILE_SVELTO
  64. if (T1entities.count != T2entities.count)
  65. throw new ECSException("Entity components count do not match in group. Entity 1: ' count: "
  66. .FastConcat(T1entities.count).FastConcat(" ", typeof(T1).ToString())
  67. .FastConcat("'. Entity 2: ' count: ".FastConcat(T2entities.count)
  68. .FastConcat(" ", typeof(T2).ToString())
  69. .FastConcat(
  70. "' group: ", groupStruct.ToName())));
  71. #endif
  72. return new EntityCollection<T1, T2>(T1entities, T2entities);
  73. }
  74. public EntityCollection<T1, T2, T3> QueryEntities<T1, T2, T3>(ExclusiveGroupStruct groupStruct)
  75. where T1 : struct, IBaseEntityComponent
  76. where T2 : struct, IBaseEntityComponent
  77. where T3 : struct, IBaseEntityComponent
  78. {
  79. if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false)
  80. {
  81. return new EntityCollection<T1, T2, T3>(
  82. new EntityCollection<T1>(default, default, 0)
  83. , new EntityCollection<T2>(default, default, 0)
  84. , new EntityCollection<T3>(default, default, 0));
  85. }
  86. var T1entities = InternalQueryEntities<T1>(entitiesInGroupPerType);
  87. var T2entities = InternalQueryEntities<T2>(entitiesInGroupPerType);
  88. var T3entities = InternalQueryEntities<T3>(entitiesInGroupPerType);
  89. #if DEBUG && !PROFILE_SVELTO
  90. if (T1entities.count != T2entities.count || T2entities.count != T3entities.count)
  91. throw new ECSException("Entity components count do not match in group. Entity 1: "
  92. .FastConcat(typeof(T1).ToString()).FastConcat(" count: ")
  93. .FastConcat(T1entities.count).FastConcat(
  94. " Entity 2: ".FastConcat(typeof(T2).ToString()).FastConcat(" count: ")
  95. .FastConcat(T2entities.count)
  96. .FastConcat(" Entity 3: ".FastConcat(typeof(T3).ToString()))
  97. .FastConcat(" count: ").FastConcat(T3entities.count)));
  98. #endif
  99. return new EntityCollection<T1, T2, T3>(T1entities, T2entities, T3entities);
  100. }
  101. public EntityCollection<T1, T2, T3, T4> QueryEntities<T1, T2, T3, T4>(ExclusiveGroupStruct groupStruct)
  102. where T1 : struct, IBaseEntityComponent
  103. where T2 : struct, IBaseEntityComponent
  104. where T3 : struct, IBaseEntityComponent
  105. where T4 : struct, IBaseEntityComponent
  106. {
  107. if (groupEntityComponentsDB.TryGetValue(groupStruct, out var entitiesInGroupPerType) == false)
  108. {
  109. return new EntityCollection<T1, T2, T3, T4>(
  110. new EntityCollection<T1>(default, default, 0)
  111. , new EntityCollection<T2>(default, default, 0)
  112. , new EntityCollection<T3>(default, default, 0)
  113. , new EntityCollection<T4>(default, default, 0));
  114. }
  115. var T1entities = InternalQueryEntities<T1>(entitiesInGroupPerType);
  116. var T2entities = InternalQueryEntities<T2>(entitiesInGroupPerType);
  117. var T3entities = InternalQueryEntities<T3>(entitiesInGroupPerType);
  118. var T4entities = InternalQueryEntities<T4>(entitiesInGroupPerType);
  119. #if DEBUG && !PROFILE_SVELTO
  120. if (T1entities.count != T2entities.count || T2entities.count != T3entities.count
  121. || T3entities.count != T4entities.count)
  122. throw new ECSException("Entity components count do not match in group. Entity 1: "
  123. .FastConcat(typeof(T1).ToString()).FastConcat(" count: ")
  124. .FastConcat(T1entities.count).FastConcat(
  125. " Entity 2: ".FastConcat(typeof(T2).ToString()).FastConcat(" count: ")
  126. .FastConcat(T2entities.count)
  127. .FastConcat(" Entity 3: ".FastConcat(typeof(T3).ToString()))
  128. .FastConcat(" count: ").FastConcat(T3entities.count)
  129. .FastConcat(" Entity 4: ".FastConcat(typeof(T4).ToString()))
  130. .FastConcat(" count: ").FastConcat(T4entities.count)));
  131. #endif
  132. return new EntityCollection<T1, T2, T3, T4>(T1entities, T2entities, T3entities, T4entities);
  133. }
  134. public GroupsEnumerable<T> QueryEntities<T>
  135. (in LocalFasterReadOnlyList<ExclusiveGroupStruct> groups) where T : struct, IBaseEntityComponent
  136. {
  137. return new GroupsEnumerable<T>(this, groups);
  138. }
  139. /// <summary>
  140. /// Note: Remember that EntityViewComponents are always put at the end of the generic parameters tuple.
  141. /// It won't compile otherwise
  142. /// </summary>
  143. /// <returns></returns>
  144. public GroupsEnumerable<T1, T2> QueryEntities<T1, T2>(in LocalFasterReadOnlyList<ExclusiveGroupStruct> groups)
  145. where T1 : struct, IBaseEntityComponent where T2 : struct, IBaseEntityComponent
  146. {
  147. return new GroupsEnumerable<T1, T2>(this, groups);
  148. }
  149. public GroupsEnumerable<T1, T2, T3> QueryEntities<T1, T2, T3>
  150. (in LocalFasterReadOnlyList<ExclusiveGroupStruct> groups) where T1 : struct, IBaseEntityComponent
  151. where T2 : struct, IBaseEntityComponent
  152. where T3 : struct, IBaseEntityComponent
  153. {
  154. return new GroupsEnumerable<T1, T2, T3>(this, groups);
  155. }
  156. public GroupsEnumerable<T1, T2, T3, T4> QueryEntities<T1, T2, T3, T4>
  157. (in LocalFasterReadOnlyList<ExclusiveGroupStruct> groups) where T1 : struct, IBaseEntityComponent
  158. where T2 : struct, IBaseEntityComponent
  159. where T3 : struct, IBaseEntityComponent
  160. where T4 : struct, IBaseEntityComponent
  161. {
  162. return new GroupsEnumerable<T1, T2, T3, T4>(this, groups);
  163. }
  164. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  165. public EGIDMapper<T> QueryMappedEntities<T>(ExclusiveGroupStruct groupStructId)
  166. where T : struct, IBaseEntityComponent
  167. {
  168. if (SafeQueryEntityDictionary<T>(groupStructId, out var typeSafeDictionary) == false)
  169. throw new EntityGroupNotFoundException(typeof(T), groupStructId.ToName());
  170. return (typeSafeDictionary as ITypeSafeDictionary<T>).ToEGIDMapper(groupStructId);
  171. }
  172. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  173. public bool TryQueryMappedEntities<T>
  174. (ExclusiveGroupStruct groupStructId, out EGIDMapper<T> mapper) where T : struct, IBaseEntityComponent
  175. {
  176. mapper = default;
  177. if (SafeQueryEntityDictionary<T>(groupStructId, out var typeSafeDictionary) == false
  178. || typeSafeDictionary.count == 0)
  179. return false;
  180. mapper = (typeSafeDictionary as ITypeSafeDictionary<T>).ToEGIDMapper(groupStructId);
  181. return true;
  182. }
  183. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  184. public bool Exists<T>(EGID entityGID) where T : struct, IBaseEntityComponent
  185. {
  186. if (SafeQueryEntityDictionary<T>(entityGID.groupID, out var casted) == false)
  187. return false;
  188. return casted != null && casted.ContainsKey(entityGID.entityID);
  189. }
  190. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  191. public bool Exists<T>(uint id, ExclusiveGroupStruct group) where T : struct, IBaseEntityComponent
  192. {
  193. if (SafeQueryEntityDictionary<T>(group, out var casted) == false)
  194. return false;
  195. return casted != null && casted.ContainsKey(id);
  196. }
  197. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  198. public bool ExistsAndIsNotEmpty(ExclusiveGroupStruct gid)
  199. {
  200. if (groupEntityComponentsDB.TryGetValue(
  201. gid, out FasterDictionary<RefWrapperType, ITypeSafeDictionary> group) == true)
  202. {
  203. return group.count > 0;
  204. }
  205. return false;
  206. }
  207. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  208. public bool HasAny<T>(ExclusiveGroupStruct groupStruct) where T : struct, IBaseEntityComponent
  209. {
  210. return Count<T>(groupStruct) > 0;
  211. }
  212. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  213. public int Count<T>(ExclusiveGroupStruct groupStruct) where T : struct, IBaseEntityComponent
  214. {
  215. if (SafeQueryEntityDictionary<T>(groupStruct, out var typeSafeDictionary) == false)
  216. return 0;
  217. return (int)typeSafeDictionary.count;
  218. }
  219. public bool FoundInGroups<T1>() where T1 : IBaseEntityComponent
  220. {
  221. return groupsPerComponent.ContainsKey(TypeRefWrapper<T1>.wrapper);
  222. }
  223. public bool IsDisposing => _enginesRoot._isDisposing;
  224. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  225. bool SafeQueryEntityDictionary<T>
  226. (out ITypeSafeDictionary typeSafeDictionary
  227. , FasterDictionary<RefWrapperType, ITypeSafeDictionary> entitiesInGroupPerType) where T : IBaseEntityComponent
  228. {
  229. if (entitiesInGroupPerType.TryGetValue(new RefWrapperType(TypeCache<T>.type), out var safeDictionary)
  230. == false)
  231. {
  232. typeSafeDictionary = default;
  233. return false;
  234. }
  235. //return the indexes entities if they exist
  236. typeSafeDictionary = safeDictionary;
  237. return true;
  238. }
  239. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  240. internal bool SafeQueryEntityDictionary<T>
  241. (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : IBaseEntityComponent
  242. {
  243. if (UnsafeQueryEntityDictionary(group, TypeCache<T>.type, out var safeDictionary) == false)
  244. {
  245. typeSafeDictionary = default;
  246. return false;
  247. }
  248. //return the indexes entities if they exist
  249. typeSafeDictionary = safeDictionary;
  250. return true;
  251. }
  252. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  253. internal bool UnsafeQueryEntityDictionary
  254. (ExclusiveGroupStruct group, Type type, out ITypeSafeDictionary typeSafeDictionary)
  255. {
  256. //search for the group
  257. if (groupEntityComponentsDB.TryGetValue(group, out var entitiesInGroupPerType) == false)
  258. {
  259. typeSafeDictionary = null;
  260. return false;
  261. }
  262. //search for the indexed entities in the group
  263. return entitiesInGroupPerType.TryGetValue(new RefWrapperType(type), out typeSafeDictionary);
  264. }
  265. static readonly FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> _emptyDictionary =
  266. new FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>();
  267. readonly EnginesRoot _enginesRoot;
  268. EntitiesStreams _entityStream => _enginesRoot._entityStreams;
  269. //grouped set of entity components, this is the standard way to handle entity components are grouped per
  270. //group, then indexable per type, then indexable per EGID. however the TypeSafeDictionary can return an array of
  271. //values directly, that can be iterated over, so that is possible to iterate over all the entity components of
  272. //a specific type inside a specific group.
  273. FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType, ITypeSafeDictionary>>
  274. groupEntityComponentsDB => _enginesRoot._groupEntityComponentsDB;
  275. //for each entity view type, return the groups (dictionary of entities indexed by entity id) where they are
  276. //found indexed by group id. TypeSafeDictionary are never created, they instead point to the ones hold
  277. //by _groupEntityComponentsDB
  278. // <EntityComponentType <groupID <entityID, EntityComponent>>>
  279. FasterDictionary<RefWrapperType, FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>> groupsPerComponent =>
  280. _enginesRoot._groupsPerEntity;
  281. EnginesRoot.EntityReferenceMap _entityReferencesMap;
  282. }
  283. }