encompass-zig/src/component_manager.zig

187 lines
5.6 KiB
Zig

const ComponentStore = @import("component_store.zig").ComponentStore;
const TypeStore = @import("type_store.zig").TypeStore;
const Entity = @import("entity.zig").Entity;
const std = @import("std");
const mem = std.mem;
const testing = std.testing;
const Allocator = mem.Allocator;
pub const ComponentManager = struct {
const Self = @This();
allocator: *Allocator,
component_stores: TypeStore,
pub fn init(allocator: *Allocator) Self {
return Self {
.allocator = allocator,
.component_stores = TypeStore.init(allocator),
};
}
pub fn deinit(self: *Self) void {
var iter = self.component_stores.map.iterator();
while (iter.next()) |ptr| {
// HACK: we dont know the Type here but we need to call deinit
var storage = @intToPtr(*ComponentStore(u1), ptr.value);
storage.deinit();
self.allocator.destroy(storage);
}
self.component_stores.deinit();
}
pub fn register(self: *Self, comptime TComponent: type) void {
const ptr = ComponentStore(TComponent).heapInit(self.allocator);
self.component_stores.add(ptr.*);
}
pub fn set_component(self: *Self, entityID: usize, component: anytype) void {
self.component_stores.get(ComponentStore(@TypeOf(component))).*.set(entityID, component);
}
pub fn get_component(self: *Self, comptime TComponent: type, entityID: usize) !TComponent {
return self.component_stores.get(ComponentStore(TComponent)).*.get(entityID) catch |err| return err;
}
pub fn has_component(self: *Self, comptime TComponent: type, entityID: usize) bool {
return self.component_stores.get(ComponentStore(TComponent)).*.has(entityID);
}
pub fn remove_component(self: *Self, comptime TComponent: type, entityID: usize) void {
return self.component_stores.get(ComponentStore(TComponent)).*.remove(entityID);
}
pub fn read_components(self: *Self, comptime TComponent: type) []TComponent {
return self.component_stores.get(ComponentStore(TComponent)).*.all_components();
}
pub fn read_entities(self: *Self, comptime TComponent: type) []Entity {
return self.component_stores.get(ComponentStore(TComponent)).*.all_entities();
}
};
const TestComponent = struct {
number: i32,
};
test "add component" {
const component = TestComponent {
.number = 3
};
var component_manager = ComponentManager.init(std.testing.allocator);
defer component_manager.deinit();
component_manager.register(TestComponent);
component_manager.set_component(2, component);
var expectedComponent = try component_manager.get_component(TestComponent, 2);
expectedComponent.number = 5; // should be immutable!
expectedComponent = try component_manager.get_component(TestComponent, 2);
testing.expect(expectedComponent.number == 3);
}
test "has component" {
const component = TestComponent {
.number = 69
};
var component_manager = ComponentManager.init(std.testing.allocator);
defer component_manager.deinit();
component_manager.register(TestComponent);
component_manager.set_component(420, component);
testing.expect(component_manager.has_component(TestComponent, 420));
testing.expect(!component_manager.has_component(TestComponent, 39));
}
test "remove component" {
const component = TestComponent {
.number = 3
};
const componentTwo = TestComponent {
.number = 8
};
const componentThree = TestComponent {
.number = 14
};
var component_manager = ComponentManager.init(std.testing.allocator);
defer component_manager.deinit();
component_manager.register(TestComponent);
component_manager.set_component(2, component);
component_manager.set_component(5, componentTwo);
component_manager.set_component(52, componentThree);
var components = component_manager.remove_component(TestComponent, 5);
testing.expect(!component_manager.has_component(TestComponent, 5));
testing.expect(component_manager.has_component(TestComponent, 52));
}
test "read components" {
const component = TestComponent {
.number = 3
};
const componentTwo = TestComponent {
.number = 8
};
const componentThree = TestComponent {
.number = 14
};
var component_manager = ComponentManager.init(std.testing.allocator);
defer component_manager.deinit();
component_manager.register(TestComponent);
component_manager.set_component(2, component);
component_manager.set_component(5, componentTwo);
component_manager.set_component(52, componentThree);
var components = component_manager.read_components(TestComponent);
testing.expect(components[0].number == 3);
testing.expect(components[1].number == 8);
testing.expect(components[2].number == 14);
}
test "read entities" {
const component = TestComponent {
.number = 3
};
const componentTwo = TestComponent {
.number = 8
};
const componentThree = TestComponent {
.number = 14
};
var component_manager = ComponentManager.init(std.testing.allocator);
defer component_manager.deinit();
component_manager.register(TestComponent);
component_manager.set_component(2, component);
component_manager.set_component(5, componentTwo);
component_manager.set_component(52, componentThree);
var entities = component_manager.read_entities(TestComponent);
testing.expect(entities[0].ID == 2);
testing.expect(entities[1].ID == 5);
testing.expect(entities[2].ID == 52);
}