forgecad 0.9.5 → 0.9.7
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/assets/{AdminPage-uTtcSXtn.js → AdminPage-DX0mpSZT.js} +1 -1
- package/dist/assets/{BlogPage-DYJMjWx3.js → BlogPage-CI_P0_Pf.js} +1 -1
- package/dist/assets/{DocsPage-C58f0K5v.js → DocsPage-DLhIIZyJ.js} +3 -3
- package/dist/assets/EditorApp-BujZvuwX.js +12874 -0
- package/dist/assets/{EditorApp-DS0AIUrZ.css → EditorApp-DfFT2Dn8.css} +1 -0
- package/dist/assets/{EmbedViewer-CMXWA2LX.js → EmbedViewer-0S0qXKog.js} +2 -2
- package/dist/assets/{LandingPageProofDriven-CAu2OZFn.js → LandingPageProofDriven-O_yMtAri.js} +1 -1
- package/dist/assets/{PricingPage-BIgW7m3X.js → PricingPage-DGkX3Ahr.js} +1 -1
- package/dist/assets/{SettingsPage-N1l1tMXO.js → SettingsPage-DBsqTB_y.js} +82 -22
- package/dist/assets/{app-CFy7g5WP.js → app-BE2nD6Yz.js} +1246 -191
- package/dist/assets/cli/{render-BrVVdj_T.js → render-iP9qh475.js} +841 -586
- package/dist/assets/{evalWorker-c_SB9gg3.js → evalWorker-Ds5U4xtN.js} +2732 -112
- package/dist/assets/inspectWorker-Dll4eVyD.js +12620 -0
- package/dist/assets/{manifold-Dp6pvFr6.js → manifold-Bk26ViCr.js} +1 -1
- package/dist/assets/{manifold-CRoBhJKH.js → manifold-DjYsd7A_.js} +2 -2
- package/dist/assets/{manifold-Cjk7WhRs.js → manifold-sJ-axdXM.js} +1 -1
- package/dist/assets/{renderSceneState-3DfsSASX.js → renderSceneState-Bngp5MrQ.js} +1 -1
- package/dist/assets/{reportWorker-BLkuIoS8.js → reportWorker-CU8RZ4O0.js} +2715 -112
- package/dist/assets/{sectionPlaneMath-CykEnkvQ.js → sectionPlaneMath-BdTjyVfs.js} +3213 -252
- package/dist/cli/render.html +1 -1
- package/dist/docs/index.html +1 -1
- package/dist/docs-raw/AI/usage.md +7 -2
- package/dist/docs-raw/CLI.md +82 -53
- package/dist/docs-raw/beta-operations.md +9 -0
- package/dist/docs-raw/coding.md +1 -1
- package/dist/docs-raw/deployment.md +38 -23
- package/dist/docs-raw/generated/concepts.md +141 -7
- package/dist/docs-raw/generated/core.md +206 -1
- package/dist/docs-raw/generated/curves.md +97 -5
- package/dist/docs-raw/generated/lib.md +17 -1
- package/dist/docs-raw/generated/sketch.md +9 -1
- package/dist/docs-raw/generated/viewport.md +1 -1
- package/dist/docs-raw/guides/inspection-bundles.md +45 -16
- package/dist/docs-raw/platform/auth.md +2 -0
- package/dist/docs-raw/platform/google-oauth-setup.md +4 -0
- package/dist/docs-raw/runbook.md +3 -3
- package/dist/docs-raw/skills/forgecad-make-a-model.md +87 -8
- package/dist/docs-raw/skills/forgecad-prepare-prompt.md +14 -6
- package/dist/docs-raw/skills/forgecad-render-inspect.md +1 -1
- package/dist/docs-raw/skills/index.md +2 -2
- package/dist/index.html +1 -1
- package/dist/sitemap.xml +6 -6
- package/dist-cli/forgecad.js +8725 -4747
- package/dist-cli/forgecad.js.map +1 -1
- package/dist-skill/CONTEXT.md +375 -25
- package/dist-skill/docs/CLI.md +82 -53
- package/dist-skill/docs/generated/core.md +206 -1
- package/dist-skill/docs/generated/curves.md +97 -5
- package/dist-skill/docs/generated/lib.md +17 -1
- package/dist-skill/docs/generated/sketch.md +9 -1
- package/dist-skill/docs/generated/viewport.md +1 -1
- package/dist-skill/docs/guides/inspection-bundles.md +45 -16
- package/dist-skill/docs-dev/CLI.md +82 -53
- package/dist-skill/docs-dev/coding.md +1 -1
- package/dist-skill/docs-dev/generated/core.md +206 -1
- package/dist-skill/docs-dev/generated/curves.md +97 -5
- package/dist-skill/docs-dev/generated/lib.md +17 -1
- package/dist-skill/docs-dev/generated/sketch.md +9 -1
- package/dist-skill/docs-dev/generated/viewport.md +1 -1
- package/dist-skill/docs-dev/guides/inspection-bundles.md +45 -16
- package/dist-skill/library/forgecad-make-a-model/SKILL.md +87 -8
- package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +14 -6
- package/dist-skill/library/forgecad-prepare-prompt/references/default-profiles.md +5 -3
- package/dist-skill/library/forgecad-prepare-prompt/references/master-prompt.md +7 -5
- package/dist-skill/library/forgecad-render-inspect/SKILL.md +1 -1
- package/examples/api/bolted-service-cover.forge.js +17 -0
- package/examples/api/cable-gland-anchor.forge.js +14 -0
- package/examples/api/captured-cartridge-guide.forge.js +14 -0
- package/examples/api/captured-linear-slide.forge.js +13 -0
- package/examples/api/clevis-pin-joint.forge.js +13 -0
- package/examples/api/datum-enclosure.forge.js +16 -0
- package/examples/api/guided-loft-olive-oil-bottle.forge.js +135 -0
- package/examples/api/hose-barb-port.forge.js +14 -0
- package/examples/api/intentional-overlap-overmold.forge.js +16 -0
- package/examples/api/knuckled-hinge-assembly.forge.js +15 -0
- package/examples/api/living-hinge-cover.forge.js +14 -0
- package/examples/api/pcb-terminal-block.forge.js +22 -0
- package/examples/api/pinned-lever-pivot-stack.forge.js +14 -0
- package/examples/api/retained-shaft-knob-stack.forge.js +15 -0
- package/examples/api/routed-tube-clip.forge.js +15 -0
- package/examples/api/seated-bearing-stack.forge.js +30 -0
- package/examples/api/snap-latch-cover.forge.js +14 -0
- package/examples/api/static-assembly-connectors.forge.js +14 -16
- package/examples/api/thumb-screw-clamp.forge.js +15 -0
- package/package.json +20 -2
- package/dist/assets/EditorApp-DNH1TEz1.js +0 -12729
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-DfFT2Dn8.css","assets/landing-proof-driven-B7_RpP79.css","assets/PricingPage-BMedqFef.css"])))=>i.map(i=>d[i]);
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
3
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
4
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
5
5
|
var _a2;
|
|
6
|
-
import { c as create,
|
|
7
|
-
import { _ as __vitePreload, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, S as Scene, a as PCFSoftShadowMap, V as VSMShadowMap, b as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, c as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, d as Layers, e as Color, f as RGBAFormat, U as UnsignedByteType, g as Vector3, h as Vector2, i as Clock, T as THREE, D as DoubleSide, j as REVISION, M as Mesh, I as IcosahedronGeometry, k as ShaderMaterial, l as Spherical, Q as Quaternion, m as MOUSE, n as TOUCH, o as Ray, p as Plane, q as DataTextureLoader, H as HalfFloatType, F as FloatType, r as DataUtils, t as LinearFilter, u as RedFormat, v as InstancedBufferGeometry, w as Float32BufferAttribute, x as InstancedInterleavedBuffer, y as InterleavedBufferAttribute, E as WireframeGeometry, G as Box3, J as Sphere, K as UniformsUtils, X as UniformsLib, Y as Vector4, Z as Line3, $ as Matrix4, a0 as MathUtils, a1 as Uniform, a2 as WebGLRenderTarget, a3 as DepthTexture, a4 as BackSide, a5 as ClampToEdgeWrapping, a6 as PlaneGeometry, a7 as UVMapping, a8 as DataTexture, a9 as Texture, aa as MeshBasicMaterial, ab as IntType, ac as ShortType, ad as ByteType, ae as UnsignedIntType, af as Loader, ag as LoadingManager, ah as LinearMipMapLinearFilter, ai as FileLoader, aj as NoBlending, ak as CubeReflectionMapping, al as EquirectangularReflectionMapping, am as CubeTextureLoader, an as WebGLCubeRenderTarget, ao as ConstraintSketch, ap as setSketchPlacement3D, aq as Sketch, ar as PROFILE_BACKEND_MARKER, as as FrozenShape, at as setShapeCompilePlan, au as hasAnyPorts, av as setShapePortsInternal, aw as markShapePortsUsed, ax as setParamOverrides, ay as DEFAULT_ACTIVE_BACKEND, az as isConstraintSketch, aA as updateConstraintValue, aB as getShapeCompilePlan, aC as resolveForgeRenderStyle, aD as publishSolverWasmRunDebug, aE as resolveForgeQualityPreset, aF as resolveImportPath, aG as BufferGeometry, aH as LineBasicMaterial, aI as Line$1, aJ as LineDashedMaterial, aK as DepthStencilFormat, aL as UnsignedInt248Type, aM as MeshNormalMaterial, aN as NearestFilter, aO as BasicDepthPacking, aP as EventDispatcher$1, aQ as NoColorSpace, aR as FrontSide, aS as Material, aT as AlwaysDepth, aU as BufferAttribute, aV as CanvasTexture, aW as Object3D, aX as FogExp2, aY as Fog, aZ as AmbientLight, a_ as HemisphereLight, a$ as SpotLight, b0 as PointLight, b1 as DirectionalLight, b2 as
|
|
6
|
+
import { c as create, j as jsxRuntimeExports, r as reactExports, a as createWithEqualityFn, R as React, T as Tb, s as schedulerExports, b as clientExports, d as reactDomExports, u as useParams, e as useSearchParams, f as useNavigate, L as Link, B as BrowserRouter, g as Routes, h as Route, N as Navigate } from "./vendor-react-Da3A2QmU.js";
|
|
7
|
+
import { _ as __vitePreload, z as zipSync, s as strToU8, W as WebGLRenderer, R as Raycaster, O as OrthographicCamera$1, P as PerspectiveCamera$1, S as Scene, a as PCFSoftShadowMap, V as VSMShadowMap, b as PCFShadowMap, B as BasicShadowMap, C as ColorManagement, L as LinearSRGBColorSpace, c as SRGBColorSpace, N as NoToneMapping, A as ACESFilmicToneMapping, d as Layers, e as Color, f as RGBAFormat, U as UnsignedByteType, g as Vector3, h as Vector2, i as Clock, T as THREE, D as DoubleSide, j as REVISION, M as Mesh, I as IcosahedronGeometry, k as ShaderMaterial, l as Spherical, Q as Quaternion, m as MOUSE, n as TOUCH, o as Ray, p as Plane, q as DataTextureLoader, H as HalfFloatType, F as FloatType, r as DataUtils, t as LinearFilter, u as RedFormat, v as InstancedBufferGeometry, w as Float32BufferAttribute, x as InstancedInterleavedBuffer, y as InterleavedBufferAttribute, E as WireframeGeometry, G as Box3, J as Sphere, K as UniformsUtils, X as UniformsLib, Y as Vector4, Z as Line3, $ as Matrix4, a0 as MathUtils, a1 as Uniform, a2 as WebGLRenderTarget, a3 as DepthTexture, a4 as BackSide, a5 as ClampToEdgeWrapping, a6 as PlaneGeometry, a7 as UVMapping, a8 as DataTexture, a9 as Texture, aa as MeshBasicMaterial, ab as IntType, ac as ShortType, ad as ByteType, ae as UnsignedIntType, af as Loader, ag as LoadingManager, ah as LinearMipMapLinearFilter, ai as FileLoader, aj as NoBlending, ak as CubeReflectionMapping, al as EquirectangularReflectionMapping, am as CubeTextureLoader, an as WebGLCubeRenderTarget, ao as ConstraintSketch, ap as setSketchPlacement3D, aq as Sketch, ar as PROFILE_BACKEND_MARKER, as as FrozenShape, at as setShapeCompilePlan, au as hasAnyPorts, av as setShapePortsInternal, aw as markShapePortsUsed, ax as setParamOverrides, ay as DEFAULT_ACTIVE_BACKEND, az as isConstraintSketch, aA as updateConstraintValue, aB as getShapeCompilePlan, aC as resolveForgeRenderStyle, aD as publishSolverWasmRunDebug, aE as resolveForgeQualityPreset, aF as resolveImportPath, aG as BufferGeometry, aH as LineBasicMaterial, aI as Line$1, aJ as LineDashedMaterial, aK as DepthStencilFormat, aL as UnsignedInt248Type, aM as MeshNormalMaterial, aN as NearestFilter, aO as BasicDepthPacking, aP as EventDispatcher$1, aQ as NoColorSpace, aR as FrontSide, aS as Material, aT as AlwaysDepth, aU as BufferAttribute, aV as CanvasTexture, aW as Object3D, aX as FogExp2, aY as Fog, aZ as AmbientLight, a_ as HemisphereLight, a$ as SpotLight, b0 as PointLight, b1 as DirectionalLight, b2 as analyzeCollisionIntersections, b3 as shapeToGeometry, b4 as buildShapeFromCompilePlan, b5 as sketchToSvg, b6 as sketchToDxf, b7 as runScript, b8 as MeshPhysicalMaterial, b9 as LineSegments, ba as getRenderStylePreset, bb as AdditiveBlending, bc as CatmullRomCurve3, bd as TubeGeometry, be as MeshStandardMaterial, bf as compileSdfNode3, bg as buildSdfRaymarchFragmentShader, bh as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bi as Shape, bj as ShapeGeometry, bk as ShaderLib, bl as CylinderGeometry, bm as parseViewportCameraState, bn as createResolvedExplodeConfig, bo as explodeBoundsCenter, bp as explodeMergeBounds, bq as resolveExplodeDirective, br as computeExplodeMotion, bs as getSketchWorldMatrix, bt as explodeAdd, bu as hasExplodeOverride, bv as resolveExplodeLocalFanDirection, bw as explodeMul, bx as explodeLeafFanStage, by as normalizeCutPlane, bz as toClippingPlane, bA as findJointAnimationClip, bB as resolveJointAnimation, bC as resolveJointViewValues, bD as getShapePorts, bE as getShapeUsedPorts, bF as DEFAULT_VIEW_CONFIG, bG as getKernelFaceNameForTriangle, bH as initKernel, bI as initSolverWasm } from "./sectionPlaneMath-BdTjyVfs.js";
|
|
8
8
|
function getCsrfToken() {
|
|
9
9
|
const match = document.cookie.match(/(?:^|;\s*)fc-csrf-token=([^;]+)/);
|
|
10
10
|
return match == null ? void 0 : match[1];
|
|
@@ -71,6 +71,9 @@ const authApi = {
|
|
|
71
71
|
logout() {
|
|
72
72
|
return authFetch("/api/auth/logout", { method: "POST" });
|
|
73
73
|
},
|
|
74
|
+
deleteAccount() {
|
|
75
|
+
return authFetch("/api/users/me", { method: "DELETE" });
|
|
76
|
+
},
|
|
74
77
|
providers() {
|
|
75
78
|
return authFetch("/api/auth/providers");
|
|
76
79
|
},
|
|
@@ -516,6 +519,17 @@ function applyAuthenticatedUser(set, user) {
|
|
|
516
519
|
set({ user, loading: false, error: null, backendAvailable: true });
|
|
517
520
|
startRefreshTimer();
|
|
518
521
|
}
|
|
522
|
+
function clearAuthenticatedState(set) {
|
|
523
|
+
stopRefreshTimer();
|
|
524
|
+
clearUserCache();
|
|
525
|
+
setCurrentUserId(void 0);
|
|
526
|
+
set({ user: void 0, loading: false, error: null });
|
|
527
|
+
useProjectStore.setState({ projects: [], activeProjectId: null, error: null });
|
|
528
|
+
try {
|
|
529
|
+
localStorage.removeItem("fc-active-project-id");
|
|
530
|
+
} catch {
|
|
531
|
+
}
|
|
532
|
+
}
|
|
519
533
|
const useAuthStore = create((set) => ({
|
|
520
534
|
user: null,
|
|
521
535
|
loading: true,
|
|
@@ -569,21 +583,58 @@ const useAuthStore = create((set) => ({
|
|
|
569
583
|
}
|
|
570
584
|
},
|
|
571
585
|
async logout() {
|
|
572
|
-
stopRefreshTimer();
|
|
573
586
|
try {
|
|
574
587
|
await authApi.logout();
|
|
575
588
|
} finally {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
589
|
+
clearAuthenticatedState(set);
|
|
590
|
+
}
|
|
591
|
+
},
|
|
592
|
+
async deleteAccount() {
|
|
593
|
+
set({ loading: true, error: null });
|
|
594
|
+
try {
|
|
595
|
+
await authApi.deleteAccount();
|
|
596
|
+
clearAuthenticatedState(set);
|
|
597
|
+
} catch (err) {
|
|
598
|
+
set({ loading: false, error: err.message || "Account deletion failed" });
|
|
599
|
+
throw err;
|
|
584
600
|
}
|
|
585
601
|
}
|
|
586
602
|
}));
|
|
603
|
+
const BRAND_MARK_SRC = "/brand/logo-mark-128.png";
|
|
604
|
+
const BRAND_MARK_SRC_SET = [
|
|
605
|
+
"/brand/logo-mark-64.png 64w",
|
|
606
|
+
"/brand/logo-mark-128.png 128w",
|
|
607
|
+
"/brand/logo-mark-256.png 256w",
|
|
608
|
+
"/brand/logo-mark.png 512w"
|
|
609
|
+
].join(", ");
|
|
610
|
+
function BrandMark({
|
|
611
|
+
size = 24,
|
|
612
|
+
alt = "ForgeCAD logo",
|
|
613
|
+
decorative = false,
|
|
614
|
+
style
|
|
615
|
+
}) {
|
|
616
|
+
const logicalSize = Math.max(1, Math.ceil(size));
|
|
617
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
618
|
+
"img",
|
|
619
|
+
{
|
|
620
|
+
src: BRAND_MARK_SRC,
|
|
621
|
+
srcSet: BRAND_MARK_SRC_SET,
|
|
622
|
+
sizes: `${logicalSize}px`,
|
|
623
|
+
alt: decorative ? "" : alt,
|
|
624
|
+
"aria-hidden": decorative ? "true" : void 0,
|
|
625
|
+
width: size,
|
|
626
|
+
height: size,
|
|
627
|
+
style: {
|
|
628
|
+
width: size,
|
|
629
|
+
height: size,
|
|
630
|
+
display: "block",
|
|
631
|
+
flex: "0 0 auto",
|
|
632
|
+
objectFit: "contain",
|
|
633
|
+
...style
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
}
|
|
587
638
|
let nextId = 0;
|
|
588
639
|
let toasts = [];
|
|
589
640
|
const listeners$1 = /* @__PURE__ */ new Set();
|
|
@@ -779,41 +830,6 @@ const styles = {
|
|
|
779
830
|
opacity: 0.65
|
|
780
831
|
}
|
|
781
832
|
};
|
|
782
|
-
const BRAND_MARK_SRC = "/brand/logo-mark-128.png";
|
|
783
|
-
const BRAND_MARK_SRC_SET = [
|
|
784
|
-
"/brand/logo-mark-64.png 64w",
|
|
785
|
-
"/brand/logo-mark-128.png 128w",
|
|
786
|
-
"/brand/logo-mark-256.png 256w",
|
|
787
|
-
"/brand/logo-mark.png 512w"
|
|
788
|
-
].join(", ");
|
|
789
|
-
function BrandMark({
|
|
790
|
-
size = 24,
|
|
791
|
-
alt = "ForgeCAD logo",
|
|
792
|
-
decorative = false,
|
|
793
|
-
style
|
|
794
|
-
}) {
|
|
795
|
-
const logicalSize = Math.max(1, Math.ceil(size));
|
|
796
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
797
|
-
"img",
|
|
798
|
-
{
|
|
799
|
-
src: BRAND_MARK_SRC,
|
|
800
|
-
srcSet: BRAND_MARK_SRC_SET,
|
|
801
|
-
sizes: `${logicalSize}px`,
|
|
802
|
-
alt: decorative ? "" : alt,
|
|
803
|
-
"aria-hidden": decorative ? "true" : void 0,
|
|
804
|
-
width: size,
|
|
805
|
-
height: size,
|
|
806
|
-
style: {
|
|
807
|
-
width: size,
|
|
808
|
-
height: size,
|
|
809
|
-
display: "block",
|
|
810
|
-
flex: "0 0 auto",
|
|
811
|
-
objectFit: "contain",
|
|
812
|
-
...style
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
|
-
);
|
|
816
|
-
}
|
|
817
833
|
function getQueryParam(name) {
|
|
818
834
|
return new URLSearchParams(window.location.search).get(name);
|
|
819
835
|
}
|
|
@@ -856,7 +872,7 @@ function toRGB555(colorHex) {
|
|
|
856
872
|
if (!rgb) return 0;
|
|
857
873
|
return 32768 | rgb.r >> 3 << 10 | rgb.g >> 3 << 5 | rgb.b >> 3;
|
|
858
874
|
}
|
|
859
|
-
function rgbToHex(r2, g2, b2) {
|
|
875
|
+
function rgbToHex$1(r2, g2, b2) {
|
|
860
876
|
const toHex = (v) => v.toString(16).padStart(2, "0").toUpperCase();
|
|
861
877
|
return `#${toHex(r2)}${toHex(g2)}${toHex(b2)}`;
|
|
862
878
|
}
|
|
@@ -871,7 +887,7 @@ function buildPure3mfBuffer(objects, options = {}) {
|
|
|
871
887
|
if (obj.color) {
|
|
872
888
|
const rgb = parseHexColor(obj.color);
|
|
873
889
|
if (rgb) {
|
|
874
|
-
const hex = rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
890
|
+
const hex = rgbToHex$1(rgb.r, rgb.g, rgb.b);
|
|
875
891
|
if (!colorMap.has(hex)) {
|
|
876
892
|
colorMap.set(hex, colors.length);
|
|
877
893
|
colors.push({ hex, objectIndices: [] });
|
|
@@ -908,7 +924,7 @@ function buildPure3mfBuffer(objects, options = {}) {
|
|
|
908
924
|
if (obj.color && hasColors) {
|
|
909
925
|
const rgb = parseHexColor(obj.color);
|
|
910
926
|
if (rgb) {
|
|
911
|
-
const hex = rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
927
|
+
const hex = rgbToHex$1(rgb.r, rgb.g, rgb.b);
|
|
912
928
|
const colorIdx = colorMap.get(hex);
|
|
913
929
|
if (colorIdx !== void 0) {
|
|
914
930
|
pidAttr = ` pid="${colorgroupId}" pindex="${colorIdx}"`;
|
|
@@ -14920,7 +14936,7 @@ function planLabel(plan) {
|
|
|
14920
14936
|
case "boolean":
|
|
14921
14937
|
return plan.op === "union" ? "Union" : plan.op === "difference" ? "Subtract" : "Intersect";
|
|
14922
14938
|
case "transform":
|
|
14923
|
-
return
|
|
14939
|
+
return formatTransformLabel(plan.steps);
|
|
14924
14940
|
case "queryOwner":
|
|
14925
14941
|
return planLabel(plan.base);
|
|
14926
14942
|
case "fillet":
|
|
@@ -14969,12 +14985,53 @@ function planLabel(plan) {
|
|
|
14969
14985
|
return `STEP Import (${plan.filePath})`;
|
|
14970
14986
|
}
|
|
14971
14987
|
}
|
|
14988
|
+
function formatTransformLabel(steps) {
|
|
14989
|
+
if (steps.length === 0) return "Transform";
|
|
14990
|
+
const kinds = [...new Set(steps.map((step) => step.kind))];
|
|
14991
|
+
return `Transform (${kinds.join(", ")})`;
|
|
14992
|
+
}
|
|
14972
14993
|
function resolvePlan(plan) {
|
|
14973
14994
|
return plan.kind === "queryOwner" ? resolvePlan(plan.base) : plan;
|
|
14974
14995
|
}
|
|
14975
14996
|
function wrapWithTransforms(plan, transformStacks) {
|
|
14976
14997
|
return transformStacks.reduceRight((inner, steps) => ({ kind: "transform", base: inner, steps }), plan);
|
|
14977
14998
|
}
|
|
14999
|
+
const SHAPE_COMPILE_PLAN_CACHE_KEY_VERSION = "shape-plan-v1";
|
|
15000
|
+
function stableJsonEncode(value, arrayMember) {
|
|
15001
|
+
if (value === void 0 || typeof value === "function" || typeof value === "symbol") {
|
|
15002
|
+
return arrayMember ? "null" : void 0;
|
|
15003
|
+
}
|
|
15004
|
+
if (value === null || typeof value === "number" || typeof value === "boolean" || typeof value === "string") {
|
|
15005
|
+
return JSON.stringify(value);
|
|
15006
|
+
}
|
|
15007
|
+
if (Array.isArray(value)) {
|
|
15008
|
+
return `[${value.map((item) => stableJsonEncode(item, true) ?? "null").join(",")}]`;
|
|
15009
|
+
}
|
|
15010
|
+
const entries = Object.entries(value).sort(([left], [right]) => left.localeCompare(right));
|
|
15011
|
+
const encodedEntries = [];
|
|
15012
|
+
for (const [key, item] of entries) {
|
|
15013
|
+
const encoded = stableJsonEncode(item, false);
|
|
15014
|
+
if (encoded !== void 0) encodedEntries.push(`${JSON.stringify(key)}:${encoded}`);
|
|
15015
|
+
}
|
|
15016
|
+
return `{${encodedEntries.join(",")}}`;
|
|
15017
|
+
}
|
|
15018
|
+
function stableJsonStringify(value) {
|
|
15019
|
+
return stableJsonEncode(value, false) ?? "null";
|
|
15020
|
+
}
|
|
15021
|
+
function shapeCompilePlanCacheKey(plan) {
|
|
15022
|
+
return `${SHAPE_COMPILE_PLAN_CACHE_KEY_VERSION}:${stableJsonStringify(plan)}`;
|
|
15023
|
+
}
|
|
15024
|
+
function constructionStepGeometryCacheKey(step) {
|
|
15025
|
+
return step.cumulativePlanCacheKey;
|
|
15026
|
+
}
|
|
15027
|
+
function makeConstructionStep(step) {
|
|
15028
|
+
const planCacheKey = shapeCompilePlanCacheKey(step.plan);
|
|
15029
|
+
return {
|
|
15030
|
+
...step,
|
|
15031
|
+
planCacheKey,
|
|
15032
|
+
cumulativePlanCacheKey: step.cumulativePlan === step.plan ? planCacheKey : shapeCompilePlanCacheKey(step.cumulativePlan)
|
|
15033
|
+
};
|
|
15034
|
+
}
|
|
14978
15035
|
function linearizeConstructionSteps(rootPlan, objectId) {
|
|
14979
15036
|
const steps = [];
|
|
14980
15037
|
const ancestorTransforms = [];
|
|
@@ -15004,16 +15061,18 @@ function linearizeConstructionSteps(rootPlan, objectId) {
|
|
|
15004
15061
|
shapes: childCumulatives
|
|
15005
15062
|
};
|
|
15006
15063
|
const worldPlan = wrapWithTransforms(cumulativePlan, ancestorTransforms);
|
|
15007
|
-
steps.push(
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15064
|
+
steps.push(
|
|
15065
|
+
makeConstructionStep({
|
|
15066
|
+
index: steps.length,
|
|
15067
|
+
label: planLabel(resolved),
|
|
15068
|
+
role: "operation",
|
|
15069
|
+
displayAsTool,
|
|
15070
|
+
stackPopCount: childCumulatives.length,
|
|
15071
|
+
plan: worldPlan,
|
|
15072
|
+
cumulativePlan: worldPlan,
|
|
15073
|
+
objectId
|
|
15074
|
+
})
|
|
15075
|
+
);
|
|
15017
15076
|
return cumulativePlan;
|
|
15018
15077
|
}
|
|
15019
15078
|
// ── Modifications: visit base, then add modification step ──
|
|
@@ -15031,16 +15090,18 @@ function linearizeConstructionSteps(rootPlan, objectId) {
|
|
|
15031
15090
|
const baseCumulative = visit(resolved.base, options);
|
|
15032
15091
|
const modPlan = { ...resolved, base: baseCumulative };
|
|
15033
15092
|
const worldPlan = wrapWithTransforms(modPlan, ancestorTransforms);
|
|
15034
|
-
steps.push(
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
|
|
15093
|
+
steps.push(
|
|
15094
|
+
makeConstructionStep({
|
|
15095
|
+
index: steps.length,
|
|
15096
|
+
label: planLabel(resolved),
|
|
15097
|
+
role: "modification",
|
|
15098
|
+
displayAsTool,
|
|
15099
|
+
stackPopCount: 1,
|
|
15100
|
+
plan: worldPlan,
|
|
15101
|
+
cumulativePlan: worldPlan,
|
|
15102
|
+
objectId
|
|
15103
|
+
})
|
|
15104
|
+
);
|
|
15044
15105
|
return modPlan;
|
|
15045
15106
|
}
|
|
15046
15107
|
case "surfaceExtend":
|
|
@@ -15048,16 +15109,18 @@ function linearizeConstructionSteps(rootPlan, objectId) {
|
|
|
15048
15109
|
const baseCumulative = visit(resolved.base, options);
|
|
15049
15110
|
const modPlan = { ...resolved, base: baseCumulative };
|
|
15050
15111
|
const worldPlan = wrapWithTransforms(modPlan, ancestorTransforms);
|
|
15051
|
-
steps.push(
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15112
|
+
steps.push(
|
|
15113
|
+
makeConstructionStep({
|
|
15114
|
+
index: steps.length,
|
|
15115
|
+
label: planLabel(resolved),
|
|
15116
|
+
role: "modification",
|
|
15117
|
+
displayAsTool,
|
|
15118
|
+
stackPopCount: 1,
|
|
15119
|
+
plan: worldPlan,
|
|
15120
|
+
cumulativePlan: worldPlan,
|
|
15121
|
+
objectId
|
|
15122
|
+
})
|
|
15123
|
+
);
|
|
15061
15124
|
return modPlan;
|
|
15062
15125
|
}
|
|
15063
15126
|
case "surfaceSew": {
|
|
@@ -15071,31 +15134,35 @@ function linearizeConstructionSteps(rootPlan, objectId) {
|
|
|
15071
15134
|
tolerance: resolved.tolerance
|
|
15072
15135
|
};
|
|
15073
15136
|
const worldPlan = wrapWithTransforms(cumulativePlan, ancestorTransforms);
|
|
15074
|
-
steps.push(
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15137
|
+
steps.push(
|
|
15138
|
+
makeConstructionStep({
|
|
15139
|
+
index: steps.length,
|
|
15140
|
+
label: planLabel(resolved),
|
|
15141
|
+
role: "operation",
|
|
15142
|
+
displayAsTool,
|
|
15143
|
+
stackPopCount: childCumulatives.length,
|
|
15144
|
+
plan: worldPlan,
|
|
15145
|
+
cumulativePlan: worldPlan,
|
|
15146
|
+
objectId
|
|
15147
|
+
})
|
|
15148
|
+
);
|
|
15084
15149
|
return cumulativePlan;
|
|
15085
15150
|
}
|
|
15086
15151
|
// ── Leaf primitives: add directly as a step ──
|
|
15087
15152
|
default: {
|
|
15088
15153
|
const worldPlan = wrapWithTransforms(resolved, ancestorTransforms);
|
|
15089
|
-
steps.push(
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15154
|
+
steps.push(
|
|
15155
|
+
makeConstructionStep({
|
|
15156
|
+
index: steps.length,
|
|
15157
|
+
label: planLabel(resolved),
|
|
15158
|
+
role: "primitive",
|
|
15159
|
+
displayAsTool,
|
|
15160
|
+
stackPopCount: 0,
|
|
15161
|
+
plan: worldPlan,
|
|
15162
|
+
cumulativePlan: worldPlan,
|
|
15163
|
+
objectId
|
|
15164
|
+
})
|
|
15165
|
+
);
|
|
15099
15166
|
return resolved;
|
|
15100
15167
|
}
|
|
15101
15168
|
}
|
|
@@ -15788,7 +15855,7 @@ const CRASH_COOLDOWN_MS = 2e3;
|
|
|
15788
15855
|
class EvalWorkerClient {
|
|
15789
15856
|
constructor(workerFactory = () => new Worker(new URL(
|
|
15790
15857
|
/* @vite-ignore */
|
|
15791
|
-
"/assets/evalWorker-
|
|
15858
|
+
"/assets/evalWorker-Ds5U4xtN.js",
|
|
15792
15859
|
import.meta.url
|
|
15793
15860
|
), { type: "module" })) {
|
|
15794
15861
|
__publicField(this, "worker", null);
|
|
@@ -17253,6 +17320,14 @@ function buildRunState(previewFile, runResult, state2) {
|
|
|
17253
17320
|
};
|
|
17254
17321
|
}
|
|
17255
17322
|
const VIEW_PREFERENCES_KEY = "fc-view-preferences-v1";
|
|
17323
|
+
const INSPECT_POINT_SAMPLE_COUNT_MIN = 100;
|
|
17324
|
+
const INSPECT_POINT_SAMPLE_COUNT_MAX = 1e4;
|
|
17325
|
+
const DEFAULT_INSPECT_POINT_SAMPLE_COUNT = 2e3;
|
|
17326
|
+
const resolveInspectPointSampleCount = (value) => {
|
|
17327
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
17328
|
+
if (!Number.isFinite(numeric)) return DEFAULT_INSPECT_POINT_SAMPLE_COUNT;
|
|
17329
|
+
return Math.max(INSPECT_POINT_SAMPLE_COUNT_MIN, Math.min(INSPECT_POINT_SAMPLE_COUNT_MAX, Math.round(numeric)));
|
|
17330
|
+
};
|
|
17256
17331
|
const readViewPreferences = () => {
|
|
17257
17332
|
if (typeof window === "undefined") return {};
|
|
17258
17333
|
try {
|
|
@@ -17361,6 +17436,22 @@ const initialActive = (() => {
|
|
|
17361
17436
|
return fallback;
|
|
17362
17437
|
})();
|
|
17363
17438
|
const INITIAL_SAVED = {};
|
|
17439
|
+
const VIEW_INSPECT_CHANNELS = /* @__PURE__ */ new Set([
|
|
17440
|
+
"none",
|
|
17441
|
+
"mask",
|
|
17442
|
+
"connectivity",
|
|
17443
|
+
"distance",
|
|
17444
|
+
"collisions",
|
|
17445
|
+
"thickness",
|
|
17446
|
+
"roughness"
|
|
17447
|
+
]);
|
|
17448
|
+
const INSPECT_DISPLAY_MODES = /* @__PURE__ */ new Set(["heatmap", "points", "both"]);
|
|
17449
|
+
function resolveViewInspectChannel(value) {
|
|
17450
|
+
return typeof value === "string" && VIEW_INSPECT_CHANNELS.has(value) ? value : "none";
|
|
17451
|
+
}
|
|
17452
|
+
function resolveInspectDisplayMode(value) {
|
|
17453
|
+
return typeof value === "string" && INSPECT_DISPLAY_MODES.has(value) ? value : "heatmap";
|
|
17454
|
+
}
|
|
17364
17455
|
const initialViewPreferences = readViewPreferences();
|
|
17365
17456
|
const initialPreviewFile = resolvePreviewFile(initialActive, INITIAL_FILES);
|
|
17366
17457
|
const initialObjectSettingsByFile = (() => {
|
|
@@ -18119,6 +18210,24 @@ Switch to LOCAL mode or wait for the server to recover.`,
|
|
|
18119
18210
|
writeViewPreferences({ renderMode: mode });
|
|
18120
18211
|
set({ renderMode: mode });
|
|
18121
18212
|
},
|
|
18213
|
+
inspectChannel: resolveViewInspectChannel(initialViewPreferences.inspectChannel),
|
|
18214
|
+
setInspectChannel: (channel) => {
|
|
18215
|
+
const next = resolveViewInspectChannel(channel);
|
|
18216
|
+
writeViewPreferences({ inspectChannel: next });
|
|
18217
|
+
set({ inspectChannel: next });
|
|
18218
|
+
},
|
|
18219
|
+
inspectDisplayMode: resolveInspectDisplayMode(initialViewPreferences.inspectDisplayMode),
|
|
18220
|
+
setInspectDisplayMode: (mode) => {
|
|
18221
|
+
const next = resolveInspectDisplayMode(mode);
|
|
18222
|
+
writeViewPreferences({ inspectDisplayMode: next });
|
|
18223
|
+
set({ inspectDisplayMode: next });
|
|
18224
|
+
},
|
|
18225
|
+
inspectPointSampleCount: resolveInspectPointSampleCount(initialViewPreferences.inspectPointSampleCount),
|
|
18226
|
+
setInspectPointSampleCount: (count) => {
|
|
18227
|
+
const next = resolveInspectPointSampleCount(count);
|
|
18228
|
+
writeViewPreferences({ inspectPointSampleCount: next });
|
|
18229
|
+
set({ inspectPointSampleCount: next });
|
|
18230
|
+
},
|
|
18122
18231
|
projectionMode: initialViewPreferences.projectionMode ?? "perspective",
|
|
18123
18232
|
setProjectionMode: (mode) => {
|
|
18124
18233
|
writeViewPreferences({ projectionMode: mode });
|
|
@@ -26690,6 +26799,129 @@ function ClippingManager({ active }) {
|
|
|
26690
26799
|
}, [gl, active]);
|
|
26691
26800
|
return null;
|
|
26692
26801
|
}
|
|
26802
|
+
const COLLISION_SOURCE_OPACITY = 0.22;
|
|
26803
|
+
const COLLISION_SOURCE_COLOR = [180, 200, 220];
|
|
26804
|
+
const COLLISION_HIGHLIGHT_COLOR = [255, 68, 16];
|
|
26805
|
+
const COLLISION_PALETTE = [
|
|
26806
|
+
COLLISION_HIGHLIGHT_COLOR,
|
|
26807
|
+
[0, 204, 255],
|
|
26808
|
+
[255, 214, 0],
|
|
26809
|
+
[66, 220, 120],
|
|
26810
|
+
[255, 76, 196],
|
|
26811
|
+
[142, 106, 255],
|
|
26812
|
+
[255, 145, 48],
|
|
26813
|
+
[86, 232, 202],
|
|
26814
|
+
[210, 245, 60],
|
|
26815
|
+
[255, 120, 120],
|
|
26816
|
+
[80, 150, 255],
|
|
26817
|
+
[190, 110, 60]
|
|
26818
|
+
];
|
|
26819
|
+
const MASK_PALETTE = [
|
|
26820
|
+
[230, 25, 75],
|
|
26821
|
+
[60, 180, 75],
|
|
26822
|
+
[255, 225, 25],
|
|
26823
|
+
[0, 130, 200],
|
|
26824
|
+
[245, 130, 48],
|
|
26825
|
+
[145, 30, 180],
|
|
26826
|
+
[70, 240, 240],
|
|
26827
|
+
[240, 50, 230],
|
|
26828
|
+
[210, 245, 60],
|
|
26829
|
+
[250, 190, 190],
|
|
26830
|
+
[0, 128, 128],
|
|
26831
|
+
[230, 190, 255],
|
|
26832
|
+
[170, 110, 40],
|
|
26833
|
+
[255, 250, 200],
|
|
26834
|
+
[128, 0, 0],
|
|
26835
|
+
[170, 255, 195],
|
|
26836
|
+
[128, 128, 0],
|
|
26837
|
+
[255, 215, 180],
|
|
26838
|
+
[0, 0, 128],
|
|
26839
|
+
[128, 128, 128]
|
|
26840
|
+
];
|
|
26841
|
+
function rgbToHex(color2) {
|
|
26842
|
+
return `#${color2.map((value) => value.toString(16).padStart(2, "0")).join("")}`;
|
|
26843
|
+
}
|
|
26844
|
+
function maskRgbForIndex(index) {
|
|
26845
|
+
return MASK_PALETTE[index % MASK_PALETTE.length];
|
|
26846
|
+
}
|
|
26847
|
+
function maskColorForIndex(index) {
|
|
26848
|
+
return rgbToHex(maskRgbForIndex(index));
|
|
26849
|
+
}
|
|
26850
|
+
function collisionColorForIndex(index) {
|
|
26851
|
+
return rgbToHex(COLLISION_PALETTE[(index - 1) % COLLISION_PALETTE.length]);
|
|
26852
|
+
}
|
|
26853
|
+
const MAX_VIEWPORT_COLLISION_CANDIDATES = 200;
|
|
26854
|
+
const MAX_VIEWPORT_COLLISION_MS = 1e3;
|
|
26855
|
+
function matrixToCollisionMat4(matrix) {
|
|
26856
|
+
if (!matrix) return void 0;
|
|
26857
|
+
const e2 = matrix.elements;
|
|
26858
|
+
return [e2[0], e2[1], e2[2], e2[3], e2[4], e2[5], e2[6], e2[7], e2[8], e2[9], e2[10], e2[11], e2[12], e2[13], e2[14], e2[15]];
|
|
26859
|
+
}
|
|
26860
|
+
function buildCollisionEntries(objects, objectSettings, objectMatrices) {
|
|
26861
|
+
const entries = [];
|
|
26862
|
+
objects.forEach((obj) => {
|
|
26863
|
+
var _a3;
|
|
26864
|
+
if (!obj.shape) return;
|
|
26865
|
+
if (((_a3 = objectSettings[obj.id]) == null ? void 0 : _a3.visible) === false) return;
|
|
26866
|
+
try {
|
|
26867
|
+
const bb = obj.shape.boundingBox();
|
|
26868
|
+
entries.push({
|
|
26869
|
+
id: obj.id,
|
|
26870
|
+
name: obj.name,
|
|
26871
|
+
shape: obj.shape,
|
|
26872
|
+
min: [bb.min[0], bb.min[1], bb.min[2]],
|
|
26873
|
+
max: [bb.max[0], bb.max[1], bb.max[2]],
|
|
26874
|
+
transform: matrixToCollisionMat4(objectMatrices[obj.id]),
|
|
26875
|
+
groupName: obj.groupName,
|
|
26876
|
+
treePath: obj.treePath,
|
|
26877
|
+
mock: obj.mock
|
|
26878
|
+
});
|
|
26879
|
+
} catch {
|
|
26880
|
+
}
|
|
26881
|
+
});
|
|
26882
|
+
return entries;
|
|
26883
|
+
}
|
|
26884
|
+
function CollisionInspectionOverlay({
|
|
26885
|
+
objects,
|
|
26886
|
+
objectSettings,
|
|
26887
|
+
objectMatrices
|
|
26888
|
+
}) {
|
|
26889
|
+
const collisionGeometries = reactExports.useMemo(() => {
|
|
26890
|
+
const report = analyzeCollisionIntersections(buildCollisionEntries(objects, objectSettings, objectMatrices), {
|
|
26891
|
+
maxCandidatePairs: MAX_VIEWPORT_COLLISION_CANDIDATES,
|
|
26892
|
+
maxElapsedMs: MAX_VIEWPORT_COLLISION_MS,
|
|
26893
|
+
includeBBoxCandidates: false
|
|
26894
|
+
});
|
|
26895
|
+
return report.collisions.flatMap((collision) => {
|
|
26896
|
+
try {
|
|
26897
|
+
const geometry = shapeToGeometry(collision.shape);
|
|
26898
|
+
return [
|
|
26899
|
+
{
|
|
26900
|
+
id: collision.id,
|
|
26901
|
+
color: collisionColorForIndex(collision.index),
|
|
26902
|
+
solid: geometry.solid,
|
|
26903
|
+
edges: geometry.edges
|
|
26904
|
+
}
|
|
26905
|
+
];
|
|
26906
|
+
} catch {
|
|
26907
|
+
return [];
|
|
26908
|
+
}
|
|
26909
|
+
});
|
|
26910
|
+
}, [objectMatrices, objectSettings, objects]);
|
|
26911
|
+
reactExports.useEffect(() => {
|
|
26912
|
+
return () => {
|
|
26913
|
+
collisionGeometries.forEach((geometry) => {
|
|
26914
|
+
var _a3;
|
|
26915
|
+
geometry.solid.dispose();
|
|
26916
|
+
(_a3 = geometry.edges) == null ? void 0 : _a3.dispose();
|
|
26917
|
+
});
|
|
26918
|
+
};
|
|
26919
|
+
}, [collisionGeometries]);
|
|
26920
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("group", { children: collisionGeometries.map((geometry) => /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { children: [
|
|
26921
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: geometry.solid, renderOrder: 20, raycast: () => null, children: /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: geometry.color, depthTest: true, depthWrite: true, toneMapped: false }) }),
|
|
26922
|
+
geometry.edges && /* @__PURE__ */ jsxRuntimeExports.jsx("lineSegments", { geometry: geometry.edges, renderOrder: 21, raycast: () => null, children: /* @__PURE__ */ jsxRuntimeExports.jsx("lineBasicMaterial", { color: "#ffffff", transparent: true, opacity: 0.65, depthTest: false, toneMapped: false }) })
|
|
26923
|
+
] }, geometry.id)) });
|
|
26924
|
+
}
|
|
26693
26925
|
function ConstructionGhostOverlay({ matrix }) {
|
|
26694
26926
|
const ghost = useForgeStore((s) => s.constructionGhost);
|
|
26695
26927
|
const { solidGeo, edgesGeo } = reactExports.useMemo(() => {
|
|
@@ -26712,7 +26944,8 @@ function ConstructionGhostOverlay({ matrix }) {
|
|
|
26712
26944
|
const MAX_CACHE_SIZE = 40;
|
|
26713
26945
|
const geometryCache = /* @__PURE__ */ new Map();
|
|
26714
26946
|
function getCachedGeometry(step) {
|
|
26715
|
-
const
|
|
26947
|
+
const cacheKey = constructionStepGeometryCacheKey(step);
|
|
26948
|
+
const cached = geometryCache.get(cacheKey);
|
|
26716
26949
|
if (cached) return cached;
|
|
26717
26950
|
try {
|
|
26718
26951
|
const shape = buildShapeFromCompilePlan(step.cumulativePlan);
|
|
@@ -26728,7 +26961,7 @@ function getCachedGeometry(step) {
|
|
|
26728
26961
|
geometryCache.delete(firstKey);
|
|
26729
26962
|
}
|
|
26730
26963
|
}
|
|
26731
|
-
geometryCache.set(
|
|
26964
|
+
geometryCache.set(cacheKey, entry);
|
|
26732
26965
|
return entry;
|
|
26733
26966
|
} catch {
|
|
26734
26967
|
return null;
|
|
@@ -28914,7 +29147,7 @@ function generateReportInWorker(options) {
|
|
|
28914
29147
|
return new Promise((resolve2, reject) => {
|
|
28915
29148
|
const worker = new Worker(new URL(
|
|
28916
29149
|
/* @vite-ignore */
|
|
28917
|
-
"/assets/reportWorker-
|
|
29150
|
+
"/assets/reportWorker-CU8RZ4O0.js",
|
|
28918
29151
|
import.meta.url
|
|
28919
29152
|
), { type: "module" });
|
|
28920
29153
|
const cleanup = () => {
|
|
@@ -32118,16 +32351,44 @@ const PHASE_CONFIG = {
|
|
|
32118
32351
|
evaluating: { color: "#4a9eff", label: "Evaluating model" },
|
|
32119
32352
|
serializing: { color: "#7c4dff", label: "Preparing display" },
|
|
32120
32353
|
exporting: { color: "#4caf50", label: "Exporting geometry" },
|
|
32354
|
+
inspecting: { color: "#14b8a6", label: "Generating inspect view" },
|
|
32121
32355
|
idle: { color: "#888", label: "" }
|
|
32122
32356
|
};
|
|
32123
32357
|
const PHASE_ORDER = ["kernel-init", "evaluating", "serializing"];
|
|
32124
|
-
function
|
|
32358
|
+
function formatEvaluationBackendLabel(activeBackend, computeTarget) {
|
|
32359
|
+
const backend = activeBackend === "occt" ? "OCCT" : activeBackend === "manifold" ? "Manifold" : activeBackend === "truck" ? "Truck" : "kernel";
|
|
32360
|
+
return computeTarget === "server" ? `Server ${backend}` : `Local ${backend}`;
|
|
32361
|
+
}
|
|
32362
|
+
function constructionStepRoleSymbol(role) {
|
|
32363
|
+
if (role === "primitive") return "+";
|
|
32364
|
+
if (role === "operation") return "->";
|
|
32365
|
+
return "~";
|
|
32366
|
+
}
|
|
32367
|
+
function constructionStepPreview(constructionSteps, previewStepIndex) {
|
|
32368
|
+
const stepCount = constructionSteps.length;
|
|
32369
|
+
const displayStepIndex = stepCount > 0 ? (previewStepIndex % stepCount + stepCount) % stepCount : 0;
|
|
32370
|
+
return {
|
|
32371
|
+
displayStepIndex,
|
|
32372
|
+
previewStep: stepCount > 0 ? constructionSteps[displayStepIndex] : null,
|
|
32373
|
+
progress: stepCount > 1 ? (displayStepIndex + 1) / stepCount : 1
|
|
32374
|
+
};
|
|
32375
|
+
}
|
|
32376
|
+
function EvaluationIndicator({
|
|
32377
|
+
phase,
|
|
32378
|
+
label,
|
|
32379
|
+
constructionSteps = [],
|
|
32380
|
+
activeBackend,
|
|
32381
|
+
computeTarget
|
|
32382
|
+
}) {
|
|
32125
32383
|
const [frame2, setFrame] = reactExports.useState(0);
|
|
32126
32384
|
const [elapsed, setElapsed] = reactExports.useState(0);
|
|
32385
|
+
const [previewStepIndex, setPreviewStepIndex] = reactExports.useState(0);
|
|
32127
32386
|
const startRef = reactExports.useRef(Date.now());
|
|
32387
|
+
const stepCount = constructionSteps.length;
|
|
32128
32388
|
reactExports.useEffect(() => {
|
|
32129
32389
|
startRef.current = Date.now();
|
|
32130
32390
|
setElapsed(0);
|
|
32391
|
+
setPreviewStepIndex(0);
|
|
32131
32392
|
}, [phase]);
|
|
32132
32393
|
reactExports.useEffect(() => {
|
|
32133
32394
|
const spinnerInterval = setInterval(() => setFrame((f2) => (f2 + 1) % BRAILLE_FRAMES.length), 80);
|
|
@@ -32137,9 +32398,17 @@ function EvaluationIndicator({ phase }) {
|
|
|
32137
32398
|
clearInterval(timerInterval);
|
|
32138
32399
|
};
|
|
32139
32400
|
}, []);
|
|
32401
|
+
reactExports.useEffect(() => {
|
|
32402
|
+
setPreviewStepIndex(0);
|
|
32403
|
+
if (stepCount <= 1) return;
|
|
32404
|
+
const interval = setInterval(() => setPreviewStepIndex((i) => (i + 1) % stepCount), 700);
|
|
32405
|
+
return () => clearInterval(interval);
|
|
32406
|
+
}, [stepCount]);
|
|
32140
32407
|
const config = PHASE_CONFIG[phase] ?? PHASE_CONFIG["evaluating"];
|
|
32141
32408
|
const elapsedSec = (elapsed / 1e3).toFixed(1);
|
|
32142
|
-
const
|
|
32409
|
+
const phaseOrder = PHASE_ORDER.includes(phase) ? PHASE_ORDER : [phase];
|
|
32410
|
+
const phaseIdx = phaseOrder.indexOf(phase);
|
|
32411
|
+
const { displayStepIndex, previewStep, progress } = constructionStepPreview(constructionSteps, previewStepIndex);
|
|
32143
32412
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
32144
32413
|
"div",
|
|
32145
32414
|
{
|
|
@@ -32147,51 +32416,368 @@ function EvaluationIndicator({ phase }) {
|
|
|
32147
32416
|
position: "absolute",
|
|
32148
32417
|
bottom: 16,
|
|
32149
32418
|
right: 16,
|
|
32419
|
+
width: previewStep ? "min(360px, calc(100vw - 32px))" : void 0,
|
|
32150
32420
|
background: "var(--fc-bgPanel)",
|
|
32151
32421
|
border: "1px solid var(--fc-border)",
|
|
32152
32422
|
borderRadius: 8,
|
|
32153
|
-
padding: "8px 14px",
|
|
32423
|
+
padding: previewStep ? "10px 12px" : "8px 14px",
|
|
32154
32424
|
pointerEvents: "none",
|
|
32155
|
-
display: "
|
|
32156
|
-
|
|
32157
|
-
gap: 10,
|
|
32425
|
+
display: "grid",
|
|
32426
|
+
gap: previewStep ? 8 : 0,
|
|
32158
32427
|
fontSize: 12,
|
|
32159
32428
|
animation: "fc-fadein 0.2s ease-out",
|
|
32160
32429
|
boxShadow: "0 4px 16px rgba(0,0,0,0.25)"
|
|
32161
32430
|
},
|
|
32162
32431
|
children: [
|
|
32163
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
32164
|
-
|
|
32165
|
-
|
|
32166
|
-
var _a3;
|
|
32167
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32432
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 10, minWidth: 0 }, children: [
|
|
32433
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: config.color, fontSize: 16, fontWeight: 700, width: 16, textAlign: "center", flex: "0 0 auto" }, children: BRAILLE_FRAMES[frame2] }),
|
|
32434
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32168
32435
|
"span",
|
|
32169
32436
|
{
|
|
32170
32437
|
style: {
|
|
32171
|
-
|
|
32172
|
-
|
|
32173
|
-
|
|
32174
|
-
|
|
32175
|
-
|
|
32176
|
-
|
|
32438
|
+
color: "var(--fc-text)",
|
|
32439
|
+
fontWeight: 500,
|
|
32440
|
+
minWidth: 0,
|
|
32441
|
+
overflow: "hidden",
|
|
32442
|
+
textOverflow: "ellipsis",
|
|
32443
|
+
whiteSpace: "nowrap"
|
|
32444
|
+
},
|
|
32445
|
+
children: label ?? config.label
|
|
32446
|
+
}
|
|
32447
|
+
),
|
|
32448
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { display: "flex", gap: 4, alignItems: "center", marginLeft: "auto", flex: "0 0 auto" }, children: phaseOrder.map((p2, i) => {
|
|
32449
|
+
var _a3;
|
|
32450
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32451
|
+
"span",
|
|
32452
|
+
{
|
|
32453
|
+
style: {
|
|
32454
|
+
width: 6,
|
|
32455
|
+
height: 6,
|
|
32456
|
+
borderRadius: "50%",
|
|
32457
|
+
background: i <= phaseIdx ? ((_a3 = PHASE_CONFIG[p2]) == null ? void 0 : _a3.color) ?? "var(--fc-border)" : "var(--fc-border)",
|
|
32458
|
+
transition: "background 0.3s ease",
|
|
32459
|
+
animation: i === phaseIdx ? "fc-pulse 1.2s ease-in-out infinite" : void 0
|
|
32460
|
+
}
|
|
32461
|
+
},
|
|
32462
|
+
p2
|
|
32463
|
+
);
|
|
32464
|
+
}) }),
|
|
32465
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { color: "var(--fc-textDim)", fontVariantNumeric: "tabular-nums", fontSize: 11, flex: "0 0 auto" }, children: [
|
|
32466
|
+
elapsedSec,
|
|
32467
|
+
"s"
|
|
32468
|
+
] })
|
|
32469
|
+
] }),
|
|
32470
|
+
previewStep && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "grid", gap: 6, minWidth: 0 }, children: [
|
|
32471
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [
|
|
32472
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32473
|
+
"span",
|
|
32474
|
+
{
|
|
32475
|
+
style: {
|
|
32476
|
+
color: "var(--fc-textDim)",
|
|
32477
|
+
fontSize: 10,
|
|
32478
|
+
textTransform: "uppercase",
|
|
32479
|
+
fontWeight: 700,
|
|
32480
|
+
letterSpacing: 0,
|
|
32481
|
+
flex: "0 0 auto"
|
|
32482
|
+
},
|
|
32483
|
+
children: "Cached build path"
|
|
32177
32484
|
}
|
|
32178
|
-
|
|
32179
|
-
|
|
32180
|
-
|
|
32181
|
-
|
|
32182
|
-
|
|
32183
|
-
|
|
32184
|
-
|
|
32485
|
+
),
|
|
32486
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32487
|
+
"span",
|
|
32488
|
+
{
|
|
32489
|
+
style: {
|
|
32490
|
+
color: "var(--fc-textMuted)",
|
|
32491
|
+
fontSize: 11,
|
|
32492
|
+
minWidth: 0,
|
|
32493
|
+
overflow: "hidden",
|
|
32494
|
+
textOverflow: "ellipsis",
|
|
32495
|
+
whiteSpace: "nowrap"
|
|
32496
|
+
},
|
|
32497
|
+
children: formatEvaluationBackendLabel(activeBackend, computeTarget)
|
|
32498
|
+
}
|
|
32499
|
+
)
|
|
32500
|
+
] }),
|
|
32501
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [
|
|
32502
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
32503
|
+
"span",
|
|
32504
|
+
{
|
|
32505
|
+
style: {
|
|
32506
|
+
color: config.color,
|
|
32507
|
+
fontVariantNumeric: "tabular-nums",
|
|
32508
|
+
fontSize: 11,
|
|
32509
|
+
fontWeight: 700,
|
|
32510
|
+
flex: "0 0 auto",
|
|
32511
|
+
width: 46
|
|
32512
|
+
},
|
|
32513
|
+
children: [
|
|
32514
|
+
displayStepIndex + 1,
|
|
32515
|
+
"/",
|
|
32516
|
+
stepCount
|
|
32517
|
+
]
|
|
32518
|
+
}
|
|
32519
|
+
),
|
|
32520
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
32521
|
+
"span",
|
|
32522
|
+
{
|
|
32523
|
+
style: {
|
|
32524
|
+
color: "var(--fc-text)",
|
|
32525
|
+
minWidth: 0,
|
|
32526
|
+
overflow: "hidden",
|
|
32527
|
+
textOverflow: "ellipsis",
|
|
32528
|
+
whiteSpace: "nowrap"
|
|
32529
|
+
},
|
|
32530
|
+
children: [
|
|
32531
|
+
constructionStepRoleSymbol(previewStep.role),
|
|
32532
|
+
" ",
|
|
32533
|
+
previewStep.label
|
|
32534
|
+
]
|
|
32535
|
+
}
|
|
32536
|
+
),
|
|
32537
|
+
previewStep.displayAsTool && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { color: config.color, fontSize: 11, flex: "0 0 auto" }, children: "tool" })
|
|
32538
|
+
] }),
|
|
32539
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { height: 3, borderRadius: 999, background: "var(--fc-borderLight)", overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32540
|
+
"div",
|
|
32541
|
+
{
|
|
32542
|
+
style: {
|
|
32543
|
+
width: `${Math.round(progress * 100)}%`,
|
|
32544
|
+
height: "100%",
|
|
32545
|
+
borderRadius: 999,
|
|
32546
|
+
background: config.color,
|
|
32547
|
+
transition: "width 0.2s ease-out"
|
|
32548
|
+
}
|
|
32549
|
+
}
|
|
32550
|
+
) })
|
|
32185
32551
|
] })
|
|
32186
32552
|
]
|
|
32187
32553
|
}
|
|
32188
32554
|
);
|
|
32189
32555
|
}
|
|
32556
|
+
const MIN_FIELD_GRID_SIZE = 18;
|
|
32557
|
+
const MAX_FIELD_GRID_SIZE = 32;
|
|
32558
|
+
const MAX_BLEND_SAMPLES = 12;
|
|
32559
|
+
const MAX_SEARCH_RADIUS = 5;
|
|
32560
|
+
const SAMPLE_RING_OFFSETS = [];
|
|
32561
|
+
for (let radius = 0; radius <= MAX_SEARCH_RADIUS; radius += 1) {
|
|
32562
|
+
const ring = [];
|
|
32563
|
+
for (let x = -radius; x <= radius; x += 1) {
|
|
32564
|
+
for (let y = -radius; y <= radius; y += 1) {
|
|
32565
|
+
for (let z = -radius; z <= radius; z += 1) {
|
|
32566
|
+
if (Math.max(Math.abs(x), Math.abs(y), Math.abs(z)) === radius) ring.push([x, y, z]);
|
|
32567
|
+
}
|
|
32568
|
+
}
|
|
32569
|
+
}
|
|
32570
|
+
SAMPLE_RING_OFFSETS.push(ring);
|
|
32571
|
+
}
|
|
32572
|
+
const INSPECT_HEATMAP_VERTEX_SHADER = `
|
|
32573
|
+
varying vec3 vLocalPosition;
|
|
32574
|
+
varying vec3 vViewDirection;
|
|
32575
|
+
varying vec3 vViewNormal;
|
|
32576
|
+
#include <clipping_planes_pars_vertex>
|
|
32577
|
+
|
|
32578
|
+
void main() {
|
|
32579
|
+
vLocalPosition = position;
|
|
32580
|
+
vViewNormal = normalize(normalMatrix * normal);
|
|
32581
|
+
vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
|
|
32582
|
+
vViewDirection = normalize(-mvPosition.xyz);
|
|
32583
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
32584
|
+
#include <clipping_planes_vertex>
|
|
32585
|
+
}
|
|
32586
|
+
`;
|
|
32587
|
+
const INSPECT_HEATMAP_FRAGMENT_SHADER = `
|
|
32588
|
+
uniform sampler2D uField;
|
|
32589
|
+
uniform float uGridSize;
|
|
32590
|
+
uniform vec3 uBoundsMin;
|
|
32591
|
+
uniform vec3 uBoundsSize;
|
|
32592
|
+
varying vec3 vLocalPosition;
|
|
32593
|
+
varying vec3 vViewDirection;
|
|
32594
|
+
varying vec3 vViewNormal;
|
|
32595
|
+
#include <clipping_planes_pars_fragment>
|
|
32596
|
+
|
|
32597
|
+
vec2 fieldUv(vec3 index) {
|
|
32598
|
+
vec2 atlasSize = vec2(uGridSize * uGridSize, uGridSize);
|
|
32599
|
+
float atlasX = index.x + index.z * uGridSize;
|
|
32600
|
+
return (vec2(atlasX, index.y) + 0.5) / atlasSize;
|
|
32601
|
+
}
|
|
32602
|
+
|
|
32603
|
+
vec3 fetchField(vec3 index) {
|
|
32604
|
+
vec3 bounded = clamp(index, vec3(0.0), vec3(uGridSize - 1.0));
|
|
32605
|
+
return texture2D(uField, fieldUv(bounded)).rgb;
|
|
32606
|
+
}
|
|
32607
|
+
|
|
32608
|
+
vec3 sampleField(vec3 position) {
|
|
32609
|
+
vec3 normalized = clamp((position - uBoundsMin) / max(uBoundsSize, vec3(0.000001)), vec3(0.0), vec3(1.0));
|
|
32610
|
+
vec3 coord = normalized * (uGridSize - 1.0);
|
|
32611
|
+
vec3 base = floor(coord);
|
|
32612
|
+
vec3 f = fract(coord);
|
|
32613
|
+
|
|
32614
|
+
vec3 c000 = fetchField(base + vec3(0.0, 0.0, 0.0));
|
|
32615
|
+
vec3 c100 = fetchField(base + vec3(1.0, 0.0, 0.0));
|
|
32616
|
+
vec3 c010 = fetchField(base + vec3(0.0, 1.0, 0.0));
|
|
32617
|
+
vec3 c110 = fetchField(base + vec3(1.0, 1.0, 0.0));
|
|
32618
|
+
vec3 c001 = fetchField(base + vec3(0.0, 0.0, 1.0));
|
|
32619
|
+
vec3 c101 = fetchField(base + vec3(1.0, 0.0, 1.0));
|
|
32620
|
+
vec3 c011 = fetchField(base + vec3(0.0, 1.0, 1.0));
|
|
32621
|
+
vec3 c111 = fetchField(base + vec3(1.0, 1.0, 1.0));
|
|
32622
|
+
|
|
32623
|
+
vec3 c00 = mix(c000, c100, f.x);
|
|
32624
|
+
vec3 c10 = mix(c010, c110, f.x);
|
|
32625
|
+
vec3 c01 = mix(c001, c101, f.x);
|
|
32626
|
+
vec3 c11 = mix(c011, c111, f.x);
|
|
32627
|
+
return mix(mix(c00, c10, f.y), mix(c01, c11, f.y), f.z);
|
|
32628
|
+
}
|
|
32629
|
+
|
|
32630
|
+
void main() {
|
|
32631
|
+
#include <clipping_planes_fragment>
|
|
32632
|
+
vec3 heat = sampleField(vLocalPosition);
|
|
32633
|
+
float rim = pow(1.0 - clamp(dot(normalize(vViewNormal), normalize(vViewDirection)), 0.0, 1.0), 2.0);
|
|
32634
|
+
vec3 color = heat * (0.88 + rim * 0.2) + vec3(0.025, 0.04, 0.055) * rim;
|
|
32635
|
+
gl_FragColor = vec4(color, 1.0);
|
|
32636
|
+
}
|
|
32637
|
+
`;
|
|
32638
|
+
function gridKey(x, y, z) {
|
|
32639
|
+
return `${x},${y},${z}`;
|
|
32640
|
+
}
|
|
32641
|
+
function buildGeometryBounds(geometry) {
|
|
32642
|
+
const position = geometry.getAttribute("position");
|
|
32643
|
+
if (!position || position.count === 0) return null;
|
|
32644
|
+
const bounds = new Box3().setFromBufferAttribute(position);
|
|
32645
|
+
if (bounds.isEmpty()) return null;
|
|
32646
|
+
const size = bounds.getSize(new Vector3());
|
|
32647
|
+
const pad = Math.max(size.x, size.y, size.z, 1) * 1e-5;
|
|
32648
|
+
bounds.expandByScalar(pad);
|
|
32649
|
+
return bounds;
|
|
32650
|
+
}
|
|
32651
|
+
function buildSampleGrid(pointCloud) {
|
|
32652
|
+
const sampleCount = Math.floor(pointCloud.positions.length / 3);
|
|
32653
|
+
if (sampleCount <= 0) return null;
|
|
32654
|
+
const bounds = new Box3();
|
|
32655
|
+
const point = new Vector3();
|
|
32656
|
+
for (let sample = 0; sample < sampleCount; sample += 1) {
|
|
32657
|
+
const offset = sample * 3;
|
|
32658
|
+
bounds.expandByPoint(point.set(pointCloud.positions[offset], pointCloud.positions[offset + 1], pointCloud.positions[offset + 2]));
|
|
32659
|
+
}
|
|
32660
|
+
const size = bounds.getSize(new Vector3());
|
|
32661
|
+
const maxDim = Math.max(size.x, size.y, size.z);
|
|
32662
|
+
const cellSize = maxDim > 0 ? Math.max(maxDim / Math.cbrt(sampleCount), 1e-6) : 1;
|
|
32663
|
+
const cells = /* @__PURE__ */ new Map();
|
|
32664
|
+
for (let sample = 0; sample < sampleCount; sample += 1) {
|
|
32665
|
+
const offset = sample * 3;
|
|
32666
|
+
const x = Math.floor((pointCloud.positions[offset] - bounds.min.x) / cellSize);
|
|
32667
|
+
const y = Math.floor((pointCloud.positions[offset + 1] - bounds.min.y) / cellSize);
|
|
32668
|
+
const z = Math.floor((pointCloud.positions[offset + 2] - bounds.min.z) / cellSize);
|
|
32669
|
+
const key = gridKey(x, y, z);
|
|
32670
|
+
const entries = cells.get(key);
|
|
32671
|
+
if (entries) {
|
|
32672
|
+
entries.push(sample);
|
|
32673
|
+
} else {
|
|
32674
|
+
cells.set(key, [sample]);
|
|
32675
|
+
}
|
|
32676
|
+
}
|
|
32677
|
+
return { origin: bounds.min, cellSize, cells };
|
|
32678
|
+
}
|
|
32679
|
+
function fieldGridSizeForSampleCount(sampleCount) {
|
|
32680
|
+
if (sampleCount <= 0) return MIN_FIELD_GRID_SIZE;
|
|
32681
|
+
const scaled = Math.ceil(Math.cbrt(sampleCount) * 2.6);
|
|
32682
|
+
return Math.max(MIN_FIELD_GRID_SIZE, Math.min(MAX_FIELD_GRID_SIZE, scaled));
|
|
32683
|
+
}
|
|
32684
|
+
function distanceSquaredToSample(pointCloud, sample, point) {
|
|
32685
|
+
const offset = sample * 3;
|
|
32686
|
+
return (pointCloud.positions[offset] - point.x) ** 2 + (pointCloud.positions[offset + 1] - point.y) ** 2 + (pointCloud.positions[offset + 2] - point.z) ** 2;
|
|
32687
|
+
}
|
|
32688
|
+
function nearestSamples(point, pointCloud, sampleGrid) {
|
|
32689
|
+
const baseX = Math.floor((point.x - sampleGrid.origin.x) / sampleGrid.cellSize);
|
|
32690
|
+
const baseY = Math.floor((point.y - sampleGrid.origin.y) / sampleGrid.cellSize);
|
|
32691
|
+
const baseZ = Math.floor((point.z - sampleGrid.origin.z) / sampleGrid.cellSize);
|
|
32692
|
+
const found = [];
|
|
32693
|
+
for (const ring of SAMPLE_RING_OFFSETS) {
|
|
32694
|
+
for (const [dx, dy, dz] of ring) {
|
|
32695
|
+
const entries = sampleGrid.cells.get(gridKey(baseX + dx, baseY + dy, baseZ + dz));
|
|
32696
|
+
if (!entries) continue;
|
|
32697
|
+
for (const sample of entries) {
|
|
32698
|
+
found.push({ sample, distSq: distanceSquaredToSample(pointCloud, sample, point) });
|
|
32699
|
+
}
|
|
32700
|
+
}
|
|
32701
|
+
if (found.length >= MAX_BLEND_SAMPLES) break;
|
|
32702
|
+
}
|
|
32703
|
+
if (found.length === 0) {
|
|
32704
|
+
const sampleCount = Math.floor(pointCloud.positions.length / 3);
|
|
32705
|
+
for (let sample = 0; sample < sampleCount; sample += 1) {
|
|
32706
|
+
found.push({ sample, distSq: distanceSquaredToSample(pointCloud, sample, point) });
|
|
32707
|
+
}
|
|
32708
|
+
}
|
|
32709
|
+
found.sort((a2, b2) => a2.distSq - b2.distSq);
|
|
32710
|
+
return found.slice(0, MAX_BLEND_SAMPLES);
|
|
32711
|
+
}
|
|
32712
|
+
function blendedColorAt(point, pointCloud, sampleGrid) {
|
|
32713
|
+
const samples = nearestSamples(point, pointCloud, sampleGrid);
|
|
32714
|
+
if (samples.length === 0) return [90, 90, 90];
|
|
32715
|
+
const sigma = Math.max(sampleGrid.cellSize * 1.65, 1e-6);
|
|
32716
|
+
const sigmaSq = sigma * sigma;
|
|
32717
|
+
let weightSum = 0;
|
|
32718
|
+
let r2 = 0;
|
|
32719
|
+
let g2 = 0;
|
|
32720
|
+
let b2 = 0;
|
|
32721
|
+
for (const { sample, distSq } of samples) {
|
|
32722
|
+
const colorOffset = sample * 3;
|
|
32723
|
+
const weight = Math.exp(-distSq / (2 * sigmaSq)) + 1e-4 / Math.max(distSq, 1e-8);
|
|
32724
|
+
weightSum += weight;
|
|
32725
|
+
r2 += (pointCloud.colors[colorOffset] ?? 0.35) * 255 * weight;
|
|
32726
|
+
g2 += (pointCloud.colors[colorOffset + 1] ?? 0.35) * 255 * weight;
|
|
32727
|
+
b2 += (pointCloud.colors[colorOffset + 2] ?? 0.35) * 255 * weight;
|
|
32728
|
+
}
|
|
32729
|
+
if (weightSum <= 0) return [90, 90, 90];
|
|
32730
|
+
return [r2 / weightSum, g2 / weightSum, b2 / weightSum];
|
|
32731
|
+
}
|
|
32732
|
+
function buildInspectHeatmapField(geometry, pointCloud) {
|
|
32733
|
+
const bounds = buildGeometryBounds(geometry);
|
|
32734
|
+
const sampleGrid = buildSampleGrid(pointCloud);
|
|
32735
|
+
if (!bounds || !sampleGrid) return null;
|
|
32736
|
+
const gridSize = fieldGridSizeForSampleCount(Math.floor(pointCloud.positions.length / 3));
|
|
32737
|
+
const boundsSize = bounds.getSize(new Vector3());
|
|
32738
|
+
const data = new Uint8Array(gridSize * gridSize * gridSize * 4);
|
|
32739
|
+
const point = new Vector3();
|
|
32740
|
+
let dataOffset = 0;
|
|
32741
|
+
for (let y = 0; y < gridSize; y += 1) {
|
|
32742
|
+
for (let z = 0; z < gridSize; z += 1) {
|
|
32743
|
+
for (let x = 0; x < gridSize; x += 1) {
|
|
32744
|
+
point.set(
|
|
32745
|
+
bounds.min.x + boundsSize.x * x / (gridSize - 1),
|
|
32746
|
+
bounds.min.y + boundsSize.y * y / (gridSize - 1),
|
|
32747
|
+
bounds.min.z + boundsSize.z * z / (gridSize - 1)
|
|
32748
|
+
);
|
|
32749
|
+
const [r2, g2, b2] = blendedColorAt(point, pointCloud, sampleGrid);
|
|
32750
|
+
data[dataOffset] = Math.max(0, Math.min(255, Math.round(r2)));
|
|
32751
|
+
data[dataOffset + 1] = Math.max(0, Math.min(255, Math.round(g2)));
|
|
32752
|
+
data[dataOffset + 2] = Math.max(0, Math.min(255, Math.round(b2)));
|
|
32753
|
+
data[dataOffset + 3] = 255;
|
|
32754
|
+
dataOffset += 4;
|
|
32755
|
+
}
|
|
32756
|
+
}
|
|
32757
|
+
}
|
|
32758
|
+
const texture = new DataTexture(data, gridSize * gridSize, gridSize, RGBAFormat, UnsignedByteType);
|
|
32759
|
+
texture.minFilter = NearestFilter;
|
|
32760
|
+
texture.magFilter = NearestFilter;
|
|
32761
|
+
texture.generateMipmaps = false;
|
|
32762
|
+
texture.unpackAlignment = 1;
|
|
32763
|
+
texture.needsUpdate = true;
|
|
32764
|
+
return {
|
|
32765
|
+
texture,
|
|
32766
|
+
boundsMin: bounds.min,
|
|
32767
|
+
boundsSize,
|
|
32768
|
+
gridSize
|
|
32769
|
+
};
|
|
32770
|
+
}
|
|
32190
32771
|
function ForgeObject({
|
|
32191
32772
|
obj,
|
|
32192
32773
|
settings,
|
|
32193
32774
|
renderStyle,
|
|
32194
32775
|
renderMode,
|
|
32776
|
+
inspectChannel = "none",
|
|
32777
|
+
inspectDisplayMode = "heatmap",
|
|
32778
|
+
inspectColor,
|
|
32779
|
+
inspectMeshColors,
|
|
32780
|
+
inspectPointCloud,
|
|
32195
32781
|
isInteracting,
|
|
32196
32782
|
matrix,
|
|
32197
32783
|
isHovered,
|
|
@@ -32228,14 +32814,56 @@ function ForgeObject({
|
|
|
32228
32814
|
};
|
|
32229
32815
|
}
|
|
32230
32816
|
}, [obj.shape]);
|
|
32817
|
+
const inspectPointGeo = reactExports.useMemo(() => {
|
|
32818
|
+
if (!inspectPointCloud) return null;
|
|
32819
|
+
const geometry = new BufferGeometry();
|
|
32820
|
+
geometry.setAttribute("position", new BufferAttribute(inspectPointCloud.positions, 3));
|
|
32821
|
+
geometry.setAttribute("color", new BufferAttribute(inspectPointCloud.colors, 3));
|
|
32822
|
+
return geometry;
|
|
32823
|
+
}, [inspectPointCloud]);
|
|
32824
|
+
const inspectMeshColorGeo = reactExports.useMemo(() => {
|
|
32825
|
+
if (!solidGeo || !inspectMeshColors) return null;
|
|
32826
|
+
const position = solidGeo.getAttribute("position");
|
|
32827
|
+
if (!position || inspectMeshColors.length !== position.count * 3) return null;
|
|
32828
|
+
const geometry = solidGeo.clone();
|
|
32829
|
+
geometry.setAttribute("color", new BufferAttribute(inspectMeshColors, 3));
|
|
32830
|
+
return geometry;
|
|
32831
|
+
}, [inspectMeshColors, solidGeo]);
|
|
32832
|
+
const isScalarInspect = inspectChannel === "thickness" || inspectChannel === "roughness";
|
|
32833
|
+
const inspectHeatmapField = reactExports.useMemo(() => {
|
|
32834
|
+
if (!isScalarInspect || !solidGeo || !inspectPointCloud) return null;
|
|
32835
|
+
return buildInspectHeatmapField(solidGeo, inspectPointCloud);
|
|
32836
|
+
}, [inspectPointCloud, isScalarInspect, solidGeo]);
|
|
32231
32837
|
reactExports.useEffect(() => {
|
|
32232
32838
|
return () => {
|
|
32233
32839
|
solidGeo == null ? void 0 : solidGeo.dispose();
|
|
32234
32840
|
edgesGeo == null ? void 0 : edgesGeo.dispose();
|
|
32235
32841
|
};
|
|
32236
32842
|
}, [edgesGeo, solidGeo]);
|
|
32843
|
+
reactExports.useEffect(() => {
|
|
32844
|
+
return () => {
|
|
32845
|
+
inspectPointGeo == null ? void 0 : inspectPointGeo.dispose();
|
|
32846
|
+
};
|
|
32847
|
+
}, [inspectPointGeo]);
|
|
32848
|
+
reactExports.useEffect(() => {
|
|
32849
|
+
return () => {
|
|
32850
|
+
inspectMeshColorGeo == null ? void 0 : inspectMeshColorGeo.dispose();
|
|
32851
|
+
};
|
|
32852
|
+
}, [inspectMeshColorGeo]);
|
|
32853
|
+
reactExports.useEffect(() => {
|
|
32854
|
+
return () => {
|
|
32855
|
+
inspectHeatmapField == null ? void 0 : inspectHeatmapField.texture.dispose();
|
|
32856
|
+
};
|
|
32857
|
+
}, [inspectHeatmapField]);
|
|
32237
32858
|
if (!solidGeo || !settings.visible) return null;
|
|
32238
32859
|
const effectiveRenderMode = isInteracting && renderMode === "overlay" ? "solid" : renderMode;
|
|
32860
|
+
const isInspecting = inspectChannel !== "none";
|
|
32861
|
+
const showInspectHeatmap = Boolean(
|
|
32862
|
+
isScalarInspect && inspectHeatmapField && (inspectDisplayMode === "heatmap" || inspectDisplayMode === "both")
|
|
32863
|
+
);
|
|
32864
|
+
const showInspectPoints = Boolean(
|
|
32865
|
+
isScalarInspect && inspectPointGeo && (inspectDisplayMode === "points" || inspectDisplayMode === "both")
|
|
32866
|
+
);
|
|
32239
32867
|
const renderStylePreset = getRenderStylePreset(renderStyle);
|
|
32240
32868
|
const materialDefaults = renderStylePreset.material;
|
|
32241
32869
|
const authoredMaterialOpacity = (_a3 = obj.materialProps) == null ? void 0 : _a3.opacity;
|
|
@@ -32247,10 +32875,12 @@ function ForgeObject({
|
|
|
32247
32875
|
const materialOpacity = Math.min(meshOpacity, styleOpacity);
|
|
32248
32876
|
const transmission = authoredMaterialTransmission ?? transparentDefaults.transmission;
|
|
32249
32877
|
const isTransparent = materialOpacity < 1 || transmission > 0;
|
|
32250
|
-
const showSolid = effectiveRenderMode !== "wireframe";
|
|
32251
|
-
const showEdges = effectiveRenderMode === "overlay";
|
|
32252
|
-
const showWire = effectiveRenderMode === "wireframe";
|
|
32878
|
+
const showSolid = isInspecting || effectiveRenderMode !== "wireframe";
|
|
32879
|
+
const showEdges = !isInspecting && effectiveRenderMode === "overlay";
|
|
32880
|
+
const showWire = !isInspecting && effectiveRenderMode === "wireframe";
|
|
32253
32881
|
const effectiveClippingPlanes = clippingPlanes ?? [];
|
|
32882
|
+
const inspectSolidGeo = inspectMeshColorGeo ?? solidGeo;
|
|
32883
|
+
const hasInspectMeshColors = inspectMeshColorGeo !== null;
|
|
32254
32884
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
32255
32885
|
"group",
|
|
32256
32886
|
{
|
|
@@ -32263,7 +32893,70 @@ function ForgeObject({
|
|
|
32263
32893
|
onDoubleClick,
|
|
32264
32894
|
onContextMenu,
|
|
32265
32895
|
children: [
|
|
32266
|
-
showSolid && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry:
|
|
32896
|
+
showSolid && (inspectChannel === "mask" || inspectChannel === "connectivity" || inspectChannel === "distance") && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: inspectSolidGeo, userData: { forgeMesh: true }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32897
|
+
"meshBasicMaterial",
|
|
32898
|
+
{
|
|
32899
|
+
color: hasInspectMeshColors ? "#ffffff" : inspectColor ?? settings.color,
|
|
32900
|
+
vertexColors: hasInspectMeshColors,
|
|
32901
|
+
side: DoubleSide,
|
|
32902
|
+
toneMapped: false,
|
|
32903
|
+
clippingPlanes: effectiveClippingPlanes
|
|
32904
|
+
}
|
|
32905
|
+
) }),
|
|
32906
|
+
showSolid && isScalarInspect && !showInspectHeatmap && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, userData: { forgeMesh: true }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32907
|
+
"meshBasicMaterial",
|
|
32908
|
+
{
|
|
32909
|
+
color: "#26313a",
|
|
32910
|
+
transparent: true,
|
|
32911
|
+
opacity: 0.24,
|
|
32912
|
+
side: DoubleSide,
|
|
32913
|
+
depthWrite: true,
|
|
32914
|
+
toneMapped: false,
|
|
32915
|
+
clippingPlanes: effectiveClippingPlanes
|
|
32916
|
+
}
|
|
32917
|
+
) }),
|
|
32918
|
+
showSolid && showInspectHeatmap && inspectHeatmapField && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, userData: { forgeMesh: true }, renderOrder: 4, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32919
|
+
"shaderMaterial",
|
|
32920
|
+
{
|
|
32921
|
+
vertexShader: INSPECT_HEATMAP_VERTEX_SHADER,
|
|
32922
|
+
fragmentShader: INSPECT_HEATMAP_FRAGMENT_SHADER,
|
|
32923
|
+
uniforms: {
|
|
32924
|
+
uField: { value: inspectHeatmapField.texture },
|
|
32925
|
+
uGridSize: { value: inspectHeatmapField.gridSize },
|
|
32926
|
+
uBoundsMin: { value: inspectHeatmapField.boundsMin },
|
|
32927
|
+
uBoundsSize: { value: inspectHeatmapField.boundsSize }
|
|
32928
|
+
},
|
|
32929
|
+
side: DoubleSide,
|
|
32930
|
+
toneMapped: false,
|
|
32931
|
+
clippingPlanes: effectiveClippingPlanes
|
|
32932
|
+
}
|
|
32933
|
+
) }),
|
|
32934
|
+
showSolid && showInspectPoints && inspectPointGeo && /* @__PURE__ */ jsxRuntimeExports.jsx("points", { geometry: inspectPointGeo, raycast: () => null, renderOrder: 5, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32935
|
+
"pointsMaterial",
|
|
32936
|
+
{
|
|
32937
|
+
size: 3,
|
|
32938
|
+
sizeAttenuation: false,
|
|
32939
|
+
vertexColors: true,
|
|
32940
|
+
depthTest: true,
|
|
32941
|
+
depthWrite: false,
|
|
32942
|
+
toneMapped: false,
|
|
32943
|
+
clippingPlanes: effectiveClippingPlanes
|
|
32944
|
+
}
|
|
32945
|
+
) }),
|
|
32946
|
+
showSolid && inspectChannel === "collisions" && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, userData: { forgeMesh: true }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32947
|
+
"meshPhysicalMaterial",
|
|
32948
|
+
{
|
|
32949
|
+
color: rgbToHex(COLLISION_SOURCE_COLOR),
|
|
32950
|
+
roughness: 0.75,
|
|
32951
|
+
metalness: 0,
|
|
32952
|
+
side: DoubleSide,
|
|
32953
|
+
transparent: true,
|
|
32954
|
+
opacity: COLLISION_SOURCE_OPACITY,
|
|
32955
|
+
depthWrite: false,
|
|
32956
|
+
clippingPlanes: effectiveClippingPlanes
|
|
32957
|
+
}
|
|
32958
|
+
) }),
|
|
32959
|
+
showSolid && inspectChannel === "none" && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, userData: { forgeMesh: true }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32267
32960
|
"meshPhysicalMaterial",
|
|
32268
32961
|
{
|
|
32269
32962
|
color: settings.color,
|
|
@@ -32288,7 +32981,7 @@ function ForgeObject({
|
|
|
32288
32981
|
clippingPlanes: effectiveClippingPlanes
|
|
32289
32982
|
}
|
|
32290
32983
|
) }),
|
|
32291
|
-
showSolid && hasAuthoredTransparency && renderStylePreset.glassShell.enabled && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, scale: renderStylePreset.glassShell.scale, raycast: () => null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32984
|
+
showSolid && inspectChannel === "none" && hasAuthoredTransparency && renderStylePreset.glassShell.enabled && /* @__PURE__ */ jsxRuntimeExports.jsx("mesh", { geometry: solidGeo, scale: renderStylePreset.glassShell.scale, raycast: () => null, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
32292
32985
|
"meshBasicMaterial",
|
|
32293
32986
|
{
|
|
32294
32987
|
color: renderStylePreset.glassShell.color,
|
|
@@ -37855,6 +38548,9 @@ function useViewportState() {
|
|
|
37855
38548
|
const files = useForgeStore((s) => s.files);
|
|
37856
38549
|
const renderMode = useForgeStore((s) => s.renderMode);
|
|
37857
38550
|
const renderStyle = useForgeStore((s) => s.renderStyle);
|
|
38551
|
+
const inspectChannel = useForgeStore((s) => s.inspectChannel);
|
|
38552
|
+
const inspectDisplayMode = useForgeStore((s) => s.inspectDisplayMode);
|
|
38553
|
+
const inspectPointSampleCount = useForgeStore((s) => s.inspectPointSampleCount);
|
|
37858
38554
|
const projectionMode = useForgeStore((s) => s.projectionMode);
|
|
37859
38555
|
const gridEnabled = useForgeStore((s) => s.gridEnabled);
|
|
37860
38556
|
const gridSize = useForgeStore((s) => s.gridSize);
|
|
@@ -38181,6 +38877,9 @@ function useViewportState() {
|
|
|
38181
38877
|
files,
|
|
38182
38878
|
renderMode,
|
|
38183
38879
|
renderStyle,
|
|
38880
|
+
inspectChannel,
|
|
38881
|
+
inspectDisplayMode,
|
|
38882
|
+
inspectPointSampleCount,
|
|
38184
38883
|
projectionMode,
|
|
38185
38884
|
gridEnabled,
|
|
38186
38885
|
gridSize,
|
|
@@ -39557,6 +40256,276 @@ function RenderLabelsOverlay({ labels }) {
|
|
|
39557
40256
|
if (labels.length === 0) return null;
|
|
39558
40257
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("group", { renderOrder: 12, children: labels.map((label) => /* @__PURE__ */ jsxRuntimeExports.jsx(RenderLabelItem, { label }, label.id)) });
|
|
39559
40258
|
}
|
|
40259
|
+
class InspectWorkerClient {
|
|
40260
|
+
constructor(workerFactory = () => new Worker(new URL(
|
|
40261
|
+
/* @vite-ignore */
|
|
40262
|
+
"/assets/inspectWorker-Dll4eVyD.js",
|
|
40263
|
+
import.meta.url
|
|
40264
|
+
), { type: "module" })) {
|
|
40265
|
+
__publicField(this, "worker", null);
|
|
40266
|
+
__publicField(this, "reqId", 0);
|
|
40267
|
+
__publicField(this, "pending", null);
|
|
40268
|
+
this.workerFactory = workerFactory;
|
|
40269
|
+
}
|
|
40270
|
+
getWorker() {
|
|
40271
|
+
if (this.worker) return this.worker;
|
|
40272
|
+
this.worker = this.workerFactory();
|
|
40273
|
+
this.worker.onmessage = (event) => {
|
|
40274
|
+
const data = event.data;
|
|
40275
|
+
const pending = this.pending;
|
|
40276
|
+
if (!pending) return;
|
|
40277
|
+
this.pending = null;
|
|
40278
|
+
if (data.type === "inspect-error") {
|
|
40279
|
+
pending.reject(new Error(data.payload.message));
|
|
40280
|
+
} else {
|
|
40281
|
+
pending.resolve(data.payload.result);
|
|
40282
|
+
}
|
|
40283
|
+
};
|
|
40284
|
+
this.worker.onerror = (event) => {
|
|
40285
|
+
var _a3, _b2;
|
|
40286
|
+
const error = new Error(event.message || "Inspect worker failed unexpectedly.");
|
|
40287
|
+
(_a3 = this.pending) == null ? void 0 : _a3.reject(error);
|
|
40288
|
+
this.pending = null;
|
|
40289
|
+
(_b2 = this.worker) == null ? void 0 : _b2.terminate();
|
|
40290
|
+
this.worker = null;
|
|
40291
|
+
};
|
|
40292
|
+
return this.worker;
|
|
40293
|
+
}
|
|
40294
|
+
replaceActiveWorker() {
|
|
40295
|
+
var _a3, _b2;
|
|
40296
|
+
(_a3 = this.pending) == null ? void 0 : _a3.reject(new Error("cancelled"));
|
|
40297
|
+
this.pending = null;
|
|
40298
|
+
(_b2 = this.worker) == null ? void 0 : _b2.terminate();
|
|
40299
|
+
this.worker = null;
|
|
40300
|
+
}
|
|
40301
|
+
analyze(payload) {
|
|
40302
|
+
if (this.pending) this.replaceActiveWorker();
|
|
40303
|
+
const reqId = ++this.reqId;
|
|
40304
|
+
const request = {
|
|
40305
|
+
type: "analyze",
|
|
40306
|
+
payload: {
|
|
40307
|
+
reqId,
|
|
40308
|
+
...payload
|
|
40309
|
+
}
|
|
40310
|
+
};
|
|
40311
|
+
const transfers = payload.objects.flatMap((object) => object.positions ? [object.positions.buffer] : []);
|
|
40312
|
+
return new Promise((resolve2, reject) => {
|
|
40313
|
+
this.pending = { resolve: resolve2, reject };
|
|
40314
|
+
this.getWorker().postMessage(request, transfers);
|
|
40315
|
+
});
|
|
40316
|
+
}
|
|
40317
|
+
dispose() {
|
|
40318
|
+
this.replaceActiveWorker();
|
|
40319
|
+
}
|
|
40320
|
+
}
|
|
40321
|
+
const inspectWorkerClient = new InspectWorkerClient();
|
|
40322
|
+
const WORKER_CHANNELS = /* @__PURE__ */ new Set(["thickness", "roughness", "connectivity", "distance"]);
|
|
40323
|
+
const SCALAR_WORKER_CHANNELS = /* @__PURE__ */ new Set(["thickness", "roughness"]);
|
|
40324
|
+
const MESH_COMPONENT_WORKER_CHANNELS = /* @__PURE__ */ new Set(["connectivity", "distance"]);
|
|
40325
|
+
const VIEWPORT_SCALAR_SCENE_BUDGET_OBJECTS = 15;
|
|
40326
|
+
class InspectBuildCancelledError extends Error {
|
|
40327
|
+
constructor() {
|
|
40328
|
+
super("cancelled");
|
|
40329
|
+
}
|
|
40330
|
+
}
|
|
40331
|
+
function isScalarWorkerChannel(channel) {
|
|
40332
|
+
return SCALAR_WORKER_CHANNELS.has(channel);
|
|
40333
|
+
}
|
|
40334
|
+
function needsMeshComponents(channel) {
|
|
40335
|
+
return MESH_COMPONENT_WORKER_CHANNELS.has(channel);
|
|
40336
|
+
}
|
|
40337
|
+
function viewportScalarSamplesPerObject(objectCount, inspectPointSampleCount) {
|
|
40338
|
+
const perObjectCap = resolveInspectPointSampleCount(inspectPointSampleCount);
|
|
40339
|
+
if (objectCount <= 0) return perObjectCap;
|
|
40340
|
+
const sceneBudget = perObjectCap * VIEWPORT_SCALAR_SCENE_BUDGET_OBJECTS;
|
|
40341
|
+
const budgeted = Math.floor(sceneBudget / objectCount);
|
|
40342
|
+
return Math.max(INSPECT_POINT_SAMPLE_COUNT_MIN, Math.min(perObjectCap, budgeted));
|
|
40343
|
+
}
|
|
40344
|
+
function yieldToBrowser() {
|
|
40345
|
+
if (typeof window === "undefined") return Promise.resolve();
|
|
40346
|
+
return new Promise((resolve2) => {
|
|
40347
|
+
const maybeIdleWindow = window;
|
|
40348
|
+
if (typeof maybeIdleWindow.requestIdleCallback === "function") {
|
|
40349
|
+
maybeIdleWindow.requestIdleCallback(() => resolve2(), { timeout: 50 });
|
|
40350
|
+
return;
|
|
40351
|
+
}
|
|
40352
|
+
window.setTimeout(resolve2, 0);
|
|
40353
|
+
});
|
|
40354
|
+
}
|
|
40355
|
+
function transformedBounds(obj, matrix) {
|
|
40356
|
+
if (!obj.shape) return null;
|
|
40357
|
+
try {
|
|
40358
|
+
const bbox = obj.shape.boundingBox();
|
|
40359
|
+
const bounds = new Box3();
|
|
40360
|
+
if (!expandBoundsByTransformedAabb(bounds, bbox.min, bbox.max, matrix)) return null;
|
|
40361
|
+
if (!isFiniteBox3(bounds)) return null;
|
|
40362
|
+
return {
|
|
40363
|
+
min: [bounds.min.x, bounds.min.y, bounds.min.z],
|
|
40364
|
+
max: [bounds.max.x, bounds.max.y, bounds.max.z]
|
|
40365
|
+
};
|
|
40366
|
+
} catch {
|
|
40367
|
+
return null;
|
|
40368
|
+
}
|
|
40369
|
+
}
|
|
40370
|
+
function clonePositions(obj, matrix) {
|
|
40371
|
+
var _a3;
|
|
40372
|
+
if (!obj.shape) return void 0;
|
|
40373
|
+
const geometry = obj.shape instanceof FrozenShape ? null : shapeToGeometry(obj.shape);
|
|
40374
|
+
try {
|
|
40375
|
+
const source = obj.shape instanceof FrozenShape ? obj.shape.getPrecomputedGeometry().positions : (_a3 = geometry == null ? void 0 : geometry.solid.getAttribute("position")) == null ? void 0 : _a3.array;
|
|
40376
|
+
if (!source) return void 0;
|
|
40377
|
+
const positions = new Float32Array(source);
|
|
40378
|
+
if (matrix) {
|
|
40379
|
+
const point = new Vector3();
|
|
40380
|
+
for (let index = 0; index < positions.length; index += 3) {
|
|
40381
|
+
point.set(positions[index], positions[index + 1], positions[index + 2]).applyMatrix4(matrix);
|
|
40382
|
+
positions[index] = point.x;
|
|
40383
|
+
positions[index + 1] = point.y;
|
|
40384
|
+
positions[index + 2] = point.z;
|
|
40385
|
+
}
|
|
40386
|
+
}
|
|
40387
|
+
return positions;
|
|
40388
|
+
} finally {
|
|
40389
|
+
geometry == null ? void 0 : geometry.solid.dispose();
|
|
40390
|
+
geometry == null ? void 0 : geometry.edges.dispose();
|
|
40391
|
+
}
|
|
40392
|
+
}
|
|
40393
|
+
async function buildWorkerObjects(args) {
|
|
40394
|
+
var _a3;
|
|
40395
|
+
const needsMesh = isScalarWorkerChannel(args.inspectChannel) || needsMeshComponents(args.inspectChannel);
|
|
40396
|
+
const out = [];
|
|
40397
|
+
for (const obj of args.objects) {
|
|
40398
|
+
if (args.isCancelled()) throw new InspectBuildCancelledError();
|
|
40399
|
+
if (!obj.shape) continue;
|
|
40400
|
+
if (((_a3 = args.objectSettings[obj.id]) == null ? void 0 : _a3.visible) === false) continue;
|
|
40401
|
+
await yieldToBrowser();
|
|
40402
|
+
if (args.isCancelled()) throw new InspectBuildCancelledError();
|
|
40403
|
+
const matrix = args.objectMatrices[obj.id] ?? new Matrix4();
|
|
40404
|
+
const bbox = transformedBounds(obj, matrix);
|
|
40405
|
+
if (!bbox) continue;
|
|
40406
|
+
if (args.isCancelled()) throw new InspectBuildCancelledError();
|
|
40407
|
+
out.push({
|
|
40408
|
+
id: obj.id,
|
|
40409
|
+
name: obj.name,
|
|
40410
|
+
groupName: obj.groupName,
|
|
40411
|
+
treePath: obj.treePath,
|
|
40412
|
+
mock: obj.mock,
|
|
40413
|
+
bbox,
|
|
40414
|
+
...needsMesh ? { positions: clonePositions(obj, needsMeshComponents(args.inspectChannel) ? matrix : void 0) } : {}
|
|
40415
|
+
});
|
|
40416
|
+
await yieldToBrowser();
|
|
40417
|
+
}
|
|
40418
|
+
return out;
|
|
40419
|
+
}
|
|
40420
|
+
function analyzePayloadFor(channel, objects, inspectPointSampleCount) {
|
|
40421
|
+
const maxSamplesPerObject = viewportScalarSamplesPerObject(objects.length, inspectPointSampleCount);
|
|
40422
|
+
if (channel === "thickness") {
|
|
40423
|
+
return {
|
|
40424
|
+
channel,
|
|
40425
|
+
objects,
|
|
40426
|
+
thickness: {
|
|
40427
|
+
maxSamplesPerObject
|
|
40428
|
+
}
|
|
40429
|
+
};
|
|
40430
|
+
}
|
|
40431
|
+
if (channel === "roughness") {
|
|
40432
|
+
return {
|
|
40433
|
+
channel,
|
|
40434
|
+
objects,
|
|
40435
|
+
roughness: {
|
|
40436
|
+
maxSamplesPerObject
|
|
40437
|
+
}
|
|
40438
|
+
};
|
|
40439
|
+
}
|
|
40440
|
+
return { channel, objects };
|
|
40441
|
+
}
|
|
40442
|
+
function resultToState(channel, result) {
|
|
40443
|
+
return {
|
|
40444
|
+
status: "ready",
|
|
40445
|
+
channel,
|
|
40446
|
+
objectColors: result.objectColors,
|
|
40447
|
+
meshColors: Object.fromEntries(result.meshColorObjects.map((object) => [object.objectId, object.colors])),
|
|
40448
|
+
pointClouds: Object.fromEntries(
|
|
40449
|
+
result.pointObjects.map((object) => [
|
|
40450
|
+
object.objectId,
|
|
40451
|
+
{
|
|
40452
|
+
sampleCount: object.sampleCount,
|
|
40453
|
+
positions: object.positions,
|
|
40454
|
+
colors: object.colors
|
|
40455
|
+
}
|
|
40456
|
+
])
|
|
40457
|
+
),
|
|
40458
|
+
warnings: result.warnings,
|
|
40459
|
+
error: null
|
|
40460
|
+
};
|
|
40461
|
+
}
|
|
40462
|
+
function useInspectWorkerAnalysis(args) {
|
|
40463
|
+
const [state2, setState] = reactExports.useState({
|
|
40464
|
+
status: "idle",
|
|
40465
|
+
channel: "none",
|
|
40466
|
+
objectColors: {},
|
|
40467
|
+
meshColors: {},
|
|
40468
|
+
pointClouds: {},
|
|
40469
|
+
warnings: [],
|
|
40470
|
+
error: null
|
|
40471
|
+
});
|
|
40472
|
+
reactExports.useEffect(() => {
|
|
40473
|
+
if (!WORKER_CHANNELS.has(args.inspectChannel)) {
|
|
40474
|
+
inspectWorkerClient.dispose();
|
|
40475
|
+
setState({
|
|
40476
|
+
status: "idle",
|
|
40477
|
+
channel: args.inspectChannel,
|
|
40478
|
+
objectColors: {},
|
|
40479
|
+
meshColors: {},
|
|
40480
|
+
pointClouds: {},
|
|
40481
|
+
warnings: [],
|
|
40482
|
+
error: null
|
|
40483
|
+
});
|
|
40484
|
+
return;
|
|
40485
|
+
}
|
|
40486
|
+
let cancelled = false;
|
|
40487
|
+
const channel = args.inspectChannel;
|
|
40488
|
+
setState({
|
|
40489
|
+
status: "loading",
|
|
40490
|
+
channel: args.inspectChannel,
|
|
40491
|
+
objectColors: {},
|
|
40492
|
+
meshColors: {},
|
|
40493
|
+
pointClouds: {},
|
|
40494
|
+
warnings: [],
|
|
40495
|
+
error: null
|
|
40496
|
+
});
|
|
40497
|
+
void (async () => {
|
|
40498
|
+
try {
|
|
40499
|
+
const objects = await buildWorkerObjects({
|
|
40500
|
+
...args,
|
|
40501
|
+
isCancelled: () => cancelled
|
|
40502
|
+
});
|
|
40503
|
+
if (cancelled) return;
|
|
40504
|
+
const result = await inspectWorkerClient.analyze(analyzePayloadFor(channel, objects, args.inspectPointSampleCount));
|
|
40505
|
+
if (cancelled) return;
|
|
40506
|
+
setState(resultToState(args.inspectChannel, result));
|
|
40507
|
+
} catch (error) {
|
|
40508
|
+
if (cancelled || error instanceof InspectBuildCancelledError || error instanceof Error && error.message === "cancelled") {
|
|
40509
|
+
return;
|
|
40510
|
+
}
|
|
40511
|
+
setState({
|
|
40512
|
+
status: "error",
|
|
40513
|
+
channel: args.inspectChannel,
|
|
40514
|
+
objectColors: {},
|
|
40515
|
+
meshColors: {},
|
|
40516
|
+
pointClouds: {},
|
|
40517
|
+
warnings: [],
|
|
40518
|
+
error: error instanceof Error ? error.message : String(error)
|
|
40519
|
+
});
|
|
40520
|
+
}
|
|
40521
|
+
})();
|
|
40522
|
+
return () => {
|
|
40523
|
+
cancelled = true;
|
|
40524
|
+
inspectWorkerClient.dispose();
|
|
40525
|
+
};
|
|
40526
|
+
}, [args.inspectChannel, args.inspectPointSampleCount, args.sceneVersion, args.objects, args.objectSettings, args.objectMatrices]);
|
|
40527
|
+
return state2;
|
|
40528
|
+
}
|
|
39560
40529
|
function panelNumber(value) {
|
|
39561
40530
|
if (!Number.isFinite(value)) return String(value);
|
|
39562
40531
|
if (Number.isInteger(value)) return String(value);
|
|
@@ -39582,6 +40551,20 @@ function edgeCurveLabel(edge) {
|
|
|
39582
40551
|
return "segment";
|
|
39583
40552
|
}
|
|
39584
40553
|
}
|
|
40554
|
+
function inspectChannelLabel(channel) {
|
|
40555
|
+
switch (channel) {
|
|
40556
|
+
case "connectivity":
|
|
40557
|
+
return "Connect";
|
|
40558
|
+
case "distance":
|
|
40559
|
+
return "Distance";
|
|
40560
|
+
case "thickness":
|
|
40561
|
+
return "Thickness";
|
|
40562
|
+
case "roughness":
|
|
40563
|
+
return "Roughness";
|
|
40564
|
+
default:
|
|
40565
|
+
return "Inspect";
|
|
40566
|
+
}
|
|
40567
|
+
}
|
|
39585
40568
|
function edgeBelongsToFace(edge, faceName) {
|
|
39586
40569
|
var _a3;
|
|
39587
40570
|
return edge.faceName === faceName || ((_a3 = edge.curve) == null ? void 0 : _a3.faceName) === faceName || edge.name.startsWith(`${faceName}:`);
|
|
@@ -39669,6 +40652,8 @@ function RenderStyleExposure({ exposure }) {
|
|
|
39669
40652
|
function Viewport() {
|
|
39670
40653
|
var _a3, _b2, _c;
|
|
39671
40654
|
const activeFile = useForgeStore((s) => s.activeFile);
|
|
40655
|
+
const activeBackend = useForgeStore((s) => s.activeBackend);
|
|
40656
|
+
const computeTarget = useForgeStore((s) => s.computeTarget);
|
|
39672
40657
|
const isSvgActive = !!activeFile && activeFile.toLowerCase().endsWith(".svg");
|
|
39673
40658
|
const state2 = useViewportState();
|
|
39674
40659
|
const {
|
|
@@ -39677,6 +40662,9 @@ function Viewport() {
|
|
|
39677
40662
|
evaluationPhase,
|
|
39678
40663
|
renderMode,
|
|
39679
40664
|
renderStyle,
|
|
40665
|
+
inspectChannel,
|
|
40666
|
+
inspectDisplayMode,
|
|
40667
|
+
inspectPointSampleCount,
|
|
39680
40668
|
projectionMode,
|
|
39681
40669
|
gridEnabled,
|
|
39682
40670
|
gridSize,
|
|
@@ -39760,6 +40748,7 @@ function Viewport() {
|
|
|
39760
40748
|
const contextMenuRef = reactExports.useRef(null);
|
|
39761
40749
|
const t2 = themes[themeName];
|
|
39762
40750
|
const renderStylePreset = reactExports.useMemo(() => getRenderStylePreset(renderStyle), [renderStyle]);
|
|
40751
|
+
const inspectChannelActive = inspectChannel !== "none";
|
|
39763
40752
|
const hasVisibleSdfObjects = objects.some((obj) => {
|
|
39764
40753
|
var _a4;
|
|
39765
40754
|
return obj.sdf && (((_a4 = objectSettings[obj.id]) == null ? void 0 : _a4.visible) ?? true);
|
|
@@ -39776,6 +40765,27 @@ function Viewport() {
|
|
|
39776
40765
|
}
|
|
39777
40766
|
return next;
|
|
39778
40767
|
}, [constructionGhost, focusedObjectIdSet, objectSettings, objects]);
|
|
40768
|
+
const inspectAnalysis = useInspectWorkerAnalysis({
|
|
40769
|
+
inspectChannel,
|
|
40770
|
+
inspectPointSampleCount,
|
|
40771
|
+
sceneVersion,
|
|
40772
|
+
objects,
|
|
40773
|
+
objectSettings,
|
|
40774
|
+
objectMatrices
|
|
40775
|
+
});
|
|
40776
|
+
const inspectLoading = inspectChannelActive && inspectAnalysis.status === "loading";
|
|
40777
|
+
const viewportBusyPhase = isEvaluating || evaluationPhase === "exporting" ? evaluationPhase : inspectLoading ? "inspecting" : null;
|
|
40778
|
+
const viewportBusyLabel = inspectLoading ? `Generating ${inspectChannelLabel(inspectChannel)} inspect view` : void 0;
|
|
40779
|
+
const rebuildHistorySteps = reactExports.useMemo(() => {
|
|
40780
|
+
if (!isEvaluating || historyMode) return [];
|
|
40781
|
+
const historyObjects = [];
|
|
40782
|
+
for (const obj of objects) {
|
|
40783
|
+
if (!obj.shape) continue;
|
|
40784
|
+
const plan = getShapeCompilePlan(obj.shape);
|
|
40785
|
+
if (plan) historyObjects.push({ id: obj.id, plan });
|
|
40786
|
+
}
|
|
40787
|
+
return historyObjects.length > 0 ? linearizeMultiObjectSteps(historyObjects) : [];
|
|
40788
|
+
}, [historyMode, isEvaluating, objects]);
|
|
39779
40789
|
const handlers = useViewportHandlers({
|
|
39780
40790
|
containerRef,
|
|
39781
40791
|
contextMenuRef,
|
|
@@ -39839,7 +40849,7 @@ function Viewport() {
|
|
|
39839
40849
|
Canvas,
|
|
39840
40850
|
{
|
|
39841
40851
|
style: {
|
|
39842
|
-
background: renderStyle === "classic" ? t2.viewportBg : renderStylePreset.background,
|
|
40852
|
+
background: inspectChannelActive ? "#000000" : renderStyle === "classic" ? t2.viewportBg : renderStylePreset.background,
|
|
39843
40853
|
cursor: measureMode ? "crosshair" : "default"
|
|
39844
40854
|
},
|
|
39845
40855
|
dpr: canvasDpr,
|
|
@@ -39907,8 +40917,8 @@ function Viewport() {
|
|
|
39907
40917
|
)
|
|
39908
40918
|
] }),
|
|
39909
40919
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ClippingManager, { active: hasAnyObjectCutPlanes }),
|
|
39910
|
-
sectionExplorerEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(SectionExplorerGizmo, { size: sectionGuideSize }),
|
|
39911
|
-
sectionPlaneGuidesEnabled && activeCutPlaneDefs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40920
|
+
!inspectChannelActive && sectionExplorerEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(SectionExplorerGizmo, { size: sectionGuideSize }),
|
|
40921
|
+
!inspectChannelActive && sectionPlaneGuidesEnabled && activeCutPlaneDefs.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
39912
40922
|
SectionPlaneGuides,
|
|
39913
40923
|
{
|
|
39914
40924
|
cutPlanes: scriptCutPlaneDefs,
|
|
@@ -39940,6 +40950,11 @@ function Viewport() {
|
|
|
39940
40950
|
settings: effectiveSettings,
|
|
39941
40951
|
renderStyle,
|
|
39942
40952
|
renderMode,
|
|
40953
|
+
inspectChannel,
|
|
40954
|
+
inspectDisplayMode,
|
|
40955
|
+
inspectColor: inspectAnalysis.objectColors[obj.id] ?? maskColorForIndex(objIndex),
|
|
40956
|
+
inspectMeshColors: inspectAnalysis.meshColors[obj.id],
|
|
40957
|
+
inspectPointCloud: inspectAnalysis.pointClouds[obj.id],
|
|
39943
40958
|
isInteracting: isViewportInteracting,
|
|
39944
40959
|
matrix,
|
|
39945
40960
|
isHovered,
|
|
@@ -40004,7 +41019,8 @@ function Viewport() {
|
|
|
40004
41019
|
}
|
|
40005
41020
|
return null;
|
|
40006
41021
|
}),
|
|
40007
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41022
|
+
inspectChannel === "collisions" && /* @__PURE__ */ jsxRuntimeExports.jsx(CollisionInspectionOverlay, { objects, objectSettings, objectMatrices }),
|
|
41023
|
+
!inspectChannelActive && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40008
41024
|
SectionCaps,
|
|
40009
41025
|
{
|
|
40010
41026
|
sceneVersion,
|
|
@@ -40016,17 +41032,17 @@ function Viewport() {
|
|
|
40016
41032
|
isInteracting: isViewportInteracting
|
|
40017
41033
|
}
|
|
40018
41034
|
),
|
|
40019
|
-
constructionGhost && /* @__PURE__ */ jsxRuntimeExports.jsx(ConstructionGhostOverlay, { matrix: constructionGhostMatrix }),
|
|
40020
|
-
historyMode && /* @__PURE__ */ jsxRuntimeExports.jsx(ConstructionHistoryOverlay, { objectMatrices, objectSettings }),
|
|
40021
|
-
hoveredJointOverlay && /* @__PURE__ */ jsxRuntimeExports.jsx(HoveredJointOverlay, { state: hoveredJointOverlay, config: jointOverlayConfig }),
|
|
40022
|
-
dimensionsVisible && dimensions.map((d) => /* @__PURE__ */ jsxRuntimeExports.jsx(DimensionAnnotation, { def: d, lengthUnit }, d.id)),
|
|
40023
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx(RenderLabelsOverlay, { labels: renderLabels }),
|
|
40024
|
-
attachmentsVisible !== "none" && attachmentPoints.map((ap) => {
|
|
41035
|
+
!inspectChannelActive && constructionGhost && /* @__PURE__ */ jsxRuntimeExports.jsx(ConstructionGhostOverlay, { matrix: constructionGhostMatrix }),
|
|
41036
|
+
!inspectChannelActive && historyMode && /* @__PURE__ */ jsxRuntimeExports.jsx(ConstructionHistoryOverlay, { objectMatrices, objectSettings }),
|
|
41037
|
+
!inspectChannelActive && hoveredJointOverlay && /* @__PURE__ */ jsxRuntimeExports.jsx(HoveredJointOverlay, { state: hoveredJointOverlay, config: jointOverlayConfig }),
|
|
41038
|
+
!inspectChannelActive && dimensionsVisible && dimensions.map((d) => /* @__PURE__ */ jsxRuntimeExports.jsx(DimensionAnnotation, { def: d, lengthUnit }, d.id)),
|
|
41039
|
+
!inspectChannelActive && /* @__PURE__ */ jsxRuntimeExports.jsx(RenderLabelsOverlay, { labels: renderLabels }),
|
|
41040
|
+
!inspectChannelActive && attachmentsVisible !== "none" && attachmentPoints.map((ap) => {
|
|
40025
41041
|
const matrix = objectMatrices[ap.objectId];
|
|
40026
41042
|
return matrix ? /* @__PURE__ */ jsxRuntimeExports.jsx("group", { matrixAutoUpdate: false, matrix, children: /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectorAttachmentAnnotation, { def: ap }) }, `${ap.objectId}:${ap.name}`) : /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectorAttachmentAnnotation, { def: ap }, `${ap.objectId}:${ap.name}`);
|
|
40027
41043
|
}),
|
|
40028
41044
|
/* @__PURE__ */ jsxRuntimeExports.jsx(MeasureTool, {}),
|
|
40029
|
-
debugHighlights3D.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(DebugHighlightsOverlay, { highlights: debugHighlights3D }),
|
|
41045
|
+
!inspectChannelActive && debugHighlights3D.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(DebugHighlightsOverlay, { highlights: debugHighlights3D }),
|
|
40030
41046
|
drawFlagEnabled && /* @__PURE__ */ jsxRuntimeExports.jsx(DrawCanvas, {}),
|
|
40031
41047
|
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40032
41048
|
PerformanceInfoSampler,
|
|
@@ -40039,7 +41055,7 @@ function Viewport() {
|
|
|
40039
41055
|
}
|
|
40040
41056
|
),
|
|
40041
41057
|
/* @__PURE__ */ jsxRuntimeExports.jsx(ZoomSampler, { onZoomChange: setZoomMmPerPx }),
|
|
40042
|
-
gridEnabled && !isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41058
|
+
!inspectChannelActive && gridEnabled && !isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40043
41059
|
Grid,
|
|
40044
41060
|
{
|
|
40045
41061
|
args: [500, 500],
|
|
@@ -40054,7 +41070,7 @@ function Viewport() {
|
|
|
40054
41070
|
infiniteGrid: true
|
|
40055
41071
|
}
|
|
40056
41072
|
),
|
|
40057
|
-
!isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41073
|
+
!inspectChannelActive && !isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40058
41074
|
SdfRaymarchLayer,
|
|
40059
41075
|
{
|
|
40060
41076
|
objects,
|
|
@@ -40069,11 +41085,11 @@ function Viewport() {
|
|
|
40069
41085
|
onContextMenu: (obj, event) => handleObjectContextMenu(obj, event)
|
|
40070
41086
|
}
|
|
40071
41087
|
),
|
|
40072
|
-
!isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(LabeledAxes, {}),
|
|
40073
|
-
isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(SketchAxes, {}),
|
|
41088
|
+
!inspectChannelActive && !isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(LabeledAxes, {}),
|
|
41089
|
+
!inspectChannelActive && isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(SketchAxes, {}),
|
|
40074
41090
|
isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(CursorTracker, { onMove: (x, y) => setCursorPos({ x, y }) }),
|
|
40075
41091
|
isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(SketchRulersUpdater, { hCanvasRef: hRulerRef, vCanvasRef: vRulerRef }),
|
|
40076
|
-
gridEnabled && isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41092
|
+
!inspectChannelActive && gridEnabled && isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40077
41093
|
Grid,
|
|
40078
41094
|
{
|
|
40079
41095
|
args: [500, 500],
|
|
@@ -40195,7 +41211,7 @@ function Viewport() {
|
|
|
40195
41211
|
}
|
|
40196
41212
|
),
|
|
40197
41213
|
/* @__PURE__ */ jsxRuntimeExports.jsx(PerformanceInfoPanel, { enabled: showPerformanceInfo, stats: performanceInfo }),
|
|
40198
|
-
!
|
|
41214
|
+
!viewportBusyPhase && /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIndicatorPanel, { mmPerPx: zoomMmPerPx }),
|
|
40199
41215
|
isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
40200
41216
|
SketchRulersOverlay,
|
|
40201
41217
|
{
|
|
@@ -40226,7 +41242,44 @@ function Viewport() {
|
|
|
40226
41242
|
}
|
|
40227
41243
|
),
|
|
40228
41244
|
measureMode && /* @__PURE__ */ jsxRuntimeExports.jsx(MeasureInfoPanel, {}),
|
|
40229
|
-
|
|
41245
|
+
viewportBusyPhase && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
41246
|
+
EvaluationIndicator,
|
|
41247
|
+
{
|
|
41248
|
+
phase: viewportBusyPhase,
|
|
41249
|
+
label: viewportBusyLabel,
|
|
41250
|
+
constructionSteps: rebuildHistorySteps,
|
|
41251
|
+
activeBackend,
|
|
41252
|
+
computeTarget
|
|
41253
|
+
}
|
|
41254
|
+
),
|
|
41255
|
+
inspectChannelActive && inspectAnalysis.status === "error" && inspectAnalysis.error && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
41256
|
+
"div",
|
|
41257
|
+
{
|
|
41258
|
+
style: {
|
|
41259
|
+
position: "absolute",
|
|
41260
|
+
top: 12,
|
|
41261
|
+
left: "50%",
|
|
41262
|
+
transform: "translateX(-50%)",
|
|
41263
|
+
background: "rgba(127, 29, 29, 0.92)",
|
|
41264
|
+
color: "#fee2e2",
|
|
41265
|
+
border: "1px solid rgba(254, 202, 202, 0.4)",
|
|
41266
|
+
borderRadius: 6,
|
|
41267
|
+
padding: "7px 12px",
|
|
41268
|
+
fontSize: 12,
|
|
41269
|
+
fontWeight: 600,
|
|
41270
|
+
pointerEvents: "none",
|
|
41271
|
+
zIndex: 12,
|
|
41272
|
+
maxWidth: "min(520px, calc(100% - 32px))",
|
|
41273
|
+
whiteSpace: "nowrap",
|
|
41274
|
+
overflow: "hidden",
|
|
41275
|
+
textOverflow: "ellipsis"
|
|
41276
|
+
},
|
|
41277
|
+
children: [
|
|
41278
|
+
"Inspect failed: ",
|
|
41279
|
+
inspectAnalysis.error
|
|
41280
|
+
]
|
|
41281
|
+
}
|
|
41282
|
+
),
|
|
40230
41283
|
/* @__PURE__ */ jsxRuntimeExports.jsx(HoverTooltipLayer, { ref: hoverTooltipRef, enabled: objectPickSyncEnabled && !measureMode }),
|
|
40231
41284
|
objectContextMenu && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
40232
41285
|
"div",
|
|
@@ -40684,7 +41737,7 @@ function Viewport() {
|
|
|
40684
41737
|
}
|
|
40685
41738
|
);
|
|
40686
41739
|
}
|
|
40687
|
-
const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-
|
|
41740
|
+
const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-BujZvuwX.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
|
|
40688
41741
|
const PENDING_SHARE_COPY_KEY = "fc-pending-share-copy";
|
|
40689
41742
|
function storePendingShareCopy(shareId) {
|
|
40690
41743
|
sessionStorage.setItem(PENDING_SHARE_COPY_KEY, shareId);
|
|
@@ -40871,15 +41924,15 @@ const PublishedModelPage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Objec
|
|
|
40871
41924
|
consumePendingShareCopy,
|
|
40872
41925
|
storePendingShareCopy
|
|
40873
41926
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
40874
|
-
reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-
|
|
40875
|
-
const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-
|
|
40876
|
-
reactExports.lazy(() => __vitePreload(() => import("./BlogPage-
|
|
40877
|
-
reactExports.lazy(() => __vitePreload(() => import("./AdminPage-
|
|
41927
|
+
reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-O_yMtAri.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
|
|
41928
|
+
const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-DLhIIZyJ.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
|
|
41929
|
+
reactExports.lazy(() => __vitePreload(() => import("./BlogPage-CI_P0_Pf.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
|
|
41930
|
+
reactExports.lazy(() => __vitePreload(() => import("./AdminPage-DX0mpSZT.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
|
|
40878
41931
|
reactExports.lazy(() => __vitePreload(() => Promise.resolve().then(() => PublishedModelPage$1), true ? void 0 : void 0).then((m2) => ({ default: m2.PublishedModelPage })));
|
|
40879
|
-
reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-
|
|
40880
|
-
reactExports.lazy(() => __vitePreload(() => import("./PricingPage-
|
|
40881
|
-
const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-
|
|
40882
|
-
const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-
|
|
41932
|
+
reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-DBsqTB_y.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
|
|
41933
|
+
reactExports.lazy(() => __vitePreload(() => import("./PricingPage-DGkX3Ahr.js"), true ? __vite__mapDeps([2,1]) : void 0).then((m2) => ({ default: m2.PricingPage })));
|
|
41934
|
+
const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-BujZvuwX.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
|
|
41935
|
+
const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-0S0qXKog.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
|
|
40883
41936
|
const embedMode = isEmbedMode() && !window.location.pathname.startsWith("/m/");
|
|
40884
41937
|
const EDITABLE_CRASH_FILE = /\.(?:forge\.js|[cm]?[jt]sx?|json|md|txt|svg)$/i;
|
|
40885
41938
|
function firstMeaningfulLine(text) {
|
|
@@ -41096,7 +42149,7 @@ function App() {
|
|
|
41096
42149
|
applyTheme(localStorage.getItem("fc-theme") || "dark");
|
|
41097
42150
|
clientExports.createRoot(document.getElementById("root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(App, {}));
|
|
41098
42151
|
export {
|
|
41099
|
-
|
|
42152
|
+
ViewController as $,
|
|
41100
42153
|
AuthApiError as A,
|
|
41101
42154
|
BrandMark as B,
|
|
41102
42155
|
exportExactFromStore as C,
|
|
@@ -41118,36 +42171,38 @@ export {
|
|
|
41118
42171
|
resolveJointRange as S,
|
|
41119
42172
|
useJointsConfig as T,
|
|
41120
42173
|
useJointAnimationValues as U,
|
|
41121
|
-
|
|
41122
|
-
|
|
41123
|
-
|
|
41124
|
-
|
|
41125
|
-
|
|
41126
|
-
|
|
42174
|
+
INSPECT_POINT_SAMPLE_COUNT_MAX as V,
|
|
42175
|
+
INSPECT_POINT_SAMPLE_COUNT_MIN as W,
|
|
42176
|
+
expandBoundsByTransformedAabb as X,
|
|
42177
|
+
Canvas as Y,
|
|
42178
|
+
PerspectiveCamera as Z,
|
|
42179
|
+
ControlsInteractionBridge as _,
|
|
41127
42180
|
applyTheme as a,
|
|
41128
|
-
|
|
41129
|
-
|
|
41130
|
-
|
|
41131
|
-
|
|
41132
|
-
|
|
41133
|
-
|
|
41134
|
-
|
|
41135
|
-
|
|
41136
|
-
|
|
41137
|
-
|
|
41138
|
-
|
|
41139
|
-
|
|
41140
|
-
|
|
41141
|
-
|
|
41142
|
-
|
|
41143
|
-
|
|
41144
|
-
|
|
41145
|
-
|
|
41146
|
-
|
|
41147
|
-
|
|
41148
|
-
|
|
41149
|
-
|
|
41150
|
-
|
|
42181
|
+
SceneConfigurator as a0,
|
|
42182
|
+
LocalStudioEnvironment as a1,
|
|
42183
|
+
RenderLabelsOverlay as a2,
|
|
42184
|
+
Grid as a3,
|
|
42185
|
+
OrbitControls2 as a4,
|
|
42186
|
+
TOUCH_GESTURES_3D as a5,
|
|
42187
|
+
MOUSE_BUTTONS_3D as a6,
|
|
42188
|
+
ModelJourneyBar as a7,
|
|
42189
|
+
FOCUS_MODE_DIM_OPACITY as a8,
|
|
42190
|
+
useJointAnimationLoop as a9,
|
|
42191
|
+
computeJointNodeMatrices as aa,
|
|
42192
|
+
computeObjectJointMatrices as ab,
|
|
42193
|
+
readLastActiveFileForUser as ac,
|
|
42194
|
+
ToastContainer as ad,
|
|
42195
|
+
isMobile as ae,
|
|
42196
|
+
useFeatureFlag as af,
|
|
42197
|
+
decodeSharedHash as ag,
|
|
42198
|
+
decodeSharedBundle as ah,
|
|
42199
|
+
getExternalUrl as ai,
|
|
42200
|
+
getGistId as aj,
|
|
42201
|
+
Viewport as ak,
|
|
42202
|
+
shouldBlockBrowserShortcut as al,
|
|
42203
|
+
useDrawStore as am,
|
|
42204
|
+
storePendingShareCopy as an,
|
|
42205
|
+
share as ao,
|
|
41151
42206
|
authFetch as b,
|
|
41152
42207
|
authApi as c,
|
|
41153
42208
|
showToast as d,
|