Compare commits

...

5 Commits

  1. 3
      src/gaemstone.ECS/Iterator.cs
  2. 9
      src/gaemstone.ECS/Observer.cs
  3. 2
      src/gaemstone.ECS/Query.cs
  4. 22
      src/gaemstone.ECS/System.cs
  5. 21
      src/gaemstone.ECS/Term.cs
  6. 2
      src/gaemstone.Utility/SpanExtensions.cs

@ -144,7 +144,8 @@ public unsafe class Iterator
public static SpanToRef<T> Empty => default; public static SpanToRef<T> Empty => default;
private readonly Span<ReferenceHandle> _span; private readonly Span<ReferenceHandle> _span;
public int Length => _span.Length; public int Length => _span.Length;
public T? this[int index] => (T?)_span[index].Target; public T this[int index] => (T)_span[index].Target!;
public T? GetOrNull(int index) => ((index >= 0) && (index < Length)) ? this[index] : null;
internal SpanToRef(Span<ReferenceHandle> span) => _span = span; internal SpanToRef(Span<ReferenceHandle> span) => _span = span;
} }
} }

@ -8,8 +8,11 @@ namespace gaemstone.ECS;
public static class ObserverExtensions public static class ObserverExtensions
{ {
public static unsafe EntityRef InitObserver(this EntityRef entity, public static unsafe EntityRef InitObserver(this EntityRef entity,
Entity @event, FilterDesc filter, Action<Iterator> callback) FilterDesc filter, Action<Iterator> callback, params Entity[] events)
{ {
if (events.Length == 0) throw new ArgumentException("Must specify at least 1 event", nameof(events));
if (events.Length > 8) throw new ArgumentException("Must specify at most 8 events", nameof(events));
var world = entity.World; var world = entity.World;
using var alloc = TempAllocator.Use(); using var alloc = TempAllocator.Use();
var desc = new ecs_observer_desc_t { var desc = new ecs_observer_desc_t {
@ -19,7 +22,9 @@ public static class ObserverExtensions
binding_ctx_free = new() { Data = new() { Pointer = &FreeContext } }, binding_ctx_free = new() { Data = new() { Pointer = &FreeContext } },
callback = new() { Data = new() { Pointer = &Callback } }, callback = new() { Data = new() { Pointer = &Callback } },
}; };
desc.events[0] = @event; var span = desc.events;
for (var i = 0; i < events.Length; i++)
span[i] = events[i];
return new(world, new(ecs_observer_init(world, &desc))); return new(world, new(ecs_observer_init(world, &desc)));
} }

@ -36,8 +36,8 @@ public unsafe class Query
public class QueryDesc : FilterDesc public class QueryDesc : FilterDesc
{ {
public QueryDesc(string expression) : base(expression) { }
public QueryDesc(params Term[] terms) : base(terms) { } public QueryDesc(params Term[] terms) : base(terms) { }
public QueryDesc(string expression) : base(expression) { }
public new unsafe ecs_query_desc_t ToFlecs(IAllocator allocator) public new unsafe ecs_query_desc_t ToFlecs(IAllocator allocator)
{ {

@ -8,10 +8,9 @@ namespace gaemstone.ECS;
public static class SystemExtensions public static class SystemExtensions
{ {
public static unsafe EntityRef InitSystem(this EntityRef entity, public static unsafe EntityRef InitSystem(this EntityRef entity,
Entity phase, QueryDesc query, Action<Iterator> callback) QueryDesc query, Action<Iterator> callback)
{ {
var world = entity.World; var world = entity.World;
entity.Add(world.DependsOn, phase);
using var alloc = TempAllocator.Use(); using var alloc = TempAllocator.Use();
var desc = new ecs_system_desc_t { var desc = new ecs_system_desc_t {
entity = entity, entity = entity,
@ -31,25 +30,6 @@ public static class SystemExtensions
callback(new Iterator(world, null, *iter)); callback(new Iterator(world, null, *iter));
} }
// [UnmanagedCallersOnly]
// private static unsafe void Run(ecs_iter_t* flecsIter)
// {
// var (world, callback) = CallbackContextHelper
// .Get<(World, Action<Iterator>)>((nint)flecsIter->binding_ctx);
// // This is what flecs does, so I guess we'll do it too!
// var type = (&flecsIter->next == (delegate*<ecs_iter_t*, Runtime.CBool>)&ecs_query_next)
// ? IteratorType.Query : (IteratorType?)null;
// using var iter = new Iterator(world, type, *flecsIter);
// If the method is marked with [Source], set the $This variable.
// if (Method.Get<SourceAttribute>()?.Type is Type sourceType)
// iter.SetThis(World.LookupOrThrow(sourceType));
// if (flecsIter->field_count == 0) callback(iter);
// else while (iter.Next()) callback(iter);
// }
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
private static unsafe void FreeContext(void* context) private static unsafe void FreeContext(void* context)
=> CallbackContextHelper.Free((nint)context); => CallbackContextHelper.Free((nint)context);

@ -10,8 +10,8 @@ public class Term
public TermId? Source { get; set; } public TermId? Source { get; set; }
public TermId? Relation { get; set; } public TermId? Relation { get; set; }
public TermId? Target { get; set; } public TermId? Target { get; set; }
public TermInOutKind InOut { get; set; } public TermInOutKind InOutKind { get; set; }
public TermOperKind Oper { get; set; } public TermOperKind OperKind { get; set; }
public IdFlags Flags { get; set; } public IdFlags Flags { get; set; }
public Term() { } public Term() { }
@ -24,21 +24,22 @@ public class Term
public static implicit operator Term(IdRef id) => new(id); public static implicit operator Term(IdRef id) => new(id);
public static implicit operator Term(Id id) => new(id); public static implicit operator Term(Id id) => new(id);
public Term None { get { InOut = TermInOutKind.None; return this; } } public Term None { get { InOutKind = TermInOutKind.None; return this; } }
public Term In { get { InOut = TermInOutKind.In; return this; } } public Term In { get { InOutKind = TermInOutKind.In; return this; } }
public Term Out { get { InOut = TermInOutKind.Out; return this; } } public Term Out { get { InOutKind = TermInOutKind.Out; return this; } }
public Term InOut { get { InOutKind = TermInOutKind.InOut; return this; } }
public Term Or { get { Oper = TermOperKind.Or; return this; } } public Term Or { get { OperKind = TermOperKind.Or; return this; } }
public Term Not { get { Oper = TermOperKind.Not; return this; } } public Term Not { get { OperKind = TermOperKind.Not; return this; } }
public Term Optional { get { Oper = TermOperKind.Optional; return this; } } public Term Optional { get { OperKind = TermOperKind.Optional; return this; } }
public ecs_term_t ToFlecs(IAllocator allocator) => new() { public ecs_term_t ToFlecs(IAllocator allocator) => new() {
id = Id, id = Id,
src = Source?.ToFlecs(allocator) ?? default, src = Source?.ToFlecs(allocator) ?? default,
first = Relation?.ToFlecs(allocator) ?? default, first = Relation?.ToFlecs(allocator) ?? default,
second = Target?.ToFlecs(allocator) ?? default, second = Target?.ToFlecs(allocator) ?? default,
inout = (ecs_inout_kind_t)InOut, inout = (ecs_inout_kind_t)InOutKind,
oper = (ecs_oper_kind_t)Oper, oper = (ecs_oper_kind_t)OperKind,
id_flags = (ecs_id_t)(ulong)Flags, id_flags = (ecs_id_t)(ulong)Flags,
}; };
} }

@ -7,7 +7,7 @@ public static class SpanExtensions
public static T? GetOrNull<T>(this Span<T> span, int index) public static T? GetOrNull<T>(this Span<T> span, int index)
where T : struct => GetOrNull((ReadOnlySpan<T>)span, index); where T : struct => GetOrNull((ReadOnlySpan<T>)span, index);
public static T? GetOrNull<T>(this ReadOnlySpan<T> span, int index) public static T? GetOrNull<T>(this ReadOnlySpan<T> span, int index)
where T : struct => (index >= 0 && index < span.Length) ? span[index] : null; where T : struct => ((index >= 0) && (index < span.Length)) ? span[index] : null;
public static ReadOnlySpanSplitEnumerator<T> Split<T>(this ReadOnlySpan<T> span, T splitOn) public static ReadOnlySpanSplitEnumerator<T> Split<T>(this ReadOnlySpan<T> span, T splitOn)

Loading…
Cancel
Save