diff --git a/zig-ecs/src/ecs/component_storage.zig b/zig-ecs/src/ecs/component_storage.zig index 0e3647c..f5e1815 100644 --- a/zig-ecs/src/ecs/component_storage.zig +++ b/zig-ecs/src/ecs/component_storage.zig @@ -6,9 +6,8 @@ const SparseSet = @import("sparse_set.zig").SparseSet; const Signal = @import("../signals/signal.zig").Signal; const Sink = @import("../signals/sink.zig").Sink; -/// Stores an ArrayList of components along with a SparseSet of entities. The max amount that can be stored is -/// based on the max value of DenseT -pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type, comptime DenseT: type) type { +/// Stores an ArrayList of components along with a SparseSet of entities +pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { std.debug.assert(!utils.isComptime(CompT)); // empty (zero-sized) structs will not have an array created @@ -25,7 +24,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type, comptime D return struct { const Self = @This(); - set: *SparseSet(EntityT, DenseT), + set: *SparseSet(EntityT), instances: std.ArrayList(CompOrAlmostEmptyT), allocator: ?*std.mem.Allocator, safe_deinit: fn (*Self) void, @@ -36,7 +35,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type, comptime D pub fn init(allocator: *std.mem.Allocator) Self { var store = Self{ - .set = SparseSet(EntityT, DenseT).initPtr(allocator), + .set = SparseSet(EntityT).initPtr(allocator), .instances = undefined, .safe_deinit = struct { fn deinit(self: *Self) void { @@ -65,7 +64,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type, comptime D pub fn initPtr(allocator: *std.mem.Allocator) *Self { var store = allocator.create(Self) catch unreachable; - store.set = SparseSet(EntityT, DenseT).initPtr(allocator); + store.set = SparseSet(EntityT).initPtr(allocator); if (!is_empty_struct) store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator); store.allocator = allocator; @@ -204,7 +203,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type, comptime D } test "add/try-get/remove/clear" { - var store = ComponentStorage(f32, u32, u8).init(std.testing.allocator); + var store = ComponentStorage(f32, u32).init(std.testing.allocator); defer store.deinit(); store.add(3, 66.45); @@ -220,7 +219,7 @@ test "add/try-get/remove/clear" { } test "add/get/remove" { - var store = ComponentStorage(f32, u32, u8).init(std.testing.allocator); + var store = ComponentStorage(f32, u32).init(std.testing.allocator); defer store.deinit(); store.add(3, 66.45); @@ -232,7 +231,7 @@ test "add/get/remove" { } test "iterate" { - var store = ComponentStorage(f32, u32, u8).initPtr(std.testing.allocator); + var store = ComponentStorage(f32, u32).initPtr(std.testing.allocator); defer store.deinit(); store.add(3, 66.45); @@ -252,7 +251,7 @@ test "iterate" { test "empty component" { const Empty = struct {}; - var store = ComponentStorage(Empty, u32, u8).initPtr(std.testing.allocator); + var store = ComponentStorage(Empty, u32).initPtr(std.testing.allocator); defer store.deinit(); store.add(3, Empty{}); @@ -270,7 +269,7 @@ fn destruct(e: u32) void { } test "signals" { - var store = ComponentStorage(f32, u32, u8).init(std.testing.allocator); + var store = ComponentStorage(f32, u32).init(std.testing.allocator); defer store.deinit(); store.onConstruct().connect(construct); diff --git a/zig-ecs/src/ecs/groups.zig b/zig-ecs/src/ecs/groups.zig index f378e7a..9e8dcda 100644 --- a/zig-ecs/src/ecs/groups.zig +++ b/zig-ecs/src/ecs/groups.zig @@ -11,7 +11,7 @@ pub fn BasicGroup(comptime n_includes: usize, comptime n_excludes: usize) type { return struct { const Self = @This(); - entity_set: *SparseSet(Entity, u16), + entity_set: *SparseSet(Entity), registry: *Registry, type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32, @@ -41,7 +41,7 @@ pub fn BasicGroup(comptime n_includes: usize, comptime n_excludes: usize) type { } }; - pub fn init(entity_set: *SparseSet(Entity, u16), registry: *Registry, type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32) Self { + pub fn init(entity_set: *SparseSet(Entity), registry: *Registry, type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32) Self { return Self{ .entity_set = entity_set, .registry = registry, diff --git a/zig-ecs/src/ecs/registry.zig b/zig-ecs/src/ecs/registry.zig index 5164162..2212c33 100644 --- a/zig-ecs/src/ecs/registry.zig +++ b/zig-ecs/src/ecs/registry.zig @@ -22,7 +22,7 @@ pub const OwningGroup = @import("groups.zig").OwningGroup; /// Stores an ArrayList of components. The max amount that can be stored is based on the type below pub fn Storage(comptime CompT: type) type { - return ComponentStorage(CompT, Entity, u16); // 65,535 components + return ComponentStorage(CompT, Entity); } /// the registry is the main gateway to all ecs functionality. It assumes all internal allocations will succeed and returns @@ -38,7 +38,7 @@ pub const Registry = struct { /// internal, persistant data structure to manage the entities in a group const GroupData = struct { hash: u32, - entity_set: SparseSet(Entity, u16) = undefined, // TODO: dont hardcode this. put it in EntityTraits maybe. All SparseSets would need to use the value. + entity_set: SparseSet(Entity) = undefined, /// optional. there will be an entity_set for non-owning groups and current for owning owned: []u32, include: []u32, exclude: []u32, @@ -53,7 +53,7 @@ pub const Registry = struct { var group_data = allocator.create(GroupData) catch unreachable; group_data.hash = hash; if (owned.len == 0) { - group_data.entity_set = SparseSet(Entity, u16).init(allocator); + group_data.entity_set = SparseSet(Entity).init(allocator); } group_data.owned = std.mem.dupe(allocator, u32, owned) catch unreachable; group_data.include = std.mem.dupe(allocator, u32, include) catch unreachable; diff --git a/zig-ecs/src/ecs/sparse_set.zig b/zig-ecs/src/ecs/sparse_set.zig index 76c01ab..3619084 100644 --- a/zig-ecs/src/ecs/sparse_set.zig +++ b/zig-ecs/src/ecs/sparse_set.zig @@ -2,18 +2,18 @@ const std = @import("std"); const warn = std.debug.warn; // TODO: fix entity_mask. it should come from EntityTraitsDefinition. -pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { +pub fn SparseSet(comptime SparseT: type) type { return struct { const Self = @This(); - sparse: std.ArrayList(DenseT), + sparse: std.ArrayList(SparseT), dense: std.ArrayList(SparseT), entity_mask: SparseT, allocator: ?*std.mem.Allocator, pub fn initPtr(allocator: *std.mem.Allocator) *Self { var set = allocator.create(Self) catch unreachable; - set.sparse = std.ArrayList(DenseT).init(allocator); + set.sparse = std.ArrayList(SparseT).init(allocator); set.dense = std.ArrayList(SparseT).init(allocator); set.entity_mask = std.math.maxInt(SparseT); set.allocator = allocator; @@ -22,7 +22,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { pub fn init(allocator: *std.mem.Allocator) Self { return Self{ - .sparse = std.ArrayList(DenseT).init(allocator), + .sparse = std.ArrayList(SparseT).init(allocator), .dense = std.ArrayList(SparseT).init(allocator), .entity_mask = std.math.maxInt(SparseT), .allocator = null, @@ -49,7 +49,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { return sparse & self.entity_mask; } - fn assure(self: *Self, pos: usize) []DenseT { + fn assure(self: *Self, pos: usize) []SparseT { // TODO: support paging if (self.sparse.capacity <= pos or self.sparse.capacity == 0) { const amount = pos + 1 - self.sparse.capacity; @@ -58,7 +58,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { const old_len = self.sparse.items.len; self.sparse.resize(self.sparse.items.len + amount) catch unreachable; self.sparse.expandToCapacity(); - std.mem.set(DenseT, self.sparse.items[old_len..self.sparse.items.len], std.math.maxInt(DenseT)); + std.mem.set(SparseT, self.sparse.items[old_len..self.sparse.items.len], std.math.maxInt(SparseT)); } return self.sparse.items; @@ -93,11 +93,11 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { return false; // testing against maxInt permits to avoid accessing the packed array - return curr < self.sparse.items.len and self.sparse.items[curr] != std.math.maxInt(DenseT); + return curr < self.sparse.items.len and self.sparse.items[curr] != std.math.maxInt(SparseT); } /// Returns the position of an entity in a sparse set - pub fn index(self: Self, sparse: SparseT) DenseT { + pub fn index(self: Self, sparse: SparseT) SparseT { std.debug.assert(self.contains(sparse)); return self.sparse.items[self.offset(sparse)]; } @@ -107,7 +107,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { std.debug.assert(!self.contains(sparse)); // assure(page(entt))[offset(entt)] = packed.size() - self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(DenseT, self.dense.items.len); + self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(SparseT, self.dense.items.len); _ = self.dense.append(sparse) catch unreachable; } @@ -121,7 +121,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { self.dense.items[self.sparse.items[curr]] = last_dense; self.sparse.items[self.page(last_dense)] = self.sparse.items[curr]; - self.sparse.items[curr] = std.math.maxInt(DenseT); + self.sparse.items[curr] = std.math.maxInt(SparseT); _ = self.dense.pop(); } @@ -132,7 +132,7 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { var to = &self.sparse.items[sparse_r]; std.mem.swap(SparseT, &self.dense.items[from.*], &self.dense.items[to.*]); - std.mem.swap(DenseT, from, to); + std.mem.swap(SparseT, from, to); } /// Sort elements according to the given comparison function @@ -141,15 +141,15 @@ pub fn SparseSet(comptime SparseT: type, comptime DenseT: type) type { var i = @as(usize, 0); for (self.dense.items) |sparse| { - // self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(DenseT, sparse); - self.sparse.items[self.page(sparse)] = @intCast(DenseT, sparse); + // self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(SparseT, sparse); + self.sparse.items[self.page(sparse)] = @intCast(SparseT, sparse); } } /// Sort entities according to their order in another sparse set. Other is the master in this case. pub fn respect(self: *Self, other: *Self) void { - var pos = @as(DenseT, 0); - var i = @as(DenseT, 0); + var pos = @as(SparseT, 0); + var i = @as(SparseT, 0); while (i < other.dense.items.len) : (i += 1) { if (self.contains(other.dense.items[i])) { if (other.dense.items[i] != self.dense.items[pos]) { @@ -181,7 +181,7 @@ fn printSet(set: *SparseSet(u32, u8)) void { } test "add/remove/clear" { - var set = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set = SparseSet(u32).initPtr(std.testing.allocator); defer set.deinit(); set.add(4); @@ -198,7 +198,7 @@ test "add/remove/clear" { } test "grow" { - var set = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set = SparseSet(u32).initPtr(std.testing.allocator); defer set.deinit(); var i = @as(usize, std.math.maxInt(u8)); @@ -210,7 +210,7 @@ test "grow" { } test "swap" { - var set = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set = SparseSet(u32).initPtr(std.testing.allocator); defer set.deinit(); set.add(4); @@ -224,7 +224,7 @@ test "swap" { } test "data() synced" { - var set = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set = SparseSet(u32).initPtr(std.testing.allocator); defer set.deinit(); set.add(0); @@ -242,10 +242,10 @@ test "data() synced" { } test "respect" { - var set1 = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set1 = SparseSet(u32).initPtr(std.testing.allocator); defer set1.deinit(); - var set2 = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set2 = SparseSet(u32).initPtr(std.testing.allocator); defer set2.deinit(); set1.add(3); @@ -265,7 +265,7 @@ test "respect" { } test "respect" { - var set = SparseSet(u32, u8).initPtr(std.testing.allocator); + var set = SparseSet(u32).initPtr(std.testing.allocator); defer set.deinit(); set.add(5);