bug fixes and speedup

master
Mike 5 years ago
parent cc92e4a225
commit 46c2af939e

@ -28,6 +28,7 @@ fn createEntities(reg: *ecs.Registry) void {
reg.add(e1, Position{ .x = 1, .y = 1 }); reg.add(e1, Position{ .x = 1, .y = 1 });
reg.add(e1, Velocity{ .x = 1, .y = 1 }); reg.add(e1, Velocity{ .x = 1, .y = 1 });
} }
var end = timer.lap(); var end = timer.lap();
std.debug.warn("create entities: \t{d}\n", .{@intToFloat(f64, end) / 1000000000}); std.debug.warn("create entities: \t{d}\n", .{@intToFloat(f64, end) / 1000000000});
} }
@ -104,11 +105,8 @@ fn owningGroup(reg: *ecs.Registry) void {
if (index == 0) break; if (index == 0) break;
index -= 1; index -= 1;
const ent = storage.set.dense.items[index]; pos[index].x += pos[index].x;
const entity_index = storage.set.index(ent); pos[index].y += pos[index].y;
pos[entity_index].x += pos[entity_index].x;
pos[entity_index].y += pos[entity_index].y;
} }
end = timer.lap(); end = timer.lap();

@ -27,8 +27,9 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
allocator: ?*std.mem.Allocator, allocator: ?*std.mem.Allocator,
/// doesnt really belong here...used to denote group ownership /// doesnt really belong here...used to denote group ownership
super: usize = 0, super: usize = 0,
safe_deinit: fn (*Self) void, safeDeinit: fn (*Self) void,
safe_swap: fn (*Self, Entity, Entity, bool) void, safeSwap: fn (*Self, Entity, Entity, bool) void,
safeRemoveIfContains: fn (*Self, Entity) void,
construction: Signal(Entity), construction: Signal(Entity),
update: Signal(Entity), update: Signal(Entity),
destruction: Signal(Entity), destruction: Signal(Entity),
@ -37,14 +38,14 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
var store = Self{ var store = Self{
.set = SparseSet(Entity).initPtr(allocator), .set = SparseSet(Entity).initPtr(allocator),
.instances = undefined, .instances = undefined,
.safe_deinit = struct { .safeDeinit = struct {
fn deinit(self: *Self) void { fn deinit(self: *Self) void {
if (!is_empty_struct) { if (!is_empty_struct) {
self.instances.deinit(); self.instances.deinit();
} }
} }
}.deinit, }.deinit,
.safe_swap = struct { .safeSwap = struct {
fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void { fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void {
if (!is_empty_struct) { if (!is_empty_struct) {
std.mem.swap(Component, &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)]);
@ -52,6 +53,13 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
if (!instances_only) self.set.swap(lhs, rhs); if (!instances_only) self.set.swap(lhs, rhs);
} }
}.swap, }.swap,
.safeRemoveIfContains = struct {
fn removeIfContains(self: *Self, entity: Entity) void {
if (self.contains(entity)) {
self.remove(entity);
}
}
}.removeIfContains,
.allocator = null, .allocator = null,
.construction = Signal(Entity).init(allocator), .construction = Signal(Entity).init(allocator),
.update = Signal(Entity).init(allocator), .update = Signal(Entity).init(allocator),
@ -78,7 +86,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
store.destruction = Signal(Entity).init(allocator); store.destruction = Signal(Entity).init(allocator);
// since we are stored as a pointer, we need to catpure this // since we are stored as a pointer, we need to catpure this
store.safe_deinit = struct { store.safeDeinit = struct {
fn deinit(self: *Self) void { fn deinit(self: *Self) void {
if (!is_empty_struct) { if (!is_empty_struct) {
self.instances.deinit(); self.instances.deinit();
@ -86,7 +94,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
} }
}.deinit; }.deinit;
store.safe_swap = struct { store.safeSwap = struct {
fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void { fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void {
if (!is_empty_struct) { if (!is_empty_struct) {
std.mem.swap(Component, &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)]);
@ -95,6 +103,14 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
} }
}.swap; }.swap;
store.safeRemoveIfContains = struct {
fn removeIfContains(self: *Self, entity: Entity) void {
if (self.contains(entity)) {
self.remove(entity);
}
}
}.removeIfContains;
return store; return store;
} }
@ -102,7 +118,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
// great care must be taken here. Due to how Registry keeps this struct as pointers anything touching a type // great care must be taken here. Due to how Registry keeps this struct as pointers anything touching a type
// will be wrong since it has to cast to a random struct when deiniting. Because of all that, is_empty_struct // will be wrong since it has to cast to a random struct when deiniting. Because of all that, is_empty_struct
// will allways be false here so we have to deinit the instances no matter what. // will allways be false here so we have to deinit the instances no matter what.
self.safe_deinit(self); self.safeDeinit(self);
self.set.deinit(); self.set.deinit();
self.construction.deinit(); self.construction.deinit();
self.update.deinit(); self.update.deinit();
@ -156,6 +172,14 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
return self.set.contains(entity); return self.set.contains(entity);
} }
pub fn removeIfContains(self: *Self, entity: Entity) void {
if (Component == u1) {
self.safeRemoveIfContains(self, entity);
} else if (self.contains(entity)) {
self.remove(entity);
}
}
pub fn len(self: Self) usize { pub fn len(self: Self) usize {
return self.set.len(); return self.set.len();
} }
@ -213,10 +237,10 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
storage: *Self, storage: *Self,
pub fn swap(this: @This(), a: Entity, b: Entity) void { pub fn swap(this: @This(), a: Entity, b: Entity) void {
this.storage.safe_swap(this.storage, a, b, true); this.storage.safeSwap(this.storage, a, b, true);
} }
}; };
const swap_context = SortContext{.storage = self}; const swap_context = SortContext{ .storage = self };
self.set.arrange(length, context, lessThan, swap_context); self.set.arrange(length, context, lessThan, swap_context);
} else { } else {
const SortContext = struct { const SortContext = struct {
@ -231,11 +255,11 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
} }
pub fn swap(this: @This(), a: Entity, b: Entity) void { pub fn swap(this: @This(), a: Entity, b: Entity) void {
this.storage.safe_swap(this.storage, a, b, true); this.storage.safeSwap(this.storage, a, b, true);
} }
}; };
const swap_context = SortContext{.storage = self, .wrapped_context = context, .lessThan = lessThan}; const swap_context = SortContext{ .storage = self, .wrapped_context = context, .lessThan = lessThan };
self.set.arrange(length, swap_context, SortContext.sort, swap_context); self.set.arrange(length, swap_context, SortContext.sort, swap_context);
} }
} }
@ -253,7 +277,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
/// Swaps entities and objects in the internal packed arrays /// Swaps entities and objects in the internal packed arrays
pub fn swap(self: *Self, lhs: Entity, rhs: Entity) void { pub fn swap(self: *Self, lhs: Entity, rhs: Entity) void {
self.safe_swap(self, lhs, rhs, false); self.safeSwap(self, lhs, rhs, false);
} }
pub fn clear(self: *Self) void { pub fn clear(self: *Self) void {

@ -101,14 +101,11 @@ pub const OwningGroup = struct {
if (it.index == 0) return null; if (it.index == 0) return null;
it.index -= 1; it.index -= 1;
const ent = it.storage.set.dense.items[it.index];
const entity_index = it.storage.set.index(ent);
// fill and return the struct // fill and return the struct
var comps: Components = undefined; var comps: Components = undefined;
inline for (@typeInfo(Components).Struct.fields) |field, i| { inline for (@typeInfo(Components).Struct.fields) |field, i| {
const typed_ptr = @ptrCast([*]field.field_type.Child, @alignCast(@alignOf(field.field_type.Child), it.component_ptrs[i])); const typed_ptr = @ptrCast([*]field.field_type.Child, @alignCast(@alignOf(field.field_type.Child), it.component_ptrs[i]));
@field(comps, field.name) = &typed_ptr[entity_index]; @field(comps, field.name) = &typed_ptr[it.index];
} }
return comps; return comps;
} }
@ -200,36 +197,9 @@ pub const OwningGroup = struct {
self.validate(Components); self.validate(Components);
// optionally we could just use an Iterator here and pay for some slight indirection for code sharing // optionally we could just use an Iterator here and pay for some slight indirection for code sharing
// var iter = self.iterator(Components); var iter = self.iterator(Components);
// while (iter.next()) |comps| { while (iter.next()) |comps| {
// @call(.{ .modifier = .always_inline }, func, .{comps}); @call(.{ .modifier = .always_inline }, func, .{comps});
// }
const component_info = @typeInfo(Components).Struct;
// get the data pointers for the requested component types
var component_ptrs: [component_info.fields.len][*]u8 = undefined;
inline for (component_info.fields) |field, i| {
const storage = self.registry.assure(field.field_type.Child);
component_ptrs[i] = @ptrCast([*]u8, storage.instances.items.ptr);
}
var storage = self.firstOwnedStorage();
var index: usize = self.group_data.current;
while (true) {
if (index == 0) return;
index -= 1;
const ent = storage.set.dense.items[index];
const entity_index = storage.set.index(ent);
var comps: Components = undefined;
inline for (component_info.fields) |field, i| {
const typed_ptr = @ptrCast([*]field.field_type.Child, @alignCast(@alignOf(field.field_type.Child), component_ptrs[i]));
@field(comps, field.name) = &typed_ptr[entity_index];
}
func(comps);
} }
} }

@ -334,8 +334,9 @@ pub const Registry = struct {
pub fn removeIfExists(self: *Registry, comptime T: type, entity: Entity) void { pub fn removeIfExists(self: *Registry, comptime T: type, entity: Entity) void {
assert(self.valid(entity)); assert(self.valid(entity));
var store = self.assure(T); var store = self.assure(T);
if (store.contains(entity)) if (store.contains(entity)) {
store.remove(entity); store.remove(entity);
}
} }
/// Removes all the components from an entity and makes it orphaned /// Removes all the components from an entity and makes it orphaned
@ -345,8 +346,8 @@ pub const Registry = struct {
var it = self.components.iterator(); var it = self.components.iterator();
while (it.next()) |ptr| { while (it.next()) |ptr| {
// HACK: we dont know the Type here but we need to be able to call methods on the Storage(T) // HACK: we dont know the Type here but we need to be able to call methods on the Storage(T)
var store = @intToPtr(*Storage(u128), ptr.value); var store = @intToPtr(*Storage(u1), ptr.value);
if (store.contains(entity)) store.remove(entity); store.removeIfContains(entity);
} }
} }

Loading…
Cancel
Save