diff --git a/src/gaemstone/ECS/EntityBase.cs b/src/gaemstone/ECS/EntityBase.cs index 24253ef..3935e2d 100644 --- a/src/gaemstone/ECS/EntityBase.cs +++ b/src/gaemstone/ECS/EntityBase.cs @@ -11,6 +11,8 @@ public abstract class EntityBase public abstract bool Has(Identifier id); public abstract T Get(); + public abstract T? MaybeGet() where T : unmanaged; + public abstract T? MaybeGet(T _ = null!) where T : class; public abstract ref T GetRef() where T : unmanaged; public abstract void Modified(); diff --git a/src/gaemstone/ECS/EntityBuilder.cs b/src/gaemstone/ECS/EntityBuilder.cs index b04cd0a..bb1b715 100644 --- a/src/gaemstone/ECS/EntityBuilder.cs +++ b/src/gaemstone/ECS/EntityBuilder.cs @@ -68,6 +68,8 @@ public class EntityBuilder : throw new NotSupportedException(); // TODO: Support wildcard. public override T Get() => throw new NotSupportedException(); + public override T? MaybeGet() => throw new NotSupportedException(); + public override T? MaybeGet(T _ = null!) where T : class => throw new NotSupportedException(); public override ref T GetRef() => throw new NotSupportedException(); public override void Modified() => throw new NotImplementedException(); diff --git a/src/gaemstone/ECS/EntityRef.cs b/src/gaemstone/ECS/EntityRef.cs index 302298b..0da0650 100644 --- a/src/gaemstone/ECS/EntityRef.cs +++ b/src/gaemstone/ECS/EntityRef.cs @@ -19,14 +19,18 @@ public unsafe sealed class EntityRef public string? Name { get => ecs_get_name(Universe, this).FlecsToString()!; - set { using var alloc = TempAllocator.Use(); ecs_set_name(Universe, this, alloc.AllocateCString(value)); } + set { using var alloc = TempAllocator.Use(); + ecs_set_name(Universe, this, alloc.AllocateCString(value)); } } public string? Symbol { get => ecs_get_symbol(Universe, this).FlecsToString()!; - set { using var alloc = TempAllocator.Use(); ecs_set_symbol(Universe, this, alloc.AllocateCString(value)); } + set { using var alloc = TempAllocator.Use(); + ecs_set_symbol(Universe, this, alloc.AllocateCString(value)); } } - // TODO: public IEnumerable Children => ... + // public IEnumerable Children { get { + // + // } } public EntityRef(Universe universe, Entity entity, bool throwOnInvalid = true) { @@ -41,6 +45,11 @@ public unsafe sealed class EntityRef public EntityBuilder NewChild(EntityPath? path = null) => Universe.New(EnsureRelativePath(path)).ChildOf(this); + public EntityRef? Lookup(EntityPath path) + => Universe.Lookup(this, EnsureRelativePath(path)!); + public EntityRef LookupOrThrow(EntityPath path) + => Universe.LookupOrThrow(this, EnsureRelativePath(path)!); + private static EntityPath? EnsureRelativePath(EntityPath? path) { if (path?.IsAbsolute == true) throw new ArgumentException("path must not be absolute", nameof(path)); return path; } @@ -53,10 +62,25 @@ public unsafe sealed class EntityRef var comp = Universe.LookupOrThrow(); var ptr = ecs_get_id(Universe, this, comp); if (ptr == null) throw new Exception($"Component {typeof(T)} not found on {this}"); - return (typeof(T).IsValueType) ? Unsafe.Read(ptr) + return typeof(T).IsValueType ? Unsafe.Read(ptr) : (T)((GCHandle)Unsafe.Read(ptr)).Target!; } + public override T? MaybeGet() + { + var comp = Universe.LookupOrThrow(); + var ptr = ecs_get_id(Universe, this, comp); + return (ptr != null) ? Unsafe.Read(ptr) : null; + } + + public override T? MaybeGet(T _ = null!) + where T : class + { + var comp = Universe.LookupOrThrow(); + var ptr = ecs_get_id(Universe, this, comp); + return (ptr != null) ? (T)((GCHandle)Unsafe.Read(ptr)).Target! : null; + } + public override ref T GetRef() { var comp = Universe.LookupOrThrow();