Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Arch.Tests/BitSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void HashSimilarity()
[Test]
public void BitsetSetAll()
{
var bitSet = new BitSet();
var bitSet = new BitSet(5);
bitSet.SetAll();

var count = 0;
Expand Down
107 changes: 107 additions & 0 deletions src/Arch.Tests/ChangedQueryTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using Arch.Core;

namespace Arch.Tests;

[TestFixture]
public class ChangedQueryTest
{
private struct A;
private struct B;
private struct C;

private World _world;
private Entity _e0, _e1, _e2, _e3, _e4, _e5;
private Entity[] _nothing = [];

[OneTimeSetUp]
public void Setup()
{
_world = World.Create();

_e0 = _world.Create<A, B>();

_e1 = _world.Create<A, B>();
_world.MarkChanged<B>(_e1);

_e2 = _world.Create<A, B, C>();
_world.MarkChanged<B>(_e2);

_e3 = _world.Create<B>();
_world.MarkChanged<B>(_e3);

_e4 = _world.Create<C>();
_world.MarkChanged<C>(_e4);

_e5 = _world.Create();
}

[Test]
public void WithChangedOnly()
{
var query = new QueryDescription().WithChanged<B>();
AssertMatches(query, _e1, _e2, _e3);
}

[Test]
public void WithAnyAndChanged()
{
var query = new QueryDescription().WithAny<C>().WithChanged<C>();
AssertMatches(query, _e4);
}

[Test]
public void WithDisjointAnyAndChanged()
{
var query = new QueryDescription().WithAny<A>().WithChanged<B>();
AssertMatches(query, _e1, _e2, _e3);
}

[Test]
public void WithNoneAndChanged()
{
var query = new QueryDescription().WithNone<B>().WithChanged<B>();
AssertMatches(query, _nothing);
}

[Test]
public void WithDisjointNoneAndChanged()
{
var query = new QueryDescription().WithNone<A>().WithChanged<C>();
AssertMatches(query, _e4);
}

[Test]
public void WithExclusiveAndChanged()
{
var query = new QueryDescription().WithExclusive<A, B>().WithChanged<B>();
AssertMatches(query, _e1);
}

[Test]
public void WithDisjointExclusiveAndChanged()
{
var query = new QueryDescription().WithExclusive<A, B>().WithChanged<C>();
AssertMatches(query, _nothing);
}

[Test]
public void WithDisjointAnyNoneAndChanged()
{
var query = new QueryDescription().WithAny<A>().WithChanged<B>().WithNone<C>();
AssertMatches(query, _e1, _e3);
}

private void AssertMatches(QueryDescription query, params Entity[] expected)
{
var entities = new Entity[10];
var total = _world.GetEntities(query, entities);
entities = entities[..total];
CollectionAssert.AreEquivalent(expected, entities);
}

[OneTimeTearDown]
public void TearDown()
{
_world.Dispose();
}
}
17 changes: 11 additions & 6 deletions src/Arch/Arch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,29 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>TRACE;</DefineConstants>
<DefineConstants>TRACE;CHANGED_FLAGS;</DefineConstants>
<Optimize>false</Optimize>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug-PureECS'">
<DefineConstants>TRACE;PURE_ECS;</DefineConstants>
<DefineConstants>TRACE;PURE_ECS;CHANGED_FLAGS;</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Debug-Events'">
<DefineConstants>TRACE;EVENTS;</DefineConstants>
<DefineConstants>TRACE;EVENTS;CHANGED_FLAGS;</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;CHANGED_FLAGS;</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release-Events'">
<DefineConstants>TRACE;EVENTS;</DefineConstants>
<DefineConstants>TRACE;EVENTS;CHANGED_FLAGS;</DefineConstants>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)'=='Release-PureECS'">
<DefineConstants>TRACE;PURE_ECS</DefineConstants>
<DefineConstants>TRACE;PURE_ECS;CHANGED_FLAGS;</DefineConstants>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -590,6 +590,11 @@
<DesignTime>True</DesignTime>
<DependentUpon>World.CreateBulk.tt</DependentUpon>
</Compile>
<Compile Update="Templates\QueryDescription.WithChanged.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>QueryDescription.WithChanged.tt</DependentUpon>
</Compile>
</ItemGroup>

</Project>
81 changes: 67 additions & 14 deletions src/Arch/Core/Archetype.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
using System.Buffers;
using System.Diagnostics.Contracts;
using Arch.Core.Extensions;
using Arch.Core.Extensions.Internal;
using Arch.Core.Utils;
using Arch.LowLevel;
using Arch.LowLevel.Jagged;
using Collections.Pooled;
using CommunityToolkit.HighPerformance;
using Array = System.Array;
using System.Runtime.InteropServices;

namespace Arch.Core;

Expand Down Expand Up @@ -339,21 +334,15 @@ internal int[] LookupArray
/// The number of <see cref="Chunk"/>'s within the <see cref="Chunks"/> array.
/// </summary>
public int ChunkCount {
get
{
return Chunks.Count;
}
get => Chunks.Count;
}

/// <summary>
/// How many <see cref="Chunk"/>' have been deposited within the <see cref="Chunks"/> array.
/// The total capacity.
/// </summary>
public int ChunkCapacity {
get
{
return Chunks.Capacity;
}
get => Chunks.Capacity;
}

/// <summary>
Expand Down Expand Up @@ -436,7 +425,7 @@ internal int Add(Entity entity, out Chunk chunk, out Slot slot) // TODO: Store
ref var currentChunk = ref GetChunk(count);

// Fill chunk
if (currentChunk.IsEmpty)
if (!currentChunk.IsFull)
{
slot = new Slot(currentChunk.Add(entity), count);
chunk = currentChunk;
Expand Down Expand Up @@ -958,3 +947,67 @@ internal static void CopyComponents(Archetype source, ref Slot fromSlot, Archety
Chunk.CopyComponents(ref oldChunk, fromSlot.Index, ref sourceSignature, ref newChunk, toSlot.Index, 1);
}
}


#if CHANGED_FLAGS

public sealed partial class Archetype
{
/// <summary>
/// Checks whether the component of an <see cref="Arch.Core.Entity"/> at a given <see cref="Slot"/> has been flagged changed.
/// </summary>
/// <param name="slot">The <see cref="Slot"/> at which the component of an <see cref="Arch.Core.Entity"/> is to be checked.</param>
/// <param name="componentType">The component type.</param>
/// <returns>True if the component is changed, false otherwise.</returns>
public bool IsChanged(ref Slot slot, ComponentType componentType)
{
ref var chunk = ref GetChunk(slot.ChunkIndex);
return chunk.IsChanged(slot.Index, componentType);
}

/// <summary>
/// Flags the component of an <see cref="Arch.Core.Entity"/> at a given <see cref="Slot"/> as changed.
/// </summary>
/// <param name="slot">The <see cref="Slot"/> at which the component of an <see cref="Arch.Core.Entity"/> is to be marked changed.</param>
/// <param name="componentType">The component type.</param>
internal void MarkChanged(ref Slot slot, ComponentType componentType)
{
ref var chunk = ref GetChunk(slot.ChunkIndex);
chunk.MarkChanged(slot.Index, componentType);
}

/// <summary>
/// Clears the changed flag of the component of an <see cref="Arch.Core.Entity"/> at a given <see cref="Slot"/>.
/// </summary>
/// <param name="slot">The <see cref="Slot"/> at which the component of an <see cref="Arch.Core.Entity"/> is to be cleared.</param>
/// <param name="componentType">The component type.</param>
internal void ClearChanged(ref Slot slot, ComponentType componentType)
{
ref var chunk = ref GetChunk(slot.ChunkIndex);
chunk.ClearChanged(slot.Index, componentType);
}

/// <summary>
/// Clears the changed flag for all components of an <see cref="Arch.Core.Entity"/> at a given <see cref="Slot"/>.
/// </summary>
/// <param name="slot">The slot.</param>
internal void ClearChanged(ref Slot slot)
{
ref var chunk = ref GetChunk(slot.ChunkIndex);
chunk.ClearChanged(slot.Index);
}

/// <summary>
/// Clears all the changed flags in this Archetype.
/// </summary>
internal void ClearAllChanged()
{
for (var i = 0; i < Chunks.Count; i++)
{
ref var chunk = ref Chunks[i];
chunk.ClearAllChanged();
}
}
}

#endif
Loading
Loading