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 = .{
|
.components = .{
|
||||||
.id = u16,
|
.id = u16,
|
||||||
},
|
},
|
||||||
|
.globals = struct{
|
||||||
|
pointer: u8,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
.geometry = Module(.{
|
.geometry = Module(.{
|
||||||
.components = .{
|
.components = .{
|
||||||
|
|
@ -66,6 +69,10 @@ test "example" {
|
||||||
var world = try World(modules).init(allocator);
|
var world = try World(modules).init(allocator);
|
||||||
defer world.deinit();
|
defer world.deinit();
|
||||||
|
|
||||||
|
// Initialize globals.
|
||||||
|
world.set(.physics, .pointer, 123);
|
||||||
|
_ = world.get(.physics, .pointer); // == 123
|
||||||
|
|
||||||
const player1 = try world.entities.new();
|
const player1 = try world.entities.new();
|
||||||
const player2 = try world.entities.new();
|
const player2 = try world.entities.new();
|
||||||
const player3 = try world.entities.new();
|
const player3 = try world.entities.new();
|
||||||
|
|
|
||||||
|
|
@ -106,12 +106,71 @@ fn namespacedComponents(comptime modules: anytype) NamespacedComponents(modules)
|
||||||
return x;
|
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 {
|
pub fn World(comptime modules: anytype) type {
|
||||||
const all_components = namespacedComponents(modules);
|
const all_components = namespacedComponents(modules);
|
||||||
return struct {
|
return struct {
|
||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
systems: std.StringArrayHashMapUnmanaged(System) = .{},
|
systems: std.StringArrayHashMapUnmanaged(System) = .{},
|
||||||
entities: Entities(all_components),
|
entities: Entities(all_components),
|
||||||
|
globals: NamespacedGlobals(modules),
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
pub const System = fn (adapter: *Adapter(modules)) void;
|
pub const System = fn (adapter: *Adapter(modules)) void;
|
||||||
|
|
@ -120,6 +179,7 @@ pub fn World(comptime modules: anytype) type {
|
||||||
return Self{
|
return Self{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.entities = try Entities(all_components).init(allocator),
|
.entities = try Entities(all_components).init(allocator),
|
||||||
|
.globals = undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,6 +188,33 @@ pub fn World(comptime modules: anytype) type {
|
||||||
world.entities.deinit();
|
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 {
|
pub fn register(world: *Self, name: []const u8, system: System) !void {
|
||||||
try world.systems.put(world.allocator, name, system);
|
try world.systems.put(world.allocator, name, system);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue