Add ForeachEntity to ArchTypeQuery
I am trying to make a wrapper around friflo...
However I want it to be fast using SIMD.
The problem I run into is with generics. In C# there is no such thing as varadic generics. So I need to either write alot of boiler plate code or build the query up one component at a time and use Get, Add, Remove methods of Entities.
I don't know how bad this in on performance but Ideally the entity and it's components would be local to the cache when using Get, Add, Remove methods.
One of the things I ran into was the non generic ArchetypeQuery has no ForEachEntity method even though I build it up with All, Any, and Without methods.
I don't even know if this code works. I hate how C# doesn't have aliases.
using System.Runtime.Intrinsics;
using Friflo.Engine.ECS;
namespace SpaceTest.Ecs;
public readonly struct Query
{
private readonly ArchetypeQuery _query;
internal Query(EntityStore store)
{
_query = store.Query();
Components = new ComponentQuery(this, _query);
Tags = new TagQuery(this, _query);
}
internal Query(ArchetypeQuery query)
{
_query = query;
Components = new ComponentQuery(this, _query);
Tags = new TagQuery(this, _query);
}
public readonly IComponentQuery Components;
public readonly ITagQuery Tags;
public Query Disabled => new(_query.WithDisabled());
public void ForEach(Action<Entity> action)
{
_query.Each()
{
}
}
public interface IComponentQuery
{
public Query AllOf <T>() where T : struct, IComponent;
public Query AnyOf <T>() where T : struct, IComponent;
public Query NoneOf<T>() where T : struct, IComponent;
}
public interface ITagQuery
{
public Query AllOf <T>() where T : struct, ITag;
public Query AnyOf <T>() where T : struct, ITag;
public Query NoneOf<T>() where T : struct, ITag;
}
public readonly struct ComponentQuery( Query query, ArchetypeQuery archetypeQuery) : IComponentQuery
{
public Query AllOf <T>() where T : struct, IComponent
{
return new(archetypeQuery.AllComponents(ComponentTypes.Get<T>()));
}
public Query AnyOf <T>() where T : struct, IComponent
{
return new(archetypeQuery.AnyComponents(ComponentTypes.Get<T>()));
}
public Query NoneOf<T>() where T : struct, IComponent
{
return new(archetypeQuery.WithoutAllComponents(ComponentTypes.Get<T>()));
}
}
public readonly struct TagQuery ( Query query, ArchetypeQuery archetypeQuery) : ITagQuery
{
public Query AllOf <T>() where T : struct, ITag
{
return new(archetypeQuery.AllTags(Friflo.Engine.ECS.Tags.Get<T>()));
}
public Query AnyOf <T>() where T : struct, ITag
{
return new(archetypeQuery.AnyTags(Friflo.Engine.ECS.Tags.Get<T>()));
}
public Query NoneOf<T>() where T : struct, ITag
{
return new(archetypeQuery.WithoutAllTags(Friflo.Engine.ECS.Tags.Get<T>()));
}
}
}
Every ArchetypeQuery has a property Entities. This property is an enumerator.
It can be used to iterate all entities matching the query.
foreach (var entity in query.Entities) {
entity.GetComponent<MyComponent>.value = 42;
}
You can use this loop in your void ForEach(Action<Entity> action) method.
Every
ArchetypeQueryhas a propertyEntities. This property is an enumerator. It can be used to iterate all entities matching the query.foreach (var entity in query.Entities) { entity.GetComponent<MyComponent>.value = 42; }
You can use this loop in your
void ForEach(Action<Entity> action)method.
Is there a way to do it with simd?
Is there a way to do it with simd?
Simd requires the use of generic ArchetypeQuery<...>.
Those queries provide access to the components with SIMD operations.
This access is available via ArchetypeQuery<...>.Chunks property.
See: https://friflo.gitbook.io/friflo.engine.ecs/documentation/query-optimization#query-vectorization-simd.
The non generic ArchetypeQuery cannot ensure that specific component chunks exist.
So it cannot provide access via a Chunks property.