diff options
Diffstat (limited to 'src/config.zig')
| -rw-r--r-- | src/config.zig | 75 |
1 files changed, 67 insertions, 8 deletions
diff --git a/src/config.zig b/src/config.zig index 1d4043ab..e8c5a705 100644 --- a/src/config.zig +++ b/src/config.zig @@ -628,7 +628,12 @@ pub const Runtime = struct { pub const Entry = struct { scene: ?Scene = null, path: Text(limits.host_path_cap) = .{}, + /// A bundled pass's strength, 1 to `max_level`; 0 for a file. + level: u8 = 0, }; + pub const max_level = 3; + /// What `on` and a bare word turn a bundled pass on at. + pub const default_level = 2; entries: [max]Entry = @splat(.{}), len: u8 = 0, /// Bumped on every change: a shell compiles the chain again when it @@ -640,8 +645,28 @@ pub const Runtime = struct { } pub fn has(post: *const Post, scene: Scene) bool { - for (post.list()) |entry| if (entry.scene == scene) return true; - return false; + return post.level(scene) != 0; + } + + /// A bundled pass's level; 0 when it is not in the chain. + pub fn level(post: *const Post, scene: Scene) u8 { + for (post.list()) |entry| if (entry.scene == scene) return entry.level; + return 0; + } + + /// Sets a bundled pass's level: 0 takes it out, anything else puts it + /// in at the end or changes it where it is. + pub fn setLevel(post: *Post, scene: Scene, to: u8) bool { + std.debug.assert(to <= max_level); + if (to == 0) return post.set(scene, "", false); + for (post.entries[0..post.len]) |*entry| if (entry.scene == scene) { + if (entry.level != to) post.generation +%= 1; + entry.level = to; + return true; + }; + if (!post.set(scene, "", true)) return false; + post.entries[post.len - 1].level = to; + return true; } /// Puts the pass in the chain, at its end, or takes it out; `want` @@ -949,8 +974,19 @@ pub const Runtime = struct { } }, .scene => |effect| { - const want = switchedTo(argument) catch return false; - return state.post.set(effect, "", want); + // A level, 0 (off) to 3; `on` is the default level, `off` 0, + // and bare flips between the two. + const text = std.mem.trim(u8, argument orelse "", " \t\r\n"); + const to: u8 = if (text.len == 0) + (if (state.post.has(effect)) 0 else Post.default_level) + else if (std.mem.eql(u8, text, "on")) + Post.default_level + else if (std.mem.eql(u8, text, "off")) + 0 + else + std.fmt.parseInt(u8, text, 10) catch return false; + if (to > Post.max_level) return false; + return state.post.setLevel(effect, to); }, .shader => { const path = std.mem.trim(u8, argument orelse return false, " \t\r\n"); @@ -1119,7 +1155,8 @@ pub const Runtime = struct { try out.print("{s} unsupported\n", .{setting.word}); continue; } - try out.print("{s} {s}\n", .{ setting.word, onOff(state.post.has(effect)) }); + const level = state.post.level(effect); + if (level == 0) try out.print("{s} off\n", .{setting.word}) else try out.print("{s} {d}\n", .{ setting.word, level }); }, .shader => { if (!setting.enabled(context.capabilities)) { @@ -1246,6 +1283,28 @@ pub const Runtime = struct { try std.testing.expect(!apply(&state, find("ShaderAnimation").?, "sometimes")); } + test "a bundled pass takes a level: on is the default, 0 and off take it out, and the old words still flip" { + var state: Runtime = .{}; + const crt = find("Crt").?; + try std.testing.expect(apply(&state, crt, "on")); + try std.testing.expectEqual(@as(u8, Post.default_level), state.post.level(.crt)); + try std.testing.expect(apply(&state, find("Glitch").?, "1")); + const moved = state.post.generation; + try std.testing.expect(apply(&state, crt, "3")); + try std.testing.expectEqual(@as(u8, 3), state.post.level(.crt)); + // A new level keeps its place in the chain. + try std.testing.expectEqual(Scene.crt, state.post.list()[0].scene.?); + try std.testing.expect(state.post.generation != moved); + try std.testing.expect(!apply(&state, crt, "4")); + try std.testing.expect(!apply(&state, crt, "loud")); + try std.testing.expect(apply(&state, crt, "0")); + try std.testing.expect(!state.post.has(.crt)); + try std.testing.expect(apply(&state, crt, null)); + try std.testing.expectEqual(@as(u8, Post.default_level), state.post.level(.crt)); + try std.testing.expect(apply(&state, crt, "off")); + try std.testing.expectEqual(@as(u8, 0), state.post.level(.crt)); + } + test "tagline size validates before mutating live state" { const setting = find("TaglineSize").?; var state: Runtime = .{}; @@ -1412,9 +1471,9 @@ pub const Runtime = struct { .typewriter => "Panel transition PanelType\n", }, .scene => |effect| switch (effect) { - .crt => "Crt on\n", - .ripple => "Ripple on\n", - .glitch => "Glitch on\n", + .crt => "Crt 2\n", + .ripple => "Ripple 2\n", + .glitch => "Glitch 2\n", }, .shader => "Shader ~/crt.glsl\n", .shader_animation => "ShaderAnimation always\n", |
