Browse Source

- put some effort to make the Sequencer declaration more readable, making more generic parameter explicit

- reworked IEntityViewsDB interface, some breaking renaming and added more functions
- added two struct friendly functions as workaround while we wait for the c# byref keyworkd: QueryEntities<T> and ExecutOnEntity<T>
- fix the SwapEntityGroup function
- various optimizations
- implement a simple and efficient way to initialize entity struct values (EntityStructInitializer)
- check (in debug only) if entitystruct has only value and primitive types, otherwise throw exception
-
tags/Rel25a
sebas77 6 years ago
parent
commit
497f97650b
19 changed files with 331 additions and 153 deletions
  1. +35
    -5
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  2. +0
    -1
      Svelto.ECS/EGID.cs
  3. +6
    -5
      Svelto.ECS/EnginesRoot.Engines.cs
  4. +56
    -18
      Svelto.ECS/EnginesRoot.Entities.cs
  5. +14
    -16
      Svelto.ECS/EnginesRoot.GenericEntityFactory.cs
  6. +6
    -1
      Svelto.ECS/EnginesRoot.GenericEntityFunctions.cs
  7. +0
    -0
      Svelto.ECS/EnginesRoot.Submission.cs
  8. +6
    -11
      Svelto.ECS/EntityDescriptor.cs
  9. +13
    -12
      Svelto.ECS/EntityFactory.cs
  10. +46
    -11
      Svelto.ECS/EntityViewBuilder.cs
  11. +2
    -2
      Svelto.ECS/EntityViewUtility.cs
  12. +77
    -31
      Svelto.ECS/EntityViewsDB.cs
  13. +0
    -1
      Svelto.ECS/GenericEntityDescriptor.cs
  14. +8
    -8
      Svelto.ECS/IEntityFactory.cs
  15. +4
    -1
      Svelto.ECS/IEntityFunctions.cs
  16. +17
    -18
      Svelto.ECS/IEntityView.cs
  17. +1
    -1
      Svelto.ECS/IEntityViewBuilder.cs
  18. +17
    -9
      Svelto.ECS/IEntityViewsDB.cs
  19. +23
    -2
      Svelto.ECS/Sequencer.cs

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

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.Utilities;

namespace Svelto.ECS.Internal
{
@@ -13,24 +14,26 @@ namespace Svelto.ECS.Internal
/// </summary>
public interface ITypeSafeDictionary
{
ITypeSafeDictionary Create();
void RemoveEntitiesFromEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>>
entityViewEnginesDB);

void RemoveEntityFromEngines(EGID entityGid,
Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>>
entityViewEnginesDB);
void FillWithIndexedEntityViews(ITypeSafeDictionary entityViews);
void AddEntityViewsToEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB);
void AddCapacity(int size);
bool Remove(int idGid);
ITypeSafeDictionary Create();
int Count { get; }
void FillWithIndexedEntityViews(ITypeSafeDictionary entityViews);
void AddEntityViewsToEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB);
}

class TypeSafeDictionary<TValue> : FasterDictionary<int, TValue>, ITypeSafeDictionary where TValue : IEntityData
{
static Type _type = typeof(TValue);

public TypeSafeDictionary(int size):base(size)
{}

@@ -115,5 +118,32 @@ namespace Svelto.ECS.Internal
{
return new TypeSafeDictionary<TValue>();
}
public void ExecuteOnEntityView<W>(int entityGidEntityId, ref W value, ActionRef<TValue, W> action)
{
uint findIndex;
if (FindIndex(entityGidEntityId, out findIndex))
{
action(ref _values[findIndex], ref value);
}
}
public void ExecuteOnEntityView(int entityGidEntityId, ActionRef<TValue> action)
{
uint findIndex;
if (FindIndex(entityGidEntityId, out findIndex))
{
action(ref _values[findIndex]);
}
}
public uint FindElementIndex(int entityGidEntityId)
{
uint findIndex;
if (FindIndex(entityGidEntityId, out findIndex) == false) throw new Exception("");
return findIndex;
}
static readonly Type _type = typeof(TValue);
}
}

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

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

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


Svelto.ECS/EnginesRootEngines.cs → Svelto.ECS/EnginesRoot.Engines.cs View File

@@ -13,17 +13,18 @@ namespace Svelto.ECS
{
public partial class EnginesRoot : IDisposable
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
/// <summary>
/// I still need to find a good solution for this. Need to move somewhere else
/// </summary>
static EnginesRoot()
{
#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
/// <summary>
/// I still need to find a good solution for this. Need to move somewhere else
/// </summary>
UnityEngine.GameObject debugEngineObject = new UnityEngine.GameObject("Svelto.ECS.Profiler");
debugEngineObject.gameObject.AddComponent<EngineProfilerBehaviour>();
UnityEngine.GameObject.DontDestroyOnLoad(debugEngineObject);
#endif
}
#endif
/// <summary>
/// Engines root contextualize your engines and entities. You don't need to limit yourself to one EngineRoot
/// as multiple engines root could promote separation of scopes. The EntitySubmissionScheduler checks

Svelto.ECS/EnginesRootEntities.cs → Svelto.ECS/EnginesRoot.Entities.cs View File

@@ -37,23 +37,26 @@ namespace Svelto.ECS

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

void BuildEntity<T>(EGID entityID, object[] implementors)
where T : IEntityDescriptor, new()
EntityStructInitializer BuildEntity<T>(EGID entityID, object[] implementors)
where T : class, IEntityDescriptor, new()
{
EntityFactory.BuildGroupedEntityViews(entityID,
var dic = EntityFactory.BuildGroupedEntityViews(entityID,
_groupedEntityToAdd.current,
EntityDescriptorTemplate<T>.Info,
EntityDescriptorTemplate<T>.Info.entityViewsToBuild,
implementors);
return new EntityStructInitializer(entityID, dic);
}

void BuildEntity(EGID entityID, EntityDescriptorInfo entityDescriptorInfo,
EntityStructInitializer BuildEntity(EGID entityID, IEntityViewBuilder[] entityViewsToBuild,
object[] implementors)
{
EntityFactory.BuildGroupedEntityViews(entityID,
var dic = EntityFactory.BuildGroupedEntityViews(entityID,
_groupedEntityToAdd.current,
entityDescriptorInfo,
entityViewsToBuild,
implementors);
return new EntityStructInitializer(entityID, dic);
}

///--------------------------------------------
@@ -64,7 +67,7 @@ namespace Svelto.ECS
/// TODO: understand if this method is useful in a performance critical
/// scenario
/// </summary>
void Preallocate<T>(int groupID, int size) where T : IEntityDescriptor, new()
void Preallocate<T>(int groupID, int size) where T : class, IEntityDescriptor, new()
{
var entityViewsToBuild = EntityDescriptorTemplate<T>.Info.entityViewsToBuild;
var count = entityViewsToBuild.Length;
@@ -145,12 +148,10 @@ 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 =
((TypeSafeDictionary<EntityInfoView>) _groupEntityDB[fromGroupID][_typeEntityInfoView])
[entityegid.entityID].entityToBuild;
var entityViewBuildersCount = entityViewBuilders.Length;

var groupedEntities = _groupEntityDB[fromGroupID];
var entityInfoViewDictionary = (TypeSafeDictionary<EntityInfoView>) groupedEntities[_typeEntityInfoView];
var entityViewBuilders = entityInfoViewDictionary[entityegid.entityID].entityToBuild;
var entityViewBuildersCount = entityViewBuilders.Length;

Dictionary<Type, ITypeSafeDictionary> groupedEntityViewsTyped;
if (_groupEntityDB.TryGetValue(toGroupID, out groupedEntityViewsTyped) == false)
@@ -159,21 +160,37 @@ namespace Svelto.ECS

_groupEntityDB.Add(toGroupID, groupedEntityViewsTyped);
}
ITypeSafeDictionary toSafeList;

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

var fromSafeList = groupedEntities[entityViewType];
ITypeSafeDictionary toSafeList;

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

entityViewBuilder.MoveEntityView(entityegid, fromSafeList, toSafeList);
entityViewBuilder.MoveEntityView(entityegid, toGroupID, fromSafeList, toSafeList);
fromSafeList.Remove(entityegid.entityID);
}
if (groupedEntityViewsTyped.TryGetValue(_typeEntityInfoView, out toSafeList) == false)
groupedEntityViewsTyped[_typeEntityInfoView] = toSafeList = entityInfoViewDictionary.Create();

EntityViewBuilder<EntityInfoView>.MoveEntityView(entityegid, toGroupID, entityInfoViewDictionary, toSafeList);
entityInfoViewDictionary.Remove(entityegid.entityID);
}
EGID SwapFirstEntityGroup(int fromGroupID, int toGroupId)
{
var firstID =
((TypeSafeDictionary<EntityInfoView>) _groupEntityDB[fromGroupID][_typeEntityInfoView]).FasterValues[0].ID.entityID;
SwapEntityGroup(firstID, fromGroupID, toGroupId);
return new EGID(firstID, toGroupId);
}

readonly EntityViewsDB _DB;
@@ -182,4 +199,25 @@ namespace Svelto.ECS
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityDB;
static readonly Type _typeEntityInfoView = typeof(EntityInfoView);
}

public struct EntityStructInitializer
{
public EntityStructInitializer(EGID id, Dictionary<Type, ITypeSafeDictionary> current)
{
_current = current;
_id = id;
}

public void Init<T>(ref T initializer) where T: struct, IEntityData
{
var typeSafeDictionary = (TypeSafeDictionary<T>) _current[typeof(T)];

initializer.ID = _id;
typeSafeDictionary.GetFasterValuesBuffer()[typeSafeDictionary.FindElementIndex(_id.entityID)] = initializer;
}

readonly Dictionary<Type, ITypeSafeDictionary> _current;
readonly EGID _id;
}
}

+ 14
- 16
Svelto.ECS/EnginesRoot.GenericEntityFactory.cs View File

@@ -17,44 +17,42 @@ namespace Svelto.ECS
_weakEngine = weakReference;
}

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

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

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


public void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptorInfo, object[] implementors)
public EntityStructInitializer BuildEntity(int entityID, IEntityViewBuilder[] entityViewsToBuild, object[] implementors)
{
_weakEngine.Target.BuildEntity(new EGID(entityID), entityDescriptorInfo, implementors);
return _weakEngine.Target.BuildEntity(new EGID(entityID), entityViewsToBuild, implementors);
}

public void BuildEntity(EGID egid, EntityDescriptorInfo entityDescriptorInfo, object[] implementors)
public EntityStructInitializer BuildEntity(EGID egid, IEntityViewBuilder[] entityViewsToBuild, object[] implementors)
{
_weakEngine.Target.BuildEntity(egid, entityDescriptorInfo, implementors);
return _weakEngine.Target.BuildEntity(egid, entityViewsToBuild, implementors);
}

public void BuildEntity(int entityID, int groupID, EntityDescriptorInfo entityDescriptorInfo, object[] implementors)
public EntityStructInitializer BuildEntity(int entityID, int groupID, IEntityViewBuilder[] entityViewsToBuild, object[] implementors)
{
_weakEngine.Target.BuildEntity(new EGID(entityID, groupID), entityDescriptorInfo, implementors);
return _weakEngine.Target.BuildEntity(new EGID(entityID, groupID), entityViewsToBuild, implementors);
}

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


+ 6
- 1
Svelto.ECS/EnginesRoot.GenericEntityFunctions.cs View File

@@ -12,7 +12,7 @@ namespace Svelto.ECS
{
readonly DataStructures.WeakReference<EnginesRoot> _weakReference;

public GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
internal GenericEntityFunctions(DataStructures.WeakReference<EnginesRoot> weakReference)
{
_weakReference = weakReference;
}
@@ -46,6 +46,11 @@ namespace Svelto.ECS
{
_weakReference.Target.SwapEntityGroup(entityID, ExclusiveGroups.StandardEntity, toGroupID);
}

public EGID SwapFirstEntityGroup(int fromGroupID, int toGroupID)
{
return _weakReference.Target.SwapFirstEntityGroup( fromGroupID, toGroupID);
}
}
}
}

Svelto.ECS/EnginesRootSubmission.cs → Svelto.ECS/EnginesRoot.Submission.cs View File


+ 6
- 11
Svelto.ECS/EntityDescriptor.cs View File

@@ -19,13 +19,15 @@ namespace Svelto.ECS
public IEntityViewBuilder[] entityViewsToBuild { get; }
}

public static class EntityDescriptorTemplate<TType> where TType : IEntityDescriptor, new()
public static class EntityDescriptorTemplate<TType> where TType : class, IEntityDescriptor, new()
{
public static readonly EntityDescriptorInfo Info = new EntityDescriptorInfo(new TType());
}

public class DynamicEntityDescriptorInfo<TType> : EntityDescriptorInfo where TType : IEntityDescriptor, new()
public struct DynamicEntityDescriptorInfo<TType> where TType : class, IEntityDescriptor, new()
{
public readonly IEntityViewBuilder[] entityViewsToBuild;
public DynamicEntityDescriptorInfo(FasterList<IEntityViewBuilder> extraEntityViews)
{
Check.Require(extraEntityViews.Count > 0,
@@ -38,23 +40,16 @@ namespace Svelto.ECS

Array.Copy(defaultEntityViewsToBuild, 0, entityViewsToBuild, 0, length);
Array.Copy(extraEntityViews.ToArrayFast(), 0, entityViewsToBuild, length, extraEntityViews.Count);

name = EntityDescriptorTemplate<TType>.Info.name;
}
}

public class EntityDescriptorInfo
public struct EntityDescriptorInfo
{
internal IEntityViewBuilder[] entityViewsToBuild;
internal string name;
public readonly IEntityViewBuilder[] entityViewsToBuild;

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

protected EntityDescriptorInfo()
{ }
}
}

+ 13
- 12
Svelto.ECS/EntityFactory.cs View File

@@ -5,14 +5,16 @@ namespace Svelto.ECS.Internal
{
static class EntityFactory
{
internal static void BuildGroupedEntityViews(EGID egid,
internal static Dictionary<Type, ITypeSafeDictionary> BuildGroupedEntityViews(EGID egid,
Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsByType,
EntityDescriptorInfo entityViewsToBuildDescriptor,
IEntityViewBuilder[] entityViewsToBuild,
object[] implementors)
{
var @group = FetchEntityViewGroup(egid.groupID, groupEntityViewsByType);

BuildEntityViewsAndAddToGroup(egid, group, entityViewsToBuildDescriptor, implementors);
BuildEntityViewsAndAddToGroup(egid, group, entityViewsToBuild, implementors);

return group;
}

static Dictionary<Type, ITypeSafeDictionary> FetchEntityViewGroup(int groupID, Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsByType)
@@ -29,32 +31,31 @@ namespace Svelto.ECS.Internal
}

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

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

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

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

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

var entityViewsPoolWillBeCreated =
entityViewsByType.TryGetValue(entityViewType, out safeDictionary) == false;
@group.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.
@@ -62,7 +63,7 @@ namespace Svelto.ECS.Internal
entityViewBuilder.BuildEntityViewAndAddToList(ref safeDictionary, entityID, implementors);

if (entityViewsPoolWillBeCreated)
entityViewsByType.Add(entityViewType, safeDictionary);
@group.Add(entityViewType, safeDictionary);
}
static readonly EntityViewBuilder<EntityInfoView> _viewBuilder = new EntityViewBuilder<EntityInfoView>();


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

@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
#if DEBUG && !PROFILER
using System.Reflection;
#endif
using Svelto.DataStructures;
using Svelto.ECS.Internal;
using Svelto.Utilities;
@@ -8,14 +11,33 @@ namespace Svelto.ECS
{
public class EntityViewBuilder<T> : IEntityViewBuilder where T : IEntityData, new()
{
public EntityViewBuilder(ref T initializer)
{
_initializer = initializer;
}
public EntityViewBuilder()
{
_initializer = default(T);
#if DEBUG && !PROFILER
if (needsReflection == false && typeof(T) != typeof(EntityInfoView))
{
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];

if (field.FieldType.IsPrimitive == true || field.FieldType.IsValueType == true)
continue;
throw new EntityStructException();
}
}
#endif
if (needsReflection == true)
{
EntityView<T>.InitCache();
}
}
public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors)
@@ -62,24 +84,37 @@ namespace Svelto.ECS
return ENTITY_VIEW_TYPE;
}

public void MoveEntityView(EGID entityID, ITypeSafeDictionary fromSafeDic, ITypeSafeDictionary toSafeDic)
void IEntityViewBuilder.MoveEntityView(EGID entityID, int toGroupID, ITypeSafeDictionary fromSafeDic, ITypeSafeDictionary toSafeDic)
{
MoveEntityView(entityID, toGroupID, fromSafeDic, toSafeDic);
}

public static void MoveEntityView(EGID entityID, int toGroupID, ITypeSafeDictionary fromSafeDic, ITypeSafeDictionary toSafeDic)
{
var fromCastedDic = fromSafeDic as TypeSafeDictionary<T>;
var toCastedDic = toSafeDic as TypeSafeDictionary<T>;

toCastedDic.Add(entityID.entityID, fromCastedDic[entityID.entityID]);
var entity = fromCastedDic[entityID.entityID];
entity.ID = new EGID(entityID.entityID, toGroupID);
toCastedDic.Add(entityID.entityID, entity);
fromCastedDic.Remove(entityID.entityID);
}

FasterList<KeyValuePair<Type, ActionRef<T>>> entityViewBlazingFastReflection
static FasterList<KeyValuePair<Type, ActionCast<T>>> entityViewBlazingFastReflection
{
get { return EntityView<T>.FieldCache.list; }
get { return EntityView<T>.cachedFields; }
}
static readonly Type ENTITY_VIEW_TYPE = typeof(T);
static string DESCRIPTOR_NAME = ENTITY_VIEW_TYPE.ToString();
static readonly string DESCRIPTOR_NAME = ENTITY_VIEW_TYPE.ToString();
static readonly bool needsReflection = typeof(IEntityView).IsAssignableFrom(typeof(T));

internal T _initializer;
readonly bool needsReflection = typeof(IEntityView).IsAssignableFrom(typeof(T));
}

public class EntityStructException : Exception
{
public EntityStructException():base("EntityStruct must contains only value types!")
{}
}
}

+ 2
- 2
Svelto.ECS/EntityViewUtility.cs View File

@@ -9,7 +9,7 @@ static class EntityViewUtility
{
public static void FillEntityView<T>(this IEntityViewBuilder entityViewBuilder
, ref T entityView
, FasterList<KeyValuePair<Type, ActionRef<T>>> entityViewBlazingFastReflection
, FasterList<KeyValuePair<Type, ActionCast<T>>> entityViewBlazingFastReflection
, object[] implementors
, string entityDescriptorName)
{
@@ -17,7 +17,7 @@ static class EntityViewUtility

//Very efficent way to collect the fields of every EntityViewType
var setters =
FasterList<KeyValuePair<Type, ActionRef<T>>>
FasterList<KeyValuePair<Type, ActionCast<T>>>
.NoVirt.ToArrayFast(entityViewBlazingFastReflection, out count);
#if DEBUG && !PROFILER
if (count == 0)


+ 77
- 31
Svelto.ECS/EntityViewsDB.cs View File

@@ -1,22 +1,23 @@
using System;
using System.Collections.Generic;
using Svelto.DataStructures;
using Svelto.Utilities;

namespace Svelto.ECS.Internal
{
class EntityViewsDB : IEntityViewsDB
{
internal EntityViewsDB(Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsDB)
internal EntityViewsDB(Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsDB)
{
_groupEntityViewsDB = groupEntityViewsDB;
}

public ReadOnlyCollectionStruct<T> QueryEntities<T>() where T:IEntityData
public ReadOnlyCollectionStruct<T> QueryEntityViews<T>() where T:class, IEntityData
{
return QueryEntities<T>(ExclusiveGroups.StandardEntity);
return QueryEntityViews<T>(ExclusiveGroups.StandardEntity);
}

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

@@ -30,12 +31,12 @@ namespace Svelto.ECS.Internal
return (outList as TypeSafeDictionary<T>).FasterValues;
}

public T[] QueryEntitiesCacheFriendly<T>(out int count) where T : struct, IEntityData
public T[] QueryEntities<T>(out int count) where T : IEntityData
{
return QueryEntitiesCacheFriendly<T>(ExclusiveGroups.StandardEntity, out count);
return QueryEntities<T>(ExclusiveGroups.StandardEntity, out count);
}
public T[] QueryEntitiesCacheFriendly<T>(int @group, out int count) where T : struct, IEntityData
public T[] QueryEntities<T>(int @group, out int count) where T : IEntityData
{
count = 0;
@@ -51,6 +52,28 @@ namespace Svelto.ECS.Internal
return ((TypeSafeDictionary<T>)typeSafeDictionary).GetFasterValuesBuffer(out count);
}

public T[] QueryEntities<T>(EGID entityGID, out uint index) where T : IEntityData
{
TypeSafeDictionary<T> casted;
if (!FindSafeDictionary(entityGID, out casted))
{
index = 0;
return null;
}

if (casted != null)
index = casted.FindElementIndex(entityGID.entityID);
else
{
index = 0;
return null;
}

int count;
return QueryEntities<T>(out count);
}

public T QueryEntityView<T>(EGID entityGID) where T : class, IEntityData
{
T entityView;
@@ -60,61 +83,84 @@ namespace Svelto.ECS.Internal
return entityView;
}

public void ExecuteOnEntity<T, W>(EGID entityGID, ref W value, ActionRef<T, W> action) where T : IEntityData
{
TypeSafeDictionary<T> casted;
if (!FindSafeDictionary(entityGID, out casted)) return;

if (casted != null)
casted.ExecuteOnEntityView(entityGID.entityID, ref value, action);
}
public void ExecuteOnEntity<T>(EGID entityGID, ActionRef<T> action) where T : IEntityData
{
TypeSafeDictionary<T> casted;
if (!FindSafeDictionary(entityGID, out casted)) return;

if (casted != null)
casted.ExecuteOnEntityView(entityGID.entityID, action);
}

public bool Exists<T>(EGID entityGID) where T : IEntityData
{
TypeSafeDictionary<T> casted;
if (!FindSafeDictionary(entityGID, out casted)) return false;

if (casted != null &&
casted.ContainsKey(entityGID.entityID))
{
return true;
}

return false;
}

bool FindSafeDictionary<T>(EGID entityGID, out TypeSafeDictionary<T> casted) where T : IEntityData
{
var type = typeof(T);

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

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

if (casted != null &&
casted.ContainsKey(entityGID.entityID))
{
return true;
}

return false;
casted = entityViews as TypeSafeDictionary<T>;
return true;
}

public void Fetch<T>(out T entity) where T : IEntityData
public bool HasAny<T>() where T : IEntityData
{
entity = QueryEntities<T>()[0];
int count;
QueryEntities<T>(out count);
return count > 0;
}

public bool Has<T>() where T : IEntityData
public bool HasAny<T>(int @group) where T : IEntityData
{
return QueryEntities<T>().Count > 0;
int count;
QueryEntities<T>(group, out count);
return count > 0;
}

public bool TryQueryEntityView<T>(EGID entityegid, out T entityView) where T : IEntityData
public bool TryQueryEntityView<T>(EGID entityegid, out T entityView) where T : class, IEntityData
{
return TryQueryEntityViewInGroup(entityegid, out entityView);
}

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

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

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

if (casted != null &&
casted.TryGetValue(entityGID.entityID, out entityView))
{


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

@@ -13,7 +13,6 @@
}

static readonly IEntityViewBuilder[] entityViewBuilders;
}

public abstract class GenericEntityDescriptor<T, U> : IEntityDescriptor where T : IEntityData, new()


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

@@ -16,8 +16,8 @@ namespace Svelto.ECS
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="size"></param>
void PreallocateEntitySpace<T>(int size) where T : IEntityDescriptor, new();
void PreallocateEntitySpace<T>(int groupID, int size) where T : IEntityDescriptor, new();
void PreallocateEntitySpace<T>(int size) where T : class, IEntityDescriptor, new();
void PreallocateEntitySpace<T>(int groupID, int size) where T : class, IEntityDescriptor, new();
/// <summary>
/// The EntityDescriptor doesn't need to be ever instantiated. It just describes the Entity
@@ -28,7 +28,7 @@ namespace Svelto.ECS
/// <typeparam name="T"></typeparam>
/// <param name="entityID"></param>
/// <param name="implementors"></param>
void BuildEntity<T>(int entityID, object[] implementors) where T:IEntityDescriptor, new();
EntityStructInitializer BuildEntity<T>(int entityID, object[] implementors) where T:class, IEntityDescriptor, new();


/// <summary>
@@ -41,9 +41,9 @@ namespace Svelto.ECS
/// <param name="groupID"></param>
/// <param name="ed"></param>
/// <param name="implementors"></param>
void BuildEntity<T>(int entityID, int groupID, object[] implementors) where T:IEntityDescriptor, new();
EntityStructInitializer BuildEntity<T>(int entityID, int groupID, object[] implementors) where T:class, IEntityDescriptor, new();
void BuildEntity<T>(EGID egid, object[] implementors) where T:IEntityDescriptor, new();
EntityStructInitializer BuildEntity<T>(EGID egid, object[] implementors) where T:class, IEntityDescriptor, new();

/// <summary>
@@ -54,8 +54,8 @@ namespace Svelto.ECS
/// <param name="entityDescriptor"></param>
/// <param name="implementors"></param>
///
void BuildEntity(int entityID, int groupID, EntityDescriptorInfo entityDescriptor, object[] implementors);
void BuildEntity(int entityID, EntityDescriptorInfo entityDescriptorInfo, object[] implementors);
void BuildEntity(EGID egid, EntityDescriptorInfo entityDescriptorInfo, object[] implementors);
EntityStructInitializer BuildEntity(int entityID, int groupID, IEntityViewBuilder[] entityViewsToBuild, object[] implementors);
EntityStructInitializer BuildEntity(int entityID, IEntityViewBuilder[] entityViewsToBuild, object[] implementors);
EntityStructInitializer BuildEntity(EGID egid, IEntityViewBuilder[] entityViewsToBuild, object[] implementors);
}
}

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

@@ -1,3 +1,5 @@
using Svelto.ECS.Internal;

namespace Svelto.ECS
{
public interface IEntityFunctions
@@ -11,7 +13,8 @@ namespace Svelto.ECS

void RemoveGroupAndEntities(int groupID);
void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID);
void SwapEntityGroup(int entityID, int fromGroupID, int toGroupID = ExclusiveGroups.StandardEntity);
void SwapEntityGroup(int entityID, int toGroupID);
EGID SwapFirstEntityGroup(int fromGroupID = ExclusiveGroups.StandardEntity, int toGroupID = ExclusiveGroups.StandardEntity);
}
}

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

@@ -6,7 +6,6 @@ using Svelto.Utilities;

namespace Svelto.ECS
{
//todo: can I remove the ID from the struct?
public interface IEntityData
{
EGID ID { get; set; }
@@ -35,33 +34,33 @@ namespace Svelto.ECS

public static class EntityView<T> where T: IEntityData, new()
{
internal static void BuildEntityView(EGID ID, out T entityView)
internal static readonly FasterList<KeyValuePair<Type, ActionCast<T>>> cachedFields;

static EntityView()
{
if (FieldCache.list == null)
{
FieldCache.list = new FasterList<KeyValuePair<Type, ActionRef<T>>>();
cachedFields = new FasterList<KeyValuePair<Type, ActionCast<T>>>();
var type = typeof(T);
var type = typeof(T);

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

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

entityView = new T { ID = ID };
}

public static class FieldCache
internal static void InitCache()
{}
internal static void BuildEntityView(EGID ID, out T entityView)
{
public static FasterList<KeyValuePair<Type, ActionRef<T>>> list;
entityView = new T { ID = ID };
}
}
}


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

@@ -9,6 +9,6 @@ namespace Svelto.ECS
ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary dictionary, int size);

Type GetEntityType();
void MoveEntityView(EGID entityID, ITypeSafeDictionary fromSafeDic, ITypeSafeDictionary toSafeDic);
void MoveEntityView(EGID entityID, int toGroupID, ITypeSafeDictionary fromSafeDic, ITypeSafeDictionary toSafeDic);
}
}

+ 17
- 9
Svelto.ECS/IEntityViewsDB.cs View File

@@ -1,23 +1,31 @@
using System;
using Svelto.DataStructures;
using Svelto.Utilities;

namespace Svelto.ECS
{
public interface IEntityViewsDB
{
//to use with EntityViews, EntityStructs and EntityViewStructs
ReadOnlyCollectionStruct<T> QueryEntities<T>() where T : IEntityData;
ReadOnlyCollectionStruct<T> QueryEntities<T>(int group) where T : IEntityData;
//to use with EntityViews
ReadOnlyCollectionStruct<T> QueryEntityViews<T>() where T : class, IEntityData;
ReadOnlyCollectionStruct<T> QueryEntityViews<T>(int group) where T : class, IEntityData;

//to use with EntityStructs and EntityViewStructs
T[] QueryEntitiesCacheFriendly<T>(out int count) where T : struct, IEntityData;
T[] QueryEntitiesCacheFriendly<T>(int group, out int count) where T : struct, IEntityData;
//to use with EntityViews, EntityStructs and EntityViewStructs
T[] QueryEntities<T>(out int count) where T : IEntityData;
T[] QueryEntities<T>(int group, out int count) where T : IEntityData;
T[] QueryEntities<T>(EGID entityGID, out uint index) where T : IEntityData;

//to use with EntityViews
bool TryQueryEntityView<T>(EGID egid, out T entityView) where T : IEntityData;
bool TryQueryEntityView<T>(EGID egid, out T entityView) where T : class, IEntityData;
T QueryEntityView<T>(EGID egid) where T : class, IEntityData;
//to use with EntityViews, EntityStructs and EntityViewStructs
void ExecuteOnEntity<T, W>(EGID egid, ref W value, ActionRef<T, W> action) where T : IEntityData;
void ExecuteOnEntity<T>(EGID egid, ActionRef<T> action) where T : IEntityData;
bool Exists<T>(EGID egid) where T : IEntityData;
void Fetch<T>(out T entity) where T:IEntityData;
bool Has<T>() where T:IEntityData;
bool HasAny<T>() where T:IEntityData;
bool HasAny<T>(int group) where T:IEntityData;
}
}

+ 23
- 2
Svelto.ECS/Sequencer.cs View File

@@ -1,9 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;

namespace Svelto.ECS
{
public class Steps : Dictionary<IEngine, Dictionary<int, IStep[]>>
public class Steps : Dictionary<IEngine, IDictionary>
{}

public class To : Dictionary<int, IStep[]>
@@ -18,6 +19,9 @@ namespace Svelto.ECS
}
}
public class To<C> : Dictionary<C, IStep[]> where C:struct,IConvertible
{}
public interface IStep
{}

@@ -26,11 +30,18 @@ namespace Svelto.ECS
void Step(ref T token, int condition);
}
public interface IStep<T, in C>:IStep where C:struct,IConvertible
{
void Step(ref T token, C condition);
}
public interface ISequencer
{
void Next<T>(IEngine engine, ref T param);

void Next<T>(IEngine engine, ref T param, int condition);

void Next<T, C>(IEngine engine, ref T param, C condition) where C : struct, IConvertible;
}

public class Sequencer : ISequencer
@@ -48,13 +59,23 @@ namespace Svelto.ECS
public void Next<T>(IEngine engine, ref T param, int condition)
{
int branch = condition;
var steps = _steps[engine][branch];
var steps = (_steps[engine] as Dictionary<int, IStep[]>)[branch];

if (steps != null)
for (int i = 0; i < steps.Length; i++)
((IStep<T>)steps[i]).Step(ref param, condition);
}

public void Next<T, C>(IEngine engine, ref T param, C condition) where C:struct,IConvertible
{
C branch = condition;
var steps = (_steps[engine] as Dictionary<C, IStep[]>)[branch];

if (steps != null)
for (int i = 0; i < steps.Length; i++)
((IStep<T, C>)steps[i]).Step(ref param, condition);
}

Steps _steps;
}



Loading…
Cancel
Save