@viamrobotics/motion-tools 1.13.0 → 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 (83) 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 +1 -5
  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} +8 -13
  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/StaticGeometries.svelte +1 -1
  33. package/dist/components/overlay/AddRelationship.svelte +1 -1
  34. package/dist/components/overlay/LiveUpdatesBanner.svelte +4 -6
  35. package/dist/components/overlay/settings/Settings.svelte +11 -13
  36. package/dist/components/overlay/widgets/Camera.svelte +11 -9
  37. package/dist/components/xr/ArmTeleop.svelte +33 -33
  38. package/dist/components/xr/CameraFeed.svelte +21 -23
  39. package/dist/components/xr/JointLimitsWidget.svelte +19 -5
  40. package/dist/components/xr/XRConfigPanel.svelte +17 -16
  41. package/dist/components/xr/XRControllerSettings.svelte +5 -4
  42. package/dist/components/xr/XRToast.svelte +11 -6
  43. package/dist/ecs/relations.d.ts +1 -0
  44. package/dist/ecs/relations.js +1 -0
  45. package/dist/ecs/useQuery.svelte.js +3 -3
  46. package/dist/format.js +1 -1
  47. package/dist/hooks/use3DModels.svelte.js +35 -35
  48. package/dist/hooks/useConfigFrames.svelte.js +2 -7
  49. package/dist/hooks/useDrawAPI.svelte.js +1 -1
  50. package/dist/hooks/useFramelessComponents.svelte.js +1 -1
  51. package/dist/hooks/useFrames.svelte.js +63 -56
  52. package/dist/hooks/useGeometries.svelte.js +1 -1
  53. package/dist/hooks/useLinked.svelte.js +5 -4
  54. package/dist/hooks/usePartConfig.svelte.js +16 -17
  55. package/dist/hooks/usePointcloudObjects.svelte.js +4 -4
  56. package/dist/hooks/usePointclouds.svelte.js +2 -4
  57. package/dist/hooks/usePose.svelte.js +3 -7
  58. package/dist/hooks/useResizable.svelte.js +4 -3
  59. package/dist/hooks/useSettings.svelte.js +2 -2
  60. package/dist/hooks/useWeblabs.svelte.js +3 -2
  61. package/dist/hooks/useWorldState.svelte.js +6 -3
  62. package/dist/loaders/pcd/index.js +2 -1
  63. package/dist/loaders/pcd/worker.inline.d.ts +1 -1
  64. package/dist/loaders/pcd/worker.inline.js +1 -1
  65. package/dist/loaders/pcd/worker.js +1 -1
  66. package/dist/snapshot.js +7 -5
  67. package/dist/three/InstancedArrows/InstancedArrows.js +1 -1
  68. package/dist/three/InstancedArrows/box.js +1 -1
  69. package/dist/three/InstancedArrows/raycast.js +12 -12
  70. package/package.json +19 -11
  71. /package/dist/components/{Arrows → Entities/Arrows}/ArrowGroups.svelte.d.ts +0 -0
  72. /package/dist/components/{Entities.svelte.d.ts → Entities/Entities.svelte.d.ts} +0 -0
  73. /package/dist/components/{Frame.svelte.d.ts → Entities/Frame.svelte.d.ts} +0 -0
  74. /package/dist/components/{GLTF.svelte.d.ts → Entities/GLTF.svelte.d.ts} +0 -0
  75. /package/dist/components/{Geometry.svelte.d.ts → Entities/Geometry.svelte.d.ts} +0 -0
  76. /package/dist/components/{Label.svelte.d.ts → Entities/Label.svelte.d.ts} +0 -0
  77. /package/dist/components/{Line.svelte.d.ts → Entities/Line.svelte.d.ts} +0 -0
  78. /package/dist/components/{LineDots.svelte → Entities/LineDots.svelte} +0 -0
  79. /package/dist/components/{LineDots.svelte.d.ts → Entities/LineDots.svelte.d.ts} +0 -0
  80. /package/dist/components/{LineGeometry.svelte → Entities/LineGeometry.svelte} +0 -0
  81. /package/dist/components/{LineGeometry.svelte.d.ts → Entities/LineGeometry.svelte.d.ts} +0 -0
  82. /package/dist/components/{Points.svelte.d.ts → Entities/Points.svelte.d.ts} +0 -0
  83. /package/dist/components/{Pose.svelte.d.ts → Entities/Pose.svelte.d.ts} +0 -0
@@ -132,7 +132,8 @@
132
132
  const iconCenterX = accentBarWidth + 30
133
133
  const textStartX = accentBarWidth + 56
134
134
 
135
- toasts.forEach((toast, index) => {
135
+ let index = 0
136
+ for (const toast of toasts) {
136
137
  const y = index * (TOAST_HEIGHT + TOAST_GAP)
137
138
  const style = VARIANT_STYLES[toast.variant]
138
139
 
@@ -165,7 +166,9 @@
165
166
  ctx.font = '28px sans-serif'
166
167
  ctx.textBaseline = 'middle'
167
168
  ctx.fillText(toast.message, textStartX, y + TOAST_HEIGHT / 2)
168
- })
169
+
170
+ index += 1
171
+ }
169
172
 
170
173
  texture.needsUpdate = true
171
174
  }
@@ -189,12 +192,14 @@
189
192
  renderToasts(toasts)
190
193
  })
191
194
 
195
+ const dispose = () => {
196
+ texture.dispose()
197
+ untrack(() => geometry?.dispose())
198
+ }
199
+
192
200
  // Cleanup
193
201
  $effect(() => {
194
- return () => {
195
- texture.dispose()
196
- untrack(() => geometry?.dispose())
197
- }
202
+ return dispose
198
203
  })
199
204
  </script>
200
205
 
@@ -1,3 +1,4 @@
1
+ export declare const ChildOf: import("koota").Relation<import("koota").Trait<Record<string, never>>>;
1
2
  export declare const SubEntityLinkType: {
2
3
  readonly HoverLink: "HoverLink";
3
4
  };
@@ -1,4 +1,5 @@
1
1
  import { relation } from 'koota';
2
+ export const ChildOf = relation({ exclusive: true });
2
3
  export const SubEntityLinkType = {
3
4
  HoverLink: 'HoverLink',
4
5
  };
@@ -31,11 +31,11 @@ export function useQuery(...parameters) {
31
31
  };
32
32
  });
33
33
  });
34
+ const handler = () => {
35
+ version += 1;
36
+ };
34
37
  // Force reattaching event listeners when the world is reset.
35
38
  $effect(() => {
36
- const handler = () => {
37
- version += 1;
38
- };
39
39
  world[internal].resetSubscriptions.add(handler);
40
40
  return () => {
41
41
  world[internal].resetSubscriptions.delete(handler);
package/dist/format.js CHANGED
@@ -2,7 +2,7 @@ export const formatNumeric = (value, decimals = 2) => {
2
2
  if (value === undefined) {
3
3
  return '––';
4
4
  }
5
- if (isNaN(value)) {
5
+ if (Number.isNaN(value)) {
6
6
  return 'NaN';
7
7
  }
8
8
  if (value === Number.POSITIVE_INFINITY) {
@@ -18,45 +18,45 @@ export const provide3DModels = (partID) => {
18
18
  const clients = $derived(armClients.filter((client) => {
19
19
  return arms.current.some((arm) => arm.name === client.current?.name);
20
20
  }));
21
- $effect(() => {
22
- const fetch3DModels = async () => {
23
- const next = {};
24
- for (const client of clients) {
25
- if (!client.current)
21
+ const fetch3DModels = async () => {
22
+ const next = {};
23
+ for (const client of clients) {
24
+ if (!client.current)
25
+ continue;
26
+ try {
27
+ const geometries = await client.current.getGeometries();
28
+ if (geometries.length === 0) {
26
29
  continue;
27
- try {
28
- const geometries = await client.current.getGeometries();
29
- if (geometries.length === 0) {
30
- continue;
31
- }
32
- const geometryLabel = geometries[0].label;
33
- const prefix = geometryLabel.split(':')[0];
34
- const models = await client.current.get3DModels();
35
- if (!(prefix in next)) {
36
- next[prefix] = {};
37
- }
38
- for (const [id, model] of Object.entries(models)) {
39
- const arrayBuffer = model.mesh.buffer.slice(model.mesh.byteOffset, model.mesh.byteOffset + model.mesh.byteLength);
40
- const gltfModel = await gltfLoader.parseAsync(arrayBuffer, '');
41
- next[prefix][id] = gltfModel.scene;
42
- gltfModel.scene.traverse((object) => {
43
- if (isInstanceOf(object, 'Mesh')) {
44
- const { material } = object;
45
- if (isInstanceOf(material, 'MeshStandardMaterial')) {
46
- material.roughness = 0.3;
47
- material.metalness = 0.1;
48
- }
49
- }
50
- });
51
- }
52
- current = next;
53
30
  }
54
- catch (error) {
55
- // some arms may not implement this api yet
56
- console.warn(`${client.current.name} returned an error: ${error} when getting 3D models`);
31
+ const geometryLabel = geometries[0].label;
32
+ const prefix = geometryLabel.split(':')[0];
33
+ const models = await client.current.get3DModels();
34
+ if (!(prefix in next)) {
35
+ next[prefix] = {};
36
+ }
37
+ for (const [id, model] of Object.entries(models)) {
38
+ const arrayBuffer = model.mesh.buffer.slice(model.mesh.byteOffset, model.mesh.byteOffset + model.mesh.byteLength);
39
+ const gltfModel = await gltfLoader.parseAsync(arrayBuffer, '');
40
+ next[prefix][id] = gltfModel.scene;
41
+ gltfModel.scene.traverse((object) => {
42
+ if (isInstanceOf(object, 'Mesh')) {
43
+ const { material } = object;
44
+ if (isInstanceOf(material, 'MeshStandardMaterial')) {
45
+ material.roughness = 0.3;
46
+ material.metalness = 0.1;
47
+ }
48
+ }
49
+ });
57
50
  }
51
+ current = next;
58
52
  }
59
- };
53
+ catch (error) {
54
+ // some arms may not implement this api yet
55
+ console.warn(`${client.current.name} returned an error: ${error} when getting 3D models`);
56
+ }
57
+ }
58
+ };
59
+ $effect(() => {
60
60
  const shouldFetchModels = settings.current.isLoaded &&
61
61
  (settings.current.renderArmModels === 'model' ||
62
62
  settings.current.renderArmModels === 'colliders+model');
@@ -8,12 +8,7 @@ export const provideConfigFrames = () => {
8
8
  const environment = useEnvironment();
9
9
  const partConfig = usePartConfig();
10
10
  $effect(() => {
11
- if (partConfig.isDirty) {
12
- environment.current.viewerMode = 'edit';
13
- }
14
- else {
15
- environment.current.viewerMode = 'monitor';
16
- }
11
+ environment.current.viewerMode = partConfig.isDirty ? 'edit' : 'monitor';
17
12
  });
18
13
  const [configFrames, configUnsetFrameNames] = $derived.by(() => {
19
14
  const { components } = partConfig.current;
@@ -74,7 +69,7 @@ export const provideConfigFrames = () => {
74
69
  }
75
70
  }
76
71
  }
77
- return Array.from(validFrames);
72
+ return [...validFrames];
78
73
  };
79
74
  const unsetFrames = $derived([...new Set([...configUnsetFrameNames, ...fragmentUnsetFrameNames])]);
80
75
  setContext(key, {
@@ -39,7 +39,7 @@ const tryParse = (json) => {
39
39
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
40
  const lowercaseKeys = (obj) => {
41
41
  if (Array.isArray(obj)) {
42
- return obj.map(lowercaseKeys);
42
+ return obj.map((item) => lowercaseKeys(item));
43
43
  }
44
44
  else if (obj && typeof obj === 'object' && obj.constructor === Object) {
45
45
  return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k.toLowerCase(), lowercaseKeys(v)]));
@@ -12,7 +12,7 @@ export const provideFramelessComponents = () => {
12
12
  .map((component) => component.name) ?? [];
13
13
  const fragmentComponentsWithNoFrame = [];
14
14
  for (const fragmentComponentName of Object.keys(partConfig.componentNameToFragmentId)) {
15
- if (frames.current.find((frame) => frame.referenceFrame === fragmentComponentName)) {
15
+ if (frames.current.some((frame) => frame.referenceFrame === fragmentComponentName)) {
16
16
  continue;
17
17
  }
18
18
  fragmentComponentsWithNoFrame.push(fragmentComponentName);
@@ -1,6 +1,7 @@
1
1
  import { getContext, setContext, untrack } from 'svelte';
2
2
  import { MachineConnectionEvent, Transform } from '@viamrobotics/sdk';
3
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
7
  import { useEnvironment } from './useEnvironment.svelte';
@@ -68,72 +69,78 @@ export const provideFrames = (partID) => {
68
69
  }
69
70
  });
70
71
  $effect.pre(() => {
71
- for (const frame of current) {
72
- if (frame === undefined) {
73
- continue;
74
- }
75
- const name = frame.referenceFrame;
76
- const parent = frame.poseInObserverFrame?.referenceFrame;
77
- const pose = createPose(frame.poseInObserverFrame?.pose);
78
- const center = frame.physicalObject?.center
79
- ? createPose(frame.physicalObject.center)
80
- : undefined;
81
- const resourceName = resourceByName.current[frame.referenceFrame];
82
- const color = resourceNameToColor(resourceName);
83
- const existing = entities.get(name);
84
- if (existing) {
85
- if (!parent || parent === 'world') {
86
- existing.remove(traits.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;
87
112
  }
88
- else if (parent && existing.has(traits.Parent)) {
89
- existing.set(traits.Parent, parent);
90
- }
91
- else {
92
- 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));
93
122
  }
94
123
  if (color) {
95
- existing.set(traits.Color, color);
124
+ entityTraits.push(traits.Color(color));
96
125
  }
97
126
  if (center) {
98
- existing.set(traits.Center, center);
127
+ entityTraits.push(traits.Center(center));
99
128
  }
100
- existing.remove(traits.Box, traits.Sphere, traits.BufferGeometry, traits.Capsule);
101
129
  if (frame.physicalObject) {
102
- const geometry = traits.Geometry(frame.physicalObject);
103
- existing.add(geometry);
130
+ entityTraits.push(traits.Geometry(frame.physicalObject));
104
131
  }
105
- existing.set(traits.EditedPose, pose);
106
- continue;
107
- }
108
- const entityTraits = [
109
- traits.Name(name),
110
- traits.Pose(pose),
111
- traits.EditedPose(pose),
112
- traits.FramesAPI,
113
- traits.ShowAxesHelper,
114
- ];
115
- if (parent && parent !== 'world') {
116
- entityTraits.push(traits.Parent(parent));
132
+ const entity = world.spawn(...entityTraits);
133
+ entities.set(name, entity);
117
134
  }
118
- if (color) {
119
- entityTraits.push(traits.Color(color));
120
- }
121
- if (center) {
122
- entityTraits.push(traits.Center(center));
123
- }
124
- if (frame.physicalObject) {
125
- entityTraits.push(traits.Geometry(frame.physicalObject));
126
- }
127
- const entity = world.spawn(...entityTraits);
128
- entities.set(name, entity);
129
- }
130
- // Clean up non-active entities
131
- for (const [name, entity] of entities) {
132
- if (!frames[name]) {
133
- entity?.destroy();
134
- entities.delete(name);
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;
141
+ }
135
142
  }
136
- }
143
+ });
137
144
  });
138
145
  setContext(key, {
139
146
  get current() {
@@ -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) => {
@@ -127,11 +127,10 @@ export const providePartConfig = (partID, params) => {
127
127
  const deletePartFrame = (componentName) => {
128
128
  const newConfig = getCurrent();
129
129
  const component = newConfig?.components?.find(({ name }) => name === componentName);
130
- if (!component) {
131
- return;
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
  },
@@ -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
  };