update to latest zig version

master
Mike 4 years ago
parent 76e322a49c
commit 9ca3e90b7b

@ -0,0 +1,46 @@
# Zig ECS
This is a zigification of the fantasic [Entt](https://github.com/skypjack/entt). Entt is _highly_ templated C++ code which depending on your opinion is either a good thing or satan itself in code form. Zig doesn't have the same concept as C++ templates (thank goodness!) so the templated code was changed over to use Zig's generics and compile time metaprogramming.
## What does a zigified Entt look like?
Below are examples of a View and a Group, the two main ways to work with entities in the ecs along with the scaffolding code.
Declare some structs to work with:
```
pub const Velocity = struct { x: f32, y: f32 };
pub const Position = struct { x: f32, y: f32 };
```
Setup the Registry, which holds the entity data and is where we run our queries:
```
var reg = ecs.Registry.init(std.testing.allocator);
```
Create a couple entities and add some components to them
```
var entity = reg.create();
reg.add(entity, Position{ .x = 0, .y = 0 });
reg.add(entity, Velocity{ .x = 5, .y = 7 });
...
```
Create and iterate a View that matches all entities with a `Velocity` and `Position` component:
```
var view = reg.view(.{ Velocity, Position }, .{});
var iter = view.iterator();
while (iter.next()) |entity| {
const pos = view.getConst(Position, entity); // readonly copy
var vel = view.get(Velocity, entity); // mutable
}
```
The same example using a non-owning Group:
```
var group = reg.group(.{}, .{ Velocity, Position }, .{});
group.each(each);
fn each(e: struct { vel: *Velocity, pos: *Position }) void {
e.pos.*.x += e.vel.x;
e.pos.*.y += e.vel.y;
}
```

@ -32,7 +32,7 @@ fn createEntities(reg: *ecs.Registry) void {
} }
var end = timer.lap(); var end = timer.lap();
std.debug.warn("create entities: {d}\n", .{@intToFloat(f64, end) / 1000000000}); std.debug.warn("create {d} entities: {d}\n", .{total_entities, @intToFloat(f64, end) / 1000000000});
} }
fn owningGroup(reg: *ecs.Registry) void { fn owningGroup(reg: *ecs.Registry) void {

@ -13,4 +13,4 @@ pub const OwningGroup = @import("ecs/groups.zig").OwningGroup;
// signals // signals
pub const Signal = @import("signals/signal.zig").Signal; pub const Signal = @import("signals/signal.zig").Signal;
pub const Dispatcher = @import("signals/dispatcher.zig").Dispatcher; pub const Dispatcher = @import("signals/dispatcher.zig").Dispatcher;

@ -18,7 +18,7 @@ pub const Actor = struct {
self.registry.destroy(self.entity); self.registry.destroy(self.entity);
} }
pub fn add(self: *Actor, value: var) void { pub fn add(self: *Actor, value: anytype) void {
self.registry.add(self.entity, value); self.registry.add(self.entity, value);
} }

@ -188,7 +188,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
struct { struct {
/// Sort Entities according to the given comparison function. Only T == Entity is allowed. The constraint param only exists for /// Sort Entities according to the given comparison function. Only T == Entity is allowed. The constraint param only exists for
/// parity with non-empty Components /// parity with non-empty Components
pub fn sort(self: Self, comptime T: type, context: var, comptime lessThan: fn (@TypeOf(context), T, T) bool) void { pub fn sort(self: Self, comptime T: type, context: anytype, comptime lessThan: fn (@TypeOf(context), T, T) bool) void {
std.debug.assert(T == Entity); std.debug.assert(T == Entity);
self.set.sort(context, lessThan); self.set.sort(context, lessThan);
} }
@ -226,7 +226,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
} }
/// Sort Entities or Components according to the given comparison function. Valid types for T are Entity or Component. /// Sort Entities or Components according to the given comparison function. Valid types for T are Entity or Component.
pub fn sort(self: *Self, comptime T: type, length: usize, context: var, comptime lessThan: fn (@TypeOf(context), T, T) bool) void { pub fn sort(self: *Self, comptime T: type, length: usize, context: anytype, comptime lessThan: fn (@TypeOf(context), T, T) bool) void {
std.debug.assert(T == Entity or T == Component); std.debug.assert(T == Entity or T == Component);
// we have to perform a swap after the sort for all moved entities so we make a helper struct for that. In the // we have to perform a swap after the sort for all moved entities so we make a helper struct for that. In the

@ -42,7 +42,7 @@ pub const BasicGroup = struct {
return self.group_data.entity_set.reverseIterator(); return self.group_data.entity_set.reverseIterator();
} }
pub fn sort(self: BasicGroup, comptime T: type, context: var, comptime lessThan: fn (@TypeOf(context), T, T) bool) void { pub fn sort(self: BasicGroup, comptime T: type, context: anytype, comptime lessThan: fn (@TypeOf(context), T, T) bool) void {
if (T == Entity) { if (T == Entity) {
self.group_data.entity_set.sort(context, lessThan); self.group_data.entity_set.sort(context, lessThan);
} else { } else {
@ -73,7 +73,7 @@ pub const OwningGroup = struct {
/// being iterated is available via the entity() method, useful for accessing non-owned component data. The get() method can /// being iterated is available via the entity() method, useful for accessing non-owned component data. The get() method can
/// also be used to fetch non-owned component data for the currently iterated Entity. /// also be used to fetch non-owned component data for the currently iterated Entity.
/// TODO: support const types in the Components struct in addition to the current ptrs /// TODO: support const types in the Components struct in addition to the current ptrs
fn Iterator(comptime Components: var) type { fn Iterator(comptime Components: anytype) type {
return struct { return struct {
group: OwningGroup, group: OwningGroup,
index: usize, index: usize,
@ -136,7 +136,7 @@ pub const OwningGroup = struct {
/// grabs an untyped (u1) reference to the first Storage(T) in the owned array /// grabs an untyped (u1) reference to the first Storage(T) in the owned array
fn firstOwnedStorage(self: OwningGroup) *Storage(u1) { fn firstOwnedStorage(self: OwningGroup) *Storage(u1) {
const ptr = self.registry.components.getValue(self.group_data.owned[0]).?; const ptr = self.registry.components.get(self.group_data.owned[0]).?;
return @intToPtr(*Storage(u1), ptr); return @intToPtr(*Storage(u1), ptr);
} }
@ -155,7 +155,7 @@ pub const OwningGroup = struct {
return storage.contains(entity) and storage.set.index(entity) < self.len(); return storage.contains(entity) and storage.set.index(entity) < self.len();
} }
fn validate(self: OwningGroup, comptime Components: var) void { fn validate(self: OwningGroup, comptime Components: anytype) void {
if (std.builtin.mode == .Debug and self.group_data.owned.len > 0) { if (std.builtin.mode == .Debug and self.group_data.owned.len > 0) {
std.debug.assert(@typeInfo(Components) == .Struct); std.debug.assert(@typeInfo(Components) == .Struct);
@ -167,7 +167,7 @@ pub const OwningGroup = struct {
} }
} }
pub fn getOwned(self: OwningGroup, entity: Entity, comptime Components: var) Components { pub fn getOwned(self: OwningGroup, entity: Entity, comptime Components: anytype) Components {
self.validate(Components); self.validate(Components);
const component_info = @typeInfo(Components).Struct; const component_info = @typeInfo(Components).Struct;
@ -188,7 +188,7 @@ pub const OwningGroup = struct {
return comps; return comps;
} }
pub fn each(self: OwningGroup, comptime func: var) void { pub fn each(self: OwningGroup, comptime func: anytype) void {
const Components = switch (@typeInfo(@TypeOf(func))) { const Components = switch (@typeInfo(@TypeOf(func))) {
.BoundFn => |func_info| func_info.args[1].arg_type.?, .BoundFn => |func_info| func_info.args[1].arg_type.?,
.Fn => |func_info| func_info.args[0].arg_type.?, .Fn => |func_info| func_info.args[0].arg_type.?,
@ -223,7 +223,7 @@ pub const OwningGroup = struct {
/// returns an iterator with optimized access to the owend Components. Note that Components should be a struct with /// returns an iterator with optimized access to the owend Components. Note that Components should be a struct with
/// fields that are pointers to the component types that you want to fetch. Only types that are owned are valid! Non-owned /// fields that are pointers to the component types that you want to fetch. Only types that are owned are valid! Non-owned
/// types should be fetched via Iterator.get. /// types should be fetched via Iterator.get.
pub fn iterator(self: OwningGroup, comptime Components: var) Iterator(Components) { pub fn iterator(self: OwningGroup, comptime Components: anytype) Iterator(Components) {
self.validate(Components); self.validate(Components);
return Iterator(Components).init(self); return Iterator(Components).init(self);
} }
@ -232,7 +232,7 @@ pub const OwningGroup = struct {
return utils.ReverseSliceIterator(Entity).init(self.firstOwnedStorage().set.dense.items[0..self.group_data.current]); return utils.ReverseSliceIterator(Entity).init(self.firstOwnedStorage().set.dense.items[0..self.group_data.current]);
} }
pub fn sort(self: OwningGroup, comptime T: type, context: var, comptime lessThan: fn (@TypeOf(context), T, T) bool) void { pub fn sort(self: OwningGroup, comptime T: type, context: anytype, comptime lessThan: fn (@TypeOf(context), T, T) bool) void {
var first_storage = self.firstOwnedStorage(); var first_storage = self.firstOwnedStorage();
if (T == Entity) { if (T == Entity) {
@ -264,7 +264,7 @@ pub const OwningGroup = struct {
// skip the first one since its what we are using to sort with // skip the first one since its what we are using to sort with
for (self.group_data.owned[1..]) |type_id| { for (self.group_data.owned[1..]) |type_id| {
var other_ptr = self.registry.components.getValue(type_id).?; var other_ptr = self.registry.components.get(type_id).?;
var storage = @intToPtr(*Storage(u1), other_ptr); var storage = @intToPtr(*Storage(u1), other_ptr);
storage.swap(storage.data()[pos], entity); storage.swap(storage.data()[pos], entity);
} }

@ -81,19 +81,19 @@ pub const Registry = struct {
pub fn maybeValidIf(self: *GroupData, entity: Entity) void { pub fn maybeValidIf(self: *GroupData, entity: Entity) void {
const isValid: bool = blk: { const isValid: bool = blk: {
for (self.owned) |tid| { for (self.owned) |tid| {
const ptr = self.registry.components.getValue(tid).?; const ptr = self.registry.components.get(tid).?;
if (!@intToPtr(*Storage(u1), ptr).contains(entity)) if (!@intToPtr(*Storage(u1), ptr).contains(entity))
break :blk false; break :blk false;
} }
for (self.include) |tid| { for (self.include) |tid| {
const ptr = self.registry.components.getValue(tid).?; const ptr = self.registry.components.get(tid).?;
if (!@intToPtr(*Storage(u1), ptr).contains(entity)) if (!@intToPtr(*Storage(u1), ptr).contains(entity))
break :blk false; break :blk false;
} }
for (self.exclude) |tid| { for (self.exclude) |tid| {
const ptr = self.registry.components.getValue(tid).?; const ptr = self.registry.components.get(tid).?;
if (@intToPtr(*Storage(u1), ptr).contains(entity)) if (@intToPtr(*Storage(u1), ptr).contains(entity))
break :blk false; break :blk false;
} }
@ -106,11 +106,11 @@ pub const Registry = struct {
} }
} else { } else {
if (isValid) { if (isValid) {
const ptr = self.registry.components.getValue(self.owned[0]).?; const ptr = self.registry.components.get(self.owned[0]).?;
if (!(@intToPtr(*Storage(u1), ptr).set.index(entity) < self.current)) { if (!(@intToPtr(*Storage(u1), ptr).set.index(entity) < self.current)) {
for (self.owned) |tid| { for (self.owned) |tid| {
// store.swap hides a safe version that types it correctly // store.swap hides a safe version that types it correctly
const store_ptr = self.registry.components.getValue(tid).?; const store_ptr = self.registry.components.get(tid).?;
var store = @intToPtr(*Storage(u1), store_ptr); var store = @intToPtr(*Storage(u1), store_ptr);
store.swap(store.data()[self.current], entity); store.swap(store.data()[self.current], entity);
} }
@ -127,12 +127,12 @@ pub const Registry = struct {
self.entity_set.remove(entity); self.entity_set.remove(entity);
} }
} else { } else {
const ptr = self.registry.components.getValue(self.owned[0]).?; const ptr = self.registry.components.get(self.owned[0]).?;
var store = @intToPtr(*Storage(u1), ptr); var store = @intToPtr(*Storage(u1), ptr);
if (store.contains(entity) and store.set.index(entity) < self.current) { if (store.contains(entity) and store.set.index(entity) < self.current) {
self.current -= 1; self.current -= 1;
for (self.owned) |tid| { for (self.owned) |tid| {
const store_ptr = self.registry.components.getValue(tid).?; const store_ptr = self.registry.components.get(tid).?;
store = @intToPtr(*Storage(u1), store_ptr); store = @intToPtr(*Storage(u1), store_ptr);
store.swap(store.data()[self.current], entity); store.swap(store.data()[self.current], entity);
} }
@ -215,7 +215,7 @@ pub const Registry = struct {
pub fn assure(self: *Registry, comptime T: type) *Storage(T) { pub fn assure(self: *Registry, comptime T: type) *Storage(T) {
var type_id = utils.typeId(T); var type_id = utils.typeId(T);
if (self.components.get(type_id)) |kv| { if (self.components.getEntry(type_id)) |kv| {
return @intToPtr(*Storage(T), kv.value); return @intToPtr(*Storage(T), kv.value);
} }
@ -281,7 +281,7 @@ pub const Registry = struct {
return self.handles.iterator(); return self.handles.iterator();
} }
pub fn add(self: *Registry, entity: Entity, value: var) void { pub fn add(self: *Registry, entity: Entity, value: anytype) void {
assert(self.valid(entity)); assert(self.valid(entity));
self.assure(@TypeOf(value)).add(entity, value); self.assure(@TypeOf(value)).add(entity, value);
} }
@ -292,14 +292,14 @@ pub const Registry = struct {
} }
/// adds all the component types passed in as zero-initialized values /// adds all the component types passed in as zero-initialized values
pub fn addTypes(self: *Registry, entity: Entity, comptime types: var) void { pub fn addTypes(self: *Registry, entity: Entity, comptime types: anytype) void {
inline for (types) |t| { inline for (types) |t| {
self.assure(t).add(entity, std.mem.zeroes(t)); self.assure(t).add(entity, std.mem.zeroes(t));
} }
} }
/// Replaces the given component for an entity /// Replaces the given component for an entity
pub fn replace(self: *Registry, entity: Entity, value: var) void { pub fn replace(self: *Registry, entity: Entity, value: anytype) void {
assert(self.valid(entity)); assert(self.valid(entity));
self.assure(@TypeOf(value)).replace(entity, value); self.assure(@TypeOf(value)).replace(entity, value);
} }
@ -309,7 +309,7 @@ pub const Registry = struct {
self.replace(entity, value); self.replace(entity, value);
} }
pub fn addOrReplace(self: *Registry, entity: Entity, value: var) void { pub fn addOrReplace(self: *Registry, entity: Entity, value: anytype) void {
assert(self.valid(entity)); assert(self.valid(entity));
const store = self.assure(@TypeOf(value)); const store = self.assure(@TypeOf(value));
@ -393,7 +393,7 @@ pub const Registry = struct {
} }
/// Binds an object to the context of the registry /// Binds an object to the context of the registry
pub fn setContext(self: *Registry, context: var) void { pub fn setContext(self: *Registry, context: anytype) void {
std.debug.assert(@typeInfo(@TypeOf(context)) == .Pointer); std.debug.assert(@typeInfo(@TypeOf(context)) == .Pointer);
var type_id = utils.typeId(@typeInfo(@TypeOf(context)).Pointer.child); var type_id = utils.typeId(@typeInfo(@TypeOf(context)).Pointer.child);
@ -432,7 +432,7 @@ pub const Registry = struct {
return self.assure(T).super == 0; return self.assure(T).super == 0;
} }
pub fn view(self: *Registry, comptime includes: var, comptime excludes: var) ViewType(includes, excludes) { pub fn view(self: *Registry, comptime includes: anytype, comptime excludes: anytype) ViewType(includes, excludes) {
std.debug.assert(@typeInfo(@TypeOf(includes)) == .Struct); std.debug.assert(@typeInfo(@TypeOf(includes)) == .Struct);
std.debug.assert(@typeInfo(@TypeOf(excludes)) == .Struct); std.debug.assert(@typeInfo(@TypeOf(excludes)) == .Struct);
std.debug.assert(includes.len > 0); std.debug.assert(includes.len > 0);
@ -457,13 +457,13 @@ pub const Registry = struct {
} }
/// returns the Type that a view will be based on the includes and excludes /// returns the Type that a view will be based on the includes and excludes
fn ViewType(comptime includes: var, comptime excludes: var) type { fn ViewType(comptime includes: anytype, comptime excludes: anytype) type {
if (includes.len == 1 and excludes.len == 0) return BasicView(includes[0]); if (includes.len == 1 and excludes.len == 0) return BasicView(includes[0]);
return MultiView(includes.len, excludes.len); return MultiView(includes.len, excludes.len);
} }
/// creates an optimized group for iterating components /// creates an optimized group for iterating components
pub fn group(self: *Registry, comptime owned: var, comptime includes: var, comptime excludes: var) (if (owned.len == 0) BasicGroup else OwningGroup) { pub fn group(self: *Registry, comptime owned: anytype, comptime includes: anytype, comptime excludes: anytype) (if (owned.len == 0) BasicGroup else OwningGroup) {
std.debug.assert(@typeInfo(@TypeOf(owned)) == .Struct); std.debug.assert(@typeInfo(@TypeOf(owned)) == .Struct);
std.debug.assert(@typeInfo(@TypeOf(includes)) == .Struct); std.debug.assert(@typeInfo(@TypeOf(includes)) == .Struct);
std.debug.assert(@typeInfo(@TypeOf(excludes)) == .Struct); std.debug.assert(@typeInfo(@TypeOf(excludes)) == .Struct);
@ -593,7 +593,7 @@ pub const Registry = struct {
/// given the 3 group Types arrays, generates a (mostly) unique u64 hash. Simultaneously ensures there are no duped types between /// given the 3 group Types arrays, generates a (mostly) unique u64 hash. Simultaneously ensures there are no duped types between
/// the 3 groups. /// the 3 groups.
inline fn hashGroupTypes(comptime owned: var, comptime includes: var, comptime excludes: var) u64 { inline fn hashGroupTypes(comptime owned: anytype, comptime includes: anytype, comptime excludes: anytype) u64 {
comptime { comptime {
for (owned) |t1| { for (owned) |t1| {
for (includes) |t2| { for (includes) |t2| {
@ -615,7 +615,7 @@ pub const Registry = struct {
} }
/// expects a tuple of types. Convertes them to type names, sorts them then concatenates and returns the string. /// expects a tuple of types. Convertes them to type names, sorts them then concatenates and returns the string.
inline fn concatTypes(comptime types: var) []const u8 { inline fn concatTypes(comptime types: anytype) []const u8 {
comptime { comptime {
if (types.len == 0) return "_"; if (types.len == 0) return "_";

@ -148,7 +148,7 @@ pub fn SparseSet(comptime SparseT: type) type {
} }
/// Sort elements according to the given comparison function /// Sort elements according to the given comparison function
pub fn sort(self: *Self, context: var, comptime lessThan: fn (@TypeOf(context), SparseT, SparseT) bool) void { pub fn sort(self: *Self, context: anytype, comptime lessThan: fn (@TypeOf(context), SparseT, SparseT) bool) void {
std.sort.insertionSort(SparseT, self.dense.items, context, lessThan); std.sort.insertionSort(SparseT, self.dense.items, context, lessThan);
for (self.dense.items) |sparse, i| { for (self.dense.items) |sparse, i| {
@ -159,7 +159,7 @@ pub fn SparseSet(comptime SparseT: type) type {
/// Sort elements according to the given comparison function. Use this when a data array needs to stay in sync with the SparseSet /// Sort elements according to the given comparison function. Use this when a data array needs to stay in sync with the SparseSet
/// by passing in a "swap_context" that contains a "swap" method with a sig of fn(ctx,SparseT,SparseT)void /// by passing in a "swap_context" that contains a "swap" method with a sig of fn(ctx,SparseT,SparseT)void
pub fn arrange(self: *Self, length: usize, context: var, comptime lessThan: fn (@TypeOf(context), SparseT, SparseT) bool, swap_context: var) void { pub fn arrange(self: *Self, length: usize, context: anytype, comptime lessThan: fn (@TypeOf(context), SparseT, SparseT) bool, swap_context: anytype) void {
std.sort.insertionSort(SparseT, self.dense.items[0..length], context, lessThan); std.sort.insertionSort(SparseT, self.dense.items[0..length], context, lessThan);
for (self.dense.items[0..length]) |sparse, pos| { for (self.dense.items[0..length]) |sparse, pos| {

@ -13,7 +13,7 @@ pub const TypeStore = struct {
}; };
} }
pub fn deinit(self: TypeStore) void { pub fn deinit(self: *TypeStore) void {
var iter = self.map.iterator(); var iter = self.map.iterator();
while (iter.next()) |kv| { while (iter.next()) |kv| {
self.allocator.free(kv.value); self.allocator.free(kv.value);
@ -22,7 +22,7 @@ pub const TypeStore = struct {
} }
/// adds instance, returning a pointer to the item as it lives in the store /// adds instance, returning a pointer to the item as it lives in the store
pub fn add(self: *TypeStore, instance: var) void { pub fn add(self: *TypeStore, instance: anytype) void {
var bytes = self.allocator.alloc(u8, @sizeOf(@TypeOf(instance))) catch unreachable; var bytes = self.allocator.alloc(u8, @sizeOf(@TypeOf(instance))) catch unreachable;
std.mem.copy(u8, bytes, std.mem.asBytes(&instance)); std.mem.copy(u8, bytes, std.mem.asBytes(&instance));
_ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable; _ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable;

@ -3,7 +3,7 @@ const std = @import("std");
pub const ErasedPtr = struct { pub const ErasedPtr = struct {
ptr: usize, ptr: usize,
pub fn init(ptr: var) ErasedPtr { pub fn init(ptr: anytype) ErasedPtr {
if (@sizeOf(@TypeOf(ptr)) == 0) { if (@sizeOf(@TypeOf(ptr)) == 0) {
return .{ .ptr = undefined }; return .{ .ptr = undefined };
} }
@ -64,7 +64,7 @@ pub fn sortSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T
} }
} }
pub fn sortSubSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T2, context: var, comptime lessThan: fn (@TypeOf(context), lhs: T1, rhs: T1) bool) void { pub fn sortSubSub(comptime T1: type, comptime T2: type, items: []T1, sub_items: []T2, context: anytype, comptime lessThan: fn (@TypeOf(context), lhs: T1, rhs: T1) bool) void {
var i: usize = 1; var i: usize = 1;
while (i < items.len) : (i += 1) { while (i < items.len) : (i += 1) {
const x = items[i]; const x = items[i];

@ -15,7 +15,7 @@ pub const Scheduler = struct {
allocator: *std.mem.Allocator, allocator: *std.mem.Allocator,
/// helper to create and prepare a process /// helper to create and prepare a process
fn createProcessHandler(comptime T: type, data: var, allocator: *std.mem.Allocator) *Process { fn createProcessHandler(comptime T: type, data: anytype, allocator: *std.mem.Allocator) *Process {
var proc = allocator.create(T) catch unreachable; var proc = allocator.create(T) catch unreachable;
proc.initialize(data); proc.initialize(data);
@ -41,7 +41,7 @@ pub const Scheduler = struct {
return .{ .process = process, .allocator = allocator }; return .{ .process = process, .allocator = allocator };
} }
pub fn next(self: *@This(), comptime T: type, data: var) *@This() { pub fn next(self: *@This(), comptime T: type, data: anytype) *@This() {
self.process.next = createProcessHandler(T, data, self.allocator); self.process.next = createProcessHandler(T, data, self.allocator);
self.process = self.process.next.?; self.process = self.process.next.?;
return self; return self;
@ -61,7 +61,7 @@ pub const Scheduler = struct {
} }
/// Schedules a process for the next tick /// Schedules a process for the next tick
pub fn attach(self: *Scheduler, comptime T: type, data: var) Continuation { pub fn attach(self: *Scheduler, comptime T: type, data: anytype) Continuation {
std.debug.assert(@hasDecl(T, "initialize")); std.debug.assert(@hasDecl(T, "initialize"));
std.debug.assert(@hasField(T, "process")); std.debug.assert(@hasField(T, "process"));
@ -137,7 +137,7 @@ test "" {
process: Process, process: Process,
fart: usize, fart: usize,
pub fn initialize(self: *@This(), data: var) void { pub fn initialize(self: *@This(), data: anytype) void {
self.process = .{ self.process = .{
.startFn = start, .startFn = start,
.updateFn = update, .updateFn = update,
@ -190,7 +190,7 @@ test "scheduler.clear" {
const Tester = struct { const Tester = struct {
process: Process, process: Process,
pub fn initialize(self: *@This(), data: var) void { pub fn initialize(self: *@This(), data: anytype) void {
self.process = .{ .updateFn = update }; self.process = .{ .updateFn = update };
} }
@ -212,7 +212,7 @@ test "scheduler.attach.next" {
process: Process, process: Process,
counter: *usize, counter: *usize,
pub fn initialize(self: *@This(), data: var) void { pub fn initialize(self: *@This(), data: anytype) void {
self.process = .{ .updateFn = update }; self.process = .{ .updateFn = update };
self.counter = data; self.counter = data;
} }

@ -33,11 +33,11 @@ pub const Assets = struct {
return cache; return cache;
} }
pub fn load(self: *Assets, id: u16, comptime loader: var) ReturnType(loader, false) { pub fn load(self: *Assets, id: u16, comptime loader: anytype) ReturnType(loader, false) {
return self.get(ReturnType(loader, true)).load(id, loader); return self.get(ReturnType(loader, true)).load(id, loader);
} }
fn ReturnType(comptime loader: var, strip_ptr: bool) type { fn ReturnType(comptime loader: anytype, strip_ptr: bool) type {
var ret = @typeInfo(@TypeOf(@field(loader, "load"))).BoundFn.return_type.?; var ret = @typeInfo(@TypeOf(@field(loader, "load"))).BoundFn.return_type.?;
if (strip_ptr) { if (strip_ptr) {
return ret.Child; return ret.Child;

@ -42,7 +42,7 @@ pub fn Cache(comptime T: type) type {
self.safe_deinit(self); self.safe_deinit(self);
} }
pub fn load(self: *@This(), id: u32, comptime loader: var) @typeInfo(@TypeOf(@field(loader, "load"))).BoundFn.return_type.? { pub fn load(self: *@This(), id: u32, comptime loader: anytype) @typeInfo(@TypeOf(@field(loader, "load"))).BoundFn.return_type.? {
if (self.resources.getValue(id)) |resource| { if (self.resources.getValue(id)) |resource| {
return resource; return resource;
} }

@ -12,7 +12,7 @@ pub fn Delegate(comptime Event: type) type {
}, },
/// sets a bound function as the Delegate callback /// sets a bound function as the Delegate callback
pub fn initBound(ctx: var, comptime fn_name: []const u8) Self { pub fn initBound(ctx: anytype, comptime fn_name: []const u8) Self {
std.debug.assert(@typeInfo(@TypeOf(ctx)) == .Pointer); std.debug.assert(@typeInfo(@TypeOf(ctx)) == .Pointer);
std.debug.assert(@ptrToInt(ctx) != 0); std.debug.assert(@ptrToInt(ctx) != 0);
@ -50,7 +50,7 @@ pub fn Delegate(comptime Event: type) type {
}; };
} }
pub fn containsBound(self: Self, ctx: var) bool { pub fn containsBound(self: Self, ctx: anytype) bool {
std.debug.assert(@ptrToInt(ctx) != 0); std.debug.assert(@ptrToInt(ctx) != 0);
std.debug.assert(@typeInfo(@TypeOf(ctx)) == .Pointer); std.debug.assert(@typeInfo(@TypeOf(ctx)) == .Pointer);

@ -27,7 +27,7 @@ pub fn Sink(comptime Event: type) type {
return self; return self;
} }
pub fn beforeBound(self: Self, ctx: var) Self { pub fn beforeBound(self: Self, ctx: anytype) Self {
if (@typeInfo(@TypeOf(ctx)) == .Pointer) { if (@typeInfo(@TypeOf(ctx)) == .Pointer) {
if (self.indexOfBound(ctx)) |index| { if (self.indexOfBound(ctx)) |index| {
return Self{ .insert_index = index }; return Self{ .insert_index = index };
@ -41,7 +41,7 @@ pub fn Sink(comptime Event: type) type {
_ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initFree(callback)) catch unreachable; _ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initFree(callback)) catch unreachable;
} }
pub fn connectBound(self: Self, ctx: var, comptime fn_name: []const u8) void { pub fn connectBound(self: Self, ctx: anytype, comptime fn_name: []const u8) void {
std.debug.assert(self.indexOfBound(ctx) == null); std.debug.assert(self.indexOfBound(ctx) == null);
_ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initBound(ctx, fn_name)) catch unreachable; _ = owning_signal.calls.insert(self.insert_index, Delegate(Event).initBound(ctx, fn_name)) catch unreachable;
} }
@ -52,7 +52,7 @@ pub fn Sink(comptime Event: type) type {
} }
} }
pub fn disconnectBound(self: Self, ctx: var) void { pub fn disconnectBound(self: Self, ctx: anytype) void {
if (self.indexOfBound(ctx)) |index| { if (self.indexOfBound(ctx)) |index| {
_ = owning_signal.calls.swapRemove(index); _ = owning_signal.calls.swapRemove(index);
} }
@ -67,7 +67,7 @@ pub fn Sink(comptime Event: type) type {
return null; return null;
} }
fn indexOfBound(self: Self, ctx: var) ?usize { fn indexOfBound(self: Self, ctx: anytype) ?usize {
for (owning_signal.calls.items) |call, i| { for (owning_signal.calls.items) |call, i| {
if (call.containsBound(ctx)) { if (call.containsBound(ctx)) {
return i; return i;
@ -112,4 +112,4 @@ test "Sink Before bound" {
signal.sink().beforeBound(&thing).connect(tester); signal.sink().beforeBound(&thing).connect(tester);
std.testing.expectEqual(signal.sink().indexOf(tester).?, 0); std.testing.expectEqual(signal.sink().indexOf(tester).?, 0);
} }

Loading…
Cancel
Save