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