@tscircuit/3d-viewer 0.0.417 → 0.0.419
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +740 -299
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14228,11 +14228,11 @@ var require_browser = __commonJS({
|
|
|
14228
14228
|
});
|
|
14229
14229
|
|
|
14230
14230
|
// src/CadViewer.tsx
|
|
14231
|
-
import { useState as
|
|
14231
|
+
import { useState as useState19, useCallback as useCallback11, useRef as useRef9, useEffect as useEffect24 } from "react";
|
|
14232
14232
|
|
|
14233
14233
|
// src/CadViewerJscad.tsx
|
|
14234
14234
|
import { su as su4 } from "@tscircuit/circuit-json-util";
|
|
14235
|
-
import { forwardRef as forwardRef3, useMemo as
|
|
14235
|
+
import { forwardRef as forwardRef3, useMemo as useMemo19 } from "react";
|
|
14236
14236
|
|
|
14237
14237
|
// src/AnyCadComponent.tsx
|
|
14238
14238
|
import { su } from "@tscircuit/circuit-json-util";
|
|
@@ -26641,17 +26641,13 @@ var AnyCadComponent = ({
|
|
|
26641
26641
|
};
|
|
26642
26642
|
|
|
26643
26643
|
// src/CadViewerContainer.tsx
|
|
26644
|
-
import {
|
|
26645
|
-
|
|
26646
|
-
useMemo as useMemo14,
|
|
26647
|
-
useState as useState8
|
|
26648
|
-
} from "react";
|
|
26649
|
-
import * as THREE13 from "three";
|
|
26644
|
+
import { forwardRef as forwardRef2, useMemo as useMemo15, useState as useState8 } from "react";
|
|
26645
|
+
import * as THREE14 from "three";
|
|
26650
26646
|
|
|
26651
26647
|
// package.json
|
|
26652
26648
|
var package_default = {
|
|
26653
26649
|
name: "@tscircuit/3d-viewer",
|
|
26654
|
-
version: "0.0.
|
|
26650
|
+
version: "0.0.418",
|
|
26655
26651
|
main: "./dist/index.js",
|
|
26656
26652
|
module: "./dist/index.js",
|
|
26657
26653
|
type: "module",
|
|
@@ -27052,13 +27048,21 @@ var OrbitControls = ({
|
|
|
27052
27048
|
zoomSpeed,
|
|
27053
27049
|
enableDamping,
|
|
27054
27050
|
dampingFactor,
|
|
27055
|
-
target
|
|
27051
|
+
target,
|
|
27052
|
+
onControlsChange
|
|
27056
27053
|
}) => {
|
|
27057
27054
|
const { camera, renderer } = useThree();
|
|
27058
27055
|
const controls = useMemo11(() => {
|
|
27059
27056
|
if (!camera || !renderer) return null;
|
|
27060
27057
|
return new ThreeOrbitControls(camera, renderer.domElement);
|
|
27061
27058
|
}, [camera, renderer]);
|
|
27059
|
+
useEffect13(() => {
|
|
27060
|
+
if (!onControlsChange) return;
|
|
27061
|
+
onControlsChange(controls ?? null);
|
|
27062
|
+
return () => {
|
|
27063
|
+
onControlsChange(null);
|
|
27064
|
+
};
|
|
27065
|
+
}, [controls, onControlsChange]);
|
|
27062
27066
|
useEffect13(() => {
|
|
27063
27067
|
if (!controls) return;
|
|
27064
27068
|
controls.autoRotate = autoRotate || false;
|
|
@@ -27222,6 +27226,272 @@ var Lights = () => {
|
|
|
27222
27226
|
return null;
|
|
27223
27227
|
};
|
|
27224
27228
|
|
|
27229
|
+
// src/hooks/useCameraController.ts
|
|
27230
|
+
import { useCallback as useCallback5, useEffect as useEffect16, useMemo as useMemo14, useRef as useRef5 } from "react";
|
|
27231
|
+
import * as THREE13 from "three";
|
|
27232
|
+
var easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
27233
|
+
var CameraAnimator = ({
|
|
27234
|
+
defaultTarget,
|
|
27235
|
+
controlsRef,
|
|
27236
|
+
onReady
|
|
27237
|
+
}) => {
|
|
27238
|
+
const { camera } = useThree();
|
|
27239
|
+
const animationRef = useRef5(null);
|
|
27240
|
+
const tempQuaternion = useRef5(new THREE13.Quaternion());
|
|
27241
|
+
const tempTarget = useRef5(new THREE13.Vector3());
|
|
27242
|
+
const tempUp = useRef5(new THREE13.Vector3());
|
|
27243
|
+
const tempRoll = useRef5(new THREE13.Quaternion());
|
|
27244
|
+
const tempRollTarget = useRef5(new THREE13.Quaternion());
|
|
27245
|
+
const baseOrientationHelper = useRef5(new THREE13.Object3D());
|
|
27246
|
+
const orientationHelper = useRef5(new THREE13.Object3D());
|
|
27247
|
+
const animateTo = useCallback5(
|
|
27248
|
+
({ position, target, up, durationMs = 600 }) => {
|
|
27249
|
+
if (!camera) return;
|
|
27250
|
+
const currentTarget = controlsRef.current?.target ?? defaultTarget;
|
|
27251
|
+
const toPosition = new THREE13.Vector3(
|
|
27252
|
+
position[0],
|
|
27253
|
+
position[1],
|
|
27254
|
+
position[2]
|
|
27255
|
+
);
|
|
27256
|
+
const resolvedTarget = target ? new THREE13.Vector3(target[0], target[1], target[2]) : defaultTarget.clone();
|
|
27257
|
+
const resolvedUp = new THREE13.Vector3(...up ?? [0, 0, 1]).normalize();
|
|
27258
|
+
const toOrientationHelper = orientationHelper.current;
|
|
27259
|
+
toOrientationHelper.position.copy(toPosition);
|
|
27260
|
+
toOrientationHelper.up.copy(resolvedUp);
|
|
27261
|
+
toOrientationHelper.lookAt(resolvedTarget);
|
|
27262
|
+
const toQuaternion = toOrientationHelper.quaternion.clone();
|
|
27263
|
+
const fromQuaternion = camera.quaternion.clone();
|
|
27264
|
+
const fromPosition = camera.position.clone();
|
|
27265
|
+
const fromTarget = currentTarget.clone();
|
|
27266
|
+
const baseHelper = baseOrientationHelper.current;
|
|
27267
|
+
baseHelper.up.set(0, 0, 1);
|
|
27268
|
+
baseHelper.position.copy(fromPosition);
|
|
27269
|
+
baseHelper.lookAt(fromTarget);
|
|
27270
|
+
const baseFromQuaternion = baseHelper.quaternion.clone();
|
|
27271
|
+
baseHelper.up.set(0, 0, 1);
|
|
27272
|
+
baseHelper.position.copy(toPosition);
|
|
27273
|
+
baseHelper.lookAt(resolvedTarget);
|
|
27274
|
+
const baseToQuaternion = baseHelper.quaternion.clone();
|
|
27275
|
+
const rollFrom = baseFromQuaternion.clone().invert().multiply(fromQuaternion).normalize();
|
|
27276
|
+
const rollTo = baseToQuaternion.clone().invert().multiply(toQuaternion).normalize();
|
|
27277
|
+
animationRef.current = {
|
|
27278
|
+
fromPosition,
|
|
27279
|
+
toPosition,
|
|
27280
|
+
fromTarget,
|
|
27281
|
+
toTarget: resolvedTarget,
|
|
27282
|
+
toQuaternion,
|
|
27283
|
+
rollFrom,
|
|
27284
|
+
rollTo,
|
|
27285
|
+
startTime: performance.now(),
|
|
27286
|
+
duration: durationMs
|
|
27287
|
+
};
|
|
27288
|
+
},
|
|
27289
|
+
[camera, controlsRef, defaultTarget]
|
|
27290
|
+
);
|
|
27291
|
+
useEffect16(() => {
|
|
27292
|
+
if (!onReady || !camera) return;
|
|
27293
|
+
onReady({ animateTo });
|
|
27294
|
+
return () => {
|
|
27295
|
+
onReady(null);
|
|
27296
|
+
};
|
|
27297
|
+
}, [animateTo, camera, onReady]);
|
|
27298
|
+
useFrame(() => {
|
|
27299
|
+
if (!camera || !animationRef.current) return;
|
|
27300
|
+
const {
|
|
27301
|
+
fromPosition,
|
|
27302
|
+
toPosition,
|
|
27303
|
+
fromTarget,
|
|
27304
|
+
toTarget,
|
|
27305
|
+
toQuaternion,
|
|
27306
|
+
rollFrom,
|
|
27307
|
+
rollTo,
|
|
27308
|
+
startTime,
|
|
27309
|
+
duration
|
|
27310
|
+
} = animationRef.current;
|
|
27311
|
+
const elapsed = performance.now() - startTime;
|
|
27312
|
+
const progress = duration <= 0 ? 1 : Math.min(elapsed / duration, 1);
|
|
27313
|
+
const eased = easeInOutCubic(progress);
|
|
27314
|
+
camera.position.lerpVectors(fromPosition, toPosition, eased);
|
|
27315
|
+
const nextTarget = tempTarget.current;
|
|
27316
|
+
nextTarget.copy(fromTarget).lerp(toTarget, eased);
|
|
27317
|
+
const baseHelper = baseOrientationHelper.current;
|
|
27318
|
+
baseHelper.up.set(0, 0, 1);
|
|
27319
|
+
baseHelper.position.copy(camera.position);
|
|
27320
|
+
baseHelper.lookAt(nextTarget);
|
|
27321
|
+
const baseQuaternion = tempQuaternion.current;
|
|
27322
|
+
baseQuaternion.copy(baseHelper.quaternion);
|
|
27323
|
+
const interpolatedRoll = tempRoll.current;
|
|
27324
|
+
interpolatedRoll.copy(rollFrom);
|
|
27325
|
+
const rollTarget = tempRollTarget.current;
|
|
27326
|
+
rollTarget.copy(rollTo);
|
|
27327
|
+
if (rollFrom.dot(rollTo) < 0) {
|
|
27328
|
+
rollTarget.x *= -1;
|
|
27329
|
+
rollTarget.y *= -1;
|
|
27330
|
+
rollTarget.z *= -1;
|
|
27331
|
+
rollTarget.w *= -1;
|
|
27332
|
+
}
|
|
27333
|
+
rollTarget.normalize();
|
|
27334
|
+
interpolatedRoll.slerp(rollTarget, eased);
|
|
27335
|
+
camera.quaternion.copy(baseQuaternion).multiply(interpolatedRoll).normalize();
|
|
27336
|
+
const upVector = tempUp.current;
|
|
27337
|
+
upVector.set(0, 1, 0).applyQuaternion(camera.quaternion).normalize();
|
|
27338
|
+
camera.up.copy(upVector);
|
|
27339
|
+
controlsRef.current?.target.copy(nextTarget);
|
|
27340
|
+
camera.updateMatrixWorld();
|
|
27341
|
+
controlsRef.current?.update();
|
|
27342
|
+
if (progress >= 1) {
|
|
27343
|
+
camera.position.copy(toPosition);
|
|
27344
|
+
camera.quaternion.copy(toQuaternion);
|
|
27345
|
+
camera.up.set(0, 0, 1);
|
|
27346
|
+
camera.updateMatrixWorld();
|
|
27347
|
+
controlsRef.current?.target.copy(toTarget);
|
|
27348
|
+
controlsRef.current?.update();
|
|
27349
|
+
animationRef.current = null;
|
|
27350
|
+
}
|
|
27351
|
+
});
|
|
27352
|
+
return null;
|
|
27353
|
+
};
|
|
27354
|
+
var useCameraController = ({
|
|
27355
|
+
defaultTarget,
|
|
27356
|
+
initialCameraPosition,
|
|
27357
|
+
onCameraControllerReady
|
|
27358
|
+
}) => {
|
|
27359
|
+
const controlsRef = useRef5(null);
|
|
27360
|
+
const baseDistance = useMemo14(() => {
|
|
27361
|
+
const [x, y, z126] = initialCameraPosition ?? [5, 5, 5];
|
|
27362
|
+
const distance2 = Math.hypot(
|
|
27363
|
+
x - defaultTarget.x,
|
|
27364
|
+
y - defaultTarget.y,
|
|
27365
|
+
z126 - defaultTarget.z
|
|
27366
|
+
);
|
|
27367
|
+
return distance2 > 0 ? distance2 : 5;
|
|
27368
|
+
}, [initialCameraPosition, defaultTarget]);
|
|
27369
|
+
const getPresetConfig = useCallback5(
|
|
27370
|
+
(preset) => {
|
|
27371
|
+
const targetVector = [
|
|
27372
|
+
defaultTarget.x,
|
|
27373
|
+
defaultTarget.y,
|
|
27374
|
+
defaultTarget.z
|
|
27375
|
+
];
|
|
27376
|
+
const distance2 = baseDistance;
|
|
27377
|
+
const heightOffset = distance2 * 0.3;
|
|
27378
|
+
switch (preset) {
|
|
27379
|
+
case "Top Centered": {
|
|
27380
|
+
const angledOffset = distance2 / Math.sqrt(2);
|
|
27381
|
+
return {
|
|
27382
|
+
position: [
|
|
27383
|
+
defaultTarget.x,
|
|
27384
|
+
defaultTarget.y - angledOffset,
|
|
27385
|
+
defaultTarget.z + angledOffset
|
|
27386
|
+
],
|
|
27387
|
+
target: targetVector,
|
|
27388
|
+
up: [0, 0, 1]
|
|
27389
|
+
};
|
|
27390
|
+
}
|
|
27391
|
+
case "Top Down":
|
|
27392
|
+
return {
|
|
27393
|
+
position: [
|
|
27394
|
+
defaultTarget.x,
|
|
27395
|
+
defaultTarget.y,
|
|
27396
|
+
defaultTarget.z + distance2
|
|
27397
|
+
],
|
|
27398
|
+
target: targetVector,
|
|
27399
|
+
up: [0, 0, 1]
|
|
27400
|
+
};
|
|
27401
|
+
case "Top Left Corner":
|
|
27402
|
+
return {
|
|
27403
|
+
position: [
|
|
27404
|
+
defaultTarget.x - distance2 * 0.6,
|
|
27405
|
+
defaultTarget.y - distance2 * 0.6,
|
|
27406
|
+
defaultTarget.z + distance2 * 0.6
|
|
27407
|
+
],
|
|
27408
|
+
target: targetVector,
|
|
27409
|
+
up: [0, 0, 1]
|
|
27410
|
+
};
|
|
27411
|
+
case "Top Right Corner":
|
|
27412
|
+
return {
|
|
27413
|
+
position: [
|
|
27414
|
+
defaultTarget.x + distance2 * 0.6,
|
|
27415
|
+
defaultTarget.y - distance2 * 0.6,
|
|
27416
|
+
defaultTarget.z + distance2 * 0.6
|
|
27417
|
+
],
|
|
27418
|
+
target: targetVector,
|
|
27419
|
+
up: [0, 0, 1]
|
|
27420
|
+
};
|
|
27421
|
+
case "Left Sideview":
|
|
27422
|
+
return {
|
|
27423
|
+
position: [
|
|
27424
|
+
defaultTarget.x - distance2,
|
|
27425
|
+
defaultTarget.y,
|
|
27426
|
+
defaultTarget.z + heightOffset
|
|
27427
|
+
],
|
|
27428
|
+
target: targetVector,
|
|
27429
|
+
up: [0, 0, 1]
|
|
27430
|
+
};
|
|
27431
|
+
case "Right Sideview":
|
|
27432
|
+
return {
|
|
27433
|
+
position: [
|
|
27434
|
+
defaultTarget.x + distance2,
|
|
27435
|
+
defaultTarget.y,
|
|
27436
|
+
defaultTarget.z + heightOffset
|
|
27437
|
+
],
|
|
27438
|
+
target: targetVector,
|
|
27439
|
+
up: [0, 0, 1]
|
|
27440
|
+
};
|
|
27441
|
+
case "Front":
|
|
27442
|
+
return {
|
|
27443
|
+
position: [
|
|
27444
|
+
defaultTarget.x,
|
|
27445
|
+
defaultTarget.y - distance2,
|
|
27446
|
+
defaultTarget.z + heightOffset
|
|
27447
|
+
],
|
|
27448
|
+
target: targetVector,
|
|
27449
|
+
up: [0, 0, 1]
|
|
27450
|
+
};
|
|
27451
|
+
case "Custom":
|
|
27452
|
+
default:
|
|
27453
|
+
return null;
|
|
27454
|
+
}
|
|
27455
|
+
},
|
|
27456
|
+
[baseDistance, defaultTarget]
|
|
27457
|
+
);
|
|
27458
|
+
const handleControllerReady = useCallback5(
|
|
27459
|
+
(controller) => {
|
|
27460
|
+
if (!onCameraControllerReady) return;
|
|
27461
|
+
if (!controller) {
|
|
27462
|
+
onCameraControllerReady(null);
|
|
27463
|
+
return;
|
|
27464
|
+
}
|
|
27465
|
+
const enhancedController = {
|
|
27466
|
+
animateTo: controller.animateTo,
|
|
27467
|
+
animateToPreset: (preset) => {
|
|
27468
|
+
if (preset === "Custom") return;
|
|
27469
|
+
const config = getPresetConfig(preset);
|
|
27470
|
+
if (!config) return;
|
|
27471
|
+
controller.animateTo(config);
|
|
27472
|
+
}
|
|
27473
|
+
};
|
|
27474
|
+
onCameraControllerReady(enhancedController);
|
|
27475
|
+
},
|
|
27476
|
+
[getPresetConfig, onCameraControllerReady]
|
|
27477
|
+
);
|
|
27478
|
+
const handleControlsChange = useCallback5(
|
|
27479
|
+
(controls) => {
|
|
27480
|
+
controlsRef.current = controls;
|
|
27481
|
+
},
|
|
27482
|
+
[]
|
|
27483
|
+
);
|
|
27484
|
+
const cameraAnimatorProps = useMemo14(
|
|
27485
|
+
() => ({
|
|
27486
|
+
defaultTarget,
|
|
27487
|
+
controlsRef,
|
|
27488
|
+
onReady: handleControllerReady
|
|
27489
|
+
}),
|
|
27490
|
+
[defaultTarget, handleControllerReady]
|
|
27491
|
+
);
|
|
27492
|
+
return { cameraAnimatorProps, handleControlsChange };
|
|
27493
|
+
};
|
|
27494
|
+
|
|
27225
27495
|
// src/CadViewerContainer.tsx
|
|
27226
27496
|
import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
27227
27497
|
var RotationTracker = () => {
|
|
@@ -27241,12 +27511,13 @@ var CadViewerContainer = forwardRef2(
|
|
|
27241
27511
|
clickToInteractEnabled = false,
|
|
27242
27512
|
boardDimensions,
|
|
27243
27513
|
boardCenter,
|
|
27244
|
-
onUserInteraction
|
|
27514
|
+
onUserInteraction,
|
|
27515
|
+
onCameraControllerReady
|
|
27245
27516
|
}, ref) => {
|
|
27246
27517
|
const [isInteractionEnabled, setIsInteractionEnabled] = useState8(
|
|
27247
27518
|
!clickToInteractEnabled
|
|
27248
27519
|
);
|
|
27249
|
-
const gridSectionSize =
|
|
27520
|
+
const gridSectionSize = useMemo15(() => {
|
|
27250
27521
|
if (!boardDimensions) return 10;
|
|
27251
27522
|
const width10 = boardDimensions.width ?? 0;
|
|
27252
27523
|
const height10 = boardDimensions.height ?? 0;
|
|
@@ -27254,10 +27525,21 @@ var CadViewerContainer = forwardRef2(
|
|
|
27254
27525
|
const desired = largest * 1.5;
|
|
27255
27526
|
return desired > 10 ? desired : 10;
|
|
27256
27527
|
}, [boardDimensions]);
|
|
27257
|
-
const orbitTarget =
|
|
27528
|
+
const orbitTarget = useMemo15(() => {
|
|
27258
27529
|
if (!boardCenter) return void 0;
|
|
27259
27530
|
return [boardCenter.x, boardCenter.y, 0];
|
|
27260
27531
|
}, [boardCenter]);
|
|
27532
|
+
const defaultTarget = useMemo15(() => {
|
|
27533
|
+
if (orbitTarget) {
|
|
27534
|
+
return new THREE14.Vector3(orbitTarget[0], orbitTarget[1], orbitTarget[2]);
|
|
27535
|
+
}
|
|
27536
|
+
return new THREE14.Vector3(0, 0, 0);
|
|
27537
|
+
}, [orbitTarget]);
|
|
27538
|
+
const { cameraAnimatorProps, handleControlsChange } = useCameraController({
|
|
27539
|
+
defaultTarget,
|
|
27540
|
+
initialCameraPosition,
|
|
27541
|
+
onCameraControllerReady
|
|
27542
|
+
});
|
|
27261
27543
|
return /* @__PURE__ */ jsxs4("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
27262
27544
|
/* @__PURE__ */ jsx12(
|
|
27263
27545
|
"div",
|
|
@@ -27286,9 +27568,10 @@ var CadViewerContainer = forwardRef2(
|
|
|
27286
27568
|
Canvas,
|
|
27287
27569
|
{
|
|
27288
27570
|
ref,
|
|
27289
|
-
scene: { up: new
|
|
27571
|
+
scene: { up: new THREE14.Vector3(0, 0, 1) },
|
|
27290
27572
|
camera: { up: [0, 0, 1], position: initialCameraPosition },
|
|
27291
27573
|
children: [
|
|
27574
|
+
/* @__PURE__ */ jsx12(CameraAnimator, { ...cameraAnimatorProps }),
|
|
27292
27575
|
/* @__PURE__ */ jsx12(RotationTracker, {}),
|
|
27293
27576
|
isInteractionEnabled && /* @__PURE__ */ jsx12(
|
|
27294
27577
|
OrbitControls,
|
|
@@ -27301,7 +27584,8 @@ var CadViewerContainer = forwardRef2(
|
|
|
27301
27584
|
zoomSpeed: 0.5,
|
|
27302
27585
|
enableDamping: true,
|
|
27303
27586
|
dampingFactor: 0.1,
|
|
27304
|
-
target: orbitTarget
|
|
27587
|
+
target: orbitTarget,
|
|
27588
|
+
onControlsChange: handleControlsChange
|
|
27305
27589
|
}
|
|
27306
27590
|
),
|
|
27307
27591
|
/* @__PURE__ */ jsx12(Lights, {}),
|
|
@@ -27379,9 +27663,9 @@ var CadViewerContainer = forwardRef2(
|
|
|
27379
27663
|
|
|
27380
27664
|
// src/hooks/use-convert-children-to-soup.ts
|
|
27381
27665
|
import { Circuit } from "@tscircuit/core";
|
|
27382
|
-
import { useMemo as
|
|
27666
|
+
import { useMemo as useMemo16 } from "react";
|
|
27383
27667
|
var useConvertChildrenToCircuitJson = (children) => {
|
|
27384
|
-
return
|
|
27668
|
+
return useMemo16(() => {
|
|
27385
27669
|
if (!children) return [];
|
|
27386
27670
|
const circuit = new Circuit();
|
|
27387
27671
|
circuit.add(children);
|
|
@@ -29089,8 +29373,8 @@ var useBoardGeomBuilder = (circuitJson) => {
|
|
|
29089
29373
|
};
|
|
29090
29374
|
|
|
29091
29375
|
// src/three-components/Error3d.tsx
|
|
29092
|
-
import { useState as useState11, useCallback as
|
|
29093
|
-
import * as
|
|
29376
|
+
import { useState as useState11, useCallback as useCallback6, useEffect as useEffect19, useMemo as useMemo17 } from "react";
|
|
29377
|
+
import * as THREE15 from "three";
|
|
29094
29378
|
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
29095
29379
|
var Error3d = ({
|
|
29096
29380
|
error,
|
|
@@ -29099,7 +29383,7 @@ var Error3d = ({
|
|
|
29099
29383
|
const { rootObject } = useThree();
|
|
29100
29384
|
const [isHovered, setIsHovered] = useState11(false);
|
|
29101
29385
|
const [hoverPosition, setHoverPosition] = useState11(null);
|
|
29102
|
-
const handleHover =
|
|
29386
|
+
const handleHover = useCallback6((e) => {
|
|
29103
29387
|
if (e?.mousePosition) {
|
|
29104
29388
|
setIsHovered(true);
|
|
29105
29389
|
setHoverPosition(e.mousePosition);
|
|
@@ -29108,11 +29392,11 @@ var Error3d = ({
|
|
|
29108
29392
|
setHoverPosition(null);
|
|
29109
29393
|
}
|
|
29110
29394
|
}, []);
|
|
29111
|
-
const handleUnhover =
|
|
29395
|
+
const handleUnhover = useCallback6(() => {
|
|
29112
29396
|
setIsHovered(false);
|
|
29113
29397
|
setHoverPosition(null);
|
|
29114
29398
|
}, []);
|
|
29115
|
-
const position =
|
|
29399
|
+
const position = useMemo17(() => {
|
|
29116
29400
|
if (cad_component2?.position) {
|
|
29117
29401
|
const p = [
|
|
29118
29402
|
cad_component2.position.x,
|
|
@@ -29123,8 +29407,8 @@ var Error3d = ({
|
|
|
29123
29407
|
}
|
|
29124
29408
|
return [0, 0, 0];
|
|
29125
29409
|
}, [cad_component2]);
|
|
29126
|
-
const group =
|
|
29127
|
-
const g = new
|
|
29410
|
+
const group = useMemo17(() => {
|
|
29411
|
+
const g = new THREE15.Group();
|
|
29128
29412
|
g.position.fromArray(position);
|
|
29129
29413
|
return g;
|
|
29130
29414
|
}, [position]);
|
|
@@ -29183,10 +29467,10 @@ var Error3d = ({
|
|
|
29183
29467
|
] });
|
|
29184
29468
|
};
|
|
29185
29469
|
var ErrorBox = ({ parent }) => {
|
|
29186
|
-
const mesh =
|
|
29187
|
-
const m = new
|
|
29188
|
-
new
|
|
29189
|
-
new
|
|
29470
|
+
const mesh = useMemo17(() => {
|
|
29471
|
+
const m = new THREE15.Mesh(
|
|
29472
|
+
new THREE15.BoxGeometry(0.5, 0.5, 0.5),
|
|
29473
|
+
new THREE15.MeshStandardMaterial({
|
|
29190
29474
|
depthTest: false,
|
|
29191
29475
|
transparent: true,
|
|
29192
29476
|
color: "red",
|
|
@@ -29207,8 +29491,8 @@ var ErrorBox = ({ parent }) => {
|
|
|
29207
29491
|
};
|
|
29208
29492
|
|
|
29209
29493
|
// src/three-components/STLModel.tsx
|
|
29210
|
-
import { useState as useState12, useEffect as useEffect20, useMemo as
|
|
29211
|
-
import * as
|
|
29494
|
+
import { useState as useState12, useEffect as useEffect20, useMemo as useMemo18 } from "react";
|
|
29495
|
+
import * as THREE16 from "three";
|
|
29212
29496
|
import { STLLoader } from "three-stdlib";
|
|
29213
29497
|
function STLModel({
|
|
29214
29498
|
stlUrl,
|
|
@@ -29237,14 +29521,14 @@ function STLModel({
|
|
|
29237
29521
|
});
|
|
29238
29522
|
}
|
|
29239
29523
|
}, [stlUrl, stlData]);
|
|
29240
|
-
const mesh =
|
|
29524
|
+
const mesh = useMemo18(() => {
|
|
29241
29525
|
if (!geom) return null;
|
|
29242
|
-
const material = new
|
|
29243
|
-
color: Array.isArray(color) ? new
|
|
29526
|
+
const material = new THREE16.MeshStandardMaterial({
|
|
29527
|
+
color: Array.isArray(color) ? new THREE16.Color(color[0], color[1], color[2]) : color,
|
|
29244
29528
|
transparent: opacity !== 1,
|
|
29245
29529
|
opacity
|
|
29246
29530
|
});
|
|
29247
|
-
return new
|
|
29531
|
+
return new THREE16.Mesh(geom, material);
|
|
29248
29532
|
}, [geom, color, opacity]);
|
|
29249
29533
|
useEffect20(() => {
|
|
29250
29534
|
if (!rootObject || !mesh) return;
|
|
@@ -29316,15 +29600,16 @@ var CadViewerJscad = forwardRef3(
|
|
|
29316
29600
|
children,
|
|
29317
29601
|
autoRotateDisabled,
|
|
29318
29602
|
clickToInteractEnabled,
|
|
29319
|
-
onUserInteraction
|
|
29603
|
+
onUserInteraction,
|
|
29604
|
+
onCameraControllerReady
|
|
29320
29605
|
}, ref) => {
|
|
29321
29606
|
const childrenSoup = useConvertChildrenToCircuitJson(children);
|
|
29322
|
-
const internalCircuitJson =
|
|
29607
|
+
const internalCircuitJson = useMemo19(() => {
|
|
29323
29608
|
const cj = soup ?? circuitJson;
|
|
29324
29609
|
return cj ?? childrenSoup;
|
|
29325
29610
|
}, [soup, circuitJson, childrenSoup]);
|
|
29326
29611
|
const boardGeom = useBoardGeomBuilder(internalCircuitJson);
|
|
29327
|
-
const initialCameraPosition =
|
|
29612
|
+
const initialCameraPosition = useMemo19(() => {
|
|
29328
29613
|
if (!internalCircuitJson) return [5, 5, 5];
|
|
29329
29614
|
try {
|
|
29330
29615
|
const board = su4(internalCircuitJson).pcb_board.list()[0];
|
|
@@ -29343,7 +29628,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
29343
29628
|
return [5, 5, 5];
|
|
29344
29629
|
}
|
|
29345
29630
|
}, [internalCircuitJson]);
|
|
29346
|
-
const boardDimensions =
|
|
29631
|
+
const boardDimensions = useMemo19(() => {
|
|
29347
29632
|
if (!internalCircuitJson) return void 0;
|
|
29348
29633
|
try {
|
|
29349
29634
|
const board = su4(internalCircuitJson).pcb_board.list()[0];
|
|
@@ -29354,7 +29639,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
29354
29639
|
return void 0;
|
|
29355
29640
|
}
|
|
29356
29641
|
}, [internalCircuitJson]);
|
|
29357
|
-
const boardCenter =
|
|
29642
|
+
const boardCenter = useMemo19(() => {
|
|
29358
29643
|
if (!internalCircuitJson) return void 0;
|
|
29359
29644
|
try {
|
|
29360
29645
|
const board = su4(internalCircuitJson).pcb_board.list()[0];
|
|
@@ -29377,6 +29662,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
29377
29662
|
boardDimensions,
|
|
29378
29663
|
boardCenter,
|
|
29379
29664
|
onUserInteraction,
|
|
29665
|
+
onCameraControllerReady,
|
|
29380
29666
|
children: [
|
|
29381
29667
|
boardStls.map(({ stlData, color, layerType }, index) => /* @__PURE__ */ jsx15(
|
|
29382
29668
|
VisibleSTLModel,
|
|
@@ -29411,22 +29697,22 @@ var CadViewerJscad = forwardRef3(
|
|
|
29411
29697
|
|
|
29412
29698
|
// src/CadViewerManifold.tsx
|
|
29413
29699
|
import { su as su13 } from "@tscircuit/circuit-json-util";
|
|
29414
|
-
import { useEffect as useEffect22, useMemo as
|
|
29700
|
+
import { useEffect as useEffect22, useMemo as useMemo21, useState as useState15 } from "react";
|
|
29415
29701
|
|
|
29416
29702
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
29417
|
-
import { useState as useState14, useEffect as useEffect21, useMemo as
|
|
29703
|
+
import { useState as useState14, useEffect as useEffect21, useMemo as useMemo20, useRef as useRef7 } from "react";
|
|
29418
29704
|
import { su as su12 } from "@tscircuit/circuit-json-util";
|
|
29419
|
-
import * as
|
|
29705
|
+
import * as THREE24 from "three";
|
|
29420
29706
|
|
|
29421
29707
|
// src/utils/manifold-mesh-to-three-geometry.ts
|
|
29422
|
-
import * as
|
|
29708
|
+
import * as THREE17 from "three";
|
|
29423
29709
|
function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
29424
|
-
const geometry = new
|
|
29710
|
+
const geometry = new THREE17.BufferGeometry();
|
|
29425
29711
|
geometry.setAttribute(
|
|
29426
29712
|
"position",
|
|
29427
|
-
new
|
|
29713
|
+
new THREE17.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
|
|
29428
29714
|
);
|
|
29429
|
-
geometry.setIndex(new
|
|
29715
|
+
geometry.setIndex(new THREE17.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
|
|
29430
29716
|
if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
|
|
29431
29717
|
for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
|
|
29432
29718
|
const start = manifoldMesh.runIndex[i];
|
|
@@ -29440,7 +29726,7 @@ function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
|
29440
29726
|
}
|
|
29441
29727
|
|
|
29442
29728
|
// src/utils/trace-texture.ts
|
|
29443
|
-
import * as
|
|
29729
|
+
import * as THREE18 from "three";
|
|
29444
29730
|
import { su as su5 } from "@tscircuit/circuit-json-util";
|
|
29445
29731
|
function isWireRoutePoint(point2) {
|
|
29446
29732
|
return point2 && point2.route_type === "wire" && typeof point2.layer === "string" && typeof point2.width === "number";
|
|
@@ -29523,10 +29809,10 @@ function createTraceTextureForLayer({
|
|
|
29523
29809
|
}
|
|
29524
29810
|
});
|
|
29525
29811
|
ctx.globalCompositeOperation = "source-over";
|
|
29526
|
-
const texture = new
|
|
29812
|
+
const texture = new THREE18.CanvasTexture(canvas);
|
|
29527
29813
|
texture.generateMipmaps = true;
|
|
29528
|
-
texture.minFilter =
|
|
29529
|
-
texture.magFilter =
|
|
29814
|
+
texture.minFilter = THREE18.LinearMipmapLinearFilter;
|
|
29815
|
+
texture.magFilter = THREE18.LinearFilter;
|
|
29530
29816
|
texture.anisotropy = 16;
|
|
29531
29817
|
texture.needsUpdate = true;
|
|
29532
29818
|
return texture;
|
|
@@ -29534,7 +29820,7 @@ function createTraceTextureForLayer({
|
|
|
29534
29820
|
|
|
29535
29821
|
// src/utils/silkscreen-texture.ts
|
|
29536
29822
|
var import_text2 = __toESM(require_text(), 1);
|
|
29537
|
-
import * as
|
|
29823
|
+
import * as THREE19 from "three";
|
|
29538
29824
|
import { su as su6 } from "@tscircuit/circuit-json-util";
|
|
29539
29825
|
function createSilkscreenTextureForLayer({
|
|
29540
29826
|
layer,
|
|
@@ -29663,10 +29949,10 @@ function createSilkscreenTextureForLayer({
|
|
|
29663
29949
|
ctx.stroke();
|
|
29664
29950
|
});
|
|
29665
29951
|
});
|
|
29666
|
-
const texture = new
|
|
29952
|
+
const texture = new THREE19.CanvasTexture(canvas);
|
|
29667
29953
|
texture.generateMipmaps = true;
|
|
29668
|
-
texture.minFilter =
|
|
29669
|
-
texture.magFilter =
|
|
29954
|
+
texture.minFilter = THREE19.LinearMipmapLinearFilter;
|
|
29955
|
+
texture.magFilter = THREE19.LinearFilter;
|
|
29670
29956
|
texture.anisotropy = 16;
|
|
29671
29957
|
texture.needsUpdate = true;
|
|
29672
29958
|
return texture;
|
|
@@ -29850,8 +30136,8 @@ function processNonPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, m
|
|
|
29850
30136
|
|
|
29851
30137
|
// src/utils/manifold/process-plated-holes.ts
|
|
29852
30138
|
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
29853
|
-
import * as
|
|
29854
|
-
var COPPER_COLOR = new
|
|
30139
|
+
import * as THREE20 from "three";
|
|
30140
|
+
var COPPER_COLOR = new THREE20.Color(...colors.copper);
|
|
29855
30141
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
29856
30142
|
function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
29857
30143
|
const platedHoleBoardDrills = [];
|
|
@@ -29875,8 +30161,7 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
29875
30161
|
Manifold,
|
|
29876
30162
|
x: ph.x,
|
|
29877
30163
|
y: ph.y,
|
|
29878
|
-
outerDiameter: ph.
|
|
29879
|
-
// Drill for the board
|
|
30164
|
+
outerDiameter: ph.hole_diameter * 1.02,
|
|
29880
30165
|
thickness: pcbThickness,
|
|
29881
30166
|
zOffset: MANIFOLD_Z_OFFSET,
|
|
29882
30167
|
segments: SMOOTH_CIRCLE_SEGMENTS
|
|
@@ -30170,7 +30455,7 @@ function processPlatedHolesForManifold(Manifold, circuitJson, pcbThickness, mani
|
|
|
30170
30455
|
|
|
30171
30456
|
// src/utils/manifold/process-vias.ts
|
|
30172
30457
|
import { su as su9 } from "@tscircuit/circuit-json-util";
|
|
30173
|
-
import * as
|
|
30458
|
+
import * as THREE21 from "three";
|
|
30174
30459
|
|
|
30175
30460
|
// src/utils/via-geoms.ts
|
|
30176
30461
|
function createViaCopper({
|
|
@@ -30203,7 +30488,7 @@ function createViaCopper({
|
|
|
30203
30488
|
}
|
|
30204
30489
|
|
|
30205
30490
|
// src/utils/manifold/process-vias.ts
|
|
30206
|
-
var COPPER_COLOR2 = new
|
|
30491
|
+
var COPPER_COLOR2 = new THREE21.Color(...colors.copper);
|
|
30207
30492
|
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
30208
30493
|
const viaBoardDrills = [];
|
|
30209
30494
|
const pcbVias = su9(circuitJson).pcb_via.list();
|
|
@@ -30256,8 +30541,8 @@ function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldIns
|
|
|
30256
30541
|
|
|
30257
30542
|
// src/utils/manifold/process-smt-pads.ts
|
|
30258
30543
|
import { su as su10 } from "@tscircuit/circuit-json-util";
|
|
30259
|
-
import * as
|
|
30260
|
-
var COPPER_COLOR3 = new
|
|
30544
|
+
import * as THREE22 from "three";
|
|
30545
|
+
var COPPER_COLOR3 = new THREE22.Color(...colors.copper);
|
|
30261
30546
|
function processSmtPadsForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, holeUnion, boardClipVolume) {
|
|
30262
30547
|
const smtPadGeoms = [];
|
|
30263
30548
|
const smtPads = su10(circuitJson).pcb_smtpad.list();
|
|
@@ -30353,8 +30638,8 @@ function createManifoldBoard(Manifold, CrossSection, boardData, pcbThickness, ma
|
|
|
30353
30638
|
}
|
|
30354
30639
|
|
|
30355
30640
|
// src/utils/manifold/process-copper-pours.ts
|
|
30356
|
-
import * as
|
|
30357
|
-
var COPPER_COLOR4 = new
|
|
30641
|
+
import * as THREE23 from "three";
|
|
30642
|
+
var COPPER_COLOR4 = new THREE23.Color(...colors.copper);
|
|
30358
30643
|
var arePointsClockwise4 = (points) => {
|
|
30359
30644
|
let area = 0;
|
|
30360
30645
|
for (let i = 0; i < points.length; i++) {
|
|
@@ -30630,7 +30915,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
30630
30915
|
const [error, setError] = useState14(null);
|
|
30631
30916
|
const [isLoading, setIsLoading] = useState14(true);
|
|
30632
30917
|
const manifoldInstancesForCleanup = useRef7([]);
|
|
30633
|
-
const boardData =
|
|
30918
|
+
const boardData = useMemo20(() => {
|
|
30634
30919
|
const boards = su12(circuitJson).pcb_board.list();
|
|
30635
30920
|
if (boards.length === 0) {
|
|
30636
30921
|
return null;
|
|
@@ -30758,7 +31043,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
30758
31043
|
{
|
|
30759
31044
|
key: "plated-holes-union",
|
|
30760
31045
|
geometry: cutPlatedGeom,
|
|
30761
|
-
color: new
|
|
31046
|
+
color: new THREE24.Color(
|
|
30762
31047
|
colors.copper[0],
|
|
30763
31048
|
colors.copper[1],
|
|
30764
31049
|
colors.copper[2]
|
|
@@ -30788,7 +31073,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
30788
31073
|
const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Green;
|
|
30789
31074
|
currentGeoms.board = {
|
|
30790
31075
|
geometry: finalBoardGeom,
|
|
30791
|
-
color: new
|
|
31076
|
+
color: new THREE24.Color(
|
|
30792
31077
|
matColorArray[0],
|
|
30793
31078
|
matColorArray[1],
|
|
30794
31079
|
matColorArray[2]
|
|
@@ -30874,18 +31159,18 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson) => {
|
|
|
30874
31159
|
};
|
|
30875
31160
|
|
|
30876
31161
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
30877
|
-
import * as
|
|
31162
|
+
import * as THREE26 from "three";
|
|
30878
31163
|
|
|
30879
31164
|
// src/utils/create-board-material.ts
|
|
30880
|
-
import * as
|
|
30881
|
-
var DEFAULT_SIDE =
|
|
31165
|
+
import * as THREE25 from "three";
|
|
31166
|
+
var DEFAULT_SIDE = THREE25.DoubleSide;
|
|
30882
31167
|
var createBoardMaterial = ({
|
|
30883
31168
|
material,
|
|
30884
31169
|
color,
|
|
30885
31170
|
side = DEFAULT_SIDE
|
|
30886
31171
|
}) => {
|
|
30887
31172
|
if (material === "fr4") {
|
|
30888
|
-
return new
|
|
31173
|
+
return new THREE25.MeshPhysicalMaterial({
|
|
30889
31174
|
color,
|
|
30890
31175
|
side,
|
|
30891
31176
|
metalness: 0,
|
|
@@ -30899,7 +31184,7 @@ var createBoardMaterial = ({
|
|
|
30899
31184
|
flatShading: true
|
|
30900
31185
|
});
|
|
30901
31186
|
}
|
|
30902
|
-
return new
|
|
31187
|
+
return new THREE25.MeshStandardMaterial({
|
|
30903
31188
|
color,
|
|
30904
31189
|
side,
|
|
30905
31190
|
flatShading: true,
|
|
@@ -30915,12 +31200,12 @@ function createGeometryMeshes(geoms) {
|
|
|
30915
31200
|
const meshes = [];
|
|
30916
31201
|
if (!geoms) return meshes;
|
|
30917
31202
|
if (geoms.board && geoms.board.geometry) {
|
|
30918
|
-
const mesh = new
|
|
31203
|
+
const mesh = new THREE26.Mesh(
|
|
30919
31204
|
geoms.board.geometry,
|
|
30920
31205
|
createBoardMaterial({
|
|
30921
31206
|
material: geoms.board.material,
|
|
30922
31207
|
color: geoms.board.color,
|
|
30923
|
-
side:
|
|
31208
|
+
side: THREE26.DoubleSide
|
|
30924
31209
|
})
|
|
30925
31210
|
);
|
|
30926
31211
|
mesh.name = "board-geom";
|
|
@@ -30929,11 +31214,11 @@ function createGeometryMeshes(geoms) {
|
|
|
30929
31214
|
const createMeshesFromArray = (geomArray) => {
|
|
30930
31215
|
if (geomArray) {
|
|
30931
31216
|
geomArray.forEach((comp) => {
|
|
30932
|
-
const mesh = new
|
|
31217
|
+
const mesh = new THREE26.Mesh(
|
|
30933
31218
|
comp.geometry,
|
|
30934
|
-
new
|
|
31219
|
+
new THREE26.MeshStandardMaterial({
|
|
30935
31220
|
color: comp.color,
|
|
30936
|
-
side:
|
|
31221
|
+
side: THREE26.DoubleSide,
|
|
30937
31222
|
flatShading: true
|
|
30938
31223
|
// Consistent with board
|
|
30939
31224
|
})
|
|
@@ -30951,21 +31236,21 @@ function createGeometryMeshes(geoms) {
|
|
|
30951
31236
|
}
|
|
30952
31237
|
|
|
30953
31238
|
// src/utils/manifold/create-three-texture-meshes.ts
|
|
30954
|
-
import * as
|
|
31239
|
+
import * as THREE27 from "three";
|
|
30955
31240
|
function createTextureMeshes(textures, boardData, pcbThickness) {
|
|
30956
31241
|
const meshes = [];
|
|
30957
31242
|
if (!textures || !boardData || pcbThickness === null) return meshes;
|
|
30958
31243
|
const createTexturePlane = (texture, yOffset, isBottomLayer, keySuffix) => {
|
|
30959
31244
|
if (!texture) return null;
|
|
30960
|
-
const planeGeom = new
|
|
30961
|
-
const material = new
|
|
31245
|
+
const planeGeom = new THREE27.PlaneGeometry(boardData.width, boardData.height);
|
|
31246
|
+
const material = new THREE27.MeshBasicMaterial({
|
|
30962
31247
|
map: texture,
|
|
30963
31248
|
transparent: true,
|
|
30964
|
-
side:
|
|
31249
|
+
side: THREE27.DoubleSide,
|
|
30965
31250
|
depthWrite: false
|
|
30966
31251
|
// Important for layers to avoid z-fighting issues with board itself
|
|
30967
31252
|
});
|
|
30968
|
-
const mesh = new
|
|
31253
|
+
const mesh = new THREE27.Mesh(planeGeom, material);
|
|
30969
31254
|
mesh.position.set(boardData.center.x, boardData.center.y, yOffset);
|
|
30970
31255
|
if (isBottomLayer) {
|
|
30971
31256
|
mesh.rotation.set(Math.PI, 0, 0);
|
|
@@ -31073,10 +31358,11 @@ var CadViewerManifold = ({
|
|
|
31073
31358
|
autoRotateDisabled,
|
|
31074
31359
|
clickToInteractEnabled,
|
|
31075
31360
|
onUserInteraction,
|
|
31076
|
-
children
|
|
31361
|
+
children,
|
|
31362
|
+
onCameraControllerReady
|
|
31077
31363
|
}) => {
|
|
31078
31364
|
const childrenCircuitJson = useConvertChildrenToCircuitJson(children);
|
|
31079
|
-
const circuitJson =
|
|
31365
|
+
const circuitJson = useMemo21(() => {
|
|
31080
31366
|
return circuitJsonProp ?? childrenCircuitJson;
|
|
31081
31367
|
}, [circuitJsonProp, childrenCircuitJson]);
|
|
31082
31368
|
const [manifoldJSModule, setManifoldJSModule] = useState15(null);
|
|
@@ -31151,27 +31437,27 @@ try {
|
|
|
31151
31437
|
isLoading: builderIsLoading,
|
|
31152
31438
|
boardData
|
|
31153
31439
|
} = useManifoldBoardBuilder(manifoldJSModule, circuitJson);
|
|
31154
|
-
const geometryMeshes =
|
|
31155
|
-
const textureMeshes =
|
|
31440
|
+
const geometryMeshes = useMemo21(() => createGeometryMeshes(geoms), [geoms]);
|
|
31441
|
+
const textureMeshes = useMemo21(
|
|
31156
31442
|
() => createTextureMeshes(textures, boardData, pcbThickness),
|
|
31157
31443
|
[textures, boardData, pcbThickness]
|
|
31158
31444
|
);
|
|
31159
|
-
const cadComponents =
|
|
31445
|
+
const cadComponents = useMemo21(
|
|
31160
31446
|
() => su13(circuitJson).cad_component.list(),
|
|
31161
31447
|
[circuitJson]
|
|
31162
31448
|
);
|
|
31163
|
-
const boardDimensions =
|
|
31449
|
+
const boardDimensions = useMemo21(() => {
|
|
31164
31450
|
if (!boardData) return void 0;
|
|
31165
31451
|
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
31166
31452
|
return { width: width10, height: height10 };
|
|
31167
31453
|
}, [boardData]);
|
|
31168
|
-
const boardCenter =
|
|
31454
|
+
const boardCenter = useMemo21(() => {
|
|
31169
31455
|
if (!boardData) return void 0;
|
|
31170
31456
|
const { center } = boardData;
|
|
31171
31457
|
if (!center) return void 0;
|
|
31172
31458
|
return { x: center.x, y: center.y };
|
|
31173
31459
|
}, [boardData]);
|
|
31174
|
-
const initialCameraPosition =
|
|
31460
|
+
const initialCameraPosition = useMemo21(() => {
|
|
31175
31461
|
if (!boardData) return [5, 5, 5];
|
|
31176
31462
|
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
31177
31463
|
const safeWidth = Math.max(width10, 1);
|
|
@@ -31228,6 +31514,7 @@ try {
|
|
|
31228
31514
|
boardDimensions,
|
|
31229
31515
|
boardCenter,
|
|
31230
31516
|
onUserInteraction,
|
|
31517
|
+
onCameraControllerReady,
|
|
31231
31518
|
children: [
|
|
31232
31519
|
/* @__PURE__ */ jsx16(
|
|
31233
31520
|
BoardMeshes,
|
|
@@ -31257,7 +31544,7 @@ try {
|
|
|
31257
31544
|
var CadViewerManifold_default = CadViewerManifold;
|
|
31258
31545
|
|
|
31259
31546
|
// src/hooks/useContextMenu.ts
|
|
31260
|
-
import { useState as useState16, useCallback as
|
|
31547
|
+
import { useState as useState16, useCallback as useCallback8, useRef as useRef8, useEffect as useEffect23 } from "react";
|
|
31261
31548
|
var useContextMenu = ({ containerRef }) => {
|
|
31262
31549
|
const [menuVisible, setMenuVisible] = useState16(false);
|
|
31263
31550
|
const [menuPos, setMenuPos] = useState16({
|
|
@@ -31274,7 +31561,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31274
31561
|
longPressTimeoutRef.current = null;
|
|
31275
31562
|
}
|
|
31276
31563
|
};
|
|
31277
|
-
const handleContextMenu =
|
|
31564
|
+
const handleContextMenu = useCallback8(
|
|
31278
31565
|
(e) => {
|
|
31279
31566
|
e.preventDefault();
|
|
31280
31567
|
const eventX = typeof e.clientX === "number" ? e.clientX : 0;
|
|
@@ -31300,7 +31587,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31300
31587
|
},
|
|
31301
31588
|
[setMenuPos, setMenuVisible]
|
|
31302
31589
|
);
|
|
31303
|
-
const handleTouchStart =
|
|
31590
|
+
const handleTouchStart = useCallback8(
|
|
31304
31591
|
(e) => {
|
|
31305
31592
|
if (e.touches.length === 1) {
|
|
31306
31593
|
const touch = e.touches[0];
|
|
@@ -31333,7 +31620,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31333
31620
|
},
|
|
31334
31621
|
[containerRef]
|
|
31335
31622
|
);
|
|
31336
|
-
const handleTouchMove =
|
|
31623
|
+
const handleTouchMove = useCallback8((e) => {
|
|
31337
31624
|
if (!interactionOriginPosRef.current || e.touches.length !== 1) {
|
|
31338
31625
|
return;
|
|
31339
31626
|
}
|
|
@@ -31351,7 +31638,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31351
31638
|
clearLongPressTimeout();
|
|
31352
31639
|
}
|
|
31353
31640
|
}, []);
|
|
31354
|
-
const handleTouchEnd =
|
|
31641
|
+
const handleTouchEnd = useCallback8(() => {
|
|
31355
31642
|
clearLongPressTimeout();
|
|
31356
31643
|
setTimeout(() => {
|
|
31357
31644
|
if (interactionOriginPosRef.current) {
|
|
@@ -31359,7 +31646,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31359
31646
|
}
|
|
31360
31647
|
}, 0);
|
|
31361
31648
|
}, []);
|
|
31362
|
-
const handleClickAway =
|
|
31649
|
+
const handleClickAway = useCallback8((e) => {
|
|
31363
31650
|
const target = e.target;
|
|
31364
31651
|
if (menuRef.current && !menuRef.current.contains(target)) {
|
|
31365
31652
|
setMenuVisible(false);
|
|
@@ -31399,10 +31686,10 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
31399
31686
|
};
|
|
31400
31687
|
|
|
31401
31688
|
// src/hooks/useGlobalDownloadGltf.ts
|
|
31402
|
-
import { useCallback as
|
|
31689
|
+
import { useCallback as useCallback9 } from "react";
|
|
31403
31690
|
import { GLTFExporter } from "three-stdlib";
|
|
31404
31691
|
var useGlobalDownloadGltf = () => {
|
|
31405
|
-
return
|
|
31692
|
+
return useCallback9(() => {
|
|
31406
31693
|
const root = window.__TSCIRCUIT_THREE_OBJECT;
|
|
31407
31694
|
if (!root) return;
|
|
31408
31695
|
const exporter = new GLTFExporter();
|
|
@@ -31427,6 +31714,9 @@ var useGlobalDownloadGltf = () => {
|
|
|
31427
31714
|
}, []);
|
|
31428
31715
|
};
|
|
31429
31716
|
|
|
31717
|
+
// src/components/ContextMenu.tsx
|
|
31718
|
+
import { useState as useState18, useCallback as useCallback10 } from "react";
|
|
31719
|
+
|
|
31430
31720
|
// src/components/AppearanceMenu.tsx
|
|
31431
31721
|
import { useState as useState17 } from "react";
|
|
31432
31722
|
import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
@@ -31603,14 +31893,258 @@ var AppearanceMenu = () => {
|
|
|
31603
31893
|
] });
|
|
31604
31894
|
};
|
|
31605
31895
|
|
|
31606
|
-
// src/
|
|
31896
|
+
// src/components/ContextMenu.tsx
|
|
31607
31897
|
import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
31898
|
+
var cameraOptions = [
|
|
31899
|
+
"Custom",
|
|
31900
|
+
"Top Centered",
|
|
31901
|
+
"Top Down",
|
|
31902
|
+
"Top Left Corner",
|
|
31903
|
+
"Top Right Corner",
|
|
31904
|
+
"Left Sideview",
|
|
31905
|
+
"Right Sideview",
|
|
31906
|
+
"Front"
|
|
31907
|
+
];
|
|
31908
|
+
var ContextMenu = ({
|
|
31909
|
+
menuRef,
|
|
31910
|
+
menuPos,
|
|
31911
|
+
engine,
|
|
31912
|
+
cameraPreset,
|
|
31913
|
+
autoRotate,
|
|
31914
|
+
onEngineSwitch,
|
|
31915
|
+
onCameraPresetSelect,
|
|
31916
|
+
onAutoRotateToggle,
|
|
31917
|
+
onDownloadGltf
|
|
31918
|
+
}) => {
|
|
31919
|
+
const [activeSubmenu, setActiveSubmenu] = useState18(null);
|
|
31920
|
+
const handleMenuItemHover = useCallback10(
|
|
31921
|
+
(event, hovered) => {
|
|
31922
|
+
event.currentTarget.style.background = hovered ? "#2d313a" : "transparent";
|
|
31923
|
+
},
|
|
31924
|
+
[]
|
|
31925
|
+
);
|
|
31926
|
+
return /* @__PURE__ */ jsxs9(
|
|
31927
|
+
"div",
|
|
31928
|
+
{
|
|
31929
|
+
ref: menuRef,
|
|
31930
|
+
style: {
|
|
31931
|
+
position: "fixed",
|
|
31932
|
+
top: menuPos.y,
|
|
31933
|
+
left: menuPos.x,
|
|
31934
|
+
background: "#23272f",
|
|
31935
|
+
color: "#f5f6fa",
|
|
31936
|
+
borderRadius: 6,
|
|
31937
|
+
boxShadow: "0 6px 24px 0 rgba(0,0,0,0.18)",
|
|
31938
|
+
zIndex: 1e3,
|
|
31939
|
+
minWidth: 200,
|
|
31940
|
+
border: "1px solid #353945",
|
|
31941
|
+
padding: 0,
|
|
31942
|
+
fontSize: 15,
|
|
31943
|
+
fontWeight: 500,
|
|
31944
|
+
transition: "opacity 0.1s"
|
|
31945
|
+
},
|
|
31946
|
+
children: [
|
|
31947
|
+
/* @__PURE__ */ jsxs9(
|
|
31948
|
+
"div",
|
|
31949
|
+
{
|
|
31950
|
+
style: {
|
|
31951
|
+
padding: "12px 18px",
|
|
31952
|
+
cursor: "pointer",
|
|
31953
|
+
display: "flex",
|
|
31954
|
+
alignItems: "center",
|
|
31955
|
+
gap: 10,
|
|
31956
|
+
color: "#f5f6fa",
|
|
31957
|
+
fontWeight: 500,
|
|
31958
|
+
borderRadius: 6,
|
|
31959
|
+
transition: "background 0.1s"
|
|
31960
|
+
},
|
|
31961
|
+
onClick: () => onEngineSwitch(engine === "jscad" ? "manifold" : "jscad"),
|
|
31962
|
+
onMouseOver: (event) => handleMenuItemHover(event, true),
|
|
31963
|
+
onMouseOut: (event) => handleMenuItemHover(event, false),
|
|
31964
|
+
children: [
|
|
31965
|
+
"Switch to ",
|
|
31966
|
+
engine === "jscad" ? "Manifold" : "JSCAD",
|
|
31967
|
+
" Engine",
|
|
31968
|
+
/* @__PURE__ */ jsx18(
|
|
31969
|
+
"span",
|
|
31970
|
+
{
|
|
31971
|
+
style: {
|
|
31972
|
+
fontSize: 12,
|
|
31973
|
+
marginLeft: "auto",
|
|
31974
|
+
opacity: 0.5,
|
|
31975
|
+
fontWeight: 400
|
|
31976
|
+
},
|
|
31977
|
+
children: engine === "jscad" ? "experimental" : "default"
|
|
31978
|
+
}
|
|
31979
|
+
)
|
|
31980
|
+
]
|
|
31981
|
+
}
|
|
31982
|
+
),
|
|
31983
|
+
/* @__PURE__ */ jsxs9(
|
|
31984
|
+
"div",
|
|
31985
|
+
{
|
|
31986
|
+
style: { position: "relative" },
|
|
31987
|
+
onMouseEnter: () => setActiveSubmenu("camera"),
|
|
31988
|
+
onMouseLeave: () => setActiveSubmenu(null),
|
|
31989
|
+
children: [
|
|
31990
|
+
/* @__PURE__ */ jsxs9(
|
|
31991
|
+
"div",
|
|
31992
|
+
{
|
|
31993
|
+
style: {
|
|
31994
|
+
padding: "10px 18px",
|
|
31995
|
+
cursor: "pointer",
|
|
31996
|
+
display: "flex",
|
|
31997
|
+
alignItems: "center",
|
|
31998
|
+
gap: 10,
|
|
31999
|
+
color: "#f5f6fa",
|
|
32000
|
+
fontWeight: 500,
|
|
32001
|
+
borderRadius: 6,
|
|
32002
|
+
transition: "background 0.1s",
|
|
32003
|
+
background: activeSubmenu === "camera" ? "#2d313a" : "transparent"
|
|
32004
|
+
},
|
|
32005
|
+
onClick: () => setActiveSubmenu(
|
|
32006
|
+
(current2) => current2 === "camera" ? null : "camera"
|
|
32007
|
+
),
|
|
32008
|
+
children: [
|
|
32009
|
+
"Camera Position",
|
|
32010
|
+
/* @__PURE__ */ jsx18("span", { style: { marginLeft: "auto", opacity: 0.75 }, children: cameraPreset }),
|
|
32011
|
+
/* @__PURE__ */ jsx18("span", { style: { marginLeft: 4, opacity: 0.5 }, children: "\u203A" })
|
|
32012
|
+
]
|
|
32013
|
+
}
|
|
32014
|
+
),
|
|
32015
|
+
activeSubmenu === "camera" && /* @__PURE__ */ jsx18(
|
|
32016
|
+
"div",
|
|
32017
|
+
{
|
|
32018
|
+
style: {
|
|
32019
|
+
position: "absolute",
|
|
32020
|
+
top: 0,
|
|
32021
|
+
left: "100%",
|
|
32022
|
+
marginLeft: -2,
|
|
32023
|
+
background: "#23272f",
|
|
32024
|
+
color: "#f5f6fa",
|
|
32025
|
+
borderRadius: 6,
|
|
32026
|
+
boxShadow: "0 6px 24px 0 rgba(0,0,0,0.18)",
|
|
32027
|
+
border: "1px solid #353945",
|
|
32028
|
+
minWidth: 200,
|
|
32029
|
+
padding: "6px 0",
|
|
32030
|
+
zIndex: 1001
|
|
32031
|
+
},
|
|
32032
|
+
children: cameraOptions.map((option) => /* @__PURE__ */ jsxs9(
|
|
32033
|
+
"div",
|
|
32034
|
+
{
|
|
32035
|
+
style: {
|
|
32036
|
+
padding: "10px 18px",
|
|
32037
|
+
cursor: "pointer",
|
|
32038
|
+
display: "flex",
|
|
32039
|
+
alignItems: "center",
|
|
32040
|
+
gap: 10,
|
|
32041
|
+
color: "#f5f6fa",
|
|
32042
|
+
fontWeight: 500,
|
|
32043
|
+
borderRadius: 6,
|
|
32044
|
+
transition: "background 0.1s"
|
|
32045
|
+
},
|
|
32046
|
+
onClick: () => onCameraPresetSelect(option),
|
|
32047
|
+
onMouseOver: (event) => handleMenuItemHover(event, true),
|
|
32048
|
+
onMouseOut: (event) => handleMenuItemHover(event, false),
|
|
32049
|
+
children: [
|
|
32050
|
+
/* @__PURE__ */ jsx18("span", { style: { width: 18 }, children: cameraPreset === option ? "\u2714" : "" }),
|
|
32051
|
+
option
|
|
32052
|
+
]
|
|
32053
|
+
},
|
|
32054
|
+
option
|
|
32055
|
+
))
|
|
32056
|
+
}
|
|
32057
|
+
)
|
|
32058
|
+
]
|
|
32059
|
+
}
|
|
32060
|
+
),
|
|
32061
|
+
/* @__PURE__ */ jsxs9(
|
|
32062
|
+
"div",
|
|
32063
|
+
{
|
|
32064
|
+
style: {
|
|
32065
|
+
padding: "12px 18px",
|
|
32066
|
+
cursor: "pointer",
|
|
32067
|
+
display: "flex",
|
|
32068
|
+
alignItems: "center",
|
|
32069
|
+
gap: 10,
|
|
32070
|
+
color: "#f5f6fa",
|
|
32071
|
+
fontWeight: 500,
|
|
32072
|
+
borderRadius: 6,
|
|
32073
|
+
transition: "background 0.1s"
|
|
32074
|
+
},
|
|
32075
|
+
onClick: onAutoRotateToggle,
|
|
32076
|
+
onMouseOver: (event) => handleMenuItemHover(event, true),
|
|
32077
|
+
onMouseOut: (event) => handleMenuItemHover(event, false),
|
|
32078
|
+
children: [
|
|
32079
|
+
/* @__PURE__ */ jsx18("span", { style: { marginRight: 8 }, children: autoRotate ? "\u2714" : "" }),
|
|
32080
|
+
"Auto rotate"
|
|
32081
|
+
]
|
|
32082
|
+
}
|
|
32083
|
+
),
|
|
32084
|
+
/* @__PURE__ */ jsx18(
|
|
32085
|
+
"div",
|
|
32086
|
+
{
|
|
32087
|
+
style: {
|
|
32088
|
+
padding: "12px 18px",
|
|
32089
|
+
cursor: "pointer",
|
|
32090
|
+
display: "flex",
|
|
32091
|
+
alignItems: "center",
|
|
32092
|
+
gap: 10,
|
|
32093
|
+
color: "#f5f6fa",
|
|
32094
|
+
fontWeight: 500,
|
|
32095
|
+
borderRadius: 6,
|
|
32096
|
+
transition: "background 0.1s"
|
|
32097
|
+
},
|
|
32098
|
+
onClick: onDownloadGltf,
|
|
32099
|
+
onMouseOver: (event) => handleMenuItemHover(event, true),
|
|
32100
|
+
onMouseOut: (event) => handleMenuItemHover(event, false),
|
|
32101
|
+
children: "Download GLTF"
|
|
32102
|
+
}
|
|
32103
|
+
),
|
|
32104
|
+
/* @__PURE__ */ jsx18(AppearanceMenu, {}),
|
|
32105
|
+
/* @__PURE__ */ jsx18(
|
|
32106
|
+
"div",
|
|
32107
|
+
{
|
|
32108
|
+
style: {
|
|
32109
|
+
display: "flex",
|
|
32110
|
+
justifyContent: "center",
|
|
32111
|
+
padding: "8px 0",
|
|
32112
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
32113
|
+
marginTop: "8px"
|
|
32114
|
+
},
|
|
32115
|
+
children: /* @__PURE__ */ jsxs9(
|
|
32116
|
+
"span",
|
|
32117
|
+
{
|
|
32118
|
+
style: {
|
|
32119
|
+
fontSize: 10,
|
|
32120
|
+
opacity: 0.6,
|
|
32121
|
+
fontWeight: 300,
|
|
32122
|
+
color: "#c0c0c0"
|
|
32123
|
+
},
|
|
32124
|
+
children: [
|
|
32125
|
+
"@tscircuit/3d-viewer@",
|
|
32126
|
+
package_default.version
|
|
32127
|
+
]
|
|
32128
|
+
}
|
|
32129
|
+
)
|
|
32130
|
+
}
|
|
32131
|
+
)
|
|
32132
|
+
]
|
|
32133
|
+
}
|
|
32134
|
+
);
|
|
32135
|
+
};
|
|
32136
|
+
|
|
32137
|
+
// src/CadViewer.tsx
|
|
32138
|
+
import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
31608
32139
|
var CadViewerInner = (props) => {
|
|
31609
|
-
const [engine, setEngine] =
|
|
32140
|
+
const [engine, setEngine] = useState19("manifold");
|
|
31610
32141
|
const containerRef = useRef9(null);
|
|
31611
|
-
const [autoRotate, setAutoRotate] =
|
|
31612
|
-
const [autoRotateUserToggled, setAutoRotateUserToggled] =
|
|
32142
|
+
const [autoRotate, setAutoRotate] = useState19(true);
|
|
32143
|
+
const [autoRotateUserToggled, setAutoRotateUserToggled] = useState19(false);
|
|
32144
|
+
const [cameraPreset, setCameraPreset] = useState19("Custom");
|
|
31613
32145
|
const { visibility, toggleLayer } = useLayerVisibility();
|
|
32146
|
+
const cameraControllerRef = useRef9(null);
|
|
32147
|
+
const externalCameraControllerReady = props.onCameraControllerReady;
|
|
31614
32148
|
const {
|
|
31615
32149
|
menuVisible,
|
|
31616
32150
|
menuPos,
|
|
@@ -31620,20 +32154,39 @@ var CadViewerInner = (props) => {
|
|
|
31620
32154
|
} = useContextMenu({ containerRef });
|
|
31621
32155
|
const autoRotateUserToggledRef = useRef9(autoRotateUserToggled);
|
|
31622
32156
|
autoRotateUserToggledRef.current = autoRotateUserToggled;
|
|
31623
|
-
const handleUserInteraction =
|
|
32157
|
+
const handleUserInteraction = useCallback11(() => {
|
|
31624
32158
|
if (!autoRotateUserToggledRef.current) {
|
|
31625
32159
|
setAutoRotate(false);
|
|
31626
32160
|
}
|
|
32161
|
+
setCameraPreset("Custom");
|
|
31627
32162
|
}, []);
|
|
31628
|
-
const toggleAutoRotate =
|
|
32163
|
+
const toggleAutoRotate = useCallback11(() => {
|
|
31629
32164
|
setAutoRotate((prev) => !prev);
|
|
31630
32165
|
setAutoRotateUserToggled(true);
|
|
31631
32166
|
}, []);
|
|
31632
32167
|
const downloadGltf = useGlobalDownloadGltf();
|
|
31633
|
-
const
|
|
31634
|
-
setEngine(newEngine);
|
|
32168
|
+
const closeMenu = useCallback11(() => {
|
|
31635
32169
|
setMenuVisible(false);
|
|
31636
|
-
};
|
|
32170
|
+
}, [setMenuVisible]);
|
|
32171
|
+
const handleCameraControllerReady = useCallback11(
|
|
32172
|
+
(controller) => {
|
|
32173
|
+
cameraControllerRef.current = controller;
|
|
32174
|
+
externalCameraControllerReady?.(controller);
|
|
32175
|
+
if (controller && cameraPreset !== "Custom") {
|
|
32176
|
+
controller.animateToPreset(cameraPreset);
|
|
32177
|
+
}
|
|
32178
|
+
},
|
|
32179
|
+
[cameraPreset, externalCameraControllerReady]
|
|
32180
|
+
);
|
|
32181
|
+
const handleCameraPresetSelect = useCallback11(
|
|
32182
|
+
(preset) => {
|
|
32183
|
+
setCameraPreset(preset);
|
|
32184
|
+
closeMenu();
|
|
32185
|
+
if (preset === "Custom") return;
|
|
32186
|
+
cameraControllerRef.current?.animateToPreset(preset);
|
|
32187
|
+
},
|
|
32188
|
+
[closeMenu]
|
|
32189
|
+
);
|
|
31637
32190
|
useEffect24(() => {
|
|
31638
32191
|
const stored = window.localStorage.getItem("cadViewerEngine");
|
|
31639
32192
|
if (stored === "jscad" || stored === "manifold") {
|
|
@@ -31644,7 +32197,7 @@ var CadViewerInner = (props) => {
|
|
|
31644
32197
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
31645
32198
|
}, [engine]);
|
|
31646
32199
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
31647
|
-
return /* @__PURE__ */
|
|
32200
|
+
return /* @__PURE__ */ jsxs10(
|
|
31648
32201
|
"div",
|
|
31649
32202
|
{
|
|
31650
32203
|
ref: containerRef,
|
|
@@ -31660,22 +32213,24 @@ var CadViewerInner = (props) => {
|
|
|
31660
32213
|
},
|
|
31661
32214
|
...contextMenuEventHandlers,
|
|
31662
32215
|
children: [
|
|
31663
|
-
engine === "jscad" ? /* @__PURE__ */
|
|
32216
|
+
engine === "jscad" ? /* @__PURE__ */ jsx19(
|
|
31664
32217
|
CadViewerJscad,
|
|
31665
32218
|
{
|
|
31666
32219
|
...props,
|
|
31667
32220
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
31668
|
-
onUserInteraction: handleUserInteraction
|
|
32221
|
+
onUserInteraction: handleUserInteraction,
|
|
32222
|
+
onCameraControllerReady: handleCameraControllerReady
|
|
31669
32223
|
}
|
|
31670
|
-
) : /* @__PURE__ */
|
|
32224
|
+
) : /* @__PURE__ */ jsx19(
|
|
31671
32225
|
CadViewerManifold_default,
|
|
31672
32226
|
{
|
|
31673
32227
|
...props,
|
|
31674
32228
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
31675
|
-
onUserInteraction: handleUserInteraction
|
|
32229
|
+
onUserInteraction: handleUserInteraction,
|
|
32230
|
+
onCameraControllerReady: handleCameraControllerReady
|
|
31676
32231
|
}
|
|
31677
32232
|
),
|
|
31678
|
-
/* @__PURE__ */
|
|
32233
|
+
/* @__PURE__ */ jsxs10(
|
|
31679
32234
|
"div",
|
|
31680
32235
|
{
|
|
31681
32236
|
style: {
|
|
@@ -31692,145 +32247,31 @@ var CadViewerInner = (props) => {
|
|
|
31692
32247
|
},
|
|
31693
32248
|
children: [
|
|
31694
32249
|
"Engine: ",
|
|
31695
|
-
/* @__PURE__ */
|
|
32250
|
+
/* @__PURE__ */ jsx19("b", { children: engine === "jscad" ? "JSCAD" : "Manifold" })
|
|
31696
32251
|
]
|
|
31697
32252
|
}
|
|
31698
32253
|
),
|
|
31699
|
-
menuVisible && /* @__PURE__ */
|
|
31700
|
-
|
|
32254
|
+
menuVisible && /* @__PURE__ */ jsx19(
|
|
32255
|
+
ContextMenu,
|
|
31701
32256
|
{
|
|
31702
|
-
|
|
31703
|
-
|
|
31704
|
-
|
|
31705
|
-
|
|
31706
|
-
|
|
31707
|
-
|
|
31708
|
-
|
|
31709
|
-
|
|
31710
|
-
boxShadow: "0 6px 24px 0 rgba(0,0,0,0.18)",
|
|
31711
|
-
zIndex: 1e3,
|
|
31712
|
-
minWidth: 200,
|
|
31713
|
-
border: "1px solid #353945",
|
|
31714
|
-
padding: 0,
|
|
31715
|
-
fontSize: 15,
|
|
31716
|
-
fontWeight: 500,
|
|
31717
|
-
transition: "opacity 0.1s"
|
|
32257
|
+
menuRef,
|
|
32258
|
+
menuPos,
|
|
32259
|
+
engine,
|
|
32260
|
+
cameraPreset,
|
|
32261
|
+
autoRotate,
|
|
32262
|
+
onEngineSwitch: (newEngine) => {
|
|
32263
|
+
setEngine(newEngine);
|
|
32264
|
+
closeMenu();
|
|
31718
32265
|
},
|
|
31719
|
-
|
|
31720
|
-
|
|
31721
|
-
|
|
31722
|
-
|
|
31723
|
-
|
|
31724
|
-
|
|
31725
|
-
|
|
31726
|
-
|
|
31727
|
-
|
|
31728
|
-
gap: 10,
|
|
31729
|
-
color: "#f5f6fa",
|
|
31730
|
-
fontWeight: 500,
|
|
31731
|
-
borderRadius: 6,
|
|
31732
|
-
transition: "background 0.1s"
|
|
31733
|
-
},
|
|
31734
|
-
onClick: () => handleMenuClick(engine === "jscad" ? "manifold" : "jscad"),
|
|
31735
|
-
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
31736
|
-
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
31737
|
-
children: [
|
|
31738
|
-
"Switch to ",
|
|
31739
|
-
engine === "jscad" ? "Manifold" : "JSCAD",
|
|
31740
|
-
" Engine",
|
|
31741
|
-
/* @__PURE__ */ jsx18(
|
|
31742
|
-
"span",
|
|
31743
|
-
{
|
|
31744
|
-
style: {
|
|
31745
|
-
fontSize: 12,
|
|
31746
|
-
marginLeft: "auto",
|
|
31747
|
-
opacity: 0.5,
|
|
31748
|
-
fontWeight: 400
|
|
31749
|
-
},
|
|
31750
|
-
children: engine === "jscad" ? "experimental" : "default"
|
|
31751
|
-
}
|
|
31752
|
-
)
|
|
31753
|
-
]
|
|
31754
|
-
}
|
|
31755
|
-
),
|
|
31756
|
-
/* @__PURE__ */ jsxs9(
|
|
31757
|
-
"div",
|
|
31758
|
-
{
|
|
31759
|
-
style: {
|
|
31760
|
-
padding: "12px 18px",
|
|
31761
|
-
cursor: "pointer",
|
|
31762
|
-
display: "flex",
|
|
31763
|
-
alignItems: "center",
|
|
31764
|
-
gap: 10,
|
|
31765
|
-
color: "#f5f6fa",
|
|
31766
|
-
fontWeight: 500,
|
|
31767
|
-
borderRadius: 6,
|
|
31768
|
-
transition: "background 0.1s"
|
|
31769
|
-
},
|
|
31770
|
-
onClick: () => {
|
|
31771
|
-
toggleAutoRotate();
|
|
31772
|
-
setMenuVisible(false);
|
|
31773
|
-
},
|
|
31774
|
-
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
31775
|
-
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
31776
|
-
children: [
|
|
31777
|
-
/* @__PURE__ */ jsx18("span", { style: { marginRight: 8 }, children: autoRotate ? "\u2714" : "" }),
|
|
31778
|
-
"Auto rotate"
|
|
31779
|
-
]
|
|
31780
|
-
}
|
|
31781
|
-
),
|
|
31782
|
-
/* @__PURE__ */ jsx18(
|
|
31783
|
-
"div",
|
|
31784
|
-
{
|
|
31785
|
-
style: {
|
|
31786
|
-
padding: "12px 18px",
|
|
31787
|
-
cursor: "pointer",
|
|
31788
|
-
display: "flex",
|
|
31789
|
-
alignItems: "center",
|
|
31790
|
-
gap: 10,
|
|
31791
|
-
color: "#f5f6fa",
|
|
31792
|
-
fontWeight: 500,
|
|
31793
|
-
borderRadius: 6,
|
|
31794
|
-
transition: "background 0.1s"
|
|
31795
|
-
},
|
|
31796
|
-
onClick: () => {
|
|
31797
|
-
downloadGltf();
|
|
31798
|
-
setMenuVisible(false);
|
|
31799
|
-
},
|
|
31800
|
-
onMouseOver: (e) => e.currentTarget.style.background = "#2d313a",
|
|
31801
|
-
onMouseOut: (e) => e.currentTarget.style.background = "transparent",
|
|
31802
|
-
children: "Download GLTF"
|
|
31803
|
-
}
|
|
31804
|
-
),
|
|
31805
|
-
/* @__PURE__ */ jsx18(AppearanceMenu, {}),
|
|
31806
|
-
/* @__PURE__ */ jsx18(
|
|
31807
|
-
"div",
|
|
31808
|
-
{
|
|
31809
|
-
style: {
|
|
31810
|
-
display: "flex",
|
|
31811
|
-
justifyContent: "center",
|
|
31812
|
-
padding: "8px 0",
|
|
31813
|
-
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
31814
|
-
marginTop: "8px"
|
|
31815
|
-
},
|
|
31816
|
-
children: /* @__PURE__ */ jsxs9(
|
|
31817
|
-
"span",
|
|
31818
|
-
{
|
|
31819
|
-
style: {
|
|
31820
|
-
fontSize: 10,
|
|
31821
|
-
opacity: 0.6,
|
|
31822
|
-
fontWeight: 300,
|
|
31823
|
-
color: "#c0c0c0"
|
|
31824
|
-
},
|
|
31825
|
-
children: [
|
|
31826
|
-
"@tscircuit/3d-viewer@",
|
|
31827
|
-
package_default.version
|
|
31828
|
-
]
|
|
31829
|
-
}
|
|
31830
|
-
)
|
|
31831
|
-
}
|
|
31832
|
-
)
|
|
31833
|
-
]
|
|
32266
|
+
onCameraPresetSelect: handleCameraPresetSelect,
|
|
32267
|
+
onAutoRotateToggle: () => {
|
|
32268
|
+
toggleAutoRotate();
|
|
32269
|
+
closeMenu();
|
|
32270
|
+
},
|
|
32271
|
+
onDownloadGltf: () => {
|
|
32272
|
+
downloadGltf();
|
|
32273
|
+
closeMenu();
|
|
32274
|
+
}
|
|
31834
32275
|
}
|
|
31835
32276
|
)
|
|
31836
32277
|
]
|
|
@@ -31839,17 +32280,17 @@ var CadViewerInner = (props) => {
|
|
|
31839
32280
|
);
|
|
31840
32281
|
};
|
|
31841
32282
|
var CadViewer = (props) => {
|
|
31842
|
-
return /* @__PURE__ */
|
|
32283
|
+
return /* @__PURE__ */ jsx19(LayerVisibilityProvider, { children: /* @__PURE__ */ jsx19(CadViewerInner, { ...props }) });
|
|
31843
32284
|
};
|
|
31844
32285
|
|
|
31845
32286
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
31846
32287
|
var import_debug = __toESM(require_browser(), 1);
|
|
31847
32288
|
import { su as su14 } from "@tscircuit/circuit-json-util";
|
|
31848
|
-
import * as
|
|
32289
|
+
import * as THREE31 from "three";
|
|
31849
32290
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
31850
32291
|
|
|
31851
32292
|
// src/utils/create-geometry-from-polygons.ts
|
|
31852
|
-
import * as
|
|
32293
|
+
import * as THREE28 from "three";
|
|
31853
32294
|
import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute2 } from "three";
|
|
31854
32295
|
function createGeometryFromPolygons(polygons) {
|
|
31855
32296
|
const geometry = new BufferGeometry3();
|
|
@@ -31863,12 +32304,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
31863
32304
|
...polygon3.vertices[i + 1]
|
|
31864
32305
|
// Third vertex
|
|
31865
32306
|
);
|
|
31866
|
-
const v1 = new
|
|
31867
|
-
const v2 = new
|
|
31868
|
-
const v3 = new
|
|
31869
|
-
const normal = new
|
|
31870
|
-
new
|
|
31871
|
-
new
|
|
32307
|
+
const v1 = new THREE28.Vector3(...polygon3.vertices[0]);
|
|
32308
|
+
const v2 = new THREE28.Vector3(...polygon3.vertices[i]);
|
|
32309
|
+
const v3 = new THREE28.Vector3(...polygon3.vertices[i + 1]);
|
|
32310
|
+
const normal = new THREE28.Vector3().crossVectors(
|
|
32311
|
+
new THREE28.Vector3().subVectors(v2, v1),
|
|
32312
|
+
new THREE28.Vector3().subVectors(v3, v1)
|
|
31872
32313
|
).normalize();
|
|
31873
32314
|
normals.push(
|
|
31874
32315
|
normal.x,
|
|
@@ -31892,10 +32333,10 @@ function createGeometryFromPolygons(polygons) {
|
|
|
31892
32333
|
var import_modeling2 = __toESM(require_src(), 1);
|
|
31893
32334
|
var import_jscad_planner2 = __toESM(require_dist(), 1);
|
|
31894
32335
|
var jscadModeling2 = __toESM(require_src(), 1);
|
|
31895
|
-
import * as
|
|
32336
|
+
import * as THREE30 from "three";
|
|
31896
32337
|
|
|
31897
32338
|
// src/utils/load-model.ts
|
|
31898
|
-
import * as
|
|
32339
|
+
import * as THREE29 from "three";
|
|
31899
32340
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
31900
32341
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
31901
32342
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -31903,12 +32344,12 @@ async function load3DModel(url) {
|
|
|
31903
32344
|
if (url.endsWith(".stl")) {
|
|
31904
32345
|
const loader = new STLLoader2();
|
|
31905
32346
|
const geometry = await loader.loadAsync(url);
|
|
31906
|
-
const material = new
|
|
32347
|
+
const material = new THREE29.MeshStandardMaterial({
|
|
31907
32348
|
color: 8947848,
|
|
31908
32349
|
metalness: 0.5,
|
|
31909
32350
|
roughness: 0.5
|
|
31910
32351
|
});
|
|
31911
|
-
return new
|
|
32352
|
+
return new THREE29.Mesh(geometry, material);
|
|
31912
32353
|
}
|
|
31913
32354
|
if (url.endsWith(".obj")) {
|
|
31914
32355
|
const loader = new OBJLoader2();
|
|
@@ -31941,9 +32382,9 @@ async function renderComponent(component, scene) {
|
|
|
31941
32382
|
}
|
|
31942
32383
|
if (component.rotation) {
|
|
31943
32384
|
model.rotation.set(
|
|
31944
|
-
|
|
31945
|
-
|
|
31946
|
-
|
|
32385
|
+
THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
32386
|
+
THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
32387
|
+
THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
31947
32388
|
);
|
|
31948
32389
|
}
|
|
31949
32390
|
scene.add(model);
|
|
@@ -31957,13 +32398,13 @@ async function renderComponent(component, scene) {
|
|
|
31957
32398
|
);
|
|
31958
32399
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
31959
32400
|
const threeGeom = convertCSGToThreeGeom(jscadObject);
|
|
31960
|
-
const material2 = new
|
|
32401
|
+
const material2 = new THREE30.MeshStandardMaterial({
|
|
31961
32402
|
color: 8947848,
|
|
31962
32403
|
metalness: 0.5,
|
|
31963
32404
|
roughness: 0.5,
|
|
31964
|
-
side:
|
|
32405
|
+
side: THREE30.DoubleSide
|
|
31965
32406
|
});
|
|
31966
|
-
const mesh2 = new
|
|
32407
|
+
const mesh2 = new THREE30.Mesh(threeGeom, material2);
|
|
31967
32408
|
if (component.position) {
|
|
31968
32409
|
mesh2.position.set(
|
|
31969
32410
|
component.position.x ?? 0,
|
|
@@ -31973,9 +32414,9 @@ async function renderComponent(component, scene) {
|
|
|
31973
32414
|
}
|
|
31974
32415
|
if (component.rotation) {
|
|
31975
32416
|
mesh2.rotation.set(
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
|
|
32417
|
+
THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
32418
|
+
THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
32419
|
+
THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
31979
32420
|
);
|
|
31980
32421
|
}
|
|
31981
32422
|
scene.add(mesh2);
|
|
@@ -31992,17 +32433,17 @@ async function renderComponent(component, scene) {
|
|
|
31992
32433
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
31993
32434
|
continue;
|
|
31994
32435
|
}
|
|
31995
|
-
const color = new
|
|
32436
|
+
const color = new THREE30.Color(geomInfo.color);
|
|
31996
32437
|
color.convertLinearToSRGB();
|
|
31997
32438
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
31998
32439
|
const threeGeom = convertCSGToThreeGeom(geomWithColor);
|
|
31999
|
-
const material2 = new
|
|
32440
|
+
const material2 = new THREE30.MeshStandardMaterial({
|
|
32000
32441
|
vertexColors: true,
|
|
32001
32442
|
metalness: 0.2,
|
|
32002
32443
|
roughness: 0.8,
|
|
32003
|
-
side:
|
|
32444
|
+
side: THREE30.DoubleSide
|
|
32004
32445
|
});
|
|
32005
|
-
const mesh2 = new
|
|
32446
|
+
const mesh2 = new THREE30.Mesh(threeGeom, material2);
|
|
32006
32447
|
if (component.position) {
|
|
32007
32448
|
mesh2.position.set(
|
|
32008
32449
|
component.position.x ?? 0,
|
|
@@ -32012,22 +32453,22 @@ async function renderComponent(component, scene) {
|
|
|
32012
32453
|
}
|
|
32013
32454
|
if (component.rotation) {
|
|
32014
32455
|
mesh2.rotation.set(
|
|
32015
|
-
|
|
32016
|
-
|
|
32017
|
-
|
|
32456
|
+
THREE30.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
32457
|
+
THREE30.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
32458
|
+
THREE30.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
32018
32459
|
);
|
|
32019
32460
|
}
|
|
32020
32461
|
scene.add(mesh2);
|
|
32021
32462
|
}
|
|
32022
32463
|
return;
|
|
32023
32464
|
}
|
|
32024
|
-
const geometry = new
|
|
32025
|
-
const material = new
|
|
32465
|
+
const geometry = new THREE30.BoxGeometry(0.5, 0.5, 0.5);
|
|
32466
|
+
const material = new THREE30.MeshStandardMaterial({
|
|
32026
32467
|
color: 16711680,
|
|
32027
32468
|
transparent: true,
|
|
32028
32469
|
opacity: 0.25
|
|
32029
32470
|
});
|
|
32030
|
-
const mesh = new
|
|
32471
|
+
const mesh = new THREE30.Mesh(geometry, material);
|
|
32031
32472
|
if (component.position) {
|
|
32032
32473
|
mesh.position.set(
|
|
32033
32474
|
component.position.x ?? 0,
|
|
@@ -32048,11 +32489,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
32048
32489
|
padding = 20,
|
|
32049
32490
|
zoom = 1.5
|
|
32050
32491
|
} = options;
|
|
32051
|
-
const scene = new
|
|
32492
|
+
const scene = new THREE31.Scene();
|
|
32052
32493
|
const renderer = new SVGRenderer();
|
|
32053
32494
|
renderer.setSize(width10, height10);
|
|
32054
|
-
renderer.setClearColor(new
|
|
32055
|
-
const camera = new
|
|
32495
|
+
renderer.setClearColor(new THREE31.Color(backgroundColor), 1);
|
|
32496
|
+
const camera = new THREE31.OrthographicCamera();
|
|
32056
32497
|
const aspect = width10 / height10;
|
|
32057
32498
|
const frustumSize = 100;
|
|
32058
32499
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -32066,11 +32507,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
32066
32507
|
camera.position.set(position.x, position.y, position.z);
|
|
32067
32508
|
camera.up.set(0, 1, 0);
|
|
32068
32509
|
const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
32069
|
-
camera.lookAt(new
|
|
32510
|
+
camera.lookAt(new THREE31.Vector3(lookAt.x, lookAt.y, lookAt.z));
|
|
32070
32511
|
camera.updateProjectionMatrix();
|
|
32071
|
-
const ambientLight = new
|
|
32512
|
+
const ambientLight = new THREE31.AmbientLight(16777215, Math.PI / 2);
|
|
32072
32513
|
scene.add(ambientLight);
|
|
32073
|
-
const pointLight = new
|
|
32514
|
+
const pointLight = new THREE31.PointLight(16777215, Math.PI / 4);
|
|
32074
32515
|
pointLight.position.set(-10, -10, 10);
|
|
32075
32516
|
scene.add(pointLight);
|
|
32076
32517
|
const components = su14(circuitJson).cad_component.list();
|
|
@@ -32084,7 +32525,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
32084
32525
|
const g = geom;
|
|
32085
32526
|
if (!g.polygons || g.polygons.length === 0) continue;
|
|
32086
32527
|
const geometry = createGeometryFromPolygons(g.polygons);
|
|
32087
|
-
const baseColor = new
|
|
32528
|
+
const baseColor = new THREE31.Color(
|
|
32088
32529
|
g.color?.[0] ?? 0,
|
|
32089
32530
|
g.color?.[1] ?? 0,
|
|
32090
32531
|
g.color?.[2] ?? 0
|
|
@@ -32092,18 +32533,18 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
32092
32533
|
const material = createBoardMaterial({
|
|
32093
32534
|
material: boardData?.material,
|
|
32094
32535
|
color: baseColor,
|
|
32095
|
-
side:
|
|
32536
|
+
side: THREE31.DoubleSide
|
|
32096
32537
|
});
|
|
32097
|
-
const mesh = new
|
|
32538
|
+
const mesh = new THREE31.Mesh(geometry, material);
|
|
32098
32539
|
scene.add(mesh);
|
|
32099
32540
|
}
|
|
32100
32541
|
}
|
|
32101
|
-
const gridHelper = new
|
|
32542
|
+
const gridHelper = new THREE31.GridHelper(100, 100);
|
|
32102
32543
|
gridHelper.rotation.x = Math.PI / 2;
|
|
32103
32544
|
scene.add(gridHelper);
|
|
32104
|
-
const box = new
|
|
32105
|
-
const center = box.getCenter(new
|
|
32106
|
-
const size2 = box.getSize(new
|
|
32545
|
+
const box = new THREE31.Box3().setFromObject(scene);
|
|
32546
|
+
const center = box.getCenter(new THREE31.Vector3());
|
|
32547
|
+
const size2 = box.getSize(new THREE31.Vector3());
|
|
32107
32548
|
scene.position.sub(center);
|
|
32108
32549
|
const maxDim = Math.max(size2.x, size2.y, size2.z);
|
|
32109
32550
|
if (maxDim > 0) {
|
|
@@ -32121,10 +32562,10 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
32121
32562
|
|
|
32122
32563
|
// src/hooks/exporter/gltf.ts
|
|
32123
32564
|
import { GLTFExporter as GLTFExporter2 } from "three-stdlib";
|
|
32124
|
-
import { useEffect as useEffect25, useState as
|
|
32565
|
+
import { useEffect as useEffect25, useState as useState20, useMemo as useMemo22, useCallback as useCallback12 } from "react";
|
|
32125
32566
|
function useSaveGltfAs(options = {}) {
|
|
32126
32567
|
const parse = useParser(options);
|
|
32127
|
-
const link =
|
|
32568
|
+
const link = useMemo22(() => document.createElement("a"), []);
|
|
32128
32569
|
const saveAs = async (filename) => {
|
|
32129
32570
|
const name = filename ?? options.filename ?? "";
|
|
32130
32571
|
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
@@ -32142,16 +32583,16 @@ function useSaveGltfAs(options = {}) {
|
|
|
32142
32583
|
[]
|
|
32143
32584
|
);
|
|
32144
32585
|
let instance;
|
|
32145
|
-
const ref =
|
|
32586
|
+
const ref = useCallback12((obj3D) => {
|
|
32146
32587
|
instance = obj3D;
|
|
32147
32588
|
}, []);
|
|
32148
32589
|
return [ref, saveAs];
|
|
32149
32590
|
}
|
|
32150
32591
|
function useExportGltfUrl(options = {}) {
|
|
32151
32592
|
const parse = useParser(options);
|
|
32152
|
-
const [url, setUrl] =
|
|
32153
|
-
const [error, setError] =
|
|
32154
|
-
const ref =
|
|
32593
|
+
const [url, setUrl] = useState20();
|
|
32594
|
+
const [error, setError] = useState20();
|
|
32595
|
+
const ref = useCallback12(
|
|
32155
32596
|
(instance) => parse(instance).then(setUrl).catch(setError),
|
|
32156
32597
|
[]
|
|
32157
32598
|
);
|
|
@@ -32159,7 +32600,7 @@ function useExportGltfUrl(options = {}) {
|
|
|
32159
32600
|
return [ref, url, error];
|
|
32160
32601
|
}
|
|
32161
32602
|
function useParser(options = {}) {
|
|
32162
|
-
const exporter =
|
|
32603
|
+
const exporter = useMemo22(() => new GLTFExporter2(), []);
|
|
32163
32604
|
return (instance) => {
|
|
32164
32605
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
32165
32606
|
exporter.parse(
|