diff --git a/examples/custom-renderer/Game.zig b/examples/custom-renderer/Game.zig index 126c1957..ec179c18 100644 --- a/examples/custom-renderer/Game.zig +++ b/examples/custom-renderer/Game.zig @@ -17,7 +17,7 @@ spawning: bool = false, spawn_timer: mach.Timer, pub const components = .{ - .{ .name = .follower, .type = void }, + .follower = .{ .type = void }, }; pub const global_events = .{ diff --git a/examples/custom-renderer/Renderer.zig b/examples/custom-renderer/Renderer.zig index 3580b367..bd3662b2 100644 --- a/examples/custom-renderer/Renderer.zig +++ b/examples/custom-renderer/Renderer.zig @@ -21,9 +21,9 @@ pub const name = .renderer; pub const Mod = mach.Mod(@This()); pub const components = .{ - .{ .name = .location, .type = Vec3 }, - .{ .name = .rotation, .type = Vec3 }, - .{ .name = .scale, .type = f32 }, + .location = .{ .type = Vec3 }, + .rotation = .{ .type = Vec3 }, + .scale = .{ .type = f32 }, }; pub const global_events = .{ diff --git a/src/ecs/entities.zig b/src/ecs/entities.zig index df74f47c..971ef3e5 100644 --- a/src/ecs/entities.zig +++ b/src/ecs/entities.zig @@ -754,9 +754,9 @@ test "example" { struct { pub const name = .game; pub const components = .{ - .{ .name = .name, .type = []const u8 }, - .{ .name = .location, .type = Location }, - .{ .name = .rotation, .type = Rotation }, + .name = .{ .type = []const u8 }, + .location = .{ .type = Location }, + .rotation = .{ .type = Rotation }, }; }, }){}; @@ -858,9 +858,9 @@ test "many entities" { struct { pub const name = .game; pub const components = .{ - .{ .name = .name, .type = []const u8 }, - .{ .name = .location, .type = Location }, - .{ .name = .rotation, .type = Rotation }, + .name = .{ .type = []const u8 }, + .location = .{ .type = Location }, + .rotation = .{ .type = Rotation }, }; }, }){}; diff --git a/src/ecs/main.zig b/src/ecs/main.zig index c98dbf49..01ae0ec2 100644 --- a/src/ecs/main.zig +++ b/src/ecs/main.zig @@ -47,7 +47,7 @@ test "example" { pub const name = .physics; pub const components = .{ - .{ .name = .id, .type = u32 }, + .id = .{ .type = u32 }, }; pub const global_events = .{ .tick = .{ .handler = tick }, @@ -61,7 +61,7 @@ test "example" { const Renderer = struct { pub const name = .renderer; pub const components = .{ - .{ .name = .id, .type = u16 }, + .id = .{ .type = u16 }, }; pub const global_events = .{ .tick = .{ .handler = tick }, diff --git a/src/ecs/query.zig b/src/ecs/query.zig index 9a8655b6..652614b7 100644 --- a/src/ecs/query.zig +++ b/src/ecs/query.zig @@ -74,14 +74,14 @@ test "query" { struct { pub const name = .game; pub const components = .{ - .{ .name = .name, .type = []const u8 }, + .name = .{ .type = []const u8 }, }; }, struct { pub const name = .physics; pub const components = .{ - .{ .name = .location, .type = Location }, - .{ .name = .rotation, .type = Rotation }, + .location = .{ .type = Location }, + .rotation = .{ .type = Rotation }, }; }, struct { diff --git a/src/gfx/Sprite.zig b/src/gfx/Sprite.zig index bd12a1d8..4d65fdda 100644 --- a/src/gfx/Sprite.zig +++ b/src/gfx/Sprite.zig @@ -19,13 +19,13 @@ pub const name = .mach_gfx_sprite; pub const Mod = mach.Mod(@This()); pub const components = .{ - .{ .name = .pipeline, .type = u8, .description = + .pipeline = .{ .type = u8, .description = \\ The ID of the pipeline this sprite belongs to. By default, zero. \\ \\ This determines which shader, textures, etc. are used for rendering the sprite. }, - .{ .name = .transform, .type = Mat4x4, .description = + .transform = .{ .type = Mat4x4, .description = \\ The sprite model transformation matrix. A sprite is measured in pixel units, starting from \\ (0, 0) at the top-left corner and extending to the size of the sprite. By default, the world \\ origin (0, 0) lives at the center of the window. @@ -34,11 +34,11 @@ pub const components = .{ \\ cover the top-right hand corner of the window. }, - .{ .name = .uv_transform, .type = Mat3x3, .description = + .uv_transform = .{ .type = Mat3x3, .description = \\ UV coordinate transformation matrix describing top-left corner / origin of sprite, in pixels. }, - .{ .name = .size, .type = Vec2, .description = + .size = .{ .type = Vec2, .description = \\ The size of the sprite, in pixels. }, }; diff --git a/src/gfx/Text.zig b/src/gfx/Text.zig index d62b101d..a5bfcc0a 100644 --- a/src/gfx/Text.zig +++ b/src/gfx/Text.zig @@ -28,52 +28,52 @@ pub const Mod = mach.Mod(@This()); // TODO: allow user to specify projection matrix (3d-space flat text etc.) pub const components = .{ - .{ .name = .pipeline, .type = u8, .description = + .pipeline = .{ .type = u8, .description = \\ The ID of the pipeline this text belongs to. By default, zero. \\ \\ This determines which shader, textures, etc. are used for rendering the text. }, - .{ .name = .transform, .type = Mat4x4, .description = + .transform = .{ .type = Mat4x4, .description = \\ The text model transformation matrix. Text is measured in pixel units, starting from \\ (0, 0) at the top-left corner and extending to the size of the text. By default, the world \\ origin (0, 0) lives at the center of the window. }, - .{ .name = .text, .type = []const []const u8, .description = + .text = .{ .type = []const []const u8, .description = \\ String segments of UTF-8 encoded text to render. \\ \\ Expected to match the length of the style component. }, - .{ .name = .style, .type = []const mach.ecs.EntityID, .description = + .style = .{ .type = []const mach.ecs.EntityID, .description = \\ The style to apply to each segment of text. \\ \\ Expected to match the length of the text component. }, // TODO: ship a default font - .{ .name = .font_name, .type = []const u8, .description = + .font_name = .{ .type = []const u8, .description = \\ Style component: desired font to render text with. }, // e.g. 12 * mach.gfx.px_per_pt // 12pt - .{ .name = .font_size, .type = f32, .description = + .font_size = .{ .type = f32, .description = \\ Style component: font size in pixels }, // e.g. mach.gfx.font_weight_normal - .{ .name = .font_weight, .type = u16, .description = + .font_weight = .{ .type = u16, .description = \\ Style component: font weight }, // e.g. false - .{ .name = .italic, .type = bool, .description = + .italic = .{ .type = bool, .description = \\ Style component: italic text }, // e.g. vec4(0, 0, 0, 1.0) - .{ .name = .color, .type = Vec4, .description = + .color = .{ .type = Vec4, .description = \\ Style component: fill color }, }; diff --git a/src/module.zig b/src/module.zig index 403d1cd0..1e716b2e 100644 --- a/src/module.zig +++ b/src/module.zig @@ -744,7 +744,7 @@ pub fn ComponentTypesByName(comptime modules: anytype) type { const BuiltinMC = ComponentTypesM(struct { pub const name = .builtin; pub const components = .{ - .{ .name = .id, .type = EntityID, .description = "Entity ID" }, + .id = .{ .type = EntityID, .description = "Entity ID" }, }; }); fields = fields ++ [_]std.builtin.Type.StructField{.{ @@ -779,42 +779,33 @@ fn ComponentTypesM(comptime M: anytype) type { if (!@hasDecl(M, "components")) { return struct {}; } - if (@typeInfo(@TypeOf(M.components)) != .Struct or !@typeInfo(@TypeOf(M.components)).Struct.is_tuple) { - @compileError(error_prefix ++ "expected a tuple of structs, found: " ++ @typeName(@TypeOf(M.components))); + if (@typeInfo(@TypeOf(M.components)) != .Struct or @typeInfo(@TypeOf(M.components)).Struct.is_tuple) { + @compileError(error_prefix ++ "expected a struct .{}, found: " ++ @typeName(@TypeOf(M.components))); } var fields: []const std.builtin.Type.StructField = &[0]std.builtin.Type.StructField{}; - inline for (M.components, 0..) |component, i| { - const Component = @TypeOf(component); + inline for (@typeInfo(@TypeOf(M.components)).Struct.fields) |field| { + const Component = field.type; if (@typeInfo(Component) != .Struct) @compileError(std.fmt.comptimePrint( - error_prefix ++ "expected a tuple of structs, found tuple element ({}): {s}", - .{ i, @typeName(Component) }, - )); - - // Verify .name = .foo component name field - const name_tag = if (@hasField(Component, "name")) component.name else @compileError(std.fmt.comptimePrint( - error_prefix ++ "tuple element ({}) missing field `.name = .foo` (component name)", - .{i}, - )); - if (@typeInfo(@TypeOf(name_tag)) != .EnumLiteral) @compileError(std.fmt.comptimePrint( - error_prefix ++ "tuple element ({}) expected field `.name = .foo`, found: {s}", - .{ i, @typeName(@TypeOf(name_tag)) }, + error_prefix ++ "expected .{s} = .{{}}, found type: {s}", + .{ field.name, @typeName(Component) }, )); + const component = @field(M.components, field.name); // Verify .type = Foo, field if (!@hasField(Component, "type")) @compileError(std.fmt.comptimePrint( - error_prefix ++ "tuple element ({}) missing field `.type = Foo`", - .{i}, + error_prefix ++ ".{s} missing field `.type = T`", + .{field.name}, )); if (@typeInfo(@TypeOf(component.type)) != .Type) @compileError(std.fmt.comptimePrint( - error_prefix ++ "tuple element ({}) expected field `.type = Foo`, found: {s}", - .{ i, @typeName(@TypeOf(component.type)) }, + error_prefix ++ ".{s} expected field `.type = T`, found: {s}", + .{ field.name, @typeName(@TypeOf(component.type)) }, )); const description = blk: { if (@hasField(Component, "description")) { if (!isString(@TypeOf(component.description))) @compileError(std.fmt.comptimePrint( - error_prefix ++ "tuple element ({}) expected (optional) field `.description = \"foo\"`, found: {s}", - .{ i, @typeName(@TypeOf(component.description)) }, + error_prefix ++ ".{s} expected (optional) field `.description = \"foo\"`, found: {s}", + .{ field.name, @typeName(@TypeOf(component.description)) }, )); break :blk component.description; } else break :blk null; @@ -826,7 +817,7 @@ fn ComponentTypesM(comptime M: anytype) type { }; const ns_component = NSComponent{ .type = component.type, .description = description }; fields = fields ++ [_]std.builtin.Type.StructField{.{ - .name = @tagName(name_tag), + .name = field.name, .type = NSComponent, .default_value = &ns_component, .is_comptime = true, @@ -888,7 +879,7 @@ test ModuleInterface { /// Physics module components pub const components = .{ - .{ .name = .location, .type = @Vector(3, f32), .description = "A location component" }, + .location = .{ .type = @Vector(3, f32), .description = "A location component" }, }; pub const global_events = .{ @@ -909,7 +900,7 @@ test Modules { /// Physics module components pub const components = .{ - .{ .name = .location, .type = @Vector(3, f32), .description = "A location component" }, + .location = .{ .type = @Vector(3, f32), .description = "A location component" }, }; pub const global_events = .{ @@ -925,9 +916,6 @@ test Modules { .tick = .{ .handler = tick }, }; - /// Renderer module components - pub const components = .{}; - fn tick() !void {} }); @@ -950,7 +938,6 @@ test Modules { test "event name" { const Physics = ModuleInterface(struct { pub const name = .engine_physics; - pub const components = .{}; pub const global_events = .{ .foo = .{ .handler = foo }, .bar = .{ .handler = bar }, @@ -968,7 +955,6 @@ test "event name" { const Renderer = ModuleInterface(struct { pub const name = .engine_renderer; - pub const components = .{}; pub const global_events = .{ .foo_unused = .{ .handler = fn (f32, i32) void }, .bar_unused = .{ .handler = fn (i32, f32) void }, @@ -1162,7 +1148,6 @@ test "event name calling" { }; const Physics = ModuleInterface(struct { pub const name = .engine_physics; - pub const components = .{}; pub const global_events = .{ .tick = .{ .handler = tick }, }; @@ -1185,7 +1170,6 @@ test "event name calling" { }); const Renderer = ModuleInterface(struct { pub const name = .engine_renderer; - pub const components = .{}; pub const global_events = .{ .tick = .{ .handler = tick }, }; @@ -1295,7 +1279,6 @@ test "dispatch" { }); const Renderer = ModuleInterface(struct { pub const name = .engine_renderer; - pub const components = .{}; pub const global_events = .{ .tick = .{ .handler = tick }, .frame_done = .{ .handler = fn (i32) void },