|
|
|
using System;
|
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using gaemstone.ECS.Utility;
|
|
|
|
using static flecs_hub.flecs;
|
|
|
|
|
|
|
|
namespace gaemstone.ECS;
|
|
|
|
|
|
|
|
public unsafe class Rule<TContext>
|
|
|
|
: IDisposable
|
|
|
|
{
|
|
|
|
public World<TContext> World { get; }
|
|
|
|
public ecs_rule_t* Handle { get; }
|
|
|
|
public Filter<TContext> Filter { get; }
|
|
|
|
|
|
|
|
private VariableCollection? _variables;
|
|
|
|
public VariableCollection Variables => _variables ??= new(this);
|
|
|
|
public Variable? ThisVar => Filter.ThisVar;
|
|
|
|
|
|
|
|
public Rule(World<TContext> world, FilterDesc desc)
|
|
|
|
{
|
|
|
|
using var alloc = TempAllocator.Use();
|
|
|
|
var flecsDesc = desc.ToFlecs(alloc);
|
|
|
|
World = world;
|
|
|
|
Handle = ecs_rule_init(world, &flecsDesc);
|
|
|
|
Filter = new(World, ecs_rule_get_filter(Handle));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
=> ecs_rule_fini(this);
|
|
|
|
|
|
|
|
public RuleIterator<TContext> Iter()
|
|
|
|
=> new(ecs_rule_iter(World, this));
|
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
=> ecs_rule_str(Handle).FlecsToStringAndFree()!;
|
|
|
|
|
|
|
|
public static implicit operator ecs_rule_t*(Rule<TContext> rule) => rule.Handle;
|
|
|
|
|
|
|
|
|
|
|
|
public unsafe class VariableCollection
|
|
|
|
: IReadOnlyCollection<Variable>
|
|
|
|
{
|
|
|
|
private readonly List<Variable> _variables = new();
|
|
|
|
|
|
|
|
public int Count => _variables.Count;
|
|
|
|
public Variable? this[int index]
|
|
|
|
=> _variables.Find(v => v.Index == index);
|
|
|
|
public Variable? this[string name]
|
|
|
|
=> _variables.Find(v => string.Equals(
|
|
|
|
v.Name, name, StringComparison.OrdinalIgnoreCase));
|
|
|
|
|
|
|
|
internal VariableCollection(ecs_rule_t* handle)
|
|
|
|
{
|
|
|
|
// Find the $this variable, if the rule has one.
|
|
|
|
var thisIndex = ecs_filter_find_this_var(ecs_rule_get_filter(handle));
|
|
|
|
if (thisIndex >= 0) _variables.Add(new(thisIndex, "this"));
|
|
|
|
|
|
|
|
// Find all the other "accessible" variables.
|
|
|
|
var count = ecs_rule_var_count(handle);
|
|
|
|
for (var i = 0; i < count; i++) {
|
|
|
|
if ((i == thisIndex) || !ecs_rule_var_is_entity(handle, i)) continue;
|
|
|
|
var name = ecs_rule_var_name(handle, i).FlecsToString()!;
|
|
|
|
_variables.Add(new(i, name));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// IEnumerable implementation
|
|
|
|
public IEnumerator<Variable> GetEnumerator() => _variables.GetEnumerator();
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => _variables.GetEnumerator();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public unsafe class RuleIterator<TContext>
|
|
|
|
: Iterator<TContext>
|
|
|
|
{
|
|
|
|
internal RuleIterator(ecs_iter_t value)
|
|
|
|
: base(value) { }
|
|
|
|
public override bool Next()
|
|
|
|
=> ecs_rule_next(Handle);
|
|
|
|
}
|