diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs index c7cdc14..0ffde6b 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs @@ -1,4 +1,5 @@ -using Svelto.DataStructures; +using System; +using Svelto.DataStructures; using System.Collections.Generic; namespace Svelto.ECS.Internal @@ -28,15 +29,22 @@ namespace Svelto.ECS.Internal int count; var buffer = FasterList.NoVirt.ToArrayFast((FasterList) entityViews, out count); - for (int i = 0; i < count; i++) + try { - var entityView = buffer[i]; + for (int i = 0; i < count; i++) + { + var entityView = buffer[i]; - Add(entityView.ID, entityView); + Add(entityView.ID, entityView); + } + } + catch (Exception e) + { + throw new TypeSafeDictionaryException(e); } } - new public bool Remove(int entityId) + public new bool Remove(int entityId) { base.Remove(entityId); diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs new file mode 100644 index 0000000..1db957d --- /dev/null +++ b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs @@ -0,0 +1,10 @@ +using System; + +namespace Svelto.ECS +{ + public class TypeSafeDictionaryException : Exception + { + public TypeSafeDictionaryException(Exception exception):base(exception.Message, exception) + {} + } +} \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootEngines.cs b/Svelto.ECS/EnginesRootEngines.cs index e8b557d..249e82f 100644 --- a/Svelto.ECS/EnginesRootEngines.cs +++ b/Svelto.ECS/EnginesRootEngines.cs @@ -42,12 +42,13 @@ namespace Svelto.ECS _metaEntityViewsDB = new Dictionary(); _groupEntityViewsDB = new Dictionary>(); _entityViewsDBDic = new Dictionary(); + _metaEntityViewsDBDic = new Dictionary(); _entityViewsToAdd = new DoubleBufferedEntityViews>(); _metaEntityViewsToAdd = new DoubleBufferedEntityViews>(); _groupedEntityViewsToAdd = new DoubleBufferedEntityViews>>(); - _DB = new EntityViewsDB(_entityViewsDB, _entityViewsDBDic, _metaEntityViewsDB, _groupEntityViewsDB); + _DB = new EntityViewsDB(_entityViewsDB, _metaEntityViewsDB, _entityViewsDBDic, _metaEntityViewsDBDic, _groupEntityViewsDB); _scheduler = entityViewScheduler; _scheduler.Schedule(new WeakAction(SubmitEntityViews)); diff --git a/Svelto.ECS/EnginesRootEntities.cs b/Svelto.ECS/EnginesRootEntities.cs index e1d7d1d..6a3adbb 100644 --- a/Svelto.ECS/EnginesRootEntities.cs +++ b/Svelto.ECS/EnginesRootEntities.cs @@ -134,32 +134,29 @@ namespace Svelto.ECS } } - void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo) + void RemoveEntity(ref EntityInfoView entityInfoView, Dictionary viewsDB, Dictionary entityViewsDBDic) { - var removeEntityImplementor = removeInfo as RemoveEntityImplementor; - - if (removeEntityImplementor.isInAGroup) - InternalRemove(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, removeEntityImplementor.groupID, _entityViewsDB); + if (entityInfoView.isInAGroup) + InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, entityInfoView.groupID, viewsDB, entityViewsDBDic); else - InternalRemoveFromDBAndEngines(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, _entityViewsDB); + InternalRemoveFromDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, viewsDB, entityViewsDBDic); } - - void RemoveEntity(int entityID) where T : IEntityDescriptor, new() - { - InternalRemoveFromDBAndEngines( ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, entityID, _entityViewsDB); - } - - void RemoveMetaEntity(int metaEntityID) where T : IEntityDescriptor, new() + + void RemoveEntity(int entityID) { - InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, metaEntityID, _metaEntityViewsDB); + var entityInfoView = _DB.QueryEntityView(entityID); + + RemoveEntity(ref entityInfoView, _entityViewsDB, _entityViewsDBDic); } - void RemoveEntityFromGroup(int entityID, int groupID) where T : IEntityDescriptor, new() + void RemoveMetaEntity(int metaEntityID) { - InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]); + var entityInfoView = _DB.QueryMetaEntityView(metaEntityID); + + RemoveEntity(ref entityInfoView, _metaEntityViewsDB, _metaEntityViewsDBDic); } - void DeleteEntityGroup(int groupID) + void RemoveGroupAndEntitiesFromDB(int groupID) { foreach (var group in _groupEntityViewsDB[groupID]) { @@ -172,7 +169,7 @@ namespace Svelto.ECS { var entityID = entities[i].ID; - InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, entityViewType, entityID); + InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, _entityViewsDBDic, entityViewType, entityID); } } @@ -180,6 +177,7 @@ namespace Svelto.ECS } void InternalRemoveEntityViewFromDBAndEngines(Dictionary entityViewsDB, + Dictionary entityViewsDBDic, Type entityViewType, int entityID) { var entityViews = entityViewsDB[entityViewType]; @@ -188,22 +186,22 @@ namespace Svelto.ECS if (entityViews.isQueryiableEntityView) { - var typeSafeDictionary = _entityViewsDBDic[entityViewType]; + var typeSafeDictionary = entityViewsDBDic[entityViewType]; var entityView = typeSafeDictionary.GetIndexedEntityView(entityID); if (typeSafeDictionary.Remove(entityID) == false) - _entityViewsDBDic.Remove(entityViewType); + entityViewsDBDic.Remove(entityViewType); for (var current = entityViewType; current != _entityViewType; current = current.BaseType) RemoveEntityViewFromEngines(_entityViewEngines, entityView, current); } } - void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() + void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) { DesignByContract.Check.Require(fromGroupID != toGroupID, "can't move an entity to the same group where it already belongs to"); - var entityViewBuilders = ((EntityDescriptorInfo) EntityDescriptorTemplate.Default).entityViewsToBuild; + var entityViewBuilders = _DB.QueryEntityView(entityID).entityViews; int entityViewBuildersCount = entityViewBuilders.Length; var dictionary = _groupEntityViewsDB[fromGroupID]; @@ -239,7 +237,7 @@ namespace Svelto.ECS } void InternalRemoveFromDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID, - Dictionary entityViewsDB) + Dictionary entityViewsDB, Dictionary entityViewsDBDic) { int entityViewBuildersCount = entityViewBuilders.Length; @@ -247,16 +245,16 @@ namespace Svelto.ECS { Type entityViewType = entityViewBuilders[i].GetEntityViewType(); - InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewType, entityID); + InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewsDBDic, entityViewType, entityID); } } - void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID, - Dictionary entityViewsDB) + void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID, + Dictionary entityViewsDB, Dictionary entityViewsDBDic) { InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID); - InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB); + InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB, entityViewsDBDic); } void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID) @@ -269,11 +267,8 @@ namespace Svelto.ECS { Type entityViewType = entityViewBuilders[i].GetEntityViewType(); - if (dictionary[entityViewType].UnorderedRemove(entityID) == false) - dictionary.Remove(entityViewType); + dictionary[entityViewType].UnorderedRemove(entityID); } - - if (dictionary.Count == 0) _groupEntityViewsDB.Remove(groupID); } static void RemoveEntityViewFromEngines(Dictionary> entityViewEngines, @@ -344,34 +339,24 @@ namespace Svelto.ECS _weakReference = weakReference; } - public void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo) - { - _weakReference.Target.RemoveEntity(entityID, removeInfo); - } - - public void RemoveEntity(int entityID) where T : IEntityDescriptor, new() + public void RemoveEntity(int entityID) { - _weakReference.Target.RemoveEntity(entityID); + _weakReference.Target.RemoveEntity(entityID); } - public void RemoveMetaEntity(int metaEntityID) where T : IEntityDescriptor, new() + public void RemoveMetaEntity(int metaEntityID) { - _weakReference.Target.RemoveEntity(metaEntityID); + _weakReference.Target.RemoveEntity(metaEntityID); } - public void RemoveEntityFromGroup(int entityID, int groupID) where T : IEntityDescriptor, new() + public void RemoveGroupAndEntities(int groupID) { - _weakReference.Target.RemoveEntity(entityID); + _weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID); } - public void DeleteEntityGroup(int groupID) + public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) { - _weakReference.Target.DeleteEntityGroup(groupID); - } - - public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new() - { - _weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID); + _weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID); } readonly DataStructures.WeakReference _weakReference; @@ -406,6 +391,6 @@ namespace Svelto.ECS readonly Dictionary> _groupEntityViewsDB; readonly Dictionary _entityViewsDBDic; - + readonly Dictionary _metaEntityViewsDBDic; } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRootSubmission.cs b/Svelto.ECS/EnginesRootSubmission.cs index c2343b9..37d9299 100644 --- a/Svelto.ECS/EnginesRootSubmission.cs +++ b/Svelto.ECS/EnginesRootSubmission.cs @@ -30,13 +30,13 @@ namespace Svelto.ECS _groupedEntityViewsToAdd.Swap(); if (_entityViewsToAdd.other.Count > 0) - AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB); + AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB, _entityViewsDBDic); if (_metaEntityViewsToAdd.other.Count > 0) - AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB); + AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB, _metaEntityViewsDBDic); if (_groupedEntityViewsToAdd.other.Count > 0) - AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB); + AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB, _entityViewsDBDic); //other can be cleared now _entityViewsToAdd.other.Clear(); @@ -57,7 +57,7 @@ namespace Svelto.ECS } void AddEntityViewsToTheDBAndSuitableEngines(Dictionary entityViewsToAdd, - Dictionary entityViewsDB) + Dictionary entityViewsDB, Dictionary entityViewsDBDic) { foreach (var entityViewList in entityViewsToAdd) { @@ -65,7 +65,7 @@ namespace Svelto.ECS if (entityViewList.Value.isQueryiableEntityView) { - AddEntityViewToEntityViewsDictionary(_entityViewsDBDic, entityViewList.Value, entityViewList.Key); + AddEntityViewToEntityViewsDictionary(entityViewsDBDic, entityViewList.Value, entityViewList.Key); } } @@ -83,13 +83,14 @@ namespace Svelto.ECS void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary> groupedEntityViewsToAdd, Dictionary> groupEntityViewsDB, - Dictionary entityViewsDB) + Dictionary entityViewsDB + , Dictionary entityViewsDBDic) { foreach (var group in groupedEntityViewsToAdd) { AddEntityViewsToGroupDB(groupEntityViewsDB, @group); - AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB); + AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB, entityViewsDBDic); } } @@ -157,6 +158,7 @@ namespace Svelto.ECS readonly DoubleBufferedEntityViews> _entityViewsToAdd; readonly DoubleBufferedEntityViews> _metaEntityViewsToAdd; + readonly DoubleBufferedEntityViews>> _groupedEntityViewsToAdd; readonly EntitySubmissionScheduler _scheduler; diff --git a/Svelto.ECS/EntityDescriptor.cs b/Svelto.ECS/EntityDescriptor.cs index d6c5aa3..6b1bc21 100644 --- a/Svelto.ECS/EntityDescriptor.cs +++ b/Svelto.ECS/EntityDescriptor.cs @@ -1,8 +1,6 @@ using Svelto.DataStructures; using Svelto.ECS.Internal; -using Svelto.Utilities; using System; -using System.Collections.Generic; namespace Svelto.ECS { @@ -43,7 +41,6 @@ namespace Svelto.ECS Array.Copy(descriptor.entityViewsToBuild, 0, entityViewsToBuild, 0, length); Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count); - removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild); name = descriptor.ToString(); } } @@ -54,219 +51,16 @@ namespace Svelto.ECS.Internal public class EntityDescriptorInfo:IEntityDescriptorInfo { internal IEntityViewBuilder[] entityViewsToBuild; - internal RemoveEntityImplementor removeEntityImplementor; internal string name; internal EntityDescriptorInfo(IEntityDescriptor descriptor) { name = descriptor.ToString(); entityViewsToBuild = descriptor.entityViewsToBuild; - - removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild); } protected EntityDescriptorInfo() {} } - - static class EntityFactory - { - internal static void BuildGroupedEntityViews(int entityID, int groupID, - Dictionary> groupEntityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors) - { - var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; - Dictionary groupedEntityViewsTyped; - - if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false) - { - groupedEntityViewsTyped = new Dictionary(); - groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped); - } - - //I would like to find a better solution for this - var removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.entityViewsToBuild, groupID); - - InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors, removeEntityImplementor); - } - - internal static void BuildEntityViews(int entityID, - Dictionary entityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors) - { - var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; - var removeEntityImplementor = entityViewsToBuildDescriptor.removeEntityImplementor; - - InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors, removeEntityImplementor); - } - - static void InternalBuildEntityViews(int entityID, - Dictionary entityViewsByType, - IEntityDescriptorInfo eentityViewsToBuildDescriptor, - object[] implementors, RemoveEntityImplementor removeEntityImplementor) - { - var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; - var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild; - int count = entityViewsToBuild.Length; - - for (int index = 0; index < count; index++) - { - var entityViewBuilder = entityViewsToBuild[index]; - var entityViewType = entityViewBuilder.GetEntityViewType(); - - //only class EntityView will be returned - //struct EntityView cannot be filled so it will be null. - var entityViewObjectToFill = - BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder); - - //the semantic of this code must still be improved - //but only classes can be filled, so I am aware - //it's a EntityView - if (entityViewObjectToFill != null) - { - FillEntityView(entityViewObjectToFill as EntityView, implementors, removeEntityImplementor, - entityViewsToBuildDescriptor.name); - } - } - } - - static IEntityView BuildEntityView(int entityID, Dictionary entityViewsByType, - Type entityViewType, IEntityViewBuilder entityViewBuilder) - { - ITypeSafeList entityViewsList; - - var entityViewsPoolWillBeCreated = - entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false; - - IEntityView entityViewObjectToFill; - - //passing the undefined entityViewsByType inside the entityViewBuilder will allow - //it to be created with the correct type and casted back to the undefined list. - //that's how the list will be eventually of the target type. - entityViewBuilder.BuildEntityViewAndAddToList(ref entityViewsList, entityID, out entityViewObjectToFill); - - if (entityViewsPoolWillBeCreated) - entityViewsByType.Add(entityViewType, entityViewsList); - - return entityViewObjectToFill as IEntityView; - } - - //this is used to avoid newing a dictionary every time, but it's used locally only and it's clearead for each use -#if DEBUG && !PROFILER - static readonly Dictionary> implementorsByType = new Dictionary>(); -#else - static readonly Dictionary implementorsByType = new Dictionary(); -#endif - - static void FillEntityView(EntityView entityView, object[] implementors, RemoveEntityImplementor removeEntity, - string entityDescriptorName) - { - for (int index = 0; index < implementors.Length; index++) - { - var implementor = implementors[index]; - - if (implementor != null) - { - var type = implementor.GetType(); - - Type[] interfaces; - if (_cachedTypes.TryGetValue(type, out interfaces) == false) - interfaces = _cachedTypes[type] = type.GetInterfacesEx(); - - for (int iindex = 0; iindex < interfaces.Length; iindex++) - { - var componentType = interfaces[iindex]; -#if DEBUG && !PROFILER - Tuple implementorHolder; - - if (implementorsByType.TryGetValue(componentType, out implementorHolder) == true) - implementorHolder.item2++; - else - implementorsByType[componentType] = new Tuple(implementor, 1); -#else - implementorsByType[componentType] = implementor; -#endif - } - } -#if DEBUG && !PROFILER - else - Utility.Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString())); -#endif - } - - int count; - - //Very efficent way to collect the fields of every EntityViewType - KeyValuePair>[] setters = - FasterList>>.NoVirt.ToArrayFast(entityView.entityViewBlazingFastReflection, out count); - - var removeEntityComponentType = typeof(IRemoveEntityComponent); - - for (int i = 0; i < count; i++) - { - var keyValuePair = setters[i]; - Type fieldType = keyValuePair.Key; - - if (fieldType != removeEntityComponentType) - { -#if DEBUG && !PROFILER - Tuple component; -#else - object component; -#endif - - if (implementorsByType.TryGetValue(fieldType, out component) == false) - { - Exception e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + " - EntityView: " + - entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); - - throw e; - } -#if DEBUG && !PROFILER - if (component.item2 > 1) - Utility.Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat( - "Component Type: ", fieldType.Name, " implementor: ", - component.item1.ToString()) + " - EntityView: " + - entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); -#endif -#if DEBUG && !PROFILER - keyValuePair.Value.Call(entityView, component.item1); -#else - keyValuePair.Value.Call(entityView, component); -#endif - } - else - { - keyValuePair.Value.Call(entityView, removeEntity); - } - } - - implementorsByType.Clear(); - } -#if DEBUG && !PROFILER - struct Tuple - { - public T1 item1; - public T2 item2; - - public Tuple(T1 implementor, T2 v) - { - item1 = implementor; - item2 = v; - } - } -#endif - static 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. "; - - const string NULL_IMPLEMENTOR_ERROR = - "Svelto.ECS Null implementor, please be careful about the implementors passed to avoid performance loss "; - - const string NOT_FOUND_EXCEPTION = "Svelto.ECS Implementor not found for an EntityView. "; - } } diff --git a/Svelto.ECS/EntityFactory.cs b/Svelto.ECS/EntityFactory.cs new file mode 100644 index 0000000..78cba8a --- /dev/null +++ b/Svelto.ECS/EntityFactory.cs @@ -0,0 +1,216 @@ +using System; +using System.Collections.Generic; +using Svelto.DataStructures; +using Svelto.Utilities; + +namespace Svelto.ECS.Internal +{ + static class EntityFactory + { + internal static void BuildGroupedEntityViews(int entityID, int groupID, + Dictionary> groupEntityViewsByType, + IEntityDescriptorInfo eentityViewsToBuildDescriptor, + object[] implementors) + { + var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; + Dictionary groupedEntityViewsTyped; + + if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false) + { + groupedEntityViewsTyped = new Dictionary(); + groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped); + } + + InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors); + + EntityInfoView removeEntityView = new EntityInfoView(); + + removeEntityView.groupID = groupID; + removeEntityView.isInAGroup = true; + removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; + + AddEntityInfoView(groupEntityViewsByType[groupID], removeEntityView); + } + + internal static void BuildEntityViews(int entityID, + Dictionary entityViewsByType, + IEntityDescriptorInfo eentityViewsToBuildDescriptor, + object[] implementors) + { + var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; + + InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors); + + EntityInfoView removeEntityView = new EntityInfoView(); + removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; + + AddEntityInfoView(entityViewsByType, removeEntityView); + } + + static void AddEntityInfoView(Dictionary entityViewsByType, EntityInfoView removeEntityView) + { + 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; + int count = entityViewsToBuild.Length; + + for (int index = 0; index < count; index++) + { + var entityViewBuilder = entityViewsToBuild[index]; + var entityViewType = entityViewBuilder.GetEntityViewType(); + + var entityViewObjectToFill = + BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder); + + if (entityViewBuilder.mustBeFilled == true) + { + FillEntityView(entityViewObjectToFill as EntityView + ,implementors + ,entityViewsToBuildDescriptor.name); + } + } + } + + static IEntityView BuildEntityView(int entityID, Dictionary entityViewsByType, + Type entityViewType, IEntityViewBuilder entityViewBuilder) + { + ITypeSafeList entityViewsList; + + var entityViewsPoolWillBeCreated = + entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false; + + IEntityView entityViewObjectToFill; + + //passing the undefined entityViewsByType inside the entityViewBuilder will allow + //it to be created with the correct type and casted back to the undefined list. + //that's how the list will be eventually of the target type. + entityViewBuilder.BuildEntityViewAndAddToList(ref entityViewsList, entityID, out entityViewObjectToFill); + + if (entityViewsPoolWillBeCreated) + entityViewsByType.Add(entityViewType, entityViewsList); + + return entityViewObjectToFill; + } + + //this is used to avoid newing a dictionary every time, but it's used locally only and it's clearead for each use +#if DEBUG && !PROFILER + static readonly Dictionary> implementorsByType = new Dictionary>(); +#else + static readonly Dictionary implementorsByType = new Dictionary(); +#endif + + static void FillEntityView(EntityView entityView + , object[] implementors + , string entityDescriptorName) + { + int count; + + //Very efficent way to collect the fields of every EntityViewType + KeyValuePair>[] setters = + FasterList>>.NoVirt.ToArrayFast(entityView.entityViewBlazingFastReflection, out count); + + if (count == 0) return; + + for (int index = 0; index < implementors.Length; index++) + { + var implementor = implementors[index]; + + if (implementor != null) + { + var type = implementor.GetType(); + + Type[] interfaces; + if (_cachedTypes.TryGetValue(type, out interfaces) == false) + interfaces = _cachedTypes[type] = type.GetInterfacesEx(); + + for (int iindex = 0; iindex < interfaces.Length; iindex++) + { + var componentType = interfaces[iindex]; +#if DEBUG && !PROFILER + Tuple implementorHolder; + + if (implementorsByType.TryGetValue(componentType, out implementorHolder) == true) + implementorHolder.numberOfImplementations++; + else + implementorsByType[componentType] = new Tuple(implementor, 1); +#else + implementorsByType[componentType] = implementor; +#endif + } + } +#if DEBUG && !PROFILER + else + Utility.Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString())); +#endif + } + + for (int i = 0; i < count; i++) + { + var fieldSetter = setters[i]; + Type fieldType = fieldSetter.Key; + +#if DEBUG && !PROFILER + Tuple component; +#else + object component; +#endif + + if (implementorsByType.TryGetValue(fieldType, out component) == false) + { + Exception e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + " - EntityView: " + + entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); + + throw e; + } +#if DEBUG && !PROFILER + if (component.numberOfImplementations > 1) + Utility.Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat( + "Component Type: ", fieldType.Name, " implementor: ", + component.implementorType.ToString()) + " - EntityView: " + + entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName); +#endif +#if DEBUG && !PROFILER + fieldSetter.Value.Call(entityView, component.implementorType); +#else + keyValuePair.Value.Call(entityView, component); +#endif + } + + implementorsByType.Clear(); + } +#if DEBUG && !PROFILER + struct Tuple + { + public T1 implementorType; + public T2 numberOfImplementations; + + public Tuple(T1 implementor, T2 v) + { + implementorType = implementor; + numberOfImplementations = v; + } + } +#endif + static 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. "; + + const string NULL_IMPLEMENTOR_ERROR = + "Svelto.ECS Null implementor, please be careful about the implementors passed to avoid performance loss "; + + const string NOT_FOUND_EXCEPTION = "Svelto.ECS Implementor not found for an EntityView. "; + } +} \ No newline at end of file diff --git a/Svelto.ECS/EntityInfoImplementor.cs b/Svelto.ECS/EntityInfoImplementor.cs new file mode 100644 index 0000000..fd47890 --- /dev/null +++ b/Svelto.ECS/EntityInfoImplementor.cs @@ -0,0 +1,10 @@ +namespace Svelto.ECS.Internal +{ + class EntityInfoView : EntityView + { + internal IEntityViewBuilder[] entityViews; + internal int groupID; + internal bool isInAGroup; + } +} + diff --git a/Svelto.ECS/EntityViewBuilder.cs b/Svelto.ECS/EntityViewBuilder.cs index 7b89bcd..2320602 100644 --- a/Svelto.ECS/EntityViewBuilder.cs +++ b/Svelto.ECS/EntityViewBuilder.cs @@ -10,6 +10,7 @@ namespace Svelto.ECS Type GetEntityViewType(); void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList); + bool mustBeFilled { get; } } public class EntityViewBuilder : IEntityViewBuilder where EntityViewType : EntityView, new() @@ -51,6 +52,11 @@ namespace Svelto.ECS toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]); } + public bool mustBeFilled + { + get { return true; } + } + readonly Type _entityViewType = typeof(EntityViewType); } @@ -94,6 +100,11 @@ namespace Svelto.ECS toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]); } + public bool mustBeFilled + { + get { return false; } + } + readonly Type _entityViewType = typeof(EntityViewType); } } \ No newline at end of file diff --git a/Svelto.ECS/EntityViewsDB.cs b/Svelto.ECS/EntityViewsDB.cs index 7024318..2cabe48 100644 --- a/Svelto.ECS/EntityViewsDB.cs +++ b/Svelto.ECS/EntityViewsDB.cs @@ -6,18 +6,22 @@ namespace Svelto.ECS.Internal { class EntityViewsDB : IEntityViewsDB { - internal EntityViewsDB( Dictionary entityViewsDB, + internal EntityViewsDB( Dictionary entityViewsDB, + Dictionary metaEntityViewsDB, Dictionary entityViewsDBdic, - Dictionary metaEntityViewsDB, + Dictionary metaEntityViewsDBdic, Dictionary> groupEntityViewsDB) { _entityViewsDB = entityViewsDB; - _entityViewsDBdic = entityViewsDBdic; _metaEntityViewsDB = metaEntityViewsDB; + + _entityViewsDBdic = entityViewsDBdic; + _metaEntityViewsDBdic = metaEntityViewsDBdic; + _groupEntityViewsDB = groupEntityViewsDB; } - public FasterReadOnlyList QueryEntityViews() where T:EntityView, new() + public FasterReadOnlyList QueryEntityViews() where T:EntityView { var type = typeof(T); @@ -29,7 +33,7 @@ namespace Svelto.ECS.Internal return new FasterReadOnlyList((FasterList)entityViews); } - public FasterReadOnlyList QueryGroupedEntityViews(int @group) where T:EntityView, new() + public FasterReadOnlyList QueryGroupedEntityViews(int @group) where T:EntityView { Dictionary entitiesInGroupPerType; @@ -65,7 +69,7 @@ namespace Svelto.ECS.Internal return FasterList.NoVirt.ToArrayFast((FasterList)entityViews[type], out count); } - public ReadOnlyDictionary QueryIndexableEntityViews() where T:IEntityView + public ReadOnlyDictionary QueryIndexableEntityViews() where T:EntityView { var type = typeof(T); @@ -76,60 +80,40 @@ namespace Svelto.ECS.Internal return new ReadOnlyDictionary(entityViews as Dictionary); } - - public bool TryQueryEntityView(int ID, out T entityView) where T : IEntityView + + public ReadOnlyDictionary QueryIndexableMetaEntityViews() where T:EntityView { var type = typeof(T); - T internalEntityView; - ITypeSafeDictionary entityViews; - TypeSafeDictionary casted; - - _entityViewsDBdic.TryGetValue(type, out entityViews); - casted = entityViews as TypeSafeDictionary; - - if (casted != null && - casted.TryGetValue(ID, out internalEntityView)) - { - entityView = internalEntityView; - - return true; - } - entityView = default(T); + if (_metaEntityViewsDBdic.TryGetValue(type, out entityViews) == false) + return TypeSafeDictionary.Default; - return false; + return new ReadOnlyDictionary(entityViews as Dictionary); } - - public T QueryEntityView(int ID) where T : IEntityView + + public T QueryEntityView(int entityID) where T:EntityView { - var type = typeof(T); - - T internalEntityView; ITypeSafeDictionary entityViews; - TypeSafeDictionary casted; - - _entityViewsDBdic.TryGetValue(type, out entityViews); - casted = entityViews as TypeSafeDictionary; - - if (casted != null && - casted.TryGetValue(ID, out internalEntityView)) - return (T)internalEntityView; + return QueryEntityView(entityID, _entityViewsDBdic); + } - throw new Exception("EntityView Not Found"); + public bool TryQueryEntityView(int entityID, out T entityView) where T:EntityView + { + return TryQueryEntityView(entityID, _entityViewsDBdic, out entityView); } - public T QueryMetaEntityView(int metaEntityID) where T:EntityView, new() + public T QueryMetaEntityView(int metaEntityID) where T:EntityView { - return QueryEntityView(metaEntityID); + return QueryEntityView(metaEntityID, _metaEntityViewsDBdic); } - public bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T:EntityView, new() + public bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T:EntityView { - return TryQueryEntityView(metaEntityID, out entityView); + return TryQueryEntityView(metaEntityID, _metaEntityViewsDBdic, out entityView); } - public FasterReadOnlyList QueryMetaEntityViews() where T:EntityView, new() + public FasterReadOnlyList QueryMetaEntityViews() where T:EntityView { var type = typeof(T); @@ -150,10 +134,55 @@ namespace Svelto.ECS.Internal { return FasterList.DefaultList.ToArrayFast(); } + + static bool TryQueryEntityView(int ID, Dictionary entityDic, out T entityView) where T : EntityView + { + var type = typeof(T); + + T internalEntityView; + + ITypeSafeDictionary entityViews; + TypeSafeDictionary casted; + + entityDic.TryGetValue(type, out entityViews); + casted = entityViews as TypeSafeDictionary; - readonly Dictionary _entityViewsDB; - readonly Dictionary _entityViewsDBdic; - readonly Dictionary _metaEntityViewsDB; + if (casted != null && + casted.TryGetValue(ID, out internalEntityView)) + { + entityView = internalEntityView; + + return true; + } + + entityView = default(T); + + return false; + } + + static T QueryEntityView(int ID, Dictionary entityDic) where T : EntityView + { + var type = typeof(T); + + 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; } } diff --git a/Svelto.ECS/IEnginesInterfaces.cs b/Svelto.ECS/IEnginesInterfaces.cs index d6203e1..4d5c34e 100644 --- a/Svelto.ECS/IEnginesInterfaces.cs +++ b/Svelto.ECS/IEnginesInterfaces.cs @@ -15,14 +15,12 @@ namespace Svelto.ECS public interface IEntityFunctions { - void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo); - void RemoveEntity(int entityID) where T:IEntityDescriptor, new(); + void RemoveEntity(int entityID); - void RemoveMetaEntity(int metaEntityID) where T:IEntityDescriptor, new(); + void RemoveMetaEntity(int metaEntityID); - void RemoveEntityFromGroup(int entityID, int groupID) where T:IEntityDescriptor, new(); + void RemoveGroupAndEntities(int groupID); - void DeleteEntityGroup(int groupID); - void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new(); + void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID); } } diff --git a/Svelto.ECS/IEntityViewsDB.cs b/Svelto.ECS/IEntityViewsDB.cs index a6eb0c6..35e7f32 100644 --- a/Svelto.ECS/IEntityViewsDB.cs +++ b/Svelto.ECS/IEntityViewsDB.cs @@ -4,19 +4,21 @@ namespace Svelto.ECS { public interface IEntityViewsDB { - FasterReadOnlyList QueryEntityViews() where T:EntityView, new(); - FasterReadOnlyList QueryMetaEntityViews() where T: EntityView, new(); - FasterReadOnlyList QueryGroupedEntityViews(int group) where T: EntityView, new(); + 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: IEntityView; - bool TryQueryEntityView(int ID, out T entityView) where T : IEntityView; - T QueryEntityView(int ID) 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, new(); - T QueryMetaEntityView(int metaEntityID) where T: EntityView, new(); + bool TryQueryMetaEntityView(int metaEntityID, out T entityView) where T: EntityView; + T QueryMetaEntityView(int metaEntityID) where T: EntityView; } } diff --git a/Svelto.ECS/RemoveEntityImplementor.cs b/Svelto.ECS/RemoveEntityImplementor.cs deleted file mode 100644 index 0ad6a93..0000000 --- a/Svelto.ECS/RemoveEntityImplementor.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Svelto.ECS.Internal -{ - sealed class RemoveEntityImplementor : IRemoveEntityComponent - { - public RemoveEntityImplementor(IEntityViewBuilder[] entityViews, int groupID):this(entityViews) - { - this.groupID = groupID; - isInAGroup = true; - } - - internal RemoveEntityImplementor(IEntityViewBuilder[] entityViews) - { - removeEntityInfo = new RemoveEntityInfo(entityViews); - } - - internal readonly RemoveEntityInfo removeEntityInfo; - internal readonly int groupID; - internal readonly bool isInAGroup; - } -} - -namespace Svelto.ECS -{ - public interface IRemoveEntityComponent - {} - - public struct RemoveEntityInfo - { - internal readonly IEntityViewBuilder[] entityViewsToBuild; - - public RemoveEntityInfo(IEntityViewBuilder[] entityViews) : this() - { - this.entityViewsToBuild = entityViews; - } - } -}