diff --git a/src/gaemstone.ECS/Component.cs b/src/gaemstone.ECS/Component.cs index cf08117..b614a6e 100644 --- a/src/gaemstone.ECS/Component.cs +++ b/src/gaemstone.ECS/Component.cs @@ -49,10 +49,8 @@ public unsafe readonly struct ReferenceHandle private readonly nint _value; - public object? Target => - (_value != default) - ? ((GCHandle)_value).Target - : null; + public object? Target => (_value != default) + ? ((GCHandle)_value).Target : null; private ReferenceHandle(nint value) => _value = value; diff --git a/src/gaemstone.ECS/Entity.cs b/src/gaemstone.ECS/Entity.cs index 3a1728d..5493c20 100644 --- a/src/gaemstone.ECS/Entity.cs +++ b/src/gaemstone.ECS/Entity.cs @@ -20,8 +20,8 @@ public readonly struct Entity public override bool Equals(object? obj) => (obj is Entity other) && Equals(other); public override int GetHashCode() => Value.Data.GetHashCode(); public override string? ToString() - => IsSome ? $"Entity(0x{Value.Data.Data:X})" - : "Entity.None"; + => IsSome ? $"Entity({Value.Data.Data})" + : "Entity.None"; public static bool operator ==(Entity left, Entity right) => left.Equals(right); public static bool operator !=(Entity left, Entity right) => !left.Equals(right); diff --git a/src/gaemstone.ECS/EntityBase.cs b/src/gaemstone.ECS/EntityBase.cs index a710c6a..8b0d85a 100644 --- a/src/gaemstone.ECS/EntityBase.cs +++ b/src/gaemstone.ECS/EntityBase.cs @@ -1,5 +1,6 @@ namespace gaemstone.ECS; +// TODO: Turn this into an interface? public abstract class EntityBase { public abstract World World { get; } diff --git a/src/gaemstone.ECS/EntityBuilder.cs b/src/gaemstone.ECS/EntityBuilder.cs index 5890379..8a4734b 100644 --- a/src/gaemstone.ECS/EntityBuilder.cs +++ b/src/gaemstone.ECS/EntityBuilder.cs @@ -38,6 +38,7 @@ public class EntityBuilder /// Ids to add to the new or existing entity. private readonly HashSet _toAdd = new(); + // (ChildOf, *) is handled explicitly, it won't be added to _toAdd. private Entity _parent = Entity.None; /// String expression with components to add. @@ -52,7 +53,7 @@ public class EntityBuilder public override EntityBuilder Add(Id id) { // If adding a ChildOf relation, store the parent separately. - if (id.AsPair(World) is (EntityRef relation, EntityRef target) && + if (new IdRef(World, id).AsPair() is (EntityRef relation, EntityRef target) && (relation == World.ChildOf)) { _parent = target; return this; } if (_toAdd.Count == 31) throw new NotSupportedException( diff --git a/src/gaemstone.ECS/EntityRef.cs b/src/gaemstone.ECS/EntityRef.cs index 9dc0e48..6a52a75 100644 --- a/src/gaemstone.ECS/EntityRef.cs +++ b/src/gaemstone.ECS/EntityRef.cs @@ -58,13 +58,15 @@ public unsafe class EntityRef private static EntityPath? EnsureRelativePath(EntityPath? path) { if (path?.IsAbsolute == true) throw new ArgumentException( - $"Path '{path}' must not be absolute", nameof(path)); return path; + $"Path '{path}' must not be absolute", nameof(path)); + return path; } public EntityRef? Parent => GetTargets(World.ChildOf).FirstOrDefault(); + // TODO: Change to property after all? public IEnumerable GetChildren() { foreach (var iter in Iterator.FromTerm(World, new(World.ChildOf, this))) diff --git a/src/gaemstone.ECS/Id.cs b/src/gaemstone.ECS/Id.cs index a3e08d1..a5bce10 100644 --- a/src/gaemstone.ECS/Id.cs +++ b/src/gaemstone.ECS/Id.cs @@ -7,12 +7,11 @@ public readonly struct Id : IEquatable { public readonly ecs_id_t Value; + public IdFlags Flags => (IdFlags)(Value & ECS_ID_FLAGS_MASK); public bool IsPair => ecs_id_is_pair(this); public bool IsWildcard => ecs_id_is_wildcard(this); - public IdFlags Flags => (IdFlags)(Value & ECS_ID_FLAGS_MASK); - public Entity RelationUnsafe => new(new() { Data = (Value & ECS_COMPONENT_MASK) >> 32 }); public Entity TargetUnsafe => new(new() { Data = Value & ECS_ENTITY_MASK }); @@ -26,17 +25,12 @@ public readonly struct Id ((relation.Value.Data << 32) & ECS_COMPONENT_MASK) | ( target.Value.Data & ECS_ENTITY_MASK ))); - public EntityRef? AsEntity(World world) - => new IdRef(world, this).AsEntity(); - public (EntityRef Relation, EntityRef Target)? AsPair(World world) - => new IdRef(world, this).AsPair(); - public bool Equals(Id other) => Value.Data == other.Value.Data; public override bool Equals(object? obj) => (obj is Id other) && Equals(other); public override int GetHashCode() => Value.Data.GetHashCode(); public override string? ToString() - => (Flags != default) ? $"Identifier(0x{Value.Data:X}, Flags={Flags})" - : $"Identifier(0x{Value.Data:X})"; + => (Flags != default) ? $"Id({Value.Data}, Flags={Flags})" + : $"Id({Value.Data})"; public static bool operator ==(Id left, Id right) => left.Equals(right); public static bool operator !=(Id left, Id right) => !left.Equals(right); diff --git a/src/gaemstone.ECS/IdRef.cs b/src/gaemstone.ECS/IdRef.cs index 1099c49..3e2fa82 100644 --- a/src/gaemstone.ECS/IdRef.cs +++ b/src/gaemstone.ECS/IdRef.cs @@ -9,12 +9,12 @@ public unsafe class IdRef { public World World { get; } public Id Id { get; } + public IdFlags Flags => Id.Flags; - public IdFlags Flags => Id.Flags; public bool IsPair => Id.IsPair; public bool IsWildcard => Id.IsWildcard; - public bool IsValid => ecs_id_is_valid(World, this); + public bool IsValid => ecs_id_is_valid(World, this); public bool IsInUse => ecs_id_in_use(World, this); public int Count => ecs_count_id(World, this); @@ -26,10 +26,10 @@ public unsafe class IdRef public static IdRef Pair(World world, Entity relation, Entity target) => new(world, Id.Pair(relation, target)); - public static IdRef Pair(Entity relation, EntityRef target) - => Pair(target.World, relation, target); public static IdRef Pair(EntityRef relation, Entity target) => Pair(relation.World, relation, target); + public static IdRef Pair(Entity relation, EntityRef target) + => Pair(target.World, relation, target); public static IdRef Pair(EntityRef relation, EntityRef target) => Pair(relation.World, relation, target); diff --git a/src/gaemstone.ECS/World+Lookup.cs b/src/gaemstone.ECS/World+Lookup.cs index 088bdb5..ec613d6 100644 --- a/src/gaemstone.ECS/World+Lookup.cs +++ b/src/gaemstone.ECS/World+Lookup.cs @@ -36,6 +36,7 @@ public unsafe partial class World => LookupAlive(entity) ?? throw new EntityNotFoundException( $"Entity {entity} is not alive"); + // TODO: Simplify method names? public EntityRef? LookupByPath(EntityPath path) => LookupByPath(default, path); public EntityRef? LookupByPath(Entity parent, EntityPath path) @@ -45,6 +46,7 @@ public unsafe partial class World public EntityRef LookupByPathOrThrow(Entity parent, EntityPath path) => new(this, EntityPath.Lookup(this, parent, path, true)); + // TODO: Provide overload that uses a UTF-8 byte span? public EntityRef? LookupBySymbol(string symbol) { using var alloc = TempAllocator.Use(); diff --git a/src/gaemstone.ECS/World.cs b/src/gaemstone.ECS/World.cs index c52d731..6d59115 100644 --- a/src/gaemstone.ECS/World.cs +++ b/src/gaemstone.ECS/World.cs @@ -11,7 +11,6 @@ public unsafe partial class World // Flecs built-ins that are important to internals. internal EntityRef ChildOf { get; } internal EntityRef Disabled { get; } - internal EntityRef DependsOn { get; } public bool IsDeferred => ecs_is_deferred(this); public bool IsQuitRequested => ecs_should_quit(this); @@ -25,9 +24,8 @@ public unsafe partial class World Handle = ecs_init_w_args(args.Length, null); - ChildOf = LookupByPathOrThrow("/flecs/core/ChildOf"); - Disabled = LookupByPathOrThrow("/flecs/core/Disabled"); - DependsOn = LookupByPathOrThrow("/flecs/core/DependsOn"); + ChildOf = LookupByPathOrThrow("/flecs/core/ChildOf"); + Disabled = LookupByPathOrThrow("/flecs/core/Disabled"); } public void Dispose()