forked from Misaki/GhostEngine
Improve ecs query performance;
This commit is contained in:
@@ -7,6 +7,10 @@
|
|||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Misaki.HighPerformance.Unsafe">
|
<Reference Include="Misaki.HighPerformance.Unsafe">
|
||||||
<HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.LowLevel\bin\Release\net9.0\Misaki.HighPerformance.LowLevel.dll</HintPath>
|
<HintPath>..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.LowLevel\bin\Release\net9.0\Misaki.HighPerformance.LowLevel.dll</HintPath>
|
||||||
@@ -17,4 +21,5 @@
|
|||||||
<Folder Include="Contracts\" />
|
<Folder Include="Contracts\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
|
using Ghost.Entities.Query;
|
||||||
using Ghost.Entities.Systems;
|
using Ghost.Entities.Systems;
|
||||||
using Ghost.Test.Core;
|
using Ghost.Test.Core;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
@@ -7,50 +8,62 @@ namespace Ghost.Entities.Test;
|
|||||||
|
|
||||||
public partial class EntityTest : ITest
|
public partial class EntityTest : ITest
|
||||||
{
|
{
|
||||||
|
private World _world = null!;
|
||||||
|
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_world = World.Create();
|
||||||
|
}
|
||||||
|
|
||||||
public void Run()
|
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();
|
_world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) });
|
||||||
var entity2 = world.EntityManager.CreateEntity();
|
_world.EntityManager.AddComponent(entity1, new Mesh { index = 42 });
|
||||||
var entity3 = world.EntityManager.CreateEntity();
|
_world.EntityManager.AddScript<UIManager>(entity1);
|
||||||
|
_world.EntityManager.AddScript<EventManager>(entity1);
|
||||||
|
|
||||||
world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) });
|
_world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) });
|
||||||
world.EntityManager.AddComponent(entity1, new Mesh { index = 42 });
|
_world.EntityManager.AddComponent(entity2, new Mesh { index = 43 });
|
||||||
world.EntityManager.AddScript<UIManager>(entity1);
|
_world.EntityManager.AddScript<UserScript>(entity2);
|
||||||
world.EntityManager.AddScript<EventManager>(entity1);
|
|
||||||
|
|
||||||
world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) });
|
_world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) });
|
||||||
world.EntityManager.AddComponent(entity2, new Mesh { index = 43 });
|
_world.EntityManager.AddScript<EventManager>(entity3);
|
||||||
world.EntityManager.AddScript<UserScript>(entity2);
|
|
||||||
|
|
||||||
world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) });
|
foreach (var (_, transform) in _world.Query<Transform>())
|
||||||
world.EntityManager.AddScript<EventManager>(entity3);
|
|
||||||
|
|
||||||
foreach (var (_, transform) in world.Query<Transform>())
|
|
||||||
{
|
{
|
||||||
transform.ValueRW.position += new Vector3(1, 1, 1);
|
transform.ValueRW.position += new Vector3(1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (_, mesh) in world.Query<Mesh>())
|
var filter = new QueryBuilder()
|
||||||
|
.WithAll<Mesh>()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
foreach (var (_, mesh) in _world.QueryFilter<Mesh>(in filter))
|
||||||
{
|
{
|
||||||
mesh.ValueRW.index += 1;
|
mesh.ValueRW.index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
world.EntityManager.RemoveEntity(ref entity2);
|
_world.EntityManager.RemoveEntity(ref entity2);
|
||||||
|
|
||||||
var entity4 = world.EntityManager.CreateEntity();
|
var entity4 = _world.EntityManager.CreateEntity();
|
||||||
world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) });
|
_world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) });
|
||||||
world.EntityManager.AddComponent(entity4, new Mesh { index = 44 });
|
_world.EntityManager.AddComponent(entity4, new Mesh { index = 45 });
|
||||||
world.EntityManager.AddScript<UserScript>(entity4);
|
_world.EntityManager.AddScript<UserScript>(entity4);
|
||||||
|
|
||||||
world.SystemStorage.AddSystem<TestSystem2>();
|
_world.SystemStorage.AddSystem<TestSystem2>();
|
||||||
world.SystemStorage.AddSystem<TestSystem>();
|
_world.SystemStorage.AddSystem<TestSystem>();
|
||||||
|
|
||||||
world.SystemStorage.CreateSystems();
|
_world.SystemStorage.CreateSystems();
|
||||||
world.SystemStorage.UpdateSystems();
|
_world.SystemStorage.UpdateSystems();
|
||||||
|
}
|
||||||
|
|
||||||
world.Dispose();
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
_world.Dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +75,9 @@ public class TestSystem : ISystem
|
|||||||
|
|
||||||
public void OnUpdate(in SystemState state)
|
public void OnUpdate(in SystemState state)
|
||||||
{
|
{
|
||||||
foreach (var (entity, transform) in state.World.Query<Transform>().WithAbsent<Mesh>())
|
foreach (var (entity, transform) in state.World.Query<Transform>())
|
||||||
{
|
{
|
||||||
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<Mesh>())
|
foreach (var (entity, mesh) in state.World.Query<Mesh>())
|
||||||
{
|
{
|
||||||
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 int ExecutionOrder => -1;
|
||||||
|
|
||||||
|
public override void OnEnable()
|
||||||
|
{
|
||||||
|
Console.WriteLine("UserScript enabled for entity: " + Owner);
|
||||||
|
EntityManager.GetComponent<Transform>(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()
|
public override void Start()
|
||||||
{
|
{
|
||||||
Console.WriteLine("UserScript started for entity: " + Owner.ID);
|
Console.WriteLine("UserScript started for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
Console.WriteLine("UserScript updating for entity: " + Owner.ID);
|
Console.WriteLine("UserScript updating for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDestroy()
|
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()
|
public override void Start()
|
||||||
{
|
{
|
||||||
Console.WriteLine("UIManager started for entity: " + Owner.ID);
|
Console.WriteLine("UIManager started for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
Console.WriteLine("UIManager updating for entity: " + Owner.ID);
|
Console.WriteLine("UIManager updating for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDestroy()
|
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()
|
public override void Start()
|
||||||
{
|
{
|
||||||
Console.WriteLine("EventManager started for entity: " + Owner.ID);
|
Console.WriteLine("EventManager started for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
{
|
{
|
||||||
Console.WriteLine("EventManager updating for entity: " + Owner.ID);
|
Console.WriteLine("EventManager updating for entity: " + Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
Console.WriteLine("EventManager destroyed for entity: " + Owner.ID);
|
Console.WriteLine("EventManager destroyed for entity: " + Owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,8 @@ internal class ComponentPool<T> : IComponentPool<T>
|
|||||||
_lookup.AsSpan().Fill(Entity.INVALID_ID);
|
_lookup.AsSpan().Fill(Entity.INVALID_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ComponentPool() : this(16)
|
public ComponentPool()
|
||||||
|
: this(16)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,12 +218,19 @@ internal class ScriptComponentPool : IComponentPool<ScriptComponent>
|
|||||||
private Dictionary<Entity, List<ScriptComponent>>? _scriptComponents;
|
private Dictionary<Entity, List<ScriptComponent>>? _scriptComponents;
|
||||||
private List<ScriptComponent>? _executionList;
|
private List<ScriptComponent>? _executionList;
|
||||||
|
|
||||||
|
private readonly World _world;
|
||||||
|
|
||||||
internal IReadOnlyDictionary<Entity, List<ScriptComponent>>? ScriptComponents => _scriptComponents;
|
internal IReadOnlyDictionary<Entity, List<ScriptComponent>>? ScriptComponents => _scriptComponents;
|
||||||
internal IReadOnlyList<ScriptComponent>? ExecutionList => _executionList;
|
internal IReadOnlyList<ScriptComponent>? ExecutionList => _executionList;
|
||||||
|
|
||||||
public bool IsInitialized => _scriptComponents != null;
|
public bool IsInitialized => _scriptComponents != null;
|
||||||
public int Count => _scriptComponents?.Keys.Count ?? 0;
|
public int Count => _scriptComponents?.Keys.Count ?? 0;
|
||||||
|
|
||||||
|
public ScriptComponentPool(World world)
|
||||||
|
{
|
||||||
|
_world = world;
|
||||||
|
}
|
||||||
|
|
||||||
internal void Initialize(int capacity = 16)
|
internal void Initialize(int capacity = 16)
|
||||||
{
|
{
|
||||||
_scriptComponents ??= new(capacity);
|
_scriptComponents ??= new(capacity);
|
||||||
@@ -263,14 +271,15 @@ internal class ScriptComponentPool : IComponentPool<ScriptComponent>
|
|||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_scriptComponents!.TryGetValue(entity, out var scriptList))
|
ref var scriptList = ref CollectionsMarshal.GetValueRefOrAddDefault(_scriptComponents!, entity, out var exists);
|
||||||
{
|
scriptList ??= new List<ScriptComponent>();
|
||||||
scriptList = new();
|
|
||||||
_scriptComponents[entity] = scriptList;
|
|
||||||
}
|
|
||||||
|
|
||||||
scriptList.Add(component);
|
scriptList.Add(component);
|
||||||
|
|
||||||
component.Owner = entity;
|
component.Owner = entity;
|
||||||
|
component._world = _world;
|
||||||
|
component.Enable = true;
|
||||||
|
component.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Remove<T>(Entity entity)
|
public bool Remove<T>(Entity entity)
|
||||||
@@ -472,22 +481,23 @@ internal struct ComponentStorage : IDisposable
|
|||||||
private int _currentCapacity = 16;
|
private int _currentCapacity = 16;
|
||||||
|
|
||||||
private IComponentPool?[] _componentPools = new IComponentPool[16];
|
private IComponentPool?[] _componentPools = new IComponentPool[16];
|
||||||
private UnsafeBitSet?[] _componentEntityMasks = new UnsafeBitSet?[16];
|
private UnsafeBitSet[] _componentEntityMasks = new UnsafeBitSet[16];
|
||||||
|
|
||||||
private readonly Dictionary<TypeHandle, int> _typeIDMap = new(16);
|
private readonly Dictionary<TypeHandle, int> _typeIDMap = new(16);
|
||||||
private readonly Dictionary<int, TypeHandle> _typeHandleMap = new(16);
|
private readonly Dictionary<int, TypeHandle> _typeHandleMap = new(16);
|
||||||
|
|
||||||
private readonly ScriptComponentPool _scriptComponentPool = new();
|
private readonly ScriptComponentPool _scriptComponentPool;
|
||||||
|
|
||||||
private readonly World _world;
|
private readonly World _world;
|
||||||
|
|
||||||
internal ComponentStorage(World world)
|
internal ComponentStorage(World world)
|
||||||
{
|
{
|
||||||
_world = world;
|
_world = world;
|
||||||
|
_scriptComponentPool = new ScriptComponentPool(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal readonly IReadOnlyList<IComponentPool?> ComponentPools => _componentPools;
|
internal readonly IReadOnlyList<IComponentPool?> ComponentPools => _componentPools;
|
||||||
internal readonly IReadOnlyList<UnsafeBitSet?> ComponentEntityMasks => _componentEntityMasks;
|
internal readonly IReadOnlyList<UnsafeBitSet> ComponentEntityMasks => _componentEntityMasks;
|
||||||
internal readonly ScriptComponentPool ScriptComponentPool => _scriptComponentPool;
|
internal readonly ScriptComponentPool ScriptComponentPool => _scriptComponentPool;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -641,29 +651,7 @@ internal struct ComponentStorage : IDisposable
|
|||||||
return TryGetMask(TypeHandle.Get<T>(), out bitSet);
|
return TryGetMask(TypeHandle.Get<T>(), out bitSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnsafeBitSet GetOrCreateMask<T>()
|
public ref UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle)
|
||||||
where T : unmanaged, IComponentData
|
|
||||||
{
|
|
||||||
var typeHandle = TypeHandle.Get<T>();
|
|
||||||
if (!_typeIDMap.TryGetValue(typeHandle, out var id))
|
|
||||||
{
|
|
||||||
id = GetTypeID<T>();
|
|
||||||
_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)
|
|
||||||
{
|
{
|
||||||
if (!_typeIDMap.TryGetValue(typeHandle, out var id))
|
if (!_typeIDMap.TryGetValue(typeHandle, out var id))
|
||||||
{
|
{
|
||||||
@@ -678,14 +666,23 @@ internal struct ComponentStorage : IDisposable
|
|||||||
}
|
}
|
||||||
|
|
||||||
ref var set = ref _componentEntityMasks[id];
|
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<T>()
|
||||||
|
where T : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
return GetOrCreateMask(TypeHandle.Get(type));
|
return ref GetOrCreateMask(TypeHandle.Get<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ref UnsafeBitSet GetOrCreateMask(Type type)
|
||||||
|
{
|
||||||
|
return ref GetOrCreateMask(TypeHandle.Get(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -710,7 +707,7 @@ internal struct ComponentStorage : IDisposable
|
|||||||
|
|
||||||
foreach (var bitSet in _componentEntityMasks)
|
foreach (var bitSet in _componentEntityMasks)
|
||||||
{
|
{
|
||||||
bitSet?.Dispose();
|
bitSet.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
_scriptComponentPool.Dispose();
|
_scriptComponentPool.Dispose();
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
public abstract class ScriptComponent : IComponentData
|
public abstract class ScriptComponent : IComponentData
|
||||||
{
|
{
|
||||||
private bool _enable = true;
|
private bool _enable;
|
||||||
|
|
||||||
|
internal World _world = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this script component is enabled.
|
/// Gets or sets a value indicating whether this script component is enabled.
|
||||||
@@ -38,6 +40,11 @@ public abstract class ScriptComponent : IComponentData
|
|||||||
internal set;
|
internal set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the EntityManager instance associated with the current world.
|
||||||
|
/// </summary>
|
||||||
|
protected EntityManager EntityManager => _world.EntityManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the priority of the script component.
|
/// Gets or sets the priority of the script component.
|
||||||
/// Change this during runtime does not affect the execution order.
|
/// Change this during runtime does not affect the execution order.
|
||||||
@@ -58,6 +65,13 @@ public abstract class ScriptComponent : IComponentData
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the script component is initialized.
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Called when the script component is started.
|
/// Called when the script component is started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Include="Template\ForEach.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>ForEach.tt</DependentUpon>
|
||||||
|
</None>
|
||||||
<None Include="Template\QueryItem.cs">
|
<None Include="Template\QueryItem.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
@@ -32,6 +37,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<None Update="Template\ForEach.tt">
|
||||||
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
|
<LastGenOutput>ForEach.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
<None Update="Template\QueryEnumerable.tt">
|
<None Update="Template\QueryEnumerable.tt">
|
||||||
<Generator>TextTemplatingFileGenerator</Generator>
|
<Generator>TextTemplatingFileGenerator</Generator>
|
||||||
<LastGenOutput>QueryEnumerable.cs</LastGenOutput>
|
<LastGenOutput>QueryEnumerable.cs</LastGenOutput>
|
||||||
@@ -59,6 +68,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Update="Template\ForEach.cs">
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>ForEach.tt</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Update="Template\Helpers.cs">
|
<Compile Update="Template\Helpers.cs">
|
||||||
<DesignTime>True</DesignTime>
|
<DesignTime>True</DesignTime>
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
|||||||
42
Ghost.Entities/Query/QueryBuilder.cs
Normal file
42
Ghost.Entities/Query/QueryBuilder.cs
Normal file
@@ -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<T>()
|
||||||
|
{
|
||||||
|
_filter._all.Add(TypeHandle.Get<T>());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryBuilder WithAny<T>()
|
||||||
|
{
|
||||||
|
_filter._any.Add(TypeHandle.Get<T>());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryBuilder WithAbsent<T>()
|
||||||
|
{
|
||||||
|
_filter._absent.Add(TypeHandle.Get<T>());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QueryBuilder WithDisabled<T>()
|
||||||
|
{
|
||||||
|
_filter._disabled.Add(TypeHandle.Get<T>());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly QueryFilter Build()
|
||||||
|
{
|
||||||
|
return _filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,98 +1,98 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
|
using Ghost.Entities.Components;
|
||||||
using Misaki.HighPerformance.LowLevel.Buffer;
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
|
|
||||||
namespace Ghost.Entities.Query;
|
namespace Ghost.Entities.Query;
|
||||||
|
|
||||||
[Flags]
|
public struct QueryFilter : IDisposable
|
||||||
internal enum FilterMode
|
|
||||||
{
|
{
|
||||||
All = 1 << 0,
|
private readonly Stack.Scope _scope;
|
||||||
Any = 1 << 1,
|
|
||||||
Absent = 1 << 2,
|
|
||||||
Disabled = 1 << 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
internal readonly struct FilterEntry(TypeHandle id, FilterMode mode)
|
internal UnsafeList<TypeHandle> _all;
|
||||||
{
|
internal UnsafeList<TypeHandle> _any;
|
||||||
public readonly TypeHandle typeHandle = id;
|
internal UnsafeList<TypeHandle> _absent;
|
||||||
public readonly FilterMode mode = mode;
|
internal UnsafeList<TypeHandle> _disabled;
|
||||||
}
|
|
||||||
|
|
||||||
internal struct QueryFilter()
|
public QueryFilter()
|
||||||
{
|
{
|
||||||
internal List<TypeHandle> _all = new(6);
|
_scope = AllocationManager.CreateStackScope();
|
||||||
internal List<TypeHandle> _any = new(6);
|
|
||||||
internal List<TypeHandle> _absent = new(6);
|
|
||||||
internal List<TypeHandle> _disabled = new(6);
|
|
||||||
|
|
||||||
public readonly UnsafeBitSet ComputeFilterBitMask(World world)
|
_all = new UnsafeList<TypeHandle>(4, Allocator.Stack);
|
||||||
|
_any = new UnsafeList<TypeHandle>(4, Allocator.Stack);
|
||||||
|
_absent = new UnsafeList<TypeHandle>(4, Allocator.Stack);
|
||||||
|
_disabled = new UnsafeList<TypeHandle>(4, Allocator.Stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public readonly UnsafeBitSet ComputeFilterBitMask(World world, Allocator allocator)
|
||||||
{
|
{
|
||||||
UnsafeBitSet allMask = default;
|
UnsafeBitSet allMask = default;
|
||||||
UnsafeBitSet anyMask = default;
|
UnsafeBitSet anyMask = default;
|
||||||
UnsafeBitSet absentMask = default;
|
UnsafeBitSet absentMask = default;
|
||||||
|
|
||||||
using var scope = AllocationManager.CreateStackScope();
|
var result = new UnsafeBitSet(world.EntityManager.EntityCount, allocator);
|
||||||
|
|
||||||
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);
|
|
||||||
result.SetAll();
|
result.SetAll();
|
||||||
|
|
||||||
if (allMask.IsCreated)
|
using (AllocationManager.CreateStackScope())
|
||||||
{
|
{
|
||||||
result.AndOperation(allMask);
|
foreach (var typeHandle in _all)
|
||||||
allMask.Dispose();
|
{
|
||||||
}
|
var mask = world.ComponentStorage.GetOrCreateMask(typeHandle);
|
||||||
|
|
||||||
if (anyMask.IsCreated)
|
if (!allMask.IsCreated)
|
||||||
{
|
{
|
||||||
result.AndOperation(anyMask);
|
allMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.None);
|
||||||
anyMask.Dispose();
|
allMask.SetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (absentMask.IsCreated)
|
allMask.AndOperation(mask);
|
||||||
{
|
}
|
||||||
result.AndOperation(~absentMask);
|
|
||||||
absentMask.Dispose();
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Dispose()
|
||||||
|
{
|
||||||
|
_scope.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,12 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Ghost.Entities.Query;
|
namespace Ghost.Entities.Query;
|
||||||
|
|
||||||
public interface IQueryTypeParameter
|
public interface IQueryTypeParameter<T>
|
||||||
|
where T : IComponentData
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref struct CompRef<T> : IQueryTypeParameter
|
public ref struct CompRef<T> : IQueryTypeParameter<T>
|
||||||
where T : IComponentData
|
where T : IComponentData
|
||||||
{
|
{
|
||||||
internal ref T _value;
|
internal ref T _value;
|
||||||
@@ -42,7 +43,7 @@ public ref struct CompRef<T> : IQueryTypeParameter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref struct CompRO<T> : IQueryTypeParameter
|
public readonly ref struct CompRO<T> : IQueryTypeParameter<T>
|
||||||
where T : IComponentData
|
where T : IComponentData
|
||||||
{
|
{
|
||||||
internal readonly ref T _value;
|
internal readonly ref T _value;
|
||||||
|
|||||||
12
Ghost.Entities/Template/ForEach.cs
Normal file
12
Ghost.Entities/Template/ForEach.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
|
public delegate void ForEach<T0>(ref T0 t0Component);
|
||||||
|
public delegate void ForEach<T0, T1>(ref T0 t0Component,ref T1 t1Component);
|
||||||
|
public delegate void ForEach<T0, T1, T2>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component);
|
||||||
|
public delegate void ForEach<T0, T1, T2, T3>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component);
|
||||||
|
public delegate void ForEach<T0, T1, T2, T3, T4>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component);
|
||||||
|
public delegate void ForEach<T0, T1, T2, T3, T4, T5>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component);
|
||||||
|
public delegate void ForEach<T0, T1, T2, T3, T4, T5, T6>(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<T0, T1, T2, T3, T4, T5, T6, T7>(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component);
|
||||||
16
Ghost.Entities/Template/ForEach.tt
Normal file
16
Ghost.Entities/Template/ForEach.tt
Normal file
@@ -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 #>);
|
||||||
|
<# } #>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
|||||||
using Ghost.Core;
|
using Ghost.Core;
|
||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
using Ghost.Entities.Query;
|
using Ghost.Entities.Query;
|
||||||
|
using Misaki.HighPerformance.LowLevel.Buffer;
|
||||||
using Misaki.HighPerformance.LowLevel.Collections;
|
using Misaki.HighPerformance.LowLevel.Collections;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
@@ -23,9 +24,11 @@ var constructorParams = Enumerable.Range(0, arity)
|
|||||||
.Aggregate((a, b) => a + ", " + b);
|
.Aggregate((a, b) => a + ", " + b);
|
||||||
|
|
||||||
#>
|
#>
|
||||||
public struct QueryEnumerable<<#= generics #>>
|
public unsafe ref struct QueryEnumerable<<#= generics #>>
|
||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
|
private QueryFilter _filter;
|
||||||
|
|
||||||
private readonly World _world;
|
private readonly World _world;
|
||||||
|
|
||||||
<# for (int i = 0; i < arity; i++){ #>
|
<# for (int i = 0; i < arity; i++){ #>
|
||||||
@@ -33,11 +36,13 @@ public struct QueryEnumerable<<#= generics #>>
|
|||||||
<# } #>
|
<# } #>
|
||||||
private readonly int _count;
|
private readonly int _count;
|
||||||
|
|
||||||
private QueryFilter _filters;
|
|
||||||
internal readonly QueryFilter Filters => _filters;
|
|
||||||
|
|
||||||
internal QueryEnumerable(World world, <#= poolParams #>, int count)
|
internal QueryEnumerable(World world, <#= poolParams #>, int count)
|
||||||
{
|
{
|
||||||
|
_filter = new();
|
||||||
|
<# for (int i = 0; i < arity; i++) {#>
|
||||||
|
_filter._all.Add(TypeHandle.Get<T<#= i #>>());
|
||||||
|
<# } #>
|
||||||
|
|
||||||
_world = world;
|
_world = world;
|
||||||
|
|
||||||
<# for (int i = 0; i < arity; i++) { #>
|
<# for (int i = 0; i < arity; i++) { #>
|
||||||
@@ -45,28 +50,39 @@ public struct QueryEnumerable<<#= generics #>>
|
|||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
_count = count;
|
_count = count;
|
||||||
|
|
||||||
_filters = new();
|
|
||||||
<# for (int i = 0; i < arity; i++) {#>
|
|
||||||
_filters._all.Add(TypeHandle.Get<T<#= i #>>());
|
|
||||||
<# } #>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Enumerator GetEnumerator() => new (_world, <#= constructorParams #>, _count, _filters);
|
internal QueryEnumerable(World world, <#= poolParams #>, int count, ref readonly QueryFilter filter)
|
||||||
|
{
|
||||||
|
_filter = filter;
|
||||||
|
|
||||||
|
_world = world;
|
||||||
|
|
||||||
|
<# for (int i = 0; i < arity; i++) { #>
|
||||||
|
_pool<#= i #> = pool<#= i #>;
|
||||||
|
<# } #>
|
||||||
|
|
||||||
|
_count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference
|
||||||
|
public Enumerator GetEnumerator() => new(_world, <#= constructorParams #>, _count, ref _filter);
|
||||||
|
#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference
|
||||||
|
|
||||||
public ref struct Enumerator
|
public ref struct Enumerator
|
||||||
{
|
{
|
||||||
private readonly World _world;
|
private ref QueryFilter _filter;
|
||||||
|
private UnsafeBitSet _filterMask;
|
||||||
|
|
||||||
private readonly ReadOnlySpan<Entity> _entities;
|
private readonly ReadOnlySpan<Entity> _entities;
|
||||||
|
private readonly Stack.Scope _stackScope;
|
||||||
|
|
||||||
<# for (int i = 0; i < arity; i++){ #>
|
<# for (int i = 0; i < arity; i++){ #>
|
||||||
private readonly ComponentPool<T<#= i #>> _pool<#= i #>;
|
private readonly ComponentPool<T<#= i #>> _pool<#= i #>;
|
||||||
<# } #>
|
<# } #>
|
||||||
|
|
||||||
private int _index;
|
private int _index;
|
||||||
private readonly int _count;
|
private int _count;
|
||||||
|
|
||||||
private UnsafeBitSet _filterMask;
|
|
||||||
|
|
||||||
public QueryItem<<#= generics #>> Current
|
public QueryItem<<#= generics #>> Current
|
||||||
{
|
{
|
||||||
@@ -74,10 +90,14 @@ public struct QueryEnumerable<<#= generics #>>
|
|||||||
private set;
|
private set;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Enumerator(World world, <#= poolParams #>, int count, QueryFilter filters)
|
internal Enumerator(World world, <#= poolParams #>, int count, ref QueryFilter filter)
|
||||||
{
|
{
|
||||||
_world = world;
|
_stackScope = AllocationManager.CreateStackScope();
|
||||||
_entities = _world.EntityManager.Entities;
|
|
||||||
|
_filter = ref filter;
|
||||||
|
_filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack);
|
||||||
|
|
||||||
|
_entities = world.EntityManager.Entities;
|
||||||
|
|
||||||
<# for (int i = 0; i < arity; i++){ #>
|
<# for (int i = 0; i < arity; i++){ #>
|
||||||
_pool<#= i #> = pool<#= i #>;
|
_pool<#= i #> = pool<#= i #>;
|
||||||
@@ -85,7 +105,6 @@ public struct QueryEnumerable<<#= generics #>>
|
|||||||
|
|
||||||
_count = count;
|
_count = count;
|
||||||
_index = -1;
|
_index = -1;
|
||||||
_filterMask = filters.ComputeFilterBitMask(_world);
|
|
||||||
|
|
||||||
Current = default;
|
Current = default;
|
||||||
}
|
}
|
||||||
@@ -93,52 +112,60 @@ public struct QueryEnumerable<<#= generics #>>
|
|||||||
public bool MoveNext()
|
public bool MoveNext()
|
||||||
{
|
{
|
||||||
_index = _filterMask.NextSetBit(_index + 1);
|
_index = _filterMask.NextSetBit(_index + 1);
|
||||||
if (_index < 0 || _index >= _world.EntityManager.EntityCount)
|
if (_index < 0 || _count <= 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_count--;
|
||||||
Current = new QueryItem<<#= generics #>>(_entities[_index], <#= constructorParams #>);
|
Current = new QueryItem<<#= generics #>>(_entities[_index], <#= constructorParams #>);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public readonly void Dispose()
|
||||||
|
{
|
||||||
|
_stackScope.Dispose();
|
||||||
|
_filter.Dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
<# for (int i = 1; i <= ExtensionAmount; i++) {
|
<# for (int i = 1; i <= ExtensionAmount; i++) {
|
||||||
var compGenerics = AppendGenerics(i, "TComponent");
|
var compGenerics = AppendGenerics(i, "TComponent");
|
||||||
var compRestrictions = AppendGenericRestrictions(i, "TComponent", "unmanaged, IComponentData");
|
var compRestrictions = AppendGenericRestrictions(i, "TComponent", "unmanaged, IComponentData");
|
||||||
#>
|
#>
|
||||||
|
|
||||||
public readonly QueryEnumerable<<#= generics #>> WithAll<<#= compGenerics #>>()
|
public QueryEnumerable<<#= generics #>> WithAll<<#= compGenerics #>>()
|
||||||
<#= compRestrictions #>
|
<#= compRestrictions #>
|
||||||
{
|
{
|
||||||
<# for (int j = 0; j < i; j++) {#>
|
<# for (int j = 0; j < i; j++) {#>
|
||||||
_filters._all.Add(TypeHandle.Get<TComponent<#= j #>>());
|
_filter._all.Add(TypeHandle.Get<TComponent<#= j #>>());
|
||||||
<# } #>
|
<# } #>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly QueryEnumerable<<#= generics #>> WithAny<<#= compGenerics #>>()
|
public QueryEnumerable<<#= generics #>> WithAny<<#= compGenerics #>>()
|
||||||
<#= compRestrictions #>
|
<#= compRestrictions #>
|
||||||
{
|
{
|
||||||
<# for (int j = 0; j < i; j++) {#>
|
<# for (int j = 0; j < i; j++) {#>
|
||||||
_filters._any.Add(TypeHandle.Get<TComponent<#= j #>>());
|
_filter._any.Add(TypeHandle.Get<TComponent<#= j #>>());
|
||||||
<# } #>
|
<# } #>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly QueryEnumerable<<#= generics #>> WithAbsent<<#= compGenerics #>>()
|
public QueryEnumerable<<#= generics #>> WithAbsent<<#= compGenerics #>>()
|
||||||
<#= compRestrictions #>
|
<#= compRestrictions #>
|
||||||
{
|
{
|
||||||
<# for (int j = 0; j < i; j++) {#>
|
<# for (int j = 0; j < i; j++) {#>
|
||||||
_filters._absent.Add(TypeHandle.Get<TComponent<#= j #>>());
|
_filter._absent.Add(TypeHandle.Get<TComponent<#= j #>>());
|
||||||
<# } #>
|
<# } #>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly QueryEnumerable<<#= generics #>> WithDisabled<<#= compGenerics #>>()
|
public QueryEnumerable<<#= generics #>> WithDisabled<<#= compGenerics #>>()
|
||||||
<#= compRestrictions #>
|
<#= compRestrictions #>
|
||||||
{
|
{
|
||||||
<# for (int j = 0; j < i; j++) {#>
|
<# for (int j = 0; j < i; j++) {#>
|
||||||
_filters._disabled.Add(TypeHandle.Get<TComponent<#= j #>>());
|
_filter._disabled.Add(TypeHandle.Get<TComponent<#= j #>>());
|
||||||
<# } #>
|
<# } #>
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public readonly struct QueryItem<T0>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ public readonly struct QueryItem<T0, T1>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ public readonly struct QueryItem<T0, T1, T2>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,10 +122,10 @@ public readonly struct QueryItem<T0, T1, T2, T3>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
c3 = new(ref _pool3.GetRef(_entity));
|
c3 = new (ref _pool3.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,11 +162,11 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
c3 = new(ref _pool3.GetRef(_entity));
|
c3 = new (ref _pool3.GetRef(_entity));
|
||||||
c4 = new(ref _pool4.GetRef(_entity));
|
c4 = new (ref _pool4.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +206,12 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
c3 = new(ref _pool3.GetRef(_entity));
|
c3 = new (ref _pool3.GetRef(_entity));
|
||||||
c4 = new(ref _pool4.GetRef(_entity));
|
c4 = new (ref _pool4.GetRef(_entity));
|
||||||
c5 = new(ref _pool5.GetRef(_entity));
|
c5 = new (ref _pool5.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,13 +254,13 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5, T6>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
c3 = new(ref _pool3.GetRef(_entity));
|
c3 = new (ref _pool3.GetRef(_entity));
|
||||||
c4 = new(ref _pool4.GetRef(_entity));
|
c4 = new (ref _pool4.GetRef(_entity));
|
||||||
c5 = new(ref _pool5.GetRef(_entity));
|
c5 = new (ref _pool5.GetRef(_entity));
|
||||||
c6 = new(ref _pool6.GetRef(_entity));
|
c6 = new (ref _pool6.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,14 +306,14 @@ public readonly struct QueryItem<T0, T1, T2, T3, T4, T5, T6, T7>
|
|||||||
{
|
{
|
||||||
entity = _entity;
|
entity = _entity;
|
||||||
|
|
||||||
c0 = new(ref _pool0.GetRef(_entity));
|
c0 = new (ref _pool0.GetRef(_entity));
|
||||||
c1 = new(ref _pool1.GetRef(_entity));
|
c1 = new (ref _pool1.GetRef(_entity));
|
||||||
c2 = new(ref _pool2.GetRef(_entity));
|
c2 = new (ref _pool2.GetRef(_entity));
|
||||||
c3 = new(ref _pool3.GetRef(_entity));
|
c3 = new (ref _pool3.GetRef(_entity));
|
||||||
c4 = new(ref _pool4.GetRef(_entity));
|
c4 = new (ref _pool4.GetRef(_entity));
|
||||||
c5 = new(ref _pool5.GetRef(_entity));
|
c5 = new (ref _pool5.GetRef(_entity));
|
||||||
c6 = new(ref _pool6.GetRef(_entity));
|
c6 = new (ref _pool6.GetRef(_entity));
|
||||||
c7 = new(ref _pool7.GetRef(_entity));
|
c7 = new (ref _pool7.GetRef(_entity));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
|
using Ghost.Entities.Query;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
@@ -10,7 +11,9 @@ public partial class World
|
|||||||
where T0 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0>(
|
return new QueryEnumerable<T0>(
|
||||||
this,
|
this,
|
||||||
@@ -18,11 +21,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0> QueryFilter<T0>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0>(
|
||||||
|
this,
|
||||||
|
pool0,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1> Query<T0, T1>()
|
public QueryEnumerable<T0, T1> Query<T0, T1>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1>(
|
return new QueryEnumerable<T0, T1>(
|
||||||
this,
|
this,
|
||||||
@@ -30,11 +50,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1> QueryFilter<T0, T1>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1>(
|
||||||
|
this,
|
||||||
|
pool0, pool1,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2> Query<T0, T1, T2>()
|
public QueryEnumerable<T0, T1, T2> Query<T0, T1, T2>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2>(
|
return new QueryEnumerable<T0, T1, T2>(
|
||||||
this,
|
this,
|
||||||
@@ -42,11 +79,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2> QueryFilter<T0, T1, T2>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3> Query<T0, T1, T2, T3>()
|
public QueryEnumerable<T0, T1, T2, T3> Query<T0, T1, T2, T3>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2, T3>(
|
return new QueryEnumerable<T0, T1, T2, T3>(
|
||||||
this,
|
this,
|
||||||
@@ -54,11 +108,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2, T3> QueryFilter<T0, T1, T2, T3>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2, T3>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2, pool3,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4> Query<T0, T1, T2, T3, T4>()
|
public QueryEnumerable<T0, T1, T2, T3, T4> Query<T0, T1, T2, T3, T4>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2, T3, T4>(
|
return new QueryEnumerable<T0, T1, T2, T3, T4>(
|
||||||
this,
|
this,
|
||||||
@@ -66,11 +137,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2, T3, T4> QueryFilter<T0, T1, T2, T3, T4>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2, T3, T4>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2, pool3, pool4,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5> Query<T0, T1, T2, T3, T4, T5>()
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5> Query<T0, T1, T2, T3, T4, T5>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2, T3, T4, T5>(
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5>(
|
||||||
this,
|
this,
|
||||||
@@ -78,11 +166,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5> QueryFilter<T0, T1, T2, T3, T4, T5>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2, pool3, pool4, pool5,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6> Query<T0, T1, T2, T3, T4, T5, T6>()
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6> Query<T0, T1, T2, T3, T4, T5, T6>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6>(
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6>(
|
||||||
this,
|
this,
|
||||||
@@ -90,11 +195,28 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6> QueryFilter<T0, T1, T2, T3, T4, T5, T6>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2, pool3, pool4, pool5, pool6,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7> Query<T0, T1, T2, T3, T4, T5, T6, T7>()
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7> Query<T0, T1, T2, T3, T4, T5, T6, T7>()
|
||||||
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6) && _componentStorage.TryGetPool<T7>(out var pool7)))
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6) && _componentStorage.TryGetPool<T7>(out var pool7)))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7>(
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7>(
|
||||||
this,
|
this,
|
||||||
@@ -102,4 +224,19 @@ public partial class World
|
|||||||
pool0.Count);
|
pool0.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7> QueryFilter<T0, T1, T2, T3, T4, T5, T6, T7>(ref readonly QueryFilter filter)
|
||||||
|
where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData
|
||||||
|
{
|
||||||
|
if (!(_componentStorage.TryGetPool<T0>(out var pool0) && _componentStorage.TryGetPool<T1>(out var pool1) && _componentStorage.TryGetPool<T2>(out var pool2) && _componentStorage.TryGetPool<T3>(out var pool3) && _componentStorage.TryGetPool<T4>(out var pool4) && _componentStorage.TryGetPool<T5>(out var pool5) && _componentStorage.TryGetPool<T6>(out var pool6) && _componentStorage.TryGetPool<T7>(out var pool7)))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<T0, T1, T2, T3, T4, T5, T6, T7>(
|
||||||
|
this,
|
||||||
|
pool0, pool1, pool2, pool3, pool4, pool5, pool6, pool7,
|
||||||
|
pool0.Count,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
<#@ include file="Helpers.ttinclude" #>
|
<#@ include file="Helpers.ttinclude" #>
|
||||||
|
|
||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
|
using Ghost.Entities.Query;
|
||||||
|
|
||||||
namespace Ghost.Entities;
|
namespace Ghost.Entities;
|
||||||
|
|
||||||
@@ -24,7 +25,9 @@ public partial class World
|
|||||||
<#= restrictions #>
|
<#= restrictions #>
|
||||||
{
|
{
|
||||||
if (!(<#= tryGetPools #>))
|
if (!(<#= tryGetPools #>))
|
||||||
|
{
|
||||||
return default;
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
return new QueryEnumerable<<#= generics #>>(
|
return new QueryEnumerable<<#= generics #>>(
|
||||||
this,
|
this,
|
||||||
@@ -32,5 +35,20 @@ public partial class World
|
|||||||
<#= countSource #>);
|
<#= countSource #>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public QueryEnumerable<<#= generics #>> QueryFilter<<#= generics #>>(ref readonly QueryFilter filter)
|
||||||
|
<#= restrictions #>
|
||||||
|
{
|
||||||
|
if (!(<#= tryGetPools #>))
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QueryEnumerable<<#= generics #>>(
|
||||||
|
this,
|
||||||
|
<#= poolParams #>,
|
||||||
|
<#= countSource #>,
|
||||||
|
in filter);
|
||||||
|
}
|
||||||
|
|
||||||
<# } #>
|
<# } #>
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Ghost.Entities.Components;
|
using Ghost.Entities.Components;
|
||||||
using Ghost.Entities.Query;
|
using Ghost.Entities.Query;
|
||||||
using Ghost.Entities.Systems;
|
using Ghost.Entities.Systems;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ public partial class World : IDisposable, IEquatable<World>
|
|||||||
private readonly ComponentStorage _componentStorage;
|
private readonly ComponentStorage _componentStorage;
|
||||||
private readonly SystemStorage _systemStorage;
|
private readonly SystemStorage _systemStorage;
|
||||||
|
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
internal ComponentStorage ComponentStorage => _componentStorage;
|
internal ComponentStorage ComponentStorage => _componentStorage;
|
||||||
|
|
||||||
public WorldID ID => _id;
|
public WorldID ID => _id;
|
||||||
@@ -67,6 +70,11 @@ public partial class World : IDisposable, IEquatable<World>
|
|||||||
_systemStorage = new SystemStorage(this);
|
_systemStorage = new SystemStorage(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~World()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public CompRef<T> GetSingleton<T>()
|
public CompRef<T> GetSingleton<T>()
|
||||||
where T : unmanaged, IComponentData
|
where T : unmanaged, IComponentData
|
||||||
@@ -87,29 +95,20 @@ public partial class World : IDisposable, IEquatable<World>
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
[Conditional("GHOST_EDITOR")]
|
||||||
public void NotifyComponentChanged(Entity entity, Type type)
|
public void NotifyComponentChanged(Entity entity, Type type)
|
||||||
{
|
{
|
||||||
//#if GHOST_EDITOR
|
|
||||||
ComponentChanged?.Invoke(this, entity, type);
|
ComponentChanged?.Invoke(this, entity, type);
|
||||||
//#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
[Conditional("GHOST_EDITOR")]
|
||||||
public void NotifyComponentChanged<T>(Entity entity)
|
public void NotifyComponentChanged<T>(Entity entity)
|
||||||
where T : unmanaged, IComponentData
|
where T : unmanaged, IComponentData
|
||||||
{
|
{
|
||||||
NotifyComponentChanged(entity, typeof(T));
|
NotifyComponentChanged(entity, typeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_entityManager.Dispose();
|
|
||||||
_componentStorage.Dispose();
|
|
||||||
_systemStorage.Dispose();
|
|
||||||
|
|
||||||
s_freeWorldSlots.Enqueue(_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(World? other)
|
public bool Equals(World? other)
|
||||||
{
|
{
|
||||||
if (other is null)
|
if (other is null)
|
||||||
@@ -144,4 +143,22 @@ public partial class World : IDisposable, IEquatable<World>
|
|||||||
{
|
{
|
||||||
return !(left == right);
|
return !(left == right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_isDisposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_entityManager.Dispose();
|
||||||
|
_componentStorage.Dispose();
|
||||||
|
_systemStorage.Dispose();
|
||||||
|
|
||||||
|
s_freeWorldSlots.Enqueue(_id);
|
||||||
|
|
||||||
|
_isDisposed = true;
|
||||||
|
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="fmod.dll">
|
<Content Include="runtime\win-x64\native\fmod.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="fmodstudio.dll">
|
<Content Include="runtime\win-x64\native\fmodstudio.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -149,21 +149,11 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
|
|
||||||
// Get compiled bytecode
|
// Get compiled bytecode
|
||||||
using ComPtr<IDxcBlob> bytecodeBlob = default;
|
using ComPtr<IDxcBlob> bytecodeBlob = default;
|
||||||
result.Get()->GetResult(bytecodeBlob.GetAddressOf());
|
ThrowIfFailed(result.Get()->GetResult(bytecodeBlob.GetAddressOf()));
|
||||||
|
|
||||||
if (bytecodeBlob.Get() == null)
|
|
||||||
{
|
|
||||||
throw new Exception("DXC compilation succeeded but no bytecode was produced");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get reflection data using DXC API
|
// Get reflection data using DXC API
|
||||||
using ComPtr<IDxcBlob> reflectionBlob = default;
|
using ComPtr<IDxcBlob> reflectionBlob = default;
|
||||||
result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), reflectionBlob.GetVoidAddressOf(), null);
|
ThrowIfFailed(result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof<IDxcBlob>(), reflectionBlob.GetVoidAddressOf(), null));
|
||||||
|
|
||||||
if (reflectionBlob.Get() == null)
|
|
||||||
{
|
|
||||||
throw new Exception("DXC compilation succeeded but no reflection data was produced");
|
|
||||||
}
|
|
||||||
|
|
||||||
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
var bytecodeSize = bytecodeBlob.Get()->GetBufferSize();
|
||||||
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
var bytecode = new UnsafeArray<byte>((int)bytecodeSize, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent);
|
||||||
@@ -210,12 +200,7 @@ internal unsafe static class D3D12ShaderCompiler
|
|||||||
};
|
};
|
||||||
|
|
||||||
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
using ComPtr<ID3D12ShaderReflection> reflection = default;
|
||||||
utils.Get()->CreateReflection(&reflectionData, __uuidof<ID3D12ShaderReflection>(), reflection.GetVoidAddressOf());
|
ThrowIfFailed(utils.Get()->CreateReflection(&reflectionData, __uuidof<ID3D12ShaderReflection>(), reflection.GetVoidAddressOf()));
|
||||||
|
|
||||||
if (reflection.Get() == null)
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to create shader reflection from DXC output");
|
|
||||||
}
|
|
||||||
|
|
||||||
D3D12_SHADER_DESC shaderDesc;
|
D3D12_SHADER_DESC shaderDesc;
|
||||||
reflection.Get()->GetDesc(&shaderDesc);
|
reflection.Get()->GetDesc(&shaderDesc);
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ internal unsafe static class Win32Utility
|
|||||||
{
|
{
|
||||||
public static void ThrowIfFailed(this HRESULT hr)
|
public static void ThrowIfFailed(this HRESULT hr)
|
||||||
{
|
{
|
||||||
if (hr.FAILED)
|
Windows.ThrowIfFailed(hr);
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Operation failed with HRESULT: 0x{hr.Value:X8}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void** GetVoidAddressOf<T>(this ComPtr<T> comPtr)
|
public static void** GetVoidAddressOf<T>(this ComPtr<T> comPtr)
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Misaki.HighPerformance.Mathematics" Version="1.1.0" />
|
<PackageReference Include="Misaki.HighPerformance.Mathematics" Version="1.1.0" />
|
||||||
<PackageReference Include="TerraFX.Interop.D3D12MemoryAllocator" Version="2.0.1.5" />
|
<PackageReference Include="TerraFX.Interop.D3D12MemoryAllocator" Version="2.0.1.5" />
|
||||||
<PackageReference Include="TerraFX.Interop.Windows" Version="10.0.26100.2" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -2,5 +2,9 @@
|
|||||||
|
|
||||||
public interface ITest
|
public interface ITest
|
||||||
{
|
{
|
||||||
|
public void Setup();
|
||||||
|
|
||||||
public void Run();
|
public void Run();
|
||||||
|
|
||||||
|
public void Cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,23 @@ public class TestRunner
|
|||||||
where T : ITest, new()
|
where T : ITest, new()
|
||||||
{
|
{
|
||||||
var test = new T();
|
var test = new T();
|
||||||
|
test.Setup();
|
||||||
test.Run();
|
test.Run();
|
||||||
|
test.Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Run<T>(int iteration)
|
||||||
|
where T : ITest, new()
|
||||||
|
{
|
||||||
|
var test = new T();
|
||||||
|
test.Setup();
|
||||||
|
|
||||||
|
iteration = iteration < 1 ? 1 : iteration;
|
||||||
|
for (var i = 0; i < iteration; i++)
|
||||||
|
{
|
||||||
|
test.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
test.Cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="meshoptimizer_native.dll">
|
<Content Include="runtime\win-x64\native\meshoptimizer_native.dll">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -252,7 +252,9 @@ Global
|
|||||||
{1ED62E09-8F36-4671-896B-16C1C1530202} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
{1ED62E09-8F36-4671-896B-16C1C1530202} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
||||||
{0D626DAF-EF18-435C-A85C-EEA1B141E8B5} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221}
|
{0D626DAF-EF18-435C-A85C-EEA1B141E8B5} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221}
|
||||||
{8A1C494B-2888-4D0D-8325-9F5C8D1D1955} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
{8A1C494B-2888-4D0D-8325-9F5C8D1D1955} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
||||||
|
{996ABECC-1C5A-4F07-B8AC-D063F91962CB} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221}
|
||||||
{4179873E-8174-4D17-9584-8C223BA71366} = {43E76E46-0E5F-4429-83C8-157689885174}
|
{4179873E-8174-4D17-9584-8C223BA71366} = {43E76E46-0E5F-4429-83C8-157689885174}
|
||||||
|
{337D9110-76FC-453C-9481-757052A216E5} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
||||||
{222A4E83-D902-423A-8E99-8321BBFC604C} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221}
|
{222A4E83-D902-423A-8E99-8321BBFC604C} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221}
|
||||||
{F55831B1-2ADE-4CEB-8023-F92C7ABF57FE} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
{F55831B1-2ADE-4CEB-8023-F92C7ABF57FE} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70}
|
||||||
{C3AB43A4-88D8-49F8-B738-A738C8BCEE3F} = {43E76E46-0E5F-4429-83C8-157689885174}
|
{C3AB43A4-88D8-49F8-B738-A738C8BCEE3F} = {43E76E46-0E5F-4429-83C8-157689885174}
|
||||||
|
|||||||
Reference in New Issue
Block a user