Browse Source

mega refactoring, now EntityView and EntityStructs use almost exactly the same code

introduced EntityViewStruct
cut a lot of code not needed anymore
breaking change engines add and remove callback now accept only ref params
breaking change QueryEntityViewsAsArray renamed in to QueryEntityViewsCacheFriendly
tags/Rel25a
sebas77 6 years ago
parent
commit
ab5e5c94bd
25 changed files with 273 additions and 815 deletions
  1. +1
    -1
      Svelto.Common
  2. +2
    -1
      Svelto.ECS.csproj
  3. +62
    -14
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  4. +0
    -225
      Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs
  5. +0
    -10
      Svelto.ECS/DataStructures/TypeSafeFasterListForECSException.cs
  6. +3
    -12
      Svelto.ECS/EGID.cs
  7. +4
    -4
      Svelto.ECS/EnginesRoot.GenericEntityFactory.cs
  8. +2
    -2
      Svelto.ECS/EnginesRoot.GenericEntityFunctions.cs
  9. +5
    -8
      Svelto.ECS/EnginesRootEngines.cs
  10. +29
    -118
      Svelto.ECS/EnginesRootEntities.cs
  11. +16
    -45
      Svelto.ECS/EnginesRootSubmission.cs
  12. +21
    -18
      Svelto.ECS/EntityFactory.cs
  13. +42
    -25
      Svelto.ECS/EntityViewBuilder.cs
  14. +0
    -56
      Svelto.ECS/EntityViewStructBuilder.cs
  15. +16
    -13
      Svelto.ECS/EntityViewUtility.cs
  16. +29
    -43
      Svelto.ECS/EntityViewsDB.cs
  17. +1
    -1
      Svelto.ECS/ExclusiveGroups.cs
  18. +1
    -5
      Svelto.ECS/IEngine.cs
  19. +18
    -11
      Svelto.ECS/IEntityView.cs
  20. +3
    -5
      Svelto.ECS/IEntityViewBuilder.cs
  21. +5
    -5
      Svelto.ECS/IEntityViewsDB.cs
  22. +0
    -107
      Svelto.ECS/MixedEntityDescriptor.cs
  23. +7
    -68
      Svelto.ECS/MultiEntityViewsEngine.cs
  24. +3
    -3
      Svelto.ECS/Profiler/EngineProfiler.cs
  25. +3
    -15
      Svelto.ECS/SingleEntityViewEngine.cs

+ 1
- 1
Svelto.Common

@@ -1 +1 @@
Subproject commit 460c00846a3b547c4567aec8bdfff82a9861869c
Subproject commit 3c1360fcb86cdb70dcb00149a26d2064ec6fbe63

+ 2
- 1
Svelto.ECS.csproj View File

@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Svelto.ECS</AssemblyName>
<LangVersion>6</LangVersion>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Reflection" Version="4.3.0" />


+ 62
- 14
Svelto.ECS/DataStructures/TypeSafeDictionary.cs View File

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

@@ -13,20 +13,31 @@ namespace Svelto.ECS.Internal
/// </summary>
public interface ITypeSafeDictionary
{
void FillWithIndexedEntityViews(ITypeSafeList entityViews);
bool Remove(EGID entityId);
IEntityData GetIndexedEntityView(EGID entityID);
void RemoveEntityFromDicAndEngines(EGID entityGid,
Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>>
entityViewEnginesDB);
void RemoveEntityViewsFromEngines(
Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEngines);
void AddCapacity(int size);
bool Remove(long idGid);
ITypeSafeDictionary Create();
int Count { get; }
void FillWithIndexedEntityViews(ITypeSafeDictionary entityViews);
void AddEntityViewsToEngines(FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView);
}

class TypeSafeDictionaryForClass<TValue> : Dictionary<long, TValue>, ITypeSafeDictionary where TValue : IEntityData
class TypeSafeDictionary<TValue> : FasterDictionary<long, TValue>, ITypeSafeDictionary where TValue : IEntityData
{
internal static readonly ReadOnlyDictionary<long, TValue> Default =
new ReadOnlyDictionary<long, TValue>(new Dictionary<long, TValue>());
public TypeSafeDictionary(int size):base(size)
{}

public void FillWithIndexedEntityViews(ITypeSafeList entityViews)
public TypeSafeDictionary()
{}

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

try
{
@@ -43,16 +54,53 @@ namespace Svelto.ECS.Internal
}
}

public bool Remove(EGID entityId)
public void AddEntityViewsToEngines(FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView)
{
throw new NotImplementedException();
}

public void RemoveEntityFromDicAndEngines(EGID entityGid,
Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>>
entityViewEnginesDB)
{
TValue entity = this[entityGid.GID];

RemoveEntityViewsFromEngines(entityViewEnginesDB, ref entity);

Remove(entityGid.GID);
}

public void RemoveEntityViewsFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB, ref TValue entity)
{
base.Remove(entityId.GID);
FasterList<IHandleEntityViewEngineAbstracted> entityViewsEngines;
if (entityViewEnginesDB.TryGetValue(typeof(TValue), out entityViewsEngines))
for (int i = 0; i < entityViewEnginesDB.Count; i++)
(entityViewsEngines[i] as IHandleEntityStructEngine<TValue>).Remove(ref entity);
}
public void RemoveEntityViewsFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB)
{
int count;
TValue[] values = this.GetFasterValuesBuffer(out count);

for (int i = 0; i < count; i++)
{
TValue entity = values[i];

return Count > 0;
RemoveEntityViewsFromEngines(entityViewEnginesDB, ref entity);
}
}

public void AddCapacity(int size)
{
throw new NotImplementedException();
}

public IEntityData GetIndexedEntityView(EGID entityID)
public ITypeSafeDictionary Create()
{
return this[entityID.GID];
return new TypeSafeDictionary<TValue>();
}
}
}

+ 0
- 225
Svelto.ECS/DataStructures/TypeSafeFasterListForECS.cs View File

@@ -1,225 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using DBC;
using Svelto.DataStructures;

namespace Svelto.ECS.Internal
{
public interface ITypeSafeList : IEnumerable
{
bool isQueryiableEntityView { get; }
void AddRange(ITypeSafeList entityViewListValue);

ITypeSafeList Create();
bool MappedRemove(EGID entityID);
ITypeSafeDictionary CreateIndexedDictionary();
EGIDEnumerator EntityIDS();
void AddCapacity(int capacity);

void Fill(FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView);
}

public struct EGIDEnumerator:IEnumerable, IEnumerator
{
Dictionary<long, int>.Enumerator _keysEnumerator;

public EGIDEnumerator(Dictionary<long, int> mappedIndices)
{
_keysEnumerator = mappedIndices.GetEnumerator();
}

public bool MoveNext()
{
return _keysEnumerator.MoveNext();
}

public void Reset()
{
throw new NotImplementedException();
}

public object Current { get { return new EGID(_keysEnumerator.Current.Key);} }
public IEnumerator GetEnumerator()
{
return this;
}
}

class TypeSafeFasterListForECS<T> : FasterList<T> where T : IEntityData
{
protected TypeSafeFasterListForECS()
{
_mappedIndices = new Dictionary<long, int>();
}

protected TypeSafeFasterListForECS(int size) : base(size)
{
_mappedIndices = new Dictionary<long, int>();
}

public bool MappedRemove(EGID entityID)
{
var index = _mappedIndices[entityID.GID];

Check.Assert(entityID.GID == this[index].ID.GID,
"Something went wrong with the Svelto.ECS code, please contact the author");

_mappedIndices.Remove(entityID.GID);

if (UnorderedRemoveAt(index))
{
_mappedIndices[this[index].ID.GID] = index;
}

return Count > 0;
}

public void AddRange(ITypeSafeList entityViewListValue)
{
var index = Count;

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

for (var i = index; i < Count; ++i)
{
try
{
_mappedIndices.Add(this[i].ID.GID, i);
}
catch (Exception e)
{
throw new TypeSafeFasterListForECSException(e);
}
}
}

public new void Add(T entityView)
{
var index = Count;

base.Add(entityView);

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

public void AddCapacity(int capacity)
{
if (ToArrayFast().Length < Count + capacity)
Resize(Count + capacity);
}

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

readonly Dictionary<long, int> _mappedIndices;
}

class TypeSafeFasterListForECSForStructs<T> : TypeSafeFasterListForECS<T>, ITypeSafeList where T:struct, IEntityData
{
public TypeSafeFasterListForECSForStructs(int size) : base(size)
{}

public TypeSafeFasterListForECSForStructs()
{}

public ITypeSafeList Create()
{
return new TypeSafeFasterListForECSForStructs<T>();
}

public bool isQueryiableEntityView
{
get { return false; }
}

public ITypeSafeDictionary CreateIndexedDictionary()
{
throw new NotImplementedException();
}

public void Fill(FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView)
{
var thisfastList = NoVirt.ToArrayFast(this);
for (int i = 0; i < Count; i++)
{
int count;
var fastList = FasterList<IHandleEntityViewEngineAbstracted>.NoVirt.ToArrayFast(enginesForEntityView, out count);
for (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED
EngineProfiler.MonitorAddDuration<T>(fastList[j], entityView);
#else
(fastList[j] as IHandleEntityStructEngine<T>).Add(ref thisfastList[j]);
#endif
}
}
}

public ITypeSafeList Create(int size)
{
return new TypeSafeFasterListForECSForStructs<T>(size);
}
}
class TypeSafeFasterListForECSForClasses<T> : TypeSafeFasterListForECS<T>, ITypeSafeList where T:IEntityData, new()
{
public TypeSafeFasterListForECSForClasses(int size) : base(size)
{}

public TypeSafeFasterListForECSForClasses()
{}

public ITypeSafeList Create()
{
return new TypeSafeFasterListForECSForClasses<T>();
}

public bool isQueryiableEntityView
{
get { return true; }
}

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

public void Fill(FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView)
{
var thisfastList = NoVirt.ToArrayFast(this);
for (int i = 0; i < Count; i++)
{
int count;
var fastList = FasterList<IHandleEntityViewEngineAbstracted>.NoVirt.ToArrayFast(enginesForEntityView, out count);
for (int j = 0; j < count; j++)
{
#if ENGINE_PROFILER_ENABLED
EngineProfiler.MonitorAddDuration(fastList[j], entityView);
#else
(fastList[j] as IHandleEntityStructEngine<T>).Add(ref thisfastList[j]);
#endif
}
}
}

public ITypeSafeList Create(int size)
{
return new TypeSafeFasterListForECSForClasses<T>(size);
}
}
}

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

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

namespace Svelto.ECS
{
public class TypeSafeFasterListForECSException : Exception
{
public TypeSafeFasterListForECSException(Exception exception):base("Trying to add an Entity View with the same ID more than once", exception)
{}
}
}

+ 3
- 12
Svelto.ECS/EGID.cs View File

@@ -11,18 +11,19 @@ namespace Svelto.ECS
get { return _GID; }
}
public int ID
public int entityID
{
get { return (int) (_GID & 0xFFFFFFFF); }
}
public int group
public int groupID
{
get { return (int) (_GID >> 32); }
}

public EGID(int entityID, int groupID) : this()
{
DBC.Check.Require(groupID != ExclusiveGroups.StandardEntity, "can't use an exclusive group ID");
_GID = MAKE_GLOBAL_ID(entityID, groupID);
}
@@ -31,19 +32,9 @@ namespace Svelto.ECS
_GID = MAKE_GLOBAL_ID(entityID, ExclusiveGroups.StandardEntity);
}

internal EGID(long otherID)
{
_GID = otherID;
}

static long MAKE_GLOBAL_ID(int entityId, int groupId)
{
return (long)groupId << 32 | (uint)entityId;
}

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

+ 4
- 4
Svelto.ECS/EnginesRoot.GenericEntityFactory.cs View File

@@ -19,24 +19,24 @@ namespace Svelto.ECS

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

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

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

public void BuildEntity(int entityID, int groupID, EntityDescriptorInfo entityDescriptor,
object[] implementors)
{
_weakEngine.Target.BuildEntity(entityID, groupID, entityDescriptor, implementors);
_weakEngine.Target.BuildEntity(new EGID(entityID, groupID), entityDescriptor, implementors);
}

public void PreallocateEntitySpace<T>(int size) where T : IEntityDescriptor, new()


+ 2
- 2
Svelto.ECS/EnginesRoot.GenericEntityFunctions.cs View File

@@ -19,12 +19,12 @@ namespace Svelto.ECS

public void RemoveEntity(int entityID)
{
_weakReference.Target.RemoveEntity(entityID, ExclusiveGroups.StandardEntity);
_weakReference.Target.RemoveEntity(new EGID(entityID));
}
public void RemoveEntity(int entityID, int groupID)
{
_weakReference.Target.RemoveEntity(entityID, groupID);
_weakReference.Target.RemoveEntity(new EGID(entityID, groupID));
}

public void RemoveEntity(EGID entityEGID)


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

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

_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeList>>();
_groupEntityViewsDB[ExclusiveGroups.StandardEntity] = new Dictionary<Type, ITypeSafeList>();
_globalEntityViewsDBDic = new Dictionary<Type, ITypeSafeDictionary>();
_groupEntityViewsDB = new Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>();
_groupEntityViewsDB[ExclusiveGroups.StandardEntity] = new Dictionary<Type, ITypeSafeDictionary>();
_entityInfos = new Dictionary<long, IEntityViewBuilder[]>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>>();
_groupedEntityViewsToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>>();

_DB = new EntityViewsDB(_globalEntityViewsDBDic, _groupEntityViewsDB);
_DB = new EntityViewsDB(_groupEntityViewsDB);

_scheduler = entityViewScheduler;
_scheduler.Schedule(new WeakAction(SubmitEntityViews));
@@ -119,7 +116,7 @@ namespace Svelto.ECS
}

readonly Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> _entityViewEngines;
readonly FasterList<IEngine> _otherEngines;
readonly FasterList<IEngine> _otherEngines;
static readonly Type _entityViewType= typeof(IEntityData);
static readonly Type _objectType = typeof(object);


+ 29
- 118
Svelto.ECS/EnginesRootEntities.cs View File

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

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
@@ -15,10 +14,8 @@ namespace Svelto.ECS
public void Dispose()
{
foreach (var groups in _groupEntityViewsDB)
foreach (var entity in groups.Value)
if (entity.Value.isQueryiableEntityView == true)
foreach (var entityView in entity.Value)
RemoveEntityViewFromEngines(_entityViewEngines, entityView as IEntityData, entity.Key);
foreach (var entityList in groups.Value)
entityList.Value.RemoveEntityViewsFromEngines(_entityViewEngines);
}

///--------------------------------------------
@@ -35,18 +32,6 @@ namespace Svelto.ECS

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

void BuildEntity<T>(int entityID, object[] implementors = null) where T : IEntityDescriptor, new()
{
BuildEntity<T>
(entityID, ExclusiveGroups.StandardEntity, implementors);
}

void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptor, object[] implementors)
{
BuildEntity
(entityID, ExclusiveGroups.StandardEntity, entityDescriptor, implementors);
}

/// <summary>
/// Build the entity using the entityID, inside the group with Id groupID, using the
/// implementors (if necessary). The entityViews generated will be stored to be
@@ -54,25 +39,22 @@ namespace Svelto.ECS
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="entityID"></param>
/// <param name="groupID"></param>
/// <param name="implementors"></param>
void BuildEntity<T>(int entityID, int groupID, object[] implementors = null)
void BuildEntity<T>(EGID entityID, object[] implementors = null)
where T : IEntityDescriptor, new()
{
EntityFactory.BuildGroupedEntityViews(entityID, groupID,
EntityFactory.BuildGroupedEntityViews(entityID,
_groupedEntityViewsToAdd.current,
EntityDescriptorTemplate<T>.Default,
_entityInfos,
implementors);
}

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

@@ -95,12 +77,12 @@ namespace Svelto.ECS
var entityViewType = entityViewBuilder.GetEntityViewType();

//reserve space for the global pool
ITypeSafeList dbList;
ITypeSafeDictionary dbList;

//reserve space for the single group
Dictionary<Type, ITypeSafeList> @group;
Dictionary<Type, ITypeSafeDictionary> @group;
if (_groupEntityViewsDB.TryGetValue(groupID, out group) == false)
group = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeList>();
group = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeDictionary>();
if (group.TryGetValue(entityViewType, out dbList) == false)
group[entityViewType] = entityViewBuilder.Preallocate(ref dbList, size);
@@ -108,7 +90,7 @@ namespace Svelto.ECS
dbList.AddCapacity(size);
if (_groupedEntityViewsToAdd.current.TryGetValue(groupID, out group) == false)
group = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeList>();
group = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeDictionary>();
//reserve space to the temporary buffer
if (group.TryGetValue(entityViewType, out dbList) == false)
@@ -120,102 +102,40 @@ namespace Svelto.ECS
///--------------------------------------------
///
void RemoveEntity(int entityID, int groupID)
{
RemoveEntity(new EGID(entityID, groupID));
}

void RemoveEntity(EGID entityGID)
{
var entityViewBuilders = _entityInfos[entityGID.GID];
var typeSafeDictionary = _groupEntityViewsDB[entityGID.groupID][typeof(EntityInfoView)] as TypeSafeDictionary<EntityInfoView>;
var entityInfoView = typeSafeDictionary[entityGID.GID];
var entityViewBuilders = entityInfoView.entityViewsToBuild;
var entityViewBuildersCount = entityViewBuilders.Length;
//for each entity view generated by the entity descriptor
for (var i = 0; i < entityViewBuildersCount; i++)
{
var entityViewType = entityViewBuilders[i].GetEntityViewType();

if (entityViewBuilders[i].isQueryiableEntityView)
{
var group = _groupEntityViewsDB[entityGID.group];
InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityGID);
RemoveEntityViewFromDB(@group, entityViewType, entityGID);
}
var group = _groupEntityViewsDB[entityGID.groupID];
_groupEntityViewsDB[entityGID.groupID][entityViewType].RemoveEntityFromDicAndEngines(entityGID, _entityViewEngines);
RemoveEntityViewFromGroup(group, entityViewType, entityGID);
}

_entityInfos.Remove(entityGID.GID);
}

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

void RemoveGroupAndEntitiesFromDB(int groupID)
{
foreach (var group in _groupEntityViewsDB[groupID])
{
var entityViewType = group.Key;

var entities = group.Value.EntityIDS();

foreach (EGID entityID in entities)
{
if (group.Value.isQueryiableEntityView)
InternalRemoveEntityViewFromDBDicAndEngines(entityViewType, entityID);
}
}
foreach (var entiTypeSafeList in _groupEntityViewsDB[groupID])
entiTypeSafeList.Value.RemoveEntityViewsFromEngines(_entityViewEngines);

_groupEntityViewsDB.Remove(groupID);
}

void InternalRemoveEntityViewFromDBDicAndEngines(Type entityViewType, EGID id)
{
var typeSafeDictionary = _globalEntityViewsDBDic[entityViewType];
{
var entityView = typeSafeDictionary.GetIndexedEntityView(id);

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

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

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

void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID)
@@ -224,15 +144,17 @@ namespace Svelto.ECS
"can't move an entity to the same group where it already belongs to");

var entityegid = new EGID(entityID, fromGroupID);
var entityViewBuilders = _entityInfos[entityegid.GID];
var entityViewBuilders =
((TypeSafeDictionary<EntityInfoView>) _groupEntityViewsDB[fromGroupID][typeof(EntityInfoView)])
[entityegid.GID].entityViewsToBuild;
var entityViewBuildersCount = entityViewBuilders.Length;

var groupedEntities = _groupEntityViewsDB[fromGroupID];

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

_groupEntityViewsDB.Add(toGroupID, groupedEntityViewsTyped);
}
@@ -243,30 +165,19 @@ namespace Svelto.ECS
var entityViewType = entityViewBuilder.GetEntityViewType();

var fromSafeList = groupedEntities[entityViewType];
ITypeSafeList toSafeList;
ITypeSafeDictionary toSafeList;

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

entityViewBuilder.MoveEntityView(entityegid, fromSafeList, toSafeList);
fromSafeList.MappedRemove(entityegid);
fromSafeList.Remove(entityegid.GID);
}

_entityInfos.Remove(entityegid.GID);
_entityInfos.Add(new EGID(entityID, toGroupID).GID, entityViewBuilders);
}

readonly EntityViewsDB _DB;
//grouped set of entity views, this is the standard way to handle entity views
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
//TODO: Use faster dictionary and merge these two?
//indexable entity views when the entity ID is known. Usually useful to handle
//event based logic.
readonly Dictionary<Type, ITypeSafeDictionary> _globalEntityViewsDBDic;
readonly Dictionary<long, IEntityViewBuilder[]> _entityInfos;
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityViewsDB;
}
}

+ 16
- 45
Svelto.ECS/EnginesRootSubmission.cs View File

@@ -40,85 +40,56 @@ namespace Svelto.ECS
}
}
//todo: can I make the entity creation less complicated?
void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeList>> groupsToSubmit)
void AddEntityViewsToTheDBAndSuitableEngines(Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupsToSubmit)
{
//for each groups there is a dictionary of built lists of EntityView grouped by type
foreach (var groupToSubmit in groupsToSubmit)
{
Dictionary<Type, ITypeSafeList> groupDB;
Dictionary<Type, ITypeSafeDictionary> groupDB;
int groupID = groupToSubmit.Key;

//if the group doesn't exist in the current DB let's create it frst
if (_groupEntityViewsDB.TryGetValue(groupID, out groupDB) == false)
groupDB = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeList>();
groupDB = _groupEntityViewsDB[groupID] = new Dictionary<Type, ITypeSafeDictionary>();

foreach (var entityViewsPerType in groupToSubmit.Value)
foreach (var entityViewList in groupToSubmit.Value)
{
//add the entity View in the group
if (entityViewsPerType.Value.isQueryiableEntityView == true)
AddEntityViewToDB(groupDB, entityViewsPerType);
//and it's not a struct, add in the indexable DB too
AddEntityViewToEntityViewsDictionary(_globalEntityViewsDBDic, entityViewsPerType.Value, entityViewsPerType.Key);
ITypeSafeDictionary dbList;
if (groupDB.TryGetValue(entityViewList.Key, out dbList) == false)
dbList = groupDB[entityViewList.Key] = entityViewList.Value.Create();

dbList.FillWithIndexedEntityViews(entityViewList.Value);
}
}

//then submit everything in the engines, so that the DB is up to date
//with all the entity views and struct created by the entity built
foreach (var groupToSubmit in groupsToSubmit)
{
{
foreach (var entityViewsPerType in groupToSubmit.Value)
{
var type = entityViewsPerType.Key;
for (var current = type;
current != _entityViewType && current != _objectType && current != _valueType;
current = current.BaseType)
AddEntityViewToTheSuitableEngines(_entityViewEngines, entityViewsPerType.Value,
AddEntityViewsToTheSuitableEngines(_entityViewEngines, entityViewsPerType.Value,
current);
}
}
}

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)
{
if (entityViews.isQueryiableEntityView == true)
{
ITypeSafeDictionary entityViewsDic;
if (entityViewsDBdic.TryGetValue(entityViewType, out entityViewsDic) == false)
entityViewsDic = entityViewsDBdic[entityViewType] = entityViews.CreateIndexedDictionary();
entityViewsDic.FillWithIndexedEntityViews(entityViews);
}
}

static void AddEntityViewToTheSuitableEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEngines,
ITypeSafeList entityViewsList,
Type entityViewType)
static void AddEntityViewsToTheSuitableEngines( Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEngines,
ITypeSafeDictionary entityViewsList,
Type entityViewType)
{
FasterList<IHandleEntityViewEngineAbstracted> enginesForEntityView;

if (entityViewEngines.TryGetValue(entityViewType, out enginesForEntityView))
{
entityViewsList.Fill(enginesForEntityView);
}
entityViewsList.AddEntityViewsToEngines(enginesForEntityView);
}
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeList>>> _groupedEntityViewsToAdd;
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>> _groupedEntityViewsToAdd;
readonly EntitySubmissionScheduler _scheduler;
}
}

+ 21
- 18
Svelto.ECS/EntityFactory.cs View File

@@ -5,26 +5,23 @@ namespace Svelto.ECS.Internal
{
static class EntityFactory
{
internal static void BuildGroupedEntityViews(int entityID, int groupID,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsByType,
internal static void BuildGroupedEntityViews(EGID egid,
Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
Dictionary<long, IEntityViewBuilder[]> entityInfos,
object[] implementors)
{
var @group = FetchGroup(groupID, groupEntityViewsByType);
var @group = FetchGroup(egid.groupID, groupEntityViewsByType);

BuildEntityViewsAndAddToGroup(new EGID(entityID, groupID), group, entityViewsToBuildDescriptor, implementors);
entityInfos.Add(new EGID(entityID, groupID).GID, entityViewsToBuildDescriptor.entityViewsToBuild);
BuildEntityViewsAndAddToGroup(egid, group, entityViewsToBuildDescriptor, implementors);
}

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

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

@@ -32,37 +29,43 @@ namespace Svelto.ECS.Internal
}

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

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

BuildEntityView(entityID, entityViewsByType, entityViewType, entityViewBuilder, implementors);
}

_viewBuilder._initializer = new EntityInfoView() {entityViewsToBuild = entityViewsToBuild};
BuildEntityView(entityID, entityViewsByType, _viewType, _viewBuilder, null);
}

static void BuildEntityView(EGID entityID, Dictionary<Type, ITypeSafeList> entityViewsByType,
Type entityViewType, IEntityViewBuilder entityViewBuilder, object[] implementors)
static void BuildEntityView(EGID entityID, Dictionary<Type, ITypeSafeDictionary> entityViewsByType,
Type entityViewType, IEntityViewBuilder entityViewBuilder, object[] implementors)
{
ITypeSafeList entityViewsList;
ITypeSafeDictionary safeDictionary;

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

//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, implementors);
entityViewBuilder.BuildEntityViewAndAddToList(ref safeDictionary, entityID, implementors);

if (entityViewsPoolWillBeCreated)
entityViewsByType.Add(entityViewType, entityViewsList);
entityViewsByType.Add(entityViewType, safeDictionary);
}
static readonly EntityViewBuilder<EntityInfoView> _viewBuilder = new EntityViewBuilder<EntityInfoView>();
static readonly Type _viewType = typeof(EntityInfoView);
}
}

+ 42
- 25
Svelto.ECS/EntityViewBuilder.cs View File

@@ -8,29 +8,48 @@ namespace Svelto.ECS
{
public class EntityViewBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : IEntityData, new()
{
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, object[] implementors)
public EntityViewBuilder(ref EntityViewType initializer)
{
_initializer = initializer;
}
public EntityViewBuilder()
{}
public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary list, EGID entityID, object[] implementors)
{
if (list == null)
list = new TypeSafeFasterListForECSForClasses<EntityViewType>();

var castedList = list as TypeSafeFasterListForECSForClasses<EntityViewType>;
list = new TypeSafeDictionary<EntityViewType>();

var lentityView = EntityView<EntityViewType>.BuildEntityView(entityID);
var castedList = list as TypeSafeDictionary<EntityViewType>;

castedList.Add(lentityView);
if (implementors != null)
{
EntityViewType lentityView;
EntityView<EntityViewType>.BuildEntityView(entityID, out lentityView);

var entityView = lentityView;

this.FillEntityView(ref entityView
, entityViewBlazingFastReflection
, implementors
, DESCRIPTOR_NAME);
this.FillEntityView(ref lentityView
, entityViewBlazingFastReflection
, implementors
, DESCRIPTOR_NAME);
castedList.Add(entityID.GID, ref lentityView);
}
else
{
DBC.Check.Require(_initializer != null, "Implementors not found on a EntityView instance");
_initializer.ID = entityID;
castedList.Add(entityID.GID, ref _initializer);
}
}

public ITypeSafeList Preallocate(ref ITypeSafeList list, int size)
public ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary list, int size)
{
if (list == null)
list = new TypeSafeFasterListForECSForClasses<EntityViewType>(size);
list = new TypeSafeDictionary<EntityViewType>(size);
else
list.AddCapacity(size);

@@ -42,24 +61,22 @@ namespace Svelto.ECS
return ENTITY_VIEW_TYPE;
}

public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
public void MoveEntityView(EGID entityID, ITypeSafeDictionary fromSafeList, ITypeSafeDictionary toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForClasses<EntityViewType>;
var fromCastedList = fromSafeList as TypeSafeDictionary<EntityViewType>;
var toCastedList = toSafeList as TypeSafeDictionary<EntityViewType>;

toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]);
}

public bool isQueryiableEntityView
{
get { return true; }
toCastedList.Add(entityID.GID, fromCastedList[entityID.GID]);
fromCastedList.Remove(entityID.GID);
}

FasterList<KeyValuePair<Type, CastedAction<EntityViewType>>> entityViewBlazingFastReflection
{
get { return EntityView<EntityViewType>.FieldCache<EntityViewType>.list; }
get { return EntityView<EntityViewType>.FieldCache.list; }
}

internal EntityViewType _initializer;
static readonly Type ENTITY_VIEW_TYPE = typeof(EntityViewType);
static string DESCRIPTOR_NAME = ENTITY_VIEW_TYPE.ToString();
}

+ 0
- 56
Svelto.ECS/EntityViewStructBuilder.cs View File

@@ -1,56 +0,0 @@
using System;
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public class EntityViewStructBuilder<EntityViewType> : IEntityViewBuilder where EntityViewType : struct, IEntityData
{
public EntityViewStructBuilder(ref EntityViewType initializer)
{
_initializer = initializer;
}
public void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, object[] implementors = null)
{
_initializer.ID = entityID;
if (list == null)
list = new TypeSafeFasterListForECSForStructs<EntityViewType>();

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

public ITypeSafeList Preallocate(ref ITypeSafeList list, int size)
{
if (list == null)
list = new TypeSafeFasterListForECSForStructs<EntityViewType>(size);
else
list.AddCapacity(size);

return list;
}

public Type GetEntityViewType()
{
return ENTITY_VIEW_TYPE;
}

public void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList)
{
var fromCastedList = fromSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;
var toCastedList = toSafeList as TypeSafeFasterListForECSForStructs<EntityViewType>;

toCastedList.Add(fromCastedList[fromCastedList.GetIndexFromID(entityID)]);
}

public bool isQueryiableEntityView
{
get { return false; }
}

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

Svelto.ECS/FillEntityView.cs → Svelto.ECS/EntityViewUtility.cs View File

@@ -5,13 +5,13 @@ using Svelto.ECS;
using Svelto.Utilities;
using Console = Utility.Console;

static class FillEntityViewASD
static class EntityViewUtility
{
public static void FillEntityView<T>(this IEntityViewBuilder entityViewBuilder,
ref T entityView,
FasterList<KeyValuePair<Type, CastedAction<T>>> entityViewBlazingFastReflection ,
object[] implementors
, string entityDescriptorName)
public static void FillEntityView<T>(this IEntityViewBuilder entityViewBuilder
, ref T entityView
, FasterList<KeyValuePair<Type, CastedAction<T>>> entityViewBlazingFastReflection
, object[] implementors
, string entityDescriptorName)
{
int count;

@@ -19,9 +19,10 @@ static class FillEntityViewASD
var setters =
FasterList<KeyValuePair<Type, CastedAction<T>>>
.NoVirt.ToArrayFast(entityViewBlazingFastReflection, out count);

if (count == 0) return;

#if DEBUG && !PROFILER
if (count == 0)
throw new Exception(NO_COMPONENTS_EXCEPTION.FastConcat("Type ", entityDescriptorName, " entityView ", entityViewBuilder.GetEntityViewType().ToString()));
#endif
for (var index = 0; index < implementors.Length; index++)
{
var implementor = implementors[index];
@@ -45,7 +46,7 @@ static class FillEntityViewASD
else
implementorsByType[componentType] = new Tuple<object, int>(implementor, 1);
#else
implementorsByType[componentType] = implementor;
implementorsByType[componentType] = implementor;
#endif
}
}
@@ -65,7 +66,7 @@ static class FillEntityViewASD
#if DEBUG && !PROFILER
Tuple<object, int> component;
#else
object component;
object component;
#endif

if (implementorsByType.TryGetValue(fieldType, out component) == false)
@@ -88,7 +89,7 @@ static class FillEntityViewASD
#if DEBUG && !PROFILER
fieldSetter.Value.Call(ref entityView, component.implementorType);
#else
fieldSetter.Value.Call(entityView, component);
fieldSetter.Value.Call(ref entityView, component);
#endif
}

@@ -118,7 +119,9 @@ static class FillEntityViewASD
}
#endif
static readonly Dictionary<Type, Type[]> _cachedTypes = new Dictionary<Type, Type[]>();
const string NO_COMPONENTS_EXCEPTION =
"<color=orange>Svelto.ECS</color> An entity view without component interfaces has been found, if you are using an entity view struct or an entity struct, do not pass implementors";

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


+ 29
- 43
Svelto.ECS/EntityViewsDB.cs View File

@@ -6,70 +6,54 @@ namespace Svelto.ECS.Internal
{
class EntityViewsDB : IEntityViewsDB
{
internal EntityViewsDB( Dictionary<Type, ITypeSafeDictionary> entityViewsDBdic,
Dictionary<int, Dictionary<Type, ITypeSafeList>> groupEntityViewsDB)
internal EntityViewsDB(Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsDB)
{
_groupedEntityViewsDBDic = entityViewsDBdic;
_groupEntityViewsDB = groupEntityViewsDB;
}

public FasterReadOnlyList<T> QueryEntityViews<T>() where T:IEntityData
public ReadOnlyCollectionStruct<T> QueryEntityViews<T>() where T:IEntityData
{
var type = typeof(T);

ITypeSafeList entityViews;

if (_groupEntityViewsDB[ExclusiveGroups.StandardEntity].TryGetValue(type, out entityViews) == false)
return RetrieveEmptyEntityViewList<T>();

return new FasterReadOnlyList<T>((FasterList<T>)entityViews);
return QueryEntityViews<T>(ExclusiveGroups.StandardEntity);
}

public FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int @group) where T:IEntityData
public ReadOnlyCollectionStruct<T> QueryEntityViews<T>(int @group) where T:IEntityData
{
Dictionary<Type, ITypeSafeList> entitiesInGroupPerType;
Dictionary<Type, ITypeSafeDictionary> entitiesInGroupPerType;

if (_groupEntityViewsDB.TryGetValue(group, out entitiesInGroupPerType) == false)
return RetrieveEmptyEntityViewList<T>();

ITypeSafeList outList;
ITypeSafeDictionary outList;
if (entitiesInGroupPerType.TryGetValue(typeof(T), out outList) == false)
return RetrieveEmptyEntityViewList<T>();
return new FasterReadOnlyList<T>((FasterList<T>) outList);
return (outList as TypeSafeDictionary<T>).FasterValues;
}

public T[] QueryEntityViewsAsArray<T>(out int count) where T : IEntityData
public T[] QueryEntityViewsCacheFriendly<T>(out int count) where T : IEntityData
{
var type = typeof(T);
count = 0;
ITypeSafeList entityViews;

if (_groupEntityViewsDB[ExclusiveGroups.StandardEntity].TryGetValue(type, out entityViews) == false)
return RetrieveEmptyEntityViewArray<T>();
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entityViews, out count);
return QueryEntityViewsCacheFriendly<T>(ExclusiveGroups.StandardEntity, out count);
}
public T[] QueryGroupedEntityViewsAsArray<T>(int @group, out int count) where T : IEntityData
public T[] QueryEntityViewsCacheFriendly<T>(int @group, out int count) where T : IEntityData
{
var type = typeof(T);
count = 0;
Dictionary<Type, ITypeSafeList> entitiesInGroupPerType;
Dictionary<Type, ITypeSafeDictionary> entitiesInGroupPerType;
if (_groupEntityViewsDB.TryGetValue(group, out entitiesInGroupPerType) == false)
return RetrieveEmptyEntityViewArray<T>();
ITypeSafeList outList;
ITypeSafeDictionary outList;
if (entitiesInGroupPerType.TryGetValue(typeof(T), out outList) == false)
return RetrieveEmptyEntityViewArray<T>();
return FasterList<T>.NoVirt.ToArrayFast((FasterList<T>)entitiesInGroupPerType[type], out count);

var typeSafeDictionary = entitiesInGroupPerType[type];
return ((TypeSafeDictionary<T>) typeSafeDictionary).GetFasterValuesBuffer(out count);
}

public T QueryEntityView<T>(EGID entityGID) where T : IEntityData
public T QueryEntityView<T>(EGID entityGID) where T : class, IEntityData
{
T entityView;

@@ -88,11 +72,17 @@ namespace Svelto.ECS.Internal
var type = typeof(T);

T internalEntityView;

ITypeSafeDictionary entityViews;
Dictionary<Type, ITypeSafeDictionary> entitiesInGroupPerType;
if (_groupEntityViewsDB.TryGetValue(entityGID.groupID, out entitiesInGroupPerType) == false)
{
entityView = default(T);
return false;
}

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

if (casted != null &&
casted.TryGetValue(entityGID.GID, out internalEntityView))
@@ -107,21 +97,17 @@ namespace Svelto.ECS.Internal
return false;
}

static FasterReadOnlyList<T> RetrieveEmptyEntityViewList<T>()
static ReadOnlyCollectionStruct<T> RetrieveEmptyEntityViewList<T>()
{
return FasterReadOnlyList<T>.DefaultList;
return ReadOnlyCollectionStruct<T>.DefaultList;
}

static T[] RetrieveEmptyEntityViewArray<T>()
{
return FasterList<T>.DefaultList.ToArrayFast();
}
//grouped set of entity views, this is the standard way to handle entity views
readonly Dictionary<int, Dictionary<Type, ITypeSafeList>> _groupEntityViewsDB;
//indexable entity views when the entity ID is known. Usually useful to handle
//event based logic.
readonly Dictionary<Type, ITypeSafeDictionary> _groupedEntityViewsDBDic;
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityViewsDB;
}
}

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

@@ -2,6 +2,6 @@
{
static class ExclusiveGroups
{
internal const int StandardEntity = 0xFF;
internal const int StandardEntity = int.MaxValue;
}
}

+ 1
- 5
Svelto.ECS/IEngine.cs View File

@@ -4,11 +4,6 @@ namespace Svelto.ECS.Internal
{
public interface IHandleEntityViewEngineAbstracted : IEngine
{}
public interface IHandleEntityViewEngine : IHandleEntityViewEngineAbstracted
{
void Remove(IEntityData entityView);
}
}

namespace Svelto.ECS
@@ -19,5 +14,6 @@ namespace Svelto.ECS
public interface IHandleEntityStructEngine<T> : IHandleEntityViewEngineAbstracted
{
void Add(ref T entityView);
void Remove(ref T entityView);
}
}

+ 18
- 11
Svelto.ECS/IEntityView.cs View File

@@ -22,36 +22,43 @@ namespace Svelto.ECS

EGID _ID;
}
static class EntityView<T> where T: IEntityData, new()
public struct EntityInfoView : IEntityData
{
internal static T BuildEntityView(EGID ID)
public EGID ID { get; set; }
public IEntityViewBuilder[] entityViewsToBuild;
}

public static class EntityView<T> where T: IEntityData, new()
{
internal static void BuildEntityView(EGID ID, out T entityView)
{
if (FieldCache<T>.list.Count == 0)
if (FieldCache.list == null)
{
FieldCache.list = new FasterList<KeyValuePair<Type, CastedAction<T>>>();
var type = typeof(T);

var fields = type.GetFields(BindingFlags.Public |
BindingFlags.Instance);
for (int i = fields.Length - 1; i >= 0; --i)
{
var field = fields[i];

CastedAction<T> setter = FastInvoke<T>.MakeSetter(field);
FieldCache<T>.list.Add(new KeyValuePair<Type, CastedAction<T>>(field.FieldType, setter));
FieldCache.list.Add(new KeyValuePair<Type, CastedAction<T>>(field.FieldType, setter));
}
}

return new T { ID = ID };
entityView = new T { ID = ID };
}

//check if I can remove W
internal static class FieldCache<W>
public static class FieldCache
{
internal static readonly FasterList<KeyValuePair<Type, CastedAction<T>>> list
= new FasterList<KeyValuePair<Type, CastedAction<T>>>();
public static FasterList<KeyValuePair<Type, CastedAction<T>>> list;
}
}
}


+ 3
- 5
Svelto.ECS/IEntityViewBuilder.cs View File

@@ -5,12 +5,10 @@ namespace Svelto.ECS
{
public interface IEntityViewBuilder
{
void BuildEntityViewAndAddToList(ref ITypeSafeList list, EGID entityID, object[] implementors);
ITypeSafeList Preallocate(ref ITypeSafeList list, int size);
void BuildEntityViewAndAddToList(ref ITypeSafeDictionary list, EGID entityID, object[] implementors);
ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary list, int size);

Type GetEntityViewType();
void MoveEntityView(EGID entityID, ITypeSafeList fromSafeList, ITypeSafeList toSafeList);

bool isQueryiableEntityView { get; }
void MoveEntityView(EGID entityID, ITypeSafeDictionary fromSafeList, ITypeSafeDictionary toSafeList);
}
}

+ 5
- 5
Svelto.ECS/IEntityViewsDB.cs View File

@@ -4,13 +4,13 @@ namespace Svelto.ECS
{
public interface IEntityViewsDB
{
FasterReadOnlyList<T> QueryEntityViews<T>() where T : IEntityData;
FasterReadOnlyList<T> QueryGroupedEntityViews<T>(int group) where T : IEntityData;
ReadOnlyCollectionStruct<T> QueryEntityViews<T>() where T : IEntityData;
ReadOnlyCollectionStruct<T> QueryEntityViews<T>(int group) where T : IEntityData;

T[] QueryEntityViewsAsArray<T>(out int count) where T : IEntityData;
T[] QueryGroupedEntityViewsAsArray<T>(int group, out int count) where T : IEntityData;
T[] QueryEntityViewsCacheFriendly<T>(out int count) where T : IEntityData;
T[] QueryEntityViewsCacheFriendly<T>(int group, out int count) where T : IEntityData;

bool TryQueryEntityView<T>(EGID ID, out T entityView) where T : IEntityData;
T QueryEntityView<T>(EGID entityGID) where T : IEntityData;
T QueryEntityView<T>(EGID entityGID) where T : class, IEntityData;
}
}

+ 0
- 107
Svelto.ECS/MixedEntityDescriptor.cs View File

@@ -1,107 +0,0 @@
namespace Svelto.ECS
{
public abstract class MixedEntityDescriptor<T>:IEntityDescriptor where T : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T()};
}
public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}

public abstract class MixedEntityDescriptor<T, U> : IEntityDescriptor where T : class, IEntityViewBuilder, new()
where U : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U()};
}

public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}

public abstract class MixedEntityDescriptor<T, U, V> : IEntityDescriptor where T : class, IEntityViewBuilder, new()
where U : class, IEntityViewBuilder, new()
where V : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V()};
}

public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}

public abstract class MixedEntityDescriptor<T, U, V, W> : IEntityDescriptor where T : class, IEntityViewBuilder, new()
where U : class, IEntityViewBuilder, new()
where V : class, IEntityViewBuilder, new()
where W : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W()};
}

public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}

public abstract class MixedEntityDescriptor<T, U, V, W, X> : IEntityDescriptor where T : class, IEntityViewBuilder, new()
where U : class, IEntityViewBuilder, new()
where V : class, IEntityViewBuilder, new()
where W : class, IEntityViewBuilder, new()
where X : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W(), new X()};
}

public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}

public abstract class MixedEntityDescriptor<T, U, V, W, X, Y> : IEntityDescriptor where T : class, IEntityViewBuilder, new()
where U : class, IEntityViewBuilder, new()
where V : class, IEntityViewBuilder, new()
where W : class, IEntityViewBuilder, new()
where X : class, IEntityViewBuilder, new()
where Y : class, IEntityViewBuilder, new()
{
static MixedEntityDescriptor()
{
_entityViewsToBuild = new IEntityViewBuilder[] {new T(), new U(), new V(), new W(), new X(), new Y()};
}

public IEntityViewBuilder[] entityViewsToBuild
{
get { return _entityViewsToBuild; }
}
static readonly IEntityViewBuilder[] _entityViewsToBuild;
}
}

+ 7
- 68
Svelto.ECS/MultiEntityViewsEngine.cs View File

@@ -1,65 +1,17 @@
using Svelto.ECS.Internal;

namespace Svelto.ECS.Internal
{
public abstract class MultiEntityViewsEngine<T>:IHandleEntityStructEngine<T>,
IHandleEntityViewEngine where T:IEntityData
{
public void Add(ref T entityView)
{
Add(entityView);
}

public virtual void Remove(IEntityData entityView)
{
Remove((T) entityView);
}

protected abstract void Add(T entityView);
protected abstract void Remove(T entityView);
}
}

namespace Svelto.ECS
{
public abstract class MultiEntityViewsEngine<T, U> : MultiEntityViewsEngine<T>, IHandleEntityStructEngine<U>
public abstract class MultiEntityViewsEngine<T, U> : SingleEntityViewEngine<T>, IHandleEntityStructEngine<U>
where U : IEntityData where T : IEntityData
{
protected abstract void Add(U entityView);
protected abstract void Remove(U entityView);

public override void Remove(IEntityData entityView)
{
if (entityView is U)
Remove((U) entityView);
else
base.Remove(entityView);
}

public void Add(ref U entityView)
{
Add(entityView);
}
public abstract void Add(ref U entityView);
public abstract void Remove(ref U entityView);
}

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

public override void Remove(IEntityData entityView)
{
if (entityView is V)
Remove((V) entityView);
else
base.Remove(entityView);
}

public void Add(ref V entityView)
{
Add(entityView);
}
public abstract void Add(ref V entityView);
public abstract void Remove(ref V entityView);
}

/// <summary>
@@ -70,20 +22,7 @@ namespace Svelto.ECS
public abstract class MultiEntityViewsEngine<T, U, V, W> : MultiEntityViewsEngine<T, U, V>, IHandleEntityStructEngine<W>
where W : IEntityData where V : IEntityData where U : IEntityData where T : IEntityData
{
protected abstract void Add(W entityView);
protected abstract void Remove(W entityView);

public override void Remove(IEntityData entityView)
{
if (entityView is W)
Remove((W) entityView);
else
base.Remove(entityView);
}

public void Add(ref W entityView)
{
Add(entityView);
}
public abstract void Add(ref W entityView);
public abstract void Remove(ref W entityView);
}
}

+ 3
- 3
Svelto.ECS/Profiler/EngineProfiler.cs View File

@@ -12,7 +12,7 @@ namespace Svelto.ECS.Profiler
{
static readonly Stopwatch _stopwatch = new Stopwatch();

public static void MonitorAddDuration<T>(IHandleEntityViewEngineAbstracted engine, T entityView)
public static void MonitorAddDuration<T>(IHandleEntityViewEngineAbstracted engine, ref T entityView)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))
@@ -25,13 +25,13 @@ namespace Svelto.ECS.Profiler
}
}

public static void MonitorRemoveDuration<T>(IHandleEntityViewEngineAbstracted engine, IEntityData entityView)
public static void MonitorRemoveDuration<T>(IHandleEntityViewEngineAbstracted engine, ref T entityView)
{
EngineInfo info;
if (engineInfos.TryGetValue(engine.GetType(), out info))
{
_stopwatch.Start();
(engine as IHandleEntityViewEngine).Remove(entityView);
(engine as IHandleEntityStructEngine<T>).Remove(ref entityView);
_stopwatch.Stop();

info.AddRemoveDuration(_stopwatch.Elapsed.TotalMilliseconds);


+ 3
- 15
Svelto.ECS/SingleEntityViewEngine.cs View File

@@ -1,20 +1,8 @@
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public abstract class SingleEntityViewEngine<T> : IHandleEntityViewEngine where T : class, IEntityData
public abstract class SingleEntityViewEngine<T> : IHandleEntityStructEngine<T> where T : IEntityData
{
public void Add(IEntityData entityView)
{
Add((T) entityView);
}

public void Remove(IEntityData entityView)
{
Remove((T) entityView);
}

protected abstract void Add(T entityView);
protected abstract void Remove(T entityView);
public abstract void Add(ref T entityView);
public abstract void Remove(ref T entityView);
}
}

Loading…
Cancel
Save