@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
package/README.md
CHANGED
|
@@ -306,6 +306,7 @@ the part opaque. For multiselection, update your own tag array and avoid duplica
|
|
|
306
306
|
| `Viewer` | Canvas, camera, lighting, controls, initial framing, and viewer-owned section state. |
|
|
307
307
|
| `EnginePart` | Validated Engine report plus cached mesh loading; imports from `/engine`. |
|
|
308
308
|
| `PartMesh` | Your normalized model and prepared geometry; selection, paint, picking, sections. |
|
|
309
|
+
| `ExplodedPart` | Supplied surface groups, translations, colors, and controlled explosion amount. |
|
|
309
310
|
| `ViewCube` | 26 orientation targets: faces, edges, and corners. |
|
|
310
311
|
| `Grid`, `Axes` | Reference geometry excluded from camera framing. |
|
|
311
312
|
| `DirectionArrows` | Candidate and optional named/preview machining directions. |
|
|
@@ -331,6 +332,7 @@ the part opaque. For multiselection, update your own tag array and avoid duplica
|
|
|
331
332
|
| `showOrbitTarget` | `false` | Show the pivot marker. |
|
|
332
333
|
| `theme` | Default lighting | Override lighting; part/cube/tool colors have their own theme props. |
|
|
333
334
|
| `onPointerMissed` | — | Empty-space primary click, with drag guarding; use it to clear selection. |
|
|
335
|
+
| `webglUnavailable` | Default message | Content of the alert shown instead of the canvas when WebGL is unavailable. |
|
|
334
336
|
| `style`, `className` | Full-size wrapper | Set dimensions and background on the wrapper or parent. |
|
|
335
337
|
| `ref` | — | `ViewerHandle` for controls outside the canvas. |
|
|
336
338
|
|
|
@@ -340,6 +342,13 @@ the part opaque. For multiselection, update your own tag array and avoid duplica
|
|
|
340
342
|
Named views are `top`, `bottom`, `front`, `back`, `left`, `right`, and `isometric`.
|
|
341
343
|
Direction vectors point from the part toward the camera.
|
|
342
344
|
|
|
345
|
+
`Viewer` checks for WebGL2 once per page, on the client. If the browser will not create a context
|
|
346
|
+
(hardware acceleration off or the GPU blocklisted), it renders a `role="alert"`
|
|
347
|
+
element (`viewer-webgl-unavailable`, `data-viewer-webgl-unavailable="true"`) in
|
|
348
|
+
place of the canvas, asking the user to turn on graphics acceleration; children are
|
|
349
|
+
not rendered. Pass `webglUnavailable` to replace that message. Server rendering assumes
|
|
350
|
+
WebGL is available; the check runs on the client after hydration.
|
|
351
|
+
|
|
343
352
|
#### CAD controls
|
|
344
353
|
|
|
345
354
|
| Preset | Rotate | Pan | Zoom |
|
|
@@ -375,6 +384,7 @@ fails or is absent. It does not fetch a report or start an Engine job.
|
|
|
375
384
|
| `activeDirection` | Candidate-direction index; `null`/omitted means all directions. |
|
|
376
385
|
| `display`, `showEdges` | `solid` or `wireframe`; outlines default on. Wireframe always shows semantic face boundaries, not triangle diagonals. |
|
|
377
386
|
| `sharpCorners` | `{ features: tags }` for externally flagged features, or `null`. |
|
|
387
|
+
| `threads` | `{ threads: marks }` to draw threads in their holes, or `null`. See "Showing threads". |
|
|
378
388
|
| `section`, `onSectionChange` | Controlled section options and change reporting. Omit `section` to follow the viewer's section store. |
|
|
379
389
|
| `onAdjacency` | Receive touching-region sets for the prepared mesh. |
|
|
380
390
|
| `theme` | Partial `ViewerTheme` for the part. |
|
|
@@ -385,6 +395,118 @@ has `best === null`. `owners` still carries all owners. `directionHighlights(mod
|
|
|
385
395
|
index)` produces region paint matching `DirectionArrows`; it does not hide geometry
|
|
386
396
|
or establish that an unpainted face is impossible to machine.
|
|
387
397
|
|
|
398
|
+
### `<ExplodedPart>`
|
|
399
|
+
|
|
400
|
+
Renders application-defined surface pieces inside `<Viewer>` or an R3F canvas. Import
|
|
401
|
+
`ExplodedPart`, `ExplodedPartProps`, `ExplodeGroup`, `ExplodeGroupIds`, `ExplodeInput`,
|
|
402
|
+
`ExplodePick`, `ExplodeRegionColors`, `createExplodeAmount`, and `ExplodeAmount` from
|
|
403
|
+
`@toolpath/viewer`. Version 2.5.0 does not contain these exports.
|
|
404
|
+
|
|
405
|
+
The application supplies the pieces and their translations. The renderer neither selects
|
|
406
|
+
feature interpretations nor chooses machining directions, setups, or an ownership policy for
|
|
407
|
+
overlapping surfaces. It reads no planning data and makes no API requests.
|
|
408
|
+
|
|
409
|
+
```tsx
|
|
410
|
+
import { useMemo, useState } from 'react'
|
|
411
|
+
import { ExplodedPart, Viewer, type ExplodeGroup, type PartModel } from '@toolpath/viewer'
|
|
412
|
+
import type { BufferGeometry } from 'three'
|
|
413
|
+
|
|
414
|
+
const ExplodeView = ({
|
|
415
|
+
model,
|
|
416
|
+
geometry,
|
|
417
|
+
groups,
|
|
418
|
+
amount,
|
|
419
|
+
}: {
|
|
420
|
+
model: PartModel
|
|
421
|
+
geometry: BufferGeometry
|
|
422
|
+
groups: readonly ExplodeGroup[]
|
|
423
|
+
amount: number
|
|
424
|
+
}) => {
|
|
425
|
+
const [selected, select] = useState<string | null>(null)
|
|
426
|
+
const [hovered, hover] = useState<string | null>(null)
|
|
427
|
+
const explode = useMemo(() => ({ groups, amount }), [groups, amount])
|
|
428
|
+
return (
|
|
429
|
+
<Viewer>
|
|
430
|
+
<ExplodedPart
|
|
431
|
+
model={model}
|
|
432
|
+
geometry={geometry}
|
|
433
|
+
explode={explode}
|
|
434
|
+
selected={selected}
|
|
435
|
+
hovered={hovered}
|
|
436
|
+
onPick={(pick) => select(pick.explodeGroupId)}
|
|
437
|
+
onHover={(pick) => hover(pick?.explodeGroupId ?? null)}
|
|
438
|
+
/>
|
|
439
|
+
</Viewer>
|
|
440
|
+
)
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Each `ExplodeGroup` contains a unique `id`, `regionIdxs`, an `offset: { x, y, z }` in
|
|
445
|
+
millimetres in the source geometry's frame, and a numeric RGB `color`. IDs belong to the
|
|
446
|
+
application and need not be feature tags. Groups may contain any region set, and different
|
|
447
|
+
groups can share the same surfaces without being merged. Region IDs must come from the same
|
|
448
|
+
model and mesh. Source geometry must be non-indexed and match `model.mesh.triangleCount`.
|
|
449
|
+
An empty `groups` array draws nothing. Invalid IDs, regions, or offsets throw before allocation.
|
|
450
|
+
|
|
451
|
+
`explode.amount` interpolates all supplied offsets from zero to their full translations;
|
|
452
|
+
values outside `[0, 1]` are clamped and nonfinite amounts use zero. The caller owns animation,
|
|
453
|
+
timing, and reduced-motion preferences. Pass a number for ordinary controlled React updates.
|
|
454
|
+
For frame-by-frame animation, create a stable controller with `createExplodeAmount(initial)`
|
|
455
|
+
and pass it as `explode.amount`:
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
const [amount] = useState(() => createExplodeAmount(0))
|
|
459
|
+
const explode = useMemo(() => ({ groups, amount }), [groups, amount])
|
|
460
|
+
// From the application's animation loop, slider, or animation library:
|
|
461
|
+
amount.set(0.5)
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
The controller clamps its value to `[0, 1]`, exposes it as `amount.value`, and notifies
|
|
465
|
+
subscribers only when it changes. `ExplodedPart` subscribes and requests a frame automatically,
|
|
466
|
+
including on a demand-driven canvas, without React updates on every frame. Subscriptions are
|
|
467
|
+
removed on unmount or when the controller changes; one controller can drive multiple viewers.
|
|
468
|
+
The application owns scheduling and cancelling its animation loop. The renderer never moves
|
|
469
|
+
the camera. Fit and Reset remain explicit.
|
|
470
|
+
|
|
471
|
+
Keep the `groups` array stable across amount, selection, and color changes. An optional
|
|
472
|
+
`explode.colors: ReadonlyMap<string, number>` changes colors by group ID without rebuilding
|
|
473
|
+
the layout. Optional `explode.regionColors: ExplodeRegionColors` (a
|
|
474
|
+
`ReadonlyMap<string, ReadonlyMap<number, number>>`) sets colors by group ID and source region index, overriding that group's color. The same
|
|
475
|
+
source region may have different colors in different groups. Regions without an override use
|
|
476
|
+
`explode.colors` or the group's own color; selection and hover tint all of a group's surfaces.
|
|
477
|
+
Replace color maps when changing paint. Unknown group/region keys are ignored. Color changes
|
|
478
|
+
retain geometry buffers, pick identities, and shader programs; they do not require one group
|
|
479
|
+
per region. `visible={false}` retains its buffers while excluding it from rendering, picking,
|
|
480
|
+
and framing. Optional `onReady` runs after warming shaders and buffers for a layout; an app can
|
|
481
|
+
keep it hidden or disable its play control until then. Changing the source or group array
|
|
482
|
+
rebuilds the owned buffers; unmounting releases them without disposing the source geometry.
|
|
483
|
+
Batching uses per-instance colors where Three.js provides them and shared vertex colors on
|
|
484
|
+
earlier supported Three.js releases.
|
|
485
|
+
|
|
486
|
+
Pass `theme?: Partial<ViewerTheme>` to match the surrounding application. `part` colors
|
|
487
|
+
the source ghost, `partEmissive` sets emissive lighting, and `edge`/`edgeOpacity` control
|
|
488
|
+
the outlines (the ghost outline fades further with the explosion). `highlight` tints the
|
|
489
|
+
selected piece, `picked` colors its source surfaces, and `hover` tints the hovered piece. Group colors and
|
|
490
|
+
`explode.colors` remain application-owned. Omit the theme to retain the default explode
|
|
491
|
+
appearance. Theme changes update materials and colors in place without rebuilding geometry,
|
|
492
|
+
changing selection, warming shaders again, or moving the camera.
|
|
493
|
+
|
|
494
|
+
The source part is drawn as an unpickable ghost during explosion. Selecting a group highlights
|
|
495
|
+
its original surfaces and draws one connector. `selected` and `hovered` also accept arrays of
|
|
496
|
+
group IDs, so an application can interact with several render chunks as one logical piece.
|
|
497
|
+
Selection highlights all their source surfaces; one connector joins their combined source and
|
|
498
|
+
translated bounds. `onPick` and `onHover` return an `ExplodePick`:
|
|
499
|
+
the usual source `region` and `triangleIndex`, the application's `explodeGroupId`, the displayed
|
|
500
|
+
world-space `point`/`normal`, and `modelPoint` in the original geometry's frame. Region owners
|
|
501
|
+
and the default ranked feature remain available as `PartPick` fields; applications can use
|
|
502
|
+
the group ID to supply their own metadata. Pass `activeDirection`, as on `<PartMesh>`, to rank
|
|
503
|
+
those owners for one machining direction. Hidden groups and source overlays do not accept picks.
|
|
504
|
+
|
|
505
|
+
At stationary zero, the example gives rendering and picking back to its ordinary `PartMesh`.
|
|
506
|
+
That assembled/exploded mode switch and its toolbar are application UI. The example's candidate
|
|
507
|
+
grouping, colors, translation spacing, and rendering-budget policy stay in
|
|
508
|
+
`examples/react-viewer/src/explode/` and are not exported by the package.
|
|
509
|
+
|
|
388
510
|
### `<ViewCube>`, `<Grid>`, and `<Axes>`
|
|
389
511
|
|
|
390
512
|
`ViewCube` defaults to `alignment="top-right"` and `margin={[80, 80]}` (pixels).
|
|
@@ -468,7 +590,7 @@ With no children, `ViewerToolbar` renders configured controls in standard order.
|
|
|
468
590
|
For custom composition use `ViewerToolbar.Controls`, `ViewerToolbar.Divider`, and
|
|
469
591
|
its `*Button` components. A button without a matching provider control throws.
|
|
470
592
|
The supported action names are `stock`, `axes`, `grid`, `banana`, `tools`,
|
|
471
|
-
`directions`, `dfm`, `sharpCorners`, `hover`, `focus`, `wireframe`, `section`,
|
|
593
|
+
`directions`, `dfm`, `sharpCorners`, `threads`, `hover`, `focus`, `wireframe`, `section`,
|
|
472
594
|
`measure`, `fit`, `reset`, and `top`; button names capitalize the action, such as
|
|
473
595
|
`ViewerToolbar.SharpCornersButton`. `useViewerToolbar()` reads those controls.
|
|
474
596
|
|
|
@@ -670,6 +792,19 @@ axis legs also have `data-axis`, and finished labels have `data-measurement-id`.
|
|
|
670
792
|
millimetres; the `format(mm)` callback changes their displayed string, not geometry
|
|
671
793
|
units or angles (which remain degrees).
|
|
672
794
|
|
|
795
|
+
### Showing threads
|
|
796
|
+
|
|
797
|
+
The Engine cuts a modeled internal thread out of the mesh, so a tapped hole arrives as a
|
|
798
|
+
plain bore. Pass `threads={{ threads: marks }}` to draw each thread back in as shading
|
|
799
|
+
over its hole's cylinders, at its pitch and hand. Build a mark from a hole's Engine
|
|
800
|
+
datasheet with `threadMark(feature, datasheet)` from `@toolpath/viewer/engine`; it is
|
|
801
|
+
`null` unless the datasheet carries a thread, so only threads the Engine reports are
|
|
802
|
+
drawn. A `ThreadMark` is `{ regions, pitch, majorDiameter }`: `pitch` is in mm and
|
|
803
|
+
negative for a left-hand thread, and cylinders wider than `majorDiameter` (a counterbore)
|
|
804
|
+
stay plain. The axis is fitted from the mesh, so marks need no coordinates. The datasheet
|
|
805
|
+
gives no thread length, so a tap-drill section of the same bore below the thread is
|
|
806
|
+
drawn threaded too.
|
|
807
|
+
|
|
673
808
|
### Showing sharp corners and tool marks
|
|
674
809
|
|
|
675
810
|
DFM decisions belong to the application. Pass flagged feature tags as
|
|
@@ -719,9 +854,9 @@ Part keys include `part`, `partEmissive`, `hover`, `highlight`, `picked`, `edge`
|
|
|
719
854
|
use `measure`/`measureSnap`; cube keys are `cube`, `cubeEdge`, and `cubeLabel`.
|
|
720
855
|
The canvas background comes from the wrapper/parent, independently of those colors.
|
|
721
856
|
|
|
722
|
-
Stable DOM classes include `viewer-root`, `viewer-
|
|
723
|
-
`viewer-canvas-
|
|
724
|
-
`viewer-toolbar`, `viewer-toolbar-button`, `viewer-toolbar-icon`,
|
|
857
|
+
Stable DOM classes include `viewer-root`, `viewer-webgl-unavailable`,
|
|
858
|
+
`viewer-canvas-container`, `viewer-canvas-frame`, `viewer-canvas`, `viewer-hover-card`,
|
|
859
|
+
`viewer-toolbar-stack`, `viewer-toolbar`, `viewer-toolbar-button`, `viewer-toolbar-icon`,
|
|
725
860
|
`viewer-toolbar-tooltip`, and `viewer-toolbar-divider`. Caller `className` values
|
|
726
861
|
append to the component's hook. Corresponding `data-viewer-*` attributes identify
|
|
727
862
|
the DOM boundaries; `data-viewer-toolbar-action` contains the control's action name.
|