Alternative managed wrapper around flecs-cs bindings for using the ECS framework Flecs in modern .NET.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.5 KiB

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using gaemstone.ECS.Utility;
using static flecs_hub.flecs;
namespace gaemstone.ECS;
public unsafe class Filter<TContext>
: IDisposable
{
public World<TContext> World { get; }
public ecs_filter_t* Handle { get; }
public Variable? ThisVar { get {
var index = ecs_filter_find_this_var(this);
return (index >= 0) ? new(index, "This") : null;
} }
internal Filter(World<TContext> world, ecs_filter_t* handle)
{ World = world; Handle = handle; }
public Filter(World<TContext> world, FilterDesc desc)
{
using var alloc = TempAllocator.Use();
var flecsDesc = desc.ToFlecs(alloc);
World = world;
Handle = ecs_filter_init(world, &flecsDesc);
}
public void Dispose()
=> ecs_filter_fini(this);
public FilterIterator<TContext> Iter()
=> new(ecs_filter_iter(World, this));
public override string ToString()
=> ecs_filter_str(World, this).FlecsToStringAndFree()!;
public static implicit operator ecs_filter_t*(Filter<TContext> filter) => filter.Handle;
}
public unsafe class FilterIterator<TContext>
: Iterator<TContext>
{
internal FilterIterator(ecs_iter_t value)
: base(value) { }
public override bool Next()
=> ecs_filter_next(Handle);
}
public class FilterDesc
{
public IReadOnlyList<Term> Terms { get; }
public string? Expression { get; }
/// <summary>
/// When true, terms returned by an iterator may either contain 1 or N
/// elements, where terms with N elements are owned, and terms with 1
/// element are shared, for example from a parent or base entity. When
/// false, the iterator will at most return 1 element when the result
/// contains both owned and shared terms.
/// </summary>
public bool Instanced { get; set; }
/// <summary>
/// Entity associated with query (optional).
/// </summary>
public Entity Entity { get; set; }
public FilterDesc(params Term[] terms)
=> Terms = terms;
public FilterDesc(string expression) : this()
=> Expression = expression;
public unsafe ecs_filter_desc_t ToFlecs(IAllocator allocator)
{
var desc = new ecs_filter_desc_t {
_expr = allocator.AllocateCString(Expression),
instanced = Instanced,
entity = Entity,
};
var span = desc.terms;
if (Terms.Count > span.Length) {
span = allocator.Allocate<ecs_term_t>(Terms.Count);
desc.terms_buffer = (ecs_term_t*)Unsafe.AsPointer(ref span[0]);
desc.terms_buffer_count = Terms.Count;
}
for (var i = 0; i < Terms.Count; i++)
span[i] = Terms[i].ToFlecs(allocator);
return desc;
}
}