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

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