|
|
|
using System;
|
|
|
|
using gaemstone.ECS.Utility;
|
|
|
|
using static flecs_hub.flecs;
|
|
|
|
|
|
|
|
namespace gaemstone.ECS;
|
|
|
|
|
|
|
|
public unsafe struct Id<TContext>
|
|
|
|
: IEquatable<Id<TContext>>
|
|
|
|
{
|
|
|
|
public readonly World<TContext> World;
|
|
|
|
public readonly Id Value;
|
|
|
|
|
|
|
|
public IdFlags Flags => Value.Flags;
|
|
|
|
public bool IsPair => Value.IsPair;
|
|
|
|
public bool IsWildcard => Value.IsWildcard;
|
|
|
|
|
|
|
|
public bool IsValid => ecs_id_is_valid(World, this);
|
|
|
|
public bool IsTag => ecs_id_is_tag(World, this);
|
|
|
|
public bool IsInUse => ecs_id_in_use(World, this);
|
|
|
|
public int Count => ecs_count_id(World, this);
|
|
|
|
|
|
|
|
private Id(World<TContext> world, Id id)
|
|
|
|
{ World = world; Value = id; }
|
|
|
|
|
|
|
|
public static Id<TContext> GetUnsafe(World<TContext> world, Id value)
|
|
|
|
=> new(world, value);
|
|
|
|
public static Id<TContext>? GetOrNull(World<TContext> world, Id value)
|
|
|
|
=> ecs_id_is_valid(world, value) ? new(world, value) : null;
|
|
|
|
public static Id<TContext> GetOrThrow(World<TContext> world, Id value)
|
|
|
|
=> ecs_id_is_valid(world, value) ? new(world, value) : throw new InvalidOperationException($"The id {value} is not valid");
|
|
|
|
|
|
|
|
public Entity<TContext>? AsEntity()
|
|
|
|
=> !IsPair ? World.LookupAliveOrNull(new Entity(new() { Data = Value })) : null;
|
|
|
|
public (Entity<TContext> Relation, Entity<TContext> Target)? AsPair()
|
|
|
|
=> IsPair && (World.LookupAliveOrNull(Value.RelationUnsafe) is Entity<TContext> relation) &&
|
|
|
|
(World.LookupAliveOrNull(Value.TargetUnsafe ) is Entity<TContext> target )
|
|
|
|
? (relation, target) : null;
|
|
|
|
|
|
|
|
public bool Equals(Id<TContext> other)
|
|
|
|
{
|
|
|
|
#if DEBUG
|
|
|
|
// In DEBUG mode, we additionally check if the worlds the two compared
|
|
|
|
// values are from the same world. This accounts for the world being a
|
|
|
|
// stage, hence why it might not be the cheapest operation.
|
|
|
|
if (World != other.World) throw new ArgumentException(
|
|
|
|
"The specified values are not from the same world");
|
|
|
|
#endif
|
|
|
|
return Value == other.Value;
|
|
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
|
|
=> (obj is Id<TContext> other) && Equals(other);
|
|
|
|
public override int GetHashCode()
|
|
|
|
=> Value.GetHashCode();
|
|
|
|
public override string? ToString()
|
|
|
|
=> ecs_id_str(World, this).FlecsToStringAndFree()!;
|
|
|
|
|
|
|
|
public static bool operator ==(Id<TContext> left, Id<TContext> right) => left.Equals(right);
|
|
|
|
public static bool operator !=(Id<TContext> left, Id<TContext> right) => !left.Equals(right);
|
|
|
|
|
|
|
|
public static implicit operator Id (Id<TContext> id) => id.Value;
|
|
|
|
public static implicit operator ecs_id_t(Id<TContext> id) => id.Value.Value;
|
|
|
|
|
|
|
|
public static implicit operator Term(Id<TContext> id) => new(id.Value);
|
|
|
|
}
|
|
|
|
|
|
|
|
[Flags]
|
|
|
|
public enum IdFlags : ulong
|
|
|
|
{
|
|
|
|
Pair = 1ul << 63,
|
|
|
|
Override = 1ul << 62,
|
|
|
|
Toggle = 1ul << 61,
|
|
|
|
And = 1ul << 60,
|
|
|
|
}
|