Mirror of Svelto.ECS because we're a fan of it
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
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
il y a 4 ans
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using Svelto.Common;
  4. using Svelto.DataStructures;
  5. using Svelto.ECS.Hybrid;
  6. namespace Svelto.ECS.Internal
  7. {
  8. sealed class TypeSafeDictionary<TValue> : ITypeSafeDictionary<TValue> where TValue : struct, IEntityComponent
  9. {
  10. static readonly Type _type = typeof(TValue);
  11. static readonly bool _hasEgid = typeof(INeedEGID).IsAssignableFrom(_type);
  12. static readonly bool _hasReference = typeof(INeedEntityReference).IsAssignableFrom(_type);
  13. internal static readonly bool isUnmanaged =
  14. _type.IsUnmanagedEx() && (typeof(IEntityViewComponent).IsAssignableFrom(_type) == false);
  15. internal SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>, ManagedStrategy<TValue>,
  16. ManagedStrategy<int>> implMgd;
  17. //used directly by native methods
  18. internal SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>, NativeStrategy<TValue>,
  19. NativeStrategy<int>> implUnmgd;
  20. public TypeSafeDictionary(uint size)
  21. {
  22. if (isUnmanaged)
  23. implUnmgd = new SveltoDictionary<uint, TValue, NativeStrategy<SveltoDictionaryNode<uint>>,
  24. NativeStrategy<TValue>, NativeStrategy<int>>(size, Allocator.Persistent);
  25. else
  26. {
  27. implMgd = new SveltoDictionary<uint, TValue, ManagedStrategy<SveltoDictionaryNode<uint>>,
  28. ManagedStrategy<TValue>, ManagedStrategy<int>>(size, Allocator.Managed);
  29. }
  30. }
  31. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  32. public void Add(uint egidEntityId, in TValue entityComponent)
  33. {
  34. if (isUnmanaged)
  35. implUnmgd.Add(egidEntityId, entityComponent);
  36. else
  37. implMgd.Add(egidEntityId, entityComponent);
  38. }
  39. /// todo: Is this really needed, cannot I just use AddEntitiesFromDictionary? Needs to be checked
  40. public void AddEntityToDictionary(EGID fromEntityGid, EGID toEntityID, ITypeSafeDictionary toGroup)
  41. {
  42. if (isUnmanaged)
  43. {
  44. var valueIndex = implUnmgd.GetIndex(fromEntityGid.entityID);
  45. DBC.ECS.Check.Require(toGroup != null
  46. , "Invalid To Group"); //todo check this, if it's right merge GetIndex
  47. {
  48. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  49. ref var entity = ref implUnmgd.GetDirectValueByRef(valueIndex);
  50. if (_hasEgid)
  51. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID);
  52. toGroupCasted.Add(toEntityID.entityID, entity);
  53. }
  54. }
  55. else
  56. {
  57. var valueIndex = implMgd.GetIndex(fromEntityGid.entityID);
  58. DBC.ECS.Check.Require(toGroup != null
  59. , "Invalid To Group"); //todo check this, if it's right merge GetIndex
  60. {
  61. var toGroupCasted = toGroup as ITypeSafeDictionary<TValue>;
  62. ref var entity = ref implMgd.GetDirectValueByRef(valueIndex);
  63. if (_hasEgid)
  64. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(ref entity, toEntityID);
  65. toGroupCasted.Add(toEntityID.entityID, entity);
  66. }
  67. }
  68. }
  69. /// <summary>
  70. /// Add entities from external typeSafeDictionary (todo: add use case)
  71. /// </summary>
  72. /// <param name="entitiesToSubmit"></param>
  73. /// <param name="groupId"></param>
  74. /// <param name="enginesRoot"></param>
  75. /// <exception cref="TypeSafeDictionaryException"></exception>
  76. public void AddEntitiesFromDictionary
  77. (ITypeSafeDictionary entitiesToSubmit, uint groupId, EnginesRoot enginesRoot)
  78. {
  79. var safeDictionary = (entitiesToSubmit as TypeSafeDictionary<TValue>);
  80. if (isUnmanaged)
  81. {
  82. var typeSafeDictionary = safeDictionary.implUnmgd;
  83. foreach (var tuple in typeSafeDictionary)
  84. try
  85. {
  86. var egid = new EGID(tuple.Key, groupId);
  87. if (_hasEgid)
  88. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(
  89. ref tuple.Value, egid);
  90. if (_hasReference)
  91. SetEGIDWithoutBoxing<TValue>.SetRefWithoutBoxing(
  92. ref tuple.Value, enginesRoot.entityLocator.GetEntityReference(egid));
  93. implUnmgd.Add(tuple.Key, tuple.Value);
  94. }
  95. catch (Exception e)
  96. {
  97. Console.LogException(
  98. e, "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString()).FastConcat(", group ").FastConcat(groupId).FastConcat(", id ").FastConcat(tuple.Key));
  99. throw;
  100. }
  101. }
  102. else
  103. {
  104. var typeSafeDictionary = safeDictionary.implMgd;
  105. foreach (var tuple in typeSafeDictionary)
  106. try
  107. {
  108. if (_hasEgid)
  109. SetEGIDWithoutBoxing<TValue>.SetIDWithoutBoxing(
  110. ref tuple.Value, new EGID(tuple.Key, groupId));
  111. implMgd.Add(tuple.Key, tuple.Value);
  112. }
  113. catch (Exception e)
  114. {
  115. Console.LogException(
  116. e, "trying to add an EntityComponent with the same ID more than once Entity: ".FastConcat(typeof(TValue).ToString()).FastConcat(", group ").FastConcat(groupId).FastConcat(", id ").FastConcat(tuple.Key));
  117. throw;
  118. }
  119. }
  120. }
  121. public void ExecuteEnginesAddOrSwapCallbacks
  122. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> entityComponentEnginesDB
  123. , ITypeSafeDictionary realDic, ExclusiveGroupStruct? fromGroup, ExclusiveGroupStruct toGroup
  124. , in PlatformProfiler profiler)
  125. {
  126. if (isUnmanaged)
  127. {
  128. var typeSafeDictionary = realDic as ITypeSafeDictionary<TValue>;
  129. //this can be optimized, should pass all the entities and not restart the process for each one
  130. foreach (var value in implUnmgd)
  131. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(entityComponentEnginesDB
  132. , ref typeSafeDictionary[value.Key], fromGroup
  133. , in profiler, new EGID(value.Key, toGroup));
  134. }
  135. else
  136. {
  137. var typeSafeDictionary = realDic as ITypeSafeDictionary<TValue>;
  138. //this can be optimized, should pass all the entities and not restart the process for each one
  139. foreach (var value in implMgd)
  140. ExecuteEnginesAddOrSwapCallbacksOnSingleEntity(entityComponentEnginesDB
  141. , ref typeSafeDictionary[value.Key], fromGroup
  142. , in profiler, new EGID(value.Key, toGroup));
  143. }
  144. }
  145. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  146. public void Clear()
  147. {
  148. if (isUnmanaged)
  149. {
  150. implUnmgd.Clear();
  151. }
  152. else
  153. {
  154. implMgd.Clear();
  155. }
  156. }
  157. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  158. public void FastClear()
  159. {
  160. if (isUnmanaged)
  161. {
  162. implUnmgd.FastClear();
  163. }
  164. else
  165. {
  166. implMgd.FastClear();
  167. }
  168. }
  169. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  170. public bool ContainsKey(uint egidEntityId)
  171. {
  172. if (isUnmanaged)
  173. {
  174. return implUnmgd.ContainsKey(egidEntityId);
  175. }
  176. else
  177. {
  178. return implMgd.ContainsKey(egidEntityId);
  179. }
  180. }
  181. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  182. public ITypeSafeDictionary Create() { return TypeSafeDictionaryFactory<TValue>.Create(1); }
  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. static void ExecuteEnginesRemoveCallbackOnSingleEntity
  415. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, ref TValue entity
  416. , in PlatformProfiler profiler, EGID egid)
  417. {
  418. if (!engines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  419. return;
  420. for (var i = 0; i < entityComponentsEngines.count; i++)
  421. try
  422. {
  423. using (profiler.Sample(entityComponentsEngines[i].name))
  424. {
  425. (entityComponentsEngines[i].engine as IReactOnAddAndRemove<TValue>).Remove(ref entity, egid);
  426. }
  427. }
  428. catch
  429. {
  430. Console.LogError(
  431. "Code crashed inside Remove callback ".FastConcat(typeof(TValue).ToString()));
  432. throw;
  433. }
  434. }
  435. void ExecuteEnginesAddOrSwapCallbacksOnSingleEntity
  436. (FasterDictionary<RefWrapperType, FasterList<ReactEngineContainer>> engines, ref TValue entity
  437. , ExclusiveGroupStruct? previousGroup, in PlatformProfiler profiler, EGID egid)
  438. {
  439. //get all the engines linked to TValue
  440. if (!engines.TryGetValue(new RefWrapperType(_type), out var entityComponentsEngines))
  441. return;
  442. if (previousGroup == null)
  443. {
  444. for (var i = 0; i < entityComponentsEngines.count; i++)
  445. try
  446. {
  447. using (profiler.Sample(entityComponentsEngines[i].name))
  448. {
  449. (entityComponentsEngines[i].engine as IReactOnAddAndRemove<TValue>).Add(ref entity, egid);
  450. }
  451. }
  452. catch
  453. {
  454. Console.LogError(
  455. "Code crashed inside Add callback ".FastConcat(typeof(TValue).ToString()));
  456. throw;
  457. }
  458. }
  459. else
  460. {
  461. for (var i = 0; i < entityComponentsEngines.count; i++)
  462. try
  463. {
  464. using (profiler.Sample(entityComponentsEngines[i].name))
  465. {
  466. (entityComponentsEngines[i].engine as IReactOnSwap<TValue>).MovedTo(
  467. ref entity, previousGroup.Value, egid);
  468. }
  469. }
  470. catch (Exception)
  471. {
  472. Console.LogError(
  473. "Code crashed inside MoveTo callback ".FastConcat(typeof(TValue).ToString()));
  474. throw;
  475. }
  476. }
  477. }
  478. public void Dispose()
  479. {
  480. if (isUnmanaged)
  481. implUnmgd.Dispose();
  482. else
  483. implMgd.Dispose();
  484. GC.SuppressFinalize(this);
  485. }
  486. }
  487. }