From 4703f4ee6bb5985ded650cc7fbf2dc9be2ca2e43 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Thu, 29 Mar 2018 15:52:25 +0100 Subject: [PATCH 1/6] refactoring in progress --- EnginesRoot.DoubleBufferedEntityViews.cs | 33 +++ EnginesRoot.GenericEntityFactory.cs | 53 ++++ EnginesRoot.GenericEntityFunctions.cs | 46 +++ .../TypeSafeFasterListForECS.cs | 8 +- Svelto.ECS/EnginesRootEngines.cs | 31 +- Svelto.ECS/EnginesRootEntities.cs | 275 +++++------------- Svelto.ECS/EnginesRootSubmission.cs | 105 +++---- Svelto.ECS/EntityDescriptor.cs | 23 +- Svelto.ECS/EntityFactory.cs | 68 ++--- Svelto.ECS/EntityInfoImplementor.cs | 9 - Svelto.ECS/EntityInfoView.cs | 8 + Svelto.ECS/EntityViewBuilder.cs | 16 +- Svelto.ECS/EntityViewsDB.cs | 98 ++----- Svelto.ECS/ExclusiveGroups.cs | 7 + Svelto.ECS/IEnginesInterfaces.cs | 26 -- Svelto.ECS/IEntityDescriptorHolder.cs | 2 +- Svelto.ECS/IEntityFactory.cs | 55 ++++ Svelto.ECS/IEntityFunctions.cs | 16 + Svelto.ECS/IEntityViewsDB.cs | 10 +- 19 files changed, 393 insertions(+), 496 deletions(-) create mode 100644 EnginesRoot.DoubleBufferedEntityViews.cs create mode 100644 EnginesRoot.GenericEntityFactory.cs create mode 100644 EnginesRoot.GenericEntityFunctions.cs delete mode 100644 Svelto.ECS/EntityInfoImplementor.cs create mode 100644 Svelto.ECS/EntityInfoView.cs create mode 100644 Svelto.ECS/ExclusiveGroups.cs delete mode 100644 Svelto.ECS/IEnginesInterfaces.cs create mode 100644 Svelto.ECS/IEntityFactory.cs create mode 100644 Svelto.ECS/IEntityFunctions.cs diff --git a/EnginesRoot.DoubleBufferedEntityViews.cs b/EnginesRoot.DoubleBufferedEntityViews.cs new file mode 100644 index 0000000..380a4a3 --- /dev/null +++ b/EnginesRoot.DoubleBufferedEntityViews.cs @@ -0,0 +1,33 @@ +using System.Collections; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot + { + class DoubleBufferedEntityViews where T : class, IDictionary, new() + { + readonly T _entityViewsToAddBufferA = new T(); + readonly T _entityViewsToAddBufferB = new T(); + + internal DoubleBufferedEntityViews() + { + this.other = _entityViewsToAddBufferA; + this.current = _entityViewsToAddBufferB; + } + + internal T other; + internal T current; + + internal void Swap() + { + var toSwap = other; + other = current; + current = toSwap; + } + } + } +} \ No newline at end of file diff --git a/EnginesRoot.GenericEntityFactory.cs b/EnginesRoot.GenericEntityFactory.cs new file mode 100644 index 0000000..0fa071f --- /dev/null +++ b/EnginesRoot.GenericEntityFactory.cs @@ -0,0 +1,53 @@ +using Svelto.ECS.Internal; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot + { + class GenericEntityFactory : IEntityFactory + { + readonly DataStructures.WeakReference _weakEngine; + + public GenericEntityFactory(DataStructures.WeakReference weakReference) + { + _weakEngine = weakReference; + } + + public void BuildEntity(int entityID, object[] implementors) where T : IEntityDescriptor, new() + { + _weakEngine.Target.BuildEntity(entityID, implementors); + } + + public void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null) + { + _weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors); + } + + public void BuildEntityInGroup(int entityID, int groupID, object[] implementors) + where T : IEntityDescriptor, new() + { + _weakEngine.Target.BuildEntityInGroup(entityID, groupID, implementors); + } + + public void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, + object[] implementors) + { + _weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors); + } + + public void PreallocateEntitySpace(int size) where T : IEntityDescriptor, new() + { + _weakEngine.Target.Preallocate(ExclusiveGroups.StandardEntity, size); + } + + public void PreallocateEntitySpaceInGroup(int groupID, int size) where T : IEntityDescriptor, new() + { + _weakEngine.Target.Preallocate(groupID, size); + } + } + } +} \ No newline at end of file diff --git a/EnginesRoot.GenericEntityFunctions.cs b/EnginesRoot.GenericEntityFunctions.cs new file mode 100644 index 0000000..de14160 --- /dev/null +++ b/EnginesRoot.GenericEntityFunctions.cs @@ -0,0 +1,46 @@ +using Svelto.ECS.Internal; + +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR +using Svelto.ECS.Profiler; +#endif + +namespace Svelto.ECS +{ + public partial class EnginesRoot + { + class GenericEntityFunctions : IEntityFunctions + { + readonly DataStructures.WeakReference _weakReference; + + public GenericEntityFunctions(DataStructures.WeakReference weakReference) + { + _weakReference = weakReference; + } + + public void RemoveEntity(int entityID) + { + _weakReference.Target.RemoveEntity(entityID, ExclusiveGroups.StandardEntity); + } + + public void RemoveEntity(int entityID, int groupID) + { + _weakReference.Target.RemoveEntity(entityID, groupID); + } + + public void RemoveGroupAndEntities(int groupID) + { + _weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID); + } + + public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) + { + _weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID); + } + + public void SwapEntityGroup(int entityID, int toGroupID) + { + _weakReference.Target.SwapEntityGroup(entityID, ExclusiveGroups.StandardEntity, toGroupID); + } + } + } +} \ No newline at end of file diff --git a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs index 0fc8437..e6603c4 100644 --- a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs +++ b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs @@ -15,7 +15,7 @@ namespace Svelto.ECS.Internal bool MappedRemove(int entityID); ITypeSafeDictionary CreateIndexedDictionary(); IEntityView[] ToArrayFast(out int count); - void ReserveCapacity(int capacity); + void AddCapacity(int capacity); } class TypeSafeFasterListForECS : FasterList where T : IEntityView @@ -66,10 +66,10 @@ namespace Svelto.ECS.Internal _mappedIndices[entityView.ID] = index; } - public void ReserveCapacity(int capacity) + public void AddCapacity(int capacity) { - if (ToArrayFast().Length < capacity) - Resize(capacity); + if (ToArrayFast().Length < Count + capacity) + Resize(Count + capacity); } public int GetIndexFromID(int entityID) diff --git a/Svelto.ECS/EnginesRootEngines.cs b/Svelto.ECS/EnginesRootEngines.cs index 249e82f..a7782b1 100644 --- a/Svelto.ECS/EnginesRootEngines.cs +++ b/Svelto.ECS/EnginesRootEngines.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using Svelto.DataStructures; using Svelto.ECS.Internal; @@ -39,16 +38,12 @@ namespace Svelto.ECS _otherEngines = new FasterList(); _entityViewsDB = new Dictionary(); - _metaEntityViewsDB = new Dictionary(); _groupEntityViewsDB = new Dictionary>(); - _entityViewsDBDic = new Dictionary(); - _metaEntityViewsDBDic = new Dictionary(); + _groupedEntityViewsDBDic = new Dictionary>(); - _entityViewsToAdd = new DoubleBufferedEntityViews>(); - _metaEntityViewsToAdd = new DoubleBufferedEntityViews>(); _groupedEntityViewsToAdd = new DoubleBufferedEntityViews>>(); - _DB = new EntityViewsDB(_entityViewsDB, _metaEntityViewsDB, _entityViewsDBDic, _metaEntityViewsDBDic, _groupEntityViewsDB); + _DB = new EntityViewsDB(_entityViewsDB, _groupedEntityViewsDBDic, _groupEntityViewsDB); _scheduler = entityViewScheduler; _scheduler.Schedule(new WeakAction(SubmitEntityViews)); @@ -125,27 +120,5 @@ namespace Svelto.ECS static readonly Type _entityViewType= typeof(EntityView); static readonly Type _object = typeof(object); - - class DoubleBufferedEntityViews where T : class, IDictionary, new() - { - readonly T _entityViewsToAddBufferA = new T(); - readonly T _entityViewsToAddBufferB = new T(); - - internal DoubleBufferedEntityViews() - { - this.other = _entityViewsToAddBufferA; - this.current = _entityViewsToAddBufferB; - } - - internal T other; - internal T current; - - internal void Swap() - { - var toSwap = other; - other = current; - current = toSwap; - } - } } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index 0b11704..77fbbfa 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -18,20 +18,10 @@ namespace Svelto.ECS if (entity.Value.isQueryiableEntityView) foreach (var entityView in entity.Value) RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key); - - foreach (var entity in _metaEntityViewsDB) - { - foreach (var entityView in entity.Value) - RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key); - } } - /// - /// an EnginesRoot reference cannot be held by anything else than the Composition Root - /// where it has been created. IEntityFactory and IEntityFunctions allow a weakreference - /// of the EnginesRoot to be passed around. - /// - /// + ///-------------------------------------------- + public IEntityFactory GenerateEntityFactory() { return new GenericEntityFactory(new DataStructures.WeakReference(this)); @@ -42,95 +32,49 @@ namespace Svelto.ECS return new GenericEntityFunctions(new DataStructures.WeakReference(this)); } - /// - /// The EntityDescriptor doesn't need to be ever instantiated. It just describes the Entity - /// itself in terms of EntityViews to build. The Implementors are passed to fill the - /// references of the EntityViews components. Please read the articles on my blog - /// to understand better the terminologies - /// - /// - /// - /// - void BuildEntity(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() - { - EntityFactory.BuildEntityViews - (entityID, _entityViewsToAdd.current, EntityDescriptorTemplate.Default, implementors); - } + ///-------------------------------------------- - /// - /// When the type of the entity is not known (this is a special case!) an EntityDescriptorInfo - /// can be built in place of the generic parameter T. - /// - /// - /// - /// - void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors) + void BuildEntity(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() { - EntityFactory.BuildEntityViews - (entityID, _entityViewsToAdd.current, entityDescriptor, implementors); + BuildEntityInGroup + (entityID, ExclusiveGroups.StandardEntity, implementors); } - /// - /// A meta entity is a way to manage a set of entitites that are not easily - /// queriable otherwise. For example you may want to group existing entities - /// by size and type and then use the meta entity entityView to manage the data - /// shared among the single entities of the same type and size. This will - /// prevent the scenario where the coder is forced to parse all the entities to - /// find the ones of the same size and type. - /// Since the entities are managed through the shared entityView, the same - /// shared entityView must be found on the single entities of the same type and size. - /// The shared entityView of the meta entity is then used by engines that are meant - /// to manage a group of entities through a single entityView. - /// The same engine can manage several meta entities entityViews too. - /// The Engine manages the logic of the Meta EntityView data and other engines - /// can read back this data through the normal entity as the shared entityView - /// will be present in their descriptor too. - /// It's a way to control a group of Entities through a entityView only. - /// This set of entities can share exactly the same entityView reference if - /// built through this function. In this way, if you need to set a variable - /// on a group of entities, instead to inject N entityViews and iterate over - /// them to set the same value, you can inject just one entityView, set the value - /// and be sure that the value is shared between entities. - /// - /// - /// - /// - void BuildMetaEntity(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new() + void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors) { - EntityFactory.BuildEntityViews(metaEntityID, _metaEntityViewsToAdd.current, - EntityDescriptorTemplate.Default, implementors); + BuildEntityInGroup + (entityID, ExclusiveGroups.StandardEntity, entityDescriptor, implementors); } /// - /// Using this function is like building a normal entity, but the entityViews - /// are grouped by groupID to be more efficently processed inside engines and - /// improve cache locality. Either class entityViews and struct entityViews can be - /// grouped. + /// Build the entity using the entityID, inside the group with Id groupID, using the + /// implementors (if necessary). The entityViews generated will be stored to be + /// added later in the engines. /// + /// /// /// - /// /// void BuildEntityInGroup(int entityID, int groupID, object[] implementors = null) where T : IEntityDescriptor, new() { EntityFactory.BuildGroupedEntityViews(entityID, groupID, _groupedEntityViewsToAdd.current, - _entityViewsToAdd.current, EntityDescriptorTemplate.Default, implementors); } - void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, + void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null) { EntityFactory.BuildGroupedEntityViews(entityID, groupID, _groupedEntityViewsToAdd.current, - _entityViewsToAdd.current, entityDescriptor, implementors); } - void Preallocate(int size) where T : IEntityDescriptor, new() + ///-------------------------------------------- + + void Preallocate(int groupID, int size) where T : IEntityDescriptor, new() { var entityViewsToBuild = ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild; var count = entityViewsToBuild.Length; @@ -140,42 +84,45 @@ namespace Svelto.ECS var entityViewBuilder = entityViewsToBuild[index]; var entityViewType = entityViewBuilder.GetEntityViewType(); + //reserve space for the global pool ITypeSafeList dbList; if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false) _entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); else - dbList.ReserveCapacity(size); - - if (_entityViewsToAdd.current.TryGetValue(entityViewType, out dbList) == false) - _entityViewsToAdd.current[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); + dbList.AddCapacity(size); + + //reserve space for the single group + Dictionary @group; + if (_groupEntityViewsDB.TryGetValue(groupID, out group) == false) + group = _groupEntityViewsDB[groupID] = new Dictionary(); + + if (group.TryGetValue(entityViewType, out dbList) == false) + group[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); else - dbList.ReserveCapacity(size); + dbList.AddCapacity(size); + + if (_groupedEntityViewsToAdd.current.TryGetValue(groupID, out group) == false) + group = _groupEntityViewsDB[groupID] = new Dictionary(); + + //reserve space to the temporary buffer + if (group.TryGetValue(entityViewType, out dbList) == false) + group[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); + else + dbList.AddCapacity(size); } } - void RemoveEntity(ref EntityInfoView entityInfoView, Dictionary viewsDB, - Dictionary entityViewsDBDic) + void RemoveEntity(ref EntityInfoView entityInfoView) { - if (entityInfoView.isInAGroup) - InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, - entityInfoView.groupID, viewsDB, entityViewsDBDic); - else - InternalRemoveFromDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, viewsDB, - entityViewsDBDic); + InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, + entityInfoView.groupID); } - void RemoveEntity(int entityID) + void RemoveEntity(int entityID, int groupID) { - var entityInfoView = _DB.QueryEntityView(entityID); + var entityInfoView = _DB.QueryEntityViewInGroup(entityID, groupID); - RemoveEntity(ref entityInfoView, _entityViewsDB, _entityViewsDBDic); - } - - void RemoveMetaEntity(int metaEntityID) - { - var entityInfoView = _DB.QueryMetaEntityView(metaEntityID); - - RemoveEntity(ref entityInfoView, _metaEntityViewsDB, _metaEntityViewsDBDic); + RemoveEntity(ref entityInfoView); } void RemoveGroupAndEntitiesFromDB(int groupID) @@ -191,30 +138,28 @@ namespace Svelto.ECS { var entityID = entities[i].ID; - InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, _entityViewsDBDic, entityViewType, - entityID); + InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID); } } _groupEntityViewsDB.Remove(groupID); } - void InternalRemoveEntityViewFromDBAndEngines(Dictionary entityViewsDB, - Dictionary entityViewsDBDic, - Type entityViewType, - int entityID) + void InternalRemoveEntityViewFromDBAndEngines(Type entityViewType, + int entityID, + int groupID) { - var entityViews = entityViewsDB[entityViewType]; + var entityViews = _entityViewsDB[entityViewType]; if (entityViews.MappedRemove(entityID) == false) - entityViewsDB.Remove(entityViewType); + _entityViewsDB.Remove(entityViewType); if (entityViews.isQueryiableEntityView) { - var typeSafeDictionary = entityViewsDBDic[entityViewType]; + var typeSafeDictionary = _groupedEntityViewsDBDic[groupID][entityViewType]; var entityView = typeSafeDictionary.GetIndexedEntityView(entityID); if (typeSafeDictionary.Remove(entityID) == false) - entityViewsDBDic.Remove(entityViewType); + _groupedEntityViewsDBDic[groupID].Remove(entityViewType); for (var current = entityViewType; current != _entityViewType; current = current.BaseType) RemoveEntityViewFromEngines(_entityViewEngines, entityView, current); @@ -259,43 +204,32 @@ namespace Svelto.ECS entityInfoView.groupID = toGroupID; } - void InternalRemoveFromDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID, - Dictionary entityViewsDB, - Dictionary entityViewsDBDic) + void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders, + int entityID, int groupID) { + InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID); + var entityViewBuildersCount = entityViewBuilders.Length; for (var i = 0; i < entityViewBuildersCount; i++) { var entityViewType = entityViewBuilders[i].GetEntityViewType(); - InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewsDBDic, entityViewType, entityID); + InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID); } - InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewsDBDic, typeof(EntityInfoView), entityID); - } - - void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders, - int entityID, int groupID, - Dictionary entityViewsDB, - Dictionary entityViewsDBDic) - { - InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID); - - InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB, entityViewsDBDic); + InternalRemoveEntityViewFromDBAndEngines(typeof(EntityInfoView), entityID, groupID); } void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID) { var entityViewBuildersCount = entityViewBuilders.Length; - - var dictionary = _groupEntityViewsDB[groupID]; + var group = _groupEntityViewsDB[groupID]; for (var i = 0; i < entityViewBuildersCount; i++) { var entityViewType = entityViewBuilders[i].GetEntityViewType(); - - var typeSafeList = dictionary[entityViewType]; + var typeSafeList = group[entityViewType]; typeSafeList.MappedRemove(entityID); } } @@ -322,86 +256,17 @@ namespace Svelto.ECS } } - class GenericEntityFactory : IEntityFactory - { - readonly DataStructures.WeakReference _weakEngine; - - public GenericEntityFactory(DataStructures.WeakReference weakReference) - { - _weakEngine = weakReference; - } - - public void BuildEntity(int entityID, object[] implementors) where T : IEntityDescriptor, new() - { - _weakEngine.Target.BuildEntity(entityID, implementors); - } - - public void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors = null) - { - _weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors); - } - - public void BuildMetaEntity(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new() - { - _weakEngine.Target.BuildMetaEntity(metaEntityID, implementors); - } - - public void BuildEntityInGroup(int entityID, int groupID, object[] implementors) - where T : IEntityDescriptor, new() - { - _weakEngine.Target.BuildEntityInGroup(entityID, groupID, implementors); - } - - public void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, - object[] implementors) - { - _weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors); - } - - public void PreallocateEntitySlots(int size) where T : IEntityDescriptor, new() - { - _weakEngine.Target.Preallocate(size); - } - } - - class GenericEntityFunctions : IEntityFunctions - { - readonly DataStructures.WeakReference _weakReference; - - public GenericEntityFunctions(DataStructures.WeakReference weakReference) - { - _weakReference = weakReference; - } - - public void RemoveEntity(int entityID) - { - _weakReference.Target.RemoveEntity(entityID); - } - - public void RemoveMetaEntity(int metaEntityID) - { - _weakReference.Target.RemoveEntity(metaEntityID); - } - - public void RemoveGroupAndEntities(int groupID) - { - _weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID); - } - - public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) - { - _weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID); - } - } - readonly EntityViewsDB _DB; - - readonly Dictionary _entityViewsDB; - - readonly Dictionary _entityViewsDBDic; - readonly Dictionary> _groupEntityViewsDB; - readonly Dictionary _metaEntityViewsDB; - readonly Dictionary _metaEntityViewsDBDic; - + + //grouped set of entity views, this is the standard way to handle entity views + readonly Dictionary> _groupEntityViewsDB; + + //indexable entity views when the entity ID is known. Usually useful to handle + //event based logic. + readonly Dictionary> _groupedEntityViewsDBDic; + + //Global pool of entity views when engines want to manage entityViews regardless + //the group + readonly Dictionary _entityViewsDB; } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootSubmission.cs b/Svelto.ECS/EnginesRootSubmission.cs index 37d9299..009fa10 100644 --- a/Svelto.ECS/EnginesRootSubmission.cs +++ b/Svelto.ECS/EnginesRootSubmission.cs @@ -14,10 +14,7 @@ namespace Svelto.ECS { void SubmitEntityViews() { - bool newEntityViewsHaveBeenAddedWhileIterating = - _metaEntityViewsToAdd.current.Count > 0 - || _entityViewsToAdd.current.Count > 0 - || _groupedEntityViewsToAdd.current.Count > 0; + bool newEntityViewsHaveBeenAddedWhileIterating = _groupedEntityViewsToAdd.current.Count > 0; int numberOfReenteringLoops = 0; @@ -25,29 +22,16 @@ namespace Svelto.ECS { //use other as source from now on //current will be use to write new entityViews - _entityViewsToAdd.Swap(); - _metaEntityViewsToAdd.Swap(); _groupedEntityViewsToAdd.Swap(); - if (_entityViewsToAdd.other.Count > 0) - AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB, _entityViewsDBDic); - - if (_metaEntityViewsToAdd.other.Count > 0) - AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB, _metaEntityViewsDBDic); - if (_groupedEntityViewsToAdd.other.Count > 0) - AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB, _entityViewsDBDic); + AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other); //other can be cleared now - _entityViewsToAdd.other.Clear(); - _metaEntityViewsToAdd.other.Clear(); _groupedEntityViewsToAdd.other.Clear(); //has current new entityViews? - newEntityViewsHaveBeenAddedWhileIterating = - _metaEntityViewsToAdd.current.Count > 0 - || _entityViewsToAdd.current.Count > 0 - || _groupedEntityViewsToAdd.current.Count > 0; + newEntityViewsHaveBeenAddedWhileIterating = _groupedEntityViewsToAdd.current.Count > 0; if (numberOfReenteringLoops > 5) throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method"); @@ -56,59 +40,55 @@ namespace Svelto.ECS } } - void AddEntityViewsToTheDBAndSuitableEngines(Dictionary entityViewsToAdd, - Dictionary entityViewsDB, Dictionary entityViewsDBDic) + void AddEntityViewsToTheDBAndSuitableEngines(Dictionary> groupsToSubmit) { - foreach (var entityViewList in entityViewsToAdd) + //for each groups there is a dictionary of built lists of EntityView grouped by type + foreach (var groupToSubmit in groupsToSubmit) { - AddEntityViewToDB(entityViewsDB, entityViewList); + Dictionary groupDB; + int groupID = groupToSubmit.Key; - if (entityViewList.Value.isQueryiableEntityView) - { - AddEntityViewToEntityViewsDictionary(entityViewsDBDic, entityViewList.Value, entityViewList.Key); - } - } + //if the group doesn't exist in the current DB let's create it frst + if (_groupEntityViewsDB.TryGetValue(groupID, out groupDB) == false) + groupDB = _groupEntityViewsDB[groupID] = new Dictionary(); - foreach (var entityViewList in entityViewsToAdd) - { - if (entityViewList.Value.isQueryiableEntityView) + foreach (var entityViewsPerType in groupToSubmit.Value) { - var type = entityViewList.Key; - for (var current = type; current != _entityViewType; current = current.BaseType) - AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value, - current); - } - } - } + //add the entity View in the group + AddEntityViewToDB(groupDB, entityViewsPerType); + //add the entity view in the gloal pool + AddEntityViewToDB(_entityViewsDB, entityViewsPerType); + //and it's not a struct, add in the indexable DB too + if (entityViewsPerType.Value.isQueryiableEntityView) + { + Dictionary groupDic; - void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary> groupedEntityViewsToAdd, - Dictionary> groupEntityViewsDB, - Dictionary entityViewsDB - , Dictionary entityViewsDBDic) - { - foreach (var group in groupedEntityViewsToAdd) - { - AddEntityViewsToGroupDB(groupEntityViewsDB, @group); + if (_groupedEntityViewsDBDic.TryGetValue(groupID, out groupDic) == false) + groupDic = _groupedEntityViewsDBDic[groupID] = + new Dictionary(); - AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB, entityViewsDBDic); + AddEntityViewToEntityViewsDictionary(groupDic, entityViewsPerType.Value, entityViewsPerType.Key); + } + } } - } - - static void AddEntityViewsToGroupDB(Dictionary> groupEntityViewsDB, - KeyValuePair> @group) - { - Dictionary groupedEntityViewsByType; - - if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false) - groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary(); - foreach (var entityView in @group.Value) + //then submit everything in the engines + foreach (var group in groupsToSubmit) { - groupedEntityViewsByType.Add(entityView.Key, entityView.Value); + foreach (var entityViewList in group.Value) + { + if (entityViewList.Value.isQueryiableEntityView) + { + var type = entityViewList.Key; + for (var current = type; current != _entityViewType; current = current.BaseType) + AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value, current); + } + } } } - static void AddEntityViewToDB(Dictionary entityViewsDB, KeyValuePair entityViewList) + static void AddEntityViewToDB(Dictionary entityViewsDB, + KeyValuePair entityViewList) { ITypeSafeList dbList; @@ -119,7 +99,7 @@ namespace Svelto.ECS } static void AddEntityViewToEntityViewsDictionary(Dictionary entityViewsDBdic, - ITypeSafeList entityViews, Type entityViewType) + ITypeSafeList entityViews, Type entityViewType) { ITypeSafeDictionary entityViewsDic; @@ -156,12 +136,7 @@ namespace Svelto.ECS } } - readonly DoubleBufferedEntityViews> _entityViewsToAdd; - readonly DoubleBufferedEntityViews> _metaEntityViewsToAdd; - readonly DoubleBufferedEntityViews>> _groupedEntityViewsToAdd; - readonly EntitySubmissionScheduler _scheduler; - } } \ No newline at end of file diff --git a/Svelto.ECS/EntityDescriptor.cs b/Svelto.ECS/EntityDescriptor.cs index 1c71dce..9958c7e 100644 --- a/Svelto.ECS/EntityDescriptor.cs +++ b/Svelto.ECS/EntityDescriptor.cs @@ -1,7 +1,6 @@ using System; using DBC; using Svelto.DataStructures; -using Svelto.ECS.Internal; namespace Svelto.ECS { @@ -17,16 +16,12 @@ namespace Svelto.ECS this.entityViewsToBuild = entityViewsToBuild; } - public IEntityViewBuilder[] entityViewsToBuild { get; private set; } - } - - public interface IEntityDescriptorInfo - { + public IEntityViewBuilder[] entityViewsToBuild { get; } } public static class EntityDescriptorTemplate where TType : IEntityDescriptor, new() { - public static readonly IEntityDescriptorInfo Default = new EntityDescriptorInfo(new TType()); + public static readonly EntityDescriptorInfo Default = new EntityDescriptorInfo(new TType()); } public class DynamicEntityDescriptorInfo : EntityDescriptorInfo where TType : IEntityDescriptor, new() @@ -47,23 +42,19 @@ namespace Svelto.ECS name = descriptor.ToString(); } } -} -namespace Svelto.ECS.Internal -{ - public class EntityDescriptorInfo : IEntityDescriptorInfo + public class EntityDescriptorInfo { internal IEntityViewBuilder[] entityViewsToBuild; - internal string name; + internal string name; internal EntityDescriptorInfo(IEntityDescriptor descriptor) { - name = descriptor.ToString(); + name = descriptor.ToString(); entityViewsToBuild = descriptor.entityViewsToBuild; } protected EntityDescriptorInfo() - { - } + { } } -} \ No newline at end of file +} diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs index 5ce8640..4c2bb9a 100644 --- a/Svelto.ECS/EntityFactory.cs +++ b/Svelto.ECS/EntityFactory.cs @@ -10,64 +10,32 @@ namespace Svelto.ECS.Internal { internal static void BuildGroupedEntityViews(int entityID, int groupID, Dictionary> groupEntityViewsByType, - Dictionary entityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors) + EntityDescriptorInfo entityViewsToBuildDescriptor, + object[] implementors) { - var entityViewsToBuildDescriptor = - eentityViewsToBuildDescriptor as EntityDescriptorInfo; - Dictionary groupedEntityViewsTyped; + Dictionary group; - if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false) + if (groupEntityViewsByType.TryGetValue(groupID, out group) == false) { - groupedEntityViewsTyped = new Dictionary(); - groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped); + group = new Dictionary(); + groupEntityViewsByType.Add(groupID, group); } - InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors); + InternalBuildEntityViews(entityID, group, entityViewsToBuildDescriptor, implementors); - var removeEntityView = EntityView.BuildEntityView(entityID); + EntityInfoView removeEntityView = + (EntityInfoView) BuildEntityView + (entityID, group, EntityViewBuilder.ENTITY_VIEW_TYPE, new EntityViewBuilder()); removeEntityView.groupID = groupID; - removeEntityView.isInAGroup = true; removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; - - AddEntityInfoView(entityViewsByType, removeEntityView); - } - - internal static void BuildEntityViews(int entityID, - Dictionary entityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors) - { - var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; - - InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors); - - var removeEntityView = EntityView.BuildEntityView(entityID); - removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; - - AddEntityInfoView(entityViewsByType, removeEntityView); } - static void AddEntityInfoView(Dictionary entityViewsByType, - EntityInfoView removeEntityView) + static void InternalBuildEntityViews(int entityID, + Dictionary entityViewsByType, + EntityDescriptorInfo entityViewsToBuildDescriptor, + object[] implementors) { - ITypeSafeList list; - - if (entityViewsByType.TryGetValue(typeof(EntityInfoView), out list) == false) - list = entityViewsByType[typeof(EntityInfoView)] = - new TypeSafeFasterListForECSForClasses(); - - (list as TypeSafeFasterListForECSForClasses).Add(removeEntityView); - } - - static void InternalBuildEntityViews(int entityID, - Dictionary entityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors) - { - var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild; var count = entityViewsToBuild.Length; @@ -185,9 +153,9 @@ namespace Svelto.ECS.Internal #if DEBUG && !PROFILER if (component.numberOfImplementations > 1) Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat( - "Component Type: ", fieldType.Name, - " implementor: ", - component.implementorType.ToString()) + + "Component Type: ", fieldType.Name, + " implementor: ", + component.implementorType.ToString()) + " - EntityView: " + entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); #endif @@ -214,7 +182,7 @@ namespace Svelto.ECS.Internal } #endif static readonly Dictionary _cachedTypes = new Dictionary(); - + const string DUPLICATE_IMPLEMENTOR_ERROR = "Svelto.ECS the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. "; diff --git a/Svelto.ECS/EntityInfoImplementor.cs b/Svelto.ECS/EntityInfoImplementor.cs deleted file mode 100644 index 81d09c1..0000000 --- a/Svelto.ECS/EntityInfoImplementor.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Svelto.ECS.Internal -{ - class EntityInfoView : EntityView - { - internal IEntityViewBuilder[] entityViews; - internal int groupID; - internal bool isInAGroup; - } -} \ No newline at end of file diff --git a/Svelto.ECS/EntityInfoView.cs b/Svelto.ECS/EntityInfoView.cs new file mode 100644 index 0000000..618518b --- /dev/null +++ b/Svelto.ECS/EntityInfoView.cs @@ -0,0 +1,8 @@ +namespace Svelto.ECS +{ + public class EntityInfoView : EntityView + { + internal IEntityViewBuilder[] entityViews; + public int groupID; + } +} \ No newline at end of file diff --git a/Svelto.ECS/EntityViewBuilder.cs b/Svelto.ECS/EntityViewBuilder.cs index 2320602..3c81486 100644 --- a/Svelto.ECS/EntityViewBuilder.cs +++ b/Svelto.ECS/EntityViewBuilder.cs @@ -13,7 +13,7 @@ namespace Svelto.ECS bool mustBeFilled { get; } } - public class EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() + public struct EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() { public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) { @@ -34,14 +34,14 @@ namespace Svelto.ECS if (list == null) list = new TypeSafeFasterListForECSForClasses(size); else - list.ReserveCapacity(size); + list.AddCapacity(size); return list; } public Type GetEntityViewType() { - return _entityViewType; + return ENTITY_VIEW_TYPE; } public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) @@ -57,10 +57,10 @@ namespace Svelto.ECS get { return true; } } - readonly Type _entityViewType = typeof(EntityViewType); + internal static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); } - public class EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct + public struct EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct { public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) { @@ -82,14 +82,14 @@ namespace Svelto.ECS if (list == null) list = new TypeSafeFasterListForECSForStructs(size); else - list.ReserveCapacity(size); + list.AddCapacity(size); return list; } public Type GetEntityViewType() { - return _entityViewType; + return ENTITY_VIEW_TYPE; } public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) @@ -105,6 +105,6 @@ namespace Svelto.ECS get { return false; } } - readonly Type _entityViewType = typeof(EntityViewType); + internal static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); } } \ No newline at end of file diff --git a/Svelto.ECS/EntityViewsDB.cs b/Svelto.ECS/EntityViewsDB.cs index d3dbc1a..e47bba5 100644 --- a/Svelto.ECS/EntityViewsDB.cs +++ b/Svelto.ECS/EntityViewsDB.cs @@ -7,17 +7,11 @@ namespace Svelto.ECS.Internal class EntityViewsDB : IEntityViewsDB { internal EntityViewsDB( Dictionary entityViewsDB, - Dictionary metaEntityViewsDB, - Dictionary entityViewsDBdic, - Dictionary metaEntityViewsDBdic, + Dictionary> entityViewsDBdic, Dictionary> groupEntityViewsDB) { _entityViewsDB = entityViewsDB; - _metaEntityViewsDB = metaEntityViewsDB; - - _entityViewsDBdic = entityViewsDBdic; - _metaEntityViewsDBdic = metaEntityViewsDBdic; - + _groupedEntityViewsDBDic = entityViewsDBdic; _groupEntityViewsDB = groupEntityViewsDB; } @@ -77,60 +71,28 @@ namespace Svelto.ECS.Internal return FasterList.NoVirt.ToArrayFast((FasterList)entitiesInGroupPerType[type], out count); } - public ReadOnlyDictionary QueryIndexableEntityViews() where T:EntityView - { - var type = typeof(T); - - ITypeSafeDictionary entityViews; - - if (_entityViewsDBdic.TryGetValue(type, out entityViews) == false) - return TypeSafeDictionary.Default; - - return new ReadOnlyDictionary(entityViews as Dictionary); - } - - public ReadOnlyDictionary QueryIndexableMetaEntityViews() where T:EntityView - { - var type = typeof(T); - - ITypeSafeDictionary entityViews; - - if (_metaEntityViewsDBdic.TryGetValue(type, out entityViews) == false) - return TypeSafeDictionary.Default; - - return new ReadOnlyDictionary(entityViews as Dictionary); - } - public T QueryEntityView(int entityID) where T:EntityView { - return QueryEntityView(entityID, _entityViewsDBdic); + return QueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity); } public bool TryQueryEntityView(int entityID, out T entityView) where T:EntityView { - return TryQueryEntityView(entityID, _entityViewsDBdic, out entityView); + return TryQueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity, out entityView); } - - public T QueryMetaEntityView(int metaEntityID) where T:EntityView + + public T QueryEntityViewInGroup(int entityID, int groupID) where T:EntityView { - return QueryEntityView(metaEntityID, _metaEntityViewsDBdic); - } + T entityView; + + TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); - public bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T:EntityView - { - return TryQueryEntityView(metaEntityID, _metaEntityViewsDBdic, out entityView); + return entityView; } - public FasterReadOnlyList QueryMetaEntityViews() where T:EntityView + public bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T:EntityView { - var type = typeof(T); - - ITypeSafeList entityViews; - - if (_metaEntityViewsDB.TryGetValue(type, out entityViews) == false) - return RetrieveEmptyEntityViewList(); - - return new FasterReadOnlyList((FasterList)entityViews); + return TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); } static FasterReadOnlyList RetrieveEmptyEntityViewList() @@ -143,7 +105,7 @@ namespace Svelto.ECS.Internal return FasterList.DefaultList.ToArrayFast(); } - static bool TryQueryEntityView(int ID, Dictionary entityDic, out T entityView) where T : EntityView + static bool TryQueryEntityView(int ID, int groupID, Dictionary> entityDic, out T entityView) where T : EntityView { var type = typeof(T); @@ -152,7 +114,11 @@ namespace Svelto.ECS.Internal ITypeSafeDictionary entityViews; TypeSafeDictionary casted; - entityDic.TryGetValue(type, out entityViews); + Dictionary @group; + if (entityDic.TryGetValue(groupID, out group) == false) + throw new Exception("Group not found"); + + group.TryGetValue(type, out entityViews); casted = entityViews as TypeSafeDictionary; if (casted != null && @@ -163,34 +129,14 @@ namespace Svelto.ECS.Internal return true; } - entityView = default(T); + entityView = null; return false; } - static T QueryEntityView(int ID, Dictionary entityDic) where T : EntityView - { - var type = typeof(T); + readonly Dictionary> _groupEntityViewsDB; + readonly Dictionary> _groupedEntityViewsDBDic; - T internalEntityView; ITypeSafeDictionary entityViews; - TypeSafeDictionary casted; - - entityDic.TryGetValue(type, out entityViews); - casted = entityViews as TypeSafeDictionary; - - if (casted != null && - casted.TryGetValue(ID, out internalEntityView)) - return (T)internalEntityView; - - throw new Exception("EntityView Not Found"); - } - - readonly Dictionary _entityViewsDB; - readonly Dictionary _metaEntityViewsDB; - - readonly Dictionary _entityViewsDBdic; - readonly Dictionary _metaEntityViewsDBdic; - - readonly Dictionary> _groupEntityViewsDB; + readonly Dictionary _entityViewsDB; } } diff --git a/Svelto.ECS/ExclusiveGroups.cs b/Svelto.ECS/ExclusiveGroups.cs new file mode 100644 index 0000000..e2a21f4 --- /dev/null +++ b/Svelto.ECS/ExclusiveGroups.cs @@ -0,0 +1,7 @@ +namespace Svelto.ECS.Internal +{ + static class ExclusiveGroups + { + internal const int StandardEntity = unchecked((int) 0xFFFFFFFF); + } +} \ No newline at end of file diff --git a/Svelto.ECS/IEnginesInterfaces.cs b/Svelto.ECS/IEnginesInterfaces.cs deleted file mode 100644 index 4d5c34e..0000000 --- a/Svelto.ECS/IEnginesInterfaces.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace Svelto.ECS -{ - public interface IEntityFactory - { - void PreallocateEntitySlots(int size) where T : IEntityDescriptor, new(); - - void BuildEntity(int entityID, object[] implementors) where T:IEntityDescriptor, new(); - void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptorInfo, object[] implementors); - - void BuildMetaEntity(int metaEntityID, object[] implementors) where T:IEntityDescriptor, new(); - - void BuildEntityInGroup(int entityID, int groupID, object[] implementors) where T:IEntityDescriptor, new(); - void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, object[] implementors); - } - - public interface IEntityFunctions - { - void RemoveEntity(int entityID); - - void RemoveMetaEntity(int metaEntityID); - - void RemoveGroupAndEntities(int groupID); - - void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID); - } -} diff --git a/Svelto.ECS/IEntityDescriptorHolder.cs b/Svelto.ECS/IEntityDescriptorHolder.cs index 1971d25..e16ca4e 100644 --- a/Svelto.ECS/IEntityDescriptorHolder.cs +++ b/Svelto.ECS/IEntityDescriptorHolder.cs @@ -2,6 +2,6 @@ namespace Svelto.ECS { public interface IEntityDescriptorHolder { - IEntityDescriptorInfo RetrieveDescriptor(); + EntityDescriptorInfo RetrieveDescriptor(); } } \ No newline at end of file diff --git a/Svelto.ECS/IEntityFactory.cs b/Svelto.ECS/IEntityFactory.cs new file mode 100644 index 0000000..ebd04a2 --- /dev/null +++ b/Svelto.ECS/IEntityFactory.cs @@ -0,0 +1,55 @@ +namespace Svelto.ECS +{ + /// + /// Entities are always built in group. Where the group is not specificed, a special standard group is used + /// ID can be reused within groups + /// an EnginesRoot reference cannot be held by anything else than the Composition Root + /// where it has been created. IEntityFactory and IEntityFunctions allow a weakreference + /// of the EnginesRoot to be passed around. + /// + public interface IEntityFactory + { + + /// + ///where performance is critical, you may wish to pre allocate the space needed + ///to store the entities + /// + /// + /// + void PreallocateEntitySpace(int size) where T : IEntityDescriptor, new(); + void PreallocateEntitySpaceInGroup(int groupID, int size) where T : IEntityDescriptor, new(); + + /// + /// Using this function is like building a normal entity, but the entityViews + /// are grouped by groupID to be more efficently processed inside engines and + /// improve cache locality. Either class entityViews and struct entityViews can be + /// grouped. + /// + /// + /// + /// + /// + void BuildEntityInGroup(int entityID, int groupID, object[] implementors) where T:IEntityDescriptor, new(); + void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors); + + /// + /// The EntityDescriptor doesn't need to be ever instantiated. It just describes the Entity + /// itself in terms of EntityViews to build. The Implementors are passed to fill the + /// references of the EntityViews components. Please read the articles on my blog + /// to understand better the terminologies + /// + /// + /// + /// + void BuildEntity(int entityID, object[] implementors) where T:IEntityDescriptor, new(); + + /// + /// When the type of the entity is not known (this is a special case!) an EntityDescriptorInfo + /// can be built in place of the generic parameter T. + /// + /// + /// + /// + void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptorInfo, object[] implementors); + } +} diff --git a/Svelto.ECS/IEntityFunctions.cs b/Svelto.ECS/IEntityFunctions.cs new file mode 100644 index 0000000..01ce4ee --- /dev/null +++ b/Svelto.ECS/IEntityFunctions.cs @@ -0,0 +1,16 @@ +namespace Svelto.ECS +{ + public interface IEntityFunctions + { + //being entity ID globally not unique, the group must be specified when + //an entity is removed. Not specificing the group will attempt to remove + //the entity from the special standard group. + void RemoveEntity(int entityID); + void RemoveEntity(int entityID, int groupID); + + void RemoveGroupAndEntities(int groupID); + + void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID); + void SwapEntityGroup(int entityID, int toGroupID); + } +} \ No newline at end of file diff --git a/Svelto.ECS/IEntityViewsDB.cs b/Svelto.ECS/IEntityViewsDB.cs index 581b698..dadb870 100644 --- a/Svelto.ECS/IEntityViewsDB.cs +++ b/Svelto.ECS/IEntityViewsDB.cs @@ -5,19 +5,15 @@ namespace Svelto.ECS public interface IEntityViewsDB { FasterReadOnlyList QueryEntityViews() where T : EntityView; - FasterReadOnlyList QueryMetaEntityViews() where T : EntityView; FasterReadOnlyList QueryGroupedEntityViews(int group) where T : EntityView; T[] QueryEntityViewsAsArray(out int count) where T : IEntityView; T[] QueryGroupedEntityViewsAsArray(int group, out int count) where T : IEntityView; - ReadOnlyDictionary QueryIndexableEntityViews() where T : EntityView; - ReadOnlyDictionary QueryIndexableMetaEntityViews() where T : EntityView; - bool TryQueryEntityView(int ID, out T entityView) where T : EntityView; T QueryEntityView(int ID) where T : EntityView; - - bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T : EntityView; - T QueryMetaEntityView(int metaEntityID) where T : EntityView; + + bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T : EntityView; + T QueryEntityViewInGroup(int entityID, int groupID) where T : EntityView; } } \ No newline at end of file From 36cae3be95fc01450799fad9938d6c7d448aa6a7 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Fri, 30 Mar 2018 23:29:48 +0100 Subject: [PATCH 2/6] refactoring complete (minus some improvements) - introduced the concept of global ID, as a combination of groupID and entityID - only 256 groups and 2^24 entities can be created - all the entities are now built always in group, when the group is not specified, the "standard" groups is used - the groupID can be retrieved from the EGID - --- EnginesRoot.GenericEntityFunctions.cs | 5 + .../DataStructures/TypeSafeDictionary.cs | 65 +++++- .../TypeSafeDictionaryException.cs | 2 +- .../TypeSafeFasterListForECS.cs | 62 ++++-- .../TypeSafeFasterListForECSException.cs | 10 + Svelto.ECS/EGID.cs | 38 ++++ Svelto.ECS/EnginesRootEngines.cs | 6 +- Svelto.ECS/EnginesRootEntities.cs | 190 ++++++++++-------- Svelto.ECS/EnginesRootSubmission.cs | 19 +- Svelto.ECS/EntityFactory.cs | 50 +++-- Svelto.ECS/EntityInfoView.cs | 5 +- Svelto.ECS/EntityView.cs | 12 +- Svelto.ECS/EntityViewBuilder.cs | 20 +- Svelto.ECS/EntityViewsDB.cs | 85 +++++--- Svelto.ECS/ExclusiveGroups.cs | 2 +- Svelto.ECS/IEntityFactory.cs | 2 +- Svelto.ECS/IEntityFunctions.cs | 1 + Svelto.ECS/IEntityViewsDB.cs | 4 +- 18 files changed, 374 insertions(+), 204 deletions(-) create mode 100644 Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs create mode 100644 Svelto.ECS/EGID.cs diff --git a/EnginesRoot.GenericEntityFunctions.cs b/EnginesRoot.GenericEntityFunctions.cs index de14160..1d3b1cf 100644 --- a/EnginesRoot.GenericEntityFunctions.cs +++ b/EnginesRoot.GenericEntityFunctions.cs @@ -27,6 +27,11 @@ namespace Svelto.ECS _weakReference.Target.RemoveEntity(entityID, groupID); } + public void RemoveEntity(EGID entityEGID) + { + _weakReference.Target.RemoveEntity(entityEGID); + } + public void RemoveGroupAndEntities(int groupID) { _weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID); diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs index d1e7dcc..164017e 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs @@ -14,11 +14,12 @@ namespace Svelto.ECS.Internal public interface ITypeSafeDictionary { void FillWithIndexedEntityViews(ITypeSafeList entityViews); - bool Remove(int entityId); - IEntityView GetIndexedEntityView(int entityID); + bool Remove(EGID entityId); + IEntityView GetIndexedEntityView(EGID entityID); + bool isQueryiableEntityView { get; } } - class TypeSafeDictionary : Dictionary, ITypeSafeDictionary where TValue : IEntityView + class TypeSafeDictionaryForClass : Dictionary, ITypeSafeDictionary where TValue : EntityView { internal static readonly ReadOnlyDictionary Default = new ReadOnlyDictionary(new Dictionary()); @@ -34,7 +35,7 @@ namespace Svelto.ECS.Internal { var entityView = buffer[i]; - Add(entityView.ID, entityView); + Add(entityView._ID.GID, entityView); } } catch (Exception e) @@ -43,16 +44,64 @@ namespace Svelto.ECS.Internal } } - public new bool Remove(int entityId) + public bool Remove(EGID entityId) { - base.Remove(entityId); + base.Remove(entityId.GID); return Count > 0; } - public IEntityView GetIndexedEntityView(int entityID) + public IEntityView GetIndexedEntityView(EGID entityID) { - return this[entityID]; + return this[entityID.GID]; + } + + public bool isQueryiableEntityView + { + get { return true; } + } + } + + class TypeSafeDictionaryForStruct : Dictionary, ITypeSafeDictionary where TValue : struct, IEntityStruct + { + internal static readonly ReadOnlyDictionary Default = + new ReadOnlyDictionary(new Dictionary()); + + public void FillWithIndexedEntityViews(ITypeSafeList entityViews) + { + int count; + var buffer = FasterList.NoVirt.ToArrayFast((FasterList) entityViews, out count); + + try + { + for (var i = 0; i < count; i++) + { + var entityView = buffer[i]; + + Add(entityView.ID.GID, entityView); + } + } + catch (Exception e) + { + throw new TypeSafeDictionaryException(e); + } + } + + public bool Remove(EGID entityId) + { + base.Remove(entityId.GID); + + return Count > 0; + } + + public IEntityView GetIndexedEntityView(EGID entityID) + { + return this[entityID.GID]; + } + + public bool isQueryiableEntityView + { + get { return false; } } } } \ No newline at end of file diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs index 4f2a321..5504e00 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs @@ -4,7 +4,7 @@ namespace Svelto.ECS { public class TypeSafeDictionaryException : Exception { - public TypeSafeDictionaryException(Exception exception) : base(exception.Message, exception) + public TypeSafeDictionaryException(Exception exception) : base("trying to add an EntityView with the same ID more than once", exception) { } } diff --git a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs index e6603c4..929b567 100644 --- a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs +++ b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs @@ -12,7 +12,7 @@ namespace Svelto.ECS.Internal void AddRange(ITypeSafeList entityViewListValue); ITypeSafeList Create(); - bool MappedRemove(int entityID); + bool MappedRemove(EGID entityID); ITypeSafeDictionary CreateIndexedDictionary(); IEntityView[] ToArrayFast(out int count); void AddCapacity(int capacity); @@ -32,17 +32,26 @@ namespace Svelto.ECS.Internal _mappedIndices = new Dictionary(); } - public bool MappedRemove(int entityID) + public bool MappedRemove(EGID entityID) { - var index = _mappedIndices[entityID]; + var index = _mappedIndices[entityID.GID]; - Check.Assert(entityID == this[index].ID, + Check.Assert(entityID.GID == this[index].ID.GID, "Something went wrong with the Svelto.ECS code, please contact the author"); - _mappedIndices.Remove(entityID); + _mappedIndices.Remove(entityID.GID); if (UnorderedRemoveAt(index)) - _mappedIndices[this[index].ID] = index; + { + try + { + _mappedIndices.Add(this[index].ID.GID, index); + } + catch (Exception e) + { + throw new TypeSafeFasterListForECSException(e); + } + } return Count > 0; } @@ -53,8 +62,18 @@ namespace Svelto.ECS.Internal base.AddRange(entityViewListValue as FasterList); + for (var i = index; i < Count; ++i) - _mappedIndices[this[i].ID] = i; + { + try + { + _mappedIndices.Add(this[i].ID.GID, i); + } + catch (Exception e) + { + throw new TypeSafeFasterListForECSException(e); + } + } } public new void Add(T entityView) @@ -63,7 +82,14 @@ namespace Svelto.ECS.Internal base.Add(entityView); - _mappedIndices[entityView.ID] = index; + try + { + _mappedIndices.Add(entityView.ID.GID, index); + } + catch (Exception e) + { + throw new TypeSafeFasterListForECSException(e); + } } public void AddCapacity(int capacity) @@ -72,9 +98,9 @@ namespace Svelto.ECS.Internal Resize(Count + capacity); } - public int GetIndexFromID(int entityID) + public int GetIndexFromID(EGID entityID) { - return _mappedIndices[entityID]; + return _mappedIndices[entityID.GID]; } } @@ -82,12 +108,10 @@ namespace Svelto.ECS.Internal where T : struct, IEntityStruct { public TypeSafeFasterListForECSForStructs(int size) : base(size) - { - } + {} public TypeSafeFasterListForECSForStructs() - { - } + {} public ITypeSafeList Create() { @@ -101,7 +125,7 @@ namespace Svelto.ECS.Internal public ITypeSafeDictionary CreateIndexedDictionary() { - throw new Exception("Not Allowed"); + return new TypeSafeDictionaryForStruct(); } public IEntityView[] ToArrayFast(out int count) @@ -118,12 +142,10 @@ namespace Svelto.ECS.Internal class TypeSafeFasterListForECSForClasses : TypeSafeFasterListForECS, ITypeSafeList where T : EntityView, new() { public TypeSafeFasterListForECSForClasses(int size) : base(size) - { - } + {} public TypeSafeFasterListForECSForClasses() - { - } + {} public ITypeSafeList Create() { @@ -137,7 +159,7 @@ namespace Svelto.ECS.Internal public ITypeSafeDictionary CreateIndexedDictionary() { - return new TypeSafeDictionary(); + return new TypeSafeDictionaryForClass(); } public IEntityView[] ToArrayFast(out int count) diff --git a/Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs b/Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs new file mode 100644 index 0000000..038eaa2 --- /dev/null +++ b/Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Svelto.ECS +{ + public class TypeSafeFasterListForECSException : Exception + { + public TypeSafeFasterListForECSException(Exception exception):base("Trying to add an Entity View with the same ID more than once", exception) + {} + } +} \ No newline at end of file diff --git a/Svelto.ECS/EGID.cs b/Svelto.ECS/EGID.cs new file mode 100644 index 0000000..e17367a --- /dev/null +++ b/Svelto.ECS/EGID.cs @@ -0,0 +1,38 @@ +using DBC; + +namespace Svelto.ECS +{ + public struct EGID + { + int _GID; + + public int GID + { + get { return _GID; } + } + + public int ID + { + get { return _GID & 0xFFFFFF; } + } + + public int group + { + get { return (int) ((_GID & 0xFF000000) >> 24); } + } + + public EGID(int entityID, int groupID) : this() + { + _GID = MAKE_GLOBAL_ID(entityID, groupID); + } + + int MAKE_GLOBAL_ID(int entityId, int groupId) + { +#if DEBUG && !PROFILER + Check.Require(entityId <= 0xFFFFFF); + Check.Require(groupId <= 0xFF); +#endif + return entityId | groupId << 24; + } + } +} \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootEngines.cs b/Svelto.ECS/EnginesRootEngines.cs index a7782b1..d16b3ac 100644 --- a/Svelto.ECS/EnginesRootEngines.cs +++ b/Svelto.ECS/EnginesRootEngines.cs @@ -37,13 +37,13 @@ namespace Svelto.ECS _entityViewEngines = new Dictionary>(); _otherEngines = new FasterList(); - _entityViewsDB = new Dictionary(); + _globalEntityViewsDB = new Dictionary(); _groupEntityViewsDB = new Dictionary>(); - _groupedEntityViewsDBDic = new Dictionary>(); + _globalEntityViewsDBDic = new Dictionary(); _groupedEntityViewsToAdd = new DoubleBufferedEntityViews>>(); - _DB = new EntityViewsDB(_entityViewsDB, _groupedEntityViewsDBDic, _groupEntityViewsDB); + _DB = new EntityViewsDB(_globalEntityViewsDB, _globalEntityViewsDBDic, _groupEntityViewsDB); _scheduler = entityViewScheduler; _scheduler.Schedule(new WeakAction(SubmitEntityViews)); diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index 77fbbfa..0703fa3 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -14,7 +14,7 @@ namespace Svelto.ECS { public void Dispose() { - foreach (var entity in _entityViewsDB) + foreach (var entity in _globalEntityViewsDB) if (entity.Value.isQueryiableEntityView) foreach (var entityView in entity.Value) RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key); @@ -64,7 +64,7 @@ namespace Svelto.ECS implementors); } - void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, + void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null) { EntityFactory.BuildGroupedEntityViews(entityID, groupID, @@ -74,9 +74,15 @@ namespace Svelto.ECS ///-------------------------------------------- + /// + /// This function is experimental and untested. I never used it in production + /// it may not be necessary. + /// TODO: understand if this method is useful in a performance critical + /// scenario + /// void Preallocate(int groupID, int size) where T : IEntityDescriptor, new() { - var entityViewsToBuild = ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild; + var entityViewsToBuild = EntityDescriptorTemplate.Default.entityViewsToBuild; var count = entityViewsToBuild.Length; for (var index = 0; index < count; index++) @@ -86,8 +92,8 @@ namespace Svelto.ECS //reserve space for the global pool ITypeSafeList dbList; - if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false) - _entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); + if (_globalEntityViewsDB.TryGetValue(entityViewType, out dbList) == false) + _globalEntityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size); else dbList.AddCapacity(size); @@ -111,18 +117,44 @@ namespace Svelto.ECS dbList.AddCapacity(size); } } - - void RemoveEntity(ref EntityInfoView entityInfoView) + + ///-------------------------------------------- + /// + void RemoveEntity(int entityID, int groupID) { - InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, - entityInfoView.groupID); + RemoveEntity(new EGID(entityID, groupID)); } - void RemoveEntity(int entityID, int groupID) + void RemoveEntity(EGID entityGID) { - var entityInfoView = _DB.QueryEntityViewInGroup(entityID, groupID); + _DB.TryQueryEntityView(entityGID, out var entityInfoView); + + var entityViewBuilders = entityInfoView.entityViews; + EGID id = entityInfoView._ID; + + var entityViewBuildersCount = entityViewBuilders.Length; + var group = _groupEntityViewsDB[id.group]; + + //for each entity view generated by the entity descriptor + for (var i = 0; i < entityViewBuildersCount; i++) + { + var entityViewType = entityViewBuilders[i].GetEntityViewType(); + + InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, id); + + RemoveEntityViewFromDB(@group, entityViewType, id); + RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, id); + } - RemoveEntity(ref entityInfoView); + InternalRemoveEntityViewFromDBDicAndEngines(_entityInfoViewType, id); + } + + static void RemoveEntityViewFromDB(Dictionary @group, Type entityViewType, EGID id) + { + //remove it from entity views group DB + var typeSafeList = @group[entityViewType]; + if (typeSafeList.MappedRemove(id) == false) //clean up + @group.Remove(entityViewType); } void RemoveGroupAndEntitiesFromDB(int groupID) @@ -138,40 +170,70 @@ namespace Svelto.ECS { var entityID = entities[i].ID; - InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID); + RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityID); + + InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID); } } _groupEntityViewsDB.Remove(groupID); } - void InternalRemoveEntityViewFromDBAndEngines(Type entityViewType, - int entityID, - int groupID) + void InternalRemoveEntityViewFromDBDicAndEngines(Type entityViewType, EGID id) { - var entityViews = _entityViewsDB[entityViewType]; - if (entityViews.MappedRemove(entityID) == false) - _entityViewsDB.Remove(entityViewType); - - if (entityViews.isQueryiableEntityView) + var typeSafeDictionary = _globalEntityViewsDBDic[entityViewType]; + if (typeSafeDictionary.isQueryiableEntityView) { - var typeSafeDictionary = _groupedEntityViewsDBDic[groupID][entityViewType]; - var entityView = typeSafeDictionary.GetIndexedEntityView(entityID); - - if (typeSafeDictionary.Remove(entityID) == false) - _groupedEntityViewsDBDic[groupID].Remove(entityViewType); + var entityView = typeSafeDictionary.GetIndexedEntityView(id); + //the reason why this for exists is because in the past hierarchical entity views + //where supported :( + //Only EntityView can be removed from engines (won't work for IEntityStruct or IEntityView) for (var current = entityViewType; current != _entityViewType; current = current.BaseType) + { +#if DEBUG && !PROFILER + if (current != entityViewType) + Utility.Console.LogWarning("Hierarchical Entity Views are design mistakes, ECS is not OOD!!"); +#endif + RemoveEntityViewFromEngines(_entityViewEngines, entityView, current); + } } + typeSafeDictionary.Remove(id); } + + static void RemoveEntityViewFromEngines(Dictionary> entityViewEngines, + IEntityView entityView, + Type entityViewType) + { + FasterList enginesForEntityView; + + if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView)) + { + int count; + var fastList = FasterList.NoVirt.ToArrayFast(enginesForEntityView, out count); + + for (var j = 0; j < count; j++) + { +#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR + EngineProfiler.MonitorRemoveDuration(fastList[j], entityView); +#else + fastList[j].Remove(entityView); +#endif + } + } + } + + ///-------------------------------------------- void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) { Check.Require(fromGroupID != toGroupID, "can't move an entity to the same group where it already belongs to"); - var entityViewBuilders = _DB.QueryEntityView(entityID).entityViews; + _DB.TryQueryEntityViewInGroup(fromGroupID, entityID, out EntityInfoView entityInfoView); + + var entityViewBuilders = entityInfoView.entityViews; var entityViewBuildersCount = entityViewBuilders.Length; var groupedEntities = _groupEntityViewsDB[fromGroupID]; @@ -195,78 +257,28 @@ namespace Svelto.ECS if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false) groupedEntityViewsTyped[entityViewType] = toSafeList = fromSafeList.Create(); - entityViewBuilder.MoveEntityView(entityID, fromSafeList, toSafeList); - - fromSafeList.MappedRemove(entityID); + entityViewBuilder.MoveEntityView(entityInfoView._ID, fromSafeList, toSafeList); + fromSafeList.MappedRemove(entityInfoView._ID); + entityInfoView._ID = new EGID(entityID, toGroupID); } - - var entityInfoView = _DB.QueryEntityView(entityID); - entityInfoView.groupID = toGroupID; - } - - void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders, - int entityID, int groupID) - { - InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID); - - var entityViewBuildersCount = entityViewBuilders.Length; - - for (var i = 0; i < entityViewBuildersCount; i++) - { - var entityViewType = entityViewBuilders[i].GetEntityViewType(); - - InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID); - } - - InternalRemoveEntityViewFromDBAndEngines(typeof(EntityInfoView), entityID, groupID); } - void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID) - { - var entityViewBuildersCount = entityViewBuilders.Length; - var group = _groupEntityViewsDB[groupID]; - - for (var i = 0; i < entityViewBuildersCount; i++) - { - var entityViewType = entityViewBuilders[i].GetEntityViewType(); - var typeSafeList = group[entityViewType]; - typeSafeList.MappedRemove(entityID); - } - } - - static void RemoveEntityViewFromEngines(Dictionary> entityViewEngines, - IEntityView entityView, - Type entityViewType) - { - FasterList enginesForEntityView; - - if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView)) - { - int count; - var fastList = FasterList.NoVirt.ToArrayFast(enginesForEntityView, out count); - - for (var j = 0; j < count; j++) - { -#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR - EngineProfiler.MonitorRemoveDuration(fastList[j], entityView); -#else - fastList[j].Remove(entityView); -#endif - } - } - } + readonly Type _entityInfoViewType = typeof(EntityInfoView); readonly EntityViewsDB _DB; //grouped set of entity views, this is the standard way to handle entity views readonly Dictionary> _groupEntityViewsDB; - //indexable entity views when the entity ID is known. Usually useful to handle - //event based logic. - readonly Dictionary> _groupedEntityViewsDBDic; - + + //TODO: Use faster dictionary and merge these two? + //Global pool of entity views when engines want to manage entityViews regardless //the group - readonly Dictionary _entityViewsDB; + readonly Dictionary _globalEntityViewsDB; + //indexable entity views when the entity ID is known. Usually useful to handle + //event based logic. + readonly Dictionary _globalEntityViewsDBDic; + } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootSubmission.cs b/Svelto.ECS/EnginesRootSubmission.cs index 009fa10..3934072 100644 --- a/Svelto.ECS/EnginesRootSubmission.cs +++ b/Svelto.ECS/EnginesRootSubmission.cs @@ -39,7 +39,7 @@ namespace Svelto.ECS numberOfReenteringLoops++; } } - + //todo: can I make the entity creation less complicated? void AddEntityViewsToTheDBAndSuitableEngines(Dictionary> groupsToSubmit) { //for each groups there is a dictionary of built lists of EntityView grouped by type @@ -57,18 +57,9 @@ namespace Svelto.ECS //add the entity View in the group AddEntityViewToDB(groupDB, entityViewsPerType); //add the entity view in the gloal pool - AddEntityViewToDB(_entityViewsDB, entityViewsPerType); + AddEntityViewToDB(_globalEntityViewsDB, entityViewsPerType); //and it's not a struct, add in the indexable DB too - if (entityViewsPerType.Value.isQueryiableEntityView) - { - Dictionary groupDic; - - if (_groupedEntityViewsDBDic.TryGetValue(groupID, out groupDic) == false) - groupDic = _groupedEntityViewsDBDic[groupID] = - new Dictionary(); - - AddEntityViewToEntityViewsDictionary(groupDic, entityViewsPerType.Value, entityViewsPerType.Key); - } + AddEntityViewToEntityViewsDictionary(_globalEntityViewsDBDic, entityViewsPerType.Value, entityViewsPerType.Key); } } @@ -87,8 +78,8 @@ namespace Svelto.ECS } } - static void AddEntityViewToDB(Dictionary entityViewsDB, - KeyValuePair entityViewList) + static void AddEntityViewToDB( Dictionary entityViewsDB, + KeyValuePair entityViewList) { ITypeSafeList dbList; diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs index 4c2bb9a..e90d220 100644 --- a/Svelto.ECS/EntityFactory.cs +++ b/Svelto.ECS/EntityFactory.cs @@ -13,25 +13,45 @@ namespace Svelto.ECS.Internal EntityDescriptorInfo entityViewsToBuildDescriptor, object[] implementors) { - Dictionary group; + var @group = FetchGroup(groupID, groupEntityViewsByType); - if (groupEntityViewsByType.TryGetValue(groupID, out group) == false) - { - group = new Dictionary(); - groupEntityViewsByType.Add(groupID, group); - } + BuildEntityViewsAndAddToGroup(new EGID(entityID, groupID), group, entityViewsToBuildDescriptor, implementors); - InternalBuildEntityViews(entityID, group, entityViewsToBuildDescriptor, implementors); + AddEntityInfoView(new EGID(entityID, groupID), entityViewsToBuildDescriptor, @group); + } - EntityInfoView removeEntityView = - (EntityInfoView) BuildEntityView - (entityID, group, EntityViewBuilder.ENTITY_VIEW_TYPE, new EntityViewBuilder()); + static void AddEntityInfoView(EGID entityID, EntityDescriptorInfo entityViewsToBuildDescriptor, + Dictionary @group) + { + //should be a struct? + var removeEntityView = new EntityInfoView(); - removeEntityView.groupID = groupID; + removeEntityView._ID = entityID; removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; + + ITypeSafeList list; + + if (group.TryGetValue(typeof(EntityInfoView), out list) == false) + list = group[typeof(EntityInfoView)] = + new TypeSafeFasterListForECSForClasses(); + + ((TypeSafeFasterListForECSForClasses) list).Add(removeEntityView); } - static void InternalBuildEntityViews(int entityID, + static Dictionary FetchGroup(int groupID, Dictionary> groupEntityViewsByType) + { + Dictionary group; + + if (groupEntityViewsByType.TryGetValue(groupID, out @group) == false) + { + @group = new Dictionary(); + groupEntityViewsByType.Add(groupID, @group); + } + + return @group; + } + + static void BuildEntityViewsAndAddToGroup(EGID entityID, Dictionary entityViewsByType, EntityDescriptorInfo entityViewsToBuildDescriptor, object[] implementors) @@ -54,8 +74,8 @@ namespace Svelto.ECS.Internal } } - static IEntityView BuildEntityView(int entityID, Dictionary entityViewsByType, - Type entityViewType, IEntityViewBuilder entityViewBuilder) + static IEntityView BuildEntityView(EGID entityID, Dictionary entityViewsByType, + Type entityViewType, IEntityViewBuilder entityViewBuilder) { ITypeSafeList entityViewsList; @@ -182,7 +202,7 @@ namespace Svelto.ECS.Internal } #endif static readonly Dictionary _cachedTypes = new Dictionary(); - + const string DUPLICATE_IMPLEMENTOR_ERROR = "Svelto.ECS the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. "; diff --git a/Svelto.ECS/EntityInfoView.cs b/Svelto.ECS/EntityInfoView.cs index 618518b..14490bd 100644 --- a/Svelto.ECS/EntityInfoView.cs +++ b/Svelto.ECS/EntityInfoView.cs @@ -1,8 +1,7 @@ -namespace Svelto.ECS +namespace Svelto.ECS.Internal { - public class EntityInfoView : EntityView + class EntityInfoView : EntityView { internal IEntityViewBuilder[] entityViews; - public int groupID; } } \ No newline at end of file diff --git a/Svelto.ECS/EntityView.cs b/Svelto.ECS/EntityView.cs index b8e56fa..c552263 100644 --- a/Svelto.ECS/EntityView.cs +++ b/Svelto.ECS/EntityView.cs @@ -6,27 +6,29 @@ using Svelto.Utilities; namespace Svelto.ECS { + //todo: can I remove the ID from the struct? + public interface IEntityView { - int ID { get; } + EGID ID { get; } } public interface IEntityStruct:IEntityView { - new int ID { set; } + new EGID ID { get; set; } } public class EntityView : IEntityView { - public int ID { get { return _ID; } } + public EGID ID { get { return _ID; } } internal FasterList>> entityViewBlazingFastReflection; - internal int _ID; + internal EGID _ID; } static class EntityView where T: EntityView, new() { - internal static T BuildEntityView(int ID) + internal static T BuildEntityView(EGID ID) { if (FieldCache.list.Count == 0) { diff --git a/Svelto.ECS/EntityViewBuilder.cs b/Svelto.ECS/EntityViewBuilder.cs index 3c81486..f709038 100644 --- a/Svelto.ECS/EntityViewBuilder.cs +++ b/Svelto.ECS/EntityViewBuilder.cs @@ -5,17 +5,17 @@ namespace Svelto.ECS { public interface IEntityViewBuilder { - void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView); + void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView); ITypeSafeList Preallocate(ref ITypeSafeList list, int size); Type GetEntityViewType(); - void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList); + void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList); bool mustBeFilled { get; } } - public struct EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() + public class EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() { - public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) + public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView) { if (list == null) list = new TypeSafeFasterListForECSForClasses(); @@ -44,7 +44,7 @@ namespace Svelto.ECS return ENTITY_VIEW_TYPE; } - public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) + public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) { var fromCastedList = fromSafeList as TypeSafeFasterListForECSForClasses; var toCastedList = toSafeList as TypeSafeFasterListForECSForClasses; @@ -57,12 +57,12 @@ namespace Svelto.ECS get { return true; } } - internal static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); + public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); } - public struct EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct + public class EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct { - public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView) + public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView) { var structEntityView = default(EntityViewType); structEntityView.ID = entityID; @@ -92,7 +92,7 @@ namespace Svelto.ECS return ENTITY_VIEW_TYPE; } - public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) + public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList) { var fromCastedList = fromSafeList as TypeSafeFasterListForECSForStructs; var toCastedList = toSafeList as TypeSafeFasterListForECSForStructs; @@ -105,6 +105,6 @@ namespace Svelto.ECS get { return false; } } - internal static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); + public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); } } \ No newline at end of file diff --git a/Svelto.ECS/EntityViewsDB.cs b/Svelto.ECS/EntityViewsDB.cs index e47bba5..1de4a3d 100644 --- a/Svelto.ECS/EntityViewsDB.cs +++ b/Svelto.ECS/EntityViewsDB.cs @@ -7,10 +7,10 @@ namespace Svelto.ECS.Internal class EntityViewsDB : IEntityViewsDB { internal EntityViewsDB( Dictionary entityViewsDB, - Dictionary> entityViewsDBdic, + Dictionary entityViewsDBdic, Dictionary> groupEntityViewsDB) { - _entityViewsDB = entityViewsDB; + _globalEntityViewsDB = entityViewsDB; _groupedEntityViewsDBDic = entityViewsDBdic; _groupEntityViewsDB = groupEntityViewsDB; } @@ -21,7 +21,7 @@ namespace Svelto.ECS.Internal ITypeSafeList entityViews; - if (_entityViewsDB.TryGetValue(type, out entityViews) == false) + if (_globalEntityViewsDB.TryGetValue(type, out entityViews) == false) return RetrieveEmptyEntityViewList(); return new FasterReadOnlyList((FasterList)entityViews); @@ -48,7 +48,7 @@ namespace Svelto.ECS.Internal ITypeSafeList entityViews; - if (_entityViewsDB.TryGetValue(type, out entityViews) == false) + if (_globalEntityViewsDB.TryGetValue(type, out entityViews) == false) return RetrieveEmptyEntityViewArray(); return FasterList.NoVirt.ToArrayFast((FasterList)entityViews, out count); @@ -73,56 +73,60 @@ namespace Svelto.ECS.Internal public T QueryEntityView(int entityID) where T:EntityView { - return QueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity); - } + T entityView; - public bool TryQueryEntityView(int entityID, out T entityView) where T:EntityView - { - return TryQueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity, out entityView); + TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView); + + return entityView; } - - public T QueryEntityViewInGroup(int entityID, int groupID) where T:EntityView + + public T QueryEntityView(EGID entityGID) where T : EntityView { T entityView; - - TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); + + TryQueryEntityViewInGroup(entityGID, out entityView); return entityView; } - public bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T:EntityView + public bool TryQueryEntityView(int entityID, out T entityView) where T:EntityView { - return TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); + return TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView); } - static FasterReadOnlyList RetrieveEmptyEntityViewList() + public bool TryQueryEntityView(EGID entityegid, out T entityView) where T : EntityView { - return FasterReadOnlyList.DefaultList; + return TryQueryEntityViewInGroup(entityegid, out entityView); } - static T[] RetrieveEmptyEntityViewArray() + public T QueryEntityViewInGroup(int entityID, int groupID) where T:EntityView { - return FasterList.DefaultList.ToArrayFast(); + T entityView; + + TryQueryEntityViewInGroup(entityID, groupID, out entityView); + + return entityView; } - - static bool TryQueryEntityView(int ID, int groupID, Dictionary> entityDic, out T entityView) where T : EntityView + + public bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T : EntityView + { + return TryQueryEntityViewInGroup(new EGID(entityID, groupID), out entityView); + } + + bool TryQueryEntityViewInGroup(EGID entityGID, out T entityView) where T:EntityView { var type = typeof(T); T internalEntityView; - ITypeSafeDictionary entityViews; - TypeSafeDictionary casted; - - Dictionary @group; - if (entityDic.TryGetValue(groupID, out group) == false) - throw new Exception("Group not found"); + ITypeSafeDictionary entityViews; + TypeSafeDictionaryForClass casted; - group.TryGetValue(type, out entityViews); - casted = entityViews as TypeSafeDictionary; + _groupedEntityViewsDBDic.TryGetValue(type, out entityViews); + casted = entityViews as TypeSafeDictionaryForClass; if (casted != null && - casted.TryGetValue(ID, out internalEntityView)) + casted.TryGetValue(entityGID.GID, out internalEntityView)) { entityView = internalEntityView; @@ -134,9 +138,24 @@ namespace Svelto.ECS.Internal return false; } - readonly Dictionary> _groupEntityViewsDB; - readonly Dictionary> _groupedEntityViewsDBDic; + static FasterReadOnlyList RetrieveEmptyEntityViewList() + { + return FasterReadOnlyList.DefaultList; + } - readonly Dictionary _entityViewsDB; + static T[] RetrieveEmptyEntityViewArray() + { + return FasterList.DefaultList.ToArrayFast(); + } + + + //grouped set of entity views, this is the standard way to handle entity views + readonly Dictionary> _groupEntityViewsDB; + //Global pool of entity views when engines want to manage entityViews regardless + //the group + readonly Dictionary _globalEntityViewsDB; + //indexable entity views when the entity ID is known. Usually useful to handle + //event based logic. + readonly Dictionary _groupedEntityViewsDBDic; } } diff --git a/Svelto.ECS/ExclusiveGroups.cs b/Svelto.ECS/ExclusiveGroups.cs index e2a21f4..5e8eb2f 100644 --- a/Svelto.ECS/ExclusiveGroups.cs +++ b/Svelto.ECS/ExclusiveGroups.cs @@ -2,6 +2,6 @@ { static class ExclusiveGroups { - internal const int StandardEntity = unchecked((int) 0xFFFFFFFF); + internal const int StandardEntity = 0xFF; } } \ No newline at end of file diff --git a/Svelto.ECS/IEntityFactory.cs b/Svelto.ECS/IEntityFactory.cs index ebd04a2..cc63776 100644 --- a/Svelto.ECS/IEntityFactory.cs +++ b/Svelto.ECS/IEntityFactory.cs @@ -41,7 +41,7 @@ namespace Svelto.ECS /// /// /// - void BuildEntity(int entityID, object[] implementors) where T:IEntityDescriptor, new(); + void BuildEntity(int entityID, object[] implementors) where T:IEntityDescriptor, new(); /// /// When the type of the entity is not known (this is a special case!) an EntityDescriptorInfo diff --git a/Svelto.ECS/IEntityFunctions.cs b/Svelto.ECS/IEntityFunctions.cs index 01ce4ee..3cf8408 100644 --- a/Svelto.ECS/IEntityFunctions.cs +++ b/Svelto.ECS/IEntityFunctions.cs @@ -7,6 +7,7 @@ namespace Svelto.ECS //the entity from the special standard group. void RemoveEntity(int entityID); void RemoveEntity(int entityID, int groupID); + void RemoveEntity(EGID entityegid); void RemoveGroupAndEntities(int groupID); diff --git a/Svelto.ECS/IEntityViewsDB.cs b/Svelto.ECS/IEntityViewsDB.cs index dadb870..0779317 100644 --- a/Svelto.ECS/IEntityViewsDB.cs +++ b/Svelto.ECS/IEntityViewsDB.cs @@ -11,8 +11,10 @@ namespace Svelto.ECS T[] QueryGroupedEntityViewsAsArray(int group, out int count) where T : IEntityView; bool TryQueryEntityView(int ID, out T entityView) where T : EntityView; + bool TryQueryEntityView(EGID ID, out T entityView) where T : EntityView; T QueryEntityView(int ID) where T : EntityView; - + T QueryEntityView(EGID entityGID) where T : EntityView; + bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T : EntityView; T QueryEntityViewInGroup(int entityID, int groupID) where T : EntityView; } From e4d3ea9e4b8487c91db98fda03bcc673f0e13e0a Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 31 Mar 2018 00:05:13 +0100 Subject: [PATCH 3/6] fix some errors remove some redundant methods --- .../TypeSafeFasterListForECS.cs | 9 +----- Svelto.ECS/EGID.cs | 11 ++++++++ Svelto.ECS/EnginesRootEntities.cs | 8 ++++-- Svelto.ECS/EntityViewsDB.cs | 28 ------------------- .../Unity/GenericEntityDescriptorHolder.cs | 2 +- Svelto.ECS/IEntityViewsDB.cs | 5 ---- 6 files changed, 19 insertions(+), 44 deletions(-) diff --git a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs index 929b567..4e54840 100644 --- a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs +++ b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs @@ -43,14 +43,7 @@ namespace Svelto.ECS.Internal if (UnorderedRemoveAt(index)) { - try - { - _mappedIndices.Add(this[index].ID.GID, index); - } - catch (Exception e) - { - throw new TypeSafeFasterListForECSException(e); - } + _mappedIndices[this[index].ID.GID] = index; } return Count > 0; diff --git a/Svelto.ECS/EGID.cs b/Svelto.ECS/EGID.cs index e17367a..64facb0 100644 --- a/Svelto.ECS/EGID.cs +++ b/Svelto.ECS/EGID.cs @@ -1,4 +1,5 @@ using DBC; +using Svelto.ECS.Internal; namespace Svelto.ECS { @@ -25,6 +26,11 @@ namespace Svelto.ECS { _GID = MAKE_GLOBAL_ID(entityID, groupID); } + + public EGID(int entityID) : this() + { + _GID = MAKE_GLOBAL_ID(entityID, ExclusiveGroups.StandardEntity); + } int MAKE_GLOBAL_ID(int entityId, int groupId) { @@ -34,5 +40,10 @@ namespace Svelto.ECS #endif return entityId | groupId << 24; } + + public bool IsEqualTo(EGID otherGID) + { + return otherGID._GID == _GID; + } } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index 0703fa3..ecac7b2 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -127,7 +127,9 @@ namespace Svelto.ECS void RemoveEntity(EGID entityGID) { - _DB.TryQueryEntityView(entityGID, out var entityInfoView); + EntityInfoView entityInfoView; + + _DB.TryQueryEntityView(entityGID, out entityInfoView); var entityViewBuilders = entityInfoView.entityViews; EGID id = entityInfoView._ID; @@ -231,7 +233,9 @@ namespace Svelto.ECS Check.Require(fromGroupID != toGroupID, "can't move an entity to the same group where it already belongs to"); - _DB.TryQueryEntityViewInGroup(fromGroupID, entityID, out EntityInfoView entityInfoView); + EntityInfoView entityInfoView; + + _DB.TryQueryEntityView(new EGID(fromGroupID, entityID), out entityInfoView); var entityViewBuilders = entityInfoView.entityViews; var entityViewBuildersCount = entityViewBuilders.Length; diff --git a/Svelto.ECS/EntityViewsDB.cs b/Svelto.ECS/EntityViewsDB.cs index 1de4a3d..0e69652 100644 --- a/Svelto.ECS/EntityViewsDB.cs +++ b/Svelto.ECS/EntityViewsDB.cs @@ -71,15 +71,6 @@ namespace Svelto.ECS.Internal return FasterList.NoVirt.ToArrayFast((FasterList)entitiesInGroupPerType[type], out count); } - public T QueryEntityView(int entityID) where T:EntityView - { - T entityView; - - TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView); - - return entityView; - } - public T QueryEntityView(EGID entityGID) where T : EntityView { T entityView; @@ -89,30 +80,11 @@ namespace Svelto.ECS.Internal return entityView; } - public bool TryQueryEntityView(int entityID, out T entityView) where T:EntityView - { - return TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView); - } - public bool TryQueryEntityView(EGID entityegid, out T entityView) where T : EntityView { return TryQueryEntityViewInGroup(entityegid, out entityView); } - public T QueryEntityViewInGroup(int entityID, int groupID) where T:EntityView - { - T entityView; - - TryQueryEntityViewInGroup(entityID, groupID, out entityView); - - return entityView; - } - - public bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T : EntityView - { - return TryQueryEntityViewInGroup(new EGID(entityID, groupID), out entityView); - } - bool TryQueryEntityViewInGroup(EGID entityGID, out T entityView) where T:EntityView { var type = typeof(T); diff --git a/Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs b/Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs index fb672cb..ebb4fcc 100644 --- a/Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs +++ b/Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs @@ -5,7 +5,7 @@ namespace Svelto.ECS UnityEngine.MonoBehaviour , IEntityDescriptorHolder where T: class, IEntityDescriptor, new() { - public IEntityDescriptorInfo RetrieveDescriptor() + public EntityDescriptorInfo RetrieveDescriptor() { return EntityDescriptorTemplate.Default; } diff --git a/Svelto.ECS/IEntityViewsDB.cs b/Svelto.ECS/IEntityViewsDB.cs index 0779317..239a9e6 100644 --- a/Svelto.ECS/IEntityViewsDB.cs +++ b/Svelto.ECS/IEntityViewsDB.cs @@ -10,12 +10,7 @@ namespace Svelto.ECS T[] QueryEntityViewsAsArray(out int count) where T : IEntityView; T[] QueryGroupedEntityViewsAsArray(int group, out int count) where T : IEntityView; - bool TryQueryEntityView(int ID, out T entityView) where T : EntityView; bool TryQueryEntityView(EGID ID, out T entityView) where T : EntityView; - T QueryEntityView(int ID) where T : EntityView; T QueryEntityView(EGID entityGID) where T : EntityView; - - bool TryQueryEntityViewInGroup(int entityID, int groupID, out T entityView) where T : EntityView; - T QueryEntityViewInGroup(int entityID, int groupID) where T : EntityView; } } \ No newline at end of file From 5179c885f7866fb8bafe05bd134ab2c0d906badc Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 31 Mar 2018 00:58:31 +0100 Subject: [PATCH 4/6] some optimizations --- Svelto.ECS/EnginesRootEngines.cs | 2 ++ Svelto.ECS/EnginesRootEntities.cs | 41 ++++++++++++++----------------- Svelto.ECS/EntityFactory.cs | 24 ++++++------------ Svelto.ECS/EntityInfoView.cs | 7 ------ 4 files changed, 27 insertions(+), 47 deletions(-) delete mode 100644 Svelto.ECS/EntityInfoView.cs diff --git a/Svelto.ECS/EnginesRootEngines.cs b/Svelto.ECS/EnginesRootEngines.cs index d16b3ac..97f7bc7 100644 --- a/Svelto.ECS/EnginesRootEngines.cs +++ b/Svelto.ECS/EnginesRootEngines.cs @@ -41,6 +41,8 @@ namespace Svelto.ECS _groupEntityViewsDB = new Dictionary>(); _globalEntityViewsDBDic = new Dictionary(); + _entityInfos = new Dictionary(); + _groupedEntityViewsToAdd = new DoubleBufferedEntityViews>>(); _DB = new EntityViewsDB(_globalEntityViewsDB, _globalEntityViewsDBDic, _groupEntityViewsDB); diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index ecac7b2..620a29c 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -61,6 +61,7 @@ namespace Svelto.ECS EntityFactory.BuildGroupedEntityViews(entityID, groupID, _groupedEntityViewsToAdd.current, EntityDescriptorTemplate.Default, + _entityInfos, implementors); } @@ -69,7 +70,9 @@ namespace Svelto.ECS { EntityFactory.BuildGroupedEntityViews(entityID, groupID, _groupedEntityViewsToAdd.current, - entityDescriptor, implementors); + entityDescriptor, + _entityInfos, + implementors); } ///-------------------------------------------- @@ -127,28 +130,23 @@ namespace Svelto.ECS void RemoveEntity(EGID entityGID) { - EntityInfoView entityInfoView; - - _DB.TryQueryEntityView(entityGID, out entityInfoView); - - var entityViewBuilders = entityInfoView.entityViews; - EGID id = entityInfoView._ID; + var entityViewBuilders = _entityInfos[entityGID.GID]; var entityViewBuildersCount = entityViewBuilders.Length; - var group = _groupEntityViewsDB[id.group]; + var group = _groupEntityViewsDB[entityGID.group]; //for each entity view generated by the entity descriptor for (var i = 0; i < entityViewBuildersCount; i++) { var entityViewType = entityViewBuilders[i].GetEntityViewType(); - InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, id); + InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityGID); - RemoveEntityViewFromDB(@group, entityViewType, id); - RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, id); + RemoveEntityViewFromDB(@group, entityViewType, entityGID); + RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityGID); } - InternalRemoveEntityViewFromDBDicAndEngines(_entityInfoViewType, id); + _entityInfos.Remove(entityGID.GID); } static void RemoveEntityViewFromDB(Dictionary @group, Type entityViewType, EGID id) @@ -233,11 +231,8 @@ namespace Svelto.ECS Check.Require(fromGroupID != toGroupID, "can't move an entity to the same group where it already belongs to"); - EntityInfoView entityInfoView; - - _DB.TryQueryEntityView(new EGID(fromGroupID, entityID), out entityInfoView); - - var entityViewBuilders = entityInfoView.entityViews; + var entityegid = new EGID(entityID, fromGroupID); + var entityViewBuilders = _entityInfos[entityegid.GID]; var entityViewBuildersCount = entityViewBuilders.Length; var groupedEntities = _groupEntityViewsDB[fromGroupID]; @@ -261,13 +256,13 @@ namespace Svelto.ECS if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false) groupedEntityViewsTyped[entityViewType] = toSafeList = fromSafeList.Create(); - entityViewBuilder.MoveEntityView(entityInfoView._ID, fromSafeList, toSafeList); - fromSafeList.MappedRemove(entityInfoView._ID); - entityInfoView._ID = new EGID(entityID, toGroupID); + entityViewBuilder.MoveEntityView(entityegid, fromSafeList, toSafeList); + fromSafeList.MappedRemove(entityegid); } - } - readonly Type _entityInfoViewType = typeof(EntityInfoView); + _entityInfos.Remove(entityegid.GID); + _entityInfos.Add(new EGID(entityID, toGroupID).GID, entityViewBuilders); + } readonly EntityViewsDB _DB; @@ -283,6 +278,6 @@ namespace Svelto.ECS //indexable entity views when the entity ID is known. Usually useful to handle //event based logic. readonly Dictionary _globalEntityViewsDBDic; - + Dictionary _entityInfos; } } \ No newline at end of file diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs index e90d220..8fe024e 100644 --- a/Svelto.ECS/EntityFactory.cs +++ b/Svelto.ECS/EntityFactory.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Xml; using Svelto.DataStructures; using Svelto.Utilities; using Console = Utility.Console; @@ -11,31 +12,20 @@ namespace Svelto.ECS.Internal internal static void BuildGroupedEntityViews(int entityID, int groupID, Dictionary> groupEntityViewsByType, EntityDescriptorInfo entityViewsToBuildDescriptor, + Dictionary entityInfos, object[] implementors) { var @group = FetchGroup(groupID, groupEntityViewsByType); BuildEntityViewsAndAddToGroup(new EGID(entityID, groupID), group, entityViewsToBuildDescriptor, implementors); - AddEntityInfoView(new EGID(entityID, groupID), entityViewsToBuildDescriptor, @group); + AddEntityInfoView(new EGID(entityID, groupID), entityViewsToBuildDescriptor, entityInfos); } - static void AddEntityInfoView(EGID entityID, EntityDescriptorInfo entityViewsToBuildDescriptor, - Dictionary @group) + static void AddEntityInfoView(EGID entityID, EntityDescriptorInfo entityViewsToBuildDescriptor, + Dictionary entityInfos) { - //should be a struct? - var removeEntityView = new EntityInfoView(); - - removeEntityView._ID = entityID; - removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; - - ITypeSafeList list; - - if (group.TryGetValue(typeof(EntityInfoView), out list) == false) - list = group[typeof(EntityInfoView)] = - new TypeSafeFasterListForECSForClasses(); - - ((TypeSafeFasterListForECSForClasses) list).Add(removeEntityView); + entityInfos.Add(entityID.GID, entityViewsToBuildDescriptor.entityViewsToBuild); } static Dictionary FetchGroup(int groupID, Dictionary> groupEntityViewsByType) @@ -202,7 +192,7 @@ namespace Svelto.ECS.Internal } #endif static readonly Dictionary _cachedTypes = new Dictionary(); - + const string DUPLICATE_IMPLEMENTOR_ERROR = "Svelto.ECS the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. "; diff --git a/Svelto.ECS/EntityInfoView.cs b/Svelto.ECS/EntityInfoView.cs deleted file mode 100644 index 14490bd..0000000 --- a/Svelto.ECS/EntityInfoView.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Svelto.ECS.Internal -{ - class EntityInfoView : EntityView - { - internal IEntityViewBuilder[] entityViews; - } -} \ No newline at end of file From ccdc03421acc78a0a2c69b00a4ec776a1954e5b1 Mon Sep 17 00:00:00 2001 From: sebas77 Date: Sat, 31 Mar 2018 23:07:57 +0100 Subject: [PATCH 5/6] better logs --- Svelto.ECS/EntityFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs index 8fe024e..a7e1a19 100644 --- a/Svelto.ECS/EntityFactory.cs +++ b/Svelto.ECS/EntityFactory.cs @@ -136,7 +136,7 @@ namespace Svelto.ECS.Internal #if DEBUG && !PROFILER else { - Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString())); + Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat("Type ", entityDescriptorName, " entityView ", entityView.ToString())); } #endif } From c2ff71d780934a7f726a7862293c26e34981fa9a Mon Sep 17 00:00:00 2001 From: sebas77 Date: Tue, 3 Apr 2018 00:03:10 +0100 Subject: [PATCH 6/6] EntityStructs cannot be put in or queried from groups anymore EnttiyStructs can now be built with an initializer --- .../DataStructures/TypeSafeDictionary.cs | 49 ----- .../TypeSafeFasterListForECS.cs | 2 +- Svelto.ECS/EnginesRootEntities.cs | 36 ++-- Svelto.ECS/EnginesRootSubmission.cs | 32 +-- Svelto.ECS/EntityDescriptor.cs | 8 +- Svelto.ECS/EntityFactory.cs | 1 - Svelto.ECS/EntityViewBuilder.cs | 29 ++- Svelto.ECS/EntityViewsDB.cs | 2 +- .../Experimental/StructNodeCollections.cs | 183 ------------------ Svelto.ECS/IEntityViewsDB.cs | 2 +- 10 files changed, 71 insertions(+), 273 deletions(-) delete mode 100644 Svelto.ECS/Experimental/StructNodeCollections.cs diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs index 164017e..9bb386f 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs @@ -16,7 +16,6 @@ namespace Svelto.ECS.Internal void FillWithIndexedEntityViews(ITypeSafeList entityViews); bool Remove(EGID entityId); IEntityView GetIndexedEntityView(EGID entityID); - bool isQueryiableEntityView { get; } } class TypeSafeDictionaryForClass : Dictionary, ITypeSafeDictionary where TValue : EntityView @@ -55,53 +54,5 @@ namespace Svelto.ECS.Internal { return this[entityID.GID]; } - - public bool isQueryiableEntityView - { - get { return true; } - } - } - - class TypeSafeDictionaryForStruct : Dictionary, ITypeSafeDictionary where TValue : struct, IEntityStruct - { - internal static readonly ReadOnlyDictionary Default = - new ReadOnlyDictionary(new Dictionary()); - - public void FillWithIndexedEntityViews(ITypeSafeList entityViews) - { - int count; - var buffer = FasterList.NoVirt.ToArrayFast((FasterList) entityViews, out count); - - try - { - for (var i = 0; i < count; i++) - { - var entityView = buffer[i]; - - Add(entityView.ID.GID, entityView); - } - } - catch (Exception e) - { - throw new TypeSafeDictionaryException(e); - } - } - - public bool Remove(EGID entityId) - { - base.Remove(entityId.GID); - - return Count > 0; - } - - public IEntityView GetIndexedEntityView(EGID entityID) - { - return this[entityID.GID]; - } - - public bool isQueryiableEntityView - { - get { return false; } - } } } \ No newline at end of file diff --git a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs index 4e54840..7fde5b9 100644 --- a/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs +++ b/Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs @@ -118,7 +118,7 @@ namespace Svelto.ECS.Internal public ITypeSafeDictionary CreateIndexedDictionary() { - return new TypeSafeDictionaryForStruct(); + throw new NotSupportedException(); } public IEntityView[] ToArrayFast(out int count) diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index 620a29c..c5c4383 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -131,18 +131,20 @@ namespace Svelto.ECS void RemoveEntity(EGID entityGID) { var entityViewBuilders = _entityInfos[entityGID.GID]; - var entityViewBuildersCount = entityViewBuilders.Length; - var group = _groupEntityViewsDB[entityGID.group]; - + //for each entity view generated by the entity descriptor for (var i = 0; i < entityViewBuildersCount; i++) { var entityViewType = entityViewBuilders[i].GetEntityViewType(); - - InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityGID); - - RemoveEntityViewFromDB(@group, entityViewType, entityGID); + + if (entityViewBuilders[i].isQueryiableEntityView) + { + var group = _groupEntityViewsDB[entityGID.group]; + InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityGID); + RemoveEntityViewFromDB(@group, entityViewType, entityGID); + } + RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityGID); } @@ -161,18 +163,21 @@ namespace Svelto.ECS { foreach (var group in _groupEntityViewsDB[groupID]) { - var entityViewType = group.Key; + { + var entityViewType = group.Key; - int count; - var entities = group.Value.ToArrayFast(out count); + int count; + var entities = group.Value.ToArrayFast(out count); - for (var i = 0; i < count; i++) - { - var entityID = entities[i].ID; + for (var i = 0; i < count; i++) + { + var entityID = entities[i].ID; - RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityID); + RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityID); - InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID); + if (group.Value.isQueryiableEntityView) + InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID); + } } } @@ -182,7 +187,6 @@ namespace Svelto.ECS void InternalRemoveEntityViewFromDBDicAndEngines(Type entityViewType, EGID id) { var typeSafeDictionary = _globalEntityViewsDBDic[entityViewType]; - if (typeSafeDictionary.isQueryiableEntityView) { var entityView = typeSafeDictionary.GetIndexedEntityView(id); diff --git a/Svelto.ECS/EnginesRootSubmission.cs b/Svelto.ECS/EnginesRootSubmission.cs index 3934072..bc1e1f8 100644 --- a/Svelto.ECS/EnginesRootSubmission.cs +++ b/Svelto.ECS/EnginesRootSubmission.cs @@ -55,7 +55,8 @@ namespace Svelto.ECS foreach (var entityViewsPerType in groupToSubmit.Value) { //add the entity View in the group - AddEntityViewToDB(groupDB, entityViewsPerType); + if (entityViewsPerType.Value.isQueryiableEntityView == true) + AddEntityViewToDB(groupDB, entityViewsPerType); //add the entity view in the gloal pool AddEntityViewToDB(_globalEntityViewsDB, entityViewsPerType); //and it's not a struct, add in the indexable DB too @@ -63,7 +64,8 @@ namespace Svelto.ECS } } - //then submit everything in the engines + //then submit everything in the engines, so that the DB is up to date + //with all the entity views and struct created by the entity built foreach (var group in groupsToSubmit) { foreach (var entityViewList in group.Value) @@ -81,23 +83,29 @@ namespace Svelto.ECS static void AddEntityViewToDB( Dictionary entityViewsDB, KeyValuePair entityViewList) { - ITypeSafeList dbList; + + { + ITypeSafeList dbList; - if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false) - dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create(); + if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false) + dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create(); - dbList.AddRange(entityViewList.Value); + dbList.AddRange(entityViewList.Value); + } } static void AddEntityViewToEntityViewsDictionary(Dictionary entityViewsDBdic, ITypeSafeList entityViews, Type entityViewType) { - ITypeSafeDictionary entityViewsDic; - - if (entityViewsDBdic.TryGetValue(entityViewType, out entityViewsDic) == false) - entityViewsDic = entityViewsDBdic[entityViewType] = entityViews.CreateIndexedDictionary(); - - entityViewsDic.FillWithIndexedEntityViews(entityViews); + if (entityViews.isQueryiableEntityView == true) + { + ITypeSafeDictionary entityViewsDic; + + if (entityViewsDBdic.TryGetValue(entityViewType, out entityViewsDic) == false) + entityViewsDic = entityViewsDBdic[entityViewType] = entityViews.CreateIndexedDictionary(); + + entityViewsDic.FillWithIndexedEntityViews(entityViews); + } } static void AddEntityViewToTheSuitableEngines(Dictionary> entityViewEngines, ITypeSafeList entityViewsList, Type entityViewType) diff --git a/Svelto.ECS/EntityDescriptor.cs b/Svelto.ECS/EntityDescriptor.cs index 9958c7e..e75b01b 100644 --- a/Svelto.ECS/EntityDescriptor.cs +++ b/Svelto.ECS/EntityDescriptor.cs @@ -31,15 +31,15 @@ namespace Svelto.ECS Check.Require(extraEntityViews.Count > 0, "don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews"); - var descriptor = new TType(); - var length = descriptor.entityViewsToBuild.Length; + var defaultEntityViewsToBuild = EntityDescriptorTemplate.Default.entityViewsToBuild; + var length = defaultEntityViewsToBuild.Length; entityViewsToBuild = new IEntityViewBuilder[length + extraEntityViews.Count]; - Array.Copy(descriptor.entityViewsToBuild, 0, entityViewsToBuild, 0, length); + Array.Copy(defaultEntityViewsToBuild, 0, entityViewsToBuild, 0, length); Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count); - name = descriptor.ToString(); + name = EntityDescriptorTemplate.Default.name; } } diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs index a7e1a19..ae600fe 100644 --- a/Svelto.ECS/EntityFactory.cs +++ b/Svelto.ECS/EntityFactory.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Xml; using Svelto.DataStructures; using Svelto.Utilities; using Console = Utility.Console; diff --git a/Svelto.ECS/EntityViewBuilder.cs b/Svelto.ECS/EntityViewBuilder.cs index f709038..3d6e24e 100644 --- a/Svelto.ECS/EntityViewBuilder.cs +++ b/Svelto.ECS/EntityViewBuilder.cs @@ -11,6 +11,7 @@ namespace Svelto.ECS Type GetEntityViewType(); void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList); bool mustBeFilled { get; } + bool isQueryiableEntityView { get; } } public class EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() @@ -56,23 +57,35 @@ namespace Svelto.ECS { get { return true; } } + + public bool isQueryiableEntityView + { + get { return true; } + } public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); } public class EntityViewStructBuilder : IEntityViewBuilder where EntityViewType : struct, IEntityStruct { + public EntityViewStructBuilder() + {} + + public EntityViewStructBuilder(ref EntityViewType initializer) + { + _initializer = initializer; + } + public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView) { - var structEntityView = default(EntityViewType); - structEntityView.ID = entityID; + _initializer.ID = entityID; if (list == null) list = new TypeSafeFasterListForECSForStructs(); var castedList = list as TypeSafeFasterListForECSForStructs; - - castedList.Add(structEntityView); + + castedList.Add(_initializer); entityView = null; } @@ -105,6 +118,12 @@ namespace Svelto.ECS get { return false; } } + public bool isQueryiableEntityView + { + get { return false; } + } + public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType); - } + EntityViewType _initializer; + } } \ No newline at end of file diff --git a/Svelto.ECS/EntityViewsDB.cs b/Svelto.ECS/EntityViewsDB.cs index 0e69652..1258a0b 100644 --- a/Svelto.ECS/EntityViewsDB.cs +++ b/Svelto.ECS/EntityViewsDB.cs @@ -54,7 +54,7 @@ namespace Svelto.ECS.Internal return FasterList.NoVirt.ToArrayFast((FasterList)entityViews, out count); } - public T[] QueryGroupedEntityViewsAsArray(int @group, out int count) where T : IEntityView + public T[] QueryGroupedEntityViewsAsArray(int @group, out int count) where T : EntityView { var type = typeof(T); count = 0; diff --git a/Svelto.ECS/Experimental/StructNodeCollections.cs b/Svelto.ECS/Experimental/StructNodeCollections.cs deleted file mode 100644 index f09b605..0000000 --- a/Svelto.ECS/Experimental/StructNodeCollections.cs +++ /dev/null @@ -1,183 +0,0 @@ -#if EXPERIMENTAL -using System; -using System.Collections.Generic; -using Svelto.DataStructures; -using Svelto.ECS.Experimental.Internal; - -namespace Svelto.ECS.Experimental.Internal -{ - public interface IStructEntityViewEngine : IEngine - { - void CreateStructEntityViews(SharedStructEntityViewLists sharedStructEntityViewLists); - } - - public interface IGroupedStructEntityViewsEngine : IEngine - { - void CreateStructEntityViews(SharedGroupedStructEntityViewsLists sharedStructEntityViewLists); - } -} - -namespace Svelto.ECS.Experimental -{ - public interface IGroupedEntityView - { - int groupID { get; set; } - } - - /// - /// The engines can receive and store IEntityViews structs - /// Unboxing will happen during the Add, but the - /// data will then be stored and processed as stucts - /// - public interface IStructEntityViewEngine : IStructEntityViewEngine where T:struct, IEntityStruct - { } - - /// - /// same as above, but the entityViews are grouped by ID - /// usually the ID is the owner of the entityViews of that - /// group - /// - public interface IGroupedStructEntityViewsEngine : IGroupedStructEntityViewsEngine where T : struct, IGroupedEntityView - { - void Add(ref T entityView); - void Remove(ref T entityView); - } - - public sealed class StructEntityViews where T:struct, IEntityStruct - { - public T[] GetList(out int numberOfItems) - { - numberOfItems = _internalList.Count; - return _internalList.ToArrayFast(); - } - - public StructEntityViews(SharedStructEntityViewLists container) - { - _internalList = SharedStructEntityViewLists.NoVirt.GetList(container); - } - - public void Add(T entityView) - { - T convert = (T)entityView; - - _internalList.Add(convert); - } - - readonly FasterList _internalList; - } - - public struct StructGroupEntityViews - where T : struct, IEntityView - { - public StructGroupEntityViews(SharedGroupedStructEntityViewsLists container) - { - _container = container; - indices = new Dictionary(); - } - - public void Add(int groupID, T entityView) - { - T convert = (T)entityView; - - var fasterList = - (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); - indices[entityView.ID] = fasterList.Count; - - fasterList.Add(convert); - } - - public void Remove(int groupID, T entityView) - { - var fasterList = - (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); - var index = indices[entityView.ID]; - indices.Remove(entityView.ID); - - if (fasterList.UnorderedRemoveAt(index)) - indices[fasterList[index].ID] = index; - } - - public T[] GetList(int groupID, out int numberOfItems) - { - var fasterList = - (SharedGroupedStructEntityViewsLists.NoVirt.GetList(_container, groupID) as FasterList); - - return FasterList.NoVirt.ToArrayFast(fasterList, out numberOfItems); - } - - readonly SharedGroupedStructEntityViewsLists _container; - readonly Dictionary indices; - } - - public class SharedStructEntityViewLists - { - internal SharedStructEntityViewLists() - { - _collection = new Dictionary(); - } - - internal static class NoVirt - { - internal static FasterList GetList(SharedStructEntityViewLists obj) where T : struct - { - IFasterList list; - if (obj._collection.TryGetValue(typeof(T), out list)) - { - return list as FasterList; - } - - list = new FasterList(); - - obj._collection.Add(typeof(T), list); - - return (FasterList)list; - } - } - - readonly Dictionary _collection; - } - - public class SharedGroupedStructEntityViewsLists - { - internal SharedGroupedStructEntityViewsLists() - { - _collection = new Dictionary>(); - } - - internal static class NoVirt - { - internal static IFasterList GetList(SharedGroupedStructEntityViewsLists list, int groupID) where T : struct - { - Dictionary dic = GetGroup(list); - IFasterList localList; - - if (dic.TryGetValue(groupID, out localList)) - return localList; - - localList = new FasterList(); - dic.Add(groupID, localList); - - return localList; - } - - internal static Dictionary GetGroup(SharedGroupedStructEntityViewsLists list) where T : struct - { - Dictionary dic; - - if (list._collection.TryGetValue(typeof(T), out dic)) - { - return dic; - } - - dic = new Dictionary(); - - list._collection.Add(typeof(T), dic); - - return dic; - } - } - - readonly Dictionary> _collection; - } -} -#endif \ No newline at end of file diff --git a/Svelto.ECS/IEntityViewsDB.cs b/Svelto.ECS/IEntityViewsDB.cs index 239a9e6..ae71152 100644 --- a/Svelto.ECS/IEntityViewsDB.cs +++ b/Svelto.ECS/IEntityViewsDB.cs @@ -8,7 +8,7 @@ namespace Svelto.ECS FasterReadOnlyList QueryGroupedEntityViews(int group) where T : EntityView; T[] QueryEntityViewsAsArray(out int count) where T : IEntityView; - T[] QueryGroupedEntityViewsAsArray(int group, out int count) where T : IEntityView; + T[] QueryGroupedEntityViewsAsArray(int group, out int count) where T : EntityView; bool TryQueryEntityView(EGID ID, out T entityView) where T : EntityView; T QueryEntityView(EGID entityGID) where T : EntityView;