@viamrobotics/motion-tools 1.12.3 → 1.13.1

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 (95) hide show
  1. package/dist/FrameConfigUpdater.svelte.js +1 -1
  2. package/dist/WorldObject.svelte.js +26 -13
  3. package/dist/buf/draw/v1/service_connect.d.ts +14 -25
  4. package/dist/buf/draw/v1/service_connect.js +14 -25
  5. package/dist/buf/draw/v1/service_pb.d.ts +61 -76
  6. package/dist/buf/draw/v1/service_pb.js +58 -111
  7. package/dist/color.js +3 -3
  8. package/dist/components/App.svelte +5 -6
  9. package/dist/components/Camera.svelte +1 -7
  10. package/dist/components/Camera.svelte.d.ts +0 -1
  11. package/dist/components/CameraControls.svelte +2 -2
  12. package/dist/components/{Arrows → Entities/Arrows}/ArrowGroups.svelte +3 -3
  13. package/dist/components/{Arrows → Entities/Arrows}/Arrows.svelte +6 -6
  14. package/dist/components/{Arrows → Entities/Arrows}/Arrows.svelte.d.ts +1 -1
  15. package/dist/components/{Entities.svelte → Entities/Entities.svelte} +5 -1
  16. package/dist/components/{Frame.svelte → Entities/Frame.svelte} +8 -8
  17. package/dist/components/{GLTF.svelte → Entities/GLTF.svelte} +5 -5
  18. package/dist/components/{Geometry.svelte → Entities/Geometry.svelte} +48 -53
  19. package/dist/components/{Label.svelte → Entities/Label.svelte} +1 -1
  20. package/dist/components/{Line.svelte → Entities/Line.svelte} +2 -2
  21. package/dist/components/{Points.svelte → Entities/Points.svelte} +5 -5
  22. package/dist/components/{Pose.svelte → Entities/Pose.svelte} +3 -3
  23. package/dist/{hooks/useObjectEvents.svelte.d.ts → components/Entities/hooks/useEntityEvents.svelte.d.ts} +1 -1
  24. package/dist/{hooks/useObjectEvents.svelte.js → components/Entities/hooks/useEntityEvents.svelte.js} +6 -6
  25. package/dist/components/FileDrop/file-names.js +6 -3
  26. package/dist/components/FileDrop/snapshot-dropper.js +8 -4
  27. package/dist/components/FileDrop/useFileDrop.svelte.js +9 -6
  28. package/dist/components/Lasso/Lasso.svelte +4 -4
  29. package/dist/components/PCD.svelte +14 -6
  30. package/dist/components/PCD.svelte.d.ts +2 -0
  31. package/dist/components/Scene.svelte +1 -3
  32. package/dist/components/SceneProviders.svelte +2 -0
  33. package/dist/components/Selected.svelte +9 -9
  34. package/dist/components/StaticGeometries.svelte +6 -3
  35. package/dist/components/overlay/AddRelationship.svelte +1 -1
  36. package/dist/components/overlay/Details.svelte +3 -3
  37. package/dist/components/overlay/FloatingPanel.svelte +3 -0
  38. package/dist/components/overlay/FloatingPanel.svelte.d.ts +1 -0
  39. package/dist/components/overlay/LiveUpdatesBanner.svelte +4 -6
  40. package/dist/components/overlay/Logs.svelte +75 -0
  41. package/dist/components/overlay/left-pane/TreeContainer.svelte +0 -3
  42. package/dist/components/overlay/settings/Settings.svelte +11 -13
  43. package/dist/components/overlay/widgets/Camera.svelte +11 -9
  44. package/dist/components/xr/ArmTeleop.svelte +33 -33
  45. package/dist/components/xr/CameraFeed.svelte +21 -23
  46. package/dist/components/xr/JointLimitsWidget.svelte +19 -5
  47. package/dist/components/xr/XRConfigPanel.svelte +17 -16
  48. package/dist/components/xr/XRControllerSettings.svelte +5 -4
  49. package/dist/components/xr/XRToast.svelte +11 -6
  50. package/dist/ecs/relations.d.ts +1 -0
  51. package/dist/ecs/relations.js +1 -0
  52. package/dist/ecs/useQuery.svelte.js +3 -3
  53. package/dist/format.js +1 -1
  54. package/dist/hooks/use3DModels.svelte.js +35 -36
  55. package/dist/hooks/useConfigFrames.svelte.d.ts +9 -0
  56. package/dist/hooks/useConfigFrames.svelte.js +87 -0
  57. package/dist/hooks/useDrawAPI.svelte.js +1 -1
  58. package/dist/hooks/useFramelessComponents.svelte.js +1 -1
  59. package/dist/hooks/useFrames.svelte.d.ts +1 -6
  60. package/dist/hooks/useFrames.svelte.js +93 -192
  61. package/dist/hooks/useGeometries.svelte.js +1 -1
  62. package/dist/hooks/useLinked.svelte.js +5 -4
  63. package/dist/hooks/usePartConfig.svelte.js +17 -18
  64. package/dist/hooks/usePointcloudObjects.svelte.js +4 -4
  65. package/dist/hooks/usePointclouds.svelte.js +2 -4
  66. package/dist/hooks/usePose.svelte.js +3 -7
  67. package/dist/hooks/useResizable.svelte.js +4 -3
  68. package/dist/hooks/useSettings.svelte.js +2 -2
  69. package/dist/hooks/useVisibility.svelte.js +0 -12
  70. package/dist/hooks/useWeblabs.svelte.js +3 -2
  71. package/dist/hooks/useWorldState.svelte.js +6 -3
  72. package/dist/loaders/pcd/index.js +2 -1
  73. package/dist/loaders/pcd/worker.inline.d.ts +1 -1
  74. package/dist/loaders/pcd/worker.inline.js +1 -1
  75. package/dist/loaders/pcd/worker.js +1 -1
  76. package/dist/snapshot.js +7 -5
  77. package/dist/three/InstancedArrows/InstancedArrows.js +1 -1
  78. package/dist/three/InstancedArrows/box.js +1 -1
  79. package/dist/three/InstancedArrows/raycast.js +12 -12
  80. package/package.json +19 -11
  81. package/dist/components/overlay/left-pane/Logs.svelte +0 -52
  82. /package/dist/components/{Arrows → Entities/Arrows}/ArrowGroups.svelte.d.ts +0 -0
  83. /package/dist/components/{Entities.svelte.d.ts → Entities/Entities.svelte.d.ts} +0 -0
  84. /package/dist/components/{Frame.svelte.d.ts → Entities/Frame.svelte.d.ts} +0 -0
  85. /package/dist/components/{GLTF.svelte.d.ts → Entities/GLTF.svelte.d.ts} +0 -0
  86. /package/dist/components/{Geometry.svelte.d.ts → Entities/Geometry.svelte.d.ts} +0 -0
  87. /package/dist/components/{Label.svelte.d.ts → Entities/Label.svelte.d.ts} +0 -0
  88. /package/dist/components/{Line.svelte.d.ts → Entities/Line.svelte.d.ts} +0 -0
  89. /package/dist/components/{LineDots.svelte → Entities/LineDots.svelte} +0 -0
  90. /package/dist/components/{LineDots.svelte.d.ts → Entities/LineDots.svelte.d.ts} +0 -0
  91. /package/dist/components/{LineGeometry.svelte → Entities/LineGeometry.svelte} +0 -0
  92. /package/dist/components/{LineGeometry.svelte.d.ts → Entities/LineGeometry.svelte.d.ts} +0 -0
  93. /package/dist/components/{Points.svelte.d.ts → Entities/Points.svelte.d.ts} +0 -0
  94. /package/dist/components/{Pose.svelte.d.ts → Entities/Pose.svelte.d.ts} +0 -0
  95. /package/dist/components/overlay/{left-pane/Logs.svelte.d.ts → Logs.svelte.d.ts} +0 -0
@@ -1,11 +1,6 @@
1
1
  import { Transform } from '@viamrobotics/sdk';
2
- interface FrameTransform {
3
- type: 'machine' | 'config' | 'fragment';
4
- transform: Transform;
5
- }
6
2
  interface FramesContext {
7
- current: FrameTransform[];
8
- getParentFrameOptions: (componentName: string) => string[];
3
+ current: Transform[];
9
4
  }
10
5
  export declare const provideFrames: (partID: () => string) => void;
11
6
  export declare const useFrames: () => FramesContext;
@@ -1,27 +1,29 @@
1
1
  import { getContext, setContext, untrack } from 'svelte';
2
- import { Transform } from '@viamrobotics/sdk';
3
- import { useRobotClient, createRobotQuery, useMachineStatus } from '@viamrobotics/svelte-sdk';
2
+ import { MachineConnectionEvent, Transform } from '@viamrobotics/sdk';
3
+ import { useRobotClient, createRobotQuery, useMachineStatus, useConnectionStatus, } from '@viamrobotics/svelte-sdk';
4
+ import {} from 'koota';
4
5
  import { useLogs } from './useLogs.svelte';
5
6
  import { resourceNameToColor } from '../color';
6
- import { createTransformFromFrame } from '../frame';
7
- import { usePartConfig } from './usePartConfig.svelte';
8
7
  import { useEnvironment } from './useEnvironment.svelte';
9
8
  import { createPose } from '../transform';
10
9
  import { useResourceByName } from './useResourceByName.svelte';
11
10
  import { traits, useWorld } from '../ecs';
11
+ import { useConfigFrames } from './useConfigFrames.svelte';
12
12
  const key = Symbol('frames-context');
13
13
  export const provideFrames = (partID) => {
14
+ const configFrames = useConfigFrames();
14
15
  const environment = useEnvironment();
15
16
  const world = useWorld();
16
17
  const resourceByName = useResourceByName();
17
18
  const client = useRobotClient(partID);
19
+ const connectionStatus = useConnectionStatus(partID);
18
20
  const machineStatus = useMachineStatus(partID);
19
21
  const logs = useLogs();
22
+ const isEditMode = $derived(environment.current.viewerMode === 'edit');
20
23
  const query = createRobotQuery(client, 'frameSystemConfig', () => ({
21
- enabled: partID() !== '' && environment.current.viewerMode === 'monitor',
24
+ enabled: partID() !== '' && !isEditMode,
22
25
  }));
23
26
  const revision = $derived(machineStatus.current?.config?.revision);
24
- const partConfig = usePartConfig();
25
27
  $effect(() => {
26
28
  if (query.isFetching) {
27
29
  logs.add('Fetching frames...');
@@ -30,218 +32,117 @@ export const provideFrames = (partID) => {
30
32
  logs.add(`Frames: ${query.error.message}`, 'error');
31
33
  }
32
34
  });
33
- $effect(() => {
34
- if (partConfig.isDirty) {
35
- environment.current.viewerMode = 'edit';
36
- }
37
- else {
38
- environment.current.viewerMode = 'monitor';
39
- }
40
- });
41
- const machineFrames = $derived.by(() => {
35
+ const frames = $derived.by(() => {
42
36
  const frames = {};
43
37
  for (const { frame } of query.data ?? []) {
44
38
  if (frame === undefined) {
45
39
  continue;
46
40
  }
47
- frames[frame.referenceFrame] = {
48
- type: 'machine',
49
- transform: frame,
50
- };
41
+ frames[frame.referenceFrame] = frame;
51
42
  }
52
- return frames;
53
- });
54
- const [configFrames, configUnsetFrameNames] = $derived.by(() => {
55
- const { components } = partConfig.current;
56
- const results = {};
57
- const unsetResults = [];
58
- for (const { name, frame } of components ?? []) {
59
- if (!frame) {
60
- unsetResults.push(name);
61
- continue;
62
- }
63
- results[name] = {
64
- type: 'config',
65
- transform: createTransformFromFrame(name, frame),
43
+ if (isEditMode || connectionStatus.current === MachineConnectionEvent.DISCONNECTED) {
44
+ const mergedFrames = {
45
+ ...frames,
46
+ ...configFrames.current,
66
47
  };
48
+ /**
49
+ * Remove frames that have just been deleted locally for optimistic updates,
50
+ * or frames that have been removed by fragment overrides
51
+ */
52
+ for (const name of configFrames.unsetFrames) {
53
+ delete mergedFrames[name];
54
+ }
55
+ return mergedFrames;
67
56
  }
68
- return [results, unsetResults];
69
- });
70
- const [fragmentFrames, fragmentUnsetFrameNames] = $derived.by(() => {
71
- const { fragment_mods: fragmentMods = [] } = partConfig.current;
72
- const fragmentDefinedComponents = Object.keys(partConfig.componentNameToFragmentId);
73
- const results = {};
74
- const unsetResults = [];
75
- // deal with fragment defined components
76
- for (const fragmentComponentName of fragmentDefinedComponents || []) {
77
- const fragmentId = partConfig.componentNameToFragmentId[fragmentComponentName];
78
- const fragmentMod = fragmentMods?.find((mod) => mod.fragment_id === fragmentId);
79
- if (!fragmentMod) {
80
- continue;
81
- }
82
- const setComponentModIndex = fragmentMod.mods.findLastIndex((mod) => mod['$set']?.[`components.${fragmentComponentName}.frame`] !== undefined);
83
- const unsetComponentModIndex = fragmentMod.mods.findLastIndex((mod) => mod['$unset']?.[`components.${fragmentComponentName}.frame`] !== undefined);
84
- if (setComponentModIndex < unsetComponentModIndex) {
85
- unsetResults.push(fragmentComponentName);
86
- }
87
- else if (unsetComponentModIndex < setComponentModIndex) {
88
- const frameData = fragmentMod.mods[setComponentModIndex]['$set'][`components.${fragmentComponentName}.frame`];
89
- results[fragmentComponentName] = {
90
- type: 'fragment',
91
- transform: createTransformFromFrame(fragmentComponentName, frameData),
92
- };
93
- }
94
- }
95
- return [results, unsetResults];
96
- });
97
- const frames = $derived.by(() => {
98
- const result = {
99
- ...machineFrames,
100
- ...configFrames,
101
- ...fragmentFrames,
102
- };
103
- // Remove frames that have just been deleted locally for optimistic updates
104
- for (const name of configUnsetFrameNames) {
105
- delete result[name];
106
- }
107
- // Remove frames that have been removed by fragment overrides
108
- for (const name of fragmentUnsetFrameNames) {
109
- delete result[name];
110
- }
111
- return result;
57
+ /**
58
+ * If we're not in edit mode and we have a robot connection,
59
+ * we only use frames reported by the machine
60
+ *
61
+ */
62
+ return frames;
112
63
  });
113
64
  const current = $derived(Object.values(frames));
114
65
  const entities = new Map();
115
66
  $effect.pre(() => {
116
67
  if (revision) {
117
- untrack(async () => {
118
- await query.refetch();
119
- for (const [name, machineFrame] of Object.entries(machineFrames)) {
120
- if (machineFrame === undefined) {
121
- continue;
122
- }
123
- const existing = entities.get(name);
124
- if (existing) {
125
- const pose = createPose(machineFrame.transform.poseInObserverFrame?.pose);
126
- existing.set(traits.Pose, pose);
127
- if (environment.current.viewerMode === 'monitor') {
128
- // if we are in monitor mode, we want the network pose to overwrite any leftover edited poses
129
- existing.set(traits.EditedPose, pose);
130
- }
131
- }
132
- }
133
- });
134
- }
135
- });
136
- $effect.pre(() => {
137
- for (const [name, configFrame] of Object.entries(configFrames)) {
138
- if (configFrame === undefined) {
139
- continue;
140
- }
141
- const existing = entities.get(name);
142
- if (existing) {
143
- const pose = createPose(configFrame.transform.poseInObserverFrame?.pose);
144
- existing.set(traits.EditedPose, pose);
145
- }
146
- }
147
- });
148
- $effect.pre(() => {
149
- for (const [name, fragmentFrame] of Object.entries(fragmentFrames)) {
150
- if (fragmentFrame === undefined) {
151
- continue;
152
- }
153
- const existing = entities.get(name);
154
- if (existing) {
155
- const pose = createPose(fragmentFrame.transform.poseInObserverFrame?.pose);
156
- existing.set(traits.EditedPose, pose);
157
- }
68
+ untrack(() => query.refetch());
158
69
  }
159
70
  });
160
71
  $effect.pre(() => {
161
- for (const frame of current) {
162
- if (frame === undefined) {
163
- continue;
164
- }
165
- const name = frame.transform.referenceFrame;
166
- const parent = frame.transform.poseInObserverFrame?.referenceFrame;
167
- const pose = createPose(frame.transform.poseInObserverFrame?.pose);
168
- const center = frame.transform.physicalObject?.center
169
- ? createPose(frame.transform.physicalObject.center)
170
- : undefined;
171
- const resourceName = resourceByName.current[frame.transform.referenceFrame];
172
- const color = resourceNameToColor(resourceName);
173
- const existing = entities.get(name);
174
- if (existing) {
175
- if (!parent || parent === 'world') {
176
- existing.remove(traits.Parent);
177
- }
178
- else if (parent && existing.has(traits.Parent)) {
179
- existing.set(traits.Parent, parent);
72
+ if (current.length === 0)
73
+ return;
74
+ const currentResourcesByName = resourceByName.current;
75
+ // We only want to update whenever "current" or "resourceByName.current" changes
76
+ untrack(() => {
77
+ const active = {};
78
+ for (const frame of current) {
79
+ const name = frame.referenceFrame;
80
+ active[name] = true;
81
+ const parent = frame.poseInObserverFrame?.referenceFrame;
82
+ const pose = createPose(frame.poseInObserverFrame?.pose);
83
+ const center = frame.physicalObject?.center
84
+ ? createPose(frame.physicalObject.center)
85
+ : undefined;
86
+ const resourceName = currentResourcesByName[frame.referenceFrame];
87
+ const color = resourceNameToColor(resourceName);
88
+ const existing = entities.get(name);
89
+ if (existing) {
90
+ if (!parent || parent === 'world') {
91
+ existing.remove(traits.Parent);
92
+ }
93
+ else if (parent && existing.has(traits.Parent)) {
94
+ existing.set(traits.Parent, parent);
95
+ }
96
+ else {
97
+ existing.add(traits.Parent(parent));
98
+ }
99
+ if (color) {
100
+ existing.set(traits.Color, color);
101
+ }
102
+ if (center) {
103
+ existing.set(traits.Center, center);
104
+ }
105
+ existing.remove(traits.Box, traits.Sphere, traits.BufferGeometry, traits.Capsule);
106
+ if (frame.physicalObject) {
107
+ const geometry = traits.Geometry(frame.physicalObject);
108
+ existing.add(geometry);
109
+ }
110
+ existing.set(traits.EditedPose, pose);
111
+ continue;
180
112
  }
181
- else {
182
- existing.add(traits.Parent(parent));
113
+ const entityTraits = [
114
+ traits.Name(name),
115
+ traits.Pose(pose),
116
+ traits.EditedPose(pose),
117
+ traits.FramesAPI,
118
+ traits.ShowAxesHelper,
119
+ ];
120
+ if (parent && parent !== 'world') {
121
+ entityTraits.push(traits.Parent(parent));
183
122
  }
184
123
  if (color) {
185
- existing.set(traits.Color, color);
124
+ entityTraits.push(traits.Color(color));
186
125
  }
187
126
  if (center) {
188
- existing.set(traits.Center, center);
127
+ entityTraits.push(traits.Center(center));
189
128
  }
190
- existing.remove(traits.Box, traits.Sphere, traits.BufferGeometry, traits.Capsule);
191
- if (frame.transform.physicalObject) {
192
- const geometry = traits.Geometry(frame.transform.physicalObject);
193
- existing.add(geometry);
129
+ if (frame.physicalObject) {
130
+ entityTraits.push(traits.Geometry(frame.physicalObject));
194
131
  }
195
- continue;
196
- }
197
- const entityTraits = [
198
- traits.Name(name),
199
- traits.Pose(pose),
200
- traits.EditedPose(pose),
201
- traits.FramesAPI,
202
- traits.ShowAxesHelper,
203
- ];
204
- if (parent && parent !== 'world') {
205
- entityTraits.push(traits.Parent(parent));
206
- }
207
- if (color) {
208
- entityTraits.push(traits.Color(color));
209
- }
210
- if (center) {
211
- entityTraits.push(traits.Center(center));
212
- }
213
- if (frame.transform.physicalObject) {
214
- entityTraits.push(traits.Geometry(frame.transform.physicalObject));
215
- }
216
- const entity = world.spawn(...entityTraits);
217
- entities.set(name, entity);
218
- }
219
- // Clean up non-active entities
220
- for (const [name, entity] of entities) {
221
- if (!frames[name]) {
222
- entity?.destroy();
223
- entities.delete(name);
224
- }
225
- }
226
- });
227
- const getParentFrameOptions = (componentName) => {
228
- const validFrames = new Set(current.map((frame) => frame.transform.referenceFrame));
229
- validFrames.add('world');
230
- const frameNameQueue = [componentName];
231
- while (frameNameQueue.length > 0) {
232
- const frameName = frameNameQueue.shift();
233
- if (frameName) {
234
- validFrames.delete(frameName);
235
- const frames = current.filter((frame) => frame.transform.poseInObserverFrame?.referenceFrame === frameName);
236
- for (const frame of frames) {
237
- frameNameQueue.push(frame.transform.referenceFrame);
132
+ const entity = world.spawn(...entityTraits);
133
+ entities.set(name, entity);
134
+ }
135
+ // Clean up non-active entities
136
+ for (const [name, entity] of entities) {
137
+ if (!active[name]) {
138
+ entity?.destroy();
139
+ entities.delete(name);
140
+ continue;
238
141
  }
239
142
  }
240
- }
241
- return Array.from(validFrames);
242
- };
143
+ });
144
+ });
243
145
  setContext(key, {
244
- getParentFrameOptions,
245
146
  get current() {
246
147
  return current;
247
148
  },
@@ -68,7 +68,7 @@ export const provideGeometries = (partID) => {
68
68
  for (const geometry of query.data) {
69
69
  index += 1;
70
70
  const resourceName = resources.current[name];
71
- const label = geometry.label ? geometry.label : `${name} geometry ${index}`;
71
+ const label = geometry.label || `${name} geometry ${index}`;
72
72
  active[`${name}:${label}`] = true;
73
73
  const pose = createPose(geometry.center);
74
74
  const subtype = resourceName?.subtype;
@@ -18,11 +18,12 @@ export const provideLinkedEntities = () => {
18
18
  linkedEntities = linkedEntities.filter((e) => e !== target);
19
19
  }
20
20
  });
21
+ const unsub = () => {
22
+ unsubAdd();
23
+ unsubRemove();
24
+ };
21
25
  $effect(() => {
22
- return () => {
23
- unsubAdd();
24
- unsubRemove();
25
- };
26
+ return unsub;
26
27
  });
27
28
  setContext(linkedKey, {
28
29
  get current() {
@@ -79,16 +79,16 @@ export const providePartConfig = (partID, params) => {
79
79
  const existingFrameIndex = fragmentMod.mods.findLastIndex(
80
80
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
81
81
  (mod) => mod?.['$set']?.[modSetPath] !== undefined);
82
- if (existingFrameIndex !== -1) {
82
+ if (existingFrameIndex === -1) {
83
+ fragmentMod.mods.push(frame);
84
+ }
85
+ else {
83
86
  const existingGeometry = fragmentMod.mods[existingFrameIndex]['$set']?.[modSetPath].geometry;
84
87
  if (existingGeometry && !frameGeometry) {
85
88
  frame['$set'][modSetPath].geometry = existingGeometry;
86
89
  }
87
90
  fragmentMod.mods[existingFrameIndex] = frame;
88
91
  }
89
- else {
90
- fragmentMod.mods.push(frame);
91
- }
92
92
  config.set(newConfig);
93
93
  };
94
94
  const updatePartFrame = (componentName, referenceFrame, pose, geometry) => {
@@ -126,12 +126,11 @@ export const providePartConfig = (partID, params) => {
126
126
  };
127
127
  const deletePartFrame = (componentName) => {
128
128
  const newConfig = getCurrent();
129
- const component = newConfig?.components?.find((comp) => comp.name === componentName);
130
- if (!component) {
131
- return;
129
+ const component = newConfig?.components?.find(({ name }) => name === componentName);
130
+ if (component) {
131
+ delete component.frame;
132
+ config.set(newConfig);
132
133
  }
133
- delete component.frame;
134
- config.set(newConfig);
135
134
  };
136
135
  const deleteFragmentFrame = (fragmentId, componentName) => {
137
136
  const newConfig = getCurrent();
@@ -168,29 +167,29 @@ export const providePartConfig = (partID, params) => {
168
167
  },
169
168
  updateFrame: (componentName, referenceFrame, framePosition, frameGeometry) => {
170
169
  const fragmentId = config.componentNameToFragmentId[componentName];
171
- if (fragmentId !== undefined) {
172
- updateFragmentFrame(fragmentId, componentName, referenceFrame, framePosition, frameGeometry);
170
+ if (fragmentId === undefined) {
171
+ updatePartFrame(componentName, referenceFrame, framePosition, frameGeometry);
173
172
  }
174
173
  else {
175
- updatePartFrame(componentName, referenceFrame, framePosition, frameGeometry);
174
+ updateFragmentFrame(fragmentId, componentName, referenceFrame, framePosition, frameGeometry);
176
175
  }
177
176
  },
178
177
  deleteFrame: (componentName) => {
179
178
  const fragmentId = config.componentNameToFragmentId[componentName];
180
- if (fragmentId !== undefined) {
181
- deleteFragmentFrame(fragmentId, componentName);
179
+ if (fragmentId === undefined) {
180
+ deletePartFrame(componentName);
182
181
  }
183
182
  else {
184
- deletePartFrame(componentName);
183
+ deleteFragmentFrame(fragmentId, componentName);
185
184
  }
186
185
  },
187
186
  createFrame: (componentName) => {
188
187
  const fragmentId = config.componentNameToFragmentId[componentName];
189
- if (fragmentId !== undefined) {
190
- createFragmentFrame(fragmentId, componentName);
188
+ if (fragmentId === undefined) {
189
+ createPartFrame(componentName);
191
190
  }
192
191
  else {
193
- createPartFrame(componentName);
192
+ createFragmentFrame(fragmentId, componentName);
194
193
  }
195
194
  },
196
195
  save: () => config.save?.(),
@@ -47,10 +47,10 @@ export const providePointcloudObjects = (partID) => {
47
47
  */
48
48
  $effect(() => {
49
49
  for (const [name, query] of propQueries) {
50
- if (name && query.data?.objectPointCloudsSupported === false) {
51
- if (disabledVisionServices.get(name) === undefined) {
52
- disabledVisionServices.set(name, true);
53
- }
50
+ if (name &&
51
+ query.data?.objectPointCloudsSupported === false &&
52
+ disabledVisionServices.get(name) === undefined) {
53
+ disabledVisionServices.set(name, true);
54
54
  }
55
55
  }
56
56
  });
@@ -50,10 +50,8 @@ export const providePointclouds = (partID) => {
50
50
  */
51
51
  $effect(() => {
52
52
  for (const [name, query] of propQueries) {
53
- if (name && query.data?.supportsPcd === false) {
54
- if (disabledCameras.get(name) === undefined) {
55
- disabledCameras.set(name, true);
56
- }
53
+ if (name && query.data?.supportsPcd === false && disabledCameras.get(name) === undefined) {
54
+ disabledCameras.set(name, true);
57
55
  }
58
56
  }
59
57
  });
@@ -10,7 +10,7 @@ import { RefetchRates } from '../components/overlay/RefreshRate.svelte';
10
10
  import { useLogs } from './useLogs.svelte';
11
11
  import { useResourceByName } from './useResourceByName.svelte';
12
12
  import { useRefetchPoses } from './useRefetchPoses';
13
- const origingFrameComponentTypes = ['arm', 'gantry', 'gripper', 'base'];
13
+ const originFrameComponentTypes = new Set(['arm', 'gantry', 'gripper', 'base']);
14
14
  export const usePose = (name, parent) => {
15
15
  const environment = useEnvironment();
16
16
  const logs = useLogs();
@@ -26,12 +26,8 @@ export const usePose = (name, parent) => {
26
26
  const frames = useFrames();
27
27
  let pose = $state();
28
28
  const interval = $derived(refreshRates.get(RefreshRates.poses));
29
- const resolvedParent = $derived(origingFrameComponentTypes.includes(parentResource?.subtype ?? '')
30
- ? `${parent()}_origin`
31
- : parent());
32
- const resolvedName = $derived(origingFrameComponentTypes.includes(resource?.subtype ?? '')
33
- ? `${currentName}_origin`
34
- : currentName);
29
+ const resolvedParent = $derived(originFrameComponentTypes.has(parentResource?.subtype ?? '') ? `${parent()}_origin` : parent());
30
+ const resolvedName = $derived(originFrameComponentTypes.has(resource?.subtype ?? '') ? `${currentName}_origin` : currentName);
35
31
  const query = createRobotQuery(robotClient, 'getPose', () => [resolvedName, resolvedParent ?? 'world', []], () => ({
36
32
  enabled: interval !== RefetchRates.OFF && environment.current.viewerMode === 'monitor',
37
33
  refetchInterval: interval === RefetchRates.MANUAL ? false : interval,
@@ -28,10 +28,11 @@ export const useResizable = (name, defaultDimensions) => {
28
28
  });
29
29
  observer.observe(target);
30
30
  };
31
+ const disconnect = () => {
32
+ observer?.disconnect();
33
+ };
31
34
  $effect(() => {
32
- return () => {
33
- observer?.disconnect();
34
- };
35
+ return disconnect;
35
36
  });
36
37
  return {
37
38
  get current() {
@@ -30,11 +30,11 @@ const defaults = () => ({
30
30
  renderSubEntityHoverDetail: false,
31
31
  xrController: {
32
32
  left: {
33
- scaleFactor: 1.0,
33
+ scaleFactor: 1,
34
34
  rotationEnabled: true,
35
35
  },
36
36
  right: {
37
- scaleFactor: 1.0,
37
+ scaleFactor: 1,
38
38
  rotationEnabled: true,
39
39
  },
40
40
  },
@@ -1,20 +1,8 @@
1
- import { get, set } from 'idb-keyval';
2
1
  import { getContext, setContext } from 'svelte';
3
2
  import { SvelteMap } from 'svelte/reactivity';
4
3
  const key = Symbol('object-visibility-context');
5
- const idbKey = 'object-visibility';
6
4
  export const provideVisibility = () => {
7
5
  const map = new SvelteMap();
8
- get(idbKey).then((entries) => {
9
- if (entries) {
10
- for (const [key, value] of entries) {
11
- map.set(key, value);
12
- }
13
- }
14
- });
15
- $effect(() => {
16
- set(idbKey, [...map.entries()]);
17
- });
18
6
  setContext(key, map);
19
7
  };
20
8
  export const useVisibility = () => {
@@ -17,6 +17,7 @@ const addCookie = (name, value, days, path = '/') => {
17
17
  date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000); // days in milliseconds
18
18
  expires = '; expires=' + date.toUTCString();
19
19
  }
20
+ // eslint-disable-next-line unicorn/no-document-cookie
20
21
  document.cookie = `${encodeURIComponent(name)}=${encodeURIComponent(value)}${expires}; path=${path}`;
21
22
  };
22
23
  const getCookieExperiments = () => {
@@ -44,10 +45,10 @@ export const createWeblabs = () => {
44
45
  };
45
46
  };
46
47
  export const provideWeblabs = () => {
47
- const urlExperiment = new URLSearchParams(window.location.search).get('experiment');
48
+ const urlExperiment = new URLSearchParams(globalThis.location.search).get('experiment');
48
49
  if (urlExperiment) {
49
50
  const experimentSet = new Set([...getCookieExperiments(), urlExperiment]);
50
- addCookie('weblab_experiments', Array.from(experimentSet).join(','));
51
+ addCookie('weblab_experiments', [...experimentSet].join(','));
51
52
  }
52
53
  setContext(WEBLABS_CONTEXT_KEY, createWeblabs());
53
54
  };
@@ -189,15 +189,17 @@ const createWorldState = (client) => {
189
189
  continue;
190
190
  }
191
191
  switch (event.changeType) {
192
- case TransformChangeType.REMOVED:
192
+ case TransformChangeType.REMOVED: {
193
193
  eventsByUUID.set(uuid, event);
194
194
  break;
195
- case TransformChangeType.ADDED:
195
+ }
196
+ case TransformChangeType.ADDED: {
196
197
  if (existing.changeType !== TransformChangeType.REMOVED) {
197
198
  eventsByUUID.set(uuid, event);
198
199
  }
199
200
  break;
200
- case TransformChangeType.UPDATED:
201
+ }
202
+ case TransformChangeType.UPDATED: {
201
203
  // merge with existing updated event
202
204
  if (existing.changeType === TransformChangeType.UPDATED) {
203
205
  existing.updatedFields ??= { paths: [] };
@@ -214,6 +216,7 @@ const createWorldState = (client) => {
214
216
  eventsByUUID.set(uuid, event);
215
217
  }
216
218
  break;
219
+ }
217
220
  }
218
221
  }
219
222
  pendingEvents.push(...eventsByUUID.values());
@@ -22,6 +22,7 @@ export const parsePcdInWorker = (data) => {
22
22
  return new Promise((resolve, reject) => {
23
23
  const id = ++requestId;
24
24
  pending.set(id, { resolve, reject });
25
- worker.postMessage({ id, data }, [data.buffer]);
25
+ const copy = new Uint8Array(data);
26
+ worker.postMessage({ id, data: copy }, [copy.buffer]);
26
27
  });
27
28
  };