udpate to Zig master
This commit is contained in:
parent
f2a302b7a4
commit
bdb4b0537d
@ -1,6 +1,8 @@
|
||||
// ecs
|
||||
pub const EntityTraitsType = @import("ecs/entity.zig").EntityTraitsType;
|
||||
|
||||
pub const ComponentStorage = @import("ecs/component_storage.zig").ComponentStorage;
|
||||
|
||||
pub const Entity = @import("ecs/registry.zig").Entity;
|
||||
pub const Registry = @import("ecs/registry.zig").Registry;
|
||||
pub const BasicView = @import("ecs/views.zig").BasicView;
|
||||
|
@ -17,9 +17,7 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
// 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 = CompT;
|
||||
if (is_empty_struct)
|
||||
CompOrAlmostEmptyT = struct { dummy: u1 };
|
||||
comptime var CompOrAlmostEmptyT = if (is_empty_struct) struct { dummy: u1 } else CompT;
|
||||
|
||||
return struct {
|
||||
const Self = @This();
|
||||
@ -27,7 +25,8 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
set: *SparseSet(EntityT),
|
||||
instances: std.ArrayList(CompOrAlmostEmptyT),
|
||||
allocator: ?*std.mem.Allocator,
|
||||
super: usize = 0, /// doesnt really belong here...used to denote group ownership
|
||||
/// 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),
|
||||
@ -40,14 +39,16 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
.instances = undefined,
|
||||
.safe_deinit = struct {
|
||||
fn deinit(self: *Self) void {
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
self.instances.deinit();
|
||||
}
|
||||
}
|
||||
}.deinit,
|
||||
.safe_swap = struct {
|
||||
fn swap(self: *Self, lhs: EntityT, rhs: EntityT) void {
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
std.mem.swap(CompT, &self.instances.items[self.set.index(lhs)], &self.instances.items[self.set.index(rhs)]);
|
||||
}
|
||||
self.set.swap(lhs, rhs);
|
||||
}
|
||||
}.swap,
|
||||
@ -57,8 +58,9 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
.destruction = Signal(EntityT).init(allocator),
|
||||
};
|
||||
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator);
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
@ -66,8 +68,9 @@ 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);
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
store.instances = std.ArrayList(CompOrAlmostEmptyT).init(allocator);
|
||||
}
|
||||
store.allocator = allocator;
|
||||
store.super = 0;
|
||||
store.construction = Signal(EntityT).init(allocator);
|
||||
@ -77,8 +80,9 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
// since we are stored as a pointer, we need to catpure this
|
||||
store.safe_deinit = struct {
|
||||
fn deinit(self: *Self) void {
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
self.instances.deinit();
|
||||
}
|
||||
}
|
||||
}.deinit;
|
||||
|
||||
@ -157,7 +161,12 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
}
|
||||
|
||||
pub usingnamespace if (is_empty_struct)
|
||||
struct {}
|
||||
struct {
|
||||
/// Sort Entities according to the given comparison function
|
||||
pub fn sort(self: Self, comptime sortFn: fn (void, EntityT, EntityT) bool) void {
|
||||
self.set.sort(sortFn);
|
||||
}
|
||||
}
|
||||
else
|
||||
struct {
|
||||
/// Direct access to the array of objects
|
||||
@ -189,6 +198,21 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
pub fn tryGetConst(self: *Self, entity: EntityT) ?CompT {
|
||||
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 sortFn: fn (void, T, T) bool) void {
|
||||
std.debug.assert(T == EntityT or T == CompT);
|
||||
if (T == EntityT) {
|
||||
self.set.sortSub(sortFn, CompT, self.instances.items);
|
||||
} else if (T == CompT) {
|
||||
// essentially need to be able to call a sort method with a bound fn. That fn would then use sortFn along
|
||||
// with self.instances.
|
||||
// fn sorter(self: Self, a: T, b: T, sortFn) bool {
|
||||
// return sortFn(self.instances[a], self.instances[b]);
|
||||
// }
|
||||
//return compare(std::as_const(instances[underlying_type::index(lhs)]), std::as_const(instances[underlying_type::index(rhs)]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Direct access to the array of entities
|
||||
@ -207,8 +231,9 @@ pub fn ComponentStorage(comptime CompT: type, comptime EntityT: type) type {
|
||||
}
|
||||
|
||||
pub fn clear(self: *Self) void {
|
||||
if (!is_empty_struct)
|
||||
if (!is_empty_struct) {
|
||||
self.instances.items.len = 0;
|
||||
}
|
||||
self.set.clear();
|
||||
}
|
||||
};
|
||||
@ -251,12 +276,15 @@ test "iterate" {
|
||||
store.add(7, 66.45);
|
||||
|
||||
for (store.data()) |entity, i| {
|
||||
if (i == 0)
|
||||
if (i == 0) {
|
||||
std.testing.expectEqual(entity, 3);
|
||||
if (i == 1)
|
||||
}
|
||||
if (i == 1) {
|
||||
std.testing.expectEqual(entity, 5);
|
||||
if (i == 2)
|
||||
}
|
||||
if (i == 2) {
|
||||
std.testing.expectEqual(entity, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,3 +328,54 @@ test "signals" {
|
||||
store.replace(4, 45.64);
|
||||
store.remove(4);
|
||||
}
|
||||
|
||||
const asc_u32 = std.sort.asc(u32);
|
||||
const desc_u32 = std.sort.desc(u32);
|
||||
|
||||
test "sort empty component" {
|
||||
const Empty = struct {};
|
||||
|
||||
var store = ComponentStorage(Empty, u32).initPtr(std.testing.allocator);
|
||||
defer store.deinit();
|
||||
|
||||
store.add(1, Empty{});
|
||||
store.add(2, Empty{});
|
||||
store.add(0, Empty{});
|
||||
|
||||
store.sort(asc_u32);
|
||||
for (store.data()) |e, i| {
|
||||
std.testing.expectEqual(@intCast(u32, i), e);
|
||||
}
|
||||
|
||||
store.sort(desc_u32);
|
||||
var counter: u32 = 2;
|
||||
for (store.data()) |e, i| {
|
||||
std.testing.expectEqual(counter, e);
|
||||
if (counter > 0) counter -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
const asc_f32 = std.sort.asc(f32);
|
||||
const desc_f32 = std.sort.desc(f32);
|
||||
|
||||
test "sort component" {
|
||||
std.debug.warn("\n", .{});
|
||||
|
||||
var store = ComponentStorage(f32, u32).initPtr(std.testing.allocator);
|
||||
defer store.deinit();
|
||||
|
||||
store.add(1, @as(f32, 1.1));
|
||||
store.add(2, @as(f32, 2.2));
|
||||
store.add(0, @as(f32, 0.0));
|
||||
|
||||
store.sort(f32, asc_f32);
|
||||
for (store.raw()) |e, i| {
|
||||
// std.debug.warn("{}: {}\n", .{i, e});
|
||||
// std.testing.expectEqual(@intCast(u32, i), e);
|
||||
}
|
||||
|
||||
store.sort(f32, desc_f32);
|
||||
for (store.raw()) |e, i| {
|
||||
// std.testing.expectEqual(counter, e);
|
||||
}
|
||||
}
|
@ -78,7 +78,7 @@ pub const Registry = struct {
|
||||
allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn maybeValidIf(self: *GroupData, entity: Entity) void {
|
||||
pub fn maybeValidIf(self: *GroupData, entity: Entity) void {
|
||||
const isValid: bool = blk: {
|
||||
for (self.owned) |tid| {
|
||||
const ptr = self.registry.components.getValue(tid).?;
|
||||
@ -120,7 +120,7 @@ pub const Registry = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn discardIf(self: *GroupData, entity: Entity) void {
|
||||
pub fn discardIf(self: *GroupData, entity: Entity) void {
|
||||
if (self.owned.len == 0) {
|
||||
if (self.entity_set.contains(entity))
|
||||
self.entity_set.remove(entity);
|
||||
@ -608,7 +608,7 @@ pub const Registry = struct {
|
||||
inline fn concatTypes(comptime types: var) []const u8 {
|
||||
comptime {
|
||||
const impl = struct {
|
||||
fn asc(lhs: []const u8, rhs: []const u8) bool {
|
||||
fn asc(context: void, lhs: []const u8, rhs: []const u8) bool {
|
||||
return std.mem.lessThan(u8, lhs, rhs);
|
||||
}
|
||||
};
|
||||
@ -618,7 +618,7 @@ pub const Registry = struct {
|
||||
name.* = @typeName(types[i]);
|
||||
}
|
||||
|
||||
std.sort.sort([]const u8, &names, impl.asc);
|
||||
std.sort.sort([]const u8, &names, {}, impl.asc);
|
||||
|
||||
comptime var res: []const u8 = "";
|
||||
inline for (names) |name| res = res ++ name;
|
||||
|
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const warn = std.debug.warn;
|
||||
const utils = @import("utils.zig");
|
||||
const ReverseSliceIterator = @import("utils.zig").ReverseSliceIterator;
|
||||
|
||||
// TODO: fix entity_mask. it should come from EntityTraitsDefinition.
|
||||
@ -38,7 +39,7 @@ pub fn SparseSet(comptime SparseT: type) type {
|
||||
allocator.destroy(self);
|
||||
}
|
||||
|
||||
fn page(self: Self, sparse: SparseT) usize {
|
||||
pub fn page(self: Self, sparse: SparseT) usize {
|
||||
// TODO: support paging
|
||||
// return (sparse & EntityTraits.entity_mask) / sparse_per_page;
|
||||
return sparse & self.entity_mask;
|
||||
@ -141,10 +142,19 @@ pub fn SparseSet(comptime SparseT: type) type {
|
||||
}
|
||||
|
||||
/// Sort elements according to the given comparison function
|
||||
pub fn sort(self: *Self, sortFn: fn (SparseT, SparseT) bool) void {
|
||||
std.sort.insertionSort(SparseT, self.dense.items, sortFn);
|
||||
pub fn sort(self: *Self, comptime sortFn: fn (void, SparseT, SparseT) bool) void {
|
||||
std.sort.insertionSort(SparseT, self.dense.items, {}, sortFn);
|
||||
|
||||
for (self.dense.items) |sparse| {
|
||||
// self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(SparseT, sparse);
|
||||
self.sparse.items[self.page(sparse)] = @intCast(SparseT, sparse);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sort elements according to the given comparison function and keeps sub_items with the same sort
|
||||
pub fn sortSub(self: *Self, comptime sortFn: fn (void, SparseT, SparseT) bool, comptime T: type, sub_items: []T) void {
|
||||
utils.sortSub(SparseT, T, self.dense.items, sub_items, sortFn);
|
||||
|
||||
var i = @as(usize, 0);
|
||||
for (self.dense.items) |sparse| {
|
||||
// self.assure(self.page(sparse))[self.offset(sparse)] = @intCast(SparseT, sparse);
|
||||
self.sparse.items[self.page(sparse)] = @intCast(SparseT, sparse);
|
||||
@ -259,7 +269,7 @@ test "iterate" {
|
||||
set.add(2);
|
||||
set.add(3);
|
||||
|
||||
var i: u32 = @intCast(u32, set.len()) - 1;
|
||||
var i: u32 = @intCast(u32, set.len()) - 1;
|
||||
var iter = set.reverseIterator();
|
||||
while (iter.next()) |entity| {
|
||||
std.testing.expectEqual(i, entity);
|
||||
@ -290,6 +300,8 @@ test "respect 1" {
|
||||
std.testing.expectEqual(set1.dense.items[1], set2.dense.items[2]);
|
||||
}
|
||||
|
||||
const desc_u32 = std.sort.desc(u32);
|
||||
|
||||
test "respect 2" {
|
||||
var set = SparseSet(u32).initPtr(std.testing.allocator);
|
||||
defer set.deinit();
|
||||
@ -300,11 +312,11 @@ test "respect 2" {
|
||||
set.add(1);
|
||||
set.add(3);
|
||||
|
||||
set.sort(std.sort.desc(u32));
|
||||
set.sort(desc_u32);
|
||||
|
||||
for (set.dense.items) |item, i| {
|
||||
if (i < set.dense.items.len - 1) {
|
||||
std.debug.assert(item > set.dense.items[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,13 +49,13 @@ pub fn ReverseSliceIterator(comptime T: type) type {
|
||||
}
|
||||
|
||||
/// sorts items using lessThan and keeps sub_items with the same sort
|
||||
pub fn sortSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T2, lessThan: fn (lhs: T1, rhs: T1) bool) void {
|
||||
pub fn sortSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T2, lessThan: fn (void, lhs: T1, rhs: T1) bool) void {
|
||||
var i: usize = 1;
|
||||
while (i < items.len) : (i += 1) {
|
||||
const x = items[i];
|
||||
const y = sub_items[i];
|
||||
var j: usize = i;
|
||||
while (j > 0 and lessThan(x, items[j - 1])) : (j -= 1) {
|
||||
while (j > 0 and lessThan({}, x, items[j - 1])) : (j -= 1) {
|
||||
items[j] = items[j - 1];
|
||||
sub_items[j] = sub_items[j - 1];
|
||||
}
|
||||
|
@ -14,12 +14,41 @@ const Rotation = struct { x: f32 = 0 };
|
||||
fn printStore(store: var, name: []const u8) void {
|
||||
warn("--- {} ---\n", .{name});
|
||||
for (store.set.dense.items) |e, i| {
|
||||
warn("{:3.0}", .{e});
|
||||
warn(" ({d:3.0})", .{store.instances.items[i]});
|
||||
warn("[{}] {}", .{e, store.set.sparse.items[store.set.page(store.set.dense.items[i])]});
|
||||
warn(" ({d:.2}) ", .{store.instances.items[i]});
|
||||
}
|
||||
warn("\n", .{});
|
||||
}
|
||||
|
||||
const asc_u32 = std.sort.asc(u32);
|
||||
const desc_u32 = std.sort.desc(f32);
|
||||
|
||||
test "sort component" {
|
||||
std.debug.warn("\n", .{});
|
||||
|
||||
var store = ecs.ComponentStorage(f32, u32).initPtr(std.testing.allocator);
|
||||
defer store.deinit();
|
||||
|
||||
store.add(1, @as(f32, 1.1));
|
||||
store.add(2, @as(f32, 2.2));
|
||||
store.add(0, @as(f32, 0.0));
|
||||
|
||||
printStore(store, "Fucker");
|
||||
|
||||
store.sort(u32, asc_u32);
|
||||
for (store.raw()) |e, i| {
|
||||
// std.debug.warn("{}: {}\n", .{i, e});
|
||||
// std.testing.expectEqual(@intCast(u32, i), e);
|
||||
}
|
||||
|
||||
printStore(store, "Fucker");
|
||||
|
||||
store.sort(f32, desc_u32);
|
||||
for (store.raw()) |e, i| {
|
||||
// std.testing.expectEqual(counter, e);
|
||||
}
|
||||
}
|
||||
|
||||
test "nested OwningGroups add/remove components" {
|
||||
var reg = Registry.init(std.testing.allocator);
|
||||
defer reg.deinit();
|
||||
|
Loading…
x
Reference in New Issue
Block a user