module: move namespaced state/components to ecs
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
e24d09cd62
commit
388a1fbfca
2 changed files with 74 additions and 85 deletions
|
|
@ -13,18 +13,18 @@ pub fn World(comptime mods: anytype) type {
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
allocator: mem.Allocator,
|
allocator: mem.Allocator,
|
||||||
entities: Entities(modules.components),
|
entities: Entities(NamespacedComponents(mods){}),
|
||||||
mod: Mods(),
|
mod: Mods(),
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
pub fn Mod(comptime Module: anytype) type {
|
pub fn Mod(comptime Module: anytype) type {
|
||||||
const module_tag = Module.name;
|
const module_tag = Module.name;
|
||||||
const State = @TypeOf(@field(@as(modules.State, undefined), @tagName(module_tag)));
|
const State = @TypeOf(@field(@as(NamespacedState(mods), undefined), @tagName(module_tag)));
|
||||||
const components = @field(modules.components, @tagName(module_tag));
|
const components = @field(NamespacedComponents(mods){}, @tagName(module_tag));
|
||||||
return struct {
|
return struct {
|
||||||
state: State,
|
state: State,
|
||||||
entities: *Entities(modules.components),
|
entities: *Entities(NamespacedComponents(mods){}),
|
||||||
allocator: mem.Allocator,
|
allocator: mem.Allocator,
|
||||||
|
|
||||||
/// Sets the named component to the specified value for the given entity,
|
/// 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 {
|
pub fn init(allocator: mem.Allocator) !Self {
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.entities = try Entities(modules.components).init(allocator),
|
.entities = try Entities(NamespacedComponents(mods){}).init(allocator),
|
||||||
.mod = undefined,
|
.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{},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,13 @@ const builtin = @import("builtin");
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const testing = @import("testing.zig");
|
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
|
/// Verifies that T matches the basic layout of a Mach module
|
||||||
pub fn Module(comptime T: type) type {
|
pub fn Module(comptime T: type) type {
|
||||||
if (@typeInfo(T) != .Struct) @compileError("Module must be a struct type. Found:" ++ @typeName(T));
|
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 (!@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));
|
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 (@hasDecl(T, "components")) {
|
||||||
if (@typeInfo(T.components) != .Struct) @compileError("Module.components must be `pub const components = struct { ... };`, found type:" ++ @typeName(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
|
/// Comptime modules
|
||||||
pub const modules = mods;
|
pub const modules = mods;
|
||||||
|
|
||||||
pub const components = NamespacedComponents(mods){};
|
|
||||||
pub const State = NamespacedState(mods);
|
|
||||||
|
|
||||||
// TODO: add runtime module support
|
// TODO: add runtime module support
|
||||||
|
|
||||||
pub const ModuleID = u32;
|
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 {
|
test {
|
||||||
testing.refAllDeclsRecursive(@This());
|
testing.refAllDeclsRecursive(@This());
|
||||||
}
|
}
|
||||||
|
|
@ -559,13 +488,6 @@ test Modules {
|
||||||
testing.refAllDeclsRecursive(Physics);
|
testing.refAllDeclsRecursive(Physics);
|
||||||
testing.refAllDeclsRecursive(Renderer);
|
testing.refAllDeclsRecursive(Renderer);
|
||||||
testing.refAllDeclsRecursive(Sprite2D);
|
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 {
|
test EventName {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue