@selvajs/compute 3.1.0-beta.3 → 3.1.0-beta.5
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/dist/chunk-54O6BO24.js +4 -0
- package/dist/chunk-54O6BO24.js.map +1 -0
- package/dist/chunk-7KFBCOZM.cjs +2 -0
- package/dist/chunk-7KFBCOZM.cjs.map +1 -0
- package/dist/chunk-EZRBMUXT.cjs +62 -0
- package/dist/chunk-EZRBMUXT.cjs.map +1 -0
- package/dist/chunk-GF6ZIJWX.cjs +4 -0
- package/dist/chunk-GF6ZIJWX.cjs.map +1 -0
- package/dist/chunk-ORGJSKR4.js +62 -0
- package/dist/chunk-ORGJSKR4.js.map +1 -0
- package/dist/chunk-PJATLYMU.js +2 -0
- package/dist/chunk-PJATLYMU.js.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +40 -3
- package/dist/core.d.ts +40 -3
- package/dist/core.js +1 -1
- package/dist/grasshopper.cjs +1 -1
- package/dist/grasshopper.cjs.map +1 -1
- package/dist/grasshopper.d.cts +220 -20
- package/dist/grasshopper.d.ts +220 -20
- package/dist/grasshopper.js +1 -1
- package/dist/{handle-files-9pkEgDIp.d.cts → handle-files-DMnx92gr.d.cts} +46 -10
- package/dist/{handle-files-9pkEgDIp.d.ts → handle-files-DMnx92gr.d.ts} +46 -10
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/{types-V7G83j5m.d.cts → types-C9YpTbr3.d.cts} +27 -6
- package/dist/{types-V7G83j5m.d.ts → types-C9YpTbr3.d.ts} +27 -6
- package/dist/{types-B-JygDUF.d.ts → types-Ci8Z0-hF.d.cts} +92 -20
- package/dist/{types-DGeAQnkB.d.cts → types-DuOh5XqS.d.ts} +92 -20
- package/dist/visualization-C3YOGQTW.js +2 -0
- package/dist/visualization-CERJ6XDX.cjs +2 -0
- package/dist/visualization-CERJ6XDX.cjs.map +1 -0
- package/dist/visualization.cjs +1 -1
- package/dist/visualization.d.cts +104 -13
- package/dist/visualization.d.ts +104 -13
- package/dist/visualization.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-CTZ4ZOSM.js +0 -2
- package/dist/chunk-CTZ4ZOSM.js.map +0 -1
- package/dist/chunk-EUMIGWRX.cjs +0 -4
- package/dist/chunk-EUMIGWRX.cjs.map +0 -1
- package/dist/chunk-HNG75VAI.js +0 -55
- package/dist/chunk-HNG75VAI.js.map +0 -1
- package/dist/chunk-JIE3W4KP.cjs +0 -2
- package/dist/chunk-JIE3W4KP.cjs.map +0 -1
- package/dist/chunk-L3CNT26S.cjs +0 -55
- package/dist/chunk-L3CNT26S.cjs.map +0 -1
- package/dist/chunk-QAOHGIFT.js +0 -4
- package/dist/chunk-QAOHGIFT.js.map +0 -1
- package/dist/visualization-SI2GEY4M.cjs +0 -2
- package/dist/visualization-SI2GEY4M.cjs.map +0 -1
- package/dist/visualization-UJZN4PJD.js +0 -2
- /package/dist/{visualization-UJZN4PJD.js.map → visualization-C3YOGQTW.js.map} +0 -0
package/dist/visualization.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
3
|
+
import { M as MaterialAppearanceOptions, f as GrasshopperComputeResponse, m as MeshExtractionOptions, n as MeshBatchParsingOptions, o as DisplayBatch, p as DisplayItem } from './types-Ci8Z0-hF.cjs';
|
|
4
|
+
export { q as DisplayCurve, r as DisplayIdentity, s as DisplayItemBase, t as DisplayPoint, u as DisplayPosition, v as MeshBatch } from './types-Ci8Z0-hF.cjs';
|
|
3
5
|
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
|
|
4
6
|
import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
|
|
5
|
-
import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as DisplayBatch, o as DisplayItem } from './types-DGeAQnkB.cjs';
|
|
6
|
-
export { p as DisplayCurve, q as DisplayIdentity, r as DisplayItemBase, s as DisplayPoint, t as DisplayPosition, u as MeshBatch } from './types-DGeAQnkB.cjs';
|
|
7
7
|
import { RhinoModule } from 'rhino3dm';
|
|
8
|
-
import './types-
|
|
8
|
+
import './types-C9YpTbr3.cjs';
|
|
9
9
|
|
|
10
10
|
type CameraConfig = {
|
|
11
11
|
position?: THREE.Vector3;
|
|
@@ -53,6 +53,16 @@ type RenderConfig = {
|
|
|
53
53
|
/** AO strength 0–1 when {@link RenderConfig.ambientOcclusion} is on. Default 1. */
|
|
54
54
|
aoIntensity?: number;
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* A coherent visual look. Seeds the initial render defaults (tone mapping, AO, edges, grid, IBL
|
|
58
|
+
* strength) at construction and can be re-applied live via `setRenderStyle`.
|
|
59
|
+
*
|
|
60
|
+
* - 'technical': matte, drawing-like — neutral tone mapping, low IBL, edges + grid on, AO on.
|
|
61
|
+
* Reads like a CAD shaded view (Rhino/Onshape).
|
|
62
|
+
* - 'rendered': presentation — ACES-filmic tone mapping, stronger IBL, edges off, AO on. Reads
|
|
63
|
+
* like a Keyshot/Fusion render.
|
|
64
|
+
*/
|
|
65
|
+
type RenderStyle = 'technical' | 'rendered';
|
|
56
66
|
/** Crisp boundary/crease edge overlays on meshes. See `addEdges`. */
|
|
57
67
|
type EdgesConfig = {
|
|
58
68
|
/** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
|
|
@@ -122,6 +132,13 @@ type MeasureConfig = {
|
|
|
122
132
|
};
|
|
123
133
|
type ThreeInitializerOptions = {
|
|
124
134
|
sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
|
|
135
|
+
/**
|
|
136
|
+
* Pick a coherent look up front — seeds sensible defaults for tone mapping, AO, edges, grid, and
|
|
137
|
+
* IBL strength (see {@link RenderStyle}). Individual `render`/`edges`/`grid` options still win
|
|
138
|
+
* when set explicitly, so this only fills in what you leave unspecified. Omit for the plain
|
|
139
|
+
* per-field defaults (no style applied). Re-apply later via the init result's `setRenderStyle`.
|
|
140
|
+
*/
|
|
141
|
+
renderStyle?: RenderStyle;
|
|
125
142
|
camera?: CameraConfig;
|
|
126
143
|
lighting?: LightingConfig;
|
|
127
144
|
environment?: EnvironmentConfig;
|
|
@@ -193,12 +210,20 @@ interface CameraController {
|
|
|
193
210
|
* singularity.
|
|
194
211
|
*/
|
|
195
212
|
setViewDirection(direction: THREE.Vector3, animate?: boolean): void;
|
|
213
|
+
/**
|
|
214
|
+
* Frame an arbitrary world-space box (e.g. a double-clicked object) from the current view
|
|
215
|
+
* direction, moving the *active* camera — in 2D mode that means resizing the ortho frustum, not
|
|
216
|
+
* just translating. No-op on an empty box.
|
|
217
|
+
*/
|
|
218
|
+
frameBounds(box: THREE.Box3, animate?: boolean): void;
|
|
196
219
|
/** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
|
|
197
220
|
setRotateEnabled(enabled: boolean): void;
|
|
198
221
|
/** Whether rotation is currently enabled. */
|
|
199
222
|
isRotateEnabled(): boolean;
|
|
200
223
|
/** Keep the orthographic frustum aspect in sync on canvas resize. Called by the resize loop. */
|
|
201
224
|
updateAspect(width: number, height: number): void;
|
|
225
|
+
/** Cancel any in-flight camera tween. Call on viewer teardown so ticks can't touch disposed controls. */
|
|
226
|
+
dispose(): void;
|
|
202
227
|
}
|
|
203
228
|
interface CameraControllerDeps {
|
|
204
229
|
scene: THREE.Scene;
|
|
@@ -265,14 +290,24 @@ declare function createGrid(options?: GridOptions): Grid;
|
|
|
265
290
|
*
|
|
266
291
|
* Caller responsibilities (mirror ViewHelper's own contract):
|
|
267
292
|
* - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
|
|
268
|
-
* - call {@link ViewGizmo.update} each frame (no-op now; kept for API symmetry),
|
|
269
293
|
* - forward pointer clicks to {@link ViewGizmo.handleClick}.
|
|
270
294
|
*/
|
|
271
295
|
interface ViewGizmo {
|
|
272
296
|
render(renderer: THREE.WebGLRenderer): void;
|
|
297
|
+
/**
|
|
298
|
+
* @deprecated No-op, kept only for API stability. This wrapper never uses ViewHelper's
|
|
299
|
+
* click→animate path (see module comment) — view changes snap instantly through the camera
|
|
300
|
+
* controller — so there is never a gizmo animation to advance. Safe to stop calling.
|
|
301
|
+
*/
|
|
273
302
|
update(delta: number): void;
|
|
274
303
|
/** Hit-test a click. Returns true if it hit the gizmo (and a view change started). */
|
|
275
304
|
handleClick(event: MouseEvent): boolean;
|
|
305
|
+
/**
|
|
306
|
+
* @deprecated Always `false`, kept only for API stability. Gizmo clicks snap the view
|
|
307
|
+
* instantly rather than animating (deliberately — ViewHelper's built-in animation assumes a
|
|
308
|
+
* Y-up world and rolls the view in this Z-up scene), so there is no animation window to gate
|
|
309
|
+
* input on.
|
|
310
|
+
*/
|
|
276
311
|
readonly isAnimating: boolean;
|
|
277
312
|
/** Show/hide the gizmo at runtime. Hidden = not rendered and not click-hittable. */
|
|
278
313
|
setVisible(visible: boolean): void;
|
|
@@ -375,6 +410,14 @@ interface MeasureDeps {
|
|
|
375
410
|
canvas: HTMLCanvasElement;
|
|
376
411
|
scene: THREE.Scene;
|
|
377
412
|
getActiveCamera: () => THREE.Camera;
|
|
413
|
+
/**
|
|
414
|
+
* The current orbit target (e.g. `controls.target`). Used to scale the line/point pick
|
|
415
|
+
* threshold with the view: the tolerance is a fraction of the camera→target distance, so it
|
|
416
|
+
* stays roughly constant on screen wherever the user has framed the model. Optional for
|
|
417
|
+
* backward compatibility — without it the perspective fallback is the camera's distance to the
|
|
418
|
+
* world origin, which misjudges the threshold for off-origin content. Thread it in when you can.
|
|
419
|
+
*/
|
|
420
|
+
getViewTarget?: () => THREE.Vector3;
|
|
378
421
|
labelLayer: LabelLayer;
|
|
379
422
|
options?: MeasureOptions;
|
|
380
423
|
}
|
|
@@ -412,6 +455,19 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
|
|
|
412
455
|
applyEdges: (root: THREE.Object3D) => void;
|
|
413
456
|
/** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
|
|
414
457
|
setAmbientOcclusion: (enabled: boolean) => void;
|
|
458
|
+
/**
|
|
459
|
+
* Apply a coherent look to the already-loaded scene: 'technical' (matte/CAD — edges, grid, low
|
|
460
|
+
* IBL, neutral tone mapping) or 'rendered' (presentation — stronger IBL, ACES tone mapping, no
|
|
461
|
+
* edges). Retunes viewer-owned dials only; per-material parse choices are set via the batch
|
|
462
|
+
* parser's `material` option. Handy for comparing the two looks in a live viewer.
|
|
463
|
+
*/
|
|
464
|
+
setRenderStyle: (style: "technical" | "rendered") => void;
|
|
465
|
+
/**
|
|
466
|
+
* The parse-time material options (backface culling, IBL strength) matching the active render
|
|
467
|
+
* style — feed into the batch parser's `material` option so freshly-loaded meshes are built to
|
|
468
|
+
* match the look. Returns undefined when no style is active. See `setRenderStyle`.
|
|
469
|
+
*/
|
|
470
|
+
getMaterialAppearance: () => MaterialAppearanceOptions | undefined;
|
|
415
471
|
/**
|
|
416
472
|
* Refit the sun's shadow frustum to the current scene content for crisp shadows. Call after
|
|
417
473
|
* loading or replacing geometry (e.g. after `updateScene`). No-op when sunlight/shadows are off.
|
|
@@ -470,6 +526,13 @@ declare const PLASTIC_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
|
470
526
|
declare const GLASS_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
471
527
|
declare const RUBBER_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
472
528
|
declare const WOOD_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
529
|
+
/**
|
|
530
|
+
* The module-scope singleton materials above, as a set. Scene-clearing code must NOT dispose a
|
|
531
|
+
* material in this set: they are shared across meshes and across solves, and `dispose()` on a
|
|
532
|
+
* still-referenced material forces a shader program rebuild on its next use (and would free any
|
|
533
|
+
* textures they gain later while other objects still use them).
|
|
534
|
+
*/
|
|
535
|
+
declare const SHARED_MATERIALS: ReadonlySet<THREE.Material>;
|
|
473
536
|
|
|
474
537
|
declare const threeMaterials_CONCRETE_MATERIAL: typeof CONCRETE_MATERIAL;
|
|
475
538
|
declare const threeMaterials_EMISSIVE_MATERIAL: typeof EMISSIVE_MATERIAL;
|
|
@@ -477,9 +540,10 @@ declare const threeMaterials_GLASS_MATERIAL: typeof GLASS_MATERIAL;
|
|
|
477
540
|
declare const threeMaterials_METAL_MATERIAL: typeof METAL_MATERIAL;
|
|
478
541
|
declare const threeMaterials_PLASTIC_MATERIAL: typeof PLASTIC_MATERIAL;
|
|
479
542
|
declare const threeMaterials_RUBBER_MATERIAL: typeof RUBBER_MATERIAL;
|
|
543
|
+
declare const threeMaterials_SHARED_MATERIALS: typeof SHARED_MATERIALS;
|
|
480
544
|
declare const threeMaterials_WOOD_MATERIAL: typeof WOOD_MATERIAL;
|
|
481
545
|
declare namespace threeMaterials {
|
|
482
|
-
export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
|
|
546
|
+
export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_SHARED_MATERIALS as SHARED_MATERIALS, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
|
|
483
547
|
}
|
|
484
548
|
|
|
485
549
|
/**
|
|
@@ -526,11 +590,18 @@ declare function removeEdges(root: THREE.Object3D): number;
|
|
|
526
590
|
* this when `render.ambientOcclusion` is enabled, and otherwise renders with a plain
|
|
527
591
|
* `renderer.render` so the cheap path stays cheap (the chosen tradeoff — see cad-viewer-plan.md).
|
|
528
592
|
*
|
|
529
|
-
* Pipeline: RenderPass → GTAOPass → OutputPass. GTAO (ground-truth AO) is the modern
|
|
530
|
-
* SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue.
|
|
531
|
-
* on so the AO radius is in screen space, which keeps it scale-robust across
|
|
532
|
-
* scenes without per-scene tuning.
|
|
533
|
-
*
|
|
593
|
+
* Pipeline: RenderPass → GTAOPass → SMAAPass → OutputPass. GTAO (ground-truth AO) is the modern
|
|
594
|
+
* replacement for SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue.
|
|
595
|
+
* `screenSpaceRadius` is on so the AO radius is in screen space, which keeps it scale-robust across
|
|
596
|
+
* the viewer's mm→m scenes without per-scene tuning.
|
|
597
|
+
*
|
|
598
|
+
* SMAA restores antialiasing on this path. The EffectComposer renders into an offscreen target, so
|
|
599
|
+
* the WebGLRenderer's own MSAA (`antialias: true`) does nothing here — without a dedicated AA pass,
|
|
600
|
+
* enabling AO would visibly *worsen* edge quality. SMAA is chosen over TAA because TAA's temporal
|
|
601
|
+
* jitter smears during OrbitControls drags; SMAA is single-frame, cheap, and stable while orbiting.
|
|
602
|
+
*
|
|
603
|
+
* OutputPass applies tone mapping + color space last (taking over the roles the renderer did
|
|
604
|
+
* directly in the non-composer path), so SMAA operates on the pre-tonemapped image as intended.
|
|
534
605
|
*
|
|
535
606
|
* Camera swaps: the active camera can flip perspective↔ortho. Rather than rebuild the composer, we
|
|
536
607
|
* retarget the passes' `camera` each render via {@link setCamera}.
|
|
@@ -551,6 +622,12 @@ interface RenderPipelineOptions {
|
|
|
551
622
|
}
|
|
552
623
|
declare function createRenderPipeline(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, width: number, height: number, options: RenderPipelineOptions): RenderPipeline;
|
|
553
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Metres per model unit, keyed by Rhino `UnitSystem` name (the `modelunits` string on the compute
|
|
627
|
+
* response). Imperial factors are the exact international definitions (1 in = 0.0254 m,
|
|
628
|
+
* 1 ft = 0.3048 m, 1 mi = 1609.344 m). Units not in this table scale 1 and log a one-time warning
|
|
629
|
+
* — see {@link getScaleFactor}.
|
|
630
|
+
*/
|
|
554
631
|
declare const SCALE_FACTORS: Record<string, number>;
|
|
555
632
|
/**
|
|
556
633
|
* Extracts and processes display meshes from a ComputePointerResponse using the Grasshopper WebDisplay component.
|
|
@@ -558,7 +635,9 @@ declare const SCALE_FACTORS: Record<string, number>;
|
|
|
558
635
|
* This is the primary entry point for extracting mesh geometry from Grasshopper compute responses.
|
|
559
636
|
* It handles all aspects of mesh processing: decompression, coordinate transformation, scaling, and positioning.
|
|
560
637
|
*
|
|
561
|
-
* **Note:**
|
|
638
|
+
* **Note:** The entire pipeline (base64 decode, inflate, dequantization, mesh construction) runs
|
|
639
|
+
* synchronously on the calling thread — large batches will block the UI for their duration. The
|
|
640
|
+
* function is `async` only so its shape can stay stable if parsing moves off-thread later.
|
|
562
641
|
*
|
|
563
642
|
* @param data - The ComputePointerResponse containing Grasshopper output trees.
|
|
564
643
|
* @param options - Configuration for mesh extraction and parsing behavior. All options are optional with sensible defaults.
|
|
@@ -569,7 +648,7 @@ declare const SCALE_FACTORS: Record<string, number>;
|
|
|
569
648
|
* - Only works with the WebDisplay component of GHHeadless.
|
|
570
649
|
* - Requires changes to Rhino.Compute (see https://github.com/TheVessen/compute.rhino3d).
|
|
571
650
|
* - Provides a performant way to display mesh data in Three.js.
|
|
572
|
-
* -
|
|
651
|
+
* - All decoding is synchronous on the main thread; there is no Web Worker offload today.
|
|
573
652
|
* - Supports mesh metadata (names, user data) if provided in the compute response.
|
|
574
653
|
*
|
|
575
654
|
* @internal Internal helper: high-level extraction remains public via visualization module, but this
|
|
@@ -614,9 +693,14 @@ interface ParseTelemetry {
|
|
|
614
693
|
* over the blob. The function stays `async` so callers don't have to change shape if we move
|
|
615
694
|
* parsing into a worker later.
|
|
616
695
|
*
|
|
696
|
+
* A batch with no `compressedData` (genuinely empty/absent geometry) resolves to `[]`. A corrupt,
|
|
697
|
+
* truncated, or unsupported blob throws so callers get a signal instead of a silent empty scene —
|
|
698
|
+
* `getThreeMeshesFromComputeResponse` documents (and now delivers) exactly that rethrow.
|
|
699
|
+
*
|
|
617
700
|
* @param batch - DisplayBatch object
|
|
618
701
|
* @param options - Rendering options
|
|
619
702
|
* @returns Promise resolving to array of Three.js mesh objects
|
|
703
|
+
* @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
|
|
620
704
|
*/
|
|
621
705
|
declare function parseMeshBatchObject(batch: DisplayBatch, options?: MeshBatchParsingOptions,
|
|
622
706
|
/** @internal Timings threaded from an outer entry point; not a caller option. */
|
|
@@ -632,13 +716,20 @@ telemetry?: ParseTelemetry): Promise<THREE.Mesh[]>;
|
|
|
632
716
|
* @param blob - Raw blob bytes from a binary WebSocket frame.
|
|
633
717
|
* @param options - Rendering options.
|
|
634
718
|
* @returns Promise resolving to array of Three.js mesh objects.
|
|
719
|
+
* @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
|
|
635
720
|
*/
|
|
636
721
|
declare function parseMeshBatchBlob(blob: ArrayBuffer | Uint8Array, options?: MeshBatchParsingOptions): Promise<THREE.Mesh[]>;
|
|
637
722
|
|
|
638
723
|
interface DisplayItemParseOptions {
|
|
639
724
|
/** rhino3dm instance for decoding curve JSON. Omit to skip curves (points still render). */
|
|
640
725
|
rhino?: RhinoModule;
|
|
641
|
-
/**
|
|
726
|
+
/**
|
|
727
|
+
* No-op. Historically toggled the Rhino Z-up → Three Y-up rotation, but the pipeline now keeps
|
|
728
|
+
* one coordinate frame end to end ({@link rhinoToThree} is the identity), so this flag no longer
|
|
729
|
+
* changes the result. Do NOT pre-rotate your own geometry to compensate — none is applied.
|
|
730
|
+
*
|
|
731
|
+
* @deprecated Retained only so existing call sites compile unchanged; has no effect.
|
|
732
|
+
*/
|
|
642
733
|
applyTransforms?: boolean;
|
|
643
734
|
}
|
|
644
735
|
/**
|
package/dist/visualization.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as THREE from 'three';
|
|
2
2
|
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
|
|
3
|
+
import { M as MaterialAppearanceOptions, f as GrasshopperComputeResponse, m as MeshExtractionOptions, n as MeshBatchParsingOptions, o as DisplayBatch, p as DisplayItem } from './types-DuOh5XqS.js';
|
|
4
|
+
export { q as DisplayCurve, r as DisplayIdentity, s as DisplayItemBase, t as DisplayPoint, u as DisplayPosition, v as MeshBatch } from './types-DuOh5XqS.js';
|
|
3
5
|
import { CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
|
|
4
6
|
import { LineSegments2 } from 'three/addons/lines/LineSegments2.js';
|
|
5
|
-
import { f as GrasshopperComputeResponse, M as MeshExtractionOptions, m as MeshBatchParsingOptions, n as DisplayBatch, o as DisplayItem } from './types-B-JygDUF.js';
|
|
6
|
-
export { p as DisplayCurve, q as DisplayIdentity, r as DisplayItemBase, s as DisplayPoint, t as DisplayPosition, u as MeshBatch } from './types-B-JygDUF.js';
|
|
7
7
|
import { RhinoModule } from 'rhino3dm';
|
|
8
|
-
import './types-
|
|
8
|
+
import './types-C9YpTbr3.js';
|
|
9
9
|
|
|
10
10
|
type CameraConfig = {
|
|
11
11
|
position?: THREE.Vector3;
|
|
@@ -53,6 +53,16 @@ type RenderConfig = {
|
|
|
53
53
|
/** AO strength 0–1 when {@link RenderConfig.ambientOcclusion} is on. Default 1. */
|
|
54
54
|
aoIntensity?: number;
|
|
55
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* A coherent visual look. Seeds the initial render defaults (tone mapping, AO, edges, grid, IBL
|
|
58
|
+
* strength) at construction and can be re-applied live via `setRenderStyle`.
|
|
59
|
+
*
|
|
60
|
+
* - 'technical': matte, drawing-like — neutral tone mapping, low IBL, edges + grid on, AO on.
|
|
61
|
+
* Reads like a CAD shaded view (Rhino/Onshape).
|
|
62
|
+
* - 'rendered': presentation — ACES-filmic tone mapping, stronger IBL, edges off, AO on. Reads
|
|
63
|
+
* like a Keyshot/Fusion render.
|
|
64
|
+
*/
|
|
65
|
+
type RenderStyle = 'technical' | 'rendered';
|
|
56
66
|
/** Crisp boundary/crease edge overlays on meshes. See `addEdges`. */
|
|
57
67
|
type EdgesConfig = {
|
|
58
68
|
/** Auto-attach edge overlays to meshes as they load. Default false (opt-in). */
|
|
@@ -122,6 +132,13 @@ type MeasureConfig = {
|
|
|
122
132
|
};
|
|
123
133
|
type ThreeInitializerOptions = {
|
|
124
134
|
sceneScale?: 'mm' | 'cm' | 'm' | 'inches' | 'feet';
|
|
135
|
+
/**
|
|
136
|
+
* Pick a coherent look up front — seeds sensible defaults for tone mapping, AO, edges, grid, and
|
|
137
|
+
* IBL strength (see {@link RenderStyle}). Individual `render`/`edges`/`grid` options still win
|
|
138
|
+
* when set explicitly, so this only fills in what you leave unspecified. Omit for the plain
|
|
139
|
+
* per-field defaults (no style applied). Re-apply later via the init result's `setRenderStyle`.
|
|
140
|
+
*/
|
|
141
|
+
renderStyle?: RenderStyle;
|
|
125
142
|
camera?: CameraConfig;
|
|
126
143
|
lighting?: LightingConfig;
|
|
127
144
|
environment?: EnvironmentConfig;
|
|
@@ -193,12 +210,20 @@ interface CameraController {
|
|
|
193
210
|
* singularity.
|
|
194
211
|
*/
|
|
195
212
|
setViewDirection(direction: THREE.Vector3, animate?: boolean): void;
|
|
213
|
+
/**
|
|
214
|
+
* Frame an arbitrary world-space box (e.g. a double-clicked object) from the current view
|
|
215
|
+
* direction, moving the *active* camera — in 2D mode that means resizing the ortho frustum, not
|
|
216
|
+
* just translating. No-op on an empty box.
|
|
217
|
+
*/
|
|
218
|
+
frameBounds(box: THREE.Box3, animate?: boolean): void;
|
|
196
219
|
/** Enable/disable orbit rotation at runtime (pan/zoom unaffected). */
|
|
197
220
|
setRotateEnabled(enabled: boolean): void;
|
|
198
221
|
/** Whether rotation is currently enabled. */
|
|
199
222
|
isRotateEnabled(): boolean;
|
|
200
223
|
/** Keep the orthographic frustum aspect in sync on canvas resize. Called by the resize loop. */
|
|
201
224
|
updateAspect(width: number, height: number): void;
|
|
225
|
+
/** Cancel any in-flight camera tween. Call on viewer teardown so ticks can't touch disposed controls. */
|
|
226
|
+
dispose(): void;
|
|
202
227
|
}
|
|
203
228
|
interface CameraControllerDeps {
|
|
204
229
|
scene: THREE.Scene;
|
|
@@ -265,14 +290,24 @@ declare function createGrid(options?: GridOptions): Grid;
|
|
|
265
290
|
*
|
|
266
291
|
* Caller responsibilities (mirror ViewHelper's own contract):
|
|
267
292
|
* - call {@link ViewGizmo.render} *after* the main scene render each frame (overlay viewport),
|
|
268
|
-
* - call {@link ViewGizmo.update} each frame (no-op now; kept for API symmetry),
|
|
269
293
|
* - forward pointer clicks to {@link ViewGizmo.handleClick}.
|
|
270
294
|
*/
|
|
271
295
|
interface ViewGizmo {
|
|
272
296
|
render(renderer: THREE.WebGLRenderer): void;
|
|
297
|
+
/**
|
|
298
|
+
* @deprecated No-op, kept only for API stability. This wrapper never uses ViewHelper's
|
|
299
|
+
* click→animate path (see module comment) — view changes snap instantly through the camera
|
|
300
|
+
* controller — so there is never a gizmo animation to advance. Safe to stop calling.
|
|
301
|
+
*/
|
|
273
302
|
update(delta: number): void;
|
|
274
303
|
/** Hit-test a click. Returns true if it hit the gizmo (and a view change started). */
|
|
275
304
|
handleClick(event: MouseEvent): boolean;
|
|
305
|
+
/**
|
|
306
|
+
* @deprecated Always `false`, kept only for API stability. Gizmo clicks snap the view
|
|
307
|
+
* instantly rather than animating (deliberately — ViewHelper's built-in animation assumes a
|
|
308
|
+
* Y-up world and rolls the view in this Z-up scene), so there is no animation window to gate
|
|
309
|
+
* input on.
|
|
310
|
+
*/
|
|
276
311
|
readonly isAnimating: boolean;
|
|
277
312
|
/** Show/hide the gizmo at runtime. Hidden = not rendered and not click-hittable. */
|
|
278
313
|
setVisible(visible: boolean): void;
|
|
@@ -375,6 +410,14 @@ interface MeasureDeps {
|
|
|
375
410
|
canvas: HTMLCanvasElement;
|
|
376
411
|
scene: THREE.Scene;
|
|
377
412
|
getActiveCamera: () => THREE.Camera;
|
|
413
|
+
/**
|
|
414
|
+
* The current orbit target (e.g. `controls.target`). Used to scale the line/point pick
|
|
415
|
+
* threshold with the view: the tolerance is a fraction of the camera→target distance, so it
|
|
416
|
+
* stays roughly constant on screen wherever the user has framed the model. Optional for
|
|
417
|
+
* backward compatibility — without it the perspective fallback is the camera's distance to the
|
|
418
|
+
* world origin, which misjudges the threshold for off-origin content. Thread it in when you can.
|
|
419
|
+
*/
|
|
420
|
+
getViewTarget?: () => THREE.Vector3;
|
|
378
421
|
labelLayer: LabelLayer;
|
|
379
422
|
options?: MeasureOptions;
|
|
380
423
|
}
|
|
@@ -412,6 +455,19 @@ declare const initThree: (canvas: HTMLCanvasElement, options?: ThreeInitializerO
|
|
|
412
455
|
applyEdges: (root: THREE.Object3D) => void;
|
|
413
456
|
/** Toggle ambient occlusion at runtime — builds or tears down the postprocessing pipeline. */
|
|
414
457
|
setAmbientOcclusion: (enabled: boolean) => void;
|
|
458
|
+
/**
|
|
459
|
+
* Apply a coherent look to the already-loaded scene: 'technical' (matte/CAD — edges, grid, low
|
|
460
|
+
* IBL, neutral tone mapping) or 'rendered' (presentation — stronger IBL, ACES tone mapping, no
|
|
461
|
+
* edges). Retunes viewer-owned dials only; per-material parse choices are set via the batch
|
|
462
|
+
* parser's `material` option. Handy for comparing the two looks in a live viewer.
|
|
463
|
+
*/
|
|
464
|
+
setRenderStyle: (style: "technical" | "rendered") => void;
|
|
465
|
+
/**
|
|
466
|
+
* The parse-time material options (backface culling, IBL strength) matching the active render
|
|
467
|
+
* style — feed into the batch parser's `material` option so freshly-loaded meshes are built to
|
|
468
|
+
* match the look. Returns undefined when no style is active. See `setRenderStyle`.
|
|
469
|
+
*/
|
|
470
|
+
getMaterialAppearance: () => MaterialAppearanceOptions | undefined;
|
|
415
471
|
/**
|
|
416
472
|
* Refit the sun's shadow frustum to the current scene content for crisp shadows. Call after
|
|
417
473
|
* loading or replacing geometry (e.g. after `updateScene`). No-op when sunlight/shadows are off.
|
|
@@ -470,6 +526,13 @@ declare const PLASTIC_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
|
470
526
|
declare const GLASS_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
471
527
|
declare const RUBBER_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
472
528
|
declare const WOOD_MATERIAL: THREE.MeshPhysicalMaterial;
|
|
529
|
+
/**
|
|
530
|
+
* The module-scope singleton materials above, as a set. Scene-clearing code must NOT dispose a
|
|
531
|
+
* material in this set: they are shared across meshes and across solves, and `dispose()` on a
|
|
532
|
+
* still-referenced material forces a shader program rebuild on its next use (and would free any
|
|
533
|
+
* textures they gain later while other objects still use them).
|
|
534
|
+
*/
|
|
535
|
+
declare const SHARED_MATERIALS: ReadonlySet<THREE.Material>;
|
|
473
536
|
|
|
474
537
|
declare const threeMaterials_CONCRETE_MATERIAL: typeof CONCRETE_MATERIAL;
|
|
475
538
|
declare const threeMaterials_EMISSIVE_MATERIAL: typeof EMISSIVE_MATERIAL;
|
|
@@ -477,9 +540,10 @@ declare const threeMaterials_GLASS_MATERIAL: typeof GLASS_MATERIAL;
|
|
|
477
540
|
declare const threeMaterials_METAL_MATERIAL: typeof METAL_MATERIAL;
|
|
478
541
|
declare const threeMaterials_PLASTIC_MATERIAL: typeof PLASTIC_MATERIAL;
|
|
479
542
|
declare const threeMaterials_RUBBER_MATERIAL: typeof RUBBER_MATERIAL;
|
|
543
|
+
declare const threeMaterials_SHARED_MATERIALS: typeof SHARED_MATERIALS;
|
|
480
544
|
declare const threeMaterials_WOOD_MATERIAL: typeof WOOD_MATERIAL;
|
|
481
545
|
declare namespace threeMaterials {
|
|
482
|
-
export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
|
|
546
|
+
export { threeMaterials_CONCRETE_MATERIAL as CONCRETE_MATERIAL, threeMaterials_EMISSIVE_MATERIAL as EMISSIVE_MATERIAL, threeMaterials_GLASS_MATERIAL as GLASS_MATERIAL, threeMaterials_METAL_MATERIAL as METAL_MATERIAL, threeMaterials_PLASTIC_MATERIAL as PLASTIC_MATERIAL, threeMaterials_RUBBER_MATERIAL as RUBBER_MATERIAL, threeMaterials_SHARED_MATERIALS as SHARED_MATERIALS, threeMaterials_WOOD_MATERIAL as WOOD_MATERIAL };
|
|
483
547
|
}
|
|
484
548
|
|
|
485
549
|
/**
|
|
@@ -526,11 +590,18 @@ declare function removeEdges(root: THREE.Object3D): number;
|
|
|
526
590
|
* this when `render.ambientOcclusion` is enabled, and otherwise renders with a plain
|
|
527
591
|
* `renderer.render` so the cheap path stays cheap (the chosen tradeoff — see cad-viewer-plan.md).
|
|
528
592
|
*
|
|
529
|
-
* Pipeline: RenderPass → GTAOPass → OutputPass. GTAO (ground-truth AO) is the modern
|
|
530
|
-
* SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue.
|
|
531
|
-
* on so the AO radius is in screen space, which keeps it scale-robust across
|
|
532
|
-
* scenes without per-scene tuning.
|
|
533
|
-
*
|
|
593
|
+
* Pipeline: RenderPass → GTAOPass → SMAAPass → OutputPass. GTAO (ground-truth AO) is the modern
|
|
594
|
+
* replacement for SSAO/SAO — better contact shadows in crevices, the "engineered" depth cue.
|
|
595
|
+
* `screenSpaceRadius` is on so the AO radius is in screen space, which keeps it scale-robust across
|
|
596
|
+
* the viewer's mm→m scenes without per-scene tuning.
|
|
597
|
+
*
|
|
598
|
+
* SMAA restores antialiasing on this path. The EffectComposer renders into an offscreen target, so
|
|
599
|
+
* the WebGLRenderer's own MSAA (`antialias: true`) does nothing here — without a dedicated AA pass,
|
|
600
|
+
* enabling AO would visibly *worsen* edge quality. SMAA is chosen over TAA because TAA's temporal
|
|
601
|
+
* jitter smears during OrbitControls drags; SMAA is single-frame, cheap, and stable while orbiting.
|
|
602
|
+
*
|
|
603
|
+
* OutputPass applies tone mapping + color space last (taking over the roles the renderer did
|
|
604
|
+
* directly in the non-composer path), so SMAA operates on the pre-tonemapped image as intended.
|
|
534
605
|
*
|
|
535
606
|
* Camera swaps: the active camera can flip perspective↔ortho. Rather than rebuild the composer, we
|
|
536
607
|
* retarget the passes' `camera` each render via {@link setCamera}.
|
|
@@ -551,6 +622,12 @@ interface RenderPipelineOptions {
|
|
|
551
622
|
}
|
|
552
623
|
declare function createRenderPipeline(renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, width: number, height: number, options: RenderPipelineOptions): RenderPipeline;
|
|
553
624
|
|
|
625
|
+
/**
|
|
626
|
+
* Metres per model unit, keyed by Rhino `UnitSystem` name (the `modelunits` string on the compute
|
|
627
|
+
* response). Imperial factors are the exact international definitions (1 in = 0.0254 m,
|
|
628
|
+
* 1 ft = 0.3048 m, 1 mi = 1609.344 m). Units not in this table scale 1 and log a one-time warning
|
|
629
|
+
* — see {@link getScaleFactor}.
|
|
630
|
+
*/
|
|
554
631
|
declare const SCALE_FACTORS: Record<string, number>;
|
|
555
632
|
/**
|
|
556
633
|
* Extracts and processes display meshes from a ComputePointerResponse using the Grasshopper WebDisplay component.
|
|
@@ -558,7 +635,9 @@ declare const SCALE_FACTORS: Record<string, number>;
|
|
|
558
635
|
* This is the primary entry point for extracting mesh geometry from Grasshopper compute responses.
|
|
559
636
|
* It handles all aspects of mesh processing: decompression, coordinate transformation, scaling, and positioning.
|
|
560
637
|
*
|
|
561
|
-
* **Note:**
|
|
638
|
+
* **Note:** The entire pipeline (base64 decode, inflate, dequantization, mesh construction) runs
|
|
639
|
+
* synchronously on the calling thread — large batches will block the UI for their duration. The
|
|
640
|
+
* function is `async` only so its shape can stay stable if parsing moves off-thread later.
|
|
562
641
|
*
|
|
563
642
|
* @param data - The ComputePointerResponse containing Grasshopper output trees.
|
|
564
643
|
* @param options - Configuration for mesh extraction and parsing behavior. All options are optional with sensible defaults.
|
|
@@ -569,7 +648,7 @@ declare const SCALE_FACTORS: Record<string, number>;
|
|
|
569
648
|
* - Only works with the WebDisplay component of GHHeadless.
|
|
570
649
|
* - Requires changes to Rhino.Compute (see https://github.com/TheVessen/compute.rhino3d).
|
|
571
650
|
* - Provides a performant way to display mesh data in Three.js.
|
|
572
|
-
* -
|
|
651
|
+
* - All decoding is synchronous on the main thread; there is no Web Worker offload today.
|
|
573
652
|
* - Supports mesh metadata (names, user data) if provided in the compute response.
|
|
574
653
|
*
|
|
575
654
|
* @internal Internal helper: high-level extraction remains public via visualization module, but this
|
|
@@ -614,9 +693,14 @@ interface ParseTelemetry {
|
|
|
614
693
|
* over the blob. The function stays `async` so callers don't have to change shape if we move
|
|
615
694
|
* parsing into a worker later.
|
|
616
695
|
*
|
|
696
|
+
* A batch with no `compressedData` (genuinely empty/absent geometry) resolves to `[]`. A corrupt,
|
|
697
|
+
* truncated, or unsupported blob throws so callers get a signal instead of a silent empty scene —
|
|
698
|
+
* `getThreeMeshesFromComputeResponse` documents (and now delivers) exactly that rethrow.
|
|
699
|
+
*
|
|
617
700
|
* @param batch - DisplayBatch object
|
|
618
701
|
* @param options - Rendering options
|
|
619
702
|
* @returns Promise resolving to array of Three.js mesh objects
|
|
703
|
+
* @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
|
|
620
704
|
*/
|
|
621
705
|
declare function parseMeshBatchObject(batch: DisplayBatch, options?: MeshBatchParsingOptions,
|
|
622
706
|
/** @internal Timings threaded from an outer entry point; not a caller option. */
|
|
@@ -632,13 +716,20 @@ telemetry?: ParseTelemetry): Promise<THREE.Mesh[]>;
|
|
|
632
716
|
* @param blob - Raw blob bytes from a binary WebSocket frame.
|
|
633
717
|
* @param options - Rendering options.
|
|
634
718
|
* @returns Promise resolving to array of Three.js mesh objects.
|
|
719
|
+
* @throws {RhinoComputeError} On a corrupt/truncated/unsupported mesh blob or malformed group metadata.
|
|
635
720
|
*/
|
|
636
721
|
declare function parseMeshBatchBlob(blob: ArrayBuffer | Uint8Array, options?: MeshBatchParsingOptions): Promise<THREE.Mesh[]>;
|
|
637
722
|
|
|
638
723
|
interface DisplayItemParseOptions {
|
|
639
724
|
/** rhino3dm instance for decoding curve JSON. Omit to skip curves (points still render). */
|
|
640
725
|
rhino?: RhinoModule;
|
|
641
|
-
/**
|
|
726
|
+
/**
|
|
727
|
+
* No-op. Historically toggled the Rhino Z-up → Three Y-up rotation, but the pipeline now keeps
|
|
728
|
+
* one coordinate frame end to end ({@link rhinoToThree} is the identity), so this flag no longer
|
|
729
|
+
* changes the result. Do NOT pre-rotate your own geometry to compensate — none is applied.
|
|
730
|
+
*
|
|
731
|
+
* @deprecated Retained only so existing call sites compile unchanged; has no effect.
|
|
732
|
+
*/
|
|
642
733
|
applyTransforms?: boolean;
|
|
643
734
|
}
|
|
644
735
|
/**
|
package/dist/visualization.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{J as h,K as c,L as v,M as j,a as e,b as r,c as t,d as o,e as i,f as a,g as s,h as p,i as n,j as l,k as f,l as m,m as y,n as u,o as d,p as x,u as C,v as g}from"./chunk-ORGJSKR4.js";import"./chunk-54O6BO24.js";export{n as EDGE_USERDATA_KIND,e as Materials,v as SCALE_FACTORS,l as addEdges,o as applyOffset,i as computeCombinedBoundingBox,a as createCameraController,s as createGrid,u as createLabelLayer,x as createMeasureTool,y as createRenderPipeline,p as createViewGizmo,j as getThreeMeshesFromComputeResponse,C as initThree,f as isEdgeOverlay,t as parseColor,g as parseDisplayItems,c as parseMeshBatchBlob,h as parseMeshBatchObject,m as removeEdges,d as snapToVertex,r as updateScene};
|
|
2
2
|
//# sourceMappingURL=visualization.js.map
|
package/package.json
CHANGED
package/dist/chunk-CTZ4ZOSM.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{b as l,c as h,d as f,e as d,h as U,i as z,k as $,l as A,m as _,n as q,r as N}from"./chunk-QAOHGIFT.js";function p(t,e){if(!t||typeof t!="object")return;let r=t;if(e in r)return r[e];let n=J(r).get(e.toLowerCase());return n===void 0?void 0:r[n]}function L(t,e){if(!t||typeof t!="object")return!1;let r=t;return e in r?!0:J(r).has(e.toLowerCase())}var H=new WeakMap;function J(t){let e=H.get(t);if(!e){e=new Map;for(let r of Object.keys(t)){let n=r.toLowerCase();e.has(n)||e.set(n,r)}H.set(t,e)}return e}function C(t,e){e||typeof window<"u"&&d().warn(`Warning: ${t} is running on the client side. For better performance and security, consider running this on the server side.`)}var Ie="Unable to load grasshopper definition";function xe(t){return t instanceof f?t.code===h.DEFINITION_NOT_CACHED||t.message.includes(Ie):!1}function Y(t,e){if(!e)return;let r=p(t,"values");if(!Array.isArray(r)||r.length===0)return;let n=[];for(let o of r){let a=p(o,"innerTree");(!a||Object.keys(a).length===0)&&n.push(p(o,"paramName")??"<unnamed>")}if(n.length===0)return;let s=n.length===r.length?"all":`${n.length}/${r.length}`;d().warn(`Solve returned empty output(s) (${s}): ${n.join(", ")}. These parameters produced no data \u2014 check the definition's inputs and the branch feeding each.`)}async function D(t,e,r){r.debug&&C("solveGrasshopperDefinition",r.suppressBrowserWarning??r.suppressClientSideWarning);let{response:n}=await O(P(e,t),r);return n}async function Q(t,e,r){return r.debug&&C("solveGrasshopperDefinitionWithCacheKey",r.suppressBrowserWarning??r.suppressClientSideWarning),O(P(e,t),r)}async function X(t,e,r,n){n.debug&&C("solveByCacheKey",n.suppressBrowserWarning??n.suppressClientSideWarning);let s={algo:null,pointer:e,values:t};try{return{...await O(s,n),missed:!1}}catch(o){if(!xe(o))throw o;return{...await O(P(r,t),n),missed:!0}}}async function O(t,e){De(t,e);let r=await A("grasshopper",t,e);if("pointer"in r){let{pointer:n,...s}=r,o=s;return Y(o,e.debug),{response:o,cacheKey:typeof n=="string"?n:null}}return Y(r,e.debug),{response:r,cacheKey:null}}function P(t,e){let r={algo:null,pointer:null,values:e};return t instanceof Uint8Array?r.algo=$(t):/^https?:\/\//i.test(t)?r.pointer=t:z(t)?r.algo=t:r.algo=U(t),r}function De(t,e){e.cachesolve!=null&&(t.cachesolve=e.cachesolve),e.cacheerroredsolves!=null&&(t.cacheerroredsolves=e.cacheerroredsolves),e.modelunits!=null&&(t.modelunits=e.modelunits),e.angletolerance!=null&&(t.angletolerance=e.angletolerance),e.absolutetolerance!=null&&(t.absolutetolerance=e.absolutetolerance),e.dataversion!=null&&(t.dataversion=e.dataversion)}function Pe(t){let e=new WeakSet,r=n=>{if(n==null)return JSON.stringify(n);if(typeof n=="number")return Number.isFinite(n)?String(n):JSON.stringify(null);if(typeof n=="string"||typeof n=="boolean")return JSON.stringify(n);if(typeof n=="bigint")return JSON.stringify(n.toString());if(n instanceof Uint8Array){let s=n.length>64?Array.from(n.slice(0,32)).concat(Array.from(n.slice(-32))):Array.from(n);return JSON.stringify({__u8:!0,len:n.length,sample:s})}return Array.isArray(n)?`[${n.map(r).join(",")}]`:typeof n=="object"?e.has(n)?JSON.stringify("[Circular]"):(e.add(n),`{${Object.keys(n).sort().map(a=>`${JSON.stringify(a)}:${r(n[a])}`).join(",")}}`):JSON.stringify(null)};return r(t)}function Z(t,e){let r=2166136261;for(let n=0;n<t;n++)r^=e(n),r=r+((r<<1)+(r<<4)+(r<<7)+(r<<8)+(r<<24))>>>0;return r.toString(16).padStart(8,"0")}function ee(t){return Z(t.length,e=>t.charCodeAt(e))}function Re(t){return Z(t.length,e=>t[e])}function te(t,e){return ee(`${W(t)}|${Pe(e)}`)}function W(t){return typeof t=="string"?`s:${t.length}:${ee(t)}`:`u8:${t.length}:${Re(t)}`}var we=100;function Ee(t){return t instanceof Uint8Array?!0:!/^https?:\/\//i.test(t)}var S=class{constructor(e,r,n={},s){l(this,"executor");l(this,"baseConfig");l(this,"mode");l(this,"maxConcurrent");l(this,"timeoutMs");l(this,"retry");l(this,"cacheEnabled");l(this,"cacheMax");l(this,"cacheTtl");l(this,"cache",new Map);l(this,"cacheKeyExecutor");l(this,"reuseServerDefinitionCache");l(this,"serverCacheKeys",new Map);l(this,"onStart");l(this,"onSettle");l(this,"onSuperseded");l(this,"subscribers",new Set);l(this,"inFlight",new Set);l(this,"pendingForLatestWins",null);l(this,"fifoQueue",[]);l(this,"_lastResult",null);l(this,"_lastError",null);l(this,"_lastDurationMs",null);l(this,"disposed",!1);this.executor=e,this.cacheKeyExecutor=s,this.baseConfig=r,this.mode=n.mode??"latest-wins",this.maxConcurrent=Math.max(1,n.maxConcurrent??(this.mode==="parallel"?4:1)),this.timeoutMs=n.timeoutMs,this.retry=n.retry;let o=n.cache;this.cacheEnabled=o!==void 0&&o!==!1;let a=typeof o=="object"?o:{};this.cacheMax=a.maxEntries??50,this.cacheTtl=a.ttlMs??0,this.reuseServerDefinitionCache=!!s&&(n.reuseServerDefinitionCache??!0),this.onStart=n.onStart,this.onSettle=n.onSettle,this.onSuperseded=n.onSuperseded}get isSolving(){return this.inFlight.size>0}get hasPending(){return this.pendingForLatestWins!==null||this.fifoQueue.length>0}get inFlightCount(){return this.inFlight.size}get queueDepth(){return this.fifoQueue.length+(this.pendingForLatestWins?1:0)}get lastResult(){return this._lastResult}get lastError(){return this._lastError}get lastDurationMs(){return this._lastDurationMs}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){for(let e of this.subscribers)try{e()}catch(r){d().error("[SolveScheduler] subscriber threw:",r)}}solve(e,r,n){if(this.disposed)return Promise.reject(new f("SolveScheduler has been disposed and cannot be used",h.INVALID_STATE));let s=te(e,r),o={key:s,enqueuedAt:Date.now(),startedAt:null};if(this.cacheEnabled){let a=this.readCache(s);if(a){let i={status:"success",response:a,durationMs:0,fromCache:!0};return this._lastResult=a,this._lastError=null,this._lastDurationMs=0,this.runHook(this.onStart,o),this.runHook(this.onSettle,o,i),this.notify(),Promise.resolve(a)}}return new Promise((a,i)=>{let u={definition:e,dataTree:r,ctx:o,resolve:a,reject:i,externalSignal:n?.signal};if(u.externalSignal?.aborted){this.settleError(u,this.makeAbortError(o));return}this.enqueue(u)})}enqueue(e){switch(this.mode){case"latest-wins":{this.pendingForLatestWins&&(this.supersede(this.pendingForLatestWins),this.pendingForLatestWins=null);for(let r of this.inFlight)this.supersede(r),r.controller.abort();this.inFlight.size===0?this.execute(e):this.pendingForLatestWins=e;break}case"queue":case"parallel":{this.inFlight.size<this.maxConcurrent?this.execute(e):this.fifoQueue.push(e);break}}this.notify()}async execute(e){let r=new AbortController,n=e;n.controller=r,this.inFlight.add(n),e.ctx.startedAt=Date.now();let s=()=>r.abort();e.externalSignal?.addEventListener("abort",s,{once:!0}),this.runHook(this.onStart,e.ctx),this.notify();let o=performance.now();try{let a={...this.baseConfig,signal:r.signal,...this.timeoutMs!==void 0&&{timeoutMs:this.timeoutMs},...this.retry!==void 0&&{retry:this.retry}},{response:i,definitionReuploaded:u}=await this.runExecutor(e.definition,e.dataTree,a),c=performance.now()-o;if(this.cacheEnabled&&this.writeCache(e.ctx.key,i),!this.settleSuccess(e,i))return;this._lastResult=i,this._lastError=null,this._lastDurationMs=c,this.runHook(this.onSettle,e.ctx,{status:"success",response:i,durationMs:c,fromCache:!1,definitionReuploaded:u})}catch(a){let i=performance.now()-o,u=this.normalizeExecutionError(a,n);this._lastError=u,this._lastDurationMs=i,this.settleError(e,u)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:u,durationMs:i})}finally{e.externalSignal?.removeEventListener("abort",s),this.inFlight.delete(n),this.drainNext(),this.notify()}}async runExecutor(e,r,n){if(!this.cacheKeyExecutor||!this.reuseServerDefinitionCache||!Ee(e))return{response:await this.executor(e,r,n)};let s=W(e),o=this.serverCacheKeys.get(s)??null,a=await this.cacheKeyExecutor(e,r,o,n);if(a.cacheKey)for(this.serverCacheKeys.delete(s),this.serverCacheKeys.set(s,a.cacheKey);this.serverCacheKeys.size>we;){let i=this.serverCacheKeys.keys().next().value;if(i===void 0)break;this.serverCacheKeys.delete(i)}else this.serverCacheKeys.delete(s);return{response:a.response,definitionReuploaded:a.missed}}drainNext(){if(!this.disposed){if(this.mode==="latest-wins"){if(this.pendingForLatestWins&&this.inFlight.size===0){let e=this.pendingForLatestWins;this.pendingForLatestWins=null,this.execute(e)}return}for(;this.fifoQueue.length>0&&this.inFlight.size<this.maxConcurrent;){let e=this.fifoQueue.shift();this.execute(e)}}}supersede(e){let r=new f("Superseded by newer solve",h.SUPERSEDED,{context:{key:e.ctx.key,enqueuedAt:e.ctx.enqueuedAt}});this.settleError(e,r)&&this.runHook(this.onSuperseded,e.ctx)}makeAbortError(e){return new f("Request aborted by caller",h.ABORTED,{context:{key:e.key,enqueuedAt:e.enqueuedAt}})}settleError(e,r){return e.settled?!1:(e.settled={error:r},e.reject(r),!0)}settleSuccess(e,r){return e.settled?!1:(e.settled={ok:!0},e.resolve(r),!0)}isAbortLikeError(e){if(e instanceof Error){if(e.name==="AbortError")return!0;if(typeof DOMException<"u"&&e instanceof DOMException)return e.name==="AbortError"}return!1}normalizeExecutionError(e,r){return r.settled&&"error"in r.settled?r.settled.error:e instanceof f?e:this.isAbortLikeError(e)?this.makeAbortError(r.ctx):new f(e instanceof Error?e.message:String(e),h.UNKNOWN_ERROR,{originalError:e instanceof Error?e:new Error(String(e))})}cancelAll(){for(this.pendingForLatestWins&&(this.rejectAsAborted(this.pendingForLatestWins),this.pendingForLatestWins=null);this.fifoQueue.length>0;){let e=this.fifoQueue.shift();this.rejectAsAborted(e)}for(let e of this.inFlight){let r=this.makeAbortError(e.ctx);this.settleError(e,r)&&this.runHook(this.onSettle,e.ctx,{status:"error",error:r,durationMs:e.ctx.startedAt?performance.now()-e.ctx.startedAt:0}),e.controller.abort()}this.notify()}rejectAsAborted(e){this.settleError(e,this.makeAbortError(e.ctx))}readCache(e){if(!this.cacheEnabled)return null;let r=this.cache.get(e);return r?this.cacheTtl>0&&Date.now()-r.insertedAt>this.cacheTtl?(this.cache.delete(e),null):(this.cache.delete(e),this.cache.set(e,r),r.response):null}writeCache(e,r){if(this.cacheEnabled)for(this.cache.set(e,{response:r,insertedAt:Date.now()});this.cache.size>this.cacheMax;){let n=this.cache.keys().next().value;if(n===void 0)break;this.cache.delete(n)}}clearCache(){this.cache.clear()}dispose(){this.disposed||(this.disposed=!0,this.cancelAll(),this.subscribers.clear(),this.cache.clear())}runHook(e,...r){if(e)try{e(...r)}catch(n){d().error("[SolveScheduler] hook threw:",n)}}};var R=class t{constructor(e){l(this,"config");l(this,"serverStats");l(this,"disposed",!1);this.config=this.normalizeComputeConfig(e),this.serverStats=new q(this.config.serverUrl,this.config.apiKey)}static async create(e){let r=new t(e),n=Math.max(1,(e.retry?.attempts??2)+1),s=e.retry?.baseDelayMs??250,o=e.retry?.maxDelayMs??1e3;for(let a=0;a<n;a++){if(await r.serverStats.isServerOnline())return r;if(a<n-1){let i=Math.min(s*2**a,o);await new Promise(u=>setTimeout(u,i))}}throw await r.dispose(),new f("Rhino Compute server is not online",h.NETWORK_ERROR,{context:{serverUrl:r.config.serverUrl,attempts:n}})}getConfig(){return this.ensureNotDisposed(),{...this.config}}async getIO(e){return this.ensureNotDisposed(),F(e,this.config)}async getRawIO(e){return this.ensureNotDisposed(),w(e,this.config)}async solve(e,r,n){this.ensureNotDisposed();try{if(typeof e=="string"&&!e?.trim())throw new f("Definition URL/content is required",h.INVALID_INPUT,{context:{receivedUrl:e}});if(e instanceof Uint8Array&&e.length===0)throw new f("Definition content is empty",h.INVALID_INPUT);let s={...this.config,...n?.signal!==void 0&&{signal:n.signal},...n?.timeoutMs!==void 0&&{timeoutMs:n.timeoutMs},...n?.retry!==void 0&&{retry:n.retry}},o=await D(r,e,s);if(o?.errors&&o.errors.length>0)throw new f(o.errors.join("; ")||"Computation failed",h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r,errors:o.errors,warnings:o.warnings}});return o}catch(s){throw this.config.debug&&d().error("Compute failed:",s),s instanceof f?s:new f(s instanceof Error?s.message:String(s),h.COMPUTATION_ERROR,{context:{definition:typeof e=="string"&&e.length<200?e:"...content...",inputs:r},originalError:s instanceof Error?s:new Error(String(s))})}}createScheduler(e){this.ensureNotDisposed();let r=(s,o,a)=>D(o,s,a),n=(s,o,a,i)=>a===null?Q(o,s,i).then(u=>({...u,missed:!1})):X(o,a,s,i);return new S(r,this.config,e,n)}async dispose(){this.disposed||(this.disposed=!0,await this.serverStats.dispose())}ensureNotDisposed(){if(this.disposed)throw new f("GrasshopperClient has been disposed and cannot be used",h.INVALID_STATE)}normalizeComputeConfig(e){return{...e,serverUrl:_(e.serverUrl),apiKey:e.apiKey,authToken:e.authToken,debug:e.debug??!1,suppressBrowserWarning:e.suppressBrowserWarning??e.suppressClientSideWarning}}};var G=new Map;function re(t,e){G.set(t,e)}re("Rhino.Geometry.Point3d",(t,e)=>{let r=e;return!r||typeof r.X!="number"?null:new t.Point([r.X,r.Y,r.Z])});re("Rhino.Geometry.Line",(t,e)=>{let r=e;return!r||!r.From||!r.To?null:new t.Line([r.From.X,r.From.Y,r.From.Z],[r.To.X,r.To.Y,r.To.Z])});function ve(t){if(G.has(t))return G.get(t);for(let[e,r]of G)if(t.startsWith(e))return r}function Ae(t){return!t||typeof t!="object"?null:t.data??t.value??null}function ne(t,e,r){let n=ve(e);if(n)try{return n(r,t)}catch(s){d().warn(`Failed to decode Rhino type ${e}:`,s)}try{let s=Ae(t);if(s)return r.CommonObject.decode(s)}catch(s){return d().warn(`Failed to decode ${e} with CommonObject:`,s),{__decodeError:!0,type:e,raw:t}}return t}var I={STRING:"System.String",INT:"System.Int32",DOUBLE:"System.Double",BOOL:"System.Boolean"},Ne="Rhino.Geometry.",Oe=["WebDisplay"],Fe="FileData";function se(t){return Oe.some(e=>t.includes(e))}function oe(t){if(typeof t!="string")return t;let e=t.trim();if(!(e.startsWith("{")||e.startsWith("[")||e.startsWith('"')))return t;try{let n=JSON.parse(e);if(typeof n=="string")try{return JSON.parse(n)}catch{return n}return n}catch{return t}}function Ge(t,e,r){switch(e){case I.STRING:return typeof t!="string"?t:t.replace(/^"(.*)"$/,"$1");case I.INT:return Number.parseInt(t,10);case I.DOUBLE:return Number.parseFloat(t);case I.BOOL:return String(t).toLowerCase()==="true";default:return r&&e.startsWith(Ne)?ne(t,e,r):t}}function ae(t,e,r,n){if(typeof t!="string")return t;let s=r?oe(t):t;return Ge(s,e,n)}function ke(t){if(!t||typeof t!="object")return!1;let e=t;return typeof e.fileName=="string"&&typeof e.fileType=="string"&&"data"in e&&typeof e.isBase64Encoded=="boolean"&&typeof e.subFolder=="string"}function k(t,e){for(let r of Object.values(t))if(Array.isArray(r))for(let n of r)e(n)}function ie(t,e=!1,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a={},i=new Set;for(let u of t.values)k(u.InnerTree,c=>{if(se(c.type)||o&&c.type!==I.STRING)return;let m=e?c.id:u.ParamName;if(!m)return;let y=ae(c.data,c.type,n,s);m in a?i.has(m)?a[m].push(y):(a[m]=[a[m],y],i.add(m)):a[m]=y});return{values:a}}function ue(t){let e=[];for(let r of t.values)k(r.InnerTree,n=>{if(!n.type.includes(Fe))return;let s=oe(n.data);ke(s)&&e.push(s)});return e}function pe(t,e,r={}){let{parseValues:n=!0,rhino:s,stringOnly:o=!1}=r,a;if("byName"in e?a=t.values.find(u=>u.ParamName===e.byName):a=t.values.find(u=>{let c=!1;return k(u.InnerTree,m=>{m.id===e.byId&&(c=!0)}),c}),!a)return;let i=[];if(k(a.InnerTree,u=>{if("byId"in e&&u.id!==e.byId||se(u.type)||o&&u.type!==I.STRING)return;let c=ae(u.data,u.type,n,s);i.push(c)}),i.length!==0)return i.length===1?i[0]:i}var E=class{constructor(e,r=!1){this.response=e;this.debug=r}getValues(e=!1,r={}){return ie(this.response,e,r)}getValue(e,r){return pe(this.response,e,r)}async extractMeshesFromResponse(e){let r={debug:this.debug,...e},n;try{({getThreeMeshesFromComputeResponse:n}=await import("./visualization-UJZN4PJD.js"))}catch(s){throw new f("Failed to load three.js visualization module. Ensure three.js is installed as a peer dependency.",h.INVALID_STATE,{context:{originalError:s instanceof Error?s.message:String(s)}})}return n(this.response,r)}getFileData(){return ue(this.response)}async getAndDownloadFiles(e,r){let n=this.getFileData();await N(n,e,r)}};function le(t){return p(t,"data")}function Me(t){return p(t,"type")}function ce(t){if(typeof t.default!="object"||t.default===null)return{schema:t};if(!L(t.default,"innerTree")){let n=`Input "${t.name??"unknown"}" default had an unrecognized shape (no innerTree key); the default was dropped.`;return d().warn("Unexpected structure in input.default:",t.default),{schema:{...t,default:null},warning:{code:"MALFORMED_DEFAULT",message:n}}}let e=p(t.default,"innerTree")??{};if(Object.keys(e).length===0)return{schema:{...t,default:void 0}};if(t.treeAccess||t.atMost&&t.atMost>1){let n={};for(let[s,o]of Object.entries(e))n[s]=o.map(a=>{let i=le(a),u=Me(a);if(typeof i=="string"){if(u==="System.Double"||u==="System.Int32"){let c=Number(i);return Number.isNaN(c)?i:c}if(u==="System.Boolean")return i.toLowerCase()==="true";if(u?.startsWith("Rhino.Geometry"))try{return JSON.parse(i)}catch{return i}}return i});return{schema:{...t,default:n}}}let r=[];for(let n of Object.values(e))Array.isArray(n)&&n.forEach(s=>{s&&typeof s=="object"&&L(s,"data")&&r.push(le(s))});return r.length===0?{schema:{...t,default:void 0}}:r.length===1?{schema:{...t,default:r[0]}}:{schema:{...t,default:r}}}var B=/^\{(\d+(?:;\d+)*)?\}$/;function v(t){if(typeof t!="object"||t===null||Array.isArray(t))return!1;let e=Object.entries(t);return e.length>0&&e.every(([r,n])=>B.test(r)&&Array.isArray(n))}function x(t,e,r){if(t==null)return t;if(Array.isArray(t)){let s=t.map(e).filter(o=>o!==null);return s.length>0?s:void 0}let n=e(t);return n!==null?n:r?void 0:t}var Ve=t=>{if(typeof t=="number")return t;if(typeof t=="string"){let e=t.trim();if(e==="")return null;let r=Number(e);return Number.isNaN(r)?null:r}return null},Le=t=>{if(typeof t=="boolean")return t;if(typeof t=="string"){let e=t.toLowerCase();if(e==="true")return!0;if(e==="false")return!1;throw new Error(`Invalid boolean string: "${t}"`)}return null},We=t=>typeof t=="string"?t.length>=2&&t.startsWith('"')&&t.endsWith('"')?t.slice(1,-1):t.startsWith('"')?t.slice(1):t:null,Be=t=>{if(typeof t=="string"){let e=t.trim();return e.startsWith('"')&&e.endsWith('"')&&(e=e.slice(1,-1).trim()),e}return null};function me(t){return e=>{if(typeof e=="object"&&e!==null)return e;if(typeof e=="string"&&e.trim()!=="")try{let r=JSON.parse(e);return typeof r=="object"&&r!==null?r:(d().warn(`Parsed value for input ${t} is not an object`),null)}catch(r){return d().warn(`Failed to parse object value "${e}" for input ${t}`,r),null}return null}}function fe(t,e,r){let n=Number(t.toFixed(e));return Math.abs(t-n)<r?n:t}function je(t,e){if(!Number.isFinite(t)||t===0)return .1;let r=Math.abs(t);if(r>=1){let g=String(t).split(".")[1];if(g&&g.length>0){let b=Math.min(g.length,12),T=Math.pow(10,-b),K=Number(T.toFixed(b));return Math.abs(K-T)<e?K:T}return 1}let n=String(t),s=n.toLowerCase().match(/e(-?\d+)/);if(s){let y=Number(s[1]);if(y<0||n.toLowerCase().includes("e-")){let g=Math.abs(y),b=Math.pow(10,-g),T=Number(b.toFixed(g));return Math.abs(T-b)<e?T:b}return .1}let o=12,i=r.toFixed(o).replace(/0+$/,""),u=Math.min((i.split(".")[1]||"").length,o);if(u===0)return .1;let c=Math.pow(10,-u),m=Number(c.toFixed(u));return Math.abs(m-c)<e?m:c}function Ke(t,e=1e-8){let r=t.paramType==="Integer";if(v(t.default))return{default:t.default,stepSize:r?1:.1};let n=x(t.default,Ve,!0);if(r)return Array.isArray(n)?n=n.map(m=>typeof m=="number"?Math.round(m):m):typeof n=="number"&&(n=Math.round(n)),{default:n,stepSize:1};let s=Array.isArray(n)?n[0]:n,o;typeof s=="number"&&Number.isFinite(s)&&s!==0?o=s:typeof t.minimum=="number"&&Number.isFinite(t.minimum)&&t.minimum!==0?o=t.minimum:typeof t.maximum=="number"&&Number.isFinite(t.maximum)&&t.maximum!==0&&(o=t.maximum);let a=o!==void 0?je(o,e):.1,i=0,u=String(a),c=u.toLowerCase().match(/e(-?\d+)/);if(c?i=Math.abs(Number(c[1])):i=u.split(".")[1]?.length??0,i===0&&typeof s=="number"&&s!==0&&Math.abs(s)<1){let m=Math.ceil(-Math.log10(Math.abs(s)));Number.isFinite(m)&&m>0&&(i=m)}return i=Math.min(Math.max(i,0),12),Array.isArray(n)?n=n.map(m=>typeof m=="number"?fe(m,i,e):m):typeof n=="number"&&(n=fe(n,i,e)),{default:n,stepSize:a}}var Ue={types:["Number","Integer"],parse(t,e){let{default:r,stepSize:n}=Ke(t);return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,stepSize:n,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:t.paramType,minimum:t.minimum,maximum:t.maximum,atLeast:t.atLeast,atMost:t.atMost,default:r?[0]:0}}},ze={types:["Boolean"],parse(t,e){let r;try{r=x(t.default,Le,!1)}catch(n){throw n instanceof Error?new f(n.message):n}return{...e,paramType:"Boolean",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Boolean",default:r?[!1]:!1}}},$e={types:["Text"],parse(t,e){let r=x(t.default,We,!1);return{...e,paramType:"Text",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Text",default:r?[""]:""}}},_e={types:["ValueList"],parse(t,e){if(!t.values||typeof t.values!="object"||Object.keys(t.values).length===0)throw f.missingValues(t.nickname||"unnamed","ValueList");if(t.default!==void 0&&t.default!==null){let r=String(t.default).toLowerCase();Object.keys(t.values).some(s=>s.toLowerCase()===r)||d().warn(`ValueList input "${t.nickname||"unnamed"}" default value "${t.default}" is not in available values`)}return{...e,paramType:"ValueList",values:t.values,default:t.default}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"ValueList",values:t.values??{},default:r?[t.default]:t.default}}},de={types:["Geometry"],parse(t,e){let r=x(t.default,me(t.nickname||"unnamed"),!0);return{...e,paramType:"Geometry",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Geometry",default:r?[null]:null}}},qe={types:["File"],parse(t,e){let r=x(t.default,me(t.nickname||"unnamed"),!0);return{...e,paramType:"File",acceptedFormats:t.acceptedFormats,default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"File",default:r?[null]:null}}},He={types:["Color"],parse(t,e){let r=x(t.default,Be,!1);return{...e,paramType:"Color",default:r}},fallback(t,e){let r=(t.atMost??1)>1;return{...e,paramType:"Color",default:r?["0, 0, 0"]:"0, 0, 0"}}},Je=[Ue,ze,$e,_e,de,qe,He],j=new Map(Je.flatMap(t=>t.types.map(e=>[e,t]))),he=de;var Ye=new Map([...j.keys()].map(t=>[t.toLowerCase(),t]));function Qe(t){return Ye.get(t?.toLowerCase())??t}function ye(t){return ge(t).input}function ge(t){let e={description:t.description,name:t.name,nickname:t.nickname,treeAccess:t.treeAccess,groupName:t.groupName??"",id:t.id},r=Qe(t.paramType),{schema:n,warning:s}=ce({...t,paramType:r}),o=s&&{inputName:t.name||"unknown",paramType:r,message:s.message,code:s.code},a=j.get(r);try{if(!a)throw f.unknownParamType(r,t.name);return{input:a.parse(n,e),error:o}}catch(i){if(i instanceof f)return d().error(`Validation error for input ${t.name||"unknown"}:`,i.message),{input:(a??he).fallback(n,e),error:{inputName:t.name||"unknown",paramType:r,message:i.message,code:i.code}};throw new f(i instanceof Error?i.message:String(i),"VALIDATION_ERROR",{context:{paramName:t.name,paramType:r},originalError:i instanceof Error?i:new Error(String(i))})}}function be(t){return M(t).inputs}function M(t){let e=[],r=[];for(let n of t){let{input:s,error:o}=ge(n);e.push(s),o&&r.push(o)}return{inputs:e,parseErrors:r}}function Te(t){return{id:p(t,"id"),name:p(t,"name"),nickname:p(t,"nickname")??null,description:p(t,"description"),paramType:p(t,"paramType"),treeAccess:p(t,"treeAccess"),minimum:p(t,"minimum")??null,maximum:p(t,"maximum")??null,atLeast:p(t,"atLeast"),atMost:p(t,"atMost"),stepSize:p(t,"stepSize"),default:p(t,"default"),values:p(t,"values"),acceptedFormats:p(t,"acceptedFormats"),groupName:p(t,"groupName")??""}}function Ce(t){return{name:p(t,"name"),nickname:p(t,"nickname")??null,paramType:p(t,"paramType"),id:p(t,"id")}}async function w(t,e){let r=P(t,[]),n={};if(r.algo&&(n.algo=r.algo),r.pointer&&(n.pointer=r.pointer),!n.algo&&!n.pointer)throw new f("Definition must resolve to either a URL pointer or base64 algo",h.INVALID_INPUT,{context:{definition:t}});let s=await A("io",n,e);if(!s||typeof s!="object")throw new f("Invalid IO response structure",h.INVALID_INPUT,{context:{response:s,definition:t}});let o=Se(p(s,"warnings")),a=Se(p(s,"errors")),i=p(s,"inputs"),u=p(s,"outputs");return{inputs:Array.isArray(i)?i.map(Te):[],outputs:Array.isArray(u)?u.map(Ce):[],...o&&{loadWarnings:o},...a&&{loadErrors:a}}}function Se(t){if(!Array.isArray(t))return;let e=t.filter(r=>typeof r=="string"&&r.trim().length>0);return e.length>0?e:void 0}async function F(t,e){C("fetchParsedDefinitionIO",e.suppressBrowserWarning??e.suppressClientSideWarning);let{inputs:r,outputs:n,loadWarnings:s,loadErrors:o}=await w(t,e),{inputs:a,parseErrors:i}=M(r);return{inputs:a,outputs:n,...i.length>0&&{parseErrors:i},...s&&{loadWarnings:s},...o&&{loadErrors:o}}}var V=class t{constructor(e){l(this,"innerTree");l(this,"paramName");this.paramName=e,this.innerTree={}}append(e,r){let n=t.formatPathString(e);this.innerTree[n]||(this.innerTree[n]=[]);let s=r.map(o=>({data:t.serializeValue(o)}));return this.innerTree[n].push(...s),this}appendSingle(e,r){return this.append(e,[r])}fromDataTreeDefault(e){this.innerTree={};for(let[r,n]of Object.entries(e)){if(!Array.isArray(n))continue;let s=t.parsePathString(r);this.append(s,n)}return this}appendFlat(e){let r=Array.isArray(e)?e:[e];return this.append([0],r)}flatten(){let e=[];for(let r of Object.values(this.innerTree))if(Array.isArray(r))for(let n of r)e.push(t.deserializeValue(n.data));return e}getPaths(){return Object.keys(this.innerTree)}getPath(e){let r=t.formatPathString(e),n=this.innerTree[r];if(n)return n.map(s=>t.deserializeValue(s.data))}toComputeFormat(){return{ParamName:this.paramName,InnerTree:this.innerTree}}getInnerTree(){return this.innerTree}getParamName(){return this.paramName}static fromInputParams(e){return e.filter(r=>t.hasValidValue(r.default)).map(r=>{let n=new t(r.nickname||"unnamed"),s=r.default;if(r.treeAccess&&v(s))n.fromDataTreeDefault(s),t.isNumericInput(r)&&n.applyNumericConstraints(r.minimum,r.maximum,r.nickname||"unnamed");else{let o=Array.isArray(s)?s:[s],a=t.processValues(o,r);n.appendFlat(a)}return n.toComputeFormat()})}static fromInputParam(e){return t.hasValidValue(e.default)?t.fromInputParams([e])[0]:void 0}static replaceTreeValue(e,r,n){let s=e.length>0&&e[0]instanceof t,o=t.buildFromValue(r,n);if(s){let c=e,m=c.findIndex(y=>y.getParamName()===r);return m!==-1?c[m]=o:c.push(o),c}let a=e,i=o.toComputeFormat(),u=a.findIndex(c=>c.ParamName===r);return u!==-1?a[u]=i:a.push(i),a}static buildFromValue(e,r){let n=new t(e);return v(r)?n.fromDataTreeDefault(r):n.appendFlat(r),n}static getTreeValue(e,r){let s=e.length>0&&e[0]instanceof t?t.readFromBuilders(e,r):t.readFromDataTrees(e,r);return s===null||s.length===0?null:s.length===1?s[0]:s}static readFromBuilders(e,r){let n=e.find(s=>s.getParamName()===r);return n?n.flatten():null}static readFromDataTrees(e,r){let n=e.find(a=>a.ParamName===r);if(!n?.InnerTree)return null;let s=Object.keys(n.InnerTree)[0];if(!s)return null;let o=n.InnerTree[s];return Array.isArray(o)?o.map(a=>a?.data!==void 0?t.deserializeValue(a.data):null).filter(a=>a!==null):o?.data!==void 0?[t.deserializeValue(o.data)]:o!==void 0?[o]:null}static parsePathString(e){let r=e.match(B);return r?r[1]?r[1].split(";").map(Number):[]:(d().warn(`Invalid TreeBuilder path format: ${e}, using [0]`),[0])}static formatPathString(e){return`{${e.join(";")}}`}applyNumericConstraints(e,r,n){for(let s of Object.values(this.innerTree))if(Array.isArray(s))for(let o of s){let a=t.deserializeValue(o.data);if(typeof a=="number"){let i=t.clampValue(a,e,r,n);o.data=t.serializeValue(i)}}}static serializeValue(e){return typeof e=="boolean"||typeof e=="number"||typeof e=="string"?e:typeof e=="object"&&e!==null?JSON.stringify(e):String(e)}static deserializeValue(e){if(typeof e=="boolean"||typeof e=="number"||typeof e!="string")return e;if(e.startsWith("{")||e.startsWith("["))try{return JSON.parse(e)}catch{return e}return e.trim()!==""&&!isNaN(Number(e))?Number(e):e==="true"?!0:e==="false"?!1:e}static hasValidValue(e){return e==null?!1:typeof e=="string"?!0:!(Array.isArray(e)&&e.length===0||typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0)}static isNumericInput(e){return e.paramType==="Number"||e.paramType==="Integer"}static processValues(e,r){return e.map(n=>t.isNumericInput(r)&&typeof n=="number"?t.clampValue(n,r.minimum,r.maximum,r.nickname||"unnamed"):n).filter(n=>n!=null)}static clampValue(e,r,n,s){let o=e;return r!=null&&o<r&&(d().warn(`${s}: ${e} below min ${r}, clamping`),o=r),n!=null&&o>n&&(d().warn(`${s}: ${e} above max ${n}, clamping`),o=n),o}};export{D as a,S as b,R as c,E as d,ye as e,be as f,w as g,F as h,V as i};
|
|
2
|
-
//# sourceMappingURL=chunk-CTZ4ZOSM.js.map
|