module: remove deprecated query API

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-05-07 17:59:46 -07:00 committed by Stephen Gutekanst
parent b5b094642a
commit 57767c2f9f
4 changed files with 0 additions and 270 deletions

View file

@ -269,34 +269,3 @@ pub inline fn debugAssertRowType(storage: *Archetype, row: anytype) void {
}
}
}
// TODO: comptime refactor
pub fn Slicer(comptime modules: anytype) type {
const component_types_by_name = ComponentTypesByName(modules){};
return struct {
archetype: *Archetype,
pub fn slice(
slicer: @This(),
// TODO: cleanup comptime
comptime namespace_name: std.meta.FieldEnum(@TypeOf(component_types_by_name)),
comptime component_name: std.meta.FieldEnum(@TypeOf(@field(component_types_by_name, @tagName(namespace_name)))),
) []@field(
@field(component_types_by_name, @tagName(namespace_name)),
@tagName(component_name),
).type {
// TODO: cleanup comptime
const Type = @field(
@field(component_types_by_name, @tagName(namespace_name)),
@tagName(component_name),
).type;
if (namespace_name == .entities and component_name == .id) {
const name_id = slicer.archetype.component_names.index("entities.id").?;
return slicer.archetype.getColumnValues(name_id, Type).?[0..slicer.archetype.len];
}
const name = @tagName(namespace_name) ++ "." ++ @tagName(component_name);
const name_id = slicer.archetype.component_names.index(name).?;
return slicer.archetype.getColumnValues(name_id, Type).?[0..slicer.archetype.len];
}
};
}

View file

@ -3,7 +3,6 @@ const Allocator = std.mem.Allocator;
const testing = std.testing;
const builtin = @import("builtin");
const assert = std.debug.assert;
const query_mod = @import("query.zig");
const Archetype = @import("Archetype.zig");
const StringTable = @import("StringTable.zig");
const ComponentTypesByName = @import("module.zig").ComponentTypesByName;
@ -112,10 +111,6 @@ pub fn Database(comptime modules: anytype) type {
row_index: u32,
};
/// A complex query for entities matching a given criteria
pub const QueryDeprecated = query_mod.QueryDeprecated(modules);
pub const QueryTag = query_mod.QueryTag;
pub fn init(allocator: Allocator) !Self {
const component_names = try allocator.create(StringTable);
errdefer allocator.destroy(component_names);
@ -626,14 +621,6 @@ pub fn Database(comptime modules: anytype) type {
});
}
// Queries for archetypes matching the given query.
pub fn queryDeprecated(
entities: *Self,
q: QueryDeprecated,
) ArchetypeIterator(modules) {
return ArchetypeIterator(modules).init(entities, q);
}
/// Represents a dynamic (runtime-generated, non type safe) query.
pub const QueryDynamic = union(enum) {
/// Logical AND operator for query expressions
@ -869,68 +856,6 @@ pub fn Database(comptime modules: anytype) type {
};
}
// TODO: move this type somewhere else
pub fn ArchetypeIterator(comptime modules: anytype) type {
const DatabaseT = Database(modules);
return struct {
entities: *DatabaseT,
query: DatabaseT.QueryDeprecated,
index: usize,
const Self = @This();
pub fn init(entities: *DatabaseT, query: DatabaseT.QueryDeprecated) Self {
return Self{
.entities = entities,
.query = query,
.index = 0,
};
}
// TODO: component_types_by_name is a superset of queried items, not type-safe.
pub fn next(iter: *Self) ?Archetype.Slicer(modules) {
while (iter.index < iter.entities.archetypes.items.len) {
const archetype = &iter.entities.archetypes.items[iter.index];
iter.index += 1;
if (iter.match(archetype)) return Archetype.Slicer(modules){ .archetype = archetype };
}
return null;
}
pub fn match(iter: *Self, consideration: *Archetype) bool {
if (consideration.len == 0) return false;
var buf: [2048]u8 = undefined;
switch (iter.query) {
.all => {
for (iter.query.all) |namespace| {
switch (namespace) {
inline else => |components| {
for (components) |component| {
if (@typeInfo(@TypeOf(component)).Enum.fields.len == 0) continue;
const name = switch (component) {
inline else => |c| std.fmt.bufPrint(&buf, "{s}.{s}", .{ @tagName(namespace), @tagName(c) }) catch break,
};
const name_id = iter.entities.componentNameString(name);
var has_column = false;
for (consideration.columns) |column| {
if (column.name == name_id) {
has_column = true;
break;
}
}
if (!has_column) return false;
}
},
}
}
return true;
},
.any => @panic("TODO"),
}
}
};
}
test {
const modules = merge(.{
builtin_modules,

View file

@ -30,7 +30,6 @@ test {
// std.testing.refAllDeclsRecursive(@This());
std.testing.refAllDeclsRecursive(@import("Archetype.zig"));
std.testing.refAllDeclsRecursive(@import("entities.zig"));
std.testing.refAllDeclsRecursive(@import("query.zig"));
std.testing.refAllDeclsRecursive(@import("StringTable.zig"));
}
@ -97,27 +96,6 @@ test "entities DB" {
try physics.set(player2, .id, 1002);
try physics.set(player3, .id, 1003);
//-------------------------------------------------------------------------
// Querying
var iter = world.entities.queryDeprecated(.{ .all = &.{
.{ .physics = &.{.id} },
} });
var archetype = iter.next().?;
var ids = archetype.slice(.physics, .id);
try testing.expectEqual(@as(usize, 2), ids.len);
try testing.expectEqual(@as(usize, 1002), ids[0]);
try testing.expectEqual(@as(usize, 1003), ids[1]);
archetype = iter.next().?;
ids = archetype.slice(.physics, .id);
try testing.expectEqual(@as(usize, 1), ids.len);
try testing.expectEqual(@as(usize, 1001), ids[0]);
// TODO: can't write @as type here easily due to generic parameter, should be exposed
// ?Archetype.Slicer(modules)
try testing.expectEqual(iter.next(), null);
//-------------------------------------------------------------------------
// Send events to modules
world.mod.renderer.sendGlobal(.tick, .{});

View file

@ -1,142 +0,0 @@
const std = @import("std");
const testing = std.testing;
const ComponentTypesByName = @import("module.zig").ComponentTypesByName;
const merge = @import("main.zig").merge;
const builtin_modules = @import("main.zig").builtin_modules;
pub const QueryTag = enum {
any,
all,
};
/// A complex query for entities matching a given criteria
pub fn QueryDeprecated(comptime modules: anytype) type {
const component_types_by_name = ComponentTypesByName(modules){};
return union(QueryTag) {
// TODO: cleanup comptime
/// Enum matching a namespace. e.g. `.game` or `.physics2d`
pub const Namespace = std.meta.FieldEnum(@TypeOf(component_types_by_name));
// 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(component_types_by_name, @tagName(namespace));
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: {
const namespaces = std.meta.fields(Namespace);
var fields: [namespaces.len]std.builtin.Type.UnionField = undefined;
for (namespaces, 0..) |namespace, i| {
const ns = stringToEnum(Namespace, namespace.name).?;
fields[i] = .{
.name = namespace.name,
.type = ComponentList(ns),
.alignment = @alignOf(ComponentList(ns)),
};
}
break :T @Type(.{ .Union = .{
.layout = .Auto,
.tag_type = Namespace,
.fields = &fields,
.decls = &.{},
} });
};
/// Matches any of these components
any: []const NamespaceComponent,
/// Matches all of these components
all: []const NamespaceComponent,
};
}
// TODO: cannot use std.meta.stringToEnum for some reason; an issue with its internal comptime map and u0 values
pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
inline for (@typeInfo(T).Enum.fields) |enumField| {
if (std.mem.eql(u8, str, enumField.name)) {
return @field(T, enumField.name);
}
}
}
test "query" {
const Location = struct {
x: f32 = 0,
y: f32 = 0,
z: f32 = 0,
};
const Rotation = struct { degrees: f32 };
const modules = merge(.{
builtin_modules,
struct {
pub const name = .game;
pub const components = .{
.name = .{ .type = []const u8 },
};
},
struct {
pub const name = .physics;
pub const components = .{
.location = .{ .type = Location },
.rotation = .{ .type = Rotation },
};
},
struct {
pub const name = .renderer;
},
});
const Q = QueryDeprecated(modules);
// Namespace type lets us select a single namespace.
try testing.expectEqual(@as(Q.Namespace, .game), .game);
try testing.expectEqual(@as(Q.Namespace, .physics), .physics);
// Component type lets us select a single component within a namespace.
try testing.expectEqual(@as(Q.Component(.physics), .location), .location);
try testing.expectEqual(@as(Q.Component(.game), .name), .name);
// ComponentList type lets us select multiple components within a namespace.
const x: Q.ComponentList(.physics) = &.{
.location,
.rotation,
};
_ = x;
// NamespaceComponent lets us select multiple components within multiple namespaces.
const y: []const Q.NamespaceComponent = &.{
.{ .physics = &.{ .location, .rotation } },
.{ .game = &.{.name} },
};
_ = y;
// Query matching entities with *any* of these components
const z: Q = .{ .any = &.{
.{ .physics = &.{ .location, .rotation } },
.{ .game = &.{.name} },
} };
_ = z;
// Query matching entities with *all* of these components.
const w: Q = .{ .all = &.{
.{ .physics = &.{ .location, .rotation } },
.{ .game = &.{.name} },
} };
_ = w;
}