@vectojs/three 0.1.1 → 0.1.3

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.
@@ -0,0 +1,67 @@
1
+ import * as THREE from 'three';
2
+ import { Scene as VectoScene, SceneOptions } from '@vectojs/core';
3
+ export interface ThreeAdapterOptions {
4
+ /** Physical layout width of the 2D UI canvas. */
5
+ width: number;
6
+ /** Physical layout height of the 2D UI canvas. */
7
+ height: number;
8
+ /** Optional pre-existing canvas element. If omitted, a new canvas is created. */
9
+ canvas?: HTMLCanvasElement;
10
+ /** Options passed to the VectoScene constructor. */
11
+ sceneOptions?: SceneOptions;
12
+ }
13
+ /**
14
+ * Adapts a VectoJS Scene into a Three.js CanvasTexture, allowing VectoJS
15
+ * components to be rendered in 3D space (e.g. on a plane, screen, or VR dashboard).
16
+ */
17
+ export declare class ThreeAdapter {
18
+ /** The Three.js CanvasTexture wrapping the offscreen Vecto canvas. */
19
+ texture: THREE.CanvasTexture;
20
+ /** The active VectoJS Scene instance. */
21
+ vectoScene: VectoScene;
22
+ /** The offscreen HTMLCanvasElement on which Vecto draws. */
23
+ canvas: HTMLCanvasElement;
24
+ /** A pre-built THREE.Mesh with PlaneGeometry and this texture for immediate use. */
25
+ mesh: THREE.Mesh;
26
+ /** Track hover states independently per pointerId for WebXR / Multi-Touch. */
27
+ private activePointers;
28
+ /**
29
+ * Holds the original `vectoScene.render` reference so {@link dispose} can
30
+ * restore it. Without restoring, a later render call would write
31
+ * `needsUpdate` on a disposed (deleted) `CanvasTexture`, which Three.js
32
+ * flags with `"THREE.Texture: trying to use deleted texture"`.
33
+ */
34
+ private _originalRender;
35
+ /** Tracks whether this adapter owns the canvas it is rendering to. */
36
+ private _ownsCanvas;
37
+ private _disposed;
38
+ constructor(options: ThreeAdapterOptions);
39
+ /**
40
+ * Processes 3D Raycasting intersections and forwards pointer/scroll events.
41
+ * Call this from window/document event listeners passing the raycaster.
42
+ *
43
+ * @param raycaster Three.js Raycaster instance.
44
+ * @param type Pointer event type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click'.
45
+ * @param originalEvent Optional original DOM Event to forward scroll deltas or button states.
46
+ * @returns true if the ray intersected the VectoJS mesh; false otherwise.
47
+ */
48
+ updateIntersection(raycaster: THREE.Raycaster, type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click', originalEvent?: Event): boolean;
49
+ /**
50
+ * Dispatches pointer events mapped from UV coordinates [0, 1] to VectoJS entities.
51
+ */
52
+ private dispatchAtUv;
53
+ /**
54
+ * Routes events to the associated A11y DOM element, or Vecto's own event dispatch system.
55
+ */
56
+ private dispatchEventToTarget;
57
+ private createDOMEvent;
58
+ private findEntityById;
59
+ /**
60
+ * Resizes the offscreen canvas and VectoScene dimensions.
61
+ */
62
+ resize(width: number, height: number): void;
63
+ /**
64
+ * Disposes of Three.js textures, geometries, and VectoJS scenes to prevent memory leaks.
65
+ */
66
+ dispose(): void;
67
+ }
@@ -0,0 +1,67 @@
1
+ import { IRenderer } from '@vectojs/core';
2
+ import * as THREE from 'three';
3
+ export declare class WebGLGradient {
4
+ x0: number;
5
+ y0: number;
6
+ x1: number;
7
+ y1: number;
8
+ colorStops: {
9
+ stop: number;
10
+ color: string;
11
+ }[];
12
+ type: string;
13
+ constructor(x0: number, y0: number, x1: number, y1: number, colorStops: {
14
+ stop: number;
15
+ color: string;
16
+ }[]);
17
+ }
18
+ /**
19
+ * WebGL/Three.js implementation of {@link IRenderer}.
20
+ *
21
+ * Bridges VectoJS's 2D canvas API to Three.js for 3D hardware-accelerated rendering.
22
+ */
23
+ export declare class ThreeRenderer implements IRenderer {
24
+ scene: THREE.Scene;
25
+ camera: THREE.OrthographicCamera;
26
+ renderer: THREE.WebGLRenderer;
27
+ private width;
28
+ private height;
29
+ private matrix;
30
+ private stack;
31
+ private globalAlpha;
32
+ private alphaStack;
33
+ private currentPath;
34
+ private activeObjects;
35
+ private scissorStack;
36
+ constructor(canvas: HTMLCanvasElement);
37
+ resize(width: number, height: number): void;
38
+ clear(): void;
39
+ private disposeActiveObjects;
40
+ save(): void;
41
+ restore(): void;
42
+ translate(x: number, y: number): void;
43
+ scale(x: number, y: number): void;
44
+ rotate(angle: number): void;
45
+ setGlobalAlpha(alpha: number): void;
46
+ clip(x: number, y: number, width: number, height: number): void;
47
+ beginPath(): void;
48
+ moveTo(x: number, y: number): void;
49
+ lineTo(x: number, y: number): void;
50
+ bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
51
+ closePath(): void;
52
+ arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
53
+ roundRect(x: number, y: number, width: number, height: number, radii: number | number[]): void;
54
+ drawImage(source: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
55
+ fill(colorOrGradient: string | any): void;
56
+ private fillSolidShape;
57
+ stroke(colorOrGradient: string | any, lineWidth?: number): void;
58
+ fillText(text: string, x: number, y: number, font: string, color: string | any): void;
59
+ fillCircle(cx: number, cy: number, radius: number, color: string, alpha?: number): void;
60
+ flush(): void;
61
+ createLinearGradient(x0: number, y0: number, x1: number, y1: number, colorStops: {
62
+ stop: number;
63
+ color: string;
64
+ }[]): any;
65
+ private disposed;
66
+ dispose(): void;
67
+ }
package/dist/index.d.ts CHANGED
@@ -1,123 +1,2 @@
1
- import { IRenderer, Scene, SceneOptions } from '@vectojs/core';
2
- import * as THREE from 'three';
3
-
4
- declare class WebGLGradient {
5
- x0: number;
6
- y0: number;
7
- x1: number;
8
- y1: number;
9
- colorStops: {
10
- stop: number;
11
- color: string;
12
- }[];
13
- type: string;
14
- constructor(x0: number, y0: number, x1: number, y1: number, colorStops: {
15
- stop: number;
16
- color: string;
17
- }[]);
18
- }
19
- /**
20
- * WebGL/Three.js implementation of {@link IRenderer}.
21
- *
22
- * Bridges VectoJS's 2D canvas API to Three.js for 3D hardware-accelerated rendering.
23
- */
24
- declare class ThreeRenderer implements IRenderer {
25
- scene: THREE.Scene;
26
- camera: THREE.OrthographicCamera;
27
- renderer: THREE.WebGLRenderer;
28
- private width;
29
- private height;
30
- private matrix;
31
- private stack;
32
- private globalAlpha;
33
- private alphaStack;
34
- private currentPath;
35
- private activeObjects;
36
- private scissorStack;
37
- constructor(canvas: HTMLCanvasElement);
38
- resize(width: number, height: number): void;
39
- clear(): void;
40
- save(): void;
41
- restore(): void;
42
- translate(x: number, y: number): void;
43
- scale(x: number, y: number): void;
44
- rotate(angle: number): void;
45
- setGlobalAlpha(alpha: number): void;
46
- clip(x: number, y: number, width: number, height: number): void;
47
- beginPath(): void;
48
- moveTo(x: number, y: number): void;
49
- lineTo(x: number, y: number): void;
50
- bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
51
- closePath(): void;
52
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
53
- roundRect(x: number, y: number, width: number, height: number, radii: number | number[]): void;
54
- drawImage(source: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
55
- fill(colorOrGradient: string | any): void;
56
- private fillSolidShape;
57
- stroke(colorOrGradient: string | any, lineWidth?: number): void;
58
- fillText(text: string, x: number, y: number, font: string, color: string | any): void;
59
- fillCircle(cx: number, cy: number, radius: number, color: string, alpha?: number): void;
60
- flush(): void;
61
- createLinearGradient(x0: number, y0: number, x1: number, y1: number, colorStops: {
62
- stop: number;
63
- color: string;
64
- }[]): any;
65
- }
66
-
67
- interface ThreeAdapterOptions {
68
- /** Physical layout width of the 2D UI canvas. */
69
- width: number;
70
- /** Physical layout height of the 2D UI canvas. */
71
- height: number;
72
- /** Optional pre-existing canvas element. If omitted, a new canvas is created. */
73
- canvas?: HTMLCanvasElement;
74
- /** Options passed to the VectoScene constructor. */
75
- sceneOptions?: SceneOptions;
76
- }
77
- /**
78
- * Adapts a VectoJS Scene into a Three.js CanvasTexture, allowing VectoJS
79
- * components to be rendered in 3D space (e.g. on a plane, screen, or VR dashboard).
80
- */
81
- declare class ThreeAdapter {
82
- /** The Three.js CanvasTexture wrapping the offscreen Vecto canvas. */
83
- texture: THREE.CanvasTexture;
84
- /** The active VectoJS Scene instance. */
85
- vectoScene: Scene;
86
- /** The offscreen HTMLCanvasElement on which Vecto draws. */
87
- canvas: HTMLCanvasElement;
88
- /** A pre-built THREE.Mesh with PlaneGeometry and this texture for immediate use. */
89
- mesh: THREE.Mesh;
90
- /** Track hover states independently per pointerId for WebXR / Multi-Touch. */
91
- private activePointers;
92
- constructor(options: ThreeAdapterOptions);
93
- /**
94
- * Processes 3D Raycasting intersections and forwards pointer/scroll events.
95
- * Call this from window/document event listeners passing the raycaster.
96
- *
97
- * @param raycaster Three.js Raycaster instance.
98
- * @param type Pointer event type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click'.
99
- * @param originalEvent Optional original DOM Event to forward scroll deltas or button states.
100
- * @returns true if the ray intersected the VectoJS mesh; false otherwise.
101
- */
102
- updateIntersection(raycaster: THREE.Raycaster, type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click', originalEvent?: Event): boolean;
103
- /**
104
- * Dispatches pointer events mapped from UV coordinates [0, 1] to VectoJS entities.
105
- */
106
- private dispatchAtUv;
107
- /**
108
- * Routes events to the associated A11y DOM element, or Vecto's own event dispatch system.
109
- */
110
- private dispatchEventToTarget;
111
- private createDOMEvent;
112
- private findEntityById;
113
- /**
114
- * Resizes the offscreen canvas and VectoScene dimensions.
115
- */
116
- resize(width: number, height: number): void;
117
- /**
118
- * Disposes of Three.js textures, geometries, and VectoJS scenes to prevent memory leaks.
119
- */
120
- dispose(): void;
121
- }
122
-
123
- export { ThreeAdapter, type ThreeAdapterOptions, ThreeRenderer, WebGLGradient };
1
+ export * from './ThreeRenderer';
2
+ export * from './ThreeAdapter';
package/dist/index.js CHANGED
@@ -39,6 +39,10 @@ module.exports = __toCommonJS(index_exports);
39
39
  // src/ThreeRenderer.ts
40
40
  var import_core = require("@vectojs/core");
41
41
  var THREE = __toESM(require("three"));
42
+ function parseThreeColor(value) {
43
+ const [r, g, b, alpha] = (0, import_core.parseColorToRGBA)(value);
44
+ return { color: new THREE.Color(r, g, b), alpha };
45
+ }
42
46
  var WebGLGradient = class {
43
47
  constructor(x0, y0, x1, y1, colorStops) {
44
48
  this.x0 = x0;
@@ -111,14 +115,16 @@ var ThreeRenderer = class {
111
115
  activeObjects = [];
112
116
  scissorStack = [];
113
117
  constructor(canvas) {
114
- this.width = window.innerWidth;
115
- this.height = window.innerHeight;
118
+ const cw = canvas.width > 0 ? canvas.width : typeof window !== "undefined" ? window.innerWidth : 1024;
119
+ const ch = canvas.height > 0 ? canvas.height : typeof window !== "undefined" ? window.innerHeight : 1024;
120
+ this.width = cw;
121
+ this.height = ch;
116
122
  this.scene = new THREE.Scene();
117
123
  this.camera = new THREE.OrthographicCamera(0, this.width, 0, this.height, 0.1, 1e3);
118
124
  this.camera.position.z = 1;
119
125
  this.renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
120
126
  this.renderer.setSize(this.width, this.height);
121
- this.renderer.setPixelRatio(window.devicePixelRatio || 1);
127
+ this.renderer.setPixelRatio(typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1);
122
128
  this.matrix = new THREE.Matrix4().identity();
123
129
  }
124
130
  resize(width, height) {
@@ -130,26 +136,42 @@ var ThreeRenderer = class {
130
136
  this.camera.updateProjectionMatrix();
131
137
  }
132
138
  clear() {
133
- for (const obj of this.activeObjects) {
134
- this.scene.remove(obj);
135
- if (obj instanceof THREE.Mesh || obj instanceof THREE.Line) {
136
- obj.geometry.dispose();
137
- if (Array.isArray(obj.material)) {
138
- for (const mat of obj.material) {
139
- mat.dispose();
140
- if (mat.map) mat.map.dispose();
141
- }
142
- } else {
143
- obj.material.dispose();
144
- if (obj.material.map) {
145
- obj.material.map.dispose();
146
- }
139
+ this.disposeActiveObjects();
140
+ this.currentPath = null;
141
+ this.matrix.identity();
142
+ this.stack.length = 0;
143
+ this.globalAlpha = 1;
144
+ this.alphaStack.length = 0;
145
+ this.scissorStack.length = 0;
146
+ this.renderer.clear();
147
+ this.renderer.setScissorTest(false);
148
+ }
149
+ disposeActiveObjects() {
150
+ const disposedGeometries = /* @__PURE__ */ new Set();
151
+ const disposedMaterials = /* @__PURE__ */ new Set();
152
+ const disposedTextures = /* @__PURE__ */ new Set();
153
+ for (const object of this.activeObjects) {
154
+ this.scene.remove(object);
155
+ if (!(object instanceof THREE.Mesh || object instanceof THREE.Line)) continue;
156
+ const geometry = object.geometry;
157
+ if (!disposedGeometries.has(geometry)) {
158
+ disposedGeometries.add(geometry);
159
+ geometry.dispose();
160
+ }
161
+ const materials = Array.isArray(object.material) ? object.material : [object.material];
162
+ for (const material of materials) {
163
+ const map = material.map;
164
+ if (map && !disposedTextures.has(map)) {
165
+ disposedTextures.add(map);
166
+ map.dispose();
167
+ }
168
+ if (!disposedMaterials.has(material)) {
169
+ disposedMaterials.add(material);
170
+ material.dispose();
147
171
  }
148
172
  }
149
173
  }
150
- this.activeObjects = [];
151
- this.renderer.clear();
152
- this.renderer.setScissorTest(false);
174
+ this.activeObjects.length = 0;
153
175
  }
154
176
  save() {
155
177
  this.stack.push(this.matrix.clone());
@@ -186,16 +208,33 @@ var ThreeRenderer = class {
186
208
  this.globalAlpha = alpha;
187
209
  }
188
210
  clip(x, y, width, height) {
189
- const pos = new THREE.Vector3(x, y, 0).applyMatrix4(this.matrix);
190
- const size = new THREE.Vector3(width, height, 0).applyMatrix4(this.matrix).sub(new THREE.Vector3(0, 0, 0).applyMatrix4(this.matrix));
211
+ const corners = [
212
+ new THREE.Vector3(x, y, 0),
213
+ new THREE.Vector3(x + width, y, 0),
214
+ new THREE.Vector3(x, y + height, 0),
215
+ new THREE.Vector3(x + width, y + height, 0)
216
+ ].map((point) => point.applyMatrix4(this.matrix));
217
+ const minX = Math.min(...corners.map((point) => point.x));
218
+ const minY = Math.min(...corners.map((point) => point.y));
219
+ const maxX = Math.max(...corners.map((point) => point.x));
220
+ const maxY = Math.max(...corners.map((point) => point.y));
191
221
  const dpr = window.devicePixelRatio || 1;
192
222
  const canvasHeight = this.renderer.domElement.height / dpr;
193
- this.renderer.setScissor(
194
- pos.x * dpr,
195
- (canvasHeight - (pos.y + size.y)) * dpr,
196
- size.x * dpr,
197
- size.y * dpr
198
- );
223
+ let scissorX = minX * dpr;
224
+ let scissorY = (canvasHeight - maxY) * dpr;
225
+ let scissorWidth = (maxX - minX) * dpr;
226
+ let scissorHeight = (maxY - minY) * dpr;
227
+ if (this.renderer.getScissorTest()) {
228
+ const current = new THREE.Vector4();
229
+ this.renderer.getScissor(current);
230
+ const right = Math.min(scissorX + scissorWidth, current.x + current.z);
231
+ const top = Math.min(scissorY + scissorHeight, current.y + current.w);
232
+ scissorX = Math.max(scissorX, current.x);
233
+ scissorY = Math.max(scissorY, current.y);
234
+ scissorWidth = Math.max(0, right - scissorX);
235
+ scissorHeight = Math.max(0, top - scissorY);
236
+ }
237
+ this.renderer.setScissor(scissorX, scissorY, scissorWidth, scissorHeight);
199
238
  this.renderer.setScissorTest(true);
200
239
  }
201
240
  beginPath() {
@@ -414,13 +453,15 @@ var ThreeRenderer = class {
414
453
  fillSolidShape(colorOrGradient) {
415
454
  if (!this.currentPath) return;
416
455
  const color = typeof colorOrGradient === "string" ? colorOrGradient : "#ffffff";
456
+ const parsed = parseThreeColor(color);
417
457
  const shapes = this.currentPath.toShapes();
418
458
  for (const shape of shapes) {
419
459
  const geometry = new THREE.ShapeGeometry(shape);
460
+ const opacity = this.globalAlpha * parsed.alpha;
420
461
  const material = new THREE.MeshBasicMaterial({
421
- color: new THREE.Color(color),
422
- transparent: this.globalAlpha < 1,
423
- opacity: this.globalAlpha,
462
+ color: parsed.color,
463
+ transparent: opacity < 1,
464
+ opacity,
424
465
  depthWrite: false
425
466
  });
426
467
  const mesh = new THREE.Mesh(geometry, material);
@@ -443,10 +484,12 @@ var ThreeRenderer = class {
443
484
  const points = this.currentPath.getPoints();
444
485
  if (points.length === 0) return;
445
486
  const geometry = new THREE.BufferGeometry().setFromPoints(points);
487
+ const parsed = parseThreeColor(color);
488
+ const opacity = this.globalAlpha * parsed.alpha;
446
489
  const material = new THREE.LineBasicMaterial({
447
- color: new THREE.Color(color),
448
- transparent: this.globalAlpha < 1,
449
- opacity: this.globalAlpha,
490
+ color: parsed.color,
491
+ transparent: opacity < 1,
492
+ opacity,
450
493
  linewidth: lineWidth
451
494
  });
452
495
  const line = new THREE.Line(geometry, material);
@@ -494,10 +537,12 @@ var ThreeRenderer = class {
494
537
  }
495
538
  fillCircle(cx, cy, radius, color, alpha = 1) {
496
539
  const geometry = new THREE.CircleGeometry(radius, 32);
540
+ const parsed = parseThreeColor(color);
541
+ const opacity = this.globalAlpha * alpha * parsed.alpha;
497
542
  const material = new THREE.MeshBasicMaterial({
498
- color: new THREE.Color(color),
499
- transparent: this.globalAlpha * alpha < 1,
500
- opacity: this.globalAlpha * alpha,
543
+ color: parsed.color,
544
+ transparent: opacity < 1,
545
+ opacity,
501
546
  depthWrite: false
502
547
  });
503
548
  const mesh = new THREE.Mesh(geometry, material);
@@ -512,6 +557,18 @@ var ThreeRenderer = class {
512
557
  createLinearGradient(x0, y0, x1, y1, colorStops) {
513
558
  return new WebGLGradient(x0, y0, x1, y1, colorStops);
514
559
  }
560
+ disposed = false;
561
+ dispose() {
562
+ if (this.disposed) return;
563
+ this.disposed = true;
564
+ this.disposeActiveObjects();
565
+ this.currentPath = null;
566
+ this.stack.length = 0;
567
+ this.alphaStack.length = 0;
568
+ this.scissorStack.length = 0;
569
+ this.renderer.setScissorTest(false);
570
+ this.renderer.dispose();
571
+ }
515
572
  };
516
573
 
517
574
  // src/ThreeAdapter.ts
@@ -528,8 +585,20 @@ var ThreeAdapter = class {
528
585
  mesh;
529
586
  /** Track hover states independently per pointerId for WebXR / Multi-Touch. */
530
587
  activePointers = /* @__PURE__ */ new Map();
588
+ /**
589
+ * Holds the original `vectoScene.render` reference so {@link dispose} can
590
+ * restore it. Without restoring, a later render call would write
591
+ * `needsUpdate` on a disposed (deleted) `CanvasTexture`, which Three.js
592
+ * flags with `"THREE.Texture: trying to use deleted texture"`.
593
+ */
594
+ _originalRender = null;
595
+ /** Tracks whether this adapter owns the canvas it is rendering to. */
596
+ _ownsCanvas;
597
+ _disposed = false;
531
598
  constructor(options) {
532
- this.canvas = options.canvas || (typeof document !== "undefined" ? document.createElement("canvas") : { width: options.width, height: options.height });
599
+ const optCanvas = options.canvas;
600
+ this._ownsCanvas = !optCanvas;
601
+ this.canvas = optCanvas || (typeof document !== "undefined" ? document.createElement("canvas") : { width: options.width, height: options.height });
533
602
  this.canvas.width = options.width;
534
603
  this.canvas.height = options.height;
535
604
  const sceneOptions = {
@@ -541,7 +610,8 @@ var ThreeAdapter = class {
541
610
  this.texture = new THREE2.CanvasTexture(this.canvas);
542
611
  this.texture.minFilter = THREE2.LinearFilter;
543
612
  this.texture.magFilter = THREE2.LinearFilter;
544
- const originalRender = this.vectoScene.render;
613
+ this._originalRender = this.vectoScene.render;
614
+ const originalRender = this._originalRender;
545
615
  this.vectoScene.render = (renderer, dt, time) => {
546
616
  originalRender.call(this.vectoScene, renderer, dt, time);
547
617
  this.texture.needsUpdate = true;
@@ -590,8 +660,8 @@ var ThreeAdapter = class {
590
660
  * Dispatches pointer events mapped from UV coordinates [0, 1] to VectoJS entities.
591
661
  */
592
662
  dispatchAtUv(type, uv, pointerId, originalEvent) {
593
- const px = uv.x * this.canvas.width;
594
- const py = (1 - uv.y) * this.canvas.height;
663
+ const px = uv.x * this.vectoScene.width;
664
+ const py = (1 - uv.y) * this.vectoScene.height;
595
665
  this.vectoScene.markDirty();
596
666
  const hitEntity = this.vectoScene.findEntityAt(px, py);
597
667
  const state = this.activePointers.get(pointerId);
@@ -637,34 +707,51 @@ var ThreeAdapter = class {
637
707
  a11yEl.focus();
638
708
  }
639
709
  } else {
640
- const e = originalEvent instanceof MouseEvent ? originalEvent : void 0;
641
- const vectoEvent = new import_core2.VectoJSEvent(type, entity, e, type !== "pointerleave");
710
+ const vectoEvent = new import_core2.VectoJSEvent(type, entity, originalEvent, type !== "pointerleave", {
711
+ x,
712
+ y
713
+ });
642
714
  entity.dispatchEvent(vectoEvent);
643
715
  }
644
716
  }
645
717
  createDOMEvent(type, x, y, pointerId, originalEvent) {
718
+ let event;
646
719
  if (type === "wheel") {
647
720
  const wheelE = originalEvent instanceof WheelEvent ? originalEvent : void 0;
648
- return new WheelEvent("wheel", {
721
+ event = new WheelEvent("wheel", {
649
722
  clientX: x,
650
723
  clientY: y,
651
724
  deltaX: wheelE ? wheelE.deltaX : 0,
652
725
  deltaY: wheelE ? wheelE.deltaY : 0,
653
726
  deltaZ: wheelE ? wheelE.deltaZ : 0,
654
727
  deltaMode: wheelE ? wheelE.deltaMode : 0,
728
+ shiftKey: wheelE ? wheelE.shiftKey : false,
729
+ ctrlKey: wheelE ? wheelE.ctrlKey : false,
730
+ altKey: wheelE ? wheelE.altKey : false,
731
+ metaKey: wheelE ? wheelE.metaKey : false,
732
+ bubbles: true,
733
+ cancelable: true
734
+ });
735
+ } else {
736
+ event = new PointerEvent(type, {
737
+ clientX: x,
738
+ clientY: y,
739
+ button: originalEvent instanceof MouseEvent ? originalEvent.button : 0,
740
+ buttons: originalEvent instanceof MouseEvent ? originalEvent.buttons : 0,
741
+ pointerId,
742
+ shiftKey: originalEvent instanceof MouseEvent ? originalEvent.shiftKey : false,
743
+ ctrlKey: originalEvent instanceof MouseEvent ? originalEvent.ctrlKey : false,
744
+ altKey: originalEvent instanceof MouseEvent ? originalEvent.altKey : false,
745
+ metaKey: originalEvent instanceof MouseEvent ? originalEvent.metaKey : false,
655
746
  bubbles: true,
656
747
  cancelable: true
657
748
  });
658
749
  }
659
- return new PointerEvent(type, {
660
- clientX: x,
661
- clientY: y,
662
- button: originalEvent instanceof MouseEvent ? originalEvent.button : 0,
663
- buttons: originalEvent instanceof MouseEvent ? originalEvent.buttons : 0,
664
- pointerId,
665
- bubbles: true,
666
- cancelable: true
750
+ Object.defineProperties(event, {
751
+ vectoSceneX: { value: x },
752
+ vectoSceneY: { value: y }
667
753
  });
754
+ return event;
668
755
  }
669
756
  findEntityById(root, id) {
670
757
  if (root.id === id) return root;
@@ -687,6 +774,12 @@ var ThreeAdapter = class {
687
774
  * Disposes of Three.js textures, geometries, and VectoJS scenes to prevent memory leaks.
688
775
  */
689
776
  dispose() {
777
+ if (this._disposed) return;
778
+ this._disposed = true;
779
+ if (this._originalRender) {
780
+ this.vectoScene.render = this._originalRender;
781
+ this._originalRender = null;
782
+ }
690
783
  this.texture.dispose();
691
784
  this.mesh.geometry.dispose();
692
785
  if (Array.isArray(this.mesh.material)) {
@@ -699,8 +792,10 @@ var ThreeAdapter = class {
699
792
  }
700
793
  this.vectoScene.destroy();
701
794
  this.activePointers.clear();
702
- this.canvas.width = 0;
703
- this.canvas.height = 0;
795
+ if (this._ownsCanvas) {
796
+ this.canvas.width = 0;
797
+ this.canvas.height = 0;
798
+ }
704
799
  }
705
800
  };
706
801
  // Annotate the CommonJS export names for ESM import in node:
package/dist/index.mjs CHANGED
@@ -1,6 +1,10 @@
1
1
  // src/ThreeRenderer.ts
2
2
  import { parseColorToRGBA } from "@vectojs/core";
3
3
  import * as THREE from "three";
4
+ function parseThreeColor(value) {
5
+ const [r, g, b, alpha] = parseColorToRGBA(value);
6
+ return { color: new THREE.Color(r, g, b), alpha };
7
+ }
4
8
  var WebGLGradient = class {
5
9
  constructor(x0, y0, x1, y1, colorStops) {
6
10
  this.x0 = x0;
@@ -73,14 +77,16 @@ var ThreeRenderer = class {
73
77
  activeObjects = [];
74
78
  scissorStack = [];
75
79
  constructor(canvas) {
76
- this.width = window.innerWidth;
77
- this.height = window.innerHeight;
80
+ const cw = canvas.width > 0 ? canvas.width : typeof window !== "undefined" ? window.innerWidth : 1024;
81
+ const ch = canvas.height > 0 ? canvas.height : typeof window !== "undefined" ? window.innerHeight : 1024;
82
+ this.width = cw;
83
+ this.height = ch;
78
84
  this.scene = new THREE.Scene();
79
85
  this.camera = new THREE.OrthographicCamera(0, this.width, 0, this.height, 0.1, 1e3);
80
86
  this.camera.position.z = 1;
81
87
  this.renderer = new THREE.WebGLRenderer({ canvas, alpha: true, antialias: true });
82
88
  this.renderer.setSize(this.width, this.height);
83
- this.renderer.setPixelRatio(window.devicePixelRatio || 1);
89
+ this.renderer.setPixelRatio(typeof window !== "undefined" ? window.devicePixelRatio || 1 : 1);
84
90
  this.matrix = new THREE.Matrix4().identity();
85
91
  }
86
92
  resize(width, height) {
@@ -92,26 +98,42 @@ var ThreeRenderer = class {
92
98
  this.camera.updateProjectionMatrix();
93
99
  }
94
100
  clear() {
95
- for (const obj of this.activeObjects) {
96
- this.scene.remove(obj);
97
- if (obj instanceof THREE.Mesh || obj instanceof THREE.Line) {
98
- obj.geometry.dispose();
99
- if (Array.isArray(obj.material)) {
100
- for (const mat of obj.material) {
101
- mat.dispose();
102
- if (mat.map) mat.map.dispose();
103
- }
104
- } else {
105
- obj.material.dispose();
106
- if (obj.material.map) {
107
- obj.material.map.dispose();
108
- }
101
+ this.disposeActiveObjects();
102
+ this.currentPath = null;
103
+ this.matrix.identity();
104
+ this.stack.length = 0;
105
+ this.globalAlpha = 1;
106
+ this.alphaStack.length = 0;
107
+ this.scissorStack.length = 0;
108
+ this.renderer.clear();
109
+ this.renderer.setScissorTest(false);
110
+ }
111
+ disposeActiveObjects() {
112
+ const disposedGeometries = /* @__PURE__ */ new Set();
113
+ const disposedMaterials = /* @__PURE__ */ new Set();
114
+ const disposedTextures = /* @__PURE__ */ new Set();
115
+ for (const object of this.activeObjects) {
116
+ this.scene.remove(object);
117
+ if (!(object instanceof THREE.Mesh || object instanceof THREE.Line)) continue;
118
+ const geometry = object.geometry;
119
+ if (!disposedGeometries.has(geometry)) {
120
+ disposedGeometries.add(geometry);
121
+ geometry.dispose();
122
+ }
123
+ const materials = Array.isArray(object.material) ? object.material : [object.material];
124
+ for (const material of materials) {
125
+ const map = material.map;
126
+ if (map && !disposedTextures.has(map)) {
127
+ disposedTextures.add(map);
128
+ map.dispose();
129
+ }
130
+ if (!disposedMaterials.has(material)) {
131
+ disposedMaterials.add(material);
132
+ material.dispose();
109
133
  }
110
134
  }
111
135
  }
112
- this.activeObjects = [];
113
- this.renderer.clear();
114
- this.renderer.setScissorTest(false);
136
+ this.activeObjects.length = 0;
115
137
  }
116
138
  save() {
117
139
  this.stack.push(this.matrix.clone());
@@ -148,16 +170,33 @@ var ThreeRenderer = class {
148
170
  this.globalAlpha = alpha;
149
171
  }
150
172
  clip(x, y, width, height) {
151
- const pos = new THREE.Vector3(x, y, 0).applyMatrix4(this.matrix);
152
- const size = new THREE.Vector3(width, height, 0).applyMatrix4(this.matrix).sub(new THREE.Vector3(0, 0, 0).applyMatrix4(this.matrix));
173
+ const corners = [
174
+ new THREE.Vector3(x, y, 0),
175
+ new THREE.Vector3(x + width, y, 0),
176
+ new THREE.Vector3(x, y + height, 0),
177
+ new THREE.Vector3(x + width, y + height, 0)
178
+ ].map((point) => point.applyMatrix4(this.matrix));
179
+ const minX = Math.min(...corners.map((point) => point.x));
180
+ const minY = Math.min(...corners.map((point) => point.y));
181
+ const maxX = Math.max(...corners.map((point) => point.x));
182
+ const maxY = Math.max(...corners.map((point) => point.y));
153
183
  const dpr = window.devicePixelRatio || 1;
154
184
  const canvasHeight = this.renderer.domElement.height / dpr;
155
- this.renderer.setScissor(
156
- pos.x * dpr,
157
- (canvasHeight - (pos.y + size.y)) * dpr,
158
- size.x * dpr,
159
- size.y * dpr
160
- );
185
+ let scissorX = minX * dpr;
186
+ let scissorY = (canvasHeight - maxY) * dpr;
187
+ let scissorWidth = (maxX - minX) * dpr;
188
+ let scissorHeight = (maxY - minY) * dpr;
189
+ if (this.renderer.getScissorTest()) {
190
+ const current = new THREE.Vector4();
191
+ this.renderer.getScissor(current);
192
+ const right = Math.min(scissorX + scissorWidth, current.x + current.z);
193
+ const top = Math.min(scissorY + scissorHeight, current.y + current.w);
194
+ scissorX = Math.max(scissorX, current.x);
195
+ scissorY = Math.max(scissorY, current.y);
196
+ scissorWidth = Math.max(0, right - scissorX);
197
+ scissorHeight = Math.max(0, top - scissorY);
198
+ }
199
+ this.renderer.setScissor(scissorX, scissorY, scissorWidth, scissorHeight);
161
200
  this.renderer.setScissorTest(true);
162
201
  }
163
202
  beginPath() {
@@ -376,13 +415,15 @@ var ThreeRenderer = class {
376
415
  fillSolidShape(colorOrGradient) {
377
416
  if (!this.currentPath) return;
378
417
  const color = typeof colorOrGradient === "string" ? colorOrGradient : "#ffffff";
418
+ const parsed = parseThreeColor(color);
379
419
  const shapes = this.currentPath.toShapes();
380
420
  for (const shape of shapes) {
381
421
  const geometry = new THREE.ShapeGeometry(shape);
422
+ const opacity = this.globalAlpha * parsed.alpha;
382
423
  const material = new THREE.MeshBasicMaterial({
383
- color: new THREE.Color(color),
384
- transparent: this.globalAlpha < 1,
385
- opacity: this.globalAlpha,
424
+ color: parsed.color,
425
+ transparent: opacity < 1,
426
+ opacity,
386
427
  depthWrite: false
387
428
  });
388
429
  const mesh = new THREE.Mesh(geometry, material);
@@ -405,10 +446,12 @@ var ThreeRenderer = class {
405
446
  const points = this.currentPath.getPoints();
406
447
  if (points.length === 0) return;
407
448
  const geometry = new THREE.BufferGeometry().setFromPoints(points);
449
+ const parsed = parseThreeColor(color);
450
+ const opacity = this.globalAlpha * parsed.alpha;
408
451
  const material = new THREE.LineBasicMaterial({
409
- color: new THREE.Color(color),
410
- transparent: this.globalAlpha < 1,
411
- opacity: this.globalAlpha,
452
+ color: parsed.color,
453
+ transparent: opacity < 1,
454
+ opacity,
412
455
  linewidth: lineWidth
413
456
  });
414
457
  const line = new THREE.Line(geometry, material);
@@ -456,10 +499,12 @@ var ThreeRenderer = class {
456
499
  }
457
500
  fillCircle(cx, cy, radius, color, alpha = 1) {
458
501
  const geometry = new THREE.CircleGeometry(radius, 32);
502
+ const parsed = parseThreeColor(color);
503
+ const opacity = this.globalAlpha * alpha * parsed.alpha;
459
504
  const material = new THREE.MeshBasicMaterial({
460
- color: new THREE.Color(color),
461
- transparent: this.globalAlpha * alpha < 1,
462
- opacity: this.globalAlpha * alpha,
505
+ color: parsed.color,
506
+ transparent: opacity < 1,
507
+ opacity,
463
508
  depthWrite: false
464
509
  });
465
510
  const mesh = new THREE.Mesh(geometry, material);
@@ -474,6 +519,18 @@ var ThreeRenderer = class {
474
519
  createLinearGradient(x0, y0, x1, y1, colorStops) {
475
520
  return new WebGLGradient(x0, y0, x1, y1, colorStops);
476
521
  }
522
+ disposed = false;
523
+ dispose() {
524
+ if (this.disposed) return;
525
+ this.disposed = true;
526
+ this.disposeActiveObjects();
527
+ this.currentPath = null;
528
+ this.stack.length = 0;
529
+ this.alphaStack.length = 0;
530
+ this.scissorStack.length = 0;
531
+ this.renderer.setScissorTest(false);
532
+ this.renderer.dispose();
533
+ }
477
534
  };
478
535
 
479
536
  // src/ThreeAdapter.ts
@@ -490,8 +547,20 @@ var ThreeAdapter = class {
490
547
  mesh;
491
548
  /** Track hover states independently per pointerId for WebXR / Multi-Touch. */
492
549
  activePointers = /* @__PURE__ */ new Map();
550
+ /**
551
+ * Holds the original `vectoScene.render` reference so {@link dispose} can
552
+ * restore it. Without restoring, a later render call would write
553
+ * `needsUpdate` on a disposed (deleted) `CanvasTexture`, which Three.js
554
+ * flags with `"THREE.Texture: trying to use deleted texture"`.
555
+ */
556
+ _originalRender = null;
557
+ /** Tracks whether this adapter owns the canvas it is rendering to. */
558
+ _ownsCanvas;
559
+ _disposed = false;
493
560
  constructor(options) {
494
- this.canvas = options.canvas || (typeof document !== "undefined" ? document.createElement("canvas") : { width: options.width, height: options.height });
561
+ const optCanvas = options.canvas;
562
+ this._ownsCanvas = !optCanvas;
563
+ this.canvas = optCanvas || (typeof document !== "undefined" ? document.createElement("canvas") : { width: options.width, height: options.height });
495
564
  this.canvas.width = options.width;
496
565
  this.canvas.height = options.height;
497
566
  const sceneOptions = {
@@ -503,7 +572,8 @@ var ThreeAdapter = class {
503
572
  this.texture = new THREE2.CanvasTexture(this.canvas);
504
573
  this.texture.minFilter = THREE2.LinearFilter;
505
574
  this.texture.magFilter = THREE2.LinearFilter;
506
- const originalRender = this.vectoScene.render;
575
+ this._originalRender = this.vectoScene.render;
576
+ const originalRender = this._originalRender;
507
577
  this.vectoScene.render = (renderer, dt, time) => {
508
578
  originalRender.call(this.vectoScene, renderer, dt, time);
509
579
  this.texture.needsUpdate = true;
@@ -552,8 +622,8 @@ var ThreeAdapter = class {
552
622
  * Dispatches pointer events mapped from UV coordinates [0, 1] to VectoJS entities.
553
623
  */
554
624
  dispatchAtUv(type, uv, pointerId, originalEvent) {
555
- const px = uv.x * this.canvas.width;
556
- const py = (1 - uv.y) * this.canvas.height;
625
+ const px = uv.x * this.vectoScene.width;
626
+ const py = (1 - uv.y) * this.vectoScene.height;
557
627
  this.vectoScene.markDirty();
558
628
  const hitEntity = this.vectoScene.findEntityAt(px, py);
559
629
  const state = this.activePointers.get(pointerId);
@@ -599,34 +669,51 @@ var ThreeAdapter = class {
599
669
  a11yEl.focus();
600
670
  }
601
671
  } else {
602
- const e = originalEvent instanceof MouseEvent ? originalEvent : void 0;
603
- const vectoEvent = new VectoJSEvent(type, entity, e, type !== "pointerleave");
672
+ const vectoEvent = new VectoJSEvent(type, entity, originalEvent, type !== "pointerleave", {
673
+ x,
674
+ y
675
+ });
604
676
  entity.dispatchEvent(vectoEvent);
605
677
  }
606
678
  }
607
679
  createDOMEvent(type, x, y, pointerId, originalEvent) {
680
+ let event;
608
681
  if (type === "wheel") {
609
682
  const wheelE = originalEvent instanceof WheelEvent ? originalEvent : void 0;
610
- return new WheelEvent("wheel", {
683
+ event = new WheelEvent("wheel", {
611
684
  clientX: x,
612
685
  clientY: y,
613
686
  deltaX: wheelE ? wheelE.deltaX : 0,
614
687
  deltaY: wheelE ? wheelE.deltaY : 0,
615
688
  deltaZ: wheelE ? wheelE.deltaZ : 0,
616
689
  deltaMode: wheelE ? wheelE.deltaMode : 0,
690
+ shiftKey: wheelE ? wheelE.shiftKey : false,
691
+ ctrlKey: wheelE ? wheelE.ctrlKey : false,
692
+ altKey: wheelE ? wheelE.altKey : false,
693
+ metaKey: wheelE ? wheelE.metaKey : false,
694
+ bubbles: true,
695
+ cancelable: true
696
+ });
697
+ } else {
698
+ event = new PointerEvent(type, {
699
+ clientX: x,
700
+ clientY: y,
701
+ button: originalEvent instanceof MouseEvent ? originalEvent.button : 0,
702
+ buttons: originalEvent instanceof MouseEvent ? originalEvent.buttons : 0,
703
+ pointerId,
704
+ shiftKey: originalEvent instanceof MouseEvent ? originalEvent.shiftKey : false,
705
+ ctrlKey: originalEvent instanceof MouseEvent ? originalEvent.ctrlKey : false,
706
+ altKey: originalEvent instanceof MouseEvent ? originalEvent.altKey : false,
707
+ metaKey: originalEvent instanceof MouseEvent ? originalEvent.metaKey : false,
617
708
  bubbles: true,
618
709
  cancelable: true
619
710
  });
620
711
  }
621
- return new PointerEvent(type, {
622
- clientX: x,
623
- clientY: y,
624
- button: originalEvent instanceof MouseEvent ? originalEvent.button : 0,
625
- buttons: originalEvent instanceof MouseEvent ? originalEvent.buttons : 0,
626
- pointerId,
627
- bubbles: true,
628
- cancelable: true
712
+ Object.defineProperties(event, {
713
+ vectoSceneX: { value: x },
714
+ vectoSceneY: { value: y }
629
715
  });
716
+ return event;
630
717
  }
631
718
  findEntityById(root, id) {
632
719
  if (root.id === id) return root;
@@ -649,6 +736,12 @@ var ThreeAdapter = class {
649
736
  * Disposes of Three.js textures, geometries, and VectoJS scenes to prevent memory leaks.
650
737
  */
651
738
  dispose() {
739
+ if (this._disposed) return;
740
+ this._disposed = true;
741
+ if (this._originalRender) {
742
+ this.vectoScene.render = this._originalRender;
743
+ this._originalRender = null;
744
+ }
652
745
  this.texture.dispose();
653
746
  this.mesh.geometry.dispose();
654
747
  if (Array.isArray(this.mesh.material)) {
@@ -661,8 +754,10 @@ var ThreeAdapter = class {
661
754
  }
662
755
  this.vectoScene.destroy();
663
756
  this.activePointers.clear();
664
- this.canvas.width = 0;
665
- this.canvas.height = 0;
757
+ if (this._ownsCanvas) {
758
+ this.canvas.width = 0;
759
+ this.canvas.height = 0;
760
+ }
666
761
  }
667
762
  };
668
763
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectojs/three",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -19,7 +19,7 @@
19
19
  "dist"
20
20
  ],
21
21
  "scripts": {
22
- "build": "tsup src/index.ts --format cjs,esm --dts --clean",
22
+ "build": "(cd ../core && bun run build) && tsup src/index.ts --format cjs,esm --clean && tsc -p tsconfig.build.json",
23
23
  "test": "vitest run"
24
24
  },
25
25
  "peerDependencies": {
package/dist/index.d.mts DELETED
@@ -1,123 +0,0 @@
1
- import { IRenderer, Scene, SceneOptions } from '@vectojs/core';
2
- import * as THREE from 'three';
3
-
4
- declare class WebGLGradient {
5
- x0: number;
6
- y0: number;
7
- x1: number;
8
- y1: number;
9
- colorStops: {
10
- stop: number;
11
- color: string;
12
- }[];
13
- type: string;
14
- constructor(x0: number, y0: number, x1: number, y1: number, colorStops: {
15
- stop: number;
16
- color: string;
17
- }[]);
18
- }
19
- /**
20
- * WebGL/Three.js implementation of {@link IRenderer}.
21
- *
22
- * Bridges VectoJS's 2D canvas API to Three.js for 3D hardware-accelerated rendering.
23
- */
24
- declare class ThreeRenderer implements IRenderer {
25
- scene: THREE.Scene;
26
- camera: THREE.OrthographicCamera;
27
- renderer: THREE.WebGLRenderer;
28
- private width;
29
- private height;
30
- private matrix;
31
- private stack;
32
- private globalAlpha;
33
- private alphaStack;
34
- private currentPath;
35
- private activeObjects;
36
- private scissorStack;
37
- constructor(canvas: HTMLCanvasElement);
38
- resize(width: number, height: number): void;
39
- clear(): void;
40
- save(): void;
41
- restore(): void;
42
- translate(x: number, y: number): void;
43
- scale(x: number, y: number): void;
44
- rotate(angle: number): void;
45
- setGlobalAlpha(alpha: number): void;
46
- clip(x: number, y: number, width: number, height: number): void;
47
- beginPath(): void;
48
- moveTo(x: number, y: number): void;
49
- lineTo(x: number, y: number): void;
50
- bezierCurveTo(cp1x: number, cp1y: number, cp2x: number, cp2y: number, x: number, y: number): void;
51
- closePath(): void;
52
- arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise?: boolean): void;
53
- roundRect(x: number, y: number, width: number, height: number, radii: number | number[]): void;
54
- drawImage(source: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
55
- fill(colorOrGradient: string | any): void;
56
- private fillSolidShape;
57
- stroke(colorOrGradient: string | any, lineWidth?: number): void;
58
- fillText(text: string, x: number, y: number, font: string, color: string | any): void;
59
- fillCircle(cx: number, cy: number, radius: number, color: string, alpha?: number): void;
60
- flush(): void;
61
- createLinearGradient(x0: number, y0: number, x1: number, y1: number, colorStops: {
62
- stop: number;
63
- color: string;
64
- }[]): any;
65
- }
66
-
67
- interface ThreeAdapterOptions {
68
- /** Physical layout width of the 2D UI canvas. */
69
- width: number;
70
- /** Physical layout height of the 2D UI canvas. */
71
- height: number;
72
- /** Optional pre-existing canvas element. If omitted, a new canvas is created. */
73
- canvas?: HTMLCanvasElement;
74
- /** Options passed to the VectoScene constructor. */
75
- sceneOptions?: SceneOptions;
76
- }
77
- /**
78
- * Adapts a VectoJS Scene into a Three.js CanvasTexture, allowing VectoJS
79
- * components to be rendered in 3D space (e.g. on a plane, screen, or VR dashboard).
80
- */
81
- declare class ThreeAdapter {
82
- /** The Three.js CanvasTexture wrapping the offscreen Vecto canvas. */
83
- texture: THREE.CanvasTexture;
84
- /** The active VectoJS Scene instance. */
85
- vectoScene: Scene;
86
- /** The offscreen HTMLCanvasElement on which Vecto draws. */
87
- canvas: HTMLCanvasElement;
88
- /** A pre-built THREE.Mesh with PlaneGeometry and this texture for immediate use. */
89
- mesh: THREE.Mesh;
90
- /** Track hover states independently per pointerId for WebXR / Multi-Touch. */
91
- private activePointers;
92
- constructor(options: ThreeAdapterOptions);
93
- /**
94
- * Processes 3D Raycasting intersections and forwards pointer/scroll events.
95
- * Call this from window/document event listeners passing the raycaster.
96
- *
97
- * @param raycaster Three.js Raycaster instance.
98
- * @param type Pointer event type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click'.
99
- * @param originalEvent Optional original DOM Event to forward scroll deltas or button states.
100
- * @returns true if the ray intersected the VectoJS mesh; false otherwise.
101
- */
102
- updateIntersection(raycaster: THREE.Raycaster, type: 'pointerdown' | 'pointerup' | 'pointermove' | 'wheel' | 'click', originalEvent?: Event): boolean;
103
- /**
104
- * Dispatches pointer events mapped from UV coordinates [0, 1] to VectoJS entities.
105
- */
106
- private dispatchAtUv;
107
- /**
108
- * Routes events to the associated A11y DOM element, or Vecto's own event dispatch system.
109
- */
110
- private dispatchEventToTarget;
111
- private createDOMEvent;
112
- private findEntityById;
113
- /**
114
- * Resizes the offscreen canvas and VectoScene dimensions.
115
- */
116
- resize(width: number, height: number): void;
117
- /**
118
- * Disposes of Three.js textures, geometries, and VectoJS scenes to prevent memory leaks.
119
- */
120
- dispose(): void;
121
- }
122
-
123
- export { ThreeAdapter, type ThreeAdapterOptions, ThreeRenderer, WebGLGradient };