module: components are written in the same style as events
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
f50a27b83d
commit
7e0b9dde68
10 changed files with 265 additions and 123 deletions
|
|
@ -42,16 +42,18 @@ pub fn ArchetypeSlicer(comptime all_components: anytype) type {
|
|||
|
||||
pub fn slice(
|
||||
slicer: @This(),
|
||||
// TODO: cleanup comptime
|
||||
comptime namespace_name: std.meta.FieldEnum(@TypeOf(all_components)),
|
||||
comptime component_name: std.meta.DeclEnum(@field(all_components, @tagName(namespace_name))),
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(@field(all_components, @tagName(namespace_name)))),
|
||||
) []@field(
|
||||
@field(all_components, @tagName(namespace_name)),
|
||||
@tagName(component_name),
|
||||
) {
|
||||
).type {
|
||||
// TODO: cleanup comptime
|
||||
const Type = @field(
|
||||
@field(all_components, @tagName(namespace_name)),
|
||||
@tagName(component_name),
|
||||
);
|
||||
).type;
|
||||
if (namespace_name == .entity and component_name == .id) {
|
||||
const name_id = slicer.archetype.component_names.index("id").?;
|
||||
return slicer.archetype.getColumnValues(name_id, Type).?[0..slicer.archetype.len];
|
||||
|
|
|
|||
|
|
@ -281,12 +281,13 @@ pub fn Entities(comptime all_components: anytype) type {
|
|||
pub fn setComponent(
|
||||
entities: *Self,
|
||||
entity: EntityID,
|
||||
// TODO: cleanup comptime
|
||||
comptime namespace_name: std.meta.FieldEnum(@TypeOf(all_components)),
|
||||
comptime component_name: std.meta.DeclEnum(@field(all_components, @tagName(namespace_name))),
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(@field(all_components, @tagName(namespace_name)))),
|
||||
component: @field(
|
||||
@field(all_components, @tagName(namespace_name)),
|
||||
@tagName(component_name),
|
||||
),
|
||||
).type,
|
||||
) !void {
|
||||
const name_str = @tagName(namespace_name) ++ "." ++ @tagName(component_name);
|
||||
const name_id = try entities.component_names.indexOrPut(entities.allocator, name_str);
|
||||
|
|
@ -483,16 +484,19 @@ pub fn Entities(comptime all_components: anytype) type {
|
|||
pub fn getComponent(
|
||||
entities: *Self,
|
||||
entity: EntityID,
|
||||
// TODO: cleanup comptime
|
||||
comptime namespace_name: std.meta.FieldEnum(@TypeOf(all_components)),
|
||||
comptime component_name: std.meta.DeclEnum(@field(all_components, @tagName(namespace_name))),
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(@field(all_components, @tagName(namespace_name)))),
|
||||
) ?@field(
|
||||
@field(all_components, @tagName(namespace_name)),
|
||||
@tagName(component_name),
|
||||
) {
|
||||
).type {
|
||||
// TODO: cleanup comptime
|
||||
const Component = comptime @field(
|
||||
@field(all_components, @tagName(namespace_name)),
|
||||
@tagName(component_name),
|
||||
);
|
||||
).type;
|
||||
|
||||
const name_str = @tagName(namespace_name) ++ "." ++ @tagName(component_name);
|
||||
const name_id = entities.component_names.index(name_str) orelse return null;
|
||||
|
||||
|
|
@ -523,8 +527,9 @@ pub fn Entities(comptime all_components: anytype) type {
|
|||
pub fn removeComponent(
|
||||
entities: *Self,
|
||||
entity: EntityID,
|
||||
// TODO: cleanup comptime
|
||||
comptime namespace_name: std.meta.FieldEnum(@TypeOf(all_components)),
|
||||
comptime component_name: std.meta.DeclEnum(@field(all_components, @tagName(namespace_name))),
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(@field(all_components, @tagName(namespace_name)))),
|
||||
) !void {
|
||||
const name_str = @tagName(namespace_name) ++ "." ++ @tagName(component_name);
|
||||
const name_id = try entities.component_names.indexOrPut(entities.allocator, name_str);
|
||||
|
|
|
|||
|
|
@ -47,8 +47,8 @@ test "example" {
|
|||
pointer: u8,
|
||||
|
||||
pub const name = .physics;
|
||||
pub const components = struct {
|
||||
pub const id = u32;
|
||||
pub const components = .{
|
||||
.{ .name = .id, .type = u32 },
|
||||
};
|
||||
pub const events = .{
|
||||
.{ .global = .tick, .handler = tick },
|
||||
|
|
@ -61,8 +61,8 @@ test "example" {
|
|||
|
||||
const Renderer = struct {
|
||||
pub const name = .renderer;
|
||||
pub const components = struct {
|
||||
pub const id = u16;
|
||||
pub const components = .{
|
||||
.{ .name = .ud, .type = u16 },
|
||||
};
|
||||
pub const events = .{
|
||||
.{ .global = .tick, .handler = tick },
|
||||
|
|
|
|||
|
|
@ -9,23 +9,27 @@ pub const QueryTag = enum {
|
|||
/// A complex query for entities matching a given criteria
|
||||
pub fn Query(comptime all_components: anytype) type {
|
||||
return union(QueryTag) {
|
||||
// TODO: cleanup comptime
|
||||
/// Enum matching a namespace. e.g. `.game` or `.physics2d`
|
||||
pub const Namespace = std.meta.FieldEnum(@TypeOf(all_components));
|
||||
|
||||
// TODO: cleanup comptime
|
||||
/// Enum matching a component within a namespace
|
||||
/// e.g. `var a: Component(.physics2d) = .location`
|
||||
pub fn Component(comptime namespace: Namespace) type {
|
||||
const components = @field(all_components, @tagName(namespace));
|
||||
if (@typeInfo(components).Struct.decls.len == 0) return enum {};
|
||||
return std.meta.DeclEnum(components);
|
||||
if (@typeInfo(@TypeOf(components)).Struct.fields.len == 0) return enum {};
|
||||
return std.meta.FieldEnum(@TypeOf(components));
|
||||
}
|
||||
|
||||
// TODO: cleanup comptime
|
||||
/// Slice of enums matching a component within a namespace
|
||||
/// e.g. `&.{.location, .rotation}`
|
||||
pub fn ComponentList(comptime namespace: Namespace) type {
|
||||
return []const Component(namespace);
|
||||
}
|
||||
|
||||
// TODO: cleanup comptime
|
||||
/// Tagged union of namespaces matching lists of components
|
||||
/// e.g. `.physics2d = &.{ .location, .rotation }`
|
||||
pub const NamespaceComponent = T: {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ const Entities = @import("entities.zig").Entities;
|
|||
const EntityID = @import("entities.zig").EntityID;
|
||||
const comp = @import("comptime.zig");
|
||||
const Module = @import("../module.zig").Module;
|
||||
const NamespacedComponents = @import("../module.zig").NamespacedComponents;
|
||||
|
||||
pub fn World(comptime mods: anytype) type {
|
||||
const StateT = NamespacedState(mods);
|
||||
|
|
@ -37,8 +38,9 @@ pub fn World(comptime mods: anytype) type {
|
|||
pub inline fn set(
|
||||
m: *@This(),
|
||||
entity: EntityID,
|
||||
comptime component_name: std.meta.DeclEnum(components),
|
||||
component: @field(components, @tagName(component_name)),
|
||||
// TODO: cleanup comptime
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(components)),
|
||||
component: @field(components, @tagName(component_name)).type,
|
||||
) !void {
|
||||
const mod_ptr: *Mods = @alignCast(@fieldParentPtr(Mods, @tagName(module_tag), m));
|
||||
const world = @fieldParentPtr(WorldT, "mod", mod_ptr);
|
||||
|
|
@ -50,8 +52,9 @@ pub fn World(comptime mods: anytype) type {
|
|||
pub inline fn get(
|
||||
m: *@This(),
|
||||
entity: EntityID,
|
||||
comptime component_name: std.meta.DeclEnum(components),
|
||||
) ?@field(components, @tagName(component_name)) {
|
||||
// TODO: cleanup comptime
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(components)),
|
||||
) ?@field(components, @tagName(component_name)).type {
|
||||
const mod_ptr: *Mods = @alignCast(@fieldParentPtr(Mods, @tagName(module_tag), m));
|
||||
const world = @fieldParentPtr(WorldT, "mod", mod_ptr);
|
||||
return world.entities.getComponent(entity, module_tag, component_name);
|
||||
|
|
@ -61,7 +64,8 @@ pub fn World(comptime mods: anytype) type {
|
|||
pub inline fn remove(
|
||||
m: *@This(),
|
||||
entity: EntityID,
|
||||
comptime component_name: std.meta.DeclEnum(components),
|
||||
// TODO: cleanup comptime
|
||||
comptime component_name: std.meta.FieldEnum(@TypeOf(components)),
|
||||
) !void {
|
||||
const mod_ptr: *Mods = @alignCast(@fieldParentPtr(Mods, @tagName(module_tag), m));
|
||||
const world = @fieldParentPtr(WorldT, "mod", mod_ptr);
|
||||
|
|
@ -80,6 +84,7 @@ pub fn World(comptime mods: anytype) type {
|
|||
world.modules.sendGlobal(module_tag, event_name, args);
|
||||
}
|
||||
|
||||
// TODO: eliminate this
|
||||
pub fn dispatchNoError(m: *@This()) void {
|
||||
const mod_ptr: *Mods = @alignCast(@fieldParentPtr(Mods, @tagName(module_tag), m));
|
||||
const world = @fieldParentPtr(WorldT, "mod", mod_ptr);
|
||||
|
|
@ -173,42 +178,6 @@ 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{};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue