@@ -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<T> 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; | |||
} | |||
} | |||
} | |||
} |
@@ -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<EnginesRoot> _weakEngine; | |||
public GenericEntityFactory(DataStructures.WeakReference<EnginesRoot> weakReference) | |||
{ | |||
_weakEngine = weakReference; | |||
} | |||
public void BuildEntity<T>(int entityID, object[] implementors) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.BuildEntity<T>(entityID, implementors); | |||
} | |||
public void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null) | |||
{ | |||
_weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors); | |||
} | |||
public void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors) | |||
where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.BuildEntityInGroup<T>(entityID, groupID, implementors); | |||
} | |||
public void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, | |||
object[] implementors) | |||
{ | |||
_weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors); | |||
} | |||
public void PreallocateEntitySpace<T>(int size) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.Preallocate<T>(ExclusiveGroups.StandardEntity, size); | |||
} | |||
public void PreallocateEntitySpaceInGroup<T>(int groupID, int size) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.Preallocate<T>(groupID, size); | |||
} | |||
} | |||
} | |||
} |
@@ -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<EnginesRoot> _weakReference; | |||
public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> 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); | |||
} | |||
} | |||
} | |||
} |
@@ -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<T> : FasterList<T> 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) | |||
@@ -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<IEngine>(); | |||
_entityViewsDB = new Dictionary<Type, ITypeSafeList>(); | |||
_metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>(); | |||
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>(); | |||
_entityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>(); | |||
_metaEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>(); | |||
_groupedEntityViewsDBDic = new Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>(); | |||
_entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>(); | |||
_metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>(); | |||
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>(); | |||
_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<T> 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; | |||
} | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <returns></returns> | |||
///-------------------------------------------- | |||
public IEntityFactory GenerateEntityFactory() | |||
{ | |||
return new GenericEntityFactory(new DataStructures.WeakReference<EnginesRoot>(this)); | |||
@@ -42,95 +32,49 @@ namespace Svelto.ECS | |||
return new GenericEntityFunctions(new DataStructures.WeakReference<EnginesRoot>(this)); | |||
} | |||
/// <summary> | |||
/// 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 | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="entityID"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntity<T>(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() | |||
{ | |||
EntityFactory.BuildEntityViews | |||
(entityID, _entityViewsToAdd.current, EntityDescriptorTemplate<T>.Default, implementors); | |||
} | |||
///-------------------------------------------- | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="entityID"></param> | |||
/// <param name="entityDescriptor"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors) | |||
void BuildEntity<T>(int entityID, object[] implementors = null) where T : IEntityDescriptor, new() | |||
{ | |||
EntityFactory.BuildEntityViews | |||
(entityID, _entityViewsToAdd.current, entityDescriptor, implementors); | |||
BuildEntityInGroup<T> | |||
(entityID, ExclusiveGroups.StandardEntity, implementors); | |||
} | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="metaEntityID"></param> | |||
/// <param name="ed"></param> | |||
/// <param name="implementors"></param> | |||
void BuildMetaEntity<T>(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new() | |||
void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors) | |||
{ | |||
EntityFactory.BuildEntityViews(metaEntityID, _metaEntityViewsToAdd.current, | |||
EntityDescriptorTemplate<T>.Default, implementors); | |||
BuildEntityInGroup | |||
(entityID, ExclusiveGroups.StandardEntity, entityDescriptor, implementors); | |||
} | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="entityID"></param> | |||
/// <param name="groupID"></param> | |||
/// <param name="ed"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors = null) | |||
where T : IEntityDescriptor, new() | |||
{ | |||
EntityFactory.BuildGroupedEntityViews(entityID, groupID, | |||
_groupedEntityViewsToAdd.current, | |||
_entityViewsToAdd.current, | |||
EntityDescriptorTemplate<T>.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<T>(int size) where T : IEntityDescriptor, new() | |||
///-------------------------------------------- | |||
void Preallocate<T>(int groupID, int size) where T : IEntityDescriptor, new() | |||
{ | |||
var entityViewsToBuild = ((EntityDescriptorInfo) EntityDescriptorTemplate<T>.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<Type, ITypeSafeList> @group; | |||
if (_groupEntityViewsDB.TryGetValue(groupID, out group) == false) | |||
group = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeList>(); | |||
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<Type, ITypeSafeList>(); | |||
//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<Type, ITypeSafeList> viewsDB, | |||
Dictionary<Type, ITypeSafeDictionary> 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<EntityInfoView>(entityID); | |||
var entityInfoView = _DB.QueryEntityViewInGroup<EntityInfoView>(entityID, groupID); | |||
RemoveEntity(ref entityInfoView, _entityViewsDB, _entityViewsDBDic); | |||
} | |||
void RemoveMetaEntity(int metaEntityID) | |||
{ | |||
var entityInfoView = _DB.QueryMetaEntityView<EntityInfoView>(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<Type, ITypeSafeList> entityViewsDB, | |||
Dictionary<Type, ITypeSafeDictionary> 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<Type, ITypeSafeList> entityViewsDB, | |||
Dictionary<Type, ITypeSafeDictionary> 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<Type, ITypeSafeList> entityViewsDB, | |||
Dictionary<Type, ITypeSafeDictionary> 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<EnginesRoot> _weakEngine; | |||
public GenericEntityFactory(DataStructures.WeakReference<EnginesRoot> weakReference) | |||
{ | |||
_weakEngine = weakReference; | |||
} | |||
public void BuildEntity<T>(int entityID, object[] implementors) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.BuildEntity<T>(entityID, implementors); | |||
} | |||
public void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptor, object[] implementors = null) | |||
{ | |||
_weakEngine.Target.BuildEntity(entityID, entityDescriptor, implementors); | |||
} | |||
public void BuildMetaEntity<T>(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.BuildMetaEntity<T>(metaEntityID, implementors); | |||
} | |||
public void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors) | |||
where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.BuildEntityInGroup<T>(entityID, groupID, implementors); | |||
} | |||
public void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor, | |||
object[] implementors) | |||
{ | |||
_weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors); | |||
} | |||
public void PreallocateEntitySlots<T>(int size) where T : IEntityDescriptor, new() | |||
{ | |||
_weakEngine.Target.Preallocate<T>(size); | |||
} | |||
} | |||
class GenericEntityFunctions : IEntityFunctions | |||
{ | |||
readonly DataStructures.WeakReference<EnginesRoot> _weakReference; | |||
public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> 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<Type, ITypeSafeList> _entityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBDic; | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeDictionary> _metaEntityViewsDBDic; | |||
//grouped set of entity views, this is the standard way to handle entity views | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB; | |||
//indexable entity views when the entity ID is known. Usually useful to handle | |||
//event based logic. | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupedEntityViewsDBDic; | |||
//Global pool of entity views when engines want to manage entityViews regardless | |||
//the group | |||
readonly Dictionary<Type, ITypeSafeList> _entityViewsDB; | |||
} | |||
} |
@@ -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<Type, ITypeSafeList> entityViewsToAdd, | |||
Dictionary<Type, ITypeSafeList> entityViewsDB, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic) | |||
void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> 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<Type, ITypeSafeList> 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<Type, ITypeSafeList>(); | |||
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<Type, ITypeSafeDictionary> groupDic; | |||
void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedEntityViewsToAdd, | |||
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB, | |||
Dictionary<Type, ITypeSafeList> entityViewsDB | |||
, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic) | |||
{ | |||
foreach (var group in groupedEntityViewsToAdd) | |||
{ | |||
AddEntityViewsToGroupDB(groupEntityViewsDB, @group); | |||
if (_groupedEntityViewsDBDic.TryGetValue(groupID, out groupDic) == false) | |||
groupDic = _groupedEntityViewsDBDic[groupID] = | |||
new Dictionary<Type, ITypeSafeDictionary>(); | |||
AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB, entityViewsDBDic); | |||
AddEntityViewToEntityViewsDictionary(groupDic, entityViewsPerType.Value, entityViewsPerType.Key); | |||
} | |||
} | |||
} | |||
} | |||
static void AddEntityViewsToGroupDB(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB, | |||
KeyValuePair<int, Dictionary<Type, ITypeSafeList>> @group) | |||
{ | |||
Dictionary<Type, ITypeSafeList> groupedEntityViewsByType; | |||
if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false) | |||
groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary<Type, ITypeSafeList>(); | |||
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<Type, ITypeSafeList> entityViewsDB, KeyValuePair<Type, ITypeSafeList> entityViewList) | |||
static void AddEntityViewToDB(Dictionary<Type, ITypeSafeList> entityViewsDB, | |||
KeyValuePair<Type, ITypeSafeList> entityViewList) | |||
{ | |||
ITypeSafeList dbList; | |||
@@ -119,7 +99,7 @@ namespace Svelto.ECS | |||
} | |||
static void AddEntityViewToEntityViewsDictionary(Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic, | |||
ITypeSafeList entityViews, Type entityViewType) | |||
ITypeSafeList entityViews, Type entityViewType) | |||
{ | |||
ITypeSafeDictionary entityViewsDic; | |||
@@ -156,12 +136,7 @@ namespace Svelto.ECS | |||
} | |||
} | |||
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd; | |||
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd; | |||
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd; | |||
readonly EntitySubmissionScheduler _scheduler; | |||
} | |||
} |
@@ -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<TType> 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<TType> : 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() | |||
{ | |||
} | |||
{ } | |||
} | |||
} | |||
} |
@@ -10,64 +10,32 @@ namespace Svelto.ECS.Internal | |||
{ | |||
internal static void BuildGroupedEntityViews(int entityID, int groupID, | |||
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType, | |||
Dictionary<Type, ITypeSafeList> entityViewsByType, | |||
IEntityDescriptorInfo eentityViewsToBuildDescriptor, | |||
object[] implementors) | |||
EntityDescriptorInfo entityViewsToBuildDescriptor, | |||
object[] implementors) | |||
{ | |||
var entityViewsToBuildDescriptor = | |||
eentityViewsToBuildDescriptor as EntityDescriptorInfo; | |||
Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped; | |||
Dictionary<Type, ITypeSafeList> group; | |||
if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false) | |||
if (groupEntityViewsByType.TryGetValue(groupID, out group) == false) | |||
{ | |||
groupedEntityViewsTyped = new Dictionary<Type, ITypeSafeList>(); | |||
groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped); | |||
group = new Dictionary<Type, ITypeSafeList>(); | |||
groupEntityViewsByType.Add(groupID, group); | |||
} | |||
InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors); | |||
InternalBuildEntityViews(entityID, group, entityViewsToBuildDescriptor, implementors); | |||
var removeEntityView = EntityView<EntityInfoView>.BuildEntityView(entityID); | |||
EntityInfoView removeEntityView = | |||
(EntityInfoView) BuildEntityView | |||
(entityID, group, EntityViewBuilder<EntityInfoView>.ENTITY_VIEW_TYPE, new EntityViewBuilder<EntityInfoView>()); | |||
removeEntityView.groupID = groupID; | |||
removeEntityView.isInAGroup = true; | |||
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; | |||
AddEntityInfoView(entityViewsByType, removeEntityView); | |||
} | |||
internal static void BuildEntityViews(int entityID, | |||
Dictionary<Type, ITypeSafeList> entityViewsByType, | |||
IEntityDescriptorInfo eentityViewsToBuildDescriptor, | |||
object[] implementors) | |||
{ | |||
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo; | |||
InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors); | |||
var removeEntityView = EntityView<EntityInfoView>.BuildEntityView(entityID); | |||
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild; | |||
AddEntityInfoView(entityViewsByType, removeEntityView); | |||
} | |||
static void AddEntityInfoView(Dictionary<Type, ITypeSafeList> entityViewsByType, | |||
EntityInfoView removeEntityView) | |||
static void InternalBuildEntityViews(int entityID, | |||
Dictionary<Type, ITypeSafeList> entityViewsByType, | |||
EntityDescriptorInfo entityViewsToBuildDescriptor, | |||
object[] implementors) | |||
{ | |||
ITypeSafeList list; | |||
if (entityViewsByType.TryGetValue(typeof(EntityInfoView), out list) == false) | |||
list = entityViewsByType[typeof(EntityInfoView)] = | |||
new TypeSafeFasterListForECSForClasses<EntityInfoView>(); | |||
(list as TypeSafeFasterListForECSForClasses<EntityInfoView>).Add(removeEntityView); | |||
} | |||
static void InternalBuildEntityViews(int entityID, | |||
Dictionary<Type, ITypeSafeList> 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<Type, Type[]> _cachedTypes = new Dictionary<Type, Type[]>(); | |||
const string DUPLICATE_IMPLEMENTOR_ERROR = | |||
"<color=orange>Svelto.ECS</color> the same component is implemented with more than one implementor. This is considered an error and MUST be fixed. "; | |||
@@ -1,9 +0,0 @@ | |||
namespace Svelto.ECS.Internal | |||
{ | |||
class EntityInfoView : EntityView | |||
{ | |||
internal IEntityViewBuilder[] entityViews; | |||
internal int groupID; | |||
internal bool isInAGroup; | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
namespace Svelto.ECS | |||
{ | |||
public class EntityInfoView : EntityView | |||
{ | |||
internal IEntityViewBuilder[] entityViews; | |||
public int groupID; | |||
} | |||
} |
@@ -13,7 +13,7 @@ namespace Svelto.ECS | |||
bool mustBeFilled { get; } | |||
} | |||
public class EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : EntityView, new() | |||
public struct EntityViewBuilder<EntityViewType> : 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<EntityViewType>(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<EntityViewType> : IEntityViewBuilder where EntityViewType : struct, IEntityStruct | |||
public struct EntityViewStructBuilder<EntityViewType> : 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<EntityViewType>(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); | |||
} | |||
} |
@@ -7,17 +7,11 @@ namespace Svelto.ECS.Internal | |||
class EntityViewsDB : IEntityViewsDB | |||
{ | |||
internal EntityViewsDB( Dictionary<Type, ITypeSafeList> entityViewsDB, | |||
Dictionary<Type, ITypeSafeList> metaEntityViewsDB, | |||
Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic, | |||
Dictionary<Type, ITypeSafeDictionary> metaEntityViewsDBdic, | |||
Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> entityViewsDBdic, | |||
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB) | |||
{ | |||
_entityViewsDB = entityViewsDB; | |||
_metaEntityViewsDB = metaEntityViewsDB; | |||
_entityViewsDBdic = entityViewsDBdic; | |||
_metaEntityViewsDBdic = metaEntityViewsDBdic; | |||
_groupedEntityViewsDBDic = entityViewsDBdic; | |||
_groupEntityViewsDB = groupEntityViewsDB; | |||
} | |||
@@ -77,60 +71,28 @@ namespace Svelto.ECS.Internal | |||
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entitiesInGroupPerType[type], out count); | |||
} | |||
public ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T:EntityView | |||
{ | |||
var type = typeof(T); | |||
ITypeSafeDictionary entityViews; | |||
if (_entityViewsDBdic.TryGetValue(type, out entityViews) == false) | |||
return TypeSafeDictionary<T>.Default; | |||
return new ReadOnlyDictionary<int, T>(entityViews as Dictionary<int, T>); | |||
} | |||
public ReadOnlyDictionary<int, T> QueryIndexableMetaEntityViews<T>() where T:EntityView | |||
{ | |||
var type = typeof(T); | |||
ITypeSafeDictionary entityViews; | |||
if (_metaEntityViewsDBdic.TryGetValue(type, out entityViews) == false) | |||
return TypeSafeDictionary<T>.Default; | |||
return new ReadOnlyDictionary<int, T>(entityViews as Dictionary<int, T>); | |||
} | |||
public T QueryEntityView<T>(int entityID) where T:EntityView | |||
{ | |||
return QueryEntityView<T>(entityID, _entityViewsDBdic); | |||
return QueryEntityViewInGroup<T>(entityID, ExclusiveGroups.StandardEntity); | |||
} | |||
public bool TryQueryEntityView<T>(int entityID, out T entityView) where T:EntityView | |||
{ | |||
return TryQueryEntityView(entityID, _entityViewsDBdic, out entityView); | |||
return TryQueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity, out entityView); | |||
} | |||
public T QueryMetaEntityView<T>(int metaEntityID) where T:EntityView | |||
public T QueryEntityViewInGroup<T>(int entityID, int groupID) where T:EntityView | |||
{ | |||
return QueryEntityView<T>(metaEntityID, _metaEntityViewsDBdic); | |||
} | |||
T entityView; | |||
TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); | |||
public bool TryQueryMetaEntityView<T>(int metaEntityID, out T entityView) where T:EntityView | |||
{ | |||
return TryQueryEntityView(metaEntityID, _metaEntityViewsDBdic, out entityView); | |||
return entityView; | |||
} | |||
public FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T:EntityView | |||
public bool TryQueryEntityViewInGroup<T>(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<T>(); | |||
return new FasterReadOnlyList<T>((FasterList<T>)entityViews); | |||
return TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView); | |||
} | |||
static FasterReadOnlyList<T> RetrieveEmptyEntityViewList<T>() | |||
@@ -143,7 +105,7 @@ namespace Svelto.ECS.Internal | |||
return FasterList<T>.DefaultList.ToArrayFast(); | |||
} | |||
static bool TryQueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic, out T entityView) where T : EntityView | |||
static bool TryQueryEntityView<T>(int ID, int groupID, Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> entityDic, out T entityView) where T : EntityView | |||
{ | |||
var type = typeof(T); | |||
@@ -152,7 +114,11 @@ namespace Svelto.ECS.Internal | |||
ITypeSafeDictionary entityViews; | |||
TypeSafeDictionary<T> casted; | |||
entityDic.TryGetValue(type, out entityViews); | |||
Dictionary<Type, ITypeSafeDictionary> @group; | |||
if (entityDic.TryGetValue(groupID, out group) == false) | |||
throw new Exception("Group not found"); | |||
group.TryGetValue(type, out entityViews); | |||
casted = entityViews as TypeSafeDictionary<T>; | |||
if (casted != null && | |||
@@ -163,34 +129,14 @@ namespace Svelto.ECS.Internal | |||
return true; | |||
} | |||
entityView = default(T); | |||
entityView = null; | |||
return false; | |||
} | |||
static T QueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic) where T : EntityView | |||
{ | |||
var type = typeof(T); | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB; | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupedEntityViewsDBDic; | |||
T internalEntityView; ITypeSafeDictionary entityViews; | |||
TypeSafeDictionary<T> casted; | |||
entityDic.TryGetValue(type, out entityViews); | |||
casted = entityViews as TypeSafeDictionary<T>; | |||
if (casted != null && | |||
casted.TryGetValue(ID, out internalEntityView)) | |||
return (T)internalEntityView; | |||
throw new Exception("EntityView Not Found"); | |||
} | |||
readonly Dictionary<Type, ITypeSafeList> _entityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic; | |||
readonly Dictionary<Type, ITypeSafeDictionary> _metaEntityViewsDBdic; | |||
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB; | |||
readonly Dictionary<Type, ITypeSafeList> _entityViewsDB; | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
namespace Svelto.ECS.Internal | |||
{ | |||
static class ExclusiveGroups | |||
{ | |||
internal const int StandardEntity = unchecked((int) 0xFFFFFFFF); | |||
} | |||
} |
@@ -1,26 +0,0 @@ | |||
namespace Svelto.ECS | |||
{ | |||
public interface IEntityFactory | |||
{ | |||
void PreallocateEntitySlots<T>(int size) where T : IEntityDescriptor, new(); | |||
void BuildEntity<T>(int entityID, object[] implementors) where T:IEntityDescriptor, new(); | |||
void BuildEntity(int entityID, IEntityDescriptorInfo entityDescriptorInfo, object[] implementors); | |||
void BuildMetaEntity<T>(int metaEntityID, object[] implementors) where T:IEntityDescriptor, new(); | |||
void BuildEntityInGroup<T>(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); | |||
} | |||
} |
@@ -2,6 +2,6 @@ namespace Svelto.ECS | |||
{ | |||
public interface IEntityDescriptorHolder | |||
{ | |||
IEntityDescriptorInfo RetrieveDescriptor(); | |||
EntityDescriptorInfo RetrieveDescriptor(); | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
namespace Svelto.ECS | |||
{ | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
public interface IEntityFactory | |||
{ | |||
/// <summary> | |||
///where performance is critical, you may wish to pre allocate the space needed | |||
///to store the entities | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="size"></param> | |||
void PreallocateEntitySpace<T>(int size) where T : IEntityDescriptor, new(); | |||
void PreallocateEntitySpaceInGroup<T>(int groupID, int size) where T : IEntityDescriptor, new(); | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="entityID"></param> | |||
/// <param name="groupID"></param> | |||
/// <param name="ed"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors) where T:IEntityDescriptor, new(); | |||
void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors); | |||
/// <summary> | |||
/// 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 | |||
/// </summary> | |||
/// <typeparam name="T"></typeparam> | |||
/// <param name="entityID"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntity<T>(int entityID, object[] implementors) where T:IEntityDescriptor, new(); | |||
/// <summary> | |||
/// 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. | |||
/// </summary> | |||
/// <param name="entityID"></param> | |||
/// <param name="entityDescriptor"></param> | |||
/// <param name="implementors"></param> | |||
void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptorInfo, object[] implementors); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -5,19 +5,15 @@ namespace Svelto.ECS | |||
public interface IEntityViewsDB | |||
{ | |||
FasterReadOnlyList<T> QueryEntityViews<T>() where T : EntityView; | |||
FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T : EntityView; | |||
FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int group) where T : EntityView; | |||
T[] QueryEntityViewsAsArray<T>(out int count) where T : IEntityView; | |||
T[] QueryGroupedEntityViewsAsArray<T>(int group, out int count) where T : IEntityView; | |||
ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T : EntityView; | |||
ReadOnlyDictionary<int, T> QueryIndexableMetaEntityViews<T>() where T : EntityView; | |||
bool TryQueryEntityView<T>(int ID, out T entityView) where T : EntityView; | |||
T QueryEntityView<T>(int ID) where T : EntityView; | |||
bool TryQueryMetaEntityView<T>(int metaEntityID, out T entityView) where T : EntityView; | |||
T QueryMetaEntityView<T>(int metaEntityID) where T : EntityView; | |||
bool TryQueryEntityViewInGroup<T>(int entityID, int groupID, out T entityView) where T : EntityView; | |||
T QueryEntityViewInGroup<T>(int entityID, int groupID) where T : EntityView; | |||
} | |||
} |