@toolpath/viewer 2.1.0 → 2.2.1
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 +2 -2
- package/dist/{chunk-WTTOUG4P.js → chunk-7S6SIYHL.js} +300 -165
- package/dist/engine/index.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +119 -81
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -357,9 +357,9 @@ individual buttons to use only the controls and order your application needs.
|
|
|
357
357
|
</ViewerToolbarProvider>
|
|
358
358
|
```
|
|
359
359
|
|
|
360
|
-
`ViewerToolbar.Controls`, `Divider`, and the
|
|
360
|
+
`ViewerToolbar.Controls`, `Divider`, and the fifteen `*Button` components are available on
|
|
361
361
|
`ViewerToolbar`: `StockButton`, `AxesButton`, `GridButton`, `BananaButton`, `ToolsButton`, `DirectionsButton`,
|
|
362
|
-
`HoverButton`, `FocusButton`, `WireframeButton`, `SectionButton`, `MeasureButton`, `FitButton`,
|
|
362
|
+
`DfmButton` (shows or hides an application's DFM flags), `HoverButton`, `FocusButton`, `WireframeButton`, `SectionButton`, `MeasureButton`, `FitButton`,
|
|
363
363
|
`ResetButton`, and `TopButton`. A rendered button requires its matching provider control. For an
|
|
364
364
|
application-specific toolbar component, `useViewerToolbar()` reads the same controls from inside
|
|
365
365
|
the provider.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// src/engine/engine-part.tsx
|
|
2
|
-
import { useEffect as
|
|
2
|
+
import { useEffect as useEffect8, useMemo as useMemo8 } from "react";
|
|
3
3
|
|
|
4
4
|
// src/part-mesh.tsx
|
|
5
|
-
import { useThree as
|
|
5
|
+
import { useThree as useThree8 } from "@react-three/fiber";
|
|
6
6
|
import {
|
|
7
7
|
useCallback as useCallback3,
|
|
8
|
-
useEffect as
|
|
9
|
-
useLayoutEffect as
|
|
10
|
-
useMemo as
|
|
8
|
+
useEffect as useEffect7,
|
|
9
|
+
useLayoutEffect as useLayoutEffect3,
|
|
10
|
+
useMemo as useMemo7,
|
|
11
11
|
useRef as useRef6,
|
|
12
12
|
useSyncExternalStore
|
|
13
13
|
} from "react";
|
|
@@ -2526,10 +2526,10 @@ var Viewer = forwardRef(function Viewer2({
|
|
|
2526
2526
|
});
|
|
2527
2527
|
|
|
2528
2528
|
// src/section-view.tsx
|
|
2529
|
-
import { useFrame as useFrame4, useThree as
|
|
2530
|
-
import { useCallback as useCallback2, useEffect as
|
|
2529
|
+
import { useFrame as useFrame4, useThree as useThree6 } from "@react-three/fiber";
|
|
2530
|
+
import { useCallback as useCallback2, useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useMemo as useMemo6, useRef as useRef4, useState } from "react";
|
|
2531
2531
|
import {
|
|
2532
|
-
Color as
|
|
2532
|
+
Color as Color4,
|
|
2533
2533
|
DoubleSide as DoubleSide4,
|
|
2534
2534
|
EdgesGeometry,
|
|
2535
2535
|
Mesh as Mesh3,
|
|
@@ -2538,42 +2538,209 @@ import {
|
|
|
2538
2538
|
Quaternion as Quaternion2,
|
|
2539
2539
|
Raycaster as Raycaster2,
|
|
2540
2540
|
Scene,
|
|
2541
|
-
Vector2 as
|
|
2541
|
+
Vector2 as Vector25,
|
|
2542
2542
|
Vector3 as Vector310
|
|
2543
2543
|
} from "three";
|
|
2544
2544
|
|
|
2545
|
-
// src/
|
|
2546
|
-
import {
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
var
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2545
|
+
// src/arrow-mesh.tsx
|
|
2546
|
+
import { useThree as useThree5 } from "@react-three/fiber";
|
|
2547
|
+
import { useEffect as useEffect5, useLayoutEffect, useMemo as useMemo5 } from "react";
|
|
2548
|
+
|
|
2549
|
+
// src/render/arrow-material.ts
|
|
2550
|
+
import { AlwaysDepth, Color as Color2, ShaderMaterial } from "three";
|
|
2551
|
+
var VERTEX = (
|
|
2552
|
+
/* glsl */
|
|
2553
|
+
`
|
|
2554
|
+
varying vec3 vNormal;
|
|
2555
|
+
|
|
2556
|
+
void main() {
|
|
2557
|
+
vNormal = normalize(normalMatrix * normal);
|
|
2558
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
2559
|
+
}
|
|
2560
|
+
`
|
|
2561
|
+
);
|
|
2562
|
+
var FRAGMENT = (
|
|
2563
|
+
/* glsl */
|
|
2564
|
+
`
|
|
2565
|
+
uniform vec3 uColor;
|
|
2566
|
+
uniform float uOpacity;
|
|
2567
|
+
|
|
2568
|
+
varying vec3 vNormal;
|
|
2569
|
+
|
|
2570
|
+
// Above, to the left and toward the camera, in the camera's own frame.
|
|
2571
|
+
const vec3 KEY = vec3(-0.4, 0.6, 0.7);
|
|
2572
|
+
|
|
2573
|
+
void main() {
|
|
2574
|
+
// Wrapped, and over a narrow range: a quarter darker at most, so the shape
|
|
2575
|
+
// shows without the colour going anywhere.
|
|
2576
|
+
float light = mix(0.75, 1.0, 0.5 + 0.5 * dot(normalize(vNormal), normalize(KEY)));
|
|
2577
|
+
gl_FragColor = vec4(uColor * light, uOpacity);
|
|
2578
|
+
#include <tonemapping_fragment>
|
|
2579
|
+
#include <colorspace_fragment>
|
|
2580
|
+
}
|
|
2581
|
+
`
|
|
2582
|
+
);
|
|
2583
|
+
function createArrowMaterial() {
|
|
2584
|
+
const uniforms = {
|
|
2585
|
+
uColor: { value: new Color2() },
|
|
2586
|
+
uOpacity: { value: 1 }
|
|
2587
|
+
};
|
|
2588
|
+
return new ShaderMaterial({
|
|
2589
|
+
vertexShader: VERTEX,
|
|
2590
|
+
fragmentShader: FRAGMENT,
|
|
2591
|
+
uniforms,
|
|
2592
|
+
transparent: true
|
|
2593
|
+
});
|
|
2594
|
+
}
|
|
2595
|
+
function createArrowDepthMaterial() {
|
|
2596
|
+
const material = createArrowMaterial();
|
|
2597
|
+
material.colorWrite = false;
|
|
2598
|
+
return material;
|
|
2599
|
+
}
|
|
2600
|
+
function applyArrowColor(material, color, opacity) {
|
|
2601
|
+
material.uniforms.uColor.value.set(color);
|
|
2602
|
+
material.uniforms.uOpacity.value = opacity;
|
|
2603
|
+
}
|
|
2604
|
+
var RESET_VERTEX = (
|
|
2605
|
+
/* glsl */
|
|
2606
|
+
`
|
|
2607
|
+
void main() {
|
|
2608
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
2609
|
+
// On the far plane, so what it leaves in the depth buffer is "nothing here".
|
|
2610
|
+
gl_Position.z = gl_Position.w;
|
|
2611
|
+
}
|
|
2612
|
+
`
|
|
2613
|
+
);
|
|
2614
|
+
var RESET_FRAGMENT = (
|
|
2615
|
+
/* glsl */
|
|
2616
|
+
`
|
|
2617
|
+
void main() {
|
|
2618
|
+
gl_FragColor = vec4(0.0);
|
|
2619
|
+
}
|
|
2620
|
+
`
|
|
2621
|
+
);
|
|
2622
|
+
function createDepthResetMaterial() {
|
|
2623
|
+
return new ShaderMaterial({
|
|
2624
|
+
vertexShader: RESET_VERTEX,
|
|
2625
|
+
fragmentShader: RESET_FRAGMENT,
|
|
2626
|
+
transparent: true,
|
|
2627
|
+
colorWrite: false,
|
|
2628
|
+
depthFunc: AlwaysDepth
|
|
2629
|
+
});
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
// src/arrow-mesh.tsx
|
|
2633
|
+
import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2634
|
+
var ArrowMesh = ({ geometry, color, opacity, onTop = false, events }) => {
|
|
2635
|
+
const invalidate = useThree5((state) => state.invalidate);
|
|
2636
|
+
const material = useMemo5(() => createArrowMaterial(), []);
|
|
2637
|
+
useEffect5(() => () => material.dispose(), [material]);
|
|
2638
|
+
const depth = useMemo5(() => createArrowDepthMaterial(), []);
|
|
2639
|
+
useEffect5(() => () => depth.dispose(), [depth]);
|
|
2640
|
+
const reset = useMemo5(() => onTop ? createDepthResetMaterial() : null, [onTop]);
|
|
2641
|
+
useEffect5(() => () => reset?.dispose(), [reset]);
|
|
2642
|
+
useLayoutEffect(() => {
|
|
2643
|
+
applyArrowColor(material, color, opacity);
|
|
2644
|
+
invalidate();
|
|
2645
|
+
}, [color, invalidate, material, opacity]);
|
|
2646
|
+
return /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
2647
|
+
reset ? /* @__PURE__ */ jsx4("mesh", { geometry, material: reset, renderOrder: 0, raycast: () => null }) : null,
|
|
2648
|
+
/* @__PURE__ */ jsx4("mesh", { geometry, material: depth, renderOrder: 1, raycast: () => null }),
|
|
2649
|
+
/* @__PURE__ */ jsx4("mesh", { geometry, material, renderOrder: 2, ...events })
|
|
2650
|
+
] });
|
|
2651
|
+
};
|
|
2652
|
+
|
|
2653
|
+
// src/render/arrow.ts
|
|
2654
|
+
import { LatheGeometry, Vector2 as Vector23, Vector3 as Vector39 } from "three";
|
|
2655
|
+
var ARROW_AXIS2 = new Vector39(0, 1, 0);
|
|
2656
|
+
var ARROW_ROUND = 32;
|
|
2657
|
+
var HEAD_LENGTH = 0.415;
|
|
2658
|
+
var HEAD_RADIUS = 0.153;
|
|
2659
|
+
var SHAFT_RADIUS = 0.0515;
|
|
2660
|
+
var HANDLE_TIP = 0.76;
|
|
2661
|
+
var HANDLE_HEAD_LENGTH = 0.3;
|
|
2662
|
+
var HANDLE_HEAD_RADIUS = 0.14;
|
|
2663
|
+
var HANDLE_SHAFT_RADIUS = 0.035;
|
|
2664
|
+
var HANDLE_BEAD_RADIUS = 0.1;
|
|
2665
|
+
var RIM_ROUND = 6e-3;
|
|
2666
|
+
var NECK_ROUND = 8e-3;
|
|
2667
|
+
var BEAD_ROUND = 0.02;
|
|
2668
|
+
var ROUND_STEPS = 4;
|
|
2669
|
+
var CAP_STEPS = 6;
|
|
2670
|
+
var BEAD_STEPS = 12;
|
|
2671
|
+
var head = ({ length, radius, shaft }) => [
|
|
2672
|
+
{ at: new Vector23(0, 0) },
|
|
2673
|
+
{ at: new Vector23(radius, length), round: RIM_ROUND },
|
|
2674
|
+
{ at: new Vector23(shaft, length), round: NECK_ROUND }
|
|
2675
|
+
];
|
|
2676
|
+
var rounded = (corners) => corners.flatMap(({ at, round = 0 }, index) => {
|
|
2677
|
+
const before = corners[index - 1]?.at;
|
|
2678
|
+
const after = corners[index + 1]?.at;
|
|
2679
|
+
if (!(round > 0) || !before || !after) return [at];
|
|
2680
|
+
const back = before.clone().sub(at);
|
|
2681
|
+
const ahead = after.clone().sub(at);
|
|
2682
|
+
const reach = Math.min(back.length(), ahead.length()) / 2;
|
|
2683
|
+
back.normalize();
|
|
2684
|
+
ahead.normalize();
|
|
2685
|
+
const angle = Math.acos(Math.min(Math.max(back.dot(ahead), -1), 1));
|
|
2686
|
+
if (angle > Math.PI - 1e-6 || angle < 1e-6) return [at];
|
|
2687
|
+
const half = angle / 2;
|
|
2688
|
+
const offset = Math.min(round / Math.tan(half), reach);
|
|
2689
|
+
const radius = offset * Math.tan(half);
|
|
2690
|
+
const centre = at.clone().addScaledVector(back.clone().add(ahead).normalize(), radius / Math.sin(half));
|
|
2691
|
+
const from = at.clone().addScaledVector(back, offset).sub(centre);
|
|
2692
|
+
const to = at.clone().addScaledVector(ahead, offset).sub(centre);
|
|
2693
|
+
const start = Math.atan2(from.y, from.x);
|
|
2694
|
+
let sweep = Math.atan2(to.y, to.x) - start;
|
|
2695
|
+
if (sweep > Math.PI) sweep -= Math.PI * 2;
|
|
2696
|
+
if (sweep < -Math.PI) sweep += Math.PI * 2;
|
|
2697
|
+
return Array.from({ length: ROUND_STEPS + 1 }, (_, step) => {
|
|
2698
|
+
const turn = start + sweep * step / ROUND_STEPS;
|
|
2699
|
+
return new Vector23(centre.x + Math.cos(turn) * radius, centre.y + Math.sin(turn) * radius);
|
|
2700
|
+
});
|
|
2701
|
+
});
|
|
2702
|
+
function arrowProfile() {
|
|
2703
|
+
const body = rounded([
|
|
2704
|
+
...head({ length: HEAD_LENGTH, radius: HEAD_RADIUS, shaft: SHAFT_RADIUS }),
|
|
2705
|
+
{ at: new Vector23(SHAFT_RADIUS, 1 - SHAFT_RADIUS) }
|
|
2706
|
+
]);
|
|
2707
|
+
const tail = Array.from({ length: CAP_STEPS }, (_, step) => {
|
|
2708
|
+
const turn = (step + 1) / CAP_STEPS * (Math.PI / 2);
|
|
2709
|
+
return new Vector23(
|
|
2710
|
+
step + 1 === CAP_STEPS ? 0 : Math.cos(turn) * SHAFT_RADIUS,
|
|
2711
|
+
1 - SHAFT_RADIUS + Math.sin(turn) * SHAFT_RADIUS
|
|
2712
|
+
);
|
|
2713
|
+
});
|
|
2714
|
+
return [...body, ...tail];
|
|
2715
|
+
}
|
|
2716
|
+
function handleProfile() {
|
|
2717
|
+
const lower = head({
|
|
2718
|
+
length: HANDLE_HEAD_LENGTH,
|
|
2719
|
+
radius: HANDLE_HEAD_RADIUS,
|
|
2720
|
+
shaft: HANDLE_SHAFT_RADIUS
|
|
2721
|
+
}).map(({ at, round }) => ({ at: new Vector23(at.x, at.y - HANDLE_TIP), round }));
|
|
2722
|
+
const upper = lower.slice().reverse().map(({ at, round }) => ({ at: new Vector23(at.x, -at.y), round }));
|
|
2723
|
+
const meet = Math.acos(HANDLE_SHAFT_RADIUS / HANDLE_BEAD_RADIUS);
|
|
2724
|
+
const bead = Array.from({ length: BEAD_STEPS + 1 }, (_, step) => {
|
|
2725
|
+
const turn = -meet + 2 * meet * step / BEAD_STEPS;
|
|
2726
|
+
const at = new Vector23(Math.cos(turn), Math.sin(turn)).multiplyScalar(HANDLE_BEAD_RADIUS);
|
|
2727
|
+
return { at, round: step === 0 || step === BEAD_STEPS ? BEAD_ROUND : 0 };
|
|
2728
|
+
});
|
|
2729
|
+
return rounded([...lower, ...bead, ...upper]);
|
|
2570
2730
|
}
|
|
2731
|
+
var turned = (profile) => {
|
|
2732
|
+
const geometry = new LatheGeometry(profile, ARROW_ROUND);
|
|
2733
|
+
geometry.normalizeNormals();
|
|
2734
|
+
return geometry;
|
|
2735
|
+
};
|
|
2736
|
+
var arrowGeometry = () => turned(arrowProfile());
|
|
2737
|
+
var handleGeometry = () => turned(handleProfile());
|
|
2571
2738
|
|
|
2572
2739
|
// src/render/section-cap.ts
|
|
2573
2740
|
import {
|
|
2574
2741
|
AlwaysStencilFunc,
|
|
2575
2742
|
BackSide,
|
|
2576
|
-
Color as
|
|
2743
|
+
Color as Color3,
|
|
2577
2744
|
DecrementWrapStencilOp,
|
|
2578
2745
|
DoubleSide as DoubleSide3,
|
|
2579
2746
|
FrontSide,
|
|
@@ -2582,11 +2749,11 @@ import {
|
|
|
2582
2749
|
MeshBasicMaterial as MeshBasicMaterial2,
|
|
2583
2750
|
NotEqualStencilFunc,
|
|
2584
2751
|
ReplaceStencilOp,
|
|
2585
|
-
ShaderMaterial,
|
|
2586
|
-
Vector2 as
|
|
2752
|
+
ShaderMaterial as ShaderMaterial2,
|
|
2753
|
+
Vector2 as Vector24,
|
|
2587
2754
|
WebGLRenderTarget
|
|
2588
2755
|
} from "three";
|
|
2589
|
-
var
|
|
2756
|
+
var VERTEX2 = (
|
|
2590
2757
|
/* glsl */
|
|
2591
2758
|
`
|
|
2592
2759
|
void main() {
|
|
@@ -2594,7 +2761,7 @@ void main() {
|
|
|
2594
2761
|
}
|
|
2595
2762
|
`
|
|
2596
2763
|
);
|
|
2597
|
-
var
|
|
2764
|
+
var FRAGMENT2 = (
|
|
2598
2765
|
/* glsl */
|
|
2599
2766
|
`
|
|
2600
2767
|
uniform sampler2D uMask;
|
|
@@ -2642,17 +2809,17 @@ function createMaskTarget() {
|
|
|
2642
2809
|
function createCapMaterial(mask) {
|
|
2643
2810
|
const uniforms = {
|
|
2644
2811
|
uMask: { value: mask },
|
|
2645
|
-
uResolution: { value: new
|
|
2646
|
-
uFill: { value: new
|
|
2647
|
-
uHatch: { value: new
|
|
2648
|
-
uOutline: { value: new
|
|
2812
|
+
uResolution: { value: new Vector24(1, 1) },
|
|
2813
|
+
uFill: { value: new Color3() },
|
|
2814
|
+
uHatch: { value: new Color3() },
|
|
2815
|
+
uOutline: { value: new Color3() },
|
|
2649
2816
|
uPitch: { value: CAP_HATCH.pitch },
|
|
2650
2817
|
uLine: { value: CAP_HATCH.line },
|
|
2651
2818
|
uThickness: { value: CAP_HATCH.outline }
|
|
2652
2819
|
};
|
|
2653
|
-
return new
|
|
2654
|
-
vertexShader:
|
|
2655
|
-
fragmentShader:
|
|
2820
|
+
return new ShaderMaterial2({
|
|
2821
|
+
vertexShader: VERTEX2,
|
|
2822
|
+
fragmentShader: FRAGMENT2,
|
|
2656
2823
|
uniforms,
|
|
2657
2824
|
side: DoubleSide3,
|
|
2658
2825
|
stencilWrite: true,
|
|
@@ -2711,7 +2878,7 @@ function createMaskMaterial() {
|
|
|
2711
2878
|
}
|
|
2712
2879
|
|
|
2713
2880
|
// src/section-view.tsx
|
|
2714
|
-
import { Fragment, jsx as
|
|
2881
|
+
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2715
2882
|
var FURNITURE2 = { [EXCLUDE_FROM_FRAME]: true };
|
|
2716
2883
|
function resolveSectionPlane(options, box) {
|
|
2717
2884
|
if (!options?.enabled || box.isEmpty()) return null;
|
|
@@ -2747,43 +2914,45 @@ var SectionView = ({
|
|
|
2747
2914
|
showHandle,
|
|
2748
2915
|
onDrag
|
|
2749
2916
|
}) => {
|
|
2750
|
-
const camera =
|
|
2751
|
-
const size =
|
|
2752
|
-
const dpr =
|
|
2753
|
-
const gl =
|
|
2754
|
-
const invalidate =
|
|
2755
|
-
const controls =
|
|
2756
|
-
const domElement =
|
|
2917
|
+
const camera = useThree6((state) => state.camera);
|
|
2918
|
+
const size = useThree6((state) => state.size);
|
|
2919
|
+
const dpr = useThree6((state) => state.viewport.dpr);
|
|
2920
|
+
const gl = useThree6((state) => state.gl);
|
|
2921
|
+
const invalidate = useThree6((state) => state.invalidate);
|
|
2922
|
+
const controls = useThree6((state) => state.controls);
|
|
2923
|
+
const domElement = useThree6((state) => state.gl.domElement);
|
|
2757
2924
|
const handleRef = useRef4(null);
|
|
2758
2925
|
const [hovered, setHovered] = useState(false);
|
|
2759
2926
|
const dragging = useRef4(null);
|
|
2760
|
-
const span =
|
|
2927
|
+
const span = useMemo6(() => box.getSize(new Vector310()).length(), [box]);
|
|
2761
2928
|
const frameSize = span * SECTION_GIZMO_FRAME_SCALE;
|
|
2762
|
-
const directionColor2 =
|
|
2929
|
+
const directionColor2 = useMemo6(() => sectionDirectionColor(plane.normal), [plane]);
|
|
2763
2930
|
const resolvedHandleColor = sectionHandleColor(handleColor, directionColor2);
|
|
2764
|
-
const clip =
|
|
2765
|
-
const capPosition =
|
|
2766
|
-
const capQuaternion =
|
|
2767
|
-
const handleQuaternion =
|
|
2768
|
-
() => new Quaternion2().setFromUnitVectors(
|
|
2931
|
+
const clip = useMemo6(() => [plane], [plane]);
|
|
2932
|
+
const capPosition = useMemo6(() => sectionAnchor(box, plane), [box, plane]);
|
|
2933
|
+
const capQuaternion = useMemo6(() => new Quaternion2().setFromUnitVectors(Z, plane.normal), [plane]);
|
|
2934
|
+
const handleQuaternion = useMemo6(
|
|
2935
|
+
() => new Quaternion2().setFromUnitVectors(ARROW_AXIS2, plane.normal.clone().negate()),
|
|
2769
2936
|
[plane]
|
|
2770
2937
|
);
|
|
2771
|
-
const frameSurface =
|
|
2772
|
-
|
|
2773
|
-
const frameEdges =
|
|
2774
|
-
|
|
2775
|
-
const
|
|
2776
|
-
|
|
2777
|
-
|
|
2938
|
+
const frameSurface = useMemo6(() => new PlaneGeometry(frameSize, frameSize), [frameSize]);
|
|
2939
|
+
useEffect6(() => () => frameSurface.dispose(), [frameSurface]);
|
|
2940
|
+
const frameEdges = useMemo6(() => new EdgesGeometry(frameSurface), [frameSurface]);
|
|
2941
|
+
useEffect6(() => () => frameEdges.dispose(), [frameEdges]);
|
|
2942
|
+
const handleShape = useMemo6(() => handleGeometry(), []);
|
|
2943
|
+
useEffect6(() => () => handleShape.dispose(), [handleShape]);
|
|
2944
|
+
const stencils = useMemo6(() => createStencilMaterials([]), []);
|
|
2945
|
+
useEffect6(() => () => stencils.forEach((material) => material.dispose()), [stencils]);
|
|
2946
|
+
useLayoutEffect2(() => {
|
|
2778
2947
|
for (const material of stencils) material.clippingPlanes = clip;
|
|
2779
2948
|
}, [clip, stencils]);
|
|
2780
|
-
const mask =
|
|
2781
|
-
|
|
2782
|
-
const cap =
|
|
2783
|
-
|
|
2784
|
-
const quad =
|
|
2785
|
-
|
|
2786
|
-
const maskScene =
|
|
2949
|
+
const mask = useMemo6(() => createMaskTarget(), []);
|
|
2950
|
+
useEffect6(() => () => mask.dispose(), [mask]);
|
|
2951
|
+
const cap = useMemo6(() => createCapMaterial(mask.texture), [mask]);
|
|
2952
|
+
useEffect6(() => () => cap.dispose(), [cap]);
|
|
2953
|
+
const quad = useMemo6(() => new PlaneGeometry(span * 1.5, span * 1.5), [span]);
|
|
2954
|
+
useEffect6(() => () => quad.dispose(), [quad]);
|
|
2955
|
+
const maskScene = useMemo6(() => {
|
|
2787
2956
|
const scene = new Scene();
|
|
2788
2957
|
const [back, front] = stencils;
|
|
2789
2958
|
const backMesh = new Mesh3(geometry, back);
|
|
@@ -2795,19 +2964,19 @@ var SectionView = ({
|
|
|
2795
2964
|
scene.add(backMesh, frontMesh, maskMesh);
|
|
2796
2965
|
return { scene, maskMesh };
|
|
2797
2966
|
}, [geometry, quad, stencils]);
|
|
2798
|
-
|
|
2799
|
-
|
|
2967
|
+
useEffect6(() => () => maskScene.maskMesh.material.dispose(), [maskScene]);
|
|
2968
|
+
useEffect6(() => {
|
|
2800
2969
|
maskScene.maskMesh.position.copy(capPosition);
|
|
2801
2970
|
maskScene.maskMesh.quaternion.copy(capQuaternion);
|
|
2802
2971
|
}, [capPosition, capQuaternion, maskScene]);
|
|
2803
|
-
|
|
2804
|
-
const buffer = gl.getDrawingBufferSize(new
|
|
2972
|
+
useLayoutEffect2(() => {
|
|
2973
|
+
const buffer = gl.getDrawingBufferSize(new Vector25());
|
|
2805
2974
|
mask.setSize(buffer.x, buffer.y);
|
|
2806
2975
|
cap.uniforms.uResolution.value.copy(buffer);
|
|
2807
2976
|
applyCapTheme(cap, theme, dpr);
|
|
2808
2977
|
invalidate();
|
|
2809
2978
|
}, [cap, dpr, gl, invalidate, mask, size, theme]);
|
|
2810
|
-
const clearColor =
|
|
2979
|
+
const clearColor = useMemo6(() => new Color4(), []);
|
|
2811
2980
|
useFrame4(({ gl: renderer, camera: eye }) => {
|
|
2812
2981
|
const previousAlpha = renderer.getClearAlpha();
|
|
2813
2982
|
renderer.getClearColor(clearColor);
|
|
@@ -2848,7 +3017,7 @@ var SectionView = ({
|
|
|
2848
3017
|
dragging.current = start;
|
|
2849
3018
|
setControlsEnabled(false);
|
|
2850
3019
|
const raycaster = new Raycaster2();
|
|
2851
|
-
const pointer = new
|
|
3020
|
+
const pointer = new Vector25();
|
|
2852
3021
|
const move = (native) => {
|
|
2853
3022
|
const rect = domElement.getBoundingClientRect();
|
|
2854
3023
|
pointer.set(
|
|
@@ -2888,8 +3057,8 @@ var SectionView = ({
|
|
|
2888
3057
|
// Excluded from framing, all of it. The cap is a quad half again as wide as
|
|
2889
3058
|
// the part's diagonal, so a Fit that measured it would frame the cut rather
|
|
2890
3059
|
// than the part and leave the part a speck in the middle of it.
|
|
2891
|
-
/* @__PURE__ */
|
|
2892
|
-
/* @__PURE__ */
|
|
3060
|
+
/* @__PURE__ */ jsxs4("group", { userData: FURNITURE2, children: [
|
|
3061
|
+
/* @__PURE__ */ jsx5(
|
|
2893
3062
|
"mesh",
|
|
2894
3063
|
{
|
|
2895
3064
|
geometry,
|
|
@@ -2898,7 +3067,7 @@ var SectionView = ({
|
|
|
2898
3067
|
raycast: () => null
|
|
2899
3068
|
}
|
|
2900
3069
|
),
|
|
2901
|
-
/* @__PURE__ */
|
|
3070
|
+
/* @__PURE__ */ jsx5(
|
|
2902
3071
|
"mesh",
|
|
2903
3072
|
{
|
|
2904
3073
|
geometry,
|
|
@@ -2907,7 +3076,7 @@ var SectionView = ({
|
|
|
2907
3076
|
raycast: () => null
|
|
2908
3077
|
}
|
|
2909
3078
|
),
|
|
2910
|
-
/* @__PURE__ */
|
|
3079
|
+
/* @__PURE__ */ jsx5(
|
|
2911
3080
|
"mesh",
|
|
2912
3081
|
{
|
|
2913
3082
|
geometry: quad,
|
|
@@ -2918,15 +3087,15 @@ var SectionView = ({
|
|
|
2918
3087
|
raycast: () => null
|
|
2919
3088
|
}
|
|
2920
3089
|
),
|
|
2921
|
-
showHandle && onDrag ? /* @__PURE__ */
|
|
2922
|
-
/* @__PURE__ */
|
|
3090
|
+
showHandle && onDrag ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
3091
|
+
/* @__PURE__ */ jsxs4(
|
|
2923
3092
|
"group",
|
|
2924
3093
|
{
|
|
2925
3094
|
position: capPosition,
|
|
2926
3095
|
quaternion: capQuaternion,
|
|
2927
3096
|
renderOrder: SECTION_RENDER_ORDER.outline,
|
|
2928
3097
|
children: [
|
|
2929
|
-
/* @__PURE__ */
|
|
3098
|
+
/* @__PURE__ */ jsx5("mesh", { geometry: frameSurface, raycast: () => null, children: /* @__PURE__ */ jsx5(
|
|
2930
3099
|
"meshBasicMaterial",
|
|
2931
3100
|
{
|
|
2932
3101
|
color: directionColor2,
|
|
@@ -2937,59 +3106,27 @@ var SectionView = ({
|
|
|
2937
3106
|
depthWrite: false
|
|
2938
3107
|
}
|
|
2939
3108
|
) }),
|
|
2940
|
-
/* @__PURE__ */
|
|
3109
|
+
/* @__PURE__ */ jsx5("lineSegments", { geometry: frameEdges, raycast: () => null, children: /* @__PURE__ */ jsx5("lineBasicMaterial", { color: directionColor2, depthTest: false, depthWrite: false }) })
|
|
2941
3110
|
]
|
|
2942
3111
|
}
|
|
2943
3112
|
),
|
|
2944
|
-
/* @__PURE__ */
|
|
3113
|
+
/* @__PURE__ */ jsx5(
|
|
2945
3114
|
"group",
|
|
2946
3115
|
{
|
|
2947
3116
|
ref: handleRef,
|
|
2948
3117
|
position: capPosition,
|
|
2949
3118
|
quaternion: handleQuaternion,
|
|
2950
3119
|
renderOrder: SECTION_RENDER_ORDER.handle,
|
|
2951
|
-
children:
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
] }),
|
|
2962
|
-
/* @__PURE__ */ jsxs3("mesh", { ...grab, children: [
|
|
2963
|
-
/* @__PURE__ */ jsx4("cylinderGeometry", { args: [0.035, 0.035, 0.9, 12] }),
|
|
2964
|
-
/* @__PURE__ */ jsx4(
|
|
2965
|
-
"meshBasicMaterial",
|
|
2966
|
-
{
|
|
2967
|
-
color: hovered ? theme.hover : resolvedHandleColor,
|
|
2968
|
-
depthTest: false
|
|
2969
|
-
}
|
|
2970
|
-
)
|
|
2971
|
-
] }),
|
|
2972
|
-
/* @__PURE__ */ jsxs3("mesh", { position: [0, 0.61, 0], ...grab, children: [
|
|
2973
|
-
/* @__PURE__ */ jsx4("coneGeometry", { args: [0.15, 0.3, 20] }),
|
|
2974
|
-
/* @__PURE__ */ jsx4(
|
|
2975
|
-
"meshBasicMaterial",
|
|
2976
|
-
{
|
|
2977
|
-
color: hovered ? theme.hover : resolvedHandleColor,
|
|
2978
|
-
depthTest: false
|
|
2979
|
-
}
|
|
2980
|
-
)
|
|
2981
|
-
] }),
|
|
2982
|
-
/* @__PURE__ */ jsxs3("mesh", { position: [0, -0.61, 0], rotation: [Math.PI, 0, 0], ...grab, children: [
|
|
2983
|
-
/* @__PURE__ */ jsx4("coneGeometry", { args: [0.15, 0.3, 20] }),
|
|
2984
|
-
/* @__PURE__ */ jsx4(
|
|
2985
|
-
"meshBasicMaterial",
|
|
2986
|
-
{
|
|
2987
|
-
color: hovered ? theme.hover : resolvedHandleColor,
|
|
2988
|
-
depthTest: false
|
|
2989
|
-
}
|
|
2990
|
-
)
|
|
2991
|
-
] })
|
|
2992
|
-
]
|
|
3120
|
+
children: /* @__PURE__ */ jsx5(
|
|
3121
|
+
ArrowMesh,
|
|
3122
|
+
{
|
|
3123
|
+
geometry: handleShape,
|
|
3124
|
+
color: hovered ? theme.hover : resolvedHandleColor,
|
|
3125
|
+
opacity: 1,
|
|
3126
|
+
onTop: true,
|
|
3127
|
+
events: grab
|
|
3128
|
+
}
|
|
3129
|
+
)
|
|
2993
3130
|
}
|
|
2994
3131
|
)
|
|
2995
3132
|
] }) : null
|
|
@@ -2998,11 +3135,11 @@ var SectionView = ({
|
|
|
2998
3135
|
};
|
|
2999
3136
|
|
|
3000
3137
|
// src/content-box.ts
|
|
3001
|
-
import { useFrame as useFrame5, useThree as
|
|
3138
|
+
import { useFrame as useFrame5, useThree as useThree7 } from "@react-three/fiber";
|
|
3002
3139
|
import { useRef as useRef5, useState as useState2 } from "react";
|
|
3003
3140
|
import { Box3 as Box34 } from "three";
|
|
3004
3141
|
function useContentBox() {
|
|
3005
|
-
const scene =
|
|
3142
|
+
const scene = useThree7((state) => state.scene);
|
|
3006
3143
|
const [box, setBox] = useState2(() => new Box34());
|
|
3007
3144
|
const measured = useRef5(false);
|
|
3008
3145
|
useFrame5(() => {
|
|
@@ -3017,7 +3154,7 @@ function useContentBox() {
|
|
|
3017
3154
|
}
|
|
3018
3155
|
|
|
3019
3156
|
// src/part-mesh.tsx
|
|
3020
|
-
import { Fragment as
|
|
3157
|
+
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3021
3158
|
var PartMesh = ({
|
|
3022
3159
|
model,
|
|
3023
3160
|
geometry,
|
|
@@ -3041,13 +3178,13 @@ var PartMesh = ({
|
|
|
3041
3178
|
display = "solid",
|
|
3042
3179
|
children
|
|
3043
3180
|
}) => {
|
|
3044
|
-
const { camera, controls, invalidate } =
|
|
3045
|
-
const context =
|
|
3181
|
+
const { camera, controls, invalidate } = useThree8();
|
|
3182
|
+
const context = useMemo7(() => ({ model, geometry }), [model, geometry]);
|
|
3046
3183
|
const viewerControls = useViewerControls();
|
|
3047
3184
|
const resolved = useStableTheme(theme);
|
|
3048
3185
|
const currentTheme = useRef6(resolved);
|
|
3049
3186
|
currentTheme.current = resolved;
|
|
3050
|
-
const part =
|
|
3187
|
+
const part = useMemo7(() => createPart(model, geometry, currentTheme.current), [geometry, model]);
|
|
3051
3188
|
const hoverRegion = useRef6(null);
|
|
3052
3189
|
const onHoverRef = useRef6(onHover);
|
|
3053
3190
|
onHoverRef.current = onHover;
|
|
@@ -3056,7 +3193,7 @@ var PartMesh = ({
|
|
|
3056
3193
|
const shared = useSyncExternalStore(store.subscribe, store.get, store.get);
|
|
3057
3194
|
const controlled = section !== void 0;
|
|
3058
3195
|
const options = controlled ? section : shared ?? void 0;
|
|
3059
|
-
const cut =
|
|
3196
|
+
const cut = useMemo7(() => resolveSectionPlane(options, box), [box, options]);
|
|
3060
3197
|
const engaged = useSyncExternalStore(store.subscribe, store.isEngaged, store.isEngaged);
|
|
3061
3198
|
const pressedWhileEngaged = useRef6(false);
|
|
3062
3199
|
const layers = useRef6({
|
|
@@ -3084,19 +3221,19 @@ var PartMesh = ({
|
|
|
3084
3221
|
);
|
|
3085
3222
|
invalidate();
|
|
3086
3223
|
}, [invalidate, part]);
|
|
3087
|
-
|
|
3088
|
-
const adjacency =
|
|
3089
|
-
|
|
3224
|
+
useEffect7(() => () => part.dispose(), [part]);
|
|
3225
|
+
const adjacency = useMemo7(() => regionAdjacency(model, geometry), [model, geometry]);
|
|
3226
|
+
useEffect7(() => {
|
|
3090
3227
|
onAdjacency?.(adjacency);
|
|
3091
3228
|
}, [adjacency, onAdjacency]);
|
|
3092
3229
|
const framed = useRef6(null);
|
|
3093
|
-
|
|
3230
|
+
useEffect7(() => {
|
|
3094
3231
|
if (focusFeature === null || focusFeature === framed.current) return;
|
|
3095
3232
|
framed.current = focusFeature;
|
|
3096
3233
|
const box2 = part.boxForFeature(focusFeature);
|
|
3097
3234
|
if (box2) viewerControls.frameBox(box2);
|
|
3098
3235
|
}, [focusFeature, part, viewerControls]);
|
|
3099
|
-
|
|
3236
|
+
useLayoutEffect3(() => {
|
|
3100
3237
|
part.setTheme(resolved);
|
|
3101
3238
|
repaint();
|
|
3102
3239
|
}, [part, repaint, resolved]);
|
|
@@ -3105,20 +3242,20 @@ var PartMesh = ({
|
|
|
3105
3242
|
const selectionRef = useRef6(selection);
|
|
3106
3243
|
selectionRef.current = selection;
|
|
3107
3244
|
const focusKey = focusStateKey(focus, selection);
|
|
3108
|
-
|
|
3245
|
+
useLayoutEffect3(() => {
|
|
3109
3246
|
part.setFocus(selectionRef.current, focusRef.current);
|
|
3110
3247
|
invalidate();
|
|
3111
3248
|
}, [focusKey, invalidate, part]);
|
|
3112
|
-
|
|
3249
|
+
useLayoutEffect3(() => {
|
|
3113
3250
|
part.setDisplay(display, showEdges);
|
|
3114
3251
|
invalidate();
|
|
3115
3252
|
}, [display, invalidate, part, showEdges]);
|
|
3116
|
-
|
|
3253
|
+
useLayoutEffect3(() => {
|
|
3117
3254
|
part.setClippingPlanes(cut ? [cut.plane] : null);
|
|
3118
3255
|
invalidate();
|
|
3119
3256
|
}, [cut, invalidate, part]);
|
|
3120
3257
|
const reportedSection = useRef6("");
|
|
3121
|
-
|
|
3258
|
+
useLayoutEffect3(() => {
|
|
3122
3259
|
const state = cut?.state ?? null;
|
|
3123
3260
|
const key = state ? `${state.constant}|${state.normal.x},${state.normal.y},${state.normal.z}` : "";
|
|
3124
3261
|
if (key === reportedSection.current) return;
|
|
@@ -3135,12 +3272,12 @@ var PartMesh = ({
|
|
|
3135
3272
|
highlights.map((entry) => `${entry.tag}:${entry.color}:${entry.weight ?? ""}`).join(" "),
|
|
3136
3273
|
regionHighlights.map((entry) => `${entry.region}:${entry.color}:${entry.weight ?? ""}`).join(" ")
|
|
3137
3274
|
].join("|");
|
|
3138
|
-
|
|
3275
|
+
useLayoutEffect3(() => {
|
|
3139
3276
|
repaint();
|
|
3140
3277
|
}, [layerKey, repaint]);
|
|
3141
3278
|
const isTap = useTapGuard();
|
|
3142
3279
|
const retarget = useRetarget();
|
|
3143
|
-
const doubles =
|
|
3280
|
+
const doubles = useMemo7(() => trackDoubleTaps(), []);
|
|
3144
3281
|
const pickFor = (event, doubled = false) => {
|
|
3145
3282
|
const triangleIndex = event.faceIndex;
|
|
3146
3283
|
if (triangleIndex == null) return null;
|
|
@@ -3175,13 +3312,13 @@ var PartMesh = ({
|
|
|
3175
3312
|
repaint();
|
|
3176
3313
|
onHover?.(next);
|
|
3177
3314
|
};
|
|
3178
|
-
|
|
3315
|
+
useLayoutEffect3(() => {
|
|
3179
3316
|
if (hover || hoverRegion.current === null) return;
|
|
3180
3317
|
hoverRegion.current = null;
|
|
3181
3318
|
repaint();
|
|
3182
3319
|
onHoverRef.current?.(null);
|
|
3183
3320
|
}, [hover, repaint]);
|
|
3184
|
-
|
|
3321
|
+
useLayoutEffect3(() => {
|
|
3185
3322
|
if (!engaged || hoverRegion.current === null) return;
|
|
3186
3323
|
hoverRegion.current = null;
|
|
3187
3324
|
repaint();
|
|
@@ -3205,8 +3342,8 @@ var PartMesh = ({
|
|
|
3205
3342
|
},
|
|
3206
3343
|
[box, controlled, cut, onSectionChange, options, store]
|
|
3207
3344
|
);
|
|
3208
|
-
return /* @__PURE__ */
|
|
3209
|
-
/* @__PURE__ */
|
|
3345
|
+
return /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
3346
|
+
/* @__PURE__ */ jsx6(
|
|
3210
3347
|
"primitive",
|
|
3211
3348
|
{
|
|
3212
3349
|
object: part.object,
|
|
@@ -3243,7 +3380,7 @@ var PartMesh = ({
|
|
|
3243
3380
|
}
|
|
3244
3381
|
}
|
|
3245
3382
|
),
|
|
3246
|
-
cut ? /* @__PURE__ */
|
|
3383
|
+
cut ? /* @__PURE__ */ jsx6(
|
|
3247
3384
|
SectionView,
|
|
3248
3385
|
{
|
|
3249
3386
|
geometry,
|
|
@@ -3255,7 +3392,7 @@ var PartMesh = ({
|
|
|
3255
3392
|
onDrag: !controlled || onSectionChange ? dragSection : void 0
|
|
3256
3393
|
}
|
|
3257
3394
|
) : null,
|
|
3258
|
-
children ? /* @__PURE__ */
|
|
3395
|
+
children ? /* @__PURE__ */ jsx6(PartContext.Provider, { value: context, children }) : null
|
|
3259
3396
|
] });
|
|
3260
3397
|
};
|
|
3261
3398
|
var ORIGIN = new Vector311();
|
|
@@ -3884,15 +4021,15 @@ function compareVersions(a, b) {
|
|
|
3884
4021
|
}
|
|
3885
4022
|
|
|
3886
4023
|
// src/engine/engine-part.tsx
|
|
3887
|
-
import { jsx as
|
|
4024
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3888
4025
|
var EnginePart = ({ report, ...props }) => {
|
|
3889
|
-
const model =
|
|
4026
|
+
const model = useMemo8(() => normalizePartReport(report), [report]);
|
|
3890
4027
|
const resource = useGeometryResource(model);
|
|
3891
|
-
|
|
4028
|
+
useEffect8(() => {
|
|
3892
4029
|
engineGeometryCache.retain(resource);
|
|
3893
4030
|
return () => engineGeometryCache.release(resource);
|
|
3894
4031
|
}, [resource]);
|
|
3895
|
-
return /* @__PURE__ */
|
|
4032
|
+
return /* @__PURE__ */ jsx7(PartMesh, { model, geometry: resource.geometry, ...props });
|
|
3896
4033
|
};
|
|
3897
4034
|
function useGeometryResource(part) {
|
|
3898
4035
|
const resource = engineGeometryCache.get(part);
|
|
@@ -4045,11 +4182,9 @@ export {
|
|
|
4045
4182
|
useSectionStore,
|
|
4046
4183
|
useRetarget,
|
|
4047
4184
|
Viewer,
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
SHAFT_RADIUS,
|
|
4052
|
-
arrowPlacement,
|
|
4185
|
+
ArrowMesh,
|
|
4186
|
+
ARROW_AXIS2 as ARROW_AXIS,
|
|
4187
|
+
arrowGeometry,
|
|
4053
4188
|
createMaskTarget,
|
|
4054
4189
|
createCapMaterial,
|
|
4055
4190
|
applyCapTheme,
|
package/dist/engine/index.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -90,6 +90,7 @@ interface ViewerToolbarControls {
|
|
|
90
90
|
/** Tools drawn on the part: see `<ToolMarks>`. */
|
|
91
91
|
tools?: ViewerToolbarControl;
|
|
92
92
|
directions?: ViewerToolbarControl;
|
|
93
|
+
dfm?: ViewerToolbarControl;
|
|
93
94
|
hover?: ViewerToolbarControl;
|
|
94
95
|
focus?: ViewerToolbarControl;
|
|
95
96
|
wireframe?: ViewerToolbarControl;
|
|
@@ -131,6 +132,7 @@ declare const ViewerToolbar: (({ className, children }: ViewerToolbarProps) => r
|
|
|
131
132
|
BananaButton: () => react.JSX.Element;
|
|
132
133
|
ToolsButton: () => react.JSX.Element;
|
|
133
134
|
DirectionsButton: () => react.JSX.Element;
|
|
135
|
+
DfmButton: () => react.JSX.Element;
|
|
134
136
|
HoverButton: () => react.JSX.Element;
|
|
135
137
|
FocusButton: () => react.JSX.Element;
|
|
136
138
|
WireframeButton: () => react.JSX.Element;
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ANGLE_ARC_FRACTION,
|
|
3
3
|
ANGLE_ARC_SEGMENTS,
|
|
4
|
+
ARROW_AXIS,
|
|
4
5
|
AXES_PLANE_OFFSET,
|
|
5
6
|
AXES_PLANE_SCALE,
|
|
6
7
|
AXIS_COLORS,
|
|
8
|
+
ArrowMesh,
|
|
7
9
|
CAD_CAMERA_UP,
|
|
8
10
|
CANDIDATE_WEIGHT,
|
|
9
11
|
CAP_HATCH,
|
|
10
12
|
CHAMFER,
|
|
11
|
-
CONE_AXIS,
|
|
12
13
|
CONTROL_SCHEME_OPTIONS,
|
|
13
14
|
CadCameraControls,
|
|
14
15
|
DEFAULT_FIT_MARGIN,
|
|
@@ -23,8 +24,6 @@ import {
|
|
|
23
24
|
ExtendedCameraControls,
|
|
24
25
|
FEATURE_TYPE_RANKS,
|
|
25
26
|
HANDLE_PIXELS,
|
|
26
|
-
HEAD,
|
|
27
|
-
HEAD_RADIUS,
|
|
28
27
|
HIGHLIGHT_COLORS,
|
|
29
28
|
HIGHLIGHT_WEIGHT,
|
|
30
29
|
HOVER_WEIGHT,
|
|
@@ -52,7 +51,6 @@ import {
|
|
|
52
51
|
REGION_ATTRIBUTE,
|
|
53
52
|
SECTION_GIZMO_FRAME_SCALE,
|
|
54
53
|
SECTION_RENDER_ORDER,
|
|
55
|
-
SHAFT_RADIUS,
|
|
56
54
|
SNAP_MARKER_PIXELS,
|
|
57
55
|
SNAP_PIXELS,
|
|
58
56
|
STOCK_OBJECT,
|
|
@@ -69,7 +67,7 @@ import {
|
|
|
69
67
|
applyCapTheme,
|
|
70
68
|
applyHighlightLayers,
|
|
71
69
|
applyProjection,
|
|
72
|
-
|
|
70
|
+
arrowGeometry,
|
|
73
71
|
aspectRatio,
|
|
74
72
|
axesPlanes,
|
|
75
73
|
bestOwner,
|
|
@@ -162,7 +160,7 @@ import {
|
|
|
162
160
|
viewUp,
|
|
163
161
|
viewVector,
|
|
164
162
|
visualSurfaces
|
|
165
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-7S6SIYHL.js";
|
|
166
164
|
|
|
167
165
|
// src/render/feature-triangles.ts
|
|
168
166
|
var EMPTY = { positions: new Float32Array(), normals: new Float32Array() };
|
|
@@ -268,6 +266,7 @@ var GridIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ j
|
|
|
268
266
|
var BananaIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { viewBox: "0 0 576 512", fill: "currentColor", children: /* @__PURE__ */ jsx2("path", { d: "M284.2 245.6c12.99 6.929 25.35 15.14 36.08 25.8L334.5 285.6l65.75-23.47c14.75-5.265 30.18-7.849 45.81-8.389c1.154-10.73 1.764-21.38 1.764-31.87c0-118.5-81.33-221.9-119.7-221.9c-21.01 0-40.91 17.04-40.91 39.25c0 16.18 16.74 41.9 16.74 103C303.1 170.1 300.6 203.1 284.2 245.6zM575.1 389.6c0-3.687-.8637-7.429-2.687-10.93l-15.12-29.11c-21.05-40.53-63.08-64.51-106.9-64.51c-13.43 0-27.02 2.252-40.22 6.969l-84.84 30.27l-28.59-28.41C274.4 270.9 243.7 258.1 212.8 258.1c-23.72 0-47.57 6.97-68.29 21.2L106.3 306.4c-6.732 4.631-10.35 12.07-10.35 19.63c0 14.93 12.7 23.87 24.04 23.87c4.695 0 9.443-1.376 13.61-4.26l38.13-26.23c12.43-8.525 26.71-12.69 40.91-12.69c10.64 0 21.24 2.339 30.97 6.934c-50.62 62.23-128.3 99.85-211.4 99.85C14.42 413.5 0 427.8 0 445.5v31.38c0 17.68 14.66 32.02 32.46 32.02l28.98.0009c14.15 0 34.69 1.098 59.07 1.098c93.51 0 243.4-16.15 304.8-172.4c9.021-3.22 17.95-4.712 26.53-4.712c27.65 0 51.7 15.49 63.7 38.55l15.12 29.11c3.484 6.723 11.74 12.98 21.41 12.98C564.1 413.6 575.1 403.8 575.1 389.6z" }) });
|
|
269
267
|
var ToolsIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M9 2h6v7H9zM9.5 9v9.5l2.5 3.5 2.5-3.5V9M9.5 12l5 2.5M9.5 15.5l5 2.5" }) });
|
|
270
268
|
var DirectionsIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M7 3v18m-4-4 4 4 4-4M17 21V3m-4 4 4-4 4 4" }) });
|
|
269
|
+
var DfmIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M8.3 3h7.4L21 8.3v7.4L15.7 21H8.3L3 15.7V8.3zM12 7.5v5.5m0 3.5v.01" }) });
|
|
271
270
|
var HoverIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M4 4h16v12H9l-5 4zm4 5h8m-8 3h5" }) });
|
|
272
271
|
var FocusIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M4 4h16v16H4zM8 8h8v8H8zM2 12h4m12 0h4M12 2v4m0 12v4" }) });
|
|
273
272
|
var WireframeIcon = () => /* @__PURE__ */ jsx2(SvgIcon, { children: /* @__PURE__ */ jsx2("path", { d: "M4 7l8-4 8 4v10l-8 4-8-4zM4 7l8 4 8-4M12 11v10M4 17l8-4 8 4M12 3v10" }) });
|
|
@@ -283,6 +282,7 @@ var ICONS = {
|
|
|
283
282
|
banana: BananaIcon,
|
|
284
283
|
tools: ToolsIcon,
|
|
285
284
|
directions: DirectionsIcon,
|
|
285
|
+
dfm: DfmIcon,
|
|
286
286
|
hover: HoverIcon,
|
|
287
287
|
focus: FocusIcon,
|
|
288
288
|
wireframe: WireframeIcon,
|
|
@@ -377,6 +377,14 @@ var DirectionsButton = () => /* @__PURE__ */ jsx3(
|
|
|
377
377
|
label: () => "Highlight faces by direction"
|
|
378
378
|
}
|
|
379
379
|
);
|
|
380
|
+
var DfmButton = () => /* @__PURE__ */ jsx3(
|
|
381
|
+
ToolbarButton,
|
|
382
|
+
{
|
|
383
|
+
action: "dfm",
|
|
384
|
+
icon: "dfm",
|
|
385
|
+
label: (pressed) => pressed ? "Hide DFM flags" : "Show DFM flags"
|
|
386
|
+
}
|
|
387
|
+
);
|
|
380
388
|
var HoverButton = () => /* @__PURE__ */ jsx3(
|
|
381
389
|
ToolbarButton,
|
|
382
390
|
{
|
|
@@ -435,6 +443,7 @@ var DefaultControls = () => {
|
|
|
435
443
|
].filter(Boolean);
|
|
436
444
|
const analysis = [
|
|
437
445
|
controls.directions ? /* @__PURE__ */ jsx3(DirectionsButton, {}, "directions") : null,
|
|
446
|
+
controls.dfm ? /* @__PURE__ */ jsx3(DfmButton, {}, "dfm") : null,
|
|
438
447
|
controls.hover ? /* @__PURE__ */ jsx3(HoverButton, {}, "hover") : null,
|
|
439
448
|
controls.focus ? /* @__PURE__ */ jsx3(FocusButton, {}, "focus") : null,
|
|
440
449
|
controls.wireframe ? /* @__PURE__ */ jsx3(WireframeButton, {}, "wireframe") : null,
|
|
@@ -474,6 +483,7 @@ var ViewerToolbar = Object.assign(ViewerToolbarRoot, {
|
|
|
474
483
|
BananaButton,
|
|
475
484
|
ToolsButton,
|
|
476
485
|
DirectionsButton,
|
|
486
|
+
DfmButton,
|
|
477
487
|
HoverButton,
|
|
478
488
|
FocusButton,
|
|
479
489
|
WireframeButton,
|
|
@@ -1111,8 +1121,33 @@ var CubePanels = ({
|
|
|
1111
1121
|
|
|
1112
1122
|
// src/direction-arrows.tsx
|
|
1113
1123
|
import { useThree as useThree4 } from "@react-three/fiber";
|
|
1114
|
-
import { useMemo as useMemo4 } from "react";
|
|
1115
|
-
import { Quaternion as Quaternion2, Vector3 as
|
|
1124
|
+
import { useEffect as useEffect4, useMemo as useMemo4 } from "react";
|
|
1125
|
+
import { Quaternion as Quaternion2, Vector3 as Vector35 } from "three";
|
|
1126
|
+
|
|
1127
|
+
// src/render/directions.ts
|
|
1128
|
+
import { Vector3 as Vector34 } from "three";
|
|
1129
|
+
var LENGTH = 0.33;
|
|
1130
|
+
var GAP = 0.2;
|
|
1131
|
+
function arrowPlacement(direction, box) {
|
|
1132
|
+
const center = box.getCenter(new Vector34());
|
|
1133
|
+
const half = box.getSize(new Vector34()).multiplyScalar(0.5);
|
|
1134
|
+
const radius = half.length() || 1;
|
|
1135
|
+
const axis = new Vector34(direction.x, direction.y, direction.z);
|
|
1136
|
+
if (axis.lengthSq() === 0) axis.set(0, 0, 1);
|
|
1137
|
+
axis.normalize();
|
|
1138
|
+
let exit = Number.POSITIVE_INFINITY;
|
|
1139
|
+
for (const [component, extent] of [
|
|
1140
|
+
[axis.x, half.x],
|
|
1141
|
+
[axis.y, half.y],
|
|
1142
|
+
[axis.z, half.z]
|
|
1143
|
+
]) {
|
|
1144
|
+
if (Math.abs(component) > 1e-6) exit = Math.min(exit, extent / Math.abs(component));
|
|
1145
|
+
}
|
|
1146
|
+
if (!Number.isFinite(exit)) exit = radius;
|
|
1147
|
+
return { tip: center.addScaledVector(axis, exit + radius * GAP), length: radius * LENGTH };
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// src/direction-arrows.tsx
|
|
1116
1151
|
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1117
1152
|
var FURNITURE3 = { [EXCLUDE_FROM_FRAME]: true };
|
|
1118
1153
|
var DirectionArrows = ({
|
|
@@ -1127,6 +1162,8 @@ var DirectionArrows = ({
|
|
|
1127
1162
|
}) => {
|
|
1128
1163
|
const box = useContentBox();
|
|
1129
1164
|
const resolved = useMemo4(() => resolveTheme(theme), [theme]);
|
|
1165
|
+
const geometry = useMemo4(() => arrowGeometry(), []);
|
|
1166
|
+
useEffect4(() => () => geometry.dispose(), [geometry]);
|
|
1130
1167
|
const shown = shownDirection === void 0 ? activeDirection : shownDirection;
|
|
1131
1168
|
const drawn = (index) => {
|
|
1132
1169
|
if (shown === null) return true;
|
|
@@ -1146,6 +1183,7 @@ var DirectionArrows = ({
|
|
|
1146
1183
|
{
|
|
1147
1184
|
direction,
|
|
1148
1185
|
box,
|
|
1186
|
+
geometry,
|
|
1149
1187
|
color: directionColor(index),
|
|
1150
1188
|
opacity: 0.9,
|
|
1151
1189
|
onPick: onPickDirection ? () => onPickDirection(index) : void 0
|
|
@@ -1158,28 +1196,37 @@ var DirectionArrows = ({
|
|
|
1158
1196
|
{
|
|
1159
1197
|
direction: named.direction,
|
|
1160
1198
|
box,
|
|
1199
|
+
geometry,
|
|
1161
1200
|
color: named.color,
|
|
1162
1201
|
opacity: 0.9,
|
|
1163
1202
|
onPick: onPickDirection ? () => onPickDirection(named.index) : void 0
|
|
1164
1203
|
},
|
|
1165
1204
|
`named-${named.index}`
|
|
1166
1205
|
)),
|
|
1167
|
-
previewDirection ? /* @__PURE__ */ jsx7(
|
|
1206
|
+
previewDirection ? /* @__PURE__ */ jsx7(
|
|
1207
|
+
Arrow,
|
|
1208
|
+
{
|
|
1209
|
+
direction: previewDirection,
|
|
1210
|
+
box,
|
|
1211
|
+
geometry,
|
|
1212
|
+
color: resolved.hover,
|
|
1213
|
+
opacity: 0.95,
|
|
1214
|
+
onTop: true
|
|
1215
|
+
}
|
|
1216
|
+
) : null
|
|
1168
1217
|
] })
|
|
1169
1218
|
);
|
|
1170
1219
|
};
|
|
1171
|
-
var Arrow = ({ direction, box, color, opacity, onPick, onTop = false }) => {
|
|
1220
|
+
var Arrow = ({ direction, box, geometry, color, opacity, onPick, onTop = false }) => {
|
|
1172
1221
|
const invalidate = useThree4((state) => state.invalidate);
|
|
1173
1222
|
const { tip, length, quaternion } = useMemo4(() => {
|
|
1174
1223
|
const placement = arrowPlacement(direction, box);
|
|
1175
1224
|
const aim = new Quaternion2().setFromUnitVectors(
|
|
1176
|
-
|
|
1177
|
-
new
|
|
1225
|
+
ARROW_AXIS,
|
|
1226
|
+
new Vector35(direction.x, direction.y, direction.z).normalize()
|
|
1178
1227
|
);
|
|
1179
1228
|
return { tip: placement.tip, length: placement.length, quaternion: aim };
|
|
1180
1229
|
}, [box, direction]);
|
|
1181
|
-
const head = length * HEAD;
|
|
1182
|
-
const shaft = length * (1 - HEAD);
|
|
1183
1230
|
const press = onPick ? {
|
|
1184
1231
|
onClick: (event) => {
|
|
1185
1232
|
event.stopPropagation();
|
|
@@ -1187,32 +1234,23 @@ var Arrow = ({ direction, box, color, opacity, onPick, onTop = false }) => {
|
|
|
1187
1234
|
invalidate();
|
|
1188
1235
|
}
|
|
1189
1236
|
} : {};
|
|
1190
|
-
return /* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */ jsxs3("mesh", { position: [0, head * 0.5, 0], rotation: [Math.PI, 0, 0], ...press, children: [
|
|
1192
|
-
/* @__PURE__ */ jsx7("coneGeometry", { args: [length * HEAD_RADIUS, head, 20] }),
|
|
1193
|
-
/* @__PURE__ */ jsx7("meshBasicMaterial", { color, transparent: true, opacity, depthTest: !onTop })
|
|
1194
|
-
] }),
|
|
1195
|
-
/* @__PURE__ */ jsxs3("mesh", { position: [0, head + shaft * 0.5, 0], ...press, children: [
|
|
1196
|
-
/* @__PURE__ */ jsx7("cylinderGeometry", { args: [length * SHAFT_RADIUS, length * SHAFT_RADIUS, shaft, 12] }),
|
|
1197
|
-
/* @__PURE__ */ jsx7("meshBasicMaterial", { color, transparent: true, opacity, depthTest: !onTop })
|
|
1198
|
-
] })
|
|
1199
|
-
] });
|
|
1237
|
+
return /* @__PURE__ */ jsx7("group", { position: tip, quaternion, scale: length, renderOrder: onTop ? 10 : 3, children: /* @__PURE__ */ jsx7(ArrowMesh, { geometry, color, opacity, onTop, events: press }) });
|
|
1200
1238
|
};
|
|
1201
1239
|
|
|
1202
1240
|
// src/section-tool.tsx
|
|
1203
1241
|
import { useFrame, useThree as useThree5 } from "@react-three/fiber";
|
|
1204
|
-
import { useEffect as
|
|
1242
|
+
import { useEffect as useEffect5, useMemo as useMemo5, useRef as useRef3, useState as useState4, useSyncExternalStore } from "react";
|
|
1205
1243
|
import {
|
|
1206
1244
|
BufferGeometry as BufferGeometry2,
|
|
1207
1245
|
DoubleSide,
|
|
1208
1246
|
Quaternion as Quaternion3,
|
|
1209
1247
|
Raycaster,
|
|
1210
1248
|
Vector2,
|
|
1211
|
-
Vector3 as
|
|
1249
|
+
Vector3 as Vector36
|
|
1212
1250
|
} from "three";
|
|
1213
1251
|
import { Fragment, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1214
1252
|
var FURNITURE4 = { [EXCLUDE_FROM_FRAME]: true };
|
|
1215
|
-
var Z = new
|
|
1253
|
+
var Z = new Vector36(0, 0, 1);
|
|
1216
1254
|
var AXIS_ROTATIONS = {
|
|
1217
1255
|
x: [0, Math.PI / 2, 0],
|
|
1218
1256
|
y: [Math.PI / 2, 0, 0],
|
|
@@ -1225,11 +1263,11 @@ var SectionTool = ({ theme }) => {
|
|
|
1225
1263
|
const section = useSyncExternalStore(store.subscribe, store.get, store.get);
|
|
1226
1264
|
const box = useContentBox();
|
|
1227
1265
|
const resolved = useMemo5(() => resolveTheme(theme), [theme]);
|
|
1228
|
-
|
|
1266
|
+
useEffect5(() => {
|
|
1229
1267
|
store.setEngaged(true);
|
|
1230
1268
|
return () => store.setEngaged(false);
|
|
1231
1269
|
}, [store]);
|
|
1232
|
-
|
|
1270
|
+
useEffect5(() => {
|
|
1233
1271
|
if (!section) return void 0;
|
|
1234
1272
|
const clear = (event) => {
|
|
1235
1273
|
if (event.key === "Escape") store.set(null);
|
|
@@ -1243,14 +1281,14 @@ var SectionTool = ({ theme }) => {
|
|
|
1243
1281
|
var useSquare = () => {
|
|
1244
1282
|
const square = useMemo5(
|
|
1245
1283
|
() => new BufferGeometry2().setFromPoints([
|
|
1246
|
-
new
|
|
1247
|
-
new
|
|
1248
|
-
new
|
|
1249
|
-
new
|
|
1284
|
+
new Vector36(-1, 1, 0),
|
|
1285
|
+
new Vector36(1, 1, 0),
|
|
1286
|
+
new Vector36(1, -1, 0),
|
|
1287
|
+
new Vector36(-1, -1, 0)
|
|
1250
1288
|
]),
|
|
1251
1289
|
[]
|
|
1252
1290
|
);
|
|
1253
|
-
|
|
1291
|
+
useEffect5(() => () => square.dispose(), [square]);
|
|
1254
1292
|
return square;
|
|
1255
1293
|
};
|
|
1256
1294
|
var Picker = ({ box, theme }) => {
|
|
@@ -1264,17 +1302,17 @@ var Picker = ({ box, theme }) => {
|
|
|
1264
1302
|
const previewRef = useRef3(null);
|
|
1265
1303
|
const hover = useRef3(null);
|
|
1266
1304
|
const [hoveredPlane, setHoveredPlane] = useState4(null);
|
|
1267
|
-
const span = useMemo5(() => box.getSize(new
|
|
1268
|
-
const centre = useMemo5(() => box.getCenter(new
|
|
1305
|
+
const span = useMemo5(() => box.getSize(new Vector36()).length(), [box]);
|
|
1306
|
+
const centre = useMemo5(() => box.getCenter(new Vector36()), [box]);
|
|
1269
1307
|
const previewSize = span * PREVIEW_SCALE;
|
|
1270
|
-
|
|
1308
|
+
useEffect5(() => {
|
|
1271
1309
|
store.setPicking(true);
|
|
1272
1310
|
return () => store.setPicking(false);
|
|
1273
1311
|
}, [store]);
|
|
1274
|
-
|
|
1312
|
+
useEffect5(() => {
|
|
1275
1313
|
const raycaster = new Raycaster();
|
|
1276
1314
|
const pointer = new Vector2();
|
|
1277
|
-
const aim = new
|
|
1315
|
+
const aim = new Vector36();
|
|
1278
1316
|
const hide = () => {
|
|
1279
1317
|
if (!hover.current) return;
|
|
1280
1318
|
hover.current = null;
|
|
@@ -1418,7 +1456,7 @@ var Picker = ({ box, theme }) => {
|
|
|
1418
1456
|
var CutSheet = ({ box, section, theme }) => {
|
|
1419
1457
|
const square = useSquare();
|
|
1420
1458
|
const cut = useMemo5(() => resolveSectionPlane(section, box), [box, section]);
|
|
1421
|
-
const span = useMemo5(() => box.getSize(new
|
|
1459
|
+
const span = useMemo5(() => box.getSize(new Vector36()).length(), [box]);
|
|
1422
1460
|
const placement = useMemo5(() => {
|
|
1423
1461
|
if (!cut) return null;
|
|
1424
1462
|
const position = sectionAnchor(box, cut.plane).addScaledVector(
|
|
@@ -1469,7 +1507,7 @@ var CutSheet = ({ box, section, theme }) => {
|
|
|
1469
1507
|
import { Html, Line } from "@react-three/drei";
|
|
1470
1508
|
import { useFrame as useFrame2, useThree as useThree6 } from "@react-three/fiber";
|
|
1471
1509
|
import {
|
|
1472
|
-
useEffect as
|
|
1510
|
+
useEffect as useEffect6,
|
|
1473
1511
|
useLayoutEffect as useLayoutEffect3,
|
|
1474
1512
|
useMemo as useMemo6,
|
|
1475
1513
|
useRef as useRef4,
|
|
@@ -1481,18 +1519,18 @@ import {
|
|
|
1481
1519
|
Raycaster as Raycaster2,
|
|
1482
1520
|
SphereGeometry,
|
|
1483
1521
|
Vector2 as Vector22,
|
|
1484
|
-
Vector3 as
|
|
1522
|
+
Vector3 as Vector38
|
|
1485
1523
|
} from "three";
|
|
1486
1524
|
|
|
1487
1525
|
// src/render/resample.ts
|
|
1488
|
-
import { Vector3 as
|
|
1526
|
+
import { Vector3 as Vector37 } from "three";
|
|
1489
1527
|
var ON_PLANE = 1e-7;
|
|
1490
1528
|
var STITCH = 1e-5;
|
|
1491
1529
|
var COLLINEAR = 1e-6;
|
|
1492
1530
|
function clipSegments(positions, plane) {
|
|
1493
1531
|
const out = [];
|
|
1494
|
-
const a = new
|
|
1495
|
-
const b = new
|
|
1532
|
+
const a = new Vector37();
|
|
1533
|
+
const b = new Vector37();
|
|
1496
1534
|
const count = Math.floor(positions.length / 6);
|
|
1497
1535
|
for (let i = 0; i < count; i += 1) {
|
|
1498
1536
|
a.set(positions[i * 6], positions[i * 6 + 1], positions[i * 6 + 2]);
|
|
@@ -1507,11 +1545,11 @@ function clipSegments(positions, plane) {
|
|
|
1507
1545
|
return Float32Array.from(out);
|
|
1508
1546
|
}
|
|
1509
1547
|
function sectionContour(positions, regionOf, plane) {
|
|
1510
|
-
const a = new
|
|
1511
|
-
const b = new
|
|
1512
|
-
const c = new
|
|
1513
|
-
const p = new
|
|
1514
|
-
const q = new
|
|
1548
|
+
const a = new Vector37();
|
|
1549
|
+
const b = new Vector37();
|
|
1550
|
+
const c = new Vector37();
|
|
1551
|
+
const p = new Vector37();
|
|
1552
|
+
const q = new Vector37();
|
|
1515
1553
|
const byRegion = /* @__PURE__ */ new Map();
|
|
1516
1554
|
const triangleCount = Math.floor(positions.length / 9);
|
|
1517
1555
|
for (let t = 0; t < triangleCount; t += 1) {
|
|
@@ -1569,17 +1607,17 @@ function stitch(segments, out) {
|
|
|
1569
1607
|
return into.set(segments[o], segments[o + 1], segments[o + 2]);
|
|
1570
1608
|
};
|
|
1571
1609
|
const direction = (i, into) => {
|
|
1572
|
-
const s = new
|
|
1573
|
-
const e = new
|
|
1610
|
+
const s = new Vector37();
|
|
1611
|
+
const e = new Vector37();
|
|
1574
1612
|
point(i, 0, s);
|
|
1575
1613
|
point(i, 1, e);
|
|
1576
1614
|
return into.subVectors(e, s).normalize();
|
|
1577
1615
|
};
|
|
1578
1616
|
const consumed = new Uint8Array(count);
|
|
1579
|
-
const d = new
|
|
1580
|
-
const n = new
|
|
1617
|
+
const d = new Vector37();
|
|
1618
|
+
const n = new Vector37();
|
|
1581
1619
|
const next = (i, end) => {
|
|
1582
|
-
const at = point(i, end, new
|
|
1620
|
+
const at = point(i, end, new Vector37());
|
|
1583
1621
|
const list = ends.get(key(at.x, at.y, at.z)) ?? [];
|
|
1584
1622
|
if (list.length !== 2) return null;
|
|
1585
1623
|
const other = list.find((entry) => entry >> 1 !== i);
|
|
@@ -1608,8 +1646,8 @@ function stitch(segments, out) {
|
|
|
1608
1646
|
};
|
|
1609
1647
|
const back = walk(0);
|
|
1610
1648
|
const forward = walk(1);
|
|
1611
|
-
const s = point(back.index, back.end, new
|
|
1612
|
-
const e = point(forward.index, forward.end, new
|
|
1649
|
+
const s = point(back.index, back.end, new Vector37());
|
|
1650
|
+
const e = point(forward.index, forward.end, new Vector37());
|
|
1613
1651
|
out.push(s.x, s.y, s.z, e.x, e.y, e.z);
|
|
1614
1652
|
}
|
|
1615
1653
|
}
|
|
@@ -1617,8 +1655,8 @@ function pointInContour(point, plane, contour) {
|
|
|
1617
1655
|
const [u, v] = planeAxes(plane);
|
|
1618
1656
|
const px = point.dot(u);
|
|
1619
1657
|
const py = point.dot(v);
|
|
1620
|
-
const a = new
|
|
1621
|
-
const b = new
|
|
1658
|
+
const a = new Vector37();
|
|
1659
|
+
const b = new Vector37();
|
|
1622
1660
|
let inside = false;
|
|
1623
1661
|
const count = Math.floor(contour.length / 6);
|
|
1624
1662
|
for (let i = 0; i < count; i += 1) {
|
|
@@ -1635,15 +1673,15 @@ function pointInContour(point, plane, contour) {
|
|
|
1635
1673
|
return inside;
|
|
1636
1674
|
}
|
|
1637
1675
|
function capHit(ray, plane, contour) {
|
|
1638
|
-
const point = ray.intersectPlane(plane, new
|
|
1676
|
+
const point = ray.intersectPlane(plane, new Vector37());
|
|
1639
1677
|
if (!point) return null;
|
|
1640
1678
|
return pointInContour(point, plane, contour) ? point : null;
|
|
1641
1679
|
}
|
|
1642
1680
|
function planeAxes(plane) {
|
|
1643
1681
|
const n = plane.normal;
|
|
1644
|
-
const seed = Math.abs(n.x) < 0.9 ? new
|
|
1645
|
-
const u = new
|
|
1646
|
-
const v = new
|
|
1682
|
+
const seed = Math.abs(n.x) < 0.9 ? new Vector37(1, 0, 0) : new Vector37(0, 1, 0);
|
|
1683
|
+
const u = new Vector37().crossVectors(n, seed).normalize();
|
|
1684
|
+
const v = new Vector37().crossVectors(n, u).normalize();
|
|
1647
1685
|
return [u, v];
|
|
1648
1686
|
}
|
|
1649
1687
|
function sampleSection(meshPositions, regionOf, edgePositions, plane) {
|
|
@@ -1676,11 +1714,11 @@ var MeasureTool = ({
|
|
|
1676
1714
|
const controlled = measurements !== void 0;
|
|
1677
1715
|
const list = controlled ? measurements : held;
|
|
1678
1716
|
const [draft, setDraft] = useState5([]);
|
|
1679
|
-
|
|
1717
|
+
useEffect6(() => {
|
|
1680
1718
|
store.setEngaged(true);
|
|
1681
1719
|
return () => store.setEngaged(false);
|
|
1682
1720
|
}, [store]);
|
|
1683
|
-
|
|
1721
|
+
useEffect6(() => {
|
|
1684
1722
|
setDraft([]);
|
|
1685
1723
|
}, [mode]);
|
|
1686
1724
|
const commit = (next) => {
|
|
@@ -1689,7 +1727,7 @@ var MeasureTool = ({
|
|
|
1689
1727
|
};
|
|
1690
1728
|
const latest = useRef4({ list, commit });
|
|
1691
1729
|
latest.current = { list, commit };
|
|
1692
|
-
|
|
1730
|
+
useEffect6(() => {
|
|
1693
1731
|
const onKey = (event) => {
|
|
1694
1732
|
if (event.key === "Escape") {
|
|
1695
1733
|
setDraft([]);
|
|
@@ -1753,7 +1791,7 @@ var MeasureTool = ({
|
|
|
1753
1791
|
] });
|
|
1754
1792
|
};
|
|
1755
1793
|
var NO_POINTER = { pointerEvents: "none" };
|
|
1756
|
-
var NOWHERE = [new
|
|
1794
|
+
var NOWHERE = [new Vector38(), new Vector38()];
|
|
1757
1795
|
var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
1758
1796
|
const camera = useThree6((state) => state.camera);
|
|
1759
1797
|
const scene = useThree6((state) => state.scene);
|
|
@@ -1774,7 +1812,7 @@ var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
|
1774
1812
|
}, []);
|
|
1775
1813
|
const current = useRef4({ mode, draft, onPlace, format, size });
|
|
1776
1814
|
current.current = { mode, draft, onPlace, format, size };
|
|
1777
|
-
|
|
1815
|
+
useEffect6(() => {
|
|
1778
1816
|
const raycaster = new Raycaster2();
|
|
1779
1817
|
const pointer = new Vector22();
|
|
1780
1818
|
const samples = new SampleCache();
|
|
@@ -1806,7 +1844,7 @@ var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
|
1806
1844
|
const snapped = snapAt(target, target.edges, camera, viewport);
|
|
1807
1845
|
const from = placed[placed.length - 1];
|
|
1808
1846
|
const lock = shift && from ? lockToAxis(from, snapped.point) : null;
|
|
1809
|
-
const found = lock ? { ...snapped, point: new
|
|
1847
|
+
const found = lock ? { ...snapped, point: new Vector38(lock.point.x, lock.point.y, lock.point.z), edge: null } : snapped;
|
|
1810
1848
|
snap.current = found;
|
|
1811
1849
|
const node = marker.current;
|
|
1812
1850
|
if (node) {
|
|
@@ -1880,7 +1918,7 @@ var Snapper = ({ mode, draft, onPlace, theme, format, label }) => {
|
|
|
1880
1918
|
window.removeEventListener("keyup", key);
|
|
1881
1919
|
};
|
|
1882
1920
|
}, [camera, domElement, invalidate, isTap, scene, theme.measure]);
|
|
1883
|
-
|
|
1921
|
+
useEffect6(() => {
|
|
1884
1922
|
if (draft.length === 0 && band.current) {
|
|
1885
1923
|
band.current.visible = false;
|
|
1886
1924
|
if (bandLabel.current) bandLabel.current.visible = false;
|
|
@@ -2114,7 +2152,7 @@ var DeltaLegs = ({ a, b, id, format, label }) => {
|
|
|
2114
2152
|
const lines = useRef4([]);
|
|
2115
2153
|
const centre = useMemo6(() => {
|
|
2116
2154
|
const at = midpoint(a, b);
|
|
2117
|
-
return new
|
|
2155
|
+
return new Vector38(at.x, at.y, at.z);
|
|
2118
2156
|
}, [a, b]);
|
|
2119
2157
|
useFrame2(() => {
|
|
2120
2158
|
const dash = screenLength(camera, centre, size, DELTA_DASH_PIXELS);
|
|
@@ -2136,8 +2174,8 @@ var DeltaLegs = ({ a, b, id, format, label }) => {
|
|
|
2136
2174
|
lines.current[index] = line;
|
|
2137
2175
|
},
|
|
2138
2176
|
points: [
|
|
2139
|
-
new
|
|
2140
|
-
new
|
|
2177
|
+
new Vector38(leg.from.x, leg.from.y, leg.from.z),
|
|
2178
|
+
new Vector38(leg.to.x, leg.to.y, leg.to.z)
|
|
2141
2179
|
],
|
|
2142
2180
|
color: AXIS_COLORS[leg.axis],
|
|
2143
2181
|
lineWidth: MEASURE_LINE_PIXELS.leg,
|
|
@@ -2173,7 +2211,7 @@ var ScreenDot = ({ point, pixels, color }) => {
|
|
|
2173
2211
|
const invalidate = useThree6((state) => state.invalidate);
|
|
2174
2212
|
const node = useRef4(null);
|
|
2175
2213
|
const dot = useDot();
|
|
2176
|
-
const position = useMemo6(() => new
|
|
2214
|
+
const position = useMemo6(() => new Vector38(point.x, point.y, point.z), [point]);
|
|
2177
2215
|
useFrame2(() => {
|
|
2178
2216
|
const group = node.current;
|
|
2179
2217
|
if (!group) return;
|
|
@@ -2188,7 +2226,7 @@ var ScreenDot = ({ point, pixels, color }) => {
|
|
|
2188
2226
|
var Segment = ({ points, color }) => {
|
|
2189
2227
|
const [a, b] = points;
|
|
2190
2228
|
const ends = useMemo6(
|
|
2191
|
-
() => [new
|
|
2229
|
+
() => [new Vector38(a.x, a.y, a.z), new Vector38(b.x, b.y, b.z)],
|
|
2192
2230
|
// Keyed on the numbers: a draft's tuple is a fresh array on every render,
|
|
2193
2231
|
// and a rebuilt array would rebuild the line's geometry with it.
|
|
2194
2232
|
[a.x, a.y, a.z, b.x, b.y, b.z]
|
|
@@ -2213,7 +2251,7 @@ var Polyline = ({ points, color }) => {
|
|
|
2213
2251
|
};
|
|
2214
2252
|
function useDot() {
|
|
2215
2253
|
const geometry = useMemo6(() => new SphereGeometry(1, 16, 12), []);
|
|
2216
|
-
|
|
2254
|
+
useEffect6(() => () => geometry.dispose(), [geometry]);
|
|
2217
2255
|
return geometry;
|
|
2218
2256
|
}
|
|
2219
2257
|
function isEditing(target) {
|
|
@@ -2230,7 +2268,7 @@ import { useMemo as useMemo7 } from "react";
|
|
|
2230
2268
|
import { DoubleSide as DoubleSide2 } from "three";
|
|
2231
2269
|
|
|
2232
2270
|
// src/render/tool-marks.ts
|
|
2233
|
-
import { Quaternion as Quaternion4, Vector2 as Vector23, Vector3 as
|
|
2271
|
+
import { Quaternion as Quaternion4, Vector2 as Vector23, Vector3 as Vector39 } from "three";
|
|
2234
2272
|
var TOOL_CORNER_STEPS = 12;
|
|
2235
2273
|
var TOOL_ROUND = 64;
|
|
2236
2274
|
function toolProfile(radius, corner, height) {
|
|
@@ -2250,9 +2288,9 @@ function toolProfile(radius, corner, height) {
|
|
|
2250
2288
|
points.push(new Vector23(radius, Math.max(height, rounded)));
|
|
2251
2289
|
return points;
|
|
2252
2290
|
}
|
|
2253
|
-
var UP = new
|
|
2254
|
-
var AXES = [new
|
|
2255
|
-
var toVector = ({ x, y, z }) => new
|
|
2291
|
+
var UP = new Vector39(0, 1, 0);
|
|
2292
|
+
var AXES = [new Vector39(1, 0, 0), new Vector39(0, 1, 0), new Vector39(0, 0, 1)];
|
|
2293
|
+
var toVector = ({ x, y, z }) => new Vector39(x, y, z);
|
|
2256
2294
|
var squareTo = (w, along) => {
|
|
2257
2295
|
const wanted = along ? toVector(along) : null;
|
|
2258
2296
|
const flat = wanted?.clone().addScaledVector(w, -wanted.dot(w));
|
|
@@ -2272,7 +2310,7 @@ function toolMarkShape(mark) {
|
|
|
2272
2310
|
if (!(mark.diameter > 0) || axis.lengthSq() === 0) return null;
|
|
2273
2311
|
const w = axis.normalize();
|
|
2274
2312
|
const u = squareTo(w, mark.across);
|
|
2275
|
-
const v = new
|
|
2313
|
+
const v = new Vector39().crossVectors(w, u);
|
|
2276
2314
|
const radius = mark.diameter / 2;
|
|
2277
2315
|
const corner = Math.min(Math.max(mark.cornerRadius ?? 0, 0), radius);
|
|
2278
2316
|
const height = Math.max(mark.height, corner);
|