@maxenve/ren-three 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +306 -2
- package/package.json +51 -4
- package/src/index.js +1633 -0
- package/src/surface.js +204 -0
- package/types/index.d.ts +473 -0
- package/types/surface.d.ts +56 -0
package/src/surface.js
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// The portable primitives in a three.js scene: a Surface is a ren-canv
|
|
2
|
+
// Document (layout, portable style, text, editing, selection, the native
|
|
3
|
+
// text entry and the accessibility mirror) drawn with a 2D canvas into a
|
|
4
|
+
// three.js texture.
|
|
5
|
+
//
|
|
6
|
+
// - The overlay: primitives placed in the scene itself lie over the canvas,
|
|
7
|
+
// pixel for pixel, drawn after the scene (a quad in front of an
|
|
8
|
+
// orthographic camera). The whole canvas is its page.
|
|
9
|
+
// - A panel: primitives placed in a three.js object become a plane in that
|
|
10
|
+
// object, as large as their content (`pixel` world units per pixel),
|
|
11
|
+
// facing +z; the texture has `scale` pixels per pixel.
|
|
12
|
+
//
|
|
13
|
+
// Input reaches a surface in its own pixels: the overlay's are the
|
|
14
|
+
// canvas's; a panel's come from the raycast hit's texture coordinate.
|
|
15
|
+
|
|
16
|
+
import { Document, attach } from 'ren-canv';
|
|
17
|
+
import { Replay2D } from 'ren-canv/backend';
|
|
18
|
+
|
|
19
|
+
/** The kinds of ren-canv's items that take the focus: an Edit, an Action. */
|
|
20
|
+
const EDIT = 4;
|
|
21
|
+
const ACTION = 5;
|
|
22
|
+
|
|
23
|
+
/** @typedef {import('./index.js').Renderer} Renderer */
|
|
24
|
+
|
|
25
|
+
export class Surface extends Document {
|
|
26
|
+
/**
|
|
27
|
+
* @param {Renderer} owner @param {boolean} panel
|
|
28
|
+
*/
|
|
29
|
+
constructor(owner, panel) {
|
|
30
|
+
const options = owner.options;
|
|
31
|
+
super(/** @type {any} */ (owner.fonts()), {
|
|
32
|
+
width: panel ? 1 : owner.width,
|
|
33
|
+
height: panel ? 1 : owner.height,
|
|
34
|
+
scale: owner.scale,
|
|
35
|
+
theme: options.theme,
|
|
36
|
+
background: 0,
|
|
37
|
+
aria: options.aria,
|
|
38
|
+
fit: panel,
|
|
39
|
+
layout: options.layout,
|
|
40
|
+
});
|
|
41
|
+
const kit = owner.kit;
|
|
42
|
+
this.owner = owner;
|
|
43
|
+
this.panel = panel;
|
|
44
|
+
this.replay = new Replay2D(
|
|
45
|
+
owner.family,
|
|
46
|
+
owner.picture,
|
|
47
|
+
() => {
|
|
48
|
+
this.damage = true;
|
|
49
|
+
this.full = true;
|
|
50
|
+
this.present();
|
|
51
|
+
},
|
|
52
|
+
owner.monoFamily,
|
|
53
|
+
// A source that fails: its Images hear `error`; one that left the cache is loaded again.
|
|
54
|
+
source => this.failed(source),
|
|
55
|
+
source => this.forgot(source),
|
|
56
|
+
owner.typefaces,
|
|
57
|
+
);
|
|
58
|
+
/** The 2D canvas it draws on, where there is a document. @type {any} */
|
|
59
|
+
this.image = null;
|
|
60
|
+
/** @type {any} */
|
|
61
|
+
this.ctx = null;
|
|
62
|
+
const doc = owner.canvas?.ownerDocument ?? null;
|
|
63
|
+
if (doc !== null) {
|
|
64
|
+
const image = doc.createElement('canvas');
|
|
65
|
+
const ctx = typeof image.getContext === 'function' ? image.getContext('2d') : null;
|
|
66
|
+
if (ctx != null) {
|
|
67
|
+
this.image = image;
|
|
68
|
+
this.ctx = ctx;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
this.texture = new kit.CanvasTexture(this.image ?? undefined);
|
|
72
|
+
if (kit.SRGBColorSpace !== undefined) this.texture.colorSpace = kit.SRGBColorSpace;
|
|
73
|
+
const material = new kit.MeshBasicMaterial({ map: this.texture, transparent: true, toneMapped: false, depthWrite: !panel, side: panel ? kit.DoubleSide : kit.FrontSide });
|
|
74
|
+
// The overlay fills the orthographic view (-1..1); a panel is a unit
|
|
75
|
+
// plane scaled to its size.
|
|
76
|
+
this.mesh = new kit.Mesh(new kit.PlaneGeometry(panel ? 1 : 2, panel ? 1 : 2), material);
|
|
77
|
+
this.mesh.userData.surface = this;
|
|
78
|
+
this.mesh.visible = false;
|
|
79
|
+
this.grow();
|
|
80
|
+
/** Stops the entry and mirror beside the three.js canvas. @type {(() => void) | null} */
|
|
81
|
+
this.stop = null;
|
|
82
|
+
if (owner.canvas != null && doc !== null) this.stop = attach(this, owner.canvas, { input: false, shift: !panel });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
get kind() {
|
|
86
|
+
return 'three';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
get drawing() {
|
|
90
|
+
return this.ctx !== null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Sizes the canvas and the texture to the page, and a panel's plane. */
|
|
94
|
+
grow() {
|
|
95
|
+
const image = this.image;
|
|
96
|
+
if (image !== null) {
|
|
97
|
+
const w = Math.max(1, Math.round(this.width * this.scale));
|
|
98
|
+
const h = Math.max(1, Math.round(this.height * this.scale));
|
|
99
|
+
if (image.width !== w || image.height !== h) {
|
|
100
|
+
image.width = w;
|
|
101
|
+
image.height = h;
|
|
102
|
+
// A texture keeps its size on the GPU: a new size needs a new upload.
|
|
103
|
+
this.texture.dispose();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (this.panel) {
|
|
107
|
+
const pixel = this.owner.pixel;
|
|
108
|
+
this.mesh.scale.set(this.width * pixel, this.height * pixel, 1);
|
|
109
|
+
}
|
|
110
|
+
this.full = true;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
sized() {
|
|
114
|
+
this.grow();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** @param {import('ren-canv/backend').Frame} frame @param {import('ren-canv/backend').Damage | null} damage */
|
|
118
|
+
draw(frame, damage) {
|
|
119
|
+
this.replay.run(this.ctx, frame, this.scale, 0, damage, this.shiftX, this.shiftY);
|
|
120
|
+
this.texture.needsUpdate = true;
|
|
121
|
+
this.owner.dirty = true;
|
|
122
|
+
this.owner.request();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
present() {
|
|
126
|
+
const painted = super.present();
|
|
127
|
+
// Shown while it holds anything.
|
|
128
|
+
const shown = this.root.first !== null || this.overlay.first !== null;
|
|
129
|
+
if (this.mesh.visible !== shown) {
|
|
130
|
+
this.mesh.visible = shown;
|
|
131
|
+
this.owner.dirty = true;
|
|
132
|
+
this.owner.request();
|
|
133
|
+
}
|
|
134
|
+
return painted;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Keyboard focus to `item` in this surface (null blurs), as ren-canv's
|
|
139
|
+
* Document moves it, taking the focus from every other surface of the
|
|
140
|
+
* renderer first: one surface has the focus and hears the keys, also when
|
|
141
|
+
* code focuses an item (`focus()`, `focusFirst()`, ren-core's `$focus`)
|
|
142
|
+
* rather than a press. An item that cannot take the focus (not an Edit
|
|
143
|
+
* or an Action, or disabled) takes it from no other surface. A blur
|
|
144
|
+
* handler there that moves the focus (in its own surface or this one)
|
|
145
|
+
* wins, and `item` hears nothing, as in Chrome.
|
|
146
|
+
* @param {import('ren-canv').Item | null} item @param {boolean} [ring]
|
|
147
|
+
*/
|
|
148
|
+
focus(item, ring = false) {
|
|
149
|
+
if (item !== null && (item.kind === EDIT || item.kind === ACTION) && !item.disabled && !this.closed) {
|
|
150
|
+
const owner = this.owner;
|
|
151
|
+
const before = this.current;
|
|
152
|
+
for (const surface of owner.surfaces) if (surface !== this) surface.focus(null);
|
|
153
|
+
// A blur handler moved the focus: its move wins.
|
|
154
|
+
if (this.current !== before) return;
|
|
155
|
+
for (const surface of owner.surfaces) if (surface !== this && surface.current !== null) return;
|
|
156
|
+
owner.active = this;
|
|
157
|
+
}
|
|
158
|
+
super.focus(item, ring);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Whether the item under a point, or an ancestor, hears a drag or a drop:
|
|
163
|
+
* where the overlay takes files dragged over it though nothing is painted
|
|
164
|
+
* there (a bare View with `onDrop`), as the DOM's element under them.
|
|
165
|
+
* @param {number} x @param {number} y
|
|
166
|
+
*/
|
|
167
|
+
drops(x, y) {
|
|
168
|
+
return this.dropTarget(x, y) !== null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Where a box of the page shows on screen: the overlay's is the canvas's;
|
|
173
|
+
* a panel's corners are projected through the camera.
|
|
174
|
+
* @param {any} canvas @param {number} x @param {number} y @param {number} right @param {number} bottom
|
|
175
|
+
* @returns {[number, number, number, number]}
|
|
176
|
+
*/
|
|
177
|
+
screen(canvas, x, y, right, bottom) {
|
|
178
|
+
if (!this.panel) return super.screen(canvas, x, y, right, bottom);
|
|
179
|
+
const owner = this.owner;
|
|
180
|
+
let left = Infinity;
|
|
181
|
+
let top = Infinity;
|
|
182
|
+
let r = -Infinity;
|
|
183
|
+
let b = -Infinity;
|
|
184
|
+
for (const [px, py] of [[x, y], [right, y], [x, bottom], [right, bottom]]) {
|
|
185
|
+
const [sx, sy] = owner.project(this, px, py);
|
|
186
|
+
left = Math.min(left, sx);
|
|
187
|
+
top = Math.min(top, sy);
|
|
188
|
+
r = Math.max(r, sx);
|
|
189
|
+
b = Math.max(b, sy);
|
|
190
|
+
}
|
|
191
|
+
return [(canvas.offsetLeft ?? 0) + left, (canvas.offsetTop ?? 0) + top, r - left, b - top];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
close() {
|
|
195
|
+
if (this.closed) return;
|
|
196
|
+
if (this.stop !== null) this.stop();
|
|
197
|
+
this.stop = null;
|
|
198
|
+
super.close();
|
|
199
|
+
this.mesh.parent?.remove(this.mesh);
|
|
200
|
+
this.mesh.geometry.dispose();
|
|
201
|
+
this.mesh.material.dispose();
|
|
202
|
+
this.texture.dispose();
|
|
203
|
+
}
|
|
204
|
+
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { Item } from 'ren-canv';
|
|
2
|
+
export { loadLayout, loadShaper, remoteLayout } from 'ren-canv';
|
|
3
|
+
import { Surface } from './surface.js';
|
|
4
|
+
export type Host = import('ren-core/host').Host;
|
|
5
|
+
export type Kit = Record<string, any>;
|
|
6
|
+
export type Drawer = {
|
|
7
|
+
render: (scene: any, camera: any) => void;
|
|
8
|
+
setSize: (width: number, height: number, style?: boolean) => void;
|
|
9
|
+
setPixelRatio?: ((ratio: number) => void) | undefined;
|
|
10
|
+
dispose?: (() => void) | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Loses the WebGL context now (a three.js WebGLRenderer has it).
|
|
13
|
+
*/
|
|
14
|
+
forceContextLoss?: (() => void) | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* its canvas
|
|
17
|
+
*/
|
|
18
|
+
domElement?: any | undefined;
|
|
19
|
+
};
|
|
20
|
+
export type Options = {
|
|
21
|
+
/**
|
|
22
|
+
* The canvas width in CSS pixels; by default the host element's, followed as it resizes (300 without one).
|
|
23
|
+
*/
|
|
24
|
+
width?: number | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The canvas height in CSS pixels; as width (150 without one).
|
|
27
|
+
*/
|
|
28
|
+
height?: number | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* The device pixel ratio (the window's by default).
|
|
31
|
+
*/
|
|
32
|
+
scale?: number | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* What draws: a WebGLRenderer made on the canvas by default (antialiased), or one given, or a function making it from the canvas.
|
|
35
|
+
*/
|
|
36
|
+
renderer?: (Drawer | ((canvas: any) => Drawer)) | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* The camera: a three.js camera, or `{ fov, near, far, position }` for a PerspectiveCamera (50°, 0.1, 1000, at [0, 0, 5] by default). A `<perspectiveCamera main>` in the view replaces it.
|
|
39
|
+
*/
|
|
40
|
+
camera?: any | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* The scene's background color.
|
|
43
|
+
*/
|
|
44
|
+
background?: (number | string) | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* `frame` (default) renders on animation frames; false renders only when `frame()` is called (tests, a host that drives its own loop).
|
|
47
|
+
*/
|
|
48
|
+
schedule?: ('frame' | false) | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* The bytes of the typeface the primitives are measured and drawn with (needed once a primitive renders).
|
|
51
|
+
*/
|
|
52
|
+
font?: (ArrayBuffer | Uint8Array) | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The bytes of a monospace typeface: text whose `fontFamily` names monospace is measured and drawn in it (in `font` without it).
|
|
55
|
+
*/
|
|
56
|
+
mono?: (ArrayBuffer | Uint8Array) | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Typefaces by family name: text whose `fontFamily` names one (the first of its list given here, before a generic family) is measured and drawn in it.
|
|
59
|
+
*/
|
|
60
|
+
families?: Record<string, ArrayBuffer | Uint8Array> | undefined;
|
|
61
|
+
/**
|
|
62
|
+
* Typefaces for the characters a typeface lacks: each such character is measured and drawn in the first of them that has it.
|
|
63
|
+
*/
|
|
64
|
+
fallback?: (ArrayBuffer | Uint8Array)[] | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* The world units of one pixel of a panel (0.01).
|
|
67
|
+
*/
|
|
68
|
+
pixel?: number | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Theme overrides for the primitives.
|
|
71
|
+
*/
|
|
72
|
+
theme?: import('ren-core/host').Tokens | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* The accessibility mirror of the primitives, as ren-canv's.
|
|
75
|
+
*/
|
|
76
|
+
aria?: (boolean | 'demand') | undefined;
|
|
77
|
+
/**
|
|
78
|
+
* Where the primitives are laid out: this thread by default, or the layout worker `remoteLayout(port)` reaches (ren-canv's).
|
|
79
|
+
*/
|
|
80
|
+
layout?: import('ren-canv').LayoutPort | undefined;
|
|
81
|
+
/**
|
|
82
|
+
* Loads an Image source into something a 2D canvas draws (an HTMLImageElement by default).
|
|
83
|
+
*/
|
|
84
|
+
image?: import('ren-canv/backend').Picture | undefined;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The props `element` reads at creation: the Host's `construct` (compiled
|
|
88
|
+
* templates pass them too), and what a worker serving a ren-three view
|
|
89
|
+
* passes as `serve`'s `construct`. `of` (`<existing>`) cannot cross
|
|
90
|
+
* to a worker: an object made elsewhere belongs to the direct runtime.
|
|
91
|
+
*/
|
|
92
|
+
export declare const CONSTRUCT: Set<string>;
|
|
93
|
+
/**
|
|
94
|
+
* The viewport a primitive's components read (the Host's `viewportOf`):
|
|
95
|
+
* its panel's size when it is placed in a panel whose primitive sets its
|
|
96
|
+
* width and height, else the root's (the canvas's). A panel sized by its
|
|
97
|
+
* content reports the root's: its size follows what it shows, so a view
|
|
98
|
+
* reading its own size could swing between two layouts. The color scheme
|
|
99
|
+
* and motion are the root's either way. A component in a panel runs before
|
|
100
|
+
* its nodes are placed: the source reports the root's until its primitive
|
|
101
|
+
* is placed, then binds to the panel.
|
|
102
|
+
*/
|
|
103
|
+
declare class Region {
|
|
104
|
+
owner: Renderer;
|
|
105
|
+
item: Item;
|
|
106
|
+
/** @type {Set<(width: number, height: number, flags: number) => void>} */
|
|
107
|
+
viewers: Set<(width: number, height: number, flags: number) => void>;
|
|
108
|
+
/** The root's viewport, as it last reported. */
|
|
109
|
+
root: number[];
|
|
110
|
+
/** The primitive placed in the panel it is bound to, whose size is the panel's when it sets one. @type {Item | null} */
|
|
111
|
+
top: Item | null;
|
|
112
|
+
/** @type {(() => void) | null} */
|
|
113
|
+
unroot: (() => void) | null;
|
|
114
|
+
/** @type {(() => void) | null} */
|
|
115
|
+
unpanel: (() => void) | null;
|
|
116
|
+
/** @param {Renderer} owner @param {Item} item */
|
|
117
|
+
constructor(owner: Renderer, item: Item);
|
|
118
|
+
/** @param {(width: number, height: number, flags: number) => void} report @returns {() => void} */
|
|
119
|
+
viewport(report: (width: number, height: number, flags: number) => void): () => void;
|
|
120
|
+
/**
|
|
121
|
+
* Finds where its primitive is placed: a panel (followed), the overlay
|
|
122
|
+
* (the root's). False while it is not placed yet.
|
|
123
|
+
*/
|
|
124
|
+
bind(): boolean;
|
|
125
|
+
/** What it reports now: the panel's size when its primitive sets one, else the root's. @returns {number[]} */
|
|
126
|
+
now(): number[];
|
|
127
|
+
/** Tells every reader. */
|
|
128
|
+
tell(): void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* The three.js renderer: the Host `mount` renders into, and the scene,
|
|
132
|
+
* camera and frame loop it draws.
|
|
133
|
+
*/
|
|
134
|
+
export declare class Renderer {
|
|
135
|
+
kit: Kit;
|
|
136
|
+
construct: Set<string>;
|
|
137
|
+
options: Options;
|
|
138
|
+
/** The scene, and the container views render into. */
|
|
139
|
+
scene: any;
|
|
140
|
+
camera: any;
|
|
141
|
+
/** @type {Drawer | null} */
|
|
142
|
+
drawer: Drawer | null;
|
|
143
|
+
/** The canvas, once open. @type {any} */
|
|
144
|
+
canvas: any;
|
|
145
|
+
/** The host element that open marked (`data-ren-root`), unmarked on close. @type {any} */
|
|
146
|
+
host: any;
|
|
147
|
+
width: number;
|
|
148
|
+
height: number;
|
|
149
|
+
/** Rendered frames. */
|
|
150
|
+
frames: number;
|
|
151
|
+
/** True when the scene changed since the last frame. */
|
|
152
|
+
dirty: boolean;
|
|
153
|
+
/** Per-frame callbacks (`$animate`): false when one threw and nothing handled it. @type {Set<(frame: Tick) => boolean>} */
|
|
154
|
+
animations: Set<(frame: Tick) => boolean>;
|
|
155
|
+
/** The callbacks that had a frame: a callback's first frame has delta 0, whatever time passed before it. @type {WeakSet<(frame: Tick) => boolean>} */
|
|
156
|
+
animated: WeakSet<(frame: Tick) => boolean>;
|
|
157
|
+
/** The pending animation frame, or null. @type {any} */
|
|
158
|
+
pending: any;
|
|
159
|
+
time: number;
|
|
160
|
+
opened: boolean;
|
|
161
|
+
closed: boolean;
|
|
162
|
+
/** Objects with handlers, for the raycast. */
|
|
163
|
+
listening: number;
|
|
164
|
+
/** Objects with a `cursor`: while any, the pointer is raycast for them too. */
|
|
165
|
+
cursors: number;
|
|
166
|
+
/** `<gl>`'s settings by property name, applied to the drawer. @type {any} */
|
|
167
|
+
gl: any;
|
|
168
|
+
/** Object3D's own fields, which a rebuild from new params leaves alone. @type {Set<string> | null} */
|
|
169
|
+
base: Set<string> | null;
|
|
170
|
+
/** The objects under the pointer, nearest first (pointerover/out). @type {any[]} */
|
|
171
|
+
hovered: any[];
|
|
172
|
+
/** Removed nodes whose resources go at the next frame unless they come back. @type {any[]} */
|
|
173
|
+
removed: any[];
|
|
174
|
+
/** @type {(() => void) | null} */
|
|
175
|
+
detach: (() => void) | null;
|
|
176
|
+
/** @type {any} */
|
|
177
|
+
observer: any;
|
|
178
|
+
raycaster: any;
|
|
179
|
+
pointer: any;
|
|
180
|
+
/** The overlay of the primitives placed in the scene, once there is one. @type {Surface | null} */
|
|
181
|
+
overlay: Surface | null;
|
|
182
|
+
/** Its scene and camera, drawn over the scene. @type {any} */
|
|
183
|
+
overlayScene: any;
|
|
184
|
+
/** @type {any} */
|
|
185
|
+
overlayCamera: any;
|
|
186
|
+
/** Every surface, the overlay first. @type {Set<Surface>} */
|
|
187
|
+
surfaces: Set<Surface>;
|
|
188
|
+
/** The root's root-wide listeners (ren-core's `$keys`, `$scrolls` on the scene), heard on every surface; `off` by surface, which goes with it. @type {Set<{ name: string, fn: (event: any) => void, off: Map<Surface, () => void> }>} */
|
|
189
|
+
rooted: Set<{
|
|
190
|
+
name: string;
|
|
191
|
+
fn: (event: any) => void;
|
|
192
|
+
off: Map<Surface, () => void>;
|
|
193
|
+
}>;
|
|
194
|
+
/** The surfaces by their page's root item. @type {WeakMap<Item, Surface>} */
|
|
195
|
+
pages: WeakMap<Item, Surface>;
|
|
196
|
+
/** The measure of the primitives' text. @type {import('ren-canv').Fonts | null} */
|
|
197
|
+
measure: import('ren-canv').Fonts | null;
|
|
198
|
+
/** The font family the 2D canvas draws them in, and its monospace one (when `mono` is given). */
|
|
199
|
+
family: string;
|
|
200
|
+
monoFamily: string | null;
|
|
201
|
+
/** The font family each typeface slot of the measure draws in (the named typefaces, then the fallbacks; none for slot 0). @type {(string | null)[]} */
|
|
202
|
+
typefaces: (string | null)[];
|
|
203
|
+
/** The faces it added to the document's fonts, deleted on close. @type {any[]} */
|
|
204
|
+
faces: any[];
|
|
205
|
+
pixel: number;
|
|
206
|
+
scale: number;
|
|
207
|
+
/** @type {import('ren-canv/backend').Picture | null} */
|
|
208
|
+
picture: import('ren-canv/backend').Picture | null;
|
|
209
|
+
/** The surface keys, copy and select all go to; the one a press grabbed (a drag); the panel under the pointer. @type {Surface | null} */
|
|
210
|
+
active: Surface | null;
|
|
211
|
+
/** @type {Surface | null} */
|
|
212
|
+
grab: Surface | null;
|
|
213
|
+
/** @type {Surface | null} */
|
|
214
|
+
over: Surface | null;
|
|
215
|
+
/** True when the last press went to a surface (its click does not reach the scene). */
|
|
216
|
+
took: boolean;
|
|
217
|
+
/** The surface under a drag over the canvas (null: none). @type {Surface | null} */
|
|
218
|
+
dragged: Surface | null;
|
|
219
|
+
/** Who follows the viewport (ren-core's `$viewport`), and the window's preference queries while one does. @type {Set<(width: number, height: number, flags: number) => void>} */
|
|
220
|
+
viewers: Set<(width: number, height: number, flags: number) => void>;
|
|
221
|
+
/** @type {any[] | null} */
|
|
222
|
+
queries: any[] | null;
|
|
223
|
+
tell: () => void;
|
|
224
|
+
/** Each primitive's viewport source (`viewportOf`), made on first use. @type {WeakMap<Item, Region>} */
|
|
225
|
+
regions: WeakMap<Item, Region>;
|
|
226
|
+
/** The sources followed whose primitive is not placed yet: bound as it is. @type {Set<Region>} */
|
|
227
|
+
unbound: Set<Region>;
|
|
228
|
+
/** The drawer is this renderer's (made here, or by the `renderer` function for its canvas): closing loses its WebGL context. */
|
|
229
|
+
owned: boolean | undefined;
|
|
230
|
+
/** @param {Kit} kit @param {Options} [options] */
|
|
231
|
+
constructor(kit: Kit, options?: Options);
|
|
232
|
+
/** The measure of the primitives' text, read from the `font` (and `mono`) option on first use. @returns {import('ren-canv').Fonts} */
|
|
233
|
+
fonts(): import('ren-canv').Fonts;
|
|
234
|
+
/** The overlay, made on first use. */
|
|
235
|
+
makeOverlay(): Surface;
|
|
236
|
+
/** A new surface: one of this renderer's, hearing the root-wide listeners. @param {Surface} surface */
|
|
237
|
+
adopt(surface: Surface): void;
|
|
238
|
+
/** The surface an item belongs to (the overlay for one not placed yet). @param {Item} item */
|
|
239
|
+
page(item: Item): Surface;
|
|
240
|
+
get kind(): string;
|
|
241
|
+
/** @param {string} tag @param {any} props */
|
|
242
|
+
element(tag: string, props: any): any;
|
|
243
|
+
/** A text node: an item, drawn inside a primitive and nothing among three.js objects. @param {string} value */
|
|
244
|
+
text(value: string): Item;
|
|
245
|
+
/** @param {any} node @param {string} value */
|
|
246
|
+
content(node: any, value: string): void;
|
|
247
|
+
/** @param {any} node @param {string} name @param {any} value @param {any} [previous] */
|
|
248
|
+
set(node: any, name: string, value: any, previous?: any): void;
|
|
249
|
+
/** Writes a property on a three.js object: a dashed name reaches into it. @param {any} node @param {string} name @param {any} value */
|
|
250
|
+
apply(node: any, name: string, value: any): void;
|
|
251
|
+
/**
|
|
252
|
+
* Rebuilds an object in place from new constructor `params`: the node keeps
|
|
253
|
+
* its identity (the view, its parent and its handlers hold it). A fresh
|
|
254
|
+
* object is made and copied in: a scene object takes only what its class
|
|
255
|
+
* sets beyond Object3D's own fields (not its transform or children);
|
|
256
|
+
* anything else (a geometry, a material, a curve) takes its whole state,
|
|
257
|
+
* a geometry's old GPU buffers freed first. The properties the view set
|
|
258
|
+
* apply again after.
|
|
259
|
+
* @param {any} node @param {any} params
|
|
260
|
+
*/
|
|
261
|
+
rebuild(node: any, params: any): void;
|
|
262
|
+
/** @param {any} node @param {string} name @param {(event: any) => void} handler */
|
|
263
|
+
listen(node: any, name: string, handler: (event: any) => void): () => void;
|
|
264
|
+
/** @param {any} parent @param {any} child @param {any} before */
|
|
265
|
+
insert(parent: any, child: any, before: any): void;
|
|
266
|
+
/**
|
|
267
|
+
* Places a primitive linked among three.js objects: in the overlay, in
|
|
268
|
+
* order among the overlay's other primitives, for the scene; in a panel
|
|
269
|
+
* of its own for any other object.
|
|
270
|
+
* @param {any} parent @param {Item} child @param {boolean} moving
|
|
271
|
+
*/
|
|
272
|
+
place(parent: any, child: Item, moving: boolean): void;
|
|
273
|
+
/** @param {any} parent @param {any} child */
|
|
274
|
+
remove(parent: any, child: any): void;
|
|
275
|
+
/** @param {any} parent @param {any} child @param {boolean} moving */
|
|
276
|
+
unlink(parent: any, child: any, moving: boolean): void;
|
|
277
|
+
marker(): Item;
|
|
278
|
+
/** @param {any} node */
|
|
279
|
+
parent(node: any): any;
|
|
280
|
+
/** @param {any} node */
|
|
281
|
+
next(node: any): any;
|
|
282
|
+
/** @param {any} value */
|
|
283
|
+
owns(value: any): boolean;
|
|
284
|
+
layer(): any;
|
|
285
|
+
/**
|
|
286
|
+
* The viewport (ren-core's `$viewport`, `$media`): the canvas's size in
|
|
287
|
+
* CSS pixels, and the color scheme and motion preferences of the window
|
|
288
|
+
* it is in (none without one); now, then on each resize or change.
|
|
289
|
+
* @param {(width: number, height: number, flags: number) => void} report
|
|
290
|
+
* @returns {() => void}
|
|
291
|
+
*/
|
|
292
|
+
viewport(report: (width: number, height: number, flags: number) => void): () => void;
|
|
293
|
+
/**
|
|
294
|
+
* The viewport of the region `node` is in (ren-core's `$viewport` and
|
|
295
|
+
* `$media` in a component built there): a primitive's is its panel's
|
|
296
|
+
* once it is placed in one with a width and height of its own (see
|
|
297
|
+
* Region), else the root's; null (the root's) for a three.js object.
|
|
298
|
+
* @param {any} node
|
|
299
|
+
* @returns {Region | null}
|
|
300
|
+
*/
|
|
301
|
+
viewportOf(node: any): Region | null;
|
|
302
|
+
/** Binds the followed sources whose primitive is placed now. */
|
|
303
|
+
bind(): void;
|
|
304
|
+
/** The viewport's flags: 1 a dark color scheme, 2 reduced motion (the window's media queries). */
|
|
305
|
+
flags(): number;
|
|
306
|
+
/** Follows the window's color scheme and motion preferences, or stops. @param {boolean} on */
|
|
307
|
+
prefer(on: boolean): void;
|
|
308
|
+
/** Reports the viewport to its followers. */
|
|
309
|
+
viewed(): void;
|
|
310
|
+
present(): void;
|
|
311
|
+
/**
|
|
312
|
+
* Prepares an application root: a canvas in its host element (none
|
|
313
|
+
* without a document), the drawer, pointer events and sizing.
|
|
314
|
+
* @param {any} element @param {string} id
|
|
315
|
+
*/
|
|
316
|
+
open(element: any, id: string): any;
|
|
317
|
+
close(): void;
|
|
318
|
+
/** Keeps the camera's aspect ratio to the canvas. */
|
|
319
|
+
aspect(): void;
|
|
320
|
+
/** Sizes the canvas and the camera. @param {number} width @param {number} height */
|
|
321
|
+
resize(width: number, height: number): void;
|
|
322
|
+
/** Follows the host element's size where the options leave it open. @param {any} element */
|
|
323
|
+
fit(element: any): void;
|
|
324
|
+
/** Asks for a frame: on the next animation frame, unless one is pending or frames are driven by hand. */
|
|
325
|
+
request(): void;
|
|
326
|
+
cancel(): void;
|
|
327
|
+
/** @param {number} time */
|
|
328
|
+
tick(time: number): void;
|
|
329
|
+
/**
|
|
330
|
+
* One frame: runs the `$animate` callbacks, then renders if anything changed
|
|
331
|
+
* (an animation always counts as a change).
|
|
332
|
+
* @param {number} [time] milliseconds
|
|
333
|
+
*/
|
|
334
|
+
frame(time?: number): boolean;
|
|
335
|
+
/**
|
|
336
|
+
* The objects at a canvas point, nearest first: three.js intersections
|
|
337
|
+
* (`object`, `point`, `distance`, …).
|
|
338
|
+
* @param {number} x @param {number} y CSS pixels from the canvas's top left
|
|
339
|
+
* @returns {any[]}
|
|
340
|
+
*/
|
|
341
|
+
pick(x: number, y: number): any[];
|
|
342
|
+
/**
|
|
343
|
+
* Dispatches a pointer event at a canvas point: to the nearest object
|
|
344
|
+
* with a handler for `type` and then its ancestors, until one stops it.
|
|
345
|
+
* `pointermove` also sends pointerover and pointerout as the objects
|
|
346
|
+
* under the pointer change. Returns true when a handler ran.
|
|
347
|
+
* @param {string} type a ren-core event name (`click`, `pointerdown`, …)
|
|
348
|
+
* @param {number} x @param {number} y
|
|
349
|
+
* @param {any} [native] the browser event
|
|
350
|
+
* @param {Record<string, any>} [more] fields the event also carries (a drop's `files`)
|
|
351
|
+
*/
|
|
352
|
+
dispatch(type: string, x: number, y: number, native?: any, more?: Record<string, any>): boolean;
|
|
353
|
+
/** The nearest hit and its ancestors that are part of the view. @param {any[]} hits */
|
|
354
|
+
chain(hits: any[]): any[];
|
|
355
|
+
/** @param {any} object @param {string} type @param {any} hit @param {number} x @param {number} y @param {any} native */
|
|
356
|
+
call(object: any, type: string, hit: any, x: number, y: number, native: any): boolean;
|
|
357
|
+
/**
|
|
358
|
+
* The surface and its pixel under a canvas point: the overlay where it
|
|
359
|
+
* has something there, else the nearest panel the ray hits (from its
|
|
360
|
+
* texture coordinate). Null when neither. For a `drag` of files, the
|
|
361
|
+
* overlay also where an item under the point hears drags or drops.
|
|
362
|
+
* @param {number} x @param {number} y @param {boolean} [drag]
|
|
363
|
+
* @returns {[Surface, number, number] | null}
|
|
364
|
+
*/
|
|
365
|
+
surfaceAt(x: number, y: number, drag?: boolean): [Surface, number, number] | null;
|
|
366
|
+
/**
|
|
367
|
+
* A canvas point on a panel's plane, in the panel's pixels, whether the
|
|
368
|
+
* panel is under it or not (a drag that leaves it). Null when the ray
|
|
369
|
+
* misses the plane.
|
|
370
|
+
* @param {Surface} surface @param {number} x @param {number} y
|
|
371
|
+
* @returns {[number, number] | null}
|
|
372
|
+
*/
|
|
373
|
+
onPanel(surface: Surface, x: number, y: number): [number, number] | null;
|
|
374
|
+
/**
|
|
375
|
+
* Where a panel's pixel shows on the canvas, in CSS pixels.
|
|
376
|
+
* @param {Surface} surface @param {number} px @param {number} py
|
|
377
|
+
* @returns {[number, number]}
|
|
378
|
+
*/
|
|
379
|
+
project(surface: Surface, px: number, py: number): [number, number];
|
|
380
|
+
/**
|
|
381
|
+
* One input event at a canvas point: to the primitives first (the overlay,
|
|
382
|
+
* then a panel under the pointer; a drag stays with the surface it
|
|
383
|
+
* started on), then, when they take nothing, raycast into the scene.
|
|
384
|
+
* Returns true when anything handled it.
|
|
385
|
+
* @param {string} type `pointerdown`, `pointermove`, `pointerup`, `pointercancel`, `pointerleave`, `click`, `dblclick`, `contextmenu` or `wheel`
|
|
386
|
+
* @param {number} x @param {number} y @param {any} [native]
|
|
387
|
+
*/
|
|
388
|
+
input(type: string, x: number, y: number, native?: any): boolean;
|
|
389
|
+
/**
|
|
390
|
+
* A drag over the canvas at a point, carrying `files` files of these MIME
|
|
391
|
+
* `types` (all a drag tells before its drop): to the surface under it, as
|
|
392
|
+
* a press (the overlay by point, a panel by the raycast's texture
|
|
393
|
+
* coordinate), whose items hear it as ren-canv's `dragOver` sends it.
|
|
394
|
+
* Moving to another surface leaves the first, then enters the second.
|
|
395
|
+
* Over no surface, the scene's objects under it hear `dragover` through
|
|
396
|
+
* the raycast. Returns whether a surface or an object took it (the
|
|
397
|
+
* browser's default is prevented only then).
|
|
398
|
+
* @param {number} x @param {number} y @param {number} [files] @param {readonly string[]} [types] @param {any} [native]
|
|
399
|
+
*/
|
|
400
|
+
dragOver(x: number, y: number, files?: number, types?: readonly string[], native?: any): boolean;
|
|
401
|
+
/** The drag left the canvas (or was cancelled): the surface under it leaves. */
|
|
402
|
+
dragLeave(): void;
|
|
403
|
+
/**
|
|
404
|
+
* Files dropped at a point: on the surface under it (its items hear
|
|
405
|
+
* `drop` with the files and the point in its pixels), else on the scene's
|
|
406
|
+
* objects through the raycast (`onDrop` with `files`). A drop ends the
|
|
407
|
+
* drag without a leave where it lands. Returns whether a surface or an
|
|
408
|
+
* object took it.
|
|
409
|
+
* @param {number} x @param {number} y @param {readonly any[]} files @param {any} [native]
|
|
410
|
+
*/
|
|
411
|
+
dropFiles(x: number, y: number, files: readonly any[], native?: any): boolean;
|
|
412
|
+
/** Shows a three.js object's cursor on the canvas (null: the page's own). @param {any} object */
|
|
413
|
+
shown(object: any): void;
|
|
414
|
+
/**
|
|
415
|
+
* Takes a new theme for the primitives at once: the overlay and every
|
|
416
|
+
* panel resolve, lay out and repaint; the scene and all state stay.
|
|
417
|
+
* @param {import('ren-core/host').Tokens} tokens
|
|
418
|
+
*/
|
|
419
|
+
setTheme(tokens: import('ren-core/host').Tokens): void;
|
|
420
|
+
/**
|
|
421
|
+
* Shows the cursor of the primitives under the pointer on the canvas (their
|
|
422
|
+
* style's `cursor`); leaves the page's own cursor over the scene.
|
|
423
|
+
* @param {Surface | null} surface
|
|
424
|
+
*/
|
|
425
|
+
show(surface: Surface | null): void;
|
|
426
|
+
/**
|
|
427
|
+
* Routes a canvas element's pointer, wheel, key and copy events: to the
|
|
428
|
+
* primitives and the scene (`input`), keys and copy to the surface last
|
|
429
|
+
* pressed (keys with none to the overlay or the first panel, for the
|
|
430
|
+
* root's `$keys`; a chord reaches the handlers, as on ren-canv's attach).
|
|
431
|
+
* Returns the function that stops.
|
|
432
|
+
* @param {any} canvas
|
|
433
|
+
*/
|
|
434
|
+
attach(canvas: any): () => void;
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* What a `$animate` callback receives each frame. In a worker there is no
|
|
438
|
+
* renderer, scene or camera: they are null there, and the callback changes
|
|
439
|
+
* signals instead.
|
|
440
|
+
*/
|
|
441
|
+
export declare class Tick {
|
|
442
|
+
renderer: Renderer | null;
|
|
443
|
+
scene: any;
|
|
444
|
+
camera: any;
|
|
445
|
+
time: number;
|
|
446
|
+
delta: number;
|
|
447
|
+
/** @param {Renderer | null} renderer @param {number} time seconds @param {number} delta seconds since the last frame */
|
|
448
|
+
constructor(renderer: Renderer | null, time: number, delta: number);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* A three.js renderer for `mount` or an application root's `renderer`.
|
|
452
|
+
* @param {Kit} kit the three.js namespace
|
|
453
|
+
* @param {Options} [options]
|
|
454
|
+
*/
|
|
455
|
+
export declare function $three(kit: Kit, options?: Options): Renderer;
|
|
456
|
+
/**
|
|
457
|
+
* Renders `view()` into a renderer's scene; returns the dispose function.
|
|
458
|
+
* @param {() => any} view
|
|
459
|
+
* @param {Renderer} target
|
|
460
|
+
* @param {import('ren-core/host').Options} [options]
|
|
461
|
+
* @returns {() => void}
|
|
462
|
+
*/
|
|
463
|
+
export declare function render(view: () => any, target: Renderer, options?: import('ren-core/host').Options): () => void;
|
|
464
|
+
/**
|
|
465
|
+
* Runs `fn` before every frame while the calling component lives (its
|
|
466
|
+
* owner's cleanup stops it). Rendered by ren-three, it runs in the
|
|
467
|
+
* renderer's frame loop, which draws every animation frame while any runs.
|
|
468
|
+
* Anywhere else (a worker serving the view), it runs on that thread's own
|
|
469
|
+
* frames (`requestAnimationFrame` where the thread has it, 16 ms timers
|
|
470
|
+
* otherwise), with a Tick whose renderer, scene and camera are null.
|
|
471
|
+
* @param {(frame: Tick) => void} fn
|
|
472
|
+
*/
|
|
473
|
+
export declare function $animate(fn: (frame: Tick) => void): void;
|