From f9fa808d6842f5b208bbdfa1925f156342ed8a60 Mon Sep 17 00:00:00 2001 From: copygirl Date: Thu, 29 Dec 2022 03:00:08 +0100 Subject: [PATCH] Add support for iterator variables - Add Iterator.Variable - Add Iterator.GetVar and .SetVar methods - Add ThisVar to Filter, Query and Rule - Add Rule.Variables, shows all its variables - Remove Iterator.SetThis --- src/gaemstone.ECS/Filter.cs | 8 +++++++ src/gaemstone.ECS/Iterator.cs | 29 ++++++++++++++++------ src/gaemstone.ECS/Query.cs | 4 ++++ src/gaemstone.ECS/Rule.cs | 45 +++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/gaemstone.ECS/Filter.cs b/src/gaemstone.ECS/Filter.cs index 5acf0c4..9437446 100644 --- a/src/gaemstone.ECS/Filter.cs +++ b/src/gaemstone.ECS/Filter.cs @@ -12,6 +12,14 @@ public unsafe class Filter public World World { get; } public ecs_filter_t* Handle { get; } + public Iterator.Variable? ThisVar { get { + var index = ecs_filter_find_this_var(this); + return (index >= 0) ? new(index, "This") : null; + } } + + internal Filter(World world, ecs_filter_t* handle) + { World = world; Handle = handle; } + public Filter(World world, FilterDesc desc) { using var alloc = TempAllocator.Use(); diff --git a/src/gaemstone.ECS/Iterator.cs b/src/gaemstone.ECS/Iterator.cs index f26d66c..5ae146f 100644 --- a/src/gaemstone.ECS/Iterator.cs +++ b/src/gaemstone.ECS/Iterator.cs @@ -31,13 +31,6 @@ public unsafe class Iterator return new(world, IteratorType.Term, flecsIter); } - public Iterator SetThis(Entity entity) - { - fixed (ecs_iter_t* ptr = &Value) - ecs_iter_set_var(ptr, 0, entity); - return this; - } - public void Dispose() { // When an iterator is iterated until completion, @@ -47,6 +40,19 @@ public unsafe class Iterator ecs_iter_fini(ptr); } + public EntityRef GetVar(Variable var) + { + fixed (ecs_iter_t* ptr = &Value) + return new(World, new(ecs_iter_get_var(ptr, var.Index))); + } + + public Iterator SetVar(Variable var, Entity entity) + { + fixed (ecs_iter_t* ptr = &Value) + ecs_iter_set_var(ptr, var.Index, entity); + return this; + } + public bool Next() { fixed (ecs_iter_t* ptr = &Value) { @@ -113,6 +119,15 @@ public unsafe class Iterator // IEnumerable implementation public IEnumerator GetEnumerator() { while (Next()) yield return this; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + + public class Variable + { + public int Index { get; } + public string Name { get; } + public Variable(int index, string name) + { Index = index; Name = name; } + } } public enum IteratorType diff --git a/src/gaemstone.ECS/Query.cs b/src/gaemstone.ECS/Query.cs index b8ab013..a215a74 100644 --- a/src/gaemstone.ECS/Query.cs +++ b/src/gaemstone.ECS/Query.cs @@ -9,6 +9,9 @@ public unsafe class Query { public World World { get; } public ecs_query_t* Handle { get; } + public Filter Filter { get; } + + public Iterator.Variable? ThisVar => Filter.ThisVar; public Query(World world, QueryDesc desc) { @@ -16,6 +19,7 @@ public unsafe class Query var flecsDesc = desc.ToFlecs(alloc); World = world; Handle = ecs_query_init(world, &flecsDesc); + Filter = new(world, ecs_query_get_filter(Handle)); } public void Dispose() diff --git a/src/gaemstone.ECS/Rule.cs b/src/gaemstone.ECS/Rule.cs index 9f6bd65..142905d 100644 --- a/src/gaemstone.ECS/Rule.cs +++ b/src/gaemstone.ECS/Rule.cs @@ -1,4 +1,6 @@ using System; +using System.Collections; +using System.Collections.Generic; using gaemstone.Utility; using static flecs_hub.flecs; @@ -9,6 +11,11 @@ public unsafe class Rule { public World World { get; } public ecs_rule_t* Handle { get; } + public Filter Filter { get; } + + private VariableCollection? _variables; + public VariableCollection Variables => _variables ??= new(this); + public Iterator.Variable? ThisVar => Filter.ThisVar; public Rule(World world, FilterDesc desc) { @@ -16,6 +23,7 @@ public unsafe class Rule var flecsDesc = desc.ToFlecs(alloc); World = world; Handle = ecs_rule_init(world, &flecsDesc); + Filter = new(World, ecs_rule_get_filter(Handle)); } public void Dispose() @@ -28,4 +36,41 @@ public unsafe class Rule => ecs_rule_str(Handle).FlecsToStringAndFree()!; public static implicit operator ecs_rule_t*(Rule q) => q.Handle; + + + public unsafe class VariableCollection + : IReadOnlyCollection + { + private readonly List _variables = new(); + + public Rule Rule { get; } + + public int Count => _variables.Count; + public Iterator.Variable? this[int index] + => _variables.Find(v => v.Index == index); + public Iterator.Variable? this[string name] + => _variables.Find(v => string.Equals( + v.Name, name, StringComparison.OrdinalIgnoreCase)); + + internal VariableCollection(Rule rule) + { + Rule = rule; + + // Find the $This variable, if the rule has one. + var thisIndex = ecs_filter_find_this_var(ecs_rule_get_filter(Rule)); + if (thisIndex >= 0) _variables.Add(new(thisIndex, "This")); + + // Find all the other "accessible" variables. + var count = ecs_rule_var_count(Rule); + for (var i = 0; i < count; i++) { + if ((i == thisIndex) || !ecs_rule_var_is_entity(Rule, i)) continue; + var name = ecs_rule_var_name(Rule, i).FlecsToString()!; + _variables.Add(new(i, name)); + } + } + + // IEnumerable implementation + public IEnumerator GetEnumerator() => _variables.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _variables.GetEnumerator(); + } }