@tscircuit/3d-viewer 0.0.623 → 0.0.625
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.d.ts +16 -5
- package/dist/index.js +691 -631
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -18979,8 +18979,8 @@ var useHiddenCadComponents = (circuitKey) => {
|
|
|
18979
18979
|
};
|
|
18980
18980
|
|
|
18981
18981
|
// src/CadViewer.tsx
|
|
18982
|
-
import { useCallback as useCallback25, useContext as useContext11, useEffect as
|
|
18983
|
-
import * as
|
|
18982
|
+
import { useCallback as useCallback25, useContext as useContext11, useEffect as useEffect51, useRef as useRef29, useState as useState42 } from "react";
|
|
18983
|
+
import * as THREE57 from "three";
|
|
18984
18984
|
|
|
18985
18985
|
// src/hooks/use-convert-children-to-soup.ts
|
|
18986
18986
|
import { Circuit } from "@tscircuit/core";
|
|
@@ -20945,13 +20945,13 @@ var AnyCadComponent = ({
|
|
|
20945
20945
|
};
|
|
20946
20946
|
|
|
20947
20947
|
// src/CadViewerContainer.tsx
|
|
20948
|
-
import { forwardRef as forwardRef2, useEffect as
|
|
20949
|
-
import * as
|
|
20948
|
+
import { forwardRef as forwardRef2, useEffect as useEffect22, useMemo as useMemo17, useState as useState13 } from "react";
|
|
20949
|
+
import * as THREE27 from "three";
|
|
20950
20950
|
|
|
20951
20951
|
// package.json
|
|
20952
20952
|
var package_default = {
|
|
20953
20953
|
name: "@tscircuit/3d-viewer",
|
|
20954
|
-
version: "0.0.
|
|
20954
|
+
version: "0.0.624",
|
|
20955
20955
|
repository: {
|
|
20956
20956
|
type: "git",
|
|
20957
20957
|
url: "https://github.com/tscircuit/3d-viewer"
|
|
@@ -21018,8 +21018,8 @@ var package_default = {
|
|
|
21018
21018
|
"@tscircuit/alphabet": "^0.0.25",
|
|
21019
21019
|
"@tscircuit/circuit-json-util": "^0.0.119",
|
|
21020
21020
|
"@tscircuit/copper-pour-solver": "^0.0.29",
|
|
21021
|
-
"@tscircuit/core": "^0.0.
|
|
21022
|
-
"@tscircuit/props": "^0.0.
|
|
21021
|
+
"@tscircuit/core": "^0.0.2152",
|
|
21022
|
+
"@tscircuit/props": "^0.0.701",
|
|
21023
21023
|
"@tscircuit/solver-utils": "^0.0.4",
|
|
21024
21024
|
"@types/debug": "^4.1.13",
|
|
21025
21025
|
"@types/jsdom": "^21.1.7",
|
|
@@ -21043,7 +21043,7 @@ var package_default = {
|
|
|
21043
21043
|
"vite-tsconfig-paths": "^4.3.2",
|
|
21044
21044
|
"circuit-json-to-gltf": "0.0.143",
|
|
21045
21045
|
zod: "^3.25.67",
|
|
21046
|
-
"@tscircuit/modelprinter": "^0.0.
|
|
21046
|
+
"@tscircuit/modelprinter": "^0.0.18"
|
|
21047
21047
|
},
|
|
21048
21048
|
engines: {
|
|
21049
21049
|
node: "24.x"
|
|
@@ -21105,44 +21105,79 @@ import {
|
|
|
21105
21105
|
useRef as useRef3,
|
|
21106
21106
|
useState as useState11
|
|
21107
21107
|
} from "react";
|
|
21108
|
+
import * as THREE16 from "three";
|
|
21109
|
+
|
|
21110
|
+
// src/utils/camera-session-storage.ts
|
|
21108
21111
|
import * as THREE15 from "three";
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21112
|
+
var CAMERA_SESSION_STORAGE_KEY = "cadViewerCameraStateSession";
|
|
21113
|
+
function getCameraSessionStorageKey(cameraSessionScope) {
|
|
21114
|
+
if (!cameraSessionScope) return CAMERA_SESSION_STORAGE_KEY;
|
|
21115
|
+
return `${CAMERA_SESSION_STORAGE_KEY}:${cameraSessionScope}`;
|
|
21116
|
+
}
|
|
21117
|
+
function saveCameraSession({
|
|
21118
|
+
camera,
|
|
21119
|
+
controls,
|
|
21120
|
+
cameraSessionScope
|
|
21121
|
+
}) {
|
|
21112
21122
|
try {
|
|
21113
|
-
const
|
|
21123
|
+
const storedCameraSession = {
|
|
21114
21124
|
position: camera.position.toArray(),
|
|
21115
21125
|
quaternion: camera.quaternion.toArray(),
|
|
21116
21126
|
up: camera.up.toArray(),
|
|
21117
|
-
fov: camera.fov
|
|
21127
|
+
fov: camera instanceof THREE15.PerspectiveCamera ? camera.fov : 50,
|
|
21118
21128
|
target: controls.target.toArray()
|
|
21119
21129
|
};
|
|
21120
|
-
sessionStorage.setItem(
|
|
21121
|
-
|
|
21122
|
-
|
|
21130
|
+
sessionStorage.setItem(
|
|
21131
|
+
getCameraSessionStorageKey(cameraSessionScope),
|
|
21132
|
+
JSON.stringify(storedCameraSession)
|
|
21133
|
+
);
|
|
21134
|
+
} catch (error) {
|
|
21135
|
+
console.warn("Failed to save camera:", error);
|
|
21123
21136
|
}
|
|
21124
|
-
}
|
|
21125
|
-
|
|
21137
|
+
}
|
|
21138
|
+
function loadCameraSession({
|
|
21139
|
+
camera,
|
|
21140
|
+
controls,
|
|
21141
|
+
cameraSessionScope
|
|
21142
|
+
}) {
|
|
21126
21143
|
try {
|
|
21127
|
-
const
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21132
|
-
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
|
|
21138
|
-
|
|
21144
|
+
const storedCameraSessionJson = sessionStorage.getItem(
|
|
21145
|
+
getCameraSessionStorageKey(cameraSessionScope)
|
|
21146
|
+
);
|
|
21147
|
+
if (!storedCameraSessionJson) return false;
|
|
21148
|
+
const storedCameraSession = JSON.parse(
|
|
21149
|
+
storedCameraSessionJson
|
|
21150
|
+
);
|
|
21151
|
+
camera.position.fromArray(storedCameraSession.position);
|
|
21152
|
+
camera.quaternion.fromArray(storedCameraSession.quaternion);
|
|
21153
|
+
camera.up.fromArray(storedCameraSession.up);
|
|
21154
|
+
if (camera instanceof THREE15.PerspectiveCamera) {
|
|
21155
|
+
camera.fov = storedCameraSession.fov;
|
|
21156
|
+
camera.updateProjectionMatrix();
|
|
21157
|
+
}
|
|
21158
|
+
controls.target.fromArray(storedCameraSession.target);
|
|
21139
21159
|
controls.update();
|
|
21140
21160
|
camera.updateMatrixWorld();
|
|
21141
21161
|
return true;
|
|
21142
|
-
} catch (
|
|
21143
|
-
console.warn("Failed to restore camera:",
|
|
21162
|
+
} catch (error) {
|
|
21163
|
+
console.warn("Failed to restore camera:", error);
|
|
21144
21164
|
return false;
|
|
21145
21165
|
}
|
|
21166
|
+
}
|
|
21167
|
+
|
|
21168
|
+
// src/contexts/CameraControllerContext.tsx
|
|
21169
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
21170
|
+
function resolveCameraSessionContext(cameraSessionContext) {
|
|
21171
|
+
if ("controls" in cameraSessionContext) return cameraSessionContext;
|
|
21172
|
+
return { controls: cameraSessionContext };
|
|
21173
|
+
}
|
|
21174
|
+
var saveCameraToSession = (camera, cameraSessionContext) => {
|
|
21175
|
+
const { controls, cameraSessionScope } = resolveCameraSessionContext(cameraSessionContext);
|
|
21176
|
+
saveCameraSession({ camera, controls, cameraSessionScope });
|
|
21177
|
+
};
|
|
21178
|
+
var loadCameraFromSession = (camera, cameraSessionContext) => {
|
|
21179
|
+
const { controls, cameraSessionScope } = resolveCameraSessionContext(cameraSessionContext);
|
|
21180
|
+
return loadCameraSession({ camera, controls, cameraSessionScope });
|
|
21146
21181
|
};
|
|
21147
21182
|
var CameraControllerContext = createContext6(void 0);
|
|
21148
21183
|
var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition, initialCameraType }) => {
|
|
@@ -21154,7 +21189,7 @@ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition
|
|
|
21154
21189
|
);
|
|
21155
21190
|
const [cameraPosition, setCameraPosition] = useState11(initialCameraPosition ?? null);
|
|
21156
21191
|
const [cameraRotation, setCameraRotation] = useState11(
|
|
21157
|
-
new
|
|
21192
|
+
new THREE16.Euler(0, 0, 0)
|
|
21158
21193
|
);
|
|
21159
21194
|
const baseDistance = useMemo11(() => {
|
|
21160
21195
|
const [x, y, z] = initialCameraPosition ?? [5, -5, 5];
|
|
@@ -21308,7 +21343,7 @@ var useCameraController = () => {
|
|
|
21308
21343
|
|
|
21309
21344
|
// src/hooks/cameraAnimation.ts
|
|
21310
21345
|
import { useCallback as useCallback5, useEffect as useEffect14, useRef as useRef4 } from "react";
|
|
21311
|
-
import * as
|
|
21346
|
+
import * as THREE17 from "three";
|
|
21312
21347
|
var easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
21313
21348
|
var CameraAnimatorWithContext = () => {
|
|
21314
21349
|
const {
|
|
@@ -21319,24 +21354,24 @@ var CameraAnimatorWithContext = () => {
|
|
|
21319
21354
|
getPresetConfig
|
|
21320
21355
|
} = useCameraController();
|
|
21321
21356
|
const animationRef = useRef4(null);
|
|
21322
|
-
const tempQuaternion = useRef4(new
|
|
21323
|
-
const tempTarget = useRef4(new
|
|
21324
|
-
const tempUp = useRef4(new
|
|
21325
|
-
const tempRoll = useRef4(new
|
|
21326
|
-
const tempRollTarget = useRef4(new
|
|
21327
|
-
const baseOrientationHelper = useRef4(new
|
|
21328
|
-
const orientationHelper = useRef4(new
|
|
21357
|
+
const tempQuaternion = useRef4(new THREE17.Quaternion());
|
|
21358
|
+
const tempTarget = useRef4(new THREE17.Vector3());
|
|
21359
|
+
const tempUp = useRef4(new THREE17.Vector3());
|
|
21360
|
+
const tempRoll = useRef4(new THREE17.Quaternion());
|
|
21361
|
+
const tempRollTarget = useRef4(new THREE17.Quaternion());
|
|
21362
|
+
const baseOrientationHelper = useRef4(new THREE17.Object3D());
|
|
21363
|
+
const orientationHelper = useRef4(new THREE17.Object3D());
|
|
21329
21364
|
const animateTo = useCallback5(
|
|
21330
21365
|
({ position, target, up, durationMs = 600 }) => {
|
|
21331
21366
|
if (!mainCameraRef.current) return;
|
|
21332
21367
|
const currentTarget = controlsRef.current?.target ?? defaultTarget;
|
|
21333
|
-
const toPosition = new
|
|
21368
|
+
const toPosition = new THREE17.Vector3(
|
|
21334
21369
|
position[0],
|
|
21335
21370
|
position[1],
|
|
21336
21371
|
position[2]
|
|
21337
21372
|
);
|
|
21338
|
-
const resolvedTarget = target ? new
|
|
21339
|
-
const resolvedUp = new
|
|
21373
|
+
const resolvedTarget = target ? new THREE17.Vector3(target[0], target[1], target[2]) : defaultTarget.clone();
|
|
21374
|
+
const resolvedUp = new THREE17.Vector3(...up ?? [0, 0, 1]).normalize();
|
|
21340
21375
|
const toOrientationHelper = orientationHelper.current;
|
|
21341
21376
|
toOrientationHelper.position.copy(toPosition);
|
|
21342
21377
|
toOrientationHelper.up.copy(resolvedUp);
|
|
@@ -21448,43 +21483,63 @@ var CameraAnimatorWithContext = () => {
|
|
|
21448
21483
|
};
|
|
21449
21484
|
|
|
21450
21485
|
// src/hooks/useCameraSession.ts
|
|
21451
|
-
import { useCallback as useCallback6, useRef as useRef5 } from "react";
|
|
21452
|
-
var
|
|
21486
|
+
import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef5 } from "react";
|
|
21487
|
+
var CAMERA_SESSION_NOT_RESTORED = /* @__PURE__ */ Symbol("camera-session-not-restored");
|
|
21488
|
+
var useCameraSession = ({
|
|
21489
|
+
cameraSessionScope
|
|
21490
|
+
} = {}) => {
|
|
21453
21491
|
const { controlsRef } = useCameraController();
|
|
21454
21492
|
const cameraRef = useRef5(null);
|
|
21455
|
-
const
|
|
21493
|
+
const restoredCameraSessionScopeRef = useRef5(CAMERA_SESSION_NOT_RESTORED);
|
|
21456
21494
|
const saveTimeoutRef = useRef5(null);
|
|
21495
|
+
useEffect15(() => {
|
|
21496
|
+
return () => {
|
|
21497
|
+
if (saveTimeoutRef.current !== null) {
|
|
21498
|
+
clearTimeout(saveTimeoutRef.current);
|
|
21499
|
+
saveTimeoutRef.current = null;
|
|
21500
|
+
}
|
|
21501
|
+
};
|
|
21502
|
+
}, [cameraSessionScope]);
|
|
21457
21503
|
const handleCameraCreated = useCallback6(
|
|
21458
21504
|
(camera) => {
|
|
21459
21505
|
cameraRef.current = camera;
|
|
21460
|
-
if (
|
|
21461
|
-
const restored = loadCameraFromSession(camera,
|
|
21506
|
+
if (restoredCameraSessionScopeRef.current !== cameraSessionScope && controlsRef.current) {
|
|
21507
|
+
const restored = loadCameraFromSession(camera, {
|
|
21508
|
+
controls: controlsRef.current,
|
|
21509
|
+
cameraSessionScope
|
|
21510
|
+
});
|
|
21511
|
+
restoredCameraSessionScopeRef.current = cameraSessionScope;
|
|
21462
21512
|
if (restored) {
|
|
21463
|
-
|
|
21513
|
+
return;
|
|
21464
21514
|
}
|
|
21465
21515
|
}
|
|
21466
21516
|
},
|
|
21467
|
-
[controlsRef]
|
|
21517
|
+
[cameraSessionScope, controlsRef]
|
|
21468
21518
|
);
|
|
21469
21519
|
const handleControlsChange = useCallback6(() => {
|
|
21470
21520
|
if (!cameraRef.current || !controlsRef.current) return;
|
|
21471
|
-
if (
|
|
21472
|
-
const restored = loadCameraFromSession(
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
);
|
|
21521
|
+
if (restoredCameraSessionScopeRef.current !== cameraSessionScope) {
|
|
21522
|
+
const restored = loadCameraFromSession(cameraRef.current, {
|
|
21523
|
+
controls: controlsRef.current,
|
|
21524
|
+
cameraSessionScope
|
|
21525
|
+
});
|
|
21526
|
+
restoredCameraSessionScopeRef.current = cameraSessionScope;
|
|
21476
21527
|
if (restored) {
|
|
21477
|
-
cameraRestoredRef.current = true;
|
|
21478
21528
|
return;
|
|
21479
21529
|
}
|
|
21480
21530
|
}
|
|
21481
|
-
|
|
21531
|
+
if (saveTimeoutRef.current !== null) {
|
|
21532
|
+
clearTimeout(saveTimeoutRef.current);
|
|
21533
|
+
}
|
|
21482
21534
|
saveTimeoutRef.current = setTimeout(() => {
|
|
21483
21535
|
if (cameraRef.current && controlsRef.current) {
|
|
21484
|
-
saveCameraToSession(cameraRef.current,
|
|
21536
|
+
saveCameraToSession(cameraRef.current, {
|
|
21537
|
+
controls: controlsRef.current,
|
|
21538
|
+
cameraSessionScope
|
|
21539
|
+
});
|
|
21485
21540
|
}
|
|
21486
21541
|
}, 150);
|
|
21487
|
-
}, [controlsRef]);
|
|
21542
|
+
}, [cameraSessionScope, controlsRef]);
|
|
21488
21543
|
return {
|
|
21489
21544
|
handleCameraCreated,
|
|
21490
21545
|
handleControlsChange
|
|
@@ -21494,14 +21549,14 @@ var useCameraSession = () => {
|
|
|
21494
21549
|
// src/react-three/Canvas.tsx
|
|
21495
21550
|
import {
|
|
21496
21551
|
useRef as useRef6,
|
|
21497
|
-
useEffect as
|
|
21552
|
+
useEffect as useEffect16,
|
|
21498
21553
|
useState as useState12,
|
|
21499
21554
|
useCallback as useCallback7,
|
|
21500
21555
|
forwardRef,
|
|
21501
21556
|
useImperativeHandle,
|
|
21502
21557
|
useMemo as useMemo12
|
|
21503
21558
|
} from "react";
|
|
21504
|
-
import * as
|
|
21559
|
+
import * as THREE19 from "three";
|
|
21505
21560
|
|
|
21506
21561
|
// src/react-three/remove-existing-canvases.ts
|
|
21507
21562
|
function removeExistingCanvases(container) {
|
|
@@ -21509,13 +21564,13 @@ function removeExistingCanvases(container) {
|
|
|
21509
21564
|
}
|
|
21510
21565
|
|
|
21511
21566
|
// src/react-three/configure-renderer.ts
|
|
21512
|
-
import * as
|
|
21567
|
+
import * as THREE18 from "three";
|
|
21513
21568
|
var configureRenderer = (renderer) => {
|
|
21514
|
-
renderer.outputColorSpace =
|
|
21515
|
-
renderer.toneMapping =
|
|
21569
|
+
renderer.outputColorSpace = THREE18.SRGBColorSpace;
|
|
21570
|
+
renderer.toneMapping = THREE18.ACESFilmicToneMapping;
|
|
21516
21571
|
renderer.toneMappingExposure = 1;
|
|
21517
21572
|
renderer.shadowMap.enabled = true;
|
|
21518
|
-
renderer.shadowMap.type =
|
|
21573
|
+
renderer.shadowMap.type = THREE18.PCFSoftShadowMap;
|
|
21519
21574
|
};
|
|
21520
21575
|
|
|
21521
21576
|
// src/react-three/Canvas.tsx
|
|
@@ -21547,16 +21602,16 @@ var Canvas = forwardRef(
|
|
|
21547
21602
|
},
|
|
21548
21603
|
[]
|
|
21549
21604
|
);
|
|
21550
|
-
const scene = useMemo12(() => new
|
|
21605
|
+
const scene = useMemo12(() => new THREE19.Scene(), []);
|
|
21551
21606
|
if (sceneProps?.up) {
|
|
21552
21607
|
scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
|
|
21553
21608
|
}
|
|
21554
|
-
const rootObject = useRef6(new
|
|
21609
|
+
const rootObject = useRef6(new THREE19.Object3D());
|
|
21555
21610
|
useImperativeHandle(ref, () => rootObject.current);
|
|
21556
|
-
|
|
21611
|
+
useEffect16(() => {
|
|
21557
21612
|
if (!mountRef.current) return;
|
|
21558
21613
|
removeExistingCanvases(mountRef.current);
|
|
21559
|
-
const renderer = new
|
|
21614
|
+
const renderer = new THREE19.WebGLRenderer({ antialias: true, alpha: true });
|
|
21560
21615
|
configureRenderer(renderer);
|
|
21561
21616
|
renderer.setSize(
|
|
21562
21617
|
mountRef.current.clientWidth,
|
|
@@ -21565,7 +21620,7 @@ var Canvas = forwardRef(
|
|
|
21565
21620
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
21566
21621
|
mountRef.current.appendChild(renderer.domElement);
|
|
21567
21622
|
const aspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
|
|
21568
|
-
const camera = cameraType === "perspective" ? new
|
|
21623
|
+
const camera = cameraType === "perspective" ? new THREE19.PerspectiveCamera(75, aspect, 0.1, 1e3) : new THREE19.OrthographicCamera(
|
|
21569
21624
|
-10 * aspect,
|
|
21570
21625
|
10 * aspect,
|
|
21571
21626
|
10,
|
|
@@ -21602,7 +21657,7 @@ var Canvas = forwardRef(
|
|
|
21602
21657
|
});
|
|
21603
21658
|
onCreatedRef.current?.({ camera, renderer });
|
|
21604
21659
|
let animationFrameId;
|
|
21605
|
-
const clock = new
|
|
21660
|
+
const clock = new THREE19.Clock();
|
|
21606
21661
|
let isVisible = true;
|
|
21607
21662
|
const visibilityObserver = new IntersectionObserver(([entry]) => {
|
|
21608
21663
|
isVisible = entry?.isIntersecting ?? false;
|
|
@@ -21621,9 +21676,9 @@ var Canvas = forwardRef(
|
|
|
21621
21676
|
const handleResize = () => {
|
|
21622
21677
|
if (mountRef.current?.clientWidth && mountRef.current.clientHeight) {
|
|
21623
21678
|
const newAspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
|
|
21624
|
-
if (camera instanceof
|
|
21679
|
+
if (camera instanceof THREE19.PerspectiveCamera) {
|
|
21625
21680
|
camera.aspect = newAspect;
|
|
21626
|
-
} else if (camera instanceof
|
|
21681
|
+
} else if (camera instanceof THREE19.OrthographicCamera) {
|
|
21627
21682
|
camera.left = -10 * newAspect;
|
|
21628
21683
|
camera.right = 10 * newAspect;
|
|
21629
21684
|
camera.top = 10;
|
|
@@ -21661,8 +21716,8 @@ var Canvas = forwardRef(
|
|
|
21661
21716
|
);
|
|
21662
21717
|
|
|
21663
21718
|
// src/react-three/Grid.tsx
|
|
21664
|
-
import { useEffect as
|
|
21665
|
-
import * as
|
|
21719
|
+
import { useEffect as useEffect17, useMemo as useMemo13 } from "react";
|
|
21720
|
+
import * as THREE20 from "three";
|
|
21666
21721
|
var vertexShader = `
|
|
21667
21722
|
varying vec3 worldPosition;
|
|
21668
21723
|
void main() {
|
|
@@ -21708,24 +21763,24 @@ var Grid = ({
|
|
|
21708
21763
|
const { scene, camera } = useThree();
|
|
21709
21764
|
const size4 = 1e3;
|
|
21710
21765
|
const gridMesh = useMemo13(() => {
|
|
21711
|
-
const geometry = new
|
|
21766
|
+
const geometry = new THREE20.PlaneGeometry(size4, size4);
|
|
21712
21767
|
geometry.rotateX(-Math.PI / 2);
|
|
21713
|
-
const material = new
|
|
21768
|
+
const material = new THREE20.ShaderMaterial({
|
|
21714
21769
|
vertexShader,
|
|
21715
21770
|
fragmentShader,
|
|
21716
21771
|
uniforms: {
|
|
21717
21772
|
cellSize: { value: cellSize },
|
|
21718
21773
|
sectionSize: { value: sectionSize },
|
|
21719
|
-
gridColor: { value: new
|
|
21720
|
-
sectionColor: { value: new
|
|
21774
|
+
gridColor: { value: new THREE20.Color(15658734) },
|
|
21775
|
+
sectionColor: { value: new THREE20.Color(13421823) },
|
|
21721
21776
|
fadeDistance: { value: 100 },
|
|
21722
21777
|
// Fade out based on sectionSize
|
|
21723
21778
|
fadeStrength: { value: 1.5 }
|
|
21724
21779
|
},
|
|
21725
21780
|
transparent: true,
|
|
21726
|
-
side:
|
|
21781
|
+
side: THREE20.DoubleSide
|
|
21727
21782
|
});
|
|
21728
|
-
const mesh = new
|
|
21783
|
+
const mesh = new THREE20.Mesh(geometry, material);
|
|
21729
21784
|
if (rotation) {
|
|
21730
21785
|
mesh.rotation.fromArray(rotation);
|
|
21731
21786
|
}
|
|
@@ -21736,7 +21791,7 @@ var Grid = ({
|
|
|
21736
21791
|
gridMesh.position.set(camera.position.x, camera.position.y, 0);
|
|
21737
21792
|
}
|
|
21738
21793
|
});
|
|
21739
|
-
|
|
21794
|
+
useEffect17(() => {
|
|
21740
21795
|
if (!scene || !gridMesh) return;
|
|
21741
21796
|
scene.add(gridMesh);
|
|
21742
21797
|
return () => {
|
|
@@ -21753,8 +21808,8 @@ var Grid = ({
|
|
|
21753
21808
|
};
|
|
21754
21809
|
|
|
21755
21810
|
// src/react-three/Lights.tsx
|
|
21756
|
-
import { useEffect as
|
|
21757
|
-
import * as
|
|
21811
|
+
import { useEffect as useEffect18, useMemo as useMemo14 } from "react";
|
|
21812
|
+
import * as THREE21 from "three";
|
|
21758
21813
|
var UNDERSIDE_LIGHT_FACTOR = 0.75;
|
|
21759
21814
|
var Lights = ({
|
|
21760
21815
|
boardDimensions,
|
|
@@ -21764,7 +21819,7 @@ var Lights = ({
|
|
|
21764
21819
|
}) => {
|
|
21765
21820
|
const { scene } = useThree();
|
|
21766
21821
|
const lightRig = useMemo14(() => {
|
|
21767
|
-
const rig = new
|
|
21822
|
+
const rig = new THREE21.Group();
|
|
21768
21823
|
rig.name = "cad-viewer-light-rig";
|
|
21769
21824
|
const centerX = boardCenter?.x ?? 0;
|
|
21770
21825
|
const centerY = boardCenter?.y ?? 0;
|
|
@@ -21776,14 +21831,14 @@ var Lights = ({
|
|
|
21776
21831
|
const shadowHalfSize = largestBoardDimension * 0.8;
|
|
21777
21832
|
const lightDistance = largestBoardDimension;
|
|
21778
21833
|
const keyLightDistance = largestBoardDimension * 1.7;
|
|
21779
|
-
const ambientLight = new
|
|
21834
|
+
const ambientLight = new THREE21.AmbientLight(16186360, 0.22);
|
|
21780
21835
|
ambientLight.name = "cad-viewer-soft-ambient";
|
|
21781
21836
|
rig.add(ambientLight);
|
|
21782
|
-
const hemisphereLight = new
|
|
21837
|
+
const hemisphereLight = new THREE21.HemisphereLight(15004141, 1581597, 0.2);
|
|
21783
21838
|
hemisphereLight.name = "cad-viewer-hemisphere";
|
|
21784
21839
|
rig.add(hemisphereLight);
|
|
21785
21840
|
const addDirectionalLight = (name, color, intensity, position, castShadow = false) => {
|
|
21786
|
-
const light = new
|
|
21841
|
+
const light = new THREE21.DirectionalLight(color, intensity);
|
|
21787
21842
|
light.name = name;
|
|
21788
21843
|
light.position.set(
|
|
21789
21844
|
centerX + position[0],
|
|
@@ -21857,17 +21912,17 @@ var Lights = ({
|
|
|
21857
21912
|
);
|
|
21858
21913
|
return rig;
|
|
21859
21914
|
}, [boardCenter, boardDimensions, shadowsEnabled]);
|
|
21860
|
-
|
|
21915
|
+
useEffect18(() => {
|
|
21861
21916
|
const previousBackground = scene.background;
|
|
21862
21917
|
const previousEnvironment = scene.environment;
|
|
21863
|
-
scene.background = darkBackgroundEnabled ? new
|
|
21918
|
+
scene.background = darkBackgroundEnabled ? new THREE21.Color(1053456) : null;
|
|
21864
21919
|
scene.environment = null;
|
|
21865
21920
|
return () => {
|
|
21866
21921
|
scene.background = previousBackground;
|
|
21867
21922
|
scene.environment = previousEnvironment;
|
|
21868
21923
|
};
|
|
21869
21924
|
}, [darkBackgroundEnabled, scene]);
|
|
21870
|
-
|
|
21925
|
+
useEffect18(() => {
|
|
21871
21926
|
if (!scene) return;
|
|
21872
21927
|
scene.add(lightRig);
|
|
21873
21928
|
return () => {
|
|
@@ -21878,12 +21933,12 @@ var Lights = ({
|
|
|
21878
21933
|
};
|
|
21879
21934
|
|
|
21880
21935
|
// src/react-three/OrbitControls.tsx
|
|
21881
|
-
import { useEffect as
|
|
21882
|
-
import * as
|
|
21936
|
+
import { useEffect as useEffect19, useMemo as useMemo15 } from "react";
|
|
21937
|
+
import * as THREE23 from "three";
|
|
21883
21938
|
import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
21884
21939
|
|
|
21885
21940
|
// src/react-three/infinite-dolly.ts
|
|
21886
|
-
import * as
|
|
21941
|
+
import * as THREE22 from "three";
|
|
21887
21942
|
var MINIMUM_DOLLY_DISTANCE_RATIO = 0.05;
|
|
21888
21943
|
var getMinimumDollyDistance = ({
|
|
21889
21944
|
camera,
|
|
@@ -21897,12 +21952,12 @@ var applyInfiniteDolly = ({
|
|
|
21897
21952
|
controls,
|
|
21898
21953
|
minimumDollyDistance
|
|
21899
21954
|
}) => {
|
|
21900
|
-
if (!(camera instanceof
|
|
21955
|
+
if (!(camera instanceof THREE22.PerspectiveCamera)) return false;
|
|
21901
21956
|
const orbitDistance = controls.getDistance();
|
|
21902
21957
|
if (Number.isFinite(orbitDistance) && orbitDistance >= minimumDollyDistance) {
|
|
21903
21958
|
return false;
|
|
21904
21959
|
}
|
|
21905
|
-
const viewDirection = new
|
|
21960
|
+
const viewDirection = new THREE22.Vector3();
|
|
21906
21961
|
camera.getWorldDirection(viewDirection);
|
|
21907
21962
|
controls.target.copy(camera.position).addScaledVector(viewDirection, minimumDollyDistance);
|
|
21908
21963
|
return true;
|
|
@@ -21927,7 +21982,7 @@ var OrbitControls = ({
|
|
|
21927
21982
|
return new ThreeOrbitControls(camera, renderer.domElement);
|
|
21928
21983
|
}, [camera, renderer]);
|
|
21929
21984
|
const minimumDollyDistance = useMemo15(() => {
|
|
21930
|
-
if (!controls || !(camera instanceof
|
|
21985
|
+
if (!controls || !(camera instanceof THREE23.PerspectiveCamera)) {
|
|
21931
21986
|
return Number.EPSILON;
|
|
21932
21987
|
}
|
|
21933
21988
|
const initialOrbitDistance = target ? Math.hypot(
|
|
@@ -21937,11 +21992,11 @@ var OrbitControls = ({
|
|
|
21937
21992
|
) : controls.getDistance();
|
|
21938
21993
|
return getMinimumDollyDistance({ camera, initialOrbitDistance });
|
|
21939
21994
|
}, [camera, controls, target]);
|
|
21940
|
-
|
|
21995
|
+
useEffect19(() => {
|
|
21941
21996
|
onControlsChange?.(controls ?? null);
|
|
21942
21997
|
return () => onControlsChange?.(null);
|
|
21943
21998
|
}, [controls, onControlsChange]);
|
|
21944
|
-
|
|
21999
|
+
useEffect19(() => {
|
|
21945
22000
|
if (!controls) return;
|
|
21946
22001
|
const handleChange = () => {
|
|
21947
22002
|
onControlsChange?.(controls);
|
|
@@ -21951,7 +22006,7 @@ var OrbitControls = ({
|
|
|
21951
22006
|
controls.removeEventListener("change", handleChange);
|
|
21952
22007
|
};
|
|
21953
22008
|
}, [controls, onControlsChange]);
|
|
21954
|
-
|
|
22009
|
+
useEffect19(() => {
|
|
21955
22010
|
if (!controls) return;
|
|
21956
22011
|
controls.autoRotate = autoRotate || false;
|
|
21957
22012
|
controls.autoRotateSpeed = autoRotateSpeed || 1;
|
|
@@ -21962,9 +22017,9 @@ var OrbitControls = ({
|
|
|
21962
22017
|
if (dampingFactor !== void 0) controls.dampingFactor = dampingFactor;
|
|
21963
22018
|
controls.zoomToCursor = true;
|
|
21964
22019
|
controls.mouseButtons = {
|
|
21965
|
-
LEFT:
|
|
22020
|
+
LEFT: THREE23.MOUSE.ROTATE,
|
|
21966
22021
|
// Left click to rotate
|
|
21967
|
-
MIDDLE:
|
|
22022
|
+
MIDDLE: THREE23.MOUSE.PAN,
|
|
21968
22023
|
// Middle click to pan
|
|
21969
22024
|
RIGHT: null
|
|
21970
22025
|
// Right-click always disabled - only context menu
|
|
@@ -21984,14 +22039,14 @@ var OrbitControls = ({
|
|
|
21984
22039
|
dampingFactor,
|
|
21985
22040
|
target
|
|
21986
22041
|
]);
|
|
21987
|
-
|
|
22042
|
+
useEffect19(() => {
|
|
21988
22043
|
if (!controls || !onStart) return;
|
|
21989
22044
|
controls.addEventListener("start", onStart);
|
|
21990
22045
|
return () => {
|
|
21991
22046
|
controls.removeEventListener("start", onStart);
|
|
21992
22047
|
};
|
|
21993
22048
|
}, [controls, onStart]);
|
|
21994
|
-
|
|
22049
|
+
useEffect19(() => {
|
|
21995
22050
|
if (!controls) return;
|
|
21996
22051
|
return () => {
|
|
21997
22052
|
controls.dispose();
|
|
@@ -22087,15 +22142,15 @@ var getComparisonBounds = (type, boardDimensions, boardCenter) => {
|
|
|
22087
22142
|
};
|
|
22088
22143
|
|
|
22089
22144
|
// src/three-components/OrientationCubeCanvas.tsx
|
|
22090
|
-
import { useEffect as
|
|
22091
|
-
import * as
|
|
22145
|
+
import { useEffect as useEffect20, useRef as useRef7 } from "react";
|
|
22146
|
+
import * as THREE24 from "three";
|
|
22092
22147
|
import { Text as TroikaText } from "troika-three-text";
|
|
22093
22148
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
22094
22149
|
function computePointInFront(rotationVector, distance5) {
|
|
22095
|
-
const quaternion = new
|
|
22096
|
-
new
|
|
22150
|
+
const quaternion = new THREE24.Quaternion().setFromEuler(
|
|
22151
|
+
new THREE24.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
|
|
22097
22152
|
);
|
|
22098
|
-
const forwardVector = new
|
|
22153
|
+
const forwardVector = new THREE24.Vector3(0, 0, 1);
|
|
22099
22154
|
forwardVector.applyQuaternion(quaternion);
|
|
22100
22155
|
const result = forwardVector.multiplyScalar(distance5);
|
|
22101
22156
|
return result;
|
|
@@ -22103,36 +22158,36 @@ function computePointInFront(rotationVector, distance5) {
|
|
|
22103
22158
|
var OrientationCubeCanvas = () => {
|
|
22104
22159
|
const { mainCameraRef } = useCameraController();
|
|
22105
22160
|
const containerRef = useRef7(null);
|
|
22106
|
-
|
|
22161
|
+
useEffect20(() => {
|
|
22107
22162
|
if (!containerRef.current) return;
|
|
22108
22163
|
const container = containerRef.current;
|
|
22109
22164
|
const canvas = document.createElement("canvas");
|
|
22110
22165
|
container.appendChild(canvas);
|
|
22111
|
-
const renderer = new
|
|
22166
|
+
const renderer = new THREE24.WebGLRenderer({
|
|
22112
22167
|
canvas,
|
|
22113
22168
|
antialias: true,
|
|
22114
22169
|
alpha: true
|
|
22115
22170
|
});
|
|
22116
22171
|
renderer.setSize(120, 120);
|
|
22117
22172
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
22118
|
-
const scene = new
|
|
22119
|
-
const camera = new
|
|
22173
|
+
const scene = new THREE24.Scene();
|
|
22174
|
+
const camera = new THREE24.PerspectiveCamera(75, 1, 0.1, 1e3);
|
|
22120
22175
|
camera.up.set(0, 0, 1);
|
|
22121
|
-
const ambientLight = new
|
|
22176
|
+
const ambientLight = new THREE24.AmbientLight(16777215, Math.PI / 2);
|
|
22122
22177
|
scene.add(ambientLight);
|
|
22123
|
-
const group = new
|
|
22178
|
+
const group = new THREE24.Group();
|
|
22124
22179
|
group.rotation.fromArray([Math.PI / 2, 0, 0]);
|
|
22125
22180
|
const cubeSize = 1;
|
|
22126
|
-
const box = new
|
|
22127
|
-
new
|
|
22128
|
-
new
|
|
22181
|
+
const box = new THREE24.Mesh(
|
|
22182
|
+
new THREE24.BoxGeometry(cubeSize, cubeSize, cubeSize),
|
|
22183
|
+
new THREE24.MeshStandardMaterial({ color: "white" })
|
|
22129
22184
|
);
|
|
22130
22185
|
group.add(box);
|
|
22131
|
-
const edges = new
|
|
22132
|
-
new
|
|
22133
|
-
new
|
|
22186
|
+
const edges = new THREE24.LineSegments(
|
|
22187
|
+
new THREE24.EdgesGeometry(
|
|
22188
|
+
new THREE24.BoxGeometry(cubeSize, cubeSize, cubeSize)
|
|
22134
22189
|
),
|
|
22135
|
-
new
|
|
22190
|
+
new THREE24.LineBasicMaterial({ color: 0, linewidth: 2 })
|
|
22136
22191
|
);
|
|
22137
22192
|
group.add(edges);
|
|
22138
22193
|
scene.add(group);
|
|
@@ -22194,7 +22249,7 @@ var OrientationCubeCanvas = () => {
|
|
|
22194
22249
|
if (!isVisible) return;
|
|
22195
22250
|
if (mainCameraRef.current) {
|
|
22196
22251
|
const cameraPosition = computePointInFront(
|
|
22197
|
-
mainCameraRef.current.rotation ?? new
|
|
22252
|
+
mainCameraRef.current.rotation ?? new THREE24.Euler(0, 0, 0),
|
|
22198
22253
|
2
|
|
22199
22254
|
);
|
|
22200
22255
|
if (!cameraPosition.equals(camera.position)) {
|
|
@@ -22243,15 +22298,15 @@ var OrientationCubeCanvas = () => {
|
|
|
22243
22298
|
};
|
|
22244
22299
|
|
|
22245
22300
|
// src/three-components/reference-object.tsx
|
|
22246
|
-
import { useEffect as
|
|
22301
|
+
import { useEffect as useEffect21, useMemo as useMemo16 } from "react";
|
|
22247
22302
|
|
|
22248
22303
|
// src/reference-objects/create-reference-object.ts
|
|
22249
|
-
import * as
|
|
22304
|
+
import * as THREE25 from "three";
|
|
22250
22305
|
var createRoundedRectangleShape = (width, height, radius) => {
|
|
22251
22306
|
const halfWidth = width / 2;
|
|
22252
22307
|
const halfHeight = height / 2;
|
|
22253
22308
|
const safeRadius = Math.min(radius, halfWidth, halfHeight);
|
|
22254
|
-
const shape = new
|
|
22309
|
+
const shape = new THREE25.Shape();
|
|
22255
22310
|
shape.moveTo(-halfWidth + safeRadius, -halfHeight);
|
|
22256
22311
|
shape.lineTo(halfWidth - safeRadius, -halfHeight);
|
|
22257
22312
|
shape.quadraticCurveTo(
|
|
@@ -22290,7 +22345,7 @@ var createRoundedPrismGeometry = (width, height, depth, radius) => {
|
|
|
22290
22345
|
);
|
|
22291
22346
|
};
|
|
22292
22347
|
var createPrismGeometryFromShape = (shape, depth) => {
|
|
22293
|
-
const geometry = new
|
|
22348
|
+
const geometry = new THREE25.ExtrudeGeometry(shape, {
|
|
22294
22349
|
depth,
|
|
22295
22350
|
bevelEnabled: false,
|
|
22296
22351
|
curveSegments: 24
|
|
@@ -22302,16 +22357,16 @@ var createPrismGeometryFromShape = (shape, depth) => {
|
|
|
22302
22357
|
var normalizeObjectToSpec = (object, type) => {
|
|
22303
22358
|
const spec = REFERENCE_OBJECT_SPECS[type];
|
|
22304
22359
|
object.updateMatrixWorld(true);
|
|
22305
|
-
const initialBounds = new
|
|
22306
|
-
const initialSize = initialBounds.getSize(new
|
|
22360
|
+
const initialBounds = new THREE25.Box3().setFromObject(object);
|
|
22361
|
+
const initialSize = initialBounds.getSize(new THREE25.Vector3());
|
|
22307
22362
|
object.scale.set(
|
|
22308
22363
|
spec.width / initialSize.x,
|
|
22309
22364
|
spec.height / initialSize.y,
|
|
22310
22365
|
spec.depth / initialSize.z
|
|
22311
22366
|
);
|
|
22312
22367
|
object.updateMatrixWorld(true);
|
|
22313
|
-
const scaledBounds = new
|
|
22314
|
-
const scaledCenter = scaledBounds.getCenter(new
|
|
22368
|
+
const scaledBounds = new THREE25.Box3().setFromObject(object);
|
|
22369
|
+
const scaledCenter = scaledBounds.getCenter(new THREE25.Vector3());
|
|
22315
22370
|
object.position.set(
|
|
22316
22371
|
-scaledCenter.x,
|
|
22317
22372
|
-scaledCenter.y,
|
|
@@ -22320,15 +22375,15 @@ var normalizeObjectToSpec = (object, type) => {
|
|
|
22320
22375
|
object.updateMatrixWorld(true);
|
|
22321
22376
|
};
|
|
22322
22377
|
var createBananaGeometry = () => {
|
|
22323
|
-
const curve = new
|
|
22324
|
-
new
|
|
22325
|
-
new
|
|
22326
|
-
new
|
|
22327
|
-
new
|
|
22328
|
-
new
|
|
22329
|
-
new
|
|
22330
|
-
new
|
|
22331
|
-
new
|
|
22378
|
+
const curve = new THREE25.CatmullRomCurve3([
|
|
22379
|
+
new THREE25.Vector3(-82, 18, 16),
|
|
22380
|
+
new THREE25.Vector3(-67, 7, 15),
|
|
22381
|
+
new THREE25.Vector3(-43, -9, 14),
|
|
22382
|
+
new THREE25.Vector3(-15, -18, 14),
|
|
22383
|
+
new THREE25.Vector3(16, -18, 14),
|
|
22384
|
+
new THREE25.Vector3(47, -8, 14.5),
|
|
22385
|
+
new THREE25.Vector3(72, 8, 16),
|
|
22386
|
+
new THREE25.Vector3(84, 19, 17)
|
|
22332
22387
|
]);
|
|
22333
22388
|
const tubularSegments = 84;
|
|
22334
22389
|
const radialSegments = 30;
|
|
@@ -22338,8 +22393,8 @@ var createBananaGeometry = () => {
|
|
|
22338
22393
|
const colors2 = [];
|
|
22339
22394
|
const uvs = [];
|
|
22340
22395
|
const indices = [];
|
|
22341
|
-
const ripeYellow = new
|
|
22342
|
-
const stemGreen = new
|
|
22396
|
+
const ripeYellow = new THREE25.Color(16766023);
|
|
22397
|
+
const stemGreen = new THREE25.Color(12038965);
|
|
22343
22398
|
for (let segment = 0; segment <= tubularSegments; segment++) {
|
|
22344
22399
|
const t = segment / tubularSegments;
|
|
22345
22400
|
const point = curve.getPointAt(t);
|
|
@@ -22354,7 +22409,7 @@ var createBananaGeometry = () => {
|
|
|
22354
22409
|
const sin = Math.sin(angle3);
|
|
22355
22410
|
const cos = Math.cos(angle3);
|
|
22356
22411
|
const ridgeScale = 1 + Math.cos(angle3 * 5 + 0.35) * 0.035;
|
|
22357
|
-
const radialNormal = new
|
|
22412
|
+
const radialNormal = new THREE25.Vector3().addScaledVector(normal, cos).addScaledVector(binormal, sin * 0.9).normalize();
|
|
22358
22413
|
const vertex = point.clone().addScaledVector(normal, cos * radius * ridgeScale).addScaledVector(binormal, sin * radius * 0.9 * ridgeScale);
|
|
22359
22414
|
positions.push(vertex.x, vertex.y, vertex.z);
|
|
22360
22415
|
normals.push(radialNormal.x, radialNormal.y, radialNormal.z);
|
|
@@ -22372,26 +22427,26 @@ var createBananaGeometry = () => {
|
|
|
22372
22427
|
indices.push(a, d, b, b, d, c);
|
|
22373
22428
|
}
|
|
22374
22429
|
}
|
|
22375
|
-
const geometry = new
|
|
22430
|
+
const geometry = new THREE25.BufferGeometry();
|
|
22376
22431
|
geometry.setIndex(indices);
|
|
22377
22432
|
geometry.setAttribute(
|
|
22378
22433
|
"position",
|
|
22379
|
-
new
|
|
22434
|
+
new THREE25.Float32BufferAttribute(positions, 3)
|
|
22380
22435
|
);
|
|
22381
|
-
geometry.setAttribute("normal", new
|
|
22382
|
-
geometry.setAttribute("color", new
|
|
22383
|
-
geometry.setAttribute("uv", new
|
|
22436
|
+
geometry.setAttribute("normal", new THREE25.Float32BufferAttribute(normals, 3));
|
|
22437
|
+
geometry.setAttribute("color", new THREE25.Float32BufferAttribute(colors2, 3));
|
|
22438
|
+
geometry.setAttribute("uv", new THREE25.Float32BufferAttribute(uvs, 2));
|
|
22384
22439
|
geometry.computeBoundingBox();
|
|
22385
22440
|
geometry.computeBoundingSphere();
|
|
22386
22441
|
return { geometry, curve };
|
|
22387
22442
|
};
|
|
22388
22443
|
var createBanana = () => {
|
|
22389
|
-
const group = new
|
|
22390
|
-
const banana = new
|
|
22444
|
+
const group = new THREE25.Group();
|
|
22445
|
+
const banana = new THREE25.Group();
|
|
22391
22446
|
const { geometry, curve } = createBananaGeometry();
|
|
22392
|
-
const peel = new
|
|
22447
|
+
const peel = new THREE25.Mesh(
|
|
22393
22448
|
geometry,
|
|
22394
|
-
new
|
|
22449
|
+
new THREE25.MeshStandardMaterial({
|
|
22395
22450
|
color: 16777215,
|
|
22396
22451
|
roughness: 0.72,
|
|
22397
22452
|
metalness: 0,
|
|
@@ -22400,9 +22455,9 @@ var createBanana = () => {
|
|
|
22400
22455
|
);
|
|
22401
22456
|
peel.name = "banana-peel";
|
|
22402
22457
|
banana.add(peel);
|
|
22403
|
-
const blossomTip = new
|
|
22404
|
-
new
|
|
22405
|
-
new
|
|
22458
|
+
const blossomTip = new THREE25.Mesh(
|
|
22459
|
+
new THREE25.SphereGeometry(3.4, 20, 12),
|
|
22460
|
+
new THREE25.MeshStandardMaterial({
|
|
22406
22461
|
color: 6242844,
|
|
22407
22462
|
roughness: 0.92
|
|
22408
22463
|
})
|
|
@@ -22413,20 +22468,20 @@ var createBanana = () => {
|
|
|
22413
22468
|
banana.add(blossomTip);
|
|
22414
22469
|
const stemLength = 11;
|
|
22415
22470
|
const stemTangent = curve.getTangentAt(1).normalize();
|
|
22416
|
-
const stem = new
|
|
22417
|
-
new
|
|
22418
|
-
new
|
|
22471
|
+
const stem = new THREE25.Mesh(
|
|
22472
|
+
new THREE25.CylinderGeometry(2.5, 4.1, stemLength, 18),
|
|
22473
|
+
new THREE25.MeshStandardMaterial({
|
|
22419
22474
|
color: 8483625,
|
|
22420
22475
|
roughness: 0.82
|
|
22421
22476
|
})
|
|
22422
22477
|
);
|
|
22423
|
-
stem.quaternion.setFromUnitVectors(new
|
|
22478
|
+
stem.quaternion.setFromUnitVectors(new THREE25.Vector3(0, 1, 0), stemTangent);
|
|
22424
22479
|
stem.position.copy(curve.getPointAt(1)).addScaledVector(stemTangent, stemLength / 2);
|
|
22425
22480
|
stem.name = "banana-stem";
|
|
22426
22481
|
banana.add(stem);
|
|
22427
|
-
const stemTip = new
|
|
22428
|
-
new
|
|
22429
|
-
new
|
|
22482
|
+
const stemTip = new THREE25.Mesh(
|
|
22483
|
+
new THREE25.SphereGeometry(2.55, 18, 10),
|
|
22484
|
+
new THREE25.MeshStandardMaterial({
|
|
22430
22485
|
color: 5981470,
|
|
22431
22486
|
roughness: 0.9
|
|
22432
22487
|
})
|
|
@@ -22440,7 +22495,7 @@ var createBanana = () => {
|
|
|
22440
22495
|
};
|
|
22441
22496
|
var createMacbookLidGeometry = (width, height, depth, radius, indentRadius) => {
|
|
22442
22497
|
const lidShape = createRoundedRectangleShape(width, height, radius);
|
|
22443
|
-
const indent = new
|
|
22498
|
+
const indent = new THREE25.Path();
|
|
22444
22499
|
indent.absarc(0, 0, indentRadius, 0, Math.PI * 2, true);
|
|
22445
22500
|
lidShape.holes.push(indent);
|
|
22446
22501
|
return createPrismGeometryFromShape(lidShape, depth);
|
|
@@ -22448,9 +22503,9 @@ var createMacbookLidGeometry = (width, height, depth, radius, indentRadius) => {
|
|
|
22448
22503
|
var createMacbookIndent = (topZ, radius) => {
|
|
22449
22504
|
const indentDepth = 0.35;
|
|
22450
22505
|
const diskDepth = 0.25;
|
|
22451
|
-
const disk = new
|
|
22452
|
-
new
|
|
22453
|
-
new
|
|
22506
|
+
const disk = new THREE25.Mesh(
|
|
22507
|
+
new THREE25.CylinderGeometry(radius - 0.15, radius - 0.15, diskDepth, 48),
|
|
22508
|
+
new THREE25.MeshStandardMaterial({
|
|
22454
22509
|
color: 10199202,
|
|
22455
22510
|
roughness: 0.48,
|
|
22456
22511
|
metalness: 0.28
|
|
@@ -22463,10 +22518,10 @@ var createMacbookIndent = (topZ, radius) => {
|
|
|
22463
22518
|
};
|
|
22464
22519
|
var createCreditCard = () => {
|
|
22465
22520
|
const spec = REFERENCE_OBJECT_SPECS["credit-card"];
|
|
22466
|
-
const group = new
|
|
22467
|
-
const body = new
|
|
22521
|
+
const group = new THREE25.Group();
|
|
22522
|
+
const body = new THREE25.Mesh(
|
|
22468
22523
|
createRoundedPrismGeometry(spec.width, spec.height, spec.depth, 3.18),
|
|
22469
|
-
new
|
|
22524
|
+
new THREE25.MeshStandardMaterial({
|
|
22470
22525
|
color: 2383272,
|
|
22471
22526
|
roughness: 0.38,
|
|
22472
22527
|
metalness: 0.08
|
|
@@ -22475,9 +22530,9 @@ var createCreditCard = () => {
|
|
|
22475
22530
|
body.name = "credit-card-body";
|
|
22476
22531
|
group.add(body);
|
|
22477
22532
|
const surfaceZ = spec.depth / 2 + 0.08;
|
|
22478
|
-
const chip = new
|
|
22533
|
+
const chip = new THREE25.Mesh(
|
|
22479
22534
|
createRoundedPrismGeometry(12, 9, 0.14, 1.2),
|
|
22480
|
-
new
|
|
22535
|
+
new THREE25.MeshStandardMaterial({
|
|
22481
22536
|
color: 14003525,
|
|
22482
22537
|
roughness: 0.3,
|
|
22483
22538
|
metalness: 0.62
|
|
@@ -22486,14 +22541,14 @@ var createCreditCard = () => {
|
|
|
22486
22541
|
chip.position.set(-21, 3, surfaceZ);
|
|
22487
22542
|
chip.name = "credit-card-chip";
|
|
22488
22543
|
group.add(chip);
|
|
22489
|
-
const stripeMaterial = new
|
|
22544
|
+
const stripeMaterial = new THREE25.MeshStandardMaterial({
|
|
22490
22545
|
color: 15331061,
|
|
22491
22546
|
roughness: 0.45,
|
|
22492
22547
|
metalness: 0.05
|
|
22493
22548
|
});
|
|
22494
22549
|
for (let index2 = 0; index2 < 4; index2++) {
|
|
22495
|
-
const stripe = new
|
|
22496
|
-
new
|
|
22550
|
+
const stripe = new THREE25.Mesh(
|
|
22551
|
+
new THREE25.BoxGeometry(index2 === 3 ? 8 : 12, 0.8, 0.1),
|
|
22497
22552
|
stripeMaterial
|
|
22498
22553
|
);
|
|
22499
22554
|
stripe.position.set(-20 + index2 * 14, -14, surfaceZ + 0.08);
|
|
@@ -22504,13 +22559,13 @@ var createCreditCard = () => {
|
|
|
22504
22559
|
};
|
|
22505
22560
|
var createMacbook = () => {
|
|
22506
22561
|
const spec = REFERENCE_OBJECT_SPECS["14in-macbook"];
|
|
22507
|
-
const group = new
|
|
22508
|
-
const aluminumMaterial = new
|
|
22562
|
+
const group = new THREE25.Group();
|
|
22563
|
+
const aluminumMaterial = new THREE25.MeshStandardMaterial({
|
|
22509
22564
|
color: 12896201,
|
|
22510
22565
|
roughness: 0.3,
|
|
22511
22566
|
metalness: 0.38
|
|
22512
22567
|
});
|
|
22513
|
-
const body = new
|
|
22568
|
+
const body = new THREE25.Mesh(
|
|
22514
22569
|
createRoundedPrismGeometry(spec.width, spec.height, 13.5, 9),
|
|
22515
22570
|
aluminumMaterial
|
|
22516
22571
|
);
|
|
@@ -22521,7 +22576,7 @@ var createMacbook = () => {
|
|
|
22521
22576
|
const lidCenterZ = 6.75;
|
|
22522
22577
|
const lidTopZ = lidCenterZ + lidDepth / 2;
|
|
22523
22578
|
const indentRadius = 12;
|
|
22524
|
-
const lid = new
|
|
22579
|
+
const lid = new THREE25.Mesh(
|
|
22525
22580
|
createMacbookLidGeometry(
|
|
22526
22581
|
spec.width - 1.8,
|
|
22527
22582
|
spec.height - 1.8,
|
|
@@ -22534,9 +22589,9 @@ var createMacbook = () => {
|
|
|
22534
22589
|
lid.position.z = lidCenterZ;
|
|
22535
22590
|
lid.name = "macbook-lid";
|
|
22536
22591
|
group.add(lid);
|
|
22537
|
-
const hinge = new
|
|
22538
|
-
new
|
|
22539
|
-
new
|
|
22592
|
+
const hinge = new THREE25.Mesh(
|
|
22593
|
+
new THREE25.BoxGeometry(spec.width - 42, 3.2, 1.2),
|
|
22594
|
+
new THREE25.MeshStandardMaterial({
|
|
22540
22595
|
color: 3158838,
|
|
22541
22596
|
roughness: 0.55,
|
|
22542
22597
|
metalness: 0.45
|
|
@@ -22546,9 +22601,9 @@ var createMacbook = () => {
|
|
|
22546
22601
|
hinge.name = "macbook-hinge";
|
|
22547
22602
|
group.add(hinge);
|
|
22548
22603
|
group.add(createMacbookIndent(lidTopZ, indentRadius));
|
|
22549
|
-
const frontNotch = new
|
|
22550
|
-
new
|
|
22551
|
-
new
|
|
22604
|
+
const frontNotch = new THREE25.Mesh(
|
|
22605
|
+
new THREE25.BoxGeometry(54, 1.2, 0.8),
|
|
22606
|
+
new THREE25.MeshStandardMaterial({
|
|
22552
22607
|
color: 6712174,
|
|
22553
22608
|
roughness: 0.45,
|
|
22554
22609
|
metalness: 0.5
|
|
@@ -22571,7 +22626,7 @@ var disposeReferenceObject = (object) => {
|
|
|
22571
22626
|
const geometries = /* @__PURE__ */ new Set();
|
|
22572
22627
|
const materials = /* @__PURE__ */ new Set();
|
|
22573
22628
|
object.traverse((child) => {
|
|
22574
|
-
if (!(child instanceof
|
|
22629
|
+
if (!(child instanceof THREE25.Mesh)) return;
|
|
22575
22630
|
geometries.add(child.geometry);
|
|
22576
22631
|
const childMaterials = Array.isArray(child.material) ? child.material : [child.material];
|
|
22577
22632
|
for (const material of childMaterials) materials.add(material);
|
|
@@ -22581,28 +22636,28 @@ var disposeReferenceObject = (object) => {
|
|
|
22581
22636
|
};
|
|
22582
22637
|
|
|
22583
22638
|
// src/reference-objects/fit-camera-to-bounds.ts
|
|
22584
|
-
import * as
|
|
22639
|
+
import * as THREE26 from "three";
|
|
22585
22640
|
var fitCameraToBounds = (camera, controls, bounds, padding = 1.18) => {
|
|
22586
22641
|
const width = Math.max(bounds.maxX - bounds.minX, 0);
|
|
22587
22642
|
const height = Math.max(bounds.maxY - bounds.minY, 0);
|
|
22588
22643
|
const depth = Math.max(bounds.maxZ - bounds.minZ, 0);
|
|
22589
|
-
const center = new
|
|
22644
|
+
const center = new THREE26.Vector3(
|
|
22590
22645
|
(bounds.minX + bounds.maxX) / 2,
|
|
22591
22646
|
(bounds.minY + bounds.maxY) / 2,
|
|
22592
22647
|
(bounds.minZ + bounds.maxZ) / 2
|
|
22593
22648
|
);
|
|
22594
22649
|
const radius = Math.max(Math.hypot(width, height, depth) / 2, 1);
|
|
22595
|
-
const previousTarget = controls?.target ?? new
|
|
22596
|
-
const direction = new
|
|
22650
|
+
const previousTarget = controls?.target ?? new THREE26.Vector3();
|
|
22651
|
+
const direction = new THREE26.Vector3(0, -0.75, 0.9).normalize();
|
|
22597
22652
|
let distance5 = Math.max(camera.position.distanceTo(previousTarget), 5);
|
|
22598
|
-
if (camera instanceof
|
|
22599
|
-
const verticalFov =
|
|
22653
|
+
if (camera instanceof THREE26.PerspectiveCamera) {
|
|
22654
|
+
const verticalFov = THREE26.MathUtils.degToRad(camera.fov);
|
|
22600
22655
|
const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
|
|
22601
22656
|
const limitingFov = Math.min(verticalFov, horizontalFov);
|
|
22602
22657
|
distance5 = radius * padding / Math.sin(limitingFov / 2);
|
|
22603
22658
|
camera.far = Math.max(camera.far, distance5 + radius * padding * 3);
|
|
22604
22659
|
camera.updateProjectionMatrix();
|
|
22605
|
-
} else if (camera instanceof
|
|
22660
|
+
} else if (camera instanceof THREE26.OrthographicCamera) {
|
|
22606
22661
|
const halfViewWidth = Math.abs(camera.right - camera.left) / 2;
|
|
22607
22662
|
const halfViewHeight = Math.abs(camera.top - camera.bottom) / 2;
|
|
22608
22663
|
camera.zoom = Math.min(
|
|
@@ -22639,7 +22694,7 @@ var ReferenceObject = ({
|
|
|
22639
22694
|
nextObject.position.set(position.x, position.y, position.z);
|
|
22640
22695
|
return nextObject;
|
|
22641
22696
|
}, [type, boardDimensions, boardCenter]);
|
|
22642
|
-
|
|
22697
|
+
useEffect21(() => {
|
|
22643
22698
|
scene.add(object);
|
|
22644
22699
|
return () => {
|
|
22645
22700
|
scene.remove(object);
|
|
@@ -22651,7 +22706,7 @@ var ReferenceObject = ({
|
|
|
22651
22706
|
var FitCameraToComparison = ({ bounds }) => {
|
|
22652
22707
|
const { camera } = useThree();
|
|
22653
22708
|
const { controlsRef } = useCameraController();
|
|
22654
|
-
|
|
22709
|
+
useEffect21(() => {
|
|
22655
22710
|
fitCameraToBounds(camera, controlsRef.current, bounds);
|
|
22656
22711
|
}, [bounds, camera, controlsRef]);
|
|
22657
22712
|
return null;
|
|
@@ -22677,6 +22732,7 @@ var CadViewerContainer = forwardRef2(
|
|
|
22677
22732
|
clickToInteractEnabled = false,
|
|
22678
22733
|
boardDimensions,
|
|
22679
22734
|
boardCenter,
|
|
22735
|
+
cameraSessionScope,
|
|
22680
22736
|
referenceObject,
|
|
22681
22737
|
onUserInteraction,
|
|
22682
22738
|
onCameraControllerReady
|
|
@@ -22689,8 +22745,8 @@ var CadViewerContainer = forwardRef2(
|
|
|
22689
22745
|
const {
|
|
22690
22746
|
handleCameraCreated,
|
|
22691
22747
|
handleControlsChange: handleSessionControlsChange
|
|
22692
|
-
} = useCameraSession();
|
|
22693
|
-
|
|
22748
|
+
} = useCameraSession({ cameraSessionScope });
|
|
22749
|
+
useEffect22(() => {
|
|
22694
22750
|
if (onCameraControllerReady) {
|
|
22695
22751
|
onCameraControllerReady(controller);
|
|
22696
22752
|
}
|
|
@@ -22722,7 +22778,7 @@ var CadViewerContainer = forwardRef2(
|
|
|
22722
22778
|
Canvas,
|
|
22723
22779
|
{
|
|
22724
22780
|
ref,
|
|
22725
|
-
scene: { up: new
|
|
22781
|
+
scene: { up: new THREE27.Vector3(0, 0, 1) },
|
|
22726
22782
|
camera: { up: [0, 0, 1], position: initialCameraPosition },
|
|
22727
22783
|
onCreated: ({ camera }) => {
|
|
22728
22784
|
mainCameraRef.current = camera;
|
|
@@ -22779,7 +22835,8 @@ var CadViewerContainer = forwardRef2(
|
|
|
22779
22835
|
),
|
|
22780
22836
|
children
|
|
22781
22837
|
]
|
|
22782
|
-
}
|
|
22838
|
+
},
|
|
22839
|
+
cameraSessionScope
|
|
22783
22840
|
),
|
|
22784
22841
|
/* @__PURE__ */ jsxs2(
|
|
22785
22842
|
"div",
|
|
@@ -22840,12 +22897,12 @@ var CadViewerContainer = forwardRef2(
|
|
|
22840
22897
|
);
|
|
22841
22898
|
|
|
22842
22899
|
// src/hooks/use-stls-from-geom.ts
|
|
22843
|
-
import { useState as useState14, useEffect as
|
|
22900
|
+
import { useState as useState14, useEffect as useEffect23 } from "react";
|
|
22844
22901
|
import stlSerializer from "@jscad/stl-serializer";
|
|
22845
22902
|
var useStlsFromGeom = (geom) => {
|
|
22846
22903
|
const [stls, setStls] = useState14([]);
|
|
22847
22904
|
const [loading, setLoading] = useState14(true);
|
|
22848
|
-
|
|
22905
|
+
useEffect23(() => {
|
|
22849
22906
|
if (!geom) return;
|
|
22850
22907
|
const generateStls = async () => {
|
|
22851
22908
|
setLoading(true);
|
|
@@ -22874,7 +22931,7 @@ var useStlsFromGeom = (geom) => {
|
|
|
22874
22931
|
};
|
|
22875
22932
|
|
|
22876
22933
|
// src/hooks/useBoardGeomBuilder.ts
|
|
22877
|
-
import { useState as useState15, useEffect as
|
|
22934
|
+
import { useState as useState15, useEffect as useEffect24, useRef as useRef8 } from "react";
|
|
22878
22935
|
|
|
22879
22936
|
// src/soup-to-3d/index.ts
|
|
22880
22937
|
var import_colors = __toESM(require_colors(), 1);
|
|
@@ -22913,7 +22970,7 @@ var createBoardGeomWithOutline = (board, depth = 1.2, options = {}) => {
|
|
|
22913
22970
|
};
|
|
22914
22971
|
|
|
22915
22972
|
// src/utils/get-board-edge-color.ts
|
|
22916
|
-
import * as
|
|
22973
|
+
import * as THREE29 from "three";
|
|
22917
22974
|
|
|
22918
22975
|
// src/geoms/constants.ts
|
|
22919
22976
|
var M = 0.01;
|
|
@@ -22946,7 +23003,7 @@ var soldermaskColors = {
|
|
|
22946
23003
|
};
|
|
22947
23004
|
|
|
22948
23005
|
// src/utils/soldermask-color.ts
|
|
22949
|
-
import * as
|
|
23006
|
+
import * as THREE28 from "three";
|
|
22950
23007
|
var SOLDERMASK_PRESET_HEX = {
|
|
22951
23008
|
red: "#650202",
|
|
22952
23009
|
blue: "#003f7d",
|
|
@@ -22977,9 +23034,9 @@ var resolveSoldermaskColor = (requestedColor) => {
|
|
|
22977
23034
|
}
|
|
22978
23035
|
const presetName = lowercaseColor;
|
|
22979
23036
|
const presetColor = SOLDERMASK_PRESET_HEX[presetName];
|
|
22980
|
-
if (presetColor) return new
|
|
22981
|
-
const isCssColor = Object.hasOwn(
|
|
22982
|
-
return isCssColor ? new
|
|
23037
|
+
if (presetColor) return new THREE28.Color(presetColor);
|
|
23038
|
+
const isCssColor = Object.hasOwn(THREE28.Color.NAMES, lowercaseColor) || CSS_HEX_COLOR_PATTERN.test(normalizedColor) || CSS_RGB_INTEGER_PATTERN.test(normalizedColor) || CSS_RGB_PERCENT_PATTERN.test(normalizedColor) || CSS_HSL_PATTERN.test(normalizedColor);
|
|
23039
|
+
return isCssColor ? new THREE28.Color(lowercaseColor) : null;
|
|
22983
23040
|
};
|
|
22984
23041
|
var resolveSoldermaskOpacity = (requestedColor) => {
|
|
22985
23042
|
const presetName = requestedColor?.trim().toLowerCase();
|
|
@@ -23006,7 +23063,7 @@ var soldermaskColorToCss = (color) => {
|
|
|
23006
23063
|
};
|
|
23007
23064
|
|
|
23008
23065
|
// src/utils/get-board-edge-color.ts
|
|
23009
|
-
var LEGACY_FR4_EDGE_COLOR = new
|
|
23066
|
+
var LEGACY_FR4_EDGE_COLOR = new THREE29.Color(1063462);
|
|
23010
23067
|
var getBoardEdgeColor = ({
|
|
23011
23068
|
material,
|
|
23012
23069
|
solder_mask_color
|
|
@@ -23015,7 +23072,7 @@ var getBoardEdgeColor = ({
|
|
|
23015
23072
|
if (soldermaskColor) return soldermaskColor;
|
|
23016
23073
|
if (material === "fr4") return LEGACY_FR4_EDGE_COLOR.clone();
|
|
23017
23074
|
const materialColor = boardMaterialColors[material] ?? colors.fr4Tan;
|
|
23018
|
-
return new
|
|
23075
|
+
return new THREE29.Color(materialColor[0], materialColor[1], materialColor[2]);
|
|
23019
23076
|
};
|
|
23020
23077
|
|
|
23021
23078
|
// src/soup-to-3d/index.ts
|
|
@@ -24363,7 +24420,7 @@ var BoardGeomBuilder = class {
|
|
|
24363
24420
|
var useBoardGeomBuilder = (circuitJson) => {
|
|
24364
24421
|
const [boardGeom, setBoardGeom] = useState15(null);
|
|
24365
24422
|
const isProcessingRef = useRef8(false);
|
|
24366
|
-
|
|
24423
|
+
useEffect24(() => {
|
|
24367
24424
|
let isCancelled = false;
|
|
24368
24425
|
if (!circuitJson) {
|
|
24369
24426
|
setBoardGeom(null);
|
|
@@ -24409,10 +24466,10 @@ var useBoardGeomBuilder = (circuitJson) => {
|
|
|
24409
24466
|
};
|
|
24410
24467
|
|
|
24411
24468
|
// src/three-components/Error3d.tsx
|
|
24412
|
-
import { useState as useState16, useCallback as useCallback8, useEffect as
|
|
24469
|
+
import { useState as useState16, useCallback as useCallback8, useEffect as useEffect26, useMemo as useMemo19 } from "react";
|
|
24413
24470
|
|
|
24414
24471
|
// src/react-three/Text.tsx
|
|
24415
|
-
import { useEffect as
|
|
24472
|
+
import { useEffect as useEffect25, useMemo as useMemo18 } from "react";
|
|
24416
24473
|
import { Text as TroikaText2 } from "troika-three-text";
|
|
24417
24474
|
var Text = ({
|
|
24418
24475
|
children,
|
|
@@ -24452,7 +24509,7 @@ var Text = ({
|
|
|
24452
24509
|
anchorY,
|
|
24453
24510
|
depthOffset
|
|
24454
24511
|
]);
|
|
24455
|
-
|
|
24512
|
+
useEffect25(() => {
|
|
24456
24513
|
const parentObject = parent || rootObject;
|
|
24457
24514
|
if (!parentObject || !mesh) return;
|
|
24458
24515
|
parentObject.add(mesh);
|
|
@@ -24465,7 +24522,7 @@ var Text = ({
|
|
|
24465
24522
|
};
|
|
24466
24523
|
|
|
24467
24524
|
// src/three-components/Error3d.tsx
|
|
24468
|
-
import * as
|
|
24525
|
+
import * as THREE30 from "three";
|
|
24469
24526
|
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
24470
24527
|
var Error3d = ({
|
|
24471
24528
|
error,
|
|
@@ -24499,13 +24556,13 @@ var Error3d = ({
|
|
|
24499
24556
|
return [0, 0, 0];
|
|
24500
24557
|
}, [cad_component]);
|
|
24501
24558
|
const group = useMemo19(() => {
|
|
24502
|
-
const g = new
|
|
24559
|
+
const g = new THREE30.Group();
|
|
24503
24560
|
g.position.fromArray(position);
|
|
24504
24561
|
return g;
|
|
24505
24562
|
}, [position]);
|
|
24506
24563
|
group.userData.cad_component_id = cad_component?.cad_component_id;
|
|
24507
24564
|
group.userData.pcb_component_id = cad_component?.pcb_component_id;
|
|
24508
|
-
|
|
24565
|
+
useEffect26(() => {
|
|
24509
24566
|
if (!rootObject) return;
|
|
24510
24567
|
rootObject.add(group);
|
|
24511
24568
|
return () => {
|
|
@@ -24561,9 +24618,9 @@ var Error3d = ({
|
|
|
24561
24618
|
};
|
|
24562
24619
|
var ErrorBox = ({ parent }) => {
|
|
24563
24620
|
const mesh = useMemo19(() => {
|
|
24564
|
-
const m = new
|
|
24565
|
-
new
|
|
24566
|
-
new
|
|
24621
|
+
const m = new THREE30.Mesh(
|
|
24622
|
+
new THREE30.BoxGeometry(0.5, 0.5, 0.5),
|
|
24623
|
+
new THREE30.MeshStandardMaterial({
|
|
24567
24624
|
depthTest: false,
|
|
24568
24625
|
transparent: true,
|
|
24569
24626
|
color: "red",
|
|
@@ -24574,7 +24631,7 @@ var ErrorBox = ({ parent }) => {
|
|
|
24574
24631
|
m.rotation.fromArray([Math.PI / 4, Math.PI / 4, 0]);
|
|
24575
24632
|
return m;
|
|
24576
24633
|
}, []);
|
|
24577
|
-
|
|
24634
|
+
useEffect26(() => {
|
|
24578
24635
|
parent.add(mesh);
|
|
24579
24636
|
return () => {
|
|
24580
24637
|
parent.remove(mesh);
|
|
@@ -24585,7 +24642,7 @@ var ErrorBox = ({ parent }) => {
|
|
|
24585
24642
|
|
|
24586
24643
|
// src/three-components/JscadBoardTextures.tsx
|
|
24587
24644
|
import { su as su9 } from "@tscircuit/circuit-json-util";
|
|
24588
|
-
import { useEffect as
|
|
24645
|
+
import { useEffect as useEffect27, useMemo as useMemo21 } from "react";
|
|
24589
24646
|
|
|
24590
24647
|
// src/textures/open-via-holes-at-pads.ts
|
|
24591
24648
|
import { CircuitToCanvasDrawer } from "circuit-to-canvas";
|
|
@@ -24740,12 +24797,12 @@ function clearViaHolesFromSurface({
|
|
|
24740
24797
|
}
|
|
24741
24798
|
|
|
24742
24799
|
// src/textures/create-combined-board-textures.ts
|
|
24743
|
-
import * as
|
|
24800
|
+
import * as THREE43 from "three";
|
|
24744
24801
|
|
|
24745
24802
|
// src/utils/pad-texture.ts
|
|
24746
24803
|
import { su as su6 } from "@tscircuit/circuit-json-util";
|
|
24747
24804
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer2 } from "circuit-to-canvas";
|
|
24748
|
-
import * as
|
|
24805
|
+
import * as THREE31 from "three";
|
|
24749
24806
|
function createPadTextureForLayer({
|
|
24750
24807
|
layer,
|
|
24751
24808
|
circuitJson,
|
|
@@ -24825,10 +24882,10 @@ function createPadTextureForLayer({
|
|
|
24825
24882
|
drawSoldermaskTop: false,
|
|
24826
24883
|
drawSoldermaskBottom: false
|
|
24827
24884
|
});
|
|
24828
|
-
const texture = new
|
|
24885
|
+
const texture = new THREE31.CanvasTexture(canvas);
|
|
24829
24886
|
texture.generateMipmaps = true;
|
|
24830
|
-
texture.minFilter =
|
|
24831
|
-
texture.magFilter =
|
|
24887
|
+
texture.minFilter = THREE31.LinearMipmapLinearFilter;
|
|
24888
|
+
texture.magFilter = THREE31.LinearFilter;
|
|
24832
24889
|
texture.anisotropy = 16;
|
|
24833
24890
|
texture.needsUpdate = true;
|
|
24834
24891
|
return texture;
|
|
@@ -24836,7 +24893,7 @@ function createPadTextureForLayer({
|
|
|
24836
24893
|
|
|
24837
24894
|
// src/utils/panel-outline-texture.ts
|
|
24838
24895
|
import { su as su7 } from "@tscircuit/circuit-json-util";
|
|
24839
|
-
import * as
|
|
24896
|
+
import * as THREE32 from "three";
|
|
24840
24897
|
var resolvePanelIdForTexture = (circuitJson) => {
|
|
24841
24898
|
const panels = circuitJson.filter(
|
|
24842
24899
|
(e) => e.type === "pcb_panel"
|
|
@@ -24904,17 +24961,17 @@ function createPanelOutlineTextureForLayer({
|
|
|
24904
24961
|
);
|
|
24905
24962
|
}
|
|
24906
24963
|
});
|
|
24907
|
-
const texture = new
|
|
24964
|
+
const texture = new THREE32.CanvasTexture(canvas);
|
|
24908
24965
|
texture.generateMipmaps = true;
|
|
24909
|
-
texture.minFilter =
|
|
24910
|
-
texture.magFilter =
|
|
24966
|
+
texture.minFilter = THREE32.LinearMipmapLinearFilter;
|
|
24967
|
+
texture.magFilter = THREE32.LinearFilter;
|
|
24911
24968
|
texture.anisotropy = 16;
|
|
24912
24969
|
texture.needsUpdate = true;
|
|
24913
24970
|
return texture;
|
|
24914
24971
|
}
|
|
24915
24972
|
|
|
24916
24973
|
// src/utils/trace-texture.ts
|
|
24917
|
-
import * as
|
|
24974
|
+
import * as THREE33 from "three";
|
|
24918
24975
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer3 } from "circuit-to-canvas";
|
|
24919
24976
|
import { getElementRenderLayers, su as su8 } from "@tscircuit/circuit-json-util";
|
|
24920
24977
|
function createTraceTextureForLayer({
|
|
@@ -25000,10 +25057,10 @@ function createTraceTextureForLayer({
|
|
|
25000
25057
|
drawSoldermaskTop: false,
|
|
25001
25058
|
drawSoldermaskBottom: false
|
|
25002
25059
|
});
|
|
25003
|
-
const texture = new
|
|
25060
|
+
const texture = new THREE33.CanvasTexture(canvas);
|
|
25004
25061
|
texture.generateMipmaps = true;
|
|
25005
|
-
texture.minFilter =
|
|
25006
|
-
texture.magFilter =
|
|
25062
|
+
texture.minFilter = THREE33.LinearMipmapLinearFilter;
|
|
25063
|
+
texture.magFilter = THREE33.LinearFilter;
|
|
25007
25064
|
texture.anisotropy = 16;
|
|
25008
25065
|
texture.needsUpdate = true;
|
|
25009
25066
|
return texture;
|
|
@@ -25011,7 +25068,7 @@ function createTraceTextureForLayer({
|
|
|
25011
25068
|
|
|
25012
25069
|
// src/textures/create-copper-pour-texture-for-layer.ts
|
|
25013
25070
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer4 } from "circuit-to-canvas";
|
|
25014
|
-
import * as
|
|
25071
|
+
import * as THREE34 from "three";
|
|
25015
25072
|
var toRgb = (colorArr) => {
|
|
25016
25073
|
const [r = 0, g = 0, b = 0] = colorArr;
|
|
25017
25074
|
return `rgb(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(
|
|
@@ -25135,17 +25192,17 @@ function createCopperPourTextureForLayer({
|
|
|
25135
25192
|
if (!onlyCoveredBySoldermask) {
|
|
25136
25193
|
setColorAndDraw(uncoveredPours, uncoveredColor);
|
|
25137
25194
|
}
|
|
25138
|
-
const texture = new
|
|
25195
|
+
const texture = new THREE34.CanvasTexture(canvas);
|
|
25139
25196
|
texture.generateMipmaps = true;
|
|
25140
|
-
texture.minFilter =
|
|
25141
|
-
texture.magFilter =
|
|
25197
|
+
texture.minFilter = THREE34.LinearMipmapLinearFilter;
|
|
25198
|
+
texture.magFilter = THREE34.LinearFilter;
|
|
25142
25199
|
texture.anisotropy = 16;
|
|
25143
25200
|
texture.needsUpdate = true;
|
|
25144
25201
|
return texture;
|
|
25145
25202
|
}
|
|
25146
25203
|
|
|
25147
25204
|
// src/textures/create-copper-text-texture-for-layer.ts
|
|
25148
|
-
import * as
|
|
25205
|
+
import * as THREE35 from "three";
|
|
25149
25206
|
|
|
25150
25207
|
// src/textures/copper-text/copper-text-drawing.ts
|
|
25151
25208
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer5 } from "circuit-to-canvas";
|
|
@@ -25260,17 +25317,17 @@ function createCopperTextTextureForLayer({
|
|
|
25260
25317
|
elements,
|
|
25261
25318
|
copperColor
|
|
25262
25319
|
});
|
|
25263
|
-
const texture = new
|
|
25320
|
+
const texture = new THREE35.CanvasTexture(canvas);
|
|
25264
25321
|
texture.generateMipmaps = true;
|
|
25265
|
-
texture.minFilter =
|
|
25266
|
-
texture.magFilter =
|
|
25322
|
+
texture.minFilter = THREE35.LinearMipmapLinearFilter;
|
|
25323
|
+
texture.magFilter = THREE35.LinearFilter;
|
|
25267
25324
|
texture.anisotropy = 16;
|
|
25268
25325
|
texture.needsUpdate = true;
|
|
25269
25326
|
return texture;
|
|
25270
25327
|
}
|
|
25271
25328
|
|
|
25272
25329
|
// src/textures/create-fabrication-note-texture-for-layer.ts
|
|
25273
|
-
import * as
|
|
25330
|
+
import * as THREE36 from "three";
|
|
25274
25331
|
|
|
25275
25332
|
// src/textures/fabrication-note/fabrication-note-drawing.ts
|
|
25276
25333
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer6 } from "circuit-to-canvas";
|
|
@@ -25500,17 +25557,17 @@ function createFabricationNoteTextureForLayer({
|
|
|
25500
25557
|
bounds,
|
|
25501
25558
|
elements
|
|
25502
25559
|
});
|
|
25503
|
-
const texture = new
|
|
25560
|
+
const texture = new THREE36.CanvasTexture(canvas);
|
|
25504
25561
|
texture.generateMipmaps = true;
|
|
25505
|
-
texture.minFilter =
|
|
25506
|
-
texture.magFilter =
|
|
25562
|
+
texture.minFilter = THREE36.LinearMipmapLinearFilter;
|
|
25563
|
+
texture.magFilter = THREE36.LinearFilter;
|
|
25507
25564
|
texture.anisotropy = 16;
|
|
25508
25565
|
texture.needsUpdate = true;
|
|
25509
25566
|
return texture;
|
|
25510
25567
|
}
|
|
25511
25568
|
|
|
25512
25569
|
// src/textures/create-keepout-texture-for-layer.ts
|
|
25513
|
-
import * as
|
|
25570
|
+
import * as THREE37 from "three";
|
|
25514
25571
|
|
|
25515
25572
|
// src/textures/keepout/keepout-drawing.ts
|
|
25516
25573
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer7 } from "circuit-to-canvas";
|
|
@@ -25585,17 +25642,17 @@ function createKeepoutTextureForLayer({
|
|
|
25585
25642
|
elements,
|
|
25586
25643
|
keepoutColor
|
|
25587
25644
|
});
|
|
25588
|
-
const texture = new
|
|
25645
|
+
const texture = new THREE37.CanvasTexture(canvas);
|
|
25589
25646
|
texture.generateMipmaps = true;
|
|
25590
|
-
texture.minFilter =
|
|
25591
|
-
texture.magFilter =
|
|
25647
|
+
texture.minFilter = THREE37.LinearMipmapLinearFilter;
|
|
25648
|
+
texture.magFilter = THREE37.LinearFilter;
|
|
25592
25649
|
texture.anisotropy = 16;
|
|
25593
25650
|
texture.needsUpdate = true;
|
|
25594
25651
|
return texture;
|
|
25595
25652
|
}
|
|
25596
25653
|
|
|
25597
25654
|
// src/textures/create-pcb-note-texture-for-layer.ts
|
|
25598
|
-
import * as
|
|
25655
|
+
import * as THREE38 from "three";
|
|
25599
25656
|
|
|
25600
25657
|
// src/textures/pcb-note/pcb-note-drawing.ts
|
|
25601
25658
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer8 } from "circuit-to-canvas";
|
|
@@ -25749,17 +25806,17 @@ function createPcbNoteTextureForLayer({
|
|
|
25749
25806
|
bounds,
|
|
25750
25807
|
elements
|
|
25751
25808
|
});
|
|
25752
|
-
const texture = new
|
|
25809
|
+
const texture = new THREE38.CanvasTexture(canvas);
|
|
25753
25810
|
texture.generateMipmaps = true;
|
|
25754
|
-
texture.minFilter =
|
|
25755
|
-
texture.magFilter =
|
|
25811
|
+
texture.minFilter = THREE38.LinearMipmapLinearFilter;
|
|
25812
|
+
texture.magFilter = THREE38.LinearFilter;
|
|
25756
25813
|
texture.anisotropy = 16;
|
|
25757
25814
|
texture.needsUpdate = true;
|
|
25758
25815
|
return texture;
|
|
25759
25816
|
}
|
|
25760
25817
|
|
|
25761
25818
|
// src/textures/create-silkscreen-texture-for-layer.ts
|
|
25762
|
-
import * as
|
|
25819
|
+
import * as THREE39 from "three";
|
|
25763
25820
|
|
|
25764
25821
|
// src/textures/silkscreen/silkscreen-drawing.ts
|
|
25765
25822
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer9 } from "circuit-to-canvas";
|
|
@@ -25910,21 +25967,21 @@ function createSilkscreenTextureForLayer({
|
|
|
25910
25967
|
silkscreenColor,
|
|
25911
25968
|
soldermaskVisible
|
|
25912
25969
|
});
|
|
25913
|
-
const texture = new
|
|
25970
|
+
const texture = new THREE39.CanvasTexture(canvas);
|
|
25914
25971
|
texture.generateMipmaps = true;
|
|
25915
|
-
texture.minFilter =
|
|
25916
|
-
texture.magFilter =
|
|
25972
|
+
texture.minFilter = THREE39.LinearMipmapLinearFilter;
|
|
25973
|
+
texture.magFilter = THREE39.LinearFilter;
|
|
25917
25974
|
texture.anisotropy = 16;
|
|
25918
25975
|
texture.needsUpdate = true;
|
|
25919
25976
|
return texture;
|
|
25920
25977
|
}
|
|
25921
25978
|
|
|
25922
25979
|
// src/textures/create-soldermask-texture-for-layer.ts
|
|
25923
|
-
import * as
|
|
25980
|
+
import * as THREE41 from "three";
|
|
25924
25981
|
|
|
25925
25982
|
// src/textures/soldermask/soldermask-drawing.ts
|
|
25926
25983
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer10 } from "circuit-to-canvas";
|
|
25927
|
-
import * as
|
|
25984
|
+
import * as THREE40 from "three";
|
|
25928
25985
|
var toRgb2 = (colorArr) => {
|
|
25929
25986
|
const [r = 0, g = 0, b = 0] = colorArr;
|
|
25930
25987
|
return `rgb(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(
|
|
@@ -25947,11 +26004,11 @@ var getSoldermaskPalette = (boardData) => {
|
|
|
25947
26004
|
transparent: "rgba(0,0,0,0)"
|
|
25948
26005
|
};
|
|
25949
26006
|
}
|
|
25950
|
-
const copperColor = new
|
|
26007
|
+
const copperColor = new THREE40.Color().setRGB(
|
|
25951
26008
|
colors.copper[0],
|
|
25952
26009
|
colors.copper[1],
|
|
25953
26010
|
colors.copper[2],
|
|
25954
|
-
|
|
26011
|
+
THREE40.SRGBColorSpace
|
|
25955
26012
|
);
|
|
25956
26013
|
return {
|
|
25957
26014
|
soldermask: soldermaskColorToCss(requestedSoldermaskColor),
|
|
@@ -26086,17 +26143,17 @@ function createSoldermaskTextureForLayer({
|
|
|
26086
26143
|
elements,
|
|
26087
26144
|
boardData
|
|
26088
26145
|
});
|
|
26089
|
-
const texture = new
|
|
26146
|
+
const texture = new THREE41.CanvasTexture(canvas);
|
|
26090
26147
|
texture.generateMipmaps = true;
|
|
26091
|
-
texture.minFilter =
|
|
26092
|
-
texture.magFilter =
|
|
26148
|
+
texture.minFilter = THREE41.LinearMipmapLinearFilter;
|
|
26149
|
+
texture.magFilter = THREE41.LinearFilter;
|
|
26093
26150
|
texture.anisotropy = 16;
|
|
26094
26151
|
texture.needsUpdate = true;
|
|
26095
26152
|
return texture;
|
|
26096
26153
|
}
|
|
26097
26154
|
|
|
26098
26155
|
// src/textures/create-through-hole-texture-for-layer.ts
|
|
26099
|
-
import * as
|
|
26156
|
+
import * as THREE42 from "three";
|
|
26100
26157
|
|
|
26101
26158
|
// src/textures/through-hole/through-hole-drawing.ts
|
|
26102
26159
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer11 } from "circuit-to-canvas";
|
|
@@ -26191,10 +26248,10 @@ function createThroughHoleTextureForLayer({
|
|
|
26191
26248
|
elements,
|
|
26192
26249
|
copperColor
|
|
26193
26250
|
});
|
|
26194
|
-
const texture = new
|
|
26251
|
+
const texture = new THREE42.CanvasTexture(canvas);
|
|
26195
26252
|
texture.generateMipmaps = true;
|
|
26196
|
-
texture.minFilter =
|
|
26197
|
-
texture.magFilter =
|
|
26253
|
+
texture.minFilter = THREE42.LinearMipmapLinearFilter;
|
|
26254
|
+
texture.magFilter = THREE42.LinearFilter;
|
|
26198
26255
|
texture.anisotropy = 16;
|
|
26199
26256
|
texture.needsUpdate = true;
|
|
26200
26257
|
return texture;
|
|
@@ -26291,10 +26348,10 @@ var createCombinedTexture = ({
|
|
|
26291
26348
|
applySoldermaskSurfaceFilter(ctx, canvasWidth, canvasHeight, {
|
|
26292
26349
|
includeReflection: layer === "top"
|
|
26293
26350
|
});
|
|
26294
|
-
const combinedTexture = new
|
|
26351
|
+
const combinedTexture = new THREE43.CanvasTexture(canvas);
|
|
26295
26352
|
combinedTexture.generateMipmaps = false;
|
|
26296
|
-
combinedTexture.minFilter =
|
|
26297
|
-
combinedTexture.magFilter =
|
|
26353
|
+
combinedTexture.minFilter = THREE43.LinearFilter;
|
|
26354
|
+
combinedTexture.magFilter = THREE43.LinearFilter;
|
|
26298
26355
|
combinedTexture.premultiplyAlpha = true;
|
|
26299
26356
|
combinedTexture.anisotropy = 16;
|
|
26300
26357
|
combinedTexture.needsUpdate = true;
|
|
@@ -26330,11 +26387,11 @@ var createMaskedCopperMask = ({
|
|
|
26330
26387
|
height
|
|
26331
26388
|
);
|
|
26332
26389
|
ctx.globalCompositeOperation = "source-over";
|
|
26333
|
-
const maskTexture = new
|
|
26334
|
-
maskTexture.colorSpace =
|
|
26390
|
+
const maskTexture = new THREE43.CanvasTexture(canvas);
|
|
26391
|
+
maskTexture.colorSpace = THREE43.NoColorSpace;
|
|
26335
26392
|
maskTexture.generateMipmaps = false;
|
|
26336
|
-
maskTexture.minFilter =
|
|
26337
|
-
maskTexture.magFilter =
|
|
26393
|
+
maskTexture.minFilter = THREE43.LinearFilter;
|
|
26394
|
+
maskTexture.magFilter = THREE43.LinearFilter;
|
|
26338
26395
|
maskTexture.premultiplyAlpha = false;
|
|
26339
26396
|
maskTexture.needsUpdate = true;
|
|
26340
26397
|
return maskTexture;
|
|
@@ -26480,7 +26537,7 @@ function createCombinedBoardTextures({
|
|
|
26480
26537
|
}
|
|
26481
26538
|
|
|
26482
26539
|
// src/textures/create-three-texture-meshes.ts
|
|
26483
|
-
import * as
|
|
26540
|
+
import * as THREE45 from "three";
|
|
26484
26541
|
|
|
26485
26542
|
// src/board-surface-textures.ts
|
|
26486
26543
|
var REALISTIC_BOARD_SURFACE_MATERIAL = {
|
|
@@ -26503,7 +26560,7 @@ var PAD_COPPER_TEXTURE_MATERIAL = {
|
|
|
26503
26560
|
};
|
|
26504
26561
|
|
|
26505
26562
|
// src/utils/create-board-relief-textures.ts
|
|
26506
|
-
import * as
|
|
26563
|
+
import * as THREE44 from "three";
|
|
26507
26564
|
var PLAIN_SOLDERMASK_HEIGHT = 0.22;
|
|
26508
26565
|
var MASKED_COPPER_HEIGHT = 0.7;
|
|
26509
26566
|
var EXPOSED_COPPER_HEIGHT = 0.86;
|
|
@@ -26598,13 +26655,13 @@ var getBoardSurfaceProfile = (r, g, b, hasMaskedCopper) => {
|
|
|
26598
26655
|
return PLAIN_SOLDERMASK_PROFILE;
|
|
26599
26656
|
};
|
|
26600
26657
|
var createDataTexture = (canvas) => {
|
|
26601
|
-
const texture = new
|
|
26602
|
-
texture.colorSpace =
|
|
26658
|
+
const texture = new THREE44.CanvasTexture(canvas);
|
|
26659
|
+
texture.colorSpace = THREE44.NoColorSpace;
|
|
26603
26660
|
texture.generateMipmaps = false;
|
|
26604
|
-
texture.minFilter =
|
|
26605
|
-
texture.magFilter =
|
|
26606
|
-
texture.wrapS =
|
|
26607
|
-
texture.wrapT =
|
|
26661
|
+
texture.minFilter = THREE44.LinearFilter;
|
|
26662
|
+
texture.magFilter = THREE44.LinearFilter;
|
|
26663
|
+
texture.wrapS = THREE44.ClampToEdgeWrapping;
|
|
26664
|
+
texture.wrapT = THREE44.ClampToEdgeWrapping;
|
|
26608
26665
|
texture.needsUpdate = true;
|
|
26609
26666
|
return texture;
|
|
26610
26667
|
};
|
|
@@ -26728,16 +26785,16 @@ function createTexturePlane(config, boardData) {
|
|
|
26728
26785
|
} = config;
|
|
26729
26786
|
if (!texture) return null;
|
|
26730
26787
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
26731
|
-
const planeGeom = new
|
|
26788
|
+
const planeGeom = new THREE45.PlaneGeometry(
|
|
26732
26789
|
boardOutlineBounds.width,
|
|
26733
26790
|
boardOutlineBounds.height
|
|
26734
26791
|
);
|
|
26735
|
-
texture.colorSpace =
|
|
26792
|
+
texture.colorSpace = THREE45.SRGBColorSpace;
|
|
26736
26793
|
const sharedMaterialOptions = {
|
|
26737
26794
|
map: texture,
|
|
26738
26795
|
transparent: true,
|
|
26739
26796
|
alphaTest: 0.08,
|
|
26740
|
-
side:
|
|
26797
|
+
side: THREE45.FrontSide,
|
|
26741
26798
|
depthWrite: true,
|
|
26742
26799
|
polygonOffset: usePolygonOffset,
|
|
26743
26800
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -26746,12 +26803,12 @@ function createTexturePlane(config, boardData) {
|
|
|
26746
26803
|
opacity: isFaux ? FAUX_BOARD_OPACITY : 1
|
|
26747
26804
|
};
|
|
26748
26805
|
const reliefTextures = createBoardReliefTextures(texture, maskedCopperMask);
|
|
26749
|
-
const material = new
|
|
26806
|
+
const material = new THREE45.MeshPhysicalMaterial({
|
|
26750
26807
|
...sharedMaterialOptions,
|
|
26751
26808
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
26752
26809
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
26753
26810
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
26754
|
-
normalScale: new
|
|
26811
|
+
normalScale: new THREE45.Vector2(
|
|
26755
26812
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
26756
26813
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
26757
26814
|
),
|
|
@@ -26765,7 +26822,7 @@ function createTexturePlane(config, boardData) {
|
|
|
26765
26822
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
26766
26823
|
envMapIntensity: 0.18
|
|
26767
26824
|
});
|
|
26768
|
-
const mesh = new
|
|
26825
|
+
const mesh = new THREE45.Mesh(planeGeom, material);
|
|
26769
26826
|
mesh.position.set(
|
|
26770
26827
|
boardOutlineBounds.centerX,
|
|
26771
26828
|
boardOutlineBounds.centerY,
|
|
@@ -26813,7 +26870,7 @@ function createTextureMeshes(textures, boardData, pcbThickness, isFaux = false)
|
|
|
26813
26870
|
}
|
|
26814
26871
|
|
|
26815
26872
|
// src/three-components/JscadBoardTextures.tsx
|
|
26816
|
-
import * as
|
|
26873
|
+
import * as THREE46 from "three";
|
|
26817
26874
|
|
|
26818
26875
|
// src/hooks/useBoardTextureVisibility.ts
|
|
26819
26876
|
import { useMemo as useMemo20 } from "react";
|
|
@@ -26931,7 +26988,7 @@ function JscadBoardTextures({
|
|
|
26931
26988
|
visibility: textureVisibility
|
|
26932
26989
|
});
|
|
26933
26990
|
}, [circuitJson, boardData, traceTextureResolution, textureVisibility]);
|
|
26934
|
-
|
|
26991
|
+
useEffect27(() => {
|
|
26935
26992
|
if (!rootObject || !boardData || !textures) return;
|
|
26936
26993
|
const meshes = [];
|
|
26937
26994
|
const disposeTextureMaterial = (material) => {
|
|
@@ -26951,7 +27008,7 @@ function JscadBoardTextures({
|
|
|
26951
27008
|
const typedMaterial = material;
|
|
26952
27009
|
for (const prop of textureProps) {
|
|
26953
27010
|
const texture = typedMaterial[prop];
|
|
26954
|
-
if (texture && texture instanceof
|
|
27011
|
+
if (texture && texture instanceof THREE46.Texture) {
|
|
26955
27012
|
texture.dispose();
|
|
26956
27013
|
typedMaterial[prop] = null;
|
|
26957
27014
|
}
|
|
@@ -26970,16 +27027,16 @@ function JscadBoardTextures({
|
|
|
26970
27027
|
}) => {
|
|
26971
27028
|
if (!texture) return null;
|
|
26972
27029
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
26973
|
-
const planeGeom = new
|
|
27030
|
+
const planeGeom = new THREE46.PlaneGeometry(
|
|
26974
27031
|
boardOutlineBounds.width,
|
|
26975
27032
|
boardOutlineBounds.height
|
|
26976
27033
|
);
|
|
26977
|
-
texture.colorSpace =
|
|
27034
|
+
texture.colorSpace = THREE46.SRGBColorSpace;
|
|
26978
27035
|
const sharedMaterialOptions = {
|
|
26979
27036
|
map: texture,
|
|
26980
27037
|
transparent: true,
|
|
26981
27038
|
alphaTest: 0.08,
|
|
26982
|
-
side:
|
|
27039
|
+
side: THREE46.FrontSide,
|
|
26983
27040
|
depthWrite,
|
|
26984
27041
|
polygonOffset: usePolygonOffset,
|
|
26985
27042
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -26990,12 +27047,12 @@ function JscadBoardTextures({
|
|
|
26990
27047
|
texture,
|
|
26991
27048
|
maskedCopperMask
|
|
26992
27049
|
);
|
|
26993
|
-
const material = new
|
|
27050
|
+
const material = new THREE46.MeshPhysicalMaterial({
|
|
26994
27051
|
...sharedMaterialOptions,
|
|
26995
27052
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
26996
27053
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
26997
27054
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
26998
|
-
normalScale: new
|
|
27055
|
+
normalScale: new THREE46.Vector2(
|
|
26999
27056
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
27000
27057
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
27001
27058
|
),
|
|
@@ -27007,7 +27064,7 @@ function JscadBoardTextures({
|
|
|
27007
27064
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
27008
27065
|
envMapIntensity: 0.18
|
|
27009
27066
|
});
|
|
27010
|
-
const mesh = new
|
|
27067
|
+
const mesh = new THREE46.Mesh(planeGeom, material);
|
|
27011
27068
|
mesh.position.set(
|
|
27012
27069
|
boardOutlineBounds.centerX,
|
|
27013
27070
|
boardOutlineBounds.centerY,
|
|
@@ -27057,7 +27114,7 @@ function JscadBoardTextures({
|
|
|
27057
27114
|
for (const material of mesh.material) {
|
|
27058
27115
|
disposeTextureMaterial(material);
|
|
27059
27116
|
}
|
|
27060
|
-
} else if (mesh.material instanceof
|
|
27117
|
+
} else if (mesh.material instanceof THREE46.Material) {
|
|
27061
27118
|
disposeTextureMaterial(mesh.material);
|
|
27062
27119
|
}
|
|
27063
27120
|
}
|
|
@@ -27069,8 +27126,8 @@ function JscadBoardTextures({
|
|
|
27069
27126
|
}
|
|
27070
27127
|
|
|
27071
27128
|
// src/three-components/STLModel.tsx
|
|
27072
|
-
import { useState as useState17, useEffect as
|
|
27073
|
-
import * as
|
|
27129
|
+
import { useState as useState17, useEffect as useEffect28, useMemo as useMemo22 } from "react";
|
|
27130
|
+
import * as THREE47 from "three";
|
|
27074
27131
|
import { STLLoader } from "three-stdlib";
|
|
27075
27132
|
function STLModel({
|
|
27076
27133
|
stlUrl,
|
|
@@ -27082,7 +27139,7 @@ function STLModel({
|
|
|
27082
27139
|
}) {
|
|
27083
27140
|
const { rootObject } = useThree();
|
|
27084
27141
|
const [geom, setGeom] = useState17(null);
|
|
27085
|
-
|
|
27142
|
+
useEffect28(() => {
|
|
27086
27143
|
const loader = new STLLoader();
|
|
27087
27144
|
if (stlData) {
|
|
27088
27145
|
try {
|
|
@@ -27103,15 +27160,15 @@ function STLModel({
|
|
|
27103
27160
|
const mesh = useMemo22(() => {
|
|
27104
27161
|
if (!geom) return null;
|
|
27105
27162
|
const isBoardLayer = layerType === "board";
|
|
27106
|
-
const material = new
|
|
27107
|
-
color: Array.isArray(color) ? new
|
|
27163
|
+
const material = new THREE47.MeshStandardMaterial({
|
|
27164
|
+
color: Array.isArray(color) ? new THREE47.Color(color[0], color[1], color[2]) : color,
|
|
27108
27165
|
transparent: opacity !== 1,
|
|
27109
27166
|
opacity,
|
|
27110
27167
|
polygonOffset: isBoardLayer,
|
|
27111
27168
|
polygonOffsetFactor: isBoardLayer ? 6 : 0,
|
|
27112
27169
|
polygonOffsetUnits: isBoardLayer ? 6 : 0
|
|
27113
27170
|
});
|
|
27114
|
-
const createdMesh = new
|
|
27171
|
+
const createdMesh = new THREE47.Mesh(geom, material);
|
|
27115
27172
|
createdMesh.renderOrder = isBoardLayer ? -1 : 1;
|
|
27116
27173
|
configureObjectShadows(createdMesh, {
|
|
27117
27174
|
castShadow: !isBoardLayer && opacity === 1,
|
|
@@ -27119,7 +27176,7 @@ function STLModel({
|
|
|
27119
27176
|
});
|
|
27120
27177
|
return createdMesh;
|
|
27121
27178
|
}, [geom, color, opacity, layerType]);
|
|
27122
|
-
|
|
27179
|
+
useEffect28(() => {
|
|
27123
27180
|
if (!rootObject || !mesh) return;
|
|
27124
27181
|
rootObject.add(mesh);
|
|
27125
27182
|
return () => {
|
|
@@ -27173,8 +27230,8 @@ function VisibleSTLModel({
|
|
|
27173
27230
|
// src/three-components/CadCable.tsx
|
|
27174
27231
|
import { parseCableString } from "@tscircuit/cableprinter";
|
|
27175
27232
|
import { createCableMeshes } from "jscad-electronics/cables";
|
|
27176
|
-
import { useEffect as
|
|
27177
|
-
import * as
|
|
27233
|
+
import { useEffect as useEffect29, useMemo as useMemo23 } from "react";
|
|
27234
|
+
import * as THREE48 from "three";
|
|
27178
27235
|
var isCadCableElement = (element) => {
|
|
27179
27236
|
if (!element || typeof element !== "object") return false;
|
|
27180
27237
|
const candidate = element;
|
|
@@ -27191,14 +27248,14 @@ var getConnectorPin1Side = ({
|
|
|
27191
27248
|
const endpoint = end === "start" ? path[0] : path[path.length - 1];
|
|
27192
27249
|
const adjacent = end === "start" ? path[1] : path[path.length - 2];
|
|
27193
27250
|
if (!endpoint || !adjacent) return void 0;
|
|
27194
|
-
const cableAxis = new
|
|
27251
|
+
const cableAxis = new THREE48.Vector3(
|
|
27195
27252
|
adjacent.x - endpoint.x,
|
|
27196
27253
|
adjacent.y - endpoint.y,
|
|
27197
27254
|
adjacent.z - endpoint.z
|
|
27198
27255
|
);
|
|
27199
27256
|
if (cableAxis.lengthSq() < 1e-12) return void 0;
|
|
27200
27257
|
cableAxis.normalize();
|
|
27201
|
-
const pin1Side = new
|
|
27258
|
+
const pin1Side = new THREE48.Vector3(
|
|
27202
27259
|
pin1Position.x - endpoint.x,
|
|
27203
27260
|
pin1Position.y - endpoint.y,
|
|
27204
27261
|
pin1Position.z - endpoint.z
|
|
@@ -27224,28 +27281,28 @@ var createCadCableObject = (cable) => {
|
|
|
27224
27281
|
end: "end"
|
|
27225
27282
|
})
|
|
27226
27283
|
});
|
|
27227
|
-
const group = new
|
|
27284
|
+
const group = new THREE48.Group();
|
|
27228
27285
|
group.name = `cad-cable-${cable.cad_cable_id}`;
|
|
27229
27286
|
group.userData = { cadCableId: cable.cad_cable_id, name: cable.name };
|
|
27230
27287
|
for (const cableMesh of cableMeshes) {
|
|
27231
|
-
let geometry = new
|
|
27288
|
+
let geometry = new THREE48.BufferGeometry();
|
|
27232
27289
|
geometry.setAttribute(
|
|
27233
27290
|
"position",
|
|
27234
|
-
new
|
|
27291
|
+
new THREE48.Float32BufferAttribute(cableMesh.positions, 3)
|
|
27235
27292
|
);
|
|
27236
27293
|
geometry.setIndex(cableMesh.indices);
|
|
27237
27294
|
if (!cableMesh.smooth) geometry = geometry.toNonIndexed();
|
|
27238
27295
|
geometry.computeVertexNormals();
|
|
27239
27296
|
const [red, green, blue, alpha] = cableMesh.color;
|
|
27240
|
-
const material = new
|
|
27241
|
-
color: new
|
|
27297
|
+
const material = new THREE48.MeshStandardMaterial({
|
|
27298
|
+
color: new THREE48.Color(red, green, blue),
|
|
27242
27299
|
metalness: cableMesh.material?.metalness ?? 0,
|
|
27243
27300
|
roughness: cableMesh.material?.roughness ?? 0.7,
|
|
27244
27301
|
opacity: alpha,
|
|
27245
27302
|
transparent: alpha < 1,
|
|
27246
|
-
side:
|
|
27303
|
+
side: THREE48.DoubleSide
|
|
27247
27304
|
});
|
|
27248
|
-
const mesh = new
|
|
27305
|
+
const mesh = new THREE48.Mesh(geometry, material);
|
|
27249
27306
|
mesh.name = `${group.name}:${cableMesh.name}`;
|
|
27250
27307
|
configureObjectShadows(mesh, { castShadow: true, receiveShadow: true });
|
|
27251
27308
|
group.add(mesh);
|
|
@@ -27254,7 +27311,7 @@ var createCadCableObject = (cable) => {
|
|
|
27254
27311
|
};
|
|
27255
27312
|
var disposeCadCableObject = (group) => {
|
|
27256
27313
|
group.traverse((object) => {
|
|
27257
|
-
if (!(object instanceof
|
|
27314
|
+
if (!(object instanceof THREE48.Mesh)) return;
|
|
27258
27315
|
object.geometry.dispose();
|
|
27259
27316
|
const materials = Array.isArray(object.material) ? object.material : [object.material];
|
|
27260
27317
|
for (const material of materials) material.dispose();
|
|
@@ -27270,7 +27327,7 @@ var CadCable = ({ cable }) => {
|
|
|
27270
27327
|
return null;
|
|
27271
27328
|
}
|
|
27272
27329
|
}, [cable]);
|
|
27273
|
-
|
|
27330
|
+
useEffect29(() => {
|
|
27274
27331
|
if (!cableObject) return;
|
|
27275
27332
|
rootObject.add(cableObject);
|
|
27276
27333
|
return () => {
|
|
@@ -27281,6 +27338,22 @@ var CadCable = ({ cable }) => {
|
|
|
27281
27338
|
return null;
|
|
27282
27339
|
};
|
|
27283
27340
|
|
|
27341
|
+
// src/utils/get-initial-camera-position.ts
|
|
27342
|
+
function getInitialCameraPosition({
|
|
27343
|
+
boardDimensions,
|
|
27344
|
+
boardCenter
|
|
27345
|
+
}) {
|
|
27346
|
+
if (!boardDimensions || !boardCenter) return [5, -5, 5];
|
|
27347
|
+
const safeWidth = Math.max(boardDimensions.width ?? 0, 1);
|
|
27348
|
+
const safeHeight = Math.max(boardDimensions.height ?? 0, 1);
|
|
27349
|
+
const largestDimension = Math.max(safeWidth, safeHeight, 5);
|
|
27350
|
+
return [
|
|
27351
|
+
boardCenter.x + largestDimension * 0.4,
|
|
27352
|
+
boardCenter.y - largestDimension * 0.7,
|
|
27353
|
+
largestDimension * 0.9
|
|
27354
|
+
];
|
|
27355
|
+
}
|
|
27356
|
+
|
|
27284
27357
|
// src/utils/preprocess-circuit-json.ts
|
|
27285
27358
|
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
27286
27359
|
|
|
@@ -27390,32 +27463,6 @@ var CadViewerJscad = forwardRef3(
|
|
|
27390
27463
|
);
|
|
27391
27464
|
}, [circuitJson, childrenSoup]);
|
|
27392
27465
|
const boardGeom = useBoardGeomBuilder(internalCircuitJson);
|
|
27393
|
-
const initialCameraPosition = useMemo24(() => {
|
|
27394
|
-
if (!internalCircuitJson) return [5, -5, 5];
|
|
27395
|
-
try {
|
|
27396
|
-
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
27397
|
-
if (!board) return [5, -5, 5];
|
|
27398
|
-
const { width, height } = board;
|
|
27399
|
-
if (!width && !height) {
|
|
27400
|
-
return [5, -5, 5];
|
|
27401
|
-
}
|
|
27402
|
-
const minCameraDistance = 5;
|
|
27403
|
-
const adjustedBoardWidth = Math.max(width, minCameraDistance);
|
|
27404
|
-
const adjustedBoardHeight = Math.max(height, minCameraDistance);
|
|
27405
|
-
const largestDim = Math.max(adjustedBoardWidth, adjustedBoardHeight);
|
|
27406
|
-
return [
|
|
27407
|
-
largestDim * 0.4,
|
|
27408
|
-
// Move right
|
|
27409
|
-
-largestDim * 0.7,
|
|
27410
|
-
// Move back (negative Y)
|
|
27411
|
-
largestDim * 0.9
|
|
27412
|
-
// Keep height but slightly lower than top-down
|
|
27413
|
-
];
|
|
27414
|
-
} catch (e) {
|
|
27415
|
-
console.error(e);
|
|
27416
|
-
return [5, -5, 5];
|
|
27417
|
-
}
|
|
27418
|
-
}, [internalCircuitJson]);
|
|
27419
27466
|
const isFauxBoard = useMemo24(() => {
|
|
27420
27467
|
if (!internalCircuitJson) return false;
|
|
27421
27468
|
try {
|
|
@@ -27449,6 +27496,19 @@ var CadViewerJscad = forwardRef3(
|
|
|
27449
27496
|
return void 0;
|
|
27450
27497
|
}
|
|
27451
27498
|
}, [internalCircuitJson]);
|
|
27499
|
+
const cameraSessionScope = useMemo24(() => {
|
|
27500
|
+
if (!internalCircuitJson) return void 0;
|
|
27501
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
27502
|
+
if (!board) return void 0;
|
|
27503
|
+
return JSON.stringify({
|
|
27504
|
+
pcbBoardId: board.pcb_board_id,
|
|
27505
|
+
center: boardCenter,
|
|
27506
|
+
dimensions: boardDimensions
|
|
27507
|
+
});
|
|
27508
|
+
}, [internalCircuitJson, boardCenter, boardDimensions]);
|
|
27509
|
+
const initialCameraPosition = useMemo24(() => {
|
|
27510
|
+
return getInitialCameraPosition({ boardDimensions, boardCenter });
|
|
27511
|
+
}, [boardDimensions, boardCenter]);
|
|
27452
27512
|
const pcbThickness = usePcbThickness(internalCircuitJson);
|
|
27453
27513
|
const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
|
|
27454
27514
|
const cad_components = su12(internalCircuitJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id));
|
|
@@ -27462,6 +27522,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
27462
27522
|
clickToInteractEnabled,
|
|
27463
27523
|
boardDimensions,
|
|
27464
27524
|
boardCenter,
|
|
27525
|
+
cameraSessionScope,
|
|
27465
27526
|
referenceObject,
|
|
27466
27527
|
onUserInteraction,
|
|
27467
27528
|
onCameraControllerReady,
|
|
@@ -27507,6 +27568,9 @@ var CadViewerJscad = forwardRef3(
|
|
|
27507
27568
|
}
|
|
27508
27569
|
);
|
|
27509
27570
|
|
|
27571
|
+
// src/CadViewerManifold.tsx
|
|
27572
|
+
import { su as su17 } from "@tscircuit/circuit-json-util";
|
|
27573
|
+
|
|
27510
27574
|
// node_modules/earcut/src/earcut.js
|
|
27511
27575
|
var steiners = /* @__PURE__ */ new Set();
|
|
27512
27576
|
var filteredOut = false;
|
|
@@ -28445,207 +28509,61 @@ function extrudePolygon({
|
|
|
28445
28509
|
pcbFace: "side"
|
|
28446
28510
|
});
|
|
28447
28511
|
}
|
|
28448
|
-
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28449
|
-
}
|
|
28450
|
-
function createStiffenerMesh({
|
|
28451
|
-
stiffener,
|
|
28452
|
-
boardThickness,
|
|
28453
|
-
fold
|
|
28454
|
-
}) {
|
|
28455
|
-
const adhesive = stiffener.adhesive_thickness ?? 0;
|
|
28456
|
-
if (!Number.isFinite(adhesive) || adhesive < 0 || !Number.isFinite(stiffener.thickness) || stiffener.thickness <= 0 || !["top", "bottom"].includes(stiffener.layer))
|
|
28457
|
-
throw new Error(`Invalid PCB stiffener ${stiffener.pcb_stiffener_id}`);
|
|
28458
|
-
const outline = stiffener.shape === "polygon" ? stiffener.outline : (() => {
|
|
28459
|
-
if (!(stiffener.width > 0 && stiffener.height > 0))
|
|
28460
|
-
throw new Error("Invalid stiffener dimensions");
|
|
28461
|
-
const a = (stiffener.rotation ?? 0) * Math.PI / 180;
|
|
28462
|
-
return [
|
|
28463
|
-
[-1, -1],
|
|
28464
|
-
[1, -1],
|
|
28465
|
-
[1, 1],
|
|
28466
|
-
[-1, 1]
|
|
28467
|
-
].map(([x, y]) => ({
|
|
28468
|
-
x: stiffener.center.x + x * stiffener.width / 2 * Math.cos(a) - y * stiffener.height / 2 * Math.sin(a),
|
|
28469
|
-
y: stiffener.center.y + x * stiffener.width / 2 * Math.sin(a) + y * stiffener.height / 2 * Math.cos(a)
|
|
28470
|
-
}));
|
|
28471
|
-
})();
|
|
28472
|
-
const near = boardThickness / 2 + adhesive, far = near + stiffener.thickness;
|
|
28473
|
-
const mesh = extrudePolygon({
|
|
28474
|
-
outline,
|
|
28475
|
-
bottom: stiffener.layer === "top" ? near : -far,
|
|
28476
|
-
top: stiffener.layer === "top" ? far : -near
|
|
28477
|
-
});
|
|
28478
|
-
if (!fold) return mesh;
|
|
28479
|
-
fold.assertRigid(
|
|
28480
|
-
mesh.triangles.flatMap((t) => t.vertices),
|
|
28481
|
-
stiffener.pcb_stiffener_id
|
|
28482
|
-
);
|
|
28483
|
-
const anchor = {
|
|
28484
|
-
x: outline.reduce((s, p) => s + p.x, 0) / outline.length,
|
|
28485
|
-
y: outline.reduce((s, p) => s + p.y, 0) / outline.length,
|
|
28486
|
-
z: 0
|
|
28487
|
-
};
|
|
28488
|
-
const triangles = mesh.triangles.map((t) => ({
|
|
28489
|
-
...t,
|
|
28490
|
-
vertices: t.vertices.map((p) => fold.point(p, anchor)),
|
|
28491
|
-
normal: fold.direction(t.normal, anchor)
|
|
28492
|
-
}));
|
|
28493
|
-
return { ...mesh, triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28494
|
-
}
|
|
28495
|
-
|
|
28496
|
-
// src/utils/flex-meshes.ts
|
|
28497
|
-
import * as THREE48 from "three";
|
|
28498
|
-
function meshToSurface(mesh, center) {
|
|
28499
|
-
mesh.updateMatrix();
|
|
28500
|
-
const geometry = mesh.geometry.index ? mesh.geometry.toNonIndexed() : mesh.geometry;
|
|
28501
|
-
const position = geometry.getAttribute("position"), uv = geometry.getAttribute("uv");
|
|
28502
|
-
const triangles = [];
|
|
28503
|
-
for (let i = 0; i < position.count; i += 3) {
|
|
28504
|
-
const vertices = [0, 1, 2].map((j) => {
|
|
28505
|
-
const v = new THREE48.Vector3().fromBufferAttribute(position, i + j).applyMatrix4(mesh.matrix);
|
|
28506
|
-
return { x: v.x - center.x, y: v.y - center.y, z: v.z };
|
|
28507
|
-
});
|
|
28508
|
-
const [a, b, c] = vertices;
|
|
28509
|
-
const n = new THREE48.Vector3(b.x - a.x, b.y - a.y, b.z - a.z).cross(new THREE48.Vector3(c.x - a.x, c.y - a.y, c.z - a.z)).normalize();
|
|
28510
|
-
triangles.push({
|
|
28511
|
-
vertices,
|
|
28512
|
-
normal: { x: n.x, y: n.y, z: n.z },
|
|
28513
|
-
...uv ? {
|
|
28514
|
-
uvs: [0, 1, 2].map((j) => ({
|
|
28515
|
-
u: uv.getX(i + j),
|
|
28516
|
-
v: uv.getY(i + j)
|
|
28517
|
-
}))
|
|
28518
|
-
} : {}
|
|
28519
|
-
});
|
|
28520
|
-
}
|
|
28521
|
-
if (geometry !== mesh.geometry) geometry.dispose();
|
|
28522
|
-
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28523
|
-
}
|
|
28524
|
-
function surfaceToGeometry(surface, center) {
|
|
28525
|
-
const positions = [], normals = [], uvs = [];
|
|
28526
|
-
for (const triangle of surface.triangles)
|
|
28527
|
-
triangle.vertices.forEach((p, i) => {
|
|
28528
|
-
positions.push(p.x + center.x, p.y + center.y, p.z);
|
|
28529
|
-
normals.push(triangle.normal.x, triangle.normal.y, triangle.normal.z);
|
|
28530
|
-
uvs.push(triangle.uvs?.[i]?.u ?? 0, triangle.uvs?.[i]?.v ?? 0);
|
|
28531
|
-
});
|
|
28532
|
-
const geometry = new THREE48.BufferGeometry();
|
|
28533
|
-
geometry.setAttribute(
|
|
28534
|
-
"position",
|
|
28535
|
-
new THREE48.Float32BufferAttribute(positions, 3)
|
|
28536
|
-
);
|
|
28537
|
-
geometry.setAttribute("normal", new THREE48.Float32BufferAttribute(normals, 3));
|
|
28538
|
-
geometry.setAttribute("uv", new THREE48.Float32BufferAttribute(uvs, 2));
|
|
28539
|
-
geometry.computeBoundingBox();
|
|
28540
|
-
geometry.computeBoundingSphere();
|
|
28541
|
-
return geometry;
|
|
28542
|
-
}
|
|
28543
|
-
function replaceGeometry(mesh, surface, board) {
|
|
28544
|
-
const output = mesh.clone();
|
|
28545
|
-
output.geometry = surfaceToGeometry(surface, board.center);
|
|
28546
|
-
output.position.set(0, 0, 0);
|
|
28547
|
-
output.rotation.set(0, 0, 0);
|
|
28548
|
-
output.scale.set(1, 1, 1);
|
|
28549
|
-
output.updateMatrix();
|
|
28550
|
-
return output;
|
|
28551
|
-
}
|
|
28552
|
-
function createFlexMeshes(geometryMeshes, textureMeshes, json, foldPcbs) {
|
|
28553
|
-
const boards = json.filter((e) => e.type === "pcb_board");
|
|
28554
|
-
const bends = json.filter((e) => e.type === "pcb_bend"), stiffeners = json.filter((e) => e.type === "pcb_stiffener");
|
|
28555
|
-
if (!bends.length && !stiffeners.length)
|
|
28556
|
-
return { geometryMeshes, textureMeshes };
|
|
28557
|
-
const board = boards[0];
|
|
28558
|
-
if (!board || boards.length !== 1 || json.some((e) => e.type === "pcb_panel") || [...bends, ...stiffeners].some((e) => e.pcb_board_id !== board.pcb_board_id))
|
|
28559
|
-
throw new Error(
|
|
28560
|
-
"Flex rendering requires one board, matching board references, and no panel"
|
|
28561
|
-
);
|
|
28562
|
-
const fold = foldPcbs ? createPcbFold(bends, board.thickness ?? 1.6) : void 0;
|
|
28563
|
-
const body = geometryMeshes.find((m) => m.name === "board-geom");
|
|
28564
|
-
const flatBody = body ? meshToSurface(body, board.center) : void 0;
|
|
28565
|
-
const geometry = fold ? geometryMeshes.map(
|
|
28566
|
-
(mesh) => replaceGeometry(
|
|
28567
|
-
mesh,
|
|
28568
|
-
foldSurfaceMesh(meshToSurface(mesh, board.center), fold),
|
|
28569
|
-
board
|
|
28570
|
-
)
|
|
28571
|
-
) : [...geometryMeshes];
|
|
28572
|
-
const textures = fold && flatBody ? textureMeshes.map((mesh) => {
|
|
28573
|
-
mesh.updateMatrix();
|
|
28574
|
-
const inverse4 = mesh.matrix.clone().invert();
|
|
28575
|
-
const bottom = mesh.name.startsWith("bottom");
|
|
28576
|
-
const dimensions = mesh.geometry.parameters;
|
|
28577
|
-
const triangles = flatBody.triangles.filter((t) => bottom ? t.normal.z < -0.9 : t.normal.z > 0.9).map((t) => {
|
|
28578
|
-
const vertices = t.vertices.map((p) => ({
|
|
28579
|
-
...p,
|
|
28580
|
-
z: mesh.position.z
|
|
28581
|
-
}));
|
|
28582
|
-
const uvs = vertices.map((p) => {
|
|
28583
|
-
const local = new THREE48.Vector3(
|
|
28584
|
-
p.x + board.center.x,
|
|
28585
|
-
p.y + board.center.y,
|
|
28586
|
-
p.z
|
|
28587
|
-
).applyMatrix4(inverse4);
|
|
28588
|
-
return {
|
|
28589
|
-
u: local.x / dimensions.width + 0.5,
|
|
28590
|
-
v: local.y / dimensions.height + 0.5
|
|
28591
|
-
};
|
|
28592
|
-
});
|
|
28593
|
-
return { ...t, vertices, uvs };
|
|
28594
|
-
});
|
|
28595
|
-
const result = replaceGeometry(
|
|
28596
|
-
mesh,
|
|
28597
|
-
foldSurfaceMesh(
|
|
28598
|
-
{ triangles, boundingBox: boundsOfTriangles(triangles) },
|
|
28599
|
-
fold
|
|
28600
|
-
),
|
|
28601
|
-
board
|
|
28602
|
-
);
|
|
28603
|
-
mesh.geometry.dispose();
|
|
28604
|
-
return result;
|
|
28605
|
-
}) : textureMeshes;
|
|
28606
|
-
for (const stiffener of stiffeners) {
|
|
28607
|
-
const mesh = new THREE48.Mesh(
|
|
28608
|
-
surfaceToGeometry(
|
|
28609
|
-
createStiffenerMesh({
|
|
28610
|
-
stiffener,
|
|
28611
|
-
boardThickness: board.thickness ?? 1.6,
|
|
28612
|
-
fold
|
|
28613
|
-
}),
|
|
28614
|
-
board.center
|
|
28615
|
-
),
|
|
28616
|
-
new THREE48.MeshStandardMaterial({
|
|
28617
|
-
color: stiffener.material === "fr4" ? "#879568" : stiffener.material === "polyimide" ? "#bd7f27" : "#b8bdc4",
|
|
28618
|
-
side: THREE48.DoubleSide
|
|
28619
|
-
})
|
|
28620
|
-
);
|
|
28621
|
-
mesh.name = "board-stiffener";
|
|
28622
|
-
configureObjectShadows(mesh);
|
|
28623
|
-
geometry.push(mesh);
|
|
28624
|
-
}
|
|
28625
|
-
const bounds = new THREE48.Box3();
|
|
28626
|
-
for (const mesh of [...geometry, ...textures]) bounds.expandByObject(mesh);
|
|
28627
|
-
return {
|
|
28628
|
-
geometryMeshes: geometry,
|
|
28629
|
-
textureMeshes: textures,
|
|
28630
|
-
bounds: {
|
|
28631
|
-
minX: bounds.min.x,
|
|
28632
|
-
maxX: bounds.max.x,
|
|
28633
|
-
minY: bounds.min.y,
|
|
28634
|
-
maxY: bounds.max.y,
|
|
28635
|
-
minZ: bounds.min.z,
|
|
28636
|
-
maxZ: bounds.max.z
|
|
28637
|
-
}
|
|
28512
|
+
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28513
|
+
}
|
|
28514
|
+
function createStiffenerMesh({
|
|
28515
|
+
stiffener,
|
|
28516
|
+
boardThickness,
|
|
28517
|
+
fold
|
|
28518
|
+
}) {
|
|
28519
|
+
const adhesive = stiffener.adhesive_thickness ?? 0;
|
|
28520
|
+
if (!Number.isFinite(adhesive) || adhesive < 0 || !Number.isFinite(stiffener.thickness) || stiffener.thickness <= 0 || !["top", "bottom"].includes(stiffener.layer))
|
|
28521
|
+
throw new Error(`Invalid PCB stiffener ${stiffener.pcb_stiffener_id}`);
|
|
28522
|
+
const outline = stiffener.shape === "polygon" ? stiffener.outline : (() => {
|
|
28523
|
+
if (!(stiffener.width > 0 && stiffener.height > 0))
|
|
28524
|
+
throw new Error("Invalid stiffener dimensions");
|
|
28525
|
+
const a = (stiffener.rotation ?? 0) * Math.PI / 180;
|
|
28526
|
+
return [
|
|
28527
|
+
[-1, -1],
|
|
28528
|
+
[1, -1],
|
|
28529
|
+
[1, 1],
|
|
28530
|
+
[-1, 1]
|
|
28531
|
+
].map(([x, y]) => ({
|
|
28532
|
+
x: stiffener.center.x + x * stiffener.width / 2 * Math.cos(a) - y * stiffener.height / 2 * Math.sin(a),
|
|
28533
|
+
y: stiffener.center.y + x * stiffener.width / 2 * Math.sin(a) + y * stiffener.height / 2 * Math.cos(a)
|
|
28534
|
+
}));
|
|
28535
|
+
})();
|
|
28536
|
+
const near = boardThickness / 2 + adhesive, far = near + stiffener.thickness;
|
|
28537
|
+
const mesh = extrudePolygon({
|
|
28538
|
+
outline,
|
|
28539
|
+
bottom: stiffener.layer === "top" ? near : -far,
|
|
28540
|
+
top: stiffener.layer === "top" ? far : -near
|
|
28541
|
+
});
|
|
28542
|
+
if (!fold) return mesh;
|
|
28543
|
+
fold.assertRigid(
|
|
28544
|
+
mesh.triangles.flatMap((t) => t.vertices),
|
|
28545
|
+
stiffener.pcb_stiffener_id
|
|
28546
|
+
);
|
|
28547
|
+
const anchor = {
|
|
28548
|
+
x: outline.reduce((s, p) => s + p.x, 0) / outline.length,
|
|
28549
|
+
y: outline.reduce((s, p) => s + p.y, 0) / outline.length,
|
|
28550
|
+
z: 0
|
|
28638
28551
|
};
|
|
28552
|
+
const triangles = mesh.triangles.map((t) => ({
|
|
28553
|
+
...t,
|
|
28554
|
+
vertices: t.vertices.map((p) => fold.point(p, anchor)),
|
|
28555
|
+
normal: fold.direction(t.normal, anchor)
|
|
28556
|
+
}));
|
|
28557
|
+
return { ...mesh, triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28639
28558
|
}
|
|
28640
28559
|
|
|
28641
28560
|
// src/CadViewerManifold.tsx
|
|
28642
|
-
import {
|
|
28643
|
-
import
|
|
28644
|
-
import * as THREE55 from "three";
|
|
28561
|
+
import { useEffect as useEffect31, useMemo as useMemo26, useState as useState19 } from "react";
|
|
28562
|
+
import * as THREE56 from "three";
|
|
28645
28563
|
|
|
28646
28564
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
28647
28565
|
import { su as su16 } from "@tscircuit/circuit-json-util";
|
|
28648
|
-
import { useEffect as
|
|
28566
|
+
import { useEffect as useEffect30, useMemo as useMemo25, useRef as useRef9, useState as useState18 } from "react";
|
|
28649
28567
|
import * as THREE52 from "three";
|
|
28650
28568
|
|
|
28651
28569
|
// src/utils/manifold/create-manifold-board.ts
|
|
@@ -29824,7 +29742,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
29824
29742
|
if (!boardData) return TRACE_TEXTURE_RESOLUTION;
|
|
29825
29743
|
return getLayerTextureResolution(boardData, TRACE_TEXTURE_RESOLUTION);
|
|
29826
29744
|
}, [boardData]);
|
|
29827
|
-
|
|
29745
|
+
useEffect30(() => {
|
|
29828
29746
|
if (!manifoldJSModule || !boardData) {
|
|
29829
29747
|
setGeoms(null);
|
|
29830
29748
|
setPcbThickness(null);
|
|
@@ -30024,12 +29942,157 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
30024
29942
|
};
|
|
30025
29943
|
};
|
|
30026
29944
|
|
|
29945
|
+
// src/utils/flex-meshes.ts
|
|
29946
|
+
import * as THREE53 from "three";
|
|
29947
|
+
function meshToSurface(mesh, center) {
|
|
29948
|
+
mesh.updateMatrix();
|
|
29949
|
+
const geometry = mesh.geometry.index ? mesh.geometry.toNonIndexed() : mesh.geometry;
|
|
29950
|
+
const position = geometry.getAttribute("position"), uv = geometry.getAttribute("uv");
|
|
29951
|
+
const triangles = [];
|
|
29952
|
+
for (let i = 0; i < position.count; i += 3) {
|
|
29953
|
+
const vertices = [0, 1, 2].map((j) => {
|
|
29954
|
+
const v = new THREE53.Vector3().fromBufferAttribute(position, i + j).applyMatrix4(mesh.matrix);
|
|
29955
|
+
return { x: v.x - center.x, y: v.y - center.y, z: v.z };
|
|
29956
|
+
});
|
|
29957
|
+
const [a, b, c] = vertices;
|
|
29958
|
+
const n = new THREE53.Vector3(b.x - a.x, b.y - a.y, b.z - a.z).cross(new THREE53.Vector3(c.x - a.x, c.y - a.y, c.z - a.z)).normalize();
|
|
29959
|
+
triangles.push({
|
|
29960
|
+
vertices,
|
|
29961
|
+
normal: { x: n.x, y: n.y, z: n.z },
|
|
29962
|
+
...uv ? {
|
|
29963
|
+
uvs: [0, 1, 2].map((j) => ({
|
|
29964
|
+
u: uv.getX(i + j),
|
|
29965
|
+
v: uv.getY(i + j)
|
|
29966
|
+
}))
|
|
29967
|
+
} : {}
|
|
29968
|
+
});
|
|
29969
|
+
}
|
|
29970
|
+
if (geometry !== mesh.geometry) geometry.dispose();
|
|
29971
|
+
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
29972
|
+
}
|
|
29973
|
+
function surfaceToGeometry(surface, center) {
|
|
29974
|
+
const positions = [], normals = [], uvs = [];
|
|
29975
|
+
for (const triangle of surface.triangles)
|
|
29976
|
+
triangle.vertices.forEach((p, i) => {
|
|
29977
|
+
positions.push(p.x + center.x, p.y + center.y, p.z);
|
|
29978
|
+
normals.push(triangle.normal.x, triangle.normal.y, triangle.normal.z);
|
|
29979
|
+
uvs.push(triangle.uvs?.[i]?.u ?? 0, triangle.uvs?.[i]?.v ?? 0);
|
|
29980
|
+
});
|
|
29981
|
+
const geometry = new THREE53.BufferGeometry();
|
|
29982
|
+
geometry.setAttribute(
|
|
29983
|
+
"position",
|
|
29984
|
+
new THREE53.Float32BufferAttribute(positions, 3)
|
|
29985
|
+
);
|
|
29986
|
+
geometry.setAttribute("normal", new THREE53.Float32BufferAttribute(normals, 3));
|
|
29987
|
+
geometry.setAttribute("uv", new THREE53.Float32BufferAttribute(uvs, 2));
|
|
29988
|
+
geometry.computeBoundingBox();
|
|
29989
|
+
geometry.computeBoundingSphere();
|
|
29990
|
+
return geometry;
|
|
29991
|
+
}
|
|
29992
|
+
function replaceGeometry(mesh, surface, board) {
|
|
29993
|
+
const output = mesh.clone();
|
|
29994
|
+
output.geometry = surfaceToGeometry(surface, board.center);
|
|
29995
|
+
output.position.set(0, 0, 0);
|
|
29996
|
+
output.rotation.set(0, 0, 0);
|
|
29997
|
+
output.scale.set(1, 1, 1);
|
|
29998
|
+
output.updateMatrix();
|
|
29999
|
+
return output;
|
|
30000
|
+
}
|
|
30001
|
+
function createFlexMeshes(geometryMeshes, textureMeshes, json, foldPcbs) {
|
|
30002
|
+
const boards = json.filter((e) => e.type === "pcb_board");
|
|
30003
|
+
const bends = json.filter((e) => e.type === "pcb_bend"), stiffeners = json.filter((e) => e.type === "pcb_stiffener");
|
|
30004
|
+
if (!bends.length && !stiffeners.length)
|
|
30005
|
+
return { geometryMeshes, textureMeshes };
|
|
30006
|
+
const board = boards[0];
|
|
30007
|
+
if (!board || boards.length !== 1 || json.some((e) => e.type === "pcb_panel") || [...bends, ...stiffeners].some((e) => e.pcb_board_id !== board.pcb_board_id))
|
|
30008
|
+
throw new Error(
|
|
30009
|
+
"Flex rendering requires one board, matching board references, and no panel"
|
|
30010
|
+
);
|
|
30011
|
+
const fold = foldPcbs ? createPcbFold(bends, board.thickness ?? 1.6) : void 0;
|
|
30012
|
+
const body = geometryMeshes.find((m) => m.name === "board-geom");
|
|
30013
|
+
const flatBody = body ? meshToSurface(body, board.center) : void 0;
|
|
30014
|
+
const geometry = fold ? geometryMeshes.map(
|
|
30015
|
+
(mesh) => replaceGeometry(
|
|
30016
|
+
mesh,
|
|
30017
|
+
foldSurfaceMesh(meshToSurface(mesh, board.center), fold),
|
|
30018
|
+
board
|
|
30019
|
+
)
|
|
30020
|
+
) : [...geometryMeshes];
|
|
30021
|
+
const textures = fold && flatBody ? textureMeshes.map((mesh) => {
|
|
30022
|
+
mesh.updateMatrix();
|
|
30023
|
+
const inverse4 = mesh.matrix.clone().invert();
|
|
30024
|
+
const bottom = mesh.name.startsWith("bottom");
|
|
30025
|
+
const dimensions = mesh.geometry.parameters;
|
|
30026
|
+
const triangles = flatBody.triangles.filter((t) => bottom ? t.normal.z < -0.9 : t.normal.z > 0.9).map((t) => {
|
|
30027
|
+
const vertices = t.vertices.map((p) => ({
|
|
30028
|
+
...p,
|
|
30029
|
+
z: mesh.position.z
|
|
30030
|
+
}));
|
|
30031
|
+
const uvs = vertices.map((p) => {
|
|
30032
|
+
const local = new THREE53.Vector3(
|
|
30033
|
+
p.x + board.center.x,
|
|
30034
|
+
p.y + board.center.y,
|
|
30035
|
+
p.z
|
|
30036
|
+
).applyMatrix4(inverse4);
|
|
30037
|
+
return {
|
|
30038
|
+
u: local.x / dimensions.width + 0.5,
|
|
30039
|
+
v: local.y / dimensions.height + 0.5
|
|
30040
|
+
};
|
|
30041
|
+
});
|
|
30042
|
+
return { ...t, vertices, uvs };
|
|
30043
|
+
});
|
|
30044
|
+
const result = replaceGeometry(
|
|
30045
|
+
mesh,
|
|
30046
|
+
foldSurfaceMesh(
|
|
30047
|
+
{ triangles, boundingBox: boundsOfTriangles(triangles) },
|
|
30048
|
+
fold
|
|
30049
|
+
),
|
|
30050
|
+
board
|
|
30051
|
+
);
|
|
30052
|
+
mesh.geometry.dispose();
|
|
30053
|
+
return result;
|
|
30054
|
+
}) : textureMeshes;
|
|
30055
|
+
for (const stiffener of stiffeners) {
|
|
30056
|
+
const mesh = new THREE53.Mesh(
|
|
30057
|
+
surfaceToGeometry(
|
|
30058
|
+
createStiffenerMesh({
|
|
30059
|
+
stiffener,
|
|
30060
|
+
boardThickness: board.thickness ?? 1.6,
|
|
30061
|
+
fold
|
|
30062
|
+
}),
|
|
30063
|
+
board.center
|
|
30064
|
+
),
|
|
30065
|
+
new THREE53.MeshStandardMaterial({
|
|
30066
|
+
color: stiffener.material === "fr4" ? "#879568" : stiffener.material === "polyimide" ? "#bd7f27" : "#b8bdc4",
|
|
30067
|
+
side: THREE53.DoubleSide
|
|
30068
|
+
})
|
|
30069
|
+
);
|
|
30070
|
+
mesh.name = "board-stiffener";
|
|
30071
|
+
configureObjectShadows(mesh);
|
|
30072
|
+
geometry.push(mesh);
|
|
30073
|
+
}
|
|
30074
|
+
const bounds = new THREE53.Box3();
|
|
30075
|
+
for (const mesh of [...geometry, ...textures]) bounds.expandByObject(mesh);
|
|
30076
|
+
return {
|
|
30077
|
+
geometryMeshes: geometry,
|
|
30078
|
+
textureMeshes: textures,
|
|
30079
|
+
bounds: {
|
|
30080
|
+
minX: bounds.min.x,
|
|
30081
|
+
maxX: bounds.max.x,
|
|
30082
|
+
minY: bounds.min.y,
|
|
30083
|
+
maxY: bounds.max.y,
|
|
30084
|
+
minZ: bounds.min.z,
|
|
30085
|
+
maxZ: bounds.max.z
|
|
30086
|
+
}
|
|
30087
|
+
};
|
|
30088
|
+
}
|
|
30089
|
+
|
|
30027
30090
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
30028
|
-
import * as
|
|
30091
|
+
import * as THREE55 from "three";
|
|
30029
30092
|
|
|
30030
30093
|
// src/utils/create-board-material.ts
|
|
30031
|
-
import * as
|
|
30032
|
-
var DEFAULT_SIDE =
|
|
30094
|
+
import * as THREE54 from "three";
|
|
30095
|
+
var DEFAULT_SIDE = THREE54.DoubleSide;
|
|
30033
30096
|
var createBoardMaterial = ({
|
|
30034
30097
|
material,
|
|
30035
30098
|
color,
|
|
@@ -30037,7 +30100,7 @@ var createBoardMaterial = ({
|
|
|
30037
30100
|
isFaux = false
|
|
30038
30101
|
}) => {
|
|
30039
30102
|
if (material === "fr4") {
|
|
30040
|
-
return new
|
|
30103
|
+
return new THREE54.MeshPhysicalMaterial({
|
|
30041
30104
|
color,
|
|
30042
30105
|
side,
|
|
30043
30106
|
metalness: 0,
|
|
@@ -30055,7 +30118,7 @@ var createBoardMaterial = ({
|
|
|
30055
30118
|
polygonOffsetUnits: 1
|
|
30056
30119
|
});
|
|
30057
30120
|
}
|
|
30058
|
-
return new
|
|
30121
|
+
return new THREE54.MeshStandardMaterial({
|
|
30059
30122
|
color,
|
|
30060
30123
|
side,
|
|
30061
30124
|
flatShading: true,
|
|
@@ -30074,12 +30137,12 @@ function createGeometryMeshes(geoms) {
|
|
|
30074
30137
|
const meshes = [];
|
|
30075
30138
|
if (!geoms) return meshes;
|
|
30076
30139
|
if (geoms.board?.geometry) {
|
|
30077
|
-
const mesh = new
|
|
30140
|
+
const mesh = new THREE55.Mesh(
|
|
30078
30141
|
geoms.board.geometry,
|
|
30079
30142
|
createBoardMaterial({
|
|
30080
30143
|
material: geoms.board.material,
|
|
30081
30144
|
color: geoms.board.color,
|
|
30082
|
-
side:
|
|
30145
|
+
side: THREE55.DoubleSide,
|
|
30083
30146
|
isFaux: geoms.board.isFaux
|
|
30084
30147
|
})
|
|
30085
30148
|
);
|
|
@@ -30090,11 +30153,11 @@ function createGeometryMeshes(geoms) {
|
|
|
30090
30153
|
const createMeshesFromArray = (geomArray) => {
|
|
30091
30154
|
if (geomArray) {
|
|
30092
30155
|
for (const comp of geomArray) {
|
|
30093
|
-
const mesh = new
|
|
30156
|
+
const mesh = new THREE55.Mesh(
|
|
30094
30157
|
comp.geometry,
|
|
30095
|
-
new
|
|
30158
|
+
new THREE55.MeshStandardMaterial({
|
|
30096
30159
|
color: comp.color,
|
|
30097
|
-
side:
|
|
30160
|
+
side: THREE55.DoubleSide,
|
|
30098
30161
|
flatShading: true
|
|
30099
30162
|
// Consistent with board
|
|
30100
30163
|
})
|
|
@@ -30139,14 +30202,14 @@ var BoardMeshes = ({
|
|
|
30139
30202
|
const typedMaterial = material;
|
|
30140
30203
|
for (const prop of textureProps) {
|
|
30141
30204
|
const texture = typedMaterial[prop];
|
|
30142
|
-
if (texture && texture instanceof
|
|
30205
|
+
if (texture && texture instanceof THREE56.Texture) {
|
|
30143
30206
|
texture.dispose();
|
|
30144
30207
|
}
|
|
30145
30208
|
}
|
|
30146
30209
|
material.dispose();
|
|
30147
30210
|
}
|
|
30148
30211
|
};
|
|
30149
|
-
|
|
30212
|
+
useEffect31(() => {
|
|
30150
30213
|
if (!rootObject) return;
|
|
30151
30214
|
for (const mesh of geometryMeshes) {
|
|
30152
30215
|
let shouldShow = true;
|
|
@@ -30168,7 +30231,7 @@ var BoardMeshes = ({
|
|
|
30168
30231
|
}
|
|
30169
30232
|
};
|
|
30170
30233
|
}, [rootObject, geometryMeshes, visibility]);
|
|
30171
|
-
|
|
30234
|
+
useEffect31(() => {
|
|
30172
30235
|
if (!rootObject) return;
|
|
30173
30236
|
for (const mesh of textureMeshes) {
|
|
30174
30237
|
rootObject.add(mesh);
|
|
@@ -30205,7 +30268,7 @@ var CadViewerManifold = ({
|
|
|
30205
30268
|
const [manifoldJSModule, setManifoldJSModule] = useState19(null);
|
|
30206
30269
|
const [manifoldLoadingError, setManifoldLoadingError] = useState19(null);
|
|
30207
30270
|
const { visibility } = useLayerVisibility();
|
|
30208
|
-
|
|
30271
|
+
useEffect31(() => {
|
|
30209
30272
|
if (window.ManifoldModule && typeof window.ManifoldModule === "object" && window.ManifoldModule.setup) {
|
|
30210
30273
|
setManifoldJSModule(window.ManifoldModule);
|
|
30211
30274
|
return;
|
|
@@ -30326,20 +30389,16 @@ try {
|
|
|
30326
30389
|
return { x: bounds.centerX, y: bounds.centerY };
|
|
30327
30390
|
}, [boardData]);
|
|
30328
30391
|
const initialCameraPosition = useMemo26(() => {
|
|
30329
|
-
|
|
30330
|
-
|
|
30331
|
-
|
|
30332
|
-
|
|
30333
|
-
|
|
30334
|
-
|
|
30335
|
-
|
|
30336
|
-
|
|
30337
|
-
|
|
30338
|
-
|
|
30339
|
-
largestDim * 0.9
|
|
30340
|
-
// Keep height but slightly lower than top-down
|
|
30341
|
-
];
|
|
30342
|
-
}, [boardData]);
|
|
30392
|
+
return getInitialCameraPosition({ boardDimensions, boardCenter });
|
|
30393
|
+
}, [boardDimensions, boardCenter]);
|
|
30394
|
+
const cameraSessionScope = useMemo26(() => {
|
|
30395
|
+
if (!boardData) return void 0;
|
|
30396
|
+
return JSON.stringify({
|
|
30397
|
+
pcbBoardId: boardData.pcb_board_id,
|
|
30398
|
+
center: boardCenter,
|
|
30399
|
+
dimensions: boardDimensions
|
|
30400
|
+
});
|
|
30401
|
+
}, [boardData, boardCenter, boardDimensions]);
|
|
30343
30402
|
if (manifoldLoadingError) {
|
|
30344
30403
|
return /* @__PURE__ */ jsxs5(
|
|
30345
30404
|
"div",
|
|
@@ -30389,6 +30448,7 @@ try {
|
|
|
30389
30448
|
clickToInteractEnabled,
|
|
30390
30449
|
boardDimensions,
|
|
30391
30450
|
boardCenter,
|
|
30451
|
+
cameraSessionScope,
|
|
30392
30452
|
referenceObject,
|
|
30393
30453
|
onUserInteraction,
|
|
30394
30454
|
onCameraControllerReady,
|
|
@@ -37871,10 +37931,10 @@ var ContextMenu = ({
|
|
|
37871
37931
|
};
|
|
37872
37932
|
|
|
37873
37933
|
// src/components/KeyboardShortcutsDialog.tsx
|
|
37874
|
-
import { useEffect as
|
|
37934
|
+
import { useEffect as useEffect49, useMemo as useMemo36, useRef as useRef27, useState as useState40 } from "react";
|
|
37875
37935
|
|
|
37876
37936
|
// src/hooks/useRegisteredHotkey.ts
|
|
37877
|
-
import { useEffect as
|
|
37937
|
+
import { useEffect as useEffect48, useMemo as useMemo35, useRef as useRef26, useState as useState39 } from "react";
|
|
37878
37938
|
var hotkeyRegistry = /* @__PURE__ */ new Map();
|
|
37879
37939
|
var subscribers = /* @__PURE__ */ new Set();
|
|
37880
37940
|
var isListenerAttached = false;
|
|
@@ -38005,7 +38065,7 @@ var useRegisteredHotkey = (id, handler, metadata) => {
|
|
|
38005
38065
|
}),
|
|
38006
38066
|
[metadata.shortcut, metadata.description]
|
|
38007
38067
|
);
|
|
38008
|
-
|
|
38068
|
+
useEffect48(() => {
|
|
38009
38069
|
const registration = {
|
|
38010
38070
|
id,
|
|
38011
38071
|
...normalizedMetadata,
|
|
@@ -38021,7 +38081,7 @@ var useHotkeyRegistry = () => {
|
|
|
38021
38081
|
const [entries, setEntries] = useState39(
|
|
38022
38082
|
() => Array.from(hotkeyRegistry.values())
|
|
38023
38083
|
);
|
|
38024
|
-
|
|
38084
|
+
useEffect48(() => subscribeToRegistry(setEntries), []);
|
|
38025
38085
|
return entries;
|
|
38026
38086
|
};
|
|
38027
38087
|
var registerHotkeyViewer = (element) => {
|
|
@@ -38038,7 +38098,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
38038
38098
|
const [query, setQuery] = useState40("");
|
|
38039
38099
|
const inputRef = useRef27(null);
|
|
38040
38100
|
const hotkeys = useHotkeyRegistry();
|
|
38041
|
-
|
|
38101
|
+
useEffect49(() => {
|
|
38042
38102
|
if (!open) return void 0;
|
|
38043
38103
|
const handleKeyDown = (event) => {
|
|
38044
38104
|
if (event.key === "Escape") {
|
|
@@ -38049,7 +38109,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
38049
38109
|
window.addEventListener("keydown", handleKeyDown);
|
|
38050
38110
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
38051
38111
|
}, [open, onClose]);
|
|
38052
|
-
|
|
38112
|
+
useEffect49(() => {
|
|
38053
38113
|
if (open) {
|
|
38054
38114
|
setTimeout(() => {
|
|
38055
38115
|
inputRef.current?.focus();
|
|
@@ -38278,7 +38338,7 @@ function useCameraPreset({
|
|
|
38278
38338
|
}
|
|
38279
38339
|
|
|
38280
38340
|
// src/hooks/useContextMenu.ts
|
|
38281
|
-
import { useState as useState41, useCallback as useCallback23, useRef as useRef28, useEffect as
|
|
38341
|
+
import { useState as useState41, useCallback as useCallback23, useRef as useRef28, useEffect as useEffect50 } from "react";
|
|
38282
38342
|
var useContextMenu = ({ containerRef, onOpen }) => {
|
|
38283
38343
|
const [menuVisible, setMenuVisible] = useState41(false);
|
|
38284
38344
|
const [menuPos, setMenuPos] = useState41({
|
|
@@ -38395,7 +38455,7 @@ var useContextMenu = ({ containerRef, onOpen }) => {
|
|
|
38395
38455
|
}
|
|
38396
38456
|
setMenuVisible(false);
|
|
38397
38457
|
}, []);
|
|
38398
|
-
|
|
38458
|
+
useEffect50(() => {
|
|
38399
38459
|
if (menuVisible) {
|
|
38400
38460
|
document.addEventListener("mousedown", handleClickAway);
|
|
38401
38461
|
document.addEventListener("touchstart", handleClickAway);
|
|
@@ -38459,7 +38519,7 @@ var useGlobalDownloadGltf = () => {
|
|
|
38459
38519
|
|
|
38460
38520
|
// src/CadViewer.tsx
|
|
38461
38521
|
import { jsx as jsx38, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
38462
|
-
var DEFAULT_TARGET = new
|
|
38522
|
+
var DEFAULT_TARGET = new THREE57.Vector3(0, 0, 0);
|
|
38463
38523
|
var INITIAL_CAMERA_POSITION = [5, -5, 5];
|
|
38464
38524
|
var readStoredCameraType = () => {
|
|
38465
38525
|
if (typeof window === "undefined") return void 0;
|
|
@@ -38626,24 +38686,24 @@ var CadViewerInner = (props) => {
|
|
|
38626
38686
|
description: "Toggle translucent components"
|
|
38627
38687
|
}
|
|
38628
38688
|
);
|
|
38629
|
-
|
|
38689
|
+
useEffect51(() => {
|
|
38630
38690
|
if (containerRef.current) {
|
|
38631
38691
|
registerHotkeyViewer(containerRef.current);
|
|
38632
38692
|
}
|
|
38633
38693
|
}, []);
|
|
38634
|
-
|
|
38694
|
+
useEffect51(() => {
|
|
38635
38695
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
38636
38696
|
}, [engine]);
|
|
38637
|
-
|
|
38697
|
+
useEffect51(() => {
|
|
38638
38698
|
window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
|
|
38639
38699
|
}, [autoRotate]);
|
|
38640
|
-
|
|
38700
|
+
useEffect51(() => {
|
|
38641
38701
|
window.localStorage.setItem(
|
|
38642
38702
|
"cadViewerAutoRotateUserToggled",
|
|
38643
38703
|
String(autoRotateUserToggled)
|
|
38644
38704
|
);
|
|
38645
38705
|
}, [autoRotateUserToggled]);
|
|
38646
|
-
|
|
38706
|
+
useEffect51(() => {
|
|
38647
38707
|
window.localStorage.setItem("cadViewerCameraType", cameraType);
|
|
38648
38708
|
}, [cameraType]);
|
|
38649
38709
|
const viewerKey = props.circuitJson ? circuitKey : void 0;
|
|
@@ -38782,11 +38842,11 @@ var CadViewer = (props) => {
|
|
|
38782
38842
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
38783
38843
|
var import_debug = __toESM(require_browser(), 1);
|
|
38784
38844
|
import { su as su18 } from "@tscircuit/circuit-json-util";
|
|
38785
|
-
import * as
|
|
38845
|
+
import * as THREE61 from "three";
|
|
38786
38846
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
38787
38847
|
|
|
38788
38848
|
// src/utils/create-geometry-from-polygons.ts
|
|
38789
|
-
import * as
|
|
38849
|
+
import * as THREE58 from "three";
|
|
38790
38850
|
import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6 } from "three";
|
|
38791
38851
|
function createGeometryFromPolygons(polygons) {
|
|
38792
38852
|
const geometry = new BufferGeometry6();
|
|
@@ -38800,12 +38860,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
38800
38860
|
...polygon2.vertices[i + 1]
|
|
38801
38861
|
// Third vertex
|
|
38802
38862
|
);
|
|
38803
|
-
const v1 = new
|
|
38804
|
-
const v2 = new
|
|
38805
|
-
const v3 = new
|
|
38806
|
-
const normal = new
|
|
38807
|
-
new
|
|
38808
|
-
new
|
|
38863
|
+
const v1 = new THREE58.Vector3(...polygon2.vertices[0]);
|
|
38864
|
+
const v2 = new THREE58.Vector3(...polygon2.vertices[i]);
|
|
38865
|
+
const v3 = new THREE58.Vector3(...polygon2.vertices[i + 1]);
|
|
38866
|
+
const normal = new THREE58.Vector3().crossVectors(
|
|
38867
|
+
new THREE58.Vector3().subVectors(v2, v1),
|
|
38868
|
+
new THREE58.Vector3().subVectors(v3, v1)
|
|
38809
38869
|
).normalize();
|
|
38810
38870
|
normals.push(
|
|
38811
38871
|
normal.x,
|
|
@@ -38833,10 +38893,10 @@ import {
|
|
|
38833
38893
|
convertCSGToThreeGeom as convertCSGToThreeGeom3,
|
|
38834
38894
|
getJscadModelForFootprint as getJscadModelForFootprint2
|
|
38835
38895
|
} from "jscad-electronics/vanilla";
|
|
38836
|
-
import * as
|
|
38896
|
+
import * as THREE60 from "three";
|
|
38837
38897
|
|
|
38838
38898
|
// src/utils/load-model.ts
|
|
38839
|
-
import * as
|
|
38899
|
+
import * as THREE59 from "three";
|
|
38840
38900
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
38841
38901
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
38842
38902
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -38844,12 +38904,12 @@ async function load3DModel(url) {
|
|
|
38844
38904
|
if (url.endsWith(".stl")) {
|
|
38845
38905
|
const loader = new STLLoader2();
|
|
38846
38906
|
const geometry = await loader.loadAsync(url);
|
|
38847
|
-
const material = new
|
|
38907
|
+
const material = new THREE59.MeshStandardMaterial({
|
|
38848
38908
|
color: 8947848,
|
|
38849
38909
|
metalness: 0.5,
|
|
38850
38910
|
roughness: 0.5
|
|
38851
38911
|
});
|
|
38852
|
-
return new
|
|
38912
|
+
return new THREE59.Mesh(geometry, material);
|
|
38853
38913
|
}
|
|
38854
38914
|
if (url.endsWith(".obj")) {
|
|
38855
38915
|
const loader = new OBJLoader2();
|
|
@@ -38882,9 +38942,9 @@ async function renderComponent(component, scene) {
|
|
|
38882
38942
|
}
|
|
38883
38943
|
if (component.rotation) {
|
|
38884
38944
|
model.rotation.set(
|
|
38885
|
-
|
|
38886
|
-
|
|
38887
|
-
|
|
38945
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
38946
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
38947
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38888
38948
|
);
|
|
38889
38949
|
}
|
|
38890
38950
|
scene.add(model);
|
|
@@ -38898,13 +38958,13 @@ async function renderComponent(component, scene) {
|
|
|
38898
38958
|
);
|
|
38899
38959
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
38900
38960
|
const threeGeom = convertCSGToThreeGeom3(jscadObject);
|
|
38901
|
-
const material2 = new
|
|
38961
|
+
const material2 = new THREE60.MeshStandardMaterial({
|
|
38902
38962
|
color: 8947848,
|
|
38903
38963
|
metalness: 0.5,
|
|
38904
38964
|
roughness: 0.5,
|
|
38905
|
-
side:
|
|
38965
|
+
side: THREE60.DoubleSide
|
|
38906
38966
|
});
|
|
38907
|
-
const mesh2 = new
|
|
38967
|
+
const mesh2 = new THREE60.Mesh(threeGeom, material2);
|
|
38908
38968
|
if (component.position) {
|
|
38909
38969
|
mesh2.position.set(
|
|
38910
38970
|
component.position.x ?? 0,
|
|
@@ -38914,9 +38974,9 @@ async function renderComponent(component, scene) {
|
|
|
38914
38974
|
}
|
|
38915
38975
|
if (component.rotation) {
|
|
38916
38976
|
mesh2.rotation.set(
|
|
38917
|
-
|
|
38918
|
-
|
|
38919
|
-
|
|
38977
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
38978
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
38979
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38920
38980
|
);
|
|
38921
38981
|
}
|
|
38922
38982
|
scene.add(mesh2);
|
|
@@ -38933,17 +38993,17 @@ async function renderComponent(component, scene) {
|
|
|
38933
38993
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
38934
38994
|
continue;
|
|
38935
38995
|
}
|
|
38936
|
-
const color = new
|
|
38996
|
+
const color = new THREE60.Color(geomInfo.color);
|
|
38937
38997
|
color.convertLinearToSRGB();
|
|
38938
38998
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
38939
38999
|
const threeGeom = convertCSGToThreeGeom3(geomWithColor);
|
|
38940
|
-
const material2 = new
|
|
39000
|
+
const material2 = new THREE60.MeshStandardMaterial({
|
|
38941
39001
|
vertexColors: true,
|
|
38942
39002
|
metalness: 0.2,
|
|
38943
39003
|
roughness: 0.8,
|
|
38944
|
-
side:
|
|
39004
|
+
side: THREE60.DoubleSide
|
|
38945
39005
|
});
|
|
38946
|
-
const mesh2 = new
|
|
39006
|
+
const mesh2 = new THREE60.Mesh(threeGeom, material2);
|
|
38947
39007
|
if (component.position) {
|
|
38948
39008
|
mesh2.position.set(
|
|
38949
39009
|
component.position.x ?? 0,
|
|
@@ -38953,22 +39013,22 @@ async function renderComponent(component, scene) {
|
|
|
38953
39013
|
}
|
|
38954
39014
|
if (component.rotation) {
|
|
38955
39015
|
mesh2.rotation.set(
|
|
38956
|
-
|
|
38957
|
-
|
|
38958
|
-
|
|
39016
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
39017
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
39018
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38959
39019
|
);
|
|
38960
39020
|
}
|
|
38961
39021
|
scene.add(mesh2);
|
|
38962
39022
|
}
|
|
38963
39023
|
return;
|
|
38964
39024
|
}
|
|
38965
|
-
const geometry = new
|
|
38966
|
-
const material = new
|
|
39025
|
+
const geometry = new THREE60.BoxGeometry(0.5, 0.5, 0.5);
|
|
39026
|
+
const material = new THREE60.MeshStandardMaterial({
|
|
38967
39027
|
color: 16711680,
|
|
38968
39028
|
transparent: true,
|
|
38969
39029
|
opacity: 0.25
|
|
38970
39030
|
});
|
|
38971
|
-
const mesh = new
|
|
39031
|
+
const mesh = new THREE60.Mesh(geometry, material);
|
|
38972
39032
|
if (component.position) {
|
|
38973
39033
|
mesh.position.set(
|
|
38974
39034
|
component.position.x ?? 0,
|
|
@@ -38989,11 +39049,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
38989
39049
|
padding = 20,
|
|
38990
39050
|
zoom = 1.5
|
|
38991
39051
|
} = options;
|
|
38992
|
-
const scene = new
|
|
39052
|
+
const scene = new THREE61.Scene();
|
|
38993
39053
|
const renderer = new SVGRenderer();
|
|
38994
39054
|
renderer.setSize(width, height);
|
|
38995
|
-
renderer.setClearColor(new
|
|
38996
|
-
const camera = new
|
|
39055
|
+
renderer.setClearColor(new THREE61.Color(backgroundColor), 1);
|
|
39056
|
+
const camera = new THREE61.OrthographicCamera();
|
|
38997
39057
|
const aspect = width / height;
|
|
38998
39058
|
const frustumSize = 100;
|
|
38999
39059
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -39007,11 +39067,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39007
39067
|
camera.position.set(position.x, position.y, position.z);
|
|
39008
39068
|
camera.up.set(0, 1, 0);
|
|
39009
39069
|
const lookAt2 = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
39010
|
-
camera.lookAt(new
|
|
39070
|
+
camera.lookAt(new THREE61.Vector3(lookAt2.x, lookAt2.y, lookAt2.z));
|
|
39011
39071
|
camera.updateProjectionMatrix();
|
|
39012
|
-
const ambientLight = new
|
|
39072
|
+
const ambientLight = new THREE61.AmbientLight(16777215, Math.PI / 2);
|
|
39013
39073
|
scene.add(ambientLight);
|
|
39014
|
-
const pointLight = new
|
|
39074
|
+
const pointLight = new THREE61.PointLight(16777215, Math.PI / 4);
|
|
39015
39075
|
pointLight.position.set(-10, -10, 10);
|
|
39016
39076
|
scene.add(pointLight);
|
|
39017
39077
|
const components = su18(circuitJson).cad_component.list();
|
|
@@ -39043,28 +39103,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39043
39103
|
const material = createBoardMaterial({
|
|
39044
39104
|
material: boardData?.material,
|
|
39045
39105
|
color: edgeColor,
|
|
39046
|
-
side:
|
|
39106
|
+
side: THREE61.DoubleSide
|
|
39047
39107
|
});
|
|
39048
|
-
const mesh = new
|
|
39108
|
+
const mesh = new THREE61.Mesh(geometry, material);
|
|
39049
39109
|
scene.add(mesh);
|
|
39050
39110
|
}
|
|
39051
39111
|
}
|
|
39052
|
-
const gridColor = new
|
|
39053
|
-
const gridHelper = new
|
|
39112
|
+
const gridColor = new THREE61.Color(8947848);
|
|
39113
|
+
const gridHelper = new THREE61.GridHelper(100, 100, gridColor, gridColor);
|
|
39054
39114
|
gridHelper.rotation.x = Math.PI / 2;
|
|
39055
39115
|
const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
|
|
39056
39116
|
for (const mat of materials) {
|
|
39057
39117
|
mat.transparent = true;
|
|
39058
39118
|
mat.opacity = 0.3;
|
|
39059
|
-
if (mat instanceof
|
|
39119
|
+
if (mat instanceof THREE61.LineBasicMaterial) {
|
|
39060
39120
|
mat.color = gridColor;
|
|
39061
39121
|
mat.vertexColors = false;
|
|
39062
39122
|
}
|
|
39063
39123
|
}
|
|
39064
39124
|
scene.add(gridHelper);
|
|
39065
|
-
const box = new
|
|
39066
|
-
const center = box.getCenter(new
|
|
39067
|
-
const size4 = box.getSize(new
|
|
39125
|
+
const box = new THREE61.Box3().setFromObject(scene);
|
|
39126
|
+
const center = box.getCenter(new THREE61.Vector3());
|
|
39127
|
+
const size4 = box.getSize(new THREE61.Vector3());
|
|
39068
39128
|
scene.position.sub(center);
|
|
39069
39129
|
const maxDim = Math.max(size4.x, size4.y, size4.z);
|
|
39070
39130
|
if (maxDim > 0) {
|
|
@@ -39082,7 +39142,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39082
39142
|
|
|
39083
39143
|
// src/hooks/exporter/gltf.ts
|
|
39084
39144
|
import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
|
|
39085
|
-
import { useEffect as
|
|
39145
|
+
import { useEffect as useEffect52, useState as useState43, useMemo as useMemo37, useCallback as useCallback26 } from "react";
|
|
39086
39146
|
function useSaveGltfAs(options = {}) {
|
|
39087
39147
|
const parse2 = useParser(options);
|
|
39088
39148
|
const link = useMemo37(() => document.createElement("a"), []);
|
|
@@ -39095,7 +39155,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
39095
39155
|
link.dispatchEvent(new MouseEvent("click"));
|
|
39096
39156
|
URL.revokeObjectURL(url);
|
|
39097
39157
|
};
|
|
39098
|
-
|
|
39158
|
+
useEffect52(
|
|
39099
39159
|
() => () => {
|
|
39100
39160
|
link.remove();
|
|
39101
39161
|
instance = null;
|
|
@@ -39116,7 +39176,7 @@ function useExportGltfUrl(options = {}) {
|
|
|
39116
39176
|
(instance) => parse2(instance).then(setUrl).catch(setError),
|
|
39117
39177
|
[]
|
|
39118
39178
|
);
|
|
39119
|
-
|
|
39179
|
+
useEffect52(() => () => URL.revokeObjectURL(url), [url]);
|
|
39120
39180
|
return [ref, url, error];
|
|
39121
39181
|
}
|
|
39122
39182
|
function useParser(options = {}) {
|