Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added refresh interval in ms for animations #709

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions res/config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
# matrix -> CMatrix
animation = none

# The minimum time between animation frames
# 32 -> ~30fps
# 16 -> ~60fps
# 8 -> ~120fps
# 6 -> ~144fps
# 4 -> ~240fps
animation_refresh_ms = 16

# Stop the animation after some time
# 0 -> Run forever
# 1..2e12 -> Stop the animation after this many seconds
Expand Down
30 changes: 26 additions & 4 deletions src/animations/Doom.zig
Original file line number Diff line number Diff line change
Expand Up @@ -50,35 +50,57 @@ pub fn realloc(self: *Doom) !void {
self.buffer = buffer;
}

pub fn draw(self: Doom) void {
pub fn drawWithUpdate(self: Doom) void {
for (0..self.terminal_buffer.width) |x| {
for (1..self.terminal_buffer.height) |y| {
// get source index
const source = y * self.terminal_buffer.width + x;

// random number between 0 and 3 inclusive
const random = (self.terminal_buffer.random.int(u16) % 7) & 3;

// adjust destination index based on random value
var dest = (source - @min(source, random)) + 1;
if (self.terminal_buffer.width > dest) dest = 0 else dest -= self.terminal_buffer.width;

// get source intensity and destination offset
const buffer_source = self.buffer[source];
const buffer_dest_offset = random & 1;

if (buffer_source < buffer_dest_offset) continue;

// calculate the destination intensity
var buffer_dest = buffer_source - buffer_dest_offset;
if (buffer_dest > 12) buffer_dest = 0;
self.buffer[dest] = @intCast(buffer_dest);

// update terminal
self.terminal_buffer.buffer[dest] = toTermboxCell(FIRE[buffer_dest]);
self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]);
}
}
}

pub fn draw(self: Doom) void {
for (0..self.terminal_buffer.width) |x| {
for (1..self.terminal_buffer.height) |y| {
// get source index
const source = y * self.terminal_buffer.width + x;

// get intensity from buffer
const buffer_source = self.buffer[source];

// set cell to correct fire char
self.terminal_buffer.buffer[source] = toTermboxCell(FIRE[buffer_source]);
}
}
}

fn initBuffer(buffer: []u8, width: usize) void {
const length = buffer.len - width;
const slice_start = buffer[0..length];
const slice_end = buffer[length..];
const slice_start = buffer[0..buffer.len];
const slice_end = buffer[buffer.len - width .. buffer.len];

// set cell initial values to 0, set bottom row to be fire sources
@memset(slice_start, 0);
@memset(slice_end, STEPS - 1);
}
Expand Down
121 changes: 62 additions & 59 deletions src/animations/Matrix.zig
Original file line number Diff line number Diff line change
Expand Up @@ -68,80 +68,83 @@ pub fn realloc(self: *Matrix) !void {
self.lines = lines;
}

pub fn draw(self: *Matrix) void {
pub fn drawWithUpdate(self: *Matrix) void {
const buf_height = self.terminal_buffer.height;
const buf_width = self.terminal_buffer.width;
self.count += 1;
if (self.count > FRAME_DELAY) {
self.frame += 1;
if (self.frame > 4) self.frame = 1;
self.count = 0;

var x: usize = 0;
while (x < self.terminal_buffer.width) : (x += 2) {
var tail: usize = 0;
var line = &self.lines[x];
if (self.frame <= line.update) continue;

if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') {
if (line.space > 0) {
line.space -= 1;
} else {
const randint = self.terminal_buffer.random.int(i16);
const h: isize = @intCast(self.terminal_buffer.height);
line.length = @mod(randint, h - 3) + 3;
self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
line.space = @mod(randint, h + 1);
}
}
self.frame += 1;
if (self.frame > 4) self.frame = 1;

var y: usize = 0;
var first_col = true;
var seg_len: u64 = 0;
height_it: while (y <= buf_height) : (y += 1) {
var dot = &self.dots[buf_width * y + x];
// Skip over spaces
while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) {
y += 1;
if (y > buf_height) break :height_it;
dot = &self.dots[buf_width * y + x];
}
var x: usize = 0;
while (x < self.terminal_buffer.width) : (x += 2) {
var tail: usize = 0;
var line = &self.lines[x];
if (self.frame <= line.update) continue;

if (self.dots[x].value == -1 and self.dots[self.terminal_buffer.width + x].value == ' ') {
if (line.space > 0) {
line.space -= 1;
} else {
const randint = self.terminal_buffer.random.int(i16);
const h: isize = @intCast(self.terminal_buffer.height);
line.length = @mod(randint, h - 3) + 3;
self.dots[x].value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
line.space = @mod(randint, h + 1);
}
}

// Find the head of this column
tail = y;
seg_len = 0;
while (y <= buf_height and dot.value != ' ' and dot.value != -1) {
dot.is_head = false;
if (MID_SCROLL_CHANGE) {
const randint = self.terminal_buffer.random.int(i16);
if (@mod(randint, 8) == 0) {
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
}
}
var y: usize = 0;
var first_col = true;
var seg_len: u64 = 0;
height_it: while (y <= buf_height) : (y += 1) {
var dot = &self.dots[buf_width * y + x];
// Skip over spaces
while (y <= buf_height and (dot.value == ' ' or dot.value == -1)) {
y += 1;
if (y > buf_height) break :height_it;
dot = &self.dots[buf_width * y + x];
}

y += 1;
seg_len += 1;
// Head's down offscreen
if (y > buf_height) {
self.dots[buf_width * tail + x].value = ' ';
break :height_it;
// Find the head of this column
tail = y;
seg_len = 0;
while (y <= buf_height and dot.value != ' ' and dot.value != -1) {
dot.is_head = false;
if (MID_SCROLL_CHANGE) {
const randint = self.terminal_buffer.random.int(i16);
if (@mod(randint, 8) == 0) {
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
}
dot = &self.dots[buf_width * y + x];
}

const randint = self.terminal_buffer.random.int(i16);
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
dot.is_head = true;

if (seg_len > line.length or !first_col) {
y += 1;
seg_len += 1;
// Head's down offscreen
if (y > buf_height) {
self.dots[buf_width * tail + x].value = ' ';
self.dots[x].value = -1;
break :height_it;
}
first_col = false;
dot = &self.dots[buf_width * y + x];
}

const randint = self.terminal_buffer.random.int(i16);
dot.value = @mod(randint, MAX_CODEPOINT) + MIN_CODEPOINT;
dot.is_head = true;

if (seg_len > line.length or !first_col) {
self.dots[buf_width * tail + x].value = ' ';
self.dots[x].value = -1;
}
first_col = false;
}
}

self.draw();
}

pub fn draw(self: *Matrix) void {
const buf_width = self.terminal_buffer.width;

var x: usize = 0;
while (x < buf_width) : (x += 2) {
var y: usize = 1;
Expand Down
1 change: 1 addition & 0 deletions src/config/Config.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const Bigclock = enums.Bigclock;

animation: Animation = .none,
animation_timeout_sec: u12 = 0,
animation_refresh_ms: u16 = 16,
asterisk: ?u8 = '*',
auth_fails: u64 = 10,
bg: u16 = 0,
Expand Down
30 changes: 26 additions & 4 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,11 @@ pub fn main() !void {
}
}

var animation_timer = switch (config.animation) {
.none => undefined,
else => try std.time.Timer.start(),
};

const animate = config.animation != .none;
const shutdown_key = try std.fmt.parseInt(u8, config.shutdown_key[1..], 10);
const shutdown_len = try utils.strWidth(lang.shutdown);
Expand Down Expand Up @@ -380,8 +385,22 @@ pub fn main() !void {
if (!animation_timed_out) {
switch (config.animation) {
.none => {},
.doom => doom.draw(),
.matrix => matrix.draw(),
.doom => {
if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) {
animation_timer.reset();
doom.drawWithUpdate();
} else {
doom.draw();
}
},
.matrix => {
if (animation_timer.read() / std.time.ns_per_ms > config.animation_refresh_ms) {
animation_timer.reset();
matrix.drawWithUpdate();
} else {
matrix.draw();
}
},
}
}

Expand Down Expand Up @@ -685,7 +704,7 @@ pub fn main() !void {
const password_text = try allocator.dupeZ(u8, password.text.items);
defer allocator.free(password_text);

// Give up control on the TTY
// Give up TTY
_ = termbox.tb_shutdown();

session_pid = try std.posix.fork();
Expand All @@ -702,10 +721,13 @@ pub fn main() !void {
session_pid = -1;
}

// Take back control of the TTY
// Take back TTY
_ = termbox.tb_init();
_ = termbox.tb_set_output_mode(termbox.TB_OUTPUT_NORMAL);

// Reinitialise buffer to avoid use after free
buffer = TerminalBuffer.init(config, labels_max_length, random);

const auth_err = shared_err.readError();
if (auth_err) |err| {
auth_fails += 1;
Expand Down