Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 2x 2x 1x 1x 2x 100x 100x 100x | /**
* The turn of a model, shared between the cells that asked to be turned
* together (§25.3).
*
* A store rather than a wire through the deck, for `ui/hoverLocus.ts`'s
* reason: the cell that is being dragged and the cells that follow it are
* peers, and neither should have to know the other exists. The deck holds
* them, but a deck is an arrangement of cells and not a bus between them —
* and the cells that follow are chosen by the reader, one toggle at a time,
* rather than by where they sit.
*
* **Only the two angles travel.** A camera is also a target, a distance and a
* projection, and none of those is *the turn*: two cells looking at one model
* from one angle at two zooms are still the same view of it, and two cells
* each centred on their own bead had a reason for that. Sending the whole
* camera would make *turn together* mean *be the same cell*, which is a thing
* a reader can already have by not opening the second one.
*
* Every subscriber ignores its own, which is what stops a pair of synced cells
* chasing each other round the sphere.
*/
/** Where a model is turned to: the camera's two angles, in radians. */
export interface Turn {
azimuth: number
elevation: number
/** The cell that turned, so the cells that follow can ignore their own. */
source: string
}
const listeners = new Set<(turn: Turn) => void>()
/** Say this cell has turned, for whoever is turning with it. */
export function publishTurn(turn: Turn): void {
for (const listener of listeners) listener(turn)
}
/** Follow the cells that publish a turn. Returns the teardown. */
export function subscribeTurn(listener: (turn: Turn) => void): () => void {
listeners.add(listener)
return () => listeners.delete(listener)
}
|