ecs: add support for module global values
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
3fddb687bc
commit
f74faf90df
2 changed files with 94 additions and 0 deletions
|
|
@ -53,6 +53,9 @@ test "example" {
|
|||
.components = .{
|
||||
.id = u16,
|
||||
},
|
||||
.globals = struct{
|
||||
pointer: u8,
|
||||
},
|
||||
}),
|
||||
.geometry = Module(.{
|
||||
.components = .{
|
||||
|
|
@ -66,6 +69,10 @@ test "example" {
|
|||
var world = try World(modules).init(allocator);
|
||||
defer world.deinit();
|
||||
|
||||
// Initialize globals.
|
||||
world.set(.physics, .pointer, 123);
|
||||
_ = world.get(.physics, .pointer); // == 123
|
||||
|
||||
const player1 = try world.entities.new();
|
||||
const player2 = try world.entities.new();
|
||||
const player3 = try world.entities.new();
|
||||
|
|
|
|||
|
|
@ -106,12 +106,71 @@ fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules)
|
|||
return x;
|
||||
}
|
||||
|
||||
/// Extracts namespaced globals from modules like this:
|
||||
///
|
||||
/// ```
|
||||
/// .{
|
||||
/// .renderer = .{
|
||||
/// .globals = struct{
|
||||
/// foo: *Bar,
|
||||
/// baz: Bam,
|
||||
/// },
|
||||
/// ...
|
||||
/// },
|
||||
/// .physics2d = .{
|
||||
/// .globals = struct{
|
||||
/// foo: *Instance,
|
||||
/// },
|
||||
/// ...
|
||||
/// },
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Into a namespaced global type like this:
|
||||
///
|
||||
/// ```
|
||||
/// struct{
|
||||
/// renderer: struct{
|
||||
/// foo: *Bar,
|
||||
/// baz: Bam,
|
||||
/// },
|
||||
/// physics2d: struct{
|
||||
/// foo: *Instance,
|
||||
/// },
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
fn NamespacedGlobals(comptime modules: anytype) type {
|
||||
var fields: []const StructField = &[0]StructField{};
|
||||
inline for (std.meta.fields(@TypeOf(modules))) |module_field| {
|
||||
const module = @field(modules, module_field.name);
|
||||
if (@hasField(@TypeOf(module), "globals")) {
|
||||
fields = fields ++ [_]std.builtin.Type.StructField{.{
|
||||
.name = module_field.name,
|
||||
.field_type = module.globals,
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(module.globals),
|
||||
}};
|
||||
}
|
||||
}
|
||||
return @Type(.{
|
||||
.Struct = .{
|
||||
.layout = .Auto,
|
||||
.is_tuple = false,
|
||||
.fields = fields,
|
||||
.decls = &[_]std.builtin.Type.Declaration{},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
pub fn World(comptime modules: anytype) type {
|
||||
const all_components = namespacedComponents(modules);
|
||||
return struct {
|
||||
allocator: Allocator,
|
||||
systems: std.StringArrayHashMapUnmanaged(System) = .{},
|
||||
entities: Entities(all_components),
|
||||
globals: NamespacedGlobals(modules),
|
||||
|
||||
const Self = @This();
|
||||
pub const System = fn (adapter: *Adapter(modules)) void;
|
||||
|
|
@ -120,6 +179,7 @@ pub fn World(comptime modules: anytype) type {
|
|||
return Self{
|
||||
.allocator = allocator,
|
||||
.entities = try Entities(all_components).init(allocator),
|
||||
.globals = undefined,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +188,33 @@ pub fn World(comptime modules: anytype) type {
|
|||
world.entities.deinit();
|
||||
}
|
||||
|
||||
/// Gets a global value called `.global_tag` from the module named `.module_tag`
|
||||
pub fn get(world: *Self, module_tag: anytype, global_tag: anytype) @TypeOf(@field(
|
||||
@field(world.globals, @tagName(module_tag)),
|
||||
@tagName(global_tag),
|
||||
)) {
|
||||
return comptime @field(
|
||||
@field(world.globals, @tagName(module_tag)),
|
||||
@tagName(global_tag),
|
||||
);
|
||||
}
|
||||
|
||||
/// Sets a global value called `.global_tag` in the module named `.module_tag`
|
||||
pub fn set(
|
||||
world: *Self,
|
||||
comptime module_tag: anytype,
|
||||
comptime global_tag: anytype,
|
||||
value: @TypeOf(@field(
|
||||
@field(world.globals, @tagName(module_tag)),
|
||||
@tagName(global_tag),
|
||||
)),
|
||||
) void {
|
||||
comptime @field(
|
||||
@field(world.globals, @tagName(module_tag)),
|
||||
@tagName(global_tag),
|
||||
) = value;
|
||||
}
|
||||
|
||||
pub fn register(world: *Self, name: []const u8, system: System) !void {
|
||||
try world.systems.put(world.allocator, name, system);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue