From 1d1ba4fe4d13d1dc7ccde809d5ef111565ee3f12 Mon Sep 17 00:00:00 2001 From: copygirl Date: Sat, 21 Jan 2023 11:07:59 +0100 Subject: [PATCH] Remove EntityBase --- src/gaemstone.ECS/EntityBase.cs | 37 ----------------- src/gaemstone.ECS/EntityBuilder.cs | 36 ++++++----------- src/gaemstone.ECS/EntityRef.cs | 64 ++++++++++++++++++++---------- 3 files changed, 56 insertions(+), 81 deletions(-) delete mode 100644 src/gaemstone.ECS/EntityBase.cs diff --git a/src/gaemstone.ECS/EntityBase.cs b/src/gaemstone.ECS/EntityBase.cs deleted file mode 100644 index 36cc2ca..0000000 --- a/src/gaemstone.ECS/EntityBase.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace gaemstone.ECS; - -// TODO: Turn this into an interface? -public abstract class EntityBase -{ - 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(Id id) where T : unmanaged; - public abstract T? GetOrNull(Id id, T _ = null!) where T : class; - public abstract T GetOrThrow(Id id); - public abstract ref T GetMut(Id id) where T : unmanaged; - public abstract ref T GetRefOrNull(Id id) where T : unmanaged; - public abstract ref T GetRefOrThrow(Id id) where T : unmanaged; - public abstract void Modified(Id id); - - public abstract TReturn Set(Id id, in T value) where T : unmanaged; - public abstract TReturn Set(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); -} diff --git a/src/gaemstone.ECS/EntityBuilder.cs b/src/gaemstone.ECS/EntityBuilder.cs index fdbd542..3361091 100644 --- a/src/gaemstone.ECS/EntityBuilder.cs +++ b/src/gaemstone.ECS/EntityBuilder.cs @@ -6,9 +6,8 @@ using static flecs_hub.flecs; namespace gaemstone.ECS; public class EntityBuilder - : EntityBase { - public override World World { get; } + public World World { get; } /// Set to modify existing entity (optional). 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(Id id) => throw new NotSupportedException(); - public override T? GetOrNull(Id id, T _ = null!) where T : class => throw new NotSupportedException(); - public override T GetOrThrow(Id id) => throw new NotSupportedException(); - public override ref T GetMut(Id id) => throw new NotSupportedException(); - public override ref T GetRefOrNull(Id id) => throw new NotSupportedException(); - public override ref T GetRefOrThrow(Id id) => throw new NotSupportedException(); - public override void Modified(Id id) => throw new NotImplementedException(); - - public override EntityBuilder Set(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(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(Id id, T obj) + public EntityBuilder Set(Id id, T obj) where T : class { _toSet.Add(e => e.Set(id, obj)); return this; } public unsafe EntityRef Build() diff --git a/src/gaemstone.ECS/EntityRef.cs b/src/gaemstone.ECS/EntityRef.cs index d7fb53b..27e9421 100644 --- a/src/gaemstone.ECS/EntityRef.cs +++ b/src/gaemstone.ECS/EntityRef.cs @@ -8,10 +8,9 @@ using static flecs_hub.flecs; namespace gaemstone.ECS; public unsafe class EntityRef - : EntityBase - , IEquatable + : IEquatable { - 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(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(Id id) + where T : unmanaged { var ptr = ecs_get_id(World, this, id); return (ptr != null) ? Unsafe.Read(ptr) : null; } - public override T? GetOrNull(Id id, T _ = null!) + public T? GetOrNull(Id id, T _ = null!) where T : class { var ptr = ecs_get_id(World, this, id); return (T?)Unsafe.Read(ptr).Target; } - public override T GetOrThrow(Id id) + public T GetOrThrow(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(ptr).Target!; } - public override ref T GetRefOrNull(Id id) + public ref T GetMut(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(ptr); + } + + public ref T GetRefOrNull(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(); } - public override ref T GetRefOrThrow(Id id) + public ref T GetRefOrThrow(Id id) + where T : unmanaged { ref var ptr = ref GetRefOrNull(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(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(ptr); - } - public override void Modified(Id id) + public void Modified(Id id) => ecs_modified_id(World, this, id); - public override EntityRef Set(Id id, in T value) + public EntityRef Set(Id id, in T value) + where T : unmanaged { var size = (ulong)Unsafe.SizeOf(); fixed (T* ptr = &value) @@ -135,7 +157,8 @@ public unsafe class EntityRef return this; } - public override EntityRef Set(Id id, T obj) where T : class + public EntityRef Set(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 GetTargets(Entity relation)