@johnmorrisdotca/kyogijo-stadiums 0.44.1 → 0.45.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.
@@ -4,6 +4,8 @@ export { buildTurn, floorOptions, openingView } from "./turn.model.ts";
4
4
  export { turnDirection } from "./turn.camera.ts";
5
5
  export type { TurnDirection } from "./turn.camera.ts";
6
6
  export type { TurnModel, TurnSettings } from "./turn.model.ts";
7
+ export { GOVERNOR_TUNING, QUALITIES, QUALITY_TIERS, TIER_PROFILES, createGovernor, handheld, isQuality, qualityOf, rasterOf, tierOf } from "./quality.ts";
8
+ export type { Governor, GovernorTuning, Quality, QualityTier, TierProfile } from "./quality.ts";
7
9
  export { layoutOf, planeMarkup, planeMatrix, turnMarkup, turnMarkupOf } from "./turn.markup.ts";
8
10
  export type { Layout } from "./turn.markup.ts";
9
11
  export { KYOGIJO_TURN_STYLE } from "./turn.style.ts";
@@ -2,6 +2,7 @@
2
2
  export { mountKyogijoTurn, mountTurn, turnSupported } from "./turn.dom.js";
3
3
  export { buildTurn, floorOptions, openingView } from "./turn.model.js";
4
4
  export { turnDirection } from "./turn.camera.js";
5
+ export { GOVERNOR_TUNING, QUALITIES, QUALITY_TIERS, TIER_PROFILES, createGovernor, handheld, isQuality, qualityOf, rasterOf, tierOf } from "./quality.js";
5
6
  export { layoutOf, planeMarkup, planeMatrix, turnMarkup, turnMarkupOf } from "./turn.markup.js";
6
7
  export { KYOGIJO_TURN_STYLE } from "./turn.style.js";
7
8
  export { CURLING_PRESETS, LONG_PRESETS, NET_PRESETS, PITCH_MAX, STEP, TURN_DEFAULT, TURN_PRESETS, TURN_PRESET_NAMES, ZOOM_MAX, ZOOM_MIN, cameraMatrix, clampView, depthOf, drag, eyeDistance, fit, matrix3d, multiply, nudge, presetOf, presetView, presetsFor, project, step } from "./turn.camera.js";
@@ -181,11 +181,12 @@ export function fit(b, view, w, h, distance, pad = 0.03) {
181
181
  }
182
182
  /** Two matrices as one: `b` first, then `a`. */
183
183
  export function multiply(a, b) {
184
- const out = new Array(16).fill(0);
185
- for (let col = 0; col < 4; col += 1)
184
+ const out = new Array(16);
185
+ for (let col = 0; col < 16; col += 4) {
186
+ const [b0, b1, b2, b3] = [b[col], b[col + 1], b[col + 2], b[col + 3]];
186
187
  for (let row = 0; row < 4; row += 1)
187
- for (let k = 0; k < 4; k += 1)
188
- out[col * 4 + row] += a[k * 4 + row] * b[col * 4 + k];
188
+ out[col + row] = a[row] * b0 + a[4 + row] * b1 + a[8 + row] * b2 + a[12 + row] * b3;
189
+ }
189
190
  return out;
190
191
  }
191
192
  const translation = (x, y, z) => [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
@@ -213,11 +214,20 @@ export function cameraMatrix(view, at, distance) {
213
214
  * surface swelled and shrank in steps.
214
215
  */
215
216
  const num = (value) => {
216
- const text = value.toFixed(10).replace(/\.?0+$/, "");
217
- return text === "-0" || text === "" ? "0" : text;
217
+ if (value === 0)
218
+ return "0";
219
+ const text = value.toFixed(10);
220
+ // Without the zeros at the end, and the point if nothing is left after it: the same text as stripping them with a pattern, a good deal faster for the thousands of numbers a turn writes.
221
+ let end = text.length;
222
+ while (text.charCodeAt(end - 1) === 48)
223
+ end -= 1;
224
+ if (text.charCodeAt(end - 1) === 46)
225
+ end -= 1;
226
+ const out = end === text.length ? text : text.slice(0, end);
227
+ return out === "-0" ? "0" : out;
218
228
  };
219
229
  /** A matrix as the CSS `transform` that applies it. */
220
- export const matrix3d = (m) => `matrix3d(${m.map(num).join(",")})`;
230
+ export const matrix3d = (m) => `matrix3d(${num(m[0])},${num(m[1])},${num(m[2])},${num(m[3])},${num(m[4])},${num(m[5])},${num(m[6])},${num(m[7])},${num(m[8])},${num(m[9])},${num(m[10])},${num(m[11])},${num(m[12])},${num(m[13])},${num(m[14])},${num(m[15])})`;
221
231
  /** How far a point is from the eye's plane after the scene is turned and tipped, in pixels towards the eye: bigger is nearer. Planes are drawn far first. */
222
232
  export function depthOf(point, view, at) {
223
233
  const k = at.k * view.zoom;
@@ -2,6 +2,7 @@ import { type TurnDirection, type TurnPreset, type TurnView } from "./turn.camer
2
2
  import { type TurnModel, type TurnSettings } from "./turn.model.ts";
3
3
  import type { ScoreOptions, SurfaceOptions } from "./types.ts";
4
4
  import type { VenueSettings } from "./venue.ts";
5
+ import { type Quality, type QualityTier } from "./quality.ts";
5
6
  import type { OutsideLevel } from "./outside.paint.ts";
6
7
  /** What `mountKyogijoTurn` gives back. `O` is what `update` takes: the options of a drawing, or (for `mountMultiTurn`) of a tournament layout. */
7
8
  export interface KyogijoTurn<O = SurfaceOptions | ScoreOptions> {
@@ -43,6 +44,12 @@ export interface KyogijoTurn<O = SurfaceOptions | ScoreOptions> {
43
44
  mode: string;
44
45
  pixels: number;
45
46
  } | undefined;
47
+ /** What the view was asked to draw: `auto`, or the tier it is held at. */
48
+ readonly quality: Quality;
49
+ /** The tier the view is drawn at now: what `quality` says, and for `auto` the one the frames have led it to (`high` at first). */
50
+ readonly tier: QualityTier;
51
+ /** Change what the view is asked to draw: a tier is taken at once, `auto` goes on from the tier it is at. The camera and the auto-turn are not touched. */
52
+ setQuality(quality: Quality): void;
46
53
  /** The flat drawing that is the floor, or `null` after `destroy`. */
47
54
  svg(): SVGSVGElement | null;
48
55
  /** Stop listening and empty the container. */
package/dist/turn.dom.js CHANGED
@@ -10,6 +10,8 @@ import { KYOGIJO_TURN_STYLE } from "./turn.style.js";
10
10
  import { esc } from "./format.js";
11
11
  import { turnBoardMarkup } from "./overlay.js";
12
12
  import { attachOutside3d } from "./outside.dom.js";
13
+ import { TIER_PROFILES, createGovernor, handheld, layerBudget, qualityOf, rasterOf, rasterShares, tierOf } from "./quality.js";
14
+ import { size } from "./turn.kit.js";
13
15
  /** True where the page can draw a plane in 3D by one `matrix3d`: that is, nearly everywhere with a stylesheet. */
14
16
  export function turnSupported(win = typeof window === "undefined" ? undefined : window) {
15
17
  const css = win?.CSS;
@@ -43,7 +45,33 @@ export function mountTurn(host, options, settings, build) {
43
45
  const win = doc.defaultView;
44
46
  /** The venue's settings as they are now: the mounted ones, altered by `update`. */
45
47
  let venue = settings.venue;
46
- let model = build(options, settings);
48
+ // How much is drawn: what was asked, and the tier it is drawn at (`auto` starts on `high` and is moved by the frames the view makes while it turns).
49
+ let quality = qualityOf(settings.quality);
50
+ let tier = tierOf(quality);
51
+ // (Set again below, once the model is built, for a view that has no tiers.)
52
+ const isHandheld = handheld(win);
53
+ /** The share of its size each layer is made at for a model, now: one number when they all are, one each when the biggest are held to a budget of pixels. */
54
+ const rasterFor = (of) => {
55
+ // (Only a model that has tiers is made smaller: a surface on its own is small, and nothing of it would be left out.)
56
+ if (of.tiered !== true)
57
+ return 1;
58
+ const dpr = win?.devicePixelRatio ?? 1;
59
+ const share = rasterOf(quality, tier, dpr, isHandheld);
60
+ const budget = layerBudget(tier, isHandheld);
61
+ if (share === 1 && budget === Infinity)
62
+ return 1;
63
+ const boxes = [[of.viewBox.w * of.scale, of.viewBox.h * of.scale], ...of.planes.map((p) => { const [w, h] = size(p); return [w * of.scale, h * of.scale]; })];
64
+ return rasterShares(boxes, share, dpr, budget);
65
+ };
66
+ const sameRaster = (a, b) => (typeof a === "number" || typeof b === "number" ? a === b : a.length === b.length && a.every((x, i) => x === b[i]));
67
+ let current = options;
68
+ let model = build(options, { ...settings, quality: tier });
69
+ if (model.tiered !== true)
70
+ tier = "high";
71
+ let raster = rasterFor(model);
72
+ /** The models built at each tier for the options now, so that a step back to a tier is not built again. */
73
+ let made = new Map([[tier, model]]);
74
+ const baseId = model.id;
47
75
  /** What names the four viewpoints: the model's own table (a tournament layout has one), else the sport's. */
48
76
  const sport = () => model.presets ?? model.options.sport;
49
77
  const supported = turnSupported(win ?? undefined) && model.turnable;
@@ -66,6 +94,9 @@ export function mountTurn(host, options, settings, build) {
66
94
  direction: () => turnDirection(settings.direction),
67
95
  setDirection: () => undefined,
68
96
  togglePlay: () => false,
97
+ quality: qualityOf(settings.quality),
98
+ tier: tierOf(settings.quality),
99
+ setQuality: () => undefined,
69
100
  update: (next, change) => {
70
101
  if (change?.venue !== undefined)
71
102
  venue = { ...(typeof venue === "object" ? venue : {}), ...change.venue };
@@ -79,7 +110,7 @@ export function mountTurn(host, options, settings, build) {
79
110
  },
80
111
  };
81
112
  }
82
- host.innerHTML = turnMarkupOf(model, settings);
113
+ host.innerHTML = turnMarkupOf(model, settings, raster);
83
114
  const root = host.querySelector(".ky-turn");
84
115
  const stage = root.querySelector(".ky-turn-view");
85
116
  const live = root.querySelector(".ky-turn-live");
@@ -103,11 +134,14 @@ export function mountTurn(host, options, settings, build) {
103
134
  let written = [];
104
135
  let stacked = [];
105
136
  let faded = [];
137
+ /** Which elements are left out of the view now (the faces of a solid that face away from the eye): they are not written to, and drawn at all, till the view turns them round. */
138
+ let gone = [];
106
139
  const gather = () => {
107
140
  elements = [...stage.querySelectorAll(".ky-turn-floor, .ky-up")];
108
141
  written = elements.map((one) => one.style.transform);
109
142
  stacked = elements.map((one) => one.style.zIndex);
110
143
  faded = elements.map((one) => one.style.opacity);
144
+ gone = elements.map(() => false);
111
145
  };
112
146
  gather();
113
147
  // The crowd outside, a canvas on the floor (the floor's matrix carries it), painted again only when its level, its detail or its colour changes.
@@ -116,8 +150,116 @@ export function mountTurn(host, options, settings, build) {
116
150
  outside?.destroy();
117
151
  const floor = stage.querySelector(".ky-turn-floor");
118
152
  outside = model.outside === undefined || floor === null ? undefined : attachOutside3d(floor, model.outside);
153
+ outside?.setDetail(TIER_PROFILES[tier].outside);
119
154
  };
120
155
  crowd();
156
+ root.dataset.quality = quality;
157
+ root.dataset.tier = tier;
158
+ // ---- Quality: in `auto`, the frames the view makes while it turns decide the tier. ----
159
+ let governor = quality === "auto" && win !== null && model.tiered === true ? createGovernor(tier, settings.qualityTuning) : undefined;
160
+ let meterFrame;
161
+ let lastStamp;
162
+ let lastPaint = 0;
163
+ /** The display's own interval, measured once with nothing else going on: an idle loop of frames a moment after the mount (the lower decile of their intervals, so that a busy moment does not count). */
164
+ let probe;
165
+ let displayMs;
166
+ const probeDisplay = () => {
167
+ if (win === null || probe !== undefined || displayMs !== undefined)
168
+ return;
169
+ const found = [];
170
+ let before;
171
+ const step = (stamp) => {
172
+ probe = undefined;
173
+ if (!alive || win === null)
174
+ return;
175
+ if (doc.hidden === true) {
176
+ // Hidden: start over when it can be seen.
177
+ found.length = 0;
178
+ before = undefined;
179
+ probe = win.setTimeout(() => (probe = win.requestAnimationFrame(step)), 400);
180
+ return;
181
+ }
182
+ if (before !== undefined)
183
+ found.push(stamp - before);
184
+ before = stamp;
185
+ if (found.length < 24)
186
+ probe = win.requestAnimationFrame(step);
187
+ else {
188
+ displayMs = [...found].sort((a, b) => a - b)[Math.floor(found.length * 0.1)];
189
+ governor?.display(displayMs);
190
+ }
191
+ };
192
+ probe = win.setTimeout(() => (probe = win.requestAnimationFrame(step)), 350);
193
+ };
194
+ const stopMeter = () => {
195
+ if (meterFrame !== undefined)
196
+ win?.cancelAnimationFrame(meterFrame);
197
+ meterFrame = undefined;
198
+ lastStamp = undefined;
199
+ };
200
+ if (governor !== undefined)
201
+ probeDisplay();
202
+ /** The loop that times the frames: it runs while the view is being painted and for a third of a second after, and does nothing while the view is still. */
203
+ const meterTick = (stamp) => {
204
+ meterFrame = undefined;
205
+ if (!alive || governor === undefined || win === null)
206
+ return;
207
+ if (doc.hidden === true || stamp - lastPaint > 300) {
208
+ lastStamp = undefined;
209
+ governor.pause();
210
+ return;
211
+ }
212
+ const next = lastStamp === undefined ? undefined : governor.frame(stamp - lastStamp, stamp);
213
+ lastStamp = next === undefined ? stamp : undefined;
214
+ // (A step draws the view again, which asks for the loop itself: only one is ever running.)
215
+ if (next !== undefined)
216
+ retier(next);
217
+ if (meterFrame === undefined)
218
+ meterFrame = win.requestAnimationFrame(meterTick);
219
+ };
220
+ /** The view was painted: the frames are timed from now until it is still. */
221
+ const touched = () => {
222
+ if (governor === undefined || win === null)
223
+ return;
224
+ lastPaint = win.performance.now();
225
+ if (meterFrame === undefined)
226
+ meterFrame = win.requestAnimationFrame(meterTick);
227
+ };
228
+ /** Draw the world again, from the model of the tier and the options now: the camera, the auto-turn and the pointer are not touched (the elements are the only thing replaced). */
229
+ const renderWorld = () => {
230
+ const known = made.get(tier);
231
+ model = known ?? build(current, { ...settings, quality: tier, id: settings.id ?? baseId, venue, preset: undefined, view });
232
+ made.set(tier, model);
233
+ raster = rasterFor(model);
234
+ const layout = layoutOf(model, shown, stage.clientWidth || 960, stage.clientHeight || 600, settings.lens, false, raster);
235
+ const world = root.querySelector(".ky-turn-world");
236
+ world.innerHTML = worldMarkup(model, layout, raster);
237
+ // The look the floor is painted in (and the theme) are attributes of the world.
238
+ for (const name of ["data-sport", "data-look", "data-theme"])
239
+ world.removeAttribute(name);
240
+ world.className = model.look === undefined ? "ky-turn-world" : "ky-turn-world kyogijo";
241
+ if (model.look !== undefined) {
242
+ world.setAttribute("data-sport", model.look.sport);
243
+ world.setAttribute("data-look", model.look.look);
244
+ const forced = model.options.theme;
245
+ if (forced === "light" || forced === "dark")
246
+ world.setAttribute("data-theme", forced);
247
+ }
248
+ gather();
249
+ crowd();
250
+ root.dataset.quality = quality;
251
+ root.dataset.tier = tier;
252
+ };
253
+ /** The governor stepped: draw at the new tier. */
254
+ const retier = (next) => {
255
+ if (next === tier)
256
+ return;
257
+ tier = next;
258
+ renderWorld();
259
+ paint(shown);
260
+ label();
261
+ settings.onQualityChange?.(tier, quality);
262
+ };
121
263
  const buttons = () => root.querySelectorAll("button[data-preset]");
122
264
  /** The Play button says what it is and what it does: pressed while the view turns. */
123
265
  const syncPlay = () => {
@@ -135,9 +277,18 @@ export function mountTurn(host, options, settings, build) {
135
277
  const paint = (now) => {
136
278
  const width = stage.clientWidth || 960;
137
279
  const height = stage.clientHeight || 600;
138
- const layout = layoutOf(model, now, width, height, settings.lens);
280
+ const layout = layoutOf(model, now, width, height, settings.lens, true, raster);
139
281
  outside?.zoom(now.zoom);
282
+ const culled = layout.culled;
140
283
  elements.forEach((one, i) => {
284
+ // A face turned away from the eye is hidden by the solid it belongs to: it is taken out of the page's drawing, not written to.
285
+ const away = culled?.[i] === true;
286
+ if (away !== gone[i]) {
287
+ one.style.display = away ? "none" : "";
288
+ gone[i] = away;
289
+ }
290
+ if (away)
291
+ return;
141
292
  if (written[i] !== layout.transforms[i])
142
293
  one.style.transform = written[i] = layout.transforms[i];
143
294
  const z = String(layout.stack[i]);
@@ -147,6 +298,7 @@ export function mountTurn(host, options, settings, build) {
147
298
  if (faded[i] !== o)
148
299
  one.style.opacity = faded[i] = o;
149
300
  });
301
+ touched();
150
302
  };
151
303
  const label = () => {
152
304
  const here = presetOf(view, sport());
@@ -469,25 +621,11 @@ export function mountTurn(host, options, settings, build) {
469
621
  return;
470
622
  if (change?.venue !== undefined)
471
623
  venue = { ...(typeof venue === "object" ? venue : {}), ...change.venue };
472
- model = build(next, { ...settings, id: settings.id ?? model.id, venue, preset: undefined, view });
624
+ current = next;
625
+ made = new Map();
473
626
  view = clampView(view);
627
+ renderWorld();
474
628
  opening = openingView(settings, sport());
475
- const layout = layoutOf(model, shown, stage.clientWidth || 960, stage.clientHeight || 600, settings.lens);
476
- const world = root.querySelector(".ky-turn-world");
477
- world.innerHTML = worldMarkup(model, layout);
478
- // The look the floor is painted in (and the theme) are attributes of the world.
479
- for (const name of ["data-sport", "data-look", "data-theme"])
480
- world.removeAttribute(name);
481
- world.className = model.look === undefined ? "ky-turn-world" : "ky-turn-world kyogijo";
482
- if (model.look !== undefined) {
483
- world.setAttribute("data-sport", model.look.sport);
484
- world.setAttribute("data-look", model.look.look);
485
- const forced = model.options.theme;
486
- if (forced === "light" || forced === "dark")
487
- world.setAttribute("data-theme", forced);
488
- }
489
- gather();
490
- crowd();
491
629
  // The board is a layer of its own over the view, after the scene: it is written again, and the view's turn is not touched.
492
630
  stage.querySelector(".ky-turn-board")?.remove();
493
631
  if (model.board !== undefined)
@@ -513,6 +651,45 @@ export function mountTurn(host, options, settings, build) {
513
651
  get playing() {
514
652
  return playing;
515
653
  },
654
+ get quality() {
655
+ return quality;
656
+ },
657
+ get tier() {
658
+ return tier;
659
+ },
660
+ setQuality(asked) {
661
+ if (!alive)
662
+ return;
663
+ quality = qualityOf(asked, quality);
664
+ const was = tier;
665
+ if (model.tiered !== true) {
666
+ // A view that has no tiers draws as it does whatever is asked: the question is kept, and answered `high`.
667
+ governor = undefined;
668
+ stopMeter();
669
+ tier = "high";
670
+ }
671
+ else if (quality === "auto") {
672
+ stopMeter();
673
+ governor = win === null ? undefined : createGovernor(tier, settings.qualityTuning);
674
+ if (displayMs !== undefined)
675
+ governor?.display(displayMs);
676
+ else
677
+ probeDisplay();
678
+ }
679
+ else {
680
+ governor = undefined;
681
+ stopMeter();
682
+ tier = quality;
683
+ }
684
+ root.dataset.quality = quality;
685
+ // The tier, or the share its layers are made at, has changed: the world is drawn again (the shares are worked out for the model of the tier, in `renderWorld`).
686
+ if (tier !== was || !sameRaster(rasterFor(model), raster)) {
687
+ renderWorld();
688
+ paint(shown);
689
+ label();
690
+ }
691
+ settings.onQualityChange?.(tier, quality);
692
+ },
516
693
  play() {
517
694
  setPlaying(true);
518
695
  return playing;
@@ -545,6 +722,7 @@ export function mountTurn(host, options, settings, build) {
545
722
  outside?.destroy();
546
723
  stop();
547
724
  stopTick();
725
+ stopMeter();
548
726
  seen?.disconnect();
549
727
  doc.removeEventListener("visibilitychange", onVisible);
550
728
  clearTimeout(spoken);
@@ -40,6 +40,11 @@ export interface Plane {
40
40
  * (a raised room is seen through every wall between it and the eye, at a low angle and from straight above alike).
41
41
  */
42
42
  fadeSide?: boolean;
43
+ /**
44
+ * A face of a closed solid that nothing shows through (a building's wall, drawn opaque): the side of it that is the solid's outside, as the way its `u` x `v` points, 1 out of the solid and -1 into it. While the face is turned away
45
+ * from the eye it is hidden by the solid's own near faces, so a page that asks for it (`layoutOf`'s `cull`) leaves it out of the view until the view turns it round, and spends nothing on it.
46
+ */
47
+ cull?: 1 | -1;
43
48
  /** A plate the other planes of its building stand on (a floor of a building picked out): it is placed by its farthest corner, so that it is drawn under everything on it, whatever way the view turns. */
44
49
  under?: boolean;
45
50
  /**
@@ -2,6 +2,8 @@ import { type Placement, type TurnDirection, type TurnView } from "./turn.camera
2
2
  import { type Plane } from "./turn.kit.ts";
3
3
  import { type TurnModel, type TurnSettings } from "./turn.model.ts";
4
4
  import type { ScoreOptions, SurfaceOptions } from "./types.ts";
5
+ /** The share of its size each layer is made at: one number for all, or one for each (the floor first, then the planes in the model's order). */
6
+ export type Raster = number | readonly number[];
5
7
  /**
6
8
  * The matrix that stands a plane in the scene, before the camera: its x along `u`, its y along `v`, its corner `o`, in pixels from the middle of the scene
7
9
  * (`centre`, in feet).
@@ -17,24 +19,30 @@ export declare function groupRanks(groups: readonly {
17
19
  /** Where everything is for a view in a container: the placement, the matrix of each element and its place in the stack. */
18
20
  export interface Layout {
19
21
  at: Placement;
20
- /** The floor, then the planes in the model's order. */
22
+ /** The floor, then the planes in the model's order. A plane that `cull` says is turned away has `""` here. */
21
23
  transforms: string[];
22
24
  /** The stack of each: 0 for the ground of a hall, 1 for the floor, then the planes far to near from 2. */
23
25
  stack: number[];
24
26
  /** How much of each is left: 1 for all but the walls that are between the eye and the surface, which are cut away as the view is low and on their side (`fadeOf`). */
25
27
  fade: number[];
28
+ /** Which elements are not drawn at this view, by their place in `transforms`: the faces of a closed solid that are turned away from the eye (`Plane.cull`). Only when `layoutOf` was asked to leave them out. */
29
+ culled?: boolean[];
26
30
  }
27
- /** Work a view out in a container `width` by `height` pixels. */
28
- export declare function layoutOf(model: TurnModel, view: TurnView, width: number, height: number, lens?: number): Layout;
31
+ /**
32
+ * Work a view out in a container `width` by `height` pixels. With `cull`, the faces of a closed solid that are turned away from the eye (`Plane.cull`) are left out: they have no transform and no place in the stack, and `culled` says
33
+ * which, so that a page need not write them at all; without it every plane is laid out, as a still picture needs. `raster` is the share of its size an element is made at (`rasterOf`): each element's matrix widens it back, so that the
34
+ * picture is the same and the layers hold `raster` squared as many pixels.
35
+ */
36
+ export declare function layoutOf(model: TurnModel, view: TurnView, width: number, height: number, lens?: number, cull?: boolean, raster?: Raster): Layout;
29
37
  /** One plane as an element: its box in pixels and the SVG drawn on it in feet. */
30
- export declare function planeMarkup(p: Plane, scale: number, transform: string, stack: number, fade?: number): string;
38
+ export declare function planeMarkup(p: Plane, scale: number, transform: string, stack: number, fade?: number, raster?: number): string;
31
39
  /**
32
40
  * A plane that is the floor's own drawing seen through its rectangle (`Plane.crop`): the floor's SVG again, its viewBox cut down to the plane's rectangle, in the plane's own box. It is a picture, not a second
33
41
  * description: it carries no role, title or description of its own.
34
42
  */
35
- export declare function cropMarkup(model: TurnModel, p: Plane, transform: string, stack: number, fade?: number): string;
43
+ export declare function cropMarkup(model: TurnModel, p: Plane, transform: string, stack: number, fade?: number, raster?: number): string;
36
44
  /** The floor as an element: the flat drawing, in the pixels of the scene. */
37
- export declare function floorMarkup(model: TurnModel, transform: string, stack: number): string;
45
+ export declare function floorMarkup(model: TurnModel, transform: string, stack: number, raster?: number): string;
38
46
  /** The patterns the venue's planes are drawn with, once, in a box of no size: every plane's SVG reads them by id, and the crowd's colours are on this element. */
39
47
  export declare function defsMarkup(model: TurnModel): string;
40
48
  /**
@@ -43,7 +51,7 @@ export declare function defsMarkup(model: TurnModel): string;
43
51
  */
44
52
  export declare function worldAttributes(model: TurnModel): string;
45
53
  /** The floor and the planes of a model, laid out. */
46
- export declare function worldMarkup(model: TurnModel, layout: Layout): string;
54
+ export declare function worldMarkup(model: TurnModel, layout: Layout, raster?: Raster): string;
47
55
  /** The buttons under the view. */
48
56
  export declare function controlsMarkup(model: TurnModel, view: TurnView, playing?: boolean, direction?: TurnDirection): string;
49
57
  /** The size, in pixels, the first view is worked out for. */
@@ -52,7 +60,7 @@ export declare const sizeOf: (settings: TurnSettings) => {
52
60
  height: number;
53
61
  };
54
62
  /** The 3D view of a model as markup, laid out for `settings.size`; a page's script then makes it turn. */
55
- export declare function turnMarkupOf(model: TurnModel, settings?: TurnSettings): string;
63
+ export declare function turnMarkupOf(model: TurnModel, settings?: TurnSettings, raster?: Raster): string;
56
64
  /**
57
65
  * A surface as a 3D view, as markup: the flat drawing for a floor, what stands on it as planes, and the controls under it. Pure, so it can be made on a
58
66
  * server; it is a still picture until `mountKyogijoTurn` (or the element) makes it turn in a page.