update to latest zig version
This commit is contained in:
parent
76e322a49c
commit
9ca3e90b7b
46
zig-ecs/README.md
Normal file
46
zig-ecs/README.md
Normal file
@ -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();
|
||||
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 {
|
||||
|
@ -13,4 +13,4 @@ pub const OwningGroup = @import("ecs/groups.zig").OwningGroup;
|
||||
|
||||
// signals
|
||||
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);
|
||||
}
|
||||
|
||||
pub fn add(self: *Actor, value: var) void {
|
||||
pub fn add(self: *Actor, value: anytype) void {
|
||||
self.registry.add(self.entity, value);
|
||||
}
|
||||
|
||||
|
@ -188,7 +188,7 @@ pub fn ComponentStorage(comptime Component: type, comptime Entity: type) type {
|
||||
struct {
|
||||
/// Sort Entities according to the given comparison function. Only T == Entity is allowed. The constraint param only exists for
|
||||
/// 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);
|
||||
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.
|
||||
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);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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) {
|
||||
self.group_data.entity_set.sort(context, lessThan);
|
||||
} 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
|
||||
/// 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
|
||||
fn Iterator(comptime Components: var) type {
|
||||
fn Iterator(comptime Components: anytype) type {
|
||||
return struct {
|
||||
group: OwningGroup,
|
||||
index: usize,
|
||||
@ -136,7 +136,7 @@ pub const OwningGroup = struct {
|
||||
|
||||
/// grabs an untyped (u1) reference to the first Storage(T) in the owned array
|
||||
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);
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ pub const OwningGroup = struct {
|
||||
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) {
|
||||
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);
|
||||
const component_info = @typeInfo(Components).Struct;
|
||||
|
||||
@ -188,7 +188,7 @@ pub const OwningGroup = struct {
|
||||
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))) {
|
||||
.BoundFn => |func_info| func_info.args[1].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
|
||||
/// 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.
|
||||
pub fn iterator(self: OwningGroup, comptime Components: var) Iterator(Components) {
|
||||
pub fn iterator(self: OwningGroup, comptime Components: anytype) Iterator(Components) {
|
||||
self.validate(Components);
|
||||
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]);
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
if (T == Entity) {
|
||||
@ -264,7 +264,7 @@ pub const OwningGroup = struct {
|
||||
|
||||
// skip the first one since its what we are using to sort with
|
||||
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);
|
||||
storage.swap(storage.data()[pos], entity);
|
||||
}
|
||||
|
@ -81,19 +81,19 @@ pub const Registry = struct {
|
||||
pub fn maybeValidIf(self: *GroupData, entity: Entity) void {
|
||||
const isValid: bool = blk: {
|
||||
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))
|
||||
break :blk false;
|
||||
}
|
||||
|
||||
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))
|
||||
break :blk false;
|
||||
}
|
||||
|
||||
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))
|
||||
break :blk false;
|
||||
}
|
||||
@ -106,11 +106,11 @@ pub const Registry = struct {
|
||||
}
|
||||
} else {
|
||||
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)) {
|
||||
for (self.owned) |tid| {
|
||||
// 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);
|
||||
store.swap(store.data()[self.current], entity);
|
||||
}
|
||||
@ -127,12 +127,12 @@ pub const Registry = struct {
|
||||
self.entity_set.remove(entity);
|
||||
}
|
||||
} 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);
|
||||
if (store.contains(entity) and store.set.index(entity) < self.current) {
|
||||
self.current -= 1;
|
||||
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.swap(store.data()[self.current], entity);
|
||||
}
|
||||
@ -215,7 +215,7 @@ pub const Registry = struct {
|
||||
|
||||
pub fn assure(self: *Registry, comptime T: type) *Storage(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);
|
||||
}
|
||||
|
||||
@ -281,7 +281,7 @@ pub const Registry = struct {
|
||||
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));
|
||||
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
|
||||
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| {
|
||||
self.assure(t).add(entity, std.mem.zeroes(t));
|
||||
}
|
||||
}
|
||||
|
||||
/// 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));
|
||||
self.assure(@TypeOf(value)).replace(entity, value);
|
||||
}
|
||||
@ -309,7 +309,7 @@ pub const Registry = struct {
|
||||
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));
|
||||
|
||||
const store = self.assure(@TypeOf(value));
|
||||
@ -393,7 +393,7 @@ pub const Registry = struct {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
||||
var type_id = utils.typeId(@typeInfo(@TypeOf(context)).Pointer.child);
|
||||
@ -432,7 +432,7 @@ pub const Registry = struct {
|
||||
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(excludes)) == .Struct);
|
||||
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
|
||||
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]);
|
||||
return MultiView(includes.len, excludes.len);
|
||||
}
|
||||
|
||||
/// 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(includes)) == .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
|
||||
/// 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 {
|
||||
for (owned) |t1| {
|
||||
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.
|
||||
inline fn concatTypes(comptime types: var) []const u8 {
|
||||
inline fn concatTypes(comptime types: anytype) []const u8 {
|
||||
comptime {
|
||||
if (types.len == 0) return "_";
|
||||
|
||||
|
@ -148,7 +148,7 @@ pub fn SparseSet(comptime SparseT: type) type {
|
||||
}
|
||||
|
||||
/// 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);
|
||||
|
||||
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
|
||||
/// 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);
|
||||
|
||||
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();
|
||||
while (iter.next()) |kv| {
|
||||
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
|
||||
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;
|
||||
std.mem.copy(u8, bytes, std.mem.asBytes(&instance));
|
||||
_ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable;
|
||||
|
@ -3,7 +3,7 @@ const std = @import("std");
|
||||
pub const ErasedPtr = struct {
|
||||
ptr: usize,
|
||||
|
||||
pub fn init(ptr: var) ErasedPtr {
|
||||
pub fn init(ptr: anytype) ErasedPtr {
|
||||
if (@sizeOf(@TypeOf(ptr)) == 0) {
|
||||
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;
|
||||
while (i < items.len) : (i += 1) {
|
||||
const x = items[i];
|
||||
|
@ -15,7 +15,7 @@ pub const Scheduler = struct {
|
||||
allocator: *std.mem.Allocator,
|
||||
|
||||
/// 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;
|
||||
proc.initialize(data);
|
||||
|
||||
@ -41,7 +41,7 @@ pub const Scheduler = struct {
|
||||
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 = self.process.next.?;
|
||||
return self;
|
||||
@ -61,7 +61,7 @@ pub const Scheduler = struct {
|
||||
}
|
||||
|
||||
/// 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(@hasField(T, "process"));
|
||||
|
||||
@ -137,7 +137,7 @@ test "" {
|
||||
process: Process,
|
||||
fart: usize,
|
||||
|
||||
pub fn initialize(self: *@This(), data: var) void {
|
||||
pub fn initialize(self: *@This(), data: anytype) void {
|
||||
self.process = .{
|
||||
.startFn = start,
|
||||
.updateFn = update,
|
||||
@ -190,7 +190,7 @@ test "scheduler.clear" {
|
||||
const Tester = struct {
|
||||
process: Process,
|
||||
|
||||
pub fn initialize(self: *@This(), data: var) void {
|
||||
pub fn initialize(self: *@This(), data: anytype) void {
|
||||
self.process = .{ .updateFn = update };
|
||||
}
|
||||
|
||||
@ -212,7 +212,7 @@ test "scheduler.attach.next" {
|
||||
process: Process,
|
||||
counter: *usize,
|
||||
|
||||
pub fn initialize(self: *@This(), data: var) void {
|
||||
pub fn initialize(self: *@This(), data: anytype) void {
|
||||
self.process = .{ .updateFn = update };
|
||||
self.counter = data;
|
||||
}
|
||||
|
@ -33,11 +33,11 @@ pub const Assets = struct {
|
||||
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);
|
||||
}
|
||||
|
||||
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.?;
|
||||
if (strip_ptr) {
|
||||
return ret.Child;
|
||||
|
@ -42,7 +42,7 @@ pub fn Cache(comptime T: type) type {
|
||||
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| {
|
||||
return resource;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub fn Delegate(comptime Event: type) type {
|
||||
},
|
||||
|
||||
/// 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(@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(@typeInfo(@TypeOf(ctx)) == .Pointer);
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub fn Sink(comptime Event: type) type {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn beforeBound(self: Self, ctx: var) Self {
|
||||
pub fn beforeBound(self: Self, ctx: anytype) Self {
|
||||
if (@typeInfo(@TypeOf(ctx)) == .Pointer) {
|
||||
if (self.indexOfBound(ctx)) |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;
|
||||
}
|
||||
|
||||
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);
|
||||
_ = 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| {
|
||||
_ = owning_signal.calls.swapRemove(index);
|
||||
}
|
||||
@ -67,7 +67,7 @@ pub fn Sink(comptime Event: type) type {
|
||||
return null;
|
||||
}
|
||||
|
||||
fn indexOfBound(self: Self, ctx: var) ?usize {
|
||||
fn indexOfBound(self: Self, ctx: anytype) ?usize {
|
||||
for (owning_signal.calls.items) |call, i| {
|
||||
if (call.containsBound(ctx)) {
|
||||
return i;
|
||||
@ -112,4 +112,4 @@ test "Sink Before bound" {
|
||||
|
||||
signal.sink().beforeBound(&thing).connect(tester);
|
||||
std.testing.expectEqual(signal.sink().indexOf(tester).?, 0);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user