diff --git a/zig-ecs/src/ecs/component_storage.zig b/zig-ecs/src/ecs/component_storage.zig index f5e1815..9d53f38 100644 --- a/zig-ecs/src/ecs/component_storage.zig +++ b/zig-ecs/src/ecs/component_storage.zig @@ -27,6 +27,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { set: *SparseSet(EntityT), instances: std.ArrayList(CompOrAlmostEmptyT), allocator: ?*std.mem.Allocator, + super: usize = 0, /// doesnt really belong here...used to denote group ownership safe_deinit: fn (*Self) void, safe_swap: fn (*Self, EntityT, EntityT) void, construction: Signal(EntityT), @@ -68,6 +69,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { if (!is_empty_struct) store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator); store.allocator = allocator; + store.super = 0; store.construction = Signal(EntityT).init(allocator); store.update = Signal(EntityT).init(allocator); store.destruction = Signal(EntityT).init(allocator); diff --git a/zig-ecs/src/ecs/groups.zig b/zig-ecs/src/ecs/groups.zig index 9e8dcda..3cb682b 100644 --- a/zig-ecs/src/ecs/groups.zig +++ b/zig-ecs/src/ecs/groups.zig @@ -78,13 +78,15 @@ pub fn OwningGroup(comptime n_owned: usize, comptime n_includes: usize, comptime const Self = @This(); current: *usize, + super: *usize, registry: *Registry, owned_type_ids: [n_owned]u32, include_type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32, - pub fn init(current: *usize, registry: *Registry, owned_type_ids: [n_owned]u32, include_type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32) Self { + pub fn init(super: *usize, current: *usize, registry: *Registry, owned_type_ids: [n_owned]u32, include_type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32) Self { return Self{ + .super = super, .current = current, .registry = registry, .owned_type_ids = owned_type_ids, @@ -96,6 +98,10 @@ pub fn OwningGroup(comptime n_owned: usize, comptime n_includes: usize, comptime pub fn len(self: Self) usize { return self.current.*; } + + pub fn sortable(self: *Registry, comptime T: type) bool { + return self.super.* == n_owned + n_includes + n_excludes; + } }; } @@ -183,4 +189,33 @@ test "OwningGroup add/remove" { reg.remove(i32, e0); std.testing.expectEqual(group.len(), 0); +} + +test "multiple OwningGroups" { + const Sprite = struct { x: f32 }; + const Transform = struct { x: f32 }; + const Renderable = struct { x: f32 }; + const Rotation = struct { x: f32 }; + + var reg = Registry.init(std.testing.allocator); + defer reg.deinit(); + + // var group1 = reg.group(.{u64, u32}, .{}, .{}); + // var group2 = reg.group(.{u64, u32, u8}, .{}, .{}); + + var group5 = reg.group(.{Sprite, Transform}, .{Renderable, Rotation}, .{}); + var group3 = reg.group(.{Sprite}, .{Renderable}, .{}); + var group4 = reg.group(.{Sprite, Transform}, .{Renderable}, .{}); + + var last_size: u8 = 0; + for (reg.groups.items) |grp| { + std.testing.expect(last_size <= grp.size); + last_size = grp.size; + std.debug.warn("grp: {}\n", .{grp.size}); + } + + std.testing.expect(!reg.sortable(Sprite)); + + // this will break the group + // var group6 = reg.group(.{Sprite, Rotation}, .{}, .{}); } \ No newline at end of file diff --git a/zig-ecs/src/ecs/type_store.zig b/zig-ecs/src/ecs/type_store.zig index 9a52341..56855ec 100644 --- a/zig-ecs/src/ecs/type_store.zig +++ b/zig-ecs/src/ecs/type_store.zig @@ -22,12 +22,10 @@ pub const TypeStore = struct { } /// adds instance, returning a pointer to the item as it lives in the store - pub fn add(self: *TypeStore, instance: var) *@TypeOf(instance) { + pub fn add(self: *TypeStore, instance: var) void { var bytes = self.allocator.alloc(u8, @sizeOf(@TypeOf(instance))) catch unreachable; - var ptr = @ptrCast(*@TypeOf(instance), @alignCast(@alignOf(@TypeOf(instance)), bytes)); - ptr.* = instance; + std.mem.copy(u8, bytes, std.mem.asBytes(&instance)); _ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable; - return ptr; } pub fn get(self: *TypeStore, comptime T: type) *T { @@ -42,9 +40,11 @@ pub const TypeStore = struct { } pub fn getOrAdd(self: *TypeStore, comptime T: type) *T { - if (self.has(T)) return self.get(T); - var instance = std.mem.zeroes(T); - return self.add(instance); + if (!self.has(T)) { + var instance = std.mem.zeroes(T); + self.add(instance); + } + return self.get(T); } pub fn remove(self: *TypeStore, comptime T: type) void { @@ -60,22 +60,22 @@ pub const TypeStore = struct { }; test "TypeStore" { - const Vector = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0}; + const Vector = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0 }; var store = TypeStore.init(std.testing.allocator); defer store.deinit(); - var orig = Vector{.x = 5, .y = 6, .z = 8}; - var inserted = store.add(orig); + var orig = Vector{ .x = 5, .y = 6, .z = 8 }; + store.add(orig); std.testing.expect(store.has(Vector)); - std.testing.expectEqual(inserted.*, Vector{.x = 5, .y = 6, .z = 8}); + std.testing.expectEqual(store.get(Vector).*, orig); var v = store.get(Vector); - std.testing.expectEqual(v.*, Vector{.x = 5, .y = 6, .z = 8}); + std.testing.expectEqual(v.*, Vector{ .x = 5, .y = 6, .z = 8 }); v.*.x = 666; var v2 = store.get(Vector); - std.testing.expectEqual(v2.*, Vector{.x = 666, .y = 6, .z = 8}); + std.testing.expectEqual(v2.*, Vector{ .x = 666, .y = 6, .z = 8 }); store.remove(Vector); std.testing.expect(!store.has(Vector)); @@ -86,4 +86,4 @@ test "TypeStore" { var v4 = store.get(u32); std.testing.expectEqual(v3.*, 777); -} \ No newline at end of file +} diff --git a/zig-ecs/src/ecs/utils.zig b/zig-ecs/src/ecs/utils.zig index 87cc054..0f7cb33 100644 --- a/zig-ecs/src/ecs/utils.zig +++ b/zig-ecs/src/ecs/utils.zig @@ -41,12 +41,12 @@ pub fn sortSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T /// comptime string hashing for the type names pub fn typeId(comptime T: type) u32 { - return hashStringFnv(u32, @typeName(T)); + comptime return hashStringFnv(u32, @typeName(T)); } /// comptime string hashing for the type names pub fn typeId64(comptime T: type) u64 { - return hashStringFnv(u64, @typeName(T)); + comptime return hashStringFnv(u64, @typeName(T)); } /// u32 Fowler-Noll-Vo string hash diff --git a/zig-ecs/tests/registry_test.zig b/zig-ecs/tests/registry_test.zig index bec5c88..a730451 100644 --- a/zig-ecs/tests/registry_test.zig +++ b/zig-ecs/tests/registry_test.zig @@ -77,9 +77,9 @@ test "singletons" { defer reg.deinit(); var pos = Position{ .x = 5, .y = 5 }; - var inserted = reg.singletons.add(pos); + reg.singletons.add(pos); std.testing.expect(reg.singletons.has(Position)); - std.testing.expectEqual(inserted.*, pos); + std.testing.expectEqual(reg.singletons.get(Position).*, pos); reg.singletons.remove(Position); std.testing.expect(!reg.singletons.has(Position));