Remove EntityBase

wip/no-type-lookup
copygirl 1 year ago
parent 60919ef1f6
commit 1d1ba4fe4d
  1. 37
      src/gaemstone.ECS/EntityBase.cs
  2. 36
      src/gaemstone.ECS/EntityBuilder.cs
  3. 64
      src/gaemstone.ECS/EntityRef.cs

@ -1,37 +0,0 @@
namespace gaemstone.ECS;
// TODO: Turn this into an interface?
public abstract class EntityBase<TReturn>
{
public abstract World World { get; }
public abstract TReturn Add(Id id);
public abstract TReturn Remove(Id id);
public abstract bool Has(Id id);
public TReturn Add(string symbol) => Add(World.LookupBySymbolOrThrow(symbol));
public TReturn Add(Entity relation, Entity target) => Add(Id.Pair(relation, target));
public TReturn Remove(string symbol) => Remove(World.LookupBySymbolOrThrow(symbol));
public TReturn Remove(Entity relation, Entity target) => Remove(Id.Pair(relation, target));
public bool Has(string symbol) => Has(World.LookupBySymbolOrThrow(symbol));
public bool Has(Entity relation, Entity target) => Has(Id.Pair(relation, target));
public abstract T? GetOrNull<T>(Id id) where T : unmanaged;
public abstract T? GetOrNull<T>(Id id, T _ = null!) where T : class;
public abstract T GetOrThrow<T>(Id id);
public abstract ref T GetMut<T>(Id id) where T : unmanaged;
public abstract ref T GetRefOrNull<T>(Id id) where T : unmanaged;
public abstract ref T GetRefOrThrow<T>(Id id) where T : unmanaged;
public abstract void Modified<T>(Id id);
public abstract TReturn Set<T>(Id id, in T value) where T : unmanaged;
public abstract TReturn Set<T>(Id id, T obj) where T : class;
public TReturn ChildOf(Entity parent) => Add(World.ChildOf, parent);
public TReturn Disable() => Add(World.Disabled);
public TReturn Enable() => Remove(World.Disabled);
public bool IsDisabled => Has(World.Disabled);
}

@ -6,9 +6,8 @@ using static flecs_hub.flecs;
namespace gaemstone.ECS;
public class EntityBuilder
: EntityBase<EntityBuilder>
{
public override World World { get; }
public World World { get; }
/// <summary> Set to modify existing entity (optional). </summary>
public Entity Id { get; set; }
@ -56,40 +55,29 @@ public class EntityBuilder
// If given path is absolute, the new entity won't be created as a
// child of the specified parent. Alternatively, EntityRef.NewChild
// can be used, which will throw when an absolute path is given.
if ((path?.IsRelative != false) && parent.IsSome) ChildOf(parent);
if ((path?.IsRelative != false) && parent.IsSome) Add(World.ChildOf, parent);
}
public override EntityBuilder Add(Id id)
public EntityBuilder Add(Id id)
{
// If adding a ChildOf relation, store the parent separately.
if (new IdRef(World, id).AsPair() is (EntityRef relation, EntityRef target) &&
(relation == World.ChildOf)) { _parent = target; return this; }
if (id.RelationUnsafe == World.ChildOf)
{ _parent = id.TargetUnsafe; return this; }
if (_toAdd.Count == 31) throw new NotSupportedException(
"Must not add more than 31 Ids at once with EntityBuilder");
_toAdd.Add(id);
return this;
}
public override EntityBuilder Remove(Id id)
=> throw new NotSupportedException();
public override bool Has(Id id)
=> !id.IsWildcard ? _toAdd.Contains(id)
: throw new NotSupportedException(); // TODO: Support wildcard.
public override T? GetOrNull<T>(Id id) => throw new NotSupportedException();
public override T? GetOrNull<T>(Id id, T _ = null!) where T : class => throw new NotSupportedException();
public override T GetOrThrow<T>(Id id) => throw new NotSupportedException();
public override ref T GetMut<T>(Id id) => throw new NotSupportedException();
public override ref T GetRefOrNull<T>(Id id) => throw new NotSupportedException();
public override ref T GetRefOrThrow<T>(Id id) => throw new NotSupportedException();
public override void Modified<T>(Id id) => throw new NotImplementedException();
public override EntityBuilder Set<T>(Id id, in T value)
public EntityBuilder Add(string symbol)
=> Add(World.LookupBySymbolOrThrow(symbol));
public EntityBuilder Add(Entity relation, Entity target)
=> Add(ECS.Id.Pair(relation, target));
public EntityBuilder Set<T>(Id id, in T value) where T : unmanaged
// "in" can't be used with lambdas, so we make a local copy.
{ var copy = value; _toSet.Add(e => e.Set(id, copy)); return this; }
public override EntityBuilder Set<T>(Id id, T obj)
public EntityBuilder Set<T>(Id id, T obj) where T : class
{ _toSet.Add(e => e.Set(id, obj)); return this; }
public unsafe EntityRef Build()

@ -8,10 +8,9 @@ using static flecs_hub.flecs;
namespace gaemstone.ECS;
public unsafe class EntityRef
: EntityBase<EntityRef>
, IEquatable<EntityRef>
: IEquatable<EntityRef>
{
public override World World { get; }
public World World { get; }
public Entity Entity { get; }
public uint Id => Entity.Id;
@ -74,25 +73,43 @@ public unsafe class EntityRef
yield return iter.Entity(i);
}
public EntityRef ChildOf(Entity parent)
=> Add(World.ChildOf, parent);
public override EntityRef Add(Id id) { ecs_add_id(World, this, id); return this; }
public override EntityRef Remove(Id id) { ecs_remove_id(World, this, id); return this; }
public override bool Has(Id id) => ecs_has_id(World, this, id);
public override T? GetOrNull<T>(Id id)
public bool IsDisabled => Has(World.Disabled);
public EntityRef Disable() => Add(World.Disabled);
public EntityRef Enable() => Remove(World.Disabled);
public EntityRef Add(Id id) { ecs_add_id(World, this, id); return this; }
public EntityRef Add(string symbol) => Add(World.LookupBySymbolOrThrow(symbol));
public EntityRef Add(Entity relation, Entity target) => Add(ECS.Id.Pair(relation, target));
public EntityRef Remove(Id id) { ecs_remove_id(World, this, id); return this; }
public EntityRef Remove(string symbol) => Remove(World.LookupBySymbolOrThrow(symbol));
public EntityRef Remove(Entity relation, Entity target) => Remove(ECS.Id.Pair(relation, target));
public bool Has(Id id) => ecs_has_id(World, this, id);
public bool Has(string symbol) => Has(World.LookupBySymbolOrThrow(symbol));
public bool Has(Entity relation, Entity target) => Has(ECS.Id.Pair(relation, target));
public T? GetOrNull<T>(Id id)
where T : unmanaged
{
var ptr = ecs_get_id(World, this, id);
return (ptr != null) ? Unsafe.Read<T>(ptr) : null;
}
public override T? GetOrNull<T>(Id id, T _ = null!)
public T? GetOrNull<T>(Id id, T _ = null!)
where T : class
{
var ptr = ecs_get_id(World, this, id);
return (T?)Unsafe.Read<ReferenceHandle>(ptr).Target;
}
public override T GetOrThrow<T>(Id id)
public T GetOrThrow<T>(Id id)
{
var ptr = ecs_get_id(World, this, id);
if (ptr == null) throw new Exception($"Component {typeof(T)} not found on {this}");
@ -100,7 +117,16 @@ public unsafe class EntityRef
else return (T)Unsafe.Read<ReferenceHandle>(ptr).Target!;
}
public override ref T GetRefOrNull<T>(Id id)
public ref T GetMut<T>(Id id)
where T : unmanaged
{
var ptr = ecs_get_mut_id(World, this, id);
// NOTE: Value is added if it doesn't exist on the entity.
return ref Unsafe.AsRef<T>(ptr);
}
public ref T GetRefOrNull<T>(Id id)
where T : unmanaged
{
var @ref = ecs_ref_init_id(World, this, id);
var ptr = ecs_ref_get_id(World, &@ref, id);
@ -108,7 +134,8 @@ public unsafe class EntityRef
: ref Unsafe.NullRef<T>();
}
public override ref T GetRefOrThrow<T>(Id id)
public ref T GetRefOrThrow<T>(Id id)
where T : unmanaged
{
ref var ptr = ref GetRefOrNull<T>(id);
if (Unsafe.IsNullRef(ref ptr)) throw new Exception(
@ -116,17 +143,12 @@ public unsafe class EntityRef
return ref ptr;
}
public override ref T GetMut<T>(Id id)
{
var ptr = ecs_get_mut_id(World, this, id);
// NOTE: Value is added if it doesn't exist on the entity.
return ref Unsafe.AsRef<T>(ptr);
}
public override void Modified<T>(Id id)
public void Modified<T>(Id id)
=> ecs_modified_id(World, this, id);
public override EntityRef Set<T>(Id id, in T value)
public EntityRef Set<T>(Id id, in T value)
where T : unmanaged
{
var size = (ulong)Unsafe.SizeOf<T>();
fixed (T* ptr = &value)
@ -135,7 +157,8 @@ public unsafe class EntityRef
return this;
}
public override EntityRef Set<T>(Id id, T obj) where T : class
public EntityRef Set<T>(Id id, T obj)
where T : class
{
if (obj == null) throw new ArgumentNullException(nameof(obj));
var size = (ulong)sizeof(ReferenceHandle);
@ -146,6 +169,7 @@ public unsafe class EntityRef
return this;
}
private EntityRef? GetTarget(Entity relation, int index)
=> CreateOrNull(World, new(ecs_get_target(World, this, relation, index)));
public IEnumerable<EntityRef> GetTargets(Entity relation)

Loading…
Cancel
Save