singletons
This commit is contained in:
parent
07905d0b09
commit
37af42daaa
@ -6,6 +6,7 @@ const Handles = @import("handles.zig").Handles;
|
|||||||
const SparseSet = @import("sparse_set.zig").SparseSet;
|
const SparseSet = @import("sparse_set.zig").SparseSet;
|
||||||
const ComponentStorage = @import("component_storage.zig").ComponentStorage;
|
const ComponentStorage = @import("component_storage.zig").ComponentStorage;
|
||||||
const Sink = @import("../signals/sink.zig").Sink;
|
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);
|
// allow overriding EntityTraits by setting in root via: EntityTraits = EntityTraitsType(.medium);
|
||||||
const root = @import("root");
|
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);
|
const EntityHandles = Handles(entity_traits.entity_type, entity_traits.index_type, entity_traits.version_type);
|
||||||
pub const Entity = entity_traits.entity_type;
|
pub const Entity = entity_traits.entity_type;
|
||||||
|
|
||||||
pub const BasicView = @import("views.zig").BasicView;
|
const BasicView = @import("views.zig").BasicView;
|
||||||
pub const MultiView = @import("views.zig").MultiView;
|
const MultiView = @import("views.zig").MultiView;
|
||||||
pub const BasicGroup = @import("groups.zig").BasicGroup;
|
const BasicGroup = @import("groups.zig").BasicGroup;
|
||||||
pub const OwningGroup = @import("groups.zig").OwningGroup;
|
const OwningGroup = @import("groups.zig").OwningGroup;
|
||||||
|
|
||||||
/// Stores an ArrayList of components. The max amount that can be stored is based on the type below
|
/// 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 {
|
pub fn Storage(comptime CompT: type) type {
|
||||||
@ -33,6 +34,7 @@ pub const Registry = struct {
|
|||||||
components: std.AutoHashMap(u32, usize),
|
components: std.AutoHashMap(u32, usize),
|
||||||
contexts: std.AutoHashMap(u32, usize),
|
contexts: std.AutoHashMap(u32, usize),
|
||||||
groups: std.ArrayList(*GroupData),
|
groups: std.ArrayList(*GroupData),
|
||||||
|
singletons: TypeStore,
|
||||||
allocator: *std.mem.Allocator,
|
allocator: *std.mem.Allocator,
|
||||||
|
|
||||||
/// internal, persistant data structure to manage the entities in a group
|
/// 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),
|
.components = std.AutoHashMap(u32, usize).init(allocator),
|
||||||
.contexts = std.AutoHashMap(u32, usize).init(allocator),
|
.contexts = std.AutoHashMap(u32, usize).init(allocator),
|
||||||
.groups = std.ArrayList(*GroupData).init(allocator),
|
.groups = std.ArrayList(*GroupData).init(allocator),
|
||||||
|
.singletons = TypeStore.init(allocator),
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -160,6 +163,7 @@ pub const Registry = struct {
|
|||||||
self.components.deinit();
|
self.components.deinit();
|
||||||
self.contexts.deinit();
|
self.contexts.deinit();
|
||||||
self.groups.deinit();
|
self.groups.deinit();
|
||||||
|
self.singletons.deinit();
|
||||||
self.handles.deinit();
|
self.handles.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +307,7 @@ pub const Registry = struct {
|
|||||||
return self.assure(T).getConst(entity);
|
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 {
|
pub fn getOrAdd(self: *Registry, comptime T: type, entity: Entity) *T {
|
||||||
if (self.has(T, entity)) return self.get(T, entity);
|
if (self.has(T, entity)) return self.get(T, entity);
|
||||||
self.add(T, entity, std.mem.zeros(T));
|
self.add(T, entity, std.mem.zeros(T));
|
||||||
@ -353,6 +357,11 @@ pub const Registry = struct {
|
|||||||
null;
|
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
|
/// Checks whether the given component belongs to any group
|
||||||
pub fn sortable(self: Registry, comptime T: type) bool {
|
pub fn sortable(self: Registry, comptime T: type) bool {
|
||||||
return true;
|
return true;
|
||||||
|
89
zig-ecs/src/ecs/type_store.zig
Normal file
89
zig-ecs/src/ecs/type_store.zig
Normal file
@ -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/sparse_set.zig");
|
||||||
_ = @import("ecs/views.zig");
|
_ = @import("ecs/views.zig");
|
||||||
_ = @import("ecs/groups.zig");
|
_ = @import("ecs/groups.zig");
|
||||||
|
_ = @import("ecs/type_store.zig");
|
||||||
|
|
||||||
// signals
|
// signals
|
||||||
_ = @import("signals/delegate.zig");
|
_ = @import("signals/delegate.zig");
|
||||||
|
@ -53,7 +53,7 @@ test "context not pointer" {
|
|||||||
// reg.setContext(pos);
|
// reg.setContext(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "component context get/set/unset" {
|
test "context get/set/unset" {
|
||||||
const SomeType = struct { dummy: u1 };
|
const SomeType = struct { dummy: u1 };
|
||||||
|
|
||||||
var reg = Registry.init(std.testing.allocator);
|
var reg = Registry.init(std.testing.allocator);
|
||||||
@ -72,6 +72,19 @@ test "component context get/set/unset" {
|
|||||||
std.testing.expectEqual(ctx, null);
|
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" {
|
test "destroy" {
|
||||||
var reg = Registry.init(std.testing.allocator);
|
var reg = Registry.init(std.testing.allocator);
|
||||||
defer reg.deinit();
|
defer reg.deinit();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user