diff --git a/Ghost.Core/Ghost.Core.csproj b/Ghost.Core/Ghost.Core.csproj
index bf47a20..db00b21 100644
--- a/Ghost.Core/Ghost.Core.csproj
+++ b/Ghost.Core/Ghost.Core.csproj
@@ -7,6 +7,10 @@
True
+
+
+
+
..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.LowLevel\bin\Release\net9.0\Misaki.HighPerformance.LowLevel.dll
@@ -17,4 +21,5 @@
+
diff --git a/Ghost.Entities.Test/EntityTest.cs b/Ghost.Entities.Test/EntityTest.cs
index bb59ca9..f20d850 100644
--- a/Ghost.Entities.Test/EntityTest.cs
+++ b/Ghost.Entities.Test/EntityTest.cs
@@ -1,4 +1,5 @@
using Ghost.Entities.Components;
+using Ghost.Entities.Query;
using Ghost.Entities.Systems;
using Ghost.Test.Core;
using System.Numerics;
@@ -7,50 +8,62 @@ namespace Ghost.Entities.Test;
public partial class EntityTest : ITest
{
+ private World _world = null!;
+
+ public void Setup()
+ {
+ _world = World.Create();
+ }
+
public void Run()
{
- var world = World.Create();
+ var entity1 = _world.EntityManager.CreateEntity();
+ var entity2 = _world.EntityManager.CreateEntity();
+ var entity3 = _world.EntityManager.CreateEntity();
- var entity1 = world.EntityManager.CreateEntity();
- var entity2 = world.EntityManager.CreateEntity();
- var entity3 = world.EntityManager.CreateEntity();
+ _world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) });
+ _world.EntityManager.AddComponent(entity1, new Mesh { index = 42 });
+ _world.EntityManager.AddScript(entity1);
+ _world.EntityManager.AddScript(entity1);
- world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) });
- world.EntityManager.AddComponent(entity1, new Mesh { index = 42 });
- world.EntityManager.AddScript(entity1);
- world.EntityManager.AddScript(entity1);
+ _world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) });
+ _world.EntityManager.AddComponent(entity2, new Mesh { index = 43 });
+ _world.EntityManager.AddScript(entity2);
- world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) });
- world.EntityManager.AddComponent(entity2, new Mesh { index = 43 });
- world.EntityManager.AddScript(entity2);
+ _world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) });
+ _world.EntityManager.AddScript(entity3);
- world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) });
- world.EntityManager.AddScript(entity3);
-
- foreach (var (_, transform) in world.Query())
+ foreach (var (_, transform) in _world.Query())
{
transform.ValueRW.position += new Vector3(1, 1, 1);
}
- foreach (var (_, mesh) in world.Query())
+ var filter = new QueryBuilder()
+ .WithAll()
+ .Build();
+
+ foreach (var (_, mesh) in _world.QueryFilter(in filter))
{
mesh.ValueRW.index += 1;
}
- world.EntityManager.RemoveEntity(ref entity2);
+ _world.EntityManager.RemoveEntity(ref entity2);
- var entity4 = world.EntityManager.CreateEntity();
- world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) });
- world.EntityManager.AddComponent(entity4, new Mesh { index = 44 });
- world.EntityManager.AddScript(entity4);
+ var entity4 = _world.EntityManager.CreateEntity();
+ _world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) });
+ _world.EntityManager.AddComponent(entity4, new Mesh { index = 45 });
+ _world.EntityManager.AddScript(entity4);
- world.SystemStorage.AddSystem();
- world.SystemStorage.AddSystem();
+ _world.SystemStorage.AddSystem();
+ _world.SystemStorage.AddSystem();
- world.SystemStorage.CreateSystems();
- world.SystemStorage.UpdateSystems();
+ _world.SystemStorage.CreateSystems();
+ _world.SystemStorage.UpdateSystems();
+ }
- world.Dispose();
+ public void Cleanup()
+ {
+ _world.Dispose();
}
}
@@ -62,9 +75,9 @@ public class TestSystem : ISystem
public void OnUpdate(in SystemState state)
{
- foreach (var (entity, transform) in state.World.Query().WithAbsent())
+ foreach (var (entity, transform) in state.World.Query())
{
- Console.WriteLine($"Entity {entity.ID}: Transform Position = {transform.ValueRO.position}");
+ Console.WriteLine($"Entity {entity}: Transform Position = {transform.ValueRO.position}");
}
}
@@ -84,7 +97,7 @@ public class TestSystem2 : ISystem
{
foreach (var (entity, mesh) in state.World.Query())
{
- Console.WriteLine($"Entity {entity.ID}: Mesh Index = {mesh.ValueRO.index}");
+ Console.WriteLine($"Entity {entity}: Mesh Index = {mesh.ValueRO.index}");
}
}
@@ -109,19 +122,35 @@ public class UserScript : ScriptComponent
{
public override int ExecutionOrder => -1;
+ public override void OnEnable()
+ {
+ Console.WriteLine("UserScript enabled for entity: " + Owner);
+ EntityManager.GetComponent(Owner).ValueRW.position += new Vector3(10, 10, 10);
+ }
+
+ override public void OnDisable()
+ {
+ Console.WriteLine("UserScript disabled for entity: " + Owner);
+ }
+
+ public override void Initialize()
+ {
+ Console.WriteLine("UserScript initialized for entity: " + Owner);
+ }
+
public override void Start()
{
- Console.WriteLine("UserScript started for entity: " + Owner.ID);
+ Console.WriteLine("UserScript started for entity: " + Owner);
}
public override void Update()
{
- Console.WriteLine("UserScript updating for entity: " + Owner.ID);
+ Console.WriteLine("UserScript updating for entity: " + Owner);
}
public override void OnDestroy()
{
- Console.WriteLine("UserScript destroyed for entity: " + Owner.ID);
+ Console.WriteLine("UserScript destroyed for entity: " + Owner);
}
}
@@ -129,17 +158,17 @@ public class UIManager : ScriptComponent
{
public override void Start()
{
- Console.WriteLine("UIManager started for entity: " + Owner.ID);
+ Console.WriteLine("UIManager started for entity: " + Owner);
}
public override void Update()
{
- Console.WriteLine("UIManager updating for entity: " + Owner.ID);
+ Console.WriteLine("UIManager updating for entity: " + Owner);
}
public override void OnDestroy()
{
- Console.WriteLine("UIManager destroyed for entity: " + Owner.ID);
+ Console.WriteLine("UIManager destroyed for entity: " + Owner);
}
}
@@ -147,16 +176,16 @@ public class EventManager : ScriptComponent
{
public override void Start()
{
- Console.WriteLine("EventManager started for entity: " + Owner.ID);
+ Console.WriteLine("EventManager started for entity: " + Owner);
}
public override void Update()
{
- Console.WriteLine("EventManager updating for entity: " + Owner.ID);
+ Console.WriteLine("EventManager updating for entity: " + Owner);
}
public override void OnDestroy()
{
- Console.WriteLine("EventManager destroyed for entity: " + Owner.ID);
+ Console.WriteLine("EventManager destroyed for entity: " + Owner);
}
}
\ No newline at end of file
diff --git a/Ghost.Entities/Components/ComponentStorage.cs b/Ghost.Entities/Components/ComponentStorage.cs
index fb1ec1c..fc00d26 100644
--- a/Ghost.Entities/Components/ComponentStorage.cs
+++ b/Ghost.Entities/Components/ComponentStorage.cs
@@ -64,7 +64,8 @@ internal class ComponentPool : IComponentPool
_lookup.AsSpan().Fill(Entity.INVALID_ID);
}
- public ComponentPool() : this(16)
+ public ComponentPool()
+ : this(16)
{
}
@@ -217,12 +218,19 @@ internal class ScriptComponentPool : IComponentPool
private Dictionary>? _scriptComponents;
private List? _executionList;
+ private readonly World _world;
+
internal IReadOnlyDictionary>? ScriptComponents => _scriptComponents;
internal IReadOnlyList? ExecutionList => _executionList;
public bool IsInitialized => _scriptComponents != null;
public int Count => _scriptComponents?.Keys.Count ?? 0;
+ public ScriptComponentPool(World world)
+ {
+ _world = world;
+ }
+
internal void Initialize(int capacity = 16)
{
_scriptComponents ??= new(capacity);
@@ -263,14 +271,15 @@ internal class ScriptComponentPool : IComponentPool
Initialize();
}
- if (!_scriptComponents!.TryGetValue(entity, out var scriptList))
- {
- scriptList = new();
- _scriptComponents[entity] = scriptList;
- }
+ ref var scriptList = ref CollectionsMarshal.GetValueRefOrAddDefault(_scriptComponents!, entity, out var exists);
+ scriptList ??= new List();
scriptList.Add(component);
+
component.Owner = entity;
+ component._world = _world;
+ component.Enable = true;
+ component.Initialize();
}
public bool Remove(Entity entity)
@@ -472,22 +481,23 @@ internal struct ComponentStorage : IDisposable
private int _currentCapacity = 16;
private IComponentPool?[] _componentPools = new IComponentPool[16];
- private UnsafeBitSet?[] _componentEntityMasks = new UnsafeBitSet?[16];
+ private UnsafeBitSet[] _componentEntityMasks = new UnsafeBitSet[16];
private readonly Dictionary _typeIDMap = new(16);
private readonly Dictionary _typeHandleMap = new(16);
- private readonly ScriptComponentPool _scriptComponentPool = new();
+ private readonly ScriptComponentPool _scriptComponentPool;
private readonly World _world;
internal ComponentStorage(World world)
{
_world = world;
+ _scriptComponentPool = new ScriptComponentPool(world);
}
internal readonly IReadOnlyList ComponentPools => _componentPools;
- internal readonly IReadOnlyList ComponentEntityMasks => _componentEntityMasks;
+ internal readonly IReadOnlyList ComponentEntityMasks => _componentEntityMasks;
internal readonly ScriptComponentPool ScriptComponentPool => _scriptComponentPool;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -641,29 +651,7 @@ internal struct ComponentStorage : IDisposable
return TryGetMask(TypeHandle.Get(), out bitSet);
}
- public UnsafeBitSet GetOrCreateMask()
- where T : unmanaged, IComponentData
- {
- var typeHandle = TypeHandle.Get();
- if (!_typeIDMap.TryGetValue(typeHandle, out var id))
- {
- id = GetTypeID();
- _typeIDMap[typeHandle] = id;
- _typeHandleMap[id] = typeHandle;
- }
-
- if (id >= _currentCapacity)
- {
- Resize(_currentCapacity * 2);
- }
-
- ref var set = ref _componentEntityMasks[id];
- set ??= new UnsafeBitSet();
-
- return set.Value;
- }
-
- public UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle)
+ public ref UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle)
{
if (!_typeIDMap.TryGetValue(typeHandle, out var id))
{
@@ -678,14 +666,23 @@ internal struct ComponentStorage : IDisposable
}
ref var set = ref _componentEntityMasks[id];
- set ??= new UnsafeBitSet();
+ if (!set.IsCreated)
+ {
+ set = new UnsafeBitSet();
+ }
- return set.Value;
+ return ref set;
}
- public UnsafeBitSet GetOrCreateMask(Type type)
+ public ref UnsafeBitSet GetOrCreateMask()
+ where T : unmanaged, IComponentData
{
- return GetOrCreateMask(TypeHandle.Get(type));
+ return ref GetOrCreateMask(TypeHandle.Get());
+ }
+
+ public ref UnsafeBitSet GetOrCreateMask(Type type)
+ {
+ return ref GetOrCreateMask(TypeHandle.Get(type));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -710,7 +707,7 @@ internal struct ComponentStorage : IDisposable
foreach (var bitSet in _componentEntityMasks)
{
- bitSet?.Dispose();
+ bitSet.Dispose();
}
_scriptComponentPool.Dispose();
diff --git a/Ghost.Entities/Components/ScriptComponent.cs b/Ghost.Entities/Components/ScriptComponent.cs
index 33f0788..00e982a 100644
--- a/Ghost.Entities/Components/ScriptComponent.cs
+++ b/Ghost.Entities/Components/ScriptComponent.cs
@@ -2,7 +2,9 @@
public abstract class ScriptComponent : IComponentData
{
- private bool _enable = true;
+ private bool _enable;
+
+ internal World _world = null!;
///
/// Gets or sets a value indicating whether this script component is enabled.
@@ -38,6 +40,11 @@ public abstract class ScriptComponent : IComponentData
internal set;
}
+ ///
+ /// Gets the EntityManager instance associated with the current world.
+ ///
+ protected EntityManager EntityManager => _world.EntityManager;
+
///
/// Gets or sets the priority of the script component.
/// Change this during runtime does not affect the execution order.
@@ -58,6 +65,13 @@ public abstract class ScriptComponent : IComponentData
{
}
+ ///
+ /// Called when the script component is initialized.
+ ///
+ public virtual void Initialize()
+ {
+ }
+
///
/// Called when the script component is started.
///
diff --git a/Ghost.Entities/Ghost.Entities.csproj b/Ghost.Entities/Ghost.Entities.csproj
index 478d9d8..f024e17 100644
--- a/Ghost.Entities/Ghost.Entities.csproj
+++ b/Ghost.Entities/Ghost.Entities.csproj
@@ -8,6 +8,11 @@
+
+ True
+ True
+ ForEach.tt
+
True
True
@@ -32,6 +37,10 @@
+
+ TextTemplatingFileGenerator
+ ForEach.cs
+
TextTemplatingFileGenerator
QueryEnumerable.cs
@@ -59,6 +68,11 @@
+
+ True
+ True
+ ForEach.tt
+
True
True
diff --git a/Ghost.Entities/Query/QueryBuilder.cs b/Ghost.Entities/Query/QueryBuilder.cs
new file mode 100644
index 0000000..028a5f5
--- /dev/null
+++ b/Ghost.Entities/Query/QueryBuilder.cs
@@ -0,0 +1,42 @@
+using Ghost.Core;
+
+namespace Ghost.Entities.Query;
+
+public struct QueryBuilder
+{
+ private QueryFilter _filter;
+
+ public QueryBuilder()
+ {
+ _filter = new QueryFilter();
+ }
+
+ public QueryBuilder WithAll()
+ {
+ _filter._all.Add(TypeHandle.Get());
+ return this;
+ }
+
+ public QueryBuilder WithAny()
+ {
+ _filter._any.Add(TypeHandle.Get());
+ return this;
+ }
+
+ public QueryBuilder WithAbsent()
+ {
+ _filter._absent.Add(TypeHandle.Get());
+ return this;
+ }
+
+ public QueryBuilder WithDisabled()
+ {
+ _filter._disabled.Add(TypeHandle.Get());
+ return this;
+ }
+
+ public readonly QueryFilter Build()
+ {
+ return _filter;
+ }
+}
\ No newline at end of file
diff --git a/Ghost.Entities/Query/QueryFilter.cs b/Ghost.Entities/Query/QueryFilter.cs
index e951cbc..5c57328 100644
--- a/Ghost.Entities/Query/QueryFilter.cs
+++ b/Ghost.Entities/Query/QueryFilter.cs
@@ -1,98 +1,98 @@
using Ghost.Core;
+using Ghost.Entities.Components;
using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
-using System.Runtime.CompilerServices;
namespace Ghost.Entities.Query;
-[Flags]
-internal enum FilterMode
+public struct QueryFilter : IDisposable
{
- All = 1 << 0,
- Any = 1 << 1,
- Absent = 1 << 2,
- Disabled = 1 << 3,
-}
+ private readonly Stack.Scope _scope;
-internal readonly struct FilterEntry(TypeHandle id, FilterMode mode)
-{
- public readonly TypeHandle typeHandle = id;
- public readonly FilterMode mode = mode;
-}
+ internal UnsafeList _all;
+ internal UnsafeList _any;
+ internal UnsafeList _absent;
+ internal UnsafeList _disabled;
-internal struct QueryFilter()
-{
- internal List _all = new(6);
- internal List _any = new(6);
- internal List _absent = new(6);
- internal List _disabled = new(6);
+ public QueryFilter()
+ {
+ _scope = AllocationManager.CreateStackScope();
- public readonly UnsafeBitSet ComputeFilterBitMask(World world)
+ _all = new UnsafeList(4, Allocator.Stack);
+ _any = new UnsafeList(4, Allocator.Stack);
+ _absent = new UnsafeList(4, Allocator.Stack);
+ _disabled = new UnsafeList(4, Allocator.Stack);
+ }
+
+ public readonly UnsafeBitSet ComputeFilterBitMask(World world, Allocator allocator)
{
UnsafeBitSet allMask = default;
UnsafeBitSet anyMask = default;
UnsafeBitSet absentMask = default;
- using var scope = AllocationManager.CreateStackScope();
-
- foreach (var typeHandle in _all)
- {
- var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
-
- if (!allMask.IsCreated)
- {
- allMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear);
- allMask.SetAll();
- }
-
- allMask.AndOperation(mask);
- }
-
- foreach (var typeHandle in _any)
- {
- var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
-
- if (!anyMask.IsCreated)
- {
- anyMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear);
- }
-
- anyMask.OrOperation(mask);
- }
-
- foreach (var typeHandle in _absent)
- {
- var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
-
- if (!absentMask.IsCreated)
- {
- absentMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear);
- }
-
- absentMask.OrOperation(mask);
- }
-
- var result = new UnsafeBitSet(world.EntityManager.EntityCount, Allocator.Persistent);
+ var result = new UnsafeBitSet(world.EntityManager.EntityCount, allocator);
result.SetAll();
- if (allMask.IsCreated)
+ using (AllocationManager.CreateStackScope())
{
- result.AndOperation(allMask);
- allMask.Dispose();
- }
+ foreach (var typeHandle in _all)
+ {
+ var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
- if (anyMask.IsCreated)
- {
- result.AndOperation(anyMask);
- anyMask.Dispose();
- }
+ if (!allMask.IsCreated)
+ {
+ allMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.None);
+ allMask.SetAll();
+ }
- if (absentMask.IsCreated)
- {
- result.AndOperation(~absentMask);
- absentMask.Dispose();
+ allMask.AndOperation(mask);
+ }
+
+ foreach (var typeHandle in _any)
+ {
+ var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
+
+ if (!anyMask.IsCreated)
+ {
+ anyMask = new UnsafeBitSet(mask.Length, Allocator.Stack);
+ }
+
+ anyMask.OrOperation(mask);
+ }
+
+ foreach (var typeHandle in _absent)
+ {
+ var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
+
+ if (!absentMask.IsCreated)
+ {
+ absentMask = new UnsafeBitSet(mask.Length, Allocator.Stack);
+ }
+
+ absentMask.OrOperation(mask);
+ }
+
+ if (allMask.IsCreated)
+ {
+ result.AndOperation(allMask);
+ }
+
+ if (anyMask.IsCreated)
+ {
+ result.AndOperation(anyMask);
+ }
+
+ if (absentMask.IsCreated)
+ {
+ result.AndOperation(~absentMask);
+ }
}
return result;
}
+
+ public readonly void Dispose()
+ {
+ _scope.Dispose();
+ }
}
\ No newline at end of file
diff --git a/Ghost.Entities/Query/QueryTypeParameter.cs b/Ghost.Entities/Query/QueryTypeParameter.cs
index 3357afc..10fc357 100644
--- a/Ghost.Entities/Query/QueryTypeParameter.cs
+++ b/Ghost.Entities/Query/QueryTypeParameter.cs
@@ -3,11 +3,12 @@ using System.Runtime.CompilerServices;
namespace Ghost.Entities.Query;
-public interface IQueryTypeParameter
+public interface IQueryTypeParameter
+ where T : IComponentData
{
}
-public ref struct CompRef : IQueryTypeParameter
+public ref struct CompRef : IQueryTypeParameter
where T : IComponentData
{
internal ref T _value;
@@ -42,7 +43,7 @@ public ref struct CompRef : IQueryTypeParameter
}
}
-public ref struct CompRO : IQueryTypeParameter
+public readonly ref struct CompRO : IQueryTypeParameter
where T : IComponentData
{
internal readonly ref T _value;
diff --git a/Ghost.Entities/Template/ForEach.cs b/Ghost.Entities/Template/ForEach.cs
new file mode 100644
index 0000000..284f72c
--- /dev/null
+++ b/Ghost.Entities/Template/ForEach.cs
@@ -0,0 +1,12 @@
+
+
+namespace Ghost.Entities;
+
+public delegate void ForEach(ref T0 t0Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component);
+public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component);
diff --git a/Ghost.Entities/Template/ForEach.tt b/Ghost.Entities/Template/ForEach.tt
new file mode 100644
index 0000000..045c196
--- /dev/null
+++ b/Ghost.Entities/Template/ForEach.tt
@@ -0,0 +1,16 @@
+<#@ template language="C#" #>
+<#@ output extension=".cs" #>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Linq" #>
+<#@ import namespace="System.Text" #>
+<#@ include file="Helpers.ttinclude" #>
+
+namespace Ghost.Entities;
+
+<# for (var i = 1; i <= Amount; i++)
+{
+ var generics = AppendGenerics(i);
+ var compGenerics = AppendGenericRefParameters(i);
+#>
+public delegate void ForEach<<#= generics #>>(<#= compGenerics #>);
+<# } #>
\ No newline at end of file
diff --git a/Ghost.Entities/Template/QueryEnumerable.cs b/Ghost.Entities/Template/QueryEnumerable.cs
index c08ab56..8202e18 100644
--- a/Ghost.Entities/Template/QueryEnumerable.cs
+++ b/Ghost.Entities/Template/QueryEnumerable.cs
@@ -3,46 +3,60 @@
using Ghost.Core;
using Ghost.Entities.Components;
using Ghost.Entities.Query;
+using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections;
namespace Ghost.Entities;
-public struct QueryEnumerable
+public unsafe ref struct QueryEnumerable
where T0 : unmanaged, IComponentData
{
+ private QueryFilter _filter;
+
private readonly World _world;
private readonly ComponentPool _pool0;
private readonly int _count;
- private QueryFilter _filters;
- internal readonly QueryFilter Filters => _filters;
-
internal QueryEnumerable(World world, ComponentPool pool0, int count)
{
+ _filter = new();
+ _filter._all.Add(TypeHandle.Get());
+
_world = world;
_pool0 = pool0;
_count = count;
-
- _filters = new();
- _filters._all.Add(TypeHandle.Get());
}
- public readonly Enumerator GetEnumerator() => new(_world, _pool0, _count, _filters);
+ internal QueryEnumerable(World world, ComponentPool pool0, int count, ref readonly QueryFilter filter)
+ {
+ _filter = filter;
+
+ _world = world;
+
+ _pool0 = pool0;
+
+ _count = count;
+ }
+
+#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference
+ public Enumerator GetEnumerator() => new(_world, _pool0, _count, ref _filter);
+#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference
public ref struct Enumerator
{
- private readonly World _world;
+ private ref QueryFilter _filter;
+ private UnsafeBitSet _filterMask;
+
private readonly ReadOnlySpan _entities;
+ private readonly Stack.Scope _stackScope;
private readonly ComponentPool _pool0;
private int _index;
- private readonly int _count;
-
- private UnsafeBitSet _filterMask;
+ private int _count;
public QueryItem Current
{
@@ -50,16 +64,19 @@ public struct QueryEnumerable
private set;
}
- internal Enumerator(World world, ComponentPool pool0, int count, QueryFilter filters)
+ internal Enumerator(World world, ComponentPool pool0, int count, ref QueryFilter filter)
{
- _world = world;
- _entities = _world.EntityManager.Entities;
+ _stackScope = AllocationManager.CreateStackScope();
+
+ _filter = ref filter;
+ _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack);
+
+ _entities = world.EntityManager.Entities;
_pool0 = pool0;
_count = count;
_index = -1;
- _filterMask = filters.ComputeFilterBitMask(_world);
Current = default;
}
@@ -67,153 +84,175 @@ public struct QueryEnumerable
public bool MoveNext()
{
_index = _filterMask.NextSetBit(_index + 1);
- if (_index < 0 || _index >= _world.EntityManager.EntityCount)
+ if (_index < 0 || _count <= 0 || _index >= _entities.Length)
{
return false;
}
+ _count--;
Current = new QueryItem(_entities[_index], _pool0);
+
return true;
}
+
+ public readonly void Dispose()
+ {
+ _stackScope.Dispose();
+ _filter.Dispose();
+ }
}
- public readonly QueryEnumerable WithAll()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._all.Add(TypeHandle.Get());
+ public QueryEnumerable WithAll()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._all.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAny()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._any.Add(TypeHandle.Get());
+ public QueryEnumerable WithAny()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._any.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAbsent()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._absent.Add(TypeHandle.Get());
+ public QueryEnumerable WithAbsent()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._absent.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithDisabled()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._disabled.Add(TypeHandle.Get());
+ public QueryEnumerable WithDisabled()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._disabled.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAll()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._all.Add(TypeHandle.Get());
- _filters._all.Add(TypeHandle.Get());
+ public QueryEnumerable WithAll()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
+ {
+ _filter._all.Add(TypeHandle.Get());
+ _filter._all.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAny()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._any.Add(TypeHandle.Get());
- _filters._any.Add(TypeHandle.Get());
+ public QueryEnumerable WithAny()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
+ {
+ _filter._any.Add(TypeHandle.Get());
+ _filter._any.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAbsent()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._absent.Add(TypeHandle.Get());
- _filters._absent.Add(TypeHandle.Get());
+ public QueryEnumerable WithAbsent()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
+ {
+ _filter._absent.Add(TypeHandle.Get());
+ _filter._absent.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithDisabled()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._disabled.Add(TypeHandle.Get());
- _filters._disabled.Add(TypeHandle.Get());
+ public QueryEnumerable WithDisabled()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
+ {
+ _filter._disabled.Add(TypeHandle.Get());
+ _filter._disabled.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAll()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
- {
- _filters._all.Add(TypeHandle.Get());
- _filters._all.Add(TypeHandle.Get());
- _filters._all.Add(TypeHandle.Get());
+ public QueryEnumerable WithAll()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
+ {
+ _filter._all.Add(TypeHandle.Get());
+ _filter._all.Add(TypeHandle.Get());
+ _filter._all.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAny()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
- {
- _filters._any.Add(TypeHandle.Get());
- _filters._any.Add(TypeHandle.Get());
- _filters._any.Add(TypeHandle.Get());
+ public QueryEnumerable WithAny()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
+ {
+ _filter._any.Add(TypeHandle.Get());
+ _filter._any.Add(TypeHandle.Get());
+ _filter._any.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAbsent()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
- {
- _filters._absent.Add(TypeHandle.Get());
- _filters._absent.Add(TypeHandle.Get());
- _filters._absent.Add(TypeHandle.Get());
+ public QueryEnumerable WithAbsent()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
+ {
+ _filter._absent.Add(TypeHandle.Get());
+ _filter._absent.Add(TypeHandle.Get());
+ _filter._absent.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithDisabled()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
- {
- _filters._disabled.Add(TypeHandle.Get());
- _filters._disabled.Add(TypeHandle.Get());
- _filters._disabled.Add(TypeHandle.Get());
+ public QueryEnumerable WithDisabled()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData
+ {
+ _filter._disabled.Add(TypeHandle.Get());
+ _filter._disabled.Add(TypeHandle.Get());
+ _filter._disabled.Add(TypeHandle.Get());
return this;
- }
+ }
}
-public struct QueryEnumerable
+public unsafe ref struct QueryEnumerable
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
{
+ private QueryFilter _filter;
+
private readonly World _world;
private readonly ComponentPool _pool0;
private readonly ComponentPool _pool1;
private readonly int _count;
- private QueryFilter _filters;
- internal readonly QueryFilter Filters => _filters;
-
internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count)
{
+ _filter = new();
+ _filter._all.Add(TypeHandle.Get());
+ _filter._all.Add(TypeHandle.Get());
+
_world = world;
_pool0 = pool0;
_pool1 = pool1;
_count = count;
-
- _filters = new();
- _filters._all.Add(TypeHandle.Get());
- _filters._all.Add(TypeHandle.Get());
}
- public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _count, _filters);
+ internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count, ref readonly QueryFilter filter)
+ {
+ _filter = filter;
+
+ _world = world;
+
+ _pool0 = pool0;
+ _pool1 = pool1;
+
+ _count = count;
+ }
+
+#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference
+ public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _count, ref _filter);
+#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference
public ref struct Enumerator
{
- private readonly World _world;
+ private ref QueryFilter _filter;
+ private UnsafeBitSet _filterMask;
+
private readonly ReadOnlySpan _entities;
+ private readonly Stack.Scope _stackScope;
private readonly ComponentPool _pool0;
private readonly ComponentPool _pool1;
private int _index;
- private readonly int _count;
-
- private UnsafeBitSet _filterMask;
+ private int _count;
public QueryItem Current
{
@@ -221,17 +260,20 @@ public struct QueryEnumerable
private set;
}
- internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, int count, QueryFilter filters)
+ internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, int count, ref QueryFilter filter)
{
- _world = world;
- _entities = _world.EntityManager.Entities;
+ _stackScope = AllocationManager.CreateStackScope();
+
+ _filter = ref filter;
+ _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack);
+
+ _entities = world.EntityManager.Entities;
_pool0 = pool0;
_pool1 = pool1;
_count = count;
_index = -1;
- _filterMask = filters.ComputeFilterBitMask(_world);
Current = default;
}
@@ -239,116 +281,126 @@ public struct QueryEnumerable
public bool MoveNext()
{
_index = _filterMask.NextSetBit(_index + 1);
- if (_index < 0 || _index >= _world.EntityManager.EntityCount)
+ if (_index < 0 || _count <= 0)
{
return false;
}
+ _count--;
Current = new QueryItem(_entities[_index], _pool0, _pool1);
+
return true;
}
+
+ public readonly void Dispose()
+ {
+ _stackScope.Dispose();
+ _filter.Dispose();
+ }
}
- public readonly QueryEnumerable WithAll()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._all.Add(TypeHandle.Get());
+ public QueryEnumerable WithAll()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._all.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAny()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._any.Add(TypeHandle.Get());
+ public QueryEnumerable WithAny()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._any.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAbsent()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._absent.Add(TypeHandle.Get());
+ public QueryEnumerable WithAbsent()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._absent.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithDisabled()
- where TComponent0 : unmanaged, IComponentData
- {
- _filters._disabled.Add(TypeHandle.Get());
+ public QueryEnumerable WithDisabled()
+ where TComponent0 : unmanaged, IComponentData
+ {
+ _filter._disabled.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAll()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._all.Add(TypeHandle.Get());
- _filters._all.Add(TypeHandle.Get());
+ public QueryEnumerable WithAll()
+ where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
+ {
+ _filter._all.Add(TypeHandle.Get());
+ _filter._all.Add(TypeHandle.Get());
return this;
- }
+ }
- public readonly QueryEnumerable WithAny()
- where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData
- {
- _filters._any.Add(TypeHandle.Get());
- _filters._any.Add(TypeHandle.Get