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