@toolpath/viewer 2.3.3 → 2.6.0
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/README.md +139 -4
- package/dist/{chunk-M2B3CQPQ.js → chunk-ESPHWO5M.js} +367 -84
- package/dist/engine/index.d.ts +14 -3
- package/dist/engine/index.js +5 -3
- package/dist/index.d.ts +81 -4
- package/dist/index.js +1141 -368
- package/dist/{normalize-C4Wj4IGK.d.ts → normalize-BBADLCmd.d.ts} +47 -2
- package/package.json +1 -1
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
useLayoutEffect as useLayoutEffect3,
|
|
10
10
|
useMemo as useMemo7,
|
|
11
11
|
useRef as useRef6,
|
|
12
|
-
useSyncExternalStore
|
|
12
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
13
13
|
} from "react";
|
|
14
|
-
import { Vector3 as
|
|
14
|
+
import { Vector3 as Vector313 } from "three";
|
|
15
15
|
|
|
16
16
|
// src/part-context.tsx
|
|
17
17
|
import { createContext, useContext } from "react";
|
|
@@ -863,6 +863,7 @@ import {
|
|
|
863
863
|
DataTexture,
|
|
864
864
|
DoubleSide as DoubleSide2,
|
|
865
865
|
Float32BufferAttribute as Float32BufferAttribute3,
|
|
866
|
+
FloatType,
|
|
866
867
|
Group as Group2,
|
|
867
868
|
LineBasicMaterial,
|
|
868
869
|
LineSegments,
|
|
@@ -871,7 +872,7 @@ import {
|
|
|
871
872
|
RedFormat,
|
|
872
873
|
RGBAFormat,
|
|
873
874
|
UnsignedByteType,
|
|
874
|
-
Vector3 as
|
|
875
|
+
Vector3 as Vector36
|
|
875
876
|
} from "three";
|
|
876
877
|
|
|
877
878
|
// src/render/edges.ts
|
|
@@ -1488,9 +1489,147 @@ function emptyCreases() {
|
|
|
1488
1489
|
};
|
|
1489
1490
|
}
|
|
1490
1491
|
|
|
1492
|
+
// src/render/threads.ts
|
|
1493
|
+
import {
|
|
1494
|
+
Vector3 as Vector35
|
|
1495
|
+
} from "three";
|
|
1496
|
+
var THREAD_TEXTURE_ROWS = 2;
|
|
1497
|
+
var MAX_AXIAL_NORMAL = 0.2;
|
|
1498
|
+
var MIN_AXIS_CROSS = 0.1;
|
|
1499
|
+
var DIAMETER_SLACK = 1.1;
|
|
1500
|
+
function facetsOf(position, ranges) {
|
|
1501
|
+
const facets = [];
|
|
1502
|
+
const a = new Vector35();
|
|
1503
|
+
const b = new Vector35();
|
|
1504
|
+
const c = new Vector35();
|
|
1505
|
+
for (const range of ranges) {
|
|
1506
|
+
for (let triangle = range.start; triangle < range.end; triangle += 1) {
|
|
1507
|
+
const first = triangle * 3;
|
|
1508
|
+
if (first + 2 >= position.count) break;
|
|
1509
|
+
a.fromBufferAttribute(position, first);
|
|
1510
|
+
b.fromBufferAttribute(position, first + 1);
|
|
1511
|
+
c.fromBufferAttribute(position, first + 2);
|
|
1512
|
+
const normal = new Vector35().subVectors(b, a).cross(new Vector35().subVectors(c, a));
|
|
1513
|
+
const doubleArea = normal.length();
|
|
1514
|
+
if (doubleArea === 0) continue;
|
|
1515
|
+
facets.push({
|
|
1516
|
+
centre: new Vector35().add(a).add(b).add(c).divideScalar(3),
|
|
1517
|
+
normal: normal.divideScalar(doubleArea),
|
|
1518
|
+
area: doubleArea / 2
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
return facets;
|
|
1523
|
+
}
|
|
1524
|
+
function axisOf(facets) {
|
|
1525
|
+
const first = facets[0];
|
|
1526
|
+
if (!first) return null;
|
|
1527
|
+
let furthest = first;
|
|
1528
|
+
for (const facet of facets) {
|
|
1529
|
+
if (Math.abs(facet.normal.dot(first.normal)) < Math.abs(furthest.normal.dot(first.normal))) {
|
|
1530
|
+
furthest = facet;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
const axis = new Vector35().crossVectors(first.normal, furthest.normal);
|
|
1534
|
+
if (axis.length() < MIN_AXIS_CROSS) return null;
|
|
1535
|
+
axis.normalize();
|
|
1536
|
+
const allSquare = facets.every((facet) => Math.abs(facet.normal.dot(axis)) <= MAX_AXIAL_NORMAL);
|
|
1537
|
+
return allSquare ? axis : null;
|
|
1538
|
+
}
|
|
1539
|
+
function fitBore(position, ranges) {
|
|
1540
|
+
const facets = facetsOf(position, ranges);
|
|
1541
|
+
const axis = axisOf(facets);
|
|
1542
|
+
if (!axis) return null;
|
|
1543
|
+
const u = new Vector35().crossVectors(axis, Math.abs(axis.x) < 0.9 ? new Vector35(1, 0, 0) : new Vector35(0, 1, 0)).normalize();
|
|
1544
|
+
const v = new Vector35().crossVectors(axis, u);
|
|
1545
|
+
let xx = 0;
|
|
1546
|
+
let xy = 0;
|
|
1547
|
+
let yy = 0;
|
|
1548
|
+
let rx = 0;
|
|
1549
|
+
let ry = 0;
|
|
1550
|
+
let along = 0;
|
|
1551
|
+
let total = 0;
|
|
1552
|
+
for (const { centre, normal, area } of facets) {
|
|
1553
|
+
const mx = normal.dot(u);
|
|
1554
|
+
const my = normal.dot(v);
|
|
1555
|
+
const length = Math.hypot(mx, my);
|
|
1556
|
+
const nx = mx / length;
|
|
1557
|
+
const ny = my / length;
|
|
1558
|
+
const qx = centre.dot(u);
|
|
1559
|
+
const qy = centre.dot(v);
|
|
1560
|
+
const pxx = 1 - nx * nx;
|
|
1561
|
+
const pxy = -nx * ny;
|
|
1562
|
+
const pyy = 1 - ny * ny;
|
|
1563
|
+
xx += area * pxx;
|
|
1564
|
+
xy += area * pxy;
|
|
1565
|
+
yy += area * pyy;
|
|
1566
|
+
rx += area * (pxx * qx + pxy * qy);
|
|
1567
|
+
ry += area * (pxy * qx + pyy * qy);
|
|
1568
|
+
along += area * centre.dot(axis);
|
|
1569
|
+
total += area;
|
|
1570
|
+
}
|
|
1571
|
+
const determinant = xx * yy - xy * xy;
|
|
1572
|
+
if (Math.abs(determinant) < 1e-9 * total * total) return null;
|
|
1573
|
+
const cx = (yy * rx - xy * ry) / determinant;
|
|
1574
|
+
const cy = (xx * ry - xy * rx) / determinant;
|
|
1575
|
+
let radius = 0;
|
|
1576
|
+
for (const { centre, area } of facets) {
|
|
1577
|
+
radius += area * Math.hypot(centre.dot(u) - cx, centre.dot(v) - cy);
|
|
1578
|
+
}
|
|
1579
|
+
return {
|
|
1580
|
+
origin: new Vector35().addScaledVector(u, cx).addScaledVector(v, cy).addScaledVector(axis, along / total),
|
|
1581
|
+
axis,
|
|
1582
|
+
radius: radius / total
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
function threadedRanges(position, model, mark) {
|
|
1586
|
+
const regions = [];
|
|
1587
|
+
const ranges = [];
|
|
1588
|
+
for (const region of mark.regions) {
|
|
1589
|
+
const range = model.regionIndex.rangeForRegion(region);
|
|
1590
|
+
if (!range) continue;
|
|
1591
|
+
const bore = fitBore(position, [range]);
|
|
1592
|
+
if (!bore || bore.radius * 2 > mark.majorDiameter * DIAMETER_SLACK) continue;
|
|
1593
|
+
regions.push(region);
|
|
1594
|
+
ranges.push(range);
|
|
1595
|
+
}
|
|
1596
|
+
return { regions, ranges };
|
|
1597
|
+
}
|
|
1598
|
+
function writeThreadTexels(data, width, geometry, model, texels, options) {
|
|
1599
|
+
data.fill(0);
|
|
1600
|
+
if (!options) return;
|
|
1601
|
+
const position = geometry.getAttribute("position");
|
|
1602
|
+
for (const mark of options.threads) {
|
|
1603
|
+
if (!Number.isFinite(mark.pitch) || mark.pitch === 0) continue;
|
|
1604
|
+
const { regions, ranges } = threadedRanges(position, model, mark);
|
|
1605
|
+
const bore = fitBore(position, ranges);
|
|
1606
|
+
if (!bore) continue;
|
|
1607
|
+
for (const region of regions) {
|
|
1608
|
+
const column = texels.get(region);
|
|
1609
|
+
if (column === void 0) continue;
|
|
1610
|
+
const first = column * 4;
|
|
1611
|
+
const second = (width + column) * 4;
|
|
1612
|
+
data[first] = bore.origin.x;
|
|
1613
|
+
data[first + 1] = bore.origin.y;
|
|
1614
|
+
data[first + 2] = bore.origin.z;
|
|
1615
|
+
data[first + 3] = mark.pitch;
|
|
1616
|
+
data[second] = bore.axis.x;
|
|
1617
|
+
data[second + 1] = bore.axis.y;
|
|
1618
|
+
data[second + 2] = bore.axis.z;
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
}
|
|
1622
|
+
function threadKey(options) {
|
|
1623
|
+
if (!options) return "";
|
|
1624
|
+
return options.threads.map((mark) => `${mark.regions.join(",")}:${mark.pitch}:${mark.majorDiameter}`).join("|");
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1491
1627
|
// src/render/part.ts
|
|
1492
1628
|
var REGION_ATTRIBUTE = "aRegion";
|
|
1493
1629
|
var EMISSIVE_MIX = 0.4;
|
|
1630
|
+
var THREAD_TILT = Math.tan(Math.PI / 4);
|
|
1631
|
+
var THREAD_ROOT_SHADE = 0.45;
|
|
1632
|
+
var THREAD_CREST_LIGHT = 1.15;
|
|
1494
1633
|
function buildRegionTexels(model) {
|
|
1495
1634
|
return new Map(model.regions.map((region, column) => [region.idx, column]));
|
|
1496
1635
|
}
|
|
@@ -1522,6 +1661,10 @@ function createPart(model, geometry, theme) {
|
|
|
1522
1661
|
const opacity = new Uint8Array(width).fill(255);
|
|
1523
1662
|
const opacityTexture = new DataTexture(opacity, width, 1, RedFormat, UnsignedByteType);
|
|
1524
1663
|
opacityTexture.needsUpdate = true;
|
|
1664
|
+
const threads = new Float32Array(width * THREAD_TEXTURE_ROWS * 4);
|
|
1665
|
+
const threadTexture = new DataTexture(threads, width, THREAD_TEXTURE_ROWS, RGBAFormat, FloatType);
|
|
1666
|
+
threadTexture.needsUpdate = true;
|
|
1667
|
+
let threadsKey = "";
|
|
1525
1668
|
const focusState = { value: false };
|
|
1526
1669
|
const wireframe = { value: false };
|
|
1527
1670
|
let focused = false;
|
|
@@ -1547,15 +1690,26 @@ function createPart(model, geometry, theme) {
|
|
|
1547
1690
|
shader.uniforms["uWireframe"] = wireframe;
|
|
1548
1691
|
shader.uniforms["uFocus"] = focusState;
|
|
1549
1692
|
shader.uniforms["uOpaqueFocusPass"] = { value: opaqueFocusPass };
|
|
1693
|
+
shader.uniforms["uThreads"] = { value: threadTexture };
|
|
1550
1694
|
shader.vertexShader = shader.vertexShader.replace(
|
|
1551
1695
|
"#include <common>",
|
|
1552
1696
|
`#include <common>
|
|
1553
1697
|
attribute float ${REGION_ATTRIBUTE};
|
|
1554
|
-
|
|
1698
|
+
uniform sampler2D uThreads;
|
|
1699
|
+
varying float vRegion;
|
|
1700
|
+
varying vec3 vThreadPosition;
|
|
1701
|
+
varying vec4 vThreadOrigin;
|
|
1702
|
+
varying vec3 vThreadAxis;
|
|
1703
|
+
varying vec3 vThreadAxisView;`
|
|
1555
1704
|
).replace(
|
|
1556
1705
|
"#include <begin_vertex>",
|
|
1557
1706
|
`#include <begin_vertex>
|
|
1558
|
-
vRegion = ${REGION_ATTRIBUTE}
|
|
1707
|
+
vRegion = ${REGION_ATTRIBUTE};
|
|
1708
|
+
// Every vertex of a triangle is in one region, so these are flat across it.
|
|
1709
|
+
vThreadOrigin = texelFetch(uThreads, ivec2(int(vRegion + 0.5), 0), 0);
|
|
1710
|
+
vThreadAxis = texelFetch(uThreads, ivec2(int(vRegion + 0.5), 1), 0).xyz;
|
|
1711
|
+
vThreadAxisView = normalMatrix * vThreadAxis;
|
|
1712
|
+
vThreadPosition = position;`
|
|
1559
1713
|
);
|
|
1560
1714
|
shader.fragmentShader = shader.fragmentShader.replace(
|
|
1561
1715
|
"#include <common>",
|
|
@@ -1566,6 +1720,10 @@ function createPart(model, geometry, theme) {
|
|
|
1566
1720
|
uniform bool uFocus;
|
|
1567
1721
|
uniform bool uOpaqueFocusPass;
|
|
1568
1722
|
varying float vRegion;
|
|
1723
|
+
varying vec3 vThreadPosition;
|
|
1724
|
+
varying vec4 vThreadOrigin;
|
|
1725
|
+
varying vec3 vThreadAxis;
|
|
1726
|
+
varying vec3 vThreadAxisView;
|
|
1569
1727
|
vec4 regionState;`
|
|
1570
1728
|
).replace(
|
|
1571
1729
|
"#include <color_fragment>",
|
|
@@ -1578,6 +1736,46 @@ function createPart(model, geometry, theme) {
|
|
|
1578
1736
|
diffuseColor.a *= regionOpacity;
|
|
1579
1737
|
if (uWireframe) diffuseColor.a *= regionState.a;
|
|
1580
1738
|
`
|
|
1739
|
+
).replace(
|
|
1740
|
+
"#include <normal_fragment_maps>",
|
|
1741
|
+
`#include <normal_fragment_maps>
|
|
1742
|
+
// Worked out for every pixel, threaded or not, and applied only where
|
|
1743
|
+
// there is a thread: derivatives are undefined inside a branch that
|
|
1744
|
+
// differs between neighbouring pixels, as it does along a region's edge.
|
|
1745
|
+
bool threaded = vThreadOrigin.w != 0.0;
|
|
1746
|
+
float threadPitch = threaded ? vThreadOrigin.w : 1.0;
|
|
1747
|
+
vec3 threadAxis = threaded ? normalize(vThreadAxis) : vec3(0.0, 0.0, 1.0);
|
|
1748
|
+
vec3 threadOffset = vThreadPosition - vThreadOrigin.xyz;
|
|
1749
|
+
float threadAlong = dot(threadOffset, threadAxis);
|
|
1750
|
+
vec3 threadU = normalize(cross(
|
|
1751
|
+
threadAxis,
|
|
1752
|
+
abs(threadAxis.x) < 0.9 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0)
|
|
1753
|
+
));
|
|
1754
|
+
vec3 threadV = cross(threadAxis, threadU);
|
|
1755
|
+
float threadX = dot(threadOffset, threadU);
|
|
1756
|
+
float threadY = dot(threadOffset, threadV);
|
|
1757
|
+
float threadTurn = atan(threadY, threadX) / PI2;
|
|
1758
|
+
float threadPhase = threadAlong / threadPitch - threadTurn;
|
|
1759
|
+
// Two angle seams on opposite sides, so the blur estimate has none.
|
|
1760
|
+
float threadBlur = fwidth(threadAlong / threadPitch) + min(
|
|
1761
|
+
fwidth(threadTurn),
|
|
1762
|
+
fwidth(atan(-threadY, -threadX) / PI2)
|
|
1763
|
+
);
|
|
1764
|
+
if (threaded) {
|
|
1765
|
+
float threadStrength = 1.0 - smoothstep(0.2, 0.45, threadBlur);
|
|
1766
|
+
// The V of the thread: 1 at its root (phase 0), 0 at its crest (phase \xBD).
|
|
1767
|
+
float threadDepth = abs(fract(threadPhase) - 0.5) * 2.0;
|
|
1768
|
+
float threadSlope = clamp(sin(PI2 * threadPhase) * 3.0, -1.0, 1.0) * sign(threadPitch);
|
|
1769
|
+
normal = normalize(
|
|
1770
|
+
normal - ${THREAD_TILT.toFixed(4)} * threadStrength * threadSlope * normalize(vThreadAxisView)
|
|
1771
|
+
);
|
|
1772
|
+
float threadShade = mix(
|
|
1773
|
+
${THREAD_CREST_LIGHT.toFixed(2)},
|
|
1774
|
+
${THREAD_ROOT_SHADE.toFixed(2)},
|
|
1775
|
+
smoothstep(0.0, 1.0, threadDepth)
|
|
1776
|
+
);
|
|
1777
|
+
diffuseColor.rgb *= mix(1.0, threadShade, threadStrength);
|
|
1778
|
+
}`
|
|
1581
1779
|
).replace(
|
|
1582
1780
|
"#include <emissivemap_fragment>",
|
|
1583
1781
|
`#include <emissivemap_fragment>
|
|
@@ -1629,7 +1827,7 @@ function createPart(model, geometry, theme) {
|
|
|
1629
1827
|
const object = new Group2();
|
|
1630
1828
|
object.add(focusMesh, mesh, edges);
|
|
1631
1829
|
const scratchColor = new Color2();
|
|
1632
|
-
const scratchVector = new
|
|
1830
|
+
const scratchVector = new Vector36();
|
|
1633
1831
|
const paintRegion = (region, color, weight) => {
|
|
1634
1832
|
const column = texels.get(region);
|
|
1635
1833
|
if (column === void 0) return;
|
|
@@ -1758,6 +1956,13 @@ function createPart(model, geometry, theme) {
|
|
|
1758
1956
|
setHoveredSharpCorner(index) {
|
|
1759
1957
|
sharpLines?.setHovered(index);
|
|
1760
1958
|
},
|
|
1959
|
+
setThreads(options) {
|
|
1960
|
+
const key = threadKey(options);
|
|
1961
|
+
if (key === threadsKey) return;
|
|
1962
|
+
threadsKey = key;
|
|
1963
|
+
writeThreadTexels(threads, width, geometry, model, texels, options);
|
|
1964
|
+
threadTexture.needsUpdate = true;
|
|
1965
|
+
},
|
|
1761
1966
|
dispose() {
|
|
1762
1967
|
object.clear();
|
|
1763
1968
|
if (geometry.getAttribute(REGION_ATTRIBUTE) === regionAttribute) {
|
|
@@ -1770,6 +1975,7 @@ function createPart(model, geometry, theme) {
|
|
|
1770
1975
|
sharpLines?.dispose();
|
|
1771
1976
|
stateTexture.dispose();
|
|
1772
1977
|
opacityTexture.dispose();
|
|
1978
|
+
threadTexture.dispose();
|
|
1773
1979
|
}
|
|
1774
1980
|
};
|
|
1775
1981
|
}
|
|
@@ -1837,6 +2043,7 @@ var NO_MODIFIERS = {
|
|
|
1837
2043
|
shift: false,
|
|
1838
2044
|
secondary: false
|
|
1839
2045
|
};
|
|
2046
|
+
var ignoreRay = () => void 0;
|
|
1840
2047
|
function viewDirection(camera, target) {
|
|
1841
2048
|
const { x, y, z } = camera.position;
|
|
1842
2049
|
const dx = x - target.x;
|
|
@@ -1883,9 +2090,10 @@ import {
|
|
|
1883
2090
|
useEffect as useEffect4,
|
|
1884
2091
|
useImperativeHandle,
|
|
1885
2092
|
useMemo as useMemo4,
|
|
1886
|
-
useRef as useRef3
|
|
2093
|
+
useRef as useRef3,
|
|
2094
|
+
useSyncExternalStore
|
|
1887
2095
|
} from "react";
|
|
1888
|
-
import { Box3 as Box33, Vector3 as
|
|
2096
|
+
import { Box3 as Box33, Vector3 as Vector310 } from "three";
|
|
1889
2097
|
|
|
1890
2098
|
// src/camera.tsx
|
|
1891
2099
|
import { useFrame, useThree as useThree2 } from "@react-three/fiber";
|
|
@@ -1902,7 +2110,7 @@ import {
|
|
|
1902
2110
|
Sphere,
|
|
1903
2111
|
Spherical,
|
|
1904
2112
|
Vector2 as Vector23,
|
|
1905
|
-
Vector3 as
|
|
2113
|
+
Vector3 as Vector37,
|
|
1906
2114
|
Vector4 as Vector42
|
|
1907
2115
|
} from "three";
|
|
1908
2116
|
|
|
@@ -2000,7 +2208,7 @@ CameraControls.install({
|
|
|
2000
2208
|
Sphere,
|
|
2001
2209
|
Spherical,
|
|
2002
2210
|
Vector2: Vector23,
|
|
2003
|
-
Vector3:
|
|
2211
|
+
Vector3: Vector37,
|
|
2004
2212
|
Vector4: Vector42
|
|
2005
2213
|
}
|
|
2006
2214
|
});
|
|
@@ -2023,9 +2231,9 @@ var ExtendedCameraControls = class extends CameraControls {
|
|
|
2023
2231
|
// Scratch objects — `#onPointerMove` and `#adaptUpVector` run at pointer and
|
|
2024
2232
|
// frame rate respectively, so neither may allocate.
|
|
2025
2233
|
#spherical = new Spherical();
|
|
2026
|
-
#scratchA = new
|
|
2027
|
-
#scratchB = new
|
|
2028
|
-
#scratchC = new
|
|
2234
|
+
#scratchA = new Vector37();
|
|
2235
|
+
#scratchB = new Vector37();
|
|
2236
|
+
#scratchC = new Vector37();
|
|
2029
2237
|
constructor(camera, domElement, options = {}) {
|
|
2030
2238
|
super(camera, domElement);
|
|
2031
2239
|
this.#domElement = domElement;
|
|
@@ -2363,6 +2571,22 @@ function counted(notify) {
|
|
|
2363
2571
|
};
|
|
2364
2572
|
}
|
|
2365
2573
|
|
|
2574
|
+
// src/render/webgl.ts
|
|
2575
|
+
var isWebGLAvailable = () => {
|
|
2576
|
+
if (typeof document === "undefined") {
|
|
2577
|
+
return false;
|
|
2578
|
+
}
|
|
2579
|
+
try {
|
|
2580
|
+
const context = document.createElement("canvas").getContext("webgl2");
|
|
2581
|
+
context?.getExtension("WEBGL_lose_context")?.loseContext();
|
|
2582
|
+
return context !== null;
|
|
2583
|
+
} catch {
|
|
2584
|
+
return false;
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
var probed;
|
|
2588
|
+
var webGLAvailableSnapshot = () => probed ??= isWebGLAvailable();
|
|
2589
|
+
|
|
2366
2590
|
// src/target-marker.tsx
|
|
2367
2591
|
import { useFrame as useFrame2, useThree as useThree3 } from "@react-three/fiber";
|
|
2368
2592
|
import { useEffect as useEffect3, useMemo as useMemo3, useRef as useRef2 } from "react";
|
|
@@ -2370,7 +2594,7 @@ import {
|
|
|
2370
2594
|
DoubleSide as DoubleSide3,
|
|
2371
2595
|
RingGeometry,
|
|
2372
2596
|
SphereGeometry,
|
|
2373
|
-
Vector3 as
|
|
2597
|
+
Vector3 as Vector38
|
|
2374
2598
|
} from "three";
|
|
2375
2599
|
|
|
2376
2600
|
// src/render/target.ts
|
|
@@ -2413,8 +2637,8 @@ var TargetMarker = ({ controlsRef }) => {
|
|
|
2413
2637
|
const heldUntil = useRef2(0);
|
|
2414
2638
|
const painted = useRef2(-1);
|
|
2415
2639
|
const placed = useRef2(false);
|
|
2416
|
-
const lastTarget = useMemo3(() => new
|
|
2417
|
-
const scratch = useMemo3(() => new
|
|
2640
|
+
const lastTarget = useMemo3(() => new Vector38(), []);
|
|
2641
|
+
const scratch = useMemo3(() => new Vector38(), []);
|
|
2418
2642
|
useEffect3(() => {
|
|
2419
2643
|
const controls = controlsRef.current;
|
|
2420
2644
|
if (!controls) return void 0;
|
|
@@ -2508,13 +2732,41 @@ var TargetMarker = ({ controlsRef }) => {
|
|
|
2508
2732
|
] });
|
|
2509
2733
|
};
|
|
2510
2734
|
|
|
2735
|
+
// src/webgl-unavailable.tsx
|
|
2736
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2737
|
+
var STYLE = {
|
|
2738
|
+
display: "flex",
|
|
2739
|
+
flexDirection: "column",
|
|
2740
|
+
alignItems: "center",
|
|
2741
|
+
justifyContent: "center",
|
|
2742
|
+
gap: "0.5rem",
|
|
2743
|
+
height: "100%",
|
|
2744
|
+
padding: "1rem",
|
|
2745
|
+
boxSizing: "border-box",
|
|
2746
|
+
textAlign: "center"
|
|
2747
|
+
};
|
|
2748
|
+
var DEFAULT_MESSAGE = /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
2749
|
+
/* @__PURE__ */ jsx3("strong", { children: "3D view unavailable" }),
|
|
2750
|
+
/* @__PURE__ */ jsx3("span", { children: "WebGL is blocked in this browser. Turn on graphics (hardware) acceleration in your browser settings, then restart the browser." })
|
|
2751
|
+
] });
|
|
2752
|
+
var WebGLUnavailable = ({ children = DEFAULT_MESSAGE }) => /* @__PURE__ */ jsx3(
|
|
2753
|
+
"div",
|
|
2754
|
+
{
|
|
2755
|
+
className: "viewer-webgl-unavailable",
|
|
2756
|
+
"data-viewer-webgl-unavailable": "true",
|
|
2757
|
+
role: "alert",
|
|
2758
|
+
style: STYLE,
|
|
2759
|
+
children
|
|
2760
|
+
}
|
|
2761
|
+
);
|
|
2762
|
+
|
|
2511
2763
|
// src/render/view-cube.ts
|
|
2512
2764
|
import {
|
|
2513
2765
|
BufferGeometry as BufferGeometry2,
|
|
2514
2766
|
CanvasTexture,
|
|
2515
2767
|
Float32BufferAttribute as Float32BufferAttribute4,
|
|
2516
2768
|
SRGBColorSpace,
|
|
2517
|
-
Vector3 as
|
|
2769
|
+
Vector3 as Vector39
|
|
2518
2770
|
} from "three";
|
|
2519
2771
|
var VIEW_NAMES = [
|
|
2520
2772
|
// The six faces.
|
|
@@ -2598,12 +2850,12 @@ function viewUp(direction) {
|
|
|
2598
2850
|
return { x: 0, y: 0, z: 1 };
|
|
2599
2851
|
}
|
|
2600
2852
|
function squaredUp(direction, currentUp) {
|
|
2601
|
-
const forward = new
|
|
2853
|
+
const forward = new Vector39(direction.x, direction.y, direction.z).normalize();
|
|
2602
2854
|
const canonical = viewUp(direction);
|
|
2603
|
-
const zero = new
|
|
2855
|
+
const zero = new Vector39(canonical.x, canonical.y, canonical.z);
|
|
2604
2856
|
zero.addScaledVector(forward, -forward.dot(zero)).normalize();
|
|
2605
|
-
const quarter = new
|
|
2606
|
-
const current = new
|
|
2857
|
+
const quarter = new Vector39().crossVectors(forward, zero);
|
|
2858
|
+
const current = new Vector39(currentUp.x, currentUp.y, currentUp.z);
|
|
2607
2859
|
const rolls = [zero, quarter, zero.clone().negate(), quarter.clone().negate()];
|
|
2608
2860
|
const nearest = rolls.reduce(
|
|
2609
2861
|
(best, roll) => roll.dot(current) > best.dot(current) ? roll : best
|
|
@@ -2621,11 +2873,11 @@ function cubeZones(chamfer = CHAMFER) {
|
|
|
2621
2873
|
const direction = viewVector(name);
|
|
2622
2874
|
const [sx, sy, sz] = VIEW_SIGNS[name];
|
|
2623
2875
|
const sign = (axis) => VIEW_SIGNS[name][axis] ?? 0;
|
|
2624
|
-
const normal = new
|
|
2876
|
+
const normal = new Vector39(direction.x, direction.y, direction.z);
|
|
2625
2877
|
let polygon;
|
|
2626
2878
|
if (kind === "face") {
|
|
2627
2879
|
const up = viewUp(direction);
|
|
2628
|
-
const upVector = new
|
|
2880
|
+
const upVector = new Vector39(up.x, up.y, up.z);
|
|
2629
2881
|
const right = normal.clone().negate().cross(upVector).normalize();
|
|
2630
2882
|
const square = [
|
|
2631
2883
|
[-1, -1],
|
|
@@ -2647,7 +2899,7 @@ function cubeZones(chamfer = CHAMFER) {
|
|
|
2647
2899
|
[chamfer, 1, -chamfer]
|
|
2648
2900
|
];
|
|
2649
2901
|
polygon = rectangle.map(
|
|
2650
|
-
([onA, onB, onC]) => new
|
|
2902
|
+
([onA, onB, onC]) => new Vector39().setComponent(a, sign(a) * onA).setComponent(b, sign(b) * onB).setComponent(c, onC)
|
|
2651
2903
|
);
|
|
2652
2904
|
} else {
|
|
2653
2905
|
const triangle = [
|
|
@@ -2655,11 +2907,11 @@ function cubeZones(chamfer = CHAMFER) {
|
|
|
2655
2907
|
[chamfer, 1, chamfer],
|
|
2656
2908
|
[chamfer, chamfer, 1]
|
|
2657
2909
|
];
|
|
2658
|
-
polygon = triangle.map(([onX, onY, onZ]) => new
|
|
2910
|
+
polygon = triangle.map(([onX, onY, onZ]) => new Vector39(sx * onX, sy * onY, sz * onZ));
|
|
2659
2911
|
}
|
|
2660
2912
|
const [first, second, third] = polygon;
|
|
2661
2913
|
if (first && second && third) {
|
|
2662
|
-
const facing = new
|
|
2914
|
+
const facing = new Vector39().subVectors(second, first).cross(new Vector39().subVectors(third, first));
|
|
2663
2915
|
if (facing.dot(normal) < 0) polygon.reverse();
|
|
2664
2916
|
}
|
|
2665
2917
|
return { name, kind, direction, polygon: polygon.map(vec) };
|
|
@@ -2749,7 +3001,7 @@ function labelTexture(label, color) {
|
|
|
2749
3001
|
}
|
|
2750
3002
|
|
|
2751
3003
|
// src/viewer.tsx
|
|
2752
|
-
import { jsx as
|
|
3004
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2753
3005
|
var ViewerControlsContext = createContext3(null);
|
|
2754
3006
|
var useViewerControls = () => {
|
|
2755
3007
|
const controls = useContext3(ViewerControlsContext);
|
|
@@ -2789,10 +3041,10 @@ var ViewerScene = ({
|
|
|
2789
3041
|
const framedRef = useRef3(null);
|
|
2790
3042
|
const scratchBox = useMemo4(() => new Box33(), []);
|
|
2791
3043
|
const scratchBoundary = useMemo4(() => new Box33(), []);
|
|
2792
|
-
const scratchDirection = useMemo4(() => new
|
|
2793
|
-
const scratchView = useMemo4(() => new
|
|
2794
|
-
const scratchTarget = useMemo4(() => new
|
|
2795
|
-
const scratchPosition = useMemo4(() => new
|
|
3044
|
+
const scratchDirection = useMemo4(() => new Vector310(), []);
|
|
3045
|
+
const scratchView = useMemo4(() => new Vector310(), []);
|
|
3046
|
+
const scratchTarget = useMemo4(() => new Vector310(), []);
|
|
3047
|
+
const scratchPosition = useMemo4(() => new Vector310(), []);
|
|
2796
3048
|
const applyLimits = useCallback(
|
|
2797
3049
|
(bounds, framed) => {
|
|
2798
3050
|
controlsRef.current?.applyLimits(
|
|
@@ -2841,8 +3093,8 @@ var ViewerScene = ({
|
|
|
2841
3093
|
(bounds) => {
|
|
2842
3094
|
const controls = controlsRef.current;
|
|
2843
3095
|
if (!controls) return false;
|
|
2844
|
-
const target = controls.getTarget(new
|
|
2845
|
-
const direction = currentViewDirection(camera, target, new
|
|
3096
|
+
const target = controls.getTarget(new Vector310());
|
|
3097
|
+
const direction = currentViewDirection(camera, target, new Vector310());
|
|
2846
3098
|
const distance = fitDistance(projection, size, bounds, DEFAULT_FIT_MARGIN);
|
|
2847
3099
|
const position = direction.multiplyScalar(distance).add(bounds.center);
|
|
2848
3100
|
void controls.setLookAt(
|
|
@@ -2867,8 +3119,8 @@ var ViewerScene = ({
|
|
|
2867
3119
|
const fitContent = useCallback(() => {
|
|
2868
3120
|
const controls = controlsRef.current;
|
|
2869
3121
|
if (!controls) return false;
|
|
2870
|
-
const target = controls.getTarget(new
|
|
2871
|
-
return frame(currentViewDirection(camera, target, new
|
|
3122
|
+
const target = controls.getTarget(new Vector310());
|
|
3123
|
+
return frame(currentViewDirection(camera, target, new Vector310()), true);
|
|
2872
3124
|
}, [camera, frame]);
|
|
2873
3125
|
const resetContent = useCallback(() => {
|
|
2874
3126
|
const bounds = measure();
|
|
@@ -2958,18 +3210,18 @@ var ViewerScene = ({
|
|
|
2958
3210
|
initialFrameComplete.current = resetContent();
|
|
2959
3211
|
}
|
|
2960
3212
|
});
|
|
2961
|
-
return /* @__PURE__ */
|
|
2962
|
-
/* @__PURE__ */
|
|
2963
|
-
/* @__PURE__ */
|
|
2964
|
-
/* @__PURE__ */
|
|
3213
|
+
return /* @__PURE__ */ jsx4(ViewerTapProvider, { value: isTap, children: /* @__PURE__ */ jsxs3(ViewerRetargetContext.Provider, { value: retargetOn, children: [
|
|
3214
|
+
/* @__PURE__ */ jsxs3("group", { ref: lightsRef, children: [
|
|
3215
|
+
/* @__PURE__ */ jsx4("ambientLight", { color: theme.ambient, intensity: theme.ambientIntensity }),
|
|
3216
|
+
/* @__PURE__ */ jsx4(
|
|
2965
3217
|
"hemisphereLight",
|
|
2966
3218
|
{
|
|
2967
3219
|
args: [theme.hemisphereSky, theme.hemisphereGround, theme.hemisphereIntensity]
|
|
2968
3220
|
}
|
|
2969
3221
|
)
|
|
2970
3222
|
] }),
|
|
2971
|
-
/* @__PURE__ */
|
|
2972
|
-
/* @__PURE__ */
|
|
3223
|
+
/* @__PURE__ */ jsx4("group", { ref: contentRef, children }),
|
|
3224
|
+
/* @__PURE__ */ jsx4(
|
|
2973
3225
|
CadCameraControls,
|
|
2974
3226
|
{
|
|
2975
3227
|
controlsRef,
|
|
@@ -2978,9 +3230,11 @@ var ViewerScene = ({
|
|
|
2978
3230
|
zoomTo
|
|
2979
3231
|
}
|
|
2980
3232
|
),
|
|
2981
|
-
showOrbitTarget ? /* @__PURE__ */
|
|
3233
|
+
showOrbitTarget ? /* @__PURE__ */ jsx4(TargetMarker, { controlsRef }) : null
|
|
2982
3234
|
] }) });
|
|
2983
3235
|
};
|
|
3236
|
+
var subscribeNever = () => () => {
|
|
3237
|
+
};
|
|
2984
3238
|
var Viewer = forwardRef(function Viewer2({
|
|
2985
3239
|
children,
|
|
2986
3240
|
className,
|
|
@@ -2993,8 +3247,10 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
2993
3247
|
retargetOnDoubleClick = true,
|
|
2994
3248
|
showOrbitTarget = false,
|
|
2995
3249
|
theme,
|
|
2996
|
-
onPointerMissed
|
|
3250
|
+
onPointerMissed,
|
|
3251
|
+
webglUnavailable
|
|
2997
3252
|
}, ref) {
|
|
3253
|
+
const webglAvailable = useSyncExternalStore(subscribeNever, webGLAvailableSnapshot, () => true);
|
|
2998
3254
|
const actionsRef = useRef3(null);
|
|
2999
3255
|
const resolved = useMemo4(() => resolveTheme(theme), [theme]);
|
|
3000
3256
|
const sectionStore = useMemo4(() => createSectionStore(), []);
|
|
@@ -3020,7 +3276,7 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
3020
3276
|
tracker.current?.dispose();
|
|
3021
3277
|
tracker.current = element ? trackTaps(element) : null;
|
|
3022
3278
|
}, []);
|
|
3023
|
-
return /* @__PURE__ */
|
|
3279
|
+
return /* @__PURE__ */ jsx4(ViewerControlsContext.Provider, { value: proxy, children: /* @__PURE__ */ jsx4(SectionStoreContext.Provider, { value: sectionStore, children: /* @__PURE__ */ jsx4(
|
|
3024
3280
|
"div",
|
|
3025
3281
|
{
|
|
3026
3282
|
className: ["viewer-root", className].filter(Boolean).join(" "),
|
|
@@ -3030,7 +3286,7 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
3030
3286
|
if (event.target instanceof HTMLCanvasElement) event.preventDefault();
|
|
3031
3287
|
},
|
|
3032
3288
|
style: { height: "100%", width: "100%", ...style },
|
|
3033
|
-
children: /* @__PURE__ */
|
|
3289
|
+
children: webglAvailable ? /* @__PURE__ */ jsx4(
|
|
3034
3290
|
Canvas,
|
|
3035
3291
|
{
|
|
3036
3292
|
className: "viewer-canvas-container",
|
|
@@ -3051,7 +3307,7 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
3051
3307
|
if (event.button !== 0) return;
|
|
3052
3308
|
if (tracker.current?.isTap(event) ?? true) onPointerMissed?.();
|
|
3053
3309
|
},
|
|
3054
|
-
children: /* @__PURE__ */
|
|
3310
|
+
children: /* @__PURE__ */ jsx4(
|
|
3055
3311
|
ViewerScene,
|
|
3056
3312
|
{
|
|
3057
3313
|
setControls,
|
|
@@ -3068,7 +3324,7 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
3068
3324
|
)
|
|
3069
3325
|
},
|
|
3070
3326
|
projection
|
|
3071
|
-
)
|
|
3327
|
+
) : /* @__PURE__ */ jsx4(WebGLUnavailable, { children: webglUnavailable })
|
|
3072
3328
|
}
|
|
3073
3329
|
) }) });
|
|
3074
3330
|
});
|
|
@@ -3087,7 +3343,7 @@ import {
|
|
|
3087
3343
|
Raycaster as Raycaster2,
|
|
3088
3344
|
Scene,
|
|
3089
3345
|
Vector2 as Vector26,
|
|
3090
|
-
Vector3 as
|
|
3346
|
+
Vector3 as Vector312
|
|
3091
3347
|
} from "three";
|
|
3092
3348
|
|
|
3093
3349
|
// src/arrow-mesh.tsx
|
|
@@ -3178,7 +3434,7 @@ function createDepthResetMaterial() {
|
|
|
3178
3434
|
}
|
|
3179
3435
|
|
|
3180
3436
|
// src/arrow-mesh.tsx
|
|
3181
|
-
import { Fragment, jsx as
|
|
3437
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
3182
3438
|
var ArrowMesh = ({ geometry, color, opacity, onTop = false, events }) => {
|
|
3183
3439
|
const invalidate = useThree5((state) => state.invalidate);
|
|
3184
3440
|
const material = useMemo5(() => createArrowMaterial(), []);
|
|
@@ -3191,16 +3447,16 @@ var ArrowMesh = ({ geometry, color, opacity, onTop = false, events }) => {
|
|
|
3191
3447
|
applyArrowColor(material, color, opacity);
|
|
3192
3448
|
invalidate();
|
|
3193
3449
|
}, [color, invalidate, material, opacity]);
|
|
3194
|
-
return /* @__PURE__ */
|
|
3195
|
-
reset ? /* @__PURE__ */
|
|
3196
|
-
/* @__PURE__ */
|
|
3197
|
-
/* @__PURE__ */
|
|
3450
|
+
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3451
|
+
reset ? /* @__PURE__ */ jsx5("mesh", { geometry, material: reset, renderOrder: 0, raycast: () => null }) : null,
|
|
3452
|
+
/* @__PURE__ */ jsx5("mesh", { geometry, material: depth, renderOrder: 1, raycast: () => null }),
|
|
3453
|
+
/* @__PURE__ */ jsx5("mesh", { geometry, material, renderOrder: 2, ...events })
|
|
3198
3454
|
] });
|
|
3199
3455
|
};
|
|
3200
3456
|
|
|
3201
3457
|
// src/render/arrow.ts
|
|
3202
|
-
import { LatheGeometry, Vector2 as Vector24, Vector3 as
|
|
3203
|
-
var ARROW_AXIS2 = new
|
|
3458
|
+
import { LatheGeometry, Vector2 as Vector24, Vector3 as Vector311 } from "three";
|
|
3459
|
+
var ARROW_AXIS2 = new Vector311(0, 1, 0);
|
|
3204
3460
|
var ARROW_ROUND = 32;
|
|
3205
3461
|
var HEAD_LENGTH = 0.415;
|
|
3206
3462
|
var HEAD_RADIUS = 0.153;
|
|
@@ -3426,12 +3682,12 @@ function createMaskMaterial() {
|
|
|
3426
3682
|
}
|
|
3427
3683
|
|
|
3428
3684
|
// src/section-view.tsx
|
|
3429
|
-
import { Fragment as
|
|
3685
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3430
3686
|
var FURNITURE2 = { [EXCLUDE_FROM_FRAME]: true };
|
|
3431
3687
|
function resolveSectionPlane(options, box) {
|
|
3432
3688
|
if (!options?.enabled || box.isEmpty()) return null;
|
|
3433
3689
|
const normal = options.plane?.normal ?? options.normal ?? DEFAULT_SECTION_NORMAL;
|
|
3434
|
-
const axis = new
|
|
3690
|
+
const axis = new Vector312(normal.x, normal.y, normal.z);
|
|
3435
3691
|
if (axis.lengthSq() === 0) axis.set(0, 0, 1);
|
|
3436
3692
|
axis.normalize();
|
|
3437
3693
|
const bounds = sectionBounds(box, normal);
|
|
@@ -3452,7 +3708,7 @@ function resolveSectionPlane(options, box) {
|
|
|
3452
3708
|
}
|
|
3453
3709
|
};
|
|
3454
3710
|
}
|
|
3455
|
-
var Z = new
|
|
3711
|
+
var Z = new Vector312(0, 0, 1);
|
|
3456
3712
|
var SectionView = ({
|
|
3457
3713
|
geometry,
|
|
3458
3714
|
box,
|
|
@@ -3472,7 +3728,7 @@ var SectionView = ({
|
|
|
3472
3728
|
const handleRef = useRef4(null);
|
|
3473
3729
|
const [hovered, setHovered] = useState(false);
|
|
3474
3730
|
const dragging = useRef4(null);
|
|
3475
|
-
const span = useMemo6(() => box.getSize(new
|
|
3731
|
+
const span = useMemo6(() => box.getSize(new Vector312()).length(), [box]);
|
|
3476
3732
|
const frameSize = span * SECTION_GIZMO_FRAME_SCALE;
|
|
3477
3733
|
const directionColor2 = useMemo6(() => sectionDirectionColor(plane.normal), [plane]);
|
|
3478
3734
|
const resolvedHandleColor = sectionHandleColor(handleColor, directionColor2);
|
|
@@ -3556,7 +3812,7 @@ var SectionView = ({
|
|
|
3556
3812
|
event.stopPropagation();
|
|
3557
3813
|
const view = camera.position.clone().sub(capPosition).normalize();
|
|
3558
3814
|
const surface = dragPlane(plane.normal.clone(), view, capPosition);
|
|
3559
|
-
const hit = event.ray.intersectPlane(surface, new
|
|
3815
|
+
const hit = event.ray.intersectPlane(surface, new Vector312());
|
|
3560
3816
|
const start = {
|
|
3561
3817
|
plane: surface,
|
|
3562
3818
|
from: hit ? hit.dot(plane.normal) : 0,
|
|
@@ -3573,7 +3829,7 @@ var SectionView = ({
|
|
|
3573
3829
|
-((native.clientY - rect.top) / rect.height) * 2 + 1
|
|
3574
3830
|
);
|
|
3575
3831
|
raycaster.setFromCamera(pointer, camera);
|
|
3576
|
-
const point = raycaster.ray.intersectPlane(start.plane, new
|
|
3832
|
+
const point = raycaster.ray.intersectPlane(start.plane, new Vector312());
|
|
3577
3833
|
if (!point) return;
|
|
3578
3834
|
onDrag(start.constant - (point.dot(plane.normal) - start.from));
|
|
3579
3835
|
invalidate();
|
|
@@ -3605,8 +3861,8 @@ var SectionView = ({
|
|
|
3605
3861
|
// Excluded from framing, all of it. The cap is a quad half again as wide as
|
|
3606
3862
|
// the part's diagonal, so a Fit that measured it would frame the cut rather
|
|
3607
3863
|
// than the part and leave the part a speck in the middle of it.
|
|
3608
|
-
/* @__PURE__ */
|
|
3609
|
-
/* @__PURE__ */
|
|
3864
|
+
/* @__PURE__ */ jsxs5("group", { userData: FURNITURE2, children: [
|
|
3865
|
+
/* @__PURE__ */ jsx6(
|
|
3610
3866
|
"mesh",
|
|
3611
3867
|
{
|
|
3612
3868
|
geometry,
|
|
@@ -3615,7 +3871,7 @@ var SectionView = ({
|
|
|
3615
3871
|
raycast: () => null
|
|
3616
3872
|
}
|
|
3617
3873
|
),
|
|
3618
|
-
/* @__PURE__ */
|
|
3874
|
+
/* @__PURE__ */ jsx6(
|
|
3619
3875
|
"mesh",
|
|
3620
3876
|
{
|
|
3621
3877
|
geometry,
|
|
@@ -3624,7 +3880,7 @@ var SectionView = ({
|
|
|
3624
3880
|
raycast: () => null
|
|
3625
3881
|
}
|
|
3626
3882
|
),
|
|
3627
|
-
/* @__PURE__ */
|
|
3883
|
+
/* @__PURE__ */ jsx6(
|
|
3628
3884
|
"mesh",
|
|
3629
3885
|
{
|
|
3630
3886
|
geometry: quad,
|
|
@@ -3635,15 +3891,15 @@ var SectionView = ({
|
|
|
3635
3891
|
raycast: () => null
|
|
3636
3892
|
}
|
|
3637
3893
|
),
|
|
3638
|
-
showHandle && onDrag ? /* @__PURE__ */
|
|
3639
|
-
/* @__PURE__ */
|
|
3894
|
+
showHandle && onDrag ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3895
|
+
/* @__PURE__ */ jsxs5(
|
|
3640
3896
|
"group",
|
|
3641
3897
|
{
|
|
3642
3898
|
position: capPosition,
|
|
3643
3899
|
quaternion: capQuaternion,
|
|
3644
3900
|
renderOrder: SECTION_RENDER_ORDER.outline,
|
|
3645
3901
|
children: [
|
|
3646
|
-
/* @__PURE__ */
|
|
3902
|
+
/* @__PURE__ */ jsx6("mesh", { geometry: frameSurface, raycast: () => null, children: /* @__PURE__ */ jsx6(
|
|
3647
3903
|
"meshBasicMaterial",
|
|
3648
3904
|
{
|
|
3649
3905
|
color: directionColor2,
|
|
@@ -3654,18 +3910,18 @@ var SectionView = ({
|
|
|
3654
3910
|
depthWrite: false
|
|
3655
3911
|
}
|
|
3656
3912
|
) }),
|
|
3657
|
-
/* @__PURE__ */
|
|
3913
|
+
/* @__PURE__ */ jsx6("lineSegments", { geometry: frameEdges, raycast: () => null, children: /* @__PURE__ */ jsx6("lineBasicMaterial", { color: directionColor2, depthTest: false, depthWrite: false }) })
|
|
3658
3914
|
]
|
|
3659
3915
|
}
|
|
3660
3916
|
),
|
|
3661
|
-
/* @__PURE__ */
|
|
3917
|
+
/* @__PURE__ */ jsx6(
|
|
3662
3918
|
"group",
|
|
3663
3919
|
{
|
|
3664
3920
|
ref: handleRef,
|
|
3665
3921
|
position: capPosition,
|
|
3666
3922
|
quaternion: handleQuaternion,
|
|
3667
3923
|
renderOrder: SECTION_RENDER_ORDER.handle,
|
|
3668
|
-
children: /* @__PURE__ */
|
|
3924
|
+
children: /* @__PURE__ */ jsx6(
|
|
3669
3925
|
ArrowMesh,
|
|
3670
3926
|
{
|
|
3671
3927
|
geometry: handleShape,
|
|
@@ -3702,7 +3958,7 @@ function useContentBox() {
|
|
|
3702
3958
|
}
|
|
3703
3959
|
|
|
3704
3960
|
// src/part-mesh.tsx
|
|
3705
|
-
import { Fragment as
|
|
3961
|
+
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3706
3962
|
var PartMesh = ({
|
|
3707
3963
|
model,
|
|
3708
3964
|
geometry,
|
|
@@ -3724,6 +3980,7 @@ var PartMesh = ({
|
|
|
3724
3980
|
theme,
|
|
3725
3981
|
showEdges = true,
|
|
3726
3982
|
sharpCorners = null,
|
|
3983
|
+
threads = null,
|
|
3727
3984
|
display = "solid",
|
|
3728
3985
|
children
|
|
3729
3986
|
}) => {
|
|
@@ -3740,11 +3997,11 @@ var PartMesh = ({
|
|
|
3740
3997
|
onHoverRef.current = onHover;
|
|
3741
3998
|
const box = useContentBox();
|
|
3742
3999
|
const store = useSectionStore();
|
|
3743
|
-
const shared =
|
|
4000
|
+
const shared = useSyncExternalStore2(store.subscribe, store.get, store.get);
|
|
3744
4001
|
const controlled = section !== void 0;
|
|
3745
4002
|
const options = controlled ? section : shared ?? void 0;
|
|
3746
4003
|
const cut = useMemo7(() => resolveSectionPlane(options, box), [box, options]);
|
|
3747
|
-
const engaged =
|
|
4004
|
+
const engaged = useSyncExternalStore2(store.subscribe, store.isEngaged, store.isEngaged);
|
|
3748
4005
|
const pressedWhileEngaged = useRef6(false);
|
|
3749
4006
|
const layers = useRef6({
|
|
3750
4007
|
selection,
|
|
@@ -3825,6 +4082,13 @@ var PartMesh = ({
|
|
|
3825
4082
|
if (hoverCorner.current !== null) dropHover();
|
|
3826
4083
|
invalidate();
|
|
3827
4084
|
}, [dropHover, invalidate, part, sharpKey]);
|
|
4085
|
+
const threadsRef = useRef6(threads);
|
|
4086
|
+
threadsRef.current = threads;
|
|
4087
|
+
const threadsKey = threadKey(threads);
|
|
4088
|
+
useLayoutEffect3(() => {
|
|
4089
|
+
part.setThreads(threadsRef.current);
|
|
4090
|
+
invalidate();
|
|
4091
|
+
}, [invalidate, part, threadsKey]);
|
|
3828
4092
|
const reportedSection = useRef6("");
|
|
3829
4093
|
useLayoutEffect3(() => {
|
|
3830
4094
|
const state = cut?.state ?? null;
|
|
@@ -3914,8 +4178,8 @@ var PartMesh = ({
|
|
|
3914
4178
|
},
|
|
3915
4179
|
[box, controlled, cut, onSectionChange, options, store]
|
|
3916
4180
|
);
|
|
3917
|
-
return /* @__PURE__ */
|
|
3918
|
-
/* @__PURE__ */
|
|
4181
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
4182
|
+
/* @__PURE__ */ jsx7(
|
|
3919
4183
|
"primitive",
|
|
3920
4184
|
{
|
|
3921
4185
|
object: part.object,
|
|
@@ -3952,7 +4216,7 @@ var PartMesh = ({
|
|
|
3952
4216
|
}
|
|
3953
4217
|
}
|
|
3954
4218
|
),
|
|
3955
|
-
cut ? /* @__PURE__ */
|
|
4219
|
+
cut ? /* @__PURE__ */ jsx7(
|
|
3956
4220
|
SectionView,
|
|
3957
4221
|
{
|
|
3958
4222
|
geometry,
|
|
@@ -3964,12 +4228,12 @@ var PartMesh = ({
|
|
|
3964
4228
|
onDrag: !controlled || onSectionChange ? dragSection : void 0
|
|
3965
4229
|
}
|
|
3966
4230
|
) : null,
|
|
3967
|
-
children ? /* @__PURE__ */
|
|
4231
|
+
children ? /* @__PURE__ */ jsx7(PartContext.Provider, { value: context, children }) : null
|
|
3968
4232
|
] });
|
|
3969
4233
|
};
|
|
3970
|
-
var ORIGIN = new
|
|
3971
|
-
var UP = new
|
|
3972
|
-
var TARGET = new
|
|
4234
|
+
var ORIGIN = new Vector313();
|
|
4235
|
+
var UP = new Vector313(0, 0, 1);
|
|
4236
|
+
var TARGET = new Vector313();
|
|
3973
4237
|
function readTarget(controls) {
|
|
3974
4238
|
if (controls && typeof controls.getTarget === "function") {
|
|
3975
4239
|
return controls.getTarget(TARGET);
|
|
@@ -4618,7 +4882,7 @@ function compareVersions(a, b) {
|
|
|
4618
4882
|
}
|
|
4619
4883
|
|
|
4620
4884
|
// src/engine/engine-part.tsx
|
|
4621
|
-
import { jsx as
|
|
4885
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
4622
4886
|
var models = /* @__PURE__ */ new WeakMap();
|
|
4623
4887
|
var modelForReport = (report) => {
|
|
4624
4888
|
if (typeof report !== "object" || report === null) {
|
|
@@ -4639,7 +4903,7 @@ var EnginePart = ({ report, ...props }) => {
|
|
|
4639
4903
|
engineGeometryCache.retain(resource);
|
|
4640
4904
|
return () => engineGeometryCache.release(resource);
|
|
4641
4905
|
}, [resource]);
|
|
4642
|
-
return /* @__PURE__ */
|
|
4906
|
+
return /* @__PURE__ */ jsx8(PartMesh, { model, geometry: resource.geometry, ...props });
|
|
4643
4907
|
};
|
|
4644
4908
|
function useGeometryResource(part) {
|
|
4645
4909
|
const resource = engineGeometryCache.get(part);
|
|
@@ -4648,6 +4912,23 @@ function useGeometryResource(part) {
|
|
|
4648
4912
|
return resource;
|
|
4649
4913
|
}
|
|
4650
4914
|
|
|
4915
|
+
// src/engine/threads.ts
|
|
4916
|
+
function threadMark(feature, datasheet) {
|
|
4917
|
+
if (!isRecord(datasheet) || !isRecord(datasheet["facts"])) return null;
|
|
4918
|
+
const facts = datasheet["facts"];
|
|
4919
|
+
if (facts["kind"] !== "Hole" || !isRecord(facts["threading"])) return null;
|
|
4920
|
+
const spec = facts["threading"]["spec"];
|
|
4921
|
+
if (!isRecord(spec)) return null;
|
|
4922
|
+
const pitch = spec["threadPitch"];
|
|
4923
|
+
const majorDiameter = spec["basicDiameter"];
|
|
4924
|
+
if (!isFiniteNumber(pitch) || pitch <= 0 || !isFiniteNumber(majorDiameter)) return null;
|
|
4925
|
+
return {
|
|
4926
|
+
regions: feature.regionIdxs,
|
|
4927
|
+
pitch: spec["handedness"] === "Left" ? -pitch : pitch,
|
|
4928
|
+
majorDiameter
|
|
4929
|
+
};
|
|
4930
|
+
}
|
|
4931
|
+
|
|
4651
4932
|
export {
|
|
4652
4933
|
usePartContext,
|
|
4653
4934
|
sameDirection,
|
|
@@ -4762,6 +5043,7 @@ export {
|
|
|
4762
5043
|
bestOwner,
|
|
4763
5044
|
cycleOwner,
|
|
4764
5045
|
NO_MODIFIERS,
|
|
5046
|
+
ignoreRay,
|
|
4765
5047
|
viewDirection,
|
|
4766
5048
|
buildPick,
|
|
4767
5049
|
focusForPick,
|
|
@@ -4822,5 +5104,6 @@ export {
|
|
|
4822
5104
|
MIN_KERNEL_VERSION,
|
|
4823
5105
|
normalizePartReport,
|
|
4824
5106
|
assertSupportedKernelVersion,
|
|
4825
|
-
EnginePart
|
|
5107
|
+
EnginePart,
|
|
5108
|
+
threadMark
|
|
4826
5109
|
};
|