@tscircuit/3d-viewer 0.0.639 → 0.0.640

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 (2) hide show
  1. package/dist/index.js +69 -33
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19303,6 +19303,17 @@ var useObjectVisibility = (circuitKey) => {
19303
19303
  };
19304
19304
  };
19305
19305
 
19306
+ // src/utils/find-model-object.ts
19307
+ var findModelObject = (root, objectId) => {
19308
+ let model;
19309
+ root.traverse((object) => {
19310
+ const { cad_component_id, cad_cable_id } = object.userData;
19311
+ if (!model && (cad_component_id ?? cad_cable_id) === objectId)
19312
+ model = object;
19313
+ });
19314
+ return model;
19315
+ };
19316
+
19306
19317
  // src/utils/configure-runtime-font.ts
19307
19318
  import { configureTextBuilder } from "troika-three-text";
19308
19319
 
@@ -22333,7 +22344,7 @@ import * as THREE31 from "three";
22333
22344
  // package.json
22334
22345
  var package_default = {
22335
22346
  name: "@tscircuit/3d-viewer",
22336
- version: "0.0.638",
22347
+ version: "0.0.639",
22337
22348
  repository: {
22338
22349
  type: "git",
22339
22350
  url: "https://github.com/tscircuit/3d-viewer"
@@ -39249,6 +39260,7 @@ var ContextMenu = ({
39249
39260
  onSectionView,
39250
39261
  onExplosionView,
39251
39262
  explosionAvailable = false,
39263
+ downloadModelName,
39252
39264
  onDownloadGltf,
39253
39265
  onOpenKeyboardShortcuts
39254
39266
  }) => {
@@ -39559,7 +39571,7 @@ var ContextMenu = ({
39559
39571
  }
39560
39572
  ),
39561
39573
  /* @__PURE__ */ jsx40(DropdownMenuSeparator, { style: separatorStyles2 }),
39562
- /* @__PURE__ */ jsx40(
39574
+ /* @__PURE__ */ jsxs10(
39563
39575
  DropdownMenuItem,
39564
39576
  {
39565
39577
  style: {
@@ -39571,7 +39583,10 @@ var ContextMenu = ({
39571
39583
  onMouseEnter: () => setHoveredItem("download"),
39572
39584
  onMouseLeave: () => setHoveredItem(null),
39573
39585
  onTouchStart: () => setHoveredItem("download"),
39574
- children: /* @__PURE__ */ jsx40("span", { style: { display: "flex", alignItems: "center" }, children: "Download GLTF" })
39586
+ children: [
39587
+ /* @__PURE__ */ jsx40("span", { style: { flex: 1, display: "flex", alignItems: "center" }, children: "Download GLTF" }),
39588
+ downloadModelName && /* @__PURE__ */ jsx40("span", { style: { opacity: 0.55, fontSize: 13 }, children: downloadModelName })
39589
+ ]
39575
39590
  }
39576
39591
  ),
39577
39592
  /* @__PURE__ */ jsx40(DropdownMenuSeparator, { style: separatorStyles2 }),
@@ -40400,34 +40415,51 @@ function createSectionExport(root, spec) {
40400
40415
  // src/hooks/useGlobalDownloadGltf.ts
40401
40416
  import { useCallback as useCallback24 } from "react";
40402
40417
  import { GLTFExporter as GLTFExporter2 } from "three/examples/jsm/exporters/GLTFExporter.js";
40418
+
40419
+ // src/utils/clone-model-for-export.ts
40420
+ var cloneModelForExport = (root, objectId) => {
40421
+ const source = findModelObject(root, objectId);
40422
+ if (!source) return;
40423
+ source.updateWorldMatrix(true, true);
40424
+ const output = source.clone(true);
40425
+ source.matrixWorld.decompose(output.position, output.quaternion, output.scale);
40426
+ return output;
40427
+ };
40428
+
40429
+ // src/hooks/useGlobalDownloadGltf.ts
40403
40430
  var useGlobalDownloadGltf = () => {
40404
- return useCallback24(() => {
40405
- const root = window.__TSCIRCUIT_THREE_OBJECT;
40406
- if (!root) return;
40407
- const section = root.userData.sectionView;
40408
- const sectionExport = section ? createSectionExport(root, section) : void 0;
40409
- const exporter = new GLTFExporter2();
40410
- exporter.parse(
40411
- sectionExport?.root ?? root,
40412
- (gltf) => {
40413
- sectionExport?.dispose();
40414
- const blob = new Blob(
40415
- [gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
40416
- { type: "model/gltf+json" }
40417
- );
40418
- const url = URL.createObjectURL(blob);
40419
- const link = document.createElement("a");
40420
- link.href = url;
40421
- link.download = "scene.gltf";
40422
- link.click();
40423
- URL.revokeObjectURL(url);
40424
- },
40425
- (err) => {
40426
- sectionExport?.dispose();
40427
- console.error("Failed to export GLTF", err);
40428
- }
40429
- );
40430
- }, []);
40431
+ return useCallback24(
40432
+ (model, root = window.__TSCIRCUIT_THREE_OBJECT) => {
40433
+ if (!root) return;
40434
+ const target = model ? cloneModelForExport(root, model.objectId) : root;
40435
+ if (!target) return;
40436
+ if (model) target.name = model.name;
40437
+ const section = root.userData.sectionView;
40438
+ const sectionExport = section ? createSectionExport(target, section) : void 0;
40439
+ const exporter = new GLTFExporter2();
40440
+ exporter.parse(
40441
+ sectionExport?.root ?? target,
40442
+ (gltf) => {
40443
+ sectionExport?.dispose();
40444
+ const blob = new Blob(
40445
+ [gltf instanceof ArrayBuffer ? gltf : JSON.stringify(gltf)],
40446
+ { type: "model/gltf+json" }
40447
+ );
40448
+ const url = URL.createObjectURL(blob);
40449
+ const link = document.createElement("a");
40450
+ link.href = url;
40451
+ link.download = model ? `${model.name}.gltf` : "scene.gltf";
40452
+ link.click();
40453
+ URL.revokeObjectURL(url);
40454
+ },
40455
+ (err) => {
40456
+ sectionExport?.dispose();
40457
+ console.error("Failed to export GLTF", err);
40458
+ }
40459
+ );
40460
+ },
40461
+ []
40462
+ );
40431
40463
  };
40432
40464
 
40433
40465
  // src/CadViewer.tsx
@@ -40493,10 +40525,13 @@ var CadViewerInner = (props) => {
40493
40525
  const sceneRef = useContext13(SchematicNavigationContext);
40494
40526
  const [selectedComponent, setSelectedComponent] = useState46();
40495
40527
  const [selectedObject, setSelectedObject] = useState46();
40528
+ const [selectedModel, setSelectedModel] = useState46();
40496
40529
  const handleMenuOpen = useCallback25(
40497
40530
  (position) => {
40498
- setSelectedObject(
40499
- pickSceneObject(sceneRef.current, position, circuitJson)
40531
+ const picked = pickSceneObject(sceneRef.current, position, circuitJson);
40532
+ setSelectedObject(picked);
40533
+ setSelectedModel(
40534
+ picked && sceneRef.current && findModelObject(sceneRef.current.rootObject, picked.objectId) ? picked : void 0
40500
40535
  );
40501
40536
  setSelectedComponent(
40502
40537
  props.onViewSchematicComponent ? pickSchematicComponent(sceneRef.current, position, circuitJson) : void 0
@@ -40775,8 +40810,9 @@ var CadViewerInner = (props) => {
40775
40810
  setCameraPreset("Custom");
40776
40811
  closeMenu();
40777
40812
  },
40813
+ downloadModelName: selectedModel?.name,
40778
40814
  onDownloadGltf: () => {
40779
- downloadGltf();
40815
+ downloadGltf(selectedModel, sceneRef.current?.rootObject);
40780
40816
  closeMenu();
40781
40817
  },
40782
40818
  onOpenKeyboardShortcuts: () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tscircuit/3d-viewer",
3
- "version": "0.0.639",
3
+ "version": "0.0.640",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/tscircuit/3d-viewer"