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
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? |
|
}; |
|
}
|
|
|