@tscircuit/3d-viewer 0.0.583 → 0.0.584
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +941 -340
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14432,12 +14432,12 @@ var require_browser = __commonJS({
|
|
|
14432
14432
|
});
|
|
14433
14433
|
|
|
14434
14434
|
// src/CadViewer.tsx
|
|
14435
|
-
import { useCallback as useCallback24, useEffect as
|
|
14436
|
-
import * as
|
|
14435
|
+
import { useCallback as useCallback24, useEffect as useEffect49, useRef as useRef29, useState as useState39 } from "react";
|
|
14436
|
+
import * as THREE48 from "three";
|
|
14437
14437
|
|
|
14438
14438
|
// src/CadViewerJscad.tsx
|
|
14439
14439
|
import { su as su11 } from "@tscircuit/circuit-json-util";
|
|
14440
|
-
import { forwardRef as forwardRef3, useMemo as
|
|
14440
|
+
import { forwardRef as forwardRef3, useMemo as useMemo22 } from "react";
|
|
14441
14441
|
|
|
14442
14442
|
// src/AnyCadComponent.tsx
|
|
14443
14443
|
import { su as su2 } from "@tscircuit/circuit-json-util";
|
|
@@ -32704,13 +32704,13 @@ var AnyCadComponent = ({
|
|
|
32704
32704
|
};
|
|
32705
32705
|
|
|
32706
32706
|
// src/CadViewerContainer.tsx
|
|
32707
|
-
import { forwardRef as forwardRef2, useEffect as
|
|
32708
|
-
import * as
|
|
32707
|
+
import { forwardRef as forwardRef2, useEffect as useEffect20, useMemo as useMemo16, useState as useState11 } from "react";
|
|
32708
|
+
import * as THREE23 from "three";
|
|
32709
32709
|
|
|
32710
32710
|
// package.json
|
|
32711
32711
|
var package_default = {
|
|
32712
32712
|
name: "@tscircuit/3d-viewer",
|
|
32713
|
-
version: "0.0.
|
|
32713
|
+
version: "0.0.583",
|
|
32714
32714
|
main: "./dist/index.js",
|
|
32715
32715
|
module: "./dist/index.js",
|
|
32716
32716
|
type: "module",
|
|
@@ -33692,6 +33692,85 @@ var OrbitControls = ({
|
|
|
33692
33692
|
return null;
|
|
33693
33693
|
};
|
|
33694
33694
|
|
|
33695
|
+
// src/reference-objects/reference-object.ts
|
|
33696
|
+
var REFERENCE_OBJECT_CLEARANCE_MM = 10;
|
|
33697
|
+
var REFERENCE_OBJECT_SPECS = {
|
|
33698
|
+
banana: {
|
|
33699
|
+
type: "banana",
|
|
33700
|
+
label: "Show Banana",
|
|
33701
|
+
// USDA describes a medium banana as 7 to 7 7/8 inches long. The 190 mm
|
|
33702
|
+
// envelope is near the midpoint of that range.
|
|
33703
|
+
width: 190,
|
|
33704
|
+
height: 60,
|
|
33705
|
+
depth: 34,
|
|
33706
|
+
zCenter: 17
|
|
33707
|
+
},
|
|
33708
|
+
"credit-card": {
|
|
33709
|
+
type: "credit-card",
|
|
33710
|
+
label: "Show Credit Card",
|
|
33711
|
+
// ISO/IEC 7810 ID-1 dimensions.
|
|
33712
|
+
width: 85.6,
|
|
33713
|
+
height: 53.98,
|
|
33714
|
+
depth: 0.76,
|
|
33715
|
+
zCenter: 0
|
|
33716
|
+
},
|
|
33717
|
+
"14in-macbook": {
|
|
33718
|
+
type: "14in-macbook",
|
|
33719
|
+
label: "Show 14in Macbook",
|
|
33720
|
+
// Current 14-inch MacBook Pro exterior dimensions.
|
|
33721
|
+
width: 312.6,
|
|
33722
|
+
height: 221.2,
|
|
33723
|
+
depth: 15.5,
|
|
33724
|
+
zCenter: 0
|
|
33725
|
+
}
|
|
33726
|
+
};
|
|
33727
|
+
var REFERENCE_OBJECT_OPTIONS = Object.values(REFERENCE_OBJECT_SPECS);
|
|
33728
|
+
var safeDimension = (dimension) => Number.isFinite(dimension) ? Math.max(dimension ?? 0, 0) : 0;
|
|
33729
|
+
var safeCoordinate = (coordinate) => Number.isFinite(coordinate) ? coordinate ?? 0 : 0;
|
|
33730
|
+
var getReferenceObjectPosition = (type, boardDimensions, boardCenter) => {
|
|
33731
|
+
const spec = REFERENCE_OBJECT_SPECS[type];
|
|
33732
|
+
const boardWidth = safeDimension(boardDimensions?.width);
|
|
33733
|
+
const centerX = safeCoordinate(boardCenter?.x);
|
|
33734
|
+
const centerY = safeCoordinate(boardCenter?.y);
|
|
33735
|
+
return {
|
|
33736
|
+
x: centerX + boardWidth / 2 + REFERENCE_OBJECT_CLEARANCE_MM + spec.width / 2,
|
|
33737
|
+
y: centerY,
|
|
33738
|
+
z: 0
|
|
33739
|
+
};
|
|
33740
|
+
};
|
|
33741
|
+
var getComparisonBounds = (type, boardDimensions, boardCenter) => {
|
|
33742
|
+
const spec = REFERENCE_OBJECT_SPECS[type];
|
|
33743
|
+
const boardWidth = safeDimension(boardDimensions?.width);
|
|
33744
|
+
const boardHeight = safeDimension(boardDimensions?.height);
|
|
33745
|
+
const centerX = safeCoordinate(boardCenter?.x);
|
|
33746
|
+
const centerY = safeCoordinate(boardCenter?.y);
|
|
33747
|
+
const referencePosition = getReferenceObjectPosition(
|
|
33748
|
+
type,
|
|
33749
|
+
boardDimensions,
|
|
33750
|
+
boardCenter
|
|
33751
|
+
);
|
|
33752
|
+
return {
|
|
33753
|
+
minX: Math.min(
|
|
33754
|
+
centerX - boardWidth / 2,
|
|
33755
|
+
referencePosition.x - spec.width / 2
|
|
33756
|
+
),
|
|
33757
|
+
maxX: Math.max(
|
|
33758
|
+
centerX + boardWidth / 2,
|
|
33759
|
+
referencePosition.x + spec.width / 2
|
|
33760
|
+
),
|
|
33761
|
+
minY: Math.min(
|
|
33762
|
+
centerY - boardHeight / 2,
|
|
33763
|
+
referencePosition.y - spec.height / 2
|
|
33764
|
+
),
|
|
33765
|
+
maxY: Math.max(
|
|
33766
|
+
centerY + boardHeight / 2,
|
|
33767
|
+
referencePosition.y + spec.height / 2
|
|
33768
|
+
),
|
|
33769
|
+
minZ: Math.min(0, referencePosition.z + spec.zCenter - spec.depth / 2),
|
|
33770
|
+
maxZ: Math.max(0, referencePosition.z + spec.zCenter + spec.depth / 2)
|
|
33771
|
+
};
|
|
33772
|
+
};
|
|
33773
|
+
|
|
33695
33774
|
// src/three-components/OrientationCubeCanvas.tsx
|
|
33696
33775
|
import { useEffect as useEffect18, useRef as useRef7 } from "react";
|
|
33697
33776
|
import * as THREE20 from "three";
|
|
@@ -33841,6 +33920,421 @@ var OrientationCubeCanvas = () => {
|
|
|
33841
33920
|
);
|
|
33842
33921
|
};
|
|
33843
33922
|
|
|
33923
|
+
// src/three-components/reference-object.tsx
|
|
33924
|
+
import { useEffect as useEffect19, useMemo as useMemo15 } from "react";
|
|
33925
|
+
|
|
33926
|
+
// src/reference-objects/create-reference-object.ts
|
|
33927
|
+
import * as THREE21 from "three";
|
|
33928
|
+
var createRoundedRectangleShape = (width10, height10, radius) => {
|
|
33929
|
+
const halfWidth = width10 / 2;
|
|
33930
|
+
const halfHeight = height10 / 2;
|
|
33931
|
+
const safeRadius = Math.min(radius, halfWidth, halfHeight);
|
|
33932
|
+
const shape = new THREE21.Shape();
|
|
33933
|
+
shape.moveTo(-halfWidth + safeRadius, -halfHeight);
|
|
33934
|
+
shape.lineTo(halfWidth - safeRadius, -halfHeight);
|
|
33935
|
+
shape.quadraticCurveTo(
|
|
33936
|
+
halfWidth,
|
|
33937
|
+
-halfHeight,
|
|
33938
|
+
halfWidth,
|
|
33939
|
+
-halfHeight + safeRadius
|
|
33940
|
+
);
|
|
33941
|
+
shape.lineTo(halfWidth, halfHeight - safeRadius);
|
|
33942
|
+
shape.quadraticCurveTo(
|
|
33943
|
+
halfWidth,
|
|
33944
|
+
halfHeight,
|
|
33945
|
+
halfWidth - safeRadius,
|
|
33946
|
+
halfHeight
|
|
33947
|
+
);
|
|
33948
|
+
shape.lineTo(-halfWidth + safeRadius, halfHeight);
|
|
33949
|
+
shape.quadraticCurveTo(
|
|
33950
|
+
-halfWidth,
|
|
33951
|
+
halfHeight,
|
|
33952
|
+
-halfWidth,
|
|
33953
|
+
halfHeight - safeRadius
|
|
33954
|
+
);
|
|
33955
|
+
shape.lineTo(-halfWidth, -halfHeight + safeRadius);
|
|
33956
|
+
shape.quadraticCurveTo(
|
|
33957
|
+
-halfWidth,
|
|
33958
|
+
-halfHeight,
|
|
33959
|
+
-halfWidth + safeRadius,
|
|
33960
|
+
-halfHeight
|
|
33961
|
+
);
|
|
33962
|
+
return shape;
|
|
33963
|
+
};
|
|
33964
|
+
var createRoundedPrismGeometry = (width10, height10, depth, radius) => {
|
|
33965
|
+
return createPrismGeometryFromShape(
|
|
33966
|
+
createRoundedRectangleShape(width10, height10, radius),
|
|
33967
|
+
depth
|
|
33968
|
+
);
|
|
33969
|
+
};
|
|
33970
|
+
var createPrismGeometryFromShape = (shape, depth) => {
|
|
33971
|
+
const geometry = new THREE21.ExtrudeGeometry(shape, {
|
|
33972
|
+
depth,
|
|
33973
|
+
bevelEnabled: false,
|
|
33974
|
+
curveSegments: 24
|
|
33975
|
+
});
|
|
33976
|
+
geometry.translate(0, 0, -depth / 2);
|
|
33977
|
+
geometry.computeVertexNormals();
|
|
33978
|
+
return geometry;
|
|
33979
|
+
};
|
|
33980
|
+
var normalizeObjectToSpec = (object, type) => {
|
|
33981
|
+
const spec = REFERENCE_OBJECT_SPECS[type];
|
|
33982
|
+
object.updateMatrixWorld(true);
|
|
33983
|
+
const initialBounds = new THREE21.Box3().setFromObject(object);
|
|
33984
|
+
const initialSize = initialBounds.getSize(new THREE21.Vector3());
|
|
33985
|
+
object.scale.set(
|
|
33986
|
+
spec.width / initialSize.x,
|
|
33987
|
+
spec.height / initialSize.y,
|
|
33988
|
+
spec.depth / initialSize.z
|
|
33989
|
+
);
|
|
33990
|
+
object.updateMatrixWorld(true);
|
|
33991
|
+
const scaledBounds = new THREE21.Box3().setFromObject(object);
|
|
33992
|
+
const scaledCenter = scaledBounds.getCenter(new THREE21.Vector3());
|
|
33993
|
+
object.position.set(
|
|
33994
|
+
-scaledCenter.x,
|
|
33995
|
+
-scaledCenter.y,
|
|
33996
|
+
spec.zCenter - scaledCenter.z
|
|
33997
|
+
);
|
|
33998
|
+
object.updateMatrixWorld(true);
|
|
33999
|
+
};
|
|
34000
|
+
var createBananaGeometry = () => {
|
|
34001
|
+
const curve = new THREE21.CatmullRomCurve3([
|
|
34002
|
+
new THREE21.Vector3(-82, 18, 16),
|
|
34003
|
+
new THREE21.Vector3(-67, 7, 15),
|
|
34004
|
+
new THREE21.Vector3(-43, -9, 14),
|
|
34005
|
+
new THREE21.Vector3(-15, -18, 14),
|
|
34006
|
+
new THREE21.Vector3(16, -18, 14),
|
|
34007
|
+
new THREE21.Vector3(47, -8, 14.5),
|
|
34008
|
+
new THREE21.Vector3(72, 8, 16),
|
|
34009
|
+
new THREE21.Vector3(84, 19, 17)
|
|
34010
|
+
]);
|
|
34011
|
+
const tubularSegments = 84;
|
|
34012
|
+
const radialSegments = 30;
|
|
34013
|
+
const frames = curve.computeFrenetFrames(tubularSegments, false);
|
|
34014
|
+
const positions = [];
|
|
34015
|
+
const normals = [];
|
|
34016
|
+
const colors2 = [];
|
|
34017
|
+
const uvs = [];
|
|
34018
|
+
const indices = [];
|
|
34019
|
+
const ripeYellow = new THREE21.Color(16766023);
|
|
34020
|
+
const stemGreen = new THREE21.Color(12038965);
|
|
34021
|
+
for (let segment = 0; segment <= tubularSegments; segment++) {
|
|
34022
|
+
const t = segment / tubularSegments;
|
|
34023
|
+
const point = curve.getPointAt(t);
|
|
34024
|
+
const normal = frames.normals[segment];
|
|
34025
|
+
const binormal = frames.binormals[segment];
|
|
34026
|
+
const taper = Math.sin(Math.PI * t) ** 0.48;
|
|
34027
|
+
const radius = 3.4 + 12.4 * taper;
|
|
34028
|
+
const stemBlend = Math.max(0, (t - 0.82) / 0.18) * 0.38;
|
|
34029
|
+
const ringColor = ripeYellow.clone().lerp(stemGreen, stemBlend);
|
|
34030
|
+
for (let side = 0; side <= radialSegments; side++) {
|
|
34031
|
+
const angle = side / radialSegments * Math.PI * 2;
|
|
34032
|
+
const sin = Math.sin(angle);
|
|
34033
|
+
const cos = Math.cos(angle);
|
|
34034
|
+
const ridgeScale = 1 + Math.cos(angle * 5 + 0.35) * 0.035;
|
|
34035
|
+
const radialNormal = new THREE21.Vector3().addScaledVector(normal, cos).addScaledVector(binormal, sin * 0.9).normalize();
|
|
34036
|
+
const vertex = point.clone().addScaledVector(normal, cos * radius * ridgeScale).addScaledVector(binormal, sin * radius * 0.9 * ridgeScale);
|
|
34037
|
+
positions.push(vertex.x, vertex.y, vertex.z);
|
|
34038
|
+
normals.push(radialNormal.x, radialNormal.y, radialNormal.z);
|
|
34039
|
+
colors2.push(ringColor.r, ringColor.g, ringColor.b);
|
|
34040
|
+
uvs.push(t, side / radialSegments);
|
|
34041
|
+
}
|
|
34042
|
+
}
|
|
34043
|
+
for (let segment = 1; segment <= tubularSegments; segment++) {
|
|
34044
|
+
for (let side = 1; side <= radialSegments; side++) {
|
|
34045
|
+
const rowSize = radialSegments + 1;
|
|
34046
|
+
const a = rowSize * (segment - 1) + (side - 1);
|
|
34047
|
+
const b = rowSize * segment + (side - 1);
|
|
34048
|
+
const c = rowSize * segment + side;
|
|
34049
|
+
const d = rowSize * (segment - 1) + side;
|
|
34050
|
+
indices.push(a, d, b, b, d, c);
|
|
34051
|
+
}
|
|
34052
|
+
}
|
|
34053
|
+
const geometry = new THREE21.BufferGeometry();
|
|
34054
|
+
geometry.setIndex(indices);
|
|
34055
|
+
geometry.setAttribute(
|
|
34056
|
+
"position",
|
|
34057
|
+
new THREE21.Float32BufferAttribute(positions, 3)
|
|
34058
|
+
);
|
|
34059
|
+
geometry.setAttribute("normal", new THREE21.Float32BufferAttribute(normals, 3));
|
|
34060
|
+
geometry.setAttribute("color", new THREE21.Float32BufferAttribute(colors2, 3));
|
|
34061
|
+
geometry.setAttribute("uv", new THREE21.Float32BufferAttribute(uvs, 2));
|
|
34062
|
+
geometry.computeBoundingBox();
|
|
34063
|
+
geometry.computeBoundingSphere();
|
|
34064
|
+
return { geometry, curve };
|
|
34065
|
+
};
|
|
34066
|
+
var createBanana = () => {
|
|
34067
|
+
const group = new THREE21.Group();
|
|
34068
|
+
const banana = new THREE21.Group();
|
|
34069
|
+
const { geometry, curve } = createBananaGeometry();
|
|
34070
|
+
const peel = new THREE21.Mesh(
|
|
34071
|
+
geometry,
|
|
34072
|
+
new THREE21.MeshStandardMaterial({
|
|
34073
|
+
color: 16777215,
|
|
34074
|
+
roughness: 0.72,
|
|
34075
|
+
metalness: 0,
|
|
34076
|
+
vertexColors: true
|
|
34077
|
+
})
|
|
34078
|
+
);
|
|
34079
|
+
peel.name = "banana-peel";
|
|
34080
|
+
banana.add(peel);
|
|
34081
|
+
const blossomTip = new THREE21.Mesh(
|
|
34082
|
+
new THREE21.SphereGeometry(3.4, 20, 12),
|
|
34083
|
+
new THREE21.MeshStandardMaterial({
|
|
34084
|
+
color: 6242844,
|
|
34085
|
+
roughness: 0.92
|
|
34086
|
+
})
|
|
34087
|
+
);
|
|
34088
|
+
blossomTip.position.copy(curve.getPointAt(0));
|
|
34089
|
+
blossomTip.scale.set(1.15, 0.78, 0.78);
|
|
34090
|
+
blossomTip.name = "banana-blossom-tip";
|
|
34091
|
+
banana.add(blossomTip);
|
|
34092
|
+
const stemLength = 11;
|
|
34093
|
+
const stemTangent = curve.getTangentAt(1).normalize();
|
|
34094
|
+
const stem = new THREE21.Mesh(
|
|
34095
|
+
new THREE21.CylinderGeometry(2.5, 4.1, stemLength, 18),
|
|
34096
|
+
new THREE21.MeshStandardMaterial({
|
|
34097
|
+
color: 8483625,
|
|
34098
|
+
roughness: 0.82
|
|
34099
|
+
})
|
|
34100
|
+
);
|
|
34101
|
+
stem.quaternion.setFromUnitVectors(new THREE21.Vector3(0, 1, 0), stemTangent);
|
|
34102
|
+
stem.position.copy(curve.getPointAt(1)).addScaledVector(stemTangent, stemLength / 2);
|
|
34103
|
+
stem.name = "banana-stem";
|
|
34104
|
+
banana.add(stem);
|
|
34105
|
+
const stemTip = new THREE21.Mesh(
|
|
34106
|
+
new THREE21.SphereGeometry(2.55, 18, 10),
|
|
34107
|
+
new THREE21.MeshStandardMaterial({
|
|
34108
|
+
color: 5981470,
|
|
34109
|
+
roughness: 0.9
|
|
34110
|
+
})
|
|
34111
|
+
);
|
|
34112
|
+
stemTip.position.copy(curve.getPointAt(1)).addScaledVector(stemTangent, stemLength);
|
|
34113
|
+
stemTip.name = "banana-stem-tip";
|
|
34114
|
+
banana.add(stemTip);
|
|
34115
|
+
normalizeObjectToSpec(banana, "banana");
|
|
34116
|
+
group.add(banana);
|
|
34117
|
+
return group;
|
|
34118
|
+
};
|
|
34119
|
+
var createMacbookLidGeometry = (width10, height10, depth, radius, indentRadius) => {
|
|
34120
|
+
const lidShape = createRoundedRectangleShape(width10, height10, radius);
|
|
34121
|
+
const indent = new THREE21.Path();
|
|
34122
|
+
indent.absarc(0, 0, indentRadius, 0, Math.PI * 2, true);
|
|
34123
|
+
lidShape.holes.push(indent);
|
|
34124
|
+
return createPrismGeometryFromShape(lidShape, depth);
|
|
34125
|
+
};
|
|
34126
|
+
var createMacbookIndent = (topZ, radius) => {
|
|
34127
|
+
const indentDepth = 0.35;
|
|
34128
|
+
const diskDepth = 0.25;
|
|
34129
|
+
const disk = new THREE21.Mesh(
|
|
34130
|
+
new THREE21.CylinderGeometry(radius - 0.15, radius - 0.15, diskDepth, 48),
|
|
34131
|
+
new THREE21.MeshStandardMaterial({
|
|
34132
|
+
color: 10199202,
|
|
34133
|
+
roughness: 0.48,
|
|
34134
|
+
metalness: 0.28
|
|
34135
|
+
})
|
|
34136
|
+
);
|
|
34137
|
+
disk.rotation.x = Math.PI / 2;
|
|
34138
|
+
disk.position.z = topZ - indentDepth - diskDepth / 2;
|
|
34139
|
+
disk.name = "macbook-lid-indent";
|
|
34140
|
+
return disk;
|
|
34141
|
+
};
|
|
34142
|
+
var createCreditCard = () => {
|
|
34143
|
+
const spec = REFERENCE_OBJECT_SPECS["credit-card"];
|
|
34144
|
+
const group = new THREE21.Group();
|
|
34145
|
+
const body = new THREE21.Mesh(
|
|
34146
|
+
createRoundedPrismGeometry(spec.width, spec.height, spec.depth, 3.18),
|
|
34147
|
+
new THREE21.MeshStandardMaterial({
|
|
34148
|
+
color: 2383272,
|
|
34149
|
+
roughness: 0.38,
|
|
34150
|
+
metalness: 0.08
|
|
34151
|
+
})
|
|
34152
|
+
);
|
|
34153
|
+
body.name = "credit-card-body";
|
|
34154
|
+
group.add(body);
|
|
34155
|
+
const surfaceZ = spec.depth / 2 + 0.08;
|
|
34156
|
+
const chip = new THREE21.Mesh(
|
|
34157
|
+
createRoundedPrismGeometry(12, 9, 0.14, 1.2),
|
|
34158
|
+
new THREE21.MeshStandardMaterial({
|
|
34159
|
+
color: 14003525,
|
|
34160
|
+
roughness: 0.3,
|
|
34161
|
+
metalness: 0.62
|
|
34162
|
+
})
|
|
34163
|
+
);
|
|
34164
|
+
chip.position.set(-21, 3, surfaceZ);
|
|
34165
|
+
chip.name = "credit-card-chip";
|
|
34166
|
+
group.add(chip);
|
|
34167
|
+
const stripeMaterial = new THREE21.MeshStandardMaterial({
|
|
34168
|
+
color: 15331061,
|
|
34169
|
+
roughness: 0.45,
|
|
34170
|
+
metalness: 0.05
|
|
34171
|
+
});
|
|
34172
|
+
for (let index2 = 0; index2 < 4; index2++) {
|
|
34173
|
+
const stripe = new THREE21.Mesh(
|
|
34174
|
+
new THREE21.BoxGeometry(index2 === 3 ? 8 : 12, 0.8, 0.1),
|
|
34175
|
+
stripeMaterial
|
|
34176
|
+
);
|
|
34177
|
+
stripe.position.set(-20 + index2 * 14, -14, surfaceZ + 0.08);
|
|
34178
|
+
stripe.name = "credit-card-detail";
|
|
34179
|
+
group.add(stripe);
|
|
34180
|
+
}
|
|
34181
|
+
return group;
|
|
34182
|
+
};
|
|
34183
|
+
var createMacbook = () => {
|
|
34184
|
+
const spec = REFERENCE_OBJECT_SPECS["14in-macbook"];
|
|
34185
|
+
const group = new THREE21.Group();
|
|
34186
|
+
const aluminumMaterial = new THREE21.MeshStandardMaterial({
|
|
34187
|
+
color: 12896201,
|
|
34188
|
+
roughness: 0.3,
|
|
34189
|
+
metalness: 0.38
|
|
34190
|
+
});
|
|
34191
|
+
const body = new THREE21.Mesh(
|
|
34192
|
+
createRoundedPrismGeometry(spec.width, spec.height, 13.5, 9),
|
|
34193
|
+
aluminumMaterial
|
|
34194
|
+
);
|
|
34195
|
+
body.position.z = -1;
|
|
34196
|
+
body.name = "macbook-body";
|
|
34197
|
+
group.add(body);
|
|
34198
|
+
const lidDepth = 2;
|
|
34199
|
+
const lidCenterZ = 6.75;
|
|
34200
|
+
const lidTopZ = lidCenterZ + lidDepth / 2;
|
|
34201
|
+
const indentRadius = 12;
|
|
34202
|
+
const lid = new THREE21.Mesh(
|
|
34203
|
+
createMacbookLidGeometry(
|
|
34204
|
+
spec.width - 1.8,
|
|
34205
|
+
spec.height - 1.8,
|
|
34206
|
+
lidDepth,
|
|
34207
|
+
8.2,
|
|
34208
|
+
indentRadius
|
|
34209
|
+
),
|
|
34210
|
+
aluminumMaterial.clone()
|
|
34211
|
+
);
|
|
34212
|
+
lid.position.z = lidCenterZ;
|
|
34213
|
+
lid.name = "macbook-lid";
|
|
34214
|
+
group.add(lid);
|
|
34215
|
+
const hinge = new THREE21.Mesh(
|
|
34216
|
+
new THREE21.BoxGeometry(spec.width - 42, 3.2, 1.2),
|
|
34217
|
+
new THREE21.MeshStandardMaterial({
|
|
34218
|
+
color: 3158838,
|
|
34219
|
+
roughness: 0.55,
|
|
34220
|
+
metalness: 0.45
|
|
34221
|
+
})
|
|
34222
|
+
);
|
|
34223
|
+
hinge.position.set(0, spec.height / 2 - 2.4, 6.15);
|
|
34224
|
+
hinge.name = "macbook-hinge";
|
|
34225
|
+
group.add(hinge);
|
|
34226
|
+
group.add(createMacbookIndent(lidTopZ, indentRadius));
|
|
34227
|
+
const frontNotch = new THREE21.Mesh(
|
|
34228
|
+
new THREE21.BoxGeometry(54, 1.2, 0.8),
|
|
34229
|
+
new THREE21.MeshStandardMaterial({
|
|
34230
|
+
color: 6712174,
|
|
34231
|
+
roughness: 0.45,
|
|
34232
|
+
metalness: 0.5
|
|
34233
|
+
})
|
|
34234
|
+
);
|
|
34235
|
+
frontNotch.position.set(0, -spec.height / 2 + 0.5, 2.5);
|
|
34236
|
+
frontNotch.name = "macbook-front-notch";
|
|
34237
|
+
group.add(frontNotch);
|
|
34238
|
+
return group;
|
|
34239
|
+
};
|
|
34240
|
+
var createReferenceObject = (type) => {
|
|
34241
|
+
const group = type === "banana" ? createBanana() : type === "credit-card" ? createCreditCard() : createMacbook();
|
|
34242
|
+
group.name = `reference-object-${type}`;
|
|
34243
|
+
group.userData.isReferenceObject = true;
|
|
34244
|
+
group.userData.referenceObjectType = type;
|
|
34245
|
+
configureObjectShadows(group);
|
|
34246
|
+
return group;
|
|
34247
|
+
};
|
|
34248
|
+
var disposeReferenceObject = (object) => {
|
|
34249
|
+
const geometries = /* @__PURE__ */ new Set();
|
|
34250
|
+
const materials = /* @__PURE__ */ new Set();
|
|
34251
|
+
object.traverse((child) => {
|
|
34252
|
+
if (!(child instanceof THREE21.Mesh)) return;
|
|
34253
|
+
geometries.add(child.geometry);
|
|
34254
|
+
const childMaterials = Array.isArray(child.material) ? child.material : [child.material];
|
|
34255
|
+
for (const material of childMaterials) materials.add(material);
|
|
34256
|
+
});
|
|
34257
|
+
for (const geometry of geometries) geometry.dispose();
|
|
34258
|
+
for (const material of materials) material.dispose();
|
|
34259
|
+
};
|
|
34260
|
+
|
|
34261
|
+
// src/reference-objects/fit-camera-to-bounds.ts
|
|
34262
|
+
import * as THREE22 from "three";
|
|
34263
|
+
var fitCameraToBounds = (camera, controls, bounds, padding = 1.18) => {
|
|
34264
|
+
const width10 = Math.max(bounds.maxX - bounds.minX, 0);
|
|
34265
|
+
const height10 = Math.max(bounds.maxY - bounds.minY, 0);
|
|
34266
|
+
const depth = Math.max(bounds.maxZ - bounds.minZ, 0);
|
|
34267
|
+
const center = new THREE22.Vector3(
|
|
34268
|
+
(bounds.minX + bounds.maxX) / 2,
|
|
34269
|
+
(bounds.minY + bounds.maxY) / 2,
|
|
34270
|
+
(bounds.minZ + bounds.maxZ) / 2
|
|
34271
|
+
);
|
|
34272
|
+
const radius = Math.max(Math.hypot(width10, height10, depth) / 2, 1);
|
|
34273
|
+
const previousTarget = controls?.target ?? new THREE22.Vector3();
|
|
34274
|
+
const direction = new THREE22.Vector3(0, -0.75, 0.9).normalize();
|
|
34275
|
+
let distance5 = Math.max(camera.position.distanceTo(previousTarget), 5);
|
|
34276
|
+
if (camera instanceof THREE22.PerspectiveCamera) {
|
|
34277
|
+
const verticalFov = THREE22.MathUtils.degToRad(camera.fov);
|
|
34278
|
+
const horizontalFov = 2 * Math.atan(Math.tan(verticalFov / 2) * camera.aspect);
|
|
34279
|
+
const limitingFov = Math.min(verticalFov, horizontalFov);
|
|
34280
|
+
distance5 = radius * padding / Math.sin(limitingFov / 2);
|
|
34281
|
+
camera.far = Math.max(camera.far, distance5 + radius * padding * 3);
|
|
34282
|
+
camera.updateProjectionMatrix();
|
|
34283
|
+
} else if (camera instanceof THREE22.OrthographicCamera) {
|
|
34284
|
+
const halfViewWidth = Math.abs(camera.right - camera.left) / 2;
|
|
34285
|
+
const halfViewHeight = Math.abs(camera.top - camera.bottom) / 2;
|
|
34286
|
+
camera.zoom = Math.min(
|
|
34287
|
+
halfViewWidth / (radius * padding),
|
|
34288
|
+
halfViewHeight / (radius * padding)
|
|
34289
|
+
);
|
|
34290
|
+
distance5 = Math.max(distance5, radius * padding * 2);
|
|
34291
|
+
camera.updateProjectionMatrix();
|
|
34292
|
+
}
|
|
34293
|
+
camera.position.copy(center).addScaledVector(direction, distance5);
|
|
34294
|
+
camera.lookAt(center);
|
|
34295
|
+
camera.updateMatrixWorld();
|
|
34296
|
+
if (controls) {
|
|
34297
|
+
controls.target.copy(center);
|
|
34298
|
+
controls.update();
|
|
34299
|
+
}
|
|
34300
|
+
return { center, radius, distance: distance5 };
|
|
34301
|
+
};
|
|
34302
|
+
|
|
34303
|
+
// src/three-components/reference-object.tsx
|
|
34304
|
+
var ReferenceObject = ({
|
|
34305
|
+
type,
|
|
34306
|
+
boardDimensions,
|
|
34307
|
+
boardCenter
|
|
34308
|
+
}) => {
|
|
34309
|
+
const { scene } = useThree();
|
|
34310
|
+
const object = useMemo15(() => {
|
|
34311
|
+
const nextObject = createReferenceObject(type);
|
|
34312
|
+
const position = getReferenceObjectPosition(
|
|
34313
|
+
type,
|
|
34314
|
+
boardDimensions,
|
|
34315
|
+
boardCenter
|
|
34316
|
+
);
|
|
34317
|
+
nextObject.position.set(position.x, position.y, position.z);
|
|
34318
|
+
return nextObject;
|
|
34319
|
+
}, [type, boardDimensions, boardCenter]);
|
|
34320
|
+
useEffect19(() => {
|
|
34321
|
+
scene.add(object);
|
|
34322
|
+
return () => {
|
|
34323
|
+
scene.remove(object);
|
|
34324
|
+
disposeReferenceObject(object);
|
|
34325
|
+
};
|
|
34326
|
+
}, [scene, object]);
|
|
34327
|
+
return null;
|
|
34328
|
+
};
|
|
34329
|
+
var FitCameraToComparison = ({ bounds }) => {
|
|
34330
|
+
const { camera } = useThree();
|
|
34331
|
+
const { controlsRef } = useCameraController();
|
|
34332
|
+
useEffect19(() => {
|
|
34333
|
+
fitCameraToBounds(camera, controlsRef.current, bounds);
|
|
34334
|
+
}, [bounds, camera, controlsRef]);
|
|
34335
|
+
return null;
|
|
34336
|
+
};
|
|
34337
|
+
|
|
33844
34338
|
// src/CadViewerContainer.tsx
|
|
33845
34339
|
import { jsx as jsx15, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
33846
34340
|
var RotationTracker = () => {
|
|
@@ -33861,6 +34355,7 @@ var CadViewerContainer = forwardRef2(
|
|
|
33861
34355
|
clickToInteractEnabled = false,
|
|
33862
34356
|
boardDimensions,
|
|
33863
34357
|
boardCenter,
|
|
34358
|
+
referenceObject,
|
|
33864
34359
|
onUserInteraction,
|
|
33865
34360
|
onCameraControllerReady
|
|
33866
34361
|
}, ref) => {
|
|
@@ -33873,28 +34368,39 @@ var CadViewerContainer = forwardRef2(
|
|
|
33873
34368
|
handleCameraCreated,
|
|
33874
34369
|
handleControlsChange: handleSessionControlsChange
|
|
33875
34370
|
} = useCameraSession();
|
|
33876
|
-
|
|
34371
|
+
useEffect20(() => {
|
|
33877
34372
|
if (onCameraControllerReady) {
|
|
33878
34373
|
onCameraControllerReady(controller);
|
|
33879
34374
|
}
|
|
33880
34375
|
}, [controller, onCameraControllerReady]);
|
|
33881
|
-
const
|
|
34376
|
+
const comparisonBounds = useMemo16(() => {
|
|
34377
|
+
if (!referenceObject) return void 0;
|
|
34378
|
+
return getComparisonBounds(referenceObject, boardDimensions, boardCenter);
|
|
34379
|
+
}, [referenceObject, boardDimensions, boardCenter]);
|
|
34380
|
+
const gridSectionSize = useMemo16(() => {
|
|
33882
34381
|
if (!boardDimensions) return 10;
|
|
33883
34382
|
const width10 = boardDimensions.width ?? 0;
|
|
33884
34383
|
const height10 = boardDimensions.height ?? 0;
|
|
33885
34384
|
return Math.max(Math.max(width10, height10) * 1.5, 10);
|
|
33886
34385
|
}, [boardDimensions]);
|
|
33887
|
-
const orbitTarget =
|
|
34386
|
+
const orbitTarget = useMemo16(() => {
|
|
34387
|
+
if (comparisonBounds) {
|
|
34388
|
+
return [
|
|
34389
|
+
(comparisonBounds.minX + comparisonBounds.maxX) / 2,
|
|
34390
|
+
(comparisonBounds.minY + comparisonBounds.maxY) / 2,
|
|
34391
|
+
(comparisonBounds.minZ + comparisonBounds.maxZ) / 2
|
|
34392
|
+
];
|
|
34393
|
+
}
|
|
33888
34394
|
if (!boardCenter) return void 0;
|
|
33889
34395
|
return [boardCenter.x, boardCenter.y, 0];
|
|
33890
|
-
}, [boardCenter]);
|
|
34396
|
+
}, [boardCenter, comparisonBounds]);
|
|
33891
34397
|
return /* @__PURE__ */ jsxs3("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
33892
34398
|
/* @__PURE__ */ jsx15(OrientationCubeCanvas, {}),
|
|
33893
34399
|
/* @__PURE__ */ jsxs3(
|
|
33894
34400
|
Canvas,
|
|
33895
34401
|
{
|
|
33896
34402
|
ref,
|
|
33897
|
-
scene: { up: new
|
|
34403
|
+
scene: { up: new THREE23.Vector3(0, 0, 1) },
|
|
33898
34404
|
camera: { up: [0, 0, 1], position: initialCameraPosition },
|
|
33899
34405
|
onCreated: ({ camera }) => {
|
|
33900
34406
|
mainCameraRef.current = camera;
|
|
@@ -33930,6 +34436,15 @@ var CadViewerContainer = forwardRef2(
|
|
|
33930
34436
|
shadowsEnabled: lightingEnabled
|
|
33931
34437
|
}
|
|
33932
34438
|
),
|
|
34439
|
+
referenceObject && /* @__PURE__ */ jsx15(
|
|
34440
|
+
ReferenceObject,
|
|
34441
|
+
{
|
|
34442
|
+
type: referenceObject,
|
|
34443
|
+
boardDimensions,
|
|
34444
|
+
boardCenter
|
|
34445
|
+
}
|
|
34446
|
+
),
|
|
34447
|
+
comparisonBounds && /* @__PURE__ */ jsx15(FitCameraToComparison, { bounds: comparisonBounds }),
|
|
33933
34448
|
gridEnabled && /* @__PURE__ */ jsx15(
|
|
33934
34449
|
Grid,
|
|
33935
34450
|
{
|
|
@@ -34003,9 +34518,9 @@ var CadViewerContainer = forwardRef2(
|
|
|
34003
34518
|
|
|
34004
34519
|
// src/hooks/use-convert-children-to-soup.ts
|
|
34005
34520
|
import { Circuit } from "@tscircuit/core";
|
|
34006
|
-
import { useMemo as
|
|
34521
|
+
import { useMemo as useMemo17 } from "react";
|
|
34007
34522
|
var useConvertChildrenToCircuitJson = (children) => {
|
|
34008
|
-
return
|
|
34523
|
+
return useMemo17(() => {
|
|
34009
34524
|
if (!children) return [];
|
|
34010
34525
|
const circuit = new Circuit();
|
|
34011
34526
|
circuit.add(children);
|
|
@@ -34015,12 +34530,12 @@ var useConvertChildrenToCircuitJson = (children) => {
|
|
|
34015
34530
|
};
|
|
34016
34531
|
|
|
34017
34532
|
// src/hooks/use-stls-from-geom.ts
|
|
34018
|
-
import { useState as useState12, useEffect as
|
|
34533
|
+
import { useState as useState12, useEffect as useEffect21 } from "react";
|
|
34019
34534
|
import stlSerializer from "@jscad/stl-serializer";
|
|
34020
34535
|
var useStlsFromGeom = (geom) => {
|
|
34021
34536
|
const [stls, setStls] = useState12([]);
|
|
34022
34537
|
const [loading, setLoading] = useState12(true);
|
|
34023
|
-
|
|
34538
|
+
useEffect21(() => {
|
|
34024
34539
|
if (!geom) return;
|
|
34025
34540
|
const generateStls = async () => {
|
|
34026
34541
|
setLoading(true);
|
|
@@ -34049,7 +34564,7 @@ var useStlsFromGeom = (geom) => {
|
|
|
34049
34564
|
};
|
|
34050
34565
|
|
|
34051
34566
|
// src/hooks/useBoardGeomBuilder.ts
|
|
34052
|
-
import { useState as useState13, useEffect as
|
|
34567
|
+
import { useState as useState13, useEffect as useEffect22, useRef as useRef8 } from "react";
|
|
34053
34568
|
|
|
34054
34569
|
// src/soup-to-3d/index.ts
|
|
34055
34570
|
var import_primitives2 = __toESM(require_primitives(), 1);
|
|
@@ -35363,7 +35878,7 @@ var BoardGeomBuilder = class {
|
|
|
35363
35878
|
var useBoardGeomBuilder = (circuitJson) => {
|
|
35364
35879
|
const [boardGeom, setBoardGeom] = useState13(null);
|
|
35365
35880
|
const isProcessingRef = useRef8(false);
|
|
35366
|
-
|
|
35881
|
+
useEffect22(() => {
|
|
35367
35882
|
let isCancelled = false;
|
|
35368
35883
|
if (!circuitJson) {
|
|
35369
35884
|
setBoardGeom(null);
|
|
@@ -35409,10 +35924,10 @@ var useBoardGeomBuilder = (circuitJson) => {
|
|
|
35409
35924
|
};
|
|
35410
35925
|
|
|
35411
35926
|
// src/three-components/Error3d.tsx
|
|
35412
|
-
import { useState as useState14, useCallback as useCallback8, useEffect as
|
|
35927
|
+
import { useState as useState14, useCallback as useCallback8, useEffect as useEffect24, useMemo as useMemo19 } from "react";
|
|
35413
35928
|
|
|
35414
35929
|
// src/react-three/Text.tsx
|
|
35415
|
-
import { useEffect as
|
|
35930
|
+
import { useEffect as useEffect23, useMemo as useMemo18 } from "react";
|
|
35416
35931
|
import { Text as TroikaText2 } from "troika-three-text";
|
|
35417
35932
|
var Text = ({
|
|
35418
35933
|
children,
|
|
@@ -35427,7 +35942,7 @@ var Text = ({
|
|
|
35427
35942
|
depthOffset
|
|
35428
35943
|
}) => {
|
|
35429
35944
|
const { rootObject } = useThree();
|
|
35430
|
-
const mesh =
|
|
35945
|
+
const mesh = useMemo18(() => {
|
|
35431
35946
|
const textMesh = new TroikaText2();
|
|
35432
35947
|
textMesh.text = children;
|
|
35433
35948
|
if (position) textMesh.position.fromArray(position);
|
|
@@ -35452,7 +35967,7 @@ var Text = ({
|
|
|
35452
35967
|
anchorY,
|
|
35453
35968
|
depthOffset
|
|
35454
35969
|
]);
|
|
35455
|
-
|
|
35970
|
+
useEffect23(() => {
|
|
35456
35971
|
const parentObject = parent || rootObject;
|
|
35457
35972
|
if (!parentObject || !mesh) return;
|
|
35458
35973
|
parentObject.add(mesh);
|
|
@@ -35465,7 +35980,7 @@ var Text = ({
|
|
|
35465
35980
|
};
|
|
35466
35981
|
|
|
35467
35982
|
// src/three-components/Error3d.tsx
|
|
35468
|
-
import * as
|
|
35983
|
+
import * as THREE24 from "three";
|
|
35469
35984
|
import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
35470
35985
|
var Error3d = ({
|
|
35471
35986
|
error,
|
|
@@ -35487,7 +36002,7 @@ var Error3d = ({
|
|
|
35487
36002
|
setIsHovered(false);
|
|
35488
36003
|
setHoverPosition(null);
|
|
35489
36004
|
}, []);
|
|
35490
|
-
const position =
|
|
36005
|
+
const position = useMemo19(() => {
|
|
35491
36006
|
if (cad_component?.position) {
|
|
35492
36007
|
const p = [
|
|
35493
36008
|
cad_component.position.x,
|
|
@@ -35498,12 +36013,12 @@ var Error3d = ({
|
|
|
35498
36013
|
}
|
|
35499
36014
|
return [0, 0, 0];
|
|
35500
36015
|
}, [cad_component]);
|
|
35501
|
-
const group =
|
|
35502
|
-
const g = new
|
|
36016
|
+
const group = useMemo19(() => {
|
|
36017
|
+
const g = new THREE24.Group();
|
|
35503
36018
|
g.position.fromArray(position);
|
|
35504
36019
|
return g;
|
|
35505
36020
|
}, [position]);
|
|
35506
|
-
|
|
36021
|
+
useEffect24(() => {
|
|
35507
36022
|
if (!rootObject) return;
|
|
35508
36023
|
rootObject.add(group);
|
|
35509
36024
|
return () => {
|
|
@@ -35558,10 +36073,10 @@ var Error3d = ({
|
|
|
35558
36073
|
] });
|
|
35559
36074
|
};
|
|
35560
36075
|
var ErrorBox = ({ parent }) => {
|
|
35561
|
-
const mesh =
|
|
35562
|
-
const m = new
|
|
35563
|
-
new
|
|
35564
|
-
new
|
|
36076
|
+
const mesh = useMemo19(() => {
|
|
36077
|
+
const m = new THREE24.Mesh(
|
|
36078
|
+
new THREE24.BoxGeometry(0.5, 0.5, 0.5),
|
|
36079
|
+
new THREE24.MeshStandardMaterial({
|
|
35565
36080
|
depthTest: false,
|
|
35566
36081
|
transparent: true,
|
|
35567
36082
|
color: "red",
|
|
@@ -35572,7 +36087,7 @@ var ErrorBox = ({ parent }) => {
|
|
|
35572
36087
|
m.rotation.fromArray([Math.PI / 4, Math.PI / 4, 0]);
|
|
35573
36088
|
return m;
|
|
35574
36089
|
}, []);
|
|
35575
|
-
|
|
36090
|
+
useEffect24(() => {
|
|
35576
36091
|
parent.add(mesh);
|
|
35577
36092
|
return () => {
|
|
35578
36093
|
parent.remove(mesh);
|
|
@@ -35581,114 +36096,12 @@ var ErrorBox = ({ parent }) => {
|
|
|
35581
36096
|
return null;
|
|
35582
36097
|
};
|
|
35583
36098
|
|
|
35584
|
-
// src/three-components/STLModel.tsx
|
|
35585
|
-
import { useState as useState15, useEffect as useEffect24, useMemo as useMemo19 } from "react";
|
|
35586
|
-
import * as THREE23 from "three";
|
|
35587
|
-
import { STLLoader } from "three-stdlib";
|
|
35588
|
-
function STLModel({
|
|
35589
|
-
stlUrl,
|
|
35590
|
-
stlData,
|
|
35591
|
-
mtlUrl,
|
|
35592
|
-
color,
|
|
35593
|
-
opacity = 1,
|
|
35594
|
-
layerType
|
|
35595
|
-
}) {
|
|
35596
|
-
const { rootObject } = useThree();
|
|
35597
|
-
const [geom, setGeom] = useState15(null);
|
|
35598
|
-
useEffect24(() => {
|
|
35599
|
-
const loader = new STLLoader();
|
|
35600
|
-
if (stlData) {
|
|
35601
|
-
try {
|
|
35602
|
-
const geometry = loader.parse(stlData);
|
|
35603
|
-
setGeom(geometry);
|
|
35604
|
-
} catch (e) {
|
|
35605
|
-
console.error("Failed to parse STL data", e);
|
|
35606
|
-
setGeom(null);
|
|
35607
|
-
}
|
|
35608
|
-
return;
|
|
35609
|
-
}
|
|
35610
|
-
if (stlUrl) {
|
|
35611
|
-
loader.load(stlUrl, (geometry) => {
|
|
35612
|
-
setGeom(geometry);
|
|
35613
|
-
});
|
|
35614
|
-
}
|
|
35615
|
-
}, [stlUrl, stlData]);
|
|
35616
|
-
const mesh = useMemo19(() => {
|
|
35617
|
-
if (!geom) return null;
|
|
35618
|
-
const isBoardLayer = layerType === "board";
|
|
35619
|
-
const material = new THREE23.MeshStandardMaterial({
|
|
35620
|
-
color: Array.isArray(color) ? new THREE23.Color(color[0], color[1], color[2]) : color,
|
|
35621
|
-
transparent: opacity !== 1,
|
|
35622
|
-
opacity,
|
|
35623
|
-
polygonOffset: isBoardLayer,
|
|
35624
|
-
polygonOffsetFactor: isBoardLayer ? 6 : 0,
|
|
35625
|
-
polygonOffsetUnits: isBoardLayer ? 6 : 0
|
|
35626
|
-
});
|
|
35627
|
-
const createdMesh = new THREE23.Mesh(geom, material);
|
|
35628
|
-
createdMesh.renderOrder = isBoardLayer ? -1 : 1;
|
|
35629
|
-
configureObjectShadows(createdMesh, {
|
|
35630
|
-
castShadow: !isBoardLayer && opacity === 1,
|
|
35631
|
-
receiveShadow: true
|
|
35632
|
-
});
|
|
35633
|
-
return createdMesh;
|
|
35634
|
-
}, [geom, color, opacity, layerType]);
|
|
35635
|
-
useEffect24(() => {
|
|
35636
|
-
if (!rootObject || !mesh) return;
|
|
35637
|
-
rootObject.add(mesh);
|
|
35638
|
-
return () => {
|
|
35639
|
-
rootObject.remove(mesh);
|
|
35640
|
-
mesh.geometry.dispose();
|
|
35641
|
-
if (Array.isArray(mesh.material)) {
|
|
35642
|
-
mesh.material.forEach((m) => m.dispose());
|
|
35643
|
-
} else {
|
|
35644
|
-
mesh.material.dispose();
|
|
35645
|
-
}
|
|
35646
|
-
};
|
|
35647
|
-
}, [rootObject, mesh]);
|
|
35648
|
-
return null;
|
|
35649
|
-
}
|
|
35650
|
-
|
|
35651
|
-
// src/three-components/VisibleSTLModel.tsx
|
|
35652
|
-
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
35653
|
-
function VisibleSTLModel({
|
|
35654
|
-
stlData,
|
|
35655
|
-
color,
|
|
35656
|
-
opacity = 1,
|
|
35657
|
-
layerType
|
|
35658
|
-
}) {
|
|
35659
|
-
const { visibility } = useLayerVisibility();
|
|
35660
|
-
let shouldShow = true;
|
|
35661
|
-
if (layerType === "board") {
|
|
35662
|
-
shouldShow = visibility.boardBody;
|
|
35663
|
-
} else if (layerType === "top-copper") {
|
|
35664
|
-
shouldShow = visibility.topCopper;
|
|
35665
|
-
} else if (layerType === "bottom-copper") {
|
|
35666
|
-
shouldShow = visibility.bottomCopper;
|
|
35667
|
-
} else if (layerType === "top-silkscreen") {
|
|
35668
|
-
shouldShow = visibility.topSilkscreen;
|
|
35669
|
-
} else if (layerType === "bottom-silkscreen") {
|
|
35670
|
-
shouldShow = visibility.bottomSilkscreen;
|
|
35671
|
-
}
|
|
35672
|
-
if (!shouldShow) {
|
|
35673
|
-
return null;
|
|
35674
|
-
}
|
|
35675
|
-
return /* @__PURE__ */ jsx17(
|
|
35676
|
-
STLModel,
|
|
35677
|
-
{
|
|
35678
|
-
stlData,
|
|
35679
|
-
color,
|
|
35680
|
-
opacity,
|
|
35681
|
-
layerType
|
|
35682
|
-
}
|
|
35683
|
-
);
|
|
35684
|
-
}
|
|
35685
|
-
|
|
35686
36099
|
// src/three-components/JscadBoardTextures.tsx
|
|
35687
36100
|
import { su as su8 } from "@tscircuit/circuit-json-util";
|
|
35688
36101
|
import { useEffect as useEffect25, useMemo as useMemo20 } from "react";
|
|
35689
36102
|
|
|
35690
36103
|
// src/textures/create-combined-board-textures.ts
|
|
35691
|
-
import * as
|
|
36104
|
+
import * as THREE36 from "three";
|
|
35692
36105
|
|
|
35693
36106
|
// node_modules/@tscircuit/math-utils/dist/chunk-5N7UJNVK.js
|
|
35694
36107
|
var getBoundsFromPoints = (points) => {
|
|
@@ -35743,7 +36156,7 @@ function calculateOutlineBounds(boardData) {
|
|
|
35743
36156
|
// src/utils/pad-texture.ts
|
|
35744
36157
|
import { su as su5 } from "@tscircuit/circuit-json-util";
|
|
35745
36158
|
import { CircuitToCanvasDrawer } from "circuit-to-canvas";
|
|
35746
|
-
import * as
|
|
36159
|
+
import * as THREE25 from "three";
|
|
35747
36160
|
function createPadTextureForLayer({
|
|
35748
36161
|
layer,
|
|
35749
36162
|
circuitJson,
|
|
@@ -35821,10 +36234,10 @@ function createPadTextureForLayer({
|
|
|
35821
36234
|
drawSoldermaskTop: false,
|
|
35822
36235
|
drawSoldermaskBottom: false
|
|
35823
36236
|
});
|
|
35824
|
-
const texture = new
|
|
36237
|
+
const texture = new THREE25.CanvasTexture(canvas);
|
|
35825
36238
|
texture.generateMipmaps = true;
|
|
35826
|
-
texture.minFilter =
|
|
35827
|
-
texture.magFilter =
|
|
36239
|
+
texture.minFilter = THREE25.LinearMipmapLinearFilter;
|
|
36240
|
+
texture.magFilter = THREE25.LinearFilter;
|
|
35828
36241
|
texture.anisotropy = 16;
|
|
35829
36242
|
texture.needsUpdate = true;
|
|
35830
36243
|
return texture;
|
|
@@ -35832,7 +36245,7 @@ function createPadTextureForLayer({
|
|
|
35832
36245
|
|
|
35833
36246
|
// src/utils/panel-outline-texture.ts
|
|
35834
36247
|
import { su as su6 } from "@tscircuit/circuit-json-util";
|
|
35835
|
-
import * as
|
|
36248
|
+
import * as THREE26 from "three";
|
|
35836
36249
|
var resolvePanelIdForTexture = (circuitJson) => {
|
|
35837
36250
|
const panels = circuitJson.filter(
|
|
35838
36251
|
(e) => e.type === "pcb_panel"
|
|
@@ -35900,17 +36313,17 @@ function createPanelOutlineTextureForLayer({
|
|
|
35900
36313
|
);
|
|
35901
36314
|
}
|
|
35902
36315
|
});
|
|
35903
|
-
const texture = new
|
|
36316
|
+
const texture = new THREE26.CanvasTexture(canvas);
|
|
35904
36317
|
texture.generateMipmaps = true;
|
|
35905
|
-
texture.minFilter =
|
|
35906
|
-
texture.magFilter =
|
|
36318
|
+
texture.minFilter = THREE26.LinearMipmapLinearFilter;
|
|
36319
|
+
texture.magFilter = THREE26.LinearFilter;
|
|
35907
36320
|
texture.anisotropy = 16;
|
|
35908
36321
|
texture.needsUpdate = true;
|
|
35909
36322
|
return texture;
|
|
35910
36323
|
}
|
|
35911
36324
|
|
|
35912
36325
|
// src/utils/trace-texture.ts
|
|
35913
|
-
import * as
|
|
36326
|
+
import * as THREE27 from "three";
|
|
35914
36327
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer2 } from "circuit-to-canvas";
|
|
35915
36328
|
import { getElementRenderLayers, su as su7 } from "@tscircuit/circuit-json-util";
|
|
35916
36329
|
|
|
@@ -36028,10 +36441,10 @@ function createTraceTextureForLayer({
|
|
|
36028
36441
|
drawSoldermaskTop: false,
|
|
36029
36442
|
drawSoldermaskBottom: false
|
|
36030
36443
|
});
|
|
36031
|
-
const texture = new
|
|
36444
|
+
const texture = new THREE27.CanvasTexture(canvas);
|
|
36032
36445
|
texture.generateMipmaps = true;
|
|
36033
|
-
texture.minFilter =
|
|
36034
|
-
texture.magFilter =
|
|
36446
|
+
texture.minFilter = THREE27.LinearMipmapLinearFilter;
|
|
36447
|
+
texture.magFilter = THREE27.LinearFilter;
|
|
36035
36448
|
texture.anisotropy = 16;
|
|
36036
36449
|
texture.needsUpdate = true;
|
|
36037
36450
|
return texture;
|
|
@@ -36039,7 +36452,7 @@ function createTraceTextureForLayer({
|
|
|
36039
36452
|
|
|
36040
36453
|
// src/textures/create-copper-pour-texture-for-layer.ts
|
|
36041
36454
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer3 } from "circuit-to-canvas";
|
|
36042
|
-
import * as
|
|
36455
|
+
import * as THREE28 from "three";
|
|
36043
36456
|
var toRgb = (colorArr) => {
|
|
36044
36457
|
const [r = 0, g = 0, b = 0] = colorArr;
|
|
36045
36458
|
return `rgb(${Math.round(r * 255)}, ${Math.round(g * 255)}, ${Math.round(
|
|
@@ -36161,17 +36574,17 @@ function createCopperPourTextureForLayer({
|
|
|
36161
36574
|
if (!onlyCoveredBySoldermask) {
|
|
36162
36575
|
setColorAndDraw(uncoveredPours, uncoveredColor);
|
|
36163
36576
|
}
|
|
36164
|
-
const texture = new
|
|
36577
|
+
const texture = new THREE28.CanvasTexture(canvas);
|
|
36165
36578
|
texture.generateMipmaps = true;
|
|
36166
|
-
texture.minFilter =
|
|
36167
|
-
texture.magFilter =
|
|
36579
|
+
texture.minFilter = THREE28.LinearMipmapLinearFilter;
|
|
36580
|
+
texture.magFilter = THREE28.LinearFilter;
|
|
36168
36581
|
texture.anisotropy = 16;
|
|
36169
36582
|
texture.needsUpdate = true;
|
|
36170
36583
|
return texture;
|
|
36171
36584
|
}
|
|
36172
36585
|
|
|
36173
36586
|
// src/textures/create-copper-text-texture-for-layer.ts
|
|
36174
|
-
import * as
|
|
36587
|
+
import * as THREE29 from "three";
|
|
36175
36588
|
|
|
36176
36589
|
// src/textures/copper-text/copper-text-drawing.ts
|
|
36177
36590
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer4 } from "circuit-to-canvas";
|
|
@@ -36282,17 +36695,17 @@ function createCopperTextTextureForLayer({
|
|
|
36282
36695
|
elements,
|
|
36283
36696
|
copperColor
|
|
36284
36697
|
});
|
|
36285
|
-
const texture = new
|
|
36698
|
+
const texture = new THREE29.CanvasTexture(canvas);
|
|
36286
36699
|
texture.generateMipmaps = true;
|
|
36287
|
-
texture.minFilter =
|
|
36288
|
-
texture.magFilter =
|
|
36700
|
+
texture.minFilter = THREE29.LinearMipmapLinearFilter;
|
|
36701
|
+
texture.magFilter = THREE29.LinearFilter;
|
|
36289
36702
|
texture.anisotropy = 16;
|
|
36290
36703
|
texture.needsUpdate = true;
|
|
36291
36704
|
return texture;
|
|
36292
36705
|
}
|
|
36293
36706
|
|
|
36294
36707
|
// src/textures/create-fabrication-note-texture-for-layer.ts
|
|
36295
|
-
import * as
|
|
36708
|
+
import * as THREE30 from "three";
|
|
36296
36709
|
|
|
36297
36710
|
// src/textures/fabrication-note/fabrication-note-drawing.ts
|
|
36298
36711
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer5 } from "circuit-to-canvas";
|
|
@@ -36520,17 +36933,17 @@ function createFabricationNoteTextureForLayer({
|
|
|
36520
36933
|
bounds,
|
|
36521
36934
|
elements
|
|
36522
36935
|
});
|
|
36523
|
-
const texture = new
|
|
36936
|
+
const texture = new THREE30.CanvasTexture(canvas);
|
|
36524
36937
|
texture.generateMipmaps = true;
|
|
36525
|
-
texture.minFilter =
|
|
36526
|
-
texture.magFilter =
|
|
36938
|
+
texture.minFilter = THREE30.LinearMipmapLinearFilter;
|
|
36939
|
+
texture.magFilter = THREE30.LinearFilter;
|
|
36527
36940
|
texture.anisotropy = 16;
|
|
36528
36941
|
texture.needsUpdate = true;
|
|
36529
36942
|
return texture;
|
|
36530
36943
|
}
|
|
36531
36944
|
|
|
36532
36945
|
// src/textures/create-keepout-texture-for-layer.ts
|
|
36533
|
-
import * as
|
|
36946
|
+
import * as THREE31 from "three";
|
|
36534
36947
|
|
|
36535
36948
|
// src/textures/keepout/keepout-drawing.ts
|
|
36536
36949
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer6 } from "circuit-to-canvas";
|
|
@@ -36605,17 +37018,17 @@ function createKeepoutTextureForLayer({
|
|
|
36605
37018
|
elements,
|
|
36606
37019
|
keepoutColor
|
|
36607
37020
|
});
|
|
36608
|
-
const texture = new
|
|
37021
|
+
const texture = new THREE31.CanvasTexture(canvas);
|
|
36609
37022
|
texture.generateMipmaps = true;
|
|
36610
|
-
texture.minFilter =
|
|
36611
|
-
texture.magFilter =
|
|
37023
|
+
texture.minFilter = THREE31.LinearMipmapLinearFilter;
|
|
37024
|
+
texture.magFilter = THREE31.LinearFilter;
|
|
36612
37025
|
texture.anisotropy = 16;
|
|
36613
37026
|
texture.needsUpdate = true;
|
|
36614
37027
|
return texture;
|
|
36615
37028
|
}
|
|
36616
37029
|
|
|
36617
37030
|
// src/textures/create-pcb-note-texture-for-layer.ts
|
|
36618
|
-
import * as
|
|
37031
|
+
import * as THREE32 from "three";
|
|
36619
37032
|
|
|
36620
37033
|
// src/textures/pcb-note/pcb-note-drawing.ts
|
|
36621
37034
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer7 } from "circuit-to-canvas";
|
|
@@ -36766,17 +37179,17 @@ function createPcbNoteTextureForLayer({
|
|
|
36766
37179
|
bounds,
|
|
36767
37180
|
elements
|
|
36768
37181
|
});
|
|
36769
|
-
const texture = new
|
|
37182
|
+
const texture = new THREE32.CanvasTexture(canvas);
|
|
36770
37183
|
texture.generateMipmaps = true;
|
|
36771
|
-
texture.minFilter =
|
|
36772
|
-
texture.magFilter =
|
|
37184
|
+
texture.minFilter = THREE32.LinearMipmapLinearFilter;
|
|
37185
|
+
texture.magFilter = THREE32.LinearFilter;
|
|
36773
37186
|
texture.anisotropy = 16;
|
|
36774
37187
|
texture.needsUpdate = true;
|
|
36775
37188
|
return texture;
|
|
36776
37189
|
}
|
|
36777
37190
|
|
|
36778
37191
|
// src/textures/create-silkscreen-texture-for-layer.ts
|
|
36779
|
-
import * as
|
|
37192
|
+
import * as THREE33 from "three";
|
|
36780
37193
|
|
|
36781
37194
|
// src/textures/silkscreen/silkscreen-drawing.ts
|
|
36782
37195
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer8 } from "circuit-to-canvas";
|
|
@@ -36885,17 +37298,17 @@ function createSilkscreenTextureForLayer({
|
|
|
36885
37298
|
elements,
|
|
36886
37299
|
silkscreenColor
|
|
36887
37300
|
});
|
|
36888
|
-
const texture = new
|
|
37301
|
+
const texture = new THREE33.CanvasTexture(canvas);
|
|
36889
37302
|
texture.generateMipmaps = true;
|
|
36890
|
-
texture.minFilter =
|
|
36891
|
-
texture.magFilter =
|
|
37303
|
+
texture.minFilter = THREE33.LinearMipmapLinearFilter;
|
|
37304
|
+
texture.magFilter = THREE33.LinearFilter;
|
|
36892
37305
|
texture.anisotropy = 16;
|
|
36893
37306
|
texture.needsUpdate = true;
|
|
36894
37307
|
return texture;
|
|
36895
37308
|
}
|
|
36896
37309
|
|
|
36897
37310
|
// src/textures/create-soldermask-texture-for-layer.ts
|
|
36898
|
-
import * as
|
|
37311
|
+
import * as THREE34 from "three";
|
|
36899
37312
|
|
|
36900
37313
|
// src/textures/soldermask/soldermask-drawing.ts
|
|
36901
37314
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer9 } from "circuit-to-canvas";
|
|
@@ -37030,17 +37443,17 @@ function createSoldermaskTextureForLayer({
|
|
|
37030
37443
|
elements,
|
|
37031
37444
|
boardMaterial: boardData.material
|
|
37032
37445
|
});
|
|
37033
|
-
const texture = new
|
|
37446
|
+
const texture = new THREE34.CanvasTexture(canvas);
|
|
37034
37447
|
texture.generateMipmaps = true;
|
|
37035
|
-
texture.minFilter =
|
|
37036
|
-
texture.magFilter =
|
|
37448
|
+
texture.minFilter = THREE34.LinearMipmapLinearFilter;
|
|
37449
|
+
texture.magFilter = THREE34.LinearFilter;
|
|
37037
37450
|
texture.anisotropy = 16;
|
|
37038
37451
|
texture.needsUpdate = true;
|
|
37039
37452
|
return texture;
|
|
37040
37453
|
}
|
|
37041
37454
|
|
|
37042
37455
|
// src/textures/create-through-hole-texture-for-layer.ts
|
|
37043
|
-
import * as
|
|
37456
|
+
import * as THREE35 from "three";
|
|
37044
37457
|
|
|
37045
37458
|
// src/textures/through-hole/through-hole-drawing.ts
|
|
37046
37459
|
import { CircuitToCanvasDrawer as CircuitToCanvasDrawer10 } from "circuit-to-canvas";
|
|
@@ -37133,10 +37546,10 @@ function createThroughHoleTextureForLayer({
|
|
|
37133
37546
|
elements,
|
|
37134
37547
|
copperColor
|
|
37135
37548
|
});
|
|
37136
|
-
const texture = new
|
|
37549
|
+
const texture = new THREE35.CanvasTexture(canvas);
|
|
37137
37550
|
texture.generateMipmaps = true;
|
|
37138
|
-
texture.minFilter =
|
|
37139
|
-
texture.magFilter =
|
|
37551
|
+
texture.minFilter = THREE35.LinearMipmapLinearFilter;
|
|
37552
|
+
texture.magFilter = THREE35.LinearFilter;
|
|
37140
37553
|
texture.anisotropy = 16;
|
|
37141
37554
|
texture.needsUpdate = true;
|
|
37142
37555
|
return texture;
|
|
@@ -37224,10 +37637,10 @@ var createCombinedTexture = ({
|
|
|
37224
37637
|
applySoldermaskSurfaceFilter(ctx, canvasWidth, canvasHeight, {
|
|
37225
37638
|
includeReflection: layer === "top"
|
|
37226
37639
|
});
|
|
37227
|
-
const combinedTexture = new
|
|
37640
|
+
const combinedTexture = new THREE36.CanvasTexture(canvas);
|
|
37228
37641
|
combinedTexture.generateMipmaps = false;
|
|
37229
|
-
combinedTexture.minFilter =
|
|
37230
|
-
combinedTexture.magFilter =
|
|
37642
|
+
combinedTexture.minFilter = THREE36.LinearFilter;
|
|
37643
|
+
combinedTexture.magFilter = THREE36.LinearFilter;
|
|
37231
37644
|
combinedTexture.premultiplyAlpha = true;
|
|
37232
37645
|
combinedTexture.anisotropy = 16;
|
|
37233
37646
|
combinedTexture.needsUpdate = true;
|
|
@@ -37252,11 +37665,11 @@ var createMaskedCopperMask = ({
|
|
|
37252
37665
|
if (!texture?.image) continue;
|
|
37253
37666
|
ctx.drawImage(texture.image, 0, 0, width10, height10);
|
|
37254
37667
|
}
|
|
37255
|
-
const maskTexture = new
|
|
37256
|
-
maskTexture.colorSpace =
|
|
37668
|
+
const maskTexture = new THREE36.CanvasTexture(canvas);
|
|
37669
|
+
maskTexture.colorSpace = THREE36.NoColorSpace;
|
|
37257
37670
|
maskTexture.generateMipmaps = false;
|
|
37258
|
-
maskTexture.minFilter =
|
|
37259
|
-
maskTexture.magFilter =
|
|
37671
|
+
maskTexture.minFilter = THREE36.LinearFilter;
|
|
37672
|
+
maskTexture.magFilter = THREE36.LinearFilter;
|
|
37260
37673
|
maskTexture.premultiplyAlpha = false;
|
|
37261
37674
|
maskTexture.needsUpdate = true;
|
|
37262
37675
|
return maskTexture;
|
|
@@ -37394,7 +37807,7 @@ function createCombinedBoardTextures({
|
|
|
37394
37807
|
}
|
|
37395
37808
|
|
|
37396
37809
|
// src/textures/create-three-texture-meshes.ts
|
|
37397
|
-
import * as
|
|
37810
|
+
import * as THREE38 from "three";
|
|
37398
37811
|
|
|
37399
37812
|
// src/board-surface-textures.ts
|
|
37400
37813
|
var REALISTIC_BOARD_SURFACE_MATERIAL = {
|
|
@@ -37417,7 +37830,7 @@ var PAD_COPPER_TEXTURE_MATERIAL = {
|
|
|
37417
37830
|
};
|
|
37418
37831
|
|
|
37419
37832
|
// src/utils/create-board-relief-textures.ts
|
|
37420
|
-
import * as
|
|
37833
|
+
import * as THREE37 from "three";
|
|
37421
37834
|
var PLAIN_SOLDERMASK_HEIGHT = 0.22;
|
|
37422
37835
|
var MASKED_COPPER_HEIGHT = 0.7;
|
|
37423
37836
|
var EXPOSED_COPPER_HEIGHT = 0.86;
|
|
@@ -37506,13 +37919,13 @@ var getBoardSurfaceProfile = (r, g, b, hasMaskedCopper) => {
|
|
|
37506
37919
|
};
|
|
37507
37920
|
};
|
|
37508
37921
|
var createDataTexture = (canvas) => {
|
|
37509
|
-
const texture = new
|
|
37510
|
-
texture.colorSpace =
|
|
37922
|
+
const texture = new THREE37.CanvasTexture(canvas);
|
|
37923
|
+
texture.colorSpace = THREE37.NoColorSpace;
|
|
37511
37924
|
texture.generateMipmaps = false;
|
|
37512
|
-
texture.minFilter =
|
|
37513
|
-
texture.magFilter =
|
|
37514
|
-
texture.wrapS =
|
|
37515
|
-
texture.wrapT =
|
|
37925
|
+
texture.minFilter = THREE37.LinearFilter;
|
|
37926
|
+
texture.magFilter = THREE37.LinearFilter;
|
|
37927
|
+
texture.wrapS = THREE37.ClampToEdgeWrapping;
|
|
37928
|
+
texture.wrapT = THREE37.ClampToEdgeWrapping;
|
|
37516
37929
|
texture.needsUpdate = true;
|
|
37517
37930
|
return texture;
|
|
37518
37931
|
};
|
|
@@ -37619,7 +38032,7 @@ var createBoardReliefTextures = (texture, maskedCopperMask) => {
|
|
|
37619
38032
|
for (let x = 0; x < sourceCanvas.width; x++) {
|
|
37620
38033
|
const dx = (getHeight4(x + 1, y) - getHeight4(x - 1, y)) * 4;
|
|
37621
38034
|
const dy = (getHeight4(x, y + 1) - getHeight4(x, y - 1)) * 4;
|
|
37622
|
-
const normal = new
|
|
38035
|
+
const normal = new THREE37.Vector3(-dx, -dy, 1).normalize();
|
|
37623
38036
|
const i = (y * sourceCanvas.width + x) * 4;
|
|
37624
38037
|
normalData[i] = (normal.x * 0.5 + 0.5) * 255;
|
|
37625
38038
|
normalData[i + 1] = (normal.y * 0.5 + 0.5) * 255;
|
|
@@ -37649,16 +38062,16 @@ function createTexturePlane(config, boardData) {
|
|
|
37649
38062
|
} = config;
|
|
37650
38063
|
if (!texture) return null;
|
|
37651
38064
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
37652
|
-
const planeGeom = new
|
|
38065
|
+
const planeGeom = new THREE38.PlaneGeometry(
|
|
37653
38066
|
boardOutlineBounds.width,
|
|
37654
38067
|
boardOutlineBounds.height
|
|
37655
38068
|
);
|
|
37656
|
-
texture.colorSpace =
|
|
38069
|
+
texture.colorSpace = THREE38.SRGBColorSpace;
|
|
37657
38070
|
const sharedMaterialOptions = {
|
|
37658
38071
|
map: texture,
|
|
37659
38072
|
transparent: true,
|
|
37660
38073
|
alphaTest: 0.08,
|
|
37661
|
-
side:
|
|
38074
|
+
side: THREE38.FrontSide,
|
|
37662
38075
|
depthWrite: true,
|
|
37663
38076
|
polygonOffset: usePolygonOffset,
|
|
37664
38077
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -37667,12 +38080,12 @@ function createTexturePlane(config, boardData) {
|
|
|
37667
38080
|
opacity: isFaux ? FAUX_BOARD_OPACITY : 1
|
|
37668
38081
|
};
|
|
37669
38082
|
const reliefTextures = createBoardReliefTextures(texture, maskedCopperMask);
|
|
37670
|
-
const material = new
|
|
38083
|
+
const material = new THREE38.MeshPhysicalMaterial({
|
|
37671
38084
|
...sharedMaterialOptions,
|
|
37672
38085
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
37673
38086
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
37674
38087
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
37675
|
-
normalScale: new
|
|
38088
|
+
normalScale: new THREE38.Vector2(
|
|
37676
38089
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
37677
38090
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
37678
38091
|
),
|
|
@@ -37686,7 +38099,7 @@ function createTexturePlane(config, boardData) {
|
|
|
37686
38099
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
37687
38100
|
envMapIntensity: 0.18
|
|
37688
38101
|
});
|
|
37689
|
-
const mesh = new
|
|
38102
|
+
const mesh = new THREE38.Mesh(planeGeom, material);
|
|
37690
38103
|
mesh.position.set(
|
|
37691
38104
|
boardOutlineBounds.centerX,
|
|
37692
38105
|
boardOutlineBounds.centerY,
|
|
@@ -37734,7 +38147,7 @@ function createTextureMeshes(textures, boardData, pcbThickness, isFaux = false)
|
|
|
37734
38147
|
}
|
|
37735
38148
|
|
|
37736
38149
|
// src/three-components/JscadBoardTextures.tsx
|
|
37737
|
-
import * as
|
|
38150
|
+
import * as THREE39 from "three";
|
|
37738
38151
|
|
|
37739
38152
|
// src/utils/layer-texture-resolution.ts
|
|
37740
38153
|
var DEFAULT_MAX_TEXTURE_PIXELS = 4e6;
|
|
@@ -37830,7 +38243,7 @@ function JscadBoardTextures({
|
|
|
37830
38243
|
const typedMaterial = material;
|
|
37831
38244
|
for (const prop of textureProps) {
|
|
37832
38245
|
const texture = typedMaterial[prop];
|
|
37833
|
-
if (texture && texture instanceof
|
|
38246
|
+
if (texture && texture instanceof THREE39.Texture) {
|
|
37834
38247
|
texture.dispose();
|
|
37835
38248
|
typedMaterial[prop] = null;
|
|
37836
38249
|
}
|
|
@@ -37849,16 +38262,16 @@ function JscadBoardTextures({
|
|
|
37849
38262
|
}) => {
|
|
37850
38263
|
if (!texture) return null;
|
|
37851
38264
|
const boardOutlineBounds = calculateOutlineBounds(boardData);
|
|
37852
|
-
const planeGeom = new
|
|
38265
|
+
const planeGeom = new THREE39.PlaneGeometry(
|
|
37853
38266
|
boardOutlineBounds.width,
|
|
37854
38267
|
boardOutlineBounds.height
|
|
37855
38268
|
);
|
|
37856
|
-
texture.colorSpace =
|
|
38269
|
+
texture.colorSpace = THREE39.SRGBColorSpace;
|
|
37857
38270
|
const sharedMaterialOptions = {
|
|
37858
38271
|
map: texture,
|
|
37859
38272
|
transparent: true,
|
|
37860
38273
|
alphaTest: 0.08,
|
|
37861
|
-
side:
|
|
38274
|
+
side: THREE39.FrontSide,
|
|
37862
38275
|
depthWrite,
|
|
37863
38276
|
polygonOffset: usePolygonOffset,
|
|
37864
38277
|
polygonOffsetFactor: usePolygonOffset ? -4 : 0,
|
|
@@ -37869,12 +38282,12 @@ function JscadBoardTextures({
|
|
|
37869
38282
|
texture,
|
|
37870
38283
|
maskedCopperMask
|
|
37871
38284
|
);
|
|
37872
|
-
const material = new
|
|
38285
|
+
const material = new THREE39.MeshPhysicalMaterial({
|
|
37873
38286
|
...sharedMaterialOptions,
|
|
37874
38287
|
bumpMap: reliefTextures?.bumpMap ?? null,
|
|
37875
38288
|
bumpScale: REALISTIC_BOARD_SURFACE_MATERIAL.bumpScale,
|
|
37876
38289
|
normalMap: reliefTextures?.normalMap ?? null,
|
|
37877
|
-
normalScale: new
|
|
38290
|
+
normalScale: new THREE39.Vector2(
|
|
37878
38291
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale,
|
|
37879
38292
|
REALISTIC_BOARD_SURFACE_MATERIAL.normalScale
|
|
37880
38293
|
),
|
|
@@ -37886,7 +38299,7 @@ function JscadBoardTextures({
|
|
|
37886
38299
|
clearcoatRoughness: REALISTIC_BOARD_SURFACE_MATERIAL.clearcoatRoughness,
|
|
37887
38300
|
envMapIntensity: 0.18
|
|
37888
38301
|
});
|
|
37889
|
-
const mesh = new
|
|
38302
|
+
const mesh = new THREE39.Mesh(planeGeom, material);
|
|
37890
38303
|
mesh.position.set(
|
|
37891
38304
|
boardOutlineBounds.centerX,
|
|
37892
38305
|
boardOutlineBounds.centerY,
|
|
@@ -37936,7 +38349,7 @@ function JscadBoardTextures({
|
|
|
37936
38349
|
for (const material of mesh.material) {
|
|
37937
38350
|
disposeTextureMaterial(material);
|
|
37938
38351
|
}
|
|
37939
|
-
} else if (mesh.material instanceof
|
|
38352
|
+
} else if (mesh.material instanceof THREE39.Material) {
|
|
37940
38353
|
disposeTextureMaterial(mesh.material);
|
|
37941
38354
|
}
|
|
37942
38355
|
}
|
|
@@ -37947,6 +38360,108 @@ function JscadBoardTextures({
|
|
|
37947
38360
|
return null;
|
|
37948
38361
|
}
|
|
37949
38362
|
|
|
38363
|
+
// src/three-components/STLModel.tsx
|
|
38364
|
+
import { useState as useState15, useEffect as useEffect26, useMemo as useMemo21 } from "react";
|
|
38365
|
+
import * as THREE40 from "three";
|
|
38366
|
+
import { STLLoader } from "three-stdlib";
|
|
38367
|
+
function STLModel({
|
|
38368
|
+
stlUrl,
|
|
38369
|
+
stlData,
|
|
38370
|
+
mtlUrl,
|
|
38371
|
+
color,
|
|
38372
|
+
opacity = 1,
|
|
38373
|
+
layerType
|
|
38374
|
+
}) {
|
|
38375
|
+
const { rootObject } = useThree();
|
|
38376
|
+
const [geom, setGeom] = useState15(null);
|
|
38377
|
+
useEffect26(() => {
|
|
38378
|
+
const loader = new STLLoader();
|
|
38379
|
+
if (stlData) {
|
|
38380
|
+
try {
|
|
38381
|
+
const geometry = loader.parse(stlData);
|
|
38382
|
+
setGeom(geometry);
|
|
38383
|
+
} catch (e) {
|
|
38384
|
+
console.error("Failed to parse STL data", e);
|
|
38385
|
+
setGeom(null);
|
|
38386
|
+
}
|
|
38387
|
+
return;
|
|
38388
|
+
}
|
|
38389
|
+
if (stlUrl) {
|
|
38390
|
+
loader.load(stlUrl, (geometry) => {
|
|
38391
|
+
setGeom(geometry);
|
|
38392
|
+
});
|
|
38393
|
+
}
|
|
38394
|
+
}, [stlUrl, stlData]);
|
|
38395
|
+
const mesh = useMemo21(() => {
|
|
38396
|
+
if (!geom) return null;
|
|
38397
|
+
const isBoardLayer = layerType === "board";
|
|
38398
|
+
const material = new THREE40.MeshStandardMaterial({
|
|
38399
|
+
color: Array.isArray(color) ? new THREE40.Color(color[0], color[1], color[2]) : color,
|
|
38400
|
+
transparent: opacity !== 1,
|
|
38401
|
+
opacity,
|
|
38402
|
+
polygonOffset: isBoardLayer,
|
|
38403
|
+
polygonOffsetFactor: isBoardLayer ? 6 : 0,
|
|
38404
|
+
polygonOffsetUnits: isBoardLayer ? 6 : 0
|
|
38405
|
+
});
|
|
38406
|
+
const createdMesh = new THREE40.Mesh(geom, material);
|
|
38407
|
+
createdMesh.renderOrder = isBoardLayer ? -1 : 1;
|
|
38408
|
+
configureObjectShadows(createdMesh, {
|
|
38409
|
+
castShadow: !isBoardLayer && opacity === 1,
|
|
38410
|
+
receiveShadow: true
|
|
38411
|
+
});
|
|
38412
|
+
return createdMesh;
|
|
38413
|
+
}, [geom, color, opacity, layerType]);
|
|
38414
|
+
useEffect26(() => {
|
|
38415
|
+
if (!rootObject || !mesh) return;
|
|
38416
|
+
rootObject.add(mesh);
|
|
38417
|
+
return () => {
|
|
38418
|
+
rootObject.remove(mesh);
|
|
38419
|
+
mesh.geometry.dispose();
|
|
38420
|
+
if (Array.isArray(mesh.material)) {
|
|
38421
|
+
mesh.material.forEach((m) => m.dispose());
|
|
38422
|
+
} else {
|
|
38423
|
+
mesh.material.dispose();
|
|
38424
|
+
}
|
|
38425
|
+
};
|
|
38426
|
+
}, [rootObject, mesh]);
|
|
38427
|
+
return null;
|
|
38428
|
+
}
|
|
38429
|
+
|
|
38430
|
+
// src/three-components/VisibleSTLModel.tsx
|
|
38431
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
38432
|
+
function VisibleSTLModel({
|
|
38433
|
+
stlData,
|
|
38434
|
+
color,
|
|
38435
|
+
opacity = 1,
|
|
38436
|
+
layerType
|
|
38437
|
+
}) {
|
|
38438
|
+
const { visibility } = useLayerVisibility();
|
|
38439
|
+
let shouldShow = true;
|
|
38440
|
+
if (layerType === "board") {
|
|
38441
|
+
shouldShow = visibility.boardBody;
|
|
38442
|
+
} else if (layerType === "top-copper") {
|
|
38443
|
+
shouldShow = visibility.topCopper;
|
|
38444
|
+
} else if (layerType === "bottom-copper") {
|
|
38445
|
+
shouldShow = visibility.bottomCopper;
|
|
38446
|
+
} else if (layerType === "top-silkscreen") {
|
|
38447
|
+
shouldShow = visibility.topSilkscreen;
|
|
38448
|
+
} else if (layerType === "bottom-silkscreen") {
|
|
38449
|
+
shouldShow = visibility.bottomSilkscreen;
|
|
38450
|
+
}
|
|
38451
|
+
if (!shouldShow) {
|
|
38452
|
+
return null;
|
|
38453
|
+
}
|
|
38454
|
+
return /* @__PURE__ */ jsx17(
|
|
38455
|
+
STLModel,
|
|
38456
|
+
{
|
|
38457
|
+
stlData,
|
|
38458
|
+
color,
|
|
38459
|
+
opacity,
|
|
38460
|
+
layerType
|
|
38461
|
+
}
|
|
38462
|
+
);
|
|
38463
|
+
}
|
|
38464
|
+
|
|
37950
38465
|
// src/utils/preprocess-circuit-json.ts
|
|
37951
38466
|
import { su as su10 } from "@tscircuit/circuit-json-util";
|
|
37952
38467
|
|
|
@@ -38045,16 +38560,17 @@ var CadViewerJscad = forwardRef3(
|
|
|
38045
38560
|
clickToInteractEnabled,
|
|
38046
38561
|
onUserInteraction,
|
|
38047
38562
|
onCameraControllerReady,
|
|
38048
|
-
resolveStaticAsset
|
|
38563
|
+
resolveStaticAsset,
|
|
38564
|
+
referenceObject
|
|
38049
38565
|
}, ref) => {
|
|
38050
38566
|
const childrenSoup = useConvertChildrenToCircuitJson(children);
|
|
38051
|
-
const internalCircuitJson =
|
|
38567
|
+
const internalCircuitJson = useMemo22(() => {
|
|
38052
38568
|
return addFauxBoardIfNeeded(
|
|
38053
38569
|
circuitJson ?? childrenSoup
|
|
38054
38570
|
);
|
|
38055
38571
|
}, [circuitJson, childrenSoup]);
|
|
38056
38572
|
const boardGeom = useBoardGeomBuilder(internalCircuitJson);
|
|
38057
|
-
const initialCameraPosition =
|
|
38573
|
+
const initialCameraPosition = useMemo22(() => {
|
|
38058
38574
|
if (!internalCircuitJson) return [5, -5, 5];
|
|
38059
38575
|
try {
|
|
38060
38576
|
const board = su11(internalCircuitJson).pcb_board.list()[0];
|
|
@@ -38080,7 +38596,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
38080
38596
|
return [5, -5, 5];
|
|
38081
38597
|
}
|
|
38082
38598
|
}, [internalCircuitJson]);
|
|
38083
|
-
const isFauxBoard =
|
|
38599
|
+
const isFauxBoard = useMemo22(() => {
|
|
38084
38600
|
if (!internalCircuitJson) return false;
|
|
38085
38601
|
try {
|
|
38086
38602
|
const board = su11(internalCircuitJson).pcb_board.list()[0];
|
|
@@ -38089,23 +38605,25 @@ var CadViewerJscad = forwardRef3(
|
|
|
38089
38605
|
return false;
|
|
38090
38606
|
}
|
|
38091
38607
|
}, [internalCircuitJson]);
|
|
38092
|
-
const boardDimensions =
|
|
38608
|
+
const boardDimensions = useMemo22(() => {
|
|
38093
38609
|
if (!internalCircuitJson) return void 0;
|
|
38094
38610
|
try {
|
|
38095
38611
|
const board = su11(internalCircuitJson).pcb_board.list()[0];
|
|
38096
38612
|
if (!board) return void 0;
|
|
38097
|
-
|
|
38613
|
+
const bounds = calculateOutlineBounds(board);
|
|
38614
|
+
return { width: bounds.width, height: bounds.height };
|
|
38098
38615
|
} catch (e) {
|
|
38099
38616
|
console.error(e);
|
|
38100
38617
|
return void 0;
|
|
38101
38618
|
}
|
|
38102
38619
|
}, [internalCircuitJson]);
|
|
38103
|
-
const boardCenter =
|
|
38620
|
+
const boardCenter = useMemo22(() => {
|
|
38104
38621
|
if (!internalCircuitJson) return void 0;
|
|
38105
38622
|
try {
|
|
38106
38623
|
const board = su11(internalCircuitJson).pcb_board.list()[0];
|
|
38107
|
-
if (!board
|
|
38108
|
-
|
|
38624
|
+
if (!board) return void 0;
|
|
38625
|
+
const bounds = calculateOutlineBounds(board);
|
|
38626
|
+
return { x: bounds.centerX, y: bounds.centerY };
|
|
38109
38627
|
} catch (e) {
|
|
38110
38628
|
console.error(e);
|
|
38111
38629
|
return void 0;
|
|
@@ -38123,6 +38641,7 @@ var CadViewerJscad = forwardRef3(
|
|
|
38123
38641
|
clickToInteractEnabled,
|
|
38124
38642
|
boardDimensions,
|
|
38125
38643
|
boardCenter,
|
|
38644
|
+
referenceObject,
|
|
38126
38645
|
onUserInteraction,
|
|
38127
38646
|
onCameraControllerReady,
|
|
38128
38647
|
children: [
|
|
@@ -38168,13 +38687,13 @@ var CadViewerJscad = forwardRef3(
|
|
|
38168
38687
|
|
|
38169
38688
|
// src/CadViewerManifold.tsx
|
|
38170
38689
|
import { su as su17 } from "@tscircuit/circuit-json-util";
|
|
38171
|
-
import { useEffect as
|
|
38172
|
-
import * as
|
|
38690
|
+
import { useEffect as useEffect28, useMemo as useMemo24, useState as useState17 } from "react";
|
|
38691
|
+
import * as THREE47 from "three";
|
|
38173
38692
|
|
|
38174
38693
|
// src/hooks/useManifoldBoardBuilder.ts
|
|
38175
38694
|
import { su as su16 } from "@tscircuit/circuit-json-util";
|
|
38176
|
-
import { useEffect as
|
|
38177
|
-
import * as
|
|
38695
|
+
import { useEffect as useEffect27, useMemo as useMemo23, useRef as useRef9, useState as useState16 } from "react";
|
|
38696
|
+
import * as THREE44 from "three";
|
|
38178
38697
|
|
|
38179
38698
|
// src/utils/manifold/create-manifold-board.ts
|
|
38180
38699
|
var arePointsClockwise2 = (points) => {
|
|
@@ -38523,17 +39042,17 @@ function processNonPlatedHolesForManifold(Manifold, CrossSection, circuitJson, p
|
|
|
38523
39042
|
|
|
38524
39043
|
// src/utils/manifold/process-plated-holes.ts
|
|
38525
39044
|
import { su as su14 } from "@tscircuit/circuit-json-util";
|
|
38526
|
-
import * as
|
|
39045
|
+
import * as THREE42 from "three";
|
|
38527
39046
|
|
|
38528
39047
|
// src/utils/manifold-mesh-to-three-geometry.ts
|
|
38529
|
-
import * as
|
|
39048
|
+
import * as THREE41 from "three";
|
|
38530
39049
|
function manifoldMeshToThreeGeometry(manifoldMesh) {
|
|
38531
|
-
const geometry = new
|
|
39050
|
+
const geometry = new THREE41.BufferGeometry();
|
|
38532
39051
|
geometry.setAttribute(
|
|
38533
39052
|
"position",
|
|
38534
|
-
new
|
|
39053
|
+
new THREE41.Float32BufferAttribute(manifoldMesh.vertProperties, 3)
|
|
38535
39054
|
);
|
|
38536
|
-
geometry.setIndex(new
|
|
39055
|
+
geometry.setIndex(new THREE41.Uint32BufferAttribute(manifoldMesh.triVerts, 1));
|
|
38537
39056
|
if (manifoldMesh.runIndex && manifoldMesh.runIndex.length > 1 && manifoldMesh.runOriginalID) {
|
|
38538
39057
|
for (let i = 0; i < manifoldMesh.runIndex.length - 1; i++) {
|
|
38539
39058
|
const start = manifoldMesh.runIndex[i];
|
|
@@ -38567,7 +39086,7 @@ var createEllipsePoints = (width10, height10, segments) => {
|
|
|
38567
39086
|
}
|
|
38568
39087
|
return points;
|
|
38569
39088
|
};
|
|
38570
|
-
var COPPER_COLOR = new
|
|
39089
|
+
var COPPER_COLOR = new THREE42.Color(...colors.copper);
|
|
38571
39090
|
var PLATED_HOLE_LIP_HEIGHT = 0.05;
|
|
38572
39091
|
var PLATED_HOLE_PAD_THICKNESS = 3e-3;
|
|
38573
39092
|
var PLATED_HOLE_SURFACE_CLEARANCE = 5e-4;
|
|
@@ -39198,7 +39717,7 @@ function processPlatedHolesForManifold(Manifold, CrossSection, circuitJson, pcbT
|
|
|
39198
39717
|
|
|
39199
39718
|
// src/utils/manifold/process-vias.ts
|
|
39200
39719
|
import { su as su15 } from "@tscircuit/circuit-json-util";
|
|
39201
|
-
import * as
|
|
39720
|
+
import * as THREE43 from "three";
|
|
39202
39721
|
|
|
39203
39722
|
// src/utils/via-geoms.ts
|
|
39204
39723
|
function createViaCopper2({
|
|
@@ -39236,7 +39755,7 @@ function createViaCopper2({
|
|
|
39236
39755
|
}
|
|
39237
39756
|
|
|
39238
39757
|
// src/utils/manifold/process-vias.ts
|
|
39239
|
-
var COPPER_COLOR2 = new
|
|
39758
|
+
var COPPER_COLOR2 = new THREE43.Color(...colors.copper);
|
|
39240
39759
|
function processViasForManifold(Manifold, circuitJson, pcbThickness, manifoldInstancesForCleanup, boardClipVolume) {
|
|
39241
39760
|
const viaBoardDrills = [];
|
|
39242
39761
|
const pcbVias = su15(circuitJson).pcb_via.list();
|
|
@@ -39294,7 +39813,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39294
39813
|
const [error, setError] = useState16(null);
|
|
39295
39814
|
const [isLoading, setIsLoading] = useState16(true);
|
|
39296
39815
|
const manifoldInstancesForCleanup = useRef9([]);
|
|
39297
|
-
const boardData =
|
|
39816
|
+
const boardData = useMemo23(() => {
|
|
39298
39817
|
const panels = circuitJson.filter(
|
|
39299
39818
|
(e) => e.type === "pcb_panel"
|
|
39300
39819
|
);
|
|
@@ -39318,15 +39837,15 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39318
39837
|
const boardsNotInPanel = boards.filter((b) => !b.pcb_panel_id);
|
|
39319
39838
|
return boardsNotInPanel.length > 0 ? boardsNotInPanel[0] : null;
|
|
39320
39839
|
}, [circuitJson]);
|
|
39321
|
-
const isFauxBoard =
|
|
39840
|
+
const isFauxBoard = useMemo23(() => {
|
|
39322
39841
|
const boards = su16(circuitJson).pcb_board.list();
|
|
39323
39842
|
return boards.length > 0 && boards[0].pcb_board_id === "faux-board";
|
|
39324
39843
|
}, [circuitJson]);
|
|
39325
|
-
const traceTextureResolution =
|
|
39844
|
+
const traceTextureResolution = useMemo23(() => {
|
|
39326
39845
|
if (!boardData) return TRACE_TEXTURE_RESOLUTION;
|
|
39327
39846
|
return getLayerTextureResolution(boardData, TRACE_TEXTURE_RESOLUTION);
|
|
39328
39847
|
}, [boardData]);
|
|
39329
|
-
|
|
39848
|
+
useEffect27(() => {
|
|
39330
39849
|
if (!manifoldJSModule || !boardData) {
|
|
39331
39850
|
setGeoms(null);
|
|
39332
39851
|
setPcbThickness(null);
|
|
@@ -39456,7 +39975,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39456
39975
|
{
|
|
39457
39976
|
key: "plated-holes-union",
|
|
39458
39977
|
geometry: cutPlatedGeom,
|
|
39459
|
-
color: new
|
|
39978
|
+
color: new THREE44.Color(
|
|
39460
39979
|
colors.copper[0],
|
|
39461
39980
|
colors.copper[1],
|
|
39462
39981
|
colors.copper[2]
|
|
@@ -39486,7 +40005,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39486
40005
|
const matColorArray = boardMaterialColors[boardData.material] ?? colors.fr4Tan;
|
|
39487
40006
|
currentGeoms.board = {
|
|
39488
40007
|
geometry: finalBoardGeom,
|
|
39489
|
-
color: new
|
|
40008
|
+
color: new THREE44.Color(
|
|
39490
40009
|
matColorArray[0],
|
|
39491
40010
|
matColorArray[1],
|
|
39492
40011
|
matColorArray[2]
|
|
@@ -39510,7 +40029,7 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39510
40029
|
manifoldInstancesForCleanup.current = [];
|
|
39511
40030
|
};
|
|
39512
40031
|
}, [manifoldJSModule, circuitJson, boardData]);
|
|
39513
|
-
const textures =
|
|
40032
|
+
const textures = useMemo23(() => {
|
|
39514
40033
|
if (!boardData || !traceTextureResolution) return null;
|
|
39515
40034
|
return createCombinedBoardTextures({
|
|
39516
40035
|
circuitJson,
|
|
@@ -39531,11 +40050,11 @@ var useManifoldBoardBuilder = (manifoldJSModule, circuitJson, visibility) => {
|
|
|
39531
40050
|
};
|
|
39532
40051
|
|
|
39533
40052
|
// src/utils/manifold/create-three-geometry-meshes.ts
|
|
39534
|
-
import * as
|
|
40053
|
+
import * as THREE46 from "three";
|
|
39535
40054
|
|
|
39536
40055
|
// src/utils/create-board-material.ts
|
|
39537
|
-
import * as
|
|
39538
|
-
var DEFAULT_SIDE =
|
|
40056
|
+
import * as THREE45 from "three";
|
|
40057
|
+
var DEFAULT_SIDE = THREE45.DoubleSide;
|
|
39539
40058
|
var createBoardMaterial = ({
|
|
39540
40059
|
material,
|
|
39541
40060
|
color,
|
|
@@ -39543,7 +40062,7 @@ var createBoardMaterial = ({
|
|
|
39543
40062
|
isFaux = false
|
|
39544
40063
|
}) => {
|
|
39545
40064
|
if (material === "fr4") {
|
|
39546
|
-
return new
|
|
40065
|
+
return new THREE45.MeshPhysicalMaterial({
|
|
39547
40066
|
// A dark edge lets the green solder mask read as a finished PCB rather
|
|
39548
40067
|
// than a tan substrate with a decal placed on top.
|
|
39549
40068
|
color: 1063462,
|
|
@@ -39563,7 +40082,7 @@ var createBoardMaterial = ({
|
|
|
39563
40082
|
polygonOffsetUnits: 1
|
|
39564
40083
|
});
|
|
39565
40084
|
}
|
|
39566
|
-
return new
|
|
40085
|
+
return new THREE45.MeshStandardMaterial({
|
|
39567
40086
|
color,
|
|
39568
40087
|
side,
|
|
39569
40088
|
flatShading: true,
|
|
@@ -39582,12 +40101,12 @@ function createGeometryMeshes(geoms) {
|
|
|
39582
40101
|
const meshes = [];
|
|
39583
40102
|
if (!geoms) return meshes;
|
|
39584
40103
|
if (geoms.board?.geometry) {
|
|
39585
|
-
const mesh = new
|
|
40104
|
+
const mesh = new THREE46.Mesh(
|
|
39586
40105
|
geoms.board.geometry,
|
|
39587
40106
|
createBoardMaterial({
|
|
39588
40107
|
material: geoms.board.material,
|
|
39589
40108
|
color: geoms.board.color,
|
|
39590
|
-
side:
|
|
40109
|
+
side: THREE46.DoubleSide,
|
|
39591
40110
|
isFaux: geoms.board.isFaux
|
|
39592
40111
|
})
|
|
39593
40112
|
);
|
|
@@ -39598,11 +40117,11 @@ function createGeometryMeshes(geoms) {
|
|
|
39598
40117
|
const createMeshesFromArray = (geomArray) => {
|
|
39599
40118
|
if (geomArray) {
|
|
39600
40119
|
for (const comp of geomArray) {
|
|
39601
|
-
const mesh = new
|
|
40120
|
+
const mesh = new THREE46.Mesh(
|
|
39602
40121
|
comp.geometry,
|
|
39603
|
-
new
|
|
40122
|
+
new THREE46.MeshStandardMaterial({
|
|
39604
40123
|
color: comp.color,
|
|
39605
|
-
side:
|
|
40124
|
+
side: THREE46.DoubleSide,
|
|
39606
40125
|
flatShading: true
|
|
39607
40126
|
// Consistent with board
|
|
39608
40127
|
})
|
|
@@ -39647,14 +40166,14 @@ var BoardMeshes = ({
|
|
|
39647
40166
|
const typedMaterial = material;
|
|
39648
40167
|
for (const prop of textureProps) {
|
|
39649
40168
|
const texture = typedMaterial[prop];
|
|
39650
|
-
if (texture && texture instanceof
|
|
40169
|
+
if (texture && texture instanceof THREE47.Texture) {
|
|
39651
40170
|
texture.dispose();
|
|
39652
40171
|
}
|
|
39653
40172
|
}
|
|
39654
40173
|
material.dispose();
|
|
39655
40174
|
}
|
|
39656
40175
|
};
|
|
39657
|
-
|
|
40176
|
+
useEffect28(() => {
|
|
39658
40177
|
if (!rootObject) return;
|
|
39659
40178
|
for (const mesh of geometryMeshes) {
|
|
39660
40179
|
let shouldShow = true;
|
|
@@ -39676,7 +40195,7 @@ var BoardMeshes = ({
|
|
|
39676
40195
|
}
|
|
39677
40196
|
};
|
|
39678
40197
|
}, [rootObject, geometryMeshes, visibility]);
|
|
39679
|
-
|
|
40198
|
+
useEffect28(() => {
|
|
39680
40199
|
if (!rootObject) return;
|
|
39681
40200
|
for (const mesh of textureMeshes) {
|
|
39682
40201
|
rootObject.add(mesh);
|
|
@@ -39700,17 +40219,18 @@ var CadViewerManifold = ({
|
|
|
39700
40219
|
onUserInteraction,
|
|
39701
40220
|
children,
|
|
39702
40221
|
onCameraControllerReady,
|
|
39703
|
-
resolveStaticAsset
|
|
40222
|
+
resolveStaticAsset,
|
|
40223
|
+
referenceObject
|
|
39704
40224
|
}) => {
|
|
39705
40225
|
const childrenCircuitJson = useConvertChildrenToCircuitJson(children);
|
|
39706
|
-
const circuitJson =
|
|
40226
|
+
const circuitJson = useMemo24(() => {
|
|
39707
40227
|
const rawCircuitJson = circuitJsonProp ?? childrenCircuitJson;
|
|
39708
40228
|
return addFauxBoardIfNeeded(rawCircuitJson);
|
|
39709
40229
|
}, [circuitJsonProp, childrenCircuitJson]);
|
|
39710
40230
|
const [manifoldJSModule, setManifoldJSModule] = useState17(null);
|
|
39711
40231
|
const [manifoldLoadingError, setManifoldLoadingError] = useState17(null);
|
|
39712
40232
|
const { visibility } = useLayerVisibility();
|
|
39713
|
-
|
|
40233
|
+
useEffect28(() => {
|
|
39714
40234
|
if (window.ManifoldModule && typeof window.ManifoldModule === "object" && window.ManifoldModule.setup) {
|
|
39715
40235
|
setManifoldJSModule(window.ManifoldModule);
|
|
39716
40236
|
return;
|
|
@@ -39781,27 +40301,26 @@ try {
|
|
|
39781
40301
|
boardData,
|
|
39782
40302
|
isFauxBoard
|
|
39783
40303
|
} = useManifoldBoardBuilder(manifoldJSModule, circuitJson, visibility);
|
|
39784
|
-
const geometryMeshes =
|
|
39785
|
-
const textureMeshes =
|
|
40304
|
+
const geometryMeshes = useMemo24(() => createGeometryMeshes(geoms), [geoms]);
|
|
40305
|
+
const textureMeshes = useMemo24(
|
|
39786
40306
|
() => createTextureMeshes(textures, boardData, pcbThickness, isFauxBoard),
|
|
39787
40307
|
[textures, boardData, pcbThickness, isFauxBoard]
|
|
39788
40308
|
);
|
|
39789
|
-
const cadComponents =
|
|
40309
|
+
const cadComponents = useMemo24(
|
|
39790
40310
|
() => su17(circuitJson).cad_component.list(),
|
|
39791
40311
|
[circuitJson]
|
|
39792
40312
|
);
|
|
39793
|
-
const boardDimensions =
|
|
40313
|
+
const boardDimensions = useMemo24(() => {
|
|
39794
40314
|
if (!boardData) return void 0;
|
|
39795
|
-
const
|
|
39796
|
-
return { width:
|
|
40315
|
+
const bounds = calculateOutlineBounds(boardData);
|
|
40316
|
+
return { width: bounds.width, height: bounds.height };
|
|
39797
40317
|
}, [boardData]);
|
|
39798
|
-
const boardCenter =
|
|
40318
|
+
const boardCenter = useMemo24(() => {
|
|
39799
40319
|
if (!boardData) return void 0;
|
|
39800
|
-
const
|
|
39801
|
-
|
|
39802
|
-
return { x: center.x, y: center.y };
|
|
40320
|
+
const bounds = calculateOutlineBounds(boardData);
|
|
40321
|
+
return { x: bounds.centerX, y: bounds.centerY };
|
|
39803
40322
|
}, [boardData]);
|
|
39804
|
-
const initialCameraPosition =
|
|
40323
|
+
const initialCameraPosition = useMemo24(() => {
|
|
39805
40324
|
if (!boardData) return [5, -5, 5];
|
|
39806
40325
|
const { width: width10 = 0, height: height10 = 0 } = boardData;
|
|
39807
40326
|
const safeWidth = Math.max(width10, 1);
|
|
@@ -39864,6 +40383,7 @@ try {
|
|
|
39864
40383
|
clickToInteractEnabled,
|
|
39865
40384
|
boardDimensions,
|
|
39866
40385
|
boardCenter,
|
|
40386
|
+
referenceObject,
|
|
39867
40387
|
onUserInteraction,
|
|
39868
40388
|
onCameraControllerReady,
|
|
39869
40389
|
children: [
|
|
@@ -39895,9 +40415,6 @@ try {
|
|
|
39895
40415
|
};
|
|
39896
40416
|
var CadViewerManifold_default = CadViewerManifold;
|
|
39897
40417
|
|
|
39898
|
-
// src/components/ContextMenu.tsx
|
|
39899
|
-
import { useState as useState35 } from "react";
|
|
39900
|
-
|
|
39901
40418
|
// node_modules/@radix-ui/react-dropdown-menu/dist/index.mjs
|
|
39902
40419
|
import * as React42 from "react";
|
|
39903
40420
|
|
|
@@ -46072,6 +46589,9 @@ var Sub2 = DropdownMenuSub;
|
|
|
46072
46589
|
var SubTrigger2 = DropdownMenuSubTrigger;
|
|
46073
46590
|
var SubContent2 = DropdownMenuSubContent;
|
|
46074
46591
|
|
|
46592
|
+
// src/components/ContextMenu.tsx
|
|
46593
|
+
import { useState as useState35 } from "react";
|
|
46594
|
+
|
|
46075
46595
|
// src/components/AppearanceMenu.tsx
|
|
46076
46596
|
import { useState as useState34 } from "react";
|
|
46077
46597
|
|
|
@@ -46588,15 +47108,19 @@ var ContextMenu = ({
|
|
|
46588
47108
|
engine,
|
|
46589
47109
|
cameraPreset,
|
|
46590
47110
|
autoRotate,
|
|
47111
|
+
referenceObject = null,
|
|
46591
47112
|
onEngineSwitch,
|
|
46592
47113
|
onCameraPresetSelect,
|
|
46593
47114
|
onAutoRotateToggle,
|
|
47115
|
+
onReferenceObjectSelect = () => {
|
|
47116
|
+
},
|
|
46594
47117
|
onDownloadGltf,
|
|
46595
47118
|
onOpenKeyboardShortcuts
|
|
46596
47119
|
}) => {
|
|
46597
47120
|
const { cameraType, setCameraType } = useCameraController();
|
|
46598
47121
|
const { gridEnabled, setGridEnabled } = useAppearance();
|
|
46599
47122
|
const [cameraSubOpen, setCameraSubOpen] = useState35(false);
|
|
47123
|
+
const [referenceObjectSubOpen, setReferenceObjectSubOpen] = useState35(false);
|
|
46600
47124
|
const [hoveredItem, setHoveredItem] = useState35(null);
|
|
46601
47125
|
return /* @__PURE__ */ jsx34(
|
|
46602
47126
|
"div",
|
|
@@ -46733,6 +47257,72 @@ var ContextMenu = ({
|
|
|
46733
47257
|
]
|
|
46734
47258
|
}
|
|
46735
47259
|
),
|
|
47260
|
+
/* @__PURE__ */ jsxs8(Sub2, { onOpenChange: setReferenceObjectSubOpen, children: [
|
|
47261
|
+
/* @__PURE__ */ jsxs8(
|
|
47262
|
+
SubTrigger2,
|
|
47263
|
+
{
|
|
47264
|
+
style: {
|
|
47265
|
+
...itemStyles2,
|
|
47266
|
+
...itemPaddingStyles2,
|
|
47267
|
+
backgroundColor: referenceObjectSubOpen || hoveredItem === "reference-object" ? "#404040" : "transparent"
|
|
47268
|
+
},
|
|
47269
|
+
onMouseEnter: () => setHoveredItem("reference-object"),
|
|
47270
|
+
onMouseLeave: () => setHoveredItem(null),
|
|
47271
|
+
onTouchStart: () => setHoveredItem("reference-object"),
|
|
47272
|
+
children: [
|
|
47273
|
+
/* @__PURE__ */ jsx34(
|
|
47274
|
+
"span",
|
|
47275
|
+
{
|
|
47276
|
+
style: { flex: 1, display: "flex", alignItems: "center" },
|
|
47277
|
+
children: "Show Reference Object"
|
|
47278
|
+
}
|
|
47279
|
+
),
|
|
47280
|
+
/* @__PURE__ */ jsx34(
|
|
47281
|
+
"div",
|
|
47282
|
+
{
|
|
47283
|
+
style: {
|
|
47284
|
+
display: "flex",
|
|
47285
|
+
alignItems: "flex-end",
|
|
47286
|
+
gap: 6,
|
|
47287
|
+
marginLeft: "auto"
|
|
47288
|
+
},
|
|
47289
|
+
children: /* @__PURE__ */ jsx34(ChevronRightIcon, { isOpen: referenceObjectSubOpen })
|
|
47290
|
+
}
|
|
47291
|
+
)
|
|
47292
|
+
]
|
|
47293
|
+
}
|
|
47294
|
+
),
|
|
47295
|
+
/* @__PURE__ */ jsx34(Portal22, { children: /* @__PURE__ */ jsx34(
|
|
47296
|
+
SubContent2,
|
|
47297
|
+
{
|
|
47298
|
+
style: { ...contentStyles2, marginLeft: -2 },
|
|
47299
|
+
collisionPadding: 10,
|
|
47300
|
+
avoidCollisions: true,
|
|
47301
|
+
children: REFERENCE_OBJECT_OPTIONS.map((option) => /* @__PURE__ */ jsxs8(
|
|
47302
|
+
Item22,
|
|
47303
|
+
{
|
|
47304
|
+
style: {
|
|
47305
|
+
...itemStyles2,
|
|
47306
|
+
backgroundColor: hoveredItem === option.type ? "#404040" : "transparent"
|
|
47307
|
+
},
|
|
47308
|
+
onSelect: (event) => event.preventDefault(),
|
|
47309
|
+
onPointerDown: (event) => {
|
|
47310
|
+
event.preventDefault();
|
|
47311
|
+
onReferenceObjectSelect(option.type);
|
|
47312
|
+
},
|
|
47313
|
+
onMouseEnter: () => setHoveredItem(option.type),
|
|
47314
|
+
onMouseLeave: () => setHoveredItem(null),
|
|
47315
|
+
onTouchStart: () => setHoveredItem(option.type),
|
|
47316
|
+
children: [
|
|
47317
|
+
/* @__PURE__ */ jsx34("span", { style: iconContainerStyles2, children: referenceObject === option.type && /* @__PURE__ */ jsx34(DotIcon, {}) }),
|
|
47318
|
+
/* @__PURE__ */ jsx34("span", { style: { display: "flex", alignItems: "center" }, children: option.label })
|
|
47319
|
+
]
|
|
47320
|
+
},
|
|
47321
|
+
option.type
|
|
47322
|
+
))
|
|
47323
|
+
}
|
|
47324
|
+
) })
|
|
47325
|
+
] }),
|
|
46736
47326
|
/* @__PURE__ */ jsxs8(
|
|
46737
47327
|
Item22,
|
|
46738
47328
|
{
|
|
@@ -46876,10 +47466,10 @@ var ContextMenu = ({
|
|
|
46876
47466
|
};
|
|
46877
47467
|
|
|
46878
47468
|
// src/components/KeyboardShortcutsDialog.tsx
|
|
46879
|
-
import { useEffect as
|
|
47469
|
+
import { useEffect as useEffect47, useMemo as useMemo32, useRef as useRef27, useState as useState37 } from "react";
|
|
46880
47470
|
|
|
46881
47471
|
// src/hooks/useRegisteredHotkey.ts
|
|
46882
|
-
import { useEffect as
|
|
47472
|
+
import { useEffect as useEffect46, useMemo as useMemo31, useRef as useRef26, useState as useState36 } from "react";
|
|
46883
47473
|
var hotkeyRegistry = /* @__PURE__ */ new Map();
|
|
46884
47474
|
var subscribers = /* @__PURE__ */ new Set();
|
|
46885
47475
|
var isListenerAttached = false;
|
|
@@ -47003,14 +47593,14 @@ var subscribeToRegistry = (subscriber) => {
|
|
|
47003
47593
|
var useRegisteredHotkey = (id, handler, metadata) => {
|
|
47004
47594
|
const handlerRef = useRef26(handler);
|
|
47005
47595
|
handlerRef.current = handler;
|
|
47006
|
-
const normalizedMetadata =
|
|
47596
|
+
const normalizedMetadata = useMemo31(
|
|
47007
47597
|
() => ({
|
|
47008
47598
|
shortcut: metadata.shortcut,
|
|
47009
47599
|
description: metadata.description
|
|
47010
47600
|
}),
|
|
47011
47601
|
[metadata.shortcut, metadata.description]
|
|
47012
47602
|
);
|
|
47013
|
-
|
|
47603
|
+
useEffect46(() => {
|
|
47014
47604
|
const registration = {
|
|
47015
47605
|
id,
|
|
47016
47606
|
...normalizedMetadata,
|
|
@@ -47026,7 +47616,7 @@ var useHotkeyRegistry = () => {
|
|
|
47026
47616
|
const [entries, setEntries] = useState36(
|
|
47027
47617
|
() => Array.from(hotkeyRegistry.values())
|
|
47028
47618
|
);
|
|
47029
|
-
|
|
47619
|
+
useEffect46(() => subscribeToRegistry(setEntries), []);
|
|
47030
47620
|
return entries;
|
|
47031
47621
|
};
|
|
47032
47622
|
var registerHotkeyViewer = (element) => {
|
|
@@ -47043,7 +47633,7 @@ var KeyboardShortcutsDialog = ({
|
|
|
47043
47633
|
const [query, setQuery] = useState37("");
|
|
47044
47634
|
const inputRef = useRef27(null);
|
|
47045
47635
|
const hotkeys = useHotkeyRegistry();
|
|
47046
|
-
|
|
47636
|
+
useEffect47(() => {
|
|
47047
47637
|
if (!open) return void 0;
|
|
47048
47638
|
const handleKeyDown = (event) => {
|
|
47049
47639
|
if (event.key === "Escape") {
|
|
@@ -47054,14 +47644,14 @@ var KeyboardShortcutsDialog = ({
|
|
|
47054
47644
|
window.addEventListener("keydown", handleKeyDown);
|
|
47055
47645
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
47056
47646
|
}, [open, onClose]);
|
|
47057
|
-
|
|
47647
|
+
useEffect47(() => {
|
|
47058
47648
|
if (open) {
|
|
47059
47649
|
setTimeout(() => {
|
|
47060
47650
|
inputRef.current?.focus();
|
|
47061
47651
|
}, 0);
|
|
47062
47652
|
}
|
|
47063
47653
|
}, [open]);
|
|
47064
|
-
const filteredHotkeys =
|
|
47654
|
+
const filteredHotkeys = useMemo32(() => {
|
|
47065
47655
|
const normalizedQuery = query.trim().toLowerCase();
|
|
47066
47656
|
if (!normalizedQuery) {
|
|
47067
47657
|
return hotkeys;
|
|
@@ -47283,7 +47873,7 @@ function useCameraPreset({
|
|
|
47283
47873
|
}
|
|
47284
47874
|
|
|
47285
47875
|
// src/hooks/useContextMenu.ts
|
|
47286
|
-
import { useState as useState38, useCallback as useCallback22, useRef as useRef28, useEffect as
|
|
47876
|
+
import { useState as useState38, useCallback as useCallback22, useRef as useRef28, useEffect as useEffect48 } from "react";
|
|
47287
47877
|
var useContextMenu = ({ containerRef }) => {
|
|
47288
47878
|
const [menuVisible, setMenuVisible] = useState38(false);
|
|
47289
47879
|
const [menuPos, setMenuPos] = useState38({
|
|
@@ -47398,7 +47988,7 @@ var useContextMenu = ({ containerRef }) => {
|
|
|
47398
47988
|
}
|
|
47399
47989
|
setMenuVisible(false);
|
|
47400
47990
|
}, []);
|
|
47401
|
-
|
|
47991
|
+
useEffect48(() => {
|
|
47402
47992
|
if (menuVisible) {
|
|
47403
47993
|
document.addEventListener("mousedown", handleClickAway);
|
|
47404
47994
|
document.addEventListener("touchstart", handleClickAway);
|
|
@@ -47462,7 +48052,7 @@ var useGlobalDownloadGltf = () => {
|
|
|
47462
48052
|
|
|
47463
48053
|
// src/CadViewer.tsx
|
|
47464
48054
|
import { jsx as jsx37, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
47465
|
-
var DEFAULT_TARGET = new
|
|
48055
|
+
var DEFAULT_TARGET = new THREE48.Vector3(0, 0, 0);
|
|
47466
48056
|
var INITIAL_CAMERA_POSITION = [5, -5, 5];
|
|
47467
48057
|
var readStoredCameraType = () => {
|
|
47468
48058
|
if (typeof window === "undefined") return void 0;
|
|
@@ -47485,6 +48075,7 @@ var CadViewerInner = (props) => {
|
|
|
47485
48075
|
return stored === "true";
|
|
47486
48076
|
});
|
|
47487
48077
|
const [cameraPreset, setCameraPreset] = useState39("Custom");
|
|
48078
|
+
const [referenceObject, setReferenceObject] = useState39(null);
|
|
47488
48079
|
const { cameraType } = useCameraController();
|
|
47489
48080
|
const { visibility, setLayerVisibility } = useLayerVisibility();
|
|
47490
48081
|
const { showToast } = useToast();
|
|
@@ -47595,24 +48186,24 @@ var CadViewerInner = (props) => {
|
|
|
47595
48186
|
description: "Toggle translucent components"
|
|
47596
48187
|
}
|
|
47597
48188
|
);
|
|
47598
|
-
|
|
48189
|
+
useEffect49(() => {
|
|
47599
48190
|
if (containerRef.current) {
|
|
47600
48191
|
registerHotkeyViewer(containerRef.current);
|
|
47601
48192
|
}
|
|
47602
48193
|
}, []);
|
|
47603
|
-
|
|
48194
|
+
useEffect49(() => {
|
|
47604
48195
|
window.localStorage.setItem("cadViewerEngine", engine);
|
|
47605
48196
|
}, [engine]);
|
|
47606
|
-
|
|
48197
|
+
useEffect49(() => {
|
|
47607
48198
|
window.localStorage.setItem("cadViewerAutoRotate", String(autoRotate));
|
|
47608
48199
|
}, [autoRotate]);
|
|
47609
|
-
|
|
48200
|
+
useEffect49(() => {
|
|
47610
48201
|
window.localStorage.setItem(
|
|
47611
48202
|
"cadViewerAutoRotateUserToggled",
|
|
47612
48203
|
String(autoRotateUserToggled)
|
|
47613
48204
|
);
|
|
47614
48205
|
}, [autoRotateUserToggled]);
|
|
47615
|
-
|
|
48206
|
+
useEffect49(() => {
|
|
47616
48207
|
window.localStorage.setItem("cadViewerCameraType", cameraType);
|
|
47617
48208
|
}, [cameraType]);
|
|
47618
48209
|
const viewerKey = props.circuitJson ? JSON.stringify(props.circuitJson) : void 0;
|
|
@@ -47639,7 +48230,8 @@ var CadViewerInner = (props) => {
|
|
|
47639
48230
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
47640
48231
|
cameraType,
|
|
47641
48232
|
onUserInteraction: handleUserInteraction,
|
|
47642
|
-
onCameraControllerReady: handleCameraControllerReady
|
|
48233
|
+
onCameraControllerReady: handleCameraControllerReady,
|
|
48234
|
+
referenceObject
|
|
47643
48235
|
}
|
|
47644
48236
|
) : /* @__PURE__ */ jsx37(
|
|
47645
48237
|
CadViewerManifold_default,
|
|
@@ -47648,7 +48240,8 @@ var CadViewerInner = (props) => {
|
|
|
47648
48240
|
autoRotateDisabled: props.autoRotateDisabled || !autoRotate,
|
|
47649
48241
|
cameraType,
|
|
47650
48242
|
onUserInteraction: handleUserInteraction,
|
|
47651
|
-
onCameraControllerReady: handleCameraControllerReady
|
|
48243
|
+
onCameraControllerReady: handleCameraControllerReady,
|
|
48244
|
+
referenceObject
|
|
47652
48245
|
}
|
|
47653
48246
|
),
|
|
47654
48247
|
/* @__PURE__ */ jsxs11(
|
|
@@ -47680,6 +48273,7 @@ var CadViewerInner = (props) => {
|
|
|
47680
48273
|
engine,
|
|
47681
48274
|
cameraPreset,
|
|
47682
48275
|
autoRotate,
|
|
48276
|
+
referenceObject,
|
|
47683
48277
|
onEngineSwitch: (newEngine) => {
|
|
47684
48278
|
setEngine(newEngine);
|
|
47685
48279
|
closeMenu();
|
|
@@ -47689,6 +48283,13 @@ var CadViewerInner = (props) => {
|
|
|
47689
48283
|
toggleAutoRotate();
|
|
47690
48284
|
closeMenu();
|
|
47691
48285
|
},
|
|
48286
|
+
onReferenceObjectSelect: (nextReferenceObject) => {
|
|
48287
|
+
setReferenceObject(nextReferenceObject);
|
|
48288
|
+
setAutoRotate(false);
|
|
48289
|
+
setAutoRotateUserToggled(true);
|
|
48290
|
+
setCameraPreset("Custom");
|
|
48291
|
+
closeMenu();
|
|
48292
|
+
},
|
|
47692
48293
|
onDownloadGltf: () => {
|
|
47693
48294
|
downloadGltf();
|
|
47694
48295
|
closeMenu();
|
|
@@ -47726,14 +48327,14 @@ var CadViewer = (props) => {
|
|
|
47726
48327
|
// src/convert-circuit-json-to-3d-svg.ts
|
|
47727
48328
|
var import_debug = __toESM(require_browser(), 1);
|
|
47728
48329
|
import { su as su18 } from "@tscircuit/circuit-json-util";
|
|
47729
|
-
import * as
|
|
48330
|
+
import * as THREE52 from "three";
|
|
47730
48331
|
import { SVGRenderer } from "three/examples/jsm/renderers/SVGRenderer.js";
|
|
47731
48332
|
|
|
47732
48333
|
// src/utils/create-geometry-from-polygons.ts
|
|
47733
|
-
import * as
|
|
47734
|
-
import { BufferGeometry as
|
|
48334
|
+
import * as THREE49 from "three";
|
|
48335
|
+
import { BufferGeometry as BufferGeometry5, Float32BufferAttribute as Float32BufferAttribute4 } from "three";
|
|
47735
48336
|
function createGeometryFromPolygons(polygons) {
|
|
47736
|
-
const geometry = new
|
|
48337
|
+
const geometry = new BufferGeometry5();
|
|
47737
48338
|
const vertices = [];
|
|
47738
48339
|
const normals = [];
|
|
47739
48340
|
for (const polygon2 of polygons) {
|
|
@@ -47744,12 +48345,12 @@ function createGeometryFromPolygons(polygons) {
|
|
|
47744
48345
|
...polygon2.vertices[i + 1]
|
|
47745
48346
|
// Third vertex
|
|
47746
48347
|
);
|
|
47747
|
-
const v1 = new
|
|
47748
|
-
const v2 = new
|
|
47749
|
-
const v3 = new
|
|
47750
|
-
const normal = new
|
|
47751
|
-
new
|
|
47752
|
-
new
|
|
48348
|
+
const v1 = new THREE49.Vector3(...polygon2.vertices[0]);
|
|
48349
|
+
const v2 = new THREE49.Vector3(...polygon2.vertices[i]);
|
|
48350
|
+
const v3 = new THREE49.Vector3(...polygon2.vertices[i + 1]);
|
|
48351
|
+
const normal = new THREE49.Vector3().crossVectors(
|
|
48352
|
+
new THREE49.Vector3().subVectors(v2, v1),
|
|
48353
|
+
new THREE49.Vector3().subVectors(v3, v1)
|
|
47753
48354
|
).normalize();
|
|
47754
48355
|
normals.push(
|
|
47755
48356
|
normal.x,
|
|
@@ -47764,8 +48365,8 @@ function createGeometryFromPolygons(polygons) {
|
|
|
47764
48365
|
);
|
|
47765
48366
|
}
|
|
47766
48367
|
}
|
|
47767
|
-
geometry.setAttribute("position", new
|
|
47768
|
-
geometry.setAttribute("normal", new
|
|
48368
|
+
geometry.setAttribute("position", new Float32BufferAttribute4(vertices, 3));
|
|
48369
|
+
geometry.setAttribute("normal", new Float32BufferAttribute4(normals, 3));
|
|
47769
48370
|
return geometry;
|
|
47770
48371
|
}
|
|
47771
48372
|
|
|
@@ -47773,10 +48374,10 @@ function createGeometryFromPolygons(polygons) {
|
|
|
47773
48374
|
var import_modeling2 = __toESM(require_src(), 1);
|
|
47774
48375
|
var import_jscad_planner2 = __toESM(require_dist(), 1);
|
|
47775
48376
|
var jscadModeling2 = __toESM(require_src(), 1);
|
|
47776
|
-
import * as
|
|
48377
|
+
import * as THREE51 from "three";
|
|
47777
48378
|
|
|
47778
48379
|
// src/utils/load-model.ts
|
|
47779
|
-
import * as
|
|
48380
|
+
import * as THREE50 from "three";
|
|
47780
48381
|
import { GLTFLoader as GLTFLoader2 } from "three/examples/jsm/loaders/GLTFLoader.js";
|
|
47781
48382
|
import { OBJLoader as OBJLoader2 } from "three/examples/jsm/loaders/OBJLoader.js";
|
|
47782
48383
|
import { STLLoader as STLLoader2 } from "three/examples/jsm/loaders/STLLoader.js";
|
|
@@ -47784,12 +48385,12 @@ async function load3DModel(url) {
|
|
|
47784
48385
|
if (url.endsWith(".stl")) {
|
|
47785
48386
|
const loader = new STLLoader2();
|
|
47786
48387
|
const geometry = await loader.loadAsync(url);
|
|
47787
|
-
const material = new
|
|
48388
|
+
const material = new THREE50.MeshStandardMaterial({
|
|
47788
48389
|
color: 8947848,
|
|
47789
48390
|
metalness: 0.5,
|
|
47790
48391
|
roughness: 0.5
|
|
47791
48392
|
});
|
|
47792
|
-
return new
|
|
48393
|
+
return new THREE50.Mesh(geometry, material);
|
|
47793
48394
|
}
|
|
47794
48395
|
if (url.endsWith(".obj")) {
|
|
47795
48396
|
const loader = new OBJLoader2();
|
|
@@ -47822,9 +48423,9 @@ async function renderComponent(component, scene) {
|
|
|
47822
48423
|
}
|
|
47823
48424
|
if (component.rotation) {
|
|
47824
48425
|
model.rotation.set(
|
|
47825
|
-
|
|
47826
|
-
|
|
47827
|
-
|
|
48426
|
+
THREE51.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
48427
|
+
THREE51.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
48428
|
+
THREE51.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
47828
48429
|
);
|
|
47829
48430
|
}
|
|
47830
48431
|
scene.add(model);
|
|
@@ -47838,13 +48439,13 @@ async function renderComponent(component, scene) {
|
|
|
47838
48439
|
);
|
|
47839
48440
|
if (jscadObject && (jscadObject.polygons || jscadObject.sides)) {
|
|
47840
48441
|
const threeGeom = convertCSGToThreeGeom(jscadObject);
|
|
47841
|
-
const material2 = new
|
|
48442
|
+
const material2 = new THREE51.MeshStandardMaterial({
|
|
47842
48443
|
color: 8947848,
|
|
47843
48444
|
metalness: 0.5,
|
|
47844
48445
|
roughness: 0.5,
|
|
47845
|
-
side:
|
|
48446
|
+
side: THREE51.DoubleSide
|
|
47846
48447
|
});
|
|
47847
|
-
const mesh2 = new
|
|
48448
|
+
const mesh2 = new THREE51.Mesh(threeGeom, material2);
|
|
47848
48449
|
if (component.position) {
|
|
47849
48450
|
mesh2.position.set(
|
|
47850
48451
|
component.position.x ?? 0,
|
|
@@ -47854,9 +48455,9 @@ async function renderComponent(component, scene) {
|
|
|
47854
48455
|
}
|
|
47855
48456
|
if (component.rotation) {
|
|
47856
48457
|
mesh2.rotation.set(
|
|
47857
|
-
|
|
47858
|
-
|
|
47859
|
-
|
|
48458
|
+
THREE51.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
48459
|
+
THREE51.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
48460
|
+
THREE51.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
47860
48461
|
);
|
|
47861
48462
|
}
|
|
47862
48463
|
scene.add(mesh2);
|
|
@@ -47873,17 +48474,17 @@ async function renderComponent(component, scene) {
|
|
|
47873
48474
|
if (!geom || !geom.polygons && !geom.sides) {
|
|
47874
48475
|
continue;
|
|
47875
48476
|
}
|
|
47876
|
-
const color = new
|
|
48477
|
+
const color = new THREE51.Color(geomInfo.color);
|
|
47877
48478
|
color.convertLinearToSRGB();
|
|
47878
48479
|
const geomWithColor = { ...geom, color: [color.r, color.g, color.b] };
|
|
47879
48480
|
const threeGeom = convertCSGToThreeGeom(geomWithColor);
|
|
47880
|
-
const material2 = new
|
|
48481
|
+
const material2 = new THREE51.MeshStandardMaterial({
|
|
47881
48482
|
vertexColors: true,
|
|
47882
48483
|
metalness: 0.2,
|
|
47883
48484
|
roughness: 0.8,
|
|
47884
|
-
side:
|
|
48485
|
+
side: THREE51.DoubleSide
|
|
47885
48486
|
});
|
|
47886
|
-
const mesh2 = new
|
|
48487
|
+
const mesh2 = new THREE51.Mesh(threeGeom, material2);
|
|
47887
48488
|
if (component.position) {
|
|
47888
48489
|
mesh2.position.set(
|
|
47889
48490
|
component.position.x ?? 0,
|
|
@@ -47893,22 +48494,22 @@ async function renderComponent(component, scene) {
|
|
|
47893
48494
|
}
|
|
47894
48495
|
if (component.rotation) {
|
|
47895
48496
|
mesh2.rotation.set(
|
|
47896
|
-
|
|
47897
|
-
|
|
47898
|
-
|
|
48497
|
+
THREE51.MathUtils.degToRad(component.rotation.x ?? 0),
|
|
48498
|
+
THREE51.MathUtils.degToRad(component.rotation.y ?? 0),
|
|
48499
|
+
THREE51.MathUtils.degToRad(component.rotation.z ?? 0)
|
|
47899
48500
|
);
|
|
47900
48501
|
}
|
|
47901
48502
|
scene.add(mesh2);
|
|
47902
48503
|
}
|
|
47903
48504
|
return;
|
|
47904
48505
|
}
|
|
47905
|
-
const geometry = new
|
|
47906
|
-
const material = new
|
|
48506
|
+
const geometry = new THREE51.BoxGeometry(0.5, 0.5, 0.5);
|
|
48507
|
+
const material = new THREE51.MeshStandardMaterial({
|
|
47907
48508
|
color: 16711680,
|
|
47908
48509
|
transparent: true,
|
|
47909
48510
|
opacity: 0.25
|
|
47910
48511
|
});
|
|
47911
|
-
const mesh = new
|
|
48512
|
+
const mesh = new THREE51.Mesh(geometry, material);
|
|
47912
48513
|
if (component.position) {
|
|
47913
48514
|
mesh.position.set(
|
|
47914
48515
|
component.position.x ?? 0,
|
|
@@ -47929,11 +48530,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
47929
48530
|
padding = 20,
|
|
47930
48531
|
zoom = 1.5
|
|
47931
48532
|
} = options;
|
|
47932
|
-
const scene = new
|
|
48533
|
+
const scene = new THREE52.Scene();
|
|
47933
48534
|
const renderer = new SVGRenderer();
|
|
47934
48535
|
renderer.setSize(width10, height10);
|
|
47935
|
-
renderer.setClearColor(new
|
|
47936
|
-
const camera = new
|
|
48536
|
+
renderer.setClearColor(new THREE52.Color(backgroundColor), 1);
|
|
48537
|
+
const camera = new THREE52.OrthographicCamera();
|
|
47937
48538
|
const aspect = width10 / height10;
|
|
47938
48539
|
const frustumSize = 100;
|
|
47939
48540
|
const halfFrustumSize = frustumSize / 2 / zoom;
|
|
@@ -47947,11 +48548,11 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
47947
48548
|
camera.position.set(position.x, position.y, position.z);
|
|
47948
48549
|
camera.up.set(0, 1, 0);
|
|
47949
48550
|
const lookAt = options.camera?.lookAt ?? { x: 0, y: 0, z: 0 };
|
|
47950
|
-
camera.lookAt(new
|
|
48551
|
+
camera.lookAt(new THREE52.Vector3(lookAt.x, lookAt.y, lookAt.z));
|
|
47951
48552
|
camera.updateProjectionMatrix();
|
|
47952
|
-
const ambientLight = new
|
|
48553
|
+
const ambientLight = new THREE52.AmbientLight(16777215, Math.PI / 2);
|
|
47953
48554
|
scene.add(ambientLight);
|
|
47954
|
-
const pointLight = new
|
|
48555
|
+
const pointLight = new THREE52.PointLight(16777215, Math.PI / 4);
|
|
47955
48556
|
pointLight.position.set(-10, -10, 10);
|
|
47956
48557
|
scene.add(pointLight);
|
|
47957
48558
|
const components = su18(circuitJson).cad_component.list();
|
|
@@ -47962,7 +48563,7 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
47962
48563
|
const boardGeom = createSimplifiedBoardGeom(circuitJson);
|
|
47963
48564
|
if (boardGeom) {
|
|
47964
48565
|
const solderMaskColor = colors.fr4SolderMaskGreen;
|
|
47965
|
-
const baseColor = new
|
|
48566
|
+
const baseColor = new THREE52.Color(
|
|
47966
48567
|
solderMaskColor[0],
|
|
47967
48568
|
solderMaskColor[1],
|
|
47968
48569
|
solderMaskColor[2]
|
|
@@ -47974,28 +48575,28 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
47974
48575
|
const material = createBoardMaterial({
|
|
47975
48576
|
material: boardData?.material,
|
|
47976
48577
|
color: baseColor,
|
|
47977
|
-
side:
|
|
48578
|
+
side: THREE52.DoubleSide
|
|
47978
48579
|
});
|
|
47979
|
-
const mesh = new
|
|
48580
|
+
const mesh = new THREE52.Mesh(geometry, material);
|
|
47980
48581
|
scene.add(mesh);
|
|
47981
48582
|
}
|
|
47982
48583
|
}
|
|
47983
|
-
const gridColor = new
|
|
47984
|
-
const gridHelper = new
|
|
48584
|
+
const gridColor = new THREE52.Color(8947848);
|
|
48585
|
+
const gridHelper = new THREE52.GridHelper(100, 100, gridColor, gridColor);
|
|
47985
48586
|
gridHelper.rotation.x = Math.PI / 2;
|
|
47986
48587
|
const materials = Array.isArray(gridHelper.material) ? gridHelper.material : [gridHelper.material];
|
|
47987
48588
|
for (const mat of materials) {
|
|
47988
48589
|
mat.transparent = true;
|
|
47989
48590
|
mat.opacity = 0.3;
|
|
47990
|
-
if (mat instanceof
|
|
48591
|
+
if (mat instanceof THREE52.LineBasicMaterial) {
|
|
47991
48592
|
mat.color = gridColor;
|
|
47992
48593
|
mat.vertexColors = false;
|
|
47993
48594
|
}
|
|
47994
48595
|
}
|
|
47995
48596
|
scene.add(gridHelper);
|
|
47996
|
-
const box = new
|
|
47997
|
-
const center = box.getCenter(new
|
|
47998
|
-
const size4 = box.getSize(new
|
|
48597
|
+
const box = new THREE52.Box3().setFromObject(scene);
|
|
48598
|
+
const center = box.getCenter(new THREE52.Vector3());
|
|
48599
|
+
const size4 = box.getSize(new THREE52.Vector3());
|
|
47999
48600
|
scene.position.sub(center);
|
|
48000
48601
|
const maxDim = Math.max(size4.x, size4.y, size4.z);
|
|
48001
48602
|
if (maxDim > 0) {
|
|
@@ -48013,10 +48614,10 @@ async function convertCircuitJsonTo3dSvg(circuitJson, options = {}) {
|
|
|
48013
48614
|
|
|
48014
48615
|
// src/hooks/exporter/gltf.ts
|
|
48015
48616
|
import { GLTFExporter as GLTFExporter3 } from "three-stdlib";
|
|
48016
|
-
import { useEffect as
|
|
48617
|
+
import { useEffect as useEffect50, useState as useState40, useMemo as useMemo33, useCallback as useCallback25 } from "react";
|
|
48017
48618
|
function useSaveGltfAs(options = {}) {
|
|
48018
48619
|
const parse2 = useParser(options);
|
|
48019
|
-
const link =
|
|
48620
|
+
const link = useMemo33(() => document.createElement("a"), []);
|
|
48020
48621
|
const saveAs = async (filename) => {
|
|
48021
48622
|
const name = filename ?? options.filename ?? "";
|
|
48022
48623
|
if (options.binary == null) options.binary = name.endsWith(".glb");
|
|
@@ -48026,7 +48627,7 @@ function useSaveGltfAs(options = {}) {
|
|
|
48026
48627
|
link.dispatchEvent(new MouseEvent("click"));
|
|
48027
48628
|
URL.revokeObjectURL(url);
|
|
48028
48629
|
};
|
|
48029
|
-
|
|
48630
|
+
useEffect50(
|
|
48030
48631
|
() => () => {
|
|
48031
48632
|
link.remove();
|
|
48032
48633
|
instance = null;
|
|
@@ -48047,11 +48648,11 @@ function useExportGltfUrl(options = {}) {
|
|
|
48047
48648
|
(instance) => parse2(instance).then(setUrl).catch(setError),
|
|
48048
48649
|
[]
|
|
48049
48650
|
);
|
|
48050
|
-
|
|
48651
|
+
useEffect50(() => () => URL.revokeObjectURL(url), [url]);
|
|
48051
48652
|
return [ref, url, error];
|
|
48052
48653
|
}
|
|
48053
48654
|
function useParser(options = {}) {
|
|
48054
|
-
const exporter =
|
|
48655
|
+
const exporter = useMemo33(() => new GLTFExporter3(), []);
|
|
48055
48656
|
return (instance) => {
|
|
48056
48657
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
48057
48658
|
exporter.parse(
|