add excludes to Views
This commit is contained in:
parent
0b2542d292
commit
61d882d1a8
@ -19,7 +19,7 @@ pub fn main() !void {
|
|||||||
reg.add(e2, Position{ .x = 10, .y = 10 });
|
reg.add(e2, Position{ .x = 10, .y = 10 });
|
||||||
reg.add(e2, Velocity{ .x = 15, .y = 17 });
|
reg.add(e2, Velocity{ .x = 15, .y = 17 });
|
||||||
|
|
||||||
var view = reg.view(.{ Velocity, Position });
|
var view = reg.view(.{ Velocity, Position }, .{});
|
||||||
|
|
||||||
var iter = view.iterator();
|
var iter = view.iterator();
|
||||||
while (iter.next()) |entity| {
|
while (iter.next()) |entity| {
|
||||||
|
@ -254,24 +254,34 @@ pub const Registry = struct {
|
|||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn view(self: *Registry, comptime includes: var) ViewType(includes) {
|
pub fn view(self: *Registry, comptime includes: var, comptime excludes: var) ViewType(includes, excludes) {
|
||||||
|
if (@typeInfo(@TypeOf(includes)) != .Struct)
|
||||||
|
@compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
|
||||||
|
if (@typeInfo(@TypeOf(excludes)) != .Struct)
|
||||||
|
@compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(excludes)));
|
||||||
std.debug.assert(includes.len > 0);
|
std.debug.assert(includes.len > 0);
|
||||||
|
|
||||||
if (includes.len == 1)
|
if (includes.len == 1 and excludes.len == 0)
|
||||||
return BasicView(includes[0]).init(self.assure(includes[0]));
|
return BasicView(includes[0]).init(self.assure(includes[0]));
|
||||||
|
|
||||||
var arr: [includes.len]u32 = undefined;
|
var includes_arr: [includes.len]u32 = undefined;
|
||||||
inline for (includes) |t, i| {
|
inline for (includes) |t, i| {
|
||||||
_ = self.assure(t);
|
_ = self.assure(t);
|
||||||
arr[i] = @as(u32, self.typemap.get(t));
|
includes_arr[i] = @as(u32, self.typemap.get(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
return BasicMultiView(includes.len).init(arr, self);
|
var excludes_arr: [excludes.len]u32 = undefined;
|
||||||
|
inline for (excludes) |t, i| {
|
||||||
|
_ = self.assure(t);
|
||||||
|
excludes_arr[i] = @as(u32, self.typemap.get(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ViewType(comptime includes: var) type {
|
return BasicMultiView(includes.len, excludes.len).init(includes_arr, excludes_arr, self);
|
||||||
if (includes.len == 1) return BasicView(includes[0]);
|
}
|
||||||
return BasicMultiView(includes.len);
|
|
||||||
|
fn ViewType(comptime includes: var, comptime excludes: var) type {
|
||||||
|
if (includes.len == 1 and excludes.len == 0) return BasicView(includes[0]);
|
||||||
|
return BasicMultiView(includes.len, excludes.len);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ const Registry = @import("registry.zig").Registry;
|
|||||||
const Storage = @import("registry.zig").Storage;
|
const Storage = @import("registry.zig").Storage;
|
||||||
const Entity = @import("registry.zig").Entity;
|
const Entity = @import("registry.zig").Entity;
|
||||||
|
|
||||||
|
|
||||||
/// single item view. Iterating raw() directly is the fastest way to get at the data.
|
/// single item view. Iterating raw() directly is the fastest way to get at the data.
|
||||||
pub fn BasicView(comptime T: type) type {
|
pub fn BasicView(comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
@ -37,14 +36,19 @@ pub fn BasicView(comptime T: type) type {
|
|||||||
pub fn get(self: Self, entity: Entity) *T {
|
pub fn get(self: Self, entity: Entity) *T {
|
||||||
return self.storage.get(entity);
|
return self.storage.get(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getConst(self: *Self, comptime T: type, entity: Entity) T {
|
||||||
|
return self.storage.getConst(entity);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn BasicMultiView(comptime n: usize) type {
|
pub fn BasicMultiView(comptime n_includes: usize, comptime n_excludes: usize) type {
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
type_ids: [n]u32,
|
type_ids: [n_includes]u32,
|
||||||
|
exclude_type_ids: [n_excludes]u32,
|
||||||
registry: *Registry,
|
registry: *Registry,
|
||||||
|
|
||||||
pub const Iterator = struct {
|
pub const Iterator = struct {
|
||||||
@ -69,10 +73,19 @@ pub fn BasicMultiView(comptime n: usize) type {
|
|||||||
// entity must be in all other Storages
|
// entity must be in all other Storages
|
||||||
for (it.view.type_ids) |tid| {
|
for (it.view.type_ids) |tid| {
|
||||||
const ptr = it.view.registry.components.getValue(@intCast(u8, tid)).?;
|
const ptr = it.view.registry.components.getValue(@intCast(u8, tid)).?;
|
||||||
if (!@intToPtr(*Storage(u8), ptr).contains(entity)) {
|
if (!@intToPtr(*Storage(u1), ptr).contains(entity)) {
|
||||||
break :blk;
|
break :blk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// entity must not be in all other excluded Storages
|
||||||
|
for (it.view.exclude_type_ids) |tid| {
|
||||||
|
const ptr = it.view.registry.components.getValue(@intCast(u8, tid)).?;
|
||||||
|
if (@intToPtr(*Storage(u1), ptr).contains(entity)) {
|
||||||
|
break :blk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
it.index += 1;
|
it.index += 1;
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
@ -86,9 +99,10 @@ pub fn BasicMultiView(comptime n: usize) type {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn init(type_ids: [n]u32, registry: *Registry) Self {
|
pub fn init(type_ids: [n_includes]u32, exclude_type_ids: [n_excludes]u32, registry: *Registry) Self {
|
||||||
return Self{
|
return Self{
|
||||||
.type_ids = type_ids,
|
.type_ids = type_ids,
|
||||||
|
.exclude_type_ids = exclude_type_ids,
|
||||||
.registry = registry,
|
.registry = registry,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -97,8 +111,6 @@ pub fn BasicMultiView(comptime n: usize) type {
|
|||||||
const type_id = self.registry.typemap.get(T);
|
const type_id = self.registry.typemap.get(T);
|
||||||
const ptr = self.registry.components.getValue(type_id).?;
|
const ptr = self.registry.components.getValue(type_id).?;
|
||||||
const store = @intToPtr(*Storage(T), ptr);
|
const store = @intToPtr(*Storage(T), ptr);
|
||||||
|
|
||||||
std.debug.assert(store.contains(entity));
|
|
||||||
return store.get(entity);
|
return store.get(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,14 +118,12 @@ pub fn BasicMultiView(comptime n: usize) type {
|
|||||||
const type_id = self.registry.typemap.get(T);
|
const type_id = self.registry.typemap.get(T);
|
||||||
const ptr = self.registry.components.getValue(type_id).?;
|
const ptr = self.registry.components.getValue(type_id).?;
|
||||||
const store = @intToPtr(*Storage(T), ptr);
|
const store = @intToPtr(*Storage(T), ptr);
|
||||||
|
|
||||||
std.debug.assert(store.contains(entity));
|
|
||||||
return store.getConst(entity);
|
return store.getConst(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort(self: *Self) void {
|
fn sort(self: *Self) void {
|
||||||
// get our component counts in an array so we can sort the type_ids based on how many entities are in each
|
// get our component counts in an array so we can sort the type_ids based on how many entities are in each
|
||||||
var sub_items: [n]usize = undefined;
|
var sub_items: [n_includes]usize = undefined;
|
||||||
for (self.type_ids) |tid, i| {
|
for (self.type_ids) |tid, i| {
|
||||||
const ptr = self.registry.components.getValue(@intCast(u8, tid)).?;
|
const ptr = self.registry.components.getValue(@intCast(u8, tid)).?;
|
||||||
const store = @intToPtr(*Storage(u8), ptr);
|
const store = @intToPtr(*Storage(u8), ptr);
|
||||||
@ -130,7 +140,6 @@ pub fn BasicMultiView(comptime n: usize) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
test "single basic view" {
|
test "single basic view" {
|
||||||
var store = Storage(f32).init(std.testing.allocator);
|
var store = Storage(f32).init(std.testing.allocator);
|
||||||
defer store.deinit();
|
defer store.deinit();
|
||||||
@ -194,8 +203,8 @@ test "basic multi view" {
|
|||||||
reg.add(e0, @as(u32, 0));
|
reg.add(e0, @as(u32, 0));
|
||||||
reg.add(e2, @as(u32, 2));
|
reg.add(e2, @as(u32, 2));
|
||||||
|
|
||||||
var single_view = reg.view(.{u32});
|
var single_view = reg.view(.{u32}, .{});
|
||||||
var view = reg.view(.{ i32, u32 });
|
var view = reg.view(.{ i32, u32 }, .{});
|
||||||
|
|
||||||
var iterated_entities: usize = 0;
|
var iterated_entities: usize = 0;
|
||||||
var iter = view.iterator();
|
var iter = view.iterator();
|
||||||
@ -215,3 +224,41 @@ test "basic multi view" {
|
|||||||
|
|
||||||
std.testing.expectEqual(iterated_entities, 1);
|
std.testing.expectEqual(iterated_entities, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "basic multi view with excludes" {
|
||||||
|
var reg = Registry.init(std.testing.allocator);
|
||||||
|
defer reg.deinit();
|
||||||
|
|
||||||
|
var e0 = reg.create();
|
||||||
|
var e1 = reg.create();
|
||||||
|
var e2 = reg.create();
|
||||||
|
|
||||||
|
reg.add(e0, @as(i32, -0));
|
||||||
|
reg.add(e1, @as(i32, -1));
|
||||||
|
reg.add(e2, @as(i32, -2));
|
||||||
|
|
||||||
|
reg.add(e0, @as(u32, 0));
|
||||||
|
reg.add(e2, @as(u32, 2));
|
||||||
|
|
||||||
|
reg.add(e2, @as(u8, 255));
|
||||||
|
|
||||||
|
var view = reg.view(.{ i32, u32 }, .{u8});
|
||||||
|
|
||||||
|
var iterated_entities: usize = 0;
|
||||||
|
var iter = view.iterator();
|
||||||
|
while (iter.next()) |entity| {
|
||||||
|
iterated_entities += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.testing.expectEqual(iterated_entities, 1);
|
||||||
|
iterated_entities = 0;
|
||||||
|
|
||||||
|
reg.remove(u8, e2);
|
||||||
|
|
||||||
|
iter.reset();
|
||||||
|
while (iter.next()) |entity| {
|
||||||
|
iterated_entities += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std.testing.expectEqual(iterated_entities, 2);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user