using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using static flecs_hub.flecs; namespace gaemstone.ECS; public unsafe class Iterator : IEnumerable { public Universe Universe { get; } public IteratorType? Type { get; } public ecs_iter_t Value; public int Count => Value.count; public TimeSpan DeltaTime => TimeSpan.FromSeconds(Value.delta_time); public TimeSpan DeltaSystemTime => TimeSpan.FromSeconds(Value.delta_system_time); public Iterator(Universe universe, IteratorType? type, ecs_iter_t value) { Universe = universe; Type = type; Value = value; } public static Iterator FromTerm(Universe universe, in ecs_term_t term) { fixed (ecs_term_t* ptr = &term) return new(universe, IteratorType.Term, ecs_term_iter(universe, ptr)); } public bool Next() { fixed (ecs_iter_t* ptr = &Value) return Type switch { IteratorType.Term => ecs_term_next(ptr), IteratorType.Filter => ecs_filter_next(ptr), IteratorType.Query => ecs_query_next(ptr), IteratorType.Rule => ecs_rule_next(ptr), _ => ecs_iter_next(ptr), }; } public Entity Entity(int index) => new(Universe, Value.entities[index]); public Span Field(int index) where T : unmanaged { fixed (ecs_iter_t* ptr = &Value) { var size = (ulong)Unsafe.SizeOf(); var pointer = ecs_field_w_size(ptr, size, index); return new Span(pointer, Count); } } public SpanToRef FieldRef(int index) where T : class => new(Field(index)); public bool FieldIsSet(int index) { fixed (ecs_iter_t* ptr = &Value) return ecs_field_is_set(ptr, index); } public bool FieldIs(int index) where T : unmanaged { fixed (ecs_iter_t* ptr = &Value) { var id = ecs_field_id(ptr, index); var comp = Universe.Lookup(); return id == comp.Value.Data; } } public readonly ref struct SpanToRef { private readonly Span _span; internal SpanToRef(Span span) => _span = span; public int Length => _span.Length; public T this[int index] => (T)((GCHandle)_span[index]).Target!; } // IEnumerable implementation public IEnumerator GetEnumerator() { while (Next()) yield return this; } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } public enum IteratorType { Term, Filter, Query, Rule, }