partforge 0.146.4 → 0.149.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.
@@ -0,0 +1,40 @@
1
+ // partforge/gltf — the cached-preview writer. Worker-safe: no three.js, no DOM.
2
+
3
+ import type { SubPartDefinition } from "./part.js";
4
+
5
+ /** The slice of a part `encodePreviewGlb` reads; any `PartDefinition` satisfies it, so does a plain object. */
6
+ export interface PreviewPart {
7
+ parts?: Record<string, { display?: SubPartDisplay }>;
8
+ meta?: { background?: number; environment?: string };
9
+ }
10
+
11
+ type SubPartDisplay = NonNullable<SubPartDefinition["display"]>;
12
+
13
+ /** One sub-part's posed display mesh — the shape the viewer, the worker's `meshes` reply and `buildView` hold. */
14
+ export interface PreviewMesh {
15
+ /** The sub-part key; names the glTF node, mesh and material. */
16
+ name: string;
17
+ /** xyz triples in millimetres, Z-up, already posed. */
18
+ positions: Float32Array;
19
+ normals?: Float32Array | null;
20
+ /** Absent for a non-indexed soup (Manifold); OCCT sends indices. */
21
+ indices?: Uint32Array | null;
22
+ triangles?: number;
23
+ /** Ignored: feature edges are not encoded in this version. */
24
+ edges?: Float32Array | null;
25
+ }
26
+
27
+ export interface EncodePreviewInput {
28
+ /** At least one; a zero-length mesh gets no node. */
29
+ meshes: PreviewMesh[];
30
+ /** Read for `parts[name].display` (materials) and `meta.background` / `meta.environment`. */
31
+ part?: PreviewPart | null;
32
+ /** The view these meshes show; names the scene and lands in the file's extras as `partforgeView`. */
33
+ view?: string | null;
34
+ }
35
+
36
+ /** Bumped whenever the encoder writes different bytes for the same input. */
37
+ export const PREVIEW_ENCODER_VERSION: number;
38
+
39
+ /** Encode one view's posed meshes as a welded, quantized, meshopt-compressed GLB (Y-up, millimetres). Deterministic. */
40
+ export function encodePreviewGlb(input: EncodePreviewInput): Promise<Uint8Array>;
package/types/index.d.ts CHANGED
@@ -243,6 +243,17 @@ export interface MountOptions {
243
243
  * dropped, never fatal.
244
244
  */
245
245
  viewerState?: ViewerState | null;
246
+ /**
247
+ * A cached preview GLB (from `partforge/gltf`'s `encodePreviewGlb`, or a previous
248
+ * runtime's `exportPreview()`) drawn before the worker is ready and replaced in
249
+ * place, sub-part by sub-part, by the first live build — the camera is kept.
250
+ * Only a file for the view the viewer opens on is drawn, and only meshes named
251
+ * for that view's sub-parts; a file for another view, or one that will not
252
+ * decode, is logged once and ignored. A file written without a view (no `view`
253
+ * given to `encodePreviewGlb`) is drawn on sub-part name match alone, for any view.
254
+ * Carries no edge lines.
255
+ */
256
+ preview?: Uint8Array | ArrayBuffer | null;
246
257
  /**
247
258
  * A previous mount's `runtime.getPanelState()`: the transient state of the
248
259
  * part's custom controls (a selected tile), keyed by param. Same remount
@@ -613,6 +624,22 @@ export interface PartRuntime {
613
624
  * view-cube click, Reframe, or an animation cue).
614
625
  */
615
626
  getViewerState(): ViewerState;
627
+ /**
628
+ * True while the `preview` GLB is on screen: from the moment it decodes until a
629
+ * build delivers the whole view (a build error leaves it on). Picking, hover
630
+ * labels, measure, sketch and cutaway wait meanwhile; orbit, zoom, pan, the view
631
+ * cube, the view style and the rail work. Read it from the runtime each time —
632
+ * a copy of the handle freezes it.
633
+ */
634
+ readonly previewActive: boolean;
635
+ /**
636
+ * The view on screen as a preview GLB (`partforge/gltf`'s format), every
637
+ * sub-part posed exactly as drawn — what a later `mount({ preview })` shows
638
+ * before its kernel boots. Rejects while `previewActive`, before the view is
639
+ * fully built at the current params (a pending rebuild counts), for a `view`
640
+ * other than the one on screen, and after `dispose()`.
641
+ */
642
+ exportPreview(opts?: { view?: string }): Promise<Uint8Array>;
616
643
  /** Every custom control's non-empty transient state, keyed by param. Hand back as `panelState`. */
617
644
  getPanelState(): PanelState;
618
645
  /** What custom controls reported failing this mount, in order. */
@@ -698,6 +725,52 @@ export interface PartRuntime {
698
725
  /** Mount a full parametric-part app from a `PartDefinition`. */
699
726
  export function mount(part: PartDefinition, options: MountOptions): PartRuntime;
700
727
 
728
+ /** Options for `mountPreview`. */
729
+ export interface MountPreviewOptions {
730
+ /** A GLB from `partforge/gltf`'s `encodePreviewGlb`, or a runtime's `exportPreview()`. */
731
+ glb: Uint8Array | ArrayBuffer;
732
+ /** Optional viewer buttons, wired as `mount()` wires them; `#viewbar` inside the container is found by id. */
733
+ elements?: { chrome?: { reframe?: HTMLElement | null; theme?: HTMLElement | null } };
734
+ /** A previous runtime's `getViewerState()`; `cutaway` is ignored (a preview has no live solid). */
735
+ viewerState?: ViewerState | null;
736
+ }
737
+
738
+ /** The handle `mountPreview()` returns. Every method is safe before `ready` settles. */
739
+ export interface PreviewRuntime {
740
+ /** Resolves once the GLB is drawn; rejects when it will not decode or holds no meshes. */
741
+ ready: Promise<void>;
742
+ /** Full teardown. Idempotent. */
743
+ dispose(): void;
744
+ /** The view the file was written for (`null` until drawn, or when the file names none). */
745
+ getView(): string | null;
746
+ /** Camera, projection, render mode and environment; `cutaway` is always `null`. */
747
+ getViewerState(): ViewerState;
748
+ /** Apply a state (camera, projection, render mode, environment) now, or once drawn. */
749
+ setViewerState(state: ViewerState | null): void;
750
+ /** Park/unpark the viewer, as `PartRuntime.setActive`. */
751
+ setActive(active: boolean): void;
752
+ /** WebGL context loss. Returns an unsubscribe. */
753
+ onContextLost(listener: () => void): () => void;
754
+ /** Accepted and ignored — there is no rail. */
755
+ setHostPane(pane: HostPane): void;
756
+ /** Accepted and ignored — there is no rail. */
757
+ setRailLayout(layout: HostRailLayout): void;
758
+ renderMode: {
759
+ get(): RenderMode;
760
+ set(mode: RenderMode): Promise<RenderMode>;
761
+ onChange(cb: (e: RenderModeEvent) => void): () => void;
762
+ };
763
+ environment: {
764
+ get(): string;
765
+ set(id: string): Promise<string>;
766
+ onChange(cb: (id: string) => void): () => void;
767
+ list(): Array<{ id: string; label: string }>;
768
+ };
769
+ }
770
+
771
+ /** A kernel-free viewer for a cached preview GLB: the viewer, view cube, view style and theme — no part, no worker, no rail. */
772
+ export function mountPreview(container: HTMLElement, options: MountPreviewOptions): PreviewRuntime;
773
+
701
774
  /** Every format `exportParts` can write in this version (`runtime.listExportFormats()` returns copies). */
702
775
  export const EXPORT_FORMATS: ReadonlyArray<ExportFormatInfo>;
703
776
 
@@ -729,3 +802,10 @@ export function viewSubParts(
729
802
  params: Record<string, ParamValue>,
730
803
  ): string[];
731
804
 
805
+ /**
806
+ * The view `mount()` opens on: a view flagged `default: true`, else the one
807
+ * placing the most sub-parts at the part's defaults (ties keep declaration
808
+ * order). `null` for a part with no views. Exported so a host building a part
809
+ * outside the viewer — a cached preview — opens the same view.
810
+ */
811
+ export function resolveDefaultView(part: PartDefinition): string | null;
@@ -869,3 +869,6 @@ export function annotationRay(
869
869
  ): AnnotationRay;
870
870
  /** Intersect a ray with a plane; null on parallel / behind-origin misses. */
871
871
  export function rayPlane(ray: AnnotationRay, plane: PlaneSpec): RayPlaneHit | null;
872
+
873
+ /** The view `mount()` opens on (see the main entry's declaration). */
874
+ export function resolveDefaultView(part: PartDefinition): string | null;