obj: Refine comments, make updated set bits back to false, swap Objects parameters
This commit is contained in:
parent
f58cb270b1
commit
0546c3d5ca
3 changed files with 38 additions and 67 deletions
|
|
@ -32,7 +32,10 @@ pub const mach_module = .mach_core;
|
||||||
|
|
||||||
pub const mach_systems = .{ .main, .init, .tick, .presentFrame, .deinit };
|
pub const mach_systems = .{ .main, .init, .tick, .presentFrame, .deinit };
|
||||||
|
|
||||||
|
// Set track_fields to true so that when these field values change, we know about it
|
||||||
|
// and can update the platform windows.
|
||||||
windows: mach.Objects(
|
windows: mach.Objects(
|
||||||
|
.{ .track_fields = true },
|
||||||
struct {
|
struct {
|
||||||
/// Window title string
|
/// Window title string
|
||||||
// TODO: document how to set this using a format string
|
// TODO: document how to set this using a format string
|
||||||
|
|
@ -57,9 +60,6 @@ windows: mach.Objects(
|
||||||
/// Whether the window is fullscreen (read-only)
|
/// Whether the window is fullscreen (read-only)
|
||||||
fullscreen: bool,
|
fullscreen: bool,
|
||||||
},
|
},
|
||||||
.{
|
|
||||||
.track_fields = true,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
|
||||||
/// Callback system invoked per tick (e.g. per-frame)
|
/// Callback system invoked per tick (e.g. per-frame)
|
||||||
|
|
@ -298,9 +298,6 @@ fn platform_update_callback(core: *Core, core_mod: mach.Mod(Core)) !bool {
|
||||||
.height = main_window.height,
|
.height = main_window.height,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
core.windows.setUpdated(core.main_window, .width, false);
|
|
||||||
core.windows.setUpdated(core.main_window, .height, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return core.state != .exited;
|
return core.state != .exited;
|
||||||
|
|
|
||||||
|
|
@ -206,8 +206,6 @@ pub fn setSize(darwin: *Darwin, size: Size) void {
|
||||||
frame.size.height = @floatFromInt(size.height);
|
frame.size.height = @floatFromInt(size.height);
|
||||||
frame.size.width = @floatFromInt(size.width);
|
frame.size.width = @floatFromInt(size.width);
|
||||||
window.setFrame_display_animate(frame, true, true);
|
window.setFrame_display_animate(frame, true, true);
|
||||||
|
|
||||||
std.log.debug("setSize successfully called", .{});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,14 @@ const PackedObjectTypeID = packed struct(u16) {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ObjectsOptions = struct {
|
pub const ObjectsOptions = struct {
|
||||||
/// If this option is true, the internal field `update` will
|
/// If set to true, Mach will track when fields are set using the setField/setAll
|
||||||
/// contain a list of bitsets representing each object field
|
/// methods using a bitset with one bit per field to indicate 'the field was set'.
|
||||||
|
/// You can get this information by calling `.updated(.field_name)`
|
||||||
|
/// Note that calling `.updated(.field_name) will also set the flag back to false.
|
||||||
track_fields: bool = false,
|
track_fields: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
pub fn Objects(options: ObjectsOptions, comptime T: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
internal: struct {
|
internal: struct {
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
@ -68,7 +70,7 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
|
|
||||||
/// This is mach's way of determining which fields are updated and
|
/// This is mach's way of determining which fields are updated and
|
||||||
/// need to trigger some other logic
|
/// need to trigger some other logic
|
||||||
updated: std.ArrayListUnmanaged(std.bit_set.DynamicBitSetUnmanaged) = .{},
|
updated: ?std.ArrayListUnmanaged(std.bit_set.DynamicBitSetUnmanaged) = if (options.track_fields) .{} else null,
|
||||||
},
|
},
|
||||||
|
|
||||||
pub const IsMachObjects = void;
|
pub const IsMachObjects = void;
|
||||||
|
|
@ -159,7 +161,6 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
const dead = &objs.internal.dead;
|
const dead = &objs.internal.dead;
|
||||||
const generation = &objs.internal.generation;
|
const generation = &objs.internal.generation;
|
||||||
const recycling_bin = &objs.internal.recycling_bin;
|
const recycling_bin = &objs.internal.recycling_bin;
|
||||||
const _updated = &objs.internal.updated;
|
|
||||||
|
|
||||||
// The recycling bin should always be big enough, but we check at this point if 10% of
|
// The recycling bin should always be big enough, but we check at this point if 10% of
|
||||||
// all objects have been thrown on the floor. If they have, we find them and grow the
|
// all objects have been thrown on the floor. If they have, we find them and grow the
|
||||||
|
|
@ -187,9 +188,9 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
try dead.resize(allocator, data.capacity, true);
|
try dead.resize(allocator, data.capacity, true);
|
||||||
try generation.ensureUnusedCapacity(allocator, 1);
|
try generation.ensureUnusedCapacity(allocator, 1);
|
||||||
|
|
||||||
if (options.track_fields) {
|
if (objs.internal.updated) |*updated_fields| {
|
||||||
try _updated.ensureUnusedCapacity(allocator, 1);
|
try updated_fields.ensureUnusedCapacity(allocator, 1);
|
||||||
_updated.appendAssumeCapacity(try std.bit_set.DynamicBitSetUnmanaged.initEmpty(allocator, @typeInfo(T).@"struct".fields.len));
|
updated_fields.appendAssumeCapacity(try std.bit_set.DynamicBitSetUnmanaged.initEmpty(allocator, @typeInfo(T).@"struct".fields.len));
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = data.len;
|
const index = data.len;
|
||||||
|
|
@ -204,13 +205,10 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function will set all fields of an object.
|
/// Sets all fields of the given object to the given value.
|
||||||
///
|
///
|
||||||
/// Note that this function has no tracking, and will not trigger
|
/// Unlike setAll(), this method does not respect any mach.Objects tracking
|
||||||
/// any internal mach functions.
|
/// options, so changes made to an object through this method will not be tracked.
|
||||||
///
|
|
||||||
/// Example: core.windows.setAllRaw(id, value) will NOT trigger the Platform
|
|
||||||
/// to update the window's size, etc.
|
|
||||||
pub fn setAllRaw(objs: *@This(), id: ObjectID, value: T) void {
|
pub fn setAllRaw(objs: *@This(), id: ObjectID, value: T) void {
|
||||||
const data = &objs.internal.data;
|
const data = &objs.internal.data;
|
||||||
|
|
||||||
|
|
@ -218,34 +216,24 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
data.set(unpacked.index, value);
|
data.set(unpacked.index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function will set all fields of an object.
|
/// Sets all fields of the given object to the given value.
|
||||||
///
|
///
|
||||||
/// Note that this function also sets a bit set value
|
/// Unlike setAllRaw, this method respects mach.Objects tracking
|
||||||
/// for each field, informing mach that the field has
|
/// and changes made to an object through this method will be tracked.
|
||||||
/// been updated and can be passed to internals that need it.
|
|
||||||
///
|
|
||||||
/// Example: core.windows.setAll(id, value) can trigger the Platform
|
|
||||||
/// to update the window's size, etc.
|
|
||||||
pub fn setAll(objs: *@This(), id: ObjectID, value: T) void {
|
pub fn setAll(objs: *@This(), id: ObjectID, value: T) void {
|
||||||
const data = &objs.internal.data;
|
const data = &objs.internal.data;
|
||||||
|
|
||||||
const unpacked = objs.validateAndUnpack(id, "setAll");
|
const unpacked = objs.validateAndUnpack(id, "setAll");
|
||||||
data.set(unpacked.index, value);
|
data.set(unpacked.index, value);
|
||||||
|
|
||||||
if (options.track_fields)
|
if (options.track_fields) objs.internal.updated.items[unpacked.index].setAll();
|
||||||
objs.internal.updated.items[unpacked.index].setAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function will set a single field of an object.
|
/// Sets a single field of the given object to the given value.
|
||||||
///
|
///
|
||||||
/// Note that this function has no tracking, and will not trigger
|
/// Unlike set(), this method does not respect any mach.Objects tracking
|
||||||
/// any internal mach functions.
|
/// options, so changes made to an object through this method will not be tracked.
|
||||||
///
|
pub fn setRaw(objs: *@This(), id: ObjectID, comptime field_name: std.meta.FieldEnum(T), value: anytype) void {
|
||||||
/// Example: core.windows.setRaw(id, .width, value) will NOT trigger the Platform
|
|
||||||
/// to update the window's size.
|
|
||||||
pub fn setRaw(objs: *@This(), id: ObjectID, comptime field_name: anytype, value: anytype) void {
|
|
||||||
if (@typeInfo(@TypeOf(field_name)) != .enum_literal) @compileError("mach: invalid field name, expected `.field` enum literal, found: " ++ @typeName(@TypeOf(field_name)));
|
|
||||||
|
|
||||||
const data = &objs.internal.data;
|
const data = &objs.internal.data;
|
||||||
const unpacked = objs.validateAndUnpack(id, "setRaw");
|
const unpacked = objs.validateAndUnpack(id, "setRaw");
|
||||||
|
|
||||||
|
|
@ -255,17 +243,11 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
data.set(unpacked.index, current);
|
data.set(unpacked.index, current);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function will set a single field of an object.
|
/// Sets a single field of the given object to the given value.
|
||||||
///
|
///
|
||||||
/// Note that this function also sets a bit set value
|
/// Unlike setAllRaw, this method respects mach.Objects tracking
|
||||||
/// for each object field, informing mach that the field has
|
/// and changes made to an object through this method will be tracked.
|
||||||
/// been updated and can be passed to internals that need it.
|
pub fn set(objs: *@This(), id: ObjectID, comptime field_name: std.meta.FieldEnum(T), value: anytype) void {
|
||||||
///
|
|
||||||
/// Example: core.windows.set(id, .width, value) will trigger the Platform
|
|
||||||
/// to update the window's size.
|
|
||||||
pub fn set(objs: *@This(), id: ObjectID, comptime field_name: anytype, value: anytype) void {
|
|
||||||
if (@typeInfo(@TypeOf(field_name)) != .enum_literal) @compileError("mach: invalid field name, expected `.field` enum literal, found: " ++ @typeName(@TypeOf(field_name)));
|
|
||||||
|
|
||||||
const data = &objs.internal.data;
|
const data = &objs.internal.data;
|
||||||
const unpacked = objs.validateAndUnpack(id, "set");
|
const unpacked = objs.validateAndUnpack(id, "set");
|
||||||
|
|
||||||
|
|
@ -276,7 +258,8 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
|
|
||||||
if (options.track_fields)
|
if (options.track_fields)
|
||||||
if (std.meta.fieldIndex(T, @tagName(field_name))) |field_index|
|
if (std.meta.fieldIndex(T, @tagName(field_name))) |field_index|
|
||||||
objs.internal.updated.items[unpacked.index].set(field_index);
|
if (objs.internal.updated) |updated_fields|
|
||||||
|
updated_fields.items[unpacked.index].set(field_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a single field.
|
/// Get a single field.
|
||||||
|
|
@ -334,29 +317,22 @@ pub fn Objects(comptime T: type, options: ObjectsOptions) type {
|
||||||
return unpacked;
|
return unpacked;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the field has an `updated` bit set in internal.
|
/// Returns true if the field has an `updated` bit set in internal, then sets the bit
|
||||||
///
|
/// back to false.
|
||||||
/// Internal functions may set this bit back to false.
|
|
||||||
pub fn updated(objs: *@This(), id: ObjectID, field_name: anytype) bool {
|
pub fn updated(objs: *@This(), id: ObjectID, field_name: anytype) bool {
|
||||||
if (options.track_fields) {
|
if (options.track_fields) {
|
||||||
const unpacked = objs.validateAndUnpack(id, "updated");
|
const unpacked = objs.validateAndUnpack(id, "updated");
|
||||||
if (std.meta.fieldIndex(T, @tagName(field_name))) |field_index|
|
if (std.meta.fieldIndex(T, @tagName(field_name))) |field_index| {
|
||||||
return objs.internal.updated.items[unpacked.index].isSet(field_index);
|
if (objs.internal.updated) |*updated_fields| {
|
||||||
|
const value = updated_fields.items[unpacked.index].isSet(field_index);
|
||||||
|
updated_fields.items[unpacked.index].unset(field_index);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets an internal bit for the field indicating it has been updated.
|
|
||||||
///
|
|
||||||
/// Internal functions may use this as a signal.
|
|
||||||
pub fn setUpdated(objs: *@This(), id: ObjectID, field_name: anytype, value: bool) void {
|
|
||||||
if (options.track_fields) {
|
|
||||||
const unpacked = objs.validateAndUnpack(id, "setUpdated");
|
|
||||||
if (std.meta.fieldIndex(T, @tagName(field_name))) |field_index|
|
|
||||||
return objs.internal.updated.items[unpacked.index].setValue(field_index, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tells if the given object (which must be alive and valid) is from this pool of objects.
|
/// Tells if the given object (which must be alive and valid) is from this pool of objects.
|
||||||
pub fn is(objs: *const @This(), id: ObjectID) bool {
|
pub fn is(objs: *const @This(), id: ObjectID) bool {
|
||||||
const unpacked = objs.validateAndUnpack(id, "is");
|
const unpacked = objs.validateAndUnpack(id, "is");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue