Make animation timeout independent of event loop

Signed-off-by: AnErrupTion <anerruption@disroot.org>
This commit is contained in:
AnErrupTion
2026-02-11 23:51:32 +01:00
parent 57c96a3478
commit 7c7aed9cb2
6 changed files with 121 additions and 45 deletions

View File

@@ -1,6 +1,10 @@
const std = @import("std");
const Allocator = std.mem.Allocator;
const ly_core = @import("ly-core");
const interop = ly_core.interop;
const TimeOfDay = interop.TimeOfDay;
const Cell = @import("../tui/Cell.zig");
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
const Widget = @import("../tui/Widget.zig");
@@ -16,6 +20,7 @@ const NEIGHBOR_DIRS = [_][2]i8{
.{ 1, 0 }, .{ 1, 1 },
};
start_time: TimeOfDay,
allocator: Allocator,
terminal_buffer: *TerminalBuffer,
current_grid: []bool,
@@ -26,7 +31,8 @@ fg_color: u32,
entropy_interval: usize,
frame_delay: usize,
initial_density: f32,
timeout: *bool,
animate: *bool,
timeout_sec: u12,
dead_cell: Cell,
width: usize,
height: usize,
@@ -38,7 +44,8 @@ pub fn init(
entropy_interval: usize,
frame_delay: usize,
initial_density: f32,
timeout: *bool,
animate: *bool,
timeout_sec: u12,
) !GameOfLife {
const width = terminal_buffer.width;
const height = terminal_buffer.height;
@@ -48,6 +55,7 @@ pub fn init(
const next_grid = try allocator.alloc(bool, grid_size);
var game = GameOfLife{
.start_time = try interop.getTimeOfDay(),
.allocator = allocator,
.terminal_buffer = terminal_buffer,
.current_grid = current_grid,
@@ -58,7 +66,8 @@ pub fn init(
.entropy_interval = entropy_interval,
.frame_delay = frame_delay,
.initial_density = initial_density,
.timeout = timeout,
.animate = animate,
.timeout_sec = timeout_sec,
.dead_cell = .{ .ch = DEAD_CHAR, .fg = @intCast(TerminalBuffer.Color.DEFAULT), .bg = terminal_buffer.bg },
.width = width,
.height = height,
@@ -77,7 +86,7 @@ pub fn widget(self: *GameOfLife) Widget {
deinit,
realloc,
draw,
null,
update,
null,
);
}
@@ -105,7 +114,7 @@ fn realloc(self: *GameOfLife) !void {
}
fn draw(self: *GameOfLife) void {
if (self.timeout.*) return;
if (!self.animate.*) return;
// Update game state at controlled frame rate
self.frame_counter += 1;
@@ -132,6 +141,14 @@ fn draw(self: *GameOfLife) void {
}
}
fn update(self: *GameOfLife, _: *anyopaque) !void {
const time = try interop.getTimeOfDay();
if (self.timeout_sec > 0 and time.seconds - self.start_time.seconds > self.timeout_sec) {
self.animate.* = false;
}
}
fn updateGeneration(self: *GameOfLife) void {
// Conway's Game of Life rules with optimized neighbor counting
for (0..self.height) |y| {