Compare commits

...

6 Commits

  1. 2
      src/flecs-cs
  2. 17
      src/gaemstone.ECS/Entity.cs
  3. 3
      src/gaemstone.ECS/EntityPath.cs
  4. 2
      src/gaemstone.ECS/Id.cs
  5. 2
      src/gaemstone.ECS/Internal/FlecsBuiltIn.cs
  6. 10
      src/gaemstone.ECS/Iterator.cs
  7. 12
      src/gaemstone.ECS/Observer.cs
  8. 2
      src/gaemstone.ECS/System.cs
  9. 22
      src/gaemstone.ECS/Term.cs

@ -1 +1 @@
Subproject commit a2047983917aa462a8c2f34d5315aea48502f4d8
Subproject commit fcce5620d21fcd14c79d73a4406db8ce85f53dad

@ -19,7 +19,7 @@ public unsafe readonly partial struct Entity<TContext>
public bool IsSome => Value.IsSome;
public bool IsValid => EntityAccess.IsValid(World, this);
public bool IsAlive => EntityAccess.IsAlive(World, this);
public bool IsAlive => IsSome && EntityAccess.IsAlive(World, this);
public string? Name { get => EntityAccess.GetName(World, this); set => EntityAccess.SetName(World, this, value); }
public string? Symbol { get => EntityAccess.GetSymbol(World, this); set => EntityAccess.SetSymbol(World, this, value); }
@ -39,9 +39,17 @@ public unsafe readonly partial struct Entity<TContext>
public static Entity<TContext> GetOrInvalid(World<TContext> world, Entity value)
=> new(world, value);
public static Entity<TContext>? GetOrNull(World<TContext> world, Entity value)
=> ecs_is_valid(world, value) ? new(world, value) : null;
=> new Entity<TContext>(world, value).ValidOrNull();
public static Entity<TContext> GetOrThrow(World<TContext> world, Entity value)
=> ecs_is_valid(world, value) ? new(world, value) : throw new InvalidOperationException($"The entity {value} is not valid");
=> new Entity<TContext>(world, value).ValidOrThrow();
public Entity<TContext>? ValidOrNull() => IsValid ? this : null;
public Entity<TContext> ValidOrThrow() => IsValid ? this
: throw new InvalidOperationException($"The entity {this} is not valid");
public Entity<TContext>? AliveOrNull() => IsAlive ? this : null;
public Entity<TContext> AliveOrThrow() => IsAlive ? this
: throw new InvalidOperationException($"The entity {this} is not alive");
public void Delete()
=> ecs_delete(World, this);
@ -50,7 +58,8 @@ public unsafe readonly partial struct Entity<TContext>
public Entity<TContext> CreateLookup<T>()
{
ref var lookup = ref Lookup<TContext>.Entity<T>.Value;
if (lookup.IsSome) throw new InvalidOperationException(
if (lookup == this) { /* Don't throw if lookup already has the same entity set. */ }
else if (lookup.IsSome) throw new InvalidOperationException(
$"The lookup for type {typeof(T)} in context {typeof(TContext)} is already in use by {lookup}");
lookup = this;
return this;

@ -52,6 +52,9 @@ public class EntityPath
public static unsafe EntityPath From(World world, Entity entity)
{
if (entity.IsNone) throw new ArgumentException(
"entity is Entity.None", nameof(entity));
var parts = new List<byte[]>(32);
do {

@ -15,7 +15,7 @@ public unsafe struct Id<TContext>
public bool IsWildcard => Value.IsWildcard;
public bool IsValid => ecs_id_is_valid(World, this);
public bool IsTag => ecs_id_is_tag(World, this).Data != default;
public bool IsTag => ecs_id_is_tag(World, this);
public bool IsInUse => ecs_id_in_use(World, this);
public int Count => ecs_count_id(World, this);

@ -7,5 +7,5 @@ public static class FlecsBuiltIn
public static Entity ChildOf { get; } = new(pinvoke_EcsChildOf());
// FIXME: Hopefully flecs-cs will expose this one day.
public static Entity Disabled { get; } = new(new() { Data = ECS_HI_COMPONENT_ID + 7 });
public static Entity Disabled { get; } = new(new() { Data = FLECS_HI_COMPONENT_ID + 7 });
}

@ -50,8 +50,8 @@ public enum IteratorFlags : uint
{
/// <summary> Does iterator contain valid result. </summary>
IsValid = EcsIterIsValid,
/// <summary> Is iterator filter (metadata only). </summary>
IsFilter = EcsIterIsFilter,
/// <summary> Does iterator provide (component). </summary>
NoData = EcsIterNoData,
/// <summary> Is iterator instanced. </summary>
IsInstanced = EcsIterIsInstanced,
/// <summary> Does result have shared terms. </summary>
@ -64,8 +64,12 @@ public enum IteratorFlags : uint
NoResults = EcsIterNoResults,
/// <summary> Only evaluate non-this terms. </summary>
IgnoreThis = EcsIterIgnoreThis,
/// <summary> Does iterator have conditionally set fields. </summary>
MatchVar = EcsIterMatchVar,
/// <summary> </summary>
HasCondSet = EcsIterHasCondSet,
/// <summary> Profile iterator performance. </summary>
Profile = EcsIterProfile,
}
public class Variable

@ -1,6 +1,5 @@
using System;
using System.Runtime.InteropServices;
using gaemstone.ECS.Internal;
using gaemstone.ECS.Utility;
using static flecs_hub.flecs;
@ -15,11 +14,12 @@ public static class ObserverExtensions
if (events.Length > 8) throw new ArgumentException("Must specify at most 8 events", nameof(events));
var world = entity.World;
var internalCallback = (nint iterPtr) => callback(new((ecs_iter_t*)iterPtr));
using var alloc = TempAllocator.Use();
var desc = new ecs_observer_desc_t {
entity = entity,
filter = filter.ToFlecs(alloc),
binding_ctx = (void*)CallbackContextHelper.Create((world, callback)),
binding_ctx = (void*)CallbackContextHelper.Create(internalCallback),
binding_ctx_free = new() { Data = new() { Pointer = &FreeContext } },
callback = new() { Data = new() { Pointer = &Callback } },
};
@ -33,11 +33,9 @@ public static class ObserverExtensions
[UnmanagedCallersOnly]
private static unsafe void Callback(ecs_iter_t* iter)
{
var (world, callback) = CallbackContextHelper
.Get<(World, Action<Iterator>)>((nint)iter->binding_ctx);
callback(new Iterator(iter));
}
=> CallbackContextHelper
.Get<Action<nint>>((nint)iter->binding_ctx)
.Invoke((nint)iter);
[UnmanagedCallersOnly]
private static unsafe void FreeContext(void* context)

@ -12,7 +12,7 @@ public static class SystemExtensions
{
var world = entity.World;
var internalCallback = (nint iter) =>
callback(new Iterator<TContext>((ecs_iter_t*)iter));
callback(new((ecs_iter_t*)iter));
using var alloc = TempAllocator.Use();
var desc = new ecs_system_desc_t {
entity = entity,

@ -90,19 +90,23 @@ public class TermId
public enum TermTraversalFlags : uint
{
/// <summary> Match on self. </summary>
Self = EcsSelf,
Self = EcsSelf,
/// <summary> Match by traversing upwards. </summary>
Up = EcsUp,
Up = EcsUp,
/// <summary> Match by traversing downwards (derived, cannot be set). </summary>
Down = EcsDown,
Down = EcsDown,
/// <summary> Match all entities encountered through traversal. </summary>
TraverseAll = EcsTraverseAll,
/// <summary> Sort results breadth first. </summary>
Cascade = EcsCascade,
Cascade = EcsCascade,
/// <summary> Short for up(ChildOf). </summary>
Parent = EcsParent,
Parent = EcsParent,
/// <summary> Term id is a variable. </summary>
IsVariable = EcsIsVariable,
IsVariable = EcsIsVariable,
/// <summary> Term id is an entity. </summary>
IsEntity = EcsIsEntity,
/// <summary> Prevent observer from triggering on term. </summary>
Filter = EcsFilter,
IsEntity = EcsIsEntity,
/// <summary> Term id is a name (don't attempt to lookup as entity). </summary>
IsName = EcsIsName,
/// <summary> revent observer from triggering on term. </summary>
Filter = EcsFilter,
}

Loading…
Cancel
Save