2020-06-02 19:55:24 -07:00
|
|
|
const std = @import("std");
|
|
|
|
const utils = @import("utils.zig");
|
|
|
|
|
|
|
|
const Registry = @import("registry.zig").Registry;
|
|
|
|
const Storage = @import("registry.zig").Storage;
|
2020-06-03 15:01:30 -07:00
|
|
|
const SparseSet = @import("sparse_set.zig").SparseSet;
|
2020-06-02 19:55:24 -07:00
|
|
|
const Entity = @import("registry.zig").Entity;
|
|
|
|
|
2020-06-03 15:01:30 -07:00
|
|
|
/// BasicGroups do not own any components
|
2020-06-08 11:27:49 -07:00
|
|
|
pub const BasicGroup = struct {
|
|
|
|
const Self = @This();
|
2020-06-03 15:01:30 -07:00
|
|
|
|
2020-06-08 11:27:49 -07:00
|
|
|
registry: *Registry,
|
|
|
|
group_data: *Registry.GroupData,
|
2020-06-03 15:01:30 -07:00
|
|
|
|
2020-06-08 11:27:49 -07:00
|
|
|
pub const Iterator = struct {
|
|
|
|
index: usize = 0,
|
2020-06-09 10:21:42 -07:00
|
|
|
entities: []const Entity,
|
2020-06-03 15:01:30 -07:00
|
|
|
|
2020-06-09 10:21:42 -07:00
|
|
|
pub fn init(entities: []const Entity) Iterator {
|
|
|
|
return .{ .entities = entities };
|
2020-06-03 15:01:30 -07:00
|
|
|
}
|
|
|
|
|
2020-06-08 11:27:49 -07:00
|
|
|
pub fn next(it: *Iterator) ?Entity {
|
|
|
|
if (it.index >= it.entities.len) return null;
|
2020-06-03 15:01:30 -07:00
|
|
|
|
2020-06-08 11:27:49 -07:00
|
|
|
it.index += 1;
|
2020-06-09 10:21:42 -07:00
|
|
|
return it.entities[it.index - 1];
|
2020-06-03 15:01:30 -07:00
|
|
|
}
|
|
|
|
|
2020-06-08 11:27:49 -07:00
|
|
|
// Reset the iterator to the initial index
|
|
|
|
pub fn reset(it: *Iterator) void {
|
|
|
|
it.index = 0;
|
2020-06-03 15:01:30 -07:00
|
|
|
}
|
2020-06-02 19:55:24 -07:00
|
|
|
};
|
2020-06-08 11:27:49 -07:00
|
|
|
|
|
|
|
pub fn init(registry: *Registry, group_data: *Registry.GroupData) Self {
|
|
|
|
return Self{
|
|
|
|
.registry = registry,
|
|
|
|
.group_data = group_data,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn len(self: Self) usize {
|
|
|
|
return self.group_data.entity_set.len();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Direct access to the array of entities
|
2020-06-09 10:21:42 -07:00
|
|
|
pub fn data(self: Self) []const Entity {
|
2020-06-08 11:27:49 -07:00
|
|
|
return self.group_data.entity_set.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(self: *Self, comptime T: type, entity: Entity) *T {
|
|
|
|
return self.registry.assure(T).get(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn getConst(self: *Self, comptime T: type, entity: Entity) T {
|
|
|
|
return self.registry.assure(T).getConst(entity);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iterator(self: *Self) Iterator {
|
2020-06-09 10:21:42 -07:00
|
|
|
return Iterator.init(self.group_data.entity_set.data());
|
2020-06-08 11:27:49 -07:00
|
|
|
}
|
|
|
|
};
|
2020-06-02 19:55:24 -07:00
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
pub const OwningGroup = struct {
|
|
|
|
registry: *Registry,
|
|
|
|
group_data: *Registry.GroupData,
|
|
|
|
super: *usize,
|
|
|
|
|
|
|
|
pub fn init(registry: *Registry, group_data: *Registry.GroupData, super: *usize) OwningGroup {
|
|
|
|
return .{
|
|
|
|
.registry = registry,
|
|
|
|
.group_data = group_data,
|
|
|
|
.super = super,
|
|
|
|
};
|
|
|
|
}
|
2020-06-03 23:33:59 -07:00
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
pub fn len(self: OwningGroup) usize {
|
|
|
|
return self.group_data.current;
|
|
|
|
}
|
2020-06-07 17:28:42 -07:00
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
pub fn sortable(self: OwningGroup, comptime T: type) bool {
|
|
|
|
return self.group_data.super == self.group_data.size;
|
|
|
|
}
|
|
|
|
};
|
2020-06-03 23:33:59 -07:00
|
|
|
|
2020-06-09 10:21:42 -07:00
|
|
|
test "BasicGroup creation/iteration" {
|
2020-06-02 19:55:24 -07:00
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
2020-06-03 15:01:30 -07:00
|
|
|
var group = reg.group(.{}, .{ i32, u32 }, .{});
|
|
|
|
std.testing.expectEqual(group.len(), 0);
|
|
|
|
|
2020-06-02 19:55:24 -07:00
|
|
|
var e0 = reg.create();
|
2020-06-03 15:01:30 -07:00
|
|
|
reg.add(e0, @as(i32, 44));
|
|
|
|
reg.add(e0, @as(u32, 55));
|
|
|
|
|
|
|
|
std.debug.assert(group.len() == 1);
|
2020-06-02 19:55:24 -07:00
|
|
|
|
2020-06-03 15:01:30 -07:00
|
|
|
var iterated_entities: usize = 0;
|
|
|
|
var iter = group.iterator();
|
|
|
|
while (iter.next()) |entity| {
|
|
|
|
iterated_entities += 1;
|
|
|
|
}
|
|
|
|
std.testing.expectEqual(iterated_entities, 1);
|
|
|
|
|
2020-06-09 10:21:42 -07:00
|
|
|
iterated_entities = 0;
|
|
|
|
for (group.data()) |entity| {
|
|
|
|
iterated_entities += 1;
|
|
|
|
}
|
|
|
|
std.testing.expectEqual(iterated_entities, 1);
|
|
|
|
|
2020-06-03 15:01:30 -07:00
|
|
|
reg.remove(i32, e0);
|
|
|
|
std.debug.assert(group.len() == 0);
|
|
|
|
}
|
2020-06-03 15:09:25 -07:00
|
|
|
|
2020-06-03 15:25:27 -07:00
|
|
|
test "BasicGroup excludes" {
|
2020-06-03 15:09:25 -07:00
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
var group = reg.group(.{}, .{i32}, .{u32});
|
2020-06-03 15:09:25 -07:00
|
|
|
std.testing.expectEqual(group.len(), 0);
|
|
|
|
|
|
|
|
var e0 = reg.create();
|
|
|
|
reg.add(e0, @as(i32, 44));
|
|
|
|
|
|
|
|
std.debug.assert(group.len() == 1);
|
|
|
|
|
|
|
|
var iterated_entities: usize = 0;
|
|
|
|
var iter = group.iterator();
|
|
|
|
while (iter.next()) |entity| {
|
|
|
|
iterated_entities += 1;
|
|
|
|
}
|
|
|
|
std.testing.expectEqual(iterated_entities, 1);
|
|
|
|
|
|
|
|
reg.add(e0, @as(u32, 55));
|
|
|
|
std.debug.assert(group.len() == 0);
|
2020-06-03 15:25:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
test "BasicGroup create late" {
|
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
|
|
|
var e0 = reg.create();
|
|
|
|
reg.add(e0, @as(i32, 44));
|
|
|
|
reg.add(e0, @as(u32, 55));
|
|
|
|
|
|
|
|
var group = reg.group(.{}, .{ i32, u32 }, .{});
|
|
|
|
std.testing.expectEqual(group.len(), 1);
|
2020-06-03 23:33:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
test "OwningGroup" {
|
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
var group = reg.group(.{ i32, u32 }, .{}, .{});
|
2020-06-03 23:33:59 -07:00
|
|
|
|
|
|
|
var e0 = reg.create();
|
|
|
|
reg.add(e0, @as(i32, 44));
|
|
|
|
reg.add(e0, @as(u32, 55));
|
|
|
|
std.testing.expectEqual(group.len(), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
test "OwningGroup add/remove" {
|
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
var group = reg.group(.{ i32, u32 }, .{}, .{});
|
2020-06-03 23:33:59 -07:00
|
|
|
|
|
|
|
var e0 = reg.create();
|
|
|
|
reg.add(e0, @as(i32, 44));
|
|
|
|
reg.add(e0, @as(u32, 55));
|
|
|
|
std.testing.expectEqual(group.len(), 1);
|
|
|
|
|
|
|
|
reg.remove(i32, e0);
|
|
|
|
std.testing.expectEqual(group.len(), 0);
|
2020-06-07 17:28:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
test "multiple OwningGroups" {
|
|
|
|
const Sprite = struct { x: f32 };
|
|
|
|
const Transform = struct { x: f32 };
|
|
|
|
const Renderable = struct { x: f32 };
|
|
|
|
const Rotation = struct { x: f32 };
|
|
|
|
|
|
|
|
var reg = Registry.init(std.testing.allocator);
|
|
|
|
defer reg.deinit();
|
|
|
|
|
|
|
|
// var group1 = reg.group(.{u64, u32}, .{}, .{});
|
|
|
|
// var group2 = reg.group(.{u64, u32, u8}, .{}, .{});
|
|
|
|
|
2020-06-08 11:06:15 -07:00
|
|
|
var group5 = reg.group(.{ Sprite, Transform }, .{ Renderable, Rotation }, .{});
|
2020-06-07 17:28:42 -07:00
|
|
|
var group3 = reg.group(.{Sprite}, .{Renderable}, .{});
|
2020-06-08 11:06:15 -07:00
|
|
|
var group4 = reg.group(.{ Sprite, Transform }, .{Renderable}, .{});
|
2020-06-07 17:28:42 -07:00
|
|
|
|
|
|
|
var last_size: u8 = 0;
|
|
|
|
for (reg.groups.items) |grp| {
|
|
|
|
std.testing.expect(last_size <= grp.size);
|
|
|
|
last_size = grp.size;
|
|
|
|
std.debug.warn("grp: {}\n", .{grp.size});
|
|
|
|
}
|
|
|
|
|
|
|
|
std.testing.expect(!reg.sortable(Sprite));
|
|
|
|
|
|
|
|
// this will break the group
|
|
|
|
// var group6 = reg.group(.{Sprite, Rotation}, .{}, .{});
|
2020-06-07 22:10:52 -07:00
|
|
|
}
|