using System; using gaemstone.ECS.Utility; using static flecs_hub.flecs; namespace gaemstone.ECS; public class Term { public Id Id { get; set; } public TermId? Source { get; set; } public TermId? Relation { get; set; } public TermId? Target { get; set; } public TermInOutKind InOutKind { get; set; } public TermOperKind OperKind { get; set; } public IdFlags Flags { get; set; } public Term() { } public Term(Id id) => Id = id; public Term(TermId relation, TermId target) { Relation = relation; Target = target; } public Term None { get { InOutKind = TermInOutKind.None; return this; } } public Term In { get { InOutKind = TermInOutKind.In; return this; } } public Term Out { get { InOutKind = TermInOutKind.Out; return this; } } public Term InOut { get { InOutKind = TermInOutKind.InOut; return this; } } public Term Or { get { OperKind = TermOperKind.Or; return this; } } public Term Not { get { OperKind = TermOperKind.Not; return this; } } public Term Optional { get { OperKind = TermOperKind.Optional; return this; } } public ecs_term_t ToFlecs(IAllocator allocator) => new() { id = Id, src = Source ?.ToFlecs(allocator) ?? default, first = Relation?.ToFlecs(allocator) ?? default, second = Target ?.ToFlecs(allocator) ?? default, inout = (ecs_inout_kind_t)InOutKind, oper = (ecs_oper_kind_t)OperKind, id_flags = (ecs_id_t)(ulong)Flags, }; } public enum TermInOutKind { Default = ecs_inout_kind_t.EcsInOutDefault, None = ecs_inout_kind_t.EcsInOutNone, InOut = ecs_inout_kind_t.EcsInOut, In = ecs_inout_kind_t.EcsIn, Out = ecs_inout_kind_t.EcsOut, } public enum TermOperKind { And = ecs_oper_kind_t.EcsAnd, Or = ecs_oper_kind_t.EcsOr, Not = ecs_oper_kind_t.EcsNot, Optional = ecs_oper_kind_t.EcsOptional, AndFrom = ecs_oper_kind_t.EcsAndFrom, OrFrom = ecs_oper_kind_t.EcsOrFrom, NotFrom = ecs_oper_kind_t.EcsNotFrom, } public class TermId { public static TermId This { get; } = new("$this"); public Entity Id { get; } public string? Name { get; } public Entity Traverse { get; set; } public TermTraversalFlags Flags { get; set; } public TermId(Entity id) => Id = id; public TermId(string name) { if (name[0] == '$') { Name = name[1..]; Flags = TermTraversalFlags.IsVariable; } else Name = name; } public ecs_term_id_t ToFlecs(IAllocator allocator) => new() { id = Id, _name = allocator.AllocateCString(Name), trav = Traverse, flags = (ecs_flags32_t)(uint)Flags }; } [Flags] public enum TermTraversalFlags : uint { /// Match on self. Self = EcsSelf, /// Match by traversing upwards. Up = EcsUp, /// Match by traversing downwards (derived, cannot be set). Down = EcsDown, /// Match all entities encountered through traversal. TraverseAll = EcsTraverseAll, /// Sort results breadth first. Cascade = EcsCascade, /// Short for up(ChildOf). Parent = EcsParent, /// Term id is a variable. IsVariable = EcsIsVariable, /// Term id is an entity. IsEntity = EcsIsEntity, /// Term id is a name (don't attempt to lookup as entity). IsName = EcsIsName, /// revent observer from triggering on term. Filter = EcsFilter, }