module: refactor: pass modules through Entities comptime logic

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-05-04 18:45:36 -07:00
parent 95c9ae5278
commit 2075959dad
5 changed files with 29 additions and 26 deletions

View file

@ -10,6 +10,7 @@ const testing = std.testing;
const assert = std.debug.assert; const assert = std.debug.assert;
const builtin = @import("builtin"); const builtin = @import("builtin");
const StringTable = @import("StringTable.zig"); const StringTable = @import("StringTable.zig");
const ComponentTypesByName = @import("module.zig").ComponentTypesByName;
const Archetype = @This(); const Archetype = @This();
@ -271,7 +272,8 @@ pub inline fn debugAssertRowType(storage: *Archetype, row: anytype) void {
} }
// TODO: comptime refactor // TODO: comptime refactor
pub fn Slicer(comptime component_types_by_name: anytype) type { pub fn Slicer(comptime modules: anytype) type {
const component_types_by_name = ComponentTypesByName(modules){};
return struct { return struct {
archetype: *Archetype, archetype: *Archetype,

View file

@ -69,8 +69,8 @@ fn byTypeId(context: void, lhs: Archetype.Column, rhs: Archetype.Column) bool {
/// row index, enabling entities to "move" from one archetype table to another seamlessly and /// row index, enabling entities to "move" from one archetype table to another seamlessly and
/// making lookup by entity ID a few cheap array indexing operations. /// making lookup by entity ID a few cheap array indexing operations.
/// * ComponentStorage(T) is a column of data within a table for a single type of component `T`. /// * ComponentStorage(T) is a column of data within a table for a single type of component `T`.
pub fn Entities(comptime component_types_by_name: anytype) type { pub fn Entities(comptime modules: anytype) type {
// TODO: validate component_types_by_name is a namespaced component set in the form we expect const component_types_by_name = ComponentTypesByName(modules){};
return struct { return struct {
allocator: Allocator, allocator: Allocator,
@ -107,7 +107,7 @@ pub fn Entities(comptime component_types_by_name: anytype) type {
}; };
/// A complex query for entities matching a given criteria /// A complex query for entities matching a given criteria
pub const Query = query_mod.Query(component_types_by_name); pub const Query = query_mod.Query(modules);
pub const QueryTag = query_mod.QueryTag; pub const QueryTag = query_mod.QueryTag;
pub fn init(allocator: Allocator) !Self { pub fn init(allocator: Allocator) !Self {
@ -615,8 +615,8 @@ pub fn Entities(comptime component_types_by_name: anytype) type {
pub fn query( pub fn query(
entities: *Self, entities: *Self,
q: Query, q: Query,
) ArchetypeIterator(component_types_by_name) { ) ArchetypeIterator(modules) {
return ArchetypeIterator(component_types_by_name).init(entities, q); return ArchetypeIterator(modules).init(entities, q);
} }
// TODO: queryDynamic // TODO: queryDynamic
@ -639,8 +639,8 @@ pub fn Entities(comptime component_types_by_name: anytype) type {
} }
// TODO: move this type somewhere else // TODO: move this type somewhere else
pub fn ArchetypeIterator(comptime component_types_by_name: anytype) type { pub fn ArchetypeIterator(comptime modules: anytype) type {
const EntitiesT = Entities(component_types_by_name); const EntitiesT = Entities(modules);
return struct { return struct {
entities: *EntitiesT, entities: *EntitiesT,
query: EntitiesT.Query, query: EntitiesT.Query,
@ -657,11 +657,11 @@ pub fn ArchetypeIterator(comptime component_types_by_name: anytype) type {
} }
// TODO: component_types_by_name is a superset of queried items, not type-safe. // TODO: component_types_by_name is a superset of queried items, not type-safe.
pub fn next(iter: *Self) ?Archetype.Slicer(component_types_by_name) { pub fn next(iter: *Self) ?Archetype.Slicer(modules) {
while (iter.index < iter.entities.archetypes.items.len) { while (iter.index < iter.entities.archetypes.items.len) {
const archetype = &iter.entities.archetypes.items[iter.index]; const archetype = &iter.entities.archetypes.items[iter.index];
iter.index += 1; iter.index += 1;
if (iter.match(archetype)) return Archetype.Slicer(component_types_by_name){ .archetype = archetype }; if (iter.match(archetype)) return Archetype.Slicer(modules){ .archetype = archetype };
} }
return null; return null;
} }
@ -701,9 +701,9 @@ pub fn ArchetypeIterator(comptime component_types_by_name: anytype) type {
} }
test { test {
const modules = ComponentTypesByName(merge(.{ const modules = merge(.{
builtin_modules, builtin_modules,
})){}; });
std.testing.refAllDeclsRecursive(Entities(modules)); std.testing.refAllDeclsRecursive(Entities(modules));
} }
@ -754,7 +754,7 @@ test "example" {
const Rotation = struct { degrees: f32 }; const Rotation = struct { degrees: f32 };
const component_types_by_name = ComponentTypesByName(merge(.{ const modules = merge(.{
builtin_modules, builtin_modules,
struct { struct {
pub const name = .game; pub const name = .game;
@ -764,11 +764,11 @@ test "example" {
.rotation = .{ .type = Rotation }, .rotation = .{ .type = Rotation },
}; };
}, },
})){}; });
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Create a world. // Create a world.
var world = try Entities(component_types_by_name).init(allocator); var world = try Entities(modules).init(allocator);
defer world.deinit(); defer world.deinit();
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -859,7 +859,7 @@ test "many entities" {
const Rotation = struct { degrees: f32 }; const Rotation = struct { degrees: f32 };
const component_types_by_name = ComponentTypesByName(.{ const modules = .{
struct { struct {
pub const name = .game; pub const name = .game;
pub const components = .{ pub const components = .{
@ -868,10 +868,10 @@ test "many entities" {
.rotation = .{ .type = Rotation }, .rotation = .{ .type = Rotation },
}; };
}, },
}){}; };
// Create many entities // Create many entities
var world = try Entities(component_types_by_name).init(allocator); var world = try Entities(modules).init(allocator);
defer world.deinit(); defer world.deinit();
for (0..8192) |_| { for (0..8192) |_| {
const player = try world.new(); const player = try world.new();

View file

@ -112,7 +112,7 @@ test "entities DB" {
try testing.expectEqual(@as(usize, 1001), ids[0]); try testing.expectEqual(@as(usize, 1001), ids[0]);
// TODO: can't write @as type here easily due to generic parameter, should be exposed // TODO: can't write @as type here easily due to generic parameter, should be exposed
// ?Archetype.Slicer(component_types_by_name) // ?Archetype.Slicer(modules)
try testing.expectEqual(iter.next(), null); try testing.expectEqual(iter.next(), null);
//------------------------------------------------------------------------- //-------------------------------------------------------------------------

View file

@ -200,12 +200,12 @@ pub fn Modules(comptime modules: anytype) type {
events: EventQueue, events: EventQueue,
mod: ModsByName(modules), mod: ModsByName(modules),
// TODO: pass mods directly instead of ComponentTypesByName? // TODO: pass mods directly instead of ComponentTypesByName?
entities: Entities(component_types_by_name), entities: Entities(modules),
debug_trace: bool, debug_trace: bool,
pub fn init(m: *@This(), allocator: std.mem.Allocator) !void { pub fn init(m: *@This(), allocator: std.mem.Allocator) !void {
// TODO: switch Entities to stack allocation like Modules is // TODO: switch Entities to stack allocation like Modules is
var entities = try Entities(component_types_by_name).init(allocator); var entities = try Entities(modules).init(allocator);
errdefer entities.deinit(); errdefer entities.deinit();
const debug_trace_str = std.process.getEnvVarOwned( const debug_trace_str = std.process.getEnvVarOwned(
@ -577,7 +577,7 @@ pub fn ModSet(comptime modules: anytype) type {
const module_tag = M.name; const module_tag = M.name;
const components = ComponentTypesM(M){}; const components = ComponentTypesM(M){};
return struct { return struct {
entities: *Entities(ComponentTypesByName(modules){}), entities: *Entities(modules),
/// Private/internal fields /// Private/internal fields
__is_initialized: bool, __is_initialized: bool,

View file

@ -8,7 +8,8 @@ pub const QueryTag = enum {
}; };
/// A complex query for entities matching a given criteria /// A complex query for entities matching a given criteria
pub fn Query(comptime component_types_by_name: anytype) type { pub fn Query(comptime modules: anytype) type {
const component_types_by_name = ComponentTypesByName(modules){};
return union(QueryTag) { return union(QueryTag) {
// TODO: cleanup comptime // TODO: cleanup comptime
/// Enum matching a namespace. e.g. `.game` or `.physics2d` /// Enum matching a namespace. e.g. `.game` or `.physics2d`
@ -79,7 +80,7 @@ test "query" {
const Rotation = struct { degrees: f32 }; const Rotation = struct { degrees: f32 };
const component_types_by_name = ComponentTypesByName(.{ const modules = .{
struct { struct {
pub const name = .game; pub const name = .game;
pub const components = .{ pub const components = .{
@ -96,9 +97,9 @@ test "query" {
struct { struct {
pub const name = .renderer; pub const name = .renderer;
}, },
}){}; };
const Q = Query(component_types_by_name); const Q = Query(modules);
// Namespace type lets us select a single namespace. // Namespace type lets us select a single namespace.
try testing.expectEqual(@as(Q.Namespace, .game), .game); try testing.expectEqual(@as(Q.Namespace, .game), .game);