module: injected mach.Entity.Mod for global entity operations

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-05-07 14:14:31 -07:00 committed by Stephen Gutekanst
parent cb6bdd7eca
commit 65e2168b9f
11 changed files with 94 additions and 56 deletions

View file

@ -106,7 +106,7 @@ fn start(core: *Mod) !void {
core.state().run_state = .running;
}
fn init(core: *Mod) !void {
fn init(entity: *mach.Entity.Mod, core: *Mod) !void {
mach.core.allocator = gpa.allocator(); // TODO: banish this global allocator
// Initialize GPU implementation
@ -116,7 +116,7 @@ fn init(core: *Mod) !void {
try mach.core.init(.{});
// TODO(important): update this information upon framebuffer resize events
const main_window = try core.newEntity();
const main_window = try entity.new();
try core.set(main_window, .framebuffer_format, mach.core.descriptor.format);
try core.set(main_window, .framebuffer_width, mach.core.descriptor.width);
try core.set(main_window, .framebuffer_height, mach.core.descriptor.height);

View file

@ -40,7 +40,7 @@ pub const EventID = @import("module/main.zig").EventID;
pub const AnyEvent = @import("module/main.zig").AnyEvent;
pub const merge = @import("module/main.zig").merge;
pub const builtin_modules = @import("module/main.zig").builtin_modules;
pub const EntityModule = @import("module/main.zig").EntityModule;
pub const Entity = @import("module/main.zig").Entity;
/// To use experimental sysgpu graphics API, you can write this in your main.zig:
///

View file

@ -9,7 +9,7 @@ const StringTable = @import("StringTable.zig");
const ComponentTypesByName = @import("module.zig").ComponentTypesByName;
const merge = @import("main.zig").merge;
const builtin_modules = @import("main.zig").builtin_modules;
const EntityModule = @import("main.zig").EntityModule;
const Entity = @import("main.zig").Entity;
const ModuleName = @import("module.zig").ModuleName;
const ComponentNameM = @import("module.zig").ComponentNameM;
const ComponentName = @import("module.zig").ComponentName;
@ -130,7 +130,7 @@ pub fn Entities(comptime modules: anytype) type {
.component_names = component_names,
.buckets = buckets,
};
entities.id_name = entities.componentName(EntityModule.name, .id);
entities.id_name = entities.componentName(Entity.name, .id);
const columns = try allocator.alloc(Archetype.Column, 1);
columns[0] = .{
@ -1076,7 +1076,7 @@ test "example" {
// Query for all entities that have all of the given components
const W = @TypeOf(world);
var q = try world.query(.{
.ids = W.ComponentQuery{ .read = W.ModuleComponentName{ .module = EntityModule.name, .component = .id } },
.ids = W.ComponentQuery{ .read = W.ModuleComponentName{ .module = Entity.name, .component = .id } },
.rotations = W.ComponentQuery{ .write = W.ModuleComponentName{ .module = Game.name, .component = .rotation } },
});
while (q.next()) |v| {
@ -1090,7 +1090,7 @@ test "example" {
// Dynamic queries (e.g. issued from another programming language without comptime)
var q2 = try world.queryDynamic(.{
.op_and = &.{
.{ .read = world.componentName(EntityModule.name, .id) },
.{ .read = world.componentName(Entity.name, .id) },
.{ .read = world.componentName(Game.name, .rotation) },
},
});

View file

@ -13,10 +13,10 @@ pub const AnyEvent = @import("module.zig").AnyEvent;
pub const Merge = @import("module.zig").Merge;
pub const merge = @import("module.zig").merge;
pub const builtin_modules = .{EntityModule};
pub const builtin_modules = .{Entity};
/// Builtin .entity module
pub const EntityModule = struct {
pub const Entity = struct {
pub const name = .entity;
pub const Mod = mach.Mod(@This());
@ -82,14 +82,15 @@ test "entities DB" {
defer world.deinit(allocator);
// Initialize module state.
var entity = &world.mod.entity;
var physics = &world.mod.physics;
var renderer = &world.mod.renderer;
physics.init(.{ .pointer = 123 });
_ = physics.state().pointer; // == 123
const player1 = try physics.newEntity();
const player2 = try physics.newEntity();
const player3 = try physics.newEntity();
const player1 = try entity.new();
const player2 = try entity.new();
const player3 = try entity.new();
try physics.set(player1, .id, 1001);
try renderer.set(player1, .id, 1001);

View file

@ -574,6 +574,36 @@ pub fn ModSet(comptime modules: anytype) type {
pub fn Mod(comptime M: anytype) type {
const module_tag = M.name;
const components = ComponentTypesM(M){};
if (M.name == .entity) {
// The .entity module is a special builtin module, with its own unique API.
return struct {
/// Private/internal fields
__entities: *Entities(modules),
__is_initialized: bool,
__state: void,
pub const IsInjectedArgument = void;
pub inline fn read(comptime component_name: ComponentNameM(M)) Entities(modules).ComponentQuery {
return .{ .read = .{
.module = M.name,
.component = comptime stringToEnum(ComponentName(modules), @tagName(component_name)).?,
} };
}
/// Returns a new entity.
pub inline fn new(m: *@This()) !EntityID {
return m.__entities.new();
}
/// Removes an entity.
pub inline fn remove(m: *@This(), entity: EntityID) !void {
try m.__entities.remove(entity);
}
};
}
return struct {
/// Private/internal fields
__entities: *Entities(modules),
@ -622,16 +652,6 @@ pub fn ModSet(comptime modules: anytype) type {
return &m.__state;
}
/// Returns a new entity.
pub inline fn newEntity(m: *@This()) !EntityID {
return m.__entities.new();
}
/// Removes an entity.
pub inline fn removeEntity(m: *@This(), entity: EntityID) !void {
try m.__entities.remove(entity);
}
/// Sets the named component to the specified value for the given entity,
/// moving the entity from it's current archetype table to the new archetype
/// table if required.