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