bug fixes and speedup

master
Mike 4 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, Velocity{ .x = 1, .y = 1 });
}
var end = timer.lap();
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;
index -= 1;
const ent = storage.set.dense.items[index];
const entity_index = storage.set.index(ent);
pos[entity_index].x += pos[entity_index].x;
pos[entity_index].y += pos[entity_index].y;
pos[index].x += pos[index].x;
pos[index].y += pos[index].y;
}
end = timer.lap();

@ -27,8 +27,9 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
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, Entity, Entity, bool) void,
safeDeinit: fn (*Self) void,
safeSwap: fn (*Self, Entity, Entity, bool) void,
safeRemoveIfContains: fn (*Self, Entity) void,
construction: Signal(Entity),
update: Signal(Entity),
destruction: Signal(Entity),
@ -37,14 +38,14 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
var store = Self{
.set = SparseSet(Entity).initPtr(allocator),
.instances = undefined,
.safe_deinit = struct {
.safeDeinit = struct {
fn deinit(self: *Self) void {
if (!is_empty_struct) {
self.instances.deinit();
}
}
}.deinit,
.safe_swap = struct {
.safeSwap = struct {
fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void {
if (!is_empty_struct) {
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);
}
}.swap,
.safeRemoveIfContains = struct {
fn removeIfContains(self: *Self, entity: Entity) void {
if (self.contains(entity)) {
self.remove(entity);
}
}
}.removeIfContains,
.allocator = null,
.construction = 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);
// since we are stored as a pointer, we need to catpure this
store.safe_deinit = struct {
store.safeDeinit = struct {
fn deinit(self: *Self) void {
if (!is_empty_struct) {
self.instances.deinit();
@ -86,7 +94,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
}
}.deinit;
store.safe_swap = struct {
store.safeSwap = struct {
fn swap(self: *Self, lhs: Entity, rhs: Entity, instances_only: bool) void {
if (!is_empty_struct) {
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;
store.safeRemoveIfContains = struct {
fn removeIfContains(self: *Self, entity: Entity) void {
if (self.contains(entity)) {
self.remove(entity);
}
}
}.removeIfContains;
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
// 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.
self.safe_deinit(self);
self.safeDeinit(self);
self.set.deinit();
self.construction.deinit();
self.update.deinit();
@ -156,6 +172,14 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
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 {
return self.set.len();
}
@ -213,10 +237,10 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
storage: *Self,
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);
} else {
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 {
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);
}
}
@ -253,7 +277,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
/// Swaps entities and objects in the internal packed arrays
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 {

@ -101,14 +101,11 @@ pub const OwningGroup = struct {
if (it.index == 0) return null;
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
var comps: Components = undefined;
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]));
@field(comps, field.name) = &typed_ptr[entity_index];
@field(comps, field.name) = &typed_ptr[it.index];
}
return comps;
}
@ -200,36 +197,9 @@ pub const OwningGroup = struct {
self.validate(Components);
// optionally we could just use an Iterator here and pay for some slight indirection for code sharing
// var iter = self.iterator(Components);
// while (iter.next()) |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);
var iter = self.iterator(Components);
while (iter.next()) |comps| {
@call(.{ .modifier = .always_inline }, func, .{comps});
}
}

@ -334,8 +334,9 @@ pub const Registry = struct {
pub fn removeIfExists(self: *Registry, comptime T: type, entity: Entity) void {
assert(self.valid(entity));
var store = self.assure(T);
if (store.contains(entity))
if (store.contains(entity)) {
store.remove(entity);
}
}
/// Removes all the components from an entity and makes it orphaned
@ -345,8 +346,8 @@ pub const Registry = struct {
var it = self.components.iterator();
while (it.next()) |ptr| {
// 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);
if (store.contains(entity)) store.remove(entity);
var store = @intToPtr(*Storage(u1), ptr.value);
store.removeIfContains(entity);
}
}

Loading…
Cancel
Save