summaryrefslogtreecommitdiff
path: root/src/draw.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/draw.zig')
-rw-r--r--src/draw.zig38
1 files changed, 35 insertions, 3 deletions
diff --git a/src/draw.zig b/src/draw.zig
index 0998db24..70b629a5 100644
--- a/src/draw.zig
+++ b/src/draw.zig
@@ -127,11 +127,12 @@ pub fn place(p: *Pardes, s: *Surface) void {
serial.* = pane.serial;
spring.* = .{};
}
- spring.retarget(if (p.settings.lift and id == p.active) 1 else 0, p.stepped_ns);
- _ = spring.step(p.stepped_ns);
+ // At this frame's own time, not the stepped animations' 16 ms grid.
+ spring.retarget(if (p.settings.lift and id == p.active) 1 else 0, p.now_ns);
+ _ = spring.step(p.now_ns);
}
for (s.regions[0..s.nregions]) |*region| switch (region.kind) {
- .grip, .tag, .body, .rail => region.lift = p.lifts[region.owner].value(p.stepped_ns),
+ .grip, .tag, .body, .rail => region.lift = p.lifts[region.owner].value(p.now_ns),
.notice => region.lift = if (p.settings.lift) 1 else 0,
else => {},
};
@@ -1122,6 +1123,37 @@ test "a notice wider than its band, as a shader's compile error is, draws its en
}
}
+test "a lift is sampled at each frame's own time, and asks for frames only while it moves" {
+ const p = try Pardes.init(std.testing.allocator, .{ .cols = 80, .rows = 24 });
+ defer p.deinit();
+ _ = try p.setTestFile("text\n");
+ var arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
+ defer arena.deinit();
+ const ms = std.time.ns_per_ms;
+ p.advance(1000 * ms);
+ _ = try p.render(arena.allocator());
+ try std.testing.expect(!p.continuous());
+ p.settings.lift = true;
+ var lifts: [3]f32 = undefined;
+ // 144 Hz: 6.9 ms apart, none of them on a 16 ms step of its own.
+ for (&lifts, 0..) |*lift, i| {
+ p.advance(1000 * ms + @as(u64, @intCast(i)) * 6_944_444);
+ _ = arena.reset(.retain_capacity);
+ const s = try p.render(arena.allocator());
+ lift.* = for (s.regionList()) |region| {
+ if (region.kind == .grip and region.owner == p.active) break region.lift;
+ } else return error.TestExpectedGrip;
+ try std.testing.expect(p.continuous());
+ }
+ try std.testing.expect(lifts[0] < lifts[1] and lifts[1] < lifts[2]);
+ // Settled, it is exactly up, and the core is idle again.
+ p.advance(2000 * ms);
+ _ = arena.reset(.retain_capacity);
+ _ = try p.render(arena.allocator());
+ try std.testing.expect(!p.continuous());
+ try std.testing.expectEqual(@as(?u64, null), p.nextWake());
+}
+
test "a monkey over notices, prompts, tags and tiny panes at a gui's metrics never panics" {
// The snapshot harness runs the tty, whose tagline pitch is the body's,
// so it never reaches what a narrower tagline does to a notice's band: