@vectojs/core 1.21.0 → 1.22.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-GKSCJ6AF.js → chunk-LHONR3GO.js} +150 -44
- package/dist/{chunk-RTENOAYT.mjs → chunk-UPULSLKA.mjs} +106 -0
- package/dist/index.js +82 -61
- package/dist/index.mjs +22 -1
- package/dist/renderer/CanvasRenderer.d.ts +18 -1
- package/dist/renderer/IRenderer.d.ts +63 -0
- package/dist/renderer/SVGRenderer.d.ts +2 -0
- package/dist/renderer/WebGLPointRenderer.d.ts +33 -0
- package/dist/renderer.js +2 -2
- package/dist/renderer.mjs +1 -1
- package/dist/tree/Entity.d.ts +6 -4
- package/dist/tree/Scene.d.ts +18 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
var
|
|
12
|
+
var _chunkLHONR3GOjs = require('./chunk-LHONR3GO.js');
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
|
|
@@ -2463,6 +2463,27 @@ var Scene = (_class7 = class _Scene {
|
|
|
2463
2463
|
get webgpuDisabled() {
|
|
2464
2464
|
return this._webgpuDisabled || this.particleBackend === "cpu";
|
|
2465
2465
|
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Draw accounting for the WebGL point layer, or null when that layer is not in
|
|
2468
|
+
* use.
|
|
2469
|
+
*
|
|
2470
|
+
* Null and all-zero mean different things: null is "this backend is not
|
|
2471
|
+
* running", zero is "it ran and drew nothing". A readout that conflates them
|
|
2472
|
+
* sends someone looking for a performance problem in a backend that was never
|
|
2473
|
+
* active.
|
|
2474
|
+
*/
|
|
2475
|
+
get webglDrawStats() {
|
|
2476
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _27 => _27.pointRenderer, 'optionalAccess', _28 => _28.stats, 'optionalCall', _29 => _29()]), () => ( null));
|
|
2477
|
+
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Whether a WebGPU device is currently live for particle compute.
|
|
2480
|
+
*
|
|
2481
|
+
* The WebGPU path only activates when a `ComputeParticleEntity` is present, so
|
|
2482
|
+
* most scenes never touch it.
|
|
2483
|
+
*/
|
|
2484
|
+
get webgpuActive() {
|
|
2485
|
+
return this.device !== null && !this.deviceLost;
|
|
2486
|
+
}
|
|
2466
2487
|
set webgpuDisabled(value) {
|
|
2467
2488
|
this._webgpuDisabled = value;
|
|
2468
2489
|
}
|
|
@@ -2494,8 +2515,8 @@ var Scene = (_class7 = class _Scene {
|
|
|
2494
2515
|
static _devModeDetected() {
|
|
2495
2516
|
if (_Scene.devMode) return true;
|
|
2496
2517
|
const gp = typeof globalThis !== "undefined" ? globalThis : void 0;
|
|
2497
|
-
if (_optionalChain([gp, 'optionalAccess',
|
|
2498
|
-
if (_optionalChain([gp, 'optionalAccess',
|
|
2518
|
+
if (_optionalChain([gp, 'optionalAccess', _30 => _30.__DEV__])) return true;
|
|
2519
|
+
if (_optionalChain([gp, 'optionalAccess', _31 => _31.process, 'optionalAccess', _32 => _32.env, 'optionalAccess', _33 => _33.NODE_ENV]) === "development") return true;
|
|
2499
2520
|
return false;
|
|
2500
2521
|
}
|
|
2501
2522
|
|
|
@@ -2526,9 +2547,9 @@ var Scene = (_class7 = class _Scene {
|
|
|
2526
2547
|
let checked = 0;
|
|
2527
2548
|
const walkProjections = (node) => {
|
|
2528
2549
|
if (checked > 10) return;
|
|
2529
|
-
const proj = _optionalChain([node, 'access',
|
|
2530
|
-
if (_optionalChain([proj, 'optionalAccess',
|
|
2531
|
-
const el = _optionalChain([this, 'access',
|
|
2550
|
+
const proj = _optionalChain([node, 'access', _34 => _34.getContentProjection, 'optionalCall', _35 => _35()]);
|
|
2551
|
+
if (_optionalChain([proj, 'optionalAccess', _36 => _36.text]) && proj.selectable !== false) {
|
|
2552
|
+
const el = _optionalChain([this, 'access', _37 => _37.contentElements, 'optionalAccess', _38 => _38.get, 'call', _39 => _39(node.id)]);
|
|
2532
2553
|
if (el) {
|
|
2533
2554
|
const projectedText = el.textContent || "";
|
|
2534
2555
|
if (projectedText !== "" && projectedText !== proj.text) {
|
|
@@ -2549,8 +2570,8 @@ var Scene = (_class7 = class _Scene {
|
|
|
2549
2570
|
this.disableWindowResize = _nullishCoalesce(options.disableWindowResize, () => ( false));
|
|
2550
2571
|
this.maxDPR = options.maxDPR;
|
|
2551
2572
|
if (this.disableWindowResize) {
|
|
2552
|
-
const styleWidth = parseInlinePx(_optionalChain([canvas, 'access',
|
|
2553
|
-
const styleHeight = parseInlinePx(_optionalChain([canvas, 'access',
|
|
2573
|
+
const styleWidth = parseInlinePx(_optionalChain([canvas, 'access', _40 => _40.style, 'optionalAccess', _41 => _41.width]));
|
|
2574
|
+
const styleHeight = parseInlinePx(_optionalChain([canvas, 'access', _42 => _42.style, 'optionalAccess', _43 => _43.height]));
|
|
2554
2575
|
this.width = _nullishCoalesce(styleWidth, () => ( (canvas.width || canvas.clientWidth || 0)));
|
|
2555
2576
|
this.height = _nullishCoalesce(styleHeight, () => ( (canvas.height || canvas.clientHeight || 0)));
|
|
2556
2577
|
} else {
|
|
@@ -2558,7 +2579,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2558
2579
|
this.height = typeof window !== "undefined" ? window.innerHeight : canvas.clientHeight || canvas.height || 600;
|
|
2559
2580
|
}
|
|
2560
2581
|
const globalProcess = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
2561
|
-
const isTest = globalProcess && (_optionalChain([globalProcess, 'access',
|
|
2582
|
+
const isTest = globalProcess && (_optionalChain([globalProcess, 'access', _44 => _44.env, 'optionalAccess', _45 => _45.NODE_ENV]) === "test" || _optionalChain([globalProcess, 'access', _46 => _46.env, 'optionalAccess', _47 => _47.VITEST]) === "true");
|
|
2562
2583
|
this.maxFPS = _nullishCoalesce(options.maxFPS, () => ( (isTest ? 0 : 60)));
|
|
2563
2584
|
this.respectReducedMotion = _nullishCoalesce(options.respectReducedMotion, () => ( true));
|
|
2564
2585
|
this.autoThrottle = _nullishCoalesce(options.autoThrottle, () => ( true));
|
|
@@ -2572,7 +2593,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2572
2593
|
if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
2573
2594
|
this.forcedColorsQuery = window.matchMedia("(forced-colors: active)");
|
|
2574
2595
|
this.forcedColorsChangeHandler = () => this.markDirty();
|
|
2575
|
-
_optionalChain([this, 'access',
|
|
2596
|
+
_optionalChain([this, 'access', _48 => _48.forcedColorsQuery, 'access', _49 => _49.addEventListener, 'optionalCall', _50 => _50("change", this.forcedColorsChangeHandler)]);
|
|
2576
2597
|
}
|
|
2577
2598
|
this.root = new class RootEntity extends _chunkAGP4VLF4js.Entity {
|
|
2578
2599
|
isPointInside() {
|
|
@@ -2594,15 +2615,15 @@ var Scene = (_class7 = class _Scene {
|
|
|
2594
2615
|
if (options.renderer) {
|
|
2595
2616
|
this.renderer = options.renderer;
|
|
2596
2617
|
} else {
|
|
2597
|
-
this.renderer = new (0,
|
|
2618
|
+
this.renderer = new (0, _chunkLHONR3GOjs.CanvasRenderer)(
|
|
2598
2619
|
canvas,
|
|
2599
2620
|
this.disableWindowResize ? { width: this.width, height: this.height } : void 0,
|
|
2600
2621
|
this.maxDPR
|
|
2601
2622
|
);
|
|
2602
2623
|
}
|
|
2603
|
-
_optionalChain([this, 'access',
|
|
2624
|
+
_optionalChain([this, 'access', _51 => _51.renderer, 'access', _52 => _52.onContextRestored, 'optionalCall', _53 => _53(() => {
|
|
2604
2625
|
this.markDirty();
|
|
2605
|
-
if (_optionalChain([this, 'access',
|
|
2626
|
+
if (_optionalChain([this, 'access', _54 => _54.renderer, 'access', _55 => _55.isContextLost, 'optionalCall', _56 => _56()]) !== true) this.render(this.renderer);
|
|
2606
2627
|
})]);
|
|
2607
2628
|
if (typeof document !== "undefined") {
|
|
2608
2629
|
this.a11yRoot = document.createElement("div");
|
|
@@ -2771,7 +2792,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2771
2792
|
watchDevicePixelRatio() {
|
|
2772
2793
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
2773
2794
|
if (this.dprMediaQuery && this.dprChangeHandler) {
|
|
2774
|
-
_optionalChain([this, 'access',
|
|
2795
|
+
_optionalChain([this, 'access', _57 => _57.dprMediaQuery, 'access', _58 => _58.removeEventListener, 'optionalCall', _59 => _59("change", this.dprChangeHandler)]);
|
|
2775
2796
|
}
|
|
2776
2797
|
const dpr = window.devicePixelRatio || 1;
|
|
2777
2798
|
const query = window.matchMedia(`(resolution: ${dpr}dppx)`);
|
|
@@ -2779,7 +2800,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2779
2800
|
this.resize(this.width, this.height);
|
|
2780
2801
|
this.watchDevicePixelRatio();
|
|
2781
2802
|
};
|
|
2782
|
-
_optionalChain([query, 'access',
|
|
2803
|
+
_optionalChain([query, 'access', _60 => _60.addEventListener, 'optionalCall', _61 => _61("change", handler)]);
|
|
2783
2804
|
this.dprMediaQuery = query;
|
|
2784
2805
|
this.dprChangeHandler = handler;
|
|
2785
2806
|
}
|
|
@@ -2799,7 +2820,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2799
2820
|
if (typeof gl.addEventListener !== "function") return;
|
|
2800
2821
|
this.glContextLostHandler = (e) => {
|
|
2801
2822
|
e.preventDefault();
|
|
2802
|
-
_optionalChain([this, 'access',
|
|
2823
|
+
_optionalChain([this, 'access', _62 => _62.pointRenderer, 'optionalAccess', _63 => _63.destroy, 'call', _64 => _64()]);
|
|
2803
2824
|
this.pointRenderer = null;
|
|
2804
2825
|
};
|
|
2805
2826
|
this.glContextRestoredHandler = () => {
|
|
@@ -2829,26 +2850,26 @@ var Scene = (_class7 = class _Scene {
|
|
|
2829
2850
|
* to the live DOM selection.
|
|
2830
2851
|
*/
|
|
2831
2852
|
contentGridSelectionLine(el) {
|
|
2832
|
-
const candidates = [_optionalChain([this, 'access',
|
|
2853
|
+
const candidates = [_optionalChain([this, 'access', _65 => _65.contentSelectionAnchor, 'optionalAccess', _66 => _66.node])];
|
|
2833
2854
|
if (typeof window !== "undefined" && typeof window.getSelection === "function") {
|
|
2834
2855
|
const selection = window.getSelection();
|
|
2835
|
-
candidates.push(_optionalChain([selection, 'optionalAccess',
|
|
2856
|
+
candidates.push(_optionalChain([selection, 'optionalAccess', _67 => _67.anchorNode]), _optionalChain([selection, 'optionalAccess', _68 => _68.focusNode]));
|
|
2836
2857
|
}
|
|
2837
2858
|
for (const candidate of candidates) {
|
|
2838
2859
|
if (!candidate || !el.contains(candidate)) continue;
|
|
2839
2860
|
let cursor = candidate;
|
|
2840
2861
|
while (cursor && cursor.parentNode !== el) cursor = cursor.parentNode;
|
|
2841
|
-
const lineIndex = _optionalChain([cursor, 'optionalAccess',
|
|
2862
|
+
const lineIndex = _optionalChain([cursor, 'optionalAccess', _69 => _69.dataset, 'optionalAccess', _70 => _70.vectoGridLine]);
|
|
2842
2863
|
if (lineIndex !== void 0) return Number(lineIndex);
|
|
2843
2864
|
}
|
|
2844
2865
|
return null;
|
|
2845
2866
|
}
|
|
2846
2867
|
releaseContentSelectionForRebuild(el) {
|
|
2847
2868
|
const selection = typeof window !== "undefined" && typeof window.getSelection === "function" ? window.getSelection() : null;
|
|
2848
|
-
const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess',
|
|
2869
|
+
const ownsSelection = this.contentSelectionAnchor && el.contains(this.contentSelectionAnchor.node) || (_optionalChain([selection, 'optionalAccess', _71 => _71.anchorNode]) ? el.contains(selection.anchorNode) : false) || (_optionalChain([selection, 'optionalAccess', _72 => _72.focusNode]) ? el.contains(selection.focusNode) : false);
|
|
2849
2870
|
if (!ownsSelection) return;
|
|
2850
2871
|
this.endContentSelectionDrag();
|
|
2851
|
-
_optionalChain([selection, 'optionalAccess',
|
|
2872
|
+
_optionalChain([selection, 'optionalAccess', _73 => _73.removeAllRanges, 'call', _74 => _74()]);
|
|
2852
2873
|
}
|
|
2853
2874
|
/**
|
|
2854
2875
|
* Rebuild a content-projection element's DOM (`rebuild`) while preserving a
|
|
@@ -2907,7 +2928,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2907
2928
|
}
|
|
2908
2929
|
/** Convert browser viewport coordinates into this Scene's logical coordinates. */
|
|
2909
2930
|
clientToScene(clientX, clientY) {
|
|
2910
|
-
const rect = _optionalChain([this, 'access',
|
|
2931
|
+
const rect = _optionalChain([this, 'access', _75 => _75.canvas, 'access', _76 => _76.getBoundingClientRect, 'optionalCall', _77 => _77()]);
|
|
2911
2932
|
if (!rect) return { x: clientX, y: clientY };
|
|
2912
2933
|
const cssWidth = rect.width || this.canvas.clientWidth || this.width;
|
|
2913
2934
|
const cssHeight = rect.height || this.canvas.clientHeight || this.height;
|
|
@@ -2945,7 +2966,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
2945
2966
|
cancelAnimationFrame(calibrationFrame);
|
|
2946
2967
|
}
|
|
2947
2968
|
this.contentGridCalibrationFrames.delete(entityId);
|
|
2948
|
-
_optionalChain([this, 'access',
|
|
2969
|
+
_optionalChain([this, 'access', _78 => _78.contentGridCalibrationProbes, 'access', _79 => _79.get, 'call', _80 => _80(entityId), 'optionalAccess', _81 => _81.remove, 'call', _82 => _82()]);
|
|
2949
2970
|
this.contentGridCalibrationProbes.delete(entityId);
|
|
2950
2971
|
delete el.dataset.vectoGridCalibrationPending;
|
|
2951
2972
|
delete el.dataset.vectoGridCalibration;
|
|
@@ -3099,12 +3120,12 @@ var Scene = (_class7 = class _Scene {
|
|
|
3099
3120
|
this.canvasResizeObserver = null;
|
|
3100
3121
|
}
|
|
3101
3122
|
if (this.dprMediaQuery && this.dprChangeHandler) {
|
|
3102
|
-
_optionalChain([this, 'access',
|
|
3123
|
+
_optionalChain([this, 'access', _83 => _83.dprMediaQuery, 'access', _84 => _84.removeEventListener, 'optionalCall', _85 => _85("change", this.dprChangeHandler)]);
|
|
3103
3124
|
this.dprMediaQuery = null;
|
|
3104
3125
|
this.dprChangeHandler = null;
|
|
3105
3126
|
}
|
|
3106
3127
|
if (this.forcedColorsQuery && this.forcedColorsChangeHandler) {
|
|
3107
|
-
_optionalChain([this, 'access',
|
|
3128
|
+
_optionalChain([this, 'access', _86 => _86.forcedColorsQuery, 'access', _87 => _87.removeEventListener, 'optionalCall', _88 => _88("change", this.forcedColorsChangeHandler)]);
|
|
3108
3129
|
this.forcedColorsQuery = null;
|
|
3109
3130
|
this.forcedColorsChangeHandler = null;
|
|
3110
3131
|
}
|
|
@@ -3122,9 +3143,9 @@ var Scene = (_class7 = class _Scene {
|
|
|
3122
3143
|
}
|
|
3123
3144
|
this.pointerEventTarget = null;
|
|
3124
3145
|
}
|
|
3125
|
-
_optionalChain([this, 'access',
|
|
3146
|
+
_optionalChain([this, 'access', _89 => _89.a11yRoot, 'optionalAccess', _90 => _90.remove, 'call', _91 => _91()]);
|
|
3126
3147
|
this.focusSentinel = null;
|
|
3127
|
-
_optionalChain([this, 'access',
|
|
3148
|
+
_optionalChain([this, 'access', _92 => _92.portalRoot, 'optionalAccess', _93 => _93.remove, 'call', _94 => _94()]);
|
|
3128
3149
|
this.a11yElements.clear();
|
|
3129
3150
|
for (const el of this.contentElements.values()) el.remove();
|
|
3130
3151
|
this.contentElements.clear();
|
|
@@ -3147,10 +3168,10 @@ var Scene = (_class7 = class _Scene {
|
|
|
3147
3168
|
}
|
|
3148
3169
|
this.glContextLostHandler = null;
|
|
3149
3170
|
this.glContextRestoredHandler = null;
|
|
3150
|
-
_optionalChain([this, 'access',
|
|
3151
|
-
_optionalChain([this, 'access',
|
|
3152
|
-
_optionalChain([this, 'access',
|
|
3153
|
-
_optionalChain([this, 'access',
|
|
3171
|
+
_optionalChain([this, 'access', _95 => _95.pointRenderer, 'optionalAccess', _96 => _96.destroy, 'call', _97 => _97()]);
|
|
3172
|
+
_optionalChain([this, 'access', _98 => _98.renderer, 'access', _99 => _99.dispose, 'optionalCall', _100 => _100()]);
|
|
3173
|
+
_optionalChain([this, 'access', _101 => _101.glCanvas, 'optionalAccess', _102 => _102.remove, 'call', _103 => _103()]);
|
|
3174
|
+
_optionalChain([this, 'access', _104 => _104.gpuCanvas, 'optionalAccess', _105 => _105.remove, 'call', _106 => _106()]);
|
|
3154
3175
|
this.gpuCanvas = null;
|
|
3155
3176
|
this.gpuContext = null;
|
|
3156
3177
|
if (this.recoveryTimerId) {
|
|
@@ -3162,7 +3183,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
3162
3183
|
this.manager = null;
|
|
3163
3184
|
}
|
|
3164
3185
|
if (this.device) {
|
|
3165
|
-
_optionalChain([this, 'access',
|
|
3186
|
+
_optionalChain([this, 'access', _107 => _107.device, 'access', _108 => _108.destroy, 'optionalCall', _109 => _109()]);
|
|
3166
3187
|
this.device = null;
|
|
3167
3188
|
}
|
|
3168
3189
|
}
|
|
@@ -3594,7 +3615,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
3594
3615
|
el.addEventListener("compositionupdate", (e) => {
|
|
3595
3616
|
const data = _nullishCoalesce(e.data, () => ( ""));
|
|
3596
3617
|
composition = {
|
|
3597
|
-
start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess',
|
|
3618
|
+
start: _nullishCoalesce(_optionalChain([composition, 'optionalAccess', _110 => _110.start]), () => ( 0)),
|
|
3598
3619
|
length: data.length
|
|
3599
3620
|
};
|
|
3600
3621
|
forward();
|
|
@@ -3667,7 +3688,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
3667
3688
|
this.syncOptionalAttribute(
|
|
3668
3689
|
el,
|
|
3669
3690
|
"href",
|
|
3670
|
-
attrs.href === void 0 ? void 0 :
|
|
3691
|
+
attrs.href === void 0 ? void 0 : _chunkLHONR3GOjs.sanitizeUrl.call(void 0, attrs.href)
|
|
3671
3692
|
);
|
|
3672
3693
|
this.syncOptionalAttribute(el, "target", attrs.target);
|
|
3673
3694
|
}
|
|
@@ -4047,9 +4068,9 @@ var Scene = (_class7 = class _Scene {
|
|
|
4047
4068
|
for (let lineIndex = 0; lineIndex < grid.lines.length; lineIndex++) {
|
|
4048
4069
|
const gridLine = grid.lines[lineIndex];
|
|
4049
4070
|
const projectedLine = projectionLines[lineIndex];
|
|
4050
|
-
const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
4051
|
-
const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
4052
|
-
const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
4071
|
+
const lineHeight = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _111 => _111.lineHeight]), () => ( grid.lineHeight));
|
|
4072
|
+
const baseline = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _112 => _112.baseline]), () => ( grid.baseline));
|
|
4073
|
+
const lineFont = _nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _113 => _113.font]), () => ( grid.font));
|
|
4053
4074
|
const lineSignature = contentGridLineSignature(
|
|
4054
4075
|
grid,
|
|
4055
4076
|
gridLine,
|
|
@@ -4069,8 +4090,8 @@ var Scene = (_class7 = class _Scene {
|
|
|
4069
4090
|
lineElement.dir = "ltr";
|
|
4070
4091
|
lineElement.dataset.vectoGridLine = `${lineIndex}`;
|
|
4071
4092
|
lineElement.style.position = "absolute";
|
|
4072
|
-
lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
4073
|
-
lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess',
|
|
4093
|
+
lineElement.style.left = `${_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _114 => _114.x]), () => ( 0))}px`;
|
|
4094
|
+
lineElement.style.top = `${(_nullishCoalesce(_optionalChain([projectedLine, 'optionalAccess', _115 => _115.y]), () => ( lineIndex * grid.lineHeight))) + baseline - _text.cssLineBoxBaseline.call(void 0, lineFont, lineHeight)}px`;
|
|
4074
4095
|
lineElement.style.width = `${gridLine.width}px`;
|
|
4075
4096
|
lineElement.style.height = `${lineHeight}px`;
|
|
4076
4097
|
lineElement.style.whiteSpace = "pre";
|
|
@@ -4140,7 +4161,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4140
4161
|
if (selectionLine !== null && selectionLine >= grid.lines.length) {
|
|
4141
4162
|
rebuiltSelectionLine = true;
|
|
4142
4163
|
}
|
|
4143
|
-
_optionalChain([el, 'access',
|
|
4164
|
+
_optionalChain([el, 'access', _116 => _116.lastElementChild, 'optionalAccess', _117 => _117.remove, 'call', _118 => _118()]);
|
|
4144
4165
|
}
|
|
4145
4166
|
if (rebuiltSelectionLine) this.releaseContentSelectionForRebuild(el);
|
|
4146
4167
|
el.dataset.vectoProjectionLines = signature;
|
|
@@ -4204,7 +4225,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4204
4225
|
if (previous !== void 0 && typeof cancelAnimationFrame === "function") {
|
|
4205
4226
|
cancelAnimationFrame(previous);
|
|
4206
4227
|
}
|
|
4207
|
-
_optionalChain([this, 'access',
|
|
4228
|
+
_optionalChain([this, 'access', _119 => _119.contentGridCalibrationProbes, 'access', _120 => _120.get, 'call', _121 => _121(entityId), 'optionalAccess', _122 => _122.remove, 'call', _123 => _123()]);
|
|
4208
4229
|
this.contentGridCalibrationProbes.delete(entityId);
|
|
4209
4230
|
const calibrationStart = typeof performance !== "undefined" ? performance.now() : 0;
|
|
4210
4231
|
const probe = document.createElement("div");
|
|
@@ -4238,7 +4259,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4238
4259
|
target.dataset.vectoGridCalib = generation;
|
|
4239
4260
|
continue;
|
|
4240
4261
|
}
|
|
4241
|
-
const sourceText = _nullishCoalesce(_optionalChain([target, 'access',
|
|
4262
|
+
const sourceText = _nullishCoalesce(_optionalChain([target, 'access', _124 => _124.textContent, 'optionalAccess', _125 => _125.slice, 'call', _126 => _126(0, sourceLength)]), () => ( ""));
|
|
4242
4263
|
if (!sourceText) {
|
|
4243
4264
|
target.dataset.vectoGridCalib = generation;
|
|
4244
4265
|
continue;
|
|
@@ -4449,12 +4470,12 @@ var Scene = (_class7 = class _Scene {
|
|
|
4449
4470
|
syncOverlayGeometry() {
|
|
4450
4471
|
const parent = this.canvas.parentElement;
|
|
4451
4472
|
if (!parent) return;
|
|
4452
|
-
const canvasRect = _optionalChain([this, 'access',
|
|
4453
|
-
const parentRect = _optionalChain([parent, 'access',
|
|
4454
|
-
const cssWidth = _optionalChain([canvasRect, 'optionalAccess',
|
|
4455
|
-
const cssHeight = _optionalChain([canvasRect, 'optionalAccess',
|
|
4456
|
-
const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess',
|
|
4457
|
-
const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess',
|
|
4473
|
+
const canvasRect = _optionalChain([this, 'access', _127 => _127.canvas, 'access', _128 => _128.getBoundingClientRect, 'optionalCall', _129 => _129()]);
|
|
4474
|
+
const parentRect = _optionalChain([parent, 'access', _130 => _130.getBoundingClientRect, 'optionalCall', _131 => _131()]);
|
|
4475
|
+
const cssWidth = _optionalChain([canvasRect, 'optionalAccess', _132 => _132.width]) || this.canvas.clientWidth || this.width;
|
|
4476
|
+
const cssHeight = _optionalChain([canvasRect, 'optionalAccess', _133 => _133.height]) || this.canvas.clientHeight || this.height;
|
|
4477
|
+
const left = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _134 => _134.left]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _135 => _135.left]), () => ( 0))) - (parent.clientLeft || 0) + parent.scrollLeft;
|
|
4478
|
+
const top = (_nullishCoalesce(_optionalChain([canvasRect, 'optionalAccess', _136 => _136.top]), () => ( 0))) - (_nullishCoalesce(_optionalChain([parentRect, 'optionalAccess', _137 => _137.top]), () => ( 0))) - (parent.clientTop || 0) + parent.scrollTop;
|
|
4458
4479
|
const scaleX = this.width > 0 ? cssWidth / this.width : 1;
|
|
4459
4480
|
const scaleY = this.height > 0 ? cssHeight / this.height : 1;
|
|
4460
4481
|
const prev = this._overlayGeometry;
|
|
@@ -4593,7 +4614,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4593
4614
|
* (and {@link respectReducedMotion} is on). `0` means uncapped.
|
|
4594
4615
|
*/
|
|
4595
4616
|
effectiveMaxFPS() {
|
|
4596
|
-
const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access',
|
|
4617
|
+
const reduced = this.respectReducedMotion && !!_optionalChain([this, 'access', _138 => _138.reducedMotionQuery, 'optionalAccess', _139 => _139.matches]);
|
|
4597
4618
|
if (reduced)
|
|
4598
4619
|
return this.maxFPS > 0 ? Math.min(this.maxFPS, REDUCED_MOTION_FPS) : REDUCED_MOTION_FPS;
|
|
4599
4620
|
return this.maxFPS;
|
|
@@ -4666,7 +4687,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4666
4687
|
* @param time - Current absolute time in milliseconds (default 0).
|
|
4667
4688
|
*/
|
|
4668
4689
|
render(renderer, dt = 0, time = 0) {
|
|
4669
|
-
if (_optionalChain([renderer, 'access',
|
|
4690
|
+
if (_optionalChain([renderer, 'access', _140 => _140.isContextLost, 'optionalCall', _141 => _141()])) return;
|
|
4670
4691
|
const isMainRenderer = renderer === this.renderer;
|
|
4671
4692
|
if (isMainRenderer && this.a11yRoot && this.canvas.parentElement) {
|
|
4672
4693
|
const parentStyle = this.canvas.parentElement.style;
|
|
@@ -4792,7 +4813,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
4792
4813
|
}
|
|
4793
4814
|
renderer.clear();
|
|
4794
4815
|
if (isMainRenderer) {
|
|
4795
|
-
_optionalChain([this, 'access',
|
|
4816
|
+
_optionalChain([this, 'access', _142 => _142.pointRenderer, 'optionalAccess', _143 => _143.begin, 'call', _144 => _144()]);
|
|
4796
4817
|
}
|
|
4797
4818
|
const vw = this.width;
|
|
4798
4819
|
const vh = this.height;
|
|
@@ -4989,9 +5010,9 @@ var Scene = (_class7 = class _Scene {
|
|
|
4989
5010
|
const flushT0 = this._phaseTiming ? performance.now() : 0;
|
|
4990
5011
|
renderer.flush();
|
|
4991
5012
|
if (isMainRenderer) {
|
|
4992
|
-
_optionalChain([this, 'access',
|
|
5013
|
+
_optionalChain([this, 'access', _145 => _145.pointRenderer, 'optionalAccess', _146 => _146.flush, 'call', _147 => _147()]);
|
|
4993
5014
|
}
|
|
4994
|
-
_optionalChain([renderer, 'access',
|
|
5015
|
+
_optionalChain([renderer, 'access', _148 => _148.present, 'optionalCall', _149 => _149()]);
|
|
4995
5016
|
if (this._phaseTiming) this._recordPhase("flush", performance.now() - flushT0);
|
|
4996
5017
|
if (this._devActive) {
|
|
4997
5018
|
this._devFrameCount++;
|
|
@@ -5002,7 +5023,7 @@ var Scene = (_class7 = class _Scene {
|
|
|
5002
5023
|
* Export the current scene state to a lightweight, flat SVG XML string.
|
|
5003
5024
|
*/
|
|
5004
5025
|
toSVG() {
|
|
5005
|
-
const renderer = new (0,
|
|
5026
|
+
const renderer = new (0, _chunkLHONR3GOjs.SVGRenderer)(this.width, this.height);
|
|
5006
5027
|
this.render(renderer, 0, 0);
|
|
5007
5028
|
return renderer.toXMLString();
|
|
5008
5029
|
}
|
|
@@ -5271,8 +5292,8 @@ function pointInBounds(b, x, y) {
|
|
|
5271
5292
|
function contentGridLineSignature(grid, line, projected, lineHeight, baseline, font, isFirstLine) {
|
|
5272
5293
|
const parts = [
|
|
5273
5294
|
// Line box: position, size, and the font that resolves its baseline.
|
|
5274
|
-
`${_nullishCoalesce(_optionalChain([projected, 'optionalAccess',
|
|
5275
|
-
`${_nullishCoalesce(_optionalChain([projected, 'optionalAccess',
|
|
5295
|
+
`${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _150 => _150.x]), () => ( 0))}`,
|
|
5296
|
+
`${_nullishCoalesce(_optionalChain([projected, 'optionalAccess', _151 => _151.y]), () => ( ""))}`,
|
|
5276
5297
|
`${lineHeight}`,
|
|
5277
5298
|
`${baseline}`,
|
|
5278
5299
|
font,
|
|
@@ -5459,7 +5480,7 @@ var GridTextEntity = (_class9 = class extends _chunkAGP4VLF4js.Entity {
|
|
|
5459
5480
|
updateGrid(ascii) {
|
|
5460
5481
|
this.grid = ascii;
|
|
5461
5482
|
this.rows = ascii.length;
|
|
5462
|
-
this.cols = _optionalChain([ascii, 'access',
|
|
5483
|
+
this.cols = _optionalChain([ascii, 'access', _152 => _152[0], 'optionalAccess', _153 => _153.length]) || 0;
|
|
5463
5484
|
}
|
|
5464
5485
|
isPointInside(_globalX, _globalY) {
|
|
5465
5486
|
return false;
|
|
@@ -5569,7 +5590,7 @@ var SplineEntity = (_class10 = class extends _chunkAGP4VLF4js.Entity {
|
|
|
5569
5590
|
this.width = this.bounds.width;
|
|
5570
5591
|
this.height = this.bounds.height;
|
|
5571
5592
|
const isGradient = (c) => c !== null && !Array.isArray(c);
|
|
5572
|
-
this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access',
|
|
5593
|
+
this.containsGradient = (_nullishCoalesce(_optionalChain([this, 'access', _154 => _154.doc, 'access', _155 => _155.equations, 'optionalAccess', _156 => _156.some, 'call', _157 => _157((eq) => isGradient(eq.color_rgb))]), () => ( false))) || (_nullishCoalesce(_optionalChain([this, 'access', _158 => _158.doc, 'access', _159 => _159.paths, 'optionalAccess', _160 => _160.some, 'call', _161 => _161((p) => isGradient(p.color_rgb))]), () => ( false)));
|
|
5573
5594
|
this.interactive = true;
|
|
5574
5595
|
}
|
|
5575
5596
|
computeBounds() {
|
|
@@ -6063,8 +6084,8 @@ var DOMPortalEntity = (_class11 = class extends _chunkAGP4VLF4js.Entity {
|
|
|
6063
6084
|
}, _class11);
|
|
6064
6085
|
|
|
6065
6086
|
// src/index.ts
|
|
6066
|
-
Scene.registerWebGLPointRendererCreator(
|
|
6067
|
-
Scene.registerWebGPUParticleSystemManager(
|
|
6087
|
+
Scene.registerWebGLPointRendererCreator(_chunkLHONR3GOjs.createWebGLPointRenderer);
|
|
6088
|
+
Scene.registerWebGPUParticleSystemManager(_chunkLHONR3GOjs.WebGPUParticleSystemManager);
|
|
6068
6089
|
|
|
6069
6090
|
|
|
6070
6091
|
|
|
@@ -6100,4 +6121,4 @@ Scene.registerWebGPUParticleSystemManager(_chunkGKSCJ6AFjs.WebGPUParticleSystemM
|
|
|
6100
6121
|
|
|
6101
6122
|
|
|
6102
6123
|
|
|
6103
|
-
exports.CanvasRenderer =
|
|
6124
|
+
exports.CanvasRenderer = _chunkLHONR3GOjs.CanvasRenderer; exports.Circle = Circle; exports.ComputeParticleEntity = ComputeParticleEntity; exports.DOMPortalEntity = DOMPortalEntity; exports.Entity = _chunkAGP4VLF4js.Entity; exports.GlyphRasterAtlas = _chunkLHONR3GOjs.GlyphRasterAtlas; exports.GridTextEntity = GridTextEntity; exports.Group = Group; exports.MSDFTextEntity = _chunkAGP4VLF4js.MSDFTextEntity; exports.PARTICLE_OFFSET_LIFE = PARTICLE_OFFSET_LIFE; exports.PARTICLE_OFFSET_ORIGIN_X = PARTICLE_OFFSET_ORIGIN_X; exports.PARTICLE_OFFSET_ORIGIN_Y = PARTICLE_OFFSET_ORIGIN_Y; exports.PARTICLE_OFFSET_POSITION_X = PARTICLE_OFFSET_POSITION_X; exports.PARTICLE_OFFSET_POSITION_Y = PARTICLE_OFFSET_POSITION_Y; exports.PARTICLE_OFFSET_SIZE = PARTICLE_OFFSET_SIZE; exports.PARTICLE_OFFSET_VELOCITY_X = PARTICLE_OFFSET_VELOCITY_X; exports.PARTICLE_OFFSET_VELOCITY_Y = PARTICLE_OFFSET_VELOCITY_Y; exports.PARTICLE_STRIDE_FLOATS = PARTICLE_STRIDE_FLOATS; exports.REDUCED_MOTION_FPS = REDUCED_MOTION_FPS; exports.Rect = Rect; exports.SVGEntity = _chunkAGP4VLF4js.SVGEntity; exports.SVGRenderer = _chunkLHONR3GOjs.SVGRenderer; exports.Scene = Scene; exports.SplineEntity = SplineEntity; exports.TextEntity = TextEntity; exports.TextRasterCache = _chunkLHONR3GOjs.TextRasterCache; exports.VectoJSEvent = _chunkAGP4VLF4js.VectoJSEvent; exports.WebGPUParticleSystemManager = _chunkLHONR3GOjs.WebGPUParticleSystemManager; exports.createWebGLPointRenderer = _chunkLHONR3GOjs.createWebGLPointRenderer; exports.isSafeUrl = _chunkLHONR3GOjs.isSafeUrl; exports.loadSpline = loadSpline; exports.parseColorToRGBA = _chunkLHONR3GOjs.parseColorToRGBA; exports.polySegmentToBezier = polySegmentToBezier; exports.sanitizeUrl = _chunkLHONR3GOjs.sanitizeUrl;
|
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isSafeUrl,
|
|
9
9
|
parseColorToRGBA,
|
|
10
10
|
sanitizeUrl
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-UPULSLKA.mjs";
|
|
12
12
|
import {
|
|
13
13
|
Entity,
|
|
14
14
|
MSDFTextEntity,
|
|
@@ -2462,6 +2462,27 @@ var Scene = class _Scene {
|
|
|
2462
2462
|
get webgpuDisabled() {
|
|
2463
2463
|
return this._webgpuDisabled || this.particleBackend === "cpu";
|
|
2464
2464
|
}
|
|
2465
|
+
/**
|
|
2466
|
+
* Draw accounting for the WebGL point layer, or null when that layer is not in
|
|
2467
|
+
* use.
|
|
2468
|
+
*
|
|
2469
|
+
* Null and all-zero mean different things: null is "this backend is not
|
|
2470
|
+
* running", zero is "it ran and drew nothing". A readout that conflates them
|
|
2471
|
+
* sends someone looking for a performance problem in a backend that was never
|
|
2472
|
+
* active.
|
|
2473
|
+
*/
|
|
2474
|
+
get webglDrawStats() {
|
|
2475
|
+
return this.pointRenderer?.stats?.() ?? null;
|
|
2476
|
+
}
|
|
2477
|
+
/**
|
|
2478
|
+
* Whether a WebGPU device is currently live for particle compute.
|
|
2479
|
+
*
|
|
2480
|
+
* The WebGPU path only activates when a `ComputeParticleEntity` is present, so
|
|
2481
|
+
* most scenes never touch it.
|
|
2482
|
+
*/
|
|
2483
|
+
get webgpuActive() {
|
|
2484
|
+
return this.device !== null && !this.deviceLost;
|
|
2485
|
+
}
|
|
2465
2486
|
set webgpuDisabled(value) {
|
|
2466
2487
|
this._webgpuDisabled = value;
|
|
2467
2488
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IRenderer } from './IRenderer';
|
|
1
|
+
import { type DrawCounters, IRenderer } from './IRenderer';
|
|
2
2
|
export declare class CanvasRenderer implements IRenderer {
|
|
3
3
|
private ctx;
|
|
4
4
|
private width;
|
|
@@ -33,6 +33,17 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
33
33
|
private batchCount;
|
|
34
34
|
private _cachedFont;
|
|
35
35
|
private _cachedFill;
|
|
36
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
37
|
+
readonly kind = "canvas2d";
|
|
38
|
+
/**
|
|
39
|
+
* Draw counters, allocated only once counting is enabled.
|
|
40
|
+
*
|
|
41
|
+
* Null when off, so the guard on every op is a single null test and an inactive
|
|
42
|
+
* renderer carries no counter object at all.
|
|
43
|
+
*/
|
|
44
|
+
private counters;
|
|
45
|
+
/** Accumulated primitive area, kept separately so the ratio is derived on read. */
|
|
46
|
+
private drawnArea;
|
|
36
47
|
/**
|
|
37
48
|
* @param canvas - The target canvas. Its backing store is resized to the
|
|
38
49
|
* logical size × devicePixelRatio.
|
|
@@ -79,6 +90,12 @@ export declare class CanvasRenderer implements IRenderer {
|
|
|
79
90
|
* restored). The owner skips its render pass while this is true. */
|
|
80
91
|
isContextLost(): boolean;
|
|
81
92
|
/** @inheritdoc */
|
|
93
|
+
/** @inheritdoc */
|
|
94
|
+
setDrawCounters(enabled: boolean): void;
|
|
95
|
+
/** @inheritdoc */
|
|
96
|
+
getDrawCounters(): DrawCounters | null;
|
|
97
|
+
/** @inheritdoc */
|
|
98
|
+
clearDrawCounters(): void;
|
|
82
99
|
clear(): void;
|
|
83
100
|
/** @inheritdoc */
|
|
84
101
|
save(): void;
|
|
@@ -12,7 +12,70 @@
|
|
|
12
12
|
* r.fill('#38bdf8');
|
|
13
13
|
* }
|
|
14
14
|
*/
|
|
15
|
+
/**
|
|
16
|
+
* Per-backend draw counters, for a DevTools GPU readout.
|
|
17
|
+
*
|
|
18
|
+
* Opt-in via {@link IRenderer.setDrawCounters}: when off, counting compiles to a
|
|
19
|
+
* single boolean test per op, matching how `Scene` gates its phase timing and
|
|
20
|
+
* dirty tracking. Totals are cumulative until cleared rather than per-frame,
|
|
21
|
+
* because a per-frame log answers the question less directly at far more memory —
|
|
22
|
+
* the same reasoning `Scene.renderPhases` documents.
|
|
23
|
+
*/
|
|
24
|
+
export interface DrawCounters {
|
|
25
|
+
/** `fill()` calls, each committing one path. */
|
|
26
|
+
fills: number;
|
|
27
|
+
/** `stroke()` calls. */
|
|
28
|
+
strokes: number;
|
|
29
|
+
/** `fillText()` calls. */
|
|
30
|
+
texts: number;
|
|
31
|
+
/** `drawImage`/`drawImageRect` blits. */
|
|
32
|
+
images: number;
|
|
33
|
+
/** `fillCircle()` calls — batched, so this exceeds the fills they produce. */
|
|
34
|
+
circles: number;
|
|
35
|
+
/** Batch commits from {@link IRenderer.flush}. */
|
|
36
|
+
flushes: number;
|
|
37
|
+
/** `save()` calls. */
|
|
38
|
+
saves: number;
|
|
39
|
+
/** `restore()` calls. */
|
|
40
|
+
restores: number;
|
|
41
|
+
/** `clip()` calls. */
|
|
42
|
+
clips: number;
|
|
43
|
+
/**
|
|
44
|
+
* Times a font or fill style actually changed, as opposed to being re-set to
|
|
45
|
+
* the value it already had.
|
|
46
|
+
*
|
|
47
|
+
* The renderer already elides redundant sets; this counts the ones that got
|
|
48
|
+
* through, which is the number that costs anything.
|
|
49
|
+
*/
|
|
50
|
+
stateSwitches: number;
|
|
51
|
+
/**
|
|
52
|
+
* Sum of drawn primitive areas divided by canvas area.
|
|
53
|
+
*
|
|
54
|
+
* A PROXY for overdraw, not a measurement: Canvas2D exposes no pixel-coverage
|
|
55
|
+
* readback, so this counts area submitted, ignoring clipping and off-screen
|
|
56
|
+
* rejection. It overstates, sometimes badly. Useful as a trend between two
|
|
57
|
+
* states of the same scene; meaningless as an absolute.
|
|
58
|
+
*/
|
|
59
|
+
overdrawRatio: number;
|
|
60
|
+
}
|
|
15
61
|
export interface IRenderer {
|
|
62
|
+
/**
|
|
63
|
+
* Stable backend identifier.
|
|
64
|
+
*
|
|
65
|
+
* A discriminator rather than `constructor.name`, which minifies to something
|
|
66
|
+
* unusable in a production bundle — and a debug tool that cannot name the
|
|
67
|
+
* backend in the build where it matters is not much of a debug tool.
|
|
68
|
+
*/
|
|
69
|
+
readonly kind?: 'canvas2d' | 'svg' | 'three' | string;
|
|
70
|
+
/**
|
|
71
|
+
* Enable or disable draw counting. Optional; a backend that cannot count omits
|
|
72
|
+
* it and a reader treats the absence as "not available".
|
|
73
|
+
*/
|
|
74
|
+
setDrawCounters?(enabled: boolean): void;
|
|
75
|
+
/** Current counter totals, or null when counting is off. */
|
|
76
|
+
getDrawCounters?(): DrawCounters | null;
|
|
77
|
+
/** Zero the totals without disabling counting. */
|
|
78
|
+
clearDrawCounters?(): void;
|
|
16
79
|
/** Clear the entire drawing surface to transparent / background color. */
|
|
17
80
|
clear(): void;
|
|
18
81
|
/** Push the current transform + state onto the renderer's stack. */
|
|
@@ -13,6 +13,8 @@ export interface SVGLinearGradient {
|
|
|
13
13
|
createMatrix: number[];
|
|
14
14
|
}
|
|
15
15
|
export declare class SVGRenderer implements IRenderer {
|
|
16
|
+
/** Backend discriminator; see {@link IRenderer.kind}. */
|
|
17
|
+
readonly kind = "svg";
|
|
16
18
|
private width;
|
|
17
19
|
private height;
|
|
18
20
|
private buffer;
|
|
@@ -4,6 +4,29 @@
|
|
|
4
4
|
* render `getBatchCircle()` / `getBatchRect()` entities — the point-cloud /
|
|
5
5
|
* particle case where Canvas2D tops out at ~7 fps for 100k primitives.
|
|
6
6
|
*/
|
|
7
|
+
/** Per-frame and cumulative WebGL draw accounting. */
|
|
8
|
+
export interface WebGLDrawStats {
|
|
9
|
+
/** Draw calls issued for the last completed frame. */
|
|
10
|
+
drawCalls: number;
|
|
11
|
+
/** Cumulative draw calls since creation. */
|
|
12
|
+
totalDrawCalls: number;
|
|
13
|
+
/** Cumulative mid-frame MSDF atlas switches, each costing an extra draw. */
|
|
14
|
+
atlasSwitches: number;
|
|
15
|
+
/** Programs compiled at creation — a fixed capability, not a per-frame cost. */
|
|
16
|
+
programs: number;
|
|
17
|
+
/** Textures currently allocated (colour atlas and/or MSDF atlas). */
|
|
18
|
+
textures: number;
|
|
19
|
+
/**
|
|
20
|
+
* Circles routed to the quad path rather than `gl.POINTS`, cumulatively.
|
|
21
|
+
*
|
|
22
|
+
* A circle takes the quad path when it could clip off-viewport or exceeds the
|
|
23
|
+
* driver's maximum aliased point size. A high share means the POINTS fast path
|
|
24
|
+
* is not being used and each circle costs four vertices instead of one.
|
|
25
|
+
*/
|
|
26
|
+
circleQuadFallbacks: number;
|
|
27
|
+
/** Circles drawn through the `gl.POINTS` fast path, cumulatively. */
|
|
28
|
+
circlePoints: number;
|
|
29
|
+
}
|
|
7
30
|
export interface PointRenderer {
|
|
8
31
|
/** Resize the backing buffer + GL viewport to a logical `w × h` (DPR applied). */
|
|
9
32
|
resize(width: number, height: number): void;
|
|
@@ -21,6 +44,16 @@ export interface PointRenderer {
|
|
|
21
44
|
maxDPR?: number;
|
|
22
45
|
/** Begin a frame: reset the accumulated primitive buffers. */
|
|
23
46
|
begin(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Draw-call counters for the most recent frame, plus cumulative totals.
|
|
49
|
+
*
|
|
50
|
+
* Batching here is by primitive type — one draw per active type — so draw calls
|
|
51
|
+
* and batches are the same number, and both are bounded at five plus one per
|
|
52
|
+
* mid-frame MSDF atlas switch. That switch is the only variable term and the
|
|
53
|
+
* only thing worth watching: it forces a commit of glyphs batched against the
|
|
54
|
+
* previous font.
|
|
55
|
+
*/
|
|
56
|
+
stats?(): WebGLDrawStats;
|
|
24
57
|
/** Add one circle in world (CSS-pixel) coordinates; `alpha` multiplies the color's. */
|
|
25
58
|
addCircle(x: number, y: number, radius: number, color: string, alpha?: number): void;
|
|
26
59
|
/**
|