@toolpath/viewer 1.3.0 → 1.4.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 +3 -0
- package/dist/{chunk-HWAEUJ4H.js → chunk-HH3W5T42.js} +17 -7
- package/dist/engine/index.js +1 -1
- package/dist/index.d.ts +20 -3
- package/dist/index.js +24 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -600,6 +600,9 @@ to, the part's edges stop at the plane, the outline where the plane passes throu
|
|
|
600
600
|
is an edge with corners of its own, and the capped face is a surface a point can land on. The
|
|
601
601
|
sample follows the cut — drag the handle or set a depth and the next pointer move sees the new cut.
|
|
602
602
|
It reads the plane off the part's own material, so a controlled `section` prop works the same way.
|
|
603
|
+
Beside a `<SectionTool>` that has no cut yet, the measure tool waits: it offers no snap and places
|
|
604
|
+
no point until a cut is chosen or the section tool is unmounted, so the click that picks the cut is
|
|
605
|
+
not also the first point of a measurement. Measurements already made stay up meanwhile.
|
|
603
606
|
|
|
604
607
|
Hold Shift to hold the next point to the X, Y or Z line through the last one — whichever axis the
|
|
605
608
|
pointer is furthest along — so a length along an edge is measured square rather than slightly across
|
|
@@ -1328,11 +1328,12 @@ function retargetPose(cameraPosition, currentTarget, hitPoint) {
|
|
|
1328
1328
|
// src/render/section-store.ts
|
|
1329
1329
|
function createSectionStore() {
|
|
1330
1330
|
let current = null;
|
|
1331
|
-
let engaged = 0;
|
|
1332
1331
|
const listeners = /* @__PURE__ */ new Set();
|
|
1333
1332
|
const notify = () => {
|
|
1334
1333
|
for (const listener of listeners) listener();
|
|
1335
1334
|
};
|
|
1335
|
+
const engaged = counted(notify);
|
|
1336
|
+
const picking = counted(notify);
|
|
1336
1337
|
return {
|
|
1337
1338
|
get: () => current,
|
|
1338
1339
|
set: (next) => {
|
|
@@ -1340,12 +1341,10 @@ function createSectionStore() {
|
|
|
1340
1341
|
current = next;
|
|
1341
1342
|
notify();
|
|
1342
1343
|
},
|
|
1343
|
-
isEngaged:
|
|
1344
|
-
setEngaged:
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
if (engaged > 0 !== was) notify();
|
|
1348
|
-
},
|
|
1344
|
+
isEngaged: engaged.is,
|
|
1345
|
+
setEngaged: engaged.set,
|
|
1346
|
+
isPicking: picking.is,
|
|
1347
|
+
setPicking: picking.set,
|
|
1349
1348
|
subscribe: (listener) => {
|
|
1350
1349
|
listeners.add(listener);
|
|
1351
1350
|
return () => {
|
|
@@ -1354,6 +1353,17 @@ function createSectionStore() {
|
|
|
1354
1353
|
}
|
|
1355
1354
|
};
|
|
1356
1355
|
}
|
|
1356
|
+
function counted(notify) {
|
|
1357
|
+
let held = 0;
|
|
1358
|
+
return {
|
|
1359
|
+
is: () => held > 0,
|
|
1360
|
+
set: (next) => {
|
|
1361
|
+
const was = held > 0;
|
|
1362
|
+
held = Math.max(0, held + (next ? 1 : -1));
|
|
1363
|
+
if (held > 0 !== was) notify();
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1357
1367
|
|
|
1358
1368
|
// src/target-marker.tsx
|
|
1359
1369
|
import { useFrame as useFrame2, useThree as useThree3 } from "@react-three/fiber";
|
package/dist/engine/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -245,7 +245,9 @@ interface SectionToolProps {
|
|
|
245
245
|
* the way to set or clear it from outside the canvas. While this is mounted
|
|
246
246
|
* the part reports no hovers or picks: a click on a face cuts through it
|
|
247
247
|
* without also selecting it, and a cut part is looked at rather than picked
|
|
248
|
-
* at. Unmounting it hands the pointer back.
|
|
248
|
+
* at. Unmounting it hands the pointer back. While it is offering a cut — up,
|
|
249
|
+
* with none placed yet — a `<MeasureTool>` beside it waits too, so the click
|
|
250
|
+
* that chooses the cut does not also place a measurement point.
|
|
249
251
|
*/
|
|
250
252
|
declare const SectionTool: ({ theme }: SectionToolProps) => react.JSX.Element | null;
|
|
251
253
|
|
|
@@ -687,7 +689,12 @@ interface MeasureToolProps {
|
|
|
687
689
|
*
|
|
688
690
|
* Nothing needs wiring. While it is mounted the part reports no hovers or
|
|
689
691
|
* picks — a click that places a point is not a click that selects a face — and
|
|
690
|
-
* unmounting it hands the pointer back.
|
|
692
|
+
* unmounting it hands the pointer back. Beside a `<SectionTool>` that has no
|
|
693
|
+
* cut yet it waits: no snap is offered and no click places a point until the
|
|
694
|
+
* cut is chosen or the section tool is unmounted, and the click that chooses
|
|
695
|
+
* the cut — the one it wakes on — places nothing either: a click counts only
|
|
696
|
+
* when it was pressed as well as released while the tool was taking points.
|
|
697
|
+
* Measurements already made stay up meanwhile. It snaps to the edges the part draws,
|
|
691
698
|
* which are the boundaries between analytic surfaces rather than the mesh's
|
|
692
699
|
* triangles, so a corner is a corner of the part and not of a facet.
|
|
693
700
|
*
|
|
@@ -723,6 +730,12 @@ declare const MeasureTool: ({ mode, measurements, onChange, showDeltas, format,
|
|
|
723
730
|
* on a face is not a request to select the face — which is why the flag is a
|
|
724
731
|
* count rather than a boolean: two tools up at once let go one at a time.
|
|
725
732
|
*
|
|
733
|
+
* And whether a tool is **picking** — `<SectionTool>` is up with no cut in
|
|
734
|
+
* place, so the next click on the part chooses where the cut goes. That click
|
|
735
|
+
* is the section tool's alone: `<MeasureTool>` beside it offers no snap and
|
|
736
|
+
* places no point until the cut is chosen or the section tool is unmounted.
|
|
737
|
+
* Counted for the same reason as `engaged`.
|
|
738
|
+
*
|
|
726
739
|
* A subscription rather than React state, so a drag re-renders the two
|
|
727
740
|
* subscribers and not everything under the canvas.
|
|
728
741
|
*/
|
|
@@ -733,7 +746,11 @@ interface SectionStore {
|
|
|
733
746
|
isEngaged(): boolean;
|
|
734
747
|
/** Counted: a tool engages on mount and disengages on unmount, and the part waits for the last. */
|
|
735
748
|
setEngaged(engaged: boolean): void;
|
|
736
|
-
/**
|
|
749
|
+
/** Whether a section tool is waiting for a click to say where the cut goes. */
|
|
750
|
+
isPicking(): boolean;
|
|
751
|
+
/** Counted, as `setEngaged` is: raised while a section tool offers a cut, dropped once one is placed. */
|
|
752
|
+
setPicking(picking: boolean): void;
|
|
753
|
+
/** Notified on every change to the cut, the engaged flag, or the picking flag. */
|
|
737
754
|
subscribe(listener: () => void): () => void;
|
|
738
755
|
}
|
|
739
756
|
declare function createSectionStore(): SectionStore;
|
package/dist/index.js
CHANGED
|
@@ -131,7 +131,7 @@ import {
|
|
|
131
131
|
viewUp,
|
|
132
132
|
viewVector,
|
|
133
133
|
visualSurfaces
|
|
134
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-HH3W5T42.js";
|
|
135
135
|
|
|
136
136
|
// src/primitives.tsx
|
|
137
137
|
import { GizmoHelper } from "@react-three/drei";
|
|
@@ -644,6 +644,10 @@ var Picker = ({ box, theme }) => {
|
|
|
644
644
|
const span = useMemo3(() => box.getSize(new Vector34()).length(), [box]);
|
|
645
645
|
const centre = useMemo3(() => box.getCenter(new Vector34()), [box]);
|
|
646
646
|
const previewSize = span * PREVIEW_SCALE;
|
|
647
|
+
useEffect2(() => {
|
|
648
|
+
store.setPicking(true);
|
|
649
|
+
return () => store.setPicking(false);
|
|
650
|
+
}, [store]);
|
|
647
651
|
useEffect2(() => {
|
|
648
652
|
const raycaster = new Raycaster();
|
|
649
653
|
const pointer = new Vector22();
|
|
@@ -840,7 +844,14 @@ var CutSheet = ({ box, section, theme }) => {
|
|
|
840
844
|
// src/measure-tool.tsx
|
|
841
845
|
import { Html, Line } from "@react-three/drei";
|
|
842
846
|
import { useFrame as useFrame2, useThree as useThree4 } from "@react-three/fiber";
|
|
843
|
-
import {
|
|
847
|
+
import {
|
|
848
|
+
useEffect as useEffect3,
|
|
849
|
+
useLayoutEffect,
|
|
850
|
+
useMemo as useMemo4,
|
|
851
|
+
useRef as useRef3,
|
|
852
|
+
useState as useState3,
|
|
853
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
854
|
+
} from "react";
|
|
844
855
|
import {
|
|
845
856
|
Matrix4,
|
|
846
857
|
Raycaster as Raycaster2,
|
|
@@ -1036,6 +1047,7 @@ var MeasureTool = ({
|
|
|
1036
1047
|
const store = useSectionStore();
|
|
1037
1048
|
const box = useContentBox();
|
|
1038
1049
|
const resolved = useMemo4(() => resolveTheme(theme), [theme]);
|
|
1050
|
+
const picking = useSyncExternalStore2(store.subscribe, store.isPicking, store.isPicking);
|
|
1039
1051
|
const [held, setHeld] = useState3([]);
|
|
1040
1052
|
const controlled = measurements !== void 0;
|
|
1041
1053
|
const list = controlled ? measurements : held;
|
|
@@ -1082,7 +1094,7 @@ var MeasureTool = ({
|
|
|
1082
1094
|
if (box.isEmpty()) return null;
|
|
1083
1095
|
const label = className(labelClassName);
|
|
1084
1096
|
return /* @__PURE__ */ jsxs4("group", { userData: FURNITURE4, children: [
|
|
1085
|
-
/* @__PURE__ */ jsx4(
|
|
1097
|
+
picking ? null : /* @__PURE__ */ jsx4(
|
|
1086
1098
|
Snapper,
|
|
1087
1099
|
{
|
|
1088
1100
|
mode,
|
|
@@ -1212,8 +1224,14 @@ var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
|
1212
1224
|
if (event.key !== "Shift" || !last || !snap.current) return;
|
|
1213
1225
|
update(last.x, last.y, event.type === "keydown");
|
|
1214
1226
|
};
|
|
1227
|
+
let pressed = false;
|
|
1228
|
+
const down = () => {
|
|
1229
|
+
pressed = true;
|
|
1230
|
+
};
|
|
1215
1231
|
const up = (event) => {
|
|
1216
|
-
|
|
1232
|
+
const seen = pressed;
|
|
1233
|
+
pressed = false;
|
|
1234
|
+
if (!seen || event.button !== 0 || !isTap(event)) return;
|
|
1217
1235
|
update(event.clientX, event.clientY, event.shiftKey);
|
|
1218
1236
|
const found = snap.current;
|
|
1219
1237
|
if (!found) return;
|
|
@@ -1225,12 +1243,14 @@ var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
|
1225
1243
|
};
|
|
1226
1244
|
domElement.addEventListener("pointermove", move);
|
|
1227
1245
|
domElement.addEventListener("pointerleave", leave);
|
|
1246
|
+
domElement.addEventListener("pointerdown", down);
|
|
1228
1247
|
domElement.addEventListener("pointerup", up);
|
|
1229
1248
|
window.addEventListener("keydown", key);
|
|
1230
1249
|
window.addEventListener("keyup", key);
|
|
1231
1250
|
return () => {
|
|
1232
1251
|
domElement.removeEventListener("pointermove", move);
|
|
1233
1252
|
domElement.removeEventListener("pointerleave", leave);
|
|
1253
|
+
domElement.removeEventListener("pointerdown", down);
|
|
1234
1254
|
domElement.removeEventListener("pointerup", up);
|
|
1235
1255
|
window.removeEventListener("keydown", key);
|
|
1236
1256
|
window.removeEventListener("keyup", key);
|