ecs: initial systems & message sending functionality
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
98ec7f5190
commit
6f7f17c5e8
2 changed files with 107 additions and 0 deletions
|
|
@ -32,6 +32,8 @@ pub const Adapter = @import("systems.zig").Adapter;
|
||||||
pub const System = @import("systems.zig").System;
|
pub const System = @import("systems.zig").System;
|
||||||
pub const Module = @import("systems.zig").Module;
|
pub const Module = @import("systems.zig").Module;
|
||||||
pub const Modules = @import("systems.zig").Modules;
|
pub const Modules = @import("systems.zig").Modules;
|
||||||
|
pub const Messages = @import("systems.zig").Messages;
|
||||||
|
pub const MessagesTag = @import("systems.zig").MessagesTag;
|
||||||
pub const World = @import("systems.zig").World;
|
pub const World = @import("systems.zig").World;
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
|
|
@ -48,6 +50,17 @@ test "inclusion" {
|
||||||
test "example" {
|
test "example" {
|
||||||
const allocator = testing.allocator;
|
const allocator = testing.allocator;
|
||||||
|
|
||||||
|
const PhysicsMsg = Messages(.{
|
||||||
|
.tick = void,
|
||||||
|
});
|
||||||
|
const physicsUpdate = (struct {
|
||||||
|
pub fn physicsUpdate(msg: PhysicsMsg) void {
|
||||||
|
switch (msg) {
|
||||||
|
.tick => std.debug.print("\nphysics tick!\n", .{}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).physicsUpdate;
|
||||||
|
|
||||||
const modules = Modules(.{
|
const modules = Modules(.{
|
||||||
.physics = Module(.{
|
.physics = Module(.{
|
||||||
.components = .{
|
.components = .{
|
||||||
|
|
@ -56,6 +69,8 @@ test "example" {
|
||||||
.globals = struct {
|
.globals = struct {
|
||||||
pointer: u8,
|
pointer: u8,
|
||||||
},
|
},
|
||||||
|
.messages = PhysicsMsg,
|
||||||
|
.update = physicsUpdate,
|
||||||
}),
|
}),
|
||||||
.renderer = Module(.{
|
.renderer = Module(.{
|
||||||
.components = .{
|
.components = .{
|
||||||
|
|
@ -81,4 +96,6 @@ test "example" {
|
||||||
|
|
||||||
try world.entities.setComponent(player2, .physics, .id, 1234);
|
try world.entities.setComponent(player2, .physics, .id, 1234);
|
||||||
try world.entities.setComponent(player3, .physics, .id, 1234);
|
try world.entities.setComponent(player3, .physics, .id, 1234);
|
||||||
|
|
||||||
|
world.tick();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,10 @@ const std = @import("std");
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
const math = std.math;
|
||||||
const StructField = std.builtin.Type.StructField;
|
const StructField = std.builtin.Type.StructField;
|
||||||
|
const EnumField = std.builtin.Type.EnumField;
|
||||||
|
const UnionField = std.builtin.Type.UnionField;
|
||||||
|
|
||||||
const Entities = @import("entities.zig").Entities;
|
const Entities = @import("entities.zig").Entities;
|
||||||
|
|
||||||
|
|
@ -18,6 +21,82 @@ pub fn Modules(modules: anytype) @TypeOf(modules) {
|
||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a tagged union representing the messages, turning this:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// .{ .tick = void, .foo = i32 }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Into `T`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// const T = union(MessagesTag(messages)) {
|
||||||
|
/// .tick = void,
|
||||||
|
/// .foo = i32,
|
||||||
|
/// };
|
||||||
|
/// ```
|
||||||
|
pub fn Messages(messages: anytype) type {
|
||||||
|
var fields: []const UnionField = &[0]UnionField{};
|
||||||
|
const message_fields = std.meta.fields(@TypeOf(messages));
|
||||||
|
inline for (message_fields) |message_field| {
|
||||||
|
const message_type = @field(messages, message_field.name);
|
||||||
|
fields = fields ++ [_]std.builtin.Type.UnionField{.{
|
||||||
|
.name = message_field.name,
|
||||||
|
.field_type = message_type,
|
||||||
|
.alignment = if (message_type == void) 0 else @alignOf(message_type),
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hack to workaround stage1 compiler bug. https://github.com/ziglang/zig/issues/8114
|
||||||
|
//
|
||||||
|
// return @Type(.{
|
||||||
|
// .Union = .{
|
||||||
|
// .layout = .Auto,
|
||||||
|
// .tag_type = MessagesTag(messages),
|
||||||
|
// .fields = fields,
|
||||||
|
// .decls = &[_]std.builtin.Type.Declaration{},
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
const Ref = union(enum) { temp };
|
||||||
|
var info = @typeInfo(Ref);
|
||||||
|
info.Union.tag_type = MessagesTag(messages);
|
||||||
|
info.Union.fields = fields;
|
||||||
|
return @Type(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the tag enum for a tagged union representing the messages, turning this:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// .{ .tick = void, .foo = i32 }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Into this:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// enum { .tick, .foo };
|
||||||
|
/// ```
|
||||||
|
pub fn MessagesTag(messages: anytype) type {
|
||||||
|
var fields: []const EnumField = &[0]EnumField{};
|
||||||
|
const message_fields = std.meta.fields(@TypeOf(messages));
|
||||||
|
inline for (message_fields) |message_field, index| {
|
||||||
|
fields = fields ++ [_]std.builtin.Type.EnumField{.{
|
||||||
|
.name = message_field.name,
|
||||||
|
.value = index,
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
return @Type(.{
|
||||||
|
.Enum = .{
|
||||||
|
.layout = .Auto,
|
||||||
|
.tag_type = std.meta.Int(.unsigned, @floatToInt(u16, math.ceil(math.log2(@intToFloat(f64, message_fields.len))))),
|
||||||
|
.fields = fields,
|
||||||
|
.decls = &[_]std.builtin.Type.Declaration{},
|
||||||
|
.is_exhaustive = true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the namespaced components struct **type**.
|
/// Returns the namespaced components struct **type**.
|
||||||
//
|
//
|
||||||
/// Consult `namespacedComponents` for how a value of this type looks.
|
/// Consult `namespacedComponents` for how a value of this type looks.
|
||||||
|
|
@ -197,5 +276,16 @@ pub fn World(comptime modules: anytype) type {
|
||||||
@tagName(global_tag),
|
@tagName(global_tag),
|
||||||
) = value;
|
) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tick sends the global 'tick' message to all modules that are subscribed to it.
|
||||||
|
pub fn tick(world: *Self) void {
|
||||||
|
_ = world;
|
||||||
|
inline for (std.meta.fields(@TypeOf(modules))) |module_field| {
|
||||||
|
const module = @field(modules, module_field.name);
|
||||||
|
if (@hasField(@TypeOf(module), "messages")) {
|
||||||
|
if (@hasField(module.messages, "tick")) module.update(.tick);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue