diff --git a/Svelto.ECS/CheckEntityUtilities.cs b/Svelto.ECS/CheckEntityUtilities.cs index cbdfc0c..60e727f 100644 --- a/Svelto.ECS/CheckEntityUtilities.cs +++ b/Svelto.ECS/CheckEntityUtilities.cs @@ -1,17 +1,18 @@ -using System; -using System.Collections.Generic; +#if !DEBUG || PROFILER +#define DISABLE_CHECKS using System.Diagnostics; -using Svelto.ECS.Internal; - -#if DEBUG && !PROFILER -#define _USE_IT #endif +using System; +using System.Collections.Generic; +using Svelto.ECS.Internal; namespace Svelto.ECS { public partial class EnginesRoot { - [Conditional("_USE_IT")] +#if DISABLE_CHECKS + [Conditional("_CHECKS_DISABLED")] +#endif void CheckRemoveEntityID(EGID entityID, IEntityDescriptor descriptorEntity) { @@ -27,7 +28,7 @@ namespace Svelto.ECS } else { - Svelto.Utilities.Console.LogError("Entity ".FastConcat(" with not found ID is about to be removed: ") + Utilities.Console.LogError("Entity ".FastConcat(" with not found ID is about to be removed: ") .FastConcat(" id: ") .FastConcat(entityID.entityID) .FastConcat(" groupid: ") @@ -35,7 +36,9 @@ namespace Svelto.ECS } } - [Conditional("_USE_IT")] +#if DISABLE_CHECKS + [Conditional("_CHECKS_DISABLED")] +#endif void CheckRemoveEntityID(EGID entityID, Type entityType, Dictionary @group, string name) { ITypeSafeDictionary entities; @@ -43,7 +46,7 @@ namespace Svelto.ECS { if (entities.Has(entityID.entityID) == false) { - Svelto.Utilities.Console.LogError("Entity ".FastConcat(name, " with not found ID is about to be removed: ") + Utilities.Console.LogError("Entity ".FastConcat(name, " with not found ID is about to be removed: ") .FastConcat(entityType) .FastConcat(" id: ") .FastConcat(entityID.entityID) @@ -53,7 +56,7 @@ namespace Svelto.ECS } else { - Svelto.Utilities.Console.LogError("Entity ".FastConcat(name, " with not found ID is about to be removed: ") + Utilities.Console.LogError("Entity ".FastConcat(name, " with not found ID is about to be removed: ") .FastConcat(entityType) .FastConcat(" id: ") .FastConcat(entityID.entityID) @@ -62,7 +65,9 @@ namespace Svelto.ECS } } - [Conditional("_USE_IT")] +#if DISABLE_CHECKS + [Conditional("_CHECKS_DISABLED")] +#endif void CheckAddEntityID(EGID entityID, T descriptorEntity) where T:IEntityDescriptor { Dictionary @group; @@ -78,7 +83,9 @@ namespace Svelto.ECS } } - [Conditional("_USE_IT")] +#if DISABLE_CHECKS + [Conditional("_CHECKS_DISABLED")] +#endif static void CheckAddEntityID(EGID entityID, Type entityType, Dictionary @group, string name) { ITypeSafeDictionary entities; @@ -86,7 +93,7 @@ namespace Svelto.ECS { if (entities.Has(entityID.entityID) == true) { - Svelto.Utilities.Console.LogError("Entity ".FastConcat(name, " with used ID is about to be built: ") + Utilities.Console.LogError("Entity ".FastConcat(name, " with used ID is about to be built: ") .FastConcat(entityType) .FastConcat(" id: ") .FastConcat(entityID.entityID) diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs index 74289c2..ebc1e81 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionary.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionary.cs @@ -39,17 +39,21 @@ namespace Svelto.ECS.Internal { int count; var buffer = (entities as TypeSafeDictionary).GetValuesArray(out count); - - try + + for (var i = 0; i < count; i++) { - for (var i = 0; i < count; i++) + int idEntityId = 0; + try { - Add(buffer[i].ID.entityID, ref buffer[i]); + idEntityId = buffer[i].ID.entityID; + + Add(idEntityId, ref buffer[i]); + } + catch (Exception e) + { + throw new TypeSafeDictionaryException("trying to add an EntityView with the same ID more than once Entity: ". + FastConcat(typeof(TValue)).FastConcat("id ").FastConcat(idEntityId), e); } - } - catch (Exception e) - { - throw new TypeSafeDictionaryException(e); } } @@ -126,9 +130,7 @@ namespace Svelto.ECS.Internal TValue[] values = GetValuesArray(out count); for (int i = 0; i < count; i++) - { RemoveEntityViewFromEngines(entityViewEnginesDB, ref values[i]); - } } public ITypeSafeDictionary Create() diff --git a/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs index 5504e00..6f0a2c9 100644 --- a/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs +++ b/Svelto.ECS/DataStructures/TypeSafeDictionaryException.cs @@ -4,7 +4,8 @@ namespace Svelto.ECS { public class TypeSafeDictionaryException : Exception { - public TypeSafeDictionaryException(Exception exception) : base("trying to add an EntityView with the same ID more than once", exception) + public TypeSafeDictionaryException(string message, Exception exception) : + base(message, exception) { } } diff --git a/Svelto.ECS/EGID.cs b/Svelto.ECS/EGID.cs index 8dfbdf7..4b30140 100644 --- a/Svelto.ECS/EGID.cs +++ b/Svelto.ECS/EGID.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; namespace Svelto.ECS { - public struct EGID:IEquatable,IEqualityComparer + public struct EGID:IEquatable,IEqualityComparer,IComparable { - long _GID; + readonly long _GID; public int entityID { @@ -56,5 +56,10 @@ namespace Svelto.ECS { return _GID.GetHashCode(); } + + public int CompareTo(long other) + { + return _GID.CompareTo(other); + } } } \ No newline at end of file diff --git a/Svelto.ECS/EnginesRoot.Entities.cs b/Svelto.ECS/EnginesRoot.Entities.cs index 830def0..c7531dc 100644 --- a/Svelto.ECS/EnginesRoot.Entities.cs +++ b/Svelto.ECS/EnginesRoot.Entities.cs @@ -75,7 +75,7 @@ namespace Svelto.ECS { var entityViewsToBuild = EntityDescriptorTemplate.descriptor.entitiesToBuild; var count = entityViewsToBuild.Length; - + //reserve space in the database Dictionary @group; if (_groupEntityDB.TryGetValue(groupID, out group) == false) diff --git a/Svelto.ECS/EnginesRoot.GenericEntityFactory.cs b/Svelto.ECS/EnginesRoot.GenericEntityFactory.cs index edd42b0..7c0a5b3 100644 --- a/Svelto.ECS/EnginesRoot.GenericEntityFactory.cs +++ b/Svelto.ECS/EnginesRoot.GenericEntityFactory.cs @@ -37,7 +37,7 @@ namespace Svelto.ECS public void PreallocateEntitySpace(ExclusiveGroup.ExclusiveGroupStruct groupStructId, int size) where T : IEntityDescriptor, new() { - _weakEngine.Target.Preallocate((int)groupStructId, size); + _weakEngine.Target.Preallocate(groupStructId, size); } } } diff --git a/Svelto.ECS/EnginesRoot.Submission.cs b/Svelto.ECS/EnginesRoot.Submission.cs index 898fd69..c03facc 100644 --- a/Svelto.ECS/EnginesRoot.Submission.cs +++ b/Svelto.ECS/EnginesRoot.Submission.cs @@ -17,69 +17,79 @@ namespace Svelto.ECS { void SubmitEntityViews() { - using (new PlatformProfiler("Svelto.ECS").Sample("Entities submit")) + using (var profiler = new PlatformProfiler("Svelto.ECS - Entities Submission")) { if (_entitiesOperations.Count > 0) { -#if DEBUG && !PROFILER - _entitiesOperationsDebug.Clear(); -#endif - _transientEntitiesOperations.FastClear(); - _transientEntitiesOperations.AddRange(_entitiesOperations); - _entitiesOperations.FastClear(); - var entitiesOperations = _transientEntitiesOperations.ToArrayFast(); - for (var i = 0; i < _transientEntitiesOperations.Count; i++) + using (profiler.Sample("Remove and Swap")) { - try +#if DEBUG && !PROFILER + _entitiesOperationsDebug.Clear(); +#endif + _transientEntitiesOperations.FastClear(); + _transientEntitiesOperations.AddRange(_entitiesOperations); + _entitiesOperations.FastClear(); + var entitiesOperations = _transientEntitiesOperations.ToArrayFast(); + for (var i = 0; i < _transientEntitiesOperations.Count; i++) { - switch (entitiesOperations[i].type) + try { - case EntitySubmitOperationType.Swap: - SwapEntityGroup(entitiesOperations[i].builders, - entitiesOperations[i].entityDescriptor, entitiesOperations[i].id, - entitiesOperations[i].fromGroupID, entitiesOperations[i].toGroupID); - break; - case EntitySubmitOperationType.Remove: - MoveEntity(entitiesOperations[i].builders, - new EGID(entitiesOperations[i].id, entitiesOperations[i].fromGroupID), - entitiesOperations[i].entityDescriptor); - break; - case EntitySubmitOperationType.RemoveGroup: - RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromGroupID); - break; + switch (entitiesOperations[i].type) + { + case EntitySubmitOperationType.Swap: + SwapEntityGroup(entitiesOperations[i].builders, + entitiesOperations[i].entityDescriptor, + entitiesOperations[i].id, + entitiesOperations[i].fromGroupID, + entitiesOperations[i].toGroupID); + break; + case EntitySubmitOperationType.Remove: + MoveEntity(entitiesOperations[i].builders, + new EGID(entitiesOperations[i].id, + entitiesOperations[i].fromGroupID), + entitiesOperations[i].entityDescriptor); + break; + case EntitySubmitOperationType.RemoveGroup: + RemoveGroupAndEntitiesFromDB(entitiesOperations[i].fromGroupID); + break; + } } - } - catch (Exception e) - { -#if DEBUG && !PROFILER - var str = "Entity Operation is ".FastConcat(entitiesOperations[i].type.ToString()) - .FastConcat(" id: ") - .FastConcat(entitiesOperations[i].id) - .FastConcat(" from groupid: ") - .FastConcat(entitiesOperations[i].fromGroupID) - .FastConcat(" to groupid: ") - .FastConcat(entitiesOperations[i].toGroupID); + catch (Exception e) + { +#if DEBUG && !PROFILER + var str = "Entity Operation is ".FastConcat(entitiesOperations[i].type.ToString()) + .FastConcat(" id: ") + .FastConcat(entitiesOperations[i].id) + .FastConcat(" from groupid: ") + .FastConcat(entitiesOperations[i].fromGroupID) + .FastConcat(" to groupid: ") + .FastConcat(entitiesOperations[i].toGroupID); - Console.LogError(e.Message.FastConcat(" ", str, " ", entitiesOperations[i].trace)); + Console.LogError(e.Message.FastConcat(" ", str, " ", entitiesOperations[i].trace)); #else - Console.LogException(e); + Console.LogException(e); #endif + } } } + } - + try { if (_groupedEntityToAdd.current.Count > 0) { - //use other as source from now on current will be use to write new entityViews - _groupedEntityToAdd.Swap(); + using (profiler.Sample("Add")) + { + //use other as source from now on current will be use to write new entityViews + _groupedEntityToAdd.Swap(); - //Note: if N entity of the same type are added on the same frame the Add callback is called N - //times on the same frame. if the Add callback builds a new entity, that entity will not - //be available in the database until the N callbacks are done solving it could be complicated as - //callback and database update must be interleaved. - AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd.other); + //Note: if N entity of the same type are added on the same frame the Add callback is called N + //times on the same frame. if the Add callback builds a new entity, that entity will not + //be available in the database until the N callbacks are done solving it could be complicated as + //callback and database update must be interleaved. + AddEntityViewsToTheDBAndSuitableEngines(_groupedEntityToAdd.other); + } } } catch (Exception e) diff --git a/Svelto.ECS/EntitiesDB.cs b/Svelto.ECS/EntitiesDB.cs index 610541a..bb7bde8 100644 --- a/Svelto.ECS/EntitiesDB.cs +++ b/Svelto.ECS/EntitiesDB.cs @@ -90,6 +90,16 @@ namespace Svelto.ECS.Internal return false; } + public T[] QueryEntitiesAndIndex(int id, ExclusiveGroup.ExclusiveGroupStruct @group, out uint index) where T : IEntityStruct + { + return QueryEntitiesAndIndex(new EGID(id, group), out index); + } + + public bool TryQueryEntitiesAndIndex(int id, ExclusiveGroup.ExclusiveGroupStruct @group, out uint index, out T[] array) where T : IEntityStruct + { + return TryQueryEntitiesAndIndex(new EGID(id, group), out index, out array); + } + public T QueryEntityView(EGID entityGID) where T : class, IEntityStruct { T entityView; diff --git a/Svelto.ECS/EntityBuilder.cs b/Svelto.ECS/EntityBuilder.cs index bedfd60..533dc70 100644 --- a/Svelto.ECS/EntityBuilder.cs +++ b/Svelto.ECS/EntityBuilder.cs @@ -1,14 +1,13 @@ -using System; -using System.Collections.Generic; +#if !DEBUG || PROFILER +#define DISABLE_CHECKS using System.Diagnostics; +#endif +using System.Reflection; +using System; +using System.Collections.Generic; using Svelto.DataStructures; using Svelto.ECS.Internal; using Svelto.Utilities; -using System.Reflection; -#if DEBUG && !PROFILER -#define _USE_IT -#endif - namespace Svelto.ECS { @@ -21,12 +20,12 @@ namespace Svelto.ECS CheckFields(ENTITY_VIEW_TYPE); if (needsReflection == true) - { EntityView.InitCache(); - } } - [Conditional("_USE_IT")] +#if DISABLE_CHECKS + [Conditional("_CHECKS_DISABLED")] +#endif static void CheckFields(Type type) { if (needsReflection == false && ENTITY_VIEW_TYPE != typeof(EntityInfoView)) diff --git a/Svelto.ECS/IEntitiesDB.cs b/Svelto.ECS/IEntitiesDB.cs index 1f7a28f..50c1841 100644 --- a/Svelto.ECS/IEntitiesDB.cs +++ b/Svelto.ECS/IEntitiesDB.cs @@ -83,6 +83,8 @@ namespace Svelto.ECS /// T[] QueryEntitiesAndIndex(EGID entityGid, out uint index) where T : IEntityStruct; bool TryQueryEntitiesAndIndex(EGID entityGid, out uint index, out T[] array) where T : IEntityStruct; + T[] QueryEntitiesAndIndex(int id, ExclusiveGroup.ExclusiveGroupStruct group, out uint index) where T : IEntityStruct; + bool TryQueryEntitiesAndIndex(int id, ExclusiveGroup.ExclusiveGroupStruct group, out uint index, out T[] array) where T : IEntityStruct; /// /// ECS is meant to work on a set of Entities. Working on a single entity is sometime necessary, but using /// the following functions inside a loop would be a mistake as performance can be significantly impacted diff --git a/Svelto.ECS/Sequencer.cs b/Svelto.ECS/Sequencer.cs index 0b0a25d..189eb76 100644 --- a/Svelto.ECS/Sequencer.cs +++ b/Svelto.ECS/Sequencer.cs @@ -99,7 +99,7 @@ namespace Svelto.ECS /// public class Sequencer where S: Sequencer, new() { - public void SetSequence(Steps steps) + protected void SetSequence(Steps steps) { _steps = steps; }