@tonybfox/threejs-tools 1.0.3 → 1.0.4

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.
Files changed (61) hide show
  1. package/dist/asset-loader/index.cjs +0 -1
  2. package/dist/asset-loader/index.mjs +1 -2
  3. package/dist/camera/index.cjs +0 -1
  4. package/dist/camera/index.mjs +1 -2
  5. package/dist/{chunk-WZ6IGBSE.mjs → chunk-27WUVRGX.mjs} +0 -1
  6. package/dist/{chunk-EQDOX34V.mjs → chunk-2CDI7ORN.mjs} +0 -1
  7. package/dist/{chunk-EIROAPF7.mjs → chunk-FBTT6MU6.mjs} +0 -1
  8. package/dist/{chunk-VETFQ3IQ.mjs → chunk-IAZH4OHC.mjs} +0 -1
  9. package/dist/{chunk-5DP6WDB3.mjs → chunk-OZKJ3GAD.mjs} +0 -1
  10. package/dist/{chunk-IIAZ2WJJ.mjs → chunk-W4DAAAW6.mjs} +0 -1
  11. package/dist/{chunk-IEE7DQOU.mjs → chunk-XA7OKYSM.mjs} +0 -1
  12. package/dist/{chunk-BJKSICFA.mjs → chunk-YMMLYGHV.mjs} +0 -1
  13. package/dist/{chunk-P35QJCOG.mjs → chunk-ZNGFST7K.mjs} +15 -6
  14. package/dist/compass/index.cjs +15 -6
  15. package/dist/compass/index.d.mts +4 -2
  16. package/dist/compass/index.d.ts +4 -2
  17. package/dist/compass/index.mjs +1 -2
  18. package/dist/grid/index.cjs +0 -1
  19. package/dist/grid/index.mjs +1 -2
  20. package/dist/index.cjs +15 -6
  21. package/dist/index.mjs +9 -10
  22. package/dist/measurements/index.cjs +0 -1
  23. package/dist/measurements/index.mjs +1 -2
  24. package/dist/sunlight/index.cjs +0 -1
  25. package/dist/sunlight/index.mjs +1 -2
  26. package/dist/terrain/index.cjs +0 -1
  27. package/dist/terrain/index.mjs +1 -2
  28. package/dist/transform-controls/index.cjs +0 -1
  29. package/dist/transform-controls/index.mjs +1 -2
  30. package/dist/view-helper/index.cjs +0 -1
  31. package/dist/view-helper/index.mjs +1 -2
  32. package/package.json +1 -1
  33. package/dist/asset-loader/index.cjs.map +0 -1
  34. package/dist/asset-loader/index.mjs.map +0 -1
  35. package/dist/camera/index.cjs.map +0 -1
  36. package/dist/camera/index.mjs.map +0 -1
  37. package/dist/chunk-5DP6WDB3.mjs.map +0 -1
  38. package/dist/chunk-BJKSICFA.mjs.map +0 -1
  39. package/dist/chunk-EIROAPF7.mjs.map +0 -1
  40. package/dist/chunk-EQDOX34V.mjs.map +0 -1
  41. package/dist/chunk-IEE7DQOU.mjs.map +0 -1
  42. package/dist/chunk-IIAZ2WJJ.mjs.map +0 -1
  43. package/dist/chunk-P35QJCOG.mjs.map +0 -1
  44. package/dist/chunk-VETFQ3IQ.mjs.map +0 -1
  45. package/dist/chunk-WZ6IGBSE.mjs.map +0 -1
  46. package/dist/compass/index.cjs.map +0 -1
  47. package/dist/compass/index.mjs.map +0 -1
  48. package/dist/grid/index.cjs.map +0 -1
  49. package/dist/grid/index.mjs.map +0 -1
  50. package/dist/index.cjs.map +0 -1
  51. package/dist/index.mjs.map +0 -1
  52. package/dist/measurements/index.cjs.map +0 -1
  53. package/dist/measurements/index.mjs.map +0 -1
  54. package/dist/sunlight/index.cjs.map +0 -1
  55. package/dist/sunlight/index.mjs.map +0 -1
  56. package/dist/terrain/index.cjs.map +0 -1
  57. package/dist/terrain/index.mjs.map +0 -1
  58. package/dist/transform-controls/index.cjs.map +0 -1
  59. package/dist/transform-controls/index.mjs.map +0 -1
  60. package/dist/view-helper/index.cjs.map +0 -1
  61. package/dist/view-helper/index.mjs.map +0 -1
@@ -394,4 +394,3 @@ var AssetLoader = class extends THREE.EventDispatcher {
394
394
  0 && (module.exports = {
395
395
  AssetLoader
396
396
  });
397
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  AssetLoader
3
- } from "../chunk-WZ6IGBSE.mjs";
3
+ } from "../chunk-27WUVRGX.mjs";
4
4
  export {
5
5
  AssetLoader
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
@@ -391,4 +391,3 @@ function resolveAspect(renderer, domElement) {
391
391
  0 && (module.exports = {
392
392
  DualCameraControls
393
393
  });
394
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  DualCameraControls
3
- } from "../chunk-IEE7DQOU.mjs";
3
+ } from "../chunk-XA7OKYSM.mjs";
4
4
  export {
5
5
  DualCameraControls
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
@@ -358,4 +358,3 @@ var AssetLoader = class extends THREE.EventDispatcher {
358
358
  export {
359
359
  AssetLoader
360
360
  };
361
- //# sourceMappingURL=chunk-WZ6IGBSE.mjs.map
@@ -161,4 +161,3 @@ var InfiniteGrid = class extends THREE.Object3D {
161
161
  export {
162
162
  InfiniteGrid
163
163
  };
164
- //# sourceMappingURL=chunk-EQDOX34V.mjs.map
@@ -384,4 +384,3 @@ var TerrainTool = class extends THREE.EventDispatcher {
384
384
  export {
385
385
  TerrainTool
386
386
  };
387
- //# sourceMappingURL=chunk-EIROAPF7.mjs.map
@@ -397,4 +397,3 @@ var ViewHelper = class extends THREE.EventDispatcher {
397
397
  export {
398
398
  ViewHelper
399
399
  };
400
- //# sourceMappingURL=chunk-VETFQ3IQ.mjs.map
@@ -1158,4 +1158,3 @@ export {
1158
1158
  SnapMode,
1159
1159
  MeasurementTool
1160
1160
  };
1161
- //# sourceMappingURL=chunk-5DP6WDB3.mjs.map
@@ -402,4 +402,3 @@ var SunLightTool = class extends THREE.EventDispatcher {
402
402
  export {
403
403
  SunLightTool
404
404
  };
405
- //# sourceMappingURL=chunk-IIAZ2WJJ.mjs.map
@@ -355,4 +355,3 @@ function resolveAspect(renderer, domElement) {
355
355
  export {
356
356
  DualCameraControls
357
357
  };
358
- //# sourceMappingURL=chunk-IEE7DQOU.mjs.map
@@ -1576,4 +1576,3 @@ export {
1576
1576
  TransformControlsGizmo,
1577
1577
  TransformControlsPlane
1578
1578
  };
1579
- //# sourceMappingURL=chunk-BJKSICFA.mjs.map
@@ -11,6 +11,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
11
11
  size: options.size || 100,
12
12
  position: options.position || "bottom-right",
13
13
  offset: options.offset || { x: 20, y: 20 },
14
+ northDirection: options.northDirection?.clone().normalize() || new THREE.Vector3(0, 0, -1),
14
15
  colors: {
15
16
  background: options.colors?.background || "#1a1a1a",
16
17
  border: options.colors?.border || "#333333",
@@ -23,6 +24,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
23
24
  this.container = this.options.container;
24
25
  this.createCompassElement();
25
26
  this.setupStyles();
27
+ this.start();
26
28
  }
27
29
  createCompassElement() {
28
30
  this.compassElement = document.createElement("div");
@@ -229,8 +231,13 @@ var CompassOverlay = class extends THREE.EventDispatcher {
229
231
  forward.transformDirection(cameraMatrix);
230
232
  forward.y = 0;
231
233
  forward.normalize();
234
+ const north = this.options.northDirection.clone();
235
+ north.y = 0;
236
+ north.normalize();
232
237
  const targetAngle = Math.atan2(-forward.x, -forward.z) * (180 / Math.PI);
233
- let angleDiff = targetAngle - this.currentRotation;
238
+ const northAngle = Math.atan2(-north.x, -north.z) * (180 / Math.PI);
239
+ const adjustedAngle = targetAngle - northAngle;
240
+ let angleDiff = adjustedAngle - this.currentRotation;
234
241
  while (angleDiff > 180) angleDiff -= 360;
235
242
  while (angleDiff < -180) angleDiff += 360;
236
243
  this.currentRotation += angleDiff;
@@ -242,6 +249,9 @@ var CompassOverlay = class extends THREE.EventDispatcher {
242
249
  setCamera(camera) {
243
250
  this.camera = camera;
244
251
  }
252
+ getNorthDirection() {
253
+ return this.options.northDirection.clone();
254
+ }
245
255
  setSize(size) {
246
256
  this.options.size = size;
247
257
  this.compassElement.style.width = `${size}px`;
@@ -275,17 +285,17 @@ var CompassOverlay = class extends THREE.EventDispatcher {
275
285
  this.updateStyles();
276
286
  }
277
287
  /**
278
- * Helper method to reset camera to look north (world Z- direction)
288
+ * Helper method to reset camera to look north
279
289
  * This is a convenience method that can be called when handling the 'resetToNorth' event
280
290
  */
281
- static resetCameraToNorth(camera, smooth = true) {
291
+ static resetCameraToNorth(camera, smooth = true, northDirection = new THREE.Vector3(0, 0, -1)) {
282
292
  if (smooth) {
283
293
  const startQuaternion = camera.quaternion.clone();
284
294
  const targetQuaternion = new THREE.Quaternion();
285
295
  const targetMatrix = new THREE.Matrix4();
286
296
  targetMatrix.lookAt(
287
297
  camera.position,
288
- camera.position.clone().add(new THREE.Vector3(0, 0, -1)),
298
+ camera.position.clone().add(northDirection),
289
299
  new THREE.Vector3(0, 1, 0)
290
300
  );
291
301
  targetQuaternion.setFromRotationMatrix(targetMatrix);
@@ -306,7 +316,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
306
316
  };
307
317
  animate();
308
318
  } else {
309
- camera.lookAt(camera.position.clone().add(new THREE.Vector3(0, 0, -1)));
319
+ camera.lookAt(camera.position.clone().add(northDirection));
310
320
  }
311
321
  }
312
322
  updateStyles() {
@@ -336,4 +346,3 @@ var CompassOverlay = class extends THREE.EventDispatcher {
336
346
  export {
337
347
  CompassOverlay
338
348
  };
339
- //# sourceMappingURL=chunk-P35QJCOG.mjs.map
@@ -47,6 +47,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
47
47
  size: options.size || 100,
48
48
  position: options.position || "bottom-right",
49
49
  offset: options.offset || { x: 20, y: 20 },
50
+ northDirection: options.northDirection?.clone().normalize() || new THREE.Vector3(0, 0, -1),
50
51
  colors: {
51
52
  background: options.colors?.background || "#1a1a1a",
52
53
  border: options.colors?.border || "#333333",
@@ -59,6 +60,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
59
60
  this.container = this.options.container;
60
61
  this.createCompassElement();
61
62
  this.setupStyles();
63
+ this.start();
62
64
  }
63
65
  createCompassElement() {
64
66
  this.compassElement = document.createElement("div");
@@ -265,8 +267,13 @@ var CompassOverlay = class extends THREE.EventDispatcher {
265
267
  forward.transformDirection(cameraMatrix);
266
268
  forward.y = 0;
267
269
  forward.normalize();
270
+ const north = this.options.northDirection.clone();
271
+ north.y = 0;
272
+ north.normalize();
268
273
  const targetAngle = Math.atan2(-forward.x, -forward.z) * (180 / Math.PI);
269
- let angleDiff = targetAngle - this.currentRotation;
274
+ const northAngle = Math.atan2(-north.x, -north.z) * (180 / Math.PI);
275
+ const adjustedAngle = targetAngle - northAngle;
276
+ let angleDiff = adjustedAngle - this.currentRotation;
270
277
  while (angleDiff > 180) angleDiff -= 360;
271
278
  while (angleDiff < -180) angleDiff += 360;
272
279
  this.currentRotation += angleDiff;
@@ -278,6 +285,9 @@ var CompassOverlay = class extends THREE.EventDispatcher {
278
285
  setCamera(camera) {
279
286
  this.camera = camera;
280
287
  }
288
+ getNorthDirection() {
289
+ return this.options.northDirection.clone();
290
+ }
281
291
  setSize(size) {
282
292
  this.options.size = size;
283
293
  this.compassElement.style.width = `${size}px`;
@@ -311,17 +321,17 @@ var CompassOverlay = class extends THREE.EventDispatcher {
311
321
  this.updateStyles();
312
322
  }
313
323
  /**
314
- * Helper method to reset camera to look north (world Z- direction)
324
+ * Helper method to reset camera to look north
315
325
  * This is a convenience method that can be called when handling the 'resetToNorth' event
316
326
  */
317
- static resetCameraToNorth(camera, smooth = true) {
327
+ static resetCameraToNorth(camera, smooth = true, northDirection = new THREE.Vector3(0, 0, -1)) {
318
328
  if (smooth) {
319
329
  const startQuaternion = camera.quaternion.clone();
320
330
  const targetQuaternion = new THREE.Quaternion();
321
331
  const targetMatrix = new THREE.Matrix4();
322
332
  targetMatrix.lookAt(
323
333
  camera.position,
324
- camera.position.clone().add(new THREE.Vector3(0, 0, -1)),
334
+ camera.position.clone().add(northDirection),
325
335
  new THREE.Vector3(0, 1, 0)
326
336
  );
327
337
  targetQuaternion.setFromRotationMatrix(targetMatrix);
@@ -342,7 +352,7 @@ var CompassOverlay = class extends THREE.EventDispatcher {
342
352
  };
343
353
  animate();
344
354
  } else {
345
- camera.lookAt(camera.position.clone().add(new THREE.Vector3(0, 0, -1)));
355
+ camera.lookAt(camera.position.clone().add(northDirection));
346
356
  }
347
357
  }
348
358
  updateStyles() {
@@ -372,4 +382,3 @@ var CompassOverlay = class extends THREE.EventDispatcher {
372
382
  0 && (module.exports = {
373
383
  CompassOverlay
374
384
  });
375
- //# sourceMappingURL=index.cjs.map
@@ -8,6 +8,7 @@ interface CompassOverlayOptions {
8
8
  x: number;
9
9
  y: number;
10
10
  };
11
+ northDirection?: THREE.Vector3;
11
12
  colors?: {
12
13
  background: string;
13
14
  border: string;
@@ -40,6 +41,7 @@ declare class CompassOverlay extends THREE.EventDispatcher<CompassOverlayEventMa
40
41
  stop(): void;
41
42
  update(): void;
42
43
  setCamera(camera: THREE.Camera): void;
44
+ getNorthDirection(): THREE.Vector3;
43
45
  setSize(size: number): void;
44
46
  setPosition(position: CompassOverlayOptions['position'], offset?: {
45
47
  x: number;
@@ -47,10 +49,10 @@ declare class CompassOverlay extends THREE.EventDispatcher<CompassOverlayEventMa
47
49
  }): void;
48
50
  setColors(colors: Partial<CompassOverlayOptions['colors']>): void;
49
51
  /**
50
- * Helper method to reset camera to look north (world Z- direction)
52
+ * Helper method to reset camera to look north
51
53
  * This is a convenience method that can be called when handling the 'resetToNorth' event
52
54
  */
53
- static resetCameraToNorth(camera: THREE.Camera, smooth?: boolean): void;
55
+ static resetCameraToNorth(camera: THREE.Camera, smooth?: boolean, northDirection?: THREE.Vector3): void;
54
56
  private updateStyles;
55
57
  dispose(): void;
56
58
  }
@@ -8,6 +8,7 @@ interface CompassOverlayOptions {
8
8
  x: number;
9
9
  y: number;
10
10
  };
11
+ northDirection?: THREE.Vector3;
11
12
  colors?: {
12
13
  background: string;
13
14
  border: string;
@@ -40,6 +41,7 @@ declare class CompassOverlay extends THREE.EventDispatcher<CompassOverlayEventMa
40
41
  stop(): void;
41
42
  update(): void;
42
43
  setCamera(camera: THREE.Camera): void;
44
+ getNorthDirection(): THREE.Vector3;
43
45
  setSize(size: number): void;
44
46
  setPosition(position: CompassOverlayOptions['position'], offset?: {
45
47
  x: number;
@@ -47,10 +49,10 @@ declare class CompassOverlay extends THREE.EventDispatcher<CompassOverlayEventMa
47
49
  }): void;
48
50
  setColors(colors: Partial<CompassOverlayOptions['colors']>): void;
49
51
  /**
50
- * Helper method to reset camera to look north (world Z- direction)
52
+ * Helper method to reset camera to look north
51
53
  * This is a convenience method that can be called when handling the 'resetToNorth' event
52
54
  */
53
- static resetCameraToNorth(camera: THREE.Camera, smooth?: boolean): void;
55
+ static resetCameraToNorth(camera: THREE.Camera, smooth?: boolean, northDirection?: THREE.Vector3): void;
54
56
  private updateStyles;
55
57
  dispose(): void;
56
58
  }
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  CompassOverlay
3
- } from "../chunk-P35QJCOG.mjs";
3
+ } from "../chunk-ZNGFST7K.mjs";
4
4
  export {
5
5
  CompassOverlay
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
@@ -197,4 +197,3 @@ var InfiniteGrid = class extends THREE.Object3D {
197
197
  0 && (module.exports = {
198
198
  InfiniteGrid
199
199
  });
200
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  InfiniteGrid
3
- } from "../chunk-EQDOX34V.mjs";
3
+ } from "../chunk-2CDI7ORN.mjs";
4
4
  export {
5
5
  InfiniteGrid
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
package/dist/index.cjs CHANGED
@@ -770,6 +770,7 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
770
770
  size: options.size || 100,
771
771
  position: options.position || "bottom-right",
772
772
  offset: options.offset || { x: 20, y: 20 },
773
+ northDirection: options.northDirection?.clone().normalize() || new THREE3.Vector3(0, 0, -1),
773
774
  colors: {
774
775
  background: options.colors?.background || "#1a1a1a",
775
776
  border: options.colors?.border || "#333333",
@@ -782,6 +783,7 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
782
783
  this.container = this.options.container;
783
784
  this.createCompassElement();
784
785
  this.setupStyles();
786
+ this.start();
785
787
  }
786
788
  createCompassElement() {
787
789
  this.compassElement = document.createElement("div");
@@ -988,8 +990,13 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
988
990
  forward.transformDirection(cameraMatrix);
989
991
  forward.y = 0;
990
992
  forward.normalize();
993
+ const north = this.options.northDirection.clone();
994
+ north.y = 0;
995
+ north.normalize();
991
996
  const targetAngle = Math.atan2(-forward.x, -forward.z) * (180 / Math.PI);
992
- let angleDiff = targetAngle - this.currentRotation;
997
+ const northAngle = Math.atan2(-north.x, -north.z) * (180 / Math.PI);
998
+ const adjustedAngle = targetAngle - northAngle;
999
+ let angleDiff = adjustedAngle - this.currentRotation;
993
1000
  while (angleDiff > 180) angleDiff -= 360;
994
1001
  while (angleDiff < -180) angleDiff += 360;
995
1002
  this.currentRotation += angleDiff;
@@ -1001,6 +1008,9 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
1001
1008
  setCamera(camera) {
1002
1009
  this.camera = camera;
1003
1010
  }
1011
+ getNorthDirection() {
1012
+ return this.options.northDirection.clone();
1013
+ }
1004
1014
  setSize(size) {
1005
1015
  this.options.size = size;
1006
1016
  this.compassElement.style.width = `${size}px`;
@@ -1034,17 +1044,17 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
1034
1044
  this.updateStyles();
1035
1045
  }
1036
1046
  /**
1037
- * Helper method to reset camera to look north (world Z- direction)
1047
+ * Helper method to reset camera to look north
1038
1048
  * This is a convenience method that can be called when handling the 'resetToNorth' event
1039
1049
  */
1040
- static resetCameraToNorth(camera, smooth = true) {
1050
+ static resetCameraToNorth(camera, smooth = true, northDirection = new THREE3.Vector3(0, 0, -1)) {
1041
1051
  if (smooth) {
1042
1052
  const startQuaternion = camera.quaternion.clone();
1043
1053
  const targetQuaternion = new THREE3.Quaternion();
1044
1054
  const targetMatrix = new THREE3.Matrix4();
1045
1055
  targetMatrix.lookAt(
1046
1056
  camera.position,
1047
- camera.position.clone().add(new THREE3.Vector3(0, 0, -1)),
1057
+ camera.position.clone().add(northDirection),
1048
1058
  new THREE3.Vector3(0, 1, 0)
1049
1059
  );
1050
1060
  targetQuaternion.setFromRotationMatrix(targetMatrix);
@@ -1065,7 +1075,7 @@ var CompassOverlay = class extends THREE3.EventDispatcher {
1065
1075
  };
1066
1076
  animate();
1067
1077
  } else {
1068
- camera.lookAt(camera.position.clone().add(new THREE3.Vector3(0, 0, -1)));
1078
+ camera.lookAt(camera.position.clone().add(northDirection));
1069
1079
  }
1070
1080
  }
1071
1081
  updateStyles() {
@@ -5154,4 +5164,3 @@ var ViewHelper = class extends THREE8.EventDispatcher {
5154
5164
  ViewHelper,
5155
5165
  calculateBoundingBoxCenter
5156
5166
  });
5157
- //# sourceMappingURL=index.cjs.map
package/dist/index.mjs CHANGED
@@ -3,32 +3,32 @@ import {
3
3
  TransformControlsGizmo,
4
4
  TransformControlsPlane,
5
5
  calculateBoundingBoxCenter
6
- } from "./chunk-BJKSICFA.mjs";
6
+ } from "./chunk-YMMLYGHV.mjs";
7
7
  import {
8
8
  ViewHelper
9
- } from "./chunk-VETFQ3IQ.mjs";
9
+ } from "./chunk-IAZH4OHC.mjs";
10
10
  import {
11
11
  AssetLoader
12
- } from "./chunk-WZ6IGBSE.mjs";
12
+ } from "./chunk-27WUVRGX.mjs";
13
13
  import {
14
14
  DualCameraControls
15
- } from "./chunk-IEE7DQOU.mjs";
15
+ } from "./chunk-XA7OKYSM.mjs";
16
16
  import {
17
17
  CompassOverlay
18
- } from "./chunk-P35QJCOG.mjs";
18
+ } from "./chunk-ZNGFST7K.mjs";
19
19
  import {
20
20
  InfiniteGrid
21
- } from "./chunk-EQDOX34V.mjs";
21
+ } from "./chunk-2CDI7ORN.mjs";
22
22
  import {
23
23
  MeasurementTool,
24
24
  SnapMode
25
- } from "./chunk-5DP6WDB3.mjs";
25
+ } from "./chunk-OZKJ3GAD.mjs";
26
26
  import {
27
27
  SunLightTool
28
- } from "./chunk-IIAZ2WJJ.mjs";
28
+ } from "./chunk-W4DAAAW6.mjs";
29
29
  import {
30
30
  TerrainTool
31
- } from "./chunk-EIROAPF7.mjs";
31
+ } from "./chunk-FBTT6MU6.mjs";
32
32
  export {
33
33
  AssetLoader,
34
34
  CompassOverlay,
@@ -44,4 +44,3 @@ export {
44
44
  ViewHelper,
45
45
  calculateBoundingBoxCenter
46
46
  };
47
- //# sourceMappingURL=index.mjs.map
@@ -1195,4 +1195,3 @@ var MeasurementTool = class extends THREE.EventDispatcher {
1195
1195
  MeasurementTool,
1196
1196
  SnapMode
1197
1197
  });
1198
- //# sourceMappingURL=index.cjs.map
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  MeasurementTool,
3
3
  SnapMode
4
- } from "../chunk-5DP6WDB3.mjs";
4
+ } from "../chunk-OZKJ3GAD.mjs";
5
5
  export {
6
6
  MeasurementTool,
7
7
  SnapMode
8
8
  };
9
- //# sourceMappingURL=index.mjs.map
@@ -438,4 +438,3 @@ var SunLightTool = class extends THREE.EventDispatcher {
438
438
  0 && (module.exports = {
439
439
  SunLightTool
440
440
  });
441
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  SunLightTool
3
- } from "../chunk-IIAZ2WJJ.mjs";
3
+ } from "../chunk-W4DAAAW6.mjs";
4
4
  export {
5
5
  SunLightTool
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
@@ -420,4 +420,3 @@ var TerrainTool = class extends THREE.EventDispatcher {
420
420
  0 && (module.exports = {
421
421
  TerrainTool
422
422
  });
423
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  TerrainTool
3
- } from "../chunk-EIROAPF7.mjs";
3
+ } from "../chunk-FBTT6MU6.mjs";
4
4
  export {
5
5
  TerrainTool
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
@@ -1584,4 +1584,3 @@ var TransformControlsPlane = class extends import_three.Mesh {
1584
1584
  TransformControlsPlane,
1585
1585
  calculateBoundingBoxCenter
1586
1586
  });
1587
- //# sourceMappingURL=index.cjs.map
@@ -3,11 +3,10 @@ import {
3
3
  TransformControlsGizmo,
4
4
  TransformControlsPlane,
5
5
  calculateBoundingBoxCenter
6
- } from "../chunk-BJKSICFA.mjs";
6
+ } from "../chunk-YMMLYGHV.mjs";
7
7
  export {
8
8
  TransformControls,
9
9
  TransformControlsGizmo,
10
10
  TransformControlsPlane,
11
11
  calculateBoundingBoxCenter
12
12
  };
13
- //# sourceMappingURL=index.mjs.map
@@ -433,4 +433,3 @@ var ViewHelper = class extends THREE.EventDispatcher {
433
433
  0 && (module.exports = {
434
434
  ViewHelper
435
435
  });
436
- //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  ViewHelper
3
- } from "../chunk-VETFQ3IQ.mjs";
3
+ } from "../chunk-IAZH4OHC.mjs";
4
4
  export {
5
5
  ViewHelper
6
6
  };
7
- //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonybfox/threejs-tools",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "A single entry point that bundles all Three.js tools (camera, terrain, measurements, helpers, and more).",
5
5
  "private": false,
6
6
  "main": "./dist/index.cjs",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../packages/asset-loader/src/index.ts","../../packages/asset-loader/src/AssetLoader.ts"],"sourcesContent":["export * from './AssetLoader'\n","import * as THREE from 'three'\nimport { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'\nimport { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js'\nimport { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js'\nimport { USDLoader } from 'three/examples/jsm/loaders/USDLoader.js'\n\n// Event types for asset loading\ninterface AssetLoaderEventMap {\n progress: { loaded: number; total: number; percentage: number }\n loaded: { asset: THREE.Object3D }\n error: { error: Error }\n placeholderCreated: { placeholder: THREE.Object3D }\n lowResLoaded: { lowRes: THREE.Object3D }\n}\n\nexport type AssetType = 'gltf' | 'fbx' | 'obj' | 'usd' | 'usdz'\n\nexport interface AssetLoaderOptions {\n type: AssetType\n url: string\n size?: [number, number, number] // Optional size for placeholder\n lowResUrl?: string // Optional low-res model URL\n enableCaching?: boolean\n placeholderColor?: number\n placeholderOpacity?: number\n errorColor?: number // Color to use when loading fails\n errorOpacity?: number // Opacity to use when loading fails\n}\n\nexport class AssetLoader extends THREE.EventDispatcher<AssetLoaderEventMap> {\n private cache: Map<string, THREE.Object3D> = new Map()\n private gltfLoader: GLTFLoader\n private fbxLoader: FBXLoader\n private objLoader: OBJLoader\n private usdLoader: USDLoader\n private placeholder: THREE.Object3D | null = null\n private loadedAsset: THREE.Object3D | null = null\n private lowResAsset: THREE.Object3D | null = null\n private errorColor: number = 0xff4444\n private errorOpacity: number = 0.5\n\n constructor() {\n super()\n this.gltfLoader = new GLTFLoader()\n this.fbxLoader = new FBXLoader()\n this.objLoader = new OBJLoader()\n this.usdLoader = new USDLoader()\n }\n\n /**\n * Create a placeholder cube with shader effect\n */\n private createPlaceholder(\n size: [number, number, number],\n color: number = 0x4fc3f7,\n opacity: number = 0.3\n ): THREE.Object3D {\n const [width, height, depth] = size\n const geometry = new THREE.BoxGeometry(width, height, depth)\n\n // Custom shader material with fill-up effect\n const material = new THREE.ShaderMaterial({\n side: THREE.DoubleSide,\n depthWrite: false,\n blending: THREE.AdditiveBlending,\n transparent: true,\n uniforms: {\n color: { value: new THREE.Color(color) },\n opacity: { value: opacity },\n fillProgress: { value: 0.0 },\n time: { value: 0.0 },\n isError: { value: 0.0 },\n yMin: { value: -height / 2 },\n yMax: { value: height / 2 },\n },\n vertexShader: `\n varying vec3 vPosition;\n void main() {\n vPosition = position;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n }\n `,\n fragmentShader: `\n uniform vec3 color;\n uniform float opacity;\n uniform float fillProgress;\n uniform float time;\n uniform float isError;\n uniform float yMin;\n uniform float yMax;\n varying vec3 vPosition;\n \n void main() {\n float normalizedY = (vPosition.y - yMin) / (yMax - yMin); // Normalize based on actual geometry bounds\n float alpha = opacity;\n \n // Create fill-up effect\n if (normalizedY > fillProgress) {\n alpha *= 0.1; // Reduce opacity for unfilled parts\n }\n \n // Error state effects\n if (isError > 0.5) {\n // Add pulsing effect for error state\n float pulse = 0.5 + 0.5 * sin(time * 4.0);\n alpha *= (0.3 + 0.4 * pulse);\n \n // Add error pattern\n float stripe = sin(vPosition.y * 20.0 + time * 2.0);\n alpha *= (0.7 + 0.3 * step(0.0, stripe));\n }\n \n // Add edge glow\n vec3 viewDirection = normalize(cameraPosition - vPosition);\n float edgeIntensity = pow(1.0 - abs(dot(viewDirection, normalize(vPosition))), 2.0);\n \n vec3 finalColor = color + edgeIntensity * 0.5;\n gl_FragColor = vec4(finalColor, alpha);\n }\n `,\n })\n\n const mesh = new THREE.Mesh(geometry, material)\n this.positionAssetAtBottomCenter(mesh)\n return mesh\n }\n\n /**\n * Update placeholder fill progress based on loading progress\n */\n private updatePlaceholder(progress: number) {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms && material.uniforms.fillProgress) {\n material.uniforms.fillProgress.value = progress\n }\n }\n }\n\n /**\n * Set placeholder to error state with configurable color and opacity\n */\n private setPlaceholderError() {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms) {\n // Change to error color\n if (material.uniforms.color) {\n material.uniforms.color.value = new THREE.Color(this.errorColor)\n }\n // Set error opacity\n if (material.uniforms.opacity) {\n material.uniforms.opacity.value = this.errorOpacity\n }\n // Set fill progress to indicate failure\n if (material.uniforms.fillProgress) {\n material.uniforms.fillProgress.value = 0.0\n }\n // Enable error state\n if (material.uniforms.isError) {\n material.uniforms.isError.value = 1.0\n }\n }\n }\n }\n\n /**\n * Update placeholder animation time (call this in your render loop)\n */\n public updatePlaceholderAnimation(deltaTime: number) {\n if (this.placeholder && this.placeholder instanceof THREE.Mesh) {\n const material = this.placeholder.material as THREE.ShaderMaterial\n if (material.uniforms && material.uniforms.time) {\n material.uniforms.time.value += deltaTime\n }\n }\n }\n\n /**\n * Reposition an asset so that its bottom-center sits at the local origin.\n */\n private positionAssetAtBottomCenter(object: THREE.Object3D) {\n object.updateMatrixWorld(true)\n\n const boundingBox = new THREE.Box3().setFromObject(object)\n if (boundingBox.isEmpty()) {\n return\n }\n\n const center = boundingBox.getCenter(new THREE.Vector3())\n const bottomCenter = new THREE.Vector3(\n center.x,\n boundingBox.min.y + 0.01,\n center.z\n )\n\n if (\n !Number.isFinite(bottomCenter.x) ||\n !Number.isFinite(bottomCenter.y) ||\n !Number.isFinite(bottomCenter.z)\n ) {\n return\n }\n\n object.position.sub(bottomCenter)\n object.userData.bottomCenterOffset = bottomCenter\n object.updateMatrixWorld(true)\n }\n\n private ensureBottomCenterOffset(\n object: THREE.Object3D\n ): THREE.Vector3 | null {\n const offset = object.userData.bottomCenterOffset\n if (offset instanceof THREE.Vector3) {\n return offset\n }\n\n if (offset && typeof offset === 'object') {\n const {\n x = 0,\n y = 0,\n z = 0,\n } = offset as Partial<Record<'x' | 'y' | 'z', number>>\n const normalized = new THREE.Vector3(x ?? 0, y ?? 0, z ?? 0)\n object.userData.bottomCenterOffset = normalized\n return normalized\n }\n\n return null\n }\n\n private normalizeBottomCenterData(object: THREE.Object3D): boolean {\n const hasOffset = this.ensureBottomCenterOffset(object) !== null\n object.children.forEach((child) => this.normalizeBottomCenterData(child))\n return hasOffset\n }\n\n /**\n * Load an asset with the specified options\n */\n async load(options: AssetLoaderOptions): Promise<THREE.Object3D> {\n const {\n type,\n url,\n size,\n lowResUrl,\n enableCaching = true,\n placeholderColor = 0x4fc3f7,\n placeholderOpacity = 0.4,\n errorColor = 0xff4444,\n errorOpacity = 0.5,\n } = options\n\n // Check cache first\n if (enableCaching && this.cache.has(url)) {\n const cachedClone = this.cache.get(url)!.clone(true)\n const hasOffset = this.normalizeBottomCenterData(cachedClone)\n\n if (!hasOffset) {\n this.positionAssetAtBottomCenter(cachedClone)\n } else {\n cachedClone.updateMatrixWorld(true)\n }\n\n this.loadedAsset = cachedClone\n this.dispatchEvent({ type: 'loaded', asset: cachedClone })\n return cachedClone\n }\n\n // Store error styling options\n this.errorColor = errorColor\n this.errorOpacity = errorOpacity\n\n // Create placeholder if size is provided\n if (size) {\n this.placeholder = this.createPlaceholder(\n size,\n placeholderColor,\n placeholderOpacity\n )\n this.dispatchEvent({\n type: 'placeholderCreated',\n placeholder: this.placeholder,\n })\n }\n\n try {\n // Load low-res model first if provided\n if (lowResUrl) {\n const lowRes = await this.loadModel(type, lowResUrl, true)\n this.lowResAsset = lowRes\n this.dispatchEvent({ type: 'lowResLoaded', lowRes })\n }\n\n // Load main asset\n const asset = await this.loadModel(type, url, false)\n this.loadedAsset = asset\n\n // Cache if enabled\n if (enableCaching) {\n const cacheEntry = asset.clone(true)\n const hasOffset = this.normalizeBottomCenterData(cacheEntry)\n if (!hasOffset) {\n this.positionAssetAtBottomCenter(cacheEntry)\n } else {\n cacheEntry.updateMatrixWorld(true)\n }\n this.cache.set(url, cacheEntry)\n }\n\n this.dispatchEvent({ type: 'loaded', asset })\n return asset\n } catch (error) {\n // Set placeholder to error state\n this.setPlaceholderError()\n this.dispatchEvent({ type: 'error', error: error as Error })\n throw error\n }\n }\n\n /**\n * Load a model based on type\n */\n private loadModel(\n type: AssetType,\n url: string,\n isLowRes: boolean\n ): Promise<THREE.Object3D> {\n return new Promise((resolve, reject) => {\n const onProgress = (event: ProgressEvent) => {\n // Handle cases where loaded > total (compressed content mismatch)\n // or total is 0 (unknown content length)\n let percentage = -1 // Default to indeterminate\n\n // Only calculate percentage if lengthComputable is true AND loaded <= total\n // This prevents false 100% when server reports compressed size\n if (\n event.lengthComputable &&\n event.total > 0 &&\n event.loaded <= event.total\n ) {\n percentage = (event.loaded / event.total) * 100\n }\n\n this.dispatchEvent({\n type: 'progress',\n loaded: event.loaded,\n total: event.total,\n percentage,\n })\n\n // Update placeholder fill only with valid percentage\n if (!isLowRes && percentage >= 0) {\n this.updatePlaceholder(percentage / 100)\n }\n }\n\n const onError = (error: unknown) => {\n reject(error)\n }\n\n switch (type) {\n case 'gltf':\n this.gltfLoader.load(\n url,\n (gltf) => {\n const scene = gltf.scene\n this.positionAssetAtBottomCenter(scene)\n resolve(scene)\n },\n onProgress,\n onError\n )\n break\n\n case 'fbx':\n this.fbxLoader.load(\n url,\n (fbx) => {\n this.positionAssetAtBottomCenter(fbx)\n resolve(fbx)\n },\n onProgress,\n onError\n )\n break\n\n case 'obj':\n this.objLoader.load(\n url,\n (obj) => {\n this.positionAssetAtBottomCenter(obj)\n resolve(obj)\n },\n onProgress,\n onError\n )\n break\n\n case 'usd':\n case 'usdz':\n this.usdLoader.load(\n url,\n (usd) => {\n this.positionAssetAtBottomCenter(usd)\n resolve(usd)\n },\n onProgress,\n onError\n )\n break\n\n default:\n reject(new Error(`Unsupported asset type: ${type}`))\n }\n })\n }\n\n /**\n * Get the placeholder object\n */\n getPlaceholder(): THREE.Object3D | null {\n return this.placeholder\n }\n\n /**\n * Get the loaded asset\n */\n getAsset(): THREE.Object3D | null {\n return this.loadedAsset\n }\n\n /**\n * Get the low-res asset\n */\n getLowResAsset(): THREE.Object3D | null {\n return this.lowResAsset\n }\n\n /**\n * Clear the cache\n */\n clearCache() {\n this.cache.clear()\n }\n\n /**\n * Remove an item from cache\n */\n removeFromCache(url: string) {\n this.cache.delete(url)\n }\n\n /**\n * Get cache size\n */\n getCacheSize(): number {\n return this.cache.size\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../packages/camera/src/index.ts","../../packages/camera/src/DualCameraControls.ts"],"sourcesContent":["export * from './DualCameraControls'\n","import * as THREE from 'three'\nimport CameraControls from 'camera-controls'\n\ntype Vector3Tuple = [number, number, number]\ntype Vector3Like = THREE.Vector3 | Vector3Tuple\n\nexport type CameraMode = 'perspective' | 'orthographic'\n\nexport interface PerspectiveCameraConfig {\n fov?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface OrthographicCameraConfig {\n size?: number\n near?: number\n far?: number\n position?: Vector3Like\n zoom?: number\n}\n\nexport interface DualCameraControlsOptions {\n domElement?: HTMLElement\n initialMode?: CameraMode\n initialTarget?: Vector3Like\n perspective?: PerspectiveCameraConfig\n orthographic?: OrthographicCameraConfig\n}\n\nexport interface ModeChangedEvent {\n type: 'modechange'\n mode: CameraMode\n previousMode: CameraMode\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nexport interface ExternalCameraChangedEvent {\n type: 'externalcamerachange'\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n previousCamera: THREE.PerspectiveCamera | THREE.OrthographicCamera\n}\n\nlet controlsInstalled = false\n\nconst tempVec3A = new THREE.Vector3()\nconst tempVec3B = new THREE.Vector3()\nconst tempVec2 = new THREE.Vector2()\n\nfunction ensureCameraControlsInstalled() {\n if (!controlsInstalled) {\n CameraControls.install({ THREE })\n controlsInstalled = true\n }\n}\n\nfunction toVector3(\n value: Vector3Like | undefined,\n fallback: Vector3Tuple,\n target: THREE.Vector3\n) {\n if (!value) {\n target.set(fallback[0], fallback[1], fallback[2])\n return target\n }\n\n if (Array.isArray(value)) {\n target.set(value[0], value[1], value[2])\n return target\n }\n\n target.copy(value)\n return target\n}\n\n/**\n * Camera controls that manage both perspective and orthographic cameras while\n * extending {@link CameraControls}. Provides helpers to toggle between the\n * camera types and keep the framing consistent.\n */\nexport class DualCameraControls extends CameraControls {\n readonly perspectiveCamera: THREE.PerspectiveCamera\n readonly orthographicCamera: THREE.OrthographicCamera\n\n private readonly renderer: THREE.WebGLRenderer\n private readonly domElementRef: HTMLElement\n private activeMode: CameraMode\n private readonly minOrthoHalfHeight: number\n private readonly updateClock = new THREE.Clock()\n private externalCamera:\n | THREE.PerspectiveCamera\n | THREE.OrthographicCamera\n | null = null\n\n constructor(\n renderer: THREE.WebGLRenderer,\n options: DualCameraControlsOptions = {}\n ) {\n ensureCameraControlsInstalled()\n\n const { domElement = renderer.domElement } = options\n const aspect = resolveAspect(renderer, domElement)\n\n const perspectiveConfig = options.perspective ?? {}\n const orthographicConfig = options.orthographic ?? {}\n\n const perspectiveCamera = new THREE.PerspectiveCamera(\n perspectiveConfig.fov ?? 60,\n aspect,\n perspectiveConfig.near ?? 0.1,\n perspectiveConfig.far ?? 2000\n )\n\n perspectiveCamera.position.copy(\n toVector3(perspectiveConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (perspectiveConfig.zoom !== undefined) {\n perspectiveCamera.zoom = perspectiveConfig.zoom\n perspectiveCamera.updateProjectionMatrix()\n }\n\n const orthoHalfHeight = Math.max(orthographicConfig.size ?? 20, 0.001) * 0.5\n const orthoHalfWidth = orthoHalfHeight * aspect\n\n const orthographicCamera = new THREE.OrthographicCamera(\n -orthoHalfWidth,\n orthoHalfWidth,\n orthoHalfHeight,\n -orthoHalfHeight,\n orthographicConfig.near ?? 0.1,\n orthographicConfig.far ?? 2000\n )\n\n orthographicCamera.position.copy(\n toVector3(orthographicConfig.position, [12, 12, 12], new THREE.Vector3())\n )\n\n if (orthographicConfig.zoom !== undefined) {\n orthographicCamera.zoom = orthographicConfig.zoom\n orthographicCamera.updateProjectionMatrix()\n }\n\n const initialMode = options.initialMode ?? 'perspective'\n const initialCamera =\n initialMode === 'orthographic' ? orthographicCamera : perspectiveCamera\n\n super(initialCamera, domElement)\n\n const initialTarget = toVector3(\n options.initialTarget,\n [0, 0, 0],\n new THREE.Vector3()\n )\n void this.setLookAt(\n initialCamera.position.x,\n initialCamera.position.y,\n initialCamera.position.z,\n initialTarget.x,\n initialTarget.y,\n initialTarget.z,\n false\n )\n\n this.renderer = renderer\n this.domElementRef = domElement\n this.perspectiveCamera = perspectiveCamera\n this.orthographicCamera = orthographicCamera\n this.activeMode = initialMode\n this.minOrthoHalfHeight = orthoHalfHeight\n\n this.updateInputBindingsForMode(initialMode)\n }\n\n get mode(): CameraMode {\n return this.activeMode\n }\n\n /**\n * Returns the currently active camera instance.\n */\n get activeCamera(): THREE.PerspectiveCamera | THREE.OrthographicCamera {\n return this.camera\n }\n\n /**\n * Switch to the perspective camera while keeping the current framing.\n */\n switchToPerspective(enableTransition = false) {\n if (this.activeMode === 'perspective' && !this.externalCamera) {\n return\n }\n\n // Clear external camera if set\n this.externalCamera = null\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.position.copy(position)\n this.perspectiveCamera.quaternion.copy(this.camera.quaternion)\n this.perspectiveCamera.up.copy(this.camera.up)\n this.perspectiveCamera.updateProjectionMatrix()\n\n this.camera = this.perspectiveCamera\n this.activeMode = 'perspective'\n this.updateInputBindingsForMode('perspective')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'orthographic',\n camera: this.perspectiveCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Switch to the orthographic camera while keeping the current framing.\n */\n switchToOrthographic(enableTransition = false) {\n if (this.activeMode === 'orthographic' && !this.externalCamera) {\n return\n }\n\n // Clear external camera if set\n this.externalCamera = null\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n this.updateOrthographicFrustum(position, target, aspect)\n\n this.orthographicCamera.position.copy(position)\n this.orthographicCamera.quaternion.copy(this.camera.quaternion)\n this.orthographicCamera.up.copy(this.camera.up)\n this.orthographicCamera.updateProjectionMatrix()\n\n this.camera = this.orthographicCamera\n this.activeMode = 'orthographic'\n this.updateInputBindingsForMode('orthographic')\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: 'perspective',\n camera: this.orthographicCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Toggles between perspective and orthographic camera modes.\n */\n toggleCameraMode(enableTransition = false) {\n if (this.activeMode === 'perspective') {\n this.switchToOrthographic(enableTransition)\n } else {\n this.switchToPerspective(enableTransition)\n }\n }\n\n /**\n * Returns true if currently using an external camera.\n */\n get isUsingExternalCamera(): boolean {\n return this.externalCamera !== null\n }\n\n /**\n * Sets an external camera to use with the controls.\n * This allows using a camera created outside of DualCameraControls.\n * Call `clearExternalCamera()` to return to the internal cameras.\n */\n setCamera(\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera,\n target?: Vector3Like,\n enableTransition = false\n ) {\n const previousCamera = this.camera\n this.externalCamera = camera\n\n // Update aspect/frustum for the external camera\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n if (camera.type === 'PerspectiveCamera') {\n ;(camera as THREE.PerspectiveCamera).aspect = aspect\n camera.updateProjectionMatrix()\n } else if (camera.type === 'OrthographicCamera') {\n // Maintain the camera's existing frustum proportions but update aspect\n const ortho = camera as THREE.OrthographicCamera\n const currentHeight = (ortho.top - ortho.bottom) * 0.5\n const newHalfWidth = currentHeight * aspect\n ortho.left = -newHalfWidth\n ortho.right = newHalfWidth\n ortho.updateProjectionMatrix()\n }\n\n this.camera = camera\n const mode: CameraMode =\n camera.type === 'PerspectiveCamera' ? 'perspective' : 'orthographic'\n this.activeMode = mode\n this.updateInputBindingsForMode(mode)\n\n // Set up the camera position and target in the controls\n const targetVec = toVector3(target, [0, 0, 0], tempVec3A)\n void this.setLookAt(\n camera.position.x,\n camera.position.y,\n camera.position.z,\n targetVec.x,\n targetVec.y,\n targetVec.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'externalcamerachange',\n camera,\n previousCamera,\n } satisfies ExternalCameraChangedEvent)\n }\n\n /**\n * Clears the external camera and returns to using the internal cameras.\n * Will switch to the camera matching the current mode.\n */\n clearExternalCamera(enableTransition = false) {\n if (!this.externalCamera) {\n return\n }\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n\n this.externalCamera = null\n\n // Return to the internal camera matching the current mode\n const internalCamera =\n this.activeMode === 'orthographic'\n ? this.orthographicCamera\n : this.perspectiveCamera\n\n internalCamera.position.copy(position)\n internalCamera.quaternion.copy(this.camera.quaternion)\n internalCamera.up.copy(this.camera.up)\n\n const aspect = resolveAspect(this.renderer, this.domElementRef)\n if (this.activeMode === 'orthographic') {\n this.updateOrthographicFrustum(position, target, aspect)\n } else {\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n }\n\n this.camera = internalCamera\n\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n enableTransition\n )\n\n this.dispatchEvent({\n type: 'modechange',\n mode: this.activeMode,\n previousMode: this.activeMode,\n camera: internalCamera,\n } satisfies ModeChangedEvent)\n }\n\n /**\n * Update camera projection parameters when the viewport size changes.\n */\n handleResize(width: number, height: number) {\n const aspect = height === 0 ? 1 : width / height\n\n this.perspectiveCamera.aspect = aspect\n this.perspectiveCamera.updateProjectionMatrix()\n\n const target = this.getTarget(tempVec3A)\n const position = this.getPosition(tempVec3B)\n this.updateOrthographicFrustum(position, target, aspect)\n\n if (this.activeMode === 'orthographic') {\n this.camera = this.orthographicCamera\n void this.setLookAt(\n position.x,\n position.y,\n position.z,\n target.x,\n target.y,\n target.z,\n false\n )\n }\n }\n\n /**\n * Moves the camera to a new position and target.\n */\n moveCamera(\n position: Vector3Like,\n target: Vector3Like,\n enableTransition = true\n ) {\n toVector3(position, [0, 0, 0], tempVec3A)\n toVector3(target, [0, 0, 0], tempVec3B)\n\n return this.setLookAt(\n tempVec3A.x,\n tempVec3A.y,\n tempVec3A.z,\n tempVec3B.x,\n tempVec3B.y,\n tempVec3B.z,\n enableTransition\n )\n }\n\n /**\n * Updates the controls using an internally managed clock.\n * Useful when you don't want to pass delta time each frame.\n */\n updateDelta(): ReturnType<CameraControls['update']> {\n const delta = this.updateClock.getDelta()\n return super.update(delta)\n }\n\n private updateInputBindingsForMode(mode: CameraMode) {\n const { ACTION } = CameraControls\n\n if (mode === 'orthographic') {\n this.mouseButtons.left = ACTION.TRUCK\n this.mouseButtons.right = ACTION.ROTATE\n this.mouseButtons.wheel = ACTION.ZOOM\n this.touches.one = ACTION.TOUCH_TRUCK\n this.touches.two = ACTION.TOUCH_ZOOM_TRUCK\n } else {\n this.mouseButtons.left = ACTION.ROTATE\n this.mouseButtons.right = ACTION.TRUCK\n this.mouseButtons.wheel = ACTION.DOLLY\n this.touches.one = ACTION.TOUCH_ROTATE\n this.touches.two = ACTION.TOUCH_DOLLY_TRUCK\n }\n }\n\n private updateOrthographicFrustum(\n position: THREE.Vector3,\n target: THREE.Vector3,\n aspect: number\n ) {\n const distance = Math.max(position.distanceTo(target), 0.001)\n const fov = this.perspectiveCamera.fov\n const halfHeight = Math.max(\n distance * Math.tan(THREE.MathUtils.degToRad(fov * 0.5)),\n this.minOrthoHalfHeight\n )\n const halfWidth = halfHeight * aspect\n\n this.orthographicCamera.left = -halfWidth\n this.orthographicCamera.right = halfWidth\n this.orthographicCamera.top = halfHeight\n this.orthographicCamera.bottom = -halfHeight\n this.orthographicCamera.updateProjectionMatrix()\n }\n}\n\nfunction resolveAspect(\n renderer: THREE.WebGLRenderer,\n domElement: HTMLElement\n): number {\n const size = renderer.getSize(tempVec2)\n if (size.y > 0) {\n return size.x / size.y\n }\n\n const { clientWidth, clientHeight } = domElement\n if (clientHeight > 0) {\n return clientWidth / clientHeight\n }\n\n return 1\n}\n"],"mappings":"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","names":["CameraControls"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}