Browse Source

refactoring complete (minus some improvements)

- introduced the concept of global ID, as a combination of groupID and entityID
- only 256 groups and 2^24 entities can be created
- all the entities are now built always in group, when the group is not specified, the "standard" groups is used
- the groupID can be retrieved from the EGID
-
tags/Rel2
sebas77 6 years ago
parent
commit
36cae3be95
18 changed files with 374 additions and 204 deletions
  1. +5
    -0
      EnginesRoot.GenericEntityFunctions.cs
  2. +57
    -8
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  3. +1
    -1
      Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs
  4. +42
    -20
      Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs
  5. +10
    -0
      Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs
  6. +38
    -0
      Svelto.ECS/EGID.cs
  7. +3
    -3
      Svelto.ECS/EnginesRootEngines.cs
  8. +101
    -89
      Svelto.ECS/EnginesRootEntities.cs
  9. +5
    -14
      Svelto.ECS/EnginesRootSubmission.cs
  10. +35
    -15
      Svelto.ECS/EntityFactory.cs
  11. +2
    -3
      Svelto.ECS/EntityInfoView.cs
  12. +7
    -5
      Svelto.ECS/EntityView.cs
  13. +10
    -10
      Svelto.ECS/EntityViewBuilder.cs
  14. +52
    -33
      Svelto.ECS/EntityViewsDB.cs
  15. +1
    -1
      Svelto.ECS/ExclusiveGroups.cs
  16. +1
    -1
      Svelto.ECS/IEntityFactory.cs
  17. +1
    -0
      Svelto.ECS/IEntityFunctions.cs
  18. +3
    -1
      Svelto.ECS/IEntityViewsDB.cs

+ 5
- 0
EnginesRoot.GenericEntityFunctions.cs View File

@@ -27,6 +27,11 @@ namespace Svelto.ECS
_weakReference.Target.RemoveEntity(entityID, groupID);
}

public void RemoveEntity(EGID entityEGID)
{
_weakReference.Target.RemoveEntity(entityEGID);
}

public void RemoveGroupAndEntities(int groupID)
{
_weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID);


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

@@ -14,11 +14,12 @@ namespace Svelto.ECS.Internal
public interface ITypeSafeDictionary
{
void FillWithIndexedEntityViews(ITypeSafeList entityViews);
bool Remove(int entityId);
IEntityView GetIndexedEntityView(int entityID);
bool Remove(EGID entityId);
IEntityView GetIndexedEntityView(EGID entityID);
bool isQueryiableEntityView { get; }
}

class TypeSafeDictionary<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 +35,7 @@ namespace Svelto.ECS.Internal
{
var entityView = buffer[i];

Add(entityView.ID, entityView);
Add(entityView._ID.GID, entityView);
}
}
catch (Exception e)
@@ -43,16 +44,64 @@ namespace Svelto.ECS.Internal
}
}

public new bool Remove(int entityId)
public bool Remove(EGID entityId)
{
base.Remove(entityId);
base.Remove(entityId.GID);

return Count > 0;
}

public IEntityView GetIndexedEntityView(int entityID)
public IEntityView GetIndexedEntityView(EGID entityID)
{
return this[entityID];
return this[entityID.GID];
}

public bool isQueryiableEntityView
{
get { return true; }
}
}
class TypeSafeDictionaryForStruct<TValue> : Dictionary<int, TValue>, ITypeSafeDictionary where TValue : struct, IEntityStruct
{
internal static readonly ReadOnlyDictionary<int, TValue> Default =
new ReadOnlyDictionary<int, TValue>(new Dictionary<int, TValue>());

public void FillWithIndexedEntityViews(ITypeSafeList entityViews)
{
int count;
var buffer = FasterList<TValue>.NoVirt.ToArrayFast((FasterList<TValue>) entityViews, out count);

try
{
for (var i = 0; i < count; i++)
{
var entityView = buffer[i];

Add(entityView.ID.GID, entityView);
}
}
catch (Exception e)
{
throw new TypeSafeDictionaryException(e);
}
}

public bool Remove(EGID entityId)
{
base.Remove(entityId.GID);

return Count > 0;
}

public IEntityView GetIndexedEntityView(EGID entityID)
{
return this[entityID.GID];
}

public bool isQueryiableEntityView
{
get { return false; }
}
}
}

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

+ 42
- 20
Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs View File

@@ -12,7 +12,7 @@ namespace Svelto.ECS.Internal
void AddRange(ITypeSafeList entityViewListValue);

ITypeSafeList Create();
bool MappedRemove(int entityID);
bool MappedRemove(EGID entityID);
ITypeSafeDictionary CreateIndexedDictionary();
IEntityView[] ToArrayFast(out int count);
void AddCapacity(int capacity);
@@ -32,17 +32,26 @@ namespace Svelto.ECS.Internal
_mappedIndices = new Dictionary<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;
{
try
{
_mappedIndices.Add(this[index].ID.GID, index);
}
catch (Exception e)
{
throw new TypeSafeFasterListForECSException(e);
}
}

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

base.AddRange(entityViewListValue as FasterList<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,7 +82,14 @@ namespace Svelto.ECS.Internal

base.Add(entityView);

_mappedIndices[entityView.ID] = index;
try
{
_mappedIndices.Add(entityView.ID.GID, index);
}
catch (Exception e)
{
throw new TypeSafeFasterListForECSException(e);
}
}

public void AddCapacity(int capacity)
@@ -72,9 +98,9 @@ namespace Svelto.ECS.Internal
Resize(Count + capacity);
}

public int GetIndexFromID(int entityID)
public int GetIndexFromID(EGID entityID)
{
return _mappedIndices[entityID];
return _mappedIndices[entityID.GID];
}
}

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

public TypeSafeFasterListForECSForStructs()
{
}
{}

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

public ITypeSafeDictionary CreateIndexedDictionary()
{
throw new Exception("Not Allowed");
return new TypeSafeDictionaryForStruct<T>();
}

public IEntityView[] ToArrayFast(out int count)
@@ -118,12 +142,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 +159,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)
{}
}
}

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

@@ -0,0 +1,38 @@
using DBC;

namespace Svelto.ECS
{
public struct EGID
{
int _GID;
public int GID
{
get { return _GID; }
}
public int ID
{
get { return _GID & 0xFFFFFF; }
}
public int group
{
get { return (int) ((_GID & 0xFF000000) >> 24); }
}

public EGID(int entityID, int groupID) : this()
{
_GID = MAKE_GLOBAL_ID(entityID, groupID);
}

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

+ 3
- 3
Svelto.ECS/EnginesRootEngines.cs View File

@@ -37,13 +37,13 @@ namespace Svelto.ECS
_entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
_otherEngines = new FasterList<IEngine>();

_entityViewsDB = new Dictionary<Type, ITypeSafeList>();
_globalEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_groupedEntityViewsDBDic = new Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>();
_globalEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();

_DB = new EntityViewsDB(_entityViewsDB, _groupedEntityViewsDBDic, _groupEntityViewsDB);
_DB = new EntityViewsDB(_globalEntityViewsDB, _globalEntityViewsDBDic, _groupEntityViewsDB);

_scheduler = entityViewScheduler;
_scheduler.Schedule(new WeakAction(SubmitEntityViews));


+ 101
- 89
Svelto.ECS/EnginesRootEntities.cs View File

@@ -14,7 +14,7 @@ namespace Svelto.ECS
{
public void Dispose()
{
foreach (var entity in _entityViewsDB)
foreach (var entity in _globalEntityViewsDB)
if (entity.Value.isQueryiableEntityView)
foreach (var entityView in entity.Value)
RemoveEntityViewFromEngines(_entityViewEngines, entityView as EntityView, entity.Key);
@@ -64,7 +64,7 @@ namespace Svelto.ECS
implementors);
}

void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor,
void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor,
object[] implementors = null)
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
@@ -74,9 +74,15 @@ namespace Svelto.ECS

///--------------------------------------------

/// <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++)
@@ -86,8 +92,8 @@ namespace Svelto.ECS

//reserve space for the global pool
ITypeSafeList dbList;
if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false)
_entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
if (_globalEntityViewsDB.TryGetValue(entityViewType, out dbList) == false)
_globalEntityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
else
dbList.AddCapacity(size);

@@ -111,18 +117,44 @@ namespace Svelto.ECS
dbList.AddCapacity(size);
}
}

void RemoveEntity(ref EntityInfoView entityInfoView)
///--------------------------------------------
///
void RemoveEntity(int entityID, int groupID)
{
InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID,
entityInfoView.groupID);
RemoveEntity(new EGID(entityID, groupID));
}

void RemoveEntity(int entityID, int groupID)
void RemoveEntity(EGID entityGID)
{
var entityInfoView = _DB.QueryEntityViewInGroup<EntityInfoView>(entityID, groupID);
_DB.TryQueryEntityView<EntityInfoView>(entityGID, out var entityInfoView);

var entityViewBuilders = entityInfoView.entityViews;
EGID id = entityInfoView._ID;

var entityViewBuildersCount = entityViewBuilders.Length;
var group = _groupEntityViewsDB[id.group];

//for each entity view generated by the entity descriptor
for (var i = 0; i < entityViewBuildersCount; i++)
{
var entityViewType = entityViewBuilders[i].GetEntityViewType();
InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, id);
RemoveEntityViewFromDB(@group, entityViewType, id);
RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, id);
}

RemoveEntity(ref entityInfoView);
InternalRemoveEntityViewFromDBDicAndEngines(_entityInfoViewType, id);
}

static void RemoveEntityViewFromDB(Dictionary<Type, ITypeSafeList> @group, Type entityViewType, EGID id)
{
//remove it from entity views group DB
var typeSafeList = @group[entityViewType];
if (typeSafeList.MappedRemove(id) == false) //clean up
@group.Remove(entityViewType);
}

void RemoveGroupAndEntitiesFromDB(int groupID)
@@ -138,40 +170,70 @@ namespace Svelto.ECS
{
var entityID = entities[i].ID;

InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID);
RemoveEntityViewFromDB(@_globalEntityViewsDB, entityViewType, entityID);

InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID);
}
}

_groupEntityViewsDB.Remove(groupID);
}

void InternalRemoveEntityViewFromDBAndEngines(Type entityViewType,
int entityID,
int groupID)
void InternalRemoveEntityViewFromDBDicAndEngines(Type entityViewType, EGID id)
{
var entityViews = _entityViewsDB[entityViewType];
if (entityViews.MappedRemove(entityID) == false)
_entityViewsDB.Remove(entityViewType);

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

if (typeSafeDictionary.Remove(entityID) == false)
_groupedEntityViewsDBDic[groupID].Remove(entityViewType);
var entityView = typeSafeDictionary.GetIndexedEntityView(id);

//the reason why this for exists is because in the past hierarchical entity views
//where supported :(
//Only EntityView can be removed from engines (won't work for IEntityStruct or IEntityView)
for (var current = entityViewType; current != _entityViewType; current = current.BaseType)
{
#if DEBUG && !PROFILER
if (current != entityViewType)
Utility.Console.LogWarning("Hierarchical Entity Views are design mistakes, ECS is not OOD!!");
#endif
RemoveEntityViewFromEngines(_entityViewEngines, entityView, current);
}
}
typeSafeDictionary.Remove(id);
}
static void RemoveEntityViewFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines,
IEntityView entityView,
Type entityViewType)
{
FasterList<IHandleEntityViewEngine> enginesForEntityView;

if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
{
int count;
var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);

for (var j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorRemoveDuration(fastList[j], entityView);
#else
fastList[j].Remove(entityView);
#endif
}
}
}
///--------------------------------------------

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

var entityViewBuilders = _DB.QueryEntityView<EntityInfoView>(entityID).entityViews;
_DB.TryQueryEntityViewInGroup(fromGroupID, entityID, out EntityInfoView entityInfoView);
var entityViewBuilders = entityInfoView.entityViews;
var entityViewBuildersCount = entityViewBuilders.Length;

var groupedEntities = _groupEntityViewsDB[fromGroupID];
@@ -195,78 +257,28 @@ namespace Svelto.ECS
if (groupedEntityViewsTyped.TryGetValue(entityViewType, out toSafeList) == false)
groupedEntityViewsTyped[entityViewType] = toSafeList = fromSafeList.Create();

entityViewBuilder.MoveEntityView(entityID, fromSafeList, toSafeList);
fromSafeList.MappedRemove(entityID);
entityViewBuilder.MoveEntityView(entityInfoView._ID, fromSafeList, toSafeList);
fromSafeList.MappedRemove(entityInfoView._ID);
entityInfoView._ID = new EGID(entityID, toGroupID);
}

var entityInfoView = _DB.QueryEntityView<EntityInfoView>(entityID);
entityInfoView.groupID = toGroupID;
}

void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders,
int entityID, int groupID)
{
InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID);

var entityViewBuildersCount = entityViewBuilders.Length;

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

InternalRemoveEntityViewFromDBAndEngines(entityViewType, entityID, groupID);
}
InternalRemoveEntityViewFromDBAndEngines(typeof(EntityInfoView), entityID, groupID);
}

void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID)
{
var entityViewBuildersCount = entityViewBuilders.Length;
var group = _groupEntityViewsDB[groupID];

for (var i = 0; i < entityViewBuildersCount; i++)
{
var entityViewType = entityViewBuilders[i].GetEntityViewType();
var typeSafeList = group[entityViewType];
typeSafeList.MappedRemove(entityID);
}
}

static void RemoveEntityViewFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines,
IEntityView entityView,
Type entityViewType)
{
FasterList<IHandleEntityViewEngine> enginesForEntityView;

if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
{
int count;
var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);

for (var j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorRemoveDuration(fastList[j], entityView);
#else
fastList[j].Remove(entityView);
#endif
}
}
}
readonly Type _entityInfoViewType = typeof(EntityInfoView);

readonly EntityViewsDB _DB;
//grouped set of entity views, this is the standard way to handle entity views
readonly Dictionary<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;

//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> _entityViewsDB;
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;
}
}

+ 5
- 14
Svelto.ECS/EnginesRootSubmission.cs View File

@@ -39,7 +39,7 @@ namespace Svelto.ECS
numberOfReenteringLoops++;
}
}
//todo: can I make the entity creation less complicated?
void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupsToSubmit)
{
//for each groups there is a dictionary of built lists of EntityView grouped by type
@@ -57,18 +57,9 @@ namespace Svelto.ECS
//add the entity View in the group
AddEntityViewToDB(groupDB, entityViewsPerType);
//add the entity view in the gloal pool
AddEntityViewToDB(_entityViewsDB, entityViewsPerType);
AddEntityViewToDB(_globalEntityViewsDB, entityViewsPerType);
//and it's not a struct, add in the indexable DB too
if (entityViewsPerType.Value.isQueryiableEntityView)
{
Dictionary<Type, ITypeSafeDictionary> groupDic;

if (_groupedEntityViewsDBDic.TryGetValue(groupID, out groupDic) == false)
groupDic = _groupedEntityViewsDBDic[groupID] =
new Dictionary<Type, ITypeSafeDictionary>();

AddEntityViewToEntityViewsDictionary(groupDic, entityViewsPerType.Value, entityViewsPerType.Key);
}
AddEntityViewToEntityViewsDictionary(_globalEntityViewsDBDic, entityViewsPerType.Value, entityViewsPerType.Key);
}
}

@@ -87,8 +78,8 @@ namespace Svelto.ECS
}
}

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



+ 35
- 15
Svelto.ECS/EntityFactory.cs View File

@@ -13,25 +13,45 @@ namespace Svelto.ECS.Internal
EntityDescriptorInfo entityViewsToBuildDescriptor,
object[] implementors)
{
Dictionary<Type, ITypeSafeList> group;
var @group = FetchGroup(groupID, groupEntityViewsByType);

if (groupEntityViewsByType.TryGetValue(groupID, out group) == false)
{
group = new Dictionary<Type, ITypeSafeList>();
groupEntityViewsByType.Add(groupID, group);
}
BuildEntityViewsAndAddToGroup(new EGID(entityID, groupID), group, entityViewsToBuildDescriptor, implementors);

InternalBuildEntityViews(entityID, group, entityViewsToBuildDescriptor, implementors);
AddEntityInfoView(new EGID(entityID, groupID), entityViewsToBuildDescriptor, @group);
}

EntityInfoView removeEntityView =
(EntityInfoView) BuildEntityView
(entityID, group, EntityViewBuilder<EntityInfoView>.ENTITY_VIEW_TYPE, new EntityViewBuilder<EntityInfoView>());
static void AddEntityInfoView(EGID entityID, EntityDescriptorInfo entityViewsToBuildDescriptor,
Dictionary<Type, ITypeSafeList> @group)
{
//should be a struct?
var removeEntityView = new EntityInfoView();

removeEntityView.groupID = groupID;
removeEntityView._ID = entityID;
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild;

ITypeSafeList list;

if (group.TryGetValue(typeof(EntityInfoView), out list) == false)
list = group[typeof(EntityInfoView)] =
new TypeSafeFasterListForECSForClasses<EntityInfoView>();

((TypeSafeFasterListForECSForClasses<EntityInfoView>) list).Add(removeEntityView);
}

static void InternalBuildEntityViews(int entityID,
static Dictionary<Type, ITypeSafeList> FetchGroup(int groupID, Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType)
{
Dictionary<Type, ITypeSafeList> group;

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

return @group;
}

static void BuildEntityViewsAndAddToGroup(EGID entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
object[] implementors)
@@ -54,8 +74,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;

@@ -182,7 +202,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. ";



+ 2
- 3
Svelto.ECS/EntityInfoView.cs View File

@@ -1,8 +1,7 @@
namespace Svelto.ECS
namespace Svelto.ECS.Internal
{
public class EntityInfoView : EntityView
class EntityInfoView : EntityView
{
internal IEntityViewBuilder[] entityViews;
public int groupID;
}
}

+ 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)
{


+ 10
- 10
Svelto.ECS/EntityViewBuilder.cs View File

@@ -5,17 +5,17 @@ namespace Svelto.ECS
{
public interface IEntityViewBuilder
{
void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView);
void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView);
ITypeSafeList Preallocate(ref ITypeSafeList list, int size);

Type GetEntityViewType();
void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList);
void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList);
bool mustBeFilled { get; }
}

public struct EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : EntityView, new()
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>();
@@ -44,7 +44,7 @@ namespace Svelto.ECS
return ENTITY_VIEW_TYPE;
}

public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
@@ -57,12 +57,12 @@ namespace Svelto.ECS
get { return true; }
}

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

public struct EntityViewStructBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : struct, IEntityStruct
public class EntityViewStructBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : struct, IEntityStruct
{
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView)
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, out IEntityView entityView)
{
var structEntityView = default(EntityViewType);
structEntityView.ID = entityID;
@@ -92,7 +92,7 @@ namespace Svelto.ECS
return ENTITY_VIEW_TYPE;
}

public void MoveEntityView(int entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;
@@ -105,6 +105,6 @@ namespace Svelto.ECS
get { return false; }
}

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

+ 52
- 33
Svelto.ECS/EntityViewsDB.cs View File

@@ -7,10 +7,10 @@ namespace Svelto.ECS.Internal
class EntityViewsDB : IEntityViewsDB
{
internal EntityViewsDB( Dictionary<Type, ITypeSafeList> entityViewsDB,
Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> entityViewsDBdic,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB)
{
_entityViewsDB = entityViewsDB;
_globalEntityViewsDB = entityViewsDB;
_groupedEntityViewsDBDic = entityViewsDBdic;
_groupEntityViewsDB = groupEntityViewsDB;
}
@@ -21,7 +21,7 @@ namespace Svelto.ECS.Internal

ITypeSafeList entityViews;

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

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

if (_entityViewsDB.TryGetValue(type, out entityViews) == false)
if (_globalEntityViewsDB.TryGetValue(type, out entityViews) == false)
return RetrieveEmptyEntityViewArray<T>();
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entityViews, out count);
@@ -73,56 +73,60 @@ namespace Svelto.ECS.Internal

public T QueryEntityView<T>(int entityID) where T:EntityView
{
return QueryEntityViewInGroup<T>(entityID, ExclusiveGroups.StandardEntity);
}
T entityView;

public bool TryQueryEntityView<T>(int entityID, out T entityView) where T:EntityView
{
return TryQueryEntityViewInGroup(entityID, ExclusiveGroups.StandardEntity, out entityView);
TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView);
return entityView;
}
public T QueryEntityViewInGroup<T>(int entityID, int groupID) where T:EntityView
public T QueryEntityView<T>(EGID entityGID) where T : EntityView
{
T entityView;
TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView);
TryQueryEntityViewInGroup(entityGID, out entityView);

return entityView;
}

public bool TryQueryEntityViewInGroup<T>(int entityID, int groupID, out T entityView) where T:EntityView
public bool TryQueryEntityView<T>(int entityID, out T entityView) where T:EntityView
{
return TryQueryEntityView(entityID, groupID, _groupedEntityViewsDBDic, out entityView);
return TryQueryEntityViewInGroup(new EGID(entityID, ExclusiveGroups.StandardEntity), out entityView);
}

static FasterReadOnlyList<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>()
public T QueryEntityViewInGroup<T>(int entityID, int groupID) where T:EntityView
{
return FasterList<T>.DefaultList.ToArrayFast();
T entityView;

TryQueryEntityViewInGroup(entityID, groupID, out entityView);

return entityView;
}
static bool TryQueryEntityView<T>(int ID, int groupID, Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> entityDic, out T entityView) where T : EntityView

public bool TryQueryEntityViewInGroup<T>(int entityID, int groupID, out T entityView) where T : EntityView
{
return TryQueryEntityViewInGroup(new EGID(entityID, groupID), out entityView);
}

bool TryQueryEntityViewInGroup<T>(EGID entityGID, out T entityView) where T:EntityView
{
var type = typeof(T);

T internalEntityView;

ITypeSafeDictionary entityViews;
TypeSafeDictionary<T> casted;

Dictionary<Type, ITypeSafeDictionary> @group;
if (entityDic.TryGetValue(groupID, out group) == false)
throw new Exception("Group not found");
ITypeSafeDictionary entityViews;
TypeSafeDictionaryForClass<T> casted;

group.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;

@@ -134,9 +138,24 @@ namespace Svelto.ECS.Internal
return false;
}

readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupedEntityViewsDBDic;
static FasterReadOnlyList<T> RetrieveEmptyEntityViewList<T>()
{
return FasterReadOnlyList<T>.DefaultList;
}

readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
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;
}
}

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

@@ -2,6 +2,6 @@
{
static class ExclusiveGroups
{
internal const int StandardEntity = unchecked((int) 0xFFFFFFFF);
internal const int StandardEntity = 0xFF;
}
}

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

@@ -41,7 +41,7 @@ namespace Svelto.ECS
/// <typeparam name="T"></typeparam>
/// <param name="entityID"></param>
/// <param name="implementors"></param>
void BuildEntity<T>(int entityID, object[] implementors) where T:IEntityDescriptor, new();
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


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

@@ -7,6 +7,7 @@ namespace Svelto.ECS
//the entity from the special standard group.
void RemoveEntity(int entityID);
void RemoveEntity(int entityID, int groupID);
void RemoveEntity(EGID entityegid);

void RemoveGroupAndEntities(int groupID);


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

@@ -11,8 +11,10 @@ namespace Svelto.ECS
T[] QueryGroupedEntityViewsAsArray<T>(int group, out int count) where T : IEntityView;

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

Loading…
Cancel
Save