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;
private readonly Span<ReferenceHandle> _span;
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;
}
}

@ -8,8 +8,11 @@ namespace gaemstone.ECS;
public static class ObserverExtensions
{
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;
using var alloc = TempAllocator.Use();
var desc = new ecs_observer_desc_t {
@ -19,7 +22,9 @@ public static class ObserverExtensions
binding_ctx_free = new() { Data = new() { Pointer = &FreeContext } },
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)));
}

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

@ -8,10 +8,9 @@ namespace gaemstone.ECS;
public static class SystemExtensions
{
public static unsafe EntityRef InitSystem(this EntityRef entity,
Entity phase, QueryDesc query, Action<Iterator> callback)
QueryDesc query, Action<Iterator> callback)
{
var world = entity.World;
entity.Add(world.DependsOn, phase);
using var alloc = TempAllocator.Use();
var desc = new ecs_system_desc_t {
entity = entity,
@ -31,25 +30,6 @@ public static class SystemExtensions
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]
private static unsafe void FreeContext(void* context)
=> CallbackContextHelper.Free((nint)context);

@ -10,8 +10,8 @@ public class Term
public TermId? Source { get; set; }
public TermId? Relation { get; set; }
public TermId? Target { get; set; }
public TermInOutKind InOut { get; set; }
public TermOperKind Oper { get; set; }
public TermInOutKind InOutKind { get; set; }
public TermOperKind OperKind { get; set; }
public IdFlags Flags { get; set; }
public Term() { }
@ -24,21 +24,22 @@ public class Term
public static implicit operator Term(IdRef id) => new(id);
public static implicit operator Term(Id id) => new(id);
public Term None { get { InOut = TermInOutKind.None; return this; } }
public Term In { get { InOut = TermInOutKind.In; return this; } }
public Term Out { get { InOut = TermInOutKind.Out; return this; } }
public Term None { get { InOutKind = TermInOutKind.None; return this; } }
public Term In { get { InOutKind = TermInOutKind.In; 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 Not { get { Oper = TermOperKind.Not; return this; } }
public Term Optional { get { Oper = TermOperKind.Optional; return this; } }
public Term Or { get { OperKind = TermOperKind.Or; return this; } }
public Term Not { get { OperKind = TermOperKind.Not; return this; } }
public Term Optional { get { OperKind = TermOperKind.Optional; return this; } }
public ecs_term_t ToFlecs(IAllocator allocator) => new() {
id = Id,
src = Source?.ToFlecs(allocator) ?? default,
first = Relation?.ToFlecs(allocator) ?? default,
second = Target?.ToFlecs(allocator) ?? default,
inout = (ecs_inout_kind_t)InOut,
oper = (ecs_oper_kind_t)Oper,
inout = (ecs_inout_kind_t)InOutKind,
oper = (ecs_oper_kind_t)OperKind,
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)
where T : struct => GetOrNull((ReadOnlySpan<T>)span, 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)

Loading…
Cancel
Save