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 17KB

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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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, _IInternalEntityComponent
  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, _IInternalEntityComponent
  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, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent
  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())).FastConcat(" this means that you are mixing descriptors in the same group that do not share the components that you are querying"));
  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, _IInternalEntityComponent
  76. where T2 : struct, _IInternalEntityComponent
  77. where T3 : struct, _IInternalEntityComponent
  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)).FastConcat(" this means that you are mixing descriptors in the same group that do not share the components that you are querying"));
  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, _IInternalEntityComponent
  103. where T2 : struct, _IInternalEntityComponent
  104. where T3 : struct, _IInternalEntityComponent
  105. where T4 : struct, _IInternalEntityComponent
  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)).FastConcat(" this means that you are mixing descriptors in the same group that do not share the components that you are querying"));
  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, _IInternalEntityComponent
  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. /// The Query entity code won't inexplicably compile otherwise
  142. /// </summary>
  143. /// <returns></returns>
  144. public GroupsEnumerable<T1, T2> QueryEntities<T1, T2>(in LocalFasterReadOnlyList<ExclusiveGroupStruct> groups)
  145. where T1 : struct, _IInternalEntityComponent where T2 : struct, _IInternalEntityComponent
  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, _IInternalEntityComponent
  151. where T2 : struct, _IInternalEntityComponent
  152. where T3 : struct, _IInternalEntityComponent
  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, _IInternalEntityComponent
  158. where T2 : struct, _IInternalEntityComponent
  159. where T3 : struct, _IInternalEntityComponent
  160. where T4 : struct, _IInternalEntityComponent
  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, _IInternalEntityComponent
  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, _IInternalEntityComponent
  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. /// <summary>
  184. /// determine if component with specific ID exists in group
  185. /// </summary>
  186. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  187. public bool Exists<T>(EGID entityGID) where T : struct, _IInternalEntityComponent
  188. {
  189. if (SafeQueryEntityDictionary<T>(entityGID.groupID, out var casted) == false)
  190. return false;
  191. return casted != null && casted.ContainsKey(entityGID.entityID);
  192. }
  193. /// <summary>
  194. /// determine if component with specific ID exists in group
  195. /// </summary>
  196. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  197. public bool Exists<T>(uint id, ExclusiveGroupStruct group) where T : struct, _IInternalEntityComponent
  198. {
  199. if (SafeQueryEntityDictionary<T>(group, out var casted) == false)
  200. return false;
  201. return casted != null && casted.ContainsKey(id);
  202. }
  203. /// <summary>
  204. /// determine if group exists and is not empty
  205. /// </summary>
  206. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  207. public bool ExistsAndIsNotEmpty(ExclusiveGroupStruct gid)
  208. {
  209. if (groupEntityComponentsDB.TryGetValue(
  210. gid, out FasterDictionary<RefWrapperType, ITypeSafeDictionary> group) == true)
  211. {
  212. return group.count > 0;
  213. }
  214. return false;
  215. }
  216. /// <summary>
  217. /// determine if entities we specific components are found in group
  218. /// </summary>
  219. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  220. public bool HasAny<T>(ExclusiveGroupStruct groupStruct) where T : struct, _IInternalEntityComponent
  221. {
  222. return Count<T>(groupStruct) > 0;
  223. }
  224. /// <summary>
  225. /// count the number of components in a group
  226. /// </summary>
  227. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  228. public int Count<T>(ExclusiveGroupStruct groupStruct) where T : struct, _IInternalEntityComponent
  229. {
  230. if (SafeQueryEntityDictionary<T>(groupStruct, out var typeSafeDictionary) == false)
  231. return 0;
  232. return (int)typeSafeDictionary.count;
  233. }
  234. public bool FoundInGroups<T1>() where T1 : _IInternalEntityComponent
  235. {
  236. return groupsPerComponent.ContainsKey(TypeRefWrapper<T1>.wrapper);
  237. }
  238. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  239. bool SafeQueryEntityDictionary<T>
  240. (out ITypeSafeDictionary typeSafeDictionary
  241. , FasterDictionary<RefWrapperType, ITypeSafeDictionary> entitiesInGroupPerType) where T : _IInternalEntityComponent
  242. {
  243. if (entitiesInGroupPerType.TryGetValue(new RefWrapperType(TypeCache<T>.type), out var safeDictionary)
  244. == false)
  245. {
  246. typeSafeDictionary = default;
  247. return false;
  248. }
  249. //return the indexes entities if they exist
  250. typeSafeDictionary = safeDictionary;
  251. return true;
  252. }
  253. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  254. internal bool SafeQueryEntityDictionary<T>
  255. (ExclusiveGroupStruct group, out ITypeSafeDictionary typeSafeDictionary) where T : _IInternalEntityComponent
  256. {
  257. if (UnsafeQueryEntityDictionary(group, TypeCache<T>.type, out var safeDictionary) == false)
  258. {
  259. typeSafeDictionary = default;
  260. return false;
  261. }
  262. //return the indexes entities if they exist
  263. typeSafeDictionary = safeDictionary;
  264. return true;
  265. }
  266. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  267. internal bool UnsafeQueryEntityDictionary
  268. (ExclusiveGroupStruct group, Type type, out ITypeSafeDictionary typeSafeDictionary)
  269. {
  270. //search for the group
  271. if (groupEntityComponentsDB.TryGetValue(group, out var entitiesInGroupPerType) == false)
  272. {
  273. typeSafeDictionary = null;
  274. return false;
  275. }
  276. //search for the indexed entities in the group
  277. return entitiesInGroupPerType.TryGetValue(new RefWrapperType(type), out typeSafeDictionary);
  278. }
  279. static readonly FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary> _emptyDictionary =
  280. new FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>();
  281. readonly EnginesRoot _enginesRoot;
  282. EntitiesStreams _entityStream => _enginesRoot._entityStreams;
  283. //grouped set of entity components, this is the standard way to handle entity components are grouped per
  284. //group, then indexable per type, then indexable per EGID. however the TypeSafeDictionary can return an array of
  285. //values directly, that can be iterated over, so that is possible to iterate over all the entity components of
  286. //a specific type inside a specific group.
  287. FasterDictionary<ExclusiveGroupStruct, FasterDictionary<RefWrapperType, ITypeSafeDictionary>>
  288. groupEntityComponentsDB => _enginesRoot._groupEntityComponentsDB;
  289. //for each entity view type, return the groups (dictionary of entities indexed by entity id) where they are
  290. //found indexed by group id. TypeSafeDictionary are never created, they instead point to the ones hold
  291. //by _groupEntityComponentsDB
  292. // <EntityComponentType <groupID <entityID, EntityComponent>>>
  293. FasterDictionary<RefWrapperType, FasterDictionary<ExclusiveGroupStruct, ITypeSafeDictionary>> groupsPerComponent =>
  294. _enginesRoot._groupsPerEntity;
  295. EnginesRoot.EntityReferenceMap _entityReferencesMap;
  296. }
  297. }