@tscircuit/3d-viewer 0.0.624 → 0.0.626
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 +782 -702
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -18978,9 +18978,44 @@ var useHiddenCadComponents = (circuitKey) => {
|
|
|
18978
18978
|
};
|
|
18979
18979
|
};
|
|
18980
18980
|
|
|
18981
|
+
// src/utils/configure-runtime-font.ts
|
|
18982
|
+
import { configureTextBuilder } from "troika-three-text";
|
|
18983
|
+
|
|
18984
|
+
// src/utils/get-runtime-asset-url.ts
|
|
18985
|
+
function getRuntimeAssetUrl(packageName, version, path) {
|
|
18986
|
+
const baseUrl = typeof window !== "undefined" ? window.TSCIRCUIT_JSCDN_BASE_URL : void 0;
|
|
18987
|
+
if (!baseUrl) {
|
|
18988
|
+
return `https://cdn.jsdelivr.net/npm/${packageName}@${version}/${path}`;
|
|
18989
|
+
}
|
|
18990
|
+
return new URL(
|
|
18991
|
+
`${baseUrl.replace(/\/+$/, "")}/${packageName}/${version}/${path}`,
|
|
18992
|
+
window.location.href
|
|
18993
|
+
).href;
|
|
18994
|
+
}
|
|
18995
|
+
|
|
18996
|
+
// src/utils/configure-runtime-font.ts
|
|
18997
|
+
var configured = false;
|
|
18998
|
+
function configureRuntimeFont() {
|
|
18999
|
+
if (configured || typeof window === "undefined" || !window.TSCIRCUIT_JSCDN_BASE_URL)
|
|
19000
|
+
return;
|
|
19001
|
+
configureTextBuilder({
|
|
19002
|
+
defaultFontURL: getRuntimeAssetUrl(
|
|
19003
|
+
"three",
|
|
19004
|
+
"0.165.0",
|
|
19005
|
+
"examples/fonts/ttf/kenpixel.ttf"
|
|
19006
|
+
),
|
|
19007
|
+
unicodeFontsURL: getRuntimeAssetUrl(
|
|
19008
|
+
"troika-three-text",
|
|
19009
|
+
"0.52.5",
|
|
19010
|
+
"unicode-fonts/"
|
|
19011
|
+
)
|
|
19012
|
+
});
|
|
19013
|
+
configured = true;
|
|
19014
|
+
}
|
|
19015
|
+
|
|
18981
19016
|
// src/CadViewer.tsx
|
|
18982
|
-
import { useCallback as useCallback25, useContext as useContext11, useEffect as
|
|
18983
|
-
import * as
|
|
19017
|
+
import { useCallback as useCallback25, useContext as useContext11, useEffect as useEffect51, useRef as useRef29, useState as useState42 } from "react";
|
|
19018
|
+
import * as THREE57 from "three";
|
|
18984
19019
|
|
|
18985
19020
|
// src/hooks/use-convert-children-to-soup.ts
|
|
18986
19021
|
import { Circuit } from "@tscircuit/core";
|
|
@@ -20129,7 +20164,6 @@ function occtMeshesToGroup(meshes) {
|
|
|
20129
20164
|
// src/three-components/StepModel.tsx
|
|
20130
20165
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
20131
20166
|
var occtImportPromise;
|
|
20132
|
-
var OCCT_CDN_BASE_URL = "https://cdn.jsdelivr.net/npm/occt-import-js@0.0.23/dist";
|
|
20133
20167
|
function resolveOcctFactory(candidate) {
|
|
20134
20168
|
if (typeof candidate === "function") {
|
|
20135
20169
|
return candidate;
|
|
@@ -20141,13 +20175,19 @@ function resolveOcctFactory(candidate) {
|
|
|
20141
20175
|
}
|
|
20142
20176
|
async function loadOcctImport() {
|
|
20143
20177
|
if (!occtImportPromise) {
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20178
|
+
occtImportPromise = (async () => {
|
|
20179
|
+
const imported = await import(
|
|
20180
|
+
/* @vite-ignore */
|
|
20181
|
+
/* webpackIgnore: true */
|
|
20182
|
+
getRuntimeAssetUrl("occt-import-js", "0.0.23", "+esm")
|
|
20183
|
+
);
|
|
20184
|
+
const factory = resolveOcctFactory(imported);
|
|
20185
|
+
return factory({
|
|
20186
|
+
locateFile: (path) => getRuntimeAssetUrl("occt-import-js", "0.0.23", `dist/${path}`)
|
|
20187
|
+
});
|
|
20188
|
+
})().catch((error) => {
|
|
20189
|
+
occtImportPromise = void 0;
|
|
20190
|
+
throw error;
|
|
20151
20191
|
});
|
|
20152
20192
|
}
|
|
20153
20193
|
return occtImportPromise;
|
|
@@ -20945,13 +20985,13 @@ var AnyCadComponent = ({
|
|
|
20945
20985
|
};
|
|
20946
20986
|
|
|
20947
20987
|
// src/CadViewerContainer.tsx
|
|
20948
|
-
import { forwardRef as forwardRef2, useEffect as
|
|
20949
|
-
import * as
|
|
20988
|
+
import { forwardRef as forwardRef2, useEffect as useEffect22, useMemo as useMemo17, useState as useState13 } from "react";
|
|
20989
|
+
import * as THREE27 from "three";
|
|
20950
20990
|
|
|
20951
20991
|
// package.json
|
|
20952
20992
|
var package_default = {
|
|
20953
20993
|
name: "@tscircuit/3d-viewer",
|
|
20954
|
-
version: "0.0.
|
|
20994
|
+
version: "0.0.625",
|
|
20955
20995
|
repository: {
|
|
20956
20996
|
type: "git",
|
|
20957
20997
|
url: "https://github.com/tscircuit/3d-viewer"
|
|
@@ -21105,44 +21145,79 @@ import {
|
|
|
21105
21145
|
useRef as useRef3,
|
|
21106
21146
|
useState as useState11
|
|
21107
21147
|
} from "react";
|
|
21148
|
+
import * as THREE16 from "three";
|
|
21149
|
+
|
|
21150
|
+
// src/utils/camera-session-storage.ts
|
|
21108
21151
|
import * as THREE15 from "three";
|
|
21109
|
-
|
|
21110
|
-
|
|
21111
|
-
|
|
21152
|
+
var CAMERA_SESSION_STORAGE_KEY = "cadViewerCameraStateSession";
|
|
21153
|
+
function getCameraSessionStorageKey(cameraSessionScope) {
|
|
21154
|
+
if (!cameraSessionScope) return CAMERA_SESSION_STORAGE_KEY;
|
|
21155
|
+
return `${CAMERA_SESSION_STORAGE_KEY}:${cameraSessionScope}`;
|
|
21156
|
+
}
|
|
21157
|
+
function saveCameraSession({
|
|
21158
|
+
camera,
|
|
21159
|
+
controls,
|
|
21160
|
+
cameraSessionScope
|
|
21161
|
+
}) {
|
|
21112
21162
|
try {
|
|
21113
|
-
const
|
|
21163
|
+
const storedCameraSession = {
|
|
21114
21164
|
position: camera.position.toArray(),
|
|
21115
21165
|
quaternion: camera.quaternion.toArray(),
|
|
21116
21166
|
up: camera.up.toArray(),
|
|
21117
|
-
fov: camera.fov
|
|
21167
|
+
fov: camera instanceof THREE15.PerspectiveCamera ? camera.fov : 50,
|
|
21118
21168
|
target: controls.target.toArray()
|
|
21119
21169
|
};
|
|
21120
|
-
sessionStorage.setItem(
|
|
21121
|
-
|
|
21122
|
-
|
|
21170
|
+
sessionStorage.setItem(
|
|
21171
|
+
getCameraSessionStorageKey(cameraSessionScope),
|
|
21172
|
+
JSON.stringify(storedCameraSession)
|
|
21173
|
+
);
|
|
21174
|
+
} catch (error) {
|
|
21175
|
+
console.warn("Failed to save camera:", error);
|
|
21123
21176
|
}
|
|
21124
|
-
}
|
|
21125
|
-
|
|
21177
|
+
}
|
|
21178
|
+
function loadCameraSession({
|
|
21179
|
+
camera,
|
|
21180
|
+
controls,
|
|
21181
|
+
cameraSessionScope
|
|
21182
|
+
}) {
|
|
21126
21183
|
try {
|
|
21127
|
-
const
|
|
21128
|
-
|
|
21129
|
-
|
|
21130
|
-
|
|
21131
|
-
|
|
21132
|
-
|
|
21133
|
-
|
|
21134
|
-
|
|
21135
|
-
|
|
21136
|
-
|
|
21137
|
-
|
|
21138
|
-
|
|
21184
|
+
const storedCameraSessionJson = sessionStorage.getItem(
|
|
21185
|
+
getCameraSessionStorageKey(cameraSessionScope)
|
|
21186
|
+
);
|
|
21187
|
+
if (!storedCameraSessionJson) return false;
|
|
21188
|
+
const storedCameraSession = JSON.parse(
|
|
21189
|
+
storedCameraSessionJson
|
|
21190
|
+
);
|
|
21191
|
+
camera.position.fromArray(storedCameraSession.position);
|
|
21192
|
+
camera.quaternion.fromArray(storedCameraSession.quaternion);
|
|
21193
|
+
camera.up.fromArray(storedCameraSession.up);
|
|
21194
|
+
if (camera instanceof THREE15.PerspectiveCamera) {
|
|
21195
|
+
camera.fov = storedCameraSession.fov;
|
|
21196
|
+
camera.updateProjectionMatrix();
|
|
21197
|
+
}
|
|
21198
|
+
controls.target.fromArray(storedCameraSession.target);
|
|
21139
21199
|
controls.update();
|
|
21140
21200
|
camera.updateMatrixWorld();
|
|
21141
21201
|
return true;
|
|
21142
|
-
} catch (
|
|
21143
|
-
console.warn("Failed to restore camera:",
|
|
21202
|
+
} catch (error) {
|
|
21203
|
+
console.warn("Failed to restore camera:", error);
|
|
21144
21204
|
return false;
|
|
21145
21205
|
}
|
|
21206
|
+
}
|
|
21207
|
+
|
|
21208
|
+
// src/contexts/CameraControllerContext.tsx
|
|
21209
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
21210
|
+
function resolveCameraSessionContext(cameraSessionContext) {
|
|
21211
|
+
if ("controls" in cameraSessionContext) return cameraSessionContext;
|
|
21212
|
+
return { controls: cameraSessionContext };
|
|
21213
|
+
}
|
|
21214
|
+
var saveCameraToSession = (camera, cameraSessionContext) => {
|
|
21215
|
+
const { controls, cameraSessionScope } = resolveCameraSessionContext(cameraSessionContext);
|
|
21216
|
+
saveCameraSession({ camera, controls, cameraSessionScope });
|
|
21217
|
+
};
|
|
21218
|
+
var loadCameraFromSession = (camera, cameraSessionContext) => {
|
|
21219
|
+
const { controls, cameraSessionScope } = resolveCameraSessionContext(cameraSessionContext);
|
|
21220
|
+
return loadCameraSession({ camera, controls, cameraSessionScope });
|
|
21146
21221
|
};
|
|
21147
21222
|
var CameraControllerContext = createContext6(void 0);
|
|
21148
21223
|
var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition, initialCameraType }) => {
|
|
@@ -21154,7 +21229,7 @@ var CameraControllerProvider = ({ children, defaultTarget, initialCameraPosition
|
|
|
21154
21229
|
);
|
|
21155
21230
|
const [cameraPosition, setCameraPosition] = useState11(initialCameraPosition ?? null);
|
|
21156
21231
|
const [cameraRotation, setCameraRotation] = useState11(
|
|
21157
|
-
new
|
|
21232
|
+
new THREE16.Euler(0, 0, 0)
|
|
21158
21233
|
);
|
|
21159
21234
|
const baseDistance = useMemo11(() => {
|
|
21160
21235
|
const [x, y, z] = initialCameraPosition ?? [5, -5, 5];
|
|
@@ -21308,7 +21383,7 @@ var useCameraController = () => {
|
|
|
21308
21383
|
|
|
21309
21384
|
// src/hooks/cameraAnimation.ts
|
|
21310
21385
|
import { useCallback as useCallback5, useEffect as useEffect14, useRef as useRef4 } from "react";
|
|
21311
|
-
import * as
|
|
21386
|
+
import * as THREE17 from "three";
|
|
21312
21387
|
var easeInOutCubic = (t) => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
21313
21388
|
var CameraAnimatorWithContext = () => {
|
|
21314
21389
|
const {
|
|
@@ -21319,24 +21394,24 @@ var CameraAnimatorWithContext = () => {
|
|
|
21319
21394
|
getPresetConfig
|
|
21320
21395
|
} = useCameraController();
|
|
21321
21396
|
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
|
|
21397
|
+
const tempQuaternion = useRef4(new THREE17.Quaternion());
|
|
21398
|
+
const tempTarget = useRef4(new THREE17.Vector3());
|
|
21399
|
+
const tempUp = useRef4(new THREE17.Vector3());
|
|
21400
|
+
const tempRoll = useRef4(new THREE17.Quaternion());
|
|
21401
|
+
const tempRollTarget = useRef4(new THREE17.Quaternion());
|
|
21402
|
+
const baseOrientationHelper = useRef4(new THREE17.Object3D());
|
|
21403
|
+
const orientationHelper = useRef4(new THREE17.Object3D());
|
|
21329
21404
|
const animateTo = useCallback5(
|
|
21330
21405
|
({ position, target, up, durationMs = 600 }) => {
|
|
21331
21406
|
if (!mainCameraRef.current) return;
|
|
21332
21407
|
const currentTarget = controlsRef.current?.target ?? defaultTarget;
|
|
21333
|
-
const toPosition = new
|
|
21408
|
+
const toPosition = new THREE17.Vector3(
|
|
21334
21409
|
position[0],
|
|
21335
21410
|
position[1],
|
|
21336
21411
|
position[2]
|
|
21337
21412
|
);
|
|
21338
|
-
const resolvedTarget = target ? new
|
|
21339
|
-
const resolvedUp = new
|
|
21413
|
+
const resolvedTarget = target ? new THREE17.Vector3(target[0], target[1], target[2]) : defaultTarget.clone();
|
|
21414
|
+
const resolvedUp = new THREE17.Vector3(...up ?? [0, 0, 1]).normalize();
|
|
21340
21415
|
const toOrientationHelper = orientationHelper.current;
|
|
21341
21416
|
toOrientationHelper.position.copy(toPosition);
|
|
21342
21417
|
toOrientationHelper.up.copy(resolvedUp);
|
|
@@ -21448,43 +21523,63 @@ var CameraAnimatorWithContext = () => {
|
|
|
21448
21523
|
};
|
|
21449
21524
|
|
|
21450
21525
|
// src/hooks/useCameraSession.ts
|
|
21451
|
-
import { useCallback as useCallback6, useRef as useRef5 } from "react";
|
|
21452
|
-
var
|
|
21526
|
+
import { useCallback as useCallback6, useEffect as useEffect15, useRef as useRef5 } from "react";
|
|
21527
|
+
var CAMERA_SESSION_NOT_RESTORED = /* @__PURE__ */ Symbol("camera-session-not-restored");
|
|
21528
|
+
var useCameraSession = ({
|
|
21529
|
+
cameraSessionScope
|
|
21530
|
+
} = {}) => {
|
|
21453
21531
|
const { controlsRef } = useCameraController();
|
|
21454
21532
|
const cameraRef = useRef5(null);
|
|
21455
|
-
const
|
|
21533
|
+
const restoredCameraSessionScopeRef = useRef5(CAMERA_SESSION_NOT_RESTORED);
|
|
21456
21534
|
const saveTimeoutRef = useRef5(null);
|
|
21535
|
+
useEffect15(() => {
|
|
21536
|
+
return () => {
|
|
21537
|
+
if (saveTimeoutRef.current !== null) {
|
|
21538
|
+
clearTimeout(saveTimeoutRef.current);
|
|
21539
|
+
saveTimeoutRef.current = null;
|
|
21540
|
+
}
|
|
21541
|
+
};
|
|
21542
|
+
}, [cameraSessionScope]);
|
|
21457
21543
|
const handleCameraCreated = useCallback6(
|
|
21458
21544
|
(camera) => {
|
|
21459
21545
|
cameraRef.current = camera;
|
|
21460
|
-
if (
|
|
21461
|
-
const restored = loadCameraFromSession(camera,
|
|
21546
|
+
if (restoredCameraSessionScopeRef.current !== cameraSessionScope && controlsRef.current) {
|
|
21547
|
+
const restored = loadCameraFromSession(camera, {
|
|
21548
|
+
controls: controlsRef.current,
|
|
21549
|
+
cameraSessionScope
|
|
21550
|
+
});
|
|
21551
|
+
restoredCameraSessionScopeRef.current = cameraSessionScope;
|
|
21462
21552
|
if (restored) {
|
|
21463
|
-
|
|
21553
|
+
return;
|
|
21464
21554
|
}
|
|
21465
21555
|
}
|
|
21466
21556
|
},
|
|
21467
|
-
[controlsRef]
|
|
21557
|
+
[cameraSessionScope, controlsRef]
|
|
21468
21558
|
);
|
|
21469
21559
|
const handleControlsChange = useCallback6(() => {
|
|
21470
21560
|
if (!cameraRef.current || !controlsRef.current) return;
|
|
21471
|
-
if (
|
|
21472
|
-
const restored = loadCameraFromSession(
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
);
|
|
21561
|
+
if (restoredCameraSessionScopeRef.current !== cameraSessionScope) {
|
|
21562
|
+
const restored = loadCameraFromSession(cameraRef.current, {
|
|
21563
|
+
controls: controlsRef.current,
|
|
21564
|
+
cameraSessionScope
|
|
21565
|
+
});
|
|
21566
|
+
restoredCameraSessionScopeRef.current = cameraSessionScope;
|
|
21476
21567
|
if (restored) {
|
|
21477
|
-
cameraRestoredRef.current = true;
|
|
21478
21568
|
return;
|
|
21479
21569
|
}
|
|
21480
21570
|
}
|
|
21481
|
-
|
|
21571
|
+
if (saveTimeoutRef.current !== null) {
|
|
21572
|
+
clearTimeout(saveTimeoutRef.current);
|
|
21573
|
+
}
|
|
21482
21574
|
saveTimeoutRef.current = setTimeout(() => {
|
|
21483
21575
|
if (cameraRef.current && controlsRef.current) {
|
|
21484
|
-
saveCameraToSession(cameraRef.current,
|
|
21576
|
+
saveCameraToSession(cameraRef.current, {
|
|
21577
|
+
controls: controlsRef.current,
|
|
21578
|
+
cameraSessionScope
|
|
21579
|
+
});
|
|
21485
21580
|
}
|
|
21486
21581
|
}, 150);
|
|
21487
|
-
}, [controlsRef]);
|
|
21582
|
+
}, [cameraSessionScope, controlsRef]);
|
|
21488
21583
|
return {
|
|
21489
21584
|
handleCameraCreated,
|
|
21490
21585
|
handleControlsChange
|
|
@@ -21494,14 +21589,14 @@ var useCameraSession = () => {
|
|
|
21494
21589
|
// src/react-three/Canvas.tsx
|
|
21495
21590
|
import {
|
|
21496
21591
|
useRef as useRef6,
|
|
21497
|
-
useEffect as
|
|
21592
|
+
useEffect as useEffect16,
|
|
21498
21593
|
useState as useState12,
|
|
21499
21594
|
useCallback as useCallback7,
|
|
21500
21595
|
forwardRef,
|
|
21501
21596
|
useImperativeHandle,
|
|
21502
21597
|
useMemo as useMemo12
|
|
21503
21598
|
} from "react";
|
|
21504
|
-
import * as
|
|
21599
|
+
import * as THREE19 from "three";
|
|
21505
21600
|
|
|
21506
21601
|
// src/react-three/remove-existing-canvases.ts
|
|
21507
21602
|
function removeExistingCanvases(container) {
|
|
@@ -21509,13 +21604,13 @@ function removeExistingCanvases(container) {
|
|
|
21509
21604
|
}
|
|
21510
21605
|
|
|
21511
21606
|
// src/react-three/configure-renderer.ts
|
|
21512
|
-
import * as
|
|
21607
|
+
import * as THREE18 from "three";
|
|
21513
21608
|
var configureRenderer = (renderer) => {
|
|
21514
|
-
renderer.outputColorSpace =
|
|
21515
|
-
renderer.toneMapping =
|
|
21609
|
+
renderer.outputColorSpace = THREE18.SRGBColorSpace;
|
|
21610
|
+
renderer.toneMapping = THREE18.ACESFilmicToneMapping;
|
|
21516
21611
|
renderer.toneMappingExposure = 1;
|
|
21517
21612
|
renderer.shadowMap.enabled = true;
|
|
21518
|
-
renderer.shadowMap.type =
|
|
21613
|
+
renderer.shadowMap.type = THREE18.PCFSoftShadowMap;
|
|
21519
21614
|
};
|
|
21520
21615
|
|
|
21521
21616
|
// src/react-three/Canvas.tsx
|
|
@@ -21547,16 +21642,16 @@ var Canvas = forwardRef(
|
|
|
21547
21642
|
},
|
|
21548
21643
|
[]
|
|
21549
21644
|
);
|
|
21550
|
-
const scene = useMemo12(() => new
|
|
21645
|
+
const scene = useMemo12(() => new THREE19.Scene(), []);
|
|
21551
21646
|
if (sceneProps?.up) {
|
|
21552
21647
|
scene.up.set(sceneProps.up.x, sceneProps.up.y, sceneProps.up.z);
|
|
21553
21648
|
}
|
|
21554
|
-
const rootObject = useRef6(new
|
|
21649
|
+
const rootObject = useRef6(new THREE19.Object3D());
|
|
21555
21650
|
useImperativeHandle(ref, () => rootObject.current);
|
|
21556
|
-
|
|
21651
|
+
useEffect16(() => {
|
|
21557
21652
|
if (!mountRef.current) return;
|
|
21558
21653
|
removeExistingCanvases(mountRef.current);
|
|
21559
|
-
const renderer = new
|
|
21654
|
+
const renderer = new THREE19.WebGLRenderer({ antialias: true, alpha: true });
|
|
21560
21655
|
configureRenderer(renderer);
|
|
21561
21656
|
renderer.setSize(
|
|
21562
21657
|
mountRef.current.clientWidth,
|
|
@@ -21565,7 +21660,7 @@ var Canvas = forwardRef(
|
|
|
21565
21660
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
21566
21661
|
mountRef.current.appendChild(renderer.domElement);
|
|
21567
21662
|
const aspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
|
|
21568
|
-
const camera = cameraType === "perspective" ? new
|
|
21663
|
+
const camera = cameraType === "perspective" ? new THREE19.PerspectiveCamera(75, aspect, 0.1, 1e3) : new THREE19.OrthographicCamera(
|
|
21569
21664
|
-10 * aspect,
|
|
21570
21665
|
10 * aspect,
|
|
21571
21666
|
10,
|
|
@@ -21602,7 +21697,7 @@ var Canvas = forwardRef(
|
|
|
21602
21697
|
});
|
|
21603
21698
|
onCreatedRef.current?.({ camera, renderer });
|
|
21604
21699
|
let animationFrameId;
|
|
21605
|
-
const clock = new
|
|
21700
|
+
const clock = new THREE19.Clock();
|
|
21606
21701
|
let isVisible = true;
|
|
21607
21702
|
const visibilityObserver = new IntersectionObserver(([entry]) => {
|
|
21608
21703
|
isVisible = entry?.isIntersecting ?? false;
|
|
@@ -21621,9 +21716,9 @@ var Canvas = forwardRef(
|
|
|
21621
21716
|
const handleResize = () => {
|
|
21622
21717
|
if (mountRef.current?.clientWidth && mountRef.current.clientHeight) {
|
|
21623
21718
|
const newAspect = mountRef.current.clientWidth / mountRef.current.clientHeight;
|
|
21624
|
-
if (camera instanceof
|
|
21719
|
+
if (camera instanceof THREE19.PerspectiveCamera) {
|
|
21625
21720
|
camera.aspect = newAspect;
|
|
21626
|
-
} else if (camera instanceof
|
|
21721
|
+
} else if (camera instanceof THREE19.OrthographicCamera) {
|
|
21627
21722
|
camera.left = -10 * newAspect;
|
|
21628
21723
|
camera.right = 10 * newAspect;
|
|
21629
21724
|
camera.top = 10;
|
|
@@ -21661,8 +21756,8 @@ var Canvas = forwardRef(
|
|
|
21661
21756
|
);
|
|
21662
21757
|
|
|
21663
21758
|
// src/react-three/Grid.tsx
|
|
21664
|
-
import { useEffect as
|
|
21665
|
-
import * as
|
|
21759
|
+
import { useEffect as useEffect17, useMemo as useMemo13 } from "react";
|
|
21760
|
+
import * as THREE20 from "three";
|
|
21666
21761
|
var vertexShader = `
|
|
21667
21762
|
varying vec3 worldPosition;
|
|
21668
21763
|
void main() {
|
|
@@ -21708,24 +21803,24 @@ var Grid = ({
|
|
|
21708
21803
|
const { scene, camera } = useThree();
|
|
21709
21804
|
const size4 = 1e3;
|
|
21710
21805
|
const gridMesh = useMemo13(() => {
|
|
21711
|
-
const geometry = new
|
|
21806
|
+
const geometry = new THREE20.PlaneGeometry(size4, size4);
|
|
21712
21807
|
geometry.rotateX(-Math.PI / 2);
|
|
21713
|
-
const material = new
|
|
21808
|
+
const material = new THREE20.ShaderMaterial({
|
|
21714
21809
|
vertexShader,
|
|
21715
21810
|
fragmentShader,
|
|
21716
21811
|
uniforms: {
|
|
21717
21812
|
cellSize: { value: cellSize },
|
|
21718
21813
|
sectionSize: { value: sectionSize },
|
|
21719
|
-
gridColor: { value: new
|
|
21720
|
-
sectionColor: { value: new
|
|
21814
|
+
gridColor: { value: new THREE20.Color(15658734) },
|
|
21815
|
+
sectionColor: { value: new THREE20.Color(13421823) },
|
|
21721
21816
|
fadeDistance: { value: 100 },
|
|
21722
21817
|
// Fade out based on sectionSize
|
|
21723
21818
|
fadeStrength: { value: 1.5 }
|
|
21724
21819
|
},
|
|
21725
21820
|
transparent: true,
|
|
21726
|
-
side:
|
|
21821
|
+
side: THREE20.DoubleSide
|
|
21727
21822
|
});
|
|
21728
|
-
const mesh = new
|
|
21823
|
+
const mesh = new THREE20.Mesh(geometry, material);
|
|
21729
21824
|
if (rotation) {
|
|
21730
21825
|
mesh.rotation.fromArray(rotation);
|
|
21731
21826
|
}
|
|
@@ -21736,7 +21831,7 @@ var Grid = ({
|
|
|
21736
21831
|
gridMesh.position.set(camera.position.x, camera.position.y, 0);
|
|
21737
21832
|
}
|
|
21738
21833
|
});
|
|
21739
|
-
|
|
21834
|
+
useEffect17(() => {
|
|
21740
21835
|
if (!scene || !gridMesh) return;
|
|
21741
21836
|
scene.add(gridMesh);
|
|
21742
21837
|
return () => {
|
|
@@ -21753,8 +21848,8 @@ var Grid = ({
|
|
|
21753
21848
|
};
|
|
21754
21849
|
|
|
21755
21850
|
// src/react-three/Lights.tsx
|
|
21756
|
-
import { useEffect as
|
|
21757
|
-
import * as
|
|
21851
|
+
import { useEffect as useEffect18, useMemo as useMemo14 } from "react";
|
|
21852
|
+
import * as THREE21 from "three";
|
|
21758
21853
|
var UNDERSIDE_LIGHT_FACTOR = 0.75;
|
|
21759
21854
|
var Lights = ({
|
|
21760
21855
|
boardDimensions,
|
|
@@ -21764,7 +21859,7 @@ var Lights = ({
|
|
|
21764
21859
|
}) => {
|
|
21765
21860
|
const { scene } = useThree();
|
|
21766
21861
|
const lightRig = useMemo14(() => {
|
|
21767
|
-
const rig = new
|
|
21862
|
+
const rig = new THREE21.Group();
|
|
21768
21863
|
rig.name = "cad-viewer-light-rig";
|
|
21769
21864
|
const centerX = boardCenter?.x ?? 0;
|
|
21770
21865
|
const centerY = boardCenter?.y ?? 0;
|
|
@@ -21776,14 +21871,14 @@ var Lights = ({
|
|
|
21776
21871
|
const shadowHalfSize = largestBoardDimension * 0.8;
|
|
21777
21872
|
const lightDistance = largestBoardDimension;
|
|
21778
21873
|
const keyLightDistance = largestBoardDimension * 1.7;
|
|
21779
|
-
const ambientLight = new
|
|
21874
|
+
const ambientLight = new THREE21.AmbientLight(16186360, 0.22);
|
|
21780
21875
|
ambientLight.name = "cad-viewer-soft-ambient";
|
|
21781
21876
|
rig.add(ambientLight);
|
|
21782
|
-
const hemisphereLight = new
|
|
21877
|
+
const hemisphereLight = new THREE21.HemisphereLight(15004141, 1581597, 0.2);
|
|
21783
21878
|
hemisphereLight.name = "cad-viewer-hemisphere";
|
|
21784
21879
|
rig.add(hemisphereLight);
|
|
21785
21880
|
const addDirectionalLight = (name, color, intensity, position, castShadow = false) => {
|
|
21786
|
-
const light = new
|
|
21881
|
+
const light = new THREE21.DirectionalLight(color, intensity);
|
|
21787
21882
|
light.name = name;
|
|
21788
21883
|
light.position.set(
|
|
21789
21884
|
centerX + position[0],
|
|
@@ -21857,17 +21952,17 @@ var Lights = ({
|
|
|
21857
21952
|
);
|
|
21858
21953
|
return rig;
|
|
21859
21954
|
}, [boardCenter, boardDimensions, shadowsEnabled]);
|
|
21860
|
-
|
|
21955
|
+
useEffect18(() => {
|
|
21861
21956
|
const previousBackground = scene.background;
|
|
21862
21957
|
const previousEnvironment = scene.environment;
|
|
21863
|
-
scene.background = darkBackgroundEnabled ? new
|
|
21958
|
+
scene.background = darkBackgroundEnabled ? new THREE21.Color(1053456) : null;
|
|
21864
21959
|
scene.environment = null;
|
|
21865
21960
|
return () => {
|
|
21866
21961
|
scene.background = previousBackground;
|
|
21867
21962
|
scene.environment = previousEnvironment;
|
|
21868
21963
|
};
|
|
21869
21964
|
}, [darkBackgroundEnabled, scene]);
|
|
21870
|
-
|
|
21965
|
+
useEffect18(() => {
|
|
21871
21966
|
if (!scene) return;
|
|
21872
21967
|
scene.add(lightRig);
|
|
21873
21968
|
return () => {
|
|
@@ -21878,12 +21973,12 @@ var Lights = ({
|
|
|
21878
21973
|
};
|
|
21879
21974
|
|
|
21880
21975
|
// src/react-three/OrbitControls.tsx
|
|
21881
|
-
import { useEffect as
|
|
21882
|
-
import * as
|
|
21976
|
+
import { useEffect as useEffect19, useMemo as useMemo15 } from "react";
|
|
21977
|
+
import * as THREE23 from "three";
|
|
21883
21978
|
import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
|
21884
21979
|
|
|
21885
21980
|
// src/react-three/infinite-dolly.ts
|
|
21886
|
-
import * as
|
|
21981
|
+
import * as THREE22 from "three";
|
|
21887
21982
|
var MINIMUM_DOLLY_DISTANCE_RATIO = 0.05;
|
|
21888
21983
|
var getMinimumDollyDistance = ({
|
|
21889
21984
|
camera,
|
|
@@ -21897,12 +21992,12 @@ var applyInfiniteDolly = ({
|
|
|
21897
21992
|
controls,
|
|
21898
21993
|
minimumDollyDistance
|
|
21899
21994
|
}) => {
|
|
21900
|
-
if (!(camera instanceof
|
|
21995
|
+
if (!(camera instanceof THREE22.PerspectiveCamera)) return false;
|
|
21901
21996
|
const orbitDistance = controls.getDistance();
|
|
21902
21997
|
if (Number.isFinite(orbitDistance) && orbitDistance >= minimumDollyDistance) {
|
|
21903
21998
|
return false;
|
|
21904
21999
|
}
|
|
21905
|
-
const viewDirection = new
|
|
22000
|
+
const viewDirection = new THREE22.Vector3();
|
|
21906
22001
|
camera.getWorldDirection(viewDirection);
|
|
21907
22002
|
controls.target.copy(camera.position).addScaledVector(viewDirection, minimumDollyDistance);
|
|
21908
22003
|
return true;
|
|
@@ -21927,7 +22022,7 @@ var OrbitControls = ({
|
|
|
21927
22022
|
return new ThreeOrbitControls(camera, renderer.domElement);
|
|
21928
22023
|
}, [camera, renderer]);
|
|
21929
22024
|
const minimumDollyDistance = useMemo15(() => {
|
|
21930
|
-
if (!controls || !(camera instanceof
|
|
22025
|
+
if (!controls || !(camera instanceof THREE23.PerspectiveCamera)) {
|
|
21931
22026
|
return Number.EPSILON;
|
|
21932
22027
|
}
|
|
21933
22028
|
const initialOrbitDistance = target ? Math.hypot(
|
|
@@ -21937,11 +22032,11 @@ var OrbitControls = ({
|
|
|
21937
22032
|
) : controls.getDistance();
|
|
21938
22033
|
return getMinimumDollyDistance({ camera, initialOrbitDistance });
|
|
21939
22034
|
}, [camera, controls, target]);
|
|
21940
|
-
|
|
22035
|
+
useEffect19(() => {
|
|
21941
22036
|
onControlsChange?.(controls ?? null);
|
|
21942
22037
|
return () => onControlsChange?.(null);
|
|
21943
22038
|
}, [controls, onControlsChange]);
|
|
21944
|
-
|
|
22039
|
+
useEffect19(() => {
|
|
21945
22040
|
if (!controls) return;
|
|
21946
22041
|
const handleChange = () => {
|
|
21947
22042
|
onControlsChange?.(controls);
|
|
@@ -21951,7 +22046,7 @@ var OrbitControls = ({
|
|
|
21951
22046
|
controls.removeEventListener("change", handleChange);
|
|
21952
22047
|
};
|
|
21953
22048
|
}, [controls, onControlsChange]);
|
|
21954
|
-
|
|
22049
|
+
useEffect19(() => {
|
|
21955
22050
|
if (!controls) return;
|
|
21956
22051
|
controls.autoRotate = autoRotate || false;
|
|
21957
22052
|
controls.autoRotateSpeed = autoRotateSpeed || 1;
|
|
@@ -21962,9 +22057,9 @@ var OrbitControls = ({
|
|
|
21962
22057
|
if (dampingFactor !== void 0) controls.dampingFactor = dampingFactor;
|
|
21963
22058
|
controls.zoomToCursor = true;
|
|
21964
22059
|
controls.mouseButtons = {
|
|
21965
|
-
LEFT:
|
|
22060
|
+
LEFT: THREE23.MOUSE.ROTATE,
|
|
21966
22061
|
// Left click to rotate
|
|
21967
|
-
MIDDLE:
|
|
22062
|
+
MIDDLE: THREE23.MOUSE.PAN,
|
|
21968
22063
|
// Middle click to pan
|
|
21969
22064
|
RIGHT: null
|
|
21970
22065
|
// Right-click always disabled - only context menu
|
|
@@ -21984,14 +22079,14 @@ var OrbitControls = ({
|
|
|
21984
22079
|
dampingFactor,
|
|
21985
22080
|
target
|
|
21986
22081
|
]);
|
|
21987
|
-
|
|
22082
|
+
useEffect19(() => {
|
|
21988
22083
|
if (!controls || !onStart) return;
|
|
21989
22084
|
controls.addEventListener("start", onStart);
|
|
21990
22085
|
return () => {
|
|
21991
22086
|
controls.removeEventListener("start", onStart);
|
|
21992
22087
|
};
|
|
21993
22088
|
}, [controls, onStart]);
|
|
21994
|
-
|
|
22089
|
+
useEffect19(() => {
|
|
21995
22090
|
if (!controls) return;
|
|
21996
22091
|
return () => {
|
|
21997
22092
|
controls.dispose();
|
|
@@ -22087,15 +22182,15 @@ var getComparisonBounds = (type, boardDimensions, boardCenter) => {
|
|
|
22087
22182
|
};
|
|
22088
22183
|
|
|
22089
22184
|
// src/three-components/OrientationCubeCanvas.tsx
|
|
22090
|
-
import { useEffect as
|
|
22091
|
-
import * as
|
|
22185
|
+
import { useEffect as useEffect20, useRef as useRef7 } from "react";
|
|
22186
|
+
import * as THREE24 from "three";
|
|
22092
22187
|
import { Text as TroikaText } from "troika-three-text";
|
|
22093
22188
|
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
22094
22189
|
function computePointInFront(rotationVector, distance5) {
|
|
22095
|
-
const quaternion = new
|
|
22096
|
-
new
|
|
22190
|
+
const quaternion = new THREE24.Quaternion().setFromEuler(
|
|
22191
|
+
new THREE24.Euler(rotationVector.x, rotationVector.y, rotationVector.z)
|
|
22097
22192
|
);
|
|
22098
|
-
const forwardVector = new
|
|
22193
|
+
const forwardVector = new THREE24.Vector3(0, 0, 1);
|
|
22099
22194
|
forwardVector.applyQuaternion(quaternion);
|
|
22100
22195
|
const result = forwardVector.multiplyScalar(distance5);
|
|
22101
22196
|
return result;
|
|
@@ -22103,36 +22198,36 @@ function computePointInFront(rotationVector, distance5) {
|
|
|
22103
22198
|
var OrientationCubeCanvas = () => {
|
|
22104
22199
|
const { mainCameraRef } = useCameraController();
|
|
22105
22200
|
const containerRef = useRef7(null);
|
|
22106
|
-
|
|
22201
|
+
useEffect20(() => {
|
|
22107
22202
|
if (!containerRef.current) return;
|
|
22108
22203
|
const container = containerRef.current;
|
|
22109
22204
|
const canvas = document.createElement("canvas");
|
|
22110
22205
|
container.appendChild(canvas);
|
|
22111
|
-
const renderer = new
|
|
22206
|
+
const renderer = new THREE24.WebGLRenderer({
|
|
22112
22207
|
canvas,
|
|
22113
22208
|
antialias: true,
|
|
22114
22209
|
alpha: true
|
|
22115
22210
|
});
|
|
22116
22211
|
renderer.setSize(120, 120);
|
|
22117
22212
|
renderer.setPixelRatio(window.devicePixelRatio);
|
|
22118
|
-
const scene = new
|
|
22119
|
-
const camera = new
|
|
22213
|
+
const scene = new THREE24.Scene();
|
|
22214
|
+
const camera = new THREE24.PerspectiveCamera(75, 1, 0.1, 1e3);
|
|
22120
22215
|
camera.up.set(0, 0, 1);
|
|
22121
|
-
const ambientLight = new
|
|
22216
|
+
const ambientLight = new THREE24.AmbientLight(16777215, Math.PI / 2);
|
|
22122
22217
|
scene.add(ambientLight);
|
|
22123
|
-
const group = new
|
|
22218
|
+
const group = new THREE24.Group();
|
|
22124
22219
|
group.rotation.fromArray([Math.PI / 2, 0, 0]);
|
|
22125
22220
|
const cubeSize = 1;
|
|
22126
|
-
const box = new
|
|
22127
|
-
new
|
|
22128
|
-
new
|
|
22221
|
+
const box = new THREE24.Mesh(
|
|
22222
|
+
new THREE24.BoxGeometry(cubeSize, cubeSize, cubeSize),
|
|
22223
|
+
new THREE24.MeshStandardMaterial({ color: "white" })
|
|
22129
22224
|
);
|
|
22130
22225
|
group.add(box);
|
|
22131
|
-
const edges = new
|
|
22132
|
-
new
|
|
22133
|
-
new
|
|
22226
|
+
const edges = new THREE24.LineSegments(
|
|
22227
|
+
new THREE24.EdgesGeometry(
|
|
22228
|
+
new THREE24.BoxGeometry(cubeSize, cubeSize, cubeSize)
|
|
22134
22229
|
),
|
|
22135
|
-
new
|
|
22230
|
+
new THREE24.LineBasicMaterial({ color: 0, linewidth: 2 })
|
|
22136
22231
|
);
|
|
22137
22232
|
group.add(edges);
|
|
22138
22233
|
scene.add(group);
|
|
@@ -22194,7 +22289,7 @@ var OrientationCubeCanvas = () => {
|
|
|
22194
22289
|
if (!isVisible) return;
|
|
22195
22290
|
if (mainCameraRef.current) {
|
|
22196
22291
|
const cameraPosition = computePointInFront(
|
|
22197
|
-
mainCameraRef.current.rotation ?? new
|
|
22292
|
+
mainCameraRef.current.rotation ?? new THREE24.Euler(0, 0, 0),
|
|
22198
22293
|
2
|
|
22199
22294
|
);
|
|
22200
22295
|
if (!cameraPosition.equals(camera.position)) {
|
|
@@ -22243,15 +22338,15 @@ var OrientationCubeCanvas = () => {
|
|
|
22243
22338
|
};
|
|
22244
22339
|
|
|
22245
22340
|
// src/three-components/reference-object.tsx
|
|
22246
|
-
import { useEffect as
|
|
22341
|
+
import { useEffect as useEffect21, useMemo as useMemo16 } from "react";
|
|
22247
22342
|
|
|
22248
22343
|
// src/reference-objects/create-reference-object.ts
|
|
22249
|
-
import * as
|
|
22344
|
+
import * as THREE25 from "three";
|
|
22250
22345
|
var createRoundedRectangleShape = (width, height, radius) => {
|
|
22251
22346
|
const halfWidth = width / 2;
|
|
22252
22347
|
const halfHeight = height / 2;
|
|
22253
22348
|
const safeRadius = Math.min(radius, halfWidth, halfHeight);
|
|
22254
|
-
const shape = new
|
|
22349
|
+
const shape = new THREE25.Shape();
|
|
22255
22350
|
shape.moveTo(-halfWidth + safeRadius, -halfHeight);
|
|
22256
22351
|
shape.lineTo(halfWidth - safeRadius, -halfHeight);
|
|
22257
22352
|
shape.quadraticCurveTo(
|
|
@@ -22290,7 +22385,7 @@ var createRoundedPrismGeometry = (width, height, depth, radius) => {
|
|
|
22290
22385
|
);
|
|
22291
22386
|
};
|
|
22292
22387
|
var createPrismGeometryFromShape = (shape, depth) => {
|
|
22293
|
-
const geometry = new
|
|
22388
|
+
const geometry = new THREE25.ExtrudeGeometry(shape, {
|
|
22294
22389
|
depth,
|
|
22295
22390
|
bevelEnabled: false,
|
|
22296
22391
|
curveSegments: 24
|
|
@@ -22302,16 +22397,16 @@ var createPrismGeometryFromShape = (shape, depth) => {
|
|
|
22302
22397
|
var normalizeObjectToSpec = (object, type) => {
|
|
22303
22398
|
const spec = REFERENCE_OBJECT_SPECS[type];
|
|
22304
22399
|
object.updateMatrixWorld(true);
|
|
22305
|
-
const initialBounds = new
|
|
22306
|
-
const initialSize = initialBounds.getSize(new
|
|
22400
|
+
const initialBounds = new THREE25.Box3().setFromObject(object);
|
|
22401
|
+
const initialSize = initialBounds.getSize(new THREE25.Vector3());
|
|
22307
22402
|
object.scale.set(
|
|
22308
22403
|
spec.width / initialSize.x,
|
|
22309
22404
|
spec.height / initialSize.y,
|
|
22310
22405
|
spec.depth / initialSize.z
|
|
22311
22406
|
);
|
|
22312
22407
|
object.updateMatrixWorld(true);
|
|
22313
|
-
const scaledBounds = new
|
|
22314
|
-
const scaledCenter = scaledBounds.getCenter(new
|
|
22408
|
+
const scaledBounds = new THREE25.Box3().setFromObject(object);
|
|
22409
|
+
const scaledCenter = scaledBounds.getCenter(new THREE25.Vector3());
|
|
22315
22410
|
object.position.set(
|
|
22316
22411
|
-scaledCenter.x,
|
|
22317
22412
|
-scaledCenter.y,
|
|
@@ -22320,15 +22415,15 @@ var normalizeObjectToSpec = (object, type) => {
|
|
|
22320
22415
|
object.updateMatrixWorld(true);
|
|
22321
22416
|
};
|
|
22322
22417
|
var createBananaGeometry = () => {
|
|
22323
|
-
const curve = new
|
|
22324
|
-
new
|
|
22325
|
-
new
|
|
22326
|
-
new
|
|
22327
|
-
new
|
|
22328
|
-
new
|
|
22329
|
-
new
|
|
22330
|
-
new
|
|
22331
|
-
new
|
|
22418
|
+
const curve = new THREE25.CatmullRomCurve3([
|
|
22419
|
+
new THREE25.Vector3(-82, 18, 16),
|
|
22420
|
+
new THREE25.Vector3(-67, 7, 15),
|
|
22421
|
+
new THREE25.Vector3(-43, -9, 14),
|
|
22422
|
+
new THREE25.Vector3(-15, -18, 14),
|
|
22423
|
+
new THREE25.Vector3(16, -18, 14),
|
|
22424
|
+
new THREE25.Vector3(47, -8, 14.5),
|
|
22425
|
+
new THREE25.Vector3(72, 8, 16),
|
|
22426
|
+
new THREE25.Vector3(84, 19, 17)
|
|
22332
22427
|
]);
|
|
22333
22428
|
const tubularSegments = 84;
|
|
22334
22429
|
const radialSegments = 30;
|
|
@@ -22338,8 +22433,8 @@ var createBananaGeometry = () => {
|
|
|
22338
22433
|
const colors2 = [];
|
|
22339
22434
|
const uvs = [];
|
|
22340
22435
|
const indices = [];
|
|
22341
|
-
const ripeYellow = new
|
|
22342
|
-
const stemGreen = new
|
|
22436
|
+
const ripeYellow = new THREE25.Color(16766023);
|
|
22437
|
+
const stemGreen = new THREE25.Color(12038965);
|
|
22343
22438
|
for (let segment = 0; segment <= tubularSegments; segment++) {
|
|
22344
22439
|
const t = segment / tubularSegments;
|
|
22345
22440
|
const point = curve.getPointAt(t);
|
|
@@ -22354,7 +22449,7 @@ var createBananaGeometry = () => {
|
|
|
22354
22449
|
const sin = Math.sin(angle3);
|
|
22355
22450
|
const cos = Math.cos(angle3);
|
|
22356
22451
|
const ridgeScale = 1 + Math.cos(angle3 * 5 + 0.35) * 0.035;
|
|
22357
|
-
const radialNormal = new
|
|
22452
|
+
const radialNormal = new THREE25.Vector3().addScaledVector(normal, cos).addScaledVector(binormal, sin * 0.9).normalize();
|
|
22358
22453
|
const vertex = point.clone().addScaledVector(normal, cos * radius * ridgeScale).addScaledVector(binormal, sin * radius * 0.9 * ridgeScale);
|
|
22359
22454
|
positions.push(vertex.x, vertex.y, vertex.z);
|
|
22360
22455
|
normals.push(radialNormal.x, radialNormal.y, radialNormal.z);
|
|
@@ -22372,26 +22467,26 @@ var createBananaGeometry = () => {
|
|
|
22372
22467
|
indices.push(a, d, b, b, d, c);
|
|
22373
22468
|
}
|
|
22374
22469
|
}
|
|
22375
|
-
const geometry = new
|
|
22470
|
+
const geometry = new THREE25.BufferGeometry();
|
|
22376
22471
|
geometry.setIndex(indices);
|
|
22377
22472
|
geometry.setAttribute(
|
|
22378
22473
|
"position",
|
|
22379
|
-
new
|
|
22474
|
+
new THREE25.Float32BufferAttribute(positions, 3)
|
|
22380
22475
|
);
|
|
22381
|
-
geometry.setAttribute("normal", new
|
|
22382
|
-
geometry.setAttribute("color", new
|
|
22383
|
-
geometry.setAttribute("uv", new
|
|
22476
|
+
geometry.setAttribute("normal", new THREE25.Float32BufferAttribute(normals, 3));
|
|
22477
|
+
geometry.setAttribute("color", new THREE25.Float32BufferAttribute(colors2, 3));
|
|
22478
|
+
geometry.setAttribute("uv", new THREE25.Float32BufferAttribute(uvs, 2));
|
|
22384
22479
|
geometry.computeBoundingBox();
|
|
22385
22480
|
geometry.computeBoundingSphere();
|
|
22386
22481
|
return { geometry, curve };
|
|
22387
22482
|
};
|
|
22388
22483
|
var createBanana = () => {
|
|
22389
|
-
const group = new
|
|
22390
|
-
const banana = new
|
|
22484
|
+
const group = new THREE25.Group();
|
|
22485
|
+
const banana = new THREE25.Group();
|
|
22391
22486
|
const { geometry, curve } = createBananaGeometry();
|
|
22392
|
-
const peel = new
|
|
22487
|
+
const peel = new THREE25.Mesh(
|
|
22393
22488
|
geometry,
|
|
22394
|
-
new
|
|
22489
|
+
new THREE25.MeshStandardMaterial({
|
|
22395
22490
|
color: 16777215,
|
|
22396
22491
|
roughness: 0.72,
|
|
22397
22492
|
metalness: 0,
|
|
@@ -22400,9 +22495,9 @@ var createBanana = () => {
|
|
|
22400
22495
|
);
|
|
22401
22496
|
peel.name = "banana-peel";
|
|
22402
22497
|
banana.add(peel);
|
|
22403
|
-
const blossomTip = new
|
|
22404
|
-
new
|
|
22405
|
-
new
|
|
22498
|
+
const blossomTip = new THREE25.Mesh(
|
|
22499
|
+
new THREE25.SphereGeometry(3.4, 20, 12),
|
|
22500
|
+
new THREE25.MeshStandardMaterial({
|
|
22406
22501
|
color: 6242844,
|
|
22407
22502
|
roughness: 0.92
|
|
22408
22503
|
})
|
|
@@ -22413,20 +22508,20 @@ var createBanana = () => {
|
|
|
22413
22508
|
banana.add(blossomTip);
|
|
22414
22509
|
const stemLength = 11;
|
|
22415
22510
|
const stemTangent = curve.getTangentAt(1).normalize();
|
|
22416
|
-
const stem = new
|
|
22417
|
-
new
|
|
22418
|
-
new
|
|
22511
|
+
const stem = new THREE25.Mesh(
|
|
22512
|
+
new THREE25.CylinderGeometry(2.5, 4.1, stemLength, 18),
|
|
22513
|
+
new THREE25.MeshStandardMaterial({
|
|
22419
22514
|
color: 8483625,
|
|
22420
22515
|
roughness: 0.82
|
|
22421
22516
|
})
|
|
22422
22517
|
);
|
|
22423
|
-
stem.quaternion.setFromUnitVectors(new
|
|
22518
|
+
stem.quaternion.setFromUnitVectors(new THREE25.Vector3(0, 1, 0), stemTangent);
|
|
22424
22519
|
stem.position.copy(curve.getPointAt(1)).addScaledVector(stemTangent, stemLength / 2);
|
|
22425
22520
|
stem.name = "banana-stem";
|
|
22426
22521
|
banana.add(stem);
|
|
22427
|
-
const stemTip = new
|
|
22428
|
-
new
|
|
22429
|
-
new
|
|
22522
|
+
const stemTip = new THREE25.Mesh(
|
|
22523
|
+
new THREE25.SphereGeometry(2.55, 18, 10),
|
|
22524
|
+
new THREE25.MeshStandardMaterial({
|
|
22430
22525
|
color: 5981470,
|
|
22431
22526
|
roughness: 0.9
|
|
22432
22527
|
})
|
|
@@ -22440,7 +22535,7 @@ var createBanana = () => {
|
|
|
22440
22535
|
};
|
|
22441
22536
|
var createMacbookLidGeometry = (width, height, depth, radius, indentRadius) => {
|
|
22442
22537
|
const lidShape = createRoundedRectangleShape(width, height, radius);
|
|
22443
|
-
const indent = new
|
|
22538
|
+
const indent = new THREE25.Path();
|
|
22444
22539
|
indent.absarc(0, 0, indentRadius, 0, Math.PI * 2, true);
|
|
22445
22540
|
lidShape.holes.push(indent);
|
|
22446
22541
|
return createPrismGeometryFromShape(lidShape, depth);
|
|
@@ -22448,9 +22543,9 @@ var createMacbookLidGeometry = (width, height, depth, radius, indentRadius) => {
|
|
|
22448
22543
|
var createMacbookIndent = (topZ, radius) => {
|
|
22449
22544
|
const indentDepth = 0.35;
|
|
22450
22545
|
const diskDepth = 0.25;
|
|
22451
|
-
const disk = new
|
|
22452
|
-
new
|
|
22453
|
-
new
|
|
22546
|
+
const disk = new THREE25.Mesh(
|
|
22547
|
+
new THREE25.CylinderGeometry(radius - 0.15, radius - 0.15, diskDepth, 48),
|
|
22548
|
+
new THREE25.MeshStandardMaterial({
|
|
22454
22549
|
color: 10199202,
|
|
22455
22550
|
roughness: 0.48,
|
|
22456
22551
|
metalness: 0.28
|
|
@@ -22463,10 +22558,10 @@ var createMacbookIndent = (topZ, radius) => {
|
|
|
22463
22558
|
};
|
|
22464
22559
|
var createCreditCard = () => {
|
|
22465
22560
|
const spec = REFERENCE_OBJECT_SPECS["credit-card"];
|
|
22466
|
-
const group = new
|
|
22467
|
-
const body = new
|
|
22561
|
+
const group = new THREE25.Group();
|
|
22562
|
+
const body = new THREE25.Mesh(
|
|
22468
22563
|
createRoundedPrismGeometry(spec.width, spec.height, spec.depth, 3.18),
|
|
22469
|
-
new
|
|
22564
|
+
new THREE25.MeshStandardMaterial({
|
|
22470
22565
|
color: 2383272,
|
|
22471
22566
|
roughness: 0.38,
|
|
22472
22567
|
metalness: 0.08
|
|
@@ -22475,9 +22570,9 @@ var createCreditCard = () => {
|
|
|
22475
22570
|
body.name = "credit-card-body";
|
|
22476
22571
|
group.add(body);
|
|
22477
22572
|
const surfaceZ = spec.depth / 2 + 0.08;
|
|
22478
|
-
const chip = new
|
|
22573
|
+
const chip = new THREE25.Mesh(
|
|
22479
22574
|
createRoundedPrismGeometry(12, 9, 0.14, 1.2),
|
|
22480
|
-
new
|
|
22575
|
+
new THREE25.MeshStandardMaterial({
|
|
22481
22576
|
color: 14003525,
|
|
22482
22577
|
roughness: 0.3,
|
|
22483
22578
|
metalness: 0.62
|
|
@@ -22486,14 +22581,14 @@ var createCreditCard = () => {
|
|
|
22486
22581
|
chip.position.set(-21, 3, surfaceZ);
|
|
22487
22582
|
chip.name = "credit-card-chip";
|
|
22488
22583
|
group.add(chip);
|
|
22489
|
-
const stripeMaterial = new
|
|
22584
|
+
const stripeMaterial = new THREE25.MeshStandardMaterial({
|
|
22490
22585
|
color: 15331061,
|
|
22491
22586
|
roughness: 0.45,
|
|
22492
22587
|
metalness: 0.05
|
|
22493
22588
|
});
|
|
22494
22589
|
for (let index2 = 0; index2 < 4; index2++) {
|
|
22495
|
-
const stripe = new
|
|
22496
|
-
new
|
|
22590
|
+
const stripe = new THREE25.Mesh(
|
|
22591
|
+
new THREE25.BoxGeometry(index2 === 3 ? 8 : 12, 0.8, 0.1),
|
|
22497
22592
|
stripeMaterial
|
|
22498
22593
|
);
|
|
22499
22594
|
stripe.position.set(-20 + index2 * 14, -14, surfaceZ + 0.08);
|
|
@@ -22504,13 +22599,13 @@ var createCreditCard = () => {
|
|
|
22504
22599
|
};
|
|
22505
22600
|
var createMacbook = () => {
|
|
22506
22601
|
const spec = REFERENCE_OBJECT_SPECS["14in-macbook"];
|
|
22507
|
-
const group = new
|
|
22508
|
-
const aluminumMaterial = new
|
|
22602
|
+
const group = new THREE25.Group();
|
|
22603
|
+
const aluminumMaterial = new THREE25.MeshStandardMaterial({
|
|
22509
22604
|
color: 12896201,
|
|
22510
22605
|
roughness: 0.3,
|
|
22511
22606
|
metalness: 0.38
|
|
22512
22607
|
});
|
|
22513
|
-
const body = new
|
|
22608
|
+
const body = new THREE25.Mesh(
|
|
22514
22609
|
createRoundedPrismGeometry(spec.width, spec.height, 13.5, 9),
|
|
22515
22610
|
aluminumMaterial
|
|
22516
22611
|
);
|
|
@@ -22521,7 +22616,7 @@ var createMacbook = () => {
|
|
|
22521
22616
|
const lidCenterZ = 6.75;
|
|
22522
22617
|
const lidTopZ = lidCenterZ + lidDepth / 2;
|
|
22523
22618
|
const indentRadius = 12;
|
|
22524
|
-
const lid = new
|
|
22619
|
+
const lid = new THREE25.Mesh(
|
|
22525
22620
|
createMacbookLidGeometry(
|
|
22526
22621
|
spec.width - 1.8,
|
|
22527
22622
|
spec.height - 1.8,
|
|
@@ -22534,9 +22629,9 @@ var createMacbook = () => {
|
|
|
22534
22629
|
lid.position.z = lidCenterZ;
|
|
22535
22630
|
lid.name = "macbook-lid";
|
|
22536
22631
|
group.add(lid);
|
|
22537
|
-
const hinge = new
|
|
22538
|
-
new
|
|
22539
|
-
new
|
|
22632
|
+
const hinge = new THREE25.Mesh(
|
|
22633
|
+
new THREE25.BoxGeometry(spec.width - 42, 3.2, 1.2),
|
|
22634
|
+
new THREE25.MeshStandardMaterial({
|
|
22540
22635
|
color: 3158838,
|
|
22541
22636
|
roughness: 0.55,
|
|
22542
22637
|
metalness: 0.45
|
|
@@ -22546,9 +22641,9 @@ var createMacbook = () => {
|
|
|
22546
22641
|
hinge.name = "macbook-hinge";
|
|
22547
22642
|
group.add(hinge);
|
|
22548
22643
|
group.add(createMacbookIndent(lidTopZ, indentRadius));
|
|
22549
|
-
const frontNotch = new
|
|
22550
|
-
new
|
|
22551
|
-
new
|
|
22644
|
+
const frontNotch = new THREE25.Mesh(
|
|
22645
|
+
new THREE25.BoxGeometry(54, 1.2, 0.8),
|
|
22646
|
+
new THREE25.MeshStandardMaterial({
|
|
22552
22647
|
color: 6712174,
|
|
22553
22648
|
roughness: 0.45,
|
|
22554
22649
|
metalness: 0.5
|
|
@@ -22571,7 +22666,7 @@ var disposeReferenceObject = (object) => {
|
|
|
22571
22666
|
const geometries = /* @__PURE__ */ new Set();
|
|
22572
22667
|
const materials = /* @__PURE__ */ new Set();
|
|
22573
22668
|
object.traverse((child) => {
|
|
22574
|
-
if (!(child instanceof
|
|
22669
|
+
if (!(child instanceof THREE25.Mesh)) return;
|
|
22575
22670
|
geometries.add(child.geometry);
|
|
22576
22671
|
const childMaterials = Array.isArray(child.material) ? child.material : [child.material];
|
|
22577
22672
|
for (const material of childMaterials) materials.add(material);
|
|
@@ -22581,28 +22676,28 @@ var disposeReferenceObject = (object) => {
|
|
|
22581
22676
|
};
|
|
22582
22677
|
|
|
22583
22678
|
// src/reference-objects/fit-camera-to-bounds.ts
|
|
22584
|
-
import * as
|
|
22679
|
+
import * as THREE26 from "three";
|
|
22585
22680
|
var fitCameraToBounds = (camera, controls, bounds, padding = 1.18) => {
|
|
22586
22681
|
const width = Math.max(bounds.maxX - bounds.minX, 0);
|
|
22587
22682
|
const height = Math.max(bounds.maxY - bounds.minY, 0);
|
|
22588
22683
|
const depth = Math.max(bounds.maxZ - bounds.minZ, 0);
|
|
22589
|
-
const center = new
|
|
22684
|
+
const center = new THREE26.Vector3(
|
|
22590
22685
|
(bounds.minX + bounds.maxX) / 2,
|
|
22591
22686
|
(bounds.minY + bounds.maxY) / 2,
|
|
22592
22687
|
(bounds.minZ + bounds.maxZ) / 2
|
|
22593
22688
|
);
|
|
22594
22689
|
const radius = Math.max(Math.hypot(width, height, depth) / 2, 1);
|
|
22595
|
-
const previousTarget = controls?.target ?? new
|
|
22596
|
-
const direction = new
|
|
22690
|
+
const previousTarget = controls?.target ?? new THREE26.Vector3();
|
|
22691
|
+
const direction = new THREE26.Vector3(0, -0.75, 0.9).normalize();
|
|
22597
22692
|
let distance5 = Math.max(camera.position.distanceTo(previousTarget), 5);
|
|
22598
|
-
if (camera instanceof
|
|
22599
|
-
const verticalFov =
|
|
22693
|
+
if (camera instanceof THREE26.PerspectiveCamera) {
|
|
22694
|
+
const verticalFov = THREE26.MathUtils.degToRad(camera.fov);
|
|
22600
22695
|
const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
|
|
22601
22696
|
const limitingFov = Math.min(verticalFov, horizontalFov);
|
|
22602
22697
|
distance5 = radius * padding / Math.sin(limitingFov / 2);
|
|
22603
22698
|
camera.far = Math.max(camera.far, distance5 + radius * padding * 3);
|
|
22604
22699
|
camera.updateProjectionMatrix();
|
|
22605
|
-
} else if (camera instanceof
|
|
22700
|
+
} else if (camera instanceof THREE26.OrthographicCamera) {
|
|
22606
22701
|
const halfViewWidth = Math.abs(camera.right - camera.left) / 2;
|
|
22607
22702
|
const halfViewHeight = Math.abs(camera.top - camera.bottom) / 2;
|
|
22608
22703
|
camera.zoom = Math.min(
|
|
@@ -22639,7 +22734,7 @@ var ReferenceObject = ({
|
|
|
22639
22734
|
nextObject.position.set(position.x, position.y, position.z);
|
|
22640
22735
|
return nextObject;
|
|
22641
22736
|
}, [type, boardDimensions, boardCenter]);
|
|
22642
|
-
|
|
22737
|
+
useEffect21(() => {
|
|
22643
22738
|
scene.add(object);
|
|
22644
22739
|
return () => {
|
|
22645
22740
|
scene.remove(object);
|
|
@@ -22651,7 +22746,7 @@ var ReferenceObject = ({
|
|
|
22651
22746
|
var FitCameraToComparison = ({ bounds }) => {
|
|
22652
22747
|
const { camera } = useThree();
|
|
22653
22748
|
const { controlsRef } = useCameraController();
|
|
22654
|
-
|
|
22749
|
+
useEffect21(() => {
|
|
22655
22750
|
fitCameraToBounds(camera, controlsRef.current, bounds);
|
|
22656
22751
|
}, [bounds, camera, controlsRef]);
|
|
22657
22752
|
return null;
|
|
@@ -22677,6 +22772,7 @@ var CadViewerContainer = forwardRef2(
|
|
|
22677
22772
|
clickToInteractEnabled = false,
|
|
22678
22773
|
boardDimensions,
|
|
22679
22774
|
boardCenter,
|
|
22775
|
+
cameraSessionScope,
|
|
22680
22776
|
referenceObject,
|
|
22681
22777
|
onUserInteraction,
|
|
22682
22778
|
onCameraControllerReady
|
|
@@ -22689,8 +22785,8 @@ var CadViewerContainer = forwardRef2(
|
|
|
22689
22785
|
const {
|
|
22690
22786
|
handleCameraCreated,
|
|
22691
22787
|
handleControlsChange: handleSessionControlsChange
|
|
22692
|
-
} = useCameraSession();
|
|
22693
|
-
|
|
22788
|
+
} = useCameraSession({ cameraSessionScope });
|
|
22789
|
+
useEffect22(() => {
|
|
22694
22790
|
if (onCameraControllerReady) {
|
|
22695
22791
|
onCameraControllerReady(controller);
|
|
22696
22792
|
}
|
|
@@ -22722,7 +22818,7 @@ var CadViewerContainer = forwardRef2(
|
|
|
22722
22818
|
Canvas,
|
|
22723
22819
|
{
|
|
22724
22820
|
ref,
|
|
22725
|
-
scene: { up: new
|
|
22821
|
+
scene: { up: new THREE27.Vector3(0, 0, 1) },
|
|
22726
22822
|
camera: { up: [0, 0, 1], position: initialCameraPosition },
|
|
22727
22823
|
onCreated: ({ camera }) => {
|
|
22728
22824
|
mainCameraRef.current = camera;
|
|
@@ -22779,7 +22875,8 @@ var CadViewerContainer = forwardRef2(
|
|
|
22779
22875
|
),
|
|
22780
22876
|
children
|
|
22781
22877
|
]
|
|
22782
|
-
}
|
|
22878
|
+
},
|
|
22879
|
+
cameraSessionScope
|
|
22783
22880
|
),
|
|
22784
22881
|
/* @__PURE__ */ jsxs2(
|
|
22785
22882
|
"div",
|
|
@@ -22840,12 +22937,12 @@ var CadViewerContainer = forwardRef2(
|
|
|
22840
22937
|
);
|
|
22841
22938
|
|
|
22842
22939
|
// src/hooks/use-stls-from-geom.ts
|
|
22843
|
-
import { useState as useState14, useEffect as
|
|
22940
|
+
import { useState as useState14, useEffect as useEffect23 } from "react";
|
|
22844
22941
|
import stlSerializer from "@jscad/stl-serializer";
|
|
22845
22942
|
var useStlsFromGeom = (geom) => {
|
|
22846
22943
|
const [stls, setStls] = useState14([]);
|
|
22847
22944
|
const [loading, setLoading] = useState14(true);
|
|
22848
|
-
|
|
22945
|
+
useEffect23(() => {
|
|
22849
22946
|
if (!geom) return;
|
|
22850
22947
|
const generateStls = async () => {
|
|
22851
22948
|
setLoading(true);
|
|
@@ -22874,7 +22971,7 @@ var useStlsFromGeom = (geom) => {
|
|
|
22874
22971
|
};
|
|
22875
22972
|
|
|
22876
22973
|
// src/hooks/useBoardGeomBuilder.ts
|
|
22877
|
-
import { useState as useState15, useEffect as
|
|
22974
|
+
import { useState as useState15, useEffect as useEffect24, useRef as useRef8 } from "react";
|
|
22878
22975
|
|
|
22879
22976
|
// src/soup-to-3d/index.ts
|
|
22880
22977
|
var import_colors = __toESM(require_colors(), 1);
|
|
@@ -22913,7 +23010,7 @@ var createBoardGeomWithOutline = (board, depth = 1.2, options = {}) => {
|
|
|
22913
23010
|
};
|
|
22914
23011
|
|
|
22915
23012
|
// src/utils/get-board-edge-color.ts
|
|
22916
|
-
import * as
|
|
23013
|
+
import * as THREE29 from "three";
|
|
22917
23014
|
|
|
22918
23015
|
// src/geoms/constants.ts
|
|
22919
23016
|
var M = 0.01;
|
|
@@ -22946,7 +23043,7 @@ var soldermaskColors = {
|
|
|
22946
23043
|
};
|
|
22947
23044
|
|
|
22948
23045
|
// src/utils/soldermask-color.ts
|
|
22949
|
-
import * as
|
|
23046
|
+
import * as THREE28 from "three";
|
|
22950
23047
|
var SOLDERMASK_PRESET_HEX = {
|
|
22951
23048
|
red: "#650202",
|
|
22952
23049
|
blue: "#003f7d",
|
|
@@ -22977,9 +23074,9 @@ var resolveSoldermaskColor = (requestedColor) => {
|
|
|
22977
23074
|
}
|
|
22978
23075
|
const presetName = lowercaseColor;
|
|
22979
23076
|
const presetColor = SOLDERMASK_PRESET_HEX[presetName];
|
|
22980
|
-
if (presetColor) return new
|
|
22981
|
-
const isCssColor = Object.hasOwn(
|
|
22982
|
-
return isCssColor ? new
|
|
23077
|
+
if (presetColor) return new THREE28.Color(presetColor);
|
|
23078
|
+
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);
|
|
23079
|
+
return isCssColor ? new THREE28.Color(lowercaseColor) : null;
|
|
22983
23080
|
};
|
|
22984
23081
|
var resolveSoldermaskOpacity = (requestedColor) => {
|
|
22985
23082
|
const presetName = requestedColor?.trim().toLowerCase();
|
|
@@ -23006,7 +23103,7 @@ var soldermaskColorToCss = (color) => {
|
|
|
23006
23103
|
};
|
|
23007
23104
|
|
|
23008
23105
|
// src/utils/get-board-edge-color.ts
|
|
23009
|
-
var LEGACY_FR4_EDGE_COLOR = new
|
|
23106
|
+
var LEGACY_FR4_EDGE_COLOR = new THREE29.Color(1063462);
|
|
23010
23107
|
var getBoardEdgeColor = ({
|
|
23011
23108
|
material,
|
|
23012
23109
|
solder_mask_color
|
|
@@ -23015,7 +23112,7 @@ var getBoardEdgeColor = ({
|
|
|
23015
23112
|
if (soldermaskColor) return soldermaskColor;
|
|
23016
23113
|
if (material === "fr4") return LEGACY_FR4_EDGE_COLOR.clone();
|
|
23017
23114
|
const materialColor = boardMaterialColors[material] ?? colors.fr4Tan;
|
|
23018
|
-
return new
|
|
23115
|
+
return new THREE29.Color(materialColor[0], materialColor[1], materialColor[2]);
|
|
23019
23116
|
};
|
|
23020
23117
|
|
|
23021
23118
|
// src/soup-to-3d/index.ts
|
|
@@ -24363,7 +24460,7 @@ var BoardGeomBuilder = class {
|
|
|
24363
24460
|
var useBoardGeomBuilder = (circuitJson) => {
|
|
24364
24461
|
const [boardGeom, setBoardGeom] = useState15(null);
|
|
24365
24462
|
const isProcessingRef = useRef8(false);
|
|
24366
|
-
|
|
24463
|
+
useEffect24(() => {
|
|
24367
24464
|
let isCancelled = false;
|
|
24368
24465
|
if (!circuitJson) {
|
|
24369
24466
|
setBoardGeom(null);
|
|
@@ -24409,10 +24506,10 @@ var useBoardGeomBuilder = (circuitJson) => {
|
|
|
24409
24506
|
};
|
|
24410
24507
|
|
|
24411
24508
|
// src/three-components/Error3d.tsx
|
|
24412
|
-
import { useState as useState16, useCallback as useCallback8, useEffect as
|
|
24509
|
+
import { useState as useState16, useCallback as useCallback8, useEffect as useEffect26, useMemo as useMemo19 } from "react";
|
|
24413
24510
|
|
|
24414
24511
|
// src/react-three/Text.tsx
|
|
24415
|
-
import { useEffect as
|
|
24512
|
+
import { useEffect as useEffect25, useMemo as useMemo18 } from "react";
|
|
24416
24513
|
import { Text as TroikaText2 } from "troika-three-text";
|
|
24417
24514
|
var Text = ({
|
|
24418
24515
|
children,
|
|
@@ -24452,7 +24549,7 @@ var Text = ({
|
|
|
24452
24549
|
anchorY,
|
|
24453
24550
|
depthOffset
|
|
24454
24551
|
]);
|
|
24455
|
-
|
|
24552
|
+
useEffect25(() => {
|
|
24456
24553
|
const parentObject = parent || rootObject;
|
|
24457
24554
|
if (!parentObject || !mesh) return;
|
|
24458
24555
|
parentObject.add(mesh);
|
|
@@ -24465,7 +24562,7 @@ var Text = ({
|
|
|
24465
24562
|
};
|
|
24466
24563
|
|
|
24467
24564
|
// src/three-components/Error3d.tsx
|
|
24468
|
-
import * as
|
|
24565
|
+
import * as THREE30 from "three";
|
|
24469
24566
|
import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
24470
24567
|
var Error3d = ({
|
|
24471
24568
|
error,
|
|
@@ -24499,13 +24596,13 @@ var Error3d = ({
|
|
|
24499
24596
|
return [0, 0, 0];
|
|
24500
24597
|
}, [cad_component]);
|
|
24501
24598
|
const group = useMemo19(() => {
|
|
24502
|
-
const g = new
|
|
24599
|
+
const g = new THREE30.Group();
|
|
24503
24600
|
g.position.fromArray(position);
|
|
24504
24601
|
return g;
|
|
24505
24602
|
}, [position]);
|
|
24506
24603
|
group.userData.cad_component_id = cad_component?.cad_component_id;
|
|
24507
24604
|
group.userData.pcb_component_id = cad_component?.pcb_component_id;
|
|
24508
|
-
|
|
24605
|
+
useEffect26(() => {
|
|
24509
24606
|
if (!rootObject) return;
|
|
24510
24607
|
rootObject.add(group);
|
|
24511
24608
|
return () => {
|
|
@@ -24561,9 +24658,9 @@ var Error3d = ({
|
|
|
24561
24658
|
};
|
|
24562
24659
|
var ErrorBox = ({ parent }) => {
|
|
24563
24660
|
const mesh = useMemo19(() => {
|
|
24564
|
-
const m = new
|
|
24565
|
-
new
|
|
24566
|
-
new
|
|
24661
|
+
const m = new THREE30.Mesh(
|
|
24662
|
+
new THREE30.BoxGeometry(0.5, 0.5, 0.5),
|
|
24663
|
+
new THREE30.MeshStandardMaterial({
|
|
24567
24664
|
depthTest: false,
|
|
24568
24665
|
transparent: true,
|
|
24569
24666
|
color: "red",
|
|
@@ -24574,7 +24671,7 @@ var ErrorBox = ({ parent }) => {
|
|
|
24574
24671
|
m.rotation.fromArray([Math.PI / 4, Math.PI / 4, 0]);
|
|
24575
24672
|
return m;
|
|
24576
24673
|
}, []);
|
|
24577
|
-
|
|
24674
|
+
useEffect26(() => {
|
|
24578
24675
|
parent.add(mesh);
|
|
24579
24676
|
return () => {
|
|
24580
24677
|
parent.remove(mesh);
|
|
@@ -24585,7 +24682,7 @@ var ErrorBox = ({ parent }) => {
|
|
|
24585
24682
|
|
|
24586
24683
|
// src/three-components/JscadBoardTextures.tsx
|
|
24587
24684
|
import { su as su9 } from "@tscircuit/circuit-json-util";
|
|
24588
|
-
import { useEffect as
|
|
24685
|
+
import { useEffect as useEffect27, useMemo as useMemo21 } from "react";
|
|
24589
24686
|
|
|
24590
24687
|
// src/textures/open-via-holes-at-pads.ts
|
|
24591
24688
|
import { CircuitToCanvasDrawer } from "circuit-to-canvas";
|
|
@@ -24740,12 +24837,12 @@ function clearViaHolesFromSurface({
|
|
|
24740
24837
|
}
|
|
24741
24838
|
|
|
24742
24839
|
// src/textures/create-combined-board-textures.ts
|
|
24743
|
-
import * as
|
|
24840
|
+
import * as THREE43 from "three";
|
|
24744
24841
|
|
|
24745
24842
|
// src/utils/pad-texture.ts
|
|
24746
24843
|
import { su as su6 } from "@tscircuit/circuit-json-util";
|
|
24747
24844
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer2 } from "circuit-to-canvas";
|
|
24748
|
-
import * as
|
|
24845
|
+
import * as THREE31 from "three";
|
|
24749
24846
|
function createPadTextureForLayer({
|
|
24750
24847
|
layer,
|
|
24751
24848
|
circuitJson,
|
|
@@ -24825,10 +24922,10 @@ function createPadTextureForLayer({
|
|
|
24825
24922
|
drawSoldermaskTop: false,
|
|
24826
24923
|
drawSoldermaskBottom: false
|
|
24827
24924
|
});
|
|
24828
|
-
const texture = new
|
|
24925
|
+
const texture = new THREE31.CanvasTexture(canvas);
|
|
24829
24926
|
texture.generateMipmaps = true;
|
|
24830
|
-
texture.minFilter =
|
|
24831
|
-
texture.magFilter =
|
|
24927
|
+
texture.minFilter = THREE31.LinearMipmapLinearFilter;
|
|
24928
|
+
texture.magFilter = THREE31.LinearFilter;
|
|
24832
24929
|
texture.anisotropy = 16;
|
|
24833
24930
|
texture.needsUpdate = true;
|
|
24834
24931
|
return texture;
|
|
@@ -24836,7 +24933,7 @@ function createPadTextureForLayer({
|
|
|
24836
24933
|
|
|
24837
24934
|
// src/utils/panel-outline-texture.ts
|
|
24838
24935
|
import { su as su7 } from "@tscircuit/circuit-json-util";
|
|
24839
|
-
import * as
|
|
24936
|
+
import * as THREE32 from "three";
|
|
24840
24937
|
var resolvePanelIdForTexture = (circuitJson) => {
|
|
24841
24938
|
const panels = circuitJson.filter(
|
|
24842
24939
|
(e) => e.type === "pcb_panel"
|
|
@@ -24904,17 +25001,17 @@ function createPanelOutlineTextureForLayer({
|
|
|
24904
25001
|
);
|
|
24905
25002
|
}
|
|
24906
25003
|
});
|
|
24907
|
-
const texture = new
|
|
25004
|
+
const texture = new THREE32.CanvasTexture(canvas);
|
|
24908
25005
|
texture.generateMipmaps = true;
|
|
24909
|
-
texture.minFilter =
|
|
24910
|
-
texture.magFilter =
|
|
25006
|
+
texture.minFilter = THREE32.LinearMipmapLinearFilter;
|
|
25007
|
+
texture.magFilter = THREE32.LinearFilter;
|
|
24911
25008
|
texture.anisotropy = 16;
|
|
24912
25009
|
texture.needsUpdate = true;
|
|
24913
25010
|
return texture;
|
|
24914
25011
|
}
|
|
24915
25012
|
|
|
24916
25013
|
// src/utils/trace-texture.ts
|
|
24917
|
-
import * as
|
|
25014
|
+
import * as THREE33 from "three";
|
|
24918
25015
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer3 } from "circuit-to-canvas";
|
|
24919
25016
|
import { getElementRenderLayers, su as su8 } from "@tscircuit/circuit-json-util";
|
|
24920
25017
|
function createTraceTextureForLayer({
|
|
@@ -25000,10 +25097,10 @@ function createTraceTextureForLayer({
|
|
|
25000
25097
|
drawSoldermaskTop: false,
|
|
25001
25098
|
drawSoldermaskBottom: false
|
|
25002
25099
|
});
|
|
25003
|
-
const texture = new
|
|
25100
|
+
const texture = new THREE33.CanvasTexture(canvas);
|
|
25004
25101
|
texture.generateMipmaps = true;
|
|
25005
|
-
texture.minFilter =
|
|
25006
|
-
texture.magFilter =
|
|
25102
|
+
texture.minFilter = THREE33.LinearMipmapLinearFilter;
|
|
25103
|
+
texture.magFilter = THREE33.LinearFilter;
|
|
25007
25104
|
texture.anisotropy = 16;
|
|
25008
25105
|
texture.needsUpdate = true;
|
|
25009
25106
|
return texture;
|
|
@@ -25011,7 +25108,7 @@ function createTraceTextureForLayer({
|
|
|
25011
25108
|
|
|
25012
25109
|
// src/textures/create-copper-pour-texture-for-layer.ts
|
|
25013
25110
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer4 } from "circuit-to-canvas";
|
|
25014
|
-
import * as
|
|
25111
|
+
import * as THREE34 from "three";
|
|
25015
25112
|
var toRgb = (colorArr) => {
|
|
25016
25113
|
const [r = 0, g = 0, b = 0] = colorArr;
|
|
25017
25114
|
return `rgb(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(
|
|
@@ -25135,17 +25232,17 @@ function createCopperPourTextureForLayer({
|
|
|
25135
25232
|
if (!onlyCoveredBySoldermask) {
|
|
25136
25233
|
setColorAndDraw(uncoveredPours, uncoveredColor);
|
|
25137
25234
|
}
|
|
25138
|
-
const texture = new
|
|
25235
|
+
const texture = new THREE34.CanvasTexture(canvas);
|
|
25139
25236
|
texture.generateMipmaps = true;
|
|
25140
|
-
texture.minFilter =
|
|
25141
|
-
texture.magFilter =
|
|
25237
|
+
texture.minFilter = THREE34.LinearMipmapLinearFilter;
|
|
25238
|
+
texture.magFilter = THREE34.LinearFilter;
|
|
25142
25239
|
texture.anisotropy = 16;
|
|
25143
25240
|
texture.needsUpdate = true;
|
|
25144
25241
|
return texture;
|
|
25145
25242
|
}
|
|
25146
25243
|
|
|
25147
25244
|
// src/textures/create-copper-text-texture-for-layer.ts
|
|
25148
|
-
import * as
|
|
25245
|
+
import * as THREE35 from "three";
|
|
25149
25246
|
|
|
25150
25247
|
// src/textures/copper-text/copper-text-drawing.ts
|
|
25151
25248
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer5 } from "circuit-to-canvas";
|
|
@@ -25260,17 +25357,17 @@ function createCopperTextTextureForLayer({
|
|
|
25260
25357
|
elements,
|
|
25261
25358
|
copperColor
|
|
25262
25359
|
});
|
|
25263
|
-
const texture = new
|
|
25360
|
+
const texture = new THREE35.CanvasTexture(canvas);
|
|
25264
25361
|
texture.generateMipmaps = true;
|
|
25265
|
-
texture.minFilter =
|
|
25266
|
-
texture.magFilter =
|
|
25362
|
+
texture.minFilter = THREE35.LinearMipmapLinearFilter;
|
|
25363
|
+
texture.magFilter = THREE35.LinearFilter;
|
|
25267
25364
|
texture.anisotropy = 16;
|
|
25268
25365
|
texture.needsUpdate = true;
|
|
25269
25366
|
return texture;
|
|
25270
25367
|
}
|
|
25271
25368
|
|
|
25272
25369
|
// src/textures/create-fabrication-note-texture-for-layer.ts
|
|
25273
|
-
import * as
|
|
25370
|
+
import * as THREE36 from "three";
|
|
25274
25371
|
|
|
25275
25372
|
// src/textures/fabrication-note/fabrication-note-drawing.ts
|
|
25276
25373
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer6 } from "circuit-to-canvas";
|
|
@@ -25500,17 +25597,17 @@ function createFabricationNoteTextureForLayer({
|
|
|
25500
25597
|
bounds,
|
|
25501
25598
|
elements
|
|
25502
25599
|
});
|
|
25503
|
-
const texture = new
|
|
25600
|
+
const texture = new THREE36.CanvasTexture(canvas);
|
|
25504
25601
|
texture.generateMipmaps = true;
|
|
25505
|
-
texture.minFilter =
|
|
25506
|
-
texture.magFilter =
|
|
25602
|
+
texture.minFilter = THREE36.LinearMipmapLinearFilter;
|
|
25603
|
+
texture.magFilter = THREE36.LinearFilter;
|
|
25507
25604
|
texture.anisotropy = 16;
|
|
25508
25605
|
texture.needsUpdate = true;
|
|
25509
25606
|
return texture;
|
|
25510
25607
|
}
|
|
25511
25608
|
|
|
25512
25609
|
// src/textures/create-keepout-texture-for-layer.ts
|
|
25513
|
-
import * as
|
|
25610
|
+
import * as THREE37 from "three";
|
|
25514
25611
|
|
|
25515
25612
|
// src/textures/keepout/keepout-drawing.ts
|
|
25516
25613
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer7 } from "circuit-to-canvas";
|
|
@@ -25585,17 +25682,17 @@ function createKeepoutTextureForLayer({
|
|
|
25585
25682
|
elements,
|
|
25586
25683
|
keepoutColor
|
|
25587
25684
|
});
|
|
25588
|
-
const texture = new
|
|
25685
|
+
const texture = new THREE37.CanvasTexture(canvas);
|
|
25589
25686
|
texture.generateMipmaps = true;
|
|
25590
|
-
texture.minFilter =
|
|
25591
|
-
texture.magFilter =
|
|
25687
|
+
texture.minFilter = THREE37.LinearMipmapLinearFilter;
|
|
25688
|
+
texture.magFilter = THREE37.LinearFilter;
|
|
25592
25689
|
texture.anisotropy = 16;
|
|
25593
25690
|
texture.needsUpdate = true;
|
|
25594
25691
|
return texture;
|
|
25595
25692
|
}
|
|
25596
25693
|
|
|
25597
25694
|
// src/textures/create-pcb-note-texture-for-layer.ts
|
|
25598
|
-
import * as
|
|
25695
|
+
import * as THREE38 from "three";
|
|
25599
25696
|
|
|
25600
25697
|
// src/textures/pcb-note/pcb-note-drawing.ts
|
|
25601
25698
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer8 } from "circuit-to-canvas";
|
|
@@ -25749,17 +25846,17 @@ function createPcbNoteTextureForLayer({
|
|
|
25749
25846
|
bounds,
|
|
25750
25847
|
elements
|
|
25751
25848
|
});
|
|
25752
|
-
const texture = new
|
|
25849
|
+
const texture = new THREE38.CanvasTexture(canvas);
|
|
25753
25850
|
texture.generateMipmaps = true;
|
|
25754
|
-
texture.minFilter =
|
|
25755
|
-
texture.magFilter =
|
|
25851
|
+
texture.minFilter = THREE38.LinearMipmapLinearFilter;
|
|
25852
|
+
texture.magFilter = THREE38.LinearFilter;
|
|
25756
25853
|
texture.anisotropy = 16;
|
|
25757
25854
|
texture.needsUpdate = true;
|
|
25758
25855
|
return texture;
|
|
25759
25856
|
}
|
|
25760
25857
|
|
|
25761
25858
|
// src/textures/create-silkscreen-texture-for-layer.ts
|
|
25762
|
-
import * as
|
|
25859
|
+
import * as THREE39 from "three";
|
|
25763
25860
|
|
|
25764
25861
|
// src/textures/silkscreen/silkscreen-drawing.ts
|
|
25765
25862
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer9 } from "circuit-to-canvas";
|
|
@@ -25910,21 +26007,21 @@ function createSilkscreenTextureForLayer({
|
|
|
25910
26007
|
silkscreenColor,
|
|
25911
26008
|
soldermaskVisible
|
|
25912
26009
|
});
|
|
25913
|
-
const texture = new
|
|
26010
|
+
const texture = new THREE39.CanvasTexture(canvas);
|
|
25914
26011
|
texture.generateMipmaps = true;
|
|
25915
|
-
texture.minFilter =
|
|
25916
|
-
texture.magFilter =
|
|
26012
|
+
texture.minFilter = THREE39.LinearMipmapLinearFilter;
|
|
26013
|
+
texture.magFilter = THREE39.LinearFilter;
|
|
25917
26014
|
texture.anisotropy = 16;
|
|
25918
26015
|
texture.needsUpdate = true;
|
|
25919
26016
|
return texture;
|
|
25920
26017
|
}
|
|
25921
26018
|
|
|
25922
26019
|
// src/textures/create-soldermask-texture-for-layer.ts
|
|
25923
|
-
import * as
|
|
26020
|
+
import * as THREE41 from "three";
|
|
25924
26021
|
|
|
25925
26022
|
// src/textures/soldermask/soldermask-drawing.ts
|
|
25926
26023
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer10 } from "circuit-to-canvas";
|
|
25927
|
-
import * as
|
|
26024
|
+
import * as THREE40 from "three";
|
|
25928
26025
|
var toRgb2 = (colorArr) => {
|
|
25929
26026
|
const [r = 0, g = 0, b = 0] = colorArr;
|
|
25930
26027
|
return `rgb(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(
|
|
@@ -25947,11 +26044,11 @@ var getSoldermaskPalette = (boardData) => {
|
|
|
25947
26044
|
transparent: "rgba(0,0,0,0)"
|
|
25948
26045
|
};
|
|
25949
26046
|
}
|
|
25950
|
-
const copperColor = new
|
|
26047
|
+
const copperColor = new THREE40.Color().setRGB(
|
|
25951
26048
|
colors.copper[0],
|
|
25952
26049
|
colors.copper[1],
|
|
25953
26050
|
colors.copper[2],
|
|
25954
|
-
|
|
26051
|
+
THREE40.SRGBColorSpace
|
|
25955
26052
|
);
|
|
25956
26053
|
return {
|
|
25957
26054
|
soldermask: soldermaskColorToCss(requestedSoldermaskColor),
|
|
@@ -26086,17 +26183,17 @@ function createSoldermaskTextureForLayer({
|
|
|
26086
26183
|
elements,
|
|
26087
26184
|
boardData
|
|
26088
26185
|
});
|
|
26089
|
-
const texture = new
|
|
26186
|
+
const texture = new THREE41.CanvasTexture(canvas);
|
|
26090
26187
|
texture.generateMipmaps = true;
|
|
26091
|
-
texture.minFilter =
|
|
26092
|
-
texture.magFilter =
|
|
26188
|
+
texture.minFilter = THREE41.LinearMipmapLinearFilter;
|
|
26189
|
+
texture.magFilter = THREE41.LinearFilter;
|
|
26093
26190
|
texture.anisotropy = 16;
|
|
26094
26191
|
texture.needsUpdate = true;
|
|
26095
26192
|
return texture;
|
|
26096
26193
|
}
|
|
26097
26194
|
|
|
26098
26195
|
// src/textures/create-through-hole-texture-for-layer.ts
|
|
26099
|
-
import * as
|
|
26196
|
+
import * as THREE42 from "three";
|
|
26100
26197
|
|
|
26101
26198
|
// src/textures/through-hole/through-hole-drawing.ts
|
|
26102
26199
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer11 } from "circuit-to-canvas";
|
|
@@ -26191,10 +26288,10 @@ function createThroughHoleTextureForLayer({
|
|
|
26191
26288
|
elements,
|
|
26192
26289
|
copperColor
|
|
26193
26290
|
});
|
|
26194
|
-
const texture = new
|
|
26291
|
+
const texture = new THREE42.CanvasTexture(canvas);
|
|
26195
26292
|
texture.generateMipmaps = true;
|
|
26196
|
-
texture.minFilter =
|
|
26197
|
-
texture.magFilter =
|
|
26293
|
+
texture.minFilter = THREE42.LinearMipmapLinearFilter;
|
|
26294
|
+
texture.magFilter = THREE42.LinearFilter;
|
|
26198
26295
|
texture.anisotropy = 16;
|
|
26199
26296
|
texture.needsUpdate = true;
|
|
26200
26297
|
return texture;
|
|
@@ -26291,10 +26388,10 @@ var createCombinedTexture = ({
|
|
|
26291
26388
|
applySoldermaskSurfaceFilter(ctx, canvasWidth, canvasHeight, {
|
|
26292
26389
|
includeReflection: layer === "top"
|
|
26293
26390
|
});
|
|
26294
|
-
const combinedTexture = new
|
|
26391
|
+
const combinedTexture = new THREE43.CanvasTexture(canvas);
|
|
26295
26392
|
combinedTexture.generateMipmaps = false;
|
|
26296
|
-
combinedTexture.minFilter =
|
|
26297
|
-
combinedTexture.magFilter =
|
|
26393
|
+
combinedTexture.minFilter = THREE43.LinearFilter;
|
|
26394
|
+
combinedTexture.magFilter = THREE43.LinearFilter;
|
|
26298
26395
|
combinedTexture.premultiplyAlpha = true;
|
|
26299
26396
|
combinedTexture.anisotropy = 16;
|
|
26300
26397
|
combinedTexture.needsUpdate = true;
|
|
@@ -26330,11 +26427,11 @@ var createMaskedCopperMask = ({
|
|
|
26330
26427
|
height
|
|
26331
26428
|
);
|
|
26332
26429
|
ctx.globalCompositeOperation = "source-over";
|
|
26333
|
-
const maskTexture = new
|
|
26334
|
-
maskTexture.colorSpace =
|
|
26430
|
+
const maskTexture = new THREE43.CanvasTexture(canvas);
|
|
26431
|
+
maskTexture.colorSpace = THREE43.NoColorSpace;
|
|
26335
26432
|
maskTexture.generateMipmaps = false;
|
|
26336
|
-
maskTexture.minFilter =
|
|
26337
|
-
maskTexture.magFilter =
|
|
26433
|
+
maskTexture.minFilter = THREE43.LinearFilter;
|
|
26434
|
+
maskTexture.magFilter = THREE43.LinearFilter;
|
|
26338
26435
|
maskTexture.premultiplyAlpha = false;
|
|
26339
26436
|
maskTexture.needsUpdate = true;
|
|
26340
26437
|
return maskTexture;
|
|
@@ -26480,7 +26577,7 @@ function createCombinedBoardTextures({
|
|
|
26480
26577
|
}
|
|
26481
26578
|
|
|
26482
26579
|
// src/textures/create-three-texture-meshes.ts
|
|
26483
|
-
import * as
|
|
26580
|
+
import * as THREE45 from "three";
|
|
26484
26581
|
|
|
26485
26582
|
// src/board-surface-textures.ts
|
|
26486
26583
|
var REALISTIC_BOARD_SURFACE_MATERIAL = {
|
|
@@ -26503,7 +26600,7 @@ var PAD_COPPER_TEXTURE_MATERIAL = {
|
|
|
26503
26600
|
};
|
|
26504
26601
|
|
|
26505
26602
|
// src/utils/create-board-relief-textures.ts
|
|
26506
|
-
import * as
|
|
26603
|
+
import * as THREE44 from "three";
|
|
26507
26604
|
var PLAIN_SOLDERMASK_HEIGHT = 0.22;
|
|
26508
26605
|
var MASKED_COPPER_HEIGHT = 0.7;
|
|
26509
26606
|
var EXPOSED_COPPER_HEIGHT = 0.86;
|
|
@@ -26598,13 +26695,13 @@ var getBoardSurfaceProfile = (r, g, b, hasMaskedCopper) => {
|
|
|
26598
26695
|
return PLAIN_SOLDERMASK_PROFILE;
|
|
26599
26696
|
};
|
|
26600
26697
|
var createDataTexture = (canvas) => {
|
|
26601
|
-
const texture = new
|
|
26602
|
-
texture.colorSpace =
|
|
26698
|
+
const texture = new THREE44.CanvasTexture(canvas);
|
|
26699
|
+
texture.colorSpace = THREE44.NoColorSpace;
|
|
26603
26700
|
texture.generateMipmaps = false;
|
|
26604
|
-
texture.minFilter =
|
|
26605
|
-
texture.magFilter =
|
|
26606
|
-
texture.wrapS =
|
|
26607
|
-
texture.wrapT =
|
|
26701
|
+
texture.minFilter = THREE44.LinearFilter;
|
|
26702
|
+
texture.magFilter = THREE44.LinearFilter;
|
|
26703
|
+
texture.wrapS = THREE44.ClampToEdgeWrapping;
|
|
26704
|
+
texture.wrapT = THREE44.ClampToEdgeWrapping;
|
|
26608
26705
|
texture.needsUpdate = true;
|
|
26609
26706
|
return texture;
|
|
26610
26707
|
};
|
|
@@ -26728,16 +26825,16 @@ function createTexturePlane(config, boardData) {
|
|
|
26728
26825
|
} = config;
|
|
26729
26826
|
if (!texture) return null;
|
|
26730
26827
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
26731
|
-
const planeGeom = new
|
|
26828
|
+
const planeGeom = new THREE45.PlaneGeometry(
|
|
26732
26829
|
boardOutlineBounds.width,
|
|
26733
26830
|
boardOutlineBounds.height
|
|
26734
26831
|
);
|
|
26735
|
-
texture.colorSpace =
|
|
26832
|
+
texture.colorSpace = THREE45.SRGBColorSpace;
|
|
26736
26833
|
const sharedMaterialOptions = {
|
|
26737
26834
|
map: texture,
|
|
26738
26835
|
transparent: true,
|
|
26739
26836
|
alphaTest: 0.08,
|
|
26740
|
-
side:
|
|
26837
|
+
side: THREE45.FrontSide,
|
|
26741
26838
|
depthWrite: true,
|
|
26742
26839
|
polygonOffset: usePolygonOffset,
|
|
26743
26840
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -26746,12 +26843,12 @@ function createTexturePlane(config, boardData) {
|
|
|
26746
26843
|
opacity: isFaux ? FAUX_BOARD_OPACITY : 1
|
|
26747
26844
|
};
|
|
26748
26845
|
const reliefTextures = createBoardReliefTextures(texture, maskedCopperMask);
|
|
26749
|
-
const material = new
|
|
26846
|
+
const material = new THREE45.MeshPhysicalMaterial({
|
|
26750
26847
|
...sharedMaterialOptions,
|
|
26751
26848
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
26752
26849
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
26753
26850
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
26754
|
-
normalScale: new
|
|
26851
|
+
normalScale: new THREE45.Vector2(
|
|
26755
26852
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
26756
26853
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
26757
26854
|
),
|
|
@@ -26765,7 +26862,7 @@ function createTexturePlane(config, boardData) {
|
|
|
26765
26862
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
26766
26863
|
envMapIntensity: 0.18
|
|
26767
26864
|
});
|
|
26768
|
-
const mesh = new
|
|
26865
|
+
const mesh = new THREE45.Mesh(planeGeom, material);
|
|
26769
26866
|
mesh.position.set(
|
|
26770
26867
|
boardOutlineBounds.centerX,
|
|
26771
26868
|
boardOutlineBounds.centerY,
|
|
@@ -26813,7 +26910,7 @@ function createTextureMeshes(textures, boardData, pcbThickness, isFaux = false)
|
|
|
26813
26910
|
}
|
|
26814
26911
|
|
|
26815
26912
|
// src/three-components/JscadBoardTextures.tsx
|
|
26816
|
-
import * as
|
|
26913
|
+
import * as THREE46 from "three";
|
|
26817
26914
|
|
|
26818
26915
|
// src/hooks/useBoardTextureVisibility.ts
|
|
26819
26916
|
import { useMemo as useMemo20 } from "react";
|
|
@@ -26931,7 +27028,7 @@ function JscadBoardTextures({
|
|
|
26931
27028
|
visibility: textureVisibility
|
|
26932
27029
|
});
|
|
26933
27030
|
}, [circuitJson, boardData, traceTextureResolution, textureVisibility]);
|
|
26934
|
-
|
|
27031
|
+
useEffect27(() => {
|
|
26935
27032
|
if (!rootObject || !boardData || !textures) return;
|
|
26936
27033
|
const meshes = [];
|
|
26937
27034
|
const disposeTextureMaterial = (material) => {
|
|
@@ -26951,7 +27048,7 @@ function JscadBoardTextures({
|
|
|
26951
27048
|
const typedMaterial = material;
|
|
26952
27049
|
for (const prop of textureProps) {
|
|
26953
27050
|
const texture = typedMaterial[prop];
|
|
26954
|
-
if (texture && texture instanceof
|
|
27051
|
+
if (texture && texture instanceof THREE46.Texture) {
|
|
26955
27052
|
texture.dispose();
|
|
26956
27053
|
typedMaterial[prop] = null;
|
|
26957
27054
|
}
|
|
@@ -26970,16 +27067,16 @@ function JscadBoardTextures({
|
|
|
26970
27067
|
}) => {
|
|
26971
27068
|
if (!texture) return null;
|
|
26972
27069
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
26973
|
-
const planeGeom = new
|
|
27070
|
+
const planeGeom = new THREE46.PlaneGeometry(
|
|
26974
27071
|
boardOutlineBounds.width,
|
|
26975
27072
|
boardOutlineBounds.height
|
|
26976
27073
|
);
|
|
26977
|
-
texture.colorSpace =
|
|
27074
|
+
texture.colorSpace = THREE46.SRGBColorSpace;
|
|
26978
27075
|
const sharedMaterialOptions = {
|
|
26979
27076
|
map: texture,
|
|
26980
27077
|
transparent: true,
|
|
26981
27078
|
alphaTest: 0.08,
|
|
26982
|
-
side:
|
|
27079
|
+
side: THREE46.FrontSide,
|
|
26983
27080
|
depthWrite,
|
|
26984
27081
|
polygonOffset: usePolygonOffset,
|
|
26985
27082
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -26990,12 +27087,12 @@ function JscadBoardTextures({
|
|
|
26990
27087
|
texture,
|
|
26991
27088
|
maskedCopperMask
|
|
26992
27089
|
);
|
|
26993
|
-
const material = new
|
|
27090
|
+
const material = new THREE46.MeshPhysicalMaterial({
|
|
26994
27091
|
...sharedMaterialOptions,
|
|
26995
27092
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
26996
27093
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
26997
27094
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
26998
|
-
normalScale: new
|
|
27095
|
+
normalScale: new THREE46.Vector2(
|
|
26999
27096
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
27000
27097
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
27001
27098
|
),
|
|
@@ -27007,7 +27104,7 @@ function JscadBoardTextures({
|
|
|
27007
27104
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
27008
27105
|
envMapIntensity: 0.18
|
|
27009
27106
|
});
|
|
27010
|
-
const mesh = new
|
|
27107
|
+
const mesh = new THREE46.Mesh(planeGeom, material);
|
|
27011
27108
|
mesh.position.set(
|
|
27012
27109
|
boardOutlineBounds.centerX,
|
|
27013
27110
|
boardOutlineBounds.centerY,
|
|
@@ -27057,7 +27154,7 @@ function JscadBoardTextures({
|
|
|
27057
27154
|
for (const material of mesh.material) {
|
|
27058
27155
|
disposeTextureMaterial(material);
|
|
27059
27156
|
}
|
|
27060
|
-
} else if (mesh.material instanceof
|
|
27157
|
+
} else if (mesh.material instanceof THREE46.Material) {
|
|
27061
27158
|
disposeTextureMaterial(mesh.material);
|
|
27062
27159
|
}
|
|
27063
27160
|
}
|
|
@@ -27069,8 +27166,8 @@ function JscadBoardTextures({
|
|
|
27069
27166
|
}
|
|
27070
27167
|
|
|
27071
27168
|
// src/three-components/STLModel.tsx
|
|
27072
|
-
import { useState as useState17, useEffect as
|
|
27073
|
-
import * as
|
|
27169
|
+
import { useState as useState17, useEffect as useEffect28, useMemo as useMemo22 } from "react";
|
|
27170
|
+
import * as THREE47 from "three";
|
|
27074
27171
|
import { STLLoader } from "three-stdlib";
|
|
27075
27172
|
function STLModel({
|
|
27076
27173
|
stlUrl,
|
|
@@ -27082,7 +27179,7 @@ function STLModel({
|
|
|
27082
27179
|
}) {
|
|
27083
27180
|
const { rootObject } = useThree();
|
|
27084
27181
|
const [geom, setGeom] = useState17(null);
|
|
27085
|
-
|
|
27182
|
+
useEffect28(() => {
|
|
27086
27183
|
const loader = new STLLoader();
|
|
27087
27184
|
if (stlData) {
|
|
27088
27185
|
try {
|
|
@@ -27103,15 +27200,15 @@ function STLModel({
|
|
|
27103
27200
|
const mesh = useMemo22(() => {
|
|
27104
27201
|
if (!geom) return null;
|
|
27105
27202
|
const isBoardLayer = layerType === "board";
|
|
27106
|
-
const material = new
|
|
27107
|
-
color: Array.isArray(color) ? new
|
|
27203
|
+
const material = new THREE47.MeshStandardMaterial({
|
|
27204
|
+
color: Array.isArray(color) ? new THREE47.Color(color[0], color[1], color[2]) : color,
|
|
27108
27205
|
transparent: opacity !== 1,
|
|
27109
27206
|
opacity,
|
|
27110
27207
|
polygonOffset: isBoardLayer,
|
|
27111
27208
|
polygonOffsetFactor: isBoardLayer ? 6 : 0,
|
|
27112
27209
|
polygonOffsetUnits: isBoardLayer ? 6 : 0
|
|
27113
27210
|
});
|
|
27114
|
-
const createdMesh = new
|
|
27211
|
+
const createdMesh = new THREE47.Mesh(geom, material);
|
|
27115
27212
|
createdMesh.renderOrder = isBoardLayer ? -1 : 1;
|
|
27116
27213
|
configureObjectShadows(createdMesh, {
|
|
27117
27214
|
castShadow: !isBoardLayer && opacity === 1,
|
|
@@ -27119,7 +27216,7 @@ function STLModel({
|
|
|
27119
27216
|
});
|
|
27120
27217
|
return createdMesh;
|
|
27121
27218
|
}, [geom, color, opacity, layerType]);
|
|
27122
|
-
|
|
27219
|
+
useEffect28(() => {
|
|
27123
27220
|
if (!rootObject || !mesh) return;
|
|
27124
27221
|
rootObject.add(mesh);
|
|
27125
27222
|
return () => {
|
|
@@ -27173,8 +27270,8 @@ function VisibleSTLModel({
|
|
|
27173
27270
|
// src/three-components/CadCable.tsx
|
|
27174
27271
|
import { parseCableString } from "@tscircuit/cableprinter";
|
|
27175
27272
|
import { createCableMeshes } from "jscad-electronics/cables";
|
|
27176
|
-
import { useEffect as
|
|
27177
|
-
import * as
|
|
27273
|
+
import { useEffect as useEffect29, useMemo as useMemo23 } from "react";
|
|
27274
|
+
import * as THREE48 from "three";
|
|
27178
27275
|
var isCadCableElement = (element) => {
|
|
27179
27276
|
if (!element || typeof element !== "object") return false;
|
|
27180
27277
|
const candidate = element;
|
|
@@ -27191,14 +27288,14 @@ var getConnectorPin1Side = ({
|
|
|
27191
27288
|
const endpoint = end === "start" ? path[0] : path[path.length - 1];
|
|
27192
27289
|
const adjacent = end === "start" ? path[1] : path[path.length - 2];
|
|
27193
27290
|
if (!endpoint || !adjacent) return void 0;
|
|
27194
|
-
const cableAxis = new
|
|
27291
|
+
const cableAxis = new THREE48.Vector3(
|
|
27195
27292
|
adjacent.x - endpoint.x,
|
|
27196
27293
|
adjacent.y - endpoint.y,
|
|
27197
27294
|
adjacent.z - endpoint.z
|
|
27198
27295
|
);
|
|
27199
27296
|
if (cableAxis.lengthSq() < 1e-12) return void 0;
|
|
27200
27297
|
cableAxis.normalize();
|
|
27201
|
-
const pin1Side = new
|
|
27298
|
+
const pin1Side = new THREE48.Vector3(
|
|
27202
27299
|
pin1Position.x - endpoint.x,
|
|
27203
27300
|
pin1Position.y - endpoint.y,
|
|
27204
27301
|
pin1Position.z - endpoint.z
|
|
@@ -27224,28 +27321,28 @@ var createCadCableObject = (cable) => {
|
|
|
27224
27321
|
end: "end"
|
|
27225
27322
|
})
|
|
27226
27323
|
});
|
|
27227
|
-
const group = new
|
|
27324
|
+
const group = new THREE48.Group();
|
|
27228
27325
|
group.name = `cad-cable-${cable.cad_cable_id}`;
|
|
27229
27326
|
group.userData = { cadCableId: cable.cad_cable_id, name: cable.name };
|
|
27230
27327
|
for (const cableMesh of cableMeshes) {
|
|
27231
|
-
let geometry = new
|
|
27328
|
+
let geometry = new THREE48.BufferGeometry();
|
|
27232
27329
|
geometry.setAttribute(
|
|
27233
27330
|
"position",
|
|
27234
|
-
new
|
|
27331
|
+
new THREE48.Float32BufferAttribute(cableMesh.positions, 3)
|
|
27235
27332
|
);
|
|
27236
27333
|
geometry.setIndex(cableMesh.indices);
|
|
27237
27334
|
if (!cableMesh.smooth) geometry = geometry.toNonIndexed();
|
|
27238
27335
|
geometry.computeVertexNormals();
|
|
27239
27336
|
const [red, green, blue, alpha] = cableMesh.color;
|
|
27240
|
-
const material = new
|
|
27241
|
-
color: new
|
|
27337
|
+
const material = new THREE48.MeshStandardMaterial({
|
|
27338
|
+
color: new THREE48.Color(red, green, blue),
|
|
27242
27339
|
metalness: cableMesh.material?.metalness ?? 0,
|
|
27243
27340
|
roughness: cableMesh.material?.roughness ?? 0.7,
|
|
27244
27341
|
opacity: alpha,
|
|
27245
27342
|
transparent: alpha < 1,
|
|
27246
|
-
side:
|
|
27343
|
+
side: THREE48.DoubleSide
|
|
27247
27344
|
});
|
|
27248
|
-
const mesh = new
|
|
27345
|
+
const mesh = new THREE48.Mesh(geometry, material);
|
|
27249
27346
|
mesh.name = `${group.name}:${cableMesh.name}`;
|
|
27250
27347
|
configureObjectShadows(mesh, { castShadow: true, receiveShadow: true });
|
|
27251
27348
|
group.add(mesh);
|
|
@@ -27254,7 +27351,7 @@ var createCadCableObject = (cable) => {
|
|
|
27254
27351
|
};
|
|
27255
27352
|
var disposeCadCableObject = (group) => {
|
|
27256
27353
|
group.traverse((object) => {
|
|
27257
|
-
if (!(object instanceof
|
|
27354
|
+
if (!(object instanceof THREE48.Mesh)) return;
|
|
27258
27355
|
object.geometry.dispose();
|
|
27259
27356
|
const materials = Array.isArray(object.material) ? object.material : [object.material];
|
|
27260
27357
|
for (const material of materials) material.dispose();
|
|
@@ -27270,7 +27367,7 @@ var CadCable = ({ cable }) => {
|
|
|
27270
27367
|
return null;
|
|
27271
27368
|
}
|
|
27272
27369
|
}, [cable]);
|
|
27273
|
-
|
|
27370
|
+
useEffect29(() => {
|
|
27274
27371
|
if (!cableObject) return;
|
|
27275
27372
|
rootObject.add(cableObject);
|
|
27276
27373
|
return () => {
|
|
@@ -27281,6 +27378,22 @@ var CadCable = ({ cable }) => {
|
|
|
27281
27378
|
return null;
|
|
27282
27379
|
};
|
|
27283
27380
|
|
|
27381
|
+
// src/utils/get-initial-camera-position.ts
|
|
27382
|
+
function getInitialCameraPosition({
|
|
27383
|
+
boardDimensions,
|
|
27384
|
+
boardCenter
|
|
27385
|
+
}) {
|
|
27386
|
+
if (!boardDimensions || !boardCenter) return [5, -5, 5];
|
|
27387
|
+
const safeWidth = Math.max(boardDimensions.width ?? 0, 1);
|
|
27388
|
+
const safeHeight = Math.max(boardDimensions.height ?? 0, 1);
|
|
27389
|
+
const largestDimension = Math.max(safeWidth, safeHeight, 5);
|
|
27390
|
+
return [
|
|
27391
|
+
boardCenter.x + largestDimension * 0.4,
|
|
27392
|
+
boardCenter.y - largestDimension * 0.7,
|
|
27393
|
+
largestDimension * 0.9
|
|
27394
|
+
];
|
|
27395
|
+
}
|
|
27396
|
+
|
|
27284
27397
|
// src/utils/preprocess-circuit-json.ts
|
|
27285
27398
|
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
27286
27399
|
|
|
@@ -27390,32 +27503,6 @@ var CadViewerJscad = forwardRef3(
|
|
|
27390
27503
|
);
|
|
27391
27504
|
}, [circuitJson, childrenSoup]);
|
|
27392
27505
|
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
27506
|
const isFauxBoard = useMemo24(() => {
|
|
27420
27507
|
if (!internalCircuitJson) return false;
|
|
27421
27508
|
try {
|
|
@@ -27449,6 +27536,19 @@ var CadViewerJscad = forwardRef3(
|
|
|
27449
27536
|
return void 0;
|
|
27450
27537
|
}
|
|
27451
27538
|
}, [internalCircuitJson]);
|
|
27539
|
+
const cameraSessionScope = useMemo24(() => {
|
|
27540
|
+
if (!internalCircuitJson) return void 0;
|
|
27541
|
+
const board = su12(internalCircuitJson).pcb_board.list()[0];
|
|
27542
|
+
if (!board) return void 0;
|
|
27543
|
+
return JSON.stringify({
|
|
27544
|
+
pcbBoardId: board.pcb_board_id,
|
|
27545
|
+
center: boardCenter,
|
|
27546
|
+
dimensions: boardDimensions
|
|
27547
|
+
});
|
|
27548
|
+
}, [internalCircuitJson, boardCenter, boardDimensions]);
|
|
27549
|
+
const initialCameraPosition = useMemo24(() => {
|
|
27550
|
+
return getInitialCameraPosition({ boardDimensions, boardCenter });
|
|
27551
|
+
}, [boardDimensions, boardCenter]);
|
|
27452
27552
|
const pcbThickness = usePcbThickness(internalCircuitJson);
|
|
27453
27553
|
const { stls: boardStls, loading } = useStlsFromGeom(boardGeom);
|
|
27454
27554
|
const cad_components = su12(internalCircuitJson).cad_component.list().filter((cad) => !hiddenCadComponentIds?.has(cad.cad_component_id));
|
|
@@ -27462,6 +27562,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
27462
27562
|
clickToInteractEnabled,
|
|
27463
27563
|
boardDimensions,
|
|
27464
27564
|
boardCenter,
|
|
27565
|
+
cameraSessionScope,
|
|
27465
27566
|
referenceObject,
|
|
27466
27567
|
onUserInteraction,
|
|
27467
27568
|
onCameraControllerReady,
|
|
@@ -27507,6 +27608,9 @@ var CadViewerJscad = forwardRef3(
|
|
|
27507
27608
|
}
|
|
27508
27609
|
);
|
|
27509
27610
|
|
|
27611
|
+
// src/CadViewerManifold.tsx
|
|
27612
|
+
import { su as su17 } from "@tscircuit/circuit-json-util";
|
|
27613
|
+
|
|
27510
27614
|
// node_modules/earcut/src/earcut.js
|
|
27511
27615
|
var steiners = /* @__PURE__ */ new Set();
|
|
27512
27616
|
var filteredOut = false;
|
|
@@ -28437,215 +28541,69 @@ function extrudePolygon({
|
|
|
28437
28541
|
b: { ...b, z: bottom },
|
|
28438
28542
|
c: { ...b, z: top },
|
|
28439
28543
|
pcbFace: "side"
|
|
28440
|
-
});
|
|
28441
|
-
add10({
|
|
28442
|
-
a: { ...a, z: bottom },
|
|
28443
|
-
b: { ...b, z: top },
|
|
28444
|
-
c: { ...a, z: top },
|
|
28445
|
-
pcbFace: "side"
|
|
28446
|
-
});
|
|
28447
|
-
}
|
|
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);
|
|
28544
|
+
});
|
|
28545
|
+
add10({
|
|
28546
|
+
a: { ...a, z: bottom },
|
|
28547
|
+
b: { ...b, z: top },
|
|
28548
|
+
c: { ...a, z: top },
|
|
28549
|
+
pcbFace: "side"
|
|
28550
|
+
});
|
|
28624
28551
|
}
|
|
28625
|
-
|
|
28626
|
-
|
|
28627
|
-
|
|
28628
|
-
|
|
28629
|
-
|
|
28630
|
-
|
|
28631
|
-
|
|
28632
|
-
|
|
28633
|
-
|
|
28634
|
-
|
|
28635
|
-
|
|
28636
|
-
|
|
28637
|
-
|
|
28552
|
+
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28553
|
+
}
|
|
28554
|
+
function createStiffenerMesh({
|
|
28555
|
+
stiffener,
|
|
28556
|
+
boardThickness,
|
|
28557
|
+
fold
|
|
28558
|
+
}) {
|
|
28559
|
+
const adhesive = stiffener.adhesive_thickness ?? 0;
|
|
28560
|
+
if (!Number.isFinite(adhesive) || adhesive < 0 || !Number.isFinite(stiffener.thickness) || stiffener.thickness <= 0 || !["top", "bottom"].includes(stiffener.layer))
|
|
28561
|
+
throw new Error(`Invalid PCB stiffener ${stiffener.pcb_stiffener_id}`);
|
|
28562
|
+
const outline = stiffener.shape === "polygon" ? stiffener.outline : (() => {
|
|
28563
|
+
if (!(stiffener.width > 0 && stiffener.height > 0))
|
|
28564
|
+
throw new Error("Invalid stiffener dimensions");
|
|
28565
|
+
const a = (stiffener.rotation ?? 0) * Math.PI / 180;
|
|
28566
|
+
return [
|
|
28567
|
+
[-1, -1],
|
|
28568
|
+
[1, -1],
|
|
28569
|
+
[1, 1],
|
|
28570
|
+
[-1, 1]
|
|
28571
|
+
].map(([x, y]) => ({
|
|
28572
|
+
x: stiffener.center.x + x * stiffener.width / 2 * Math.cos(a) - y * stiffener.height / 2 * Math.sin(a),
|
|
28573
|
+
y: stiffener.center.y + x * stiffener.width / 2 * Math.sin(a) + y * stiffener.height / 2 * Math.cos(a)
|
|
28574
|
+
}));
|
|
28575
|
+
})();
|
|
28576
|
+
const near = boardThickness / 2 + adhesive, far = near + stiffener.thickness;
|
|
28577
|
+
const mesh = extrudePolygon({
|
|
28578
|
+
outline,
|
|
28579
|
+
bottom: stiffener.layer === "top" ? near : -far,
|
|
28580
|
+
top: stiffener.layer === "top" ? far : -near
|
|
28581
|
+
});
|
|
28582
|
+
if (!fold) return mesh;
|
|
28583
|
+
fold.assertRigid(
|
|
28584
|
+
mesh.triangles.flatMap((t) => t.vertices),
|
|
28585
|
+
stiffener.pcb_stiffener_id
|
|
28586
|
+
);
|
|
28587
|
+
const anchor = {
|
|
28588
|
+
x: outline.reduce((s, p) => s + p.x, 0) / outline.length,
|
|
28589
|
+
y: outline.reduce((s, p) => s + p.y, 0) / outline.length,
|
|
28590
|
+
z: 0
|
|
28638
28591
|
};
|
|
28592
|
+
const triangles = mesh.triangles.map((t) => ({
|
|
28593
|
+
...t,
|
|
28594
|
+
vertices: t.vertices.map((p) => fold.point(p, anchor)),
|
|
28595
|
+
normal: fold.direction(t.normal, anchor)
|
|
28596
|
+
}));
|
|
28597
|
+
return { ...mesh, triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
28639
28598
|
}
|
|
28640
28599
|
|
|
28641
28600
|
// src/CadViewerManifold.tsx
|
|
28642
|
-
import {
|
|
28643
|
-
import
|
|
28644
|
-
import * as THREE55 from "three";
|
|
28601
|
+
import { useEffect as useEffect31, useMemo as useMemo26, useState as useState19 } from "react";
|
|
28602
|
+
import * as THREE56 from "three";
|
|
28645
28603
|
|
|
28646
28604
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
28647
28605
|
import { su as su16 } from "@tscircuit/circuit-json-util";
|
|
28648
|
-
import { useEffect as
|
|
28606
|
+
import { useEffect as useEffect30, useMemo as useMemo25, useRef as useRef9, useState as useState18 } from "react";
|
|
28649
28607
|
import * as THREE52 from "three";
|
|
28650
28608
|
|
|
28651
28609
|
// src/utils/manifold/create-manifold-board.ts
|
|
@@ -29824,7 +29782,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
29824
29782
|
if (!boardData) return TRACE_TEXTURE_RESOLUTION;
|
|
29825
29783
|
return getLayerTextureResolution(boardData, TRACE_TEXTURE_RESOLUTION);
|
|
29826
29784
|
}, [boardData]);
|
|
29827
|
-
|
|
29785
|
+
useEffect30(() => {
|
|
29828
29786
|
if (!manifoldJSModule || !boardData) {
|
|
29829
29787
|
setGeoms(null);
|
|
29830
29788
|
setPcbThickness(null);
|
|
@@ -30024,12 +29982,157 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
30024
29982
|
};
|
|
30025
29983
|
};
|
|
30026
29984
|
|
|
29985
|
+
// src/utils/flex-meshes.ts
|
|
29986
|
+
import * as THREE53 from "three";
|
|
29987
|
+
function meshToSurface(mesh, center) {
|
|
29988
|
+
mesh.updateMatrix();
|
|
29989
|
+
const geometry = mesh.geometry.index ? mesh.geometry.toNonIndexed() : mesh.geometry;
|
|
29990
|
+
const position = geometry.getAttribute("position"), uv = geometry.getAttribute("uv");
|
|
29991
|
+
const triangles = [];
|
|
29992
|
+
for (let i = 0; i < position.count; i += 3) {
|
|
29993
|
+
const vertices = [0, 1, 2].map((j) => {
|
|
29994
|
+
const v = new THREE53.Vector3().fromBufferAttribute(position, i + j).applyMatrix4(mesh.matrix);
|
|
29995
|
+
return { x: v.x - center.x, y: v.y - center.y, z: v.z };
|
|
29996
|
+
});
|
|
29997
|
+
const [a, b, c] = vertices;
|
|
29998
|
+
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();
|
|
29999
|
+
triangles.push({
|
|
30000
|
+
vertices,
|
|
30001
|
+
normal: { x: n.x, y: n.y, z: n.z },
|
|
30002
|
+
...uv ? {
|
|
30003
|
+
uvs: [0, 1, 2].map((j) => ({
|
|
30004
|
+
u: uv.getX(i + j),
|
|
30005
|
+
v: uv.getY(i + j)
|
|
30006
|
+
}))
|
|
30007
|
+
} : {}
|
|
30008
|
+
});
|
|
30009
|
+
}
|
|
30010
|
+
if (geometry !== mesh.geometry) geometry.dispose();
|
|
30011
|
+
return { triangles, boundingBox: boundsOfTriangles(triangles) };
|
|
30012
|
+
}
|
|
30013
|
+
function surfaceToGeometry(surface, center) {
|
|
30014
|
+
const positions = [], normals = [], uvs = [];
|
|
30015
|
+
for (const triangle of surface.triangles)
|
|
30016
|
+
triangle.vertices.forEach((p, i) => {
|
|
30017
|
+
positions.push(p.x + center.x, p.y + center.y, p.z);
|
|
30018
|
+
normals.push(triangle.normal.x, triangle.normal.y, triangle.normal.z);
|
|
30019
|
+
uvs.push(triangle.uvs?.[i]?.u ?? 0, triangle.uvs?.[i]?.v ?? 0);
|
|
30020
|
+
});
|
|
30021
|
+
const geometry = new THREE53.BufferGeometry();
|
|
30022
|
+
geometry.setAttribute(
|
|
30023
|
+
"position",
|
|
30024
|
+
new THREE53.Float32BufferAttribute(positions, 3)
|
|
30025
|
+
);
|
|
30026
|
+
geometry.setAttribute("normal", new THREE53.Float32BufferAttribute(normals, 3));
|
|
30027
|
+
geometry.setAttribute("uv", new THREE53.Float32BufferAttribute(uvs, 2));
|
|
30028
|
+
geometry.computeBoundingBox();
|
|
30029
|
+
geometry.computeBoundingSphere();
|
|
30030
|
+
return geometry;
|
|
30031
|
+
}
|
|
30032
|
+
function replaceGeometry(mesh, surface, board) {
|
|
30033
|
+
const output = mesh.clone();
|
|
30034
|
+
output.geometry = surfaceToGeometry(surface, board.center);
|
|
30035
|
+
output.position.set(0, 0, 0);
|
|
30036
|
+
output.rotation.set(0, 0, 0);
|
|
30037
|
+
output.scale.set(1, 1, 1);
|
|
30038
|
+
output.updateMatrix();
|
|
30039
|
+
return output;
|
|
30040
|
+
}
|
|
30041
|
+
function createFlexMeshes(geometryMeshes, textureMeshes, json, foldPcbs) {
|
|
30042
|
+
const boards = json.filter((e) => e.type === "pcb_board");
|
|
30043
|
+
const bends = json.filter((e) => e.type === "pcb_bend"), stiffeners = json.filter((e) => e.type === "pcb_stiffener");
|
|
30044
|
+
if (!bends.length && !stiffeners.length)
|
|
30045
|
+
return { geometryMeshes, textureMeshes };
|
|
30046
|
+
const board = boards[0];
|
|
30047
|
+
if (!board || boards.length !== 1 || json.some((e) => e.type === "pcb_panel") || [...bends, ...stiffeners].some((e) => e.pcb_board_id !== board.pcb_board_id))
|
|
30048
|
+
throw new Error(
|
|
30049
|
+
"Flex rendering requires one board, matching board references, and no panel"
|
|
30050
|
+
);
|
|
30051
|
+
const fold = foldPcbs ? createPcbFold(bends, board.thickness ?? 1.6) : void 0;
|
|
30052
|
+
const body = geometryMeshes.find((m) => m.name === "board-geom");
|
|
30053
|
+
const flatBody = body ? meshToSurface(body, board.center) : void 0;
|
|
30054
|
+
const geometry = fold ? geometryMeshes.map(
|
|
30055
|
+
(mesh) => replaceGeometry(
|
|
30056
|
+
mesh,
|
|
30057
|
+
foldSurfaceMesh(meshToSurface(mesh, board.center), fold),
|
|
30058
|
+
board
|
|
30059
|
+
)
|
|
30060
|
+
) : [...geometryMeshes];
|
|
30061
|
+
const textures = fold && flatBody ? textureMeshes.map((mesh) => {
|
|
30062
|
+
mesh.updateMatrix();
|
|
30063
|
+
const inverse4 = mesh.matrix.clone().invert();
|
|
30064
|
+
const bottom = mesh.name.startsWith("bottom");
|
|
30065
|
+
const dimensions = mesh.geometry.parameters;
|
|
30066
|
+
const triangles = flatBody.triangles.filter((t) => bottom ? t.normal.z < -0.9 : t.normal.z > 0.9).map((t) => {
|
|
30067
|
+
const vertices = t.vertices.map((p) => ({
|
|
30068
|
+
...p,
|
|
30069
|
+
z: mesh.position.z
|
|
30070
|
+
}));
|
|
30071
|
+
const uvs = vertices.map((p) => {
|
|
30072
|
+
const local = new THREE53.Vector3(
|
|
30073
|
+
p.x + board.center.x,
|
|
30074
|
+
p.y + board.center.y,
|
|
30075
|
+
p.z
|
|
30076
|
+
).applyMatrix4(inverse4);
|
|
30077
|
+
return {
|
|
30078
|
+
u: local.x / dimensions.width + 0.5,
|
|
30079
|
+
v: local.y / dimensions.height + 0.5
|
|
30080
|
+
};
|
|
30081
|
+
});
|
|
30082
|
+
return { ...t, vertices, uvs };
|
|
30083
|
+
});
|
|
30084
|
+
const result = replaceGeometry(
|
|
30085
|
+
mesh,
|
|
30086
|
+
foldSurfaceMesh(
|
|
30087
|
+
{ triangles, boundingBox: boundsOfTriangles(triangles) },
|
|
30088
|
+
fold
|
|
30089
|
+
),
|
|
30090
|
+
board
|
|
30091
|
+
);
|
|
30092
|
+
mesh.geometry.dispose();
|
|
30093
|
+
return result;
|
|
30094
|
+
}) : textureMeshes;
|
|
30095
|
+
for (const stiffener of stiffeners) {
|
|
30096
|
+
const mesh = new THREE53.Mesh(
|
|
30097
|
+
surfaceToGeometry(
|
|
30098
|
+
createStiffenerMesh({
|
|
30099
|
+
stiffener,
|
|
30100
|
+
boardThickness: board.thickness ?? 1.6,
|
|
30101
|
+
fold
|
|
30102
|
+
}),
|
|
30103
|
+
board.center
|
|
30104
|
+
),
|
|
30105
|
+
new THREE53.MeshStandardMaterial({
|
|
30106
|
+
color: stiffener.material === "fr4" ? "#879568" : stiffener.material === "polyimide" ? "#bd7f27" : "#b8bdc4",
|
|
30107
|
+
side: THREE53.DoubleSide
|
|
30108
|
+
})
|
|
30109
|
+
);
|
|
30110
|
+
mesh.name = "board-stiffener";
|
|
30111
|
+
configureObjectShadows(mesh);
|
|
30112
|
+
geometry.push(mesh);
|
|
30113
|
+
}
|
|
30114
|
+
const bounds = new THREE53.Box3();
|
|
30115
|
+
for (const mesh of [...geometry, ...textures]) bounds.expandByObject(mesh);
|
|
30116
|
+
return {
|
|
30117
|
+
geometryMeshes: geometry,
|
|
30118
|
+
textureMeshes: textures,
|
|
30119
|
+
bounds: {
|
|
30120
|
+
minX: bounds.min.x,
|
|
30121
|
+
maxX: bounds.max.x,
|
|
30122
|
+
minY: bounds.min.y,
|
|
30123
|
+
maxY: bounds.max.y,
|
|
30124
|
+
minZ: bounds.min.z,
|
|
30125
|
+
maxZ: bounds.max.z
|
|
30126
|
+
}
|
|
30127
|
+
};
|
|
30128
|
+
}
|
|
30129
|
+
|
|
30027
30130
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
30028
|
-
import * as
|
|
30131
|
+
import * as THREE55 from "three";
|
|
30029
30132
|
|
|
30030
30133
|
// src/utils/create-board-material.ts
|
|
30031
|
-
import * as
|
|
30032
|
-
var DEFAULT_SIDE =
|
|
30134
|
+
import * as THREE54 from "three";
|
|
30135
|
+
var DEFAULT_SIDE = THREE54.DoubleSide;
|
|
30033
30136
|
var createBoardMaterial = ({
|
|
30034
30137
|
material,
|
|
30035
30138
|
color,
|
|
@@ -30037,7 +30140,7 @@ var createBoardMaterial = ({
|
|
|
30037
30140
|
isFaux = false
|
|
30038
30141
|
}) => {
|
|
30039
30142
|
if (material === "fr4") {
|
|
30040
|
-
return new
|
|
30143
|
+
return new THREE54.MeshPhysicalMaterial({
|
|
30041
30144
|
color,
|
|
30042
30145
|
side,
|
|
30043
30146
|
metalness: 0,
|
|
@@ -30055,7 +30158,7 @@ var createBoardMaterial = ({
|
|
|
30055
30158
|
polygonOffsetUnits: 1
|
|
30056
30159
|
});
|
|
30057
30160
|
}
|
|
30058
|
-
return new
|
|
30161
|
+
return new THREE54.MeshStandardMaterial({
|
|
30059
30162
|
color,
|
|
30060
30163
|
side,
|
|
30061
30164
|
flatShading: true,
|
|
@@ -30074,12 +30177,12 @@ function createGeometryMeshes(geoms) {
|
|
|
30074
30177
|
const meshes = [];
|
|
30075
30178
|
if (!geoms) return meshes;
|
|
30076
30179
|
if (geoms.board?.geometry) {
|
|
30077
|
-
const mesh = new
|
|
30180
|
+
const mesh = new THREE55.Mesh(
|
|
30078
30181
|
geoms.board.geometry,
|
|
30079
30182
|
createBoardMaterial({
|
|
30080
30183
|
material: geoms.board.material,
|
|
30081
30184
|
color: geoms.board.color,
|
|
30082
|
-
side:
|
|
30185
|
+
side: THREE55.DoubleSide,
|
|
30083
30186
|
isFaux: geoms.board.isFaux
|
|
30084
30187
|
})
|
|
30085
30188
|
);
|
|
@@ -30090,11 +30193,11 @@ function createGeometryMeshes(geoms) {
|
|
|
30090
30193
|
const createMeshesFromArray = (geomArray) => {
|
|
30091
30194
|
if (geomArray) {
|
|
30092
30195
|
for (const comp of geomArray) {
|
|
30093
|
-
const mesh = new
|
|
30196
|
+
const mesh = new THREE55.Mesh(
|
|
30094
30197
|
comp.geometry,
|
|
30095
|
-
new
|
|
30198
|
+
new THREE55.MeshStandardMaterial({
|
|
30096
30199
|
color: comp.color,
|
|
30097
|
-
side:
|
|
30200
|
+
side: THREE55.DoubleSide,
|
|
30098
30201
|
flatShading: true
|
|
30099
30202
|
// Consistent with board
|
|
30100
30203
|
})
|
|
@@ -30110,6 +30213,33 @@ function createGeometryMeshes(geoms) {
|
|
|
30110
30213
|
return meshes;
|
|
30111
30214
|
}
|
|
30112
30215
|
|
|
30216
|
+
// src/utils/manifold/load-manifold.ts
|
|
30217
|
+
var manifoldPromise;
|
|
30218
|
+
function loadManifold() {
|
|
30219
|
+
if (!manifoldPromise) {
|
|
30220
|
+
manifoldPromise = (async () => {
|
|
30221
|
+
const existing = window.ManifoldModule ?? window.MANIFOLD ?? window.MANIFOLD_MODULE;
|
|
30222
|
+
if (existing && typeof existing === "object" && existing.setup) {
|
|
30223
|
+
window.ManifoldModule = existing;
|
|
30224
|
+
return existing;
|
|
30225
|
+
}
|
|
30226
|
+
const factory = existing ?? (await import(
|
|
30227
|
+
/* @vite-ignore */
|
|
30228
|
+
/* webpackIgnore: true */
|
|
30229
|
+
getRuntimeAssetUrl("manifold-3d", "3.2.1", "manifold.js")
|
|
30230
|
+
)).default;
|
|
30231
|
+
const module = await factory();
|
|
30232
|
+
module.setup();
|
|
30233
|
+
window.ManifoldModule = module;
|
|
30234
|
+
return module;
|
|
30235
|
+
})().catch((error) => {
|
|
30236
|
+
manifoldPromise = void 0;
|
|
30237
|
+
throw error;
|
|
30238
|
+
});
|
|
30239
|
+
}
|
|
30240
|
+
return manifoldPromise;
|
|
30241
|
+
}
|
|
30242
|
+
|
|
30113
30243
|
// src/CadViewerManifold.tsx
|
|
30114
30244
|
import { jsx as jsx19, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
30115
30245
|
var BoardMeshes = ({
|
|
@@ -30139,14 +30269,14 @@ var BoardMeshes = ({
|
|
|
30139
30269
|
const typedMaterial = material;
|
|
30140
30270
|
for (const prop of textureProps) {
|
|
30141
30271
|
const texture = typedMaterial[prop];
|
|
30142
|
-
if (texture && texture instanceof
|
|
30272
|
+
if (texture && texture instanceof THREE56.Texture) {
|
|
30143
30273
|
texture.dispose();
|
|
30144
30274
|
}
|
|
30145
30275
|
}
|
|
30146
30276
|
material.dispose();
|
|
30147
30277
|
}
|
|
30148
30278
|
};
|
|
30149
|
-
|
|
30279
|
+
useEffect31(() => {
|
|
30150
30280
|
if (!rootObject) return;
|
|
30151
30281
|
for (const mesh of geometryMeshes) {
|
|
30152
30282
|
let shouldShow = true;
|
|
@@ -30168,7 +30298,7 @@ var BoardMeshes = ({
|
|
|
30168
30298
|
}
|
|
30169
30299
|
};
|
|
30170
30300
|
}, [rootObject, geometryMeshes, visibility]);
|
|
30171
|
-
|
|
30301
|
+
useEffect31(() => {
|
|
30172
30302
|
if (!rootObject) return;
|
|
30173
30303
|
for (const mesh of textureMeshes) {
|
|
30174
30304
|
rootObject.add(mesh);
|
|
@@ -30184,7 +30314,6 @@ var BoardMeshes = ({
|
|
|
30184
30314
|
}, [rootObject, textureMeshes]);
|
|
30185
30315
|
return null;
|
|
30186
30316
|
};
|
|
30187
|
-
var MANIFOLD_CDN_BASE_URL = "https://cdn.jsdelivr.net/npm/manifold-3d@3.2.1";
|
|
30188
30317
|
var CadViewerManifold = ({
|
|
30189
30318
|
circuitJson: circuitJsonProp,
|
|
30190
30319
|
foldPcbs,
|
|
@@ -30205,66 +30334,19 @@ var CadViewerManifold = ({
|
|
|
30205
30334
|
const [manifoldJSModule, setManifoldJSModule] = useState19(null);
|
|
30206
30335
|
const [manifoldLoadingError, setManifoldLoadingError] = useState19(null);
|
|
30207
30336
|
const { visibility } = useLayerVisibility();
|
|
30208
|
-
|
|
30209
|
-
|
|
30210
|
-
|
|
30211
|
-
|
|
30212
|
-
}
|
|
30213
|
-
|
|
30214
|
-
|
|
30215
|
-
|
|
30216
|
-
|
|
30217
|
-
|
|
30218
|
-
|
|
30219
|
-
} catch (error) {
|
|
30220
|
-
console.error("Failed to initialize Manifold:", error);
|
|
30221
|
-
setManifoldLoadingError(
|
|
30222
|
-
`Failed to initialize Manifold: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
30223
|
-
);
|
|
30224
|
-
}
|
|
30225
|
-
};
|
|
30226
|
-
const existingManifold = window.ManifoldModule ?? window.MANIFOLD ?? window.MANIFOLD_MODULE;
|
|
30227
|
-
if (existingManifold) {
|
|
30228
|
-
window.ManifoldModule = existingManifold;
|
|
30229
|
-
initManifold(window.ManifoldModule);
|
|
30230
|
-
return;
|
|
30231
|
-
}
|
|
30232
|
-
const eventName = "manifoldLoaded";
|
|
30233
|
-
const handleLoad = () => {
|
|
30234
|
-
const loadedManifold = window.ManifoldModule ?? window.MANIFOLD ?? window.MANIFOLD_MODULE;
|
|
30235
|
-
if (loadedManifold) {
|
|
30236
|
-
window.ManifoldModule = loadedManifold;
|
|
30237
|
-
initManifold(window.ManifoldModule);
|
|
30238
|
-
} else {
|
|
30239
|
-
const errText = "ManifoldModule not found on window after script load.";
|
|
30240
|
-
console.error(errText);
|
|
30241
|
-
setManifoldLoadingError(errText);
|
|
30242
|
-
}
|
|
30243
|
-
};
|
|
30244
|
-
window.addEventListener(eventName, handleLoad, { once: true });
|
|
30245
|
-
const script = document.createElement("script");
|
|
30246
|
-
script.type = "module";
|
|
30247
|
-
script.innerHTML = `
|
|
30248
|
-
try {
|
|
30249
|
-
const { default: ManifoldModule } = await import('${MANIFOLD_CDN_BASE_URL}/manifold.js');
|
|
30250
|
-
window.ManifoldModule = ManifoldModule;
|
|
30251
|
-
} catch (e) {
|
|
30252
|
-
console.error('Error importing manifold in dynamic script:', e);
|
|
30253
|
-
} finally {
|
|
30254
|
-
window.dispatchEvent(new CustomEvent('${eventName}'));
|
|
30255
|
-
}
|
|
30256
|
-
`.trim();
|
|
30257
|
-
const scriptError = (err) => {
|
|
30258
|
-
const errText = "Failed to load Manifold loader script.";
|
|
30259
|
-
console.error(errText, err);
|
|
30260
|
-
setManifoldLoadingError(errText);
|
|
30261
|
-
window.removeEventListener(eventName, handleLoad);
|
|
30262
|
-
};
|
|
30263
|
-
script.addEventListener("error", scriptError);
|
|
30264
|
-
document.body.appendChild(script);
|
|
30337
|
+
useEffect31(() => {
|
|
30338
|
+
let isActive = true;
|
|
30339
|
+
loadManifold().then((module) => {
|
|
30340
|
+
if (isActive) setManifoldJSModule(module);
|
|
30341
|
+
}).catch((error) => {
|
|
30342
|
+
if (!isActive) return;
|
|
30343
|
+
console.error("Failed to initialize Manifold:", error);
|
|
30344
|
+
setManifoldLoadingError(
|
|
30345
|
+
`Failed to initialize Manifold: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
30346
|
+
);
|
|
30347
|
+
});
|
|
30265
30348
|
return () => {
|
|
30266
|
-
|
|
30267
|
-
script.removeEventListener("error", scriptError);
|
|
30349
|
+
isActive = false;
|
|
30268
30350
|
};
|
|
30269
30351
|
}, []);
|
|
30270
30352
|
const {
|
|
@@ -30326,20 +30408,16 @@ try {
|
|
|
30326
30408
|
return { x: bounds.centerX, y: bounds.centerY };
|
|
30327
30409
|
}, [boardData]);
|
|
30328
30410
|
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]);
|
|
30411
|
+
return getInitialCameraPosition({ boardDimensions, boardCenter });
|
|
30412
|
+
}, [boardDimensions, boardCenter]);
|
|
30413
|
+
const cameraSessionScope = useMemo26(() => {
|
|
30414
|
+
if (!boardData) return void 0;
|
|
30415
|
+
return JSON.stringify({
|
|
30416
|
+
pcbBoardId: boardData.pcb_board_id,
|
|
30417
|
+
center: boardCenter,
|
|
30418
|
+
dimensions: boardDimensions
|
|
30419
|
+
});
|
|
30420
|
+
}, [boardData, boardCenter, boardDimensions]);
|
|
30343
30421
|
if (manifoldLoadingError) {
|
|
30344
30422
|
return /* @__PURE__ */ jsxs5(
|
|
30345
30423
|
"div",
|
|
@@ -30389,6 +30467,7 @@ try {
|
|
|
30389
30467
|
clickToInteractEnabled,
|
|
30390
30468
|
boardDimensions,
|
|
30391
30469
|
boardCenter,
|
|
30470
|
+
cameraSessionScope,
|
|
30392
30471
|
referenceObject,
|
|
30393
30472
|
onUserInteraction,
|
|
30394
30473
|
onCameraControllerReady,
|
|
@@ -37871,10 +37950,10 @@ var ContextMenu = ({
|
|
|
37871
37950
|
};
|
|
37872
37951
|
|
|
37873
37952
|
// src/components/KeyboardShortcutsDialog.tsx
|
|
37874
|
-
import { useEffect as
|
|
37953
|
+
import { useEffect as useEffect49, useMemo as useMemo36, useRef as useRef27, useState as useState40 } from "react";
|
|
37875
37954
|
|
|
37876
37955
|
// src/hooks/useRegisteredHotkey.ts
|
|
37877
|
-
import { useEffect as
|
|
37956
|
+
import { useEffect as useEffect48, useMemo as useMemo35, useRef as useRef26, useState as useState39 } from "react";
|
|
37878
37957
|
var hotkeyRegistry = /* @__PURE__ */ new Map();
|
|
37879
37958
|
var subscribers = /* @__PURE__ */ new Set();
|
|
37880
37959
|
var isListenerAttached = false;
|
|
@@ -38005,7 +38084,7 @@ var useRegisteredHotkey = (id, handler, metadata) => {
|
|
|
38005
38084
|
}),
|
|
38006
38085
|
[metadata.shortcut, metadata.description]
|
|
38007
38086
|
);
|
|
38008
|
-
|
|
38087
|
+
useEffect48(() => {
|
|
38009
38088
|
const registration = {
|
|
38010
38089
|
id,
|
|
38011
38090
|
...normalizedMetadata,
|
|
@@ -38021,7 +38100,7 @@ var useHotkeyRegistry = () => {
|
|
|
38021
38100
|
const [entries, setEntries] = useState39(
|
|
38022
38101
|
() => Array.from(hotkeyRegistry.values())
|
|
38023
38102
|
);
|
|
38024
|
-
|
|
38103
|
+
useEffect48(() => subscribeToRegistry(setEntries), []);
|
|
38025
38104
|
return entries;
|
|
38026
38105
|
};
|
|
38027
38106
|
var registerHotkeyViewer = (element) => {
|
|
@@ -38038,7 +38117,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
38038
38117
|
const [query, setQuery] = useState40("");
|
|
38039
38118
|
const inputRef = useRef27(null);
|
|
38040
38119
|
const hotkeys = useHotkeyRegistry();
|
|
38041
|
-
|
|
38120
|
+
useEffect49(() => {
|
|
38042
38121
|
if (!open) return void 0;
|
|
38043
38122
|
const handleKeyDown = (event) => {
|
|
38044
38123
|
if (event.key === "Escape") {
|
|
@@ -38049,7 +38128,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
38049
38128
|
window.addEventListener("keydown", handleKeyDown);
|
|
38050
38129
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
38051
38130
|
}, [open, onClose]);
|
|
38052
|
-
|
|
38131
|
+
useEffect49(() => {
|
|
38053
38132
|
if (open) {
|
|
38054
38133
|
setTimeout(() => {
|
|
38055
38134
|
inputRef.current?.focus();
|
|
@@ -38278,7 +38357,7 @@ function useCameraPreset({
|
|
|
38278
38357
|
}
|
|
38279
38358
|
|
|
38280
38359
|
// src/hooks/useContextMenu.ts
|
|
38281
|
-
import { useState as useState41, useCallback as useCallback23, useRef as useRef28, useEffect as
|
|
38360
|
+
import { useState as useState41, useCallback as useCallback23, useRef as useRef28, useEffect as useEffect50 } from "react";
|
|
38282
38361
|
var useContextMenu = ({ containerRef, onOpen }) => {
|
|
38283
38362
|
const [menuVisible, setMenuVisible] = useState41(false);
|
|
38284
38363
|
const [menuPos, setMenuPos] = useState41({
|
|
@@ -38395,7 +38474,7 @@ var useContextMenu = ({ containerRef, onOpen }) => {
|
|
|
38395
38474
|
}
|
|
38396
38475
|
setMenuVisible(false);
|
|
38397
38476
|
}, []);
|
|
38398
|
-
|
|
38477
|
+
useEffect50(() => {
|
|
38399
38478
|
if (menuVisible) {
|
|
38400
38479
|
document.addEventListener("mousedown", handleClickAway);
|
|
38401
38480
|
document.addEventListener("touchstart", handleClickAway);
|
|
@@ -38459,7 +38538,7 @@ var useGlobalDownloadGltf = () => {
|
|
|
38459
38538
|
|
|
38460
38539
|
// src/CadViewer.tsx
|
|
38461
38540
|
import { jsx as jsx38, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
38462
|
-
var DEFAULT_TARGET = new
|
|
38541
|
+
var DEFAULT_TARGET = new THREE57.Vector3(0, 0, 0);
|
|
38463
38542
|
var INITIAL_CAMERA_POSITION = [5, -5, 5];
|
|
38464
38543
|
var readStoredCameraType = () => {
|
|
38465
38544
|
if (typeof window === "undefined") return void 0;
|
|
@@ -38626,24 +38705,24 @@ var CadViewerInner = (props) => {
|
|
|
38626
38705
|
description: "Toggle translucent components"
|
|
38627
38706
|
}
|
|
38628
38707
|
);
|
|
38629
|
-
|
|
38708
|
+
useEffect51(() => {
|
|
38630
38709
|
if (containerRef.current) {
|
|
38631
38710
|
registerHotkeyViewer(containerRef.current);
|
|
38632
38711
|
}
|
|
38633
38712
|
}, []);
|
|
38634
|
-
|
|
38713
|
+
useEffect51(() => {
|
|
38635
38714
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
38636
38715
|
}, [engine]);
|
|
38637
|
-
|
|
38716
|
+
useEffect51(() => {
|
|
38638
38717
|
window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
|
|
38639
38718
|
}, [autoRotate]);
|
|
38640
|
-
|
|
38719
|
+
useEffect51(() => {
|
|
38641
38720
|
window.localStorage.setItem(
|
|
38642
38721
|
"cadViewerAutoRotateUserToggled",
|
|
38643
38722
|
String(autoRotateUserToggled)
|
|
38644
38723
|
);
|
|
38645
38724
|
}, [autoRotateUserToggled]);
|
|
38646
|
-
|
|
38725
|
+
useEffect51(() => {
|
|
38647
38726
|
window.localStorage.setItem("cadViewerCameraType", cameraType);
|
|
38648
38727
|
}, [cameraType]);
|
|
38649
38728
|
const viewerKey = props.circuitJson ? circuitKey : void 0;
|
|
@@ -38767,6 +38846,7 @@ var CadViewerInner = (props) => {
|
|
|
38767
38846
|
);
|
|
38768
38847
|
};
|
|
38769
38848
|
var CadViewer = (props) => {
|
|
38849
|
+
configureRuntimeFont();
|
|
38770
38850
|
const sceneRef = useRef29(null);
|
|
38771
38851
|
return /* @__PURE__ */ jsx38(SchematicNavigationContext.Provider, { value: sceneRef, children: /* @__PURE__ */ jsx38(
|
|
38772
38852
|
CameraControllerProvider,
|
|
@@ -38782,11 +38862,11 @@ var CadViewer = (props) => {
|
|
|
38782
38862
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
38783
38863
|
var import_debug = __toESM(require_browser(), 1);
|
|
38784
38864
|
import { su as su18 } from "@tscircuit/circuit-json-util";
|
|
38785
|
-
import * as
|
|
38865
|
+
import * as THREE61 from "three";
|
|
38786
38866
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
38787
38867
|
|
|
38788
38868
|
// src/utils/create-geometry-from-polygons.ts
|
|
38789
|
-
import * as
|
|
38869
|
+
import * as THREE58 from "three";
|
|
38790
38870
|
import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6 } from "three";
|
|
38791
38871
|
function createGeometryFromPolygons(polygons) {
|
|
38792
38872
|
const geometry = new BufferGeometry6();
|
|
@@ -38800,12 +38880,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
38800
38880
|
...polygon2.vertices[i + 1]
|
|
38801
38881
|
// Third vertex
|
|
38802
38882
|
);
|
|
38803
|
-
const v1 = new
|
|
38804
|
-
const v2 = new
|
|
38805
|
-
const v3 = new
|
|
38806
|
-
const normal = new
|
|
38807
|
-
new
|
|
38808
|
-
new
|
|
38883
|
+
const v1 = new THREE58.Vector3(...polygon2.vertices[0]);
|
|
38884
|
+
const v2 = new THREE58.Vector3(...polygon2.vertices[i]);
|
|
38885
|
+
const v3 = new THREE58.Vector3(...polygon2.vertices[i + 1]);
|
|
38886
|
+
const normal = new THREE58.Vector3().crossVectors(
|
|
38887
|
+
new THREE58.Vector3().subVectors(v2, v1),
|
|
38888
|
+
new THREE58.Vector3().subVectors(v3, v1)
|
|
38809
38889
|
).normalize();
|
|
38810
38890
|
normals.push(
|
|
38811
38891
|
normal.x,
|
|
@@ -38833,10 +38913,10 @@ import {
|
|
|
38833
38913
|
convertCSGToThreeGeom as convertCSGToThreeGeom3,
|
|
38834
38914
|
getJscadModelForFootprint as getJscadModelForFootprint2
|
|
38835
38915
|
} from "jscad-electronics/vanilla";
|
|
38836
|
-
import * as
|
|
38916
|
+
import * as THREE60 from "three";
|
|
38837
38917
|
|
|
38838
38918
|
// src/utils/load-model.ts
|
|
38839
|
-
import * as
|
|
38919
|
+
import * as THREE59 from "three";
|
|
38840
38920
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
38841
38921
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
38842
38922
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -38844,12 +38924,12 @@ async function load3DModel(url) {
|
|
|
38844
38924
|
if (url.endsWith(".stl")) {
|
|
38845
38925
|
const loader = new STLLoader2();
|
|
38846
38926
|
const geometry = await loader.loadAsync(url);
|
|
38847
|
-
const material = new
|
|
38927
|
+
const material = new THREE59.MeshStandardMaterial({
|
|
38848
38928
|
color: 8947848,
|
|
38849
38929
|
metalness: 0.5,
|
|
38850
38930
|
roughness: 0.5
|
|
38851
38931
|
});
|
|
38852
|
-
return new
|
|
38932
|
+
return new THREE59.Mesh(geometry, material);
|
|
38853
38933
|
}
|
|
38854
38934
|
if (url.endsWith(".obj")) {
|
|
38855
38935
|
const loader = new OBJLoader2();
|
|
@@ -38882,9 +38962,9 @@ async function renderComponent(component, scene) {
|
|
|
38882
38962
|
}
|
|
38883
38963
|
if (component.rotation) {
|
|
38884
38964
|
model.rotation.set(
|
|
38885
|
-
|
|
38886
|
-
|
|
38887
|
-
|
|
38965
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
38966
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
38967
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38888
38968
|
);
|
|
38889
38969
|
}
|
|
38890
38970
|
scene.add(model);
|
|
@@ -38898,13 +38978,13 @@ async function renderComponent(component, scene) {
|
|
|
38898
38978
|
);
|
|
38899
38979
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
38900
38980
|
const threeGeom = convertCSGToThreeGeom3(jscadObject);
|
|
38901
|
-
const material2 = new
|
|
38981
|
+
const material2 = new THREE60.MeshStandardMaterial({
|
|
38902
38982
|
color: 8947848,
|
|
38903
38983
|
metalness: 0.5,
|
|
38904
38984
|
roughness: 0.5,
|
|
38905
|
-
side:
|
|
38985
|
+
side: THREE60.DoubleSide
|
|
38906
38986
|
});
|
|
38907
|
-
const mesh2 = new
|
|
38987
|
+
const mesh2 = new THREE60.Mesh(threeGeom, material2);
|
|
38908
38988
|
if (component.position) {
|
|
38909
38989
|
mesh2.position.set(
|
|
38910
38990
|
component.position.x ?? 0,
|
|
@@ -38914,9 +38994,9 @@ async function renderComponent(component, scene) {
|
|
|
38914
38994
|
}
|
|
38915
38995
|
if (component.rotation) {
|
|
38916
38996
|
mesh2.rotation.set(
|
|
38917
|
-
|
|
38918
|
-
|
|
38919
|
-
|
|
38997
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
38998
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
38999
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38920
39000
|
);
|
|
38921
39001
|
}
|
|
38922
39002
|
scene.add(mesh2);
|
|
@@ -38933,17 +39013,17 @@ async function renderComponent(component, scene) {
|
|
|
38933
39013
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
38934
39014
|
continue;
|
|
38935
39015
|
}
|
|
38936
|
-
const color = new
|
|
39016
|
+
const color = new THREE60.Color(geomInfo.color);
|
|
38937
39017
|
color.convertLinearToSRGB();
|
|
38938
39018
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
38939
39019
|
const threeGeom = convertCSGToThreeGeom3(geomWithColor);
|
|
38940
|
-
const material2 = new
|
|
39020
|
+
const material2 = new THREE60.MeshStandardMaterial({
|
|
38941
39021
|
vertexColors: true,
|
|
38942
39022
|
metalness: 0.2,
|
|
38943
39023
|
roughness: 0.8,
|
|
38944
|
-
side:
|
|
39024
|
+
side: THREE60.DoubleSide
|
|
38945
39025
|
});
|
|
38946
|
-
const mesh2 = new
|
|
39026
|
+
const mesh2 = new THREE60.Mesh(threeGeom, material2);
|
|
38947
39027
|
if (component.position) {
|
|
38948
39028
|
mesh2.position.set(
|
|
38949
39029
|
component.position.x ?? 0,
|
|
@@ -38953,22 +39033,22 @@ async function renderComponent(component, scene) {
|
|
|
38953
39033
|
}
|
|
38954
39034
|
if (component.rotation) {
|
|
38955
39035
|
mesh2.rotation.set(
|
|
38956
|
-
|
|
38957
|
-
|
|
38958
|
-
|
|
39036
|
+
THREE60.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
39037
|
+
THREE60.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
39038
|
+
THREE60.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
38959
39039
|
);
|
|
38960
39040
|
}
|
|
38961
39041
|
scene.add(mesh2);
|
|
38962
39042
|
}
|
|
38963
39043
|
return;
|
|
38964
39044
|
}
|
|
38965
|
-
const geometry = new
|
|
38966
|
-
const material = new
|
|
39045
|
+
const geometry = new THREE60.BoxGeometry(0.5, 0.5, 0.5);
|
|
39046
|
+
const material = new THREE60.MeshStandardMaterial({
|
|
38967
39047
|
color: 16711680,
|
|
38968
39048
|
transparent: true,
|
|
38969
39049
|
opacity: 0.25
|
|
38970
39050
|
});
|
|
38971
|
-
const mesh = new
|
|
39051
|
+
const mesh = new THREE60.Mesh(geometry, material);
|
|
38972
39052
|
if (component.position) {
|
|
38973
39053
|
mesh.position.set(
|
|
38974
39054
|
component.position.x ?? 0,
|
|
@@ -38989,11 +39069,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
38989
39069
|
padding = 20,
|
|
38990
39070
|
zoom = 1.5
|
|
38991
39071
|
} = options;
|
|
38992
|
-
const scene = new
|
|
39072
|
+
const scene = new THREE61.Scene();
|
|
38993
39073
|
const renderer = new SVGRenderer();
|
|
38994
39074
|
renderer.setSize(width, height);
|
|
38995
|
-
renderer.setClearColor(new
|
|
38996
|
-
const camera = new
|
|
39075
|
+
renderer.setClearColor(new THREE61.Color(backgroundColor), 1);
|
|
39076
|
+
const camera = new THREE61.OrthographicCamera();
|
|
38997
39077
|
const aspect = width / height;
|
|
38998
39078
|
const frustumSize = 100;
|
|
38999
39079
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -39007,11 +39087,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39007
39087
|
camera.position.set(position.x, position.y, position.z);
|
|
39008
39088
|
camera.up.set(0, 1, 0);
|
|
39009
39089
|
const lookAt2 = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
39010
|
-
camera.lookAt(new
|
|
39090
|
+
camera.lookAt(new THREE61.Vector3(lookAt2.x, lookAt2.y, lookAt2.z));
|
|
39011
39091
|
camera.updateProjectionMatrix();
|
|
39012
|
-
const ambientLight = new
|
|
39092
|
+
const ambientLight = new THREE61.AmbientLight(16777215, Math.PI / 2);
|
|
39013
39093
|
scene.add(ambientLight);
|
|
39014
|
-
const pointLight = new
|
|
39094
|
+
const pointLight = new THREE61.PointLight(16777215, Math.PI / 4);
|
|
39015
39095
|
pointLight.position.set(-10, -10, 10);
|
|
39016
39096
|
scene.add(pointLight);
|
|
39017
39097
|
const components = su18(circuitJson).cad_component.list();
|
|
@@ -39043,28 +39123,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39043
39123
|
const material = createBoardMaterial({
|
|
39044
39124
|
material: boardData?.material,
|
|
39045
39125
|
color: edgeColor,
|
|
39046
|
-
side:
|
|
39126
|
+
side: THREE61.DoubleSide
|
|
39047
39127
|
});
|
|
39048
|
-
const mesh = new
|
|
39128
|
+
const mesh = new THREE61.Mesh(geometry, material);
|
|
39049
39129
|
scene.add(mesh);
|
|
39050
39130
|
}
|
|
39051
39131
|
}
|
|
39052
|
-
const gridColor = new
|
|
39053
|
-
const gridHelper = new
|
|
39132
|
+
const gridColor = new THREE61.Color(8947848);
|
|
39133
|
+
const gridHelper = new THREE61.GridHelper(100, 100, gridColor, gridColor);
|
|
39054
39134
|
gridHelper.rotation.x = Math.PI / 2;
|
|
39055
39135
|
const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
|
|
39056
39136
|
for (const mat of materials) {
|
|
39057
39137
|
mat.transparent = true;
|
|
39058
39138
|
mat.opacity = 0.3;
|
|
39059
|
-
if (mat instanceof
|
|
39139
|
+
if (mat instanceof THREE61.LineBasicMaterial) {
|
|
39060
39140
|
mat.color = gridColor;
|
|
39061
39141
|
mat.vertexColors = false;
|
|
39062
39142
|
}
|
|
39063
39143
|
}
|
|
39064
39144
|
scene.add(gridHelper);
|
|
39065
|
-
const box = new
|
|
39066
|
-
const center = box.getCenter(new
|
|
39067
|
-
const size4 = box.getSize(new
|
|
39145
|
+
const box = new THREE61.Box3().setFromObject(scene);
|
|
39146
|
+
const center = box.getCenter(new THREE61.Vector3());
|
|
39147
|
+
const size4 = box.getSize(new THREE61.Vector3());
|
|
39068
39148
|
scene.position.sub(center);
|
|
39069
39149
|
const maxDim = Math.max(size4.x, size4.y, size4.z);
|
|
39070
39150
|
if (maxDim > 0) {
|
|
@@ -39082,7 +39162,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
39082
39162
|
|
|
39083
39163
|
// src/hooks/exporter/gltf.ts
|
|
39084
39164
|
import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
|
|
39085
|
-
import { useEffect as
|
|
39165
|
+
import { useEffect as useEffect52, useState as useState43, useMemo as useMemo37, useCallback as useCallback26 } from "react";
|
|
39086
39166
|
function useSaveGltfAs(options = {}) {
|
|
39087
39167
|
const parse2 = useParser(options);
|
|
39088
39168
|
const link = useMemo37(() => document.createElement("a"), []);
|
|
@@ -39095,7 +39175,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
39095
39175
|
link.dispatchEvent(new MouseEvent("click"));
|
|
39096
39176
|
URL.revokeObjectURL(url);
|
|
39097
39177
|
};
|
|
39098
|
-
|
|
39178
|
+
useEffect52(
|
|
39099
39179
|
() => () => {
|
|
39100
39180
|
link.remove();
|
|
39101
39181
|
instance = null;
|
|
@@ -39116,7 +39196,7 @@ function useExportGltfUrl(options = {}) {
|
|
|
39116
39196
|
(instance) => parse2(instance).then(setUrl).catch(setError),
|
|
39117
39197
|
[]
|
|
39118
39198
|
);
|
|
39119
|
-
|
|
39199
|
+
useEffect52(() => () => URL.revokeObjectURL(url), [url]);
|
|
39120
39200
|
return [ref, url, error];
|
|
39121
39201
|
}
|
|
39122
39202
|
function useParser(options = {}) {
|