forgecad 0.9.2 → 0.9.3

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.
Files changed (79) hide show
  1. package/LICENSE +7 -5
  2. package/README.md +1 -1
  3. package/README.public.md +24 -2
  4. package/dist/assets/{AdminPage-Bs4PiK00.js → AdminPage-4jihcEk_.js} +1 -1
  5. package/dist/assets/{BlogPage-DVmgN0ma.js → BlogPage-BvzruKtw.js} +1 -1
  6. package/dist/assets/{DocsPage-BP6wlsBN.js → DocsPage-DHbd-WS-.js} +13 -13
  7. package/dist/assets/{EditorApp-Arw2NnGJ.js → EditorApp-C5P2rBfh.js} +433 -84
  8. package/dist/assets/{EditorApp-VY9lXx0N.css → EditorApp-DS0AIUrZ.css} +25 -0
  9. package/dist/assets/{EmbedViewer-qgQiOahL.js → EmbedViewer-B70wQwlE.js} +2 -2
  10. package/dist/assets/{LandingPageProofDriven-DvhtmWOz.js → LandingPageProofDriven-DIsYTnep.js} +1 -1
  11. package/dist/assets/{PricingPage-Ck3CP2ti.css → PricingPage-BMedqFef.css} +48 -0
  12. package/dist/assets/{PricingPage-657oLvWh.js → PricingPage-YPOr12pP.js} +34 -6
  13. package/dist/assets/{SettingsPage-wNy3_2yn.js → SettingsPage-rntoyJ3b.js} +10 -13
  14. package/dist/assets/{app-BdBoMQeO.js → app-CWucmnLZ.js} +801 -1208
  15. package/dist/assets/cli/{render-Ci3jjyT1.js → render-DZHmUySW.js} +214 -23
  16. package/dist/assets/copy-CQKQppF-.js +8 -0
  17. package/dist/assets/{evalWorker-CMCAbK8r.js → evalWorker-C3dKxi9Y.js} +1117 -95
  18. package/dist/assets/{manifold-BMn-8Vf8.js → manifold-CQ3FhfWB.js} +1 -1
  19. package/dist/assets/{manifold-jlYQ6E5R.js → manifold-CU0G1yYL.js} +1 -1
  20. package/dist/assets/{manifold-DbyILno4.js → manifold-CYWZMfjB.js} +2 -2
  21. package/dist/assets/{renderSceneState-DAnqvxSt.js → renderSceneState-BBUrnsUN.js} +1 -1
  22. package/dist/assets/{reportWorker-BcRVMHK-.js → reportWorker-BhZ7DjxQ.js} +1091 -95
  23. package/dist/assets/{sectionPlaneMath-DXJ_TdIW.js → sectionPlaneMath-BxfokaJE.js} +1091 -95
  24. package/dist/cli/render.html +1 -1
  25. package/dist/docs/index.html +2 -2
  26. package/dist/docs-raw/AI/usage.md +182 -89
  27. package/dist/docs-raw/API/core/concepts.md +26 -0
  28. package/dist/docs-raw/CLI.md +58 -37
  29. package/dist/docs-raw/INDEX.md +81 -64
  30. package/dist/docs-raw/cli-monetization.md +9 -8
  31. package/dist/docs-raw/generated/concepts.md +111 -4
  32. package/dist/docs-raw/generated/core.md +2 -0
  33. package/dist/docs-raw/generated/curves.md +480 -1
  34. package/dist/docs-raw/generated/output.md +1 -0
  35. package/dist/docs-raw/generated/sketch.md +2 -0
  36. package/dist/docs-raw/generated/viewport.md +81 -3
  37. package/dist/docs-raw/product/user-outreach-email-templates.md +159 -0
  38. package/dist/docs-raw/skills/forgecad-image-replicator.md +1 -1
  39. package/dist/docs-raw/skills/forgecad-make-a-model.md +33 -4
  40. package/dist/docs-raw/skills/forgecad-prepare-prompt.md +1 -1
  41. package/dist/docs-raw/skills/forgecad-project.md +1 -1
  42. package/dist/docs-raw/skills/forgecad-render-inspect.md +1 -1
  43. package/dist/docs-raw/skills/forgecad.md +2 -1
  44. package/dist/docs-raw/welcome.md +85 -137
  45. package/dist/index.html +1 -1
  46. package/dist/llms.txt +4 -3
  47. package/dist/sitemap.xml +6 -6
  48. package/dist-cli/forgecad.js +1413 -219
  49. package/dist-cli/forgecad.js.map +1 -1
  50. package/dist-skill/CONTEXT.md +594 -5
  51. package/dist-skill/SKILL-dev.md +2 -1
  52. package/dist-skill/SKILL.md +2 -1
  53. package/dist-skill/docs/API/core/concepts.md +26 -0
  54. package/dist-skill/docs/CLI.md +58 -37
  55. package/dist-skill/docs/generated/core.md +2 -0
  56. package/dist-skill/docs/generated/curves.md +480 -1
  57. package/dist-skill/docs/generated/output.md +1 -0
  58. package/dist-skill/docs/generated/sketch.md +2 -0
  59. package/dist-skill/docs/generated/viewport.md +81 -3
  60. package/dist-skill/docs-dev/API/core/concepts.md +26 -0
  61. package/dist-skill/docs-dev/CLI.md +58 -37
  62. package/dist-skill/docs-dev/generated/core.md +2 -0
  63. package/dist-skill/docs-dev/generated/curves.md +480 -1
  64. package/dist-skill/docs-dev/generated/output.md +1 -0
  65. package/dist-skill/docs-dev/generated/sketch.md +2 -0
  66. package/dist-skill/docs-dev/generated/viewport.md +81 -3
  67. package/dist-skill/library/README.md +0 -1
  68. package/dist-skill/library/forgecad-image-replicator/SKILL.md +1 -1
  69. package/dist-skill/library/forgecad-make-a-model/SKILL.md +33 -4
  70. package/dist-skill/library/forgecad-prepare-prompt/SKILL.md +1 -1
  71. package/dist-skill/library/forgecad-project/SKILL.md +1 -1
  72. package/dist-skill/library/forgecad-render-inspect/SKILL.md +1 -1
  73. package/examples/api/conformal-product-ribbon.forge.js +77 -0
  74. package/examples/api/render-labels.forge.js +33 -0
  75. package/examples/api/text2d-basics.forge.js +6 -3
  76. package/package.json +1 -1
  77. package/dist-skill/library/forgecad-deep-dive/SKILL.md +0 -120
  78. package/dist-skill/library/forgecad-deep-dive/agents/openai.yaml +0 -4
  79. package/dist-skill/library/forgecad-deep-dive/references/output-shape.md +0 -64
@@ -1,10 +1,10 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-VY9lXx0N.css","assets/landing-proof-driven-cLluTm9y.css","assets/PricingPage-Ck3CP2ti.css"])))=>i.map(i=>d[i]);
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/EditorApp-DS0AIUrZ.css","assets/landing-proof-driven-cLluTm9y.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
6
  import { c as create, r as reactExports, j as jsxRuntimeExports, 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-mDaEzY3y.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 isConstraintSketch, az as updateConstraintValue, aA as getShapeCompilePlan, aB as resolveForgeRenderStyle, aC as publishSolverWasmRunDebug, aD as resolveForgeQualityPreset, aE as resolveImportPath, aF as BufferGeometry, aG as LineBasicMaterial, aH as Line$1, aI as LineDashedMaterial, aJ as DepthStencilFormat, aK as UnsignedInt248Type, aL as MeshNormalMaterial, aM as NearestFilter, aN as BasicDepthPacking, aO as EventDispatcher$1, aP as NoColorSpace, aQ as FrontSide, aR as Material, aS as AlwaysDepth, aT as BufferAttribute, aU as CanvasTexture, aV as Object3D, aW as FogExp2, aX as Fog, aY as AmbientLight, aZ as HemisphereLight, a_ as SpotLight, a$ as PointLight, b0 as DirectionalLight, b1 as buildShapeFromCompilePlan, b2 as shapeToGeometry, b3 as sketchToSvg, b4 as sketchToDxf, b5 as runScript, b6 as MeshPhysicalMaterial, b7 as LineSegments, b8 as getRenderStylePreset, b9 as AdditiveBlending, ba as CatmullRomCurve3, bb as TubeGeometry, bc as MeshStandardMaterial, bd as compileSdfNode3, be as buildSdfRaymarchFragmentShader, bf as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bg as Shape, bh as ShapeGeometry, bi as ShaderLib, bj as CylinderGeometry, bk as parseViewportCameraState, bl as createResolvedExplodeConfig, bm as explodeBoundsCenter, bn as explodeMergeBounds, bo as resolveExplodeDirective, bp as computeExplodeMotion, bq as getSketchWorldMatrix, br as explodeAdd, bs as hasExplodeOverride, bt as resolveExplodeLocalFanDirection, bu as explodeMul, bv as explodeLeafFanStage, bw as normalizeCutPlane, bx as toClippingPlane, by as findJointAnimationClip, bz as resolveJointAnimation, bA as resolveJointViewValues, bB as getShapePorts, bC as getShapeUsedPorts, bD as DEFAULT_VIEW_CONFIG, bE as initKernel, bF as initSolverWasm } from "./sectionPlaneMath-DXJ_TdIW.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 isConstraintSketch, az as updateConstraintValue, aA as getShapeCompilePlan, aB as resolveForgeRenderStyle, aC as publishSolverWasmRunDebug, aD as resolveForgeQualityPreset, aE as resolveImportPath, aF as BufferGeometry, aG as LineBasicMaterial, aH as Line$1, aI as LineDashedMaterial, aJ as DepthStencilFormat, aK as UnsignedInt248Type, aL as MeshNormalMaterial, aM as NearestFilter, aN as BasicDepthPacking, aO as EventDispatcher$1, aP as NoColorSpace, aQ as FrontSide, aR as Material, aS as AlwaysDepth, aT as BufferAttribute, aU as CanvasTexture, aV as Object3D, aW as FogExp2, aX as Fog, aY as AmbientLight, aZ as HemisphereLight, a_ as SpotLight, a$ as PointLight, b0 as DirectionalLight, b1 as buildShapeFromCompilePlan, b2 as shapeToGeometry, b3 as sketchToSvg, b4 as sketchToDxf, b5 as runScript, b6 as MeshPhysicalMaterial, b7 as LineSegments, b8 as getRenderStylePreset, b9 as AdditiveBlending, ba as CatmullRomCurve3, bb as TubeGeometry, bc as MeshStandardMaterial, bd as compileSdfNode3, be as buildSdfRaymarchFragmentShader, bf as SDF_RAYMARCH_PROXY_VERTEX_SHADER, bg as Shape, bh as ShapeGeometry, bi as ShaderLib, bj as CylinderGeometry, bk as parseViewportCameraState, bl as createResolvedExplodeConfig, bm as explodeBoundsCenter, bn as explodeMergeBounds, bo as resolveExplodeDirective, bp as computeExplodeMotion, bq as getSketchWorldMatrix, br as explodeAdd, bs as hasExplodeOverride, bt as resolveExplodeLocalFanDirection, bu as explodeMul, bv as explodeLeafFanStage, bw as normalizeCutPlane, bx as toClippingPlane, by as findJointAnimationClip, bz as resolveJointAnimation, bA as resolveJointViewValues, bB as getShapePorts, bC as getShapeUsedPorts, bD as DEFAULT_VIEW_CONFIG, bE as initKernel, bF as initSolverWasm } from "./sectionPlaneMath-BxfokaJE.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];
@@ -17,6 +17,14 @@ class AuthApiError extends Error {
17
17
  this.name = "AuthApiError";
18
18
  }
19
19
  }
20
+ function responseErrorMessage(body, fallback) {
21
+ if (body && typeof body === "object") {
22
+ const record = body;
23
+ if (typeof record.message === "string" && record.message.length > 0) return record.message;
24
+ if (typeof record.error === "string" && record.error.length > 0) return record.error;
25
+ }
26
+ return fallback;
27
+ }
20
28
  async function doFetch(url2, init) {
21
29
  var _a3;
22
30
  const headers = {};
@@ -38,7 +46,7 @@ async function authFetch(url2, init) {
38
46
  {
39
47
  const { res: res2, body: body2 } = await doFetch(url2, init);
40
48
  if (res2.ok) return body2;
41
- throw new AuthApiError(body2.error || "Request failed", res2.status, body2);
49
+ throw new AuthApiError(responseErrorMessage(body2, "Request failed"), res2.status, body2);
42
50
  }
43
51
  }
44
52
  const authApi = {
@@ -279,6 +287,35 @@ function storeCache(filePath, code, files, paramOverrides, quality, backend, res
279
287
  function ensureFirstWorkspace() {
280
288
  return authFetch("/api/onboarding/ensure-first-workspace", { method: "POST" });
281
289
  }
290
+ function formatStorageBytes(bytes2) {
291
+ if (bytes2 <= 0) return "0 B";
292
+ const units = ["B", "KB", "MB", "GB"];
293
+ const i = Math.min(Math.floor(Math.log(bytes2) / Math.log(1024)), units.length - 1);
294
+ const value = bytes2 / 1024 ** i;
295
+ return `${value.toFixed(i === 0 ? 0 : 1)} ${units[i]}`;
296
+ }
297
+ function storageUsagePercent(usedBytes, limitBytes) {
298
+ if (limitBytes <= 0) return 0;
299
+ return Math.min(Math.max(usedBytes / limitBytes * 100, 0), 100);
300
+ }
301
+ const STORAGE_QUOTA_EXCEEDED_CODE = "storage_quota_exceeded";
302
+ function isRecord(value) {
303
+ return typeof value === "object" && value !== null;
304
+ }
305
+ function numberField(body, key) {
306
+ const value = body[key];
307
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
308
+ }
309
+ function storageQuotaUpgradeMessage(errorOrBody) {
310
+ const body = isRecord(errorOrBody) && isRecord(errorOrBody.body) ? errorOrBody.body : errorOrBody;
311
+ if (!isRecord(body) || body.code !== STORAGE_QUOTA_EXCEEDED_CODE) return null;
312
+ const used = numberField(body, "used");
313
+ const limit = numberField(body, "limit");
314
+ const targetLimit = numberField(body, "targetLimitBytes");
315
+ const usage = used !== null && limit !== null ? ` (${formatStorageBytes(used)} of ${formatStorageBytes(limit)} used)` : "";
316
+ const target = targetLimit !== null ? formatStorageBytes(targetLimit) : "more hosted storage";
317
+ return `Hosted storage is full${usage}. Upgrade to Pro for ${target} and commercial coverage, or delete files to free space.`;
318
+ }
282
319
  const ACTIVE_PROJECT_KEY = "fc-active-project-id";
283
320
  function loadSavedProjectId() {
284
321
  try {
@@ -324,7 +361,7 @@ const useProjectStore = create((set, get) => ({
324
361
  set({ projects, activeProjectId: activeId, loading: false });
325
362
  persistProjectId(activeId);
326
363
  } catch (err) {
327
- set({ loading: false, error: err.message || "Failed to fetch projects" });
364
+ set({ loading: false, error: storageQuotaUpgradeMessage(err) ?? err.message ?? "Failed to fetch projects" });
328
365
  }
329
366
  },
330
367
  async ensureFirstWorkspace() {
@@ -344,7 +381,7 @@ const useProjectStore = create((set, get) => ({
344
381
  persistProjectId(selected.id);
345
382
  return selected;
346
383
  } catch (err) {
347
- set({ loading: false, error: err.message || "Failed to ensure first workspace" });
384
+ set({ loading: false, error: storageQuotaUpgradeMessage(err) ?? err.message ?? "Failed to ensure first workspace" });
348
385
  throw err;
349
386
  }
350
387
  },
@@ -1707,7 +1744,7 @@ function createEvents(store) {
1707
1744
  var _internal$capturedMap, _internal$capturedMap2;
1708
1745
  return (_internal$capturedMap = (_internal$capturedMap2 = internal.capturedMap.get(id)) == null ? void 0 : _internal$capturedMap2.has(hit.eventObject)) != null ? _internal$capturedMap : false;
1709
1746
  };
1710
- const setPointerCapture = (id) => {
1747
+ const setPointerCapture2 = (id) => {
1711
1748
  const captureData = {
1712
1749
  intersection: hit,
1713
1750
  target: event.target
@@ -1719,7 +1756,7 @@ function createEvents(store) {
1719
1756
  }
1720
1757
  event.target.setPointerCapture(id);
1721
1758
  };
1722
- const releasePointerCapture = (id) => {
1759
+ const releasePointerCapture2 = (id) => {
1723
1760
  const captures = internal.capturedMap.get(id);
1724
1761
  if (captures) {
1725
1762
  releaseInternalPointerCapture(internal.capturedMap, hit.eventObject, captures, id);
@@ -1758,13 +1795,13 @@ function createEvents(store) {
1758
1795
  // there should be a distinction between target and currentTarget
1759
1796
  target: {
1760
1797
  hasPointerCapture,
1761
- setPointerCapture,
1762
- releasePointerCapture
1798
+ setPointerCapture: setPointerCapture2,
1799
+ releasePointerCapture: releasePointerCapture2
1763
1800
  },
1764
1801
  currentTarget: {
1765
1802
  hasPointerCapture,
1766
- setPointerCapture,
1767
- releasePointerCapture
1803
+ setPointerCapture: setPointerCapture2,
1804
+ releasePointerCapture: releasePointerCapture2
1768
1805
  },
1769
1806
  nativeEvent: event
1770
1807
  };
@@ -1884,7 +1921,7 @@ function createEvents(store) {
1884
1921
  };
1885
1922
  }
1886
1923
  const isRenderer = (def) => !!(def != null && def.render);
1887
- const context$1 = /* @__PURE__ */ reactExports.createContext(null);
1924
+ const context = /* @__PURE__ */ reactExports.createContext(null);
1888
1925
  const createStore = (invalidate2, advance2) => {
1889
1926
  const rootStore = createWithEqualityFn((set, get) => {
1890
1927
  const position = new Vector3();
@@ -2103,7 +2140,7 @@ const createStore = (invalidate2, advance2) => {
2103
2140
  return rootStore;
2104
2141
  };
2105
2142
  function useStore() {
2106
- const store = reactExports.useContext(context$1);
2143
+ const store = reactExports.useContext(context);
2107
2144
  if (!store) throw new Error("R3F: Hooks can only be used within the Canvas component!");
2108
2145
  return store;
2109
2146
  }
@@ -7947,7 +7984,7 @@ function Provider({
7947
7984
  if (onCreated) onCreated(state2);
7948
7985
  if (!store.getState().events.connected) state2.events.connect == null ? void 0 : state2.events.connect(rootElement);
7949
7986
  }, []);
7950
- return /* @__PURE__ */ jsxRuntimeExports.jsx(context$1.Provider, {
7987
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(context.Provider, {
7951
7988
  value: store,
7952
7989
  children
7953
7990
  });
@@ -8053,7 +8090,7 @@ function Portal({
8053
8090
  return (
8054
8091
  // @ts-ignore, reconciler types are not maintained
8055
8092
  /* @__PURE__ */ jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, {
8056
- children: reconciler.createPortal(/* @__PURE__ */ jsxRuntimeExports.jsx(context$1.Provider, {
8093
+ children: reconciler.createPortal(/* @__PURE__ */ jsxRuntimeExports.jsx(context.Provider, {
8057
8094
  value: usePortalStore,
8058
8095
  children
8059
8096
  }), usePortalStore, null)
@@ -10609,10 +10646,10 @@ class EXRLoader extends DataTextureLoader {
10609
10646
  function wdec16(l2, h2) {
10610
10647
  var m2 = UInt16(l2);
10611
10648
  var d = UInt16(h2);
10612
- var bb2 = m2 - (d >> 1) & MOD_MASK;
10613
- var aa = d + bb2 - A_OFFSET & MOD_MASK;
10649
+ var bb = m2 - (d >> 1) & MOD_MASK;
10650
+ var aa = d + bb - A_OFFSET & MOD_MASK;
10614
10651
  wdec14Return.a = aa;
10615
- wdec14Return.b = bb2;
10652
+ wdec14Return.b = bb;
10616
10653
  }
10617
10654
  function wav2Decode(buffer2, j2, nx, ox, ny, oy, mx) {
10618
10655
  var w14 = mx < 1 << 14;
@@ -12705,33 +12742,6 @@ class Line2 extends LineSegments2$1 {
12705
12742
  this.type = "Line2";
12706
12743
  }
12707
12744
  }
12708
- const tV0 = /* @__PURE__ */ new Vector3();
12709
- const tV1 = /* @__PURE__ */ new Vector3();
12710
- const tV2 = /* @__PURE__ */ new Vector3();
12711
- const getPoint2 = (point3, camera, size) => {
12712
- const widthHalf = size.width / 2;
12713
- const heightHalf = size.height / 2;
12714
- camera.updateMatrixWorld(false);
12715
- const vector = point3.project(camera);
12716
- vector.x = vector.x * widthHalf + widthHalf;
12717
- vector.y = -(vector.y * heightHalf) + heightHalf;
12718
- return vector;
12719
- };
12720
- const getPoint3 = (point2, camera, size, zValue = 1) => {
12721
- const vector = tV0.set(point2.x / size.width * 2 - 1, -(point2.y / size.height) * 2 + 1, zValue);
12722
- vector.unproject(camera);
12723
- return vector;
12724
- };
12725
- const calculateScaleFactor = (point3, radiusPx, camera, size) => {
12726
- const point2 = getPoint2(tV2.copy(point3), camera, size);
12727
- let scale = 0;
12728
- for (let i = 0; i < 2; ++i) {
12729
- const point2off = tV1.copy(point2).setComponent(i, point2.getComponent(i) + radiusPx);
12730
- const point3off = getPoint3(point2off, camera, size, point2off.z);
12731
- scale = Math.max(scale, point3.distanceTo(point3off));
12732
- }
12733
- return scale;
12734
- };
12735
12745
  const Line = /* @__PURE__ */ reactExports.forwardRef(function Line4({
12736
12746
  points,
12737
12747
  color: color2 = 16777215,
@@ -14546,960 +14556,6 @@ const Lightformer = /* @__PURE__ */ reactExports.forwardRef(({
14546
14556
  castShadow: true
14547
14557
  }, light2)));
14548
14558
  });
14549
- const context = /* @__PURE__ */ reactExports.createContext(null);
14550
- const vec1$1 = /* @__PURE__ */ new Vector3();
14551
- const vec2$1 = /* @__PURE__ */ new Vector3();
14552
- const calculateOffset$1 = (clickPoint, normal, rayStart, rayDir) => {
14553
- const e1 = normal.dot(normal);
14554
- const e2 = normal.dot(clickPoint) - normal.dot(rayStart);
14555
- const e3 = normal.dot(rayDir);
14556
- if (e3 === 0) {
14557
- return -e2 / e1;
14558
- }
14559
- vec1$1.copy(rayDir).multiplyScalar(e1 / e3).sub(normal);
14560
- vec2$1.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
14561
- const offset = -vec1$1.dot(vec2$1) / vec1$1.dot(vec1$1);
14562
- return offset;
14563
- };
14564
- const upV$1 = /* @__PURE__ */ new Vector3(0, 1, 0);
14565
- const offsetMatrix$1 = /* @__PURE__ */ new Matrix4();
14566
- const AxisArrow = ({
14567
- direction,
14568
- axis
14569
- }) => {
14570
- const {
14571
- translation,
14572
- translationLimits,
14573
- annotations,
14574
- annotationsClass,
14575
- depthTest,
14576
- scale,
14577
- lineWidth,
14578
- fixed,
14579
- axisColors,
14580
- hoveredColor,
14581
- opacity,
14582
- renderOrder,
14583
- onDragStart,
14584
- onDrag,
14585
- onDragEnd,
14586
- userData
14587
- } = reactExports.useContext(context);
14588
- const camControls = useThree((state2) => state2.controls);
14589
- const divRef = reactExports.useRef(null);
14590
- const objRef = reactExports.useRef(null);
14591
- const clickInfo = reactExports.useRef(null);
14592
- const offset0 = reactExports.useRef(0);
14593
- const [isHovered, setIsHovered] = reactExports.useState(false);
14594
- const onPointerDown = reactExports.useCallback((e2) => {
14595
- if (annotations) {
14596
- divRef.current.innerText = `${translation.current[axis].toFixed(2)}`;
14597
- divRef.current.style.display = "block";
14598
- }
14599
- e2.stopPropagation();
14600
- const rotation = new Matrix4().extractRotation(objRef.current.matrixWorld);
14601
- const clickPoint = e2.point.clone();
14602
- const origin = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
14603
- const dir = direction.clone().applyMatrix4(rotation).normalize();
14604
- clickInfo.current = {
14605
- clickPoint,
14606
- dir
14607
- };
14608
- offset0.current = translation.current[axis];
14609
- onDragStart({
14610
- component: "Arrow",
14611
- axis,
14612
- origin,
14613
- directions: [dir]
14614
- });
14615
- camControls && (camControls.enabled = false);
14616
- e2.target.setPointerCapture(e2.pointerId);
14617
- }, [annotations, direction, camControls, onDragStart, translation, axis]);
14618
- const onPointerMove = reactExports.useCallback((e2) => {
14619
- e2.stopPropagation();
14620
- if (!isHovered) setIsHovered(true);
14621
- if (clickInfo.current) {
14622
- const {
14623
- clickPoint,
14624
- dir
14625
- } = clickInfo.current;
14626
- const [min, max2] = (translationLimits == null ? void 0 : translationLimits[axis]) || [void 0, void 0];
14627
- let offset = calculateOffset$1(clickPoint, dir, e2.ray.origin, e2.ray.direction);
14628
- if (min !== void 0) {
14629
- offset = Math.max(offset, min - offset0.current);
14630
- }
14631
- if (max2 !== void 0) {
14632
- offset = Math.min(offset, max2 - offset0.current);
14633
- }
14634
- translation.current[axis] = offset0.current + offset;
14635
- if (annotations) {
14636
- divRef.current.innerText = `${translation.current[axis].toFixed(2)}`;
14637
- }
14638
- offsetMatrix$1.makeTranslation(dir.x * offset, dir.y * offset, dir.z * offset);
14639
- onDrag(offsetMatrix$1);
14640
- }
14641
- }, [annotations, onDrag, isHovered, translation, translationLimits, axis]);
14642
- const onPointerUp = reactExports.useCallback((e2) => {
14643
- if (annotations) {
14644
- divRef.current.style.display = "none";
14645
- }
14646
- e2.stopPropagation();
14647
- clickInfo.current = null;
14648
- onDragEnd();
14649
- camControls && (camControls.enabled = true);
14650
- e2.target.releasePointerCapture(e2.pointerId);
14651
- }, [annotations, camControls, onDragEnd]);
14652
- const onPointerOut = reactExports.useCallback((e2) => {
14653
- e2.stopPropagation();
14654
- setIsHovered(false);
14655
- }, []);
14656
- const {
14657
- cylinderLength,
14658
- coneWidth,
14659
- coneLength,
14660
- matrixL
14661
- } = reactExports.useMemo(() => {
14662
- const coneWidth2 = fixed ? lineWidth / scale * 1.6 : scale / 20;
14663
- const coneLength2 = fixed ? 0.2 : scale / 5;
14664
- const cylinderLength2 = fixed ? 1 - coneLength2 : scale - coneLength2;
14665
- const quaternion = new Quaternion().setFromUnitVectors(upV$1, direction.clone().normalize());
14666
- const matrixL2 = new Matrix4().makeRotationFromQuaternion(quaternion);
14667
- return {
14668
- cylinderLength: cylinderLength2,
14669
- coneWidth: coneWidth2,
14670
- coneLength: coneLength2,
14671
- matrixL: matrixL2
14672
- };
14673
- }, [direction, scale, lineWidth, fixed]);
14674
- const color_ = isHovered ? hoveredColor : axisColors[axis];
14675
- return /* @__PURE__ */ reactExports.createElement("group", {
14676
- ref: objRef
14677
- }, /* @__PURE__ */ reactExports.createElement("group", {
14678
- matrix: matrixL,
14679
- matrixAutoUpdate: false,
14680
- onPointerDown,
14681
- onPointerMove,
14682
- onPointerUp,
14683
- onPointerOut
14684
- }, annotations && /* @__PURE__ */ reactExports.createElement(Html, {
14685
- position: [0, -coneLength, 0]
14686
- }, /* @__PURE__ */ reactExports.createElement("div", {
14687
- style: {
14688
- display: "none",
14689
- background: "#151520",
14690
- color: "white",
14691
- padding: "6px 8px",
14692
- borderRadius: 7,
14693
- whiteSpace: "nowrap"
14694
- },
14695
- className: annotationsClass,
14696
- ref: divRef
14697
- })), /* @__PURE__ */ reactExports.createElement("mesh", {
14698
- visible: false,
14699
- position: [0, (cylinderLength + coneLength) / 2, 0],
14700
- userData
14701
- }, /* @__PURE__ */ reactExports.createElement("cylinderGeometry", {
14702
- args: [coneWidth * 1.4, coneWidth * 1.4, cylinderLength + coneLength, 8, 1]
14703
- })), /* @__PURE__ */ reactExports.createElement(Line, {
14704
- transparent: true,
14705
- raycast: () => null,
14706
- depthTest,
14707
- points: [0, 0, 0, 0, cylinderLength, 0],
14708
- lineWidth,
14709
- side: DoubleSide,
14710
- color: color_,
14711
- opacity,
14712
- polygonOffset: true,
14713
- renderOrder,
14714
- polygonOffsetFactor: -10,
14715
- fog: false
14716
- }), /* @__PURE__ */ reactExports.createElement("mesh", {
14717
- raycast: () => null,
14718
- position: [0, cylinderLength + coneLength / 2, 0],
14719
- renderOrder
14720
- }, /* @__PURE__ */ reactExports.createElement("coneGeometry", {
14721
- args: [coneWidth, coneLength, 24, 1]
14722
- }), /* @__PURE__ */ reactExports.createElement("meshBasicMaterial", {
14723
- transparent: true,
14724
- depthTest,
14725
- color: color_,
14726
- opacity,
14727
- polygonOffset: true,
14728
- polygonOffsetFactor: -10,
14729
- fog: false
14730
- }))));
14731
- };
14732
- const clickDir = /* @__PURE__ */ new Vector3();
14733
- const intersectionDir = /* @__PURE__ */ new Vector3();
14734
- const toDegrees = (radians) => radians * 180 / Math.PI;
14735
- const toRadians = (degrees) => degrees * Math.PI / 180;
14736
- const calculateAngle = (clickPoint, intersectionPoint, origin, e1, e2) => {
14737
- clickDir.copy(clickPoint).sub(origin);
14738
- intersectionDir.copy(intersectionPoint).sub(origin);
14739
- const dote1e1 = e1.dot(e1);
14740
- const dote2e2 = e2.dot(e2);
14741
- const uClick = clickDir.dot(e1) / dote1e1;
14742
- const vClick = clickDir.dot(e2) / dote2e2;
14743
- const uIntersection = intersectionDir.dot(e1) / dote1e1;
14744
- const vIntersection = intersectionDir.dot(e2) / dote2e2;
14745
- const angleClick = Math.atan2(vClick, uClick);
14746
- const angleIntersection = Math.atan2(vIntersection, uIntersection);
14747
- return angleIntersection - angleClick;
14748
- };
14749
- const fmod = (num, denom) => {
14750
- let k2 = Math.floor(num / denom);
14751
- k2 = k2 < 0 ? k2 + 1 : k2;
14752
- return num - k2 * denom;
14753
- };
14754
- const minimizeAngle = (angle) => {
14755
- let result = fmod(angle, 2 * Math.PI);
14756
- if (Math.abs(result) < 1e-6) {
14757
- return 0;
14758
- }
14759
- if (result < 0) {
14760
- result += 2 * Math.PI;
14761
- }
14762
- return result;
14763
- };
14764
- const rotMatrix = /* @__PURE__ */ new Matrix4();
14765
- const posNew = /* @__PURE__ */ new Vector3();
14766
- const ray$1 = /* @__PURE__ */ new Ray();
14767
- const intersection$1 = /* @__PURE__ */ new Vector3();
14768
- const AxisRotator = ({
14769
- dir1,
14770
- dir2,
14771
- axis
14772
- }) => {
14773
- const {
14774
- rotationLimits,
14775
- annotations,
14776
- annotationsClass,
14777
- depthTest,
14778
- scale,
14779
- lineWidth,
14780
- fixed,
14781
- axisColors,
14782
- hoveredColor,
14783
- renderOrder,
14784
- opacity,
14785
- onDragStart,
14786
- onDrag,
14787
- onDragEnd,
14788
- userData
14789
- } = reactExports.useContext(context);
14790
- const camControls = useThree((state2) => state2.controls);
14791
- const divRef = reactExports.useRef(null);
14792
- const objRef = reactExports.useRef(null);
14793
- const angle0 = reactExports.useRef(0);
14794
- const angle = reactExports.useRef(0);
14795
- const clickInfo = reactExports.useRef(null);
14796
- const [isHovered, setIsHovered] = reactExports.useState(false);
14797
- const onPointerDown = reactExports.useCallback((e2) => {
14798
- if (annotations) {
14799
- divRef.current.innerText = `${toDegrees(angle.current).toFixed(0)}º`;
14800
- divRef.current.style.display = "block";
14801
- }
14802
- e2.stopPropagation();
14803
- const clickPoint = e2.point.clone();
14804
- const origin = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
14805
- const e1 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
14806
- const e22 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
14807
- const normal = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
14808
- const plane = new Plane().setFromNormalAndCoplanarPoint(normal, origin);
14809
- clickInfo.current = {
14810
- clickPoint,
14811
- origin,
14812
- e1,
14813
- e2: e22,
14814
- normal,
14815
- plane
14816
- };
14817
- onDragStart({
14818
- component: "Rotator",
14819
- axis,
14820
- origin,
14821
- directions: [e1, e22, normal]
14822
- });
14823
- camControls && (camControls.enabled = false);
14824
- e2.target.setPointerCapture(e2.pointerId);
14825
- }, [annotations, camControls, onDragStart, axis]);
14826
- const onPointerMove = reactExports.useCallback((e2) => {
14827
- e2.stopPropagation();
14828
- if (!isHovered) setIsHovered(true);
14829
- if (clickInfo.current) {
14830
- const {
14831
- clickPoint,
14832
- origin,
14833
- e1,
14834
- e2: e22,
14835
- normal,
14836
- plane
14837
- } = clickInfo.current;
14838
- const [min, max2] = (rotationLimits == null ? void 0 : rotationLimits[axis]) || [void 0, void 0];
14839
- ray$1.copy(e2.ray);
14840
- ray$1.intersectPlane(plane, intersection$1);
14841
- ray$1.direction.negate();
14842
- ray$1.intersectPlane(plane, intersection$1);
14843
- let deltaAngle = calculateAngle(clickPoint, intersection$1, origin, e1, e22);
14844
- let degrees = toDegrees(deltaAngle);
14845
- if (e2.shiftKey) {
14846
- degrees = Math.round(degrees / 10) * 10;
14847
- deltaAngle = toRadians(degrees);
14848
- }
14849
- if (min !== void 0 && max2 !== void 0 && max2 - min < 2 * Math.PI) {
14850
- deltaAngle = minimizeAngle(deltaAngle);
14851
- deltaAngle = deltaAngle > Math.PI ? deltaAngle - 2 * Math.PI : deltaAngle;
14852
- deltaAngle = MathUtils.clamp(deltaAngle, min - angle0.current, max2 - angle0.current);
14853
- angle.current = angle0.current + deltaAngle;
14854
- } else {
14855
- angle.current = minimizeAngle(angle0.current + deltaAngle);
14856
- angle.current = angle.current > Math.PI ? angle.current - 2 * Math.PI : angle.current;
14857
- }
14858
- if (annotations) {
14859
- degrees = toDegrees(angle.current);
14860
- divRef.current.innerText = `${degrees.toFixed(0)}º`;
14861
- }
14862
- rotMatrix.makeRotationAxis(normal, deltaAngle);
14863
- posNew.copy(origin).applyMatrix4(rotMatrix).sub(origin).negate();
14864
- rotMatrix.setPosition(posNew);
14865
- onDrag(rotMatrix);
14866
- }
14867
- }, [annotations, onDrag, isHovered, rotationLimits, axis]);
14868
- const onPointerUp = reactExports.useCallback((e2) => {
14869
- if (annotations) {
14870
- divRef.current.style.display = "none";
14871
- }
14872
- e2.stopPropagation();
14873
- angle0.current = angle.current;
14874
- clickInfo.current = null;
14875
- onDragEnd();
14876
- camControls && (camControls.enabled = true);
14877
- e2.target.releasePointerCapture(e2.pointerId);
14878
- }, [annotations, camControls, onDragEnd]);
14879
- const onPointerOut = reactExports.useCallback((e2) => {
14880
- e2.stopPropagation();
14881
- setIsHovered(false);
14882
- }, []);
14883
- const matrixL = reactExports.useMemo(() => {
14884
- const dir1N = dir1.clone().normalize();
14885
- const dir2N = dir2.clone().normalize();
14886
- return new Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
14887
- }, [dir1, dir2]);
14888
- const r2 = fixed ? 0.65 : scale * 0.65;
14889
- const arc = reactExports.useMemo(() => {
14890
- const segments = 32;
14891
- const points = [];
14892
- for (let j2 = 0; j2 <= segments; j2++) {
14893
- const angle2 = j2 * (Math.PI / 2) / segments;
14894
- points.push(new Vector3(Math.cos(angle2) * r2, Math.sin(angle2) * r2, 0));
14895
- }
14896
- return points;
14897
- }, [r2]);
14898
- return /* @__PURE__ */ reactExports.createElement("group", {
14899
- ref: objRef,
14900
- onPointerDown,
14901
- onPointerMove,
14902
- onPointerUp,
14903
- onPointerOut,
14904
- matrix: matrixL,
14905
- matrixAutoUpdate: false
14906
- }, annotations && /* @__PURE__ */ reactExports.createElement(Html, {
14907
- position: [r2, r2, 0]
14908
- }, /* @__PURE__ */ reactExports.createElement("div", {
14909
- style: {
14910
- display: "none",
14911
- background: "#151520",
14912
- color: "white",
14913
- padding: "6px 8px",
14914
- borderRadius: 7,
14915
- whiteSpace: "nowrap"
14916
- },
14917
- className: annotationsClass,
14918
- ref: divRef
14919
- })), /* @__PURE__ */ reactExports.createElement(Line, {
14920
- points: arc,
14921
- lineWidth: lineWidth * 4,
14922
- visible: false,
14923
- userData
14924
- }), /* @__PURE__ */ reactExports.createElement(Line, {
14925
- transparent: true,
14926
- raycast: () => null,
14927
- depthTest,
14928
- points: arc,
14929
- lineWidth,
14930
- side: DoubleSide,
14931
- color: isHovered ? hoveredColor : axisColors[axis],
14932
- opacity,
14933
- polygonOffset: true,
14934
- polygonOffsetFactor: -10,
14935
- renderOrder,
14936
- fog: false
14937
- }));
14938
- };
14939
- const decomposeIntoBasis = (e1, e2, offset) => {
14940
- const i1 = Math.abs(e1.x) >= Math.abs(e1.y) && Math.abs(e1.x) >= Math.abs(e1.z) ? 0 : Math.abs(e1.y) >= Math.abs(e1.x) && Math.abs(e1.y) >= Math.abs(e1.z) ? 1 : 2;
14941
- const e2DegrowthOrder = [0, 1, 2].sort((a3, b3) => Math.abs(e2.getComponent(b3)) - Math.abs(e2.getComponent(a3)));
14942
- const i2 = i1 === e2DegrowthOrder[0] ? e2DegrowthOrder[1] : e2DegrowthOrder[0];
14943
- const a1 = e1.getComponent(i1);
14944
- const a2 = e1.getComponent(i2);
14945
- const b1 = e2.getComponent(i1);
14946
- const b2 = e2.getComponent(i2);
14947
- const c1 = offset.getComponent(i1);
14948
- const c2 = offset.getComponent(i2);
14949
- const y = (c2 - c1 * (a2 / a1)) / (b2 - b1 * (a2 / a1));
14950
- const x = (c1 - y * b1) / a1;
14951
- return [x, y];
14952
- };
14953
- const ray = /* @__PURE__ */ new Ray();
14954
- const intersection = /* @__PURE__ */ new Vector3();
14955
- const offsetMatrix = /* @__PURE__ */ new Matrix4();
14956
- const PlaneSlider = ({
14957
- dir1,
14958
- dir2,
14959
- axis
14960
- }) => {
14961
- const {
14962
- translation,
14963
- translationLimits,
14964
- annotations,
14965
- annotationsClass,
14966
- depthTest,
14967
- scale,
14968
- lineWidth,
14969
- fixed,
14970
- axisColors,
14971
- hoveredColor,
14972
- opacity,
14973
- renderOrder,
14974
- onDragStart,
14975
- onDrag,
14976
- onDragEnd,
14977
- userData
14978
- } = reactExports.useContext(context);
14979
- const camControls = useThree((state2) => state2.controls);
14980
- const divRef = reactExports.useRef(null);
14981
- const objRef = reactExports.useRef(null);
14982
- const clickInfo = reactExports.useRef(null);
14983
- const offsetX0 = reactExports.useRef(0);
14984
- const offsetY0 = reactExports.useRef(0);
14985
- const [isHovered, setIsHovered] = reactExports.useState(false);
14986
- const onPointerDown = reactExports.useCallback((e2) => {
14987
- if (annotations) {
14988
- divRef.current.innerText = `${translation.current[(axis + 1) % 3].toFixed(2)}, ${translation.current[(axis + 2) % 3].toFixed(2)}`;
14989
- divRef.current.style.display = "block";
14990
- }
14991
- e2.stopPropagation();
14992
- const clickPoint = e2.point.clone();
14993
- const origin = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
14994
- const e1 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 0).normalize();
14995
- const e22 = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 1).normalize();
14996
- const normal = new Vector3().setFromMatrixColumn(objRef.current.matrixWorld, 2).normalize();
14997
- const plane = new Plane().setFromNormalAndCoplanarPoint(normal, origin);
14998
- clickInfo.current = {
14999
- clickPoint,
15000
- e1,
15001
- e2: e22,
15002
- plane
15003
- };
15004
- offsetX0.current = translation.current[(axis + 1) % 3];
15005
- offsetY0.current = translation.current[(axis + 2) % 3];
15006
- onDragStart({
15007
- component: "Slider",
15008
- axis,
15009
- origin,
15010
- directions: [e1, e22, normal]
15011
- });
15012
- camControls && (camControls.enabled = false);
15013
- e2.target.setPointerCapture(e2.pointerId);
15014
- }, [annotations, camControls, onDragStart, axis]);
15015
- const onPointerMove = reactExports.useCallback((e2) => {
15016
- e2.stopPropagation();
15017
- if (!isHovered) setIsHovered(true);
15018
- if (clickInfo.current) {
15019
- const {
15020
- clickPoint,
15021
- e1,
15022
- e2: e22,
15023
- plane
15024
- } = clickInfo.current;
15025
- const [minX, maxX] = (translationLimits == null ? void 0 : translationLimits[(axis + 1) % 3]) || [void 0, void 0];
15026
- const [minY, maxY] = (translationLimits == null ? void 0 : translationLimits[(axis + 2) % 3]) || [void 0, void 0];
15027
- ray.copy(e2.ray);
15028
- ray.intersectPlane(plane, intersection);
15029
- ray.direction.negate();
15030
- ray.intersectPlane(plane, intersection);
15031
- intersection.sub(clickPoint);
15032
- let [offsetX, offsetY] = decomposeIntoBasis(e1, e22, intersection);
15033
- if (minX !== void 0) {
15034
- offsetX = Math.max(offsetX, minX - offsetX0.current);
15035
- }
15036
- if (maxX !== void 0) {
15037
- offsetX = Math.min(offsetX, maxX - offsetX0.current);
15038
- }
15039
- if (minY !== void 0) {
15040
- offsetY = Math.max(offsetY, minY - offsetY0.current);
15041
- }
15042
- if (maxY !== void 0) {
15043
- offsetY = Math.min(offsetY, maxY - offsetY0.current);
15044
- }
15045
- translation.current[(axis + 1) % 3] = offsetX0.current + offsetX;
15046
- translation.current[(axis + 2) % 3] = offsetY0.current + offsetY;
15047
- if (annotations) {
15048
- divRef.current.innerText = `${translation.current[(axis + 1) % 3].toFixed(2)}, ${translation.current[(axis + 2) % 3].toFixed(2)}`;
15049
- }
15050
- offsetMatrix.makeTranslation(offsetX * e1.x + offsetY * e22.x, offsetX * e1.y + offsetY * e22.y, offsetX * e1.z + offsetY * e22.z);
15051
- onDrag(offsetMatrix);
15052
- }
15053
- }, [annotations, onDrag, isHovered, translation, translationLimits, axis]);
15054
- const onPointerUp = reactExports.useCallback((e2) => {
15055
- if (annotations) {
15056
- divRef.current.style.display = "none";
15057
- }
15058
- e2.stopPropagation();
15059
- clickInfo.current = null;
15060
- onDragEnd();
15061
- camControls && (camControls.enabled = true);
15062
- e2.target.releasePointerCapture(e2.pointerId);
15063
- }, [annotations, camControls, onDragEnd]);
15064
- const onPointerOut = reactExports.useCallback((e2) => {
15065
- e2.stopPropagation();
15066
- setIsHovered(false);
15067
- }, []);
15068
- const matrixL = reactExports.useMemo(() => {
15069
- const dir1N = dir1.clone().normalize();
15070
- const dir2N = dir2.clone().normalize();
15071
- return new Matrix4().makeBasis(dir1N, dir2N, dir1N.clone().cross(dir2N));
15072
- }, [dir1, dir2]);
15073
- const pos1 = fixed ? 1 / 7 : scale / 7;
15074
- const length = fixed ? 0.225 : scale * 0.225;
15075
- const color2 = isHovered ? hoveredColor : axisColors[axis];
15076
- const points = reactExports.useMemo(() => [new Vector3(0, 0, 0), new Vector3(0, length, 0), new Vector3(length, length, 0), new Vector3(length, 0, 0), new Vector3(0, 0, 0)], [length]);
15077
- return /* @__PURE__ */ reactExports.createElement("group", {
15078
- ref: objRef,
15079
- matrix: matrixL,
15080
- matrixAutoUpdate: false
15081
- }, annotations && /* @__PURE__ */ reactExports.createElement(Html, {
15082
- position: [0, 0, 0]
15083
- }, /* @__PURE__ */ reactExports.createElement("div", {
15084
- style: {
15085
- display: "none",
15086
- background: "#151520",
15087
- color: "white",
15088
- padding: "6px 8px",
15089
- borderRadius: 7,
15090
- whiteSpace: "nowrap"
15091
- },
15092
- className: annotationsClass,
15093
- ref: divRef
15094
- })), /* @__PURE__ */ reactExports.createElement("group", {
15095
- position: [pos1 * 1.7, pos1 * 1.7, 0]
15096
- }, /* @__PURE__ */ reactExports.createElement("mesh", {
15097
- visible: true,
15098
- onPointerDown,
15099
- onPointerMove,
15100
- onPointerUp,
15101
- onPointerOut,
15102
- scale: length,
15103
- userData,
15104
- renderOrder
15105
- }, /* @__PURE__ */ reactExports.createElement("planeGeometry", null), /* @__PURE__ */ reactExports.createElement("meshBasicMaterial", {
15106
- transparent: true,
15107
- depthTest,
15108
- color: color2,
15109
- polygonOffset: true,
15110
- polygonOffsetFactor: -10,
15111
- side: DoubleSide,
15112
- fog: false
15113
- })), /* @__PURE__ */ reactExports.createElement(Line, {
15114
- position: [-length / 2, -length / 2, 0],
15115
- transparent: true,
15116
- depthTest,
15117
- points,
15118
- lineWidth,
15119
- color: color2,
15120
- opacity,
15121
- polygonOffset: true,
15122
- polygonOffsetFactor: -10,
15123
- userData,
15124
- fog: false,
15125
- renderOrder
15126
- })));
15127
- };
15128
- const vec1 = /* @__PURE__ */ new Vector3();
15129
- const vec2 = /* @__PURE__ */ new Vector3();
15130
- const calculateOffset = (clickPoint, normal, rayStart, rayDir) => {
15131
- const e1 = normal.dot(normal);
15132
- const e2 = normal.dot(clickPoint) - normal.dot(rayStart);
15133
- const e3 = normal.dot(rayDir);
15134
- if (e3 === 0) {
15135
- return -e2 / e1;
15136
- }
15137
- vec1.copy(rayDir).multiplyScalar(e1 / e3).sub(normal);
15138
- vec2.copy(rayDir).multiplyScalar(e2 / e3).add(rayStart).sub(clickPoint);
15139
- const offset = -vec1.dot(vec2) / vec1.dot(vec1);
15140
- return offset;
15141
- };
15142
- const upV = /* @__PURE__ */ new Vector3(0, 1, 0);
15143
- const scaleV = /* @__PURE__ */ new Vector3();
15144
- const scaleMatrix = /* @__PURE__ */ new Matrix4();
15145
- const ScalingSphere = ({
15146
- direction,
15147
- axis
15148
- }) => {
15149
- const {
15150
- scaleLimits,
15151
- annotations,
15152
- annotationsClass,
15153
- depthTest,
15154
- scale,
15155
- lineWidth,
15156
- fixed,
15157
- axisColors,
15158
- hoveredColor,
15159
- opacity,
15160
- renderOrder,
15161
- onDragStart,
15162
- onDrag,
15163
- onDragEnd,
15164
- userData
15165
- } = reactExports.useContext(context);
15166
- const size = useThree((state2) => state2.size);
15167
- const camControls = useThree((state2) => state2.controls);
15168
- const divRef = reactExports.useRef(null);
15169
- const objRef = reactExports.useRef(null);
15170
- const meshRef = reactExports.useRef(null);
15171
- const scale0 = reactExports.useRef(1);
15172
- const scaleCur = reactExports.useRef(1);
15173
- const clickInfo = reactExports.useRef(null);
15174
- const [isHovered, setIsHovered] = reactExports.useState(false);
15175
- const position = fixed ? 1.2 : 1.2 * scale;
15176
- const onPointerDown = reactExports.useCallback((e2) => {
15177
- if (annotations) {
15178
- divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
15179
- divRef.current.style.display = "block";
15180
- }
15181
- e2.stopPropagation();
15182
- const rotation = new Matrix4().extractRotation(objRef.current.matrixWorld);
15183
- const clickPoint = e2.point.clone();
15184
- const origin = new Vector3().setFromMatrixPosition(objRef.current.matrixWorld);
15185
- const dir = direction.clone().applyMatrix4(rotation).normalize();
15186
- const mPLG = objRef.current.matrixWorld.clone();
15187
- const mPLGInv = mPLG.clone().invert();
15188
- const offsetMultiplier = fixed ? 1 / calculateScaleFactor(objRef.current.getWorldPosition(vec1), scale, e2.camera, size) : 1;
15189
- clickInfo.current = {
15190
- clickPoint,
15191
- dir,
15192
- mPLG,
15193
- mPLGInv,
15194
- offsetMultiplier
15195
- };
15196
- onDragStart({
15197
- component: "Sphere",
15198
- axis,
15199
- origin,
15200
- directions: [dir]
15201
- });
15202
- camControls && (camControls.enabled = false);
15203
- e2.target.setPointerCapture(e2.pointerId);
15204
- }, [annotations, camControls, direction, onDragStart, axis, fixed, scale, size]);
15205
- const onPointerMove = reactExports.useCallback((e2) => {
15206
- e2.stopPropagation();
15207
- if (!isHovered) setIsHovered(true);
15208
- if (clickInfo.current) {
15209
- const {
15210
- clickPoint,
15211
- dir,
15212
- mPLG,
15213
- mPLGInv,
15214
- offsetMultiplier
15215
- } = clickInfo.current;
15216
- const [min, max2] = (scaleLimits == null ? void 0 : scaleLimits[axis]) || [1e-5, void 0];
15217
- const offsetW = calculateOffset(clickPoint, dir, e2.ray.origin, e2.ray.direction);
15218
- const offsetL = offsetW * offsetMultiplier;
15219
- const offsetH = fixed ? offsetL : offsetL / scale;
15220
- let upscale = Math.pow(2, offsetH * 0.2);
15221
- if (e2.shiftKey) {
15222
- upscale = Math.round(upscale * 10) / 10;
15223
- }
15224
- upscale = Math.max(upscale, min / scale0.current);
15225
- if (max2 !== void 0) {
15226
- upscale = Math.min(upscale, max2 / scale0.current);
15227
- }
15228
- scaleCur.current = scale0.current * upscale;
15229
- meshRef.current.position.set(0, position + offsetL, 0);
15230
- if (annotations) {
15231
- divRef.current.innerText = `${scaleCur.current.toFixed(2)}`;
15232
- }
15233
- scaleV.set(1, 1, 1);
15234
- scaleV.setComponent(axis, upscale);
15235
- scaleMatrix.makeScale(scaleV.x, scaleV.y, scaleV.z).premultiply(mPLG).multiply(mPLGInv);
15236
- onDrag(scaleMatrix);
15237
- }
15238
- }, [annotations, position, onDrag, isHovered, scaleLimits, axis]);
15239
- const onPointerUp = reactExports.useCallback((e2) => {
15240
- if (annotations) {
15241
- divRef.current.style.display = "none";
15242
- }
15243
- e2.stopPropagation();
15244
- scale0.current = scaleCur.current;
15245
- clickInfo.current = null;
15246
- meshRef.current.position.set(0, position, 0);
15247
- onDragEnd();
15248
- camControls && (camControls.enabled = true);
15249
- e2.target.releasePointerCapture(e2.pointerId);
15250
- }, [annotations, camControls, onDragEnd, position]);
15251
- const onPointerOut = reactExports.useCallback((e2) => {
15252
- e2.stopPropagation();
15253
- setIsHovered(false);
15254
- }, []);
15255
- const {
15256
- radius,
15257
- matrixL
15258
- } = reactExports.useMemo(() => {
15259
- const radius2 = fixed ? lineWidth / scale * 1.8 : scale / 22.5;
15260
- const quaternion = new Quaternion().setFromUnitVectors(upV, direction.clone().normalize());
15261
- const matrixL2 = new Matrix4().makeRotationFromQuaternion(quaternion);
15262
- return {
15263
- radius: radius2,
15264
- matrixL: matrixL2
15265
- };
15266
- }, [direction, scale, lineWidth, fixed]);
15267
- const color2 = isHovered ? hoveredColor : axisColors[axis];
15268
- return /* @__PURE__ */ reactExports.createElement("group", {
15269
- ref: objRef
15270
- }, /* @__PURE__ */ reactExports.createElement("group", {
15271
- matrix: matrixL,
15272
- matrixAutoUpdate: false,
15273
- onPointerDown,
15274
- onPointerMove,
15275
- onPointerUp,
15276
- onPointerOut
15277
- }, annotations && /* @__PURE__ */ reactExports.createElement(Html, {
15278
- position: [0, position / 2, 0]
15279
- }, /* @__PURE__ */ reactExports.createElement("div", {
15280
- style: {
15281
- display: "none",
15282
- background: "#151520",
15283
- color: "white",
15284
- padding: "6px 8px",
15285
- borderRadius: 7,
15286
- whiteSpace: "nowrap"
15287
- },
15288
- className: annotationsClass,
15289
- ref: divRef
15290
- })), /* @__PURE__ */ reactExports.createElement("mesh", {
15291
- ref: meshRef,
15292
- position: [0, position, 0],
15293
- renderOrder,
15294
- userData
15295
- }, /* @__PURE__ */ reactExports.createElement("sphereGeometry", {
15296
- args: [radius, 12, 12]
15297
- }), /* @__PURE__ */ reactExports.createElement("meshBasicMaterial", {
15298
- transparent: true,
15299
- depthTest,
15300
- color: color2,
15301
- opacity,
15302
- polygonOffset: true,
15303
- polygonOffsetFactor: -10
15304
- }))));
15305
- };
15306
- const mL0 = /* @__PURE__ */ new Matrix4();
15307
- const mW0 = /* @__PURE__ */ new Matrix4();
15308
- const mP = /* @__PURE__ */ new Matrix4();
15309
- const mPInv = /* @__PURE__ */ new Matrix4();
15310
- const mW = /* @__PURE__ */ new Matrix4();
15311
- const mL = /* @__PURE__ */ new Matrix4();
15312
- const mL0Inv = /* @__PURE__ */ new Matrix4();
15313
- const mdL = /* @__PURE__ */ new Matrix4();
15314
- const mG = /* @__PURE__ */ new Matrix4();
15315
- const bb = /* @__PURE__ */ new Box3();
15316
- const bbObj = /* @__PURE__ */ new Box3();
15317
- const vCenter = /* @__PURE__ */ new Vector3();
15318
- const vSize = /* @__PURE__ */ new Vector3();
15319
- const vAnchorOffset = /* @__PURE__ */ new Vector3();
15320
- const vPosition = /* @__PURE__ */ new Vector3();
15321
- const vScale = /* @__PURE__ */ new Vector3();
15322
- const xDir = /* @__PURE__ */ new Vector3(1, 0, 0);
15323
- const yDir = /* @__PURE__ */ new Vector3(0, 1, 0);
15324
- const zDir = /* @__PURE__ */ new Vector3(0, 0, 1);
15325
- const PivotControls = /* @__PURE__ */ reactExports.forwardRef(({
15326
- enabled = true,
15327
- matrix,
15328
- onDragStart,
15329
- onDrag,
15330
- onDragEnd,
15331
- autoTransform = true,
15332
- anchor,
15333
- disableAxes = false,
15334
- disableSliders = false,
15335
- disableRotations = false,
15336
- disableScaling = false,
15337
- activeAxes = [true, true, true],
15338
- offset = [0, 0, 0],
15339
- rotation = [0, 0, 0],
15340
- scale = 1,
15341
- lineWidth = 4,
15342
- fixed = false,
15343
- translationLimits,
15344
- rotationLimits,
15345
- scaleLimits,
15346
- depthTest = true,
15347
- renderOrder = 500,
15348
- axisColors = ["#ff2060", "#20df80", "#2080ff"],
15349
- hoveredColor = "#ffff40",
15350
- annotations = false,
15351
- annotationsClass,
15352
- opacity = 1,
15353
- visible = true,
15354
- userData,
15355
- children,
15356
- ...props
15357
- }, fRef) => {
15358
- const invalidate2 = useThree((state2) => state2.invalidate);
15359
- const parentRef = reactExports.useRef(null);
15360
- const ref = reactExports.useRef(null);
15361
- const gizmoRef = reactExports.useRef(null);
15362
- const childrenRef = reactExports.useRef(null);
15363
- const translation = reactExports.useRef([0, 0, 0]);
15364
- const cameraScale = reactExports.useRef(new Vector3(1, 1, 1));
15365
- const gizmoScale = reactExports.useRef(new Vector3(1, 1, 1));
15366
- reactExports.useLayoutEffect(() => {
15367
- if (!anchor) return;
15368
- childrenRef.current.updateWorldMatrix(true, true);
15369
- mPInv.copy(childrenRef.current.matrixWorld).invert();
15370
- bb.makeEmpty();
15371
- childrenRef.current.traverse((obj) => {
15372
- if (!obj.geometry) return;
15373
- if (!obj.geometry.boundingBox) obj.geometry.computeBoundingBox();
15374
- mL.copy(obj.matrixWorld).premultiply(mPInv);
15375
- bbObj.copy(obj.geometry.boundingBox);
15376
- bbObj.applyMatrix4(mL);
15377
- bb.union(bbObj);
15378
- });
15379
- vCenter.copy(bb.max).add(bb.min).multiplyScalar(0.5);
15380
- vSize.copy(bb.max).sub(bb.min).multiplyScalar(0.5);
15381
- vAnchorOffset.copy(vSize).multiply(new Vector3(...anchor)).add(vCenter);
15382
- vPosition.set(...offset).add(vAnchorOffset);
15383
- gizmoRef.current.position.copy(vPosition);
15384
- invalidate2();
15385
- });
15386
- const config = reactExports.useMemo(() => ({
15387
- onDragStart: (props2) => {
15388
- mL0.copy(ref.current.matrix);
15389
- mW0.copy(ref.current.matrixWorld);
15390
- onDragStart && onDragStart(props2);
15391
- invalidate2();
15392
- },
15393
- onDrag: (mdW) => {
15394
- mP.copy(parentRef.current.matrixWorld);
15395
- mPInv.copy(mP).invert();
15396
- mW.copy(mW0).premultiply(mdW);
15397
- mL.copy(mW).premultiply(mPInv);
15398
- mL0Inv.copy(mL0).invert();
15399
- mdL.copy(mL).multiply(mL0Inv);
15400
- if (autoTransform) {
15401
- ref.current.matrix.copy(mL);
15402
- }
15403
- onDrag && onDrag(mL, mdL, mW, mdW);
15404
- invalidate2();
15405
- },
15406
- onDragEnd: () => {
15407
- if (onDragEnd) onDragEnd();
15408
- invalidate2();
15409
- },
15410
- translation,
15411
- translationLimits,
15412
- rotationLimits,
15413
- axisColors,
15414
- hoveredColor,
15415
- opacity,
15416
- scale,
15417
- lineWidth,
15418
- fixed,
15419
- depthTest,
15420
- renderOrder,
15421
- userData,
15422
- annotations,
15423
- annotationsClass
15424
- }), [onDragStart, onDrag, onDragEnd, translation, translationLimits, rotationLimits, scaleLimits, depthTest, scale, lineWidth, fixed, ...axisColors, hoveredColor, opacity, userData, autoTransform, annotations, annotationsClass]);
15425
- const vec = new Vector3();
15426
- useFrame((state2) => {
15427
- if (fixed) {
15428
- const sf = calculateScaleFactor(gizmoRef.current.getWorldPosition(vec), scale, state2.camera, state2.size);
15429
- cameraScale.current.setScalar(sf);
15430
- }
15431
- if (matrix && matrix instanceof Matrix4) {
15432
- ref.current.matrix = matrix;
15433
- }
15434
- ref.current.updateWorldMatrix(true, true);
15435
- mG.makeRotationFromEuler(gizmoRef.current.rotation).setPosition(gizmoRef.current.position).premultiply(ref.current.matrixWorld);
15436
- gizmoScale.current.setFromMatrixScale(mG);
15437
- vScale.copy(cameraScale.current).divide(gizmoScale.current);
15438
- if (Math.abs(gizmoRef.current.scale.x - vScale.x) > 1e-4 || Math.abs(gizmoRef.current.scale.y - vScale.y) > 1e-4 || Math.abs(gizmoRef.current.scale.z - vScale.z) > 1e-4) {
15439
- gizmoRef.current.scale.copy(vScale);
15440
- state2.invalidate();
15441
- }
15442
- });
15443
- reactExports.useImperativeHandle(fRef, () => ref.current, []);
15444
- return /* @__PURE__ */ reactExports.createElement(context.Provider, {
15445
- value: config
15446
- }, /* @__PURE__ */ reactExports.createElement("group", {
15447
- ref: parentRef
15448
- }, /* @__PURE__ */ reactExports.createElement("group", _extends({
15449
- ref,
15450
- matrix,
15451
- matrixAutoUpdate: false
15452
- }, props), /* @__PURE__ */ reactExports.createElement("group", {
15453
- visible,
15454
- ref: gizmoRef,
15455
- position: offset,
15456
- rotation
15457
- }, enabled && /* @__PURE__ */ reactExports.createElement(reactExports.Fragment, null, !disableAxes && activeAxes[0] && /* @__PURE__ */ reactExports.createElement(AxisArrow, {
15458
- axis: 0,
15459
- direction: xDir
15460
- }), !disableAxes && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(AxisArrow, {
15461
- axis: 1,
15462
- direction: yDir
15463
- }), !disableAxes && activeAxes[2] && /* @__PURE__ */ reactExports.createElement(AxisArrow, {
15464
- axis: 2,
15465
- direction: zDir
15466
- }), !disableSliders && activeAxes[0] && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(PlaneSlider, {
15467
- axis: 2,
15468
- dir1: xDir,
15469
- dir2: yDir
15470
- }), !disableSliders && activeAxes[0] && activeAxes[2] && /* @__PURE__ */ reactExports.createElement(PlaneSlider, {
15471
- axis: 1,
15472
- dir1: zDir,
15473
- dir2: xDir
15474
- }), !disableSliders && activeAxes[2] && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(PlaneSlider, {
15475
- axis: 0,
15476
- dir1: yDir,
15477
- dir2: zDir
15478
- }), !disableRotations && activeAxes[0] && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(AxisRotator, {
15479
- axis: 2,
15480
- dir1: xDir,
15481
- dir2: yDir
15482
- }), !disableRotations && activeAxes[0] && activeAxes[2] && /* @__PURE__ */ reactExports.createElement(AxisRotator, {
15483
- axis: 1,
15484
- dir1: zDir,
15485
- dir2: xDir
15486
- }), !disableRotations && activeAxes[2] && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(AxisRotator, {
15487
- axis: 0,
15488
- dir1: yDir,
15489
- dir2: zDir
15490
- }), !disableScaling && activeAxes[0] && /* @__PURE__ */ reactExports.createElement(ScalingSphere, {
15491
- axis: 0,
15492
- direction: xDir
15493
- }), !disableScaling && activeAxes[1] && /* @__PURE__ */ reactExports.createElement(ScalingSphere, {
15494
- axis: 1,
15495
- direction: yDir
15496
- }), !disableScaling && activeAxes[2] && /* @__PURE__ */ reactExports.createElement(ScalingSphere, {
15497
- axis: 2,
15498
- direction: zDir
15499
- }))), /* @__PURE__ */ reactExports.createElement("group", {
15500
- ref: childrenRef
15501
- }, children))));
15502
- });
15503
14559
  function StudioLightformers() {
15504
14560
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
15505
14561
  /* @__PURE__ */ jsxRuntimeExports.jsx(Lightformer, { form: "rect", intensity: 4, color: "#ffffff", "rotation-x": Math.PI / 2, position: [0, 40, 0], scale: [120, 120, 1] }),
@@ -16729,7 +15785,7 @@ const CRASH_COOLDOWN_MS = 2e3;
16729
15785
  class EvalWorkerClient {
16730
15786
  constructor(workerFactory = () => new Worker(new URL(
16731
15787
  /* @vite-ignore */
16732
- "/assets/evalWorker-CMCAbK8r.js",
15788
+ "/assets/evalWorker-C3dKxi9Y.js",
16733
15789
  import.meta.url
16734
15790
  ), { type: "module" })) {
16735
15791
  __publicField(this, "worker", null);
@@ -16748,6 +15804,8 @@ class EvalWorkerClient {
16748
15804
  __publicField(this, "activeRunSeq", null);
16749
15805
  /** Called when the worker reports a progress phase change. */
16750
15806
  __publicField(this, "onProgress", null);
15807
+ /** Called when the worker has UI metadata before full geometry serialization completes. */
15808
+ __publicField(this, "onRunMetadata", null);
16751
15809
  /** Latest WASM heap sizes reported by the worker. */
16752
15810
  __publicField(this, "workerWasmHeap", null);
16753
15811
  /** Most recent worker failure reason, cleared after the next successful run. */
@@ -16762,7 +15820,7 @@ class EvalWorkerClient {
16762
15820
  this.worker.postMessage({ type: "set-project", payload: { projectId } });
16763
15821
  }
16764
15822
  this.worker.onmessage = (event) => {
16765
- var _a3;
15823
+ var _a3, _b2;
16766
15824
  const { data } = event;
16767
15825
  if (data.type === "progress") {
16768
15826
  if (data.payload.phase === "export-evaluating" || data.payload.phase === "export-writing") {
@@ -16779,6 +15837,11 @@ class EvalWorkerClient {
16779
15837
  }
16780
15838
  return;
16781
15839
  }
15840
+ if (data.type === "run-metadata") {
15841
+ if (data.payload.seq !== this.activeRunSeq) return;
15842
+ (_b2 = this.onRunMetadata) == null ? void 0 : _b2.call(this, data.payload.metadata);
15843
+ return;
15844
+ }
16782
15845
  if (data.type === "run-success" || data.type === "run-error") {
16783
15846
  const req = this.pendingRuns.get(data.payload.seq);
16784
15847
  if (!req) return;
@@ -18103,6 +17166,7 @@ function createErrorRunResult(message, quality) {
18103
17166
  bom: [],
18104
17167
  sheetStock: [],
18105
17168
  cutPlanes: [],
17169
+ renderLabels: [],
18106
17170
  cameraTrajectory: null,
18107
17171
  explodeView: null,
18108
17172
  jointsView: null,
@@ -18117,6 +17181,33 @@ function createErrorRunResult(message, quality) {
18117
17181
  mocks: []
18118
17182
  };
18119
17183
  }
17184
+ function runMetadataToRunResult(metadata) {
17185
+ const objects = metadata.objects.map((obj) => ({
17186
+ id: obj.id,
17187
+ name: obj.name,
17188
+ shape: null,
17189
+ sketch: null,
17190
+ sdf: obj.sdfData ?? null,
17191
+ toolpath: obj.toolpathData ?? null,
17192
+ color: obj.color,
17193
+ materialProps: obj.materialProps,
17194
+ geometryInfo: obj.geometryInfo,
17195
+ sketchMeta: obj.sketchMeta,
17196
+ groupName: obj.groupName,
17197
+ treePath: obj.treePath,
17198
+ mock: obj.mock,
17199
+ serverShapeRef: obj.serverShapeRef,
17200
+ exactState: obj.exactState
17201
+ }));
17202
+ return {
17203
+ shape: null,
17204
+ sketch: null,
17205
+ ...metadata,
17206
+ objects,
17207
+ debugHighlights3D: [],
17208
+ mocks: []
17209
+ };
17210
+ }
18120
17211
  function buildRunState(previewFile, runResult, state2) {
18121
17212
  const synced = syncObjectSettings(
18122
17213
  runResult.objects,
@@ -18246,6 +17337,7 @@ function errorRunResult(error, timeMs = 0) {
18246
17337
  bom: [],
18247
17338
  sheetStock: [],
18248
17339
  cutPlanes: [],
17340
+ renderLabels: [],
18249
17341
  cameraTrajectory: null,
18250
17342
  explodeView: null,
18251
17343
  jointsView: null,
@@ -18738,7 +17830,7 @@ const useForgeStore = create((set, get) => ({
18738
17830
  writeViewPreferences({ objectSettingsByFile: applied.nextObjectSettingsByFile, cutPlaneEnabled: applied.nextCutPlaneEnabled });
18739
17831
  return;
18740
17832
  }
18741
- set({ isEvaluating: true, evaluationPhase: "kernel-init" });
17833
+ set({ isEvaluating: true, evaluationPhase: "kernel-init", previewFile });
18742
17834
  const useServer = get().computeTarget === "server";
18743
17835
  const execId = ++currentExecutionId;
18744
17836
  if (serverComputeAbortController) {
@@ -18758,6 +17850,7 @@ const useForgeStore = create((set, get) => ({
18758
17850
  };
18759
17851
  let serialized;
18760
17852
  if (useServer) {
17853
+ evalWorkerClient.onRunMetadata = null;
18761
17854
  const abortController = new AbortController();
18762
17855
  serverComputeAbortController = abortController;
18763
17856
  try {
@@ -18786,6 +17879,13 @@ Switch to LOCAL mode or wait for the server to recover.`,
18786
17879
  }
18787
17880
  }
18788
17881
  } else {
17882
+ evalWorkerClient.onRunMetadata = (metadata) => {
17883
+ if (execId !== currentExecutionId) return;
17884
+ const metadataResult = runMetadataToRunResult(metadata);
17885
+ const applied = buildRunState(previewFile, metadataResult, get());
17886
+ set({ ...applied.nextState });
17887
+ writeViewPreferences({ objectSettingsByFile: applied.nextObjectSettingsByFile, cutPlaneEnabled: applied.nextCutPlaneEnabled });
17888
+ };
18789
17889
  serialized = await evalWorkerClient.run(runPayload);
18790
17890
  }
18791
17891
  if (execId !== currentExecutionId) return;
@@ -19385,7 +18485,7 @@ Switch to LOCAL mode or wait for the server to recover.`,
19385
18485
  }),
19386
18486
  sectionPlaneGuidesEnabled: initialViewPreferences.sectionPlaneGuidesEnabled ?? true,
19387
18487
  sectionPlaneFillEnabled: initialViewPreferences.sectionPlaneFillEnabled ?? true,
19388
- sectionPlaneFillOpacity: initialViewPreferences.sectionPlaneFillOpacity ?? 0.05,
18488
+ sectionPlaneFillOpacity: initialViewPreferences.sectionPlaneFillOpacity ?? 0.025,
19389
18489
  sectionPlaneBorderEnabled: initialViewPreferences.sectionPlaneBorderEnabled ?? true,
19390
18490
  sectionPlaneAxisEnabled: initialViewPreferences.sectionPlaneAxisEnabled ?? true,
19391
18491
  setSectionPlaneGuidesEnabled: (enabled) => {
@@ -19397,7 +18497,7 @@ Switch to LOCAL mode or wait for the server to recover.`,
19397
18497
  set({ sectionPlaneFillEnabled: enabled });
19398
18498
  },
19399
18499
  setSectionPlaneFillOpacity: (opacity) => {
19400
- const safeOpacity = Math.max(0, Math.min(1, opacity));
18500
+ const safeOpacity = Math.max(0, Math.min(0.04, opacity));
19401
18501
  writeViewPreferences({ sectionPlaneFillOpacity: safeOpacity });
19402
18502
  set({ sectionPlaneFillOpacity: safeOpacity });
19403
18503
  },
@@ -19465,7 +18565,8 @@ Switch to LOCAL mode or wait for the server to recover.`,
19465
18565
  }));
19466
18566
  } catch (e2) {
19467
18567
  console.error("Save failed:", e2);
19468
- showToast((e2 == null ? void 0 : e2.message) || "Failed to save file", "error");
18568
+ const quotaMessage = storageQuotaUpgradeMessage(e2);
18569
+ showToast(quotaMessage ?? (e2 == null ? void 0 : e2.message) ?? "Failed to save file", "error", quotaMessage ? 8e3 : 3e3);
19469
18570
  }
19470
18571
  },
19471
18572
  saveFileAs: async () => {
@@ -19609,7 +18710,8 @@ Switch to LOCAL mode or wait for the server to recover.`,
19609
18710
  });
19610
18711
  showToast(`Imported ${imported.length === 1 ? imported[0].path : `${imported.length} files`}`, "success");
19611
18712
  } catch (e2) {
19612
- showToast((e2 == null ? void 0 : e2.message) || "Failed to import project files", "error");
18713
+ const quotaMessage = storageQuotaUpgradeMessage(e2);
18714
+ showToast(quotaMessage ?? (e2 == null ? void 0 : e2.message) ?? "Failed to import project files", "error", quotaMessage ? 8e3 : 3e3);
19613
18715
  console.error("Import save failed:", e2);
19614
18716
  }
19615
18717
  return imported.map((entry) => entry.path);
@@ -19699,6 +18801,9 @@ Switch to LOCAL mode or wait for the server to recover.`,
19699
18801
  commandPaletteOpen: false,
19700
18802
  openCommandPalette: () => set({ commandPaletteOpen: true }),
19701
18803
  closeCommandPalette: () => set({ commandPaletteOpen: false }),
18804
+ objectSearchOpen: false,
18805
+ openObjectSearch: () => set({ objectSearchOpen: true }),
18806
+ closeObjectSearch: () => set({ objectSearchOpen: false }),
19702
18807
  fileSwitcherOpen: false,
19703
18808
  openFileSwitcher: () => set({ fileSwitcherOpen: true }),
19704
18809
  closeFileSwitcher: () => set({ fileSwitcherOpen: false }),
@@ -29731,7 +28836,7 @@ function generateReportInWorker(options) {
29731
28836
  return new Promise((resolve2, reject) => {
29732
28837
  const worker = new Worker(new URL(
29733
28838
  /* @vite-ignore */
29734
- "/assets/reportWorker-BcRVMHK-.js",
28839
+ "/assets/reportWorker-BhZ7DjxQ.js",
29735
28840
  import.meta.url
29736
28841
  ), { type: "module" });
29737
28842
  const cleanup = () => {
@@ -30659,13 +29764,13 @@ function createOverrideSessionFromRunResult(runResult, objectSettings, backgroun
30659
29764
  scene.add(wire);
30660
29765
  wires.push(wire);
30661
29766
  try {
30662
- const bb2 = obj.shape.boundingBox();
30663
- minX = Math.min(minX, bb2.min[0]);
30664
- minY = Math.min(minY, bb2.min[1]);
30665
- minZ = Math.min(minZ, bb2.min[2]);
30666
- maxX = Math.max(maxX, bb2.max[0]);
30667
- maxY = Math.max(maxY, bb2.max[1]);
30668
- maxZ = Math.max(maxZ, bb2.max[2]);
29767
+ const bb = obj.shape.boundingBox();
29768
+ minX = Math.min(minX, bb.min[0]);
29769
+ minY = Math.min(minY, bb.min[1]);
29770
+ minZ = Math.min(minZ, bb.min[2]);
29771
+ maxX = Math.max(maxX, bb.max[0]);
29772
+ maxY = Math.max(maxY, bb.max[1]);
29773
+ maxZ = Math.max(maxZ, bb.max[2]);
30669
29774
  } catch {
30670
29775
  }
30671
29776
  });
@@ -31447,13 +30552,13 @@ function computeSceneBounds$1() {
31447
30552
  for (const obj of result.objects) {
31448
30553
  if (!obj.shape) continue;
31449
30554
  try {
31450
- const bb2 = obj.shape.boundingBox();
31451
- minX = Math.min(minX, bb2.min[0]);
31452
- minY = Math.min(minY, bb2.min[1]);
31453
- minZ = Math.min(minZ, bb2.min[2]);
31454
- maxX = Math.max(maxX, bb2.max[0]);
31455
- maxY = Math.max(maxY, bb2.max[1]);
31456
- maxZ = Math.max(maxZ, bb2.max[2]);
30555
+ const bb = obj.shape.boundingBox();
30556
+ minX = Math.min(minX, bb.min[0]);
30557
+ minY = Math.min(minY, bb.min[1]);
30558
+ minZ = Math.min(minZ, bb.min[2]);
30559
+ maxX = Math.max(maxX, bb.max[0]);
30560
+ maxY = Math.max(maxY, bb.max[1]);
30561
+ maxZ = Math.max(maxZ, bb.max[2]);
31457
30562
  } catch {
31458
30563
  }
31459
30564
  }
@@ -32651,14 +31756,14 @@ function DebugHighlightShapeItem({ hl, opacity }) {
32651
31756
  solid.setAttribute("normal", new Float32BufferAttribute(snapshot.geometryNormals, 3));
32652
31757
  const edges = new BufferGeometry();
32653
31758
  edges.setAttribute("position", new Float32BufferAttribute(snapshot.geometryEdgePositions, 3));
32654
- const bb2 = snapshot.boundingBox;
31759
+ const bb = snapshot.boundingBox;
32655
31760
  return {
32656
31761
  solidGeo: solid,
32657
31762
  edgesGeo: edges,
32658
31763
  center: [
32659
- (bb2.min[0] + bb2.max[0]) / 2,
32660
- (bb2.min[1] + bb2.max[1]) / 2,
32661
- (bb2.min[2] + bb2.max[2]) / 2
31764
+ (bb.min[0] + bb.max[0]) / 2,
31765
+ (bb.min[1] + bb.max[1]) / 2,
31766
+ (bb.min[2] + bb.max[2]) / 2
32662
31767
  ]
32663
31768
  };
32664
31769
  }, [snapshot]);
@@ -34591,83 +33696,192 @@ function PerformanceInfoPanel({ enabled, stats }) {
34591
33696
  }
34592
33697
  );
34593
33698
  }
34594
- const PLANE_COLOR = "#00bbff";
34595
- const PLANE_OPACITY = 0.035;
34596
- function SectionGizmoInner({
34597
- size,
34598
- initialNormal,
34599
- initialOffset
33699
+ const GUIDE_COLOR = "#9aa6af";
33700
+ const GUIDE_HOVER_COLOR = "#c7d0d7";
33701
+ const GUIDE_ACTIVE_COLOR = "#d8e0e6";
33702
+ const PLANE_OPACITY = 0.018;
33703
+ const BORDER_OPACITY = 0.36;
33704
+ const HANDLE_OPACITY = 0.62;
33705
+ const MIN_HANDLE_LENGTH = 10;
33706
+ const MAX_HANDLE_LENGTH = 64;
33707
+ const dragAxisScratchA = new Vector3();
33708
+ const dragAxisScratchB = new Vector3();
33709
+ function setPointerCapture(event) {
33710
+ var _a3;
33711
+ const target = event.target;
33712
+ (_a3 = target.setPointerCapture) == null ? void 0 : _a3.call(target, event.pointerId);
33713
+ }
33714
+ function releasePointerCapture(event) {
33715
+ var _a3;
33716
+ const target = event.target;
33717
+ (_a3 = target.releasePointerCapture) == null ? void 0 : _a3.call(target, event.pointerId);
33718
+ }
33719
+ function calculateAxisDragDelta(clickPoint, axis, ray) {
33720
+ const axisLenSq = axis.dot(axis);
33721
+ if (axisLenSq <= 1e-8) return 0;
33722
+ const startOffset = axis.dot(clickPoint) - axis.dot(ray.origin);
33723
+ const rayAxisDot = axis.dot(ray.direction);
33724
+ if (Math.abs(rayAxisDot) <= 1e-8) {
33725
+ return -startOffset / axisLenSq;
33726
+ }
33727
+ dragAxisScratchA.copy(ray.direction).multiplyScalar(axisLenSq / rayAxisDot).sub(axis);
33728
+ dragAxisScratchB.copy(ray.direction).multiplyScalar(startOffset / rayAxisDot).add(ray.origin).sub(clickPoint);
33729
+ const denom = dragAxisScratchA.dot(dragAxisScratchA);
33730
+ return denom <= 1e-8 ? 0 : -dragAxisScratchA.dot(dragAxisScratchB) / denom;
33731
+ }
33732
+ function SectionExplorerHandle({
33733
+ normal,
33734
+ offset,
33735
+ handleLength,
33736
+ onOffsetChange,
33737
+ onDragEnd
34600
33738
  }) {
34601
- const setNormal = useForgeStore((s) => s.setSectionExplorerNormal);
34602
- const setOffset = useForgeStore((s) => s.setSectionExplorerOffset);
34603
- const persist = useForgeStore((s) => s.persistSectionExplorer);
34604
- const initialMatrix = reactExports.useMemo(() => {
34605
- const m2 = new Matrix4();
34606
- const n = new Vector3(...initialNormal).normalize();
34607
- const center = n.clone().multiplyScalar(initialOffset);
34608
- const q2 = new Quaternion().setFromUnitVectors(new Vector3(0, 0, 1), n);
34609
- m2.compose(center, q2, new Vector3(1, 1, 1));
34610
- return m2;
34611
- }, [initialNormal, initialOffset]);
34612
- const handleDrag = reactExports.useCallback(
34613
- (local) => {
34614
- const pos = new Vector3();
34615
- const rot = new Quaternion();
34616
- const scl = new Vector3();
34617
- local.decompose(pos, rot, scl);
34618
- const n = new Vector3(0, 0, 1).applyQuaternion(rot).normalize();
34619
- setNormal([n.x, n.y, n.z]);
34620
- setOffset(pos.dot(n));
33739
+ const controls = useThree((state2) => state2.controls);
33740
+ const invalidate2 = useThree((state2) => state2.invalidate);
33741
+ const [isHovered, setIsHovered] = reactExports.useState(false);
33742
+ const [isDragging, setIsDragging] = reactExports.useState(false);
33743
+ const dragInfo = reactExports.useRef(null);
33744
+ const color2 = isDragging ? GUIDE_ACTIVE_COLOR : isHovered ? GUIDE_HOVER_COLOR : GUIDE_COLOR;
33745
+ const stemLength = handleLength * 0.72;
33746
+ const coneHeight = Math.max(2.2, handleLength * 0.18);
33747
+ const stemRadius = Math.max(0.11, handleLength * 0.012);
33748
+ const coneRadius = Math.max(0.46, handleLength * 0.042);
33749
+ const hitRadius = Math.max(4.5, handleLength * 0.18);
33750
+ const hitLength = stemLength + coneHeight + hitRadius * 2;
33751
+ const handlePointerDown = reactExports.useCallback(
33752
+ (event) => {
33753
+ if (event.button !== 0) return;
33754
+ event.stopPropagation();
33755
+ dragInfo.current = {
33756
+ clickPoint: event.point.clone(),
33757
+ normal: normal.clone().normalize(),
33758
+ offset
33759
+ };
33760
+ if (controls) controls.enabled = false;
33761
+ setIsDragging(true);
33762
+ setPointerCapture(event);
33763
+ invalidate2();
33764
+ },
33765
+ [controls, invalidate2, normal, offset]
33766
+ );
33767
+ const handlePointerMove = reactExports.useCallback(
33768
+ (event) => {
33769
+ event.stopPropagation();
33770
+ if (!isHovered) setIsHovered(true);
33771
+ const info = dragInfo.current;
33772
+ if (!info) return;
33773
+ const delta = calculateAxisDragDelta(info.clickPoint, info.normal, event.ray);
33774
+ onOffsetChange(info.offset + delta);
33775
+ invalidate2();
34621
33776
  },
34622
- [setNormal, setOffset]
33777
+ [invalidate2, isHovered, onOffsetChange]
34623
33778
  );
33779
+ const finishDrag = reactExports.useCallback(
33780
+ (event) => {
33781
+ if (!dragInfo.current) return;
33782
+ event.stopPropagation();
33783
+ dragInfo.current = null;
33784
+ if (controls) controls.enabled = true;
33785
+ setIsDragging(false);
33786
+ releasePointerCapture(event);
33787
+ onDragEnd();
33788
+ invalidate2();
33789
+ },
33790
+ [controls, invalidate2, onDragEnd]
33791
+ );
33792
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { userData: { measureHelper: true }, children: [
33793
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
33794
+ "mesh",
33795
+ {
33796
+ userData: { measureHelper: true },
33797
+ position: [0, 0, hitLength * 0.5],
33798
+ rotation: [Math.PI / 2, 0, 0],
33799
+ onPointerDown: handlePointerDown,
33800
+ onPointerMove: handlePointerMove,
33801
+ onPointerUp: finishDrag,
33802
+ onPointerCancel: finishDrag,
33803
+ onPointerOver: (event) => {
33804
+ event.stopPropagation();
33805
+ setIsHovered(true);
33806
+ },
33807
+ onPointerOut: (event) => {
33808
+ event.stopPropagation();
33809
+ if (!dragInfo.current) setIsHovered(false);
33810
+ },
33811
+ children: [
33812
+ /* @__PURE__ */ jsxRuntimeExports.jsx("cylinderGeometry", { args: [hitRadius, hitRadius, hitLength, 12] }),
33813
+ /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { transparent: true, opacity: 0, depthWrite: false })
33814
+ ]
33815
+ }
33816
+ ),
33817
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, 0, stemLength * 0.5], rotation: [Math.PI / 2, 0, 0], renderOrder: 25, children: [
33818
+ /* @__PURE__ */ jsxRuntimeExports.jsx("cylinderGeometry", { args: [stemRadius, stemRadius, stemLength, 10] }),
33819
+ /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: color2, transparent: true, opacity: HANDLE_OPACITY, depthTest: false, depthWrite: false })
33820
+ ] }),
33821
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
33822
+ "mesh",
33823
+ {
33824
+ userData: { measureHelper: true },
33825
+ position: [0, 0, stemLength + coneHeight * 0.5],
33826
+ rotation: [Math.PI / 2, 0, 0],
33827
+ renderOrder: 26,
33828
+ children: [
33829
+ /* @__PURE__ */ jsxRuntimeExports.jsx("coneGeometry", { args: [coneRadius, coneHeight, 18] }),
33830
+ /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: color2, transparent: true, opacity: isDragging ? 0.86 : 0.72, depthTest: false, depthWrite: false })
33831
+ ]
33832
+ }
33833
+ )
33834
+ ] });
33835
+ }
33836
+ function SectionGizmoInner({ size, normal, offset }) {
33837
+ const setOffset = useForgeStore((s) => s.setSectionExplorerOffset);
33838
+ const persist = useForgeStore((s) => s.persistSectionExplorer);
34624
33839
  const planeSize = Math.max(40, size * 0.9);
34625
- const borderPositions = reactExports.useMemo(() => {
33840
+ const handleLength = MathUtils.clamp(planeSize * 0.14, MIN_HANDLE_LENGTH, MAX_HANDLE_LENGTH);
33841
+ const { center, quaternion, borderPositions } = reactExports.useMemo(() => {
33842
+ const n = new Vector3(...normal).normalize();
34626
33843
  const h2 = planeSize / 2;
34627
- return new Float32Array([-h2, -h2, 0, h2, -h2, 0, h2, h2, 0, -h2, h2, 0]);
34628
- }, [planeSize]);
34629
- return /* @__PURE__ */ jsxRuntimeExports.jsxs(
34630
- PivotControls,
34631
- {
34632
- matrix: initialMatrix,
34633
- onDrag: handleDrag,
34634
- onDragEnd: persist,
34635
- autoTransform: true,
34636
- depthTest: false,
34637
- scale: planeSize * 0.45,
34638
- lineWidth: 2,
34639
- axisColors: ["#ff4060", "#40ff60", "#4080ff"],
34640
- hoveredColor: "#ffcc00",
34641
- disableScaling: true,
34642
- userData: { measureHelper: true },
34643
- children: [
34644
- /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, renderOrder: 19, children: [
34645
- /* @__PURE__ */ jsxRuntimeExports.jsx("planeGeometry", { args: [planeSize, planeSize] }),
34646
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: PLANE_COLOR, transparent: true, opacity: PLANE_OPACITY, side: DoubleSide, depthWrite: false })
34647
- ] }),
34648
- /* @__PURE__ */ jsxRuntimeExports.jsxs("lineLoop", { renderOrder: 20, children: [
34649
- /* @__PURE__ */ jsxRuntimeExports.jsx("bufferGeometry", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("bufferAttribute", { attach: "attributes-position", args: [borderPositions, 3] }) }),
34650
- /* @__PURE__ */ jsxRuntimeExports.jsx("lineBasicMaterial", { color: PLANE_COLOR, transparent: true, opacity: 0.65, depthTest: false })
34651
- ] }),
34652
- /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { rotation: [Math.PI / 2, 0, 0], children: [
34653
- /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, planeSize * 0.06, 0], children: [
34654
- /* @__PURE__ */ jsxRuntimeExports.jsx("cylinderGeometry", { args: [planeSize * 4e-3, planeSize * 4e-3, planeSize * 0.12, 8] }),
34655
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: PLANE_COLOR, depthTest: false })
34656
- ] }),
34657
- /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, planeSize * 0.13, 0], children: [
34658
- /* @__PURE__ */ jsxRuntimeExports.jsx("coneGeometry", { args: [planeSize * 0.012, planeSize * 0.035, 10] }),
34659
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: PLANE_COLOR, depthTest: false })
34660
- ] })
34661
- ] })
34662
- ]
34663
- }
34664
- );
33844
+ return {
33845
+ center: n.clone().multiplyScalar(offset),
33846
+ quaternion: new Quaternion().setFromUnitVectors(new Vector3(0, 0, 1), n),
33847
+ borderPositions: new Float32Array([-h2, -h2, 0, h2, -h2, 0, h2, h2, 0, -h2, h2, 0])
33848
+ };
33849
+ }, [normal, offset, planeSize]);
33850
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { position: [center.x, center.y, center.z], quaternion, userData: { measureHelper: true }, children: [
33851
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, renderOrder: 19, children: [
33852
+ /* @__PURE__ */ jsxRuntimeExports.jsx("planeGeometry", { args: [planeSize, planeSize] }),
33853
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
33854
+ "meshBasicMaterial",
33855
+ {
33856
+ color: GUIDE_COLOR,
33857
+ transparent: true,
33858
+ opacity: PLANE_OPACITY,
33859
+ side: DoubleSide,
33860
+ depthTest: false,
33861
+ depthWrite: false
33862
+ }
33863
+ )
33864
+ ] }),
33865
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("lineLoop", { renderOrder: 20, children: [
33866
+ /* @__PURE__ */ jsxRuntimeExports.jsx("bufferGeometry", { children: /* @__PURE__ */ jsxRuntimeExports.jsx("bufferAttribute", { attach: "attributes-position", args: [borderPositions, 3] }) }),
33867
+ /* @__PURE__ */ jsxRuntimeExports.jsx("lineBasicMaterial", { color: GUIDE_COLOR, transparent: true, opacity: BORDER_OPACITY, depthTest: false })
33868
+ ] }),
33869
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
33870
+ SectionExplorerHandle,
33871
+ {
33872
+ normal: new Vector3(...normal).normalize(),
33873
+ offset,
33874
+ handleLength,
33875
+ onOffsetChange: setOffset,
33876
+ onDragEnd: persist
33877
+ }
33878
+ )
33879
+ ] });
34665
33880
  }
34666
33881
  function SectionExplorerGizmo({ size }) {
34667
33882
  const normal = useForgeStore((s) => s.sectionExplorerNormal);
34668
33883
  const offset = useForgeStore((s) => s.sectionExplorerOffset);
34669
- const resetKey = useForgeStore((s) => s.sectionExplorerResetKey);
34670
- return /* @__PURE__ */ jsxRuntimeExports.jsx(SectionGizmoInner, { size, initialNormal: normal, initialOffset: offset }, resetKey);
33884
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(SectionGizmoInner, { size, normal, offset });
34671
33885
  }
34672
33886
  const PLANE_TRANSFORM_EPS = 1e-8;
34673
33887
  function distToSegment2D(px, py, ax, ay, bx, by) {
@@ -34886,11 +34100,11 @@ function computeSceneBounds(objects, objectMatrices) {
34886
34100
  }
34887
34101
  const colorFromName = (name) => {
34888
34102
  const hue = hashString(name || "default") % 360;
34889
- return `hsl(${hue}, 72%, 58%)`;
34103
+ return `hsl(${hue}, 24%, 64%)`;
34890
34104
  };
34891
34105
  function SectionPlaneGuide({ def, sectionSize, style }) {
34892
34106
  const transform = reactExports.useMemo(() => resolvePlaneTransform(def.normal, def.offset), [def.normal, def.offset]);
34893
- const fillOpacity = Math.min(style.fillOpacity, 0.08);
34107
+ const fillOpacity = Math.min(style.fillOpacity, 0.04);
34894
34108
  const borderGeometry = reactExports.useMemo(() => {
34895
34109
  const half = sectionSize / 2;
34896
34110
  return new BufferGeometry().setFromPoints([
@@ -34901,25 +34115,35 @@ function SectionPlaneGuide({ def, sectionSize, style }) {
34901
34115
  ]);
34902
34116
  }, [sectionSize]);
34903
34117
  const guideColor = reactExports.useMemo(() => colorFromName(def.name), [def.name]);
34904
- const axisLength = Math.max(8, sectionSize * 0.2);
34905
- const axisRadius = Math.max(0.2, sectionSize * 45e-4);
34906
- const coneRadius = Math.max(0.45, sectionSize * 8e-3);
34907
- const coneHeight = Math.max(1.8, sectionSize * 0.03);
34118
+ const axisLength = MathUtils.clamp(sectionSize * 0.12, 8, 56);
34119
+ const axisRadius = Math.max(0.14, axisLength * 0.018);
34120
+ const coneRadius = Math.max(0.38, axisLength * 0.055);
34121
+ const coneHeight = Math.max(1.6, axisLength * 0.2);
34908
34122
  if (!transform) return null;
34909
34123
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { position: [transform.center.x, transform.center.y, transform.center.z], quaternion: transform.quaternion, children: [
34910
34124
  style.showFill && /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, renderOrder: 20, children: [
34911
34125
  /* @__PURE__ */ jsxRuntimeExports.jsx("planeGeometry", { args: [sectionSize, sectionSize] }),
34912
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: guideColor, transparent: true, opacity: fillOpacity, side: DoubleSide, depthWrite: false })
34126
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
34127
+ "meshBasicMaterial",
34128
+ {
34129
+ color: guideColor,
34130
+ transparent: true,
34131
+ opacity: fillOpacity,
34132
+ side: DoubleSide,
34133
+ depthTest: false,
34134
+ depthWrite: false
34135
+ }
34136
+ )
34913
34137
  ] }),
34914
- style.showBorder && /* @__PURE__ */ jsxRuntimeExports.jsx("lineLoop", { geometry: borderGeometry, renderOrder: 21, children: /* @__PURE__ */ jsxRuntimeExports.jsx("lineBasicMaterial", { color: guideColor, transparent: true, opacity: 0.9, depthTest: false }) }),
34138
+ style.showBorder && /* @__PURE__ */ jsxRuntimeExports.jsx("lineLoop", { geometry: borderGeometry, renderOrder: 21, children: /* @__PURE__ */ jsxRuntimeExports.jsx("lineBasicMaterial", { color: guideColor, transparent: true, opacity: 0.42, depthTest: false }) }),
34915
34139
  style.showAxis && /* @__PURE__ */ jsxRuntimeExports.jsxs("group", { renderOrder: 22, children: [
34916
- /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, 0, axisLength * 0.5], children: [
34140
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, 0, axisLength * 0.5], rotation: [Math.PI / 2, 0, 0], children: [
34917
34141
  /* @__PURE__ */ jsxRuntimeExports.jsx("cylinderGeometry", { args: [axisRadius, axisRadius, axisLength, 12] }),
34918
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: guideColor, depthTest: false })
34142
+ /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: guideColor, transparent: true, opacity: 0.58, depthTest: false, depthWrite: false })
34919
34143
  ] }),
34920
- /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, 0, axisLength + coneHeight * 0.5], children: [
34144
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("mesh", { userData: { measureHelper: true }, position: [0, 0, axisLength + coneHeight * 0.5], rotation: [Math.PI / 2, 0, 0], children: [
34921
34145
  /* @__PURE__ */ jsxRuntimeExports.jsx("coneGeometry", { args: [coneRadius, coneHeight, 14] }),
34922
- /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: guideColor, depthTest: false })
34146
+ /* @__PURE__ */ jsxRuntimeExports.jsx("meshBasicMaterial", { color: guideColor, transparent: true, opacity: 0.66, depthTest: false, depthWrite: false })
34923
34147
  ] })
34924
34148
  ] })
34925
34149
  ] });
@@ -35028,7 +34252,7 @@ function buildMeshPayload(sceneVersion, obj) {
35028
34252
  if (!obj.shape) return null;
35029
34253
  try {
35030
34254
  const mesh = obj.shape.getMesh();
35031
- const bb2 = obj.shape.boundingBox();
34255
+ const bb = obj.shape.boundingBox();
35032
34256
  if (!mesh.triVerts.length || !mesh.vertProperties.length) return null;
35033
34257
  return {
35034
34258
  meshId: meshIdForSection(sceneVersion, obj.id),
@@ -35036,8 +34260,8 @@ function buildMeshPayload(sceneVersion, obj) {
35036
34260
  triVerts: mesh.triVerts,
35037
34261
  vertProperties: mesh.vertProperties,
35038
34262
  boundingBox: {
35039
- min: [bb2.min[0], bb2.min[1], bb2.min[2]],
35040
- max: [bb2.max[0], bb2.max[1], bb2.max[2]]
34263
+ min: [bb.min[0], bb.min[1], bb.min[2]],
34264
+ max: [bb.max[0], bb.max[1], bb.max[2]]
35041
34265
  }
35042
34266
  };
35043
34267
  } catch {
@@ -35353,11 +34577,11 @@ function clipPlaneDistance(point, clippingPlanes) {
35353
34577
  function clippedDistance(fn, point, clippingPlanes) {
35354
34578
  return Math.max(fn(point.x, point.y, point.z), clipPlaneDistance(point, clippingPlanes));
35355
34579
  }
35356
- function intersectRayBoxRange(ray2, box2) {
34580
+ function intersectRayBoxRange(ray, box2) {
35357
34581
  let tNear = -Infinity;
35358
34582
  let tFar = Infinity;
35359
- const origin = ray2.origin;
35360
- const direction = ray2.direction;
34583
+ const origin = ray.origin;
34584
+ const direction = ray.direction;
35361
34585
  for (const axis of ["x", "y", "z"]) {
35362
34586
  const o2 = origin[axis];
35363
34587
  const d = direction[axis];
@@ -35378,8 +34602,8 @@ function intersectRayBoxRange(ray2, box2) {
35378
34602
  if (tFar < 0) return null;
35379
34603
  return { near: Math.max(0, tNear), far: tFar };
35380
34604
  }
35381
- function raymarchHit(ray2, box2, diagonal, sdfFn, clippingPlanes) {
35382
- const range = intersectRayBoxRange(ray2, box2);
34605
+ function raymarchHit(ray, box2, diagonal, sdfFn, clippingPlanes) {
34606
+ const range = intersectRayBoxRange(ray, box2);
35383
34607
  if (!range) return null;
35384
34608
  const maxStep = Math.max(PICK_MIN_STEP, diagonal / 180);
35385
34609
  const point = new Vector3();
@@ -35389,7 +34613,7 @@ function raymarchHit(ray2, box2, diagonal, sdfFn, clippingPlanes) {
35389
34613
  let bestT = t2;
35390
34614
  let bestAbsDist = Number.POSITIVE_INFINITY;
35391
34615
  for (let i = 0; i < PICK_MAX_STEPS; i++) {
35392
- point.copy(ray2.origin).addScaledVector(ray2.direction, t2);
34616
+ point.copy(ray.origin).addScaledVector(ray.direction, t2);
35393
34617
  const dist = clippedDistance(sdfFn, point, clippingPlanes);
35394
34618
  const absDist = Math.abs(dist);
35395
34619
  if (absDist < bestAbsDist) {
@@ -35404,7 +34628,7 @@ function raymarchHit(ray2, box2, diagonal, sdfFn, clippingPlanes) {
35404
34628
  let dLo = prevDist;
35405
34629
  for (let step = 0; step < 8; step++) {
35406
34630
  const mid = (lo + hi) * 0.5;
35407
- midPoint.copy(ray2.origin).addScaledVector(ray2.direction, mid);
34631
+ midPoint.copy(ray.origin).addScaledVector(ray.direction, mid);
35408
34632
  const dMid = clippedDistance(sdfFn, midPoint, clippingPlanes);
35409
34633
  if (Math.abs(dMid) < PICK_HIT_EPS) return midPoint;
35410
34634
  if (dLo < 0 && dMid > 0 || dLo > 0 && dMid < 0) {
@@ -35421,7 +34645,7 @@ function raymarchHit(ray2, box2, diagonal, sdfFn, clippingPlanes) {
35421
34645
  t2 += MathUtils.clamp(absDist * 0.5, PICK_MIN_STEP, maxStep);
35422
34646
  if (t2 > range.far) break;
35423
34647
  }
35424
- return bestAbsDist < PICK_HIT_EPS * 2 ? ray2.origin.clone().addScaledVector(ray2.direction, bestT) : null;
34648
+ return bestAbsDist < PICK_HIT_EPS * 2 ? ray.origin.clone().addScaledVector(ray.direction, bestT) : null;
35425
34649
  }
35426
34650
  function SdfRaymarchObject({
35427
34651
  obj,
@@ -37885,6 +37109,32 @@ function ViewController({
37885
37109
  reactExports.useEffect(() => {
37886
37110
  if (!command) return;
37887
37111
  if (command.type === "sceneCamera") return;
37112
+ if (command.type === "camera") {
37113
+ const state2 = command.camera;
37114
+ if (!state2) {
37115
+ clearCommand();
37116
+ return;
37117
+ }
37118
+ camera.position.set(state2.position[0], state2.position[1], state2.position[2]);
37119
+ camera.up.set(state2.up[0], state2.up[1], state2.up[2]);
37120
+ if ("fov" in camera && state2.fov !== void 0) {
37121
+ camera.fov = state2.fov;
37122
+ }
37123
+ if (camera.isOrthographicCamera && state2.orthoZoom !== void 0) {
37124
+ camera.zoom = state2.orthoZoom;
37125
+ }
37126
+ camera.lookAt(state2.target[0], state2.target[1], state2.target[2]);
37127
+ if ("updateProjectionMatrix" in camera) {
37128
+ camera.updateProjectionMatrix();
37129
+ }
37130
+ const controls2 = controlsRef.current;
37131
+ if (controls2) {
37132
+ controls2.target.set(state2.target[0], state2.target[1], state2.target[2]);
37133
+ controls2.update();
37134
+ }
37135
+ clearCommand();
37136
+ return;
37137
+ }
37888
37138
  const visibleObjects = objects.filter((obj) => {
37889
37139
  var _a3;
37890
37140
  return ((_a3 = settings[obj.id]) == null ? void 0 : _a3.visible) !== false;
@@ -38234,10 +37484,10 @@ const getExplodeTreePath = (object) => {
38234
37484
  const resolveSceneObjectBounds = (object) => {
38235
37485
  if (object.shape) {
38236
37486
  try {
38237
- const bb2 = object.shape.boundingBox();
37487
+ const bb = object.shape.boundingBox();
38238
37488
  return {
38239
- min: [bb2.min[0], bb2.min[1], bb2.min[2]],
38240
- max: [bb2.max[0], bb2.max[1], bb2.max[2]]
37489
+ min: [bb.min[0], bb.min[1], bb.min[2]],
37490
+ max: [bb.max[0], bb.max[1], bb.max[2]]
38241
37491
  };
38242
37492
  } catch {
38243
37493
  return null;
@@ -38245,13 +37495,13 @@ const resolveSceneObjectBounds = (object) => {
38245
37495
  }
38246
37496
  if (object.sketch) {
38247
37497
  try {
38248
- const bb2 = object.sketch.bounds();
37498
+ const bb = object.sketch.bounds();
38249
37499
  const matrix = new Matrix4().fromArray(getSketchWorldMatrix(object.sketch));
38250
37500
  const corners = [
38251
- new Vector3(bb2.min[0], bb2.min[1], 0),
38252
- new Vector3(bb2.min[0], bb2.max[1], 0),
38253
- new Vector3(bb2.max[0], bb2.min[1], 0),
38254
- new Vector3(bb2.max[0], bb2.max[1], 0)
37501
+ new Vector3(bb.min[0], bb.min[1], 0),
37502
+ new Vector3(bb.min[0], bb.max[1], 0),
37503
+ new Vector3(bb.max[0], bb.min[1], 0),
37504
+ new Vector3(bb.max[0], bb.max[1], 0)
38255
37505
  ].map((corner) => corner.applyMatrix4(matrix));
38256
37506
  const min = [...corners[0].toArray()];
38257
37507
  const max2 = [...corners[0].toArray()];
@@ -38585,6 +37835,7 @@ function useViewportState() {
38585
37835
  const drawModeActive = useDrawStore((s) => s.active) && drawFlagEnabled;
38586
37836
  const objects = reactExports.useMemo(() => (result == null ? void 0 : result.objects) ?? [], [result]);
38587
37837
  const dimensions = reactExports.useMemo(() => (result == null ? void 0 : result.dimensions) ?? [], [result]);
37838
+ const renderLabels = reactExports.useMemo(() => (result == null ? void 0 : result.renderLabels) ?? [], [result]);
38588
37839
  const attachmentPoints = reactExports.useMemo(() => {
38589
37840
  if (attachmentsVisible === "none") return [];
38590
37841
  const points = [];
@@ -38674,16 +37925,16 @@ function useViewportState() {
38674
37925
  const matrix = objectMatrices[obj.id] ?? new Matrix4();
38675
37926
  if (obj.shape) {
38676
37927
  try {
38677
- const bb2 = obj.shape.boundingBox();
38678
- if (expandBoundsByTransformedAabb(bounds, bb2.min, bb2.max, matrix)) hasBounds = true;
37928
+ const bb = obj.shape.boundingBox();
37929
+ if (expandBoundsByTransformedAabb(bounds, bb.min, bb.max, matrix)) hasBounds = true;
38679
37930
  } catch {
38680
37931
  }
38681
37932
  return;
38682
37933
  }
38683
37934
  if (obj.sketch) {
38684
37935
  try {
38685
- const bb2 = obj.sketch.bounds();
38686
- if (expandBoundsByTransformedAabb(bounds, [bb2.min[0], bb2.min[1], 0], [bb2.max[0], bb2.max[1], 0], matrix)) hasBounds = true;
37936
+ const bb = obj.sketch.bounds();
37937
+ if (expandBoundsByTransformedAabb(bounds, [bb.min[0], bb.min[1], 0], [bb.max[0], bb.max[1], 0], matrix)) hasBounds = true;
38687
37938
  } catch {
38688
37939
  }
38689
37940
  return;
@@ -38713,16 +37964,16 @@ function useViewportState() {
38713
37964
  const matrix = objectMatrices[obj.id] ?? new Matrix4();
38714
37965
  if (obj.shape) {
38715
37966
  try {
38716
- const bb2 = obj.shape.boundingBox();
38717
- if (expandBoundsByTransformedAabb(bounds, bb2.min, bb2.max, matrix)) hasBounds = true;
37967
+ const bb = obj.shape.boundingBox();
37968
+ if (expandBoundsByTransformedAabb(bounds, bb.min, bb.max, matrix)) hasBounds = true;
38718
37969
  } catch {
38719
37970
  }
38720
37971
  return;
38721
37972
  }
38722
37973
  if (obj.sketch) {
38723
37974
  try {
38724
- const bb2 = obj.sketch.bounds();
38725
- if (expandBoundsByTransformedAabb(bounds, [bb2.min[0], bb2.min[1], 0], [bb2.max[0], bb2.max[1], 0], matrix)) hasBounds = true;
37975
+ const bb = obj.sketch.bounds();
37976
+ if (expandBoundsByTransformedAabb(bounds, [bb.min[0], bb.min[1], 0], [bb.max[0], bb.max[1], 0], matrix)) hasBounds = true;
38726
37977
  } catch {
38727
37978
  }
38728
37979
  return;
@@ -38749,19 +38000,19 @@ function useViewportState() {
38749
38000
  objects.forEach((obj) => {
38750
38001
  if (obj.shape) {
38751
38002
  try {
38752
- const bb2 = obj.shape.boundingBox();
38753
- if (expandBoundsByTransformedAabb(bounds, bb2.min, bb2.max, IDENTITY_MATRIX)) hasBounds = true;
38003
+ const bb = obj.shape.boundingBox();
38004
+ if (expandBoundsByTransformedAabb(bounds, bb.min, bb.max, IDENTITY_MATRIX)) hasBounds = true;
38754
38005
  } catch {
38755
38006
  }
38756
38007
  return;
38757
38008
  }
38758
38009
  if (obj.sketch) {
38759
38010
  try {
38760
- const bb2 = obj.sketch.bounds();
38011
+ const bb = obj.sketch.bounds();
38761
38012
  if (expandBoundsByTransformedAabb(
38762
38013
  bounds,
38763
- [bb2.min[0], bb2.min[1], 0],
38764
- [bb2.max[0], bb2.max[1], 0],
38014
+ [bb.min[0], bb.min[1], 0],
38015
+ [bb.max[0], bb.max[1], 0],
38765
38016
  new Matrix4().fromArray(getSketchWorldMatrix(obj.sketch))
38766
38017
  )) {
38767
38018
  hasBounds = true;
@@ -38893,6 +38144,7 @@ function useViewportState() {
38893
38144
  constructionGhost,
38894
38145
  objects,
38895
38146
  dimensions,
38147
+ renderLabels,
38896
38148
  debugHighlights3D,
38897
38149
  dimensionsVisible,
38898
38150
  attachmentsVisible,
@@ -39912,6 +39164,329 @@ const HoverTooltipLayer = reactExports.forwardRef(
39912
39164
  );
39913
39165
  }
39914
39166
  );
39167
+ const buttonStyle = {
39168
+ border: "1px solid var(--fc-border)",
39169
+ background: "var(--fc-btn)",
39170
+ color: "var(--fc-text)",
39171
+ borderRadius: 6,
39172
+ padding: "6px 10px",
39173
+ fontSize: 12,
39174
+ cursor: "pointer",
39175
+ lineHeight: 1
39176
+ };
39177
+ const iconButtonStyle = {
39178
+ ...buttonStyle,
39179
+ width: 30,
39180
+ height: 30,
39181
+ padding: 0,
39182
+ display: "inline-flex",
39183
+ alignItems: "center",
39184
+ justifyContent: "center",
39185
+ fontSize: 15
39186
+ };
39187
+ function sceneCameraToViewportState(camera) {
39188
+ return {
39189
+ projectionMode: camera.type ?? "perspective",
39190
+ position: camera.position,
39191
+ target: camera.target,
39192
+ up: camera.up ?? [0, 0, 1],
39193
+ ...camera.fov !== void 0 ? { fov: camera.fov } : {}
39194
+ };
39195
+ }
39196
+ function getStepStartIndex(journey) {
39197
+ if (!journey.startsAt) return 0;
39198
+ const index = journey.steps.findIndex((step) => step.id === journey.startsAt);
39199
+ return index >= 0 ? index : 0;
39200
+ }
39201
+ function readJourneyUrlState() {
39202
+ try {
39203
+ const params = new URL(window.location.href).searchParams;
39204
+ const journeyId = params.get("journey");
39205
+ if (!journeyId) return null;
39206
+ return { journeyId, stepId: params.get("step") };
39207
+ } catch {
39208
+ return null;
39209
+ }
39210
+ }
39211
+ function writeJourneyUrlState(active) {
39212
+ try {
39213
+ const url2 = new URL(window.location.href);
39214
+ if (active) {
39215
+ url2.searchParams.set("journey", active.journeyId);
39216
+ url2.searchParams.set("step", active.stepId);
39217
+ } else {
39218
+ url2.searchParams.delete("journey");
39219
+ url2.searchParams.delete("step");
39220
+ }
39221
+ window.history.replaceState(null, "", `${url2.pathname}${url2.search}${url2.hash}`);
39222
+ } catch {
39223
+ }
39224
+ }
39225
+ function stepTitle(step) {
39226
+ var _a3;
39227
+ return ((_a3 = step.title) == null ? void 0 : _a3.trim()) || step.resolvedFocusPath || step.focus || step.id;
39228
+ }
39229
+ function hasErrorDiagnostics(journey) {
39230
+ return (journey.diagnostics ?? []).some((diagnostic) => diagnostic.level === "error");
39231
+ }
39232
+ function ModelJourneyBar({
39233
+ journeys,
39234
+ isViewportInteracting,
39235
+ requestViewCommand,
39236
+ selectObject,
39237
+ focusObject,
39238
+ clearFocusedObject
39239
+ }) {
39240
+ var _a3, _b2;
39241
+ const availableJourneys = reactExports.useMemo(
39242
+ () => Object.entries(journeys ?? {}).filter(([, journey]) => journey.steps.length > 0 && journey.valid !== false && !hasErrorDiagnostics(journey)),
39243
+ [journeys]
39244
+ );
39245
+ const [active, setActive] = reactExports.useState(() => {
39246
+ const urlState = typeof window !== "undefined" ? readJourneyUrlState() : null;
39247
+ if (!urlState) return null;
39248
+ const journey = journeys == null ? void 0 : journeys[urlState.journeyId];
39249
+ if (!journey || journey.valid === false || hasErrorDiagnostics(journey)) return null;
39250
+ const stepIndex = urlState.stepId ? journey.steps.findIndex((step) => step.id === urlState.stepId) : getStepStartIndex(journey);
39251
+ return { journeyId: urlState.journeyId, stepIndex: stepIndex >= 0 ? stepIndex : getStepStartIndex(journey), interrupted: false };
39252
+ });
39253
+ const activeJourney = active ? journeys == null ? void 0 : journeys[active.journeyId] : null;
39254
+ const activeStep = active ? (activeJourney == null ? void 0 : activeJourney.steps[active.stepIndex]) ?? null : null;
39255
+ const applyStep = (step) => {
39256
+ if (step.resolvedFocusId) {
39257
+ selectObject(step.resolvedFocusId);
39258
+ focusObject(step.resolvedFocusId);
39259
+ } else {
39260
+ clearFocusedObject();
39261
+ }
39262
+ if (step.camera) {
39263
+ requestViewCommand({ type: "camera", camera: sceneCameraToViewportState(step.camera) });
39264
+ return;
39265
+ }
39266
+ if (step.resolvedFocusId) {
39267
+ requestViewCommand({ type: "fit", targetId: step.resolvedFocusId });
39268
+ }
39269
+ };
39270
+ const activateStep = (journeyId, stepIndex) => {
39271
+ const journey = journeys == null ? void 0 : journeys[journeyId];
39272
+ const boundedStepIndex = Math.max(0, Math.min(stepIndex, ((journey == null ? void 0 : journey.steps.length) ?? 1) - 1));
39273
+ const step = journey == null ? void 0 : journey.steps[boundedStepIndex];
39274
+ if (!journey || !step) return;
39275
+ setActive({ journeyId, stepIndex: boundedStepIndex, interrupted: false });
39276
+ writeJourneyUrlState({ journeyId, stepId: step.id });
39277
+ applyStep(step);
39278
+ };
39279
+ reactExports.useEffect(() => {
39280
+ if (active) return;
39281
+ const autoEntry = availableJourneys.find(([, journey]) => journey.behavior === "auto");
39282
+ if (!autoEntry) return;
39283
+ const [autoJourneyId, autoJourney] = autoEntry;
39284
+ activateStep(autoJourneyId, getStepStartIndex(autoJourney));
39285
+ }, [active, availableJourneys]);
39286
+ reactExports.useEffect(() => {
39287
+ if (!activeStep || !active) return;
39288
+ writeJourneyUrlState({ journeyId: active.journeyId, stepId: activeStep.id });
39289
+ }, [active, activeStep]);
39290
+ reactExports.useEffect(() => {
39291
+ if (!active) return;
39292
+ if (!activeJourney || !activeStep || activeJourney.valid === false) {
39293
+ setActive(null);
39294
+ writeJourneyUrlState(null);
39295
+ }
39296
+ }, [active, activeJourney, activeStep]);
39297
+ reactExports.useEffect(() => {
39298
+ if (!active || !activeStep || !isViewportInteracting || active.interrupted) return;
39299
+ setActive({ ...active, interrupted: true });
39300
+ }, [active, activeStep, isViewportInteracting]);
39301
+ reactExports.useEffect(() => {
39302
+ if (!active || !activeJourney || !activeStep) return;
39303
+ applyStep(activeStep);
39304
+ }, []);
39305
+ if (availableJourneys.length === 0) return null;
39306
+ if (!active || !activeJourney || !activeStep) {
39307
+ const [firstId, firstJourney] = availableJourneys[0];
39308
+ const label = ((_a3 = firstJourney.title) == null ? void 0 : _a3.trim()) || firstId;
39309
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
39310
+ "div",
39311
+ {
39312
+ style: {
39313
+ position: "absolute",
39314
+ left: 16,
39315
+ bottom: 16,
39316
+ zIndex: 18,
39317
+ display: "flex",
39318
+ gap: 6,
39319
+ pointerEvents: "auto"
39320
+ },
39321
+ children: [
39322
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { type: "button", style: buttonStyle, onClick: () => activateStep(firstId, getStepStartIndex(firstJourney)), children: [
39323
+ "Explore: ",
39324
+ label
39325
+ ] }),
39326
+ availableJourneys.length > 1 && /* @__PURE__ */ jsxRuntimeExports.jsx(
39327
+ "select",
39328
+ {
39329
+ "aria-label": "Choose model journey",
39330
+ defaultValue: firstId,
39331
+ onChange: (event) => {
39332
+ const journey = journeys == null ? void 0 : journeys[event.target.value];
39333
+ if (journey) activateStep(event.target.value, getStepStartIndex(journey));
39334
+ },
39335
+ style: {
39336
+ background: "var(--fc-bgInput)",
39337
+ border: "1px solid var(--fc-border)",
39338
+ borderRadius: 6,
39339
+ color: "var(--fc-text)",
39340
+ fontSize: 12,
39341
+ padding: "5px 8px"
39342
+ },
39343
+ children: availableJourneys.map(([journeyId, journey]) => {
39344
+ var _a4;
39345
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("option", { value: journeyId, children: ((_a4 = journey.title) == null ? void 0 : _a4.trim()) || journeyId }, journeyId);
39346
+ })
39347
+ }
39348
+ )
39349
+ ]
39350
+ }
39351
+ );
39352
+ }
39353
+ const atStart = active.stepIndex <= 0;
39354
+ const atEnd = active.stepIndex >= activeJourney.steps.length - 1;
39355
+ const caption = (_b2 = activeStep.caption) == null ? void 0 : _b2.trim();
39356
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
39357
+ "div",
39358
+ {
39359
+ style: {
39360
+ position: "absolute",
39361
+ left: "50%",
39362
+ bottom: 16,
39363
+ transform: "translateX(-50%)",
39364
+ zIndex: 18,
39365
+ maxWidth: "min(720px, calc(100% - 32px))",
39366
+ background: "color-mix(in srgb, var(--fc-bgPanel) 96%, transparent)",
39367
+ border: "1px solid var(--fc-border)",
39368
+ borderRadius: 8,
39369
+ boxShadow: "0 10px 28px rgba(0, 0, 0, 0.28)",
39370
+ color: "var(--fc-text)",
39371
+ padding: caption ? "8px 10px 9px" : "8px 10px",
39372
+ pointerEvents: "auto"
39373
+ },
39374
+ children: [
39375
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, children: [
39376
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39377
+ "button",
39378
+ {
39379
+ type: "button",
39380
+ "aria-label": "Exit journey",
39381
+ title: "Exit journey",
39382
+ style: iconButtonStyle,
39383
+ onClick: () => {
39384
+ setActive(null);
39385
+ clearFocusedObject();
39386
+ writeJourneyUrlState(null);
39387
+ },
39388
+ children: "x"
39389
+ }
39390
+ ),
39391
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39392
+ "button",
39393
+ {
39394
+ type: "button",
39395
+ "aria-label": "Previous step",
39396
+ style: iconButtonStyle,
39397
+ disabled: atStart,
39398
+ onClick: () => activateStep(active.journeyId, active.stepIndex - 1),
39399
+ children: "‹"
39400
+ }
39401
+ ),
39402
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { style: { minWidth: 0, display: "flex", alignItems: "baseline", gap: 8 }, children: [
39403
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { style: { fontSize: 11, color: "var(--fc-textMuted)", whiteSpace: "nowrap" }, children: [
39404
+ active.stepIndex + 1,
39405
+ " / ",
39406
+ activeJourney.steps.length
39407
+ ] }),
39408
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { style: { fontSize: 13, fontWeight: 600, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: stepTitle(activeStep) })
39409
+ ] }),
39410
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { flex: 1 } }),
39411
+ active.interrupted && /* @__PURE__ */ jsxRuntimeExports.jsx(
39412
+ "button",
39413
+ {
39414
+ type: "button",
39415
+ style: buttonStyle,
39416
+ onClick: () => {
39417
+ setActive({ ...active, interrupted: false });
39418
+ applyStep(activeStep);
39419
+ },
39420
+ children: "Resume"
39421
+ }
39422
+ ),
39423
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
39424
+ "button",
39425
+ {
39426
+ type: "button",
39427
+ style: buttonStyle,
39428
+ disabled: atEnd,
39429
+ onClick: () => activateStep(active.journeyId, active.stepIndex + 1),
39430
+ children: "Next"
39431
+ }
39432
+ )
39433
+ ] }),
39434
+ caption && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { style: { marginTop: 6, paddingLeft: 76, fontSize: 12, color: "var(--fc-textDim)" }, children: caption })
39435
+ ]
39436
+ }
39437
+ );
39438
+ }
39439
+ const anchorTransform = {
39440
+ center: "translate(-50%, -50%)",
39441
+ top: "translate(-50%, 0)",
39442
+ bottom: "translate(-50%, -100%)",
39443
+ left: "translate(0, -50%)",
39444
+ right: "translate(-100%, -50%)",
39445
+ "top-left": "translate(0, 0)",
39446
+ "top-right": "translate(-100%, 0)",
39447
+ "bottom-left": "translate(0, -100%)",
39448
+ "bottom-right": "translate(-100%, -100%)"
39449
+ };
39450
+ function RenderLabelItem({ label }) {
39451
+ const position = reactExports.useMemo(
39452
+ () => new Vector3(
39453
+ label.at[0] + label.offset[0],
39454
+ label.at[1] + label.offset[1],
39455
+ label.at[2] + label.offset[2]
39456
+ ),
39457
+ [label.at, label.offset]
39458
+ );
39459
+ const fontSize = Math.max(8, Math.min(64, label.size ?? 12));
39460
+ const background = label.background ?? "rgba(15, 23, 42, 0.82)";
39461
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(Html, { position, occlude: !label.alwaysOnTop, zIndexRange: [80, 0], style: { pointerEvents: "none" }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
39462
+ "span",
39463
+ {
39464
+ style: {
39465
+ display: "inline-block",
39466
+ transform: anchorTransform[label.anchor],
39467
+ color: label.color ?? "#f8fafc",
39468
+ background,
39469
+ border: background === "transparent" ? "none" : "1px solid rgba(255,255,255,0.16)",
39470
+ borderRadius: 4,
39471
+ padding: "2px 6px",
39472
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
39473
+ fontSize,
39474
+ fontWeight: 650,
39475
+ lineHeight: 1.25,
39476
+ maxWidth: 260,
39477
+ overflowWrap: "break-word",
39478
+ whiteSpace: "pre-wrap",
39479
+ boxShadow: background === "transparent" ? "none" : "0 4px 12px rgba(0,0,0,0.22)",
39480
+ userSelect: "none"
39481
+ },
39482
+ children: label.text
39483
+ }
39484
+ ) });
39485
+ }
39486
+ function RenderLabelsOverlay({ labels }) {
39487
+ if (labels.length === 0) return null;
39488
+ return /* @__PURE__ */ jsxRuntimeExports.jsx("group", { renderOrder: 12, children: labels.map((label) => /* @__PURE__ */ jsxRuntimeExports.jsx(RenderLabelItem, { label }, label.id)) });
39489
+ }
39915
39490
  function RenderStyleExposure({ exposure }) {
39916
39491
  const { gl } = useThree();
39917
39492
  reactExports.useEffect(() => {
@@ -39953,6 +39528,7 @@ function Viewport() {
39953
39528
  constructionGhost,
39954
39529
  objects,
39955
39530
  dimensions,
39531
+ renderLabels,
39956
39532
  debugHighlights3D,
39957
39533
  dimensionsVisible,
39958
39534
  attachmentsVisible,
@@ -40275,6 +39851,7 @@ function Viewport() {
40275
39851
  historyMode && /* @__PURE__ */ jsxRuntimeExports.jsx(ConstructionHistoryOverlay, { objectMatrices, objectSettings }),
40276
39852
  hoveredJointOverlay && /* @__PURE__ */ jsxRuntimeExports.jsx(HoveredJointOverlay, { state: hoveredJointOverlay, config: jointOverlayConfig }),
40277
39853
  dimensionsVisible && dimensions.map((d) => /* @__PURE__ */ jsxRuntimeExports.jsx(DimensionAnnotation, { def: d, lengthUnit }, d.id)),
39854
+ /* @__PURE__ */ jsxRuntimeExports.jsx(RenderLabelsOverlay, { labels: renderLabels }),
40278
39855
  attachmentsVisible !== "none" && attachmentPoints.map((ap) => {
40279
39856
  const matrix = objectMatrices[ap.objectId];
40280
39857
  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}`);
@@ -40437,6 +40014,17 @@ function Viewport() {
40437
40014
  })(),
40438
40015
  /* @__PURE__ */ jsxRuntimeExports.jsx(AnimationBar, {}),
40439
40016
  /* @__PURE__ */ jsxRuntimeExports.jsx(TrajectoryTimeline, {}),
40017
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
40018
+ ModelJourneyBar,
40019
+ {
40020
+ journeys: sceneConfig == null ? void 0 : sceneConfig.journeys,
40021
+ isViewportInteracting,
40022
+ requestViewCommand,
40023
+ selectObject,
40024
+ focusObject,
40025
+ clearFocusedObject
40026
+ }
40027
+ ),
40440
40028
  /* @__PURE__ */ jsxRuntimeExports.jsx(PerformanceInfoPanel, { enabled: showPerformanceInfo, stats: performanceInfo }),
40441
40029
  !(isEvaluating || evaluationPhase === "exporting") && /* @__PURE__ */ jsxRuntimeExports.jsx(ZoomIndicatorPanel, { mmPerPx: zoomMmPerPx }),
40442
40030
  isSketchOnly && /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -40813,7 +40401,7 @@ function Viewport() {
40813
40401
  }
40814
40402
  );
40815
40403
  }
40816
- const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-Arw2NnGJ.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
40404
+ const EditorApp$1 = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-C5P2rBfh.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
40817
40405
  const PENDING_SHARE_COPY_KEY = "fc-pending-share-copy";
40818
40406
  function storePendingShareCopy(shareId) {
40819
40407
  sessionStorage.setItem(PENDING_SHARE_COPY_KEY, shareId);
@@ -41006,15 +40594,15 @@ const PublishedModelPage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Objec
41006
40594
  consumePendingShareCopy,
41007
40595
  storePendingShareCopy
41008
40596
  }, Symbol.toStringTag, { value: "Module" }));
41009
- reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-DvhtmWOz.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
41010
- const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-BP6wlsBN.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
41011
- reactExports.lazy(() => __vitePreload(() => import("./BlogPage-DVmgN0ma.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
41012
- reactExports.lazy(() => __vitePreload(() => import("./AdminPage-Bs4PiK00.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
40597
+ reactExports.lazy(() => __vitePreload(() => import("./LandingPageProofDriven-DIsYTnep.js"), true ? __vite__mapDeps([1]) : void 0).then((m2) => ({ default: m2.LandingPageProofDriven })));
40598
+ const DocsPage = reactExports.lazy(() => __vitePreload(() => import("./DocsPage-DHbd-WS-.js"), true ? [] : void 0).then((m2) => ({ default: m2.DocsPage })));
40599
+ reactExports.lazy(() => __vitePreload(() => import("./BlogPage-BvzruKtw.js"), true ? [] : void 0).then((m2) => ({ default: m2.BlogPage })));
40600
+ reactExports.lazy(() => __vitePreload(() => import("./AdminPage-4jihcEk_.js"), true ? [] : void 0).then((m2) => ({ default: m2.AdminPage })));
41013
40601
  reactExports.lazy(() => __vitePreload(() => Promise.resolve().then(() => PublishedModelPage$1), true ? void 0 : void 0).then((m2) => ({ default: m2.PublishedModelPage })));
41014
- reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-wNy3_2yn.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
41015
- reactExports.lazy(() => __vitePreload(() => import("./PricingPage-657oLvWh.js"), true ? __vite__mapDeps([2,1]) : void 0).then((m2) => ({ default: m2.PricingPage })));
41016
- const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-Arw2NnGJ.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
41017
- const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-qgQiOahL.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
40602
+ reactExports.lazy(() => __vitePreload(() => import("./SettingsPage-rntoyJ3b.js"), true ? [] : void 0).then((m2) => ({ default: m2.SettingsPage })));
40603
+ reactExports.lazy(() => __vitePreload(() => import("./PricingPage-YPOr12pP.js"), true ? __vite__mapDeps([2,1]) : void 0).then((m2) => ({ default: m2.PricingPage })));
40604
+ const EditorApp = reactExports.lazy(() => __vitePreload(() => import("./EditorApp-C5P2rBfh.js"), true ? __vite__mapDeps([0]) : void 0).then((m2) => ({ default: m2.EditorApp })));
40605
+ const EmbedViewer = reactExports.lazy(() => __vitePreload(() => import("./EmbedViewer-B70wQwlE.js"), true ? [] : void 0).then((m2) => ({ default: m2.EmbedViewer })));
41018
40606
  const embedMode = isEmbedMode() && !window.location.pathname.startsWith("/m/");
41019
40607
  const EDITABLE_CRASH_FILE = /\.(?:forge\.js|[cm]?[jt]sx?|json|md|txt|svg)$/i;
41020
40608
  function firstMeaningfulLine(text) {
@@ -41231,76 +40819,81 @@ function App() {
41231
40819
  applyTheme(localStorage.getItem("fc-theme") || "dark");
41232
40820
  clientExports.createRoot(document.getElementById("root")).render(/* @__PURE__ */ jsxRuntimeExports.jsx(App, {}));
41233
40821
  export {
41234
- TOUCH_GESTURES_3D as $,
40822
+ LocalStudioEnvironment as $,
41235
40823
  AuthApiError as A,
41236
40824
  BrandMark as B,
41237
- isImportableProjectMeshFile as C,
41238
- isImportableProjectBinaryFile as D,
41239
- hasExternalFiles as E,
40825
+ exportExactFromStore as C,
40826
+ deriveExportStem as D,
40827
+ storageQuotaUpgradeMessage as E,
41240
40828
  FLAG_DEFINITIONS as F,
41241
- isImportableProjectExactFile as G,
41242
- resolvePreviewFile as H,
41243
- countParamSnapshotDiff as I,
41244
- buildEmbedSnippet as J,
41245
- themes as K,
41246
- formatArea as L,
41247
- sliderToAnimationSpeed as M,
41248
- animationSpeedToSlider as N,
41249
- formatAnimationSpeed as O,
41250
- resolveJointRange as P,
41251
- useJointsConfig as Q,
41252
- useJointAnimationValues as R,
41253
- expandBoundsByTransformedAabb as S,
41254
- Canvas as T,
41255
- PerspectiveCamera as U,
41256
- ControlsInteractionBridge as V,
41257
- ViewController as W,
41258
- SceneConfigurator as X,
41259
- LocalStudioEnvironment as Y,
41260
- Grid as Z,
41261
- OrbitControls2 as _,
40829
+ isImportableProjectMeshFile as G,
40830
+ isImportableProjectBinaryFile as H,
40831
+ hasExternalFiles as I,
40832
+ isImportableProjectExactFile as J,
40833
+ resolvePreviewFile as K,
40834
+ countParamSnapshotDiff as L,
40835
+ buildEmbedSnippet as M,
40836
+ themes as N,
40837
+ formatArea as O,
40838
+ sliderToAnimationSpeed as P,
40839
+ animationSpeedToSlider as Q,
40840
+ formatAnimationSpeed as R,
40841
+ resolveJointRange as S,
40842
+ useJointsConfig as T,
40843
+ useJointAnimationValues as U,
40844
+ expandBoundsByTransformedAabb as V,
40845
+ Canvas as W,
40846
+ PerspectiveCamera as X,
40847
+ ControlsInteractionBridge as Y,
40848
+ ViewController as Z,
40849
+ SceneConfigurator as _,
41262
40850
  applyTheme as a,
41263
- MOUSE_BUTTONS_3D as a0,
41264
- FOCUS_MODE_DIM_OPACITY as a1,
41265
- useJointAnimationLoop as a2,
41266
- computeJointNodeMatrices as a3,
41267
- computeObjectJointMatrices as a4,
41268
- readLastActiveFileForUser as a5,
41269
- ToastContainer as a6,
41270
- isMobile as a7,
41271
- useFeatureFlag as a8,
41272
- decodeSharedHash as a9,
41273
- decodeSharedBundle as aa,
41274
- getExternalUrl as ab,
41275
- getGistId as ac,
41276
- Viewport as ad,
41277
- shouldBlockBrowserShortcut as ae,
41278
- useDrawStore as af,
41279
- storePendingShareCopy as ag,
41280
- share as ah,
40851
+ RenderLabelsOverlay as a0,
40852
+ Grid as a1,
40853
+ OrbitControls2 as a2,
40854
+ TOUCH_GESTURES_3D as a3,
40855
+ MOUSE_BUTTONS_3D as a4,
40856
+ ModelJourneyBar as a5,
40857
+ FOCUS_MODE_DIM_OPACITY as a6,
40858
+ useJointAnimationLoop as a7,
40859
+ computeJointNodeMatrices as a8,
40860
+ computeObjectJointMatrices as a9,
40861
+ readLastActiveFileForUser as aa,
40862
+ ToastContainer as ab,
40863
+ isMobile as ac,
40864
+ useFeatureFlag as ad,
40865
+ decodeSharedHash as ae,
40866
+ decodeSharedBundle as af,
40867
+ getExternalUrl as ag,
40868
+ getGistId as ah,
40869
+ Viewport as ai,
40870
+ shouldBlockBrowserShortcut as aj,
40871
+ useDrawStore as ak,
40872
+ storePendingShareCopy as al,
40873
+ share as am,
41281
40874
  authFetch as b,
41282
40875
  authApi as c,
41283
- useProjectStore as d,
41284
- useForgeStore as e,
41285
- collectDependencies as f,
41286
- buildBundleShareUrl as g,
40876
+ showToast as d,
40877
+ useProjectStore as e,
40878
+ formatStorageBytes as f,
40879
+ useForgeStore as g,
41287
40880
  hasImports as h,
41288
- buildBundleEmbedUrl as i,
41289
- buildShareUrl as j,
41290
- buildEmbedUrl as k,
41291
- fileSystem as l,
41292
- useFeatureFlagStore as m,
41293
- fetchGistModel as n,
41294
- fetchUrlModel as o,
41295
- exportMeshFromStore as p,
41296
- exportReportFromStore as q,
40881
+ collectDependencies as i,
40882
+ buildBundleShareUrl as j,
40883
+ buildBundleEmbedUrl as k,
40884
+ buildShareUrl as l,
40885
+ buildEmbedUrl as m,
40886
+ fileSystem as n,
40887
+ useFeatureFlagStore as o,
40888
+ fetchGistModel as p,
40889
+ fetchUrlModel as q,
41297
40890
  readProjectFilesFromDataTransfer as r,
41298
- showToast as s,
40891
+ storageUsagePercent as s,
41299
40892
  triggerDownload as t,
41300
40893
  useAuthStore as u,
41301
- exportOrbitVideoFromStore as v,
41302
- exportSketchFromStore as w,
41303
- buildGistShareUrl as x,
41304
- exportExactFromStore as y,
41305
- deriveExportStem as z
40894
+ exportMeshFromStore as v,
40895
+ exportReportFromStore as w,
40896
+ exportOrbitVideoFromStore as x,
40897
+ exportSketchFromStore as y,
40898
+ buildGistShareUrl as z
41306
40899
  };