@vectojs/core 1.15.0 → 1.16.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/dist/{chunk-64UFEHOJ.mjs → chunk-AQTO7OSU.mjs} +246 -32
- package/dist/{chunk-J6NHSFIE.js → chunk-DUYB4GX4.js} +285 -69
- package/dist/{chunk-BEUIB3U7.js → chunk-IYPLG4Z4.js} +93 -43
- package/dist/{chunk-L5BCKFQE.mjs → chunk-JFU56BX4.mjs} +48 -0
- package/dist/index.js +2144 -325
- package/dist/index.mjs +1966 -148
- package/dist/layout.js +3 -1
- package/dist/renderer/CanvasRenderer.d.ts +22 -0
- package/dist/renderer/IRenderer.d.ts +13 -0
- package/dist/renderer.js +4 -3
- package/dist/renderer.mjs +1 -1
- package/dist/text/MSDFTextEntity.d.ts +29 -0
- package/dist/text.js +4 -3
- package/dist/text.mjs +1 -1
- package/dist/tree/ComputeParticleEntity.d.ts +18 -0
- package/dist/tree/DOMPortalEntity.d.ts +18 -0
- package/dist/tree/Entity.d.ts +121 -5
- package/dist/tree/Scene.d.ts +380 -0
- package/dist/wasm/anim-backend.d.ts +86 -0
- package/dist/wasm/asset.d.ts +25 -0
- package/dist/wasm/asset.js +7 -0
- package/dist/wasm/asset.mjs +5 -0
- package/dist/wasm/backend.d.ts +154 -0
- package/dist/wasm/hit-backend.d.ts +92 -0
- package/dist/wasm/hit-store.d.ts +48 -0
- package/dist/wasm/particle-backend.d.ts +104 -0
- package/dist/wasm/scene-store.d.ts +28 -0
- package/dist/wasm/soa.d.ts +146 -0
- package/dist/wasm/vectojs_core.wasm +0 -0
- package/package.json +15 -8
package/dist/layout.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }const __vecto_cjs_url=require("url").pathToFileURL(__filename).href;
|
|
2
|
+
|
|
3
|
+
// src/layout/index.ts
|
|
2
4
|
var _layout = require('@vectojs/layout'); _createStarExport(_layout);
|
|
@@ -3,6 +3,14 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
3
3
|
private ctx;
|
|
4
4
|
private width;
|
|
5
5
|
private height;
|
|
6
|
+
private canvas;
|
|
7
|
+
/** True between a `contextlost` and its `contextrestored` — the 2D context is
|
|
8
|
+
* unusable, so draw calls are skipped until it comes back. Canvas2D context
|
|
9
|
+
* loss is rare (GPU reset / memory pressure) but a real browser event. */
|
|
10
|
+
private contextLost;
|
|
11
|
+
/** Invoked after the context is restored + re-initialized, so the owner
|
|
12
|
+
* (`Scene`) can repaint the now-blank canvas. Set via {@link onContextRestored}. */
|
|
13
|
+
private contextRestoredCb;
|
|
6
14
|
/**
|
|
7
15
|
* Cap on the effective device pixel ratio applied by the constructor and
|
|
8
16
|
* {@link resize}. `undefined` (default) uses the real, uncapped
|
|
@@ -38,6 +46,17 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
38
46
|
width: number;
|
|
39
47
|
height: number;
|
|
40
48
|
}, maxDPR?: number);
|
|
49
|
+
/** Register a callback fired after a lost 2D context is restored + re-scaled,
|
|
50
|
+
* so the owner can repaint (the restored canvas comes back cleared). */
|
|
51
|
+
onContextRestored(cb: () => void): void;
|
|
52
|
+
/**
|
|
53
|
+
* Handle Canvas2D context loss/restore (GPU reset, memory pressure). The
|
|
54
|
+
* `contextlost` handler MUST call `preventDefault()` or the browser never
|
|
55
|
+
* fires `contextrestored`; while lost, draw calls are skipped. On restore we
|
|
56
|
+
* re-acquire the 2D context, re-apply the DPR scale, drop cached style, and
|
|
57
|
+
* notify the owner to repaint.
|
|
58
|
+
*/
|
|
59
|
+
private setupContextLossRecovery;
|
|
41
60
|
/**
|
|
42
61
|
* Expose the underlying `CanvasRenderingContext2D` for operations not
|
|
43
62
|
* covered by the {@link IRenderer} interface.
|
|
@@ -56,6 +75,9 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
56
75
|
* @param height - New logical height in CSS pixels.
|
|
57
76
|
*/
|
|
58
77
|
resize(width: number, height: number): void;
|
|
78
|
+
/** Whether the 2D context is currently lost (drawing is a no-op until it is
|
|
79
|
+
* restored). The owner skips its render pass while this is true. */
|
|
80
|
+
isContextLost(): boolean;
|
|
59
81
|
/** @inheritdoc */
|
|
60
82
|
clear(): void;
|
|
61
83
|
/** @inheritdoc */
|
|
@@ -191,4 +191,17 @@ export interface IRenderer {
|
|
|
191
191
|
* successful teardown must be a silent no-op, not throw.
|
|
192
192
|
*/
|
|
193
193
|
dispose?(): void;
|
|
194
|
+
/**
|
|
195
|
+
* Whether the renderer's drawing context is currently lost (e.g. a Canvas2D
|
|
196
|
+
* `contextlost` before its `contextrestored`, or a WebGL context loss). While
|
|
197
|
+
* true the renderer's draw calls are no-ops and the owner should skip its
|
|
198
|
+
* render pass. Optional — a renderer that can't lose its context omits it.
|
|
199
|
+
*/
|
|
200
|
+
isContextLost?(): boolean;
|
|
201
|
+
/**
|
|
202
|
+
* Register a callback invoked after a lost context is restored and
|
|
203
|
+
* re-initialized, so the owner can repaint (a restored canvas comes back
|
|
204
|
+
* cleared). Optional, paired with {@link isContextLost}.
|
|
205
|
+
*/
|
|
206
|
+
onContextRestored?(cb: () => void): void;
|
|
194
207
|
}
|
package/dist/renderer.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});const __vecto_cjs_url=require("url").pathToFileURL(__filename).href;
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var _chunkBEUIB3U7js = require('./chunk-BEUIB3U7.js');
|
|
9
8
|
|
|
9
|
+
var _chunkIYPLG4Z4js = require('./chunk-IYPLG4Z4.js');
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
exports.CanvasRenderer = _chunkIYPLG4Z4js.CanvasRenderer; exports.SVGRenderer = _chunkIYPLG4Z4js.SVGRenderer; exports.TextRasterCache = _chunkIYPLG4Z4js.TextRasterCache; exports.WebGPUParticleSystemManager = _chunkIYPLG4Z4js.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkIYPLG4Z4js.createWebGLPointRenderer; exports.parseColorToRGBA = _chunkIYPLG4Z4js.parseColorToRGBA;
|
package/dist/renderer.mjs
CHANGED
|
@@ -12,6 +12,12 @@ export interface MSDFTextEntityOptions {
|
|
|
12
12
|
maxWidth?: number;
|
|
13
13
|
/** Layout height limit in logical pixels. Defaults to 1000. */
|
|
14
14
|
maxHeight?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Horizontal alignment. `'justify'` stretches every wrapped line flush to
|
|
17
|
+
* {@link maxWidth} (the paragraph-final and newline-ended lines stay ragged);
|
|
18
|
+
* `'left'` (default) leaves them ragged.
|
|
19
|
+
*/
|
|
20
|
+
textAlign?: 'left' | 'justify';
|
|
15
21
|
}
|
|
16
22
|
export declare class MSDFTextEntity extends Entity {
|
|
17
23
|
private font;
|
|
@@ -23,6 +29,9 @@ export declare class MSDFTextEntity extends Entity {
|
|
|
23
29
|
private lineHeight?;
|
|
24
30
|
private maxWidth;
|
|
25
31
|
private maxHeight;
|
|
32
|
+
private textAlign;
|
|
33
|
+
private hyphenator;
|
|
34
|
+
private layoutText;
|
|
26
35
|
private text;
|
|
27
36
|
private lastRenderedSeqId;
|
|
28
37
|
private rgbColorCache;
|
|
@@ -31,7 +40,27 @@ export declare class MSDFTextEntity extends Entity {
|
|
|
31
40
|
constructor(text: string, options: MSDFTextEntityOptions);
|
|
32
41
|
/** Change the wrap boundary and re-run layout for the current text. */
|
|
33
42
|
setMaxWidth(maxWidth: number): void;
|
|
43
|
+
/**
|
|
44
|
+
* Set horizontal alignment (`'justify'` stretches wrapped lines flush to
|
|
45
|
+
* {@link setMaxWidth}'s width; the last line stays ragged) and re-run layout.
|
|
46
|
+
*/
|
|
47
|
+
setTextAlign(align: 'left' | 'justify'): void;
|
|
48
|
+
/**
|
|
49
|
+
* Plug a hyphenator (word → parts). Break opportunities are inserted as soft
|
|
50
|
+
* hyphens (U+00AD) into the string sent to layout, so a word that doesn't fit
|
|
51
|
+
* can break with a visible hyphen. Soft hyphens already present in the text
|
|
52
|
+
* work without one. Pass `null` to disable. The original text is preserved
|
|
53
|
+
* for accessibility — only the layout string carries the hyphens.
|
|
54
|
+
*/
|
|
55
|
+
setHyphenator(fn: ((word: string) => string[]) | null): void;
|
|
34
56
|
setText(text: string): void;
|
|
57
|
+
/**
|
|
58
|
+
* Recompute {@link layoutText} from {@link text}: with a hyphenator active,
|
|
59
|
+
* split each whitespace-delimited word and rejoin its parts with U+00AD so
|
|
60
|
+
* the worker sees the break opportunities. Without one, the layout string is
|
|
61
|
+
* the text unchanged.
|
|
62
|
+
*/
|
|
63
|
+
private rebuildLayoutText;
|
|
35
64
|
private queueLayout;
|
|
36
65
|
/**
|
|
37
66
|
* Mirror the rendered text into the DOM content layer: find-in-page, screen
|
package/dist/text.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _createStarExport(obj) { Object.keys(obj) .filter((key) => key !== "default" && key !== "__esModule") .forEach((key) => { if (exports.hasOwnProperty(key)) { return; } Object.defineProperty(exports, key, {enumerable: true, configurable: true, get: () => obj[key]}); }); }const __vecto_cjs_url=require("url").pathToFileURL(__filename).href;
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
var _chunkDUYB4GX4js = require('./chunk-DUYB4GX4.js');
|
|
5
6
|
|
|
6
7
|
// src/text/index.ts
|
|
7
8
|
var _text = require('@vectojs/text'); _createStarExport(_text);
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
|
|
11
|
-
exports.MSDFTextEntity =
|
|
12
|
+
exports.MSDFTextEntity = _chunkDUYB4GX4js.MSDFTextEntity; exports.SVGEntity = _chunkDUYB4GX4js.SVGEntity;
|
package/dist/text.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Entity } from './Entity';
|
|
2
2
|
import { IRenderer } from '../renderer/IRenderer';
|
|
3
|
+
import type { ParticleBackend } from '../wasm/particle-backend';
|
|
3
4
|
/**
|
|
4
5
|
* Options for configuring a {@link ComputeParticleEntity}.
|
|
5
6
|
*/
|
|
@@ -60,6 +61,10 @@ export declare class ComputeParticleEntity extends Entity {
|
|
|
60
61
|
computeBindGroup: any;
|
|
61
62
|
/** WebGPU bind group for the render pass (usually same as compute). */
|
|
62
63
|
renderBindGroup: any;
|
|
64
|
+
/** When the last simulation step ran through the WASM backend, its fused
|
|
65
|
+
* pending-animation flag; `null` when the last step used the JS `updateCPU`
|
|
66
|
+
* path (so `hasPendingAnimations` falls back to its own scan). */
|
|
67
|
+
private _wasmPending;
|
|
63
68
|
constructor(options?: ComputeParticleOptions);
|
|
64
69
|
/**
|
|
65
70
|
* Disperses all particles randomly across the specified screen bounds.
|
|
@@ -127,6 +132,19 @@ export declare class ComputeParticleEntity extends Entity {
|
|
|
127
132
|
* @param height - Boundary height.
|
|
128
133
|
*/
|
|
129
134
|
updateCPU(dt: number, mouseX: number, mouseY: number, width: number, height: number): void;
|
|
135
|
+
/**
|
|
136
|
+
* Advance the simulation one step through the WASM particle kernel: transpose
|
|
137
|
+
* this entity's AoS buffer into the backend's SoA views, run `particle_step`,
|
|
138
|
+
* and scatter position/velocity/life back. Produces an f32 result (matching
|
|
139
|
+
* the WGSL shader) that differs from {@link updateCPU}'s f64 by <1 ULP/step —
|
|
140
|
+
* the accepted CPU-vs-GPU-class divergence. Caches the kernel's fused
|
|
141
|
+
* pending-animation flag so {@link hasPendingAnimations} needs no second scan.
|
|
142
|
+
*
|
|
143
|
+
* The backend holds one resident SoA store, so a Scene with multiple particle
|
|
144
|
+
* entities reuses it sequentially — origin is therefore re-gathered each call
|
|
145
|
+
* (not upload-once), a couple of extra f32 reads per particle.
|
|
146
|
+
*/
|
|
147
|
+
stepWithBackend(backend: ParticleBackend, dt: number, mouseX: number, mouseY: number, width: number, height: number): void;
|
|
130
148
|
destroy(): void;
|
|
131
149
|
/**
|
|
132
150
|
* Frees all GPU resources allocated for WebGPU simulation.
|
|
@@ -4,6 +4,7 @@ export declare class DOMPortalEntity extends Entity {
|
|
|
4
4
|
isDOMPortal: boolean;
|
|
5
5
|
private domListeners;
|
|
6
6
|
private resizeObserver;
|
|
7
|
+
private domBound;
|
|
7
8
|
cachedWidth: number;
|
|
8
9
|
cachedHeight: number;
|
|
9
10
|
lastWidth: string;
|
|
@@ -12,6 +13,23 @@ export declare class DOMPortalEntity extends Entity {
|
|
|
12
13
|
lastZIndex: string;
|
|
13
14
|
lastOpacity: string;
|
|
14
15
|
constructor(domElement: HTMLElement, width?: number, height?: number, id?: string);
|
|
16
|
+
/**
|
|
17
|
+
* Attach the ResizeObserver + DOM event listeners that bridge native DOM
|
|
18
|
+
* events into the Vecto event system. Idempotent: safe to call every frame
|
|
19
|
+
* from the projection path (`Scene.syncPortalGeometry`), which is what lets a
|
|
20
|
+
* portal survive a `scene.remove()` -> re-add cycle — {@link releaseDOMBindings}
|
|
21
|
+
* tears these down on removal and the next projection re-attaches them.
|
|
22
|
+
*/
|
|
23
|
+
attachDOMBindings(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Disconnect the ResizeObserver and remove the DOM event listeners, without
|
|
26
|
+
* touching the scene graph or the element's DOM parentage. Called on the
|
|
27
|
+
* `scene.remove()` path so a detached portal doesn't leak an observer that
|
|
28
|
+
* keeps its element alive and firing; the element itself is removed from the
|
|
29
|
+
* document by the scene's portal pruning. Re-attached lazily on the next
|
|
30
|
+
* projection frame via {@link attachDOMBindings}.
|
|
31
|
+
*/
|
|
32
|
+
releaseDOMBindings(): void;
|
|
15
33
|
isPointInside(globalX: number, globalY: number): boolean;
|
|
16
34
|
add(..._children: Entity[]): this;
|
|
17
35
|
render(): void;
|
package/dist/tree/Entity.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type MotionConfig, type TweenConfig, type SpringConfig } from '@vectojs/animation';
|
|
1
|
+
import { type PropertyDriver, type MotionConfig, type TweenConfig, type SpringConfig } from '@vectojs/animation';
|
|
2
2
|
import type { PreparedContentGrid } from '@vectojs/text';
|
|
3
3
|
/** A numeric transform/visual property that participates in the animation system. */
|
|
4
4
|
export type AnimatableProp = 'x' | 'y' | 'scaleX' | 'scaleY' | 'rotation' | 'opacity';
|
|
@@ -65,6 +65,21 @@ export interface ContentProjectionRun {
|
|
|
65
65
|
text: string;
|
|
66
66
|
/** CSS font shorthand matching the canvas run. */
|
|
67
67
|
font?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Absolute local x of this run within the entity. Set it (with {@link width})
|
|
70
|
+
* for justified or otherwise non-naturally-spaced text: the Scene then places
|
|
71
|
+
* each run as a positioned carrier (`inline-block` + relative `left`) at the
|
|
72
|
+
* exact canvas x, so the DOM selection box overlaps the drawn glyphs instead
|
|
73
|
+
* of drifting under the browser's own inter-word spacing. When omitted, runs
|
|
74
|
+
* flow naturally (the default for left-aligned text).
|
|
75
|
+
*/
|
|
76
|
+
x?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Advance (width in px) the canvas used for this run, including any widened
|
|
79
|
+
* trailing gap for justify. Used only alongside {@link x} to size the
|
|
80
|
+
* positioned carrier so the next run starts flush at its own `x`.
|
|
81
|
+
*/
|
|
82
|
+
width?: number;
|
|
68
83
|
}
|
|
69
84
|
export interface ContentProjectionLine {
|
|
70
85
|
/** Text for browser find-in-page and native selection. */
|
|
@@ -186,6 +201,30 @@ export interface A11yAttributes {
|
|
|
186
201
|
activedescendant?: string;
|
|
187
202
|
valuemin?: string;
|
|
188
203
|
valuemax?: string;
|
|
204
|
+
/**
|
|
205
|
+
* ARIA live-region politeness (`aria-live`). Set on the container whose text
|
|
206
|
+
* changes as content streams in (chat message, toast, async validation
|
|
207
|
+
* summary) so a screen reader announces updates without moving focus.
|
|
208
|
+
* `'polite'` waits for a pause; `'assertive'` interrupts. WCAG 4.1.3.
|
|
209
|
+
*/
|
|
210
|
+
live?: 'off' | 'polite' | 'assertive';
|
|
211
|
+
/** `aria-atomic`: announce the whole region on change, not just the diff. */
|
|
212
|
+
atomic?: boolean;
|
|
213
|
+
/** `aria-relevant`: which mutation types to announce (e.g. `'additions text'`). */
|
|
214
|
+
relevant?: string;
|
|
215
|
+
/** `aria-labelledby`: id(s) of the element(s) that label this one. */
|
|
216
|
+
labelledby?: string;
|
|
217
|
+
/** `aria-describedby`: id(s) of the element(s) that describe this one. */
|
|
218
|
+
describedby?: string;
|
|
219
|
+
/** `aria-required`: the field must be filled before submit. */
|
|
220
|
+
required?: boolean;
|
|
221
|
+
/** `aria-invalid`: the field's current value fails validation. */
|
|
222
|
+
invalid?: boolean;
|
|
223
|
+
/** `aria-level`: hierarchical level (headings, tree items, etc.). */
|
|
224
|
+
level?: number;
|
|
225
|
+
/** `aria-modal`: marks a `role="dialog"` as modal so assistive tech confines
|
|
226
|
+
* reading to it. Set on a modal dialog's shell. */
|
|
227
|
+
ariaModal?: 'true' | 'false';
|
|
189
228
|
/** Explicit native editor typography; ignored for non-input elements. */
|
|
190
229
|
textInputStyle?: TextInputStyle;
|
|
191
230
|
}
|
|
@@ -295,6 +334,18 @@ export declare abstract class Entity {
|
|
|
295
334
|
private _transitions;
|
|
296
335
|
private _drivers;
|
|
297
336
|
private _mounted;
|
|
337
|
+
private _destroyed;
|
|
338
|
+
_driversTickedFrame: number;
|
|
339
|
+
private readonly _trig;
|
|
340
|
+
private _trigRotation;
|
|
341
|
+
private _wa;
|
|
342
|
+
private _wb;
|
|
343
|
+
private _wc;
|
|
344
|
+
private _wd;
|
|
345
|
+
private _we;
|
|
346
|
+
private _wf;
|
|
347
|
+
private _worldFrame;
|
|
348
|
+
_storeSlot: number;
|
|
298
349
|
get x(): number;
|
|
299
350
|
set x(v: number);
|
|
300
351
|
get y(): number;
|
|
@@ -330,9 +381,9 @@ export declare abstract class Entity {
|
|
|
330
381
|
* fixed viewport. Off by default (children render unclipped). Canvas2D only.
|
|
331
382
|
*/
|
|
332
383
|
clipChildren: boolean;
|
|
333
|
-
protected listeners: Map<VectoEvent, Array<(e: any) => void
|
|
384
|
+
protected listeners: Map<VectoEvent, Array<(e: any) => void>> | null;
|
|
334
385
|
/** Capture-phase listeners (fired root→target before bubble). */
|
|
335
|
-
protected captureListeners: Map<VectoEvent, Array<(e: any) => void
|
|
386
|
+
protected captureListeners: Map<VectoEvent, Array<(e: any) => void>> | null;
|
|
336
387
|
private animations;
|
|
337
388
|
constructor(id?: string);
|
|
338
389
|
/**
|
|
@@ -422,6 +473,26 @@ export declare abstract class Entity {
|
|
|
422
473
|
private _driveTo;
|
|
423
474
|
/** Advance active property drivers one frame. Call from update(). */
|
|
424
475
|
protected tickDrivers(dt: number): void;
|
|
476
|
+
/**
|
|
477
|
+
* Internal: this entity's active-driver map (read-only view), or `null` if
|
|
478
|
+
* it has none. Called only by Scene's batched WASM animation pass, never
|
|
479
|
+
* application code. Returns the Map directly (not a callback iteration) so
|
|
480
|
+
* a caller can `for...of` it with zero per-entity closure allocation — the
|
|
481
|
+
* integrated benchmark (benchmarks/anim-wasm-scene) found a fresh callback
|
|
482
|
+
* per entity per frame was a real cost, not a negligible one.
|
|
483
|
+
*/
|
|
484
|
+
_driverEntries(): ReadonlyMap<AnimatableProp, PropertyDriver> | null;
|
|
485
|
+
/**
|
|
486
|
+
* Internal: finalize one driver that was ALREADY advanced externally this
|
|
487
|
+
* frame (e.g. by Scene's batched WASM tick via `driver.syncExternal`, or a
|
|
488
|
+
* direct `driver.tick()` call for a driver the batch can't offload) —
|
|
489
|
+
* exactly mirrors tickDrivers()'s own per-driver completion logic, so a
|
|
490
|
+
* driver behaves identically regardless of which path ticked it. Called
|
|
491
|
+
* only by Scene, never application code.
|
|
492
|
+
*/
|
|
493
|
+
_applyDriverTick(prop: AnimatableProp, driver: PropertyDriver): void;
|
|
494
|
+
/** Internal: true if this entity currently has any active property driver. */
|
|
495
|
+
_hasActiveDrivers(): boolean;
|
|
425
496
|
/**
|
|
426
497
|
* Advance the entity's internal state for one frame.
|
|
427
498
|
*
|
|
@@ -456,8 +527,21 @@ export declare abstract class Entity {
|
|
|
456
527
|
*/
|
|
457
528
|
off(event: VectoEvent, callback: (e: any) => void, options?: ListenerOptions): this;
|
|
458
529
|
/**
|
|
459
|
-
* Tear down this entity
|
|
460
|
-
*
|
|
530
|
+
* Tear down this entity **and its entire subtree**: recursively destroy every
|
|
531
|
+
* descendant (leaf-first), clear all animations, event listeners, and property
|
|
532
|
+
* drivers, then detach from the parent. Call before discarding an entity to
|
|
533
|
+
* prevent memory leaks.
|
|
534
|
+
*
|
|
535
|
+
* Recursing here is what frees a subtree's GPU buffers, layout workers, and DOM
|
|
536
|
+
* observers when an app does `entity.destroy()` or `scene.remove(subtree)` on a
|
|
537
|
+
* route change — without it, only the root's own state was released and every
|
|
538
|
+
* descendant (and its subclass resources) was stranded. Subclasses that own
|
|
539
|
+
* external resources override `destroy()`, free their resource, then call
|
|
540
|
+
* `super.destroy()`; because children don't depend on a parent's resource, the
|
|
541
|
+
* order (parent resource first, then descendants) is safe.
|
|
542
|
+
*
|
|
543
|
+
* Idempotent and re-entrancy safe: a second call is a no-op, and because each
|
|
544
|
+
* child is detached as it is destroyed, destroying a subtree never double-frees.
|
|
461
545
|
*/
|
|
462
546
|
destroy(): void;
|
|
463
547
|
/**
|
|
@@ -498,10 +582,42 @@ export declare abstract class Entity {
|
|
|
498
582
|
* @returns World-space {@link Point} for this entity.
|
|
499
583
|
*/
|
|
500
584
|
getGlobalPosition(): Point;
|
|
585
|
+
/**
|
|
586
|
+
* Internal: read this entity's cached world matrix into `out` — the SAME
|
|
587
|
+
* cache {@link getWorldTransform} reads — without allocating a wrapper
|
|
588
|
+
* object. Returns `false` (leaving `out` untouched) when the cache isn't
|
|
589
|
+
* valid for `frame` (typically the caller's `scene.currentFrame`), exactly
|
|
590
|
+
* mirroring {@link getWorldTransform}'s own validity check; the caller
|
|
591
|
+
* falls back to {@link getWorldTransform}'s full walk in that case. Exists
|
|
592
|
+
* so a per-entity gather that runs every entity through this (e.g. G3's
|
|
593
|
+
* `gatherHitAABBs`) pays for six scalar reads instead of one object
|
|
594
|
+
* allocation per entity per call — the exact class of per-frame garbage
|
|
595
|
+
* the G2 integrated benchmark found dominating its own gather cost.
|
|
596
|
+
*/
|
|
597
|
+
_readWorldCache(frame: number, out: AffineTransform): boolean;
|
|
501
598
|
/**
|
|
502
599
|
* Return the exact accumulated Canvas `T * S * R` transform for this entity.
|
|
503
600
|
*/
|
|
504
601
|
getWorldTransform(): AffineTransform;
|
|
602
|
+
/**
|
|
603
|
+
* Return this entity's cached `{ cos, sin }` of its current rotation,
|
|
604
|
+
* recomputing only when `rotation` has actually changed since the last call.
|
|
605
|
+
* The same object identity is returned across calls with an unchanged
|
|
606
|
+
* rotation, so callers must treat it as read-only. Used by the render walk
|
|
607
|
+
* and {@link getWorldTransform} to avoid V8's comparatively slow Math.cos/sin
|
|
608
|
+
* (a software libm call, ~2.5x slower than other engines) per entity/frame.
|
|
609
|
+
*/
|
|
610
|
+
_getTrig(): Readonly<{
|
|
611
|
+
cos: number;
|
|
612
|
+
sin: number;
|
|
613
|
+
}>;
|
|
614
|
+
/**
|
|
615
|
+
* Store the world matrix Scene computed for this entity during the render
|
|
616
|
+
* walk, stamped with the frame it belongs to. {@link getWorldTransform}
|
|
617
|
+
* returns it verbatim while `frame === scene.currentFrame`. Internal: called
|
|
618
|
+
* only by Scene's renderer, never by application code.
|
|
619
|
+
*/
|
|
620
|
+
_setWorldCache(a: number, b: number, c: number, d: number, e: number, f: number, frame: number): void;
|
|
505
621
|
/** Convert a point from this entity's local space to Scene/world space. */
|
|
506
622
|
localToWorld(localX: number, localY: number): Point;
|
|
507
623
|
/**
|