diff --git a/zig-ecs/src/ecs/component_storage.zig b/zig-ecs/src/ecs/component_storage.zig index ede1bb6..c31e3a6 100644 --- a/zig-ecs/src/ecs/component_storage.zig +++ b/zig-ecs/src/ecs/component_storage.zig @@ -7,35 +7,35 @@ 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 -pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { - std.debug.assert(!utils.isComptime(CompT)); +pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type { + std.debug.assert(!utils.isComptime(Component)); // empty (zero-sized) structs will not have an array created - comptime const is_empty_struct = @sizeOf(CompT) == 0; + comptime const is_empty_struct = @sizeOf(Component) == 0; - // HACK: due to this being stored as untyped ptrs, when deinit is called we are casted to a CompT of some random + // HACK: due to this being stored as untyped ptrs, when deinit is called we are casted to a Component of some random // non-zero sized type. That will make is_empty_struct false in deinit always so we can't use it. Instead, we stick // a small dummy struct in the instances ArrayList so it can safely be deallocated. // Perhaps we should just allocate instances with a dummy allocator or the tmp allocator? - comptime var CompOrAlmostEmptyT = if (is_empty_struct) struct { dummy: u1 } else CompT; + comptime var ComponentOrDummy = if (is_empty_struct) struct { dummy: u1 } else Component; return struct { const Self = @This(); - set: *SparseSet(EntityT), - instances: std.ArrayList(CompOrAlmostEmptyT), + set: *SparseSet(Entity), + instances: std.ArrayList(ComponentOrDummy), allocator: ?*std.mem.Allocator, /// doesnt really belong here...used to denote group ownership super: usize = 0, safe_deinit: fn (*Self) void, - safe_swap: fn (*Self, EntityT, EntityT) void, - construction: Signal(EntityT), - update: Signal(EntityT), - destruction: Signal(EntityT), + safe_swap: fn (*Self, Entity, Entity) void, + construction: Signal(Entity), + update: Signal(Entity), + destruction: Signal(Entity), pub fn init(allocator: *std.mem.Allocator) Self { var store = Self{ - .set = SparseSet(EntityT).initPtr(allocator), + .set = SparseSet(Entity).initPtr(allocator), .instances = undefined, .safe_deinit = struct { fn deinit(self: *Self) void { @@ -45,21 +45,21 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { } }.deinit, .safe_swap = struct { - fn swap(self: *Self, lhs: EntityT, rhs: EntityT) void { + fn swap(self: *Self, lhs: Entity, rhs: Entity) void { if (!is_empty_struct) { - std.mem.swap(CompT, &self.instances.items[self.set.index(lhs)], &self.instances.items[self.set.index(rhs)]); + std.mem.swap(Component, &self.instances.items[self.set.index(lhs)], &self.instances.items[self.set.index(rhs)]); } self.set.swap(lhs, rhs); } }.swap, .allocator = null, - .construction = Signal(EntityT).init(allocator), - .update = Signal(EntityT).init(allocator), - .destruction = Signal(EntityT).init(allocator), + .construction = Signal(Entity).init(allocator), + .update = Signal(Entity).init(allocator), + .destruction = Signal(Entity).init(allocator), }; if (!is_empty_struct) { - store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator); + store.instances = std.ArrayList(ComponentOrDummy).init(allocator); } return store; @@ -67,15 +67,15 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { pub fn initPtr(allocator: *std.mem.Allocator) *Self { var store = allocator.create(Self) catch unreachable; - store.set = SparseSet(EntityT).initPtr(allocator); + store.set = SparseSet(Entity).initPtr(allocator); if (!is_empty_struct) { - store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator); + store.instances = std.ArrayList(ComponentOrDummy).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); + store.construction = Signal(Entity).init(allocator); + store.update = Signal(Entity).init(allocator); + store.destruction = Signal(Entity).init(allocator); // since we are stored as a pointer, we need to catpure this store.safe_deinit = struct { @@ -87,9 +87,9 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { }.deinit; store.safe_swap = struct { - fn swap(self: *Self, lhs: EntityT, rhs: EntityT) void { + fn swap(self: *Self, lhs: Entity, rhs: Entity) void { if (!is_empty_struct) { - std.mem.swap(CompT, &self.instances.items[self.set.index(lhs)], &self.instances.items[self.set.index(rhs)]); + std.mem.swap(Component, &self.instances.items[self.set.index(lhs)], &self.instances.items[self.set.index(rhs)]); } self.set.swap(lhs, rhs); } @@ -113,15 +113,15 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { } } - pub fn onConstruct(self: *Self) Sink(EntityT) { + pub fn onConstruct(self: *Self) Sink(Entity) { return self.construction.sink(); } - pub fn onUpdate(self: *Self) Sink(EntityT) { + pub fn onUpdate(self: *Self) Sink(Entity) { return self.update.sink(); } - pub fn onDestruct(self: *Self) Sink(EntityT) { + pub fn onDestruct(self: *Self) Sink(Entity) { return self.destruction.sink(); } @@ -134,7 +134,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { } /// Assigns an entity to a storage and assigns its object - pub fn add(self: *Self, entity: EntityT, value: CompT) void { + pub fn add(self: *Self, entity: Entity, value: Component) void { if (!is_empty_struct) { _ = self.instances.append(value) catch unreachable; } @@ -143,7 +143,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { } /// Removes an entity from a storage - pub fn remove(self: *Self, entity: EntityT) void { + pub fn remove(self: *Self, entity: Entity) void { self.destruction.publish(entity); if (!is_empty_struct) { _ = self.instances.swapRemove(self.set.index(entity)); @@ -152,7 +152,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { } /// Checks if a view contains an entity - pub fn contains(self: Self, entity: EntityT) bool { + pub fn contains(self: Self, entity: Entity) bool { return self.set.contains(entity); } @@ -163,49 +163,49 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { pub usingnamespace if (is_empty_struct) struct { /// Sort Entities according to the given comparison function - pub fn sort(self: Self, comptime sortFn: fn (void, EntityT, EntityT) bool) void { + pub fn sort(self: Self, comptime sortFn: fn (void, Entity, Entity) bool) void { self.set.sort(sortFn); } } else struct { /// Direct access to the array of objects - pub fn raw(self: Self) []CompT { + pub fn raw(self: Self) []Component { return self.instances.items; } /// Replaces the given component for an entity - pub fn replace(self: *Self, entity: EntityT, value: CompT) void { + pub fn replace(self: *Self, entity: Entity, value: Component) void { self.get(entity).* = value; self.update.publish(entity); } /// Returns the object associated with an entity - pub fn get(self: *Self, entity: EntityT) *CompT { + pub fn get(self: *Self, entity: Entity) *Component { std.debug.assert(self.contains(entity)); return &self.instances.items[self.set.index(entity)]; } - pub fn getConst(self: *Self, entity: EntityT) CompT { + pub fn getConst(self: *Self, entity: Entity) Component { return self.instances.items[self.set.index(entity)]; } /// Returns a pointer to the object associated with an entity, if any. - pub fn tryGet(self: *Self, entity: EntityT) ?*CompT { + pub fn tryGet(self: *Self, entity: Entity) ?*Component { return if (self.set.contains(entity)) &self.instances.items[self.set.index(entity)] else null; } - pub fn tryGetConst(self: *Self, entity: EntityT) ?CompT { + pub fn tryGetConst(self: *Self, entity: Entity) ?Component { return if (self.set.contains(entity)) self.instances.items[self.set.index(entity)] else null; } /// Sort Entities or Components according to the given comparison function pub fn sort(self: *Self, comptime T: type, comptime lessThan: fn (void, T, T) bool) void { - std.debug.assert(T == EntityT or T == CompT); - if (T == EntityT) { - self.set.sortSub(lessThan, CompT, self.instances.items); - } else if (T == CompT) { - self.set.sortSubSub({}, CompT, lessThan, self.instances.items); + std.debug.assert(T == Entity or T == Component); + if (T == Entity) { + self.set.sortSub(lessThan, Component, self.instances.items); + } else if (T == Component) { + self.set.sortSubSub({}, Component, lessThan, self.instances.items); // fn sorter(self: Self, a: T, b: T, sortFn) bool { // return sortFn(self.instances[a], self.instances[b]); // } @@ -215,17 +215,17 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type { }; /// Direct access to the array of entities - pub fn data(self: Self) []const EntityT { + pub fn data(self: Self) []const Entity { return self.set.data(); } /// Direct access to the array of entities - pub fn dataPtr(self: Self) *const []EntityT { + pub fn dataPtr(self: Self) *const []Entity { return self.set.dataPtr(); } /// Swaps entities and objects in the internal packed arrays - pub fn swap(self: *Self, lhs: EntityT, rhs: EntityT) void { + pub fn swap(self: *Self, lhs: Entity, rhs: Entity) void { self.safe_swap(self, lhs, rhs); }