paperlab 0.2.0 → 0.3.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/README.md +25 -7
- package/dist/chunk-3IMUEESH.js +7035 -0
- package/dist/chunk-3IMUEESH.js.map +1 -0
- package/dist/index.cjs +1938 -1753
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +582 -4400
- package/dist/index.d.ts +582 -4400
- package/dist/index.js +225 -6727
- package/dist/index.js.map +1 -1
- package/dist/slots-D0Nc_5dq.d.cts +6661 -0
- package/dist/slots-D0Nc_5dq.d.ts +6661 -0
- package/dist/stage.cjs +8871 -0
- package/dist/stage.cjs.map +1 -0
- package/dist/stage.d.cts +1156 -0
- package/dist/stage.d.ts +1156 -0
- package/dist/stage.js +2214 -0
- package/dist/stage.js.map +1 -0
- package/package.json +37 -8
package/dist/stage.d.cts
ADDED
|
@@ -0,0 +1,1156 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { F as FieldPaperSlot, a as PaperConfigInput } from './slots-D0Nc_5dq.cjs';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The room the walk is in.
|
|
7
|
+
*
|
|
8
|
+
* Stage mode was a void with a horizon: a graded dome, a flat plane, and a
|
|
9
|
+
* bright rectangle at the end, none of it a knowable size. That is why the
|
|
10
|
+
* walking figure was carrying the whole scale burden by itself — and why
|
|
11
|
+
* simply removing the figure would have left an abstraction rather than a
|
|
12
|
+
* hall. Architecture is the better answer: objects whose size the viewer
|
|
13
|
+
* already knows, made of flat surfaces under good light, which is the one
|
|
14
|
+
* thing a renderer never gets wrong.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* What holds the paper up.
|
|
18
|
+
*
|
|
19
|
+
* Every paper installation shows its hardware — monofilament from a ceiling
|
|
20
|
+
* grid, steel wire, bulldog clips, a rod — and in the scattered-sheet pieces
|
|
21
|
+
* the threads are half the composition. Stage mode's banners hung from
|
|
22
|
+
* nothing at all, which is a bigger realism gap than any shader in the
|
|
23
|
+
* backlog and closes for a few thin lines of geometry.
|
|
24
|
+
*/
|
|
25
|
+
declare const stageSuspensionSchema: z.ZodObject<{
|
|
26
|
+
/**
|
|
27
|
+
* What carries the load.
|
|
28
|
+
*
|
|
29
|
+
* `thread` is monofilament to the ceiling — one straight line per sheet.
|
|
30
|
+
* `rod` is a dowel across each sheet's top edge, hung from the ceiling at
|
|
31
|
+
* both ends, which is a different image entirely: a rank on threads reads
|
|
32
|
+
* as sheets floating in a row, and a rank on rods reads as sheets that
|
|
33
|
+
* were HUNG, by someone, on something. `none` is for a stage where the
|
|
34
|
+
* paper is meant to be impossible.
|
|
35
|
+
*/
|
|
36
|
+
type: z.ZodDefault<z.ZodEnum<["none", "thread", "rod"]>>;
|
|
37
|
+
color: z.ZodDefault<z.ZodString>;
|
|
38
|
+
/**
|
|
39
|
+
* What grips the sheet.
|
|
40
|
+
*
|
|
41
|
+
* A clip is wide and shallow — the bulldog clip of a gallery. A peg is
|
|
42
|
+
* narrow and deep, and grips DOWN the face of the sheet rather than
|
|
43
|
+
* across its edge: the domestic one, a line of paper on a washing line.
|
|
44
|
+
* They are told apart by silhouette at any distance, which is the only
|
|
45
|
+
* thing that survives being one instanced box at the top of an
|
|
46
|
+
* eight-metre banner.
|
|
47
|
+
*
|
|
48
|
+
* This replaced a `clips: boolean`. Two of the four pieces of hardware the
|
|
49
|
+
* plan named — pegs, and a rod — had no way to be asked for, and a boolean
|
|
50
|
+
* cannot grow a third answer.
|
|
51
|
+
*/
|
|
52
|
+
hardware: z.ZodDefault<z.ZodEnum<["none", "clip", "peg"]>>;
|
|
53
|
+
}, "strip", z.ZodTypeAny, {
|
|
54
|
+
type: "none" | "thread" | "rod";
|
|
55
|
+
color: string;
|
|
56
|
+
hardware: "none" | "clip" | "peg";
|
|
57
|
+
}, {
|
|
58
|
+
type?: "none" | "thread" | "rod" | undefined;
|
|
59
|
+
color?: string | undefined;
|
|
60
|
+
hardware?: "none" | "clip" | "peg" | undefined;
|
|
61
|
+
}>;
|
|
62
|
+
declare const stageRoomSchema: z.ZodObject<{
|
|
63
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
64
|
+
/**
|
|
65
|
+
* Ceiling height, as a multiple of the paper's own height.
|
|
66
|
+
*
|
|
67
|
+
* Relative rather than absolute because the banners ARE the architecture
|
|
68
|
+
* here: a hall whose ceiling sits just above its hangings reads as built
|
|
69
|
+
* for them, and one at a fixed world height reads as whatever the paper
|
|
70
|
+
* happened to be scaled to that day.
|
|
71
|
+
*/
|
|
72
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
73
|
+
color: z.ZodDefault<z.ZodString>;
|
|
74
|
+
/** Columns flanking the walk — see `stageColumnsSchema`. */
|
|
75
|
+
columns: z.ZodDefault<z.ZodObject<{
|
|
76
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
77
|
+
/** Centres this far apart along the walk. Roughly a bay. */
|
|
78
|
+
spacing: z.ZodDefault<z.ZodNumber>;
|
|
79
|
+
/** Shaft width. The number doing the work — a column is a known size. */
|
|
80
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
81
|
+
/**
|
|
82
|
+
* How far off the walk's centreline each rank stands.
|
|
83
|
+
*
|
|
84
|
+
* Outside the banners, always. Columns are the room; the paper is the
|
|
85
|
+
* subject, and a column standing between the viewer and a banner has
|
|
86
|
+
* swapped the two over. Default clears a `colonnade`'s widest sensible
|
|
87
|
+
* aisle with room to spare.
|
|
88
|
+
*/
|
|
89
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
90
|
+
/**
|
|
91
|
+
* Stone, and darker than paper on purpose.
|
|
92
|
+
*
|
|
93
|
+
* The brightest thing in any of these frames has to be the light, and the
|
|
94
|
+
* second brightest has to be the paper. A column the same value as a
|
|
95
|
+
* banner does not read as architecture behind the subject; it reads as
|
|
96
|
+
* more banners, and the eye stops being able to tell what the room is made
|
|
97
|
+
* of from what is hanging in it.
|
|
98
|
+
*/
|
|
99
|
+
color: z.ZodDefault<z.ZodString>;
|
|
100
|
+
}, "strip", z.ZodTypeAny, {
|
|
101
|
+
width: number;
|
|
102
|
+
offset: number;
|
|
103
|
+
color: string;
|
|
104
|
+
spacing: number;
|
|
105
|
+
enabled: boolean;
|
|
106
|
+
}, {
|
|
107
|
+
width?: number | undefined;
|
|
108
|
+
offset?: number | undefined;
|
|
109
|
+
color?: string | undefined;
|
|
110
|
+
spacing?: number | undefined;
|
|
111
|
+
enabled?: boolean | undefined;
|
|
112
|
+
}>>;
|
|
113
|
+
/** A wall at the end of the walk with the source in it. */
|
|
114
|
+
doorway: z.ZodDefault<z.ZodObject<{
|
|
115
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
116
|
+
/** Opening size, as a multiple of the source's own. 1 frames it exactly. */
|
|
117
|
+
opening: z.ZodDefault<z.ZodNumber>;
|
|
118
|
+
color: z.ZodDefault<z.ZodString>;
|
|
119
|
+
}, "strip", z.ZodTypeAny, {
|
|
120
|
+
color: string;
|
|
121
|
+
enabled: boolean;
|
|
122
|
+
opening: number;
|
|
123
|
+
}, {
|
|
124
|
+
color?: string | undefined;
|
|
125
|
+
enabled?: boolean | undefined;
|
|
126
|
+
opening?: number | undefined;
|
|
127
|
+
}>>;
|
|
128
|
+
}, "strip", z.ZodTypeAny, {
|
|
129
|
+
height: number;
|
|
130
|
+
color: string;
|
|
131
|
+
enabled: boolean;
|
|
132
|
+
columns: {
|
|
133
|
+
width: number;
|
|
134
|
+
offset: number;
|
|
135
|
+
color: string;
|
|
136
|
+
spacing: number;
|
|
137
|
+
enabled: boolean;
|
|
138
|
+
};
|
|
139
|
+
doorway: {
|
|
140
|
+
color: string;
|
|
141
|
+
enabled: boolean;
|
|
142
|
+
opening: number;
|
|
143
|
+
};
|
|
144
|
+
}, {
|
|
145
|
+
height?: number | undefined;
|
|
146
|
+
color?: string | undefined;
|
|
147
|
+
enabled?: boolean | undefined;
|
|
148
|
+
columns?: {
|
|
149
|
+
width?: number | undefined;
|
|
150
|
+
offset?: number | undefined;
|
|
151
|
+
color?: string | undefined;
|
|
152
|
+
spacing?: number | undefined;
|
|
153
|
+
enabled?: boolean | undefined;
|
|
154
|
+
} | undefined;
|
|
155
|
+
doorway?: {
|
|
156
|
+
color?: string | undefined;
|
|
157
|
+
enabled?: boolean | undefined;
|
|
158
|
+
opening?: number | undefined;
|
|
159
|
+
} | undefined;
|
|
160
|
+
}>;
|
|
161
|
+
/**
|
|
162
|
+
* The print: what happens to the frame after the scene is drawn.
|
|
163
|
+
*
|
|
164
|
+
* This lives on the stage rather than on the lighting rig, even though it
|
|
165
|
+
* belongs to the same family as `exposure` and `film`, because the rig is
|
|
166
|
+
* read by `<Paper>` too and `<Paper>` has no composer. A grade in the rig
|
|
167
|
+
* would be a promise one of the two modes could not keep.
|
|
168
|
+
*
|
|
169
|
+
* Every value defaults to a real look rather than to zero — a stage that
|
|
170
|
+
* asks for nothing should still be graded, and `grade: { bloom: 0 }` is how
|
|
171
|
+
* you say you want it raw.
|
|
172
|
+
*/
|
|
173
|
+
declare const stageGradeSchema: z.ZodObject<{
|
|
174
|
+
/**
|
|
175
|
+
* How far light bleeds past what is emitting it.
|
|
176
|
+
*
|
|
177
|
+
* This is the one that matters most in a backlit hall, because the source
|
|
178
|
+
* plane is drawn with `toneMapped: false` — it is light, not an object, so
|
|
179
|
+
* no tone curve ever rolls it off. Bloom is the only thing that gives it
|
|
180
|
+
* an edge that behaves like light instead of like a lit rectangle.
|
|
181
|
+
*/
|
|
182
|
+
bloom: z.ZodDefault<z.ZodNumber>;
|
|
183
|
+
/**
|
|
184
|
+
* How bright a pixel has to be before it blooms at all, in LINEAR light.
|
|
185
|
+
*
|
|
186
|
+
* Above 1.0 is not only legal, it is the useful range — and that is the
|
|
187
|
+
* whole reason the bound is 4 rather than 1. Bloom reads the scene before
|
|
188
|
+
* the tone curve, while values are still unbounded, so "1.0" means "as
|
|
189
|
+
* bright as white" rather than "as bright as the brightest pixel on
|
|
190
|
+
* screen". Lit near-white paper sits close to 1.0 all by itself; the
|
|
191
|
+
* source burns at `SOURCE_INTENSITY`, several times that. A threshold
|
|
192
|
+
* under 1 therefore blooms the PAPER, which fogs the hall and costs the
|
|
193
|
+
* sheets their edges — the exact failure this default is set to avoid.
|
|
194
|
+
*/
|
|
195
|
+
threshold: z.ZodDefault<z.ZodNumber>;
|
|
196
|
+
/**
|
|
197
|
+
* Depth falloff — how much the near and far ends of the walk go soft.
|
|
198
|
+
*
|
|
199
|
+
* **Defaults to 0, and that is a considered default rather than a stub.**
|
|
200
|
+
* Depth in this scene is already staged by haze, which is how a real hall
|
|
201
|
+
* does it and which costs one fragment instruction; optical blur is a
|
|
202
|
+
* second full-screen pass with a circle-of-confusion buffer behind it, and
|
|
203
|
+
* it is the effect most likely to read as a video game rather than as a
|
|
204
|
+
* photograph. Every paper installation worth copying is shot deep — an
|
|
205
|
+
* f/11 room where the sheets at the far end are as sharp as the ones you
|
|
206
|
+
* can touch.
|
|
207
|
+
*
|
|
208
|
+
* It is here because a shallow frame is a legitimate look and the schema
|
|
209
|
+
* is the only place a look is allowed to live. Turn it up for a close shot
|
|
210
|
+
* on one banner; leave it alone for a hall.
|
|
211
|
+
*/
|
|
212
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
213
|
+
/** How far the corners fall off. A frame with no edge reads as a viewport rather than a photograph. */
|
|
214
|
+
vignette: z.ZodDefault<z.ZodNumber>;
|
|
215
|
+
/**
|
|
216
|
+
* Film grain.
|
|
217
|
+
*
|
|
218
|
+
* Worth more here than in most scenes: grain is the one texture shared
|
|
219
|
+
* between the render and the thing being rendered. Keep it under ~0.05 —
|
|
220
|
+
* past that it stops reading as stock and starts reading as noise.
|
|
221
|
+
*/
|
|
222
|
+
grain: z.ZodDefault<z.ZodNumber>;
|
|
223
|
+
}, "strip", z.ZodTypeAny, {
|
|
224
|
+
grain: number;
|
|
225
|
+
depth: number;
|
|
226
|
+
bloom: number;
|
|
227
|
+
threshold: number;
|
|
228
|
+
vignette: number;
|
|
229
|
+
}, {
|
|
230
|
+
grain?: number | undefined;
|
|
231
|
+
depth?: number | undefined;
|
|
232
|
+
bloom?: number | undefined;
|
|
233
|
+
threshold?: number | undefined;
|
|
234
|
+
vignette?: number | undefined;
|
|
235
|
+
}>;
|
|
236
|
+
declare const stageSchema: z.ZodObject<{
|
|
237
|
+
path: z.ZodDefault<z.ZodObject<{
|
|
238
|
+
points: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">>;
|
|
239
|
+
closed: z.ZodDefault<z.ZodBoolean>;
|
|
240
|
+
}, "strip", z.ZodTypeAny, {
|
|
241
|
+
points: [number, number][];
|
|
242
|
+
closed: boolean;
|
|
243
|
+
}, {
|
|
244
|
+
points?: [number, number][] | undefined;
|
|
245
|
+
closed?: boolean | undefined;
|
|
246
|
+
}>>;
|
|
247
|
+
shot: z.ZodDefault<z.ZodObject<{
|
|
248
|
+
shot: z.ZodDefault<z.ZodEnum<["follow", "lead", "low", "wide"]>>;
|
|
249
|
+
distance: z.ZodDefault<z.ZodNumber>;
|
|
250
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
251
|
+
lookAhead: z.ZodDefault<z.ZodNumber>;
|
|
252
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
253
|
+
}, "strip", z.ZodTypeAny, {
|
|
254
|
+
height: number;
|
|
255
|
+
offset: number;
|
|
256
|
+
distance: number;
|
|
257
|
+
shot: "low" | "follow" | "lead" | "wide";
|
|
258
|
+
lookAhead: number;
|
|
259
|
+
}, {
|
|
260
|
+
height?: number | undefined;
|
|
261
|
+
offset?: number | undefined;
|
|
262
|
+
distance?: number | undefined;
|
|
263
|
+
shot?: "low" | "follow" | "lead" | "wide" | undefined;
|
|
264
|
+
lookAhead?: number | undefined;
|
|
265
|
+
}>>;
|
|
266
|
+
figure: z.ZodDefault<z.ZodObject<{
|
|
267
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
268
|
+
speed: z.ZodDefault<z.ZodNumber>;
|
|
269
|
+
stride: z.ZodDefault<z.ZodNumber>;
|
|
270
|
+
swing: z.ZodDefault<z.ZodNumber>;
|
|
271
|
+
color: z.ZodDefault<z.ZodString>;
|
|
272
|
+
finish: z.ZodDefault<z.ZodEnum<["silhouette", "shaded"]>>;
|
|
273
|
+
gait: z.ZodDefault<z.ZodEnum<["auto", "walk", "run"]>>;
|
|
274
|
+
model: z.ZodOptional<z.ZodString>;
|
|
275
|
+
}, "strip", z.ZodTypeAny, {
|
|
276
|
+
height: number;
|
|
277
|
+
speed: number;
|
|
278
|
+
color: string;
|
|
279
|
+
stride: number;
|
|
280
|
+
swing: number;
|
|
281
|
+
finish: "silhouette" | "shaded";
|
|
282
|
+
gait: "auto" | "walk" | "run";
|
|
283
|
+
model?: string | undefined;
|
|
284
|
+
}, {
|
|
285
|
+
height?: number | undefined;
|
|
286
|
+
speed?: number | undefined;
|
|
287
|
+
color?: string | undefined;
|
|
288
|
+
stride?: number | undefined;
|
|
289
|
+
swing?: number | undefined;
|
|
290
|
+
finish?: "silhouette" | "shaded" | undefined;
|
|
291
|
+
gait?: "auto" | "walk" | "run" | undefined;
|
|
292
|
+
model?: string | undefined;
|
|
293
|
+
}>>;
|
|
294
|
+
/** Stage mode is built for `nave`; the others are all front-lit. */
|
|
295
|
+
lighting: z.ZodDefault<z.ZodEnum<["studio", "window", "leaves", "goldenhour", "noir", "nave", "raking", "lightbox"]>>;
|
|
296
|
+
/**
|
|
297
|
+
* The light, by hand: exposure, key, direction, height, ambient, studio,
|
|
298
|
+
* haze. Overrides on `lighting` rather than a replacement for it, so a
|
|
299
|
+
* shared stage carries the sliders that were moved and nothing else.
|
|
300
|
+
*/
|
|
301
|
+
light: z.ZodDefault<z.ZodObject<{
|
|
302
|
+
exposure: z.ZodOptional<z.ZodNumber>;
|
|
303
|
+
film: z.ZodOptional<z.ZodEnum<["agx", "neutral", "filmic"]>>;
|
|
304
|
+
key: z.ZodOptional<z.ZodNumber>;
|
|
305
|
+
color: z.ZodOptional<z.ZodString>;
|
|
306
|
+
direction: z.ZodOptional<z.ZodNumber>;
|
|
307
|
+
height: z.ZodOptional<z.ZodNumber>;
|
|
308
|
+
ambient: z.ZodOptional<z.ZodNumber>;
|
|
309
|
+
studio: z.ZodOptional<z.ZodNumber>;
|
|
310
|
+
haze: z.ZodOptional<z.ZodNumber>;
|
|
311
|
+
}, "strip", z.ZodTypeAny, {
|
|
312
|
+
key?: number | undefined;
|
|
313
|
+
height?: number | undefined;
|
|
314
|
+
color?: string | undefined;
|
|
315
|
+
studio?: number | undefined;
|
|
316
|
+
exposure?: number | undefined;
|
|
317
|
+
film?: "agx" | "neutral" | "filmic" | undefined;
|
|
318
|
+
direction?: number | undefined;
|
|
319
|
+
ambient?: number | undefined;
|
|
320
|
+
haze?: number | undefined;
|
|
321
|
+
}, {
|
|
322
|
+
key?: number | undefined;
|
|
323
|
+
height?: number | undefined;
|
|
324
|
+
color?: string | undefined;
|
|
325
|
+
studio?: number | undefined;
|
|
326
|
+
exposure?: number | undefined;
|
|
327
|
+
film?: "agx" | "neutral" | "filmic" | undefined;
|
|
328
|
+
direction?: number | undefined;
|
|
329
|
+
ambient?: number | undefined;
|
|
330
|
+
haze?: number | undefined;
|
|
331
|
+
}>>;
|
|
332
|
+
/**
|
|
333
|
+
* OFF by default now.
|
|
334
|
+
*
|
|
335
|
+
* The figure existed to say "this is a room at gallery scale", which is a
|
|
336
|
+
* real job and the right instinct. A rendered human is simply the most
|
|
337
|
+
* expensive and least reliable way to do it: it is the one thing in frame
|
|
338
|
+
* every viewer appraises, and a low-polygon one reads as an asset-store
|
|
339
|
+
* placeholder no matter how good the hall around it is.
|
|
340
|
+
*
|
|
341
|
+
* `stageRoomSchema` does the job instead, with objects whose size the
|
|
342
|
+
* viewer already knows. And the deciding argument is that the stage is
|
|
343
|
+
* NAVIGABLE — drag, wheel, arrow-step, click-to-approach — so there is
|
|
344
|
+
* already a person in the hall and it is the viewer. A second one walking
|
|
345
|
+
* the same aisle on its own clock competes for that role.
|
|
346
|
+
*
|
|
347
|
+
* Still one flag away for anyone who wants it.
|
|
348
|
+
*/
|
|
349
|
+
showFigure: z.ZodDefault<z.ZodBoolean>;
|
|
350
|
+
source: z.ZodDefault<z.ZodObject<{
|
|
351
|
+
/** The bright void the walk resolves toward. Without it the vanishing point is a hole. */
|
|
352
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
353
|
+
color: z.ZodDefault<z.ZodString>;
|
|
354
|
+
/** How far past the end of the walk it stands, world units. */
|
|
355
|
+
beyond: z.ZodDefault<z.ZodNumber>;
|
|
356
|
+
/**
|
|
357
|
+
* A cyclorama around the whole stage, graded from the source colour at the
|
|
358
|
+
* horizon to near-dark overhead. The source plane only faces down the walk,
|
|
359
|
+
* so without this every shot that isn't axial — `wide` especially — looks
|
|
360
|
+
* out at a black void where the room should be.
|
|
361
|
+
*/
|
|
362
|
+
surround: z.ZodDefault<z.ZodBoolean>;
|
|
363
|
+
/** Colour overhead. The horizon takes the source's own colour. */
|
|
364
|
+
zenith: z.ZodDefault<z.ZodString>;
|
|
365
|
+
/**
|
|
366
|
+
* Size, as a multiple of the PAPER height.
|
|
367
|
+
*
|
|
368
|
+
* It is an OPENING, not a wall. At 5 the plane was 100 units across and
|
|
369
|
+
* filled the entire frame behind the colonnade, so the hall had no dark
|
|
370
|
+
* end to resolve toward and the whole picture sat at one value. Sized to
|
|
371
|
+
* roughly the height of the paper it stands behind, it reads as the way
|
|
372
|
+
* out — which is what the figure is walking toward.
|
|
373
|
+
*/
|
|
374
|
+
spread: z.ZodDefault<z.ZodNumber>;
|
|
375
|
+
}, "strip", z.ZodTypeAny, {
|
|
376
|
+
color: string;
|
|
377
|
+
enabled: boolean;
|
|
378
|
+
spread: number;
|
|
379
|
+
zenith: string;
|
|
380
|
+
beyond: number;
|
|
381
|
+
surround: boolean;
|
|
382
|
+
}, {
|
|
383
|
+
color?: string | undefined;
|
|
384
|
+
enabled?: boolean | undefined;
|
|
385
|
+
spread?: number | undefined;
|
|
386
|
+
zenith?: string | undefined;
|
|
387
|
+
beyond?: number | undefined;
|
|
388
|
+
surround?: boolean | undefined;
|
|
389
|
+
}>>;
|
|
390
|
+
ground: z.ZodDefault<z.ZodObject<{
|
|
391
|
+
/** The floor. Without something to catch the shadows there is no ground and no scale. */
|
|
392
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
393
|
+
/**
|
|
394
|
+
* Lifted off near-black (`#0e0b09`). A floor dark enough to disappear
|
|
395
|
+
* cannot show its own seams, and the seams are the scale cue — the hall
|
|
396
|
+
* kept its contrast against the source and gained a surface you can read
|
|
397
|
+
* the size of the room from.
|
|
398
|
+
*/
|
|
399
|
+
color: z.ZodDefault<z.ZodString>;
|
|
400
|
+
/**
|
|
401
|
+
* Width of one poured slab, in world units. 0 leaves the floor unseamed.
|
|
402
|
+
*
|
|
403
|
+
* The cheapest scale cue there is, and the one this scene most lacked. A
|
|
404
|
+
* concrete floor is poured in bays of roughly two and a half metres, and a
|
|
405
|
+
* viewer knows that without being told — so a floor with seams in it
|
|
406
|
+
* states the size of the room, while a floor without them is a gradient
|
|
407
|
+
* that happens to be horizontal.
|
|
408
|
+
*/
|
|
409
|
+
slab: z.ZodDefault<z.ZodNumber>;
|
|
410
|
+
}, "strip", z.ZodTypeAny, {
|
|
411
|
+
color: string;
|
|
412
|
+
enabled: boolean;
|
|
413
|
+
slab: number;
|
|
414
|
+
}, {
|
|
415
|
+
color?: string | undefined;
|
|
416
|
+
enabled?: boolean | undefined;
|
|
417
|
+
slab?: number | undefined;
|
|
418
|
+
}>>;
|
|
419
|
+
/** Ceiling and the architecture around the walk — see `stageRoomSchema`. */
|
|
420
|
+
room: z.ZodDefault<z.ZodObject<{
|
|
421
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
422
|
+
/**
|
|
423
|
+
* Ceiling height, as a multiple of the paper's own height.
|
|
424
|
+
*
|
|
425
|
+
* Relative rather than absolute because the banners ARE the architecture
|
|
426
|
+
* here: a hall whose ceiling sits just above its hangings reads as built
|
|
427
|
+
* for them, and one at a fixed world height reads as whatever the paper
|
|
428
|
+
* happened to be scaled to that day.
|
|
429
|
+
*/
|
|
430
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
431
|
+
color: z.ZodDefault<z.ZodString>;
|
|
432
|
+
/** Columns flanking the walk — see `stageColumnsSchema`. */
|
|
433
|
+
columns: z.ZodDefault<z.ZodObject<{
|
|
434
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
435
|
+
/** Centres this far apart along the walk. Roughly a bay. */
|
|
436
|
+
spacing: z.ZodDefault<z.ZodNumber>;
|
|
437
|
+
/** Shaft width. The number doing the work — a column is a known size. */
|
|
438
|
+
width: z.ZodDefault<z.ZodNumber>;
|
|
439
|
+
/**
|
|
440
|
+
* How far off the walk's centreline each rank stands.
|
|
441
|
+
*
|
|
442
|
+
* Outside the banners, always. Columns are the room; the paper is the
|
|
443
|
+
* subject, and a column standing between the viewer and a banner has
|
|
444
|
+
* swapped the two over. Default clears a `colonnade`'s widest sensible
|
|
445
|
+
* aisle with room to spare.
|
|
446
|
+
*/
|
|
447
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
448
|
+
/**
|
|
449
|
+
* Stone, and darker than paper on purpose.
|
|
450
|
+
*
|
|
451
|
+
* The brightest thing in any of these frames has to be the light, and the
|
|
452
|
+
* second brightest has to be the paper. A column the same value as a
|
|
453
|
+
* banner does not read as architecture behind the subject; it reads as
|
|
454
|
+
* more banners, and the eye stops being able to tell what the room is made
|
|
455
|
+
* of from what is hanging in it.
|
|
456
|
+
*/
|
|
457
|
+
color: z.ZodDefault<z.ZodString>;
|
|
458
|
+
}, "strip", z.ZodTypeAny, {
|
|
459
|
+
width: number;
|
|
460
|
+
offset: number;
|
|
461
|
+
color: string;
|
|
462
|
+
spacing: number;
|
|
463
|
+
enabled: boolean;
|
|
464
|
+
}, {
|
|
465
|
+
width?: number | undefined;
|
|
466
|
+
offset?: number | undefined;
|
|
467
|
+
color?: string | undefined;
|
|
468
|
+
spacing?: number | undefined;
|
|
469
|
+
enabled?: boolean | undefined;
|
|
470
|
+
}>>;
|
|
471
|
+
/** A wall at the end of the walk with the source in it. */
|
|
472
|
+
doorway: z.ZodDefault<z.ZodObject<{
|
|
473
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
474
|
+
/** Opening size, as a multiple of the source's own. 1 frames it exactly. */
|
|
475
|
+
opening: z.ZodDefault<z.ZodNumber>;
|
|
476
|
+
color: z.ZodDefault<z.ZodString>;
|
|
477
|
+
}, "strip", z.ZodTypeAny, {
|
|
478
|
+
color: string;
|
|
479
|
+
enabled: boolean;
|
|
480
|
+
opening: number;
|
|
481
|
+
}, {
|
|
482
|
+
color?: string | undefined;
|
|
483
|
+
enabled?: boolean | undefined;
|
|
484
|
+
opening?: number | undefined;
|
|
485
|
+
}>>;
|
|
486
|
+
}, "strip", z.ZodTypeAny, {
|
|
487
|
+
height: number;
|
|
488
|
+
color: string;
|
|
489
|
+
enabled: boolean;
|
|
490
|
+
columns: {
|
|
491
|
+
width: number;
|
|
492
|
+
offset: number;
|
|
493
|
+
color: string;
|
|
494
|
+
spacing: number;
|
|
495
|
+
enabled: boolean;
|
|
496
|
+
};
|
|
497
|
+
doorway: {
|
|
498
|
+
color: string;
|
|
499
|
+
enabled: boolean;
|
|
500
|
+
opening: number;
|
|
501
|
+
};
|
|
502
|
+
}, {
|
|
503
|
+
height?: number | undefined;
|
|
504
|
+
color?: string | undefined;
|
|
505
|
+
enabled?: boolean | undefined;
|
|
506
|
+
columns?: {
|
|
507
|
+
width?: number | undefined;
|
|
508
|
+
offset?: number | undefined;
|
|
509
|
+
color?: string | undefined;
|
|
510
|
+
spacing?: number | undefined;
|
|
511
|
+
enabled?: boolean | undefined;
|
|
512
|
+
} | undefined;
|
|
513
|
+
doorway?: {
|
|
514
|
+
color?: string | undefined;
|
|
515
|
+
enabled?: boolean | undefined;
|
|
516
|
+
opening?: number | undefined;
|
|
517
|
+
} | undefined;
|
|
518
|
+
}>>;
|
|
519
|
+
/** Thread and clips — see `stageSuspensionSchema`. */
|
|
520
|
+
suspension: z.ZodDefault<z.ZodObject<{
|
|
521
|
+
/**
|
|
522
|
+
* What carries the load.
|
|
523
|
+
*
|
|
524
|
+
* `thread` is monofilament to the ceiling — one straight line per sheet.
|
|
525
|
+
* `rod` is a dowel across each sheet's top edge, hung from the ceiling at
|
|
526
|
+
* both ends, which is a different image entirely: a rank on threads reads
|
|
527
|
+
* as sheets floating in a row, and a rank on rods reads as sheets that
|
|
528
|
+
* were HUNG, by someone, on something. `none` is for a stage where the
|
|
529
|
+
* paper is meant to be impossible.
|
|
530
|
+
*/
|
|
531
|
+
type: z.ZodDefault<z.ZodEnum<["none", "thread", "rod"]>>;
|
|
532
|
+
color: z.ZodDefault<z.ZodString>;
|
|
533
|
+
/**
|
|
534
|
+
* What grips the sheet.
|
|
535
|
+
*
|
|
536
|
+
* A clip is wide and shallow — the bulldog clip of a gallery. A peg is
|
|
537
|
+
* narrow and deep, and grips DOWN the face of the sheet rather than
|
|
538
|
+
* across its edge: the domestic one, a line of paper on a washing line.
|
|
539
|
+
* They are told apart by silhouette at any distance, which is the only
|
|
540
|
+
* thing that survives being one instanced box at the top of an
|
|
541
|
+
* eight-metre banner.
|
|
542
|
+
*
|
|
543
|
+
* This replaced a `clips: boolean`. Two of the four pieces of hardware the
|
|
544
|
+
* plan named — pegs, and a rod — had no way to be asked for, and a boolean
|
|
545
|
+
* cannot grow a third answer.
|
|
546
|
+
*/
|
|
547
|
+
hardware: z.ZodDefault<z.ZodEnum<["none", "clip", "peg"]>>;
|
|
548
|
+
}, "strip", z.ZodTypeAny, {
|
|
549
|
+
type: "none" | "thread" | "rod";
|
|
550
|
+
color: string;
|
|
551
|
+
hardware: "none" | "clip" | "peg";
|
|
552
|
+
}, {
|
|
553
|
+
type?: "none" | "thread" | "rod" | undefined;
|
|
554
|
+
color?: string | undefined;
|
|
555
|
+
hardware?: "none" | "clip" | "peg" | undefined;
|
|
556
|
+
}>>;
|
|
557
|
+
/**
|
|
558
|
+
* The print — bloom, vignette, grain.
|
|
559
|
+
*
|
|
560
|
+
* Needs `@react-three/postprocessing` and `postprocessing`. They are
|
|
561
|
+
* declared OPTIONAL peers, which means `<Paper>` never pulls them in and a
|
|
562
|
+
* bundle that only imports `<Paper>` never contains them — not that a
|
|
563
|
+
* stage renders without them. A bundler asked to resolve `<PaperStage>`
|
|
564
|
+
* without them installed fails at build time, and that is the intended
|
|
565
|
+
* behaviour: a stage silently losing its grade would be worse than a
|
|
566
|
+
* missing-module error that names the package.
|
|
567
|
+
*/
|
|
568
|
+
grade: z.ZodDefault<z.ZodObject<{
|
|
569
|
+
/**
|
|
570
|
+
* How far light bleeds past what is emitting it.
|
|
571
|
+
*
|
|
572
|
+
* This is the one that matters most in a backlit hall, because the source
|
|
573
|
+
* plane is drawn with `toneMapped: false` — it is light, not an object, so
|
|
574
|
+
* no tone curve ever rolls it off. Bloom is the only thing that gives it
|
|
575
|
+
* an edge that behaves like light instead of like a lit rectangle.
|
|
576
|
+
*/
|
|
577
|
+
bloom: z.ZodDefault<z.ZodNumber>;
|
|
578
|
+
/**
|
|
579
|
+
* How bright a pixel has to be before it blooms at all, in LINEAR light.
|
|
580
|
+
*
|
|
581
|
+
* Above 1.0 is not only legal, it is the useful range — and that is the
|
|
582
|
+
* whole reason the bound is 4 rather than 1. Bloom reads the scene before
|
|
583
|
+
* the tone curve, while values are still unbounded, so "1.0" means "as
|
|
584
|
+
* bright as white" rather than "as bright as the brightest pixel on
|
|
585
|
+
* screen". Lit near-white paper sits close to 1.0 all by itself; the
|
|
586
|
+
* source burns at `SOURCE_INTENSITY`, several times that. A threshold
|
|
587
|
+
* under 1 therefore blooms the PAPER, which fogs the hall and costs the
|
|
588
|
+
* sheets their edges — the exact failure this default is set to avoid.
|
|
589
|
+
*/
|
|
590
|
+
threshold: z.ZodDefault<z.ZodNumber>;
|
|
591
|
+
/**
|
|
592
|
+
* Depth falloff — how much the near and far ends of the walk go soft.
|
|
593
|
+
*
|
|
594
|
+
* **Defaults to 0, and that is a considered default rather than a stub.**
|
|
595
|
+
* Depth in this scene is already staged by haze, which is how a real hall
|
|
596
|
+
* does it and which costs one fragment instruction; optical blur is a
|
|
597
|
+
* second full-screen pass with a circle-of-confusion buffer behind it, and
|
|
598
|
+
* it is the effect most likely to read as a video game rather than as a
|
|
599
|
+
* photograph. Every paper installation worth copying is shot deep — an
|
|
600
|
+
* f/11 room where the sheets at the far end are as sharp as the ones you
|
|
601
|
+
* can touch.
|
|
602
|
+
*
|
|
603
|
+
* It is here because a shallow frame is a legitimate look and the schema
|
|
604
|
+
* is the only place a look is allowed to live. Turn it up for a close shot
|
|
605
|
+
* on one banner; leave it alone for a hall.
|
|
606
|
+
*/
|
|
607
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
608
|
+
/** How far the corners fall off. A frame with no edge reads as a viewport rather than a photograph. */
|
|
609
|
+
vignette: z.ZodDefault<z.ZodNumber>;
|
|
610
|
+
/**
|
|
611
|
+
* Film grain.
|
|
612
|
+
*
|
|
613
|
+
* Worth more here than in most scenes: grain is the one texture shared
|
|
614
|
+
* between the render and the thing being rendered. Keep it under ~0.05 —
|
|
615
|
+
* past that it stops reading as stock and starts reading as noise.
|
|
616
|
+
*/
|
|
617
|
+
grain: z.ZodDefault<z.ZodNumber>;
|
|
618
|
+
}, "strip", z.ZodTypeAny, {
|
|
619
|
+
grain: number;
|
|
620
|
+
depth: number;
|
|
621
|
+
bloom: number;
|
|
622
|
+
threshold: number;
|
|
623
|
+
vignette: number;
|
|
624
|
+
}, {
|
|
625
|
+
grain?: number | undefined;
|
|
626
|
+
depth?: number | undefined;
|
|
627
|
+
bloom?: number | undefined;
|
|
628
|
+
threshold?: number | undefined;
|
|
629
|
+
vignette?: number | undefined;
|
|
630
|
+
}>>;
|
|
631
|
+
}, "strip", z.ZodTypeAny, {
|
|
632
|
+
path: {
|
|
633
|
+
points: [number, number][];
|
|
634
|
+
closed: boolean;
|
|
635
|
+
};
|
|
636
|
+
lighting: "studio" | "window" | "leaves" | "goldenhour" | "noir" | "nave" | "raking" | "lightbox";
|
|
637
|
+
figure: {
|
|
638
|
+
height: number;
|
|
639
|
+
speed: number;
|
|
640
|
+
color: string;
|
|
641
|
+
stride: number;
|
|
642
|
+
swing: number;
|
|
643
|
+
finish: "silhouette" | "shaded";
|
|
644
|
+
gait: "auto" | "walk" | "run";
|
|
645
|
+
model?: string | undefined;
|
|
646
|
+
};
|
|
647
|
+
source: {
|
|
648
|
+
color: string;
|
|
649
|
+
enabled: boolean;
|
|
650
|
+
spread: number;
|
|
651
|
+
zenith: string;
|
|
652
|
+
beyond: number;
|
|
653
|
+
surround: boolean;
|
|
654
|
+
};
|
|
655
|
+
light: {
|
|
656
|
+
key?: number | undefined;
|
|
657
|
+
height?: number | undefined;
|
|
658
|
+
color?: string | undefined;
|
|
659
|
+
studio?: number | undefined;
|
|
660
|
+
exposure?: number | undefined;
|
|
661
|
+
film?: "agx" | "neutral" | "filmic" | undefined;
|
|
662
|
+
direction?: number | undefined;
|
|
663
|
+
ambient?: number | undefined;
|
|
664
|
+
haze?: number | undefined;
|
|
665
|
+
};
|
|
666
|
+
shot: {
|
|
667
|
+
height: number;
|
|
668
|
+
offset: number;
|
|
669
|
+
distance: number;
|
|
670
|
+
shot: "low" | "follow" | "lead" | "wide";
|
|
671
|
+
lookAhead: number;
|
|
672
|
+
};
|
|
673
|
+
ground: {
|
|
674
|
+
color: string;
|
|
675
|
+
enabled: boolean;
|
|
676
|
+
slab: number;
|
|
677
|
+
};
|
|
678
|
+
showFigure: boolean;
|
|
679
|
+
room: {
|
|
680
|
+
height: number;
|
|
681
|
+
color: string;
|
|
682
|
+
enabled: boolean;
|
|
683
|
+
columns: {
|
|
684
|
+
width: number;
|
|
685
|
+
offset: number;
|
|
686
|
+
color: string;
|
|
687
|
+
spacing: number;
|
|
688
|
+
enabled: boolean;
|
|
689
|
+
};
|
|
690
|
+
doorway: {
|
|
691
|
+
color: string;
|
|
692
|
+
enabled: boolean;
|
|
693
|
+
opening: number;
|
|
694
|
+
};
|
|
695
|
+
};
|
|
696
|
+
suspension: {
|
|
697
|
+
type: "none" | "thread" | "rod";
|
|
698
|
+
color: string;
|
|
699
|
+
hardware: "none" | "clip" | "peg";
|
|
700
|
+
};
|
|
701
|
+
grade: {
|
|
702
|
+
grain: number;
|
|
703
|
+
depth: number;
|
|
704
|
+
bloom: number;
|
|
705
|
+
threshold: number;
|
|
706
|
+
vignette: number;
|
|
707
|
+
};
|
|
708
|
+
}, {
|
|
709
|
+
path?: {
|
|
710
|
+
points?: [number, number][] | undefined;
|
|
711
|
+
closed?: boolean | undefined;
|
|
712
|
+
} | undefined;
|
|
713
|
+
lighting?: "studio" | "window" | "leaves" | "goldenhour" | "noir" | "nave" | "raking" | "lightbox" | undefined;
|
|
714
|
+
figure?: {
|
|
715
|
+
height?: number | undefined;
|
|
716
|
+
speed?: number | undefined;
|
|
717
|
+
color?: string | undefined;
|
|
718
|
+
stride?: number | undefined;
|
|
719
|
+
swing?: number | undefined;
|
|
720
|
+
finish?: "silhouette" | "shaded" | undefined;
|
|
721
|
+
gait?: "auto" | "walk" | "run" | undefined;
|
|
722
|
+
model?: string | undefined;
|
|
723
|
+
} | undefined;
|
|
724
|
+
source?: {
|
|
725
|
+
color?: string | undefined;
|
|
726
|
+
enabled?: boolean | undefined;
|
|
727
|
+
spread?: number | undefined;
|
|
728
|
+
zenith?: string | undefined;
|
|
729
|
+
beyond?: number | undefined;
|
|
730
|
+
surround?: boolean | undefined;
|
|
731
|
+
} | undefined;
|
|
732
|
+
light?: {
|
|
733
|
+
key?: number | undefined;
|
|
734
|
+
height?: number | undefined;
|
|
735
|
+
color?: string | undefined;
|
|
736
|
+
studio?: number | undefined;
|
|
737
|
+
exposure?: number | undefined;
|
|
738
|
+
film?: "agx" | "neutral" | "filmic" | undefined;
|
|
739
|
+
direction?: number | undefined;
|
|
740
|
+
ambient?: number | undefined;
|
|
741
|
+
haze?: number | undefined;
|
|
742
|
+
} | undefined;
|
|
743
|
+
shot?: {
|
|
744
|
+
height?: number | undefined;
|
|
745
|
+
offset?: number | undefined;
|
|
746
|
+
distance?: number | undefined;
|
|
747
|
+
shot?: "low" | "follow" | "lead" | "wide" | undefined;
|
|
748
|
+
lookAhead?: number | undefined;
|
|
749
|
+
} | undefined;
|
|
750
|
+
ground?: {
|
|
751
|
+
color?: string | undefined;
|
|
752
|
+
enabled?: boolean | undefined;
|
|
753
|
+
slab?: number | undefined;
|
|
754
|
+
} | undefined;
|
|
755
|
+
showFigure?: boolean | undefined;
|
|
756
|
+
room?: {
|
|
757
|
+
height?: number | undefined;
|
|
758
|
+
color?: string | undefined;
|
|
759
|
+
enabled?: boolean | undefined;
|
|
760
|
+
columns?: {
|
|
761
|
+
width?: number | undefined;
|
|
762
|
+
offset?: number | undefined;
|
|
763
|
+
color?: string | undefined;
|
|
764
|
+
spacing?: number | undefined;
|
|
765
|
+
enabled?: boolean | undefined;
|
|
766
|
+
} | undefined;
|
|
767
|
+
doorway?: {
|
|
768
|
+
color?: string | undefined;
|
|
769
|
+
enabled?: boolean | undefined;
|
|
770
|
+
opening?: number | undefined;
|
|
771
|
+
} | undefined;
|
|
772
|
+
} | undefined;
|
|
773
|
+
suspension?: {
|
|
774
|
+
type?: "none" | "thread" | "rod" | undefined;
|
|
775
|
+
color?: string | undefined;
|
|
776
|
+
hardware?: "none" | "clip" | "peg" | undefined;
|
|
777
|
+
} | undefined;
|
|
778
|
+
grade?: {
|
|
779
|
+
grain?: number | undefined;
|
|
780
|
+
depth?: number | undefined;
|
|
781
|
+
bloom?: number | undefined;
|
|
782
|
+
threshold?: number | undefined;
|
|
783
|
+
vignette?: number | undefined;
|
|
784
|
+
} | undefined;
|
|
785
|
+
}>;
|
|
786
|
+
type StageConfig = z.infer<typeof stageSchema>;
|
|
787
|
+
type StageConfigInput = z.input<typeof stageSchema>;
|
|
788
|
+
type StageGradeConfig = z.infer<typeof stageGradeSchema>;
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* Moving through a stage.
|
|
792
|
+
*
|
|
793
|
+
* The scene was a picture you watched: the camera is stationed on the walk,
|
|
794
|
+
* the walk is driven by `progress`, and if nobody supplied one it ran on a
|
|
795
|
+
* clock. There was nothing to touch. This is the other half — the viewer
|
|
796
|
+
* drives the walk themselves, by dragging, by wheel, by arrow key, or by
|
|
797
|
+
* clicking the paper they want to stand in front of.
|
|
798
|
+
*
|
|
799
|
+
* It drives ONE number: distance walked. Everything else in the scene is
|
|
800
|
+
* already derived from that — the figure, the camera, the light at the end —
|
|
801
|
+
* so navigation cannot pull the parts of the scene away from each other,
|
|
802
|
+
* which is the failure this whole component is arranged to prevent. In
|
|
803
|
+
* particular the camera is still not something anything else may move: there
|
|
804
|
+
* is no orbit here, and dragging does not look around. It walks.
|
|
805
|
+
*
|
|
806
|
+
* Pure math lives here so it tests in node; the listeners are in `useWalk`.
|
|
807
|
+
*/
|
|
808
|
+
declare const stageMotionSchema: z.ZodObject<{
|
|
809
|
+
/**
|
|
810
|
+
* Who drives the walk. Same three names as a field's, and they mean the
|
|
811
|
+
* same things — a stage and a field are the same contract seen from two
|
|
812
|
+
* distances.
|
|
813
|
+
*
|
|
814
|
+
* - `drag` — the viewer. Pointer, wheel, arrow keys, or a click on a paper.
|
|
815
|
+
* It DRIFTS on the clock until the first time they touch it, and then it
|
|
816
|
+
* is theirs for good. That is one behaviour rather than two drivers, and
|
|
817
|
+
* it is the default because the alternatives are each half wrong: a stage
|
|
818
|
+
* that only autoplays cannot be touched, and one that only waits opens as
|
|
819
|
+
* a still photograph of itself.
|
|
820
|
+
* - `autoplay` — the clock, and only the clock. It never hands over.
|
|
821
|
+
* - `none` — nothing. The walk stands wherever it was left.
|
|
822
|
+
*
|
|
823
|
+
* An explicit `progress` prop outranks all three: a stage bound to page
|
|
824
|
+
* scroll is a controlled component, and a driver fighting the page for the
|
|
825
|
+
* same number is the bug you would spend an afternoon on.
|
|
826
|
+
*/
|
|
827
|
+
driver: z.ZodDefault<z.ZodEnum<["autoplay", "drag", "none"]>>;
|
|
828
|
+
/** Multiplier on the pace: the figure's walking speed for `autoplay`, the hand for `drag`. */
|
|
829
|
+
speed: z.ZodDefault<z.ZodNumber>;
|
|
830
|
+
/**
|
|
831
|
+
* Whether the walk takes the WHEEL and the TOUCH away from the page.
|
|
832
|
+
*
|
|
833
|
+
* True for a stage that fills the screen — it is the page, so there is
|
|
834
|
+
* nothing to take it from. False for one sitting in a column of prose,
|
|
835
|
+
* where capturing them means a reader who scrolls past it has their scroll
|
|
836
|
+
* eaten and a reader on a phone has their finger trapped. Dragging with a
|
|
837
|
+
* mouse and stepping with the arrow keys work either way, because neither
|
|
838
|
+
* is a gesture the page also wants.
|
|
839
|
+
*
|
|
840
|
+
* Even when captured, the wheel is handed BACK at the ends of an open
|
|
841
|
+
* walk: scrolling past the last banner should carry on down the page
|
|
842
|
+
* rather than press silently into a wall.
|
|
843
|
+
*/
|
|
844
|
+
capture: z.ZodDefault<z.ZodBoolean>;
|
|
845
|
+
}, "strip", z.ZodTypeAny, {
|
|
846
|
+
speed: number;
|
|
847
|
+
driver: "none" | "autoplay" | "drag";
|
|
848
|
+
capture: boolean;
|
|
849
|
+
}, {
|
|
850
|
+
speed?: number | undefined;
|
|
851
|
+
driver?: "none" | "autoplay" | "drag" | undefined;
|
|
852
|
+
capture?: boolean | undefined;
|
|
853
|
+
}>;
|
|
854
|
+
type StageMotion = z.infer<typeof stageMotionSchema>;
|
|
855
|
+
type StageMotionInput = z.input<typeof stageMotionSchema>;
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Render quality tiers.
|
|
859
|
+
*
|
|
860
|
+
* A stage is the heaviest thing this library draws — tens of thousands of
|
|
861
|
+
* subdivided vertices, a shadow pass, a translucent fragment shader and a
|
|
862
|
+
* full-screen backdrop — and it has to run on machines nobody developing it
|
|
863
|
+
* owns. Quality is deliberately NOT part of `stageSchema`: it describes the
|
|
864
|
+
* device, not the artwork, so it must never travel in a preset or a shared
|
|
865
|
+
* link. Two people opening the same link should see the same scene at
|
|
866
|
+
* whatever fidelity their hardware can hold.
|
|
867
|
+
*
|
|
868
|
+
* The five knobs, in the order they actually cost:
|
|
869
|
+
*
|
|
870
|
+
* - `segments` — a CEILING on what `segments: 'auto'` may ask for along the
|
|
871
|
+
* direction a banner's folds run. Quadratic in principle, though a
|
|
872
|
+
* deformer's own floor holds the bottom: `drape` states it needs 48 across
|
|
873
|
+
* its folds, so `low` cannot take the banners below that and should not.
|
|
874
|
+
*
|
|
875
|
+
* It used to be written straight over the sheet's `segments` as a number,
|
|
876
|
+
* and that made it **do nothing at all**. A number applies to BOTH axes,
|
|
877
|
+
* the field caps it at 48 on the way down, and the deformer floor raised
|
|
878
|
+
* it back to 48 on the way up — so every tier drew the identical 48 × 48
|
|
879
|
+
* banner. Measured before the fix: 143,644 triangles at `medium` whatever
|
|
880
|
+
* the tier said. Worth remembering as a shape of bug — a knob nobody had
|
|
881
|
+
* measured, in the file that exists to describe what things cost.
|
|
882
|
+
* - `shadowMapSize` — the shadow pass re-renders the scene's geometry. 0
|
|
883
|
+
* turns shadows off, which on a weak machine is the difference between
|
|
884
|
+
* moving and not.
|
|
885
|
+
* - `dpr` — fragment cost scales with the square of it, and this scene is
|
|
886
|
+
* fragment-heavy (translucency, fog, a full-screen backdrop).
|
|
887
|
+
* - `environment` — the studio light. One prefiltered cube built once, then
|
|
888
|
+
* a texture read per fragment for every lit surface in the scene. Measured
|
|
889
|
+
* at a third of the frame at `medium` (51 ms → 33 ms with it off), which
|
|
890
|
+
* makes it the most expensive single thing here after the geometry, so the
|
|
891
|
+
* bottom tier falls back to the flat ambient it replaced.
|
|
892
|
+
* - `surround` — one more full-screen draw; cheap, but free to drop.
|
|
893
|
+
*/
|
|
894
|
+
declare const qualityNames: readonly ["auto", "low", "medium", "high"];
|
|
895
|
+
type QualityName = (typeof qualityNames)[number];
|
|
896
|
+
type QualityTier = Exclude<QualityName, 'auto'>;
|
|
897
|
+
|
|
898
|
+
interface PaperStageSceneProps {
|
|
899
|
+
/** Walk, shot, figure, lighting — see `stageSchema`. */
|
|
900
|
+
stage?: StageConfigInput;
|
|
901
|
+
/** Any layout, but `colonnade` is the one built to arrange along a walk. */
|
|
902
|
+
layout?: string;
|
|
903
|
+
layoutOptions?: Record<string, unknown>;
|
|
904
|
+
/** Per-banner slots, exactly as in field mode. */
|
|
905
|
+
papers?: FieldPaperSlot[];
|
|
906
|
+
images?: string[];
|
|
907
|
+
/**
|
|
908
|
+
* Words on the banners. A string is split across them a line at a time; an
|
|
909
|
+
* array is used as given. This is the whole point of the mode — a space
|
|
910
|
+
* built out of something the viewer wrote.
|
|
911
|
+
*/
|
|
912
|
+
text?: string | string[];
|
|
913
|
+
/** Shared preset behind every banner. */
|
|
914
|
+
preset?: string | PaperConfigInput;
|
|
915
|
+
/** How many banners, when none of `papers` / `images` / `text` says. */
|
|
916
|
+
count?: number;
|
|
917
|
+
/**
|
|
918
|
+
* How far along the walk the figure is, 0..1. Bind it to scroll and the
|
|
919
|
+
* page scrolls the walk. Omit and `motion` decides who drives.
|
|
920
|
+
*
|
|
921
|
+
* Supplying it makes the stage a CONTROLLED component and outranks
|
|
922
|
+
* `motion` entirely — a driver and a page both writing the same number is
|
|
923
|
+
* a fight, not a feature.
|
|
924
|
+
*/
|
|
925
|
+
progress?: number;
|
|
926
|
+
/**
|
|
927
|
+
* Who drives the walk when `progress` does not: `drag` hands it to the
|
|
928
|
+
* viewer (pointer, wheel, arrow keys, clicking a paper), `autoplay` to the
|
|
929
|
+
* clock, `none` to nobody. Same contract as a field's `motion`.
|
|
930
|
+
*/
|
|
931
|
+
motion?: StageMotionInput;
|
|
932
|
+
/** Fires when the viewer moves to a paper — by clicking it, or by stepping onto it. */
|
|
933
|
+
onVisit?(paper: number): void;
|
|
934
|
+
/**
|
|
935
|
+
* The live position on the walk, 0..1, every frame it changes — whoever is
|
|
936
|
+
* driving. Mirror it into an uncontrolled input to show a scrubber that
|
|
937
|
+
* follows the walk without re-rendering the scene sixty times a second;
|
|
938
|
+
* `<PaperMesh>`'s `onProgress` is the same affordance for a behavior.
|
|
939
|
+
*/
|
|
940
|
+
onProgress?(walk: number): void;
|
|
941
|
+
reducedMotion?: boolean;
|
|
942
|
+
/**
|
|
943
|
+
* How much the render is allowed to cost. `auto` (the default) starts in
|
|
944
|
+
* the middle and adapts to whatever the machine turns out to manage — this
|
|
945
|
+
* scene runs on hardware nobody developing it owns. Not part of the stage
|
|
946
|
+
* config: quality describes the DEVICE, not the artwork, so it must never
|
|
947
|
+
* travel in a preset or a shared link.
|
|
948
|
+
*/
|
|
949
|
+
quality?: QualityName;
|
|
950
|
+
/**
|
|
951
|
+
* Fires when `auto` moves the tier. Useful for showing the viewer what
|
|
952
|
+
* they are getting, and for measuring what real machines settle on.
|
|
953
|
+
*/
|
|
954
|
+
onQualityChange?(tier: QualityTier): void;
|
|
955
|
+
}
|
|
956
|
+
interface PaperStageProps extends PaperStageSceneProps {
|
|
957
|
+
children?: React.ReactNode;
|
|
958
|
+
className?: string;
|
|
959
|
+
style?: React.CSSProperties;
|
|
960
|
+
}
|
|
961
|
+
declare function PaperStageScene({ stage: stageInput, quality, onQualityChange, layout, layoutOptions, papers, images, text, preset, count, progress, motion, onVisit, onProgress, reducedMotion, }: PaperStageSceneProps): react.JSX.Element;
|
|
962
|
+
/** `<PaperStage />` owns its Canvas; `<PaperStageScene />` drops into an existing one. */
|
|
963
|
+
declare function PaperStage({ children, className, style, ...sceneProps }: PaperStageProps): react.JSX.Element;
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* The source's default burn, in linear light.
|
|
967
|
+
*
|
|
968
|
+
* Chosen by matching: at 3.4 the tone-mapped source lands on the same read
|
|
969
|
+
* as the un-mapped plane it replaces, so a stage that never mounts a
|
|
970
|
+
* composer looks the way it always did, and one that does gets a source
|
|
971
|
+
* that blooms instead of a rectangle that clips.
|
|
972
|
+
*/
|
|
973
|
+
declare const SOURCE_INTENSITY = 3.4;
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* Named stages. A mode with no presets asks its visitor to invent a space
|
|
977
|
+
* out of eleven sliders before it will show them anything — and stage mode
|
|
978
|
+
* takes about fifteen seconds to understand once you have seen one, which
|
|
979
|
+
* means the presets ARE the explanation.
|
|
980
|
+
*
|
|
981
|
+
* Each names somewhere paper is actually hung at architectural scale, the
|
|
982
|
+
* same rule the layouts follow.
|
|
983
|
+
*/
|
|
984
|
+
interface StagePreset {
|
|
985
|
+
id: string;
|
|
986
|
+
label: string;
|
|
987
|
+
/** One line, shown under the name. What you are about to look at. */
|
|
988
|
+
description: string;
|
|
989
|
+
stage: StageConfigInput;
|
|
990
|
+
layout: string;
|
|
991
|
+
layoutOptions?: Record<string, unknown>;
|
|
992
|
+
/** The paper itself — banners differ per stage more than anything else. */
|
|
993
|
+
paper?: PaperConfigInput;
|
|
994
|
+
count: number;
|
|
995
|
+
text?: string;
|
|
996
|
+
}
|
|
997
|
+
declare const stagePresets: Record<string, StagePreset>;
|
|
998
|
+
declare function getStagePreset(id: string): StagePreset;
|
|
999
|
+
declare function listStagePresets(): string[];
|
|
1000
|
+
|
|
1001
|
+
/**
|
|
1002
|
+
* The walk — a path across the ground plane that a figure follows and that
|
|
1003
|
+
* layouts arrange paper along. Pure 2D math (x, z on the floor, y is always
|
|
1004
|
+
* up), no three.js, so it tests in node and is cheap enough to call from
|
|
1005
|
+
* inside a layout's pure `pose`.
|
|
1006
|
+
*
|
|
1007
|
+
* Centripetal Catmull-Rom through the control points — it will not cusp or
|
|
1008
|
+
* overshoot when two points bunch together, which a uniform spline does —
|
|
1009
|
+
* resampled to a uniform arc-length polyline. That resampling is the point:
|
|
1010
|
+
* `pointAt(s)` advances at constant SPEED, so a figure stepping `s` forward
|
|
1011
|
+
* at a steady rate covers ground at a steady rate. A raw spline parameter
|
|
1012
|
+
* would have it sprint through the straights and crawl around the corners.
|
|
1013
|
+
*/
|
|
1014
|
+
/** A point on the floor. */
|
|
1015
|
+
type Ground = [x: number, z: number];
|
|
1016
|
+
declare const walkPathSchema: z.ZodObject<{
|
|
1017
|
+
/**
|
|
1018
|
+
* Control points on the ground plane, [x, z]. The default walks away from
|
|
1019
|
+
* the camera down -Z — the shot every reference image is composed on.
|
|
1020
|
+
*/
|
|
1021
|
+
points: z.ZodDefault<z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, "many">>;
|
|
1022
|
+
/** Join the last point back to the first: an endless walk, and the only form `phase` can slide. */
|
|
1023
|
+
closed: z.ZodDefault<z.ZodBoolean>;
|
|
1024
|
+
}, "strip", z.ZodTypeAny, {
|
|
1025
|
+
points: [number, number][];
|
|
1026
|
+
closed: boolean;
|
|
1027
|
+
}, {
|
|
1028
|
+
points?: [number, number][] | undefined;
|
|
1029
|
+
closed?: boolean | undefined;
|
|
1030
|
+
}>;
|
|
1031
|
+
type WalkPathOptions = z.infer<typeof walkPathSchema>;
|
|
1032
|
+
interface WalkPath {
|
|
1033
|
+
/** Total arc length in world units. */
|
|
1034
|
+
readonly length: number;
|
|
1035
|
+
readonly closed: boolean;
|
|
1036
|
+
/** `s` is normalized arc length: 0 = the start, 1 = the end. Closed paths wrap, open paths clamp. */
|
|
1037
|
+
pointAt(s: number): Ground;
|
|
1038
|
+
/** Unit forward direction at `s`. */
|
|
1039
|
+
tangentAt(s: number): Ground;
|
|
1040
|
+
/** Unit LEFT-hand normal at `s` — the side of the aisle a walker's left hand points to. */
|
|
1041
|
+
normalAt(s: number): Ground;
|
|
1042
|
+
}
|
|
1043
|
+
declare function createWalkPath(options: WalkPathOptions): WalkPath;
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* Named walks. A path is a list of control points, which is the right thing
|
|
1047
|
+
* to serialize and the wrong thing to put in front of someone — nobody wants
|
|
1048
|
+
* to type coordinates to find out what a curved colonnade looks like. These
|
|
1049
|
+
* are the shapes worth starting from; every one resolves to ordinary points,
|
|
1050
|
+
* so editing on from here stays possible.
|
|
1051
|
+
*/
|
|
1052
|
+
declare const walkNames: readonly ["straight", "bend", "ess", "ring", "spiral"];
|
|
1053
|
+
type WalkName = (typeof walkNames)[number];
|
|
1054
|
+
declare const walks: Record<WalkName, WalkPathOptions>;
|
|
1055
|
+
declare function getWalk(name: WalkName): WalkPathOptions;
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Where to put the camera on a walk.
|
|
1059
|
+
*
|
|
1060
|
+
* `fitCamera` in field/framing.ts solves a different problem — get every
|
|
1061
|
+
* sheet inside the frustum — and solving it here would produce the neutral
|
|
1062
|
+
* three-quarter product shot that stage mode exists to avoid. These are
|
|
1063
|
+
* SHOTS: a camera stationed relative to the walking figure, framing the
|
|
1064
|
+
* space rather than the objects, with the vanishing point doing the work.
|
|
1065
|
+
*/
|
|
1066
|
+
declare const shotNames: readonly ["follow", "lead", "low", "wide"];
|
|
1067
|
+
type ShotName = (typeof shotNames)[number];
|
|
1068
|
+
declare const shotSchema: z.ZodObject<{
|
|
1069
|
+
shot: z.ZodDefault<z.ZodEnum<["follow", "lead", "low", "wide"]>>;
|
|
1070
|
+
/**
|
|
1071
|
+
* How far the camera stands off the figure ALONG the walk, world units.
|
|
1072
|
+
* `wide` reads it as how far back it stands; how far it steps aside is
|
|
1073
|
+
* derived from the paper, since that is what it has to clear.
|
|
1074
|
+
*/
|
|
1075
|
+
distance: z.ZodDefault<z.ZodNumber>;
|
|
1076
|
+
/** Multiplier on the shot's natural camera height. 1 is as designed. */
|
|
1077
|
+
height: z.ZodDefault<z.ZodNumber>;
|
|
1078
|
+
/** How far up the walk the camera looks past the figure, world units. */
|
|
1079
|
+
lookAhead: z.ZodDefault<z.ZodNumber>;
|
|
1080
|
+
/** Sideways step off the walk line, world units. Positive is the walker's left. */
|
|
1081
|
+
offset: z.ZodDefault<z.ZodNumber>;
|
|
1082
|
+
}, "strip", z.ZodTypeAny, {
|
|
1083
|
+
height: number;
|
|
1084
|
+
offset: number;
|
|
1085
|
+
distance: number;
|
|
1086
|
+
shot: "low" | "follow" | "lead" | "wide";
|
|
1087
|
+
lookAhead: number;
|
|
1088
|
+
}, {
|
|
1089
|
+
height?: number | undefined;
|
|
1090
|
+
offset?: number | undefined;
|
|
1091
|
+
distance?: number | undefined;
|
|
1092
|
+
shot?: "low" | "follow" | "lead" | "wide" | undefined;
|
|
1093
|
+
lookAhead?: number | undefined;
|
|
1094
|
+
}>;
|
|
1095
|
+
type ShotOptions = z.infer<typeof shotSchema>;
|
|
1096
|
+
interface StageShot {
|
|
1097
|
+
position: [x: number, y: number, z: number];
|
|
1098
|
+
target: [x: number, y: number, z: number];
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* What each shot is FOR. A stage has two subjects at very different scales —
|
|
1102
|
+
* a body about 1.75 units tall and paper five times that — and a camera that
|
|
1103
|
+
* only knows about the body frames the body, which is how a colonnade of
|
|
1104
|
+
* printed banners ends up showing its bottom third and the tops of some
|
|
1105
|
+
* letterforms. Camera height stays a body measurement (eye level is eye
|
|
1106
|
+
* level); where it AIMS is a blend, and the paper carries most of it.
|
|
1107
|
+
*/
|
|
1108
|
+
interface StageScale {
|
|
1109
|
+
/** Standing height of the figure. */
|
|
1110
|
+
figure: number;
|
|
1111
|
+
/** Height of the tallest paper on the stage. */
|
|
1112
|
+
paper: number;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* Stage-mode export. Same anatomy and version as the paper and field
|
|
1117
|
+
* exports, with one addition that matters more than the rest: the scroll
|
|
1118
|
+
* variant. `progress` is the whole interaction model of a stage, and a
|
|
1119
|
+
* scroll-driven hero is what most people opening this menu actually want —
|
|
1120
|
+
* so the export writes the pinning and the scroll math, which is the part
|
|
1121
|
+
* that is fiddly to get right and boring to write.
|
|
1122
|
+
*/
|
|
1123
|
+
interface StageExportInput {
|
|
1124
|
+
stage: StageConfigInput;
|
|
1125
|
+
layout: string;
|
|
1126
|
+
layoutOptions?: Record<string, unknown>;
|
|
1127
|
+
/** The banner itself — dims, stock, drape. Omitted uses the built-in banner. */
|
|
1128
|
+
paper?: PaperConfigInput;
|
|
1129
|
+
/** The words the space is built from. Omitted renders blank banners. */
|
|
1130
|
+
text?: string;
|
|
1131
|
+
count?: number;
|
|
1132
|
+
/** Bind the walk to page scroll, pinned, rather than to the clock. */
|
|
1133
|
+
scroll?: boolean;
|
|
1134
|
+
/** Exported component name. */
|
|
1135
|
+
componentName?: string;
|
|
1136
|
+
}
|
|
1137
|
+
/** Which named walk these points are, if any — the export reads better for it. */
|
|
1138
|
+
declare function walkNameFor(path: StageConfig['path']): WalkName | undefined;
|
|
1139
|
+
/** The stage config with defaults removed — what actually needs writing down. */
|
|
1140
|
+
declare function diffStage(stage: StageConfigInput): Record<string, unknown>;
|
|
1141
|
+
/**
|
|
1142
|
+
* JSON.stringify, except an array of plain numbers stays on one line. A walk
|
|
1143
|
+
* is a list of coordinate pairs, and the default pretty-printer spreads each
|
|
1144
|
+
* `[6, 17]` over four lines — twenty lines of punctuation for one gentle
|
|
1145
|
+
* curve. Exported code is a product surface; it should read like something a
|
|
1146
|
+
* person wrote.
|
|
1147
|
+
*/
|
|
1148
|
+
declare function stringifyStage(value: unknown, indent?: number): string;
|
|
1149
|
+
/** The one-line visual an agent verifies after `npm run dev`. */
|
|
1150
|
+
declare function describeStage(input: StageExportInput): string;
|
|
1151
|
+
/** Component source shared by the JSX snippet and the agent payload. */
|
|
1152
|
+
declare function buildStageComponentSource(input: StageExportInput): string;
|
|
1153
|
+
/** The self-contained stage integration brief — one paste into a coding agent. */
|
|
1154
|
+
declare function buildStageAgentPayload(input: StageExportInput): string;
|
|
1155
|
+
|
|
1156
|
+
export { type Ground, PaperStage, type PaperStageProps, PaperStageScene, type PaperStageSceneProps, type QualityName, type QualityTier, SOURCE_INTENSITY, type ShotName, type ShotOptions, type StageConfig, type StageConfigInput, type StageExportInput, type StageGradeConfig, type StageMotion, type StageMotionInput, type StagePreset, type StageScale, type StageShot, type WalkName, type WalkPath, type WalkPathOptions, buildStageAgentPayload, buildStageComponentSource, createWalkPath, describeStage, diffStage, getStagePreset, getWalk, listStagePresets, qualityNames, shotNames, stageGradeSchema, stageMotionSchema, stagePresets, stageRoomSchema, stageSchema, stageSuspensionSchema, stringifyStage, walkNameFor, walkNames, walks };
|