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 QueryEntityViewsCacheFriendlytags/Rel25a
@@ -1 +1 @@ | |||
Subproject commit 460c00846a3b547c4567aec8bdfff82a9861869c | |||
Subproject commit 3c1360fcb86cdb70dcb00149a26d2064ec6fbe63 |
@@ -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" /> | |||
@@ -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>(); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |
@@ -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) | |||
{} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -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() | |||
@@ -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) | |||
@@ -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); | |||
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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(); | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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. "; | |||
@@ -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; | |||
} | |||
} |
@@ -2,6 +2,6 @@ | |||
{ | |||
static class ExclusiveGroups | |||
{ | |||
internal const int StandardEntity = 0xFF; | |||
internal const int StandardEntity = int.MaxValue; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
@@ -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); | |||
} | |||
} |