Browse Source

Sequencer cannot pass data anymore, just the EGID

More debug info
Better memory usage
Query entity must throw an exception if entity is not found
runtime validation for EntityStructs
tags/2.6a
sebas77 6 years ago
parent
commit
89cc341f6f
12 changed files with 163 additions and 104 deletions
  1. +7
    -1
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  2. +18
    -4
      Svelto.ECS/EnginesRoot.DoubleBufferedEntityViews.cs
  3. +1
    -1
      Svelto.ECS/EnginesRoot.Engines.cs
  4. +47
    -5
      Svelto.ECS/EnginesRoot.Entities.cs
  5. +1
    -1
      Svelto.ECS/EnginesRoot.GenericEntityFunctions.cs
  6. +7
    -9
      Svelto.ECS/EnginesRoot.Submission.cs
  7. +25
    -17
      Svelto.ECS/EntitiesDB.cs
  8. +2
    -0
      Svelto.ECS/EntityFactory.cs
  9. +27
    -15
      Svelto.ECS/EntityViewBuilder.cs
  10. +6
    -4
      Svelto.ECS/EntityViewUtility.cs
  11. +0
    -2
      Svelto.ECS/IEntitiesDB.cs
  12. +22
    -45
      Svelto.ECS/Sequencer.cs

+ 7
- 1
Svelto.ECS/DataStructures/TypeSafeDictionary.cs View File

@@ -29,10 +29,11 @@ namespace Svelto.ECS.Internal
void AddEntitiesToEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB);
void AddCapacity(int size);
bool Remove(int idGid);
int Count { get; }
void Trim();
void Clear();
bool Has(int entityIdEntityId);
}

class TypeSafeDictionary<TValue> : FasterDictionary<int, TValue>, ITypeSafeDictionary where TValue : IEntityStruct
@@ -74,6 +75,11 @@ namespace Svelto.ECS.Internal
}
}

public bool Has(int entityIdEntityId)
{
return ContainsKey(entityIdEntityId);
}

void AddEntityViewToEngines(Dictionary<Type, FasterList<IHandleEntityViewEngineAbstracted>> entityViewEnginesDB, ref TValue entity)
{
FasterList<IHandleEntityViewEngineAbstracted> entityViewsEngines;


+ 18
- 4
Svelto.ECS/EnginesRoot.DoubleBufferedEntityViews.cs View File

@@ -1,4 +1,7 @@
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using Svelto.ECS.Internal;

#if ENGINE_PROFILER_ENABLED && UNITY_EDITOR
using Svelto.ECS.Profiler;
@@ -8,12 +11,12 @@ namespace Svelto.ECS
{
public partial class EnginesRoot
{
class DoubleBufferedEntityViews<T> where T : class, IDictionary, new()
class DoubleBufferedEntitiesToAdd<T> where T : Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>, new()
{
readonly T _entityViewsToAddBufferA = new T();
readonly T _entityViewsToAddBufferB = new T();

internal DoubleBufferedEntityViews()
internal DoubleBufferedEntitiesToAdd()
{
this.other = _entityViewsToAddBufferA;
this.current = _entityViewsToAddBufferB;
@@ -21,13 +24,24 @@ namespace Svelto.ECS

internal T other;
internal T current;
internal void Swap()
{
var toSwap = other;
other = current;
current = toSwap;
}

public void ClearOther()
{
foreach (var item in other)
{
foreach (var subitem in item.Value)
{
subitem.Value.Clear();
}
}
}
}
}
}

+ 1
- 1
Svelto.ECS/EnginesRoot.Engines.cs View File

@@ -42,7 +42,7 @@ namespace Svelto.ECS
_groupEntityDB = new Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>();
_groupEntityDB[ExclusiveGroup.StandardEntitiesGroup] = new Dictionary<Type, ITypeSafeDictionary>();
_groupedGroups = new Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>>();
_groupedEntityToAdd = new DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>>();
_groupedEntityToAdd = new DoubleBufferedEntitiesToAdd<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>>();

_DB = new entitiesDB(_groupEntityDB, _groupedGroups);



+ 47
- 5
Svelto.ECS/EnginesRoot.Entities.cs View File

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

@@ -40,10 +41,16 @@ namespace Svelto.ECS
EntityStructInitializer BuildEntity<T>(EGID entityID, object[] implementors)
where T : IEntityDescriptor, new()
{
var descriptorEntitiesToBuild = EntityDescriptorTemplate<T>.descriptor.entitiesToBuild;
#if DEBUG && !PROFILER
CheckEntityID(entityID, descriptorEntitiesToBuild);
#endif
var dic = EntityFactory.BuildGroupedEntityViews(entityID,
_groupedEntityToAdd.current,
EntityDescriptorTemplate<T>.descriptor.entitiesToBuild,
descriptorEntitiesToBuild,
implementors);

_newEntitiesBuiltToProcess++;
return new EntityStructInitializer(entityID, dic);
}
@@ -52,13 +59,48 @@ namespace Svelto.ECS
IEntityBuilder[] entityToBuild,
object[] implementors)
{
#if DEBUG && !PROFILER
CheckEntityID(entityID, entityToBuild);
#endif
var dic = EntityFactory.BuildGroupedEntityViews(entityID,
_groupedEntityToAdd.current,
entityToBuild,
implementors);
_newEntitiesBuiltToProcess++;
return new EntityStructInitializer(entityID, dic);
}
void CheckEntityID(EGID entityID, IEntityBuilder[] descriptorEntitiesToBuild)
{
Dictionary<Type, ITypeSafeDictionary> @group;
if (_groupEntityDB.TryGetValue(entityID.groupID, out @group) == true)
{
for (int i = 0; i < descriptorEntitiesToBuild.Length; i++)
{
CheckEntityID(entityID, descriptorEntitiesToBuild[i].GetEntityType(), @group);
}
CheckEntityID(entityID, _typeEntityInfoView, @group);
}
}

static void CheckEntityID(EGID entityID, Type entityType, Dictionary<Type, ITypeSafeDictionary> @group)
{
ITypeSafeDictionary entities;
if (@group.TryGetValue(entityType, out entities))
{
if (entities.Has(entityID.entityID) == true)
{
Utility.Console.LogError("Entity with used ID is about to be built: "
.FastConcat(entityType)
.FastConcat(" id: ")
.FastConcat(entityID.entityID)
.FastConcat(" groupid: ")
.FastConcat(entityID.groupID));
}
}
}

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

@@ -181,7 +223,7 @@ namespace Svelto.ECS
MoveEntity(new EGID(entityID, fromGroupID), toGroupID, toGroup);
}
EGID SwapFirstEntityGroup(int fromGroupID, int toGroupId)
EGID SwapFirstEntityInGroup(int fromGroupID, int toGroupId)
{
var firstID =
((TypeSafeDictionary<EntityInfoView>) _groupEntityDB[fromGroupID][_typeEntityInfoView]).FasterValues[0].ID.entityID;
@@ -191,10 +233,10 @@ namespace Svelto.ECS
return new EGID(firstID, toGroupId);
}

readonly entitiesDB _DB;
readonly DoubleBufferedEntityViews<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>> _groupedEntityToAdd;
readonly entitiesDB _DB;
static readonly Type _typeEntityInfoView = typeof(EntityInfoView);
static readonly Type _typeEntityInfoView = typeof(EntityInfoView);
int _newEntitiesBuiltToProcess;
}

public struct EntityStructInitializer


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

@@ -54,7 +54,7 @@ namespace Svelto.ECS

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

+ 7
- 9
Svelto.ECS/EnginesRoot.Submission.cs View File

@@ -14,11 +14,10 @@ namespace Svelto.ECS
{
void SubmitEntityViews()
{
bool newEntityViewsHaveBeenAddedWhileIterating = _groupedEntityToAdd.current.Count > 0;

int numberOfReenteringLoops = 0;

while (newEntityViewsHaveBeenAddedWhileIterating)
//are there new entities built to process?
while ( _newEntitiesBuiltToProcess > 0)
{
//use other as source from now on
//current will be use to write new entityViews
@@ -33,15 +32,13 @@ namespace Svelto.ECS
if (_groupedEntityToAdd.other.Count > 0)
AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd.other);

//other can be cleared now
_groupedEntityToAdd.other.Clear();

//has current new entityViews?
newEntityViewsHaveBeenAddedWhileIterating = _groupedEntityToAdd.current.Count > 0;
//other can be cleared now, but let's avoid deleting the dictionary every time
_groupedEntityToAdd.ClearOther();

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

_newEntitiesBuiltToProcess = 0;
numberOfReenteringLoops++;
}
}
@@ -70,7 +67,7 @@ namespace Svelto.ECS
if (_groupedGroups.TryGetValue(entityViewTypeSafeDictionary.Key, out groupedGroup) == false)
groupedGroup = _groupedGroups[entityViewTypeSafeDictionary.Key] = new FasterDictionary<int, ITypeSafeDictionary>();

//type safe copy
//Fill the DB with the entity views generate this frame.
dbDic.FillWithIndexedEntities(entityViewTypeSafeDictionary.Value);
groupedGroup[groupID] = dbDic;
}
@@ -95,6 +92,7 @@ namespace Svelto.ECS
readonly Dictionary<int, Dictionary<Type, ITypeSafeDictionary>> _groupEntityDB;
readonly Dictionary<Type, FasterDictionary<int, ITypeSafeDictionary>> _groupedGroups; //yes I am being sarcastic
readonly DoubleBufferedEntitiesToAdd<Dictionary<int, Dictionary<Type, ITypeSafeDictionary>>> _groupedEntityToAdd;
readonly EntitySubmissionScheduler _scheduler;
}
}

+ 25
- 17
Svelto.ECS/EntitiesDB.cs View File

@@ -57,27 +57,16 @@ namespace Svelto.ECS.Internal

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

if (casted == null || casted.TryFindElementIndex(entityGID.entityID, out index) == false)
{
index = 0;
return null;
}

int count;
T[] array;
if ((array = QueryEntitiesAndIndexInternal<T>(entityGID, out index)) != null)
return array;
return QueryEntities<T>(entityGID.groupID, out count);
throw new Exception("Entity not found id: ".FastConcat(entityGID.entityID).FastConcat(" groupID: ").FastConcat(entityGID.groupID));
}
public bool TryQueryEntitiesAndIndex<T>(EGID entityGid, out uint index, out T[] array) where T : IEntityStruct
{
if ((array = QueryEntitiesAndIndex<T>(entityGid, out index)) != null)
if ((array = QueryEntitiesAndIndexInternal<T>(entityGid, out index)) != null)
return true;
return false;
@@ -275,7 +264,26 @@ namespace Svelto.ECS.Internal

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

if (casted == null || casted.TryFindElementIndex(entityGID.entityID, out index) == false)
{
index = 0;
return null;
}

int count;
return QueryEntities<T>(entityGID.groupID, out count);
}
static ReadOnlyCollectionStruct<T> RetrieveEmptyEntityViewList<T>()
{
return ReadOnlyCollectionStruct<T>.DefaultList;


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

@@ -48,6 +48,7 @@ namespace Svelto.ECS.Internal
}

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

@@ -62,6 +63,7 @@ namespace Svelto.ECS.Internal
//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.
entityBuilder.BuildEntityViewAndAddToList(ref safeDictionary, entityID, implementors);

if (entityViewsPoolWillBeCreated)


+ 27
- 15
Svelto.ECS/EntityViewBuilder.cs View File

@@ -18,20 +18,7 @@ namespace Svelto.ECS
#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(field.FieldType);
}
CheckFields(typeof(T));
}
#endif
if (needsReflection == true)
@@ -39,7 +26,32 @@ namespace Svelto.ECS
EntityView<T>.InitCache();
}
}
#if DEBUG && !PROFILER
static void CheckFields(Type type)
{
var fields = type.GetFields(BindingFlags.Public |
BindingFlags.Instance);

for (int i = fields.Length - 1; i >= 0; --i)
{
var field = fields[i];

var fieldFieldType = field.FieldType;
if (fieldFieldType.IsPrimitive == true || fieldFieldType.IsValueType == true)
{
if (fieldFieldType.IsValueType && !fieldFieldType.IsEnum)
{
CheckFields(fieldFieldType);
}

continue;
}

throw new EntityStructException(fieldFieldType);
}
}
#endif

public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors)
{
if (dictionary == null)


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

@@ -20,7 +20,8 @@ static class EntityViewUtility
.NoVirt.ToArrayFast(entityViewBlazingFastReflection, out count);
#if DEBUG && !PROFILER
if (count == 0)
throw new Exception(NO_COMPONENTS_EXCEPTION.FastConcat("Type ", entityDescriptorName, " entityView ", entityBuilder.GetEntityType().ToString()));
throw new Exception(NO_COMPONENTS_EXCEPTION.FastConcat("Type ", entityDescriptorName, " entityView ",
entityBuilder.GetEntityType().ToString()));
#endif
for (var index = 0; index < implementors.Length; index++)
{
@@ -52,7 +53,8 @@ static class EntityViewUtility
#if DEBUG && !PROFILER
else
{
Utility.Console.Log(NULL_IMPLEMENTOR_ERROR.FastConcat("Type ", entityDescriptorName, " entityView ", entityBuilder.GetEntityType().ToString()));
Utility.Console.Log(NULL_IMPLEMENTOR_ERROR.FastConcat("Type ", entityDescriptorName, " entityView ",
entityBuilder.GetEntityType().ToString()));
}
#endif
}
@@ -71,8 +73,8 @@ static class EntityViewUtility
if (implementorsByType.TryGetValue(fieldType, out component) == false)
{
var e = new Exception(NOT_FOUND_EXCEPTION + " Component Type: " + fieldType.Name +
" - EntityView: " +
entityBuilder.GetEntityType().Name + " - EntityDescriptor " + entityDescriptorName);
" - EntityView: " + entityBuilder.GetEntityType().Name +
" - EntityDescriptor " + entityDescriptorName);

throw e;
}


+ 0
- 2
Svelto.ECS/IEntitiesDB.cs View File

@@ -40,7 +40,6 @@ namespace Svelto.ECS
//to use with EntityViews, EntityStructs and EntityViewStructs
void ExecuteOnEntity<T>(EGID egid, ActionRef<T> action) where T : IEntityStruct;
void ExecuteOnEntity<T>(int id, ActionRef<T> action) where T : IEntityStruct;
void ExecuteOnEntity<T>(int id, int groupid, ActionRef<T> action) where T : IEntityStruct;

@@ -48,7 +47,6 @@ namespace Svelto.ECS
void ExecuteOnEntities<T>(ActionRef<T> action) where T : IEntityStruct;

void ExecuteOnEntity<T, W>(EGID egid, ref W value, ActionRef<T, W> action) where T : IEntityStruct;

void ExecuteOnEntity<T, W>(int id, ref W value, ActionRef<T, W> action) where T : IEntityStruct;
void ExecuteOnEntity<T, W>(int id, int groupid, ref W value, ActionRef<T, W> action) where T : IEntityStruct;


+ 22
- 45
Svelto.ECS/Sequencer.cs View File

@@ -7,39 +7,30 @@ namespace Svelto.ECS
public class Steps : Dictionary<IEngine, IDictionary>
{}

public class To : Dictionary<int, IStep[]>
public class To<C> : Dictionary<C, IStep[]> where C : struct, IConvertible
{
public void Add(IStep engine)
public void Add(C condition, IStep engine)
{
Add(Condition.Always, new [] {engine});
Add(condition, new [] {engine});
}
public void Add(IStep[] engines)
public void Add(C condition, params IStep[] engines)
{
Add(Condition.Always, engines);
Add(condition, engines);
}
public void Add(params IStep[] engines)
{
Add(default(C), engines);
}
}
public class To<C> : Dictionary<C, IStep[]> where C:struct,IConvertible
{}
public interface IStep
{}

public interface IStep<T>:IStep
public interface IStep<in C>:IStep where C:struct,IConvertible
{
void Step(ref T token, int condition);
void Step(C condition, EGID id);
}
public interface IStep<T, in C>:IStep where C:struct,IConvertible
{
void Step(ref T token, C condition);
}
public interface IEnumStep<T>:IStep
{
void Step(ref T token, Enum condition);
}

public abstract class Sequencer
{
public void SetSequence(Steps steps)
@@ -47,39 +38,25 @@ namespace Svelto.ECS
_steps = steps;
}

public void Next<T>(IEngine engine, ref T param)
{
Next(engine, ref param, Condition.Always);
}

public void Next<T>(IEngine engine, ref T param, int condition)
public void Next(IEngine engine, EGID id)
{
int branch = condition;
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);
Next(engine, Condition.Always, id);
}
public void Next<T>(IEngine engine, ref T param, Enum condition)
public void Next(IEngine engine)
{
int branch = Convert.ToInt32(condition);
var steps = (_steps[engine] as Dictionary<int, IStep[]>)[branch];

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

public void Next<T, C>(IEngine engine, ref T param, C condition) where C:struct,IConvertible
public void Next<C>(IEngine engine, C condition, EGID id = new EGID()) 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);
if (steps == null) return;
for (var i = 0; i < steps.Length; i++)
((IStep<C>)steps[i]).Step(condition, id);
}

Steps _steps;
@@ -89,4 +66,4 @@ namespace Svelto.ECS
{
public const int Always = 0;
}
}
}

Loading…
Cancel
Save