diff --git a/zig-ecs/src/ecs/groups.zig b/zig-ecs/src/ecs/groups.zig index 3cb682b..95c30f7 100644 --- a/zig-ecs/src/ecs/groups.zig +++ b/zig-ecs/src/ecs/groups.zig @@ -218,4 +218,4 @@ test "multiple OwningGroups" { // this will break the group // var group6 = reg.group(.{Sprite, Rotation}, .{}, .{}); -} \ No newline at end of file +} diff --git a/zig-ecs/src/ecs/registry.zig b/zig-ecs/src/ecs/registry.zig index 842d63e..d79cc60 100644 --- a/zig-ecs/src/ecs/registry.zig +++ b/zig-ecs/src/ecs/registry.zig @@ -283,6 +283,13 @@ pub const Registry = struct { self.add(entity, value); } + /// adds all the component types passed in as zero-initialized values + pub fn addTypes(self: *Registry, entity: Entity, comptime types: var) void { + inline for (types) |t| { + self.assure(t).add(entity, std.mem.zeroes(t)); + } + } + /// Replaces the given component for an entity pub fn replace(self: *Registry, entity: Entity, value: var) void { assert(self.valid(entity)); @@ -519,7 +526,6 @@ pub const Registry = struct { } const check = overlapping == 0 or ((sz == size) or (sz == grp.size)); - std.debug.warn("overlapping: {}, sz: {}, (sz == size): {}, (sz == gdata.size): {}\t--- check: {}\n", .{ overlapping, sz, sz == size, sz == grp.size, check }); std.debug.assert(check); } } @@ -571,8 +577,7 @@ pub const Registry = struct { new_group_data.entity_set.add(entity); } } else { - // we cannot iterate backwards because we want to leave behind valid entities in case of owned types - // maybeValidIf all the entities in the first owned group + // ??we cannot iterate backwards because we want to leave behind valid entities in case of owned types var first_owned_storage = self.assure(owned[0]); for (first_owned_storage.data().*) |entity| { new_group_data.maybeValidIf(entity); diff --git a/zig-ecs/tests/groups_test.zig b/zig-ecs/tests/groups_test.zig new file mode 100644 index 0000000..ced5870 --- /dev/null +++ b/zig-ecs/tests/groups_test.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const warn = std.debug.warn; +const ecs = @import("ecs"); +const Registry = @import("ecs").Registry; + +const Velocity = struct { x: f32 = 0, y: f32 = 0 }; +const Position = struct { x: f32 = 0, y: f32 = 0 }; +const Empty = struct {}; +const Sprite = struct { x: f32 = 0 }; +const Transform = struct { x: f32 = 0 }; +const Renderable = struct { x: f32 = 0 }; +const Rotation = struct { x: f32 = 0 }; + +fn printStore(store: var, name: []const u8) void { + warn("--- {} ---\n", .{name}); + for (store.set.dense.items) |e, i| { + warn("{:3.0}", .{e}); + warn(" ({d:3.0})", .{store.instances.items[i]}); + } + warn("\n", .{}); +} + +test "nested OwningGroups add/remove components" { + var reg = Registry.init(std.testing.allocator); + defer reg.deinit(); + + var group1 = reg.group(.{Sprite}, .{Renderable}, .{}); + var group2 = reg.group(.{ Sprite, Transform }, .{Renderable}, .{}); + var group3 = reg.group(.{ Sprite, Transform }, .{ Renderable, Rotation }, .{}); + + std.testing.expect(!reg.sortable(Sprite)); + std.testing.expect(!reg.sortable(Transform)); + std.testing.expect(reg.sortable(Renderable)); + + var e1 = reg.create(); + reg.addTypes(e1, .{ Sprite, Renderable, Rotation }); + std.testing.expectEqual(group1.len(), 1); + std.testing.expectEqual(group2.len(), 0); + std.testing.expectEqual(group3.len(), 0); + + reg.add(e1, Transform{}); + std.testing.expectEqual(group3.len(), 1); + + reg.remove(Sprite, e1); + std.testing.expectEqual(group1.len(), 0); + std.testing.expectEqual(group2.len(), 0); + std.testing.expectEqual(group3.len(), 0); +} + +test "nested OwningGroups entity order" { + var reg = Registry.init(std.testing.allocator); + defer reg.deinit(); + + var group1 = reg.group(.{Sprite}, .{Renderable}, .{}); + var group2 = reg.group(.{ Sprite, Transform }, .{Renderable}, .{}); + + var i: usize = 0; + while (i < 5) : (i += 1) { + var e = reg.create(); + reg.add(e, Sprite{ .x = @intToFloat(f32, i) }); + reg.add(e, Renderable{ .x = @intToFloat(f32, i) }); + } + + std.testing.expectEqual(group1.len(), 5); + std.testing.expectEqual(group2.len(), 0); + + var sprite_store = reg.assure(Sprite); + var transform_store = reg.assure(Transform); + printStore(sprite_store, "Sprite"); + + reg.add(1, Transform{.x = 1}); + + printStore(sprite_store, "Sprite"); + printStore(transform_store, "Transform"); + warn("group2.current: {}\n", .{group2.current.*}); +} diff --git a/zig-ecs/tests/registry_test.zig b/zig-ecs/tests/registry_test.zig index a730451..b2b7ea8 100644 --- a/zig-ecs/tests/registry_test.zig +++ b/zig-ecs/tests/registry_test.zig @@ -3,7 +3,7 @@ const ecs = @import("ecs"); const Registry = @import("ecs").Registry; const Velocity = struct { x: f32, y: f32 }; -const Position = struct { x: f32, y: f32 }; +const Position = struct { x: f32 = 0, y: f32 = 0 }; const Empty = struct {}; const BigOne = struct { pos: Position, vel: Velocity, accel: Velocity }; @@ -17,11 +17,12 @@ test "Registry" { var e1 = reg.create(); - reg.add(e1, Empty{}); - reg.add(e1, Position{ .x = 5, .y = 5 }); + reg.addTypes(e1, .{Empty, Position}); reg.add(e1, BigOne{ .pos = Position{ .x = 5, .y = 5 }, .vel = Velocity{ .x = 5, .y = 5 }, .accel = Velocity{ .x = 5, .y = 5 } }); std.testing.expect(reg.has(Empty, e1)); + std.testing.expect(reg.has(Position, e1)); + std.testing.expect(reg.has(BigOne, e1)); reg.remove(Empty, e1); std.testing.expect(!reg.has(Empty, e1)); diff --git a/zig-ecs/tests/tests.zig b/zig-ecs/tests/tests.zig index 2f11302..10eaf86 100644 --- a/zig-ecs/tests/tests.zig +++ b/zig-ecs/tests/tests.zig @@ -1,4 +1,5 @@ test "ecs test suite" { _ = @import("dispatcher_test.zig"); _ = @import("registry_test.zig"); + _ = @import("groups_test.zig"); }