diff --git a/src/Arch.Tests/EntityTest.cs b/src/Arch.Tests/EntityTest.cs index 766e415..bc26bed 100644 --- a/src/Arch.Tests/EntityTest.cs +++ b/src/Arch.Tests/EntityTest.cs @@ -132,14 +132,14 @@ public void AddAndRemove_NonGeneric() using var world = World.Create(); var entity = world.Create(); - entity.AddRange(new List{typeof(Transform), typeof(Rotation)}); - That(entity.HasRange(typeof(Transform), typeof(Rotation))); + entity.AddRange(new ComponentType[]{typeof(Transform), typeof(Rotation)}); + That(entity.HasRange(new ComponentType[]{typeof(Transform), typeof(Rotation)})); - entity.RemoveRange(typeof(Transform), typeof(Rotation)); - That(!entity.HasRange(typeof(Transform), typeof(Rotation))); + entity.RemoveRange(new ComponentType[]{typeof(Transform), typeof(Rotation)}); + That(!entity.HasRange(new ComponentType[]{ typeof(Transform), typeof(Rotation)})); - entity.AddRange(new Transform(), new Rotation()); - That(entity.HasRange(typeof(Transform), typeof(Rotation))); + entity.AddRange(new object[]{ new Transform(), new Rotation()}); + That(entity.HasRange(new ComponentType[]{ typeof(Transform), typeof(Rotation)})); } } diff --git a/src/Arch.Tests/WorldTest.cs b/src/Arch.Tests/WorldTest.cs index a5b9520..3f89e58 100644 --- a/src/Arch.Tests/WorldTest.cs +++ b/src/Arch.Tests/WorldTest.cs @@ -3,6 +3,7 @@ using Arch.Core.Extensions; using Arch.Core.Extensions.Dangerous; using Arch.Core.Utils; +using CommunityToolkit.HighPerformance; using static NUnit.Framework.Assert; namespace Arch.Tests; @@ -91,10 +92,10 @@ public void DestroyAll() { var query = new QueryDescription { All = new ComponentType[] { typeof(Transform) } }; - var entities = new List(); - _world.GetEntities(query, entities); + var entities = new Entity[_world.CountEntities(query)]; + _world.GetEntities(query, entities.AsSpan()); - for (var i = 0; i < entities.Count; i++) + for (var i = 0; i < entities.Length; i++) { var entity = entities[i]; _world.Destroy(entity); @@ -363,15 +364,15 @@ public void GetEntitesTest() var entity = world.Create(archTypes); // Get entities - var entites = new List(); - world.GetEntities(query, entites); + var entites = new Entity[world.CountEntities(query)]; + world.GetEntities(query, entites.AsSpan()); That(entites.Count, Is.EqualTo(1)); // Destroy the one entity - entites.Clear(); world.Destroy(entity); - world.GetEntities(query, entites); + entites = new Entity[world.CountEntities(query)]; + world.GetEntities(query, entites.AsSpan()); That(entites.Count, Is.EqualTo(0)); } @@ -634,8 +635,8 @@ public void Remove_NonGeneric() { var entity = _world.Create(_entityGroup); var entity2 = _world.Create(_entityGroup); - _world.RemoveRange(entity, typeof(Transform)); - _world.RemoveRange(entity2, typeof(Transform)); + _world.RemoveRange(entity, new ComponentType[]{typeof(Transform)}); + _world.RemoveRange(entity2, new ComponentType[]{typeof(Transform)}); That(_world.GetArchetype(entity2), Is.EqualTo(_world.GetArchetype(entity))); That(_world.GetArchetype(entity).ChunkCount, Is.EqualTo(1)); @@ -650,8 +651,8 @@ public void Add_NonGeneric() { var entity = _world.Create(_entityGroup); var entity2 = _world.Create(_entityGroup); - _world.AddRange(entity, new Ai()); - _world.AddRange(entity2, new Ai()); + _world.AddRange(entity, new object[]{new Ai()}); + _world.AddRange(entity2, new object[]{new Ai()}); _world.TryGetArchetype(_entityAiGroup, out var arch); That(_world.GetArchetype(entity2), Is.EqualTo(_world.GetArchetype(entity))); diff --git a/src/Arch/Buffer/CommandBuffer.cs b/src/Arch/Buffer/CommandBuffer.cs index d962608..d40f950 100644 --- a/src/Arch/Buffer/CommandBuffer.cs +++ b/src/Arch/Buffer/CommandBuffer.cs @@ -387,7 +387,7 @@ public void Playback(World world, bool dispose = true) var entity = Resolve(wrappedEntity.Entity); Debug.Assert(world.IsAlive(entity), $"CommandBuffer can not to remove components from the dead {wrappedEntity.Entity}"); - world.RemoveRange(entity, _removeTypes); + world.RemoveRange(entity, _removeTypes.Span); _removeTypes.Clear(); } diff --git a/src/Arch/Core/Extensions/EntityExtensions.cs b/src/Arch/Core/Extensions/EntityExtensions.cs index 7acf5bb..6768610 100644 --- a/src/Arch/Core/Extensions/EntityExtensions.cs +++ b/src/Arch/Core/Extensions/EntityExtensions.cs @@ -242,7 +242,7 @@ public static void Set(this in Entity entity, object cmp) /// The . /// The components . [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetRange(this in Entity entity, params object[] components) + public static void SetRange(this in Entity entity, Span components) { var world = World.Worlds[entity.WorldId]; world.SetRange(entity, components); @@ -270,7 +270,7 @@ public static bool Has(this in Entity entity, ComponentType type) /// True if it has the desired component, otherwhise false. [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] - public static bool HasRange(this in Entity entity, params ComponentType[] types) + public static bool HasRange(this in Entity entity, Span types) { var world = World.Worlds[entity.WorldId]; return world.HasRange(entity, types); @@ -298,7 +298,7 @@ public static bool HasRange(this in Entity entity, params ComponentType[] types) /// A reference to the component. [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] - public static object?[] GetRange(this in Entity entity, params ComponentType[] types) + public static object?[] GetRange(this in Entity entity, Span types) { var world = World.Worlds[entity.WorldId]; return world.GetRange(entity, types); @@ -314,7 +314,7 @@ public static bool HasRange(this in Entity entity, params ComponentType[] types) /// A reference to the component. [MethodImpl(MethodImplOptions.AggressiveInlining)] [Pure] - public static void GetRange(this in Entity entity, ComponentType[] types, IList components) + public static void GetRange(this in Entity entity, Span types, Span components) { var world = World.Worlds[entity.WorldId]; world.GetRange(entity, types, components); @@ -356,7 +356,7 @@ public static void Add(this in Entity entity, in object cmp) /// The component . [SkipLocalsInit] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void AddRange(this in Entity entity, params object[] components) + public static void AddRange(this in Entity entity, Span components) { var world = World.Worlds[entity.WorldId]; world.AddRange(entity, components); @@ -366,10 +366,10 @@ public static void AddRange(this in Entity entity, params object[] components) /// Adds an list of new components to the and moves it to the new . /// /// The . - /// A of 's, those are added to the . + /// A of 's, those are added to the . [SkipLocalsInit] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void AddRange(this in Entity entity, IList components) + public static void AddRange(this in Entity entity, Span components) { var world = World.Worlds[entity.WorldId]; world.AddRange(entity, components); @@ -382,20 +382,7 @@ public static void AddRange(this in Entity entity, IList componen /// A of 's, those are removed from the . [SkipLocalsInit] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveRange(this in Entity entity, params ComponentType[] types) - { - var world = World.Worlds[entity.WorldId]; - world.RemoveRange(entity, types); - } - - /// - /// Removes a list of 's from the and moves it to a different . - /// - /// The . - /// A of 's, those are removed from the . - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveRange(this in Entity entity, IList types) + public static void RemoveRange(this in Entity entity, Span types) { var world = World.Worlds[entity.WorldId]; world.RemoveRange(entity, types); diff --git a/src/Arch/Core/Extensions/WorldExtensions.cs b/src/Arch/Core/Extensions/WorldExtensions.cs index cd0c5be..ea0b63a 100644 --- a/src/Arch/Core/Extensions/WorldExtensions.cs +++ b/src/Arch/Core/Extensions/WorldExtensions.cs @@ -10,246 +10,6 @@ namespace Arch.Core.Extensions; [WorldExtensions] public static class WorldExtensions { - /* - /// - /// Reserves space for a certain number of s of a given component structure/. - /// - /// - /// Causes a structural change. - /// - /// The component structure/. - /// The amount of s to reserve space for. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [StructuralChange] - public static void Reserve(this World world, Span types, int amount) - { - var archetype = world.GetOrCreate(types); - archetype.Reserve(amount); - var requiredCapacity = world.Capacity + amount; - EntityInfo.EnsureCapacity(requiredCapacity); - Capacity = requiredCapacity; - }*/ - /// - /// Search all matching 's and put them into the given . - /// - /// The . - /// The which specifies which components or 's are searched for. - /// The receiving the found 's. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetEntities(this World world, in QueryDescription queryDescription, IList list) - { - var query = world.Query(in queryDescription); - foreach (ref var chunk in query) - { - ref var entityFirstElement = ref chunk.Entity(0); - foreach (var entityIndex in chunk) - { - var entity = Unsafe.Add(ref entityFirstElement, entityIndex); - list.Add(entity); - } - } - } - - /// - /// Search all matching 's and put them into the given . - /// - /// The . - /// The which specifies which components are searched for. - /// The receiving 's containing 's with the matching components. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetArchetypes(this World world, in QueryDescription queryDescription, IList archetypes) - { - var query = world.Query(in queryDescription); - foreach (var archetype in query.GetArchetypeIterator()) - { - archetypes.Add(archetype); - } - } - - /// - /// Search all matching 's and put them into the given . - /// - /// The . - /// The which specifies which components are searched for. - /// The receiving 's containing 's with the matching components. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetChunks(this World world, in QueryDescription queryDescription, IList chunks) - { - var query = world.Query(in queryDescription); - foreach (ref var chunk in query) - { - chunks.Add(chunk); - } - } - - /// - /// Sets or replaces a of components for an . - /// - /// The . - /// The . - /// The components . - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SetRange(this World world, Entity entity, params object[] components) - { - world.SetRange(entity, components); - } - - /// - /// Checks if an has a certain component. - /// - /// The . - /// The . - /// The component . - /// True if it has the desired component, otherwhise false. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static bool HasRange(this World world, Entity entity, params ComponentType[] types) - { - return world.HasRange(entity, types); - } - - /// - /// Returns an array of components of an . - /// - /// The . - /// The . - /// The component . - /// A reference to the component. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static object?[] GetRange(this World world, Entity entity, params ComponentType[] types) - { - return world.GetRange(entity, types); - } - - /// - /// Returns an array of components of an . - /// - /// The . - /// The . - /// The component . - /// A where the components are put it. - /// A reference to the component. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetRange(this World world, Entity entity, ComponentType[] types, IList components) - { - var entitySlot = world.EntityInfo.GetEntitySlot(entity.Id); - for (var index = 0; index < types.Length; index++) - { - var type = types[index]; - components.Add(entitySlot.Archetype.Get(ref entitySlot.Slot, type)); - } - } - - /// - /// Adds a of new components to the and moves it to the new . - /// - /// - /// Causes a structural change. - /// - /// The . - /// The . - /// The component . - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void AddRange(this World world, Entity entity, params object[] components) - { - world.AddRange(entity, components); - } - - /// - /// Adds an list of new components to the and moves it to the new . - /// - /// - /// Causes a structural change. - /// - /// The . - /// The . - /// A of 's, those are added to the . - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [StructuralChange] - public static void AddRange(this World world, Entity entity, IList components) - { - var oldArchetype = world.EntityInfo.GetArchetype(entity.Id); - - // BitSet to stack/span bitset, size big enough to contain ALL registered components. - Span stack = stackalloc uint[BitSet.RequiredLength(ComponentRegistry.Size)]; - oldArchetype.BitSet.AsSpan(stack); - - // Create a span bitset, doing it local saves us headache and gargabe - var spanBitSet = new SpanBitSet(stack); - - for (var index = 0; index < components.Count; index++) - { - var type = components[index]; - spanBitSet.SetBit(type.Id); - } - - if (!world.TryGetArchetype(spanBitSet.GetHashCode(), out var newArchetype)) - { - newArchetype = world.GetOrCreate(oldArchetype.Types.Add(components)); - } - - world.Move(entity, oldArchetype, newArchetype, out _); - -#if EVENTS - for (var i = 0; i < components.Count; i++) - { - world.OnComponentAdded(entity, components[i]); - } -#endif - } - - /// - /// Removes a list of 's from the and moves it to a different . - /// - /// - /// Causes a structural change. - /// - /// The . - /// The . - /// A of 's, those are removed from the . - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void RemoveRange(this World world, Entity entity, params ComponentType[] types) - { - world.RemoveRange(entity, types); - } - - /// - /// Removes a list of 's from the and moves it to a different . - /// - /// - /// Causes a structural change. - /// - /// The . - /// The . - /// A of 's, those are removed from the . - [SkipLocalsInit] - [MethodImpl(MethodImplOptions.AggressiveInlining)] - [StructuralChange] - public static void RemoveRange(this World world, Entity entity, IList types) - { - var oldArchetype = world.EntityInfo.GetArchetype(entity.Id); - - // BitSet to stack/span bitset, size big enough to contain ALL registered components. - Span stack = stackalloc uint[oldArchetype.BitSet.Length]; - oldArchetype.BitSet.AsSpan(stack); - - // Create a span bitset, doing it local saves us headache and gargabe - var spanBitSet = new SpanBitSet(stack); - for (var index = 0; index < types.Count; index++) - { - var cmp = types[index]; - spanBitSet.ClearBit(cmp.Id); - } - - if (!world.TryGetArchetype(spanBitSet.GetHashCode(), out var newArchetype)) - { - newArchetype = world.GetOrCreate(oldArchetype.Types.Remove(types)); - } - - world.Move(entity, oldArchetype, newArchetype, out _); - } } diff --git a/src/Arch/Core/World.cs b/src/Arch/Core/World.cs index e559d64..7f189a9 100644 --- a/src/Arch/Core/World.cs +++ b/src/Arch/Core/World.cs @@ -1360,6 +1360,50 @@ public void AddRange(Entity entity, Span components) } } + /// + /// Adds an list of new components to the and moves it to the new . + /// + /// + /// Causes a structural change. + /// + /// The . + /// The . + /// A of 's, those are added to the . + [SkipLocalsInit] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + [StructuralChange] + public void AddRange(Entity entity, Span components) + { + var oldArchetype = EntityInfo.GetArchetype(entity.Id); + + // BitSet to stack/span bitset, size big enough to contain ALL registered components. + Span stack = stackalloc uint[BitSet.RequiredLength(ComponentRegistry.Size)]; + oldArchetype.BitSet.AsSpan(stack); + + // Create a span bitset, doing it local saves us headache and gargabe + var spanBitSet = new SpanBitSet(stack); + + for (var index = 0; index < components.Length; index++) + { + var type = components[index]; + spanBitSet.SetBit(type.Id); + } + + if (!TryGetArchetype(spanBitSet.GetHashCode(), out var newArchetype)) + { + newArchetype = GetOrCreate(oldArchetype.Types.Add(components.ToArray())); + } + + Move(entity, oldArchetype, newArchetype, out _); + +#if EVENTS + for (var i = 0; i < components.Count; i++) + { + OnComponentAdded(entity, components[i]); + } +#endif + } + /// /// Removes a from the and moves it to a different . ///