using System.Runtime.CompilerServices; using Svelto.Common; using Svelto.DataStructures; using Svelto.ECS.Internal; namespace Svelto.ECS { public partial class EnginesRoot { /// /// todo: EnginesRoot was a weakreference to give the change to inject /// entity functions from other engines root. It probably should be reverted /// class GenericEntityFunctions : IEntityFunctions { internal GenericEntityFunctions(EnginesRoot weakReference) { _enginesRoot = new Svelto.DataStructures.WeakReference(weakReference); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveEntity(uint entityID, ExclusiveBuildGroup groupID) where T : IEntityDescriptor, new() { RemoveEntity(new EGID(entityID, groupID)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveEntity(EGID entityEGID) where T : IEntityDescriptor, new() { DBC.ECS.Check.Require((uint)entityEGID.groupID != 0, "invalid group detected"); var descriptorComponentsToBuild = EntityDescriptorTemplate.descriptor.componentsToBuild; _enginesRoot.Target.CheckRemoveEntityID(entityEGID, TypeCache.type); _enginesRoot.Target.QueueEntitySubmitOperation( new EntitySubmitOperation(EntitySubmitOperationType.Remove, entityEGID, entityEGID, descriptorComponentsToBuild)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveEntitiesFromGroup(ExclusiveBuildGroup groupID) { DBC.ECS.Check.Require((uint)groupID != 0, "invalid group detected"); _enginesRoot.Target.RemoveGroupID(groupID); _enginesRoot.Target.QueueEntitySubmitOperation( new EntitySubmitOperation(EntitySubmitOperationType.RemoveGroup, new EGID(0, groupID), new EGID())); } // [MethodImpl(MethodImplOptions.AggressiveInlining)] // void RemoveAllEntities(ExclusiveGroup group) // where D : IEntityDescriptor, new() where S : unmanaged, IEntityComponent // { // var targetEntitiesDB = _enginesRoot.Target._entitiesDB; // var (buffer, count) = targetEntitiesDB.QueryEntities(@group); // for (uint i = 0; i < count; ++i) // { // RemoveEntity(new EGID(i, group)); // } // } // // [MethodImpl(MethodImplOptions.AggressiveInlining)] // void RemoveAllEntities() // where D : IEntityDescriptor, new() where S : unmanaged, IEntityComponent // { // var targetEntitiesDB = _enginesRoot.Target._entitiesDB; // foreach (var ((buffer, count), exclusiveGroupStruct) in targetEntitiesDB.QueryEntities()) // for (uint i = 0; i < count; ++i) // { // RemoveEntity(new EGID(i, exclusiveGroupStruct)); // } // } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntitiesInGroup(ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID) where T : IEntityDescriptor, new() { if (_enginesRoot.Target._groupEntityComponentsDB.TryGetValue( fromGroupID.group, out FasterDictionary entitiesInGroupPerType) == true) { #if DEBUG && !PROFILE_SVELTO IComponentBuilder[] components = EntityDescriptorTemplate.descriptor.componentsToBuild; var dictionary = entitiesInGroupPerType[new RefWrapperType(components[0].GetEntityComponentType())]; dictionary.KeysEvaluator((key) => { _enginesRoot.Target.CheckRemoveEntityID(new EGID(key, fromGroupID), TypeCache.type); _enginesRoot.Target.CheckAddEntityID(new EGID(key, toGroupID), TypeCache.type); }); #endif _enginesRoot.Target.QueueEntitySubmitOperation( new EntitySubmitOperation(EntitySubmitOperationType.SwapGroup, new EGID(0, fromGroupID) , new EGID(0, toGroupID))); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntityGroup(uint entityID, ExclusiveBuildGroup fromGroupID, ExclusiveBuildGroup toGroupID) where T : IEntityDescriptor, new() { SwapEntityGroup(new EGID(entityID, fromGroupID), toGroupID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntityGroup(EGID fromID, ExclusiveBuildGroup toGroupID) where T : IEntityDescriptor, new() { SwapEntityGroup(fromID, new EGID(fromID.entityID, (uint) toGroupID)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntityGroup(EGID fromID, ExclusiveBuildGroup mustBeFromGroup, ExclusiveBuildGroup toGroupID) where T : IEntityDescriptor, new() { if (fromID.groupID != mustBeFromGroup) throw new ECSException($"Entity is not coming from the expected group. Expected {mustBeFromGroup} is {fromID.groupID}"); SwapEntityGroup(fromID, toGroupID); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntityGroup(EGID fromID, EGID toID, ExclusiveBuildGroup mustBeFromGroup) where T : IEntityDescriptor, new() { if (fromID.groupID != mustBeFromGroup) throw new ECSException($"Entity is not coming from the expected group Expected {mustBeFromGroup} is {fromID.groupID}"); SwapEntityGroup(fromID, toID); } #if UNITY_NATIVE public Svelto.ECS.Native.NativeEntityRemove ToNativeRemove(string memberName) where T : IEntityDescriptor, new() { return _enginesRoot.Target.ProvideNativeEntityRemoveQueue(memberName); } public Svelto.ECS.Native.NativeEntitySwap ToNativeSwap(string memberName) where T : IEntityDescriptor, new() { return _enginesRoot.Target.ProvideNativeEntitySwapQueue(memberName); } #endif [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapEntityGroup(EGID fromID, EGID toID) where T : IEntityDescriptor, new() { DBC.ECS.Check.Require((uint)fromID.groupID != 0, "invalid group detected"); DBC.ECS.Check.Require((uint)toID.groupID != 0, "invalid group detected"); var enginesRootTarget = _enginesRoot.Target; var descriptorComponentsToBuild = EntityDescriptorTemplate.descriptor.componentsToBuild; enginesRootTarget.CheckRemoveEntityID(fromID, TypeCache.type); enginesRootTarget.CheckAddEntityID(toID, TypeCache.type); enginesRootTarget.QueueEntitySubmitOperation( new EntitySubmitOperation(EntitySubmitOperationType.Swap, fromID, toID, descriptorComponentsToBuild)); } //enginesRoot is a weakreference because GenericEntityStreamConsumerFactory can be injected inside //engines of other enginesRoot readonly Svelto.DataStructures.WeakReference _enginesRoot; } void QueueEntitySubmitOperation(EntitySubmitOperation entitySubmitOperation) { #if DEBUG && !PROFILE_SVELTO entitySubmitOperation.trace = new System.Diagnostics.StackFrame(1, true); #endif _entitiesOperations.Add((ulong) entitySubmitOperation.fromID, entitySubmitOperation); } void QueueEntitySubmitOperation(EntitySubmitOperation entitySubmitOperation) where T : IEntityDescriptor { #if DEBUG && !PROFILE_SVELTO entitySubmitOperation.trace = new System.Diagnostics.StackFrame(1, true); if (_entitiesOperations.TryGetValue((ulong) entitySubmitOperation.fromID, out var entitySubmitedOperation)) { if (entitySubmitedOperation != entitySubmitOperation) throw new ECSException("Only one entity operation per submission is allowed" .FastConcat(" entityComponentType: ") .FastConcat(typeof(T).Name) .FastConcat(" submission type ", entitySubmitOperation.type.ToString(), " from ID: ", entitySubmitOperation.fromID.entityID.ToString()) .FastConcat(" previous operation type: ", _entitiesOperations[(ulong) entitySubmitOperation.fromID].type .ToString())); } else #endif _entitiesOperations[(ulong) entitySubmitOperation.fromID] = entitySubmitOperation; } } }