mirror of https://github.com/fairyglade/ly.git
Add ASCII Background Animation
This commit is contained in:
parent
933e5bdd2d
commit
0380b8d32b
|
@ -24,6 +24,7 @@ allow_empty_password = true
|
|||
# matrix -> CMatrix
|
||||
# colormix -> Color mixing shader
|
||||
# gameoflife -> John Conway's Game of Life
|
||||
# ascii -> Custom ASCII art background loaded from a file
|
||||
animation = none
|
||||
|
||||
# Stop the animation after some time
|
||||
|
@ -155,6 +156,17 @@ gameoflife_frame_delay = 6
|
|||
# 0.7+ -> Dense, chaotic patterns
|
||||
gameoflife_initial_density = 0.4
|
||||
|
||||
# ASCII background file path (absolute)
|
||||
ascii_filename = /etc/ly/config.ini
|
||||
|
||||
# ASCII background text foreground color id
|
||||
ascii_fg = 0x00FFFFFF
|
||||
|
||||
# ASCII background offset (top left = 0,0; specified in characters)
|
||||
# These must be >= 0
|
||||
ascii_x = 0
|
||||
ascii_y = 0
|
||||
|
||||
# Remove main box borders
|
||||
hide_borders = false
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
const std = @import("std");
|
||||
const Animation = @import("../tui/Animation.zig");
|
||||
const Cell = @import("../tui/Cell.zig");
|
||||
const TerminalBuffer = @import("../tui/TerminalBuffer.zig");
|
||||
|
||||
const Ascii = @This();
|
||||
|
||||
const MAX_WIDTH = 512;
|
||||
const MAX_HEIGHT = 256;
|
||||
|
||||
terminal_buffer: *TerminalBuffer,
|
||||
ascii_art: [MAX_HEIGHT][MAX_WIDTH]u8 = undefined,
|
||||
line_len: [MAX_HEIGHT]usize = undefined,
|
||||
line_count: usize = undefined,
|
||||
fg: u32 = undefined,
|
||||
x: u32 = undefined,
|
||||
y: u32 = undefined,
|
||||
|
||||
pub fn init(terminal_buffer: *TerminalBuffer, filename: []const u8, fg: u32, x: u32, y: u32) !Ascii {
|
||||
var ascii_art: [MAX_HEIGHT][MAX_WIDTH]u8 = undefined;
|
||||
var line_len: [MAX_HEIGHT]usize = [_]usize{0} ** MAX_HEIGHT;
|
||||
var line_count: usize = 0;
|
||||
|
||||
var file = std.fs.openFileAbsolute(filename, .{}) catch {
|
||||
std.log.err("ASCII background file not found: {s}", .{filename});
|
||||
return .{
|
||||
.terminal_buffer = terminal_buffer,
|
||||
.ascii_art = undefined, // Undefined buffers here are safe, as line_count
|
||||
.line_len = undefined, // is set to 0 so nothing will be drawn
|
||||
.line_count = 0,
|
||||
.fg = 0x00000000,
|
||||
.x = 0, .y = 0,
|
||||
};
|
||||
};
|
||||
var reader = file.reader();
|
||||
defer file.close();
|
||||
|
||||
while (line_count < MAX_HEIGHT) {
|
||||
const line = reader.readUntilDelimiterOrEof(&ascii_art[line_count], '\n') catch |err| switch (err) {
|
||||
error.StreamTooLong => {
|
||||
_ = try reader.skipUntilDelimiterOrEof('\n'); // consume remainder of line
|
||||
line_len[line_count] = MAX_WIDTH;
|
||||
line_count += 1;
|
||||
continue;
|
||||
},
|
||||
else => return err,
|
||||
} orelse break;
|
||||
|
||||
line_len[line_count] = line.len;
|
||||
line_count += 1;
|
||||
}
|
||||
|
||||
return .{
|
||||
.terminal_buffer = terminal_buffer,
|
||||
.ascii_art = ascii_art,
|
||||
.line_len = line_len,
|
||||
.line_count = line_count,
|
||||
.fg = fg, .x = x, .y = y,
|
||||
};
|
||||
}
|
||||
pub fn animation(self: *Ascii) Animation {
|
||||
return Animation.init(self, deinit, realloc, draw);
|
||||
}
|
||||
|
||||
fn deinit(_: *Ascii) void {}
|
||||
|
||||
fn realloc(_: *Ascii) anyerror!void {}
|
||||
|
||||
fn min(a: usize, b: usize) usize {
|
||||
if (a < b) return a;
|
||||
return b;
|
||||
}
|
||||
|
||||
fn draw(self: *Ascii) void {
|
||||
const buf_width = self.terminal_buffer.width;
|
||||
const buf_height = self.terminal_buffer.height;
|
||||
|
||||
var y: usize = 0;
|
||||
while (y < min(buf_height, self.line_count)) : (y += 1) {
|
||||
const line_width = self.line_len[y];
|
||||
var x: usize = 0;
|
||||
while (x < min(buf_width, line_width)) : (x += 1) {
|
||||
const cell = Cell {
|
||||
.ch = self.ascii_art[y][x],
|
||||
.fg = self.fg,
|
||||
.bg = self.terminal_buffer.bg,
|
||||
};
|
||||
cell.put(x + self.x, y + self.y);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,6 +42,10 @@ gameoflife_fg: u32 = 0x0000FF00,
|
|||
gameoflife_entropy_interval: usize = 10,
|
||||
gameoflife_frame_delay: usize = 6,
|
||||
gameoflife_initial_density: f32 = 0.4,
|
||||
ascii_filename: []const u8 = "/etc/ly/config.ini",
|
||||
ascii_fg: u32 = 0x00FF0000,
|
||||
ascii_x: u32 = 0,
|
||||
ascii_y: u32 = 0,
|
||||
hide_borders: bool = false,
|
||||
hide_version_string: bool = false,
|
||||
hide_key_hints: bool = false,
|
||||
|
|
|
@ -4,6 +4,7 @@ pub const Animation = enum {
|
|||
matrix,
|
||||
colormix,
|
||||
gameoflife,
|
||||
ascii,
|
||||
};
|
||||
|
||||
pub const DisplayServer = enum {
|
||||
|
|
|
@ -13,6 +13,7 @@ const Doom = @import("animations/Doom.zig");
|
|||
const Dummy = @import("animations/Dummy.zig");
|
||||
const Matrix = @import("animations/Matrix.zig");
|
||||
const GameOfLife = @import("animations/GameOfLife.zig");
|
||||
const Ascii = @import("animations/Ascii.zig");
|
||||
const Animation = @import("tui/Animation.zig");
|
||||
const TerminalBuffer = @import("tui/TerminalBuffer.zig");
|
||||
const Session = @import("tui/components/Session.zig");
|
||||
|
@ -400,6 +401,10 @@ pub fn main() !void {
|
|||
var game_of_life = try GameOfLife.init(allocator, &buffer, config.gameoflife_fg, config.gameoflife_entropy_interval, config.gameoflife_frame_delay, config.gameoflife_initial_density);
|
||||
animation = game_of_life.animation();
|
||||
},
|
||||
.ascii => {
|
||||
var ascii = try Ascii.init(&buffer, config.ascii_filename, config.ascii_fg, config.ascii_x, config.ascii_y);
|
||||
animation = ascii.animation();
|
||||
},
|
||||
}
|
||||
defer animation.deinit();
|
||||
|
||||
|
|
Loading…
Reference in New Issue