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.4 KiB
94 lines
2.4 KiB
2 years ago
|
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,
|
||
|
}
|