Browse Source

Merge pull request #24 from sebas77/database_refactoring

Database and ID refactoring
tags/Rel2
Sebastiano Mandalà GitHub 6 years ago
parent
commit
ced337e144
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 640 additions and 820 deletions
  1. +33
    -0
      EnginesRoot.DoubleBufferedEntityViews.cs
  2. +53
    -0
      EnginesRoot.GenericEntityFactory.cs
  3. +51
    -0
      EnginesRoot.GenericEntityFunctions.cs
  4. +8
    -8
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  5. +1
    -1
      Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs
  6. +39
    -24
      Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs
  7. +10
    -0
      Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs
  8. +49
    -0
      Svelto.ECS/EGID.cs
  9. +5
    -30
      Svelto.ECS/EnginesRootEngines.cs
  10. +145
    -265
      Svelto.ECS/EnginesRootEntities.cs
  11. +48
    -74
      Svelto.ECS/EnginesRootSubmission.cs
  12. +11
    -20
      Svelto.ECS/EntityDescriptor.cs
  13. +28
    -51
      Svelto.ECS/EntityFactory.cs
  14. +0
    -9
      Svelto.ECS/EntityInfoImplementor.cs
  15. +7
    -5
      Svelto.ECS/EntityView.cs
  16. +36
    -17
      Svelto.ECS/EntityViewBuilder.cs
  17. +32
    -95
      Svelto.ECS/EntityViewsDB.cs
  18. +7
    -0
      Svelto.ECS/ExclusiveGroups.cs
  19. +0
    -183
      Svelto.ECS/Experimental/StructNodeCollections.cs
  20. +1
    -1
      Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs
  21. +0
    -26
      Svelto.ECS/IEnginesInterfaces.cs
  22. +1
    -1
      Svelto.ECS/IEntityDescriptorHolder.cs
  23. +55
    -0
      Svelto.ECS/IEntityFactory.cs
  24. +17
    -0
      Svelto.ECS/IEntityFunctions.cs
  25. +3
    -10
      Svelto.ECS/IEntityViewsDB.cs

+ 33
- 0
EnginesRoot.DoubleBufferedEntityViews.cs View File

@@ -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;
}
}
}
}

+ 53
- 0
EnginesRoot.GenericEntityFactory.cs View File

@@ -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);
}
}
}
}

+ 51
- 0
EnginesRoot.GenericEntityFunctions.cs View File

@@ -0,0 +1,51 @@
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 RemoveEntity(EGID entityEGID)
{
_weakReference.Target.RemoveEntity(entityEGID);
}

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);
}
}
}
}

+ 8
- 8
Svelto.ECS/DataStructures/TypeSafeDictionary.cs View File

@@ -14,11 +14,11 @@ 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);
}

class TypeSafeDictionary<TValue> : Dictionary<int, TValue>, ITypeSafeDictionary where TValue : IEntityView
class TypeSafeDictionaryForClass<TValue> : Dictionary<int, TValue>, ITypeSafeDictionary where TValue : EntityView
{
internal static readonly ReadOnlyDictionary<int, TValue> Default =
new ReadOnlyDictionary<int, TValue>(new Dictionary<int, TValue>());
@@ -34,7 +34,7 @@ namespace Svelto.ECS.Internal
{
var entityView = buffer[i];

Add(entityView.ID, entityView);
Add(entityView._ID.GID, entityView);
}
}
catch (Exception e)
@@ -43,16 +43,16 @@ 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];
}
}
}

+ 1
- 1
Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs View File

@@ -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)
{
}
}

+ 39
- 24
Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs View File

@@ -12,10 +12,10 @@ 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 ReserveCapacity(int capacity);
void AddCapacity(int capacity);
}

class TypeSafeFasterListForECS<T> : FasterList<T> where T : IEntityView
@@ -32,17 +32,19 @@ namespace Svelto.ECS.Internal
_mappedIndices = new Dictionary<int, int>();
}

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;
{
_mappedIndices[this[index].ID.GID] = index;
}

return Count > 0;
}
@@ -53,8 +55,18 @@ namespace Svelto.ECS.Internal

base.AddRange(entityViewListValue as FasterList<T>);


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,18 +75,25 @@ 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 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)
public int GetIndexFromID(EGID entityID)
{
return _mappedIndices[entityID];
return _mappedIndices[entityID.GID];
}
}

@@ -82,12 +101,10 @@ namespace Svelto.ECS.Internal
where T : struct, IEntityStruct
{
public TypeSafeFasterListForECSForStructs(int size) : base(size)
{
}
{}

public TypeSafeFasterListForECSForStructs()
{
}
{}

public ITypeSafeList Create()
{
@@ -101,7 +118,7 @@ namespace Svelto.ECS.Internal

public ITypeSafeDictionary CreateIndexedDictionary()
{
throw new Exception("Not Allowed");
throw new NotSupportedException();
}

public IEntityView[] ToArrayFast(out int count)
@@ -118,12 +135,10 @@ namespace Svelto.ECS.Internal
class TypeSafeFasterListForECSForClasses<T> : TypeSafeFasterListForECS<T>, ITypeSafeList where T : EntityView, new()
{
public TypeSafeFasterListForECSForClasses(int size) : base(size)
{
}
{}

public TypeSafeFasterListForECSForClasses()
{
}
{}

public ITypeSafeList Create()
{
@@ -137,7 +152,7 @@ namespace Svelto.ECS.Internal

public ITypeSafeDictionary CreateIndexedDictionary()
{
return new TypeSafeDictionary<T>();
return new TypeSafeDictionaryForClass<T>();
}

public IEntityView[] ToArrayFast(out int count)


+ 10
- 0
Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs View File

@@ -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)
{}
}
}

+ 49
- 0
Svelto.ECS/EGID.cs View File

@@ -0,0 +1,49 @@
using DBC;
using Svelto.ECS.Internal;

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);
}
public EGID(int entityID) : this()
{
_GID = MAKE_GLOBAL_ID(entityID, ExclusiveGroups.StandardEntity);
}

int MAKE_GLOBAL_ID(int entityId, int groupId)
{
#if DEBUG && !PROFILER
Check.Require(entityId <= 0xFFFFFF);
Check.Require(groupId <= 0xFF);
#endif
return entityId | groupId << 24;
}

public bool IsEqualTo(EGID otherGID)
{
return otherGID._GID == _GID;
}
}
}

+ 5
- 30
Svelto.ECS/EnginesRootEngines.cs View File

@@ -1,5 +1,4 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;
@@ -38,17 +37,15 @@ namespace Svelto.ECS
_entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
_otherEngines = new FasterList<IEngine>();

_entityViewsDB = new Dictionary<Type, ITypeSafeList>();
_metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_globalEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_entityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_metaEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_globalEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_entityInfos = new Dictionary<int, IEntityViewBuilder[]>();
_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(_globalEntityViewsDB, _globalEntityViewsDBDic, _groupEntityViewsDB);

_scheduler = entityViewScheduler;
_scheduler.Schedule(new WeakAction(SubmitEntityViews));
@@ -125,27 +122,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;
}
}
}
}

+ 145
- 265
Svelto.ECS/EnginesRootEntities.cs View File

@@ -14,24 +14,14 @@ 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);

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,97 +32,60 @@ 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);
BuildEntityInGroup<T>
(entityID, ExclusiveGroups.StandardEntity, 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(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors)
{
EntityFactory.BuildEntityViews
(entityID, _entityViewsToAdd.current, entityDescriptor, implementors);
BuildEntityInGroup
(entityID, ExclusiveGroups.StandardEntity, entityDescriptor, 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()
{
EntityFactory.BuildEntityViews(metaEntityID, _metaEntityViewsToAdd.current,
EntityDescriptorTemplate<T>.Default, 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,
_entityInfos,
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);
entityDescriptor,
_entityInfos,
implementors);
}

void Preallocate<T>(int size) where T : IEntityDescriptor, new()
///--------------------------------------------

/// <summary>
/// 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
/// </summary>
void Preallocate<T>(int groupID, int size) where T : IEntityDescriptor, new()
{
var entityViewsToBuild = ((EntityDescriptorInfo) EntityDescriptorTemplate<T>.Default).entityViewsToBuild;
var entityViewsToBuild = EntityDescriptorTemplate<T>.Default.entityViewsToBuild;
var count = entityViewsToBuild.Length;

for (var index = 0; index < count; index++)
@@ -140,166 +93,119 @@ 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);
if (_globalEntityViewsDB.TryGetValue(entityViewType, out dbList) == false)
_globalEntityViewsDB[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.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.ReserveCapacity(size);
dbList.AddCapacity(size);
}
}

void RemoveEntity(ref EntityInfoView entityInfoView, Dictionary<Type, ITypeSafeList> viewsDB,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
///--------------------------------------------
///
void RemoveEntity(int entityID, int groupID)
{
if (entityInfoView.isInAGroup)
InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID,
entityInfoView.groupID, viewsDB, entityViewsDBDic);
else
InternalRemoveFromDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, viewsDB,
entityViewsDBDic);
RemoveEntity(new EGID(entityID, groupID));
}

void RemoveEntity(int entityID)
void RemoveEntity(EGID entityGID)
{
var entityInfoView = _DB.QueryEntityView<EntityInfoView>(entityID);

RemoveEntity(ref entityInfoView, _entityViewsDB, _entityViewsDBDic);
}

void RemoveMetaEntity(int metaEntityID)
{
var entityInfoView = _DB.QueryMetaEntityView<EntityInfoView>(metaEntityID);

RemoveEntity(ref entityInfoView, _metaEntityViewsDB, _metaEntityViewsDBDic);
}

void RemoveGroupAndEntitiesFromDB(int groupID)
{
foreach (var group in _groupEntityViewsDB[groupID])
var entityViewBuilders = _entityInfos[entityGID.GID];
var entityViewBuildersCount = entityViewBuilders.Length;
//for each entity view generated by the entity descriptor
for (var i = 0; i < entityViewBuildersCount; i++)
{
var entityViewType = group.Key;

int count;
var entities = group.Value.ToArrayFast(out count);
var entityViewType = entityViewBuilders[i].GetEntityViewType();

for (var i = 0; i < count; i++)
if (entityViewBuilders[i].isQueryiableEntityView)
{
var entityID = entities[i].ID;

InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, _entityViewsDBDic, entityViewType,
entityID);
var group = _groupEntityViewsDB[entityGID.group];
InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityGID);
RemoveEntityViewFromDB(@group, entityViewType, entityGID);
}

RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityGID);
}

_groupEntityViewsDB.Remove(groupID);
_entityInfos.Remove(entityGID.GID);
}

void InternalRemoveEntityViewFromDBAndEngines(Dictionary<Type, ITypeSafeList> entityViewsDB,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic,
Type entityViewType,
int entityID)
static void RemoveEntityViewFromDB(Dictionary<Type, ITypeSafeList> @group, Type entityViewType, EGID id)
{
var entityViews = entityViewsDB[entityViewType];
if (entityViews.MappedRemove(entityID) == false)
entityViewsDB.Remove(entityViewType);

if (entityViews.isQueryiableEntityView)
{
var typeSafeDictionary = entityViewsDBDic[entityViewType];
var entityView = typeSafeDictionary.GetIndexedEntityView(entityID);

if (typeSafeDictionary.Remove(entityID) == false)
entityViewsDBDic.Remove(entityViewType);

for (var current = entityViewType; current != _entityViewType; current = current.BaseType)
RemoveEntityViewFromEngines(_entityViewEngines, entityView, current);
}
//remove it from entity views group DB
var typeSafeList = @group[entityViewType];
if (typeSafeList.MappedRemove(id) == false) //clean up
@group.Remove(entityViewType);
}

void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID)
void RemoveGroupAndEntitiesFromDB(int groupID)
{
Check.Require(fromGroupID != toGroupID,
"can't move an entity to the same group where it already belongs to");

var entityViewBuilders = _DB.QueryEntityView<EntityInfoView>(entityID).entityViews;
var entityViewBuildersCount = entityViewBuilders.Length;

var groupedEntities = _groupEntityViewsDB[fromGroupID];

Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped;
if (_groupEntityViewsDB.TryGetValue(toGroupID, out groupedEntityViewsTyped) == false)
{
groupedEntityViewsTyped = new Dictionary<Type, ITypeSafeList>();

_groupEntityViewsDB.Add(toGroupID, groupedEntityViewsTyped);
}

for (var i = 0; i < entityViewBuildersCount; i++)
foreach (var group in _groupEntityViewsDB[groupID])
{
var entityViewBuilder = entityViewBuilders[i];
var entityViewType = entityViewBuilder.GetEntityViewType();

var fromSafeList = groupedEntities[entityViewType];
ITypeSafeList toSafeList;

if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false)
groupedEntityViewsTyped[entityViewType] = toSafeList = fromSafeList.Create();
{
var entityViewType = group.Key;

entityViewBuilder.MoveEntityView(entityID, fromSafeList, toSafeList);
int count;
var entities = group.Value.ToArrayFast(out count);

fromSafeList.MappedRemove(entityID);
}
for (var i = 0; i < count; i++)
{
var entityID = entities[i].ID;

var entityInfoView = _DB.QueryEntityView<EntityInfoView>(entityID);
entityInfoView.groupID = toGroupID;
}
RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityID);

void InternalRemoveFromDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID,
Dictionary<Type, ITypeSafeList> entityViewsDB,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
{
var entityViewBuildersCount = entityViewBuilders.Length;

for (var i = 0; i < entityViewBuildersCount; i++)
{
var entityViewType = entityViewBuilders[i].GetEntityViewType();

InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewsDBDic, entityViewType, entityID);
if (group.Value.isQueryiableEntityView)
InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID);
}
}
}
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);
_groupEntityViewsDB.Remove(groupID);
}

void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID)
void InternalRemoveEntityViewFromDBDicAndEngines(Type entityViewType, EGID id)
{
var entityViewBuildersCount = entityViewBuilders.Length;

var dictionary = _groupEntityViewsDB[groupID];

for (var i = 0; i < entityViewBuildersCount; i++)
var typeSafeDictionary = _globalEntityViewsDBDic[entityViewType];
{
var entityViewType = entityViewBuilders[i].GetEntityViewType();
var entityView = typeSafeDictionary.GetIndexedEntityView(id);

var typeSafeList = dictionary[entityViewType];
typeSafeList.MappedRemove(entityID);
//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<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines,
IEntityView entityView,
Type entityViewType)
@@ -321,87 +227,61 @@ namespace Svelto.ECS
}
}
}
///--------------------------------------------

class GenericEntityFactory : IEntityFactory
void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID)
{
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);
}
Check.Require(fromGroupID != toGroupID,
"can't move an entity to the same group where it already belongs to");

public void BuildMetaEntity<T>(int metaEntityID, object[] implementors) where T : IEntityDescriptor, new()
{
_weakEngine.Target.BuildMetaEntity<T>(metaEntityID, implementors);
}
var entityegid = new EGID(entityID, fromGroupID);
var entityViewBuilders = _entityInfos[entityegid.GID];
var entityViewBuildersCount = entityViewBuilders.Length;

public void BuildEntityInGroup<T>(int entityID, int groupID, object[] implementors)
where T : IEntityDescriptor, new()
{
_weakEngine.Target.BuildEntityInGroup<T>(entityID, groupID, implementors);
}
var groupedEntities = _groupEntityViewsDB[fromGroupID];

public void BuildEntityInGroup(int entityID, int groupID, IEntityDescriptorInfo entityDescriptor,
object[] implementors)
Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped;
if (_groupEntityViewsDB.TryGetValue(toGroupID, out groupedEntityViewsTyped) == false)
{
_weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors);
}
groupedEntityViewsTyped = new Dictionary<Type, ITypeSafeList>();

public void PreallocateEntitySlots<T>(int size) where T : IEntityDescriptor, new()
{
_weakEngine.Target.Preallocate<T>(size);
_groupEntityViewsDB.Add(toGroupID, groupedEntityViewsTyped);
}
}

class GenericEntityFunctions : IEntityFunctions
{
readonly DataStructures.WeakReference<EnginesRoot> _weakReference;

public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
for (var i = 0; i < entityViewBuildersCount; i++)
{
_weakReference = weakReference;
}
var entityViewBuilder = entityViewBuilders[i];
var entityViewType = entityViewBuilder.GetEntityViewType();

public void RemoveEntity(int entityID)
{
_weakReference.Target.RemoveEntity(entityID);
}
var fromSafeList = groupedEntities[entityViewType];
ITypeSafeList toSafeList;

public void RemoveMetaEntity(int metaEntityID)
{
_weakReference.Target.RemoveEntity(metaEntityID);
}
if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false)
groupedEntityViewsTyped[entityViewType] = toSafeList = fromSafeList.Create();

public void RemoveGroupAndEntities(int groupID)
{
_weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID);
entityViewBuilder.MoveEntityView(entityegid, fromSafeList, toSafeList);
fromSafeList.MappedRemove(entityegid);
}

public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID)
{
_weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID);
}
_entityInfos.Remove(entityegid.GID);
_entityInfos.Add(new EGID(entityID, toGroupID).GID, entityViewBuilders);
}

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;
//TODO: Use faster dictionary and merge these two?
//Global pool of entity views when engines want to manage entityViews regardless
//the group
readonly Dictionary<Type, ITypeSafeList> _globalEntityViewsDB;
//indexable entity views when the entity ID is known. Usually useful to handle
//event based logic.
readonly Dictionary<Type, ITypeSafeDictionary> _globalEntityViewsDBDic;
Dictionary<int, IEntityViewBuilder[]> _entityInfos;
}
}

+ 48
- 74
Svelto.ECS/EnginesRootSubmission.cs View File

@@ -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");
@@ -55,78 +39,73 @@ namespace Svelto.ECS
numberOfReenteringLoops++;
}
}

void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> entityViewsToAdd,
Dictionary<Type, ITypeSafeList> entityViewsDB, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
//todo: can I make the entity creation less complicated?
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)
//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 entityViewsPerType in groupToSubmit.Value)
{
AddEntityViewToEntityViewsDictionary(entityViewsDBDic, entityViewList.Value, entityViewList.Key);
//add the entity View in the group
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
AddEntityViewToEntityViewsDictionary(_globalEntityViewsDBDic, entityViewsPerType.Value, entityViewsPerType.Key);
}
}

foreach (var entityViewList in entityViewsToAdd)
//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)
{
if (entityViewList.Value.isQueryiableEntityView)
foreach (var entityViewList in group.Value)
{
var type = entityViewList.Key;
for (var current = type; current != _entityViewType; current = current.BaseType)
AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value,
current);
if (entityViewList.Value.isQueryiableEntityView)
{
var type = entityViewList.Key;
for (var current = type; current != _entityViewType; current = current.BaseType)
AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value, current);
}
}
}
}

void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedEntityViewsToAdd,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
Dictionary<Type, ITypeSafeList> entityViewsDB
, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
static void AddEntityViewToDB( Dictionary<Type, ITypeSafeList> entityViewsDB,
KeyValuePair<Type, ITypeSafeList> entityViewList)
{
foreach (var group in groupedEntityViewsToAdd)
{
AddEntityViewsToGroupDB(groupEntityViewsDB, @group);
ITypeSafeList dbList;

AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB, entityViewsDBDic);
}
}

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>();
if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false)
dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create();

foreach (var entityView in @group.Value)
{
groupedEntityViewsByType.Add(entityView.Key, entityView.Value);
dbList.AddRange(entityViewList.Value);
}
}

static void AddEntityViewToDB(Dictionary<Type, ITypeSafeList> entityViewsDB, KeyValuePair<Type, ITypeSafeList> entityViewList)
{
ITypeSafeList dbList;

if (entityViewsDB.TryGetValue(entityViewList.Key, out dbList) == false)
dbList = entityViewsDB[entityViewList.Key] = entityViewList.Value.Create();

dbList.AddRange(entityViewList.Value);
}

static void AddEntityViewToEntityViewsDictionary(Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic,
ITypeSafeList entityViews, Type entityViewType)
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<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines, ITypeSafeList entityViewsList, Type entityViewType)
@@ -156,12 +135,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;

}
}

+ 11
- 20
Svelto.ECS/EntityDescriptor.cs View File

@@ -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()
@@ -36,34 +31,30 @@ 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<TType>.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<TType>.Default.name;
}
}
}

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()
{
}
{ }
}
}
}

+ 28
- 51
Svelto.ECS/EntityFactory.cs View File

@@ -10,64 +10,41 @@ 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,
Dictionary<int, IEntityViewBuilder[]> entityInfos,
object[] implementors)
{
var entityViewsToBuildDescriptor =
eentityViewsToBuildDescriptor as EntityDescriptorInfo;
Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped;
var @group = FetchGroup(groupID, groupEntityViewsByType);

if (groupEntityViewsByType.TryGetValue(groupID, out groupedEntityViewsTyped) == false)
{
groupedEntityViewsTyped = new Dictionary<Type, ITypeSafeList>();
groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped);
}

InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors);
BuildEntityViewsAndAddToGroup(new EGID(entityID, groupID), group, entityViewsToBuildDescriptor, implementors);

var removeEntityView = EntityView<EntityInfoView>.BuildEntityView(entityID);

removeEntityView.groupID = groupID;
removeEntityView.isInAGroup = true;
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild;

AddEntityInfoView(entityViewsByType, removeEntityView);
AddEntityInfoView(new EGID(entityID, groupID), entityViewsToBuildDescriptor, entityInfos);
}

internal static void BuildEntityViews(int entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
IEntityDescriptorInfo eentityViewsToBuildDescriptor,
object[] implementors)
static void AddEntityInfoView(EGID entityID, EntityDescriptorInfo entityViewsToBuildDescriptor,
Dictionary<int, IEntityViewBuilder[]> entityInfos)
{
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo;

InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors);

var removeEntityView = EntityView<EntityInfoView>.BuildEntityView(entityID);
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild;

AddEntityInfoView(entityViewsByType, removeEntityView);
entityInfos.Add(entityID.GID, entityViewsToBuildDescriptor.entityViewsToBuild);
}

static void AddEntityInfoView(Dictionary<Type, ITypeSafeList> entityViewsByType,
EntityInfoView removeEntityView)
static Dictionary<Type, ITypeSafeList> FetchGroup(int groupID, Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType)
{
ITypeSafeList list;
Dictionary<Type, ITypeSafeList> group;

if (entityViewsByType.TryGetValue(typeof(EntityInfoView), out list) == false)
list = entityViewsByType[typeof(EntityInfoView)] =
new TypeSafeFasterListForECSForClasses<EntityInfoView>();
if (groupEntityViewsByType.TryGetValue(groupID, out @group) == false)
{
@group = new Dictionary<Type, ITypeSafeList>();
groupEntityViewsByType.Add(groupID, @group);
}

(list as TypeSafeFasterListForECSForClasses<EntityInfoView>).Add(removeEntityView);
return @group;
}

static void InternalBuildEntityViews(int entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
IEntityDescriptorInfo eentityViewsToBuildDescriptor,
object[] implementors)
static void BuildEntityViewsAndAddToGroup(EGID entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo;
var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild;
var count = entityViewsToBuild.Length;

@@ -86,8 +63,8 @@ namespace Svelto.ECS.Internal
}
}

static IEntityView BuildEntityView(int entityID, Dictionary<Type, ITypeSafeList> entityViewsByType,
Type entityViewType, IEntityViewBuilder entityViewBuilder)
static IEntityView BuildEntityView(EGID entityID, Dictionary<Type, ITypeSafeList> entityViewsByType,
Type entityViewType, IEntityViewBuilder entityViewBuilder)
{
ITypeSafeList entityViewsList;

@@ -158,7 +135,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
}
@@ -185,9 +162,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 +191,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. ";



+ 0
- 9
Svelto.ECS/EntityInfoImplementor.cs View File

@@ -1,9 +0,0 @@
namespace Svelto.ECS.Internal
{
class EntityInfoView : EntityView
{
internal IEntityViewBuilder[] entityViews;
internal int groupID;
internal bool isInAGroup;
}
}

+ 7
- 5
Svelto.ECS/EntityView.cs View File

@@ -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<KeyValuePair<Type, CastedAction<EntityView>>> entityViewBlazingFastReflection;
internal int _ID;
internal EGID _ID;
}

static class EntityView<T> where T: EntityView, new()
{
internal static T BuildEntityView(int ID)
internal static T BuildEntityView(EGID ID)
{
if (FieldCache<T>.list.Count == 0)
{


+ 36
- 17
Svelto.ECS/EntityViewBuilder.cs View File

@@ -5,17 +5,18 @@ 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; }
bool isQueryiableEntityView { get; }
}

public class EntityViewBuilder<EntityViewType> : 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<EntityViewType>();
@@ -34,17 +35,17 @@ 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)
public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
@@ -56,23 +57,35 @@ namespace Svelto.ECS
{
get { return true; }
}
public bool isQueryiableEntityView
{
get { return true; }
}

readonly Type _entityViewType = typeof(EntityViewType);
public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType);
}

public class EntityViewStructBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : struct, IEntityStruct
{
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView)
public EntityViewStructBuilder()
{}
public EntityViewStructBuilder(ref EntityViewType initializer)
{
var structEntityView = default(EntityViewType);
structEntityView.ID = entityID;
_initializer = initializer;
}
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView)
{
_initializer.ID = entityID;
if (list == null)
list = new TypeSafeFasterListForECSForStructs<EntityViewType>();

var castedList = list as TypeSafeFasterListForECSForStructs<EntityViewType>;
castedList.Add(structEntityView);
castedList.Add(_initializer);

entityView = null;
}
@@ -82,17 +95,17 @@ 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)
public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;
@@ -105,6 +118,12 @@ namespace Svelto.ECS
get { return false; }
}

readonly Type _entityViewType = typeof(EntityViewType);
}
public bool isQueryiableEntityView
{
get { return false; }
}

public static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType);
EntityViewType _initializer;
}
}

+ 32
- 95
Svelto.ECS/EntityViewsDB.cs View File

@@ -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, ITypeSafeList>> groupEntityViewsDB)
{
_entityViewsDB = entityViewsDB;
_metaEntityViewsDB = metaEntityViewsDB;
_entityViewsDBdic = entityViewsDBdic;
_metaEntityViewsDBdic = metaEntityViewsDBdic;
_globalEntityViewsDB = entityViewsDB;
_groupedEntityViewsDBDic = entityViewsDBdic;
_groupEntityViewsDB = groupEntityViewsDB;
}

@@ -27,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<T>();

return new FasterReadOnlyList<T>((FasterList<T>)entityViews);
@@ -54,13 +48,13 @@ namespace Svelto.ECS.Internal
ITypeSafeList entityViews;

if (_entityViewsDB.TryGetValue(type, out entityViews) == false)
if (_globalEntityViewsDB.TryGetValue(type, out entityViews) == false)
return RetrieveEmptyEntityViewArray<T>();
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entityViews, out count);
}
public T[] QueryGroupedEntityViewsAsArray<T>(int @group, out int count) where T : IEntityView
public T[] QueryGroupedEntityViewsAsArray<T>(int @group, out int count) where T : EntityView
{
var type = typeof(T);
count = 0;
@@ -77,120 +71,63 @@ 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);
}

public bool TryQueryEntityView<T>(int entityID, out T entityView) where T:EntityView
{
return TryQueryEntityView(entityID, _entityViewsDBdic, out entityView);
}

public T QueryMetaEntityView<T>(int metaEntityID) where T:EntityView
{
return QueryEntityView<T>(metaEntityID, _metaEntityViewsDBdic);
}

public bool TryQueryMetaEntityView<T>(int metaEntityID, out T entityView) where T:EntityView
{
return TryQueryEntityView(metaEntityID, _metaEntityViewsDBdic, out entityView);
}

public FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T:EntityView
public T QueryEntityView<T>(EGID entityGID) where T : EntityView
{
var type = typeof(T);
T entityView;

ITypeSafeList entityViews;
TryQueryEntityViewInGroup(entityGID, out entityView);

if (_metaEntityViewsDB.TryGetValue(type, out entityViews) == false)
return RetrieveEmptyEntityViewList<T>();

return new FasterReadOnlyList<T>((FasterList<T>)entityViews);
return entityView;
}

static FasterReadOnlyList<T> RetrieveEmptyEntityViewList<T>()
public bool TryQueryEntityView<T>(EGID entityegid, out T entityView) where T : EntityView
{
return FasterReadOnlyList<T>.DefaultList;
return TryQueryEntityViewInGroup(entityegid, out entityView);
}

static T[] RetrieveEmptyEntityViewArray<T>()
{
return FasterList<T>.DefaultList.ToArrayFast();
}
static bool TryQueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic, out T entityView) where T : EntityView
bool TryQueryEntityViewInGroup<T>(EGID entityGID, out T entityView) where T:EntityView
{
var type = typeof(T);

T internalEntityView;

ITypeSafeDictionary entityViews;
TypeSafeDictionary<T> casted;
ITypeSafeDictionary entityViews;
TypeSafeDictionaryForClass<T> casted;

entityDic.TryGetValue(type, out entityViews);
casted = entityViews as TypeSafeDictionary<T>;
_groupedEntityViewsDBDic.TryGetValue(type, out entityViews);
casted = entityViews as TypeSafeDictionaryForClass<T>;

if (casted != null &&
casted.TryGetValue(ID, out internalEntityView))
casted.TryGetValue(entityGID.GID, out internalEntityView))
{
entityView = internalEntityView;

return true;
}

entityView = default(T);
entityView = null;

return false;
}

static T QueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic) where T : EntityView
static FasterReadOnlyList<T> RetrieveEmptyEntityViewList<T>()
{
var type = typeof(T);

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");
return FasterReadOnlyList<T>.DefaultList;
}

readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
readonly Dictionary<Type, ITypeSafeDictionary> _metaEntityViewsDBdic;
static T[] RetrieveEmptyEntityViewArray<T>()
{
return FasterList<T>.DefaultList.ToArrayFast();
}
//grouped set of entity views, this is the standard way to handle entity views
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
//Global pool of entity views when engines want to manage entityViews regardless
//the group
readonly Dictionary<Type, ITypeSafeList> _globalEntityViewsDB;
//indexable entity views when the entity ID is known. Usually useful to handle
//event based logic.
readonly Dictionary<Type, ITypeSafeDictionary> _groupedEntityViewsDBDic;
}
}

+ 7
- 0
Svelto.ECS/ExclusiveGroups.cs View File

@@ -0,0 +1,7 @@
namespace Svelto.ECS.Internal
{
static class ExclusiveGroups
{
internal const int StandardEntity = 0xFF;
}
}

+ 0
- 183
Svelto.ECS/Experimental/StructNodeCollections.cs View File

@@ -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; }
}
/// <summary>
/// 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
/// </summary>
public interface IStructEntityViewEngine<T> : IStructEntityViewEngine where T:struct, IEntityStruct
{ }

/// <summary>
/// same as above, but the entityViews are grouped by ID
/// usually the ID is the owner of the entityViews of that
/// group
/// </summary>
public interface IGroupedStructEntityViewsEngine<T> : IGroupedStructEntityViewsEngine where T : struct, IGroupedEntityView
{
void Add(ref T entityView);
void Remove(ref T entityView);
}
public sealed class StructEntityViews<T> where T:struct, IEntityStruct
{
public T[] GetList(out int numberOfItems)
{
numberOfItems = _internalList.Count;
return _internalList.ToArrayFast();
}

public StructEntityViews(SharedStructEntityViewLists container)
{
_internalList = SharedStructEntityViewLists.NoVirt.GetList<T>(container);
}

public void Add(T entityView)
{
T convert = (T)entityView;

_internalList.Add(convert);
}

readonly FasterList<T> _internalList;
}

public struct StructGroupEntityViews<T>
where T : struct, IEntityView
{
public StructGroupEntityViews(SharedGroupedStructEntityViewsLists container)
{
_container = container;
indices = new Dictionary<int, int>();
}

public void Add(int groupID, T entityView)
{
T convert = (T)entityView;

var fasterList =
(SharedGroupedStructEntityViewsLists.NoVirt.GetList<T>(_container, groupID) as FasterList<T>);
indices[entityView.ID] = fasterList.Count;

fasterList.Add(convert);
}

public void Remove(int groupID, T entityView)
{
var fasterList =
(SharedGroupedStructEntityViewsLists.NoVirt.GetList<T>(_container, groupID) as FasterList<T>);
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<T>(_container, groupID) as FasterList<T>);
return FasterList<T>.NoVirt.ToArrayFast(fasterList, out numberOfItems);
}

readonly SharedGroupedStructEntityViewsLists _container;
readonly Dictionary<int, int> indices;
}

public class SharedStructEntityViewLists
{
internal SharedStructEntityViewLists()
{
_collection = new Dictionary<Type, IFasterList>();
}

internal static class NoVirt
{
internal static FasterList<T> GetList<T>(SharedStructEntityViewLists obj) where T : struct
{
IFasterList list;
if (obj._collection.TryGetValue(typeof(T), out list))
{
return list as FasterList<T>;
}

list = new FasterList<T>();

obj._collection.Add(typeof(T), list);

return (FasterList<T>)list;
}
}

readonly Dictionary<Type, IFasterList> _collection;
}

public class SharedGroupedStructEntityViewsLists
{
internal SharedGroupedStructEntityViewsLists()
{
_collection = new Dictionary<Type, Dictionary<int, IFasterList>>();
}

internal static class NoVirt
{
internal static IFasterList GetList<T>(SharedGroupedStructEntityViewsLists list, int groupID) where T : struct
{
Dictionary<int, IFasterList> dic = GetGroup<T>(list);
IFasterList localList;

if (dic.TryGetValue(groupID, out localList))
return localList;

localList = new FasterList<T>();
dic.Add(groupID, localList);

return localList;
}

internal static Dictionary<int, IFasterList> GetGroup<T>(SharedGroupedStructEntityViewsLists list) where T : struct
{
Dictionary<int, IFasterList> dic;

if (list._collection.TryGetValue(typeof(T), out dic))
{
return dic;
}

dic = new Dictionary<int, IFasterList>();

list._collection.Add(typeof(T), dic);

return dic;
}
}

readonly Dictionary<Type, Dictionary<int, IFasterList>> _collection;
}
}
#endif

+ 1
- 1
Svelto.ECS/Extensions/Unity/GenericEntityDescriptorHolder.cs View File

@@ -5,7 +5,7 @@ namespace Svelto.ECS
UnityEngine.MonoBehaviour , IEntityDescriptorHolder
where T: class, IEntityDescriptor, new()
{
public IEntityDescriptorInfo RetrieveDescriptor()
public EntityDescriptorInfo RetrieveDescriptor()
{
return EntityDescriptorTemplate<T>.Default;
}


+ 0
- 26
Svelto.ECS/IEnginesInterfaces.cs View File

@@ -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);
}
}

+ 1
- 1
Svelto.ECS/IEntityDescriptorHolder.cs View File

@@ -2,6 +2,6 @@ namespace Svelto.ECS
{
public interface IEntityDescriptorHolder
{
IEntityDescriptorInfo RetrieveDescriptor();
EntityDescriptorInfo RetrieveDescriptor();
}
}

+ 55
- 0
Svelto.ECS/IEntityFactory.cs View File

@@ -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);
}
}

+ 17
- 0
Svelto.ECS/IEntityFunctions.cs View File

@@ -0,0 +1,17 @@
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 RemoveEntity(EGID entityegid);

void RemoveGroupAndEntities(int groupID);
void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID);
void SwapEntityGroup(int entityID, int toGroupID);
}
}

+ 3
- 10
Svelto.ECS/IEntityViewsDB.cs View File

@@ -5,19 +5,12 @@ 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;
T[] QueryGroupedEntityViewsAsArray<T>(int group, out int count) where T : EntityView;

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 TryQueryEntityView<T>(EGID ID, out T entityView) where T : EntityView;
T QueryEntityView<T>(EGID entityGID) where T : EntityView;
}
}

Loading…
Cancel
Save