@cardstack/choreo 0.0.0 → 0.1.0-unstable.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +55 -6
- package/addon-main.cjs +4 -0
- package/declarations/anchors.d.ts +26 -0
- package/declarations/anchors.d.ts.map +1 -0
- package/declarations/arming.d.ts +33 -0
- package/declarations/arming.d.ts.map +1 -0
- package/declarations/beacon.d.ts +9 -0
- package/declarations/beacon.d.ts.map +1 -0
- package/declarations/beacons.d.ts +23 -0
- package/declarations/beacons.d.ts.map +1 -0
- package/declarations/changeset.d.ts +46 -0
- package/declarations/changeset.d.ts.map +1 -0
- package/declarations/choreo.d.ts +261 -0
- package/declarations/choreo.d.ts.map +1 -0
- package/declarations/compile.d.ts +45 -0
- package/declarations/compile.d.ts.map +1 -0
- package/declarations/deliver.d.ts +44 -0
- package/declarations/deliver.d.ts.map +1 -0
- package/declarations/easings.d.ts +20 -0
- package/declarations/easings.d.ts.map +1 -0
- package/declarations/far.d.ts +33 -0
- package/declarations/far.d.ts.map +1 -0
- package/declarations/film/clip.d.ts +51 -0
- package/declarations/film/clip.d.ts.map +1 -0
- package/declarations/film/clips.d.ts +155 -0
- package/declarations/film/clips.d.ts.map +1 -0
- package/declarations/film/film.d.ts +1208 -0
- package/declarations/film/film.d.ts.map +1 -0
- package/declarations/film/graph/adjust.d.ts +112 -0
- package/declarations/film/graph/adjust.d.ts.map +1 -0
- package/declarations/film/graph/compile.d.ts +140 -0
- package/declarations/film/graph/compile.d.ts.map +1 -0
- package/declarations/film/graph/host.d.ts +67 -0
- package/declarations/film/graph/host.d.ts.map +1 -0
- package/declarations/film/graph/nodes.d.ts +287 -0
- package/declarations/film/graph/nodes.d.ts.map +1 -0
- package/declarations/film/index.d.ts +24 -0
- package/declarations/film/index.d.ts.map +1 -0
- package/declarations/film/joins.d.ts +143 -0
- package/declarations/film/joins.d.ts.map +1 -0
- package/declarations/film/math.d.ts +15 -0
- package/declarations/film/math.d.ts.map +1 -0
- package/declarations/film/overlays.d.ts +54 -0
- package/declarations/film/overlays.d.ts.map +1 -0
- package/declarations/film/picture.d.ts +104 -0
- package/declarations/film/picture.d.ts.map +1 -0
- package/declarations/film/plate.d.ts +37 -0
- package/declarations/film/plate.d.ts.map +1 -0
- package/declarations/film/player.d.ts +120 -0
- package/declarations/film/player.d.ts.map +1 -0
- package/declarations/film/rail.d.ts +40 -0
- package/declarations/film/rail.d.ts.map +1 -0
- package/declarations/film/schedule.d.ts +93 -0
- package/declarations/film/schedule.d.ts.map +1 -0
- package/declarations/film/seam.d.ts +38 -0
- package/declarations/film/seam.d.ts.map +1 -0
- package/declarations/film/titles.d.ts +37 -0
- package/declarations/film/titles.d.ts.map +1 -0
- package/declarations/film/types.d.ts +544 -0
- package/declarations/film/types.d.ts.map +1 -0
- package/declarations/film.d.ts +3 -0
- package/declarations/film.d.ts.map +1 -0
- package/declarations/gesture.d.ts +33 -0
- package/declarations/gesture.d.ts.map +1 -0
- package/declarations/index.d.ts +26 -0
- package/declarations/index.d.ts.map +1 -0
- package/declarations/measure.d.ts +29 -0
- package/declarations/measure.d.ts.map +1 -0
- package/declarations/path.d.ts +73 -0
- package/declarations/path.d.ts.map +1 -0
- package/declarations/registry.d.ts +46 -0
- package/declarations/registry.d.ts.map +1 -0
- package/declarations/run.d.ts +406 -0
- package/declarations/run.d.ts.map +1 -0
- package/declarations/space.d.ts +31 -0
- package/declarations/space.d.ts.map +1 -0
- package/declarations/steps.d.ts +479 -0
- package/declarations/steps.d.ts.map +1 -0
- package/declarations/test-support/index.d.ts +30 -0
- package/declarations/test-support/index.d.ts.map +1 -0
- package/declarations/types.d.ts +761 -0
- package/declarations/types.d.ts.map +1 -0
- package/dist/anchors.js +34 -0
- package/dist/anchors.js.map +1 -0
- package/dist/arming.js +120 -0
- package/dist/arming.js.map +1 -0
- package/dist/beacon.js +25 -0
- package/dist/beacon.js.map +1 -0
- package/dist/beacons.js +77 -0
- package/dist/beacons.js.map +1 -0
- package/dist/changeset.js +129 -0
- package/dist/changeset.js.map +1 -0
- package/dist/choreo.js +1026 -0
- package/dist/choreo.js.map +1 -0
- package/dist/compile.js +1403 -0
- package/dist/compile.js.map +1 -0
- package/dist/deliver.js +326 -0
- package/dist/deliver.js.map +1 -0
- package/dist/easings.js +39 -0
- package/dist/easings.js.map +1 -0
- package/dist/far.js +147 -0
- package/dist/far.js.map +1 -0
- package/dist/film/clip.js +100 -0
- package/dist/film/clip.js.map +1 -0
- package/dist/film/clips.js +147 -0
- package/dist/film/clips.js.map +1 -0
- package/dist/film/film.js +4424 -0
- package/dist/film/film.js.map +1 -0
- package/dist/film/graph/adjust.js +160 -0
- package/dist/film/graph/adjust.js.map +1 -0
- package/dist/film/graph/compile.js +225 -0
- package/dist/film/graph/compile.js.map +1 -0
- package/dist/film/graph/host.js +77 -0
- package/dist/film/graph/host.js.map +1 -0
- package/dist/film/graph/nodes.js +500 -0
- package/dist/film/graph/nodes.js.map +1 -0
- package/dist/film/index.js +18 -0
- package/dist/film/index.js.map +1 -0
- package/dist/film/joins.js +260 -0
- package/dist/film/joins.js.map +1 -0
- package/dist/film/math.js +49 -0
- package/dist/film/math.js.map +1 -0
- package/dist/film/overlays.js +66 -0
- package/dist/film/overlays.js.map +1 -0
- package/dist/film/picture.js +58 -0
- package/dist/film/picture.js.map +1 -0
- package/dist/film/plate.js +36 -0
- package/dist/film/plate.js.map +1 -0
- package/dist/film/player.js +79 -0
- package/dist/film/player.js.map +1 -0
- package/dist/film/rail.js +38 -0
- package/dist/film/rail.js.map +1 -0
- package/dist/film/schedule.js +238 -0
- package/dist/film/schedule.js.map +1 -0
- package/dist/film/seam.js +64 -0
- package/dist/film/seam.js.map +1 -0
- package/dist/film/titles.js +45 -0
- package/dist/film/titles.js.map +1 -0
- package/dist/film/types.js +2 -0
- package/dist/film/types.js.map +1 -0
- package/dist/film.js +18 -0
- package/dist/film.js.map +1 -0
- package/dist/gesture.js +111 -0
- package/dist/gesture.js.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/measure.js +99 -0
- package/dist/measure.js.map +1 -0
- package/dist/path.js +272 -0
- package/dist/path.js.map +1 -0
- package/dist/registry.js +55 -0
- package/dist/registry.js.map +1 -0
- package/dist/run.js +2423 -0
- package/dist/run.js.map +1 -0
- package/dist/space.js +57 -0
- package/dist/space.js.map +1 -0
- package/dist/steps.js +831 -0
- package/dist/steps.js.map +1 -0
- package/dist/test-support/index.js +150 -0
- package/dist/test-support/index.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +202 -6
|
@@ -0,0 +1,1208 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { type FilmVocabulary } from './graph/host';
|
|
3
|
+
import type { PictureSpec } from './picture';
|
|
4
|
+
import { type RailMark } from './rail';
|
|
5
|
+
import { TICK } from './schedule.ts';
|
|
6
|
+
import type { Beat, Chapter, FilmClock, FilmHandle, Join, Over, Picture } from './types.ts';
|
|
7
|
+
/**
|
|
8
|
+
* `<Film>` — a headless cutting room, in which a 3D scene takes the place
|
|
9
|
+
* of the video track.
|
|
10
|
+
*
|
|
11
|
+
* The model is an editor: one clock, a shot list dropped onto it, and
|
|
12
|
+
* components that read the clock — the lens, the joins, the type, the
|
|
13
|
+
* voice, the timeline. The film is a pure function of that clock, which
|
|
14
|
+
* is why a beat can be widened and the type, the voice, the transport
|
|
15
|
+
* and the readout all re-time together. The picture is whatever the film
|
|
16
|
+
* hands in through the `Picture` port; two reference films hand in a
|
|
17
|
+
* WebGL page in an iframe (notes/film-construct.md).
|
|
18
|
+
*
|
|
19
|
+
* THE CAMERA. The score authors the shot and the lens CHASES it: one
|
|
20
|
+
* critically-damped stage here, the page's own chase as the second, so
|
|
21
|
+
* two integrators in series bound the jerk. That is what gives the films
|
|
22
|
+
* their hand-held quality, and it is exactly what forfeits seeking — so
|
|
23
|
+
* a skip here is an edit, never a seek: the score is re-cut from a
|
|
24
|
+
* chapter's head and replays.
|
|
25
|
+
*
|
|
26
|
+
* WHAT THE POSE ARGS MEAN (an orbit rig):
|
|
27
|
+
* yaw → the orbit's azimuth, degrees
|
|
28
|
+
* pitch → elevation, degrees
|
|
29
|
+
* dolly → magnification: 1 fits the subject, bigger is tighter
|
|
30
|
+
* lookY → how far up the subject the lens aims, from the rig's mid-height
|
|
31
|
+
* fx, fz → where on the ground the lens aims
|
|
32
|
+
* ox → an off-centre frustum, fractions of the frame
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* ONE TICK IS TWO SECONDS, and every beat is a whole number of them.
|
|
36
|
+
* `@through` splits its clock evenly between waypoints, so a beat buys
|
|
37
|
+
* the screen time it wants by contributing that many waypoints to the
|
|
38
|
+
* path — and a beat that wants to HOLD contributes the same pose several
|
|
39
|
+
* times over, which a Catmull-Rom spline comes smoothly to rest on.
|
|
40
|
+
*/
|
|
41
|
+
export { TICK };
|
|
42
|
+
export interface FilmSignature {
|
|
43
|
+
Args: {
|
|
44
|
+
/** which cut of the film this is: logged at boot, shown under `?debug` */
|
|
45
|
+
build?: string;
|
|
46
|
+
/** the film's own clock, when the picture keeps one (years) */
|
|
47
|
+
clock?: FilmClock;
|
|
48
|
+
/** mounted in a page's iframe: the door still opens it, but no transport and no plate */
|
|
49
|
+
embed?: boolean;
|
|
50
|
+
/** the seam a beat gets when it names none */
|
|
51
|
+
join?: Join;
|
|
52
|
+
/** the chapter menu's second line */
|
|
53
|
+
menuSub?: string;
|
|
54
|
+
/** the film's name, as the menu heads it */
|
|
55
|
+
menuTitle: string;
|
|
56
|
+
/** a short name for the film (a body class, the boot log) */
|
|
57
|
+
name: string;
|
|
58
|
+
/** the air of a shot has been applied: grade, sun, weather — a hook for what the construct does not know */
|
|
59
|
+
onAir?: (beat: Beat, picture: Picture, hard: boolean) => void;
|
|
60
|
+
/** a beat has landed — a hook for what the construct does not know */
|
|
61
|
+
onBeat?: (beat: Beat, picture: Picture) => void;
|
|
62
|
+
/**
|
|
63
|
+
* HOW DEEP THE FILM'S SEAMS GO, when a beat does not say. `picture`
|
|
64
|
+
* (the default) transitions the picture and makes the incoming type
|
|
65
|
+
* wait for the seam; `everything` puts the seam above the type, the
|
|
66
|
+
* insert and the clip, so the incoming setting is already under way
|
|
67
|
+
* when the sweep reveals it. See `Over`.
|
|
68
|
+
*/
|
|
69
|
+
over?: Over;
|
|
70
|
+
/**
|
|
71
|
+
* THE RAIL — the film on one line, on the picture: chapters as dots
|
|
72
|
+
* on a rule, the head riding it, the year when the rule is a clock.
|
|
73
|
+
* It is the second film's transport and not every film's: a film
|
|
74
|
+
* whose own bar is the whole story of its progress says `false` and
|
|
75
|
+
* keeps the floating player alone.
|
|
76
|
+
*/
|
|
77
|
+
rail?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* HOW THE FILM SEEKS — the fork everything hangs on.
|
|
80
|
+
*
|
|
81
|
+
* `cut` (the default) is the hand-held film: a cascaded spring chases
|
|
82
|
+
* the score, which is what gives the lens its sway and its arrival at
|
|
83
|
+
* pace, and exactly what forfeits random access — a spring's state is
|
|
84
|
+
* its history, so a skip re-cuts the score from a chapter's head.
|
|
85
|
+
*
|
|
86
|
+
* `exact` makes the whole film a pure function of one clock: no
|
|
87
|
+
* integrator in the pose path, the beat in force derived from the
|
|
88
|
+
* time, the seams driven by it, the type's run seeked to it. Scrub
|
|
89
|
+
* anywhere and the frame is correct; `renderAt(t)` on a fresh page is
|
|
90
|
+
* the same frame as playing there. It used to cost the hand — the
|
|
91
|
+
* spring was the only thing softening the spline, and an exact film
|
|
92
|
+
* could not have one. `@settle` is that hand written as a function of
|
|
93
|
+
* the clock, so it no longer does.
|
|
94
|
+
*
|
|
95
|
+
* What `exact` still costs is a read-back per cut: every seam holds a
|
|
96
|
+
* still of the outgoing frame, because the page's own dissolves run
|
|
97
|
+
* on their own clock.
|
|
98
|
+
*/
|
|
99
|
+
seek?: 'cut' | 'exact';
|
|
100
|
+
/**
|
|
101
|
+
* THE OPERATOR'S SECOND HAND, in seconds.
|
|
102
|
+
*
|
|
103
|
+
* The camera path is a spline through every shot's pose, and a spline
|
|
104
|
+
* crosses its control points with a step in curvature — a tick, on
|
|
105
|
+
* every waypoint, for the whole running time. A spring chasing the
|
|
106
|
+
* pose hides it and cannot be seeked; this is an average of the path
|
|
107
|
+
* over a window this wide, which is the same cure written as a pure
|
|
108
|
+
* function of the clock (`settleThrough`). Zero turns it off.
|
|
109
|
+
*
|
|
110
|
+
* Keep it well under the gap between waypoints — a film that holds a
|
|
111
|
+
* pose for two seconds wants a fraction of a second here, not two —
|
|
112
|
+
* or the lens stops visiting the poses the score wrote.
|
|
113
|
+
*/
|
|
114
|
+
settle?: number;
|
|
115
|
+
/** the level each line was mixed to (0..1) */
|
|
116
|
+
voGain?: Record<string, number>;
|
|
117
|
+
};
|
|
118
|
+
Blocks: {
|
|
119
|
+
/** under the stage, outside the picture: a wall plate, a cutting room */
|
|
120
|
+
default: [FilmContext];
|
|
121
|
+
/** the back matter, inside the end card */
|
|
122
|
+
end: [FilmHandle];
|
|
123
|
+
/** the front matter, on the door */
|
|
124
|
+
gate: [FilmHandle];
|
|
125
|
+
/** the picture: a component that registers what it is (`IframePicture`), and declares `f.picture.*` */
|
|
126
|
+
picture: [(spec: PictureSpec | null) => void];
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** what the blocks are given: the handle, and the vocabulary a film's score is written in */
|
|
130
|
+
export type FilmContext = FilmHandle & FilmVocabulary;
|
|
131
|
+
export declare class Film extends Component<FilmSignature> {
|
|
132
|
+
/**
|
|
133
|
+
* THE GRAPH, compiled. A film written as `f.Spine` / `f.Chapter` /
|
|
134
|
+
* `f.Shot` in the default block compiles to the same rows a table would
|
|
135
|
+
* hand in (`graph/compile.ts`); the table arguments, when given, win.
|
|
136
|
+
*/
|
|
137
|
+
private graph;
|
|
138
|
+
private takeGraph;
|
|
139
|
+
/**
|
|
140
|
+
* THE PICTURE, as it registered itself from the `<:picture>` block: the
|
|
141
|
+
* page, its files, how it is seated, its rig, its moods. Nothing here
|
|
142
|
+
* is about the edit, which is why none of it is an argument any more.
|
|
143
|
+
*/
|
|
144
|
+
private picture;
|
|
145
|
+
private takePicture;
|
|
146
|
+
private get assets();
|
|
147
|
+
private get standing();
|
|
148
|
+
private get frameTitle();
|
|
149
|
+
/**
|
|
150
|
+
* THE WHOLE SHOT LIST, and there is only one place it comes from: the
|
|
151
|
+
* score in the default block, compiled. The film used to take a
|
|
152
|
+
* `Beat[]` as an argument as well, which is how both films were fed
|
|
153
|
+
* until Phase 2 migrated them; the table path is gone now that nothing
|
|
154
|
+
* hands one in, and the graph is the only way to write a film.
|
|
155
|
+
*/
|
|
156
|
+
private get all();
|
|
157
|
+
private get chapters();
|
|
158
|
+
private get voSecs();
|
|
159
|
+
private get voGain();
|
|
160
|
+
private get grades();
|
|
161
|
+
private get lookFx();
|
|
162
|
+
private get lutAmount();
|
|
163
|
+
private get defaultJoin();
|
|
164
|
+
/**
|
|
165
|
+
* WHERE THIS SEAM IS PLAYED. A seam the PICTURE declares by name is
|
|
166
|
+
* played in its glass with that name; the three the film knows how to
|
|
167
|
+
* mix are played there under the film's own law; everything else is an
|
|
168
|
+
* overlay in this document. The name is the only thing that decides,
|
|
169
|
+
* which is what makes the vocabulary open: a picture that declares
|
|
170
|
+
* `ridged-burn` gets `<f.Join @presentation="ridged-burn" />` for free,
|
|
171
|
+
* and the film learns nothing about it but its length.
|
|
172
|
+
*/
|
|
173
|
+
private glassFor;
|
|
174
|
+
/** how deep a seam goes when nothing says: the film's own default */
|
|
175
|
+
private get defaultOver();
|
|
176
|
+
/**
|
|
177
|
+
* HOW DEEP THIS BEAT'S SEAM GOES. The row says, or the presentation
|
|
178
|
+
* says, or the film does. A seam that covers the furniture is always a
|
|
179
|
+
* seam with a still in the DOM: the picture's own glass is inside the
|
|
180
|
+
* canvas and cannot cover anything outside it.
|
|
181
|
+
*/
|
|
182
|
+
private overOf;
|
|
183
|
+
/** every seam the film can play: its own twelve, and any the score brought */
|
|
184
|
+
private get presentations();
|
|
185
|
+
/** seconds a seam holds the picture; nothing, for one the film does not know */
|
|
186
|
+
private secsOf;
|
|
187
|
+
/** does the seam paint a still of the outgoing frame over the incoming one */
|
|
188
|
+
private holdsStill;
|
|
189
|
+
/** how much of a frosted city a film frame can carry */
|
|
190
|
+
private get cityGlass();
|
|
191
|
+
/** the rig's mid-height: `lookY` is world height minus this */
|
|
192
|
+
private get rigMid();
|
|
193
|
+
/** how much the passing cloud thickens the air */
|
|
194
|
+
private get cloudHaze();
|
|
195
|
+
/** the face type in the world is set in; a film that names none of it
|
|
196
|
+
* leaves the page's own */
|
|
197
|
+
private get worldFamily();
|
|
198
|
+
private get worldWeight();
|
|
199
|
+
private get worldTrack();
|
|
200
|
+
/** the editorial accent: the film's own, or the scene's palette by day */
|
|
201
|
+
private accentFor;
|
|
202
|
+
/** the film's handles, as the door and the card are given them */
|
|
203
|
+
get handle(): FilmContext;
|
|
204
|
+
private get exact();
|
|
205
|
+
/** the master clock: seconds into the whole film (exact mode) */
|
|
206
|
+
private t;
|
|
207
|
+
/** a seek happened since the last fold: it lands instantly, seam re-made */
|
|
208
|
+
private jumped;
|
|
209
|
+
/** the score region's context, read every frame for its current run */
|
|
210
|
+
private scoreCtx;
|
|
211
|
+
private scoreRun;
|
|
212
|
+
/** the element the seam overlays live in, so their animations can be seeked */
|
|
213
|
+
private joinsEl?;
|
|
214
|
+
/** where the seam on screen began, film seconds, and how long it plays */
|
|
215
|
+
private seamAt;
|
|
216
|
+
private seamLen;
|
|
217
|
+
/** the lead whose air has been applied ahead of its beat */
|
|
218
|
+
private airedFor;
|
|
219
|
+
/** where the sun was before this beat asked, for a deterministic walk */
|
|
220
|
+
private sunFrom;
|
|
221
|
+
/**
|
|
222
|
+
* THE CLIPS ON SCREEN, one row per lane, in lane order — which is also
|
|
223
|
+
* paint order. There used to be one of these and a beat that declared
|
|
224
|
+
* two clips kept the second one only.
|
|
225
|
+
*/
|
|
226
|
+
private clipRows;
|
|
227
|
+
/** the picture read back, per lane, for a freeze */
|
|
228
|
+
private clipFreezes;
|
|
229
|
+
private clipNow;
|
|
230
|
+
private clipMedia;
|
|
231
|
+
private clipEl;
|
|
232
|
+
/**
|
|
233
|
+
* THE CLIP, EVERY FRAME. Resolve what should be on screen at this film
|
|
234
|
+
* time, land the DOM when that changes (a new window is a new element,
|
|
235
|
+
* so the entrance replays), and drive the media: a playing video is
|
|
236
|
+
* left to run and corrected when it drifts, a paused or scrubbed one
|
|
237
|
+
* is seeked, a held one stands at its out point, a frozen one is left
|
|
238
|
+
* alone. A freeze reads the picture back when its window opens — or,
|
|
239
|
+
* on a seek into it, after the page has been stood at that moment.
|
|
240
|
+
*/
|
|
241
|
+
private clips;
|
|
242
|
+
/**
|
|
243
|
+
* ONE LANE'S MEDIA, every frame. A playing video is left to run and
|
|
244
|
+
* corrected when it drifts, a paused or scrubbed one is seeked, a held
|
|
245
|
+
* one stands at its out point, a frozen one is left alone.
|
|
246
|
+
*
|
|
247
|
+
* A CLIP'S SOUND NEVER STEPS. The element arrives at zero and is eased
|
|
248
|
+
* up to its level, and when its window closes it is eased back down
|
|
249
|
+
* before the exit fade takes the element away — a source that starts or
|
|
250
|
+
* stops at level is a click, whatever it is playing.
|
|
251
|
+
*/
|
|
252
|
+
private driveClip;
|
|
253
|
+
/**
|
|
254
|
+
* THE PICTURE AT A MOMENT THAT HAS PASSED. A freeze seeked into needs
|
|
255
|
+
* the frame from its window's head: the score is stood there for one
|
|
256
|
+
* evaluation (the camera step reports the pose), the page is posed and
|
|
257
|
+
* clocked to that moment, and the fold's own time is restored after
|
|
258
|
+
* the read-back.
|
|
259
|
+
*/
|
|
260
|
+
private freezeClipAt;
|
|
261
|
+
/**
|
|
262
|
+
* FILM SECONDS AT WHICH A BEAT'S OWN SHOT BEGINS. The cues fire one
|
|
263
|
+
* tick after the beat table says, because the pose-in-force seed
|
|
264
|
+
* occupies the spline's first slot — so the windows the exact clock
|
|
265
|
+
* derives carry the same offset, and the picture and the type agree
|
|
266
|
+
* with the cut film to the frame.
|
|
267
|
+
*/
|
|
268
|
+
private beatStart;
|
|
269
|
+
/** the beat in force at a film time */
|
|
270
|
+
private indexAt;
|
|
271
|
+
/** the score's region, held so its run can be driven by the clock */
|
|
272
|
+
private grabScore;
|
|
273
|
+
private joinsWrap;
|
|
274
|
+
/** the score must stand even while paused: a paused exact film is a still */
|
|
275
|
+
get scoreOn(): boolean;
|
|
276
|
+
/**
|
|
277
|
+
* SEEK. In exact mode the clock is set and the next fold lands there;
|
|
278
|
+
* in cut mode the nearest shot's head is re-cut to, which is the only
|
|
279
|
+
* honest seek a chased lens has.
|
|
280
|
+
*/
|
|
281
|
+
private seek;
|
|
282
|
+
/**
|
|
283
|
+
* A STILL AT A TIME, for a capture worker: pause, seek, run one frame
|
|
284
|
+
* of the loop against a zero step, and give the page two frames to
|
|
285
|
+
* draw it. The same code path as playing there — that is the claim.
|
|
286
|
+
*/
|
|
287
|
+
/** a frame is being rendered rather than scrubbed to: seams play */
|
|
288
|
+
private rendering;
|
|
289
|
+
/**
|
|
290
|
+
* A RENDER OPENS THE DOOR ITSELF.
|
|
291
|
+
*
|
|
292
|
+
* `?from=0` puts the title card up and leaves the film unbooted — and
|
|
293
|
+
* an unbooted film HAS NO SCORE, because the whole `<Choreo>` sits
|
|
294
|
+
* behind `{{#if this.booted}}` (the rig has to be an insertion before
|
|
295
|
+
* the camera step has a subject). So `fold`'s `run.time = t` wrote to
|
|
296
|
+
* a null run, `onCamera3D` never fired, `goal` stayed wherever the
|
|
297
|
+
* load path's `snap` seated it, and exact mode copied that one pose
|
|
298
|
+
* forward on every frame. Measured on towers, a stepped render swept
|
|
299
|
+
* half a degree of yaw across 273 seconds where the compiled path
|
|
300
|
+
* sweeps 380 — a whole render of a frozen lens, and `film-render.mjs`
|
|
301
|
+
* hit it every time, because its default `--from` is 0.
|
|
302
|
+
*
|
|
303
|
+
* A render is a request for the film, not for the lobby. So it opens
|
|
304
|
+
* the door itself, MUTED — nothing was clicked, and no browser hands
|
|
305
|
+
* out audio for a gesture nobody made.
|
|
306
|
+
*/
|
|
307
|
+
private renderAt;
|
|
308
|
+
/**
|
|
309
|
+
* THE DOOR, OPENED BY A SCRIPT. Two waits, and neither is optional.
|
|
310
|
+
*
|
|
311
|
+
* The handle publishes itself from the mount modifier, a frame before
|
|
312
|
+
* the iframe's load seats the port — so a renderer that polls for
|
|
313
|
+
* `__choreo[name]` can call in before there is a picture to begin
|
|
314
|
+
* against, and `begin` would only pocket the choice. And `begin`
|
|
315
|
+
* itself DEFERS the lap bump that buys the score region its second
|
|
316
|
+
* render pass: until that pass lands the run does not exist, and a
|
|
317
|
+
* seek against a missing run is exactly the frozen lens this avoids.
|
|
318
|
+
*
|
|
319
|
+
* Both waits are bounded. A render against a film that never arrives
|
|
320
|
+
* degrades to the frame it would have drawn before, rather than
|
|
321
|
+
* hanging the worker on a promise that will not settle.
|
|
322
|
+
*/
|
|
323
|
+
private openTheDoor;
|
|
324
|
+
/**
|
|
325
|
+
* THE FOLD (exact mode): the beat in force is the one whose window
|
|
326
|
+
* holds the clock; entering it — forward by playing, or by a seek in
|
|
327
|
+
* either direction — applies it whole, because every beat asserts its
|
|
328
|
+
* complete state and never inherits. A seek that lands inside a seam
|
|
329
|
+
* re-makes the outgoing frame first, so the seam plays from the middle
|
|
330
|
+
* exactly as it would have played into it.
|
|
331
|
+
*/
|
|
332
|
+
private fold;
|
|
333
|
+
/** a line, from the middle: what a seek owes the voice */
|
|
334
|
+
private speakAt;
|
|
335
|
+
/**
|
|
336
|
+
* THE SEAM'S GATE (`film/seam.ts`). A join's still is a JPEG the
|
|
337
|
+
* browser has not decoded yet on the frame it is handed over, and the
|
|
338
|
+
* lens moves on that frame — so every cut used to show three frames of
|
|
339
|
+
* the incoming shot before the outgoing one was on screen. The gate
|
|
340
|
+
* decodes first and holds the cut; a seam with no still runs at once.
|
|
341
|
+
*/
|
|
342
|
+
private seam;
|
|
343
|
+
/**
|
|
344
|
+
* THE SEAM, EXACT. Every join that carries the outgoing frame carries it
|
|
345
|
+
* as a still in the DOM — the page's own dissolves run on the page's
|
|
346
|
+
* clock and cannot be stood at a time — and the whip, which is the
|
|
347
|
+
* chaser's, becomes a cut. The overlay is then driven by the fold.
|
|
348
|
+
*/
|
|
349
|
+
private seamExact;
|
|
350
|
+
/** the seam itself: the still on screen, the lens on the incoming shot */
|
|
351
|
+
private seamPlay;
|
|
352
|
+
/** the last cue has run: hold the pose, settle the music, offer the card */
|
|
353
|
+
private end;
|
|
354
|
+
/** the beat on screen; the score names it, the front layer renders it */
|
|
355
|
+
private beatIndex;
|
|
356
|
+
private playing;
|
|
357
|
+
/** bumping this edits the score, which is how a finite film loops */
|
|
358
|
+
private lap;
|
|
359
|
+
private booted;
|
|
360
|
+
/** which seam is playing, and a key that replays it: bumped on every cut */
|
|
361
|
+
private joinKind;
|
|
362
|
+
private joinStamp;
|
|
363
|
+
/** the seam on screen covers the furniture, not only the picture */
|
|
364
|
+
private joinOver;
|
|
365
|
+
private overTimer;
|
|
366
|
+
/**
|
|
367
|
+
* THE SEAM IN THE GLASS. Its kind, how long it has and the colour it
|
|
368
|
+
* passes through — and `reveal`, how much of the incoming frame is NOT
|
|
369
|
+
* covered by it, which is the film's other half: the type, the stamp
|
|
370
|
+
* and the inserts wear it, so a caption is uncovered by the same
|
|
371
|
+
* gesture that uncovers the picture.
|
|
372
|
+
*/
|
|
373
|
+
private glassKind;
|
|
374
|
+
/** the picture's own name for it, when the picture declared this seam */
|
|
375
|
+
private glassName;
|
|
376
|
+
private glassLen;
|
|
377
|
+
private glassColor;
|
|
378
|
+
private reveal;
|
|
379
|
+
/** the captured outgoing frame every freeze-based join plays with */
|
|
380
|
+
private freeze;
|
|
381
|
+
/** the 'dip' join's veil colour */
|
|
382
|
+
private dipColor;
|
|
383
|
+
/** where the iris closes to, as inline custom properties */
|
|
384
|
+
private irisAt;
|
|
385
|
+
/** dev beacon: the first uncaught error, worn on the sleeve */
|
|
386
|
+
private fault;
|
|
387
|
+
/**
|
|
388
|
+
* THE SEAM, DRIVEN. Half of it is the picture, which is handed two
|
|
389
|
+
* numbers and composites them in light; half is the furniture, which
|
|
390
|
+
* wears what is left over. Both come from one progress, and that
|
|
391
|
+
* progress is a function of the clock — so a seek through a seam needs
|
|
392
|
+
* nothing stood at a time, which is what the DOM overlay always did.
|
|
393
|
+
*/
|
|
394
|
+
/** take a driven seam off: the picture back to live, the furniture whole */
|
|
395
|
+
private endSeam;
|
|
396
|
+
private driveSeam;
|
|
397
|
+
/**
|
|
398
|
+
* Run a seam's overlay: a new element per cut, from its own first
|
|
399
|
+
* frame. A seam played `everything` is lifted above the type, the
|
|
400
|
+
* insert and the clip for as long as it runs, and put back after — an
|
|
401
|
+
* empty layer left standing over the furniture would swallow the next
|
|
402
|
+
* shot's pointer events, and there is no event for a CSS animation the
|
|
403
|
+
* film did not start.
|
|
404
|
+
*/
|
|
405
|
+
private play;
|
|
406
|
+
/**
|
|
407
|
+
* THE ENDING. A film that laps back to its own first frame has no
|
|
408
|
+
* ending, and the coda earns one — so when the last cue has run, the
|
|
409
|
+
* run simply stops: the final pose holds, the music settles down a
|
|
410
|
+
* step, and a card offers the way back in. Replay is a choice the
|
|
411
|
+
* viewer makes, never something the clock does to them.
|
|
412
|
+
*/
|
|
413
|
+
private ended;
|
|
414
|
+
/**
|
|
415
|
+
* THE YEAR IS THE SUBJECT. A film whose whole argument is that one
|
|
416
|
+
* building took a hundred and forty-four years cannot leave the audience
|
|
417
|
+
* to infer the date from the state of the scaffolding: the year is on
|
|
418
|
+
* screen, and it is on a line from the first stone to the present, so
|
|
419
|
+
* 1954 is not a number but a POSITION — two thirds along a rule that
|
|
420
|
+
* still has a third to run.
|
|
421
|
+
*/
|
|
422
|
+
private yearNow;
|
|
423
|
+
private yearSent;
|
|
424
|
+
/** whether the announced year is currently seated in the scene */
|
|
425
|
+
private stampOn;
|
|
426
|
+
/** the page has been told the picture is static — see the frame loop */
|
|
427
|
+
private idled;
|
|
428
|
+
private gradeSent;
|
|
429
|
+
private rakeSent;
|
|
430
|
+
private rakeDeg;
|
|
431
|
+
/** which beat's lightning cue has fired (reset on every beat change) */
|
|
432
|
+
private struck;
|
|
433
|
+
/** which of the beat's hours (Beat.hours) is in force; -1 between beats */
|
|
434
|
+
private hourStep;
|
|
435
|
+
/** the next grade goes to the glass without its ease (a still-join) */
|
|
436
|
+
private gradeSnap;
|
|
437
|
+
/** the last stock sent to the glass, by name; undefined before the first */
|
|
438
|
+
private lutSent;
|
|
439
|
+
/** the last hour a beat named, so the night can be known without naming it again */
|
|
440
|
+
private hourNow;
|
|
441
|
+
/** the scrub track's width in px, kept by a ResizeObserver */
|
|
442
|
+
private trackW;
|
|
443
|
+
private trackRO?;
|
|
444
|
+
/** the chapter fractions the bar is drawn with, computed once */
|
|
445
|
+
private segFr?;
|
|
446
|
+
private trackWrap;
|
|
447
|
+
/**
|
|
448
|
+
* THE KNOB IS THE FILL'S END. The bar is chapters with a gap between
|
|
449
|
+
* them, so the playhead's position is not linear in the playhead's
|
|
450
|
+
* value — a second formula for the knob drifts from the fill inside
|
|
451
|
+
* every segment. This is the one formula: the same fractions the fill
|
|
452
|
+
* uses, over the measured track, with the gaps added back.
|
|
453
|
+
*/
|
|
454
|
+
private headPx;
|
|
455
|
+
/** which tower the lineup's metronome is on; -1 between lineups */
|
|
456
|
+
private cycleStep;
|
|
457
|
+
private film?;
|
|
458
|
+
/**
|
|
459
|
+
* THE FRAME'S DRESSING, WHERE THE PICTURE CAN TAKE IT.
|
|
460
|
+
*
|
|
461
|
+
* The wash and the cloud were CSS layers over the canvas, which meant a
|
|
462
|
+
* seam could not touch them: the picture dissolved and the paper behind
|
|
463
|
+
* the type snapped on the cut frame — two edits at once. A transition
|
|
464
|
+
* applies to what its own container renders, so they belong in the
|
|
465
|
+
* container, and the container is the picture's post pass (where the
|
|
466
|
+
* vignette, the grain, the split tone and the grade already live). A
|
|
467
|
+
* picture that offers `wash`/`cloud` gets them and the film stops
|
|
468
|
+
* drawing its own; one that does not keeps the CSS layers.
|
|
469
|
+
*/
|
|
470
|
+
private washInGlass;
|
|
471
|
+
private cloudInGlass;
|
|
472
|
+
private dimInGlass;
|
|
473
|
+
/** the palette's paper, as `wear` last read it, for the wash */
|
|
474
|
+
private paperNow;
|
|
475
|
+
/** the last wash the picture was told about: mode and paper, told on change */
|
|
476
|
+
private washSent;
|
|
477
|
+
private frameEl?;
|
|
478
|
+
private lineEl?;
|
|
479
|
+
private dotEl?;
|
|
480
|
+
private tetherEl?;
|
|
481
|
+
private dim?;
|
|
482
|
+
/** the dim's own value, chased rather than cut so it never snaps on */
|
|
483
|
+
private dimNow;
|
|
484
|
+
private plateEl?;
|
|
485
|
+
private rowEls;
|
|
486
|
+
private raf;
|
|
487
|
+
private lastTick;
|
|
488
|
+
/** when the current beat was entered, for the clocks it owns */
|
|
489
|
+
private beatAt;
|
|
490
|
+
/** where the beat's sky word was planted, in world azimuth */
|
|
491
|
+
private skyAz;
|
|
492
|
+
/** the azimuth the mark word is planted on, behind the building */
|
|
493
|
+
private markAz;
|
|
494
|
+
/** a sideways nudge in world units, for a word too short to centre */
|
|
495
|
+
private markOff;
|
|
496
|
+
/** the height the word rises FROM — set when it actually arrives */
|
|
497
|
+
private markFrom;
|
|
498
|
+
private markSeated;
|
|
499
|
+
/** the last pose actually pushed — the final smoothing stage */
|
|
500
|
+
private sent?;
|
|
501
|
+
/** the light in force, and the light the beat asked for */
|
|
502
|
+
private sunNow;
|
|
503
|
+
private sunGoal;
|
|
504
|
+
private idle;
|
|
505
|
+
/** the fraction the hand is holding while scrubbing, else null */
|
|
506
|
+
private scrubAt;
|
|
507
|
+
/** the fraction under a resting pointer on the bar, else null */
|
|
508
|
+
private hoverAt;
|
|
509
|
+
/** the master fader, 0..1, remembered across visits */
|
|
510
|
+
private vol;
|
|
511
|
+
/** the centre-screen glyph that confirms a play or a pause */
|
|
512
|
+
private burst;
|
|
513
|
+
/** the viewer's pause: the run, the page and the beat clock all hold */
|
|
514
|
+
private paused;
|
|
515
|
+
private pausedAt;
|
|
516
|
+
/** the lap whose head beat the cut itself already applied */
|
|
517
|
+
private primedLap;
|
|
518
|
+
/** the bar's own element, for the slider's live value */
|
|
519
|
+
private scrubEl?;
|
|
520
|
+
private shownPct;
|
|
521
|
+
private clock;
|
|
522
|
+
private full;
|
|
523
|
+
private idleTimer;
|
|
524
|
+
private shownSec;
|
|
525
|
+
/** the whole film, in seconds, leads included */
|
|
526
|
+
private get totalSecs();
|
|
527
|
+
private secsBefore;
|
|
528
|
+
/** one segment per chapter, sized and placed in whole-film fractions */
|
|
529
|
+
get playbar(): {
|
|
530
|
+
head: number;
|
|
531
|
+
n: string;
|
|
532
|
+
style: string;
|
|
533
|
+
title: string;
|
|
534
|
+
}[];
|
|
535
|
+
private static mmss;
|
|
536
|
+
get duration(): string;
|
|
537
|
+
/**
|
|
538
|
+
* What the hand is pointing at — resting on the bar or dragging it:
|
|
539
|
+
* the chapter under it and the time, on two lines, the way every
|
|
540
|
+
* player's hover bubble does. A drag wins over a hover.
|
|
541
|
+
*/
|
|
542
|
+
get tip(): {
|
|
543
|
+
ch: string;
|
|
544
|
+
t: string;
|
|
545
|
+
} | null;
|
|
546
|
+
/** rolling AND not held by the viewer: what the play button shows */
|
|
547
|
+
get live(): boolean;
|
|
548
|
+
/** the fader's setting, as it was left last time — one setting for
|
|
549
|
+
* every film, the way a viewer's volume is theirs and not the film's */
|
|
550
|
+
private static savedVol;
|
|
551
|
+
/** sound on, and the fader up: the speaker glyph's three states */
|
|
552
|
+
get loud(): 'high' | 'low' | 'off';
|
|
553
|
+
get volStyle(): string;
|
|
554
|
+
/**
|
|
555
|
+
* THE FADER. Dragging it up while muted unmutes, because that is what
|
|
556
|
+
* the hand means; the value is the page's master gain, under the mix
|
|
557
|
+
* and the mute, and it is remembered for the next visit.
|
|
558
|
+
*/
|
|
559
|
+
private fade;
|
|
560
|
+
/** the glyph that flashes in the middle of the picture on play/pause */
|
|
561
|
+
private pop;
|
|
562
|
+
private burstDone;
|
|
563
|
+
/**
|
|
564
|
+
* A tap on the picture is play/pause and two taps are full screen —
|
|
565
|
+
* the grammar of every player since the first one. The controls, the
|
|
566
|
+
* door, the end card, the rail and the menu keep their own clicks.
|
|
567
|
+
*/
|
|
568
|
+
private static onGlass;
|
|
569
|
+
private tap;
|
|
570
|
+
private tapTwice;
|
|
571
|
+
/** the bar's own element, for the slider's live value */
|
|
572
|
+
private slider;
|
|
573
|
+
private wake;
|
|
574
|
+
private scrubFrom;
|
|
575
|
+
/**
|
|
576
|
+
* The bubble and the ghost fill follow the pointer, not the playhead:
|
|
577
|
+
* the bubble's x in pixels (held off the edges so it never clips) and
|
|
578
|
+
* the hover fraction, both as properties, both without a re-render.
|
|
579
|
+
*/
|
|
580
|
+
private point;
|
|
581
|
+
private scrubDown;
|
|
582
|
+
private scrubMove;
|
|
583
|
+
private scrubLeave;
|
|
584
|
+
/**
|
|
585
|
+
* THE PLAYHEAD SNAPS TO A SHOT, because this film cannot seek: the
|
|
586
|
+
* lens is an integrator and a run dropped into its own middle arrives
|
|
587
|
+
* with the wrong velocity (docs/choreo-splices.md). So the drag reads
|
|
588
|
+
* as time, the label names the shot under the hand, and the release
|
|
589
|
+
* RE-CUTS from that shot's head — which is the same edit the chapter
|
|
590
|
+
* buttons and the arrow keys make.
|
|
591
|
+
*/
|
|
592
|
+
/**
|
|
593
|
+
* A HAND ON THE BAR NEVER LANDS ON THE CARD. The bar's right edge is
|
|
594
|
+
* the film's last second, and a click there — or a drag that ran off
|
|
595
|
+
* the end — seeks to the total, which is the ending itself: the card
|
|
596
|
+
* came up under a hand that wanted the last shot. The bar stops two
|
|
597
|
+
* seconds short; the ending is reached by playing to it.
|
|
598
|
+
*/
|
|
599
|
+
private barSecs;
|
|
600
|
+
private scrubUp;
|
|
601
|
+
private screen;
|
|
602
|
+
private fullChange;
|
|
603
|
+
/**
|
|
604
|
+
* THE POINTER MOVES THE WORLD A LITTLE.
|
|
605
|
+
*
|
|
606
|
+
* A film that cannot be touched is a video, and the whole argument
|
|
607
|
+
* here is that this is a scene. So the cursor gets a few degrees of
|
|
608
|
+
* lean: the lens takes a fraction of it (real parallax — the building
|
|
609
|
+
* and the hills separate) and the type planes take more of it in the
|
|
610
|
+
* other direction, each layer by its own depth. It is small enough to
|
|
611
|
+
* be felt rather than played with, and damped, so it never fights the
|
|
612
|
+
* shot the score is composing.
|
|
613
|
+
*/
|
|
614
|
+
private lean;
|
|
615
|
+
private leanTo;
|
|
616
|
+
private aim;
|
|
617
|
+
/** the haze the beat asked for — the weather drift breathes around it */
|
|
618
|
+
private hazeBase;
|
|
619
|
+
private goal;
|
|
620
|
+
private mid;
|
|
621
|
+
private midV;
|
|
622
|
+
private now;
|
|
623
|
+
private nowV;
|
|
624
|
+
/** the world-layer plane's own fade, so a chapter's type breathes in */
|
|
625
|
+
private skyOn;
|
|
626
|
+
/**
|
|
627
|
+
* THE SKY WORD'S OPACITY AS ACTUALLY SENT — not the ramp above.
|
|
628
|
+
*
|
|
629
|
+
* `skyOn` only says a word is WANTED; what the word is actually wearing
|
|
630
|
+
* is that ramp times the beat's own in and out, and the out takes it to
|
|
631
|
+
* nothing by 68% of the beat. When the next beat had no word the film
|
|
632
|
+
* used to hand the picture `skyOn` to fade from — a number still sitting
|
|
633
|
+
* near 1 — so a word that had been gone for seconds snapped back to 92%
|
|
634
|
+
* on the frame after the cut and faded out a second time, across the
|
|
635
|
+
* seam. Fade from what the word is wearing instead.
|
|
636
|
+
*/
|
|
637
|
+
private skyA;
|
|
638
|
+
/** the time of day the furniture is currently dressed for */
|
|
639
|
+
private wearing;
|
|
640
|
+
/** the cast-shadow offset the type is currently wearing, px */
|
|
641
|
+
private shadow;
|
|
642
|
+
private pageEl?;
|
|
643
|
+
/**
|
|
644
|
+
* WHERE THE CUT STARTS — the arrow keys' one piece of state.
|
|
645
|
+
*
|
|
646
|
+
* A film this long is unwatchable without chapter skip, and seeking a run
|
|
647
|
+
* that carries an integrator is not honest (the chaser's pose depends on
|
|
648
|
+
* its history, which is the price Drift's doctrine names out loud). So
|
|
649
|
+
* skipping RE-CUTS instead of seeking: the beat list is sliced here, the
|
|
650
|
+
* path and the cues are both derived from that list, and the score the
|
|
651
|
+
* region sees is a different, shorter film. An edited timeline replays
|
|
652
|
+
* from its own head, which is exactly the behaviour wanted — and it is
|
|
653
|
+
* the same move Sylva's lap makes to loop.
|
|
654
|
+
*
|
|
655
|
+
* `?from=N` seeds it, so a shot can be linked to.
|
|
656
|
+
*/
|
|
657
|
+
/**
|
|
658
|
+
* The deep link's shot, as asked (`?from=N`). Clamped against the
|
|
659
|
+
* rows when READ, never when set: with the score a graph the rows
|
|
660
|
+
* arrive a frame after construction, and clamping here against zero
|
|
661
|
+
* rows once made every deep link −1.
|
|
662
|
+
*/
|
|
663
|
+
private fromRaw;
|
|
664
|
+
private get from();
|
|
665
|
+
private set from(value);
|
|
666
|
+
/** sound is off until asked for: nobody's first second should be音 */
|
|
667
|
+
private sound;
|
|
668
|
+
/**
|
|
669
|
+
* THE GATE. This film is narrated, and narration behind a mute button
|
|
670
|
+
* is a film shown with the projector lamp off — so the front door asks.
|
|
671
|
+
* One held frame, one choice, and the choice IS the user gesture that
|
|
672
|
+
* autoplay policy wants anyway: the browser unlocks audio on the same
|
|
673
|
+
* click that starts the picture. Museums have worked this way forever.
|
|
674
|
+
*
|
|
675
|
+
* `?from` skips it (an authoring link wants the shot, not the lobby)
|
|
676
|
+
* and so does embedding.
|
|
677
|
+
*/
|
|
678
|
+
private gate;
|
|
679
|
+
/** the scene is loaded and seated behind the gate — the door can open */
|
|
680
|
+
private ready;
|
|
681
|
+
/**
|
|
682
|
+
* One pass BEHIND `booted`, on purpose. A region's first render
|
|
683
|
+
* collects no score, so anything standing in it on that pass — the
|
|
684
|
+
* first beat's type, a head photo — was never inserted and never
|
|
685
|
+
* animates. Content mounts on this flag instead, which flips a tick
|
|
686
|
+
* later: the same render that gives the score its first real pass
|
|
687
|
+
* hands the front layer a genuine insertion, and the opening beat's
|
|
688
|
+
* type is DELIVERED like every other beat's instead of being found
|
|
689
|
+
* already on the glass.
|
|
690
|
+
*/
|
|
691
|
+
private rolling;
|
|
692
|
+
get beats(): Beat[];
|
|
693
|
+
/** the first beat of each chapter, in whole-film indices */
|
|
694
|
+
get chapterHeads(): number[];
|
|
695
|
+
/** where we are in the WHOLE film, not the current cut */
|
|
696
|
+
get absoluteIndex(): number;
|
|
697
|
+
get beat(): Beat;
|
|
698
|
+
/**
|
|
699
|
+
* CAPTIONS. `?subs` seeds them on; CC toggles them.
|
|
700
|
+
*
|
|
701
|
+
* They are the narration, printed. That makes them two things at once
|
|
702
|
+
* and both are wanted: an accessibility track for anyone who cannot or
|
|
703
|
+
* would rather not hear the voice, and — before any voice exists — the
|
|
704
|
+
* only reliable way to find out that a line is two seconds too long for
|
|
705
|
+
* the shot it is sitting on.
|
|
706
|
+
*/
|
|
707
|
+
private subsOn;
|
|
708
|
+
get subs(): boolean;
|
|
709
|
+
private cc;
|
|
710
|
+
get grade(): string;
|
|
711
|
+
get chapter(): Chapter;
|
|
712
|
+
get embed(): boolean;
|
|
713
|
+
/** `?debug` puts the build stamp in the corner — see `@build` */
|
|
714
|
+
get debug(): boolean;
|
|
715
|
+
get build(): string;
|
|
716
|
+
get srcdoc(): string | undefined;
|
|
717
|
+
get src(): string;
|
|
718
|
+
get photoSrc(): string;
|
|
719
|
+
/** a photograph that failed to load is no photograph — drop the plate */
|
|
720
|
+
private lost;
|
|
721
|
+
private lostStamp;
|
|
722
|
+
get hasPhoto(): boolean;
|
|
723
|
+
private missing;
|
|
724
|
+
/** a fresh name per lap: an edited score replays, a restarted one fights */
|
|
725
|
+
get filmName(): string;
|
|
726
|
+
/**
|
|
727
|
+
* HOW MUCH HAND, in seconds — see `@settle`.
|
|
728
|
+
*
|
|
729
|
+
* The default is a QUARTER OF THE GAP BETWEEN WAYPOINTS, because that
|
|
730
|
+
* is the only number that means the same thing to two different films.
|
|
731
|
+
* A window is smoothing relative to the spacing of the kinks it
|
|
732
|
+
* smooths: a quarter takes the curvature step off every pose change
|
|
733
|
+
* and is far too little to stop the lens visiting the poses. Both
|
|
734
|
+
* films that ship here spend two seconds a waypoint, so both get half
|
|
735
|
+
* a second; a score that cuts four times as fast gets a quarter of
|
|
736
|
+
* that without being asked, and half a second imposed on it would have
|
|
737
|
+
* flattened its shots.
|
|
738
|
+
*
|
|
739
|
+
* Capped at half a second so a very slow film does not drift, and
|
|
740
|
+
* floored at nothing: `@settle={{0}}` gives the raw spline.
|
|
741
|
+
*/
|
|
742
|
+
get settle(): number;
|
|
743
|
+
/**
|
|
744
|
+
* The pose the score OPENS on, declared to the region — without it the
|
|
745
|
+
* first spline segment travels in from the library's default rig, a
|
|
746
|
+
* two-second bounce every cold boot wore before its first real frame.
|
|
747
|
+
*/
|
|
748
|
+
get openPose(): {
|
|
749
|
+
dolly: number;
|
|
750
|
+
look: {
|
|
751
|
+
x: number;
|
|
752
|
+
y: number;
|
|
753
|
+
z: number;
|
|
754
|
+
};
|
|
755
|
+
pitch: number;
|
|
756
|
+
x: number;
|
|
757
|
+
y: number;
|
|
758
|
+
yaw: number;
|
|
759
|
+
};
|
|
760
|
+
get filmSeconds(): number;
|
|
761
|
+
/**
|
|
762
|
+
* THE WHOLE FILM IS ONE CAMERA STEP.
|
|
763
|
+
*
|
|
764
|
+
* Every beat contributes `ticks` waypoints: a moving beat is sampled from
|
|
765
|
+
* its head pose to its tail, a holding beat repeats its pose, and the
|
|
766
|
+
* spline runs through the lot on one clock. So the shot list is a path
|
|
767
|
+
* rather than a playlist, the camera crosses each mark with velocity
|
|
768
|
+
* instead of arriving at it, and a hold is genuinely still without
|
|
769
|
+
* anything having stopped.
|
|
770
|
+
*/
|
|
771
|
+
/**
|
|
772
|
+
* WHERE A SHOT ENDS — the beat's authored tail, floored so it always
|
|
773
|
+
* reads as a move, and clamped so it never travels past the pose the
|
|
774
|
+
* next shot begins on. Shared by the path (which lerps its waypoints
|
|
775
|
+
* across it) and by the LAUNCH: a cut hands the chaser this shot's own
|
|
776
|
+
* speed, so the lens is already travelling when the cut lands rather
|
|
777
|
+
* than easing up from a standstill.
|
|
778
|
+
*/
|
|
779
|
+
private tailFor;
|
|
780
|
+
get path(): import("./schedule.ts").Waypoint[];
|
|
781
|
+
/**
|
|
782
|
+
* Each beat's entrance, as a delay into the one camera step — offset
|
|
783
|
+
* one tick, because the pose-in-force seed occupies the spline's first
|
|
784
|
+
* slot: waypoint k is crossed at (k+1) slots, not k. The old uniform
|
|
785
|
+
* skew was invisible (camera and cues equally late, a constant the
|
|
786
|
+
* chaser's own lag swallowed); a SPLICE made it audible — the snap
|
|
787
|
+
* fired two seconds before the goal stepped, and the chaser spent the
|
|
788
|
+
* gap dragged back toward the old shot. Cue 0 stays at zero: the boot
|
|
789
|
+
* and every re-cut apply their head beat by hand, and its immediate
|
|
790
|
+
* re-fire has always been the first cue's job.
|
|
791
|
+
*/
|
|
792
|
+
get cues(): import("./schedule.ts").Cue[];
|
|
793
|
+
/**
|
|
794
|
+
* THE ATTACHMENTS: every window the score drives another region over.
|
|
795
|
+
* The plate for every beat, the insert for a beat with a photograph,
|
|
796
|
+
* the clip for a beat with one — each on the score's own clock, so a
|
|
797
|
+
* seek stands all of them where playing there would. The regions are
|
|
798
|
+
* keyed per beat and mounted for their windows; `remove` past a window
|
|
799
|
+
* leaves them to that; a clip may outlive its beat and holds.
|
|
800
|
+
*/
|
|
801
|
+
get windows(): {
|
|
802
|
+
end: "hold" | "remove";
|
|
803
|
+
length: number;
|
|
804
|
+
region: string;
|
|
805
|
+
start: number;
|
|
806
|
+
}[];
|
|
807
|
+
/**
|
|
808
|
+
* THE TRANSPORT — a broadcast bar, not a thermometer. One segment per
|
|
809
|
+
* chapter, sized by the chapter's actual running time, filled by
|
|
810
|
+
* WHOLE-film progress (the old bar measured the current cut, so a
|
|
811
|
+
* skip made it lie), and clickable: the segments are the same re-cut
|
|
812
|
+
* the menu and the arrows perform.
|
|
813
|
+
*/
|
|
814
|
+
/**
|
|
815
|
+
* ONE TIMELINE, NOT TWO.
|
|
816
|
+
*
|
|
817
|
+
* The corner carried a strip of chapter segments beside a rule of years:
|
|
818
|
+
* two timelines of the same film, at two different scales, in two
|
|
819
|
+
* different shapes, six inches apart. So the chapters are ON the years
|
|
820
|
+
* now — each one a dot at the year it opens, so the gap between THE SITE
|
|
821
|
+
* and SILENCE is fifty-four years wide and the gap between the last two
|
|
822
|
+
* is a decade, which is the fact the film is about. The dots are still
|
|
823
|
+
* the doors into the chapters.
|
|
824
|
+
*/
|
|
825
|
+
get transport(): RailMark[];
|
|
826
|
+
/** the ends of the rule, when it is a clock */
|
|
827
|
+
get railLabels(): [string, string] | undefined;
|
|
828
|
+
/** the rail is on unless the film says otherwise */
|
|
829
|
+
get railOn(): boolean;
|
|
830
|
+
get railReadout(): string;
|
|
831
|
+
/**
|
|
832
|
+
* WHEN EACH CUE LANDS — paced against the voice, not the clock.
|
|
833
|
+
*
|
|
834
|
+
* The phrases used to arrive on four fixed delays, which meant a
|
|
835
|
+
* fourteen-second beat finished its type with five seconds of dead air
|
|
836
|
+
* and a short one crowded the read. So the cues spread themselves: the
|
|
837
|
+
* first lands early, the last lands as the measured line is finishing
|
|
838
|
+
* (`VO_SECS`), and a beat with no recording paces against two thirds of
|
|
839
|
+
* its own length, which is where a read for it would sit anyway.
|
|
840
|
+
*/
|
|
841
|
+
/**
|
|
842
|
+
* THE TRANSITION FIRST, THEN THE TYPE. A setting that arrives while the
|
|
843
|
+
* seam is still on screen is read against two pictures at once. The
|
|
844
|
+
* block waits for the incoming join to finish and a breath more, then
|
|
845
|
+
* enters in its order: kicker, glyph, reading — and the lines after.
|
|
846
|
+
*/
|
|
847
|
+
get typeAt(): number[];
|
|
848
|
+
get sayAt(): number[];
|
|
849
|
+
/**
|
|
850
|
+
* Thai and Khmer are not kanji: their ascenders, vowel marks and
|
|
851
|
+
* subscripts stand far outside a CJK-tuned glyph box, so at the kanji
|
|
852
|
+
* size they collide with the kicker above and the reading below. Tall
|
|
853
|
+
* scripts take a reduced setting with real leading.
|
|
854
|
+
*/
|
|
855
|
+
/**
|
|
856
|
+
* HOW MANY CHARACTERS HAVE TO FIT. A vertical setting is as tall as
|
|
857
|
+
* its string, and 一国一城令 is five glyphs — at the plate's own size
|
|
858
|
+
* that column runs off the top of the frame and the film crops its
|
|
859
|
+
* own title. The count goes to CSS, which sizes the column to the
|
|
860
|
+
* height available rather than to a number somebody typed once while
|
|
861
|
+
* looking at a three-glyph word.
|
|
862
|
+
*/
|
|
863
|
+
get glyphFit(): string;
|
|
864
|
+
get glyphTone(): string;
|
|
865
|
+
/** the lineup's current kanji; empty between lineups */
|
|
866
|
+
get stamp(): string;
|
|
867
|
+
/**
|
|
868
|
+
* THE POSTER IS AN EVENING (by default). The film proper opens in the
|
|
869
|
+
* morning, so the door stands in the last of the light with a long hard
|
|
870
|
+
* shadow across the empty half of the frame; pressing it turns the day
|
|
871
|
+
* over. The film may dress its door otherwise (`@poster`).
|
|
872
|
+
*/
|
|
873
|
+
private dressPoster;
|
|
874
|
+
private announced;
|
|
875
|
+
private mount;
|
|
876
|
+
private trackEls;
|
|
877
|
+
private dimEl;
|
|
878
|
+
private plate;
|
|
879
|
+
private snap;
|
|
880
|
+
/**
|
|
881
|
+
* THE WHIP. A 'whip' join does not snap: the goal steps across the
|
|
882
|
+
* seam (the splice does that) and the chaser races it on a briefly
|
|
883
|
+
* stiff spring — a fast, smooth tween between the shots that is over
|
|
884
|
+
* in a third of a second and never reads as a glide. While it runs,
|
|
885
|
+
* the spring is ~3× its documentary stiffness; then the hand relaxes.
|
|
886
|
+
*/
|
|
887
|
+
private whipUntil;
|
|
888
|
+
/**
|
|
889
|
+
* One critically-damped stage. The page's own chase is the second, which
|
|
890
|
+
* is the whole cascade argument getting made for free by the fact that the
|
|
891
|
+
* scene lives in another document.
|
|
892
|
+
*/
|
|
893
|
+
private chase;
|
|
894
|
+
/**
|
|
895
|
+
* THE POSTER TURNS.
|
|
896
|
+
*
|
|
897
|
+
* A still frame behind a title is indistinguishable from a JPEG, and
|
|
898
|
+
* this whole film's argument is that it is not one. So while the door
|
|
899
|
+
* is up the lens makes a slow circuit of the opening pose — a few
|
|
900
|
+
* degrees either side, breathing in and out — which says "live 3D"
|
|
901
|
+
* before a word is read and costs one rAF. It hands over on the
|
|
902
|
+
* click: the film does not snap away from the poster, it flies from
|
|
903
|
+
* wherever the circuit had reached.
|
|
904
|
+
*/
|
|
905
|
+
private poster;
|
|
906
|
+
private posterRaf?;
|
|
907
|
+
private posterAt;
|
|
908
|
+
/** where the poster's circuit had reached when the door was answered */
|
|
909
|
+
private posterPose?;
|
|
910
|
+
/**
|
|
911
|
+
* ONE SETTING AT A TIME, AND THIS TIME IT IS GUARANTEED.
|
|
912
|
+
*
|
|
913
|
+
* The hand-off is a leaver and an arriver sharing the corner for half
|
|
914
|
+
* a second, which is the design. But a leaver whose exit never
|
|
915
|
+
* completes just stays — and a block from the first beat was still
|
|
916
|
+
* standing at full strength eight beats later, with two settings of
|
|
917
|
+
* different chapters overprinting each other. Whatever strands it (a
|
|
918
|
+
* removal that waits on a cue the outgoing beat never had), the rule
|
|
919
|
+
* the film states out loud in its own comment is worth enforcing
|
|
920
|
+
* rather than trusting: any block that is not the current one and has
|
|
921
|
+
* outstayed the longest hand-off is taken off the glass.
|
|
922
|
+
*/
|
|
923
|
+
private sweepBlocks;
|
|
924
|
+
private frame;
|
|
925
|
+
private tick;
|
|
926
|
+
/**
|
|
927
|
+
* TYPE THROWS ITS SHADOW WHERE THE BUILDING THROWS ITS OWN.
|
|
928
|
+
*
|
|
929
|
+
* The scene lights itself from a key whose position is a property of the
|
|
930
|
+
* hour, and the tower's cast shadow lies along the ground at whatever
|
|
931
|
+
* diagonal that produces. Type set over the frame with a shadow offset
|
|
932
|
+
* down and right — the default of every drop shadow ever shipped — is
|
|
933
|
+
* lit by a different sun than everything behind it, and the eye reads
|
|
934
|
+
* the mismatch long before it can name it. So the key's own screen
|
|
935
|
+
* position comes back from the scene and the offset is simply the
|
|
936
|
+
* direction away from it. At night, or with the sun behind the lens,
|
|
937
|
+
* there is no honest cast shadow and the type wears none.
|
|
938
|
+
*/
|
|
939
|
+
private follow;
|
|
940
|
+
/** which of the frame's layers this picture draws itself */
|
|
941
|
+
private takeGlass;
|
|
942
|
+
/**
|
|
943
|
+
* THE WASH, TOLD ON A CHANGE. Two things decide it — the shot's own mode
|
|
944
|
+
* and the palette's paper — and neither changes often, so the picture is
|
|
945
|
+
* told when one does and eases the change itself over the same 700 ms
|
|
946
|
+
* the stylesheet used to.
|
|
947
|
+
*/
|
|
948
|
+
private pushWash;
|
|
949
|
+
/** the cloud: into the glass where the picture takes it, onto a CSS plate where it does not */
|
|
950
|
+
private setCloud;
|
|
951
|
+
/**
|
|
952
|
+
* THE FURNITURE WEARS THE SCENE'S PALETTE.
|
|
953
|
+
*
|
|
954
|
+
* The page carries four times of day and swings its whole palette between
|
|
955
|
+
* them, so a scrim and a caption painted in one fixed ochre are correct in
|
|
956
|
+
* exactly one chapter and wrong in the other four — at noon the film's
|
|
957
|
+
* warm paper sits on a cool scene like a sticker. The scene already
|
|
958
|
+
* publishes its ink as CSS variables, so the film simply reads them and
|
|
959
|
+
* dresses itself the same, once per change rather than once per frame.
|
|
960
|
+
*/
|
|
961
|
+
private wear;
|
|
962
|
+
/**
|
|
963
|
+
* PLANES, MOVING AT THEIR OWN RATES.
|
|
964
|
+
*
|
|
965
|
+
* The world layer parallaxes because it is genuinely out in the scene at
|
|
966
|
+
* different distances. The front layer has no depth to borrow, so it is
|
|
967
|
+
* given one: over the life of a beat each row drifts and scales on its
|
|
968
|
+
* own rate, the big glyph fastest and nearest, the small print slowest
|
|
969
|
+
* and furthest, so the type reads as a set of planes rather than a
|
|
970
|
+
* sheet. It is the oldest trick in motion graphics and it is here for
|
|
971
|
+
* the oldest reason — a still caption over a moving picture looks
|
|
972
|
+
* pasted on, and a caption that moves WITH the picture looks composited
|
|
973
|
+
* into it.
|
|
974
|
+
*
|
|
975
|
+
* It runs on the beat's own clock rather than Motion's, deliberately:
|
|
976
|
+
* the entrances belong to the score and this belongs to the shot, and
|
|
977
|
+
* putting the two on one timeline would mean the drift restarting every
|
|
978
|
+
* time a word did.
|
|
979
|
+
*/
|
|
980
|
+
private parallax;
|
|
981
|
+
/**
|
|
982
|
+
* THE TRACES LIVE IN THE SCENE NOW. They began as SVG projected over
|
|
983
|
+
* the frame — approximately right and one frame behind the lens on
|
|
984
|
+
* every move. As tubes in the page's own scene they are exact: they
|
|
985
|
+
* lie ON the eave because they are geometry at the eave's own
|
|
986
|
+
* coordinates, the building occludes them honestly, and the draw-on
|
|
987
|
+
* is the tube's index buffer revealed in path order. Each line in a
|
|
988
|
+
* set starts a moment after the one before it — a hand annotating,
|
|
989
|
+
* not a diagram switching on.
|
|
990
|
+
*/
|
|
991
|
+
/** how much of the follow is in force (eased), and its last aim and zoom */
|
|
992
|
+
private riseK;
|
|
993
|
+
private riseAim;
|
|
994
|
+
private riseZoom;
|
|
995
|
+
/**
|
|
996
|
+
* THE LENS FOLLOWS THE WORK. Chris's rule for a building that goes up
|
|
997
|
+
* in the shot: if a spire is rising, ZOOM OUT; as you push in, follow
|
|
998
|
+
* the top that is being built. So while the followed campaign is
|
|
999
|
+
* between its base and its top, the aim rides a little above the
|
|
1000
|
+
* middle of what stands and the zoom is capped to keep base and top
|
|
1001
|
+
* in the frame; when it finishes, the authored pose takes over again,
|
|
1002
|
+
* on a one-pole so the release is a move and not a jump.
|
|
1003
|
+
*/
|
|
1004
|
+
private followRise;
|
|
1005
|
+
/** the beat whose lines are being timed, and the local time they became drawable */
|
|
1006
|
+
private traceBeat;
|
|
1007
|
+
private traceFrom;
|
|
1008
|
+
/** whether the beat's lines may be on the glass right now */
|
|
1009
|
+
private traceOk;
|
|
1010
|
+
/**
|
|
1011
|
+
* NO LINE ON A THING STILL GOING UP. A trace or a callout is drawn on a
|
|
1012
|
+
* finished part: the followed campaign must be done (or, with nothing
|
|
1013
|
+
* followed, the built height must have passed the line). The draw-on
|
|
1014
|
+
* is timed from the moment that became true, not from the head.
|
|
1015
|
+
*/
|
|
1016
|
+
private traceReady;
|
|
1017
|
+
private traceShape;
|
|
1018
|
+
/** the mark's facing, damped behind the camera's own bearing */
|
|
1019
|
+
private markFace;
|
|
1020
|
+
/**
|
|
1021
|
+
* Place the stage mark: climb to its height with a settle, hold, and
|
|
1022
|
+
* face the camera a beat late.
|
|
1023
|
+
*/
|
|
1024
|
+
private stageMark;
|
|
1025
|
+
/**
|
|
1026
|
+
* THE TRACKING LINE — the one piece of the front layer that has to know
|
|
1027
|
+
* where the camera is pointing this frame. The caption stays where the
|
|
1028
|
+
* layout put it and a line reaches from it to the actual point on the
|
|
1029
|
+
* building, redrawn every frame, so the label is attached to the thing
|
|
1030
|
+
* rather than merely near it.
|
|
1031
|
+
*/
|
|
1032
|
+
private trackPoint;
|
|
1033
|
+
/**
|
|
1034
|
+
* THE READOUT AND THE MARKER. The numeral is tracked and written only
|
|
1035
|
+
* when the whole year changes, which is a handful of times a run; the
|
|
1036
|
+
* marker's position is a custom property written every frame, because a
|
|
1037
|
+
* dot that steps once a year along a rule is a dot that looks broken.
|
|
1038
|
+
*/
|
|
1039
|
+
/**
|
|
1040
|
+
* WHEN THE NUMERAL IS ON. It rises as the voice reaches the year, holds
|
|
1041
|
+
* while the phrase finishes, and is gone well before the cut — a date
|
|
1042
|
+
* that outstays the sentence that said it becomes a watermark.
|
|
1043
|
+
*/
|
|
1044
|
+
private stampAt;
|
|
1045
|
+
/** the film's clock readout, from page seconds — nothing without a clock */
|
|
1046
|
+
private showYear;
|
|
1047
|
+
/** everything a beat changes in the world, done once on entry */
|
|
1048
|
+
private applyBeat;
|
|
1049
|
+
/**
|
|
1050
|
+
* THE AIR OF A SHOT: grade, sun, haze, weather. Split out of the beat
|
|
1051
|
+
* so a chapter's sky can begin turning while the lens is still flying
|
|
1052
|
+
* into it — the `air` cue fires at the head of a lead, the beat's own
|
|
1053
|
+
* cue when it lands, and applying it twice is harmless because every
|
|
1054
|
+
* one of these is a set, not a step.
|
|
1055
|
+
*/
|
|
1056
|
+
private applyAir;
|
|
1057
|
+
/**
|
|
1058
|
+
* THE HOUR A CUT INHERITS.
|
|
1059
|
+
*
|
|
1060
|
+
* Theme and weather are stated where they CHANGE, so a beat halfway
|
|
1061
|
+
* through the film usually says nothing about either — which is right
|
|
1062
|
+
* for a film played from the top and wrong for one dropped into. A
|
|
1063
|
+
* deep link (or a chapter skip) would open in whatever sky was last
|
|
1064
|
+
* set, which since the front door became an evening meant the
|
|
1065
|
+
* construction chapter got built at dusk. So a cut resolves its own
|
|
1066
|
+
* hour first: walk back to the last beat that named one, and take it.
|
|
1067
|
+
*/
|
|
1068
|
+
private settleAir;
|
|
1069
|
+
private shot;
|
|
1070
|
+
private dispatch;
|
|
1071
|
+
/**
|
|
1072
|
+
* PAUSE MEANS EVERYTHING STOPS. The score's run holds where it is (the
|
|
1073
|
+
* lens included), the page's own clock holds (grass, weather, the
|
|
1074
|
+
* build, the day), the audio graph suspends, and the beat clock is
|
|
1075
|
+
* shifted forward by the length of the hold on resume so the hours,
|
|
1076
|
+
* the build and the type pick up exactly where they stood. Tearing the
|
|
1077
|
+
* Sequence down was the old pause, and it re-ran the chapter on play.
|
|
1078
|
+
* An exact film's runs are already standing — its clock is the only
|
|
1079
|
+
* thing that has to hold.
|
|
1080
|
+
*/
|
|
1081
|
+
private toggle;
|
|
1082
|
+
/** any re-cut or restart clears a hold: the new run starts rolling */
|
|
1083
|
+
private unhold;
|
|
1084
|
+
/**
|
|
1085
|
+
* SKIP A CHAPTER — by re-cutting, never by seeking.
|
|
1086
|
+
*
|
|
1087
|
+
* `from` moves to a chapter head, which changes the beat list, which
|
|
1088
|
+
* changes the path, the cues and the sequence's name all at once. The
|
|
1089
|
+
* region sees a different score and plays it from its head. Seeking the
|
|
1090
|
+
* existing run would be the obvious alternative and it would be wrong:
|
|
1091
|
+
* the lens is an integrator whose pose depends on where it has been, so
|
|
1092
|
+
* a run dropped into the middle of itself arrives with the wrong
|
|
1093
|
+
* velocity — the same reason `notes/sylva-one-world.md` calls the chaser
|
|
1094
|
+
* seek-unsafe and means it.
|
|
1095
|
+
*/
|
|
1096
|
+
private goChapter;
|
|
1097
|
+
private cutTo;
|
|
1098
|
+
/** an uncaught error anywhere becomes a visible line — a film that
|
|
1099
|
+
* dies silently mid-reel cannot be debugged from a chair */
|
|
1100
|
+
private trip;
|
|
1101
|
+
private prev;
|
|
1102
|
+
private next;
|
|
1103
|
+
private key;
|
|
1104
|
+
/**
|
|
1105
|
+
* THE NARRATION, one file per beat.
|
|
1106
|
+
*
|
|
1107
|
+
* `assets/vo/<id>.mp3`, played on the beat's entrance and stopped
|
|
1108
|
+
* when the beat changes. Per beat rather than one long track because
|
|
1109
|
+
* chapter skip RE-CUTS the film: a single track would have to be sought,
|
|
1110
|
+
* and a sought track against a re-cut score drifts inside a chapter.
|
|
1111
|
+
*
|
|
1112
|
+
* A missing file is silence, not an error. The film ships before the
|
|
1113
|
+
* voice does, and the score has to be right either way. While a line
|
|
1114
|
+
* plays the scene's own music ducks under it, which is the one piece of
|
|
1115
|
+
* mixing that cannot wait for a mix.
|
|
1116
|
+
*/
|
|
1117
|
+
private voSrc;
|
|
1118
|
+
/** ask the page to fetch and decode the line after this one, now */
|
|
1119
|
+
private primeNext;
|
|
1120
|
+
/**
|
|
1121
|
+
* A BOUNDARY NEVER CLIPS THE VOICE — and every line has its own
|
|
1122
|
+
* throat. One shared element made politeness impossible: however
|
|
1123
|
+
* gently the old line was being faded, the new line's src swap
|
|
1124
|
+
* guillotined it mid-word. So an interrupted line keeps its OWN
|
|
1125
|
+
* element and fades there (~120ms, fast enough to read as a stop,
|
|
1126
|
+
* slow enough that no waveform is cut mid-cycle) while the new line
|
|
1127
|
+
* starts clean on a fresh one — the game-dialogue barge-in, which is
|
|
1128
|
+
* what a chapter skip actually is. ("Stop at the next word" is the
|
|
1129
|
+
* refinement this is built to take: an analyser watching for the
|
|
1130
|
+
* inter-word trough before the fade — see docs/choreo-splices.md.)
|
|
1131
|
+
*/
|
|
1132
|
+
/**
|
|
1133
|
+
* A JOIN, EXHIBITED. Any seam as a pure overlay on whatever is playing —
|
|
1134
|
+
* no beat change, no snap: the transition itself, on the living
|
|
1135
|
+
* picture. What a cutting room's wall plate triggers.
|
|
1136
|
+
*/
|
|
1137
|
+
private preview;
|
|
1138
|
+
/** the wrapper the live picture sits in, for rack-defocus */
|
|
1139
|
+
private liveEl?;
|
|
1140
|
+
private liveWrap;
|
|
1141
|
+
/**
|
|
1142
|
+
* THE LIGHT SWEEP: the sun itself flares across the seam — swings
|
|
1143
|
+
* high and past, then settles back onto whatever light the beat
|
|
1144
|
+
* actually asked for. Fire-and-forget; the restore hands the key
|
|
1145
|
+
* back to the beat's own sun (or the hour's).
|
|
1146
|
+
*/
|
|
1147
|
+
private lightSweep;
|
|
1148
|
+
/** the scene brought its own score — six of them, one per tower */
|
|
1149
|
+
/** the line for this beat, at the level the session was mixed to */
|
|
1150
|
+
private speak;
|
|
1151
|
+
private hush;
|
|
1152
|
+
private hear;
|
|
1153
|
+
/**
|
|
1154
|
+
* FROM THE TOP means the front door, not the first beat.
|
|
1155
|
+
*
|
|
1156
|
+
* A film restarted straight into its opening shot skips the one piece
|
|
1157
|
+
* of the picture that says what it is — and the poster is a
|
|
1158
|
+
* composition in its own right, with the building turning in the last
|
|
1159
|
+
* of the light. So this clears everything the run has done and puts
|
|
1160
|
+
* the door back up, with the lens seated where it opens.
|
|
1161
|
+
*/
|
|
1162
|
+
private restart;
|
|
1163
|
+
/** a choice made at the door before the scene finished loading */
|
|
1164
|
+
private wanted?;
|
|
1165
|
+
/** through the gate — on the click the audio policy was waiting for */
|
|
1166
|
+
private begin;
|
|
1167
|
+
/** the whole film's running time, said the way a poster says it */
|
|
1168
|
+
get runtime(): string;
|
|
1169
|
+
/**
|
|
1170
|
+
* BACK IN FROM THE END CARD — a dissolve, not a flight.
|
|
1171
|
+
*
|
|
1172
|
+
* The film ends three hundred degrees around the building from where
|
|
1173
|
+
* it opened, so tweening the lens home spins it like a globe. The
|
|
1174
|
+
* ending cross-fades into the opening frame instead: the last frame
|
|
1175
|
+
* is held as a still, the camera is PLACED at the opening pose behind
|
|
1176
|
+
* it, and the still fades away.
|
|
1177
|
+
*/
|
|
1178
|
+
/**
|
|
1179
|
+
* BACK IN FROM THE END CARD — a hard reset, not a journey.
|
|
1180
|
+
*
|
|
1181
|
+
* The film ends three hundred degrees around the building, with the
|
|
1182
|
+
* tower dissolved, the sky at golden hour, the rain gone and a chapter
|
|
1183
|
+
* numeral on screen. Tweening any of that back to the opening is a
|
|
1184
|
+
* confusing ten seconds in which nothing is either the ending or the
|
|
1185
|
+
* beginning. So the ending is CLEARED: every overlay, the model, the
|
|
1186
|
+
* weather, the world type, the traces and the lens all go back to
|
|
1187
|
+
* their opening state in one frame, and the film starts.
|
|
1188
|
+
*/
|
|
1189
|
+
/** the end card's WATCH AGAIN is the front door, not the first beat: the
|
|
1190
|
+
* choice of sound is made there, every time */
|
|
1191
|
+
private replay;
|
|
1192
|
+
/** the chapter menu. The film keeps running behind it, blurred: a
|
|
1193
|
+
* menu that freezes the picture makes the picture feel like a file, and
|
|
1194
|
+
* this one is meant to feel like a broadcast you are stepping around in */
|
|
1195
|
+
private menu;
|
|
1196
|
+
private toc;
|
|
1197
|
+
/** every chapter, with the beat it starts at and whether we are in it */
|
|
1198
|
+
get contents(): {
|
|
1199
|
+
here: boolean;
|
|
1200
|
+
head: number;
|
|
1201
|
+
n: string;
|
|
1202
|
+
secs: number;
|
|
1203
|
+
shots: number;
|
|
1204
|
+
title: string;
|
|
1205
|
+
}[];
|
|
1206
|
+
private pick;
|
|
1207
|
+
}
|
|
1208
|
+
//# sourceMappingURL=film.d.ts.map
|