master
Mike 5 years ago
parent 07905d0b09
commit 37af42daaa

@ -6,6 +6,7 @@ const Handles = @import("handles.zig").Handles;
const SparseSet = @import("sparse_set.zig").SparseSet;
const ComponentStorage = @import("component_storage.zig").ComponentStorage;
const Sink = @import("../signals/sink.zig").Sink;
const TypeStore = @import("type_store.zig").TypeStore;
// allow overriding EntityTraits by setting in root via: EntityTraits = EntityTraitsType(.medium);
const root = @import("root");
@ -15,10 +16,10 @@ const entity_traits = if (@hasDecl(root, "EntityTraits")) root.EntityTraits.init
const EntityHandles = Handles(entity_traits.entity_type, entity_traits.index_type, entity_traits.version_type);
pub const Entity = entity_traits.entity_type;
pub const BasicView = @import("views.zig").BasicView;
pub const MultiView = @import("views.zig").MultiView;
pub const BasicGroup = @import("groups.zig").BasicGroup;
pub const OwningGroup = @import("groups.zig").OwningGroup;
const BasicView = @import("views.zig").BasicView;
const MultiView = @import("views.zig").MultiView;
const BasicGroup = @import("groups.zig").BasicGroup;
const OwningGroup = @import("groups.zig").OwningGroup;
/// Stores an ArrayList of components. The max amount that can be stored is based on the type below
pub fn Storage(comptime CompT: type) type {
@ -33,6 +34,7 @@ pub const Registry = struct {
components: std.AutoHashMap(u32, usize),
contexts: std.AutoHashMap(u32, usize),
groups: std.ArrayList(*GroupData),
singletons: TypeStore,
allocator: *std.mem.Allocator,
/// internal, persistant data structure to manage the entities in a group
@ -141,6 +143,7 @@ pub const Registry = struct {
.components = std.AutoHashMap(u32, usize).init(allocator),
.contexts = std.AutoHashMap(u32, usize).init(allocator),
.groups = std.ArrayList(*GroupData).init(allocator),
.singletons = TypeStore.init(allocator),
.allocator = allocator,
};
}
@ -160,6 +163,7 @@ pub const Registry = struct {
self.components.deinit();
self.contexts.deinit();
self.groups.deinit();
self.singletons.deinit();
self.handles.deinit();
}
@ -303,7 +307,7 @@ pub const Registry = struct {
return self.assure(T).getConst(entity);
}
/// Returns a reference to the given component for an entity
/// Returns a reference to the given component for an entity creating it if necessary
pub fn getOrAdd(self: *Registry, comptime T: type, entity: Entity) *T {
if (self.has(T, entity)) return self.get(T, entity);
self.add(T, entity, std.mem.zeros(T));
@ -353,6 +357,11 @@ pub const Registry = struct {
null;
}
/// provides access to a TypeStore letting you add singleton components to the registry
pub fn singletons(self: Registry) TypeStore {
return self.singletons;
}
/// Checks whether the given component belongs to any group
pub fn sortable(self: Registry, comptime T: type) bool {
return true;

@ -0,0 +1,89 @@
const std = @import("std");
const utils = @import("utils.zig");
/// stores a single object of type T for each T added
pub const TypeStore = struct {
map: std.AutoHashMap(u32, []u8),
allocator: *std.mem.Allocator,
pub fn init(allocator: *std.mem.Allocator) TypeStore {
return TypeStore{
.map = std.AutoHashMap(u32, []u8).init(allocator),
.allocator = allocator,
};
}
pub fn deinit(self: TypeStore) void {
var iter = self.map.iterator();
while (iter.next()) |kv| {
self.allocator.free(kv.value);
}
self.map.deinit();
}
/// adds instance, returning a pointer to the item as it lives in the store
pub fn add(self: *TypeStore, instance: var) *@TypeOf(instance) {
var bytes = self.allocator.alloc(u8, @sizeOf(@TypeOf(instance))) catch unreachable;
var ptr = @ptrCast(*@TypeOf(instance), @alignCast(@alignOf(@TypeOf(instance)), bytes));
ptr.* = instance;
_ = self.map.put(utils.typeId(@TypeOf(instance)), bytes) catch unreachable;
return ptr;
}
pub fn get(self: *TypeStore, comptime T: type) *T {
if (self.map.getValue(utils.typeId(T))) |bytes| {
return @ptrCast(*T, @alignCast(@alignOf(T), bytes));
}
unreachable;
}
pub fn getConst(self: *TypeStore, comptime T: type) T {
return self.get(T).*;
}
pub fn getOrAdd(self: *TypeStore, comptime T: type) *T {
if (self.has(T)) return self.get(T);
var instance = std.mem.zeroes(T);
return self.add(instance);
}
pub fn remove(self: *TypeStore, comptime T: type) void {
if (self.map.getValue(utils.typeId(T))) |bytes| {
self.allocator.free(bytes);
_ = self.map.remove(utils.typeId(T));
}
}
pub fn has(self: *TypeStore, comptime T: type) bool {
return self.map.contains(utils.typeId(T));
}
};
test "TypeStore" {
const Vector = struct { x: f32 = 0, y: f32 = 0, z: f32 = 0};
var store = TypeStore.init(std.testing.allocator);
defer store.deinit();
var orig = Vector{.x = 5, .y = 6, .z = 8};
var inserted = store.add(orig);
std.testing.expect(store.has(Vector));
std.testing.expectEqual(inserted.*, Vector{.x = 5, .y = 6, .z = 8});
var v = store.get(Vector);
std.testing.expectEqual(v.*, Vector{.x = 5, .y = 6, .z = 8});
v.*.x = 666;
var v2 = store.get(Vector);
std.testing.expectEqual(v2.*, Vector{.x = 666, .y = 6, .z = 8});
store.remove(Vector);
std.testing.expect(!store.has(Vector));
var v3 = store.getOrAdd(u32);
std.testing.expectEqual(v3.*, 0);
v3.* = 777;
var v4 = store.get(u32);
std.testing.expectEqual(v3.*, 777);
}

@ -8,6 +8,7 @@ comptime {
_ = @import("ecs/sparse_set.zig");
_ = @import("ecs/views.zig");
_ = @import("ecs/groups.zig");
_ = @import("ecs/type_store.zig");
// signals
_ = @import("signals/delegate.zig");

@ -53,7 +53,7 @@ test "context not pointer" {
// reg.setContext(pos);
}
test "component context get/set/unset" {
test "context get/set/unset" {
const SomeType = struct { dummy: u1 };
var reg = Registry.init(std.testing.allocator);
@ -72,6 +72,19 @@ test "component context get/set/unset" {
std.testing.expectEqual(ctx, null);
}
test "singletons" {
var reg = Registry.init(std.testing.allocator);
defer reg.deinit();
var pos = Position{ .x = 5, .y = 5 };
var inserted = reg.singletons.add(pos);
std.testing.expect(reg.singletons.has(Position));
std.testing.expectEqual(inserted.*, pos);
reg.singletons.remove(Position);
std.testing.expect(!reg.singletons.has(Position));
}
test "destroy" {
var reg = Registry.init(std.testing.allocator);
defer reg.deinit();

Loading…
Cancel
Save