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.
165 lines
6.5 KiB
165 lines
6.5 KiB
const c = @import("./c.zig"); |
|
|
|
pub const IdError = error{ |
|
/// Id is `0`. |
|
IsNone, |
|
/// Id is or contains wildcards. |
|
IsWildcard, |
|
/// Id is not valid. |
|
IsInvalid, |
|
}; |
|
|
|
/// `Id`s are the things that can be added to an `Entity`. |
|
/// It can be an `Entity` or `Pair`, and can have optional id flags. |
|
pub fn Id(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 Pair = Context.Pair; |
|
|
|
world: *World, |
|
raw: c.ecs_id_t, |
|
|
|
pub fn fromRaw(world: *World, raw: c.ecs_id_t) Self { |
|
return .{ .world = world, .raw = raw }; |
|
} |
|
|
|
/// Ensures this `Id` is valid. |
|
/// That is, it can be added to an entity. |
|
/// |
|
/// An `Id` is valid if .. |
|
/// - .. it is not `0`. |
|
/// - .. it does not contain wildcards. |
|
/// - .. it does not contain invalid entities. |
|
pub fn ensureValid(self: Self) !void { |
|
if (self.raw == 0) return IdError.IsNone; |
|
if (c.ecs_id_is_wildcard(self.raw)) return IdError.IsWildcard; |
|
if (self.asPairUnsafe()) |p| |
|
try p.ensureValid() |
|
else if (!self.isEntity()) |
|
if (!c.ecs_is_valid(self.raw & c.ECS_COMPONENT_MASK)) |
|
return IdError.IsInvalid; |
|
} |
|
|
|
pub fn isEntity(self: Self) bool { |
|
return (self.raw & c.ECS_ID_FLAGS_MASK) != 0; |
|
} |
|
|
|
/// Attempts to return this `Id` as an `Entity`, or an error if it's |
|
/// not an entity, not a valid entity or not alive in the world. |
|
pub fn asEntityAlive(self: Self) !Entity { |
|
const result = self.asEntityUnsafe(); |
|
try result.ensureAlive(); |
|
return result; |
|
} |
|
|
|
/// Returns this `Id` as an `Entity`, or `null` otherwise. |
|
/// This assumes the `Id` is valid, or an invalid result could be returned. |
|
pub fn asEntityUnsafe(self: Self) ?Entity { |
|
return if (isEntity(self)) .{ .world = self.world, .raw = self.raw } else null; |
|
} |
|
|
|
pub fn isPair(self: Self) bool { |
|
return c.ecs_id_is_pair(self.raw); |
|
} |
|
|
|
/// Attempts to return this `Id` as a `Pair`, or an error if it's not |
|
/// a pair, or either of its elements are not valid or not alive in |
|
/// the world. |
|
pub fn asPairAlive(self: Self) !Pair { |
|
const result = Pair{ .world = self.world, .raw = self.raw }; |
|
try result.ensureAlive(); |
|
return result; |
|
} |
|
|
|
/// Attempts to return this `Id` as a `Pair`, or an error if it's not |
|
/// a pair, or either of its elements are not valid. |
|
pub fn asPairValid(self: Self) !Pair { |
|
const result = Pair{ .world = self.world, .raw = self.raw }; |
|
try result.ensureValid(); |
|
return result; |
|
} |
|
|
|
/// Returns this `Id` as a `Pair`, or `null` otherwise. |
|
/// This assumes the `Id` is valid, or an invalid result could be returned. |
|
pub fn asPairUnsafe(self: Self) ?Pair { |
|
return if (isPair(self)) .{ .world = self.world, .raw = self.raw } else null; |
|
} |
|
|
|
pub fn isWildcard(self: Self) bool { |
|
return c.ecs_id_is_wildcard(self.raw); |
|
} |
|
|
|
/// Returns whether this `Id` a tag. |
|
/// That is, a component without data / size. |
|
/// |
|
/// An `Id` is a tag when it .. |
|
/// - .. is an entity without the `Component` component. |
|
/// - .. has an `Component` with size member set to 0. |
|
/// - .. is a `Pair` where both elements are a tag. |
|
/// - .. is a `Pair` where `.relation` has the `Tag` tag. |
|
pub fn isTag(self: Self) bool { |
|
return c.ecs_id_is_tag(self.world.raw, self.raw); |
|
} |
|
|
|
/// Returns whether this `Id` represents a union. |
|
/// Only `Pair`s can be unions. |
|
/// |
|
/// An `Id` represents a union when .. |
|
/// - .. the `.relation` of the pair is `Union`. |
|
/// - .. the `.relation` of the pair has `Union`. |
|
pub fn isUnion(self: Self) bool { |
|
return c.ecs_id_is_union(self.world.raw, self.raw); |
|
} |
|
|
|
/// Returns whether this `Id` is in use in the world. |
|
/// That is, if it has been added to one or more tables. |
|
/// |
|
/// Note that empty tables may reference this `Id`, in which case |
|
/// this function can return `true`. Consider using `count()` instead. |
|
pub fn isInUse(self: Self) bool { |
|
return c.ecs_id_in_use(self.world.raw, self.raw); |
|
} |
|
|
|
/// Gets the number of entities in the world that have this `Id`. |
|
pub fn count(self: Self) usize { |
|
return @intCast(c.ecs_count_id(self.world.raw, self.raw)); |
|
} |
|
|
|
// Get the type for an id. |
|
// This function returns the type information for an id. The specified id can be |
|
// any valid id. For the rules on how type information is determined based on |
|
// id, see ecs_get_typeid. |
|
// TODO: const ecs_type_info_t* ecs_get_type_info(const ecs_world_t *world, ecs_id_t id); |
|
|
|
/// Returns the entity representing the component type for this `Id`, |
|
/// if it is associated with a type, or `null` otherwise. |
|
/// |
|
/// For a regular component with a non-zero size (an entity with the |
|
/// `flecs.core.Component` component) the operation will return the |
|
/// entity itself. |
|
/// |
|
/// For an entity that does not have the `Component` component, or |
|
/// its component is zero-sized, the operation will return `null`. |
|
/// |
|
/// For a `Pair`, the operation will return the type associated with |
|
/// the pair, by applying the following rules in order: |
|
/// - If `.relation` is a component, it is returned. |
|
/// - If `.relation` has `flecs.core.Tag`, `null` is returned. |
|
/// - If `.target` is a component, it is returned. |
|
/// - Otherwise, `null` is returned. |
|
pub fn typeId(self: Self) ?Entity { |
|
const raw = c.ecs_get_typeid(self.world.raw, self.raw); |
|
return if (raw != 0) Entity.fromRaw(self.world, raw); |
|
} |
|
|
|
/// Returns if the provided `pattern` matches this `Id`. |
|
/// The pattern may contain a wildcard (or wildcards, if a `Pair`). |
|
pub fn matches(self: Self, pattern: Self) bool { |
|
return c.ecs_id_match(self.raw, pattern.raw); |
|
} |
|
}; |
|
}
|
|
|