parent
41d5155d4d
commit
bb5f20e810
3 changed files with 293 additions and 2 deletions
@ -0,0 +1,73 @@ |
||||
const c = @import("./c.zig"); |
||||
|
||||
const Entity = @import("./entity.zig").Entity; |
||||
const Id = @import("./id.zig").Id; |
||||
const World = @import("./world.zig").World; |
||||
|
||||
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 `getRelation()` and `getTarget()`. |
||||
pub fn Pair(comptime ctx: anytype) type { |
||||
return struct { |
||||
world: *World(ctx), |
||||
raw: c.ecs_id_t, |
||||
|
||||
const Self = @This(); |
||||
|
||||
/// Build a pair from the specified `relation` and `target` entities. |
||||
/// The specified entities must be alive in the world. |
||||
pub fn init(relation: Entity(ctx), target: Entity(ctx)) !Self { |
||||
const raw = c.ecs_make_pair(relation.ensureAlive().raw, target.ensureAlive().raw); |
||||
return .{ .world = relation.world, .raw = 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) !Self { |
||||
if (self.raw == 0) return error.IsNone; |
||||
if (!c.ecs_id_is_pair(self.raw)) return error.IsntPair; |
||||
_ = try self.getRelation().ensureAlive(); |
||||
_ = try self.getTarget().ensureAlive(); |
||||
return self; |
||||
} |
||||
|
||||
/// Ensures this `Pair` and its elements are valid. |
||||
pub fn ensureValid(self: Self) !Self { |
||||
if (self.raw == 0) return error.IsNone; |
||||
if (!c.ecs_id_is_pair(self.raw)) return error.IsntPair; |
||||
_ = try self.getRelation().ensureValid(); |
||||
_ = try self.getTarget().ensureValid(); |
||||
return self; |
||||
} |
||||
|
||||
pub fn asId(self: Self) Id(ctx) { |
||||
return @bitCast(self); |
||||
} |
||||
|
||||
pub fn getRelation(self: Self) Entity(ctx) { |
||||
return Entity(ctx).fromRaw(self.world.raw, c.ECS_PAIR_FIRST(self.raw)); |
||||
} |
||||
|
||||
pub fn getTarget(self: Self) Entity(ctx) { |
||||
return Entity(ctx).fromRaw(self.world.raw, c.ECS_PAIR_SECOND(self.raw)); |
||||
} |
||||
|
||||
// TODO: Decide whether to copy `Id` functions over? |
||||
}; |
||||
} |
Loading…
Reference in new issue