partforge 0.123.0 → 0.124.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/types/index.d.ts CHANGED
@@ -110,10 +110,6 @@ export interface MountElements {
110
110
  measure?: HTMLElement | null;
111
111
  annotate?: HTMLElement | null;
112
112
  railToggle?: HTMLElement | null;
113
- /** Realistic-mode toggle (default id `#realistic`). */
114
- realistic?: HTMLButtonElement | null;
115
- /** Environment picker, an empty `<select>` the mount fills (default id `#environment`). Shown only while realistic. */
116
- environment?: HTMLSelectElement | null;
117
113
  };
118
114
  }
119
115
 
@@ -194,13 +190,16 @@ export interface MountOptions {
194
190
  annotateSend?: "viewbar" | "host";
195
191
  /**
196
192
  * A previous mount's `runtime.getViewerState()`, handed back so this mount
197
- * resumes the camera, projection and cutaway where that one left them. For a
193
+ * resumes the camera, projection, cutaway, render mode, chosen environment
194
+ * and per-style feature lines where that one left them (the last three
195
+ * outrank what is stored). For a
198
196
  * host that applies edits by REMOUNTING: the part changed, the user's view of
199
197
  * it should not.
200
198
  *
201
- * Omit on a first mount — the viewer then restores its own persisted camera
202
- * and projection as before. Restore is best-effort per field: a pose this
203
- * part cannot support is dropped, never fatal.
199
+ * Omit on a first mount — the viewer then restores its own persisted camera,
200
+ * in perspective (the projection is automatic, so it is not persisted).
201
+ * Restore is best-effort per field: a pose this part cannot support is
202
+ * dropped, never fatal.
204
203
  */
205
204
  viewerState?: ViewerState | null;
206
205
  /**
@@ -267,6 +266,13 @@ export interface CutawayState {
267
266
  export interface ViewerState {
268
267
  /** The live camera pose, or `null` when the viewer could not report one. */
269
268
  camera: { pos: [number, number, number]; target: [number, number, number] } | null;
269
+ /**
270
+ * The live projection. It is AUTOMATIC — orthographic only on a view cube
271
+ * face view (Fusion 360's "Perspective with Ortho Faces"), left by the first
272
+ * rotation — so `"orthographic"` is restored only when `camera` is itself a
273
+ * face view (looking straight down a world axis); carried with any other
274
+ * camera, or none, the remount comes back in perspective.
275
+ */
270
276
  projection: "perspective" | "orthographic";
271
277
  cutaway: CutawayState | null;
272
278
  /** Always reported by `getViewerState()` — the mode being headed for, so a realistic switch still loading reads `"realistic"` (a failed one settles to `"cad"`). Optional on the way back in (a state saved by an older partforge has none). */
@@ -1,78 +0,0 @@
1
- // Viewbar chrome for realistic mode: a toggle button and an environment <select>.
2
- // Both optional (a host without the elements simply has no built-in controls and
3
- // drives runtime.renderMode / runtime.environment itself). Same shape as
4
- // viewer-controls.js. The state shown is always the viewer's: the toggle is
5
- // pressed only once realistic has actually landed, and the menu shows the
6
- // environment in effect (a failed switch snaps it back).
7
- import { ENVIRONMENTS } from "./materials/environments.js";
8
- import { saveRenderMode, saveEnvironment } from "./view-state.js";
9
- import { attachButtonTooltips } from "./tooltip.js";
10
-
11
- const LABEL = "Realistic view";
12
- const ERROR_LABEL = "Couldn't load realistic view";
13
-
14
- export function attachRealisticControls(viewer, { toggle, envMenu } = {}, { tooltip } = {}) {
15
- const binding = tooltip && toggle ? attachButtonTooltips(tooltip, [{ element: toggle }]) : null;
16
- if (envMenu && !envMenu.options.length) {
17
- for (const env of Object.values(ENVIRONMENTS)) {
18
- const o = document.createElement("option");
19
- o.value = env.id;
20
- o.textContent = env.label;
21
- envMenu.append(o);
22
- }
23
- envMenu.setAttribute("aria-label", "Environment");
24
- }
25
-
26
- // The last mode event's busy/error, so an environment event or sync() —
27
- // which carry neither — re-render without clearing them.
28
- let busy = false;
29
- let error = null;
30
-
31
- function render() {
32
- const mode = viewer.getRenderMode();
33
- if (toggle) {
34
- const on = mode === "realistic";
35
- toggle.classList.toggle("on", on);
36
- toggle.setAttribute("aria-pressed", String(on));
37
- if (busy) toggle.dataset.busy = "true"; else delete toggle.dataset.busy;
38
- const label = error ? ERROR_LABEL : LABEL;
39
- toggle.setAttribute("aria-label", label);
40
- if (!tooltip) toggle.title = label;
41
- }
42
- if (envMenu) {
43
- envMenu.hidden = mode !== "realistic";
44
- envMenu.value = viewer.getEnvironment();
45
- }
46
- binding?.sync();
47
- }
48
-
49
- // A click while realistic is still loading is a change of mind: back to CAD.
50
- // What persists is what the viewer says took effect, not what was asked for.
51
- const onToggle = () => {
52
- const next = viewer.getRenderMode() === "realistic" || busy ? "cad" : "realistic";
53
- viewer.setRenderMode(next).then(saveRenderMode, () => {});
54
- };
55
- const onEnv = () => {
56
- viewer.setEnvironment(envMenu.value).then(saveEnvironment, () => {});
57
- };
58
- toggle?.addEventListener("click", onToggle);
59
- envMenu?.addEventListener("change", onEnv);
60
- const offMode = viewer.onRenderModeChange((e) => {
61
- busy = !!e?.busy;
62
- error = e?.error ?? null;
63
- render();
64
- });
65
- const offEnv = viewer.onEnvironmentChange(() => render());
66
- render();
67
-
68
- return {
69
- sync: render,
70
- detach() {
71
- toggle?.removeEventListener("click", onToggle);
72
- envMenu?.removeEventListener("change", onEnv);
73
- offMode();
74
- offEnv();
75
- binding?.detach();
76
- },
77
- };
78
- }