@nebula-spatial/viewer 0.4.3 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export type { Disposable, ToolbarItem, ViewerState, ViewerInteractionHooks, View
5
5
  export { configureViewerText } from './cad/text';
6
6
  export type { ViewerTextBuilderOptions } from './cad/text';
7
7
  export type { CadBlockModel, CadDocumentHandle, CadDocumentUnits, CadFontResolver, CadFontRequest, CadResolvedFont, CadResolvedTextFont, CadTextWarmupOptions, CadHudModel, CadHudSnapshot, CadInspectorModel, CadInspectorSnapshot, CadLayerModel, CadLayerRow, CadBlockUsageRow, CadSessionPhase, CadWorldBounds, CadScaleRulerState, CadInsertDetails, CadInsertSelection, CadInsertSelectionId, CadTextDetails, CadTextSelection, CadTextSelectionId, CadSelection, CadHit, CadViewerSnapshot, CadLoadProgress, CadViewerErrorCode, CadViewerErrorEvent, CadLoadSource, CadOpenOptions, CadSessionLoadTiming, RenderDebugBreakdownEntry, SplitBlockLayerDetail, CadViewerCapability, ResolveTextFont, CadViewerEventMap, CameraStateStore, Viewer, ViewerEventMap, ViewerEnvironment, ViewerFitViewOptions, ViewerHighlightOptions, ViewerOptions, ViewerPickOptions, ViewerPickResult, ViewerPointerEvent, ViewerObjectOptions, ViewerCameraSnapshot, ViewerOrthographicSnapshot, ViewerOrbitSnapshot, ViewerRenderStats, ViewerDocumentRect, ViewerCadUiKeyboardOptions, ViewerUiOptions, ViewerCadUiParts, ViewerCadUiOptions, ViewerUiPreset, ViewerCadUiStateStore, ViewerUiTheme, ViewerViewMode, CadInteractionMode, CameraChangeReason, ViewerUiTokens, } from './types';
8
+ export type { AssetInspection, UrdfEntityKind, UrdfInspection, UrdfInspectionEntity, UrdfInspectionIssue, UrdfInspectionJoint, UrdfInspectionLink, UrdfInspectionMode, UrdfInspectionNode, UrdfInspectionOverlays, UrdfInspectionRobot, UrdfInspectionSnapshot, UrdfSourceRange } from './inspection/types';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { c as o } from "./index-BDo6voB2.js";
1
+ import { c as o } from "./index-D-o1ODOX.js";
2
2
  import { configureCadTextBuilder as t } from "@nebula-spatial/cad-loader";
3
3
  export {
4
4
  t as configureViewerText,
@@ -0,0 +1,99 @@
1
+ export type UrdfEntityKind = 'robot' | 'link' | 'joint';
2
+ export interface UrdfSourceRange {
3
+ readonly file: string;
4
+ readonly startOffset: number;
5
+ readonly endOffset: number;
6
+ readonly startLine: number;
7
+ readonly startColumn: number;
8
+ readonly endLine: number;
9
+ readonly endColumn: number;
10
+ }
11
+ export interface UrdfInspectionEntity {
12
+ readonly id: string;
13
+ readonly kind: UrdfEntityKind;
14
+ readonly name: string;
15
+ readonly parentId?: string;
16
+ readonly childIds: readonly string[];
17
+ readonly source?: UrdfSourceRange;
18
+ }
19
+ export interface UrdfInspectionLink extends UrdfInspectionEntity {
20
+ readonly kind: 'link';
21
+ readonly mass?: number;
22
+ readonly centerOfMass?: readonly number[];
23
+ readonly inertiaTensor?: readonly number[];
24
+ readonly inertiaMass?: number;
25
+ readonly visualCount: number;
26
+ readonly collisionCount: number;
27
+ }
28
+ export interface UrdfInspectionJoint extends UrdfInspectionEntity {
29
+ readonly kind: 'joint';
30
+ readonly jointType: string;
31
+ readonly parentLink: string;
32
+ readonly childLink: string;
33
+ readonly axis: readonly number[];
34
+ readonly originPosition: readonly number[];
35
+ readonly originRotationRpy: readonly number[];
36
+ readonly limits?: {
37
+ readonly lower: number;
38
+ readonly upper: number;
39
+ };
40
+ readonly effort?: number;
41
+ readonly velocity?: number;
42
+ readonly movable: boolean;
43
+ }
44
+ export interface UrdfInspectionRobot extends UrdfInspectionEntity {
45
+ readonly kind: 'robot';
46
+ readonly rootLinkIds: readonly string[];
47
+ }
48
+ export type UrdfInspectionNode = UrdfInspectionRobot | UrdfInspectionLink | UrdfInspectionJoint;
49
+ export interface UrdfInspectionIssue {
50
+ readonly id: string;
51
+ readonly ruleId: string;
52
+ readonly severity: 'error';
53
+ readonly title: string;
54
+ readonly message: string;
55
+ readonly entityId: string;
56
+ readonly source?: UrdfSourceRange;
57
+ readonly values?: Readonly<Record<string, unknown>>;
58
+ }
59
+ export interface UrdfInspectionOverlays {
60
+ readonly collision: boolean;
61
+ readonly jointAxis: boolean;
62
+ readonly centerOfMass: boolean;
63
+ readonly inertia?: boolean;
64
+ }
65
+ export type UrdfInspectionMode = 'kinematic' | 'dynamics-initializing' | 'dynamics-paused' | 'dynamics-running' | 'dynamics-unavailable';
66
+ export interface UrdfInspectionSnapshot {
67
+ readonly revision: number;
68
+ readonly kind: 'urdf';
69
+ readonly robotName: string;
70
+ readonly sourcePath: string;
71
+ readonly sourceText: string;
72
+ readonly nodes: readonly UrdfInspectionNode[];
73
+ readonly rootEntityId: string;
74
+ readonly selectedEntityId: string | null;
75
+ readonly jointValues: Readonly<Record<string, number>>;
76
+ readonly overlays: UrdfInspectionOverlays;
77
+ readonly issues: readonly UrdfInspectionIssue[];
78
+ readonly mode: UrdfInspectionMode;
79
+ readonly dynamicsAvailable: boolean;
80
+ readonly dynamicsMessage?: string;
81
+ }
82
+ export interface UrdfInspection {
83
+ readonly kind: 'urdf';
84
+ getSnapshot(): UrdfInspectionSnapshot;
85
+ subscribe(listener: (snapshot: UrdfInspectionSnapshot) => void): () => void;
86
+ select(entityId: string | null): void;
87
+ setJointValue(jointId: string, value: number): void;
88
+ resetJoint(jointId: string): void;
89
+ resetPose(): void;
90
+ setOverlay(name: keyof UrdfInspectionOverlays, visible: boolean): void;
91
+ enterKinematicPreview(): void;
92
+ jointWorldFrame?(jointId: string): {
93
+ position: import('three').Vector3;
94
+ axis: import('three').Vector3;
95
+ } | null;
96
+ pickRoots?(): readonly import('three').Object3D[];
97
+ }
98
+ /** Tagged inspection surface. Future formats can extend this union without changing AssetPreview. */
99
+ export type AssetInspection = UrdfInspection;
@@ -1,5 +1,5 @@
1
1
  import { Group as A, Euler as C, BoxGeometry as E, SphereGeometry as F, CylinderGeometry as x, CapsuleGeometry as J, PlaneGeometry as q, MeshStandardMaterial as G, Mesh as z } from "three";
2
- import { d as S } from "./stage-BKqg5vNe.js";
2
+ import { d as S } from "./stage-D113SHD8.js";
3
3
  function v(d) {
4
4
  const f = d.extension.documents, l = new A();
5
5
  l.name = d.name;
@@ -0,0 +1,258 @@
1
+ var M = Object.defineProperty;
2
+ var O = (l, t, i) => t in l ? M(l, t, { enumerable: !0, configurable: !0, writable: !0, value: i }) : l[t] = i;
3
+ var _ = (l, t, i) => O(l, typeof t != "symbol" ? t + "" : t, i);
4
+ import I from "@mujoco/mujoco";
5
+ import T from "@mujoco/mujoco/mujoco.wasm?url";
6
+ let v = 0;
7
+ function G(l, t) {
8
+ const i = `/viewer-simulation-${++v}`;
9
+ l.mkdir(i);
10
+ const n = /* @__PURE__ */ new Set([i]), o = /* @__PURE__ */ new Set(), a = (e, s) => {
11
+ const m = e.replaceAll("\\", "/").split("/");
12
+ if (m[0] === "" || m.some((d) => d === ".." || d.includes(":"))) throw p(`Invalid package path: ${e}`, "E_SIMULATION_PATH");
13
+ const h = m.filter((d) => d && d !== ".");
14
+ if (!h.length) throw p("Package path is empty.", "E_SIMULATION_PATH");
15
+ let c = i;
16
+ for (const d of h.slice(0, -1))
17
+ c += `/${d}`, n.has(c) || (l.mkdir(c), n.add(c));
18
+ const u = `${i}/${h.join("/")}`;
19
+ return l.writeFile(u, s), o.add(u), u;
20
+ }, r = () => {
21
+ for (const e of o) l.unlink(e);
22
+ o.clear();
23
+ for (const e of [...n].reverse()) l.rmdir(e);
24
+ n.clear();
25
+ };
26
+ try {
27
+ for (const [e, s] of t) a(e, s);
28
+ return { writeEntry: (e) => a("__viewer_entry.xml", e), dispose: r };
29
+ } catch (e) {
30
+ throw r(), e;
31
+ }
32
+ }
33
+ function p(l, t) {
34
+ return Object.assign(new Error(l), { code: t });
35
+ }
36
+ function w({
37
+ target: l,
38
+ point: t,
39
+ velocity: i,
40
+ stiffness: n,
41
+ damping: o,
42
+ maxForce: a,
43
+ strength: r
44
+ }) {
45
+ const e = [
46
+ n * (l[0] - t[0]) - o * i[0],
47
+ n * (l[1] - t[1]) - o * i[1],
48
+ n * (l[2] - t[2]) - o * i[2]
49
+ ], s = Math.hypot(e[0], e[1], e[2]), m = a * r;
50
+ if (s > m && s > 0) {
51
+ const h = m / s;
52
+ e[0] *= h, e[1] *= h, e[2] *= h;
53
+ }
54
+ return e;
55
+ }
56
+ const g = 1 / 240, F = 0.05, x = 80, J = 1.15, b = 3.5, y = 14;
57
+ class S {
58
+ constructor() {
59
+ _(this, "mujoco", null);
60
+ _(this, "model", null);
61
+ _(this, "data", null);
62
+ _(this, "grab", null);
63
+ _(this, "lastGrabForce", [0, 0, 0]);
64
+ _(this, "velocityBuffer", new Float64Array(6));
65
+ _(this, "initialControls", []);
66
+ _(this, "accumulator", 0);
67
+ _(this, "initialGround", null);
68
+ _(this, "initialVelocities", []);
69
+ }
70
+ async initialize(t, i) {
71
+ var e;
72
+ this.mujoco ?? (this.mujoco = await I({ locateFile: (s) => s.endsWith(".wasm") ? i ? new URL(s, i).href : T : s }));
73
+ const n = G(this.mujoco.FS, t.files);
74
+ let o = null, a = null;
75
+ try {
76
+ o = this.mujoco.MjModel.from_xml_path(n.writeEntry(t.xml));
77
+ for (const s of t.massOverrides ?? []) {
78
+ const m = this.mujoco.mj_name2id(o, this.mujoco.mjtObj.mjOBJ_BODY.value, s.body);
79
+ if (m <= 0 || !Number.isFinite(s.mass) || s.mass <= 0 || !(o.body_mass[m] > 0)) throw new Error(`Invalid mass override: ${s.body}`);
80
+ const h = s.mass / o.body_mass[m];
81
+ o.body_mass[m] = s.mass;
82
+ for (let c = 0; c < 3; c++) o.body_inertia[m * 3 + c] *= h;
83
+ }
84
+ a = new this.mujoco.MjData(o), (e = t.massOverrides) != null && e.length && this.mujoco.mj_setConst(o, a), o.opt.timestep = g, this.applyInitialControls(a, t.initialControls), this.applyInitialVelocities(o, a, t.initialVelocities), this.mujoco.mj_forward(o, a), this.seatDefaultGround(o, a);
85
+ } catch (s) {
86
+ throw a == null || a.delete(), o == null || o.delete(), f(s, "E_MUJOCO_INITIALIZE");
87
+ } finally {
88
+ n.dispose();
89
+ }
90
+ this.disposeModel(), this.model = o, this.data = a, this.initialControls = t.initialControls ?? [], this.initialVelocities = t.initialVelocities ?? [], this.accumulator = 0;
91
+ const r = this.mujoco.mj_name2id(o, this.mujoco.mjtObj.mjOBJ_GEOM.value, "__viewer_default_ground__");
92
+ this.initialGround = r < 0 ? null : { id: r, height: o.geom_pos[r * 3 + 2], sameFrame: o.geom_sameframe[r] };
93
+ }
94
+ get defaultGroundHeight() {
95
+ if (!this.mujoco || !this.model) return;
96
+ const t = this.mujoco.mj_name2id(this.model, this.mujoco.mjtObj.mjOBJ_GEOM.value, "__viewer_default_ground__");
97
+ return t < 0 ? void 0 : this.model.geom_pos[t * 3 + 2];
98
+ }
99
+ /** Lower only the viewer-owned plane, never authored bodies or authored floors.
100
+ * Run after forward kinematics, not during stepping (the floor must not follow falling bodies).
101
+ */
102
+ seatDefaultGround(t, i) {
103
+ const n = this.mujoco, o = n.mj_name2id(t, n.mjtObj.mjOBJ_GEOM.value, "__viewer_default_ground__");
104
+ if (o < 0 || t.geom_bodyid[o] !== 0 || t.geom_type[o] !== n.mjtGeom.mjGEOM_PLANE.value) return;
105
+ let a = t.geom_pos[o * 3 + 2];
106
+ for (let r = 0; r < t.ngeom; r++) {
107
+ if (r === o || t.geom_type[r] === n.mjtGeom.mjGEOM_PLANE.value || !(t.geom_contype[r] & t.geom_conaffinity[o]) && !(t.geom_conaffinity[r] & t.geom_contype[o])) continue;
108
+ const e = r * 6, s = r * 9, m = i.geom_xmat[s + 6], h = i.geom_xmat[s + 7], c = i.geom_xmat[s + 8], u = i.geom_xpos[r * 3 + 2] + m * t.geom_aabb[e] + h * t.geom_aabb[e + 1] + c * t.geom_aabb[e + 2], d = Math.abs(m) * t.geom_aabb[e + 3] + Math.abs(h) * t.geom_aabb[e + 4] + Math.abs(c) * t.geom_aabb[e + 5], j = u - d, E = Math.max(1e-3, t.geom_margin[r] + t.geom_margin[o]);
109
+ Number.isFinite(j) && j < a && (a = Math.min(a, j - E));
110
+ }
111
+ a !== t.geom_pos[o * 3 + 2] && (t.geom_pos[o * 3 + 2] = a, t.geom_sameframe[o] = 0, n.mj_forward(t, i));
112
+ }
113
+ beginGrab({
114
+ bodyId: t,
115
+ localPoint: i,
116
+ target: n,
117
+ stiffness: o = x,
118
+ damping: a,
119
+ maxForce: r,
120
+ dampingRatio: e = J,
121
+ maxTargetSpeed: s = b,
122
+ targetResponse: m = y
123
+ }) {
124
+ var j;
125
+ const h = Math.max(((j = this.model) == null ? void 0 : j.body_mass[t]) ?? 1, 1e-3), c = a ?? 2 * Math.sqrt(o * h) * e, u = r ?? Math.max(120, h * 60), d = [n[0], n[1], n[2]];
126
+ this.grab = {
127
+ bodyId: t,
128
+ localPoint: [i[0], i[1], i[2]],
129
+ target: [...d],
130
+ requestedTarget: d,
131
+ stiffness: o,
132
+ damping: c,
133
+ maxForce: u,
134
+ strength: 1,
135
+ maxTargetSpeed: s,
136
+ targetResponse: m
137
+ };
138
+ }
139
+ updateGrabTarget(t) {
140
+ this.grab && (this.grab.requestedTarget = [t[0], t[1], t[2]]);
141
+ }
142
+ updateGrabStrength(t) {
143
+ this.grab && (this.grab.strength = t);
144
+ }
145
+ applyGrabForce() {
146
+ if (!this.grab || !this.model || !this.data || !this.mujoco) return;
147
+ const { bodyId: t, localPoint: i, target: n, stiffness: o, damping: a, maxForce: r, strength: e } = this.grab, s = this.data.xmat.subarray(t * 9, t * 9 + 9), m = this.data.xpos.subarray(t * 3, t * 3 + 3), h = [
148
+ m[0] + s[0] * i[0] + s[1] * i[1] + s[2] * i[2],
149
+ m[1] + s[3] * i[0] + s[4] * i[1] + s[5] * i[2],
150
+ m[2] + s[6] * i[0] + s[7] * i[1] + s[8] * i[2]
151
+ ];
152
+ this.mujoco.mj_objectVelocity(
153
+ this.model,
154
+ this.data,
155
+ this.mujoco.mjtObj.mjOBJ_BODY.value,
156
+ t,
157
+ this.velocityBuffer,
158
+ 0
159
+ );
160
+ const c = this.velocityBuffer, u = [
161
+ h[0] - m[0],
162
+ h[1] - m[1],
163
+ h[2] - m[2]
164
+ ], d = [
165
+ c[3] + c[1] * u[2] - c[2] * u[1],
166
+ c[4] + c[2] * u[0] - c[0] * u[2],
167
+ c[5] + c[0] * u[1] - c[1] * u[0]
168
+ ], j = w({ target: n, point: h, velocity: d, stiffness: o, damping: a, maxForce: r, strength: e });
169
+ this.lastGrabForce = [...j], this.data.qfrc_applied.fill(0), this.mujoco.mj_applyFT(
170
+ this.model,
171
+ this.data,
172
+ j,
173
+ [0, 0, 0],
174
+ h,
175
+ t,
176
+ this.data.qfrc_applied
177
+ );
178
+ }
179
+ endGrab() {
180
+ this.data && this.data.qfrc_applied.fill(0), this.lastGrabForce = [0, 0, 0], this.grab = null;
181
+ }
182
+ step(t) {
183
+ if (!this.mujoco || !this.model || !this.data || t <= 0) return !1;
184
+ this.accumulator += Math.min(t, F);
185
+ let i = !1;
186
+ for (; this.accumulator >= g; )
187
+ this.updateGrabTargetForStep(), this.applyGrabForce(), this.mujoco.mj_step(this.model, this.data), this.accumulator -= g, i = !0;
188
+ return i;
189
+ }
190
+ updateGrabTargetForStep() {
191
+ const t = this.grab;
192
+ if (!t) return;
193
+ const i = t.requestedTarget ?? t.target, n = (t.maxTargetSpeed ?? b) * Math.max(1, Math.sqrt(t.strength)), o = t.targetResponse ?? y, a = 1 - Math.exp(-o * g), r = n * g;
194
+ for (let e = 0; e < 3; e++) {
195
+ const s = i[e] - t.target[e], m = Math.sign(s) * Math.min(Math.abs(s) * a, r);
196
+ t.target[e] += m;
197
+ }
198
+ }
199
+ setJointValues(t) {
200
+ if (!(!this.mujoco || !this.model || !this.data)) {
201
+ for (const [i, n] of Object.entries(t)) {
202
+ const o = this.mujoco.mj_name2id(this.model, this.mujoco.mjtObj.mjOBJ_JOINT.value, i);
203
+ if (o < 0 || !Number.isFinite(n)) continue;
204
+ const a = this.model.jnt_type[o], r = this.mujoco.mjtJoint.mjJNT_HINGE.value, e = this.mujoco.mjtJoint.mjJNT_SLIDE.value;
205
+ a !== r && a !== e || (this.data.qpos[this.model.jnt_qposadr[o]] = n);
206
+ }
207
+ this.mujoco.mj_forward(this.model, this.data), this.seatDefaultGround(this.model, this.data), this.accumulator = 0;
208
+ }
209
+ }
210
+ getJointValues(t) {
211
+ const i = {};
212
+ if (!this.mujoco || !this.model || !this.data) return i;
213
+ for (const n of t) {
214
+ const o = this.mujoco.mj_name2id(this.model, this.mujoco.mjtObj.mjOBJ_JOINT.value, n);
215
+ if (o < 0) continue;
216
+ const a = this.model.jnt_type[o], r = this.mujoco.mjtJoint.mjJNT_HINGE.value, e = this.mujoco.mjtJoint.mjJNT_SLIDE.value;
217
+ (a === r || a === e) && (i[n] = this.data.qpos[this.model.jnt_qposadr[o]]);
218
+ }
219
+ return i;
220
+ }
221
+ reset() {
222
+ if (!(!this.mujoco || !this.model || !this.data)) {
223
+ if (this.endGrab(), this.initialGround) {
224
+ const { id: t, height: i, sameFrame: n } = this.initialGround;
225
+ this.model.geom_pos[t * 3 + 2] = i, this.model.geom_sameframe[t] = n;
226
+ }
227
+ this.mujoco.mj_resetData(this.model, this.data), this.applyInitialControls(this.data, this.initialControls), this.applyInitialVelocities(this.model, this.data, this.initialVelocities), this.mujoco.mj_forward(this.model, this.data), this.accumulator = 0;
228
+ }
229
+ }
230
+ dispose() {
231
+ this.disposeModel(), this.mujoco = null;
232
+ }
233
+ applyInitialControls(t, i) {
234
+ if (i != null && i.length) {
235
+ if (i.length !== t.ctrl.length) throw f(new Error(`Initial control count ${i.length} does not match MuJoCo actuator count ${t.ctrl.length}.`), "E_MUJOCO_INITIALIZE");
236
+ t.ctrl.set(i);
237
+ }
238
+ }
239
+ applyInitialVelocities(t, i, n) {
240
+ for (const o of n ?? []) {
241
+ const a = this.mujoco.mj_name2id(t, this.mujoco.mjtObj.mjOBJ_BODY.value, o.body), r = a >= 0 ? t.body_jntadr[a] : -1;
242
+ if (r < 0 || t.jnt_type[r] !== this.mujoco.mjtJoint.mjJNT_FREE.value || o.velocity.length !== 6 || !o.velocity.every(Number.isFinite))
243
+ throw f(new Error(`Invalid free-body initial velocity: ${o.body}`), "E_MUJOCO_INITIALIZE");
244
+ i.qvel.set(o.velocity, t.jnt_dofadr[r]);
245
+ }
246
+ }
247
+ disposeModel() {
248
+ var t, i;
249
+ this.endGrab(), (t = this.data) == null || t.delete(), (i = this.model) == null || i.delete(), this.data = null, this.model = null, this.initialGround = null, this.initialControls = [], this.initialVelocities = [], this.accumulator = 0;
250
+ }
251
+ }
252
+ function f(l, t) {
253
+ const i = l instanceof Error ? l : new Error(String(l));
254
+ return Object.assign(i, { code: t });
255
+ }
256
+ export {
257
+ S as MujocoRuntime
258
+ };
package/dist/plugins.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { Box3, Object3D } from 'three';
2
2
  import type { CadHit, CadSelection, CadViewerSnapshot, CadViewerEventMap } from './cad/types';
3
3
  import type { ViewerEventMap, ViewerViewMode, ViewerUiTheme } from './types';
4
4
  import type { AssetControlState, AssetLoaderContribution, AssetPreviewSnapshot, AssetUpAxis } from './assets/types';
5
+ import type { AssetInspection } from './inspection/types';
5
6
  export interface Disposable {
6
7
  dispose(): void;
7
8
  }
@@ -27,6 +28,7 @@ export interface ViewerAssetReadApi {
27
28
  $read(): AssetPreviewSnapshot | null;
28
29
  /** Authoritative control state, safe to bind button pressed states to. */
29
30
  $readControl(): AssetControlState;
31
+ $inspection(): AssetInspection | null;
30
32
  }
31
33
  export interface ViewerPluginContext {
32
34
  readonly cad: {
@@ -112,6 +114,7 @@ type SnapshotReader = () => CadViewerSnapshot;
112
114
  type StateReader = () => ViewerState;
113
115
  type AssetReader = () => AssetPreviewSnapshot | null;
114
116
  type ControlStateReader = () => AssetControlState;
117
+ type InspectionReader = () => AssetInspection | null;
115
118
  type PluginEventMap = ViewerEventMap & CadViewerEventMap;
116
119
  type EventSubscriber = <K extends keyof PluginEventMap>(type: K, listener: (event: PluginEventMap[K]) => void) => () => void;
117
120
  type CommandApi = ViewerPluginContext['commands'];
@@ -137,6 +140,7 @@ export declare class ViewerPluginManager implements ViewerPluginRegistry {
137
140
  private readonly commands;
138
141
  private readonly hostElement;
139
142
  private readonly layout;
143
+ private readonly readInspection;
140
144
  private readonly pluginsById;
141
145
  private readonly contributions;
142
146
  private readonly commandContributions;
@@ -144,7 +148,7 @@ export declare class ViewerPluginManager implements ViewerPluginRegistry {
144
148
  private readonly contributionRemovedListeners;
145
149
  private refreshingInspectors;
146
150
  private disposed;
147
- constructor(readCad: SnapshotReader, readState: StateReader, readAsset: AssetReader, readControlState: ControlStateReader, subscribe: EventSubscriber, commands: CommandApi, hostElement: HTMLElement, layout?: PluginLayoutPort | null);
151
+ constructor(readCad: SnapshotReader, readState: StateReader, readAsset: AssetReader, readControlState: ControlStateReader, subscribe: EventSubscriber, commands: CommandApi, hostElement: HTMLElement, layout?: PluginLayoutPort | null, readInspection?: InspectionReader);
148
152
  register(plugin: ViewerPlugin): Disposable;
149
153
  use(plugins: readonly ViewerPlugin[], options?: {
150
154
  replace?: boolean;