Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

TypeSafeDictionary.cs 20KB

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
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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using Svelto.Common;
  4. using Svelto.DataStructures;
  5. using Svelto.DataStructures.Native;
  6. using Svelto.ECS.Hybrid;
  7. namespace Svelto.ECS.Internal
  8. {
  9. sealed class TypeSafeDictionary<TValue> : ITypeSafeDictionary<TValue> where TValue : struct, IEntityComponent
  10. {
  11. static readonly Type _type = typeof(TValue);
  12. static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type);
  13. static readonly bool _hasReference = typeof(INeedEntityReference).IsAssignableFrom(_type);
  14. internal static readonly bool isUnmanaged =
  15. _type.IsUnmanagedEx() && (typeof(IEntityViewComponent).IsAssignableFrom(_type) == false);
  16. public TypeSafeDictionary(uint size)
  17. {
  18. if (isUnmanaged)
  19. implUnmgd =
  20. new SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>,
  21. NativeStrategy<TValue>, NativeStrategy<int>>(size, Allocator.Persistent);
  22. else
  23. {
  24. implMgd =
  25. new SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>,
  26. ManagedStrategy<TValue>, ManagedStrategy<int>>(size, Allocator.Managed);
  27. }
  28. }
  29. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  30. public void Add(uint egidEntityId, in TValue entityComponent)
  31. {
  32. if (isUnmanaged)
  33. implUnmgd.Add(egidEntityId, entityComponent);
  34. else
  35. implMgd.Add(egidEntityId, entityComponent);
  36. }
  37. /// todo: Is this really needed, cannot I just use AddEntitiesFromDictionary? Needs to be checked
  38. public void AddEntityToDictionary(EGID fromEntityGid, EGID toEntityID, ITypeSafeDictionary toGroup)
  39. {
  40. if (isUnmanaged)
  41. {
  42. var valueIndex = implUnmgd.GetIndex(fromEntityGid.entityID);
  43. DBC.ECS.Check.Require(toGroup != null
  44. , "Invalid To Group"); //todo check this, if it's right merge GetIndex
  45. {
  46. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  47. ref var entity = ref implUnmgd.GetDirectValueByRef(valueIndex);
  48. if (_hasEgid)
  49. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID);
  50. toGroupCasted.Add(toEntityID.entityID, entity);
  51. }
  52. }
  53. else
  54. {
  55. var valueIndex = implMgd.GetIndex(fromEntityGid.entityID);
  56. DBC.ECS.Check.Require(toGroup != null
  57. , "Invalid To Group"); //todo check this, if it's right merge GetIndex
  58. {
  59. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  60. ref var entity = ref implMgd.GetDirectValueByRef(valueIndex);
  61. if (_hasEgid)
  62. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID);
  63. toGroupCasted.Add(toEntityID.entityID, entity);
  64. }
  65. }
  66. }
  67. /// <summary>
  68. /// Add entities from external typeSafeDictionary (todo: add use case)
  69. /// </summary>
  70. /// <param name="entitiesToSubmit"></param>
  71. /// <param name="groupId"></param>
  72. /// <param name="enginesRoot"></param>
  73. /// <exception cref="TypeSafeDictionaryException"></exception>
  74. public void AddEntitiesFromDictionary
  75. (ITypeSafeDictionary entitiesToSubmit, ExclusiveGroupStruct groupId, EnginesRoot enginesRoot)
  76. {
  77. var safeDictionary = (entitiesToSubmit as TypeSafeDictionary<TValue>);
  78. if (isUnmanaged)
  79. {
  80. var typeSafeDictionary = safeDictionary.implUnmgd;
  81. foreach (var tuple in typeSafeDictionary)
  82. try
  83. {
  84. var egid = new EGID(tuple.Key, groupId);
  85. if (_hasEgid)
  86. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref tuple.Value, egid);
  87. if (_hasReference)
  88. SetEGIDWithoutBoxing<TValue>.SetRefWithoutBoxing(
  89. ref tuple.Value, enginesRoot.entityLocator.GetEntityReference(egid));
  90. implUnmgd.Add(tuple.Key, tuple.Value);
  91. }
  92. catch (Exception e)
  93. {
  94. Console.LogException(
  95. e, "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString()).FastConcat(", group ").FastConcat(groupId.ToName()).FastConcat(", id ").FastConcat(tuple.Key));
  96. throw;
  97. }
  98. }
  99. else
  100. {
  101. var typeSafeDictionary = safeDictionary.implMgd;
  102. foreach (var tuple in typeSafeDictionary)
  103. try
  104. {
  105. if (_hasEgid)
  106. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(
  107. ref tuple.Value, new EGID(tuple.Key, groupId));
  108. implMgd.Add(tuple.Key, tuple.Value);
  109. }
  110. catch (Exception e)
  111. {
  112. Console.LogException(
  113. e, "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString()).FastConcat(", group ").FastConcat(groupId.ToName()).FastConcat(", id ").FastConcat(tuple.Key));
  114. throw;
  115. }
  116. }
  117. }
  118. public void ExecuteEnginesAddOrSwapCallbacks
  119. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> entityComponentEnginesDB
  120. , ITypeSafeDictionary realDic, ExclusiveGroupStruct? fromGroup, ExclusiveGroupStruct toGroup
  121. , in PlatformProfiler profiler)
  122. {
  123. if (isUnmanaged)
  124. {
  125. var typeSafeDictionary = realDic as ITypeSafeDictionary<TValue>;
  126. //this can be optimized, should pass all the entities and not restart the process for each one
  127. foreach (var value in implUnmgd)
  128. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(entityComponentEnginesDB
  129. , ref typeSafeDictionary[value.Key], fromGroup
  130. , in profiler, new EGID(value.Key, toGroup));
  131. }
  132. else
  133. {
  134. var typeSafeDictionary = realDic as ITypeSafeDictionary<TValue>;
  135. //this can be optimized, should pass all the entities and not restart the process for each one
  136. foreach (var value in implMgd)
  137. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(entityComponentEnginesDB
  138. , ref typeSafeDictionary[value.Key], fromGroup
  139. , in profiler, new EGID(value.Key, toGroup));
  140. }
  141. }
  142. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  143. public void Clear()
  144. {
  145. if (isUnmanaged)
  146. {
  147. implUnmgd.Clear();
  148. }
  149. else
  150. {
  151. implMgd.Clear();
  152. }
  153. }
  154. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  155. public void FastClear()
  156. {
  157. if (isUnmanaged)
  158. {
  159. implUnmgd.FastClear();
  160. }
  161. else
  162. {
  163. implMgd.FastClear();
  164. }
  165. }
  166. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  167. public bool ContainsKey(uint egidEntityId)
  168. {
  169. if (isUnmanaged)
  170. {
  171. return implUnmgd.ContainsKey(egidEntityId);
  172. }
  173. else
  174. {
  175. return implMgd.ContainsKey(egidEntityId);
  176. }
  177. }
  178. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  179. public ITypeSafeDictionary Create()
  180. {
  181. return TypeSafeDictionaryFactory<TValue>.Create(1);
  182. }
  183. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  184. public uint GetIndex(uint valueEntityId)
  185. {
  186. if (isUnmanaged)
  187. {
  188. return implUnmgd.GetIndex(valueEntityId);
  189. }
  190. else
  191. {
  192. return implMgd.GetIndex(valueEntityId);
  193. }
  194. }
  195. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  196. public ref TValue GetOrCreate(uint idEntityId)
  197. {
  198. if (isUnmanaged)
  199. {
  200. return ref implUnmgd.GetOrCreate(idEntityId);
  201. }
  202. else
  203. {
  204. return ref implMgd.GetOrCreate(idEntityId);
  205. }
  206. }
  207. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  208. public IBuffer<TValue> GetValues(out uint count)
  209. {
  210. if (isUnmanaged)
  211. {
  212. return implUnmgd.GetValues(out count);
  213. }
  214. else
  215. {
  216. return implMgd.GetValues(out count);
  217. }
  218. }
  219. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  220. public ref TValue GetDirectValueByRef(uint key)
  221. {
  222. if (isUnmanaged)
  223. {
  224. return ref implUnmgd.GetDirectValueByRef(key);
  225. }
  226. else
  227. {
  228. return ref implMgd.GetDirectValueByRef(key);
  229. }
  230. }
  231. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  232. public bool Has(uint key)
  233. {
  234. if (isUnmanaged)
  235. {
  236. return implUnmgd.ContainsKey(key);
  237. }
  238. else
  239. {
  240. return implMgd.ContainsKey(key);
  241. }
  242. }
  243. public void ExecuteEnginesSwapOrRemoveCallbacks
  244. (EGID fromEntityGid, EGID? toEntityID, ITypeSafeDictionary toGroup
  245. , FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, in PlatformProfiler profiler)
  246. {
  247. if (isUnmanaged)
  248. {
  249. var valueIndex = implUnmgd.GetIndex(fromEntityGid.entityID);
  250. ref var entity = ref implUnmgd.GetDirectValueByRef(valueIndex);
  251. //move
  252. if (toGroup != null)
  253. {
  254. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  255. var previousGroup = fromEntityGid.groupID;
  256. //todo: why is setting the EGID if this code just execute callbacks?
  257. if (_hasEgid)
  258. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID.Value);
  259. var index = toGroupCasted.GetIndex(toEntityID.Value.entityID);
  260. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(engines, ref toGroupCasted.GetDirectValueByRef(index)
  261. , previousGroup, in profiler, toEntityID.Value);
  262. }
  263. //remove
  264. else
  265. {
  266. ExecuteEnginesRemoveCallbackOnSingleEntity(engines, ref entity, in profiler, fromEntityGid);
  267. }
  268. }
  269. else
  270. {
  271. var valueIndex = implMgd.GetIndex(fromEntityGid.entityID);
  272. ref var entity = ref implMgd.GetDirectValueByRef(valueIndex);
  273. if (toGroup != null)
  274. {
  275. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  276. var previousGroup = fromEntityGid.groupID;
  277. //todo: why is setting the EGID if this code just execute callbacks?
  278. if (_hasEgid)
  279. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID.Value);
  280. var index = toGroupCasted.GetIndex(toEntityID.Value.entityID);
  281. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(engines, ref toGroupCasted.GetDirectValueByRef(index)
  282. , previousGroup, in profiler, toEntityID.Value);
  283. }
  284. else
  285. {
  286. ExecuteEnginesRemoveCallbackOnSingleEntity(engines, ref entity, in profiler, fromEntityGid);
  287. }
  288. }
  289. }
  290. public void ExecuteEnginesRemoveCallbacks
  291. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, in PlatformProfiler profiler
  292. , ExclusiveGroupStruct group)
  293. {
  294. if (isUnmanaged)
  295. {
  296. foreach (var value in implUnmgd)
  297. ExecuteEnginesRemoveCallbackOnSingleEntity(engines, ref implUnmgd.GetValueByRef(value.Key)
  298. , in profiler, new EGID(value.Key, group));
  299. }
  300. else
  301. {
  302. foreach (var value in implMgd)
  303. ExecuteEnginesRemoveCallbackOnSingleEntity(engines, ref implMgd.GetValueByRef(value.Key)
  304. , in profiler, new EGID(value.Key, group));
  305. }
  306. }
  307. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  308. public void RemoveEntityFromDictionary(EGID fromEntityGid)
  309. {
  310. if (isUnmanaged)
  311. {
  312. implUnmgd.Remove(fromEntityGid.entityID);
  313. }
  314. else
  315. {
  316. implMgd.Remove(fromEntityGid.entityID);
  317. }
  318. }
  319. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  320. public void ResizeTo(uint size)
  321. {
  322. if (isUnmanaged)
  323. {
  324. implUnmgd.ResizeTo(size);
  325. }
  326. else
  327. {
  328. implMgd.ResizeTo(size);
  329. }
  330. }
  331. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  332. public void Trim()
  333. {
  334. if (isUnmanaged)
  335. {
  336. implUnmgd.Trim();
  337. }
  338. else
  339. {
  340. implMgd.Trim();
  341. }
  342. }
  343. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  344. public bool TryFindIndex(uint entityId, out uint index)
  345. {
  346. if (isUnmanaged)
  347. {
  348. return implUnmgd.TryFindIndex(entityId, out index);
  349. }
  350. else
  351. {
  352. return implMgd.TryFindIndex(entityId, out index);
  353. }
  354. }
  355. public void KeysEvaluator(Action<uint> action)
  356. {
  357. if (isUnmanaged)
  358. {
  359. foreach (var key in implUnmgd.keys)
  360. {
  361. action(key);
  362. }
  363. }
  364. else
  365. {
  366. foreach (var key in implMgd.keys)
  367. {
  368. action(key);
  369. }
  370. }
  371. }
  372. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  373. public bool TryGetValue(uint entityId, out TValue item)
  374. {
  375. if (isUnmanaged)
  376. {
  377. return implUnmgd.TryGetValue(entityId, out item);
  378. }
  379. else
  380. {
  381. return implMgd.TryGetValue(entityId, out item);
  382. }
  383. }
  384. public uint count
  385. {
  386. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  387. get
  388. {
  389. if (isUnmanaged)
  390. {
  391. return (uint) implUnmgd.count;
  392. }
  393. else
  394. {
  395. return (uint) implMgd.count;
  396. }
  397. }
  398. }
  399. public ref TValue this[uint idEntityId]
  400. {
  401. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  402. get
  403. {
  404. if (isUnmanaged)
  405. {
  406. return ref implUnmgd.GetValueByRef(idEntityId);
  407. }
  408. else
  409. {
  410. return ref implMgd.GetValueByRef(idEntityId);
  411. }
  412. }
  413. }
  414. public void Dispose()
  415. {
  416. if (isUnmanaged)
  417. implUnmgd.Dispose();
  418. else
  419. implMgd.Dispose();
  420. GC.SuppressFinalize(this);
  421. }
  422. void ExecuteEnginesAddOrSwapCallbacksOnSingleEntity
  423. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, ref TValue entity
  424. , ExclusiveGroupStruct? previousGroup, in PlatformProfiler profiler, EGID egid)
  425. {
  426. //get all the engines linked to TValue
  427. if (!engines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  428. return;
  429. if (previousGroup == null)
  430. {
  431. for (var i = 0; i < entityComponentsEngines.count; i++)
  432. try
  433. {
  434. using (profiler.Sample(entityComponentsEngines[i].name))
  435. {
  436. (entityComponentsEngines[i].engine as IReactOnAddAndRemove<TValue>).Add(ref entity, egid);
  437. }
  438. }
  439. catch
  440. {
  441. Console.LogError("Code crashed inside Add callback ".FastConcat(typeof(TValue).ToString()));
  442. throw;
  443. }
  444. }
  445. else
  446. {
  447. for (var i = 0; i < entityComponentsEngines.count; i++)
  448. try
  449. {
  450. using (profiler.Sample(entityComponentsEngines[i].name))
  451. {
  452. (entityComponentsEngines[i].engine as IReactOnSwap<TValue>).MovedTo(
  453. ref entity, previousGroup.Value, egid);
  454. }
  455. }
  456. catch (Exception)
  457. {
  458. Console.LogError("Code crashed inside MoveTo callback ".FastConcat(typeof(TValue).ToString()));
  459. throw;
  460. }
  461. }
  462. }
  463. static void ExecuteEnginesRemoveCallbackOnSingleEntity
  464. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, ref TValue entity
  465. , in PlatformProfiler profiler, EGID egid)
  466. {
  467. if (!engines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  468. return;
  469. for (var i = 0; i < entityComponentsEngines.count; i++)
  470. try
  471. {
  472. using (profiler.Sample(entityComponentsEngines[i].name))
  473. {
  474. (entityComponentsEngines[i].engine as IReactOnAddAndRemove<TValue>).Remove(ref entity, egid);
  475. }
  476. }
  477. catch
  478. {
  479. Console.LogError("Code crashed inside Remove callback ".FastConcat(typeof(TValue).ToString()));
  480. throw;
  481. }
  482. }
  483. internal SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>, ManagedStrategy<TValue>,
  484. ManagedStrategy<int>> implMgd;
  485. //used directly by native methods
  486. internal SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>, NativeStrategy<TValue>,
  487. NativeStrategy<int>> implUnmgd;
  488. }
  489. }