diff --git a/zig-ecs/src/ecs/handles.zig b/zig-ecs/src/ecs/handles.zig index cbf71d1..567aeb9 100644 --- a/zig-ecs/src/ecs/handles.zig +++ b/zig-ecs/src/ecs/handles.zig @@ -21,6 +21,28 @@ pub fn Handles(comptime HandleType: type, comptime IndexType: type, comptime Ver const invalid_id = std.math.maxInt(IndexType); + pub const Iterator = struct { + hm: Self, + index: usize = 0, + + pub fn init(hm: Self) @This() { + return .{ .hm = hm }; + } + + pub fn next(self: *@This()) ?HandleType { + if (self.index == self.hm.append_cursor) return null; + + for (self.hm.handles[self.index..self.hm.append_cursor]) |h| { + self.index += 1; + if (self.hm.alive(h)) { + return h; + } + } + + return null; + } + }; + pub fn init(allocator: *std.mem.Allocator) Self { return initWithCapacity(allocator, 32); } @@ -88,10 +110,14 @@ pub fn Handles(comptime HandleType: type, comptime IndexType: type, comptime Ver self.last_destroyed = id; } - pub fn isAlive(self: Self, handle: HandleType) bool { + pub fn alive(self: Self, handle: HandleType) bool { const id = self.extractId(handle); return id < self.append_cursor and self.handles[id] == handle; } + + pub fn iterator(self: Self) Iterator { + return Iterator.init(self); + } }; } @@ -103,33 +129,33 @@ test "handles" { const e1 = hm.create(); const e2 = hm.create(); - std.debug.assert(hm.isAlive(e0)); - std.debug.assert(hm.isAlive(e1)); - std.debug.assert(hm.isAlive(e2)); + std.debug.assert(hm.alive(e0)); + std.debug.assert(hm.alive(e1)); + std.debug.assert(hm.alive(e2)); hm.remove(e1) catch unreachable; - std.debug.assert(!hm.isAlive(e1)); + std.debug.assert(!hm.alive(e1)); std.testing.expectError(error.RemovedInvalidHandle, hm.remove(e1)); var e_tmp = hm.create(); - std.debug.assert(hm.isAlive(e_tmp)); + std.debug.assert(hm.alive(e_tmp)); hm.remove(e_tmp) catch unreachable; - std.debug.assert(!hm.isAlive(e_tmp)); + std.debug.assert(!hm.alive(e_tmp)); hm.remove(e0) catch unreachable; - std.debug.assert(!hm.isAlive(e0)); + std.debug.assert(!hm.alive(e0)); hm.remove(e2) catch unreachable; - std.debug.assert(!hm.isAlive(e2)); + std.debug.assert(!hm.alive(e2)); e_tmp = hm.create(); - std.debug.assert(hm.isAlive(e_tmp)); + std.debug.assert(hm.alive(e_tmp)); e_tmp = hm.create(); - std.debug.assert(hm.isAlive(e_tmp)); + std.debug.assert(hm.alive(e_tmp)); e_tmp = hm.create(); - std.debug.assert(hm.isAlive(e_tmp)); + std.debug.assert(hm.alive(e_tmp)); } diff --git a/zig-ecs/src/ecs/registry.zig b/zig-ecs/src/ecs/registry.zig index b07d91d..a6c8e0d 100644 --- a/zig-ecs/src/ecs/registry.zig +++ b/zig-ecs/src/ecs/registry.zig @@ -250,7 +250,7 @@ pub const Registry = struct { } pub fn valid(self: *Registry, entity: Entity) bool { - return self.handles.isAlive(entity); + return self.handles.alive(entity); } /// Returns the entity identifier without the version @@ -275,6 +275,11 @@ pub const Registry = struct { self.handles.remove(entity) catch unreachable; } + /// returns an interator that iterates all live entities + pub fn entities(self: Registry) EntityHandles.Iterator { + return self.handles.iterator(); + } + pub fn add(self: *Registry, entity: Entity, value: var) void { assert(self.valid(entity)); self.assure(@TypeOf(value)).add(entity, value); diff --git a/zig-ecs/tests/registry_test.zig b/zig-ecs/tests/registry_test.zig index b2b7ea8..dd8144b 100644 --- a/zig-ecs/tests/registry_test.zig +++ b/zig-ecs/tests/registry_test.zig @@ -24,6 +24,9 @@ test "Registry" { std.testing.expect(reg.has(Position, e1)); std.testing.expect(reg.has(BigOne, e1)); + var iter = reg.entities(); + while (iter.next()) |e| std.testing.expectEqual(e1, e); + reg.remove(Empty, e1); std.testing.expect(!reg.has(Empty, e1)); }