improve code add more debug checkstags/2.7
@@ -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 | |||
@@ -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; | |||
} | |||
} |
@@ -0,0 +1,10 @@ | |||
using System; | |||
namespace Svelto.ECS.Internal | |||
{ | |||
class ECSException : Exception | |||
{ | |||
public ECSException(string message):base(message) | |||
{} | |||
} | |||
} |
@@ -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 | |||
@@ -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); | |||
} | |||
@@ -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>(); | |||
@@ -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); | |||
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
@@ -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; | |||
} | |||
} |
@@ -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) | |||