diff --git a/src/ecs/systems.zig b/src/ecs/systems.zig index 08ce1623..b380edc7 100644 --- a/src/ecs/systems.zig +++ b/src/ecs/systems.zig @@ -13,18 +13,18 @@ pub fn World(comptime mods: anytype) type { return struct { allocator: mem.Allocator, - entities: Entities(modules.components), + entities: Entities(NamespacedComponents(mods){}), mod: Mods(), const Self = @This(); pub fn Mod(comptime Module: anytype) type { const module_tag = Module.name; - const State = @TypeOf(@field(@as(modules.State, undefined), @tagName(module_tag))); - const components = @field(modules.components, @tagName(module_tag)); + const State = @TypeOf(@field(@as(NamespacedState(mods), undefined), @tagName(module_tag))); + const components = @field(NamespacedComponents(mods){}, @tagName(module_tag)); return struct { state: State, - entities: *Entities(modules.components), + entities: *Entities(NamespacedComponents(mods){}), allocator: mem.Allocator, /// Sets the named component to the specified value for the given entity, @@ -110,7 +110,7 @@ pub fn World(comptime mods: anytype) type { pub fn init(allocator: mem.Allocator) !Self { return Self{ .allocator = allocator, - .entities = try Entities(modules.components).init(allocator), + .entities = try Entities(NamespacedComponents(mods){}).init(allocator), .mod = undefined, }; } @@ -199,3 +199,70 @@ pub fn World(comptime mods: anytype) type { } }; } + +// TODO: reconsider components concept +fn NamespacedComponents(comptime modules: anytype) type { + var fields: []const std.builtin.Type.StructField = &[0]std.builtin.Type.StructField{}; + inline for (modules) |M| { + const components = if (@hasDecl(M, "components")) M.components else struct {}; + fields = fields ++ [_]std.builtin.Type.StructField{.{ + .name = @tagName(M.name), + .type = type, + .default_value = &components, + .is_comptime = true, + .alignment = @alignOf(@TypeOf(components)), + }}; + } + + // Builtin components + const entity_components = struct { + pub const id = EntityID; + }; + fields = fields ++ [_]std.builtin.Type.StructField{.{ + .name = "entity", + .type = type, + .default_value = &entity_components, + .is_comptime = true, + .alignment = @alignOf(@TypeOf(entity_components)), + }}; + + return @Type(.{ + .Struct = .{ + .layout = .Auto, + .is_tuple = false, + .fields = fields, + .decls = &[_]std.builtin.Type.Declaration{}, + }, + }); +} + +// TODO: reconsider state concept +fn NamespacedState(comptime modules: anytype) type { + var fields: []const std.builtin.Type.StructField = &[0]std.builtin.Type.StructField{}; + inline for (modules) |M| { + const state_fields = std.meta.fields(M); + const State = if (state_fields.len > 0) @Type(.{ + .Struct = .{ + .layout = .Auto, + .is_tuple = false, + .fields = state_fields, + .decls = &[_]std.builtin.Type.Declaration{}, + }, + }) else struct {}; + fields = fields ++ [_]std.builtin.Type.StructField{.{ + .name = @tagName(M.name), + .type = State, + .default_value = null, + .is_comptime = false, + .alignment = @alignOf(State), + }}; + } + return @Type(.{ + .Struct = .{ + .layout = .Auto, + .is_tuple = false, + .fields = fields, + .decls = &[_]std.builtin.Type.Declaration{}, + }, + }); +} diff --git a/src/module.zig b/src/module.zig index c66931f6..58bf23ea 100644 --- a/src/module.zig +++ b/src/module.zig @@ -2,14 +2,13 @@ const builtin = @import("builtin"); const std = @import("std"); const testing = @import("testing.zig"); -// TODO: eliminate dependency on ECS here. -const EntityID = @import("ecs/entities.zig").EntityID; - /// Verifies that T matches the basic layout of a Mach module pub fn Module(comptime T: type) type { if (@typeInfo(T) != .Struct) @compileError("Module must be a struct type. Found:" ++ @typeName(T)); if (!@hasDecl(T, "name")) @compileError("Module must have `pub const name = .foobar;`"); if (@typeInfo(@TypeOf(T.name)) != .EnumLiteral) @compileError("Module must have `pub const name = .foobar;`, found type:" ++ @typeName(T.name)); + + // TODO: move this to ecs if (@hasDecl(T, "components")) { if (@typeInfo(T.components) != .Struct) @compileError("Module.components must be `pub const components = struct { ... };`, found type:" ++ @typeName(T.components)); } @@ -32,9 +31,6 @@ pub fn Modules(comptime mods: anytype, comptime Injectable: type) type { /// Comptime modules pub const modules = mods; - pub const components = NamespacedComponents(mods){}; - pub const State = NamespacedState(mods); - // TODO: add runtime module support pub const ModuleID = u32; @@ -429,73 +425,6 @@ fn NamespacedModules(comptime modules: anytype) type { }); } -// TODO: reconsider components concept -fn NamespacedComponents(comptime modules: anytype) type { - var fields: []const std.builtin.Type.StructField = &[0]std.builtin.Type.StructField{}; - inline for (modules) |M| { - const components = if (@hasDecl(M, "components")) M.components else struct {}; - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = @tagName(M.name), - .type = type, - .default_value = &components, - .is_comptime = true, - .alignment = @alignOf(@TypeOf(components)), - }}; - } - - // Builtin components - const entity_components = struct { - pub const id = EntityID; - }; - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = "entity", - .type = type, - .default_value = &entity_components, - .is_comptime = true, - .alignment = @alignOf(@TypeOf(entity_components)), - }}; - - return @Type(.{ - .Struct = .{ - .layout = .Auto, - .is_tuple = false, - .fields = fields, - .decls = &[_]std.builtin.Type.Declaration{}, - }, - }); -} - -// TODO: reconsider state concept -fn NamespacedState(comptime modules: anytype) type { - var fields: []const std.builtin.Type.StructField = &[0]std.builtin.Type.StructField{}; - inline for (modules) |M| { - const state_fields = std.meta.fields(M); - const State = if (state_fields.len > 0) @Type(.{ - .Struct = .{ - .layout = .Auto, - .is_tuple = false, - .fields = state_fields, - .decls = &[_]std.builtin.Type.Declaration{}, - }, - }) else struct {}; - fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = @tagName(M.name), - .type = State, - .default_value = null, - .is_comptime = false, - .alignment = @alignOf(State), - }}; - } - return @Type(.{ - .Struct = .{ - .layout = .Auto, - .is_tuple = false, - .fields = fields, - .decls = &[_]std.builtin.Type.Declaration{}, - }, - }); -} - test { testing.refAllDeclsRecursive(@This()); } @@ -559,13 +488,6 @@ test Modules { testing.refAllDeclsRecursive(Physics); testing.refAllDeclsRecursive(Renderer); testing.refAllDeclsRecursive(Sprite2D); - - // access namespaced components - try testing.expect(type, Physics.components.location).eql(@TypeOf(modules).components.engine_physics.location); - try testing.expect(type, Renderer.components).eql(@TypeOf(modules).components.engine_renderer); - - // implicitly generated - _ = @TypeOf(modules).components.entity.id; } test EventName {