Browse Source

Fix DynamicEntityDescriptor based entities, now they can be removed and swapped again

improve code
add more debug  checks
tags/2.7
sebas77 6 years ago
parent
commit
df921b47eb
11 changed files with 132 additions and 76 deletions
  1. +0
    -1
      Svelto.ECS/DataStructures/TypeSafeDictionary.cs
  2. +37
    -0
      Svelto.ECS/DynamicEntityDescriptorInfo.cs
  3. +10
    -0
      Svelto.ECS/ECSException.cs
  4. +34
    -16
      Svelto.ECS/EnginesRoot.Entities.cs
  5. +2
    -2
      Svelto.ECS/EnginesRoot.GenericEntityFactory.cs
  6. +2
    -2
      Svelto.ECS/EntityBuilder.cs
  7. +26
    -12
      Svelto.ECS/EntityFactory.cs
  8. +18
    -18
      Svelto.ECS/GenericEntityDescriptor.cs
  9. +1
    -1
      Svelto.ECS/IEntityBuilder.cs
  10. +2
    -2
      Svelto.ECS/IEntityFactory.cs
  11. +0
    -22
      Svelto.ECS/StaticEntityDescriptorInfo.cs

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

@@ -25,7 +25,6 @@ namespace Svelto.ECS.Internal
void Trim();
void Clear();
bool Has(int entityIdEntityId);
int GetFirstID();
}

class TypeSafeDictionary<TValue> : FasterDictionary<int, TValue>, ITypeSafeDictionary where TValue : IEntityStruct


+ 37
- 0
Svelto.ECS/DynamicEntityDescriptorInfo.cs View File

@@ -0,0 +1,37 @@
using System;
using Svelto.DataStructures;

namespace Svelto.ECS
{
public struct DynamicEntityDescriptorInfo<TType>:IEntityDescriptor where TType : IEntityDescriptor, new()
{
public DynamicEntityDescriptorInfo(FasterList<IEntityBuilder> extraEntities) : this()
{
DBC.ECS.Check.Require(extraEntities.Count > 0,
"don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews");

var defaultEntities = EntityDescriptorTemplate<TType>.descriptor.entitiesToBuild;
var length = defaultEntities.Length;

entitiesToBuild = new IEntityBuilder[length + extraEntities.Count + 1];

Array.Copy(defaultEntities, 0, entitiesToBuild, 0, length);
Array.Copy(extraEntities.ToArrayFast(), 0, entitiesToBuild, length, extraEntities.Count);

var _builder = new EntityBuilder<EntityInfoView>
{
_initializer = new EntityInfoView { entitiesToBuild = entitiesToBuild }
};
entitiesToBuild[entitiesToBuild.Length - 1] = _builder;
}

public IEntityBuilder[] entitiesToBuild { get; private set; }
}
public struct EntityInfoView : IEntityStruct
{
public EGID ID { get; set; }
public IEntityBuilder[] entitiesToBuild;
}
}

+ 10
- 0
Svelto.ECS/ECSException.cs View File

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

namespace Svelto.ECS.Internal
{
class ECSException : Exception
{
public ECSException(string message):base(message)
{}
}
}

+ 34
- 16
Svelto.ECS/EnginesRoot.Entities.cs View File

@@ -44,16 +44,16 @@ namespace Svelto.ECS
return BuildEntity(entityID, EntityDescriptorTemplate<T>.descriptor, implementors);
}

EntityStructInitializer BuildEntity(EGID entityID,
IEntityDescriptor entityDescriptor,
object[] implementors)
EntityStructInitializer BuildEntity<T>(EGID entityID,
T entityDescriptor,
object[] implementors) where T:IEntityDescriptor
{
var descriptorEntitiesToBuild = entityDescriptor.entitiesToBuild;
#if DEBUG && !PROFILER
CheckEntityID(entityID, entityDescriptor);
#endif
var dic = EntityFactory.BuildGroupedEntityViews(entityID,
var dic = EntityFactory.BuildGroupedEntities(entityID,
_groupedEntityToAdd.current,
descriptorEntitiesToBuild,
implementors);
@@ -132,25 +132,41 @@ namespace Svelto.ECS
///--------------------------------------------
///
void MoveEntity(IEntityBuilder[] entityBuilders, EGID entityGID, int toGroupID = -1, Dictionary<Type, ITypeSafeDictionary> toGroup = null)
void MoveEntity(IEntityBuilder[] entityBuilders, EGID entityGID, int toGroupID = -1,
Dictionary<Type, ITypeSafeDictionary> toGroup = null)
{
var entityBuildersCount = entityBuilders.Length;
//for each entity view generated by the entity descriptor
for (var i = 0; i < entityBuildersCount; i++)
DBC.ECS.Check.Require(_groupEntityDB.ContainsKey(entityGID.groupID) == true, "from group not found");
var fromGroup = _groupEntityDB[entityGID.groupID];
ITypeSafeDictionary entityInfoViewDic;
if (fromGroup.TryGetValue(_entityInfoView, out entityInfoViewDic) == true)
{
var entityType = entityBuilders[i].GetEntityType();
var realEntityInfoView = entityInfoViewDic as TypeSafeDictionary<EntityInfoView>;
var entitiesToMove = realEntityInfoView[entityGID.entityID].entitiesToBuild;
MoveEntity(entityGID, toGroupID, toGroup, entityType);
for (int i = 0; i < entitiesToMove.Length; i++)
MoveEntityView(entityGID, toGroupID, toGroup, fromGroup, entitiesToMove[i].GetEntityType());
}
else
{
for (var i = 0; i < entityBuildersCount; i++)
{
var entityType = entityBuilders[i].GetEntityType();

MoveEntityView(entityGID, toGroupID, toGroup, fromGroup, entityType);
}
}
}

void MoveEntity(EGID fromEntityGID, int toGroupID, Dictionary<Type, ITypeSafeDictionary> toGroup, Type entityType)
void MoveEntityView(EGID entityGID, int toGroupID, Dictionary<Type, ITypeSafeDictionary> toGroup,
Dictionary<Type, ITypeSafeDictionary> fromGroup, Type entityType)
{
var fromGroup = _groupEntityDB[fromEntityGID.groupID];

var fromTypeSafeDictionary = fromGroup[entityType];
ITypeSafeDictionary safeDictionary = null;
DBC.ECS.Check.Require(fromGroup.ContainsKey(entityType) == true, "from group not found");
var fromTypeSafeDictionary = fromGroup[entityType];
ITypeSafeDictionary safeDictionary = null;

if (toGroup != null)
{
@@ -164,17 +180,18 @@ namespace Svelto.ECS
_groupedGroups[entityType][toGroupID] = safeDictionary;
}

fromTypeSafeDictionary.MoveEntityFromDictionaryAndEngines(fromEntityGID, toGroupID, safeDictionary, _entityEngines);
DBC.ECS.Check.Assert(fromTypeSafeDictionary.Has(entityGID.entityID), "entity not found");
fromTypeSafeDictionary.MoveEntityFromDictionaryAndEngines(entityGID, toGroupID, safeDictionary, _entityEngines);

if (fromTypeSafeDictionary.Count == 0) //clean up
{
_groupedGroups[entityType].Remove(fromEntityGID.groupID);
_groupedGroups[entityType].Remove(entityGID.groupID);

//it's probably better to not remove this, but the dictionary should be trimmed?
//fromGroup.Remove(entityType);
fromTypeSafeDictionary.Trim();
}
//it doesn't eliminate the fromGroup itself on purpose
}

@@ -202,6 +219,7 @@ namespace Svelto.ECS
readonly EntitiesDB _DB;
int _newEntitiesBuiltToProcess;
Type _entityInfoView = typeof(EntityInfoView);
}

public struct EntityStructInitializer


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

@@ -25,12 +25,12 @@ namespace Svelto.ECS
return _weakEngine.Target.BuildEntity<T>(egid, implementors);
}

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

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


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

@@ -16,7 +16,7 @@ namespace Svelto.ECS
_initializer = default(T);

#if DEBUG && !PROFILER
if (needsReflection == false)
if (needsReflection == false && typeof(T) != typeof(EntityInfoView) )
{
CheckFields(typeof(T));
}
@@ -78,7 +78,7 @@ namespace Svelto.ECS
}
#endif

public void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors)
public void BuildEntityAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors)
{
if (dictionary == null)
dictionary = new TypeSafeDictionary<T>();


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

@@ -7,19 +7,19 @@ namespace Svelto.ECS.Internal
static class EntityFactory
{
internal static Dictionary<Type, ITypeSafeDictionary>
BuildGroupedEntityViews(EGID egid,
BuildGroupedEntities(EGID egid,
FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsByType,
IEntityBuilder[] entityToBuild,
IEntityBuilder[] entitiesToBuild,
object[] implementors)
{
var @group = FetchEntityViewGroup(egid.groupID, groupEntityViewsByType);
var @group = FetchEntityGroup(egid.groupID, groupEntityViewsByType);

BuildEntityViewsAndAddToGroup(egid, group, entityToBuild, implementors);
BuildEntitiesAndAddToGroup(egid, group, entitiesToBuild, implementors);

return group;
}

static Dictionary<Type, ITypeSafeDictionary> FetchEntityViewGroup(int groupID,
static Dictionary<Type, ITypeSafeDictionary> FetchEntityGroup(int groupID,
FasterDictionary<int, Dictionary<Type, ITypeSafeDictionary>> groupEntityViewsByType)
{
Dictionary<Type, ITypeSafeDictionary> group;
@@ -33,23 +33,37 @@ namespace Svelto.ECS.Internal
return @group;
}

static void BuildEntityViewsAndAddToGroup(EGID entityID,
static void BuildEntitiesAndAddToGroup(EGID entityID,
Dictionary<Type, ITypeSafeDictionary> @group,
IEntityBuilder[] entityToBuild,
IEntityBuilder[] entitiesToBuild,
object[] implementors)
{
var count = entityToBuild.Length;
var count = entitiesToBuild.Length;
#if DEBUG && !PROFILER
HashSet<Type> types = new HashSet<Type>();
for (var index = 0; index < count; ++index)
{
var entityType = entitiesToBuild[index].GetEntityType();
if (types.Contains(entityType))
{
throw new ECSException("EntityBuilders must be unique inside an EntityDescriptor");
}
types.Add(entityType);
}
#endif

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

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

static void BuildEntityView(EGID entityID, Dictionary<Type, ITypeSafeDictionary> @group,
static void BuildEntity(EGID entityID, Dictionary<Type, ITypeSafeDictionary> @group,
Type entityViewType, IEntityBuilder entityBuilder, object[] implementors)
{
ITypeSafeDictionary safeDictionary;
@@ -59,7 +73,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);
entityBuilder.BuildEntityAndAddToList(ref safeDictionary, entityID, implementors);

if (entityViewsPoolWillBeCreated)
@group.Add(entityViewType, safeDictionary);


+ 18
- 18
Svelto.ECS/GenericEntityDescriptor.cs View File

@@ -4,15 +4,15 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] { new EntityBuilder<T>() };
_entityBuilders = new IEntityBuilder[] { new EntityBuilder<T>() };
}
public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}

public abstract class GenericEntityDescriptor<T, U> : IEntityDescriptor where T : IEntityStruct, new()
@@ -20,15 +20,15 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>()};
_entityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>()};
}

public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}

public abstract class GenericEntityDescriptor<T, U, V> : IEntityDescriptor where T : IEntityStruct, new()
@@ -37,15 +37,15 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>()};
_entityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>()};
}

public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}

public abstract class GenericEntityDescriptor<T, U, V, W> : IEntityDescriptor where T : IEntityStruct, new()
@@ -55,15 +55,15 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>()};
_entityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>()};
}

public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}

public abstract class GenericEntityDescriptor<T, U, V, W, X> : IEntityDescriptor where T : IEntityStruct, new()
@@ -74,15 +74,15 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>(), new EntityBuilder<X>()};
_entityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>(), new EntityBuilder<X>()};
}

public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}

public abstract class GenericEntityDescriptor<T, U, V, W, X, Y> : IEntityDescriptor where T : IEntityStruct, new()
@@ -94,14 +94,14 @@
{
static GenericEntityDescriptor()
{
EntityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>(), new EntityBuilder<X>(), new EntityBuilder<Y>()};
_entityBuilders = new IEntityBuilder[] {new EntityBuilder<T>(), new EntityBuilder<U>(), new EntityBuilder<V>(), new EntityBuilder<W>(), new EntityBuilder<X>(), new EntityBuilder<Y>()};
}

public IEntityBuilder[] entitiesToBuild
{
get { return EntityBuilders; }
get { return _entityBuilders; }
}

static readonly IEntityBuilder[] EntityBuilders;
static readonly IEntityBuilder[] _entityBuilders;
}
}

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

@@ -5,7 +5,7 @@ namespace Svelto.ECS
{
public interface IEntityBuilder
{
void BuildEntityViewAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors);
void BuildEntityAndAddToList(ref ITypeSafeDictionary dictionary, EGID entityID, object[] implementors);
ITypeSafeDictionary Preallocate(ref ITypeSafeDictionary dictionary, int size);

Type GetEntityType();


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

@@ -48,7 +48,7 @@ namespace Svelto.ECS
/// <param name="entityDescriptor"></param>
/// <param name="implementors"></param>
///
EntityStructInitializer BuildEntity(int entityID, ExclusiveGroup groupID, IEntityDescriptor descriptorEntity, object[] implementors);
EntityStructInitializer BuildEntity(EGID egid, IEntityDescriptor descriptorEntity, object[] implementors);
EntityStructInitializer BuildEntity<T>(int entityID, ExclusiveGroup groupID, T descriptorEntity, object[] implementors) where T:IEntityDescriptor;
EntityStructInitializer BuildEntity<T>(EGID egid, T descriptorEntity, object[] implementors) where T:IEntityDescriptor;
}
}

+ 0
- 22
Svelto.ECS/StaticEntityDescriptorInfo.cs View File

@@ -1,6 +1,3 @@
using System;
using Svelto.DataStructures;

namespace Svelto.ECS
{
public interface IEntityDescriptor
@@ -23,25 +20,6 @@ namespace Svelto.ECS
public static readonly StaticEntityDescriptorInfo<TType> descriptor = new StaticEntityDescriptorInfo<TType>(new TType());
}

public struct DynamicEntityDescriptorInfo<TType>:IEntityDescriptor where TType : IEntityDescriptor, new()
{
public DynamicEntityDescriptorInfo(FasterList<IEntityBuilder> extraEntityViews) : this()
{
DBC.ECS.Check.Require(extraEntityViews.Count > 0,
"don't use a DynamicEntityDescriptorInfo if you don't need to use extra EntityViews");

var defaultEntityViewsToBuild = EntityDescriptorTemplate<TType>.descriptor.entitiesToBuild;
var length = defaultEntityViewsToBuild.Length;

entitiesToBuild = new IEntityBuilder[length + extraEntityViews.Count];

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

public IEntityBuilder[] entitiesToBuild { get; private set; }
}

public class StaticEntityDescriptorInfo<TType>: IEntityDescriptor where TType : IEntityDescriptor
{
internal StaticEntityDescriptorInfo(TType descriptor)


Loading…
Cancel
Save