High-level wrapper around Flecs, a powerful ECS (Entity Component System) library, written in Zig language
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.9 KiB

const c = @import("./c.zig");
pub const PairError = error{
/// Id is `0`.
IsNone,
/// Id is not a `Pair`.
IsNotPair,
};
/// A `Pair` is an `Id` which encodes a relationship between two entities.
/// It is made of two parts, `relation` and `target`, each represented as
/// entities themselves. `relation` is an entity describing the nature of the
/// relationship, and `target` is the target this relationship is about.
///
/// For example, if the entity `Alice` likes another entity `Bob`, you would
/// add the pair `(Likes, Bob)` to entity `Alice`.
///
/// `Pair`s are created using `init()`, or can be converted from `Id`s using
/// `Id.asPair()` (fails if the id isn't a pair). They can be turned back
/// to an `Id` with `asId()` (always succeeds). Elements of the relationship
/// can be extracted by calling `relation()` and `target()`.
pub fn Pair(comptime ctx: anytype) type {
return struct {
const Self = @This();
const Context = @import("./context.zig").Context(ctx);
const World = Context.World;
const Entity = Context.Entity;
const Id = Context.Id;
world: *World,
raw: c.ecs_id_t,
pub fn fromRaw(world: *World, relation_: c.ecs_entity_t, target_: c.ecs_entity_t) Self {
return .{ .world = world, .raw = c.ecs_pair(relation_, target_) };
}
/// Build a pair from the specified `relation` and `target` entities.
/// Returns an error if either of the entities is not alive.
pub fn init(relation_: Entity, target_: Entity) !Self {
try relation_.ensureAlive();
try target_.ensureAlive();
return fromRaw(relation_.world, relation_.raw, target_.raw);
}
/// Ensures this `Pair` is valid and its `relation` and `target`
/// entities are alive in the world, returning an error otherwise.
pub fn ensureAlive(self: Self) !void {
if (self.raw == 0) return error.IsNone;
if (!c.ecs_id_is_pair(self.raw)) return error.IsntPair;
try self.relation().ensureAlive();
try self.target().ensureAlive();
}
/// Ensures this `Pair` and its elements are valid.
pub fn ensureValid(self: Self) !void {
if (self.raw == 0) return error.IsNone;
if (!c.ecs_id_is_pair(self.raw)) return error.IsntPair;
try self.relation().ensureValid();
try self.target().ensureValid();
}
pub fn asId(self: Self) Id {
return .{ .world = self.world, .raw = self.raw };
}
pub fn relation(self: Self) Entity {
return Entity.fromRaw(self.world, c.ECS_PAIR_FIRST(self.raw));
}
pub fn target(self: Self) Entity {
return Entity.fromRaw(self.world, c.ECS_PAIR_SECOND(self.raw));
}
// TODO: Decide whether to copy `Id` functions over?
};
}