Browse Source

refactored the RemoveEntity logic, made simpler, made it working

tags/Rel2b2
sebas77 7 years ago
parent
commit
ac656a776a
13 changed files with 395 additions and 365 deletions
  1. +13
    -5
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  2. +10
    -0
      Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs
  3. +2
    -1
      Svelto.ECS/EnginesRootEngines.cs
  4. +35
    -50
      Svelto.ECS/EnginesRootEntities.cs
  5. +9
    -7
      Svelto.ECS/EnginesRootSubmission.cs
  6. +0
    -206
      Svelto.ECS/EntityDescriptor.cs
  7. +216
    -0
      Svelto.ECS/EntityFactory.cs
  8. +10
    -0
      Svelto.ECS/EntityInfoImplementor.cs
  9. +11
    -0
      Svelto.ECS/EntityViewBuilder.cs
  10. +75
    -46
      Svelto.ECS/EntityViewsDB.cs
  11. +4
    -6
      Svelto.ECS/IEnginesInterfaces.cs
  12. +10
    -8
      Svelto.ECS/IEntityViewsDB.cs
  13. +0
    -36
      Svelto.ECS/RemoveEntityImplementor.cs

+ 13
- 5
Svelto.ECS/DataStructures/TypeSafeDictionary.cs View File

@@ -1,4 +1,5 @@
using Svelto.DataStructures;
using System;
using Svelto.DataStructures;
using System.Collections.Generic;

namespace Svelto.ECS.Internal
@@ -28,15 +29,22 @@ namespace Svelto.ECS.Internal
int count;
var buffer = FasterList<TValue>.NoVirt.ToArrayFast((FasterList<TValue>) entityViews, out count);

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

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

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



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

@@ -0,0 +1,10 @@
using System;

namespace Svelto.ECS
{
public class TypeSafeDictionaryException : Exception
{
public TypeSafeDictionaryException(Exception exception):base(exception.Message, exception)
{}
}
}

+ 2
- 1
Svelto.ECS/EnginesRootEngines.cs View File

@@ -42,12 +42,13 @@ namespace Svelto.ECS
_metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_entityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_metaEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();

_DB = new EntityViewsDB(_entityViewsDB, _entityViewsDBDic, _metaEntityViewsDB, _groupEntityViewsDB);
_DB = new EntityViewsDB(_entityViewsDB, _metaEntityViewsDB, _entityViewsDBDic, _metaEntityViewsDBDic, _groupEntityViewsDB);

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


+ 35
- 50
Svelto.ECS/EnginesRootEntities.cs View File

@@ -134,32 +134,29 @@ namespace Svelto.ECS
}
}

void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo)
void RemoveEntity(ref EntityInfoView entityInfoView, Dictionary<Type, ITypeSafeList> viewsDB, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
{
var removeEntityImplementor = removeInfo as RemoveEntityImplementor;

if (removeEntityImplementor.isInAGroup)
InternalRemove(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, removeEntityImplementor.groupID, _entityViewsDB);
if (entityInfoView.isInAGroup)
InternalRemoveFromGroupAndDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, entityInfoView.groupID, viewsDB, entityViewsDBDic);
else
InternalRemoveFromDBAndEngines(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, _entityViewsDB);
InternalRemoveFromDBAndEngines(entityInfoView.entityViews, entityInfoView.ID, viewsDB, entityViewsDBDic);
}

void RemoveEntity<T>(int entityID) where T : IEntityDescriptor, new()
{
InternalRemoveFromDBAndEngines( ((EntityDescriptorInfo) EntityDescriptorTemplate<T>.Default).entityViewsToBuild, entityID, _entityViewsDB);
}

void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
void RemoveEntity(int entityID)
{
InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate<T>.Default).entityViewsToBuild, metaEntityID, _metaEntityViewsDB);
var entityInfoView = _DB.QueryEntityView<EntityInfoView>(entityID);
RemoveEntity(ref entityInfoView, _entityViewsDB, _entityViewsDBDic);
}

void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
void RemoveMetaEntity(int metaEntityID)
{
InternalRemoveFromDBAndEngines(((EntityDescriptorInfo) EntityDescriptorTemplate<T>.Default).entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]);
var entityInfoView = _DB.QueryMetaEntityView<EntityInfoView>(metaEntityID);
RemoveEntity(ref entityInfoView, _metaEntityViewsDB, _metaEntityViewsDBDic);
}
void DeleteEntityGroup(int groupID)
void RemoveGroupAndEntitiesFromDB(int groupID)
{
foreach (var group in _groupEntityViewsDB[groupID])
{
@@ -172,7 +169,7 @@ namespace Svelto.ECS
{
var entityID = entities[i].ID;

InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, entityViewType, entityID);
InternalRemoveEntityViewFromDBAndEngines(_entityViewsDB, _entityViewsDBDic, entityViewType, entityID);
}
}
@@ -180,6 +177,7 @@ namespace Svelto.ECS
}
void InternalRemoveEntityViewFromDBAndEngines(Dictionary<Type, ITypeSafeList> entityViewsDB,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic,
Type entityViewType, int entityID)
{
var entityViews = entityViewsDB[entityViewType];
@@ -188,22 +186,22 @@ namespace Svelto.ECS

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

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

for (var current = entityViewType; current != _entityViewType; current = current.BaseType)
RemoveEntityViewFromEngines(_entityViewEngines, entityView, current);
}
}

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

var entityViewBuilders = ((EntityDescriptorInfo) EntityDescriptorTemplate<T>.Default).entityViewsToBuild;
var entityViewBuilders = _DB.QueryEntityView<EntityInfoView>(entityID).entityViews;
int entityViewBuildersCount = entityViewBuilders.Length;

var dictionary = _groupEntityViewsDB[fromGroupID];
@@ -239,7 +237,7 @@ namespace Svelto.ECS
}

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

@@ -247,16 +245,16 @@ namespace Svelto.ECS
{
Type entityViewType = entityViewBuilders[i].GetEntityViewType();

InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewType, entityID);
InternalRemoveEntityViewFromDBAndEngines(entityViewsDB, entityViewsDBDic, entityViewType, entityID);
}
}

void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID,
Dictionary<Type, ITypeSafeList> entityViewsDB)
void InternalRemoveFromGroupAndDBAndEngines(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID,
Dictionary<Type, ITypeSafeList> entityViewsDB, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
{
InternalRemoveFromGroupDB(entityViewBuilders, entityID, groupID);

InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB);
InternalRemoveFromDBAndEngines(entityViewBuilders, entityID, entityViewsDB, entityViewsDBDic);
}

void InternalRemoveFromGroupDB(IEntityViewBuilder[] entityViewBuilders, int entityID, int groupID)
@@ -269,11 +267,8 @@ namespace Svelto.ECS
{
Type entityViewType = entityViewBuilders[i].GetEntityViewType();

if (dictionary[entityViewType].UnorderedRemove(entityID) == false)
dictionary.Remove(entityViewType);
dictionary[entityViewType].UnorderedRemove(entityID);
}

if (dictionary.Count == 0) _groupEntityViewsDB.Remove(groupID);
}

static void RemoveEntityViewFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngine>> entityViewEngines,
@@ -344,34 +339,24 @@ namespace Svelto.ECS
_weakReference = weakReference;
}

public void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo)
{
_weakReference.Target.RemoveEntity(entityID, removeInfo);
}

public void RemoveEntity<T>(int entityID) where T : IEntityDescriptor, new()
public void RemoveEntity(int entityID)
{
_weakReference.Target.RemoveEntity<T>(entityID);
_weakReference.Target.RemoveEntity(entityID);
}

public void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
public void RemoveMetaEntity(int metaEntityID)
{
_weakReference.Target.RemoveEntity<T>(metaEntityID);
_weakReference.Target.RemoveEntity(metaEntityID);
}

public void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
public void RemoveGroupAndEntities(int groupID)
{
_weakReference.Target.RemoveEntity<T>(entityID);
_weakReference.Target.RemoveGroupAndEntitiesFromDB(groupID);
}

public void DeleteEntityGroup(int groupID)
public void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID)
{
_weakReference.Target.DeleteEntityGroup(groupID);
}

public void SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new()
{
_weakReference.Target.SwapEntityGroup<T>(entityID, fromGroupID, toGroupID);
_weakReference.Target.SwapEntityGroup(entityID, fromGroupID, toGroupID);
}

readonly DataStructures.WeakReference<EnginesRoot> _weakReference;
@@ -406,6 +391,6 @@ namespace Svelto.ECS
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBDic;
readonly Dictionary<Type, ITypeSafeDictionary> _metaEntityViewsDBDic;
}
}

+ 9
- 7
Svelto.ECS/EnginesRootSubmission.cs View File

@@ -30,13 +30,13 @@ namespace Svelto.ECS
_groupedEntityViewsToAdd.Swap();

if (_entityViewsToAdd.other.Count > 0)
AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB);
AddEntityViewsToTheDBAndSuitableEngines(_entityViewsToAdd.other, _entityViewsDB, _entityViewsDBDic);

if (_metaEntityViewsToAdd.other.Count > 0)
AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB);
AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB, _metaEntityViewsDBDic);

if (_groupedEntityViewsToAdd.other.Count > 0)
AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB);
AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB, _entityViewsDBDic);

//other can be cleared now
_entityViewsToAdd.other.Clear();
@@ -57,7 +57,7 @@ namespace Svelto.ECS
}

void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> entityViewsToAdd,
Dictionary<Type, ITypeSafeList> entityViewsDB)
Dictionary<Type, ITypeSafeList> entityViewsDB, Dictionary<Type, ITypeSafeDictionary> entityViewsDBDic)
{
foreach (var entityViewList in entityViewsToAdd)
{
@@ -65,7 +65,7 @@ namespace Svelto.ECS

if (entityViewList.Value.isQueryiableEntityView)
{
AddEntityViewToEntityViewsDictionary(_entityViewsDBDic, entityViewList.Value, entityViewList.Key);
AddEntityViewToEntityViewsDictionary(entityViewsDBDic, entityViewList.Value, entityViewList.Key);
}
}

@@ -83,13 +83,14 @@ namespace Svelto.ECS

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

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

@@ -157,6 +158,7 @@ namespace Svelto.ECS
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
readonly EntitySubmissionScheduler _scheduler;


+ 0
- 206
Svelto.ECS/EntityDescriptor.cs View File

@@ -1,8 +1,6 @@
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using Svelto.Utilities;
using System;
using System.Collections.Generic;

namespace Svelto.ECS
{
@@ -43,7 +41,6 @@ namespace Svelto.ECS
Array.Copy(descriptor.entityViewsToBuild, 0, entityViewsToBuild, 0, length);
Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count);
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild);
name = descriptor.ToString();
}
}
@@ -54,219 +51,16 @@ namespace Svelto.ECS.Internal
public class EntityDescriptorInfo:IEntityDescriptorInfo
{
internal IEntityViewBuilder[] entityViewsToBuild;
internal RemoveEntityImplementor removeEntityImplementor;
internal string name;

internal EntityDescriptorInfo(IEntityDescriptor descriptor)
{
name = descriptor.ToString();
entityViewsToBuild = descriptor.entityViewsToBuild;
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild);
}

protected EntityDescriptorInfo()
{}
}
static class EntityFactory
{
internal static void BuildGroupedEntityViews(int entityID, int groupID,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType,
IEntityDescriptorInfo eentityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo;
Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped;

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

//I would like to find a better solution for this
var removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.entityViewsToBuild, groupID);

InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors, removeEntityImplementor);
}

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

InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors, removeEntityImplementor);
}

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

for (int index = 0; index < count; index++)
{
var entityViewBuilder = entityViewsToBuild[index];
var entityViewType = entityViewBuilder.GetEntityViewType();

//only class EntityView will be returned
//struct EntityView cannot be filled so it will be null.
var entityViewObjectToFill =
BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder);

//the semantic of this code must still be improved
//but only classes can be filled, so I am aware
//it's a EntityView
if (entityViewObjectToFill != null)
{
FillEntityView(entityViewObjectToFill as EntityView, implementors, removeEntityImplementor,
entityViewsToBuildDescriptor.name);
}
}
}

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

var entityViewsPoolWillBeCreated =
entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false;

IEntityView entityViewObjectToFill;

//passing the undefined entityViewsByType inside the entityViewBuilder will allow
//it to be created with the correct type and casted back to the undefined list.
//that's how the list will be eventually of the target type.
entityViewBuilder.BuildEntityViewAndAddToList(ref entityViewsList, entityID, out entityViewObjectToFill);

if (entityViewsPoolWillBeCreated)
entityViewsByType.Add(entityViewType, entityViewsList);

return entityViewObjectToFill as IEntityView;
}

//this is used to avoid newing a dictionary every time, but it's used locally only and it's clearead for each use
#if DEBUG && !PROFILER
static readonly Dictionary<Type, Tuple<object, int>> implementorsByType = new Dictionary<Type, Tuple<object, int>>();
#else
static readonly Dictionary<Type, object> implementorsByType = new Dictionary<Type, object>();
#endif

static void FillEntityView(EntityView entityView, object[] implementors, RemoveEntityImplementor removeEntity,
string entityDescriptorName)
{
for (int index = 0; index < implementors.Length; index++)
{
var implementor = implementors[index];

if (implementor != null)
{
var type = implementor.GetType();

Type[] interfaces;
if (_cachedTypes.TryGetValue(type, out interfaces) == false)
interfaces = _cachedTypes[type] = type.GetInterfacesEx();

for (int iindex = 0; iindex < interfaces.Length; iindex++)
{
var componentType = interfaces[iindex];
#if DEBUG && !PROFILER
Tuple<object, int> implementorHolder;

if (implementorsByType.TryGetValue(componentType, out implementorHolder) == true)
implementorHolder.item2++;
else
implementorsByType[componentType] = new Tuple<object, int>(implementor, 1);
#else
implementorsByType[componentType] = implementor;
#endif
}
}
#if DEBUG && !PROFILER
else
Utility.Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString()));
#endif
}

int count;

//Very efficent way to collect the fields of every EntityViewType
KeyValuePair<Type, CastedAction<EntityView>>[] setters =
FasterList<KeyValuePair<Type, CastedAction<EntityView>>>.NoVirt.ToArrayFast(entityView.entityViewBlazingFastReflection, out count);

var removeEntityComponentType = typeof(IRemoveEntityComponent);

for (int i = 0; i < count; i++)
{
var keyValuePair = setters[i];
Type fieldType = keyValuePair.Key;
if (fieldType != removeEntityComponentType)
{
#if DEBUG && !PROFILER
Tuple<object, int> component;
#else
object component;
#endif

if (implementorsByType.TryGetValue(fieldType, out component) == false)
{
Exception e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + " - EntityView: " +
entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName);

throw e;
}
#if DEBUG && !PROFILER
if (component.item2 > 1)
Utility.Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
"Component Type: ", fieldType.Name, " implementor: ",
component.item1.ToString()) + " - EntityView: " +
entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName);
#endif
#if DEBUG && !PROFILER
keyValuePair.Value.Call(entityView, component.item1);
#else
keyValuePair.Value.Call(entityView, component);
#endif
}
else
{
keyValuePair.Value.Call(entityView, removeEntity);
}
}

implementorsByType.Clear();
}
#if DEBUG && !PROFILER
struct Tuple<T1, T2>
{
public T1 item1;
public T2 item2;

public Tuple(T1 implementor, T2 v)
{
item1 = implementor;
item2 = v;
}
}
#endif
static 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. ";

const string NULL_IMPLEMENTOR_ERROR =
"<color=orange>Svelto.ECS</color> Null implementor, please be careful about the implementors passed to avoid performance loss ";

const string NOT_FOUND_EXCEPTION = "<color=orange>Svelto.ECS</color> Implementor not found for an EntityView. ";
}
}


+ 216
- 0
Svelto.ECS/EntityFactory.cs View File

@@ -0,0 +1,216 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.Utilities;

namespace Svelto.ECS.Internal
{
static class EntityFactory
{
internal static void BuildGroupedEntityViews(int entityID, int groupID,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType,
IEntityDescriptorInfo eentityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo;
Dictionary<Type, ITypeSafeList> groupedEntityViewsTyped;

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

InternalBuildEntityViews(entityID, groupedEntityViewsTyped, entityViewsToBuildDescriptor, implementors);
EntityInfoView removeEntityView = new EntityInfoView();

removeEntityView.groupID = groupID;
removeEntityView.isInAGroup = true;
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild;
AddEntityInfoView(groupEntityViewsByType[groupID], removeEntityView);
}

internal static void BuildEntityViews(int entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
IEntityDescriptorInfo eentityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuildDescriptor = eentityViewsToBuildDescriptor as EntityDescriptorInfo;
InternalBuildEntityViews(entityID, entityViewsByType, entityViewsToBuildDescriptor, implementors);
EntityInfoView removeEntityView = new EntityInfoView();
removeEntityView.entityViews = entityViewsToBuildDescriptor.entityViewsToBuild;
AddEntityInfoView(entityViewsByType, removeEntityView);
}
static void AddEntityInfoView(Dictionary<Type, ITypeSafeList> entityViewsByType, EntityInfoView removeEntityView)
{
ITypeSafeList list;
if (entityViewsByType.TryGetValue(typeof(EntityInfoView), out list) == false)
list = entityViewsByType[typeof(EntityInfoView)] = new TypeSafeFasterListForECSForClasses<EntityInfoView>();
(list as TypeSafeFasterListForECSForClasses<EntityInfoView>).Add(removeEntityView);
}

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

for (int index = 0; index < count; index++)
{
var entityViewBuilder = entityViewsToBuild[index];
var entityViewType = entityViewBuilder.GetEntityViewType();

var entityViewObjectToFill =
BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder);

if (entityViewBuilder.mustBeFilled == true)
{
FillEntityView(entityViewObjectToFill as EntityView
,implementors
,entityViewsToBuildDescriptor.name);
}
}
}

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

var entityViewsPoolWillBeCreated =
entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false;

IEntityView entityViewObjectToFill;

//passing the undefined entityViewsByType inside the entityViewBuilder will allow
//it to be created with the correct type and casted back to the undefined list.
//that's how the list will be eventually of the target type.
entityViewBuilder.BuildEntityViewAndAddToList(ref entityViewsList, entityID, out entityViewObjectToFill);

if (entityViewsPoolWillBeCreated)
entityViewsByType.Add(entityViewType, entityViewsList);

return entityViewObjectToFill;
}

//this is used to avoid newing a dictionary every time, but it's used locally only and it's clearead for each use
#if DEBUG && !PROFILER
static readonly Dictionary<Type, Tuple<object, int>> implementorsByType = new Dictionary<Type, Tuple<object, int>>();
#else
static readonly Dictionary<Type, object> implementorsByType = new Dictionary<Type, object>();
#endif

static void FillEntityView(EntityView entityView
, object[] implementors
, string entityDescriptorName)
{
int count;

//Very efficent way to collect the fields of every EntityViewType
KeyValuePair<Type, CastedAction<EntityView>>[] setters =
FasterList<KeyValuePair<Type, CastedAction<EntityView>>>.NoVirt.ToArrayFast(entityView.entityViewBlazingFastReflection, out count);

if (count == 0) return;
for (int index = 0; index < implementors.Length; index++)
{
var implementor = implementors[index];

if (implementor != null)
{
var type = implementor.GetType();

Type[] interfaces;
if (_cachedTypes.TryGetValue(type, out interfaces) == false)
interfaces = _cachedTypes[type] = type.GetInterfacesEx();

for (int iindex = 0; iindex < interfaces.Length; iindex++)
{
var componentType = interfaces[iindex];
#if DEBUG && !PROFILER
Tuple<object, int> implementorHolder;

if (implementorsByType.TryGetValue(componentType, out implementorHolder) == true)
implementorHolder.numberOfImplementations++;
else
implementorsByType[componentType] = new Tuple<object, int>(implementor, 1);
#else
implementorsByType[componentType] = implementor;
#endif
}
}
#if DEBUG && !PROFILER
else
Utility.Console.LogError(NULL_IMPLEMENTOR_ERROR.FastConcat(entityView.ToString()));
#endif
}

for (int i = 0; i < count; i++)
{
var fieldSetter = setters[i];
Type fieldType = fieldSetter.Key;
#if DEBUG && !PROFILER
Tuple<object, int> component;
#else
object component;
#endif

if (implementorsByType.TryGetValue(fieldType, out component) == false)
{
Exception e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name + " - EntityView: " +
entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName);

throw e;
}
#if DEBUG && !PROFILER
if (component.numberOfImplementations > 1)
Utility.Console.LogError(DUPLICATE_IMPLEMENTOR_ERROR.FastConcat(
"Component Type: ", fieldType.Name, " implementor: ",
component.implementorType.ToString()) + " - EntityView: " +
entityView.GetType().Name + " - EntityDescriptor " + entityDescriptorName);
#endif
#if DEBUG && !PROFILER
fieldSetter.Value.Call(entityView, component.implementorType);
#else
keyValuePair.Value.Call(entityView, component);
#endif
}

implementorsByType.Clear();
}
#if DEBUG && !PROFILER
struct Tuple<T1, T2>
{
public T1 implementorType;
public T2 numberOfImplementations;

public Tuple(T1 implementor, T2 v)
{
implementorType = implementor;
numberOfImplementations = v;
}
}
#endif
static 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. ";

const string NULL_IMPLEMENTOR_ERROR =
"<color=orange>Svelto.ECS</color> Null implementor, please be careful about the implementors passed to avoid performance loss ";

const string NOT_FOUND_EXCEPTION = "<color=orange>Svelto.ECS</color> Implementor not found for an EntityView. ";
}
}

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

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


+ 11
- 0
Svelto.ECS/EntityViewBuilder.cs View File

@@ -10,6 +10,7 @@ namespace Svelto.ECS

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

public class EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : EntityView, new()
@@ -51,6 +52,11 @@ namespace Svelto.ECS
toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]);
}

public bool mustBeFilled
{
get { return true; }
}

readonly Type _entityViewType = typeof(EntityViewType);
}

@@ -94,6 +100,11 @@ namespace Svelto.ECS
toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]);
}

public bool mustBeFilled
{
get { return false; }
}

readonly Type _entityViewType = typeof(EntityViewType);
}
}

+ 75
- 46
Svelto.ECS/EntityViewsDB.cs View File

@@ -6,18 +6,22 @@ namespace Svelto.ECS.Internal
{
class EntityViewsDB : IEntityViewsDB
{
internal EntityViewsDB( Dictionary<Type, ITypeSafeList> entityViewsDB,
internal EntityViewsDB( Dictionary<Type, ITypeSafeList> entityViewsDB,
Dictionary<Type, ITypeSafeList> metaEntityViewsDB,
Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic,
Dictionary<Type, ITypeSafeList> metaEntityViewsDB,
Dictionary<Type, ITypeSafeDictionary> metaEntityViewsDBdic,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB)
{
_entityViewsDB = entityViewsDB;
_entityViewsDBdic = entityViewsDBdic;
_metaEntityViewsDB = metaEntityViewsDB;
_entityViewsDBdic = entityViewsDBdic;
_metaEntityViewsDBdic = metaEntityViewsDBdic;
_groupEntityViewsDB = groupEntityViewsDB;
}

public FasterReadOnlyList<T> QueryEntityViews<T>() where T:EntityView, new()
public FasterReadOnlyList<T> QueryEntityViews<T>() where T:EntityView
{
var type = typeof(T);

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

public FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int @group) where T:EntityView, new()
public FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int @group) where T:EntityView
{
Dictionary<Type, ITypeSafeList> entitiesInGroupPerType;

@@ -65,7 +69,7 @@ namespace Svelto.ECS.Internal
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entityViews[type], out count);
}

public ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T:IEntityView
public ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T:EntityView
{
var type = typeof(T);

@@ -76,60 +80,40 @@ namespace Svelto.ECS.Internal

return new ReadOnlyDictionary<int, T>(entityViews as Dictionary<int, T>);
}
public bool TryQueryEntityView<T>(int ID, out T entityView) where T : IEntityView
public ReadOnlyDictionary<int, T> QueryIndexableMetaEntityViews<T>() where T:EntityView
{
var type = typeof(T);

T internalEntityView;

ITypeSafeDictionary entityViews;
TypeSafeDictionary<T> casted;

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

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

return true;
}

entityView = default(T);
if (_metaEntityViewsDBdic.TryGetValue(type, out entityViews) == false)
return TypeSafeDictionary<T>.Default;

return false;
return new ReadOnlyDictionary<int, T>(entityViews as Dictionary<int, T>);
}
public T QueryEntityView<T>(int ID) where T : IEntityView
public T QueryEntityView<T>(int entityID) where T:EntityView
{
var type = typeof(T);

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

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

if (casted != null &&
casted.TryGetValue(ID, out internalEntityView))
return (T)internalEntityView;
return QueryEntityView<T>(entityID, _entityViewsDBdic);
}

throw new Exception("EntityView Not Found");
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, new()
public T QueryMetaEntityView<T>(int metaEntityID) where T:EntityView
{
return QueryEntityView<T>(metaEntityID);
return QueryEntityView<T>(metaEntityID, _metaEntityViewsDBdic);
}

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

public FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T:EntityView, new()
public FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T:EntityView
{
var type = typeof(T);

@@ -150,10 +134,55 @@ namespace Svelto.ECS.Internal
{
return FasterList<T>.DefaultList.ToArrayFast();
}
static bool TryQueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic, out T entityView) where T : EntityView
{
var type = typeof(T);

T internalEntityView;

ITypeSafeDictionary entityViews;
TypeSafeDictionary<T> casted;

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

readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
if (casted != null &&
casted.TryGetValue(ID, out internalEntityView))
{
entityView = internalEntityView;

return true;
}

entityView = default(T);

return false;
}

static T QueryEntityView<T>(int ID, Dictionary<Type, ITypeSafeDictionary> entityDic) where T : EntityView
{
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");
}

readonly Dictionary<Type, ITypeSafeList> _entityViewsDB;
readonly Dictionary<Type, ITypeSafeList> _metaEntityViewsDB;
readonly Dictionary<Type, ITypeSafeDictionary> _entityViewsDBdic;
readonly Dictionary<Type, ITypeSafeDictionary> _metaEntityViewsDBdic;
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
}
}

+ 4
- 6
Svelto.ECS/IEnginesInterfaces.cs View File

@@ -15,14 +15,12 @@ namespace Svelto.ECS
public interface IEntityFunctions
{
void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo);
void RemoveEntity<T>(int entityID) where T:IEntityDescriptor, new();
void RemoveEntity(int entityID);

void RemoveMetaEntity<T>(int metaEntityID) where T:IEntityDescriptor, new();
void RemoveMetaEntity(int metaEntityID);

void RemoveEntityFromGroup<T>(int entityID, int groupID) where T:IEntityDescriptor, new();
void RemoveGroupAndEntities(int groupID);
void DeleteEntityGroup(int groupID);
void SwapEntityGroup<T>(int entityID, int fromGroupID, int toGroupID) where T : IEntityDescriptor, new();
void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID);
}
}

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

@@ -4,19 +4,21 @@ namespace Svelto.ECS
{
public interface IEntityViewsDB
{
FasterReadOnlyList<T> QueryEntityViews<T>() where T:EntityView, new();
FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T: EntityView, new();
FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int group) where T: EntityView, new();
FasterReadOnlyList<T> QueryEntityViews<T>() where T:EntityView;
FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T: EntityView;
FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int group) where T: EntityView;
T[] QueryEntityViewsAsArray<T>(out int count) where T: IEntityView;
T[] QueryGroupedEntityViewsAsArray<T>(int @group, out int count) where T: IEntityView;
ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T: IEntityView;
bool TryQueryEntityView<T>(int ID, out T entityView) where T : IEntityView;
T QueryEntityView<T>(int ID) where T: IEntityView;
ReadOnlyDictionary<int, T> QueryIndexableEntityViews<T>() where T: EntityView;
ReadOnlyDictionary<int, T> QueryIndexableMetaEntityViews<T>() where T: EntityView;
bool TryQueryEntityView<T>(int ID, out T entityView) where T : EntityView;
T QueryEntityView<T>(int ID) where T: EntityView;

bool TryQueryMetaEntityView<T>(int metaEntityID, out T entityView) where T: EntityView, new();
T QueryMetaEntityView<T>(int metaEntityID) where T: EntityView, new();
bool TryQueryMetaEntityView<T>(int metaEntityID, out T entityView) where T: EntityView;
T QueryMetaEntityView<T>(int metaEntityID) where T: EntityView;
}
}


+ 0
- 36
Svelto.ECS/RemoveEntityImplementor.cs View File

@@ -1,36 +0,0 @@
namespace Svelto.ECS.Internal
{
sealed class RemoveEntityImplementor : IRemoveEntityComponent
{
public RemoveEntityImplementor(IEntityViewBuilder[] entityViews, int groupID):this(entityViews)
{
this.groupID = groupID;
isInAGroup = true;
}

internal RemoveEntityImplementor(IEntityViewBuilder[] entityViews)
{
removeEntityInfo = new RemoveEntityInfo(entityViews);
}

internal readonly RemoveEntityInfo removeEntityInfo;
internal readonly int groupID;
internal readonly bool isInAGroup;
}
}

namespace Svelto.ECS
{
public interface IRemoveEntityComponent
{}

public struct RemoveEntityInfo
{
internal readonly IEntityViewBuilder[] entityViewsToBuild;
public RemoveEntityInfo(IEntityViewBuilder[] entityViews) : this()
{
this.entityViewsToBuild = entityViews;
}
}
}

Loading…
Cancel
Save