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.
 
 

93 lines
2.4 KiB

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<Iterator>
{
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<T> Field<T>(int index)
where T : unmanaged
{
fixed (ecs_iter_t* ptr = &Value) {
var size = (ulong)Unsafe.SizeOf<T>();
var pointer = ecs_field_w_size(ptr, size, index);
return new Span<T>(pointer, Count);
}
}
public SpanToRef<T> FieldRef<T>(int index)
where T : class => new(Field<nint>(index));
public bool FieldIsSet(int index)
{
fixed (ecs_iter_t* ptr = &Value)
return ecs_field_is_set(ptr, index);
}
public bool FieldIs<T>(int index)
where T : unmanaged
{
fixed (ecs_iter_t* ptr = &Value) {
var id = ecs_field_id(ptr, index);
var comp = Universe.Lookup<T>();
return id == comp.Value.Data;
}
}
public readonly ref struct SpanToRef<T>
{
private readonly Span<nint> _span;
internal SpanToRef(Span<nint> span) => _span = span;
public int Length => _span.Length;
public T this[int index] => (T)((GCHandle)_span[index]).Target!;
}
// IEnumerable implementation
public IEnumerator<Iterator> GetEnumerator() { while (Next()) yield return this; }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
public enum IteratorType
{
Term,
Filter,
Query,
Rule,
}