Browse Source

found a way to avoid some awkward breaking changes from 1.0

split EngineRoot for better readability and add comments
tags/Rel2b
sebas77 6 years ago
parent
commit
ba2e592eda
15 changed files with 850 additions and 784 deletions
  1. +5
    -5
      ECS/EngineEntityViewDB.cs
  2. +0
    -665
      ECS/EnginesRoot.cs
  3. +238
    -0
      ECS/EnginesRootEngines.cs
  4. +337
    -0
      ECS/EnginesRootEntities.cs
  5. +160
    -0
      ECS/EnginesRootSubmission.cs
  6. +43
    -28
      ECS/EntityDescriptorTemplate.cs
  7. +9
    -22
      ECS/EntityView.cs
  8. +11
    -11
      ECS/EntityViewBuilder.cs
  9. +1
    -1
      ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs
  10. +21
    -21
      ECS/GenericEntityDescriptor.cs
  11. +5
    -5
      ECS/IEngineEntityViewDB.cs
  12. +1
    -1
      ECS/IEnginesInterfaces.cs
  13. +6
    -6
      ECS/MultiEntityViewsEngine.cs
  14. +12
    -18
      ECS/RemoveEntityImplementor.cs
  15. +1
    -1
      ECS/SingleEntityViewEngine.cs

+ 5
- 5
ECS/EngineEntityViewDB.cs View File

@@ -18,7 +18,7 @@ namespace Svelto.ECS
_groupEntityViewsDB = groupEntityViewsDB;
}

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

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

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

@@ -128,17 +128,17 @@ namespace Svelto.ECS
throw new Exception("EntityView Not Found");
}

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

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

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



+ 0
- 665
ECS/EnginesRoot.cs View File

@@ -1,665 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using Svelto.ECS.Schedulers;
using Svelto.Utilities;
using Svelto.WeakEvents;

#if EXPERIMENTAL
using Svelto.ECS.Experimental;
using Svelto.ECS.Experimental.Internal;
#endif

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
#endif

namespace Svelto.ECS
{
public sealed class EnginesRoot : IDisposable
{
public EnginesRoot(EntitySubmissionScheduler entityViewScheduler)
{
_entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
_otherEngines = new FasterList<IEngine>();

_entityViewsDB = new Dictionary<Type, ITypeSafeList>();
_metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_entityViewsDBdic = new Dictionary<Type, ITypeSafeDictionary>();
_entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
_addEntityViewToEngine = AddEntityViewToEngine;
_removeEntityViewFromEngine = RemoveEntityViewFromEngine;
#endif
_engineEntityViewDB = new EngineEntityViewDB(_entityViewsDB, _entityViewsDBdic, _metaEntityViewsDB, _groupEntityViewsDB);

_scheduler = entityViewScheduler;
_scheduler.Schedule(new WeakAction(SubmitEntityViews));
#if EXPERIMENTAL
_sharedStructEntityViewLists = new SharedStructEntityViewLists();
_sharedGroupedStructEntityViewLists = new SharedGroupedStructEntityViewsLists();

_structEntityViewEngineType = typeof(IStructEntityViewEngine<>);
_groupedStructEntityViewsEngineType = typeof(IGroupedStructEntityViewsEngine<>);
_implementedInterfaceTypes = new Dictionary<Type, Type[]>();
#endif
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
#endif
}

public IEntityFactory GenerateEntityFactory()
{
return new GenericEntityFactory(new DataStructures.WeakReference<EnginesRoot>(this));
}

public IEntityFunctions GenerateEntityFunctions()
{
return new GenericEntityFunctions(new DataStructures.WeakReference<EnginesRoot>(this));
}
void BuildEntity<T>(int entityID, object[] implementors = null) where T:IEntityDescriptor, new()
{
EntityFactory.BuildEntityViews
(entityID, _entityViewsToAdd.current, EntityDescriptorTemplate<T>.Default, implementors);
}

void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
EntityFactory.BuildEntityViews
(entityID, _entityViewsToAdd.current, 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, _entityViewsToAdd.current,
EntityDescriptorTemplate<T>.Default, implementors);
}

/// <summary>
/// Using this function is like building a normal entity, but the entityViews
/// are grouped by groupID to be better processed inside engines and
/// improve cache locality. Only IGroupStructEntityViewWithID entityViews are grouped
/// other entityViews are managed as usual.
/// </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 = null) where T:IEntityDescriptor, new()
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
_groupedEntityViewsToAdd.current,
EntityDescriptorTemplate<T>.Default,
implementors);
}

void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
_groupedEntityViewsToAdd.current,
entityDescriptor, implementors);
}

void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo)
{
var removeEntityImplementor = removeInfo as RemoveEntityImplementor;

if (removeEntityImplementor.removeEntityInfo.isInAGroup)
InternalRemove(removeEntityImplementor.removeEntityInfo.descriptor.entityViewsToBuild, entityID, removeEntityImplementor.removeEntityInfo.groupID, _entityViewsDB);
else
InternalRemove(removeEntityImplementor.removeEntityInfo.descriptor.entityViewsToBuild, entityID, _entityViewsDB);
}

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

void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
{
InternalRemove(EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild, metaEntityID, _metaEntityViewsDB);
}

void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
{
InternalRemove(EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]);
}

void Preallocate<T>(int size) where T : IEntityDescriptor, new()
{
var entityViewsToBuild = EntityDescriptorTemplate<T>.Default.descriptor.entityViewsToBuild;
int count = entityViewsToBuild.Length;

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

ITypeSafeList dbList;
if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false)
_entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
else
dbList.ReserveCapacity(size);

if (_entityViewsToAdd.current.TryGetValue(entityViewType, out dbList) == false)
_entityViewsToAdd.current[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
else
dbList.ReserveCapacity(size);
}
}

public void AddEngine(IEngine engine)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
Profiler.EngineProfiler.AddEngine(engine);
#endif
var engineType = engine.GetType();
#if EXPERIMENTAL
bool engineAdded;
var implementedInterfaces = engineType.GetInterfaces();
CollectImplementedInterfaces(implementedInterfaces);
engineAdded = CheckSpecialEngine(engine);
#endif
var viewEngine = engine as IHandleEntityViewEngine;
if (viewEngine != null)
CheckEntityViewsEngine(viewEngine, engineType);
else
_otherEngines.Add(engine);
var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
if (queryableEntityViewEngine != null)
{
queryableEntityViewEngine.entityViewsDB = _engineEntityViewDB;
queryableEntityViewEngine.Ready();
}
}
#if EXPERIMENTAL
void CollectImplementedInterfaces(Type[] implementedInterfaces)
{
_implementedInterfaceTypes.Clear();

var type = typeof(IHandleEntityViewEngine);

for (int index = 0; index < implementedInterfaces.Length; index++)
{
var interfaceType = implementedInterfaces[index];

if (type.IsAssignableFrom(interfaceType) == false)
continue;

if (false == interfaceType.IsGenericTypeEx())
{
continue;
}

var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();

_implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments());
}
}
bool CheckSpecialEngine(IEngine engine)
{
if (_implementedInterfaceTypes.Count == 0) return false;

bool engineAdded = false;

if (_implementedInterfaceTypes.ContainsKey(_structEntityViewEngineType))
{
((IStructEntityViewEngine)engine).CreateStructEntityViews
(_sharedStructEntityViewLists);
}

if (_implementedInterfaceTypes.ContainsKey(_groupedStructEntityViewsEngineType))
{
((IGroupedStructEntityViewsEngine)engine).CreateStructEntityViews
(_sharedGroupedStructEntityViewLists);
}

return engineAdded;
}
#endif
void CheckEntityViewsEngine(IEngine engine, Type engineType)
{
var baseType = engineType.GetBaseType();

if (baseType.IsGenericTypeEx())
{
var genericArguments = baseType.GetGenericArguments();
AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
#if EXPERIMENTAL
var activableEngine = engine as IHandleActivableEntityEngine;
if (activableEngine != null)
AddEngine(activableEngine, genericArguments, _activableViewEntitiesEngines);
#endif

return;
}

throw new Exception("Not Supported Engine");
}

static void AddEngine<T>(T engine, Type[] types,
Dictionary<Type, FasterList<T>> engines)
{
for (int i = 0; i < types.Length; i++)
{
FasterList<T> list;

var type = types[i];

if (engines.TryGetValue(type, out list) == false)
{
list = new FasterList<T>();

engines.Add(type, list);
}

list.Add(engine);
}
}

void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> entityViewsToAdd,
Dictionary<Type, ITypeSafeList> entityViewsDB)
{
foreach (var entityViewList in entityViewsToAdd)
{
AddEntityViewToDB(entityViewsDB, entityViewList);

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

foreach (var entityViewList in entityViewsToAdd)
{
if (entityViewList.Value.isQueryiableEntityView)
{
AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value,
entityViewList.Key);
}
}
}

void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedEntityViewsToAdd,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
Dictionary<Type, ITypeSafeList> entityViewsDB)
{
foreach (var group in groupedEntityViewsToAdd)
{
AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB);

AddEntityViewsToGroupDB(groupEntityViewsDB, @group);
}
}

static void AddEntityViewsToGroupDB(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
KeyValuePair<int, Dictionary<Type, ITypeSafeList>> @group)
{
Dictionary<Type, ITypeSafeList> groupedEntityViewsByType;

if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false)
groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary<Type, ITypeSafeList>();

foreach (var entityView in @group.Value)
{
groupedEntityViewsByType.Add(entityView.Key, entityView.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)
{
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)
{
FasterList<IHandleEntityViewEngine> enginesForEntityView;

if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
{
int viewsCount;

var entityViews = entityViewsList.ToArrayFast(out viewsCount);

for (int i = 0; i < viewsCount; i++)
{
int count;
var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);
IEntityView entityView = entityViews[i];
for (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorAddDuration(_addEntityViewToEngine, fastList[j], entityView);
#else
fastList[j].Add(entityView);
#endif
}
}
}
}

void InternalRemove(IEntityViewBuilder[] entityViewBuilders, int entityID,
Dictionary<Type, ITypeSafeList> entityViewsDB)
{
int entityViewBuildersCount = entityViewBuilders.Length;
for (int i = 0; i < entityViewBuildersCount; i++)
{
Type entityViewType = entityViewBuilders[i].GetEntityViewType();

ITypeSafeList entityViews = entityViewsDB[entityViewType];
if (entityViews.UnorderedRemove(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);

RemoveEntityViewFromEngines(_entityViewEngines, entityView, entityViewType);
}
}
}

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

for (int i = 0; i < entityViewBuildersCount; i++)
{
Type entityViewType = entityViewBuilders[i].GetEntityViewType();
Dictionary<Type, ITypeSafeList> dictionary = _groupEntityViewsDB[groupID];

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

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

InternalRemove(entityViewBuilders, entityID, entityViewsDB);
}

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 (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorRemoveDuration(_removeEntityViewFromEngine, fastList[j], entityView);
#else
fastList[j].Remove(entityView);
#endif
}
}
}

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
static void AddEntityViewToEngine(IHandleEntityViewEngine engine, IEntityView entityView)
{
engine.Add(entityView);
}

static void RemoveEntityViewFromEngine(IHandleEntityViewEngine engine, IEntityView entityView)
{
engine.Remove(entityView);
}
#endif

void SubmitEntityViews()
{
bool newEntityViewsHaveBeenAddedWhileIterating =
_metaEntityViewsToAdd.current.Count > 0
|| _entityViewsToAdd.current.Count > 0
|| _groupedEntityViewsToAdd.current.Count > 0;

int numberOfReenteringLoops = 0;

while (newEntityViewsHaveBeenAddedWhileIterating)
{
//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);
if ( _metaEntityViewsToAdd.other.Count > 0)
AddEntityViewsToTheDBAndSuitableEngines(_metaEntityViewsToAdd.other, _metaEntityViewsDB);
if (_groupedEntityViewsToAdd.other.Count > 0)
AddGroupEntityViewsToTheDBAndSuitableEngines(_groupedEntityViewsToAdd.other, _groupEntityViewsDB, _entityViewsDB);
//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;

if (numberOfReenteringLoops > 5)
throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method");

numberOfReenteringLoops++;
}
}

readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;

readonly FasterList<IEngine> _otherEngines;

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

readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
readonly EntitySubmissionScheduler _scheduler;
#if EXPERIMENTAL
readonly Type _structEntityViewEngineType;
readonly Type _groupedStructEntityViewsEngineType;
readonly SharedStructEntityViewLists _sharedStructEntityViewLists;
readonly SharedGroupedStructEntityViewsLists _sharedGroupedStructEntityViewLists;

readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
#endif
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
static Action<IHandleEntityViewEngine, IEntityView> _addEntityViewToEngine;
static Action<IHandleEntityViewEngine, IEntityView> _removeEntityViewFromEngine;
#endif
readonly EngineEntityViewDB _engineEntityViewDB;

class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
{
readonly T _entityViewsToAddBufferA = new T();
readonly T _entityViewsToAddBufferB = new T();

public DoubleBufferedEntityViews()
{
this.other = _entityViewsToAddBufferA;
this.current = _entityViewsToAddBufferB;
}

public T other { get; private set; }
public T current { get; private set; }
public void Swap()
{
var toSwap = other;
other = current;
current = toSwap;
}
}
class GenericEntityFactory : IEntityFactory
{
DataStructures.WeakReference<EnginesRoot> _weakEngine;

public GenericEntityFactory(DataStructures.WeakReference<EnginesRoot> weakReference)
{
_weakEngine = weakReference;
}

public void BuildEntity<T>(int entityID, object[] implementors = null) 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 BuildMetaEntity<T>(int metaEntityID, object[] implementors = null) where T : IEntityDescriptor, new()
{
_weakEngine.Target.BuildMetaEntity<T>(metaEntityID, implementors);
}

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

public void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
_weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors);
}

public void Preallocate<T>(int size) where T : IEntityDescriptor, new()
{
_weakEngine.Target.Preallocate<T>(size);
}
}
class GenericEntityFunctions : IEntityFunctions
{
public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
{
_weakReference = weakReference;
}

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

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

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

public void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
{
_weakReference.Target.RemoveEntity<T>(entityID);
}
readonly DataStructures.WeakReference<EnginesRoot> _weakReference;
}

public void Dispose()
{
foreach (var entity in _entityViewsDB)
{
if (entity.Value.isQueryiableEntityView == true)
{
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);
}
}
}
}
}

+ 238
- 0
ECS/EnginesRootEngines.cs View File

@@ -0,0 +1,238 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using Svelto.ECS.Schedulers;
using Svelto.Utilities;
using Svelto.WeakEvents;

#if EXPERIMENTAL
using Svelto.ECS.Experimental;
using Svelto.ECS.Experimental.Internal;
#endif

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
#endif

namespace Svelto.ECS
{
public partial class EnginesRoot : IDisposable
{
/// <summary>
/// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot
/// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks
/// periodically if new entity must be submited to the database and the engines. It's an external
/// dependencies to be indipendent by the running platform as the user can define it.
/// The EntitySubmissionScheduler cannot hold an EnginesRoot reference, that's why
/// it must receive a weak reference of the EnginesRoot callback.
/// </summary>
public EnginesRoot(EntitySubmissionScheduler entityViewScheduler)
{
_entityViewEngines = new Dictionary<Type, FasterList<IHandleEntityViewEngine>>();
_otherEngines = new FasterList<IEngine>();

_entityViewsDB = new Dictionary<Type, ITypeSafeList>();
_metaEntityViewsDB = new Dictionary<Type, ITypeSafeList>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_entityViewsDBdic = new Dictionary<Type, ITypeSafeDictionary>();
_entityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_metaEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();

_engineEntityViewDB = new EngineEntityViewDB(_entityViewsDB, _entityViewsDBdic, _metaEntityViewsDB, _groupEntityViewsDB);

_scheduler = entityViewScheduler;
_scheduler.Schedule(new WeakAction(SubmitEntityViews));
#if EXPERIMENTAL
_sharedStructEntityViewLists = new SharedStructEntityViewLists();
_sharedGroupedStructEntityViewLists = new SharedGroupedStructEntityViewsLists();

_structEntityViewEngineType = typeof(IStructEntityViewEngine<>);
_groupedStructEntityViewsEngineType = typeof(IGroupedStructEntityViewsEngine<>);
_implementedInterfaceTypes = new Dictionary<Type, Type[]>();
#endif
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
_addEntityViewToEngine = AddEntityViewToEngine;
_removeEntityViewFromEngine = RemoveEntityViewFromEngine;

UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Engine Debugger");
debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
#endif
}

public void AddEngine(IEngine engine)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
Profiler.EngineProfiler.AddEngine(engine);
#endif
var engineType = engine.GetType();
#if EXPERIMENTAL
bool engineAdded;
var implementedInterfaces = engineType.GetInterfaces();
CollectImplementedInterfaces(implementedInterfaces);
engineAdded = CheckSpecialEngine(engine);
#endif
var viewEngine = engine as IHandleEntityViewEngine;
if (viewEngine != null)
CheckEntityViewsEngine(viewEngine, engineType);
else
_otherEngines.Add(engine);
var queryableEntityViewEngine = engine as IQueryingEntityViewEngine;
if (queryableEntityViewEngine != null)
{
queryableEntityViewEngine.entityViewsDB = _engineEntityViewDB;
queryableEntityViewEngine.Ready();
}
}
#if EXPERIMENTAL
void CollectImplementedInterfaces(Type[] implementedInterfaces)
{
_implementedInterfaceTypes.Clear();

var type = typeof(IHandleEntityViewEngine);

for (int index = 0; index < implementedInterfaces.Length; index++)
{
var interfaceType = implementedInterfaces[index];

if (type.IsAssignableFrom(interfaceType) == false)
continue;

if (false == interfaceType.IsGenericTypeEx())
{
continue;
}

var genericTypeDefinition = interfaceType.GetGenericTypeDefinition();

_implementedInterfaceTypes.Add(genericTypeDefinition, interfaceType.GetGenericArguments());
}
}
bool CheckSpecialEngine(IEngine engine)
{
if (_implementedInterfaceTypes.Count == 0) return false;

bool engineAdded = false;

if (_implementedInterfaceTypes.ContainsKey(_structEntityViewEngineType))
{
((IStructEntityViewEngine)engine).CreateStructEntityViews
(_sharedStructEntityViewLists);
}

if (_implementedInterfaceTypes.ContainsKey(_groupedStructEntityViewsEngineType))
{
((IGroupedStructEntityViewsEngine)engine).CreateStructEntityViews
(_sharedGroupedStructEntityViewLists);
}

return engineAdded;
}
#endif
void CheckEntityViewsEngine(IEngine engine, Type engineType)
{
var baseType = engineType.GetBaseType();

if (baseType.IsGenericTypeEx())
{
var genericArguments = baseType.GetGenericArguments();
AddEngine(engine as IHandleEntityViewEngine, genericArguments, _entityViewEngines);
#if EXPERIMENTAL
var activableEngine = engine as IHandleActivableEntityEngine;
if (activableEngine != null)
AddEngine(activableEngine, genericArguments, _activableViewEntitiesEngines);
#endif

return;
}

throw new Exception("Not Supported Engine");
}

//The T parameter allows to pass datastructure sthat not necessarly are
//defined with IEngine, but must be defined with IEngine implementations
static void AddEngine<T>(T engine, Type[] types,
Dictionary<Type, FasterList<T>> engines) where T:IEngine
{
for (int i = 0; i < types.Length; i++)
{
FasterList<T> list;

var type = types[i];

if (engines.TryGetValue(type, out list) == false)
{
list = new FasterList<T>();

engines.Add(type, list);
}

list.Add(engine);
}
}

readonly Dictionary<Type, FasterList<IHandleEntityViewEngine>> _entityViewEngines;

readonly FasterList<IEngine> _otherEngines;

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

readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _entityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<Type, ITypeSafeList>> _metaEntityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
readonly EntitySubmissionScheduler _scheduler;
#if EXPERIMENTAL
readonly Type _structEntityViewEngineType;
readonly Type _groupedStructEntityViewsEngineType;
readonly SharedStructEntityViewLists _sharedStructEntityViewLists;
readonly SharedGroupedStructEntityViewsLists _sharedGroupedStructEntityViewLists;

readonly Dictionary<Type, Type[]> _implementedInterfaceTypes;
#endif
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
static Action<IHandleEntityViewEngine, IEntityView> _addEntityViewToEngine;
static Action<IHandleEntityViewEngine, IEntityView> _removeEntityViewFromEngine;
#endif
readonly EngineEntityViewDB _engineEntityViewDB;

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

+ 337
- 0
ECS/EnginesRootEntities.cs View File

@@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;

#if EXPERIMENTAL
using Svelto.ECS.Experimental;
using Svelto.ECS.Experimental.Internal;
#endif

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
#endif

namespace Svelto.ECS
{
public partial class EnginesRoot : IDisposable
{
/// <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));
}

public IEntityFunctions GenerateEntityFunctions()
{
return new GenericEntityFunctions(new DataStructures.WeakReference<EnginesRoot>(this));
}

/// <summary>
/// The EntityDescriptor doesn't need to be ever instantiated. It just describes the Entity
/// itself in terms of EntityViews to build. The Implementors are passed to fill the
/// references of the EntityViews components. Please read the articles on my blog
/// to understand better the terminologies
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entityID"></param>
/// <param name="implementors"></param>
void BuildEntity<T>(int entityID, object[] implementors = null) where T : IEntityDescriptor, new()
{
EntityFactory.BuildEntityViews
(entityID, _entityViewsToAdd.current, EntityDescriptorTemplate<T>.Default, implementors);
}

/// <summary>
/// When the type of the entity is not known (this is a special case!) an EntityDescriptorInfo
/// can be built in place of the generic parameter T.
/// </summary>
/// <param name="entityID"></param>
/// <param name="entityDescriptor"></param>
/// <param name="implementors"></param>
void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
EntityFactory.BuildEntityViews
(entityID, _entityViewsToAdd.current, 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, _entityViewsToAdd.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.
/// </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 = null) where T : IEntityDescriptor, new()
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
_groupedEntityViewsToAdd.current,
EntityDescriptorTemplate<T>.Default,
implementors);
}

void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
_groupedEntityViewsToAdd.current,
entityDescriptor, implementors);
}

void Preallocate<T>(int size) where T : IEntityDescriptor, new()
{
var entityViewsToBuild = EntityDescriptorTemplate<T>.Default.entityViewsToBuild;
int count = entityViewsToBuild.Length;

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

ITypeSafeList dbList;
if (_entityViewsDB.TryGetValue(entityViewType, out dbList) == false)
_entityViewsDB[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
else
dbList.ReserveCapacity(size);

if (_entityViewsToAdd.current.TryGetValue(entityViewType, out dbList) == false)
_entityViewsToAdd.current[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
else
dbList.ReserveCapacity(size);
}
}

void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo)
{
var removeEntityImplementor = removeInfo as RemoveEntityImplementor;

if (removeEntityImplementor.isInAGroup)
InternalRemove(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, removeEntityImplementor.groupID, _entityViewsDB);
else
InternalRemove(removeEntityImplementor.removeEntityInfo.entityViewsToBuild, entityID, _entityViewsDB);
}

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

void RemoveMetaEntity<T>(int metaEntityID) where T : IEntityDescriptor, new()
{
InternalRemove(EntityDescriptorTemplate<T>.Default.entityViewsToBuild, metaEntityID, _metaEntityViewsDB);
}

void RemoveEntityFromGroup<T>(int entityID, int groupID) where T : IEntityDescriptor, new()
{
InternalRemove(EntityDescriptorTemplate<T>.Default.entityViewsToBuild, entityID, _groupEntityViewsDB[groupID]);
}

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

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

ITypeSafeList entityViews = entityViewsDB[entityViewType];
if (entityViews.UnorderedRemove(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);

RemoveEntityViewFromEngines(_entityViewEngines, entityView, entityViewType);
}
}
}

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

for (int i = 0; i < entityViewBuildersCount; i++)
{
Type entityViewType = entityViewBuilders[i].GetEntityViewType();
Dictionary<Type, ITypeSafeList> dictionary = _groupEntityViewsDB[groupID];

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

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

InternalRemove(entityViewBuilders, entityID, entityViewsDB);
}

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 (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorRemoveDuration(_removeEntityViewFromEngine, fastList[j], entityView);
#else
fastList[j].Remove(entityView);
#endif
}
}
}

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
static void AddEntityViewToEngine(IHandleEntityViewEngine engine, IEntityView entityView)
{
engine.Add(entityView);
}

static void RemoveEntityViewFromEngine(IHandleEntityViewEngine engine, IEntityView entityView)
{
engine.Remove(entityView);
}
#endif

class GenericEntityFactory : IEntityFactory
{
DataStructures.WeakReference<EnginesRoot> _weakEngine;

public GenericEntityFactory(DataStructures.WeakReference<EnginesRoot> weakReference)
{
_weakEngine = weakReference;
}

public void BuildEntity<T>(int entityID, object[] implementors = null) 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 BuildMetaEntity<T>(int metaEntityID, object[] implementors = null) where T : IEntityDescriptor, new()
{
_weakEngine.Target.BuildMetaEntity<T>(metaEntityID, implementors);
}

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

public void BuildEntityInGroup(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors = null)
{
_weakEngine.Target.BuildEntityInGroup(entityID, groupID, entityDescriptor, implementors);
}

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

class GenericEntityFunctions : IEntityFunctions
{
public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
{
_weakReference = weakReference;
}

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

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

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

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

readonly DataStructures.WeakReference<EnginesRoot> _weakReference;
}

public void Dispose()
{
foreach (var entity in _entityViewsDB)
{
if (entity.Value.isQueryiableEntityView == true)
{
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);
}
}
}
}
}

+ 160
- 0
ECS/EnginesRootSubmission.cs View File

@@ -0,0 +1,160 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.ECS.Internal;

#if EXPERIMENTAL
using Svelto.ECS.Experimental;
using Svelto.ECS.Experimental.Internal;
#endif

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
#endif

namespace Svelto.ECS
{
public partial class EnginesRoot : IDisposable
{
void SubmitEntityViews()
{
bool newEntityViewsHaveBeenAddedWhileIterating =
_metaEntityViewsToAdd.current.Count > 0
|| _entityViewsToAdd.current.Count > 0
|| _groupedEntityViewsToAdd.current.Count > 0;

int numberOfReenteringLoops = 0;

while (newEntityViewsHaveBeenAddedWhileIterating)
{
//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);

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

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

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

if (numberOfReenteringLoops > 5)
throw new Exception("possible infinite loop found creating Entities inside IEntityViewsEngine Add method, please consider building entities outside IEntityViewsEngine Add method");

numberOfReenteringLoops++;
}
}

void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<Type, ITypeSafeList> entityViewsToAdd,
Dictionary<Type, ITypeSafeList> entityViewsDB)
{
foreach (var entityViewList in entityViewsToAdd)
{
AddEntityViewToDB(entityViewsDB, entityViewList);

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

foreach (var entityViewList in entityViewsToAdd)
{
if (entityViewList.Value.isQueryiableEntityView)
{
AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewList.Value,
entityViewList.Key);
}
}
}

void AddGroupEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupedEntityViewsToAdd,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
Dictionary<Type, ITypeSafeList> entityViewsDB)
{
foreach (var group in groupedEntityViewsToAdd)
{
AddEntityViewsToTheDBAndSuitableEngines(group.Value, entityViewsDB);

AddEntityViewsToGroupDB(groupEntityViewsDB, @group);
}
}

static void AddEntityViewsToGroupDB(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB,
KeyValuePair<int, Dictionary<Type, ITypeSafeList>> @group)
{
Dictionary<Type, ITypeSafeList> groupedEntityViewsByType;

if (groupEntityViewsDB.TryGetValue(@group.Key, out groupedEntityViewsByType) == false)
groupedEntityViewsByType = groupEntityViewsDB[@group.Key] = new Dictionary<Type, ITypeSafeList>();

foreach (var entityView in @group.Value)
{
groupedEntityViewsByType.Add(entityView.Key, entityView.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)
{
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)
{
FasterList<IHandleEntityViewEngine> enginesForEntityView;

if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
{
int viewsCount;

var entityViews = entityViewsList.ToArrayFast(out viewsCount);

for (int i = 0; i < viewsCount; i++)
{
int count;
var fastList = FasterList<IHandleEntityViewEngine>.NoVirt.ToArrayFast(enginesForEntityView, out count);
IEntityView entityView = entityViews[i];
for (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
EngineProfiler.MonitorAddDuration(_addEntityViewToEngine, fastList[j], entityView);
#else
fastList[j].Add(entityView);
#endif
}
}
}
}
}
}

+ 43
- 28
ECS/EntityDescriptorTemplate.cs View File

@@ -1,3 +1,5 @@
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using System;
using System.Collections.Generic;

@@ -8,20 +10,22 @@ namespace Svelto.ECS
IEntityViewBuilder[] entityViewsToBuild { get; }
}
static class EntityDescriptorTemplate<TType> where TType : IEntityDescriptor, new()
internal static class EntityDescriptorTemplate<TType> where TType : IEntityDescriptor, new()
{
public static readonly EntityDescriptorInfo Default = new EntityDescriptorInfo(new TType());
}

public class EntityDescriptorInfo
{
public readonly IEntityDescriptor descriptor;
public readonly string name;
readonly internal IEntityViewBuilder[] entityViewsToBuild;
readonly internal RemoveEntityImplementor removeEntityImplementor;
internal readonly string name;

public EntityDescriptorInfo(IEntityDescriptor entityDescriptor)
internal EntityDescriptorInfo(IEntityDescriptor descriptor)
{
descriptor = entityDescriptor;
name = descriptor.ToString();
entityViewsToBuild = descriptor.entityViewsToBuild;
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuild);
}
}
}
@@ -31,11 +35,11 @@ namespace Svelto.ECS.Internal
static class EntityFactory
{
internal static void BuildGroupedEntityViews(int entityID, int groupID,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuild = entityViewsToBuildDescriptor.descriptor.entityViewsToBuild;
var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild;
int count = entityViewsToBuild.Length;

RemoveEntityImplementor removeEntityImplementor = null;
@@ -53,6 +57,8 @@ namespace Svelto.ECS.Internal
groupEntityViewsByType.Add(groupID, groupedEntityViewsTyped);
}

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

@@ -62,7 +68,7 @@ namespace Svelto.ECS.Internal
if (entityViewObjectToFill != null)
{
if (removeEntityImplementor == null)
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.descriptor, groupID);
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.entityViewsToBuild, groupID);

FillEntityView(entityViewObjectToFill as EntityView, implementors, removeEntityImplementor,
entityViewsToBuildDescriptor.name);
@@ -70,20 +76,21 @@ namespace Svelto.ECS.Internal
}
}

internal static void BuildEntityViews(int entityID, Dictionary<Type, ITypeSafeList> entityViewsByType,
internal static void BuildEntityViews(int entityID,
Dictionary<Type, ITypeSafeList> entityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
object[] implementors)
{
var entityViewsToBuild = entityViewsToBuildDescriptor.descriptor.entityViewsToBuild;
var entityViewsToBuild = entityViewsToBuildDescriptor.entityViewsToBuild;
int count = entityViewsToBuild.Length;
RemoveEntityImplementor removeEntityImplementor = null;

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

@@ -92,23 +99,26 @@ namespace Svelto.ECS.Internal
//it's a EntityView
if (entityViewObjectToFill != null)
{
if (removeEntityImplementor == null)
removeEntityImplementor = new RemoveEntityImplementor(entityViewsToBuildDescriptor.descriptor);
FillEntityView(entityViewObjectToFill as EntityView, implementors, removeEntityImplementor,
FillEntityView(entityViewObjectToFill as EntityView, implementors, entityViewsToBuildDescriptor.removeEntityImplementor,
entityViewsToBuildDescriptor.name);
}
}
}

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

var entityViewsPoolWillBeCreated =
entityViewsByType.TryGetValue(entityViewType, out entityViewsList) == false;
var entityViewObjectToFill = entityViewBuilderId.BuildEntityViewAndAddToList(ref entityViewsList, entityID);

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);
@@ -116,6 +126,13 @@ namespace Svelto.ECS.Internal
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)
{
@@ -136,12 +153,16 @@ namespace Svelto.ECS.Internal
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

implementorsByType[componentType] = new Tuple<object, int>(implementor, 0);
}
}
#if DEBUG && !PROFILER
@@ -153,8 +174,8 @@ namespace Svelto.ECS.Internal
int count;

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

var removeEntityComponentType = typeof(IRemoveEntityComponent);

@@ -211,13 +232,7 @@ namespace Svelto.ECS.Internal
item2 = v;
}
}
#endif
//this is used to avoid newing a dictionary every time, but it's used locally only
#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
#endif
static Dictionary<Type, Type[]> _cachedTypes = new Dictionary<Type, Type[]>();

const string DUPLICATE_IMPLEMENTOR_ERROR =


+ 9
- 22
ECS/EntityView.cs View File

@@ -20,19 +20,17 @@ namespace Svelto.ECS
{
public int ID { get { return _ID; } }

abstract internal KeyValuePair<Type, Action<EntityView, object>>[]
EntityViewBlazingFastReflection(out int count);

protected int _ID;
internal FasterList<KeyValuePair<Type, Action<EntityView, object>>> EntityViewBlazingFastReflection;
internal int _ID;
}

public class EntityView<T>: EntityView where T: EntityView
internal static class EntityView<T> where T: EntityView, new()
{
internal static TEntityViewType BuildEntityView<TEntityViewType>(int ID) where TEntityViewType: EntityView<T>, new()
internal static T BuildEntityView(int ID)
{
if (FieldCache.list.Count == 0)
if (FieldCache<T>.list.Count == 0)
{
var type = typeof(TEntityViewType);
var type = typeof(T);

var fields = type.GetFields(BindingFlags.Public |
BindingFlags.Instance);
@@ -43,26 +41,15 @@ namespace Svelto.ECS

Action<EntityView, object> setter = FastInvoke<EntityView>.MakeSetter(field);

FieldCache.Add(new KeyValuePair<Type, Action<EntityView, object>>(field.FieldType, setter));
FieldCache<T>.list.Add(new KeyValuePair<Type, Action<EntityView, object>>(field.FieldType, setter));
}
}

return new TEntityViewType { _ID = ID };
}

override internal KeyValuePair<Type, Action<EntityView, object>>[]
EntityViewBlazingFastReflection(out int count)
{
return FasterList<KeyValuePair<Type, Action<EntityView, object>>>.NoVirt.ToArrayFast(FieldCache.list, out count);
return new T { _ID = ID, EntityViewBlazingFastReflection = FieldCache<T>.list };
}

static class FieldCache
static class FieldCache<W> where W:T
{
internal static void Add(KeyValuePair<Type, Action<EntityView, object>> setter)
{
list.Add(setter);
}
internal static readonly FasterList<KeyValuePair<Type, Action<EntityView, object>>> list = new FasterList<KeyValuePair<Type, Action<EntityView, object>>>();
}
}


+ 11
- 11
ECS/EntityViewBuilder.cs View File

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

Type GetEntityViewType();
}

public class EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : EntityView<EntityViewType>, new()
public class EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : EntityView, new()
{
public IEntityView BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID)
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, int entityID, out IEntityView entityView)
{
if (list == null)
list = new TypeSafeFasterListForECSForClasses<EntityViewType>();

var castedList = list as TypeSafeFasterListForECSForClasses<EntityViewType>;

var entityView = EntityView<EntityViewType>.BuildEntityView<EntityViewType>(entityID);
var lentityView = EntityView<EntityViewType>.BuildEntityView(entityID);

castedList.Add(entityView);
castedList.Add(lentityView);

return entityView;
entityView = lentityView;
}

public ITypeSafeList Preallocate(ref ITypeSafeList list, int size)
@@ -47,19 +47,19 @@ namespace Svelto.ECS

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

var castedList = list as TypeSafeFasterListForECSForStructs<EntityViewType>;

castedList.Add(entityView);
castedList.Add(lentityView);

return null;
entityView = null;
}

public ITypeSafeList Preallocate(ref ITypeSafeList list, int size)


+ 1
- 1
ECS/Extensions/Unity/UnitySumbmissionNodeScheduler.cs View File

@@ -13,7 +13,7 @@ namespace Svelto.ECS.Schedulers
//the entityViews immediatly just because convenient for your game
//logic. This is not how it works.
public class UnitySumbmissionEntityViewScheduler : EntityViewSubmissionScheduler
public class UnitySumbmissionEntityViewScheduler : EntitySubmissionScheduler
{
public UnitySumbmissionEntityViewScheduler()
{


+ 21
- 21
ECS/GenericEntityDescriptor.cs View File

@@ -2,7 +2,7 @@

namespace Svelto.ECS
{
public class GenericEntityDescriptor<T>:IEntityDescriptor where T : EntityView<T>, new()
public class GenericEntityDescriptor<T>:IEntityDescriptor where T : EntityView, new()
{
static GenericEntityDescriptor()
{
@@ -18,8 +18,8 @@ namespace Svelto.ECS
}

public class GenericEntityDescriptor<T, U> : IEntityDescriptor where T : EntityView<T>, new()
where U : EntityView<U>, new()
public class GenericEntityDescriptor<T, U> : IEntityDescriptor where T : EntityView, new()
where U : EntityView, new()
{
static GenericEntityDescriptor()
{
@@ -34,9 +34,9 @@ namespace Svelto.ECS
public static readonly IEntityViewBuilder[] entityViewBuilders;
}

public class GenericEntityDescriptor<T, U, V> : IEntityDescriptor where T : EntityView<T>, new()
where U : EntityView<U>, new()
where V : EntityView<V>, new()
public class GenericEntityDescriptor<T, U, V> : IEntityDescriptor where T : EntityView, new()
where U : EntityView, new()
where V : EntityView, new()
{
static GenericEntityDescriptor()
{
@@ -51,10 +51,10 @@ namespace Svelto.ECS
public static readonly IEntityViewBuilder[] entityViewBuilders;
}

public class GenericEntityDescriptor<T, U, V, W> : IEntityDescriptor where T : EntityView<T>, new()
where U : EntityView<U>, new()
where V : EntityView<V>, new()
where W : EntityView<W>, new()
public class GenericEntityDescriptor<T, U, V, W> : IEntityDescriptor where T : EntityView, new()
where U : EntityView, new()
where V : EntityView, new()
where W : EntityView, new()
{
static GenericEntityDescriptor()
{
@@ -69,11 +69,11 @@ namespace Svelto.ECS
public static readonly IEntityViewBuilder[] entityViewBuilders;
}

public class GenericEntityDescriptor<T, U, V, W, X> : IEntityDescriptor where T : EntityView<T>, new()
where U : EntityView<U>, new()
where V : EntityView<V>, new()
where W : EntityView<W>, new()
where X : EntityView<X>, new()
public class GenericEntityDescriptor<T, U, V, W, X> : IEntityDescriptor where T : EntityView, new()
where U : EntityView, new()
where V : EntityView, new()
where W : EntityView, new()
where X : EntityView, new()
{
static GenericEntityDescriptor()
{
@@ -88,12 +88,12 @@ namespace Svelto.ECS
public static readonly IEntityViewBuilder[] entityViewBuilders;
}

public class GenericEntityDescriptor<T, U, V, W, X, Y> : IEntityDescriptor where T : EntityView<T>, new()
where U : EntityView<U>, new()
where V : EntityView<V>, new()
where W : EntityView<W>, new()
where X : EntityView<X>, new()
where Y : EntityView<Y>, new()
public class GenericEntityDescriptor<T, U, V, W, X, Y> : IEntityDescriptor where T : EntityView, new()
where U : EntityView, new()
where V : EntityView, new()
where W : EntityView, new()
where X : EntityView, new()
where Y : EntityView, new()
{
static GenericEntityDescriptor()
{


+ 5
- 5
ECS/IEngineEntityViewDB.cs View File

@@ -4,9 +4,9 @@ namespace Svelto.ECS
{
public interface IEngineEntityViewDB
{
FasterReadOnlyList<T> QueryEntityViews<T>() where T:EntityView<T>, new();
FasterReadOnlyList<T> QueryMetaEntityViews<T>() where T: EntityView<T>, new();
FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int group) where T: EntityView<T>, new();
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();
T[] QueryEntityViewsAsArray<T>(out int count) where T: IEntityView;
T[] QueryGroupedEntityViewsAsArray<T>(int @group, out int count) where T: IEntityView;
@@ -15,8 +15,8 @@ namespace Svelto.ECS
bool TryQueryEntityView<T>(int ID, out T entityView) where T : IEntityView;
T QueryEntityView<T>(int ID) where T: IEntityView;

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


+ 1
- 1
ECS/IEnginesInterfaces.cs View File

@@ -15,7 +15,7 @@ namespace Svelto.ECS
public interface IEntityFunctions
{
void RemoveEntity(int entityID, IRemoveEntityComponent template);
void RemoveEntity(int entityID, IRemoveEntityComponent removeInfo);

void RemoveEntity<T>(int entityID) where T:IEntityDescriptor, new();


+ 6
- 6
ECS/MultiEntityViewsEngine.cs View File

@@ -2,7 +2,7 @@ using Svelto.ECS.Internal;

namespace Svelto.ECS.Internal
{
public abstract class MultiEntityViewsEngine<T>:IHandleEntityViewEngine where T:EntityView<T>, new()
public abstract class MultiEntityViewsEngine<T>:IHandleEntityViewEngine where T:EntityView, new()
{
protected abstract void Add(T entityView);
protected abstract void Remove(T entityView);
@@ -22,8 +22,8 @@ namespace Svelto.ECS.Internal
namespace Svelto.ECS
{
public abstract class MultiEntityViewsEngine<T, U> : MultiEntityViewsEngine<T>
where T:EntityView<T>, new()
where U:EntityView<U>, new()
where T:EntityView, new()
where U:EntityView, new()
{
protected abstract void Add(U entityView);
protected abstract void Remove(U entityView);
@@ -55,9 +55,9 @@ namespace Svelto.ECS
}

public abstract class MultiEntityViewsEngine<T, U, V> : MultiEntityViewsEngine<T, U>
where T : EntityView<T>, new()
where U : EntityView<U>, new()
where V : EntityView<V>, new()
where T : EntityView, new()
where U : EntityView, new()
where V : EntityView, new()
{
protected abstract void Add(V entityView);
protected abstract void Remove(V entityView);


+ 12
- 18
ECS/RemoveEntityImplementor.cs View File

@@ -2,17 +2,20 @@
{
sealed class RemoveEntityImplementor : IRemoveEntityComponent
{
public RemoveEntityImplementor(IEntityDescriptor descriptor, int groupID) : this(descriptor)
public RemoveEntityImplementor(IEntityViewBuilder[] entityViews, int groupID):this(entityViews)
{
removeEntityInfo = new RemoveEntityInfo(descriptor, groupID);
this.groupID = groupID;
isInAGroup = true;
}

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

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

@@ -23,20 +26,11 @@ namespace Svelto.ECS

public struct RemoveEntityInfo
{
readonly public IEntityDescriptor descriptor;
readonly public int groupID;
readonly public bool isInAGroup;

public RemoveEntityInfo(IEntityDescriptor descriptor) : this()
{
this.descriptor = descriptor;
}

public RemoveEntityInfo(IEntityDescriptor descriptor, int groupID)
readonly internal IEntityViewBuilder[] entityViewsToBuild;
public RemoveEntityInfo(IEntityViewBuilder[] entityViews) : this()
{
this.descriptor = descriptor;
this.groupID = groupID;
isInAGroup = true;
this.entityViewsToBuild = entityViews;
}
}
}

+ 1
- 1
ECS/SingleEntityViewEngine.cs View File

@@ -2,7 +2,7 @@ using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public abstract class SingleEntityViewEngine<T> : IHandleEntityViewEngine where T:EntityView<T>, new()
public abstract class SingleEntityViewEngine<T> : IHandleEntityViewEngine where T:EntityView, new()
{
public void Add(IEntityView entityView)
{


Loading…
Cancel
Save