Skip to content
Merged
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
125 changes: 124 additions & 1 deletion specs/t27f/reel.t27
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
; and the MCP Apps quickstart): the terminal CLI does not render MCP Apps, and an image block in a tool
; result reaches the model but is not documented to reach the user. A file on disk with its path in the
; answer reaches the user everywhere; the desktop Code tab opens it in its Browser pane. CHANNEL_* below.
; Not claimed: no host imports this file yet, no renderer exists, no reel has been rendered.
; Host: gHashTag/t27-mcp t27f_view draws stills of the demo reel from a wasm build of this file's
; Zig output (bodies) and its gen-js output (constants); see "host entry points" below.
; Not claimed: no video has been rendered, and no host but t27f_view imports this file.
; phi^2 + 1/phi^2 = 3 | TRINITY

module T27fReel;
Expand Down Expand Up @@ -450,6 +452,77 @@ pub fn channel_for(host: u8) -> u8 {
return CHANNEL_FILE_PATH;
}

/// --- host entry points ---

/// A host runs the bodies above as a wasm build of the Zig backend (gHashTag/t27-mcp t27f_view).
/// A wasm export carries scalars only, so these name the demo reel instead of taking its arrays,
/// and they compose the camera with the screen mapping here, so a host only draws what they return.

/// Corner i (0..5) of a pointy-top hexagon in world units from its centre, clockwise from the top.
pub fn corner_dx(i: i32) -> i32 {
if (i == 1 or i == 2) {
return HALF_W;
}
if (i == 4 or i == 5) {
return 0 - HALF_W;
}
return 0;
}

pub fn corner_dy(i: i32) -> i32 {
if (i == 0) {
return 0 - HEX_R;
}
if (i == 3) {
return HEX_R;
}
if (i == 1 or i == 5) {
return 0 - @divTrunc(HEX_R, 2);
}
if (i == 2 or i == 4) {
return @divTrunc(HEX_R, 2);
}
return 0;
}

pub fn demo_frames() -> i32 {
return total_frames(DEMO_COUNT, DEMO_FRAMES);
}

pub fn demo_scene_at(f: i32) -> i32 {
return scene_at(DEMO_COUNT, DEMO_FRAMES, f);
}

/// The still of a demo scene, or END_OF_REEL for a scene the demo does not have.
pub fn demo_still(scene: i32) -> i32 {
if (scene < 0 or scene >= DEMO_COUNT) {
return END_OF_REEL;
}
return still_frame(DEMO_FRAMES, scene);
}

/// A world point of the demo reel on screen at base frame f.
pub fn demo_sx(f: i32, preset: u8, x: i32) -> i32 {
return screen_x(camera_cx(DEMO_COUNT, DEMO_KIND, DEMO_CELL, DEMO_FRAMES, f), camera_hw(DEMO_COUNT, DEMO_KIND, DEMO_CELL, DEMO_FRAMES, f), preset, x);
}

pub fn demo_sy(f: i32, preset: u8, y: i32) -> i32 {
return screen_y(camera_cy(DEMO_COUNT, DEMO_KIND, DEMO_CELL, DEMO_LENS, DEMO_FRAMES, f), camera_hw(DEMO_COUNT, DEMO_KIND, DEMO_CELL, DEMO_FRAMES, f), preset, y);
}

pub fn demo_r(f: i32, preset: u8) -> i32 {
return screen_r(camera_hw(DEMO_COUNT, DEMO_KIND, DEMO_CELL, DEMO_FRAMES, f), preset);
}

/// Corner i of a cell on screen: what a host draws as the cell's polygon.
pub fn demo_corner_sx(f: i32, preset: u8, cell: i32, i: i32) -> i32 {
return demo_sx(f, preset, cell_x(cell) + corner_dx(i));
}

pub fn demo_corner_sy(f: i32, preset: u8, cell: i32, i: i32) -> i32 {
return demo_sy(f, preset, cell_y(cell) + corner_dy(i));
}

/// --- tests ---

test map_geometry {
Expand Down Expand Up @@ -646,6 +719,56 @@ test stills_reach_the_user {
assert channel_for(9) == CHANNEL_FILE_PATH;
}

test hexagon_corners_close_the_cell {
// six corners, opposite corners mirror each other, and the side corners sit on the half width
// the map steps by, so neighbours share an edge
var i : i32 = 0;
while (i < 3) {
assert corner_dx(i) + corner_dx(i + 3) == 0;
assert corner_dy(i) + corner_dy(i + 3) == 0;
i = i + 1;
}
assert corner_dy(0) == 0 - HEX_R;
assert corner_dx(1) == HALF_W;
assert corner_dx(4) == 0 - HALF_W;
assert corner_dx(6) == 0 and corner_dy(6) == 0;
}

test demo_entry_points_match_the_reel {
assert demo_frames() == 360;
assert demo_scene_at(224) == 2;
assert demo_still(2) == 224;
assert demo_still(5) == END_OF_REEL;
assert demo_still(-1) == END_OF_REEL;
// the focus still is centred on step 10 at focus scale
assert demo_sx(224, PRESET_WIDE, cell_x(10)) == 640;
assert demo_sy(224, PRESET_WIDE, cell_y(10)) == 360;
assert demo_r(224, PRESET_WIDE) == screen_r(FOCUS_HW, PRESET_WIDE);
assert demo_corner_sy(224, PRESET_WIDE, 10, 0) == 360 - demo_r(224, PRESET_WIDE);
// step 10 sits in the middle row, at the overview's height; the lens still on row 0 is what
// shows the camera moving vertically
assert demo_sy(demo_still(1), PRESET_WIDE, lens_cy(0)) == 360;
}

test overview_still_fits_every_frame {
// every corner of every cell of the first still lands inside the picture on every preset
var p : u8 = 0;
while (p < PRESET_COUNT) {
var k : i32 = 0;
while (k < CELL_COUNT) {
var i : i32 = 0;
while (i < 6) {
const x : i32 = demo_corner_sx(demo_still(0), p, k, i);
const y : i32 = demo_corner_sy(demo_still(0), p, k, i);
assert x >= 0 and x <= PRESET_W[p] and y >= 0 and y <= PRESET_H[p];
i = i + 1;
}
k = k + 1;
}
p = p + 1;
}
}

invariant catalog_is_closed {
assert SCENE_KIND_COUNT == 6 and valid_kind(SCENE_CALL) and valid_kind(SCENE_KIND_COUNT) == false;
}
Expand Down
Loading