summaryrefslogtreecommitdiff
path: root/src/gui
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-09-28 12:57:47 -0300
committerGabriel Schneider <[email protected]>2026-10-01 00:12:14 -0300
commit30c2c8a154e770b3920bcfd7d553825fe9182bf4 (patch)
treeecdce274f1cb25095c72f4da62b7c35e23aee04c /src/gui
parent8f31fc6bfaae2d29b2bb5cc2149fcd7033cd9724 (diff)
downloadpardes-30c2c8a154e770b3920bcfd7d553825fe9182bf4.tar.gz
pardes-30c2c8a154e770b3920bcfd7d553825fe9182bf4.zip
Move the frame into draw.zig and the transitions out of layout.zig
Pure moves, no behaviour change. draw.zig holds the whole core frame in order: render, the pane, tag, header and notice painters it calls, and the character-effect composition (Pardes.render stays a declaration alias). Presentation.zig is the panel presentation state as a file struct, and animation.zig the easing curves, transition kinds, tracks and boxes, the character effects' sources and the generic displayed-value transition, all of which lived in layout.zig. layout.zig keeps only layout.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/gui.zig66
1 files changed, 33 insertions, 33 deletions
diff --git a/src/gui/gui.zig b/src/gui/gui.zig
index 6978284b..0737bb63 100644
--- a/src/gui/gui.zig
+++ b/src/gui/gui.zig
@@ -209,11 +209,11 @@ const AnimationClock = struct {
return false;
}
if (clock.next_ns == 0) {
- clock.next_ns = now_ns +| pardes.layout.Animation.frame_ns;
+ clock.next_ns = now_ns +| pardes.animation.Animation.frame_ns;
return false;
}
if (now_ns < clock.next_ns) return false;
- clock.next_ns = now_ns +| pardes.layout.Animation.frame_ns;
+ clock.next_ns = now_ns +| pardes.animation.Animation.frame_ns;
return true;
}
};
@@ -221,7 +221,7 @@ const AnimationClock = struct {
fn finishPresentedAnimationFrame(
clock: *AnimationClock,
core: *pardes.Pardes,
- tracks: []const pardes.layout.Track,
+ tracks: []const pardes.animation.Track,
now_ns: u64,
) void {
core.acknowledgePanelPresentation(tracks);
@@ -232,9 +232,9 @@ test "GUI animation clock is active-only and cadence gated" {
var clock: AnimationClock = .{};
try std.testing.expect(!clock.due(false, 100));
try std.testing.expect(!clock.due(true, 100));
- try std.testing.expect(!clock.due(true, 100 + pardes.layout.Animation.frame_ns - 1));
- try std.testing.expect(clock.due(true, 100 + pardes.layout.Animation.frame_ns));
- try std.testing.expect(!clock.due(false, 100 + 2 * pardes.layout.Animation.frame_ns));
+ try std.testing.expect(!clock.due(true, 100 + pardes.animation.Animation.frame_ns - 1));
+ try std.testing.expect(clock.due(true, 100 + pardes.animation.Animation.frame_ns));
+ try std.testing.expect(!clock.due(false, 100 + 2 * pardes.animation.Animation.frame_ns));
try std.testing.expectEqual(@as(u64, 0), clock.next_ns);
}
@@ -248,7 +248,7 @@ test "a persistent scene presents a new panel's frame zero before advancing it"
core.settings.scene_effects.crt = true;
const scene_frame = try core.render(arena.allocator());
finishPresentedAnimationFrame(&clock, core, scene_frame.panelTracks(), 100);
- try std.testing.expectEqual(@as(u64, 100 + pardes.layout.Animation.frame_ns), clock.next_ns);
+ try std.testing.expectEqual(@as(u64, 100 + pardes.animation.Animation.frame_ns), clock.next_ns);
core.settings.panel_transition = .slide;
core.update(.{ .command = "Newcol" });
@@ -262,7 +262,7 @@ test "a persistent scene presents a new panel's frame zero before advancing it"
&clock,
core,
first.panelTracks(),
- 100 + pardes.layout.Animation.frame_ns,
+ 100 + pardes.animation.Animation.frame_ns,
);
_ = arena.reset(.retain_capacity);
const second = try core.render(arena.allocator());
@@ -557,8 +557,8 @@ const SavedImagePlace = struct {
const PreparedImage = struct {
place: SavedImagePlace,
texture: *c.SDL_GPUTexture,
- track: ?pardes.layout.Track = null,
- clip: ?pardes.layout.Box = null,
+ track: ?pardes.animation.Track = null,
+ clip: ?pardes.animation.Box = null,
old_layer: bool = false,
};
@@ -592,7 +592,7 @@ test "shader instance ABI carries aligned transition vectors" {
try std.testing.expectEqual(@as(usize, 64), @offsetOf(ImageInstance, "effect"));
try std.testing.expectEqual(@as(usize, 32), @sizeOf([8]f32));
- const tracks = [_]pardes.layout.Track{
+ const tracks = [_]pardes.animation.Track{
.{ .pane = 0, .phase = .opening, .effect = .slide },
.{ .pane = 1, .phase = .moving, .effect = .slide },
.{ .pane = 2, .phase = .moving, .effect = .slide },
@@ -606,19 +606,19 @@ test "shader instance ABI carries aligned transition vectors" {
}
test "GUI paint plan snaps history effects without a frozen grid" {
- const tracks = [_]pardes.layout.Track{
+ const tracks = [_]pardes.animation.Track{
.{ .pane = 0, .phase = .opening, .effect = .ascii },
.{ .pane = 1, .phase = .closing, .effect = .vertical },
};
try std.testing.expectEqual(@as(usize, 1), makePaintPlan(&tracks, false).len);
const ready = makePaintPlan(&tracks, true);
try std.testing.expectEqual(@as(usize, 3), ready.len);
- try std.testing.expectEqual(pardes.layout.Phase.opening, ready.batches[1].track.?.phase);
- try std.testing.expectEqual(pardes.layout.Phase.closing, ready.batches[2].track.?.phase);
+ try std.testing.expectEqual(pardes.animation.Phase.opening, ready.batches[1].track.?.phase);
+ try std.testing.expectEqual(pardes.animation.Phase.closing, ready.batches[2].track.?.phase);
}
test "closing tombstone overlays but never owns canonical cells" {
- const closing: pardes.layout.Track = .{
+ const closing: pardes.animation.Track = .{
.pane = 0,
.phase = .closing,
.effect = .vertical,
@@ -628,7 +628,7 @@ test "closing tombstone overlays but never owns canonical cells" {
const plan = makePaintPlan(&.{closing}, true);
try std.testing.expectEqual(@as(usize, 0), paintBatchAt(&plan, 4, 4));
try std.testing.expectEqual(@as(usize, 2), plan.len);
- try std.testing.expectEqual(pardes.layout.Phase.closing, plan.batches[1].track.?.phase);
+ try std.testing.expectEqual(pardes.animation.Phase.closing, plan.batches[1].track.?.phase);
}
fn updateCoreResize(core: *pardes.Pardes, cols: u16, rows: u16, cell_w: u32, cell_h: u32, tag_w: u32, tag_h: u32) bool {
@@ -2031,10 +2031,10 @@ fn taglineLayoutForCell(g: *const Gui, col: u16) CellLayout {
return compactTaglineLayout(g, @floatFromInt(col));
}
-const boxContains = pardes.layout.Box.contains;
+const boxContains = pardes.animation.Box.contains;
const PaintBatch = struct {
- track: ?pardes.layout.Track = null,
+ track: ?pardes.animation.Track = null,
cell_start: u32 = 0,
cell_count: u32 = 0,
image_start: u32 = 0,
@@ -2046,9 +2046,9 @@ const PaintPlan = struct {
len: usize = 1,
};
-fn makePaintPlan(tracks: []const pardes.layout.Track, has_diff: bool) PaintPlan {
+fn makePaintPlan(tracks: []const pardes.animation.Track, has_diff: bool) PaintPlan {
var plan: PaintPlan = .{};
- for ([_]pardes.layout.Phase{ .moving, .opening, .closing }) |phase| {
+ for ([_]pardes.animation.Phase{ .moving, .opening, .closing }) |phase| {
for (tracks) |track| {
if (!track.active() or track.phase != phase) continue;
if (track.effect.needsPreviousGrid() and !has_diff) continue;
@@ -2074,21 +2074,21 @@ fn paintBatchForSerial(plan: *const PaintPlan, serial: u32) usize {
return 0;
}
-fn panelCellCoord(track: pardes.layout.Track, col: u16, row: u16) u32 {
+fn panelCellCoord(track: pardes.animation.Track, col: u16, row: u16) u32 {
const source = track.contentBox();
const x0: u16 = @intFromFloat(@max(0.0, @floor(source.x)));
const y0: u16 = @intFromFloat(@max(0.0, @floor(source.y)));
return @as(u32, row -| y0) << 16 | @as(u32, col -| x0);
}
-fn panelGridSize(track: pardes.layout.Track) u32 {
+fn panelGridSize(track: pardes.animation.Track) u32 {
const source = track.contentBox();
const cols: u16 = @intFromFloat(@min(@as(f32, std.math.maxInt(u16)), @max(1.0, @ceil(source.w))));
const rows: u16 = @intFromFloat(@min(@as(f32, std.math.maxInt(u16)), @max(1.0, @ceil(source.h))));
return @as(u32, rows) << 16 | @as(u32, cols);
}
-fn ndcBox(box: pardes.layout.Box, layout: CellLayout, win_w: f32, win_h: f32) [4]f32 {
+fn ndcBox(box: pardes.animation.Box, layout: CellLayout, win_w: f32, win_h: f32) [4]f32 {
const px0 = layout.x_off + box.x * layout.w;
const py0 = layout.y_off + box.y * layout.h;
const px1 = px0 + box.w * layout.w;
@@ -2103,7 +2103,7 @@ fn ndcBox(box: pardes.layout.Box, layout: CellLayout, win_w: f32, win_h: f32) [4
fn setTransitionFields(
instance: anytype,
- track: ?pardes.layout.Track,
+ track: ?pardes.animation.Track,
layout: CellLayout,
win_w: f32,
win_h: f32,
@@ -4636,7 +4636,7 @@ fn snapshotContainsPlacement(g: *const Gui, current: pardes.ImagePlace) bool {
return false;
}
-fn placeIntersectsBox(place: SavedImagePlace, box: pardes.layout.Box) bool {
+fn placeIntersectsBox(place: SavedImagePlace, box: pardes.animation.Box) bool {
const x0: f32 = @floatFromInt(place.x);
const y0: f32 = @floatFromInt(place.y);
const x1: f32 = @floatFromInt(@as(u32, place.x) + place.w);
@@ -4808,8 +4808,8 @@ fn appendPreparedImage(
g: *Gui,
gpa: std.mem.Allocator,
place: SavedImagePlace,
- track: ?pardes.layout.Track,
- clip: ?pardes.layout.Box,
+ track: ?pardes.animation.Track,
+ clip: ?pardes.animation.Box,
old_layer: bool,
) void {
const texture = g.native_images.get(place.key) orelse return;
@@ -4998,7 +4998,7 @@ fn imageScissor(
};
}
-fn panelBoxScissor(g: *const Gui, box: pardes.layout.Box, max_w: u32, max_h: u32) c.SDL_Rect {
+fn panelBoxScissor(g: *const Gui, box: pardes.animation.Box, max_w: u32, max_h: u32) c.SDL_Rect {
const x0: i32 = @intFromFloat(@floor(box.x * @as(f32, @floatFromInt(g.cell_w))));
const y0: i32 = @intFromFloat(@floor(box.y * @as(f32, @floatFromInt(g.cell_h))));
const x1: i32 = @intFromFloat(@ceil((box.x + box.w) * @as(f32, @floatFromInt(g.cell_w))));
@@ -5059,7 +5059,7 @@ fn renderFrame(
theme_bg: ?[3]u8,
topbar_pane_border_rgb: [3]u8,
tagline_rgb: [3]u8,
- scene_effects: pardes.layout.SceneEffect,
+ scene_effects: pardes.animation.SceneEffect,
debug_on: bool,
) !bool {
if (surface.pointer_shape != g.pointer_shape) {
@@ -5763,7 +5763,7 @@ fn tagLayerCellCount(g: *const Gui, layer: *const pardes.TagLayer) u32 {
return @min(layer.cols, (pixels + g.tagline_width - 1) / g.tagline_width);
}
-fn emitTagLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.TagLayer, win_w: f32, win_h: f32, track: ?pardes.layout.Track, page: Ground, show_cursor: bool, old_layer: bool) void {
+fn emitTagLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.TagLayer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool) void {
const bw: f32 = @floatFromInt(g.cell_w);
const bh: f32 = @floatFromInt(g.cell_h);
const tw: f32 = @floatFromInt(g.tagline_width);
@@ -5826,7 +5826,7 @@ fn clipBodyInstance(instance: *CellInstance, bottom: f32, win_h: f32) void {
instance.y1 = limit;
}
-fn emitBodyLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.BodyLayer, win_w: f32, win_h: f32, track: ?pardes.layout.Track, page: Ground, show_cursor: bool, old_layer: bool, border_rgb: [3]u8) void {
+fn emitBodyLayer(g: *Gui, instances: [*]CellInstance, next: *u32, layer: *const pardes.BodyLayer, win_w: f32, win_h: f32, track: ?pardes.animation.Track, page: Ground, show_cursor: bool, old_layer: bool, border_rgb: [3]u8) void {
const bw: f32 = @floatFromInt(g.cell_w);
const bh: f32 = @floatFromInt(g.cell_h);
const tw: f32 = @floatFromInt(g.tagline_width);
@@ -5919,7 +5919,7 @@ fn emitSurfaceCell(
body_layout: CellLayout,
win_w: f32,
win_h: f32,
- track: ?pardes.layout.Track,
+ track: ?pardes.animation.Track,
line: []const pardes.Cell,
at: usize,
cursor: ?usize,
@@ -6018,7 +6018,7 @@ fn emitInstance(
layout: CellLayout,
win_w: f32,
win_h: f32,
- track: ?pardes.layout.Track,
+ track: ?pardes.animation.Track,
role: pardes.FontRole,
line: []const pardes.Cell,
at: usize,