@viamrobotics/motion-tools 0.11.7 → 0.12.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.
Files changed (51) hide show
  1. package/dist/WorldObject.svelte.d.ts +12 -24
  2. package/dist/WorldObject.svelte.js +1 -1
  3. package/dist/components/App.svelte +32 -25
  4. package/dist/components/Details.svelte +94 -10
  5. package/dist/components/FileDrop.svelte +5 -2
  6. package/dist/components/Geometry.svelte +86 -70
  7. package/dist/components/Geometry.svelte.d.ts +3 -3
  8. package/dist/components/Pointcloud.svelte +3 -3
  9. package/dist/components/Pointcloud.svelte.d.ts +2 -5
  10. package/dist/components/RefreshRate.svelte +11 -6
  11. package/dist/components/RefreshRate.svelte.d.ts +3 -1
  12. package/dist/components/SceneProviders.svelte +5 -1
  13. package/dist/components/StaticGeometries.svelte +2 -2
  14. package/dist/components/Tree/Settings.svelte +10 -4
  15. package/dist/components/Tree/TreeContainer.svelte +2 -0
  16. package/dist/components/Tree/Widgets.svelte +24 -0
  17. package/dist/components/Tree/Widgets.svelte.d.ts +18 -0
  18. package/dist/components/WorldObjects.svelte +9 -9
  19. package/dist/components/shared/Table.svelte +37 -0
  20. package/dist/components/shared/Table.svelte.d.ts +7 -0
  21. package/dist/components/weblab/WeblabActive.svelte +20 -0
  22. package/dist/components/weblab/WeblabActive.svelte.d.ts +8 -0
  23. package/dist/components/weblab/WeblabProvider.svelte +8 -0
  24. package/dist/components/weblab/WeblabProvider.svelte.d.ts +5 -0
  25. package/dist/components/widgets/ArmPositions.svelte +76 -0
  26. package/dist/components/widgets/ArmPositions.svelte.d.ts +3 -0
  27. package/dist/format.d.ts +1 -0
  28. package/dist/format.js +15 -0
  29. package/dist/hooks/useArmClient.svelte.d.ts +7 -0
  30. package/dist/hooks/useArmClient.svelte.js +36 -0
  31. package/dist/hooks/useArrows.svelte.d.ts +3 -0
  32. package/dist/hooks/useArrows.svelte.js +9 -0
  33. package/dist/hooks/useDrawAPI.svelte.d.ts +0 -4
  34. package/dist/hooks/useDrawAPI.svelte.js +34 -29
  35. package/dist/hooks/useFrames.svelte.js +5 -8
  36. package/dist/hooks/useGeometries.svelte.js +4 -7
  37. package/dist/hooks/useMachineSettings.svelte.d.ts +4 -0
  38. package/dist/hooks/useMachineSettings.svelte.js +8 -1
  39. package/dist/hooks/usePointclouds.svelte.js +3 -6
  40. package/dist/hooks/usePose.svelte.js +2 -2
  41. package/dist/hooks/useSettings.svelte.d.ts +1 -0
  42. package/dist/hooks/useSettings.svelte.js +1 -0
  43. package/dist/hooks/useStaticGeometries.svelte.js +1 -1
  44. package/dist/hooks/useWeblabs.svelte.d.ts +12 -0
  45. package/dist/hooks/useWeblabs.svelte.js +25 -0
  46. package/dist/hooks/useWorldState.svelte.d.ts +2 -38
  47. package/dist/three/BatchedArrow.d.ts +2 -2
  48. package/dist/three/BatchedArrow.js +11 -6
  49. package/package.json +1 -1
  50. package/dist/hooks/usePoses.svelte.d.ts +0 -12
  51. package/dist/hooks/usePoses.svelte.js +0 -63
@@ -1,14 +1,20 @@
1
1
  import type { Geometry, Pose, TransformWithUUID } from '@viamrobotics/sdk';
2
2
  import { BatchedMesh, Box3, Object3D, Vector3, type ColorRepresentation } from 'three';
3
3
  export type PointsGeometry = {
4
- case: 'points';
5
- value: Float32Array<ArrayBuffer>;
4
+ center: undefined;
5
+ geometryType: {
6
+ case: 'points';
7
+ value: Float32Array<ArrayBuffer>;
8
+ };
6
9
  };
7
10
  export type LinesGeometry = {
8
- case: 'line';
9
- value: Float32Array;
11
+ center: undefined;
12
+ geometryType: {
13
+ case: 'line';
14
+ value: Float32Array;
15
+ };
10
16
  };
11
- export type Geometries = Geometry['geometryType'] | PointsGeometry | LinesGeometry;
17
+ export type Geometries = Geometry | PointsGeometry | LinesGeometry;
12
18
  export type Metadata = {
13
19
  colors?: Float32Array;
14
20
  color?: ColorRepresentation;
@@ -35,22 +41,4 @@ export declare class WorldObject<T extends Geometries = Geometries> {
35
41
  metadata: Metadata;
36
42
  constructor(name: string, pose?: Pose, parent?: string, geometry?: T, metadata?: Metadata);
37
43
  }
38
- export declare const fromTransform: (transform: TransformWithUUID) => WorldObject<{
39
- case: undefined;
40
- value?: undefined;
41
- } | {
42
- case: "sphere";
43
- value: import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").Sphere>;
44
- } | {
45
- case: "box";
46
- value: import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").RectangularPrism>;
47
- } | {
48
- case: "capsule";
49
- value: import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").Capsule>;
50
- } | {
51
- case: "mesh";
52
- value: import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").Mesh>;
53
- } | {
54
- case: "pointcloud";
55
- value: import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").PointCloud>;
56
- }>;
44
+ export declare const fromTransform: (transform: TransformWithUUID) => WorldObject<import("@viamrobotics/sdk").PlainMessage<import("@viamrobotics/sdk/dist/gen/common/v1/common_pb").Geometry>>;
@@ -61,7 +61,7 @@ export const fromTransform = (transform) => {
61
61
  const metadata = transform.metadata
62
62
  ? parseMetadata(transform.metadata.fields)
63
63
  : {};
64
- const worldObject = new WorldObject(transform.referenceFrame, transform.poseInObserverFrame?.pose, transform.poseInObserverFrame?.referenceFrame, transform.physicalObject?.geometryType, metadata);
64
+ const worldObject = new WorldObject(transform.referenceFrame, transform.poseInObserverFrame?.pose, transform.poseInObserverFrame?.referenceFrame, transform.physicalObject, metadata);
65
65
  worldObject.uuid = transform.uuidString;
66
66
  return worldObject;
67
67
  };
@@ -15,7 +15,8 @@
15
15
  import { domPortal } from '../portal'
16
16
  import { provideSettings } from '../hooks/useSettings.svelte'
17
17
  import FileDrop from './FileDrop.svelte'
18
-
18
+ import WeblabProvider from './weblab/WeblabProvider.svelte'
19
+ import ArmPositions from './widgets/ArmPositions.svelte'
19
20
  interface Props {
20
21
  partID?: string
21
22
  enableKeybindings?: boolean
@@ -41,32 +42,38 @@
41
42
  <SvelteQueryDevtools initialIsOpen />
42
43
  {/if}
43
44
 
44
- <div
45
- class="relative h-full w-full overflow-hidden"
46
- bind:this={root}
47
- >
48
- <Canvas renderMode="always">
49
- <World>
50
- <SceneProviders>
51
- {#snippet children({ focus })}
52
- <Scene>
53
- {@render appChildren?.()}
54
- </Scene>
45
+ <WeblabProvider>
46
+ <div
47
+ class="relative h-full w-full overflow-hidden"
48
+ bind:this={root}
49
+ >
50
+ <Canvas renderMode="always">
51
+ <World>
52
+ <SceneProviders>
53
+ {#snippet children({ focus })}
54
+ <Scene>
55
+ {@render appChildren?.()}
56
+ </Scene>
57
+
58
+ <XR {@attach domPortal(root)} />
55
59
 
56
- <XR {@attach domPortal(root)} />
60
+ <Dashboard {@attach domPortal(root)} />
61
+ <Details {@attach domPortal(root)} />
57
62
 
58
- <Dashboard {@attach domPortal(root)} />
59
- <Details {@attach domPortal(root)} />
63
+ {#if !focus}
64
+ <TreeContainer {@attach domPortal(root)} />
65
+ {/if}
60
66
 
61
- {#if !focus}
62
- <TreeContainer {@attach domPortal(root)} />
63
- {/if}
67
+ {#if !focus && settings.current.enableArmPositionsWidget}
68
+ <ArmPositions {@attach domPortal(root)} />
69
+ {/if}
64
70
 
65
- <FileDrop {@attach domPortal(root)} />
66
- {/snippet}
67
- </SceneProviders>
68
- </World>
69
- </Canvas>
71
+ <FileDrop {@attach domPortal(root)} />
72
+ {/snippet}
73
+ </SceneProviders>
74
+ </World>
75
+ </Canvas>
70
76
 
71
- <ToastContainer />
72
- </div>
77
+ <ToastContainer />
78
+ </div>
79
+ </WeblabProvider>
@@ -22,7 +22,7 @@
22
22
  useSelectedObject3d,
23
23
  } from '../hooks/useSelection.svelte'
24
24
  import { useDraggable } from '../hooks/useDraggable.svelte'
25
-
25
+ import WeblabActive from './weblab/WeblabActive.svelte'
26
26
  const { ...rest } = $props()
27
27
 
28
28
  const focused = useFocused()
@@ -37,6 +37,9 @@
37
37
  const worldPosition = $state({ x: 0, y: 0, z: 0 })
38
38
  const worldOrientation = $state({ x: 0, y: 0, z: 1, th: 0 })
39
39
 
40
+ const localPose = $derived(object?.pose)
41
+ const referenceFrame = $derived(object?.referenceFrame ?? 'world')
42
+
40
43
  let copied = $state(false)
41
44
 
42
45
  const draggable = useDraggable('details')
@@ -157,11 +160,77 @@
157
160
  </div>
158
161
  {/if}
159
162
 
163
+ <WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
164
+ {#if localPose}
165
+ <div>
166
+ <strong class="font-semibold">local position</strong>
167
+
168
+ <div class="flex gap-3">
169
+ <div>
170
+ <span
171
+ class="text-subtle-2"
172
+ aria-label="local position x coordinate">x</span
173
+ >
174
+ {localPose.x.toFixed(2)}
175
+ </div>
176
+ <div>
177
+ <span
178
+ class="text-subtle-2"
179
+ aria-label="local position y coordinate">y</span
180
+ >
181
+ {localPose.y.toFixed(2)}
182
+ </div>
183
+ <div>
184
+ <span
185
+ class="text-subtle-2"
186
+ aria-label="local position z coordinate">z</span
187
+ >
188
+ {localPose.z.toFixed(2)}
189
+ </div>
190
+ </div>
191
+ </div>
192
+
193
+ <div>
194
+ <strong class="font-semibold">local orientation</strong>
195
+ <div class="flex gap-3">
196
+ <div>
197
+ <span
198
+ class="text-subtle-2"
199
+ aria-label="local orientation x coordinate">x</span
200
+ >
201
+ {localPose.oX.toFixed(2)}
202
+ </div>
203
+ <div>
204
+ <span
205
+ class="text-subtle-2"
206
+ aria-label="local orientation y coordinate">y</span
207
+ >
208
+ {localPose.oY.toFixed(2)}
209
+ </div>
210
+ <div>
211
+ <span
212
+ class="text-subtle-2"
213
+ aria-label="local orientation z coordinate">z</span
214
+ >
215
+ {localPose.oZ.toFixed(2)}
216
+ </div>
217
+ <div>
218
+ <span
219
+ class="text-subtle-2"
220
+ aria-label="local orientation theta degrees">th</span
221
+ >
222
+ {localPose.theta.toFixed(2)}
223
+ </div>
224
+ </div>
225
+ </div>
226
+ {/if}
227
+ </WeblabActive>
228
+
160
229
  {#if geometry}
161
- {#if geometry.case === 'box'}
162
- {@const { dimsMm } = geometry.value}
230
+ {#if geometry.geometryType.case === 'box'}
231
+ {@const { dimsMm } = geometry.geometryType.value}
163
232
  <div>
164
- <strong class="font-semibold">dimensions</strong>
233
+ <strong class="font-semibold">dimensions (box)</strong>
165
234
  <div class="flex gap-3">
166
235
  <div>
167
236
  <span class="text-subtle-2">x</span>
@@ -177,10 +246,10 @@
177
246
  </div>
178
247
  </div>
179
248
  </div>
180
- {:else if geometry.case === 'capsule'}
181
- {@const { value } = geometry}
249
+ {:else if geometry.geometryType.case === 'capsule'}
250
+ {@const { value } = geometry.geometryType}
182
251
  <div>
183
- <strong class="font-semibold">dimensions</strong>
252
+ <strong class="font-semibold">dimensions (capsule)</strong>
184
253
  <div class="flex gap-3">
185
254
  <div>
186
255
  <span class="text-subtle-2">r</span>
@@ -192,20 +261,35 @@
192
261
  </div>
193
262
  </div>
194
263
  </div>
195
- {:else if geometry.case === 'sphere'}
264
+ {:else if geometry.geometryType.case === 'sphere'}
196
265
  <div class="flex justify-between">
197
266
  <div>
198
- <strong class="font-semibold">dimensions</strong>
267
+ <strong class="font-semibold">dimensions (sphere)</strong>
199
268
  <div class="flex gap-3">
200
269
  <div>
201
270
  <span class="text-subtle-2">r</span>
202
- {geometry.value.radiusMm.toFixed(2)}
271
+ {geometry.geometryType.value.radiusMm.toFixed(2)}
203
272
  </div>
204
273
  </div>
205
274
  </div>
206
275
  </div>
207
276
  {/if}
208
277
  {/if}
278
+
279
+ <WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
280
+ <div>
281
+ <strong class="font-semibold">parent frame</strong>
282
+ <div class="flex gap-3">
283
+ <div>
284
+ <span
285
+ class="text-subtle-2"
286
+ aria-label="parent frame name">name</span
287
+ >
288
+ {referenceFrame}
289
+ </div>
290
+ </div>
291
+ </div>
292
+ </WeblabActive>
209
293
  </div>
210
294
 
211
295
  <h3 class="text-subtle-2 pt-3 pb-2">Actions</h3>
@@ -83,8 +83,11 @@
83
83
  undefined,
84
84
  undefined,
85
85
  {
86
- case: 'points',
87
- value: result.positions,
86
+ center: undefined,
87
+ geometryType: {
88
+ case: 'points',
89
+ value: result.positions,
90
+ },
88
91
  },
89
92
  result.colors ? { colors: result.colors } : undefined
90
93
  )
@@ -2,7 +2,7 @@
2
2
  import { T, type Props as ThrelteProps } from '@threlte/core'
3
3
  import { type Snippet } from 'svelte'
4
4
  import { meshBounds, MeshLineGeometry, MeshLineMaterial } from '@threlte/extras'
5
- import { BufferGeometry, DoubleSide, FrontSide, Mesh, Object3D } from 'three'
5
+ import { BufferGeometry, DoubleSide, FrontSide, Group, Mesh } from 'three'
6
6
  import { CapsuleGeometry } from '../three/CapsuleGeometry'
7
7
  import { poseToObject3d } from '../transform'
8
8
  import { colors, darkenColor } from '../color'
@@ -12,13 +12,13 @@
12
12
 
13
13
  const plyLoader = new PLYLoader()
14
14
 
15
- interface Props extends ThrelteProps<Object3D> {
15
+ interface Props extends ThrelteProps<Group> {
16
16
  uuid: string
17
17
  name: string
18
18
  geometry?: WorldObject['geometry']
19
19
  pose: WorldObject['pose']
20
20
  metadata: WorldObject['metadata']
21
- children?: Snippet<[{ ref: Object3D }]>
21
+ children?: Snippet<[{ ref: Group }]>
22
22
  color?: string
23
23
  }
24
24
 
@@ -33,19 +33,31 @@
33
33
  ...rest
34
34
  }: Props = $props()
35
35
 
36
- const type = $derived(geometry?.case)
36
+ const type = $derived(geometry?.geometryType?.case)
37
+ const color = $derived(overrideColor ?? metadata.color ?? colors.default)
38
+
39
+ const group = new Group()
37
40
  const mesh = $derived.by(() => {
38
- const object3d = type === undefined ? new Object3D() : new Mesh()
41
+ if (type === undefined) {
42
+ return
43
+ }
44
+ const result = new Mesh()
39
45
 
40
46
  if (type === 'mesh' || type === 'points' || type === 'line') {
41
- object3d.raycast = meshBounds
47
+ result.raycast = meshBounds
42
48
  }
43
49
 
44
- return object3d
50
+ return result
51
+ })
52
+
53
+ $effect.pre(() => {
54
+ if (geometry?.center && mesh) {
55
+ poseToObject3d(geometry.center, mesh)
56
+ }
45
57
  })
46
58
 
47
59
  $effect.pre(() => {
48
- poseToObject3d(pose, mesh)
60
+ poseToObject3d(pose, group)
49
61
  })
50
62
 
51
63
  let geo = $state.raw<BufferGeometry>()
@@ -53,75 +65,79 @@
53
65
  const oncreate = (ref: BufferGeometry) => {
54
66
  geo = ref
55
67
  }
56
-
57
- const color = $derived(overrideColor ?? metadata.color ?? colors.default)
58
68
  </script>
59
69
 
60
70
  <T
61
- is={mesh}
62
- {name}
63
- {uuid}
71
+ is={group}
64
72
  {...rest}
65
- bvh={{ enabled: false }}
66
73
  >
67
- {#if geometry?.case === 'mesh'}
68
- {@const mesh = geometry.value.mesh as Uint8Array<ArrayBuffer>}
69
- {@const meshGeometry = plyLoader.parse(typeof mesh === 'string' ? atob(mesh) : mesh.buffer)}
70
- <T
71
- is={meshGeometry}
72
- {oncreate}
73
- />
74
- {:else if geometry?.case === 'line' && metadata.points}
75
- <MeshLineGeometry points={metadata.points} />
76
- {:else if geometry?.case === 'box'}
77
- {@const dimsMm = geometry.value.dimsMm ?? { x: 0, y: 0, z: 0 }}
78
- <T.BoxGeometry
79
- args={[dimsMm.x * 0.001, dimsMm.y * 0.001, dimsMm.z * 0.001]}
80
- {oncreate}
81
- />
82
- {:else if geometry?.case === 'sphere'}
83
- {@const radiusMm = geometry.value.radiusMm ?? 0}
84
- <T.SphereGeometry
85
- args={[radiusMm * 0.001]}
86
- {oncreate}
87
- />
88
- {:else if geometry?.case === 'capsule'}
89
- {@const { lengthMm, radiusMm } = geometry.value}
74
+ <AxesHelper
75
+ width={3}
76
+ length={0.1}
77
+ />
78
+
79
+ {#if geometry?.geometryType}
90
80
  <T
91
- is={CapsuleGeometry}
92
- args={[radiusMm * 0.001, lengthMm * 0.001]}
93
- {oncreate}
94
- />
95
- {:else}
96
- <AxesHelper
97
- width={3}
98
- length={0.1}
99
- />
100
- {/if}
81
+ is={mesh}
82
+ {name}
83
+ {uuid}
84
+ bvh={{ enabled: false }}
85
+ >
86
+ {#if geometry.geometryType.case === 'mesh'}
87
+ {@const mesh = geometry.geometryType.value.mesh as Uint8Array<ArrayBuffer>}
88
+ {@const meshGeometry = plyLoader.parse(typeof mesh === 'string' ? atob(mesh) : mesh.buffer)}
89
+ <T
90
+ is={meshGeometry}
91
+ {oncreate}
92
+ />
93
+ {:else if geometry.geometryType.case === 'line' && metadata.points}
94
+ <MeshLineGeometry points={metadata.points} />
95
+ {:else if geometry.geometryType.case === 'box'}
96
+ {@const dimsMm = geometry.geometryType.value.dimsMm ?? { x: 0, y: 0, z: 0 }}
97
+ <T.BoxGeometry
98
+ args={[dimsMm.x * 0.001, dimsMm.y * 0.001, dimsMm.z * 0.001]}
99
+ {oncreate}
100
+ />
101
+ {:else if geometry.geometryType.case === 'sphere'}
102
+ {@const radiusMm = geometry.geometryType.value.radiusMm ?? 0}
103
+ <T.SphereGeometry
104
+ args={[radiusMm * 0.001]}
105
+ {oncreate}
106
+ />
107
+ {:else if geometry.geometryType.case === 'capsule'}
108
+ {@const { lengthMm, radiusMm } = geometry.geometryType.value}
109
+ <T
110
+ is={CapsuleGeometry}
111
+ args={[radiusMm * 0.001, lengthMm * 0.001]}
112
+ {oncreate}
113
+ />
114
+ {:else}{/if}
115
+
116
+ {#if geometry.geometryType.case === 'line'}
117
+ <MeshLineMaterial
118
+ {color}
119
+ width={metadata.lineWidth ?? 0.005}
120
+ />
121
+ {:else}
122
+ <T.MeshToonMaterial
123
+ {color}
124
+ side={geometry.geometryType.case === 'mesh' ? DoubleSide : FrontSide}
125
+ transparent
126
+ opacity={metadata.opacity ?? 0.7}
127
+ />
101
128
 
102
- {#if geometry?.case === 'line'}
103
- <MeshLineMaterial
104
- {color}
105
- width={metadata.lineWidth ?? 0.005}
106
- />
107
- {:else if geometry}
108
- <T.MeshToonMaterial
109
- {color}
110
- side={geometry.case === 'mesh' ? DoubleSide : FrontSide}
111
- transparent
112
- opacity={metadata.opacity ?? 0.7}
113
- />
114
-
115
- {#if geo}
116
- <T.LineSegments
117
- raycast={() => null}
118
- bvh={{ enabled: false }}
119
- >
120
- <T.EdgesGeometry args={[geo, 0]} />
121
- <T.LineBasicMaterial color={darkenColor(color, 10)} />
122
- </T.LineSegments>
123
- {/if}
129
+ {#if geo}
130
+ <T.LineSegments
131
+ raycast={() => null}
132
+ bvh={{ enabled: false }}
133
+ >
134
+ <T.EdgesGeometry args={[geo, 0]} />
135
+ <T.LineBasicMaterial color={darkenColor(color, 10)} />
136
+ </T.LineSegments>
137
+ {/if}
138
+ {/if}
139
+ </T>
124
140
  {/if}
125
141
 
126
- {@render children?.({ ref: mesh })}
142
+ {@render children?.({ ref: group })}
127
143
  </T>
@@ -1,15 +1,15 @@
1
1
  import { type Props as ThrelteProps } from '@threlte/core';
2
2
  import { type Snippet } from 'svelte';
3
- import { Object3D } from 'three';
3
+ import { Group } from 'three';
4
4
  import type { WorldObject } from '../WorldObject.svelte';
5
- interface Props extends ThrelteProps<Object3D> {
5
+ interface Props extends ThrelteProps<Group> {
6
6
  uuid: string;
7
7
  name: string;
8
8
  geometry?: WorldObject['geometry'];
9
9
  pose: WorldObject['pose'];
10
10
  metadata: WorldObject['metadata'];
11
11
  children?: Snippet<[{
12
- ref: Object3D;
12
+ ref: Group;
13
13
  }]>;
14
14
  color?: string;
15
15
  }
@@ -7,14 +7,14 @@
7
7
  OrthographicCamera,
8
8
  } from 'three'
9
9
  import { T, useTask, useThrelte } from '@threlte/core'
10
- import type { WorldObject } from '../WorldObject.svelte'
10
+ import type { PointsGeometry, WorldObject } from '../WorldObject.svelte'
11
11
  import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
12
12
  import { poseToObject3d } from '../transform'
13
13
  import { useSettings } from '../hooks/useSettings.svelte'
14
14
  import type { Snippet } from 'svelte'
15
15
 
16
16
  interface Props {
17
- object: WorldObject<{ case: 'points'; value: Float32Array<ArrayBuffer> }>
17
+ object: WorldObject<PointsGeometry>
18
18
  children?: Snippet
19
19
  }
20
20
 
@@ -25,7 +25,7 @@
25
25
 
26
26
  const colors = $derived(object.metadata.colors)
27
27
  const pointSize = $derived(object.metadata.pointSize ?? settings.current.pointSize)
28
- const positions = $derived(object.geometry?.value ?? new Float32Array())
28
+ const positions = $derived(object.geometry?.geometryType?.value ?? new Float32Array())
29
29
  const orthographic = $derived(settings.current.cameraMode === 'orthographic')
30
30
 
31
31
  const points = new Points()
@@ -1,10 +1,7 @@
1
- import type { WorldObject } from '../WorldObject.svelte';
1
+ import type { PointsGeometry, WorldObject } from '../WorldObject.svelte';
2
2
  import type { Snippet } from 'svelte';
3
3
  interface Props {
4
- object: WorldObject<{
5
- case: 'points';
6
- value: Float32Array<ArrayBuffer>;
7
- }>;
4
+ object: WorldObject<PointsGeometry>;
8
5
  children?: Snippet;
9
6
  }
10
7
  declare const Pointcloud: import("svelte").Component<Props, {}, "">;
@@ -4,23 +4,25 @@
4
4
  import type { Snippet } from 'svelte'
5
5
 
6
6
  interface Props {
7
- name: string
7
+ id: string
8
+ label: string
9
+ allowLive?: boolean
8
10
  children?: Snippet
9
11
  }
10
12
 
11
- let { name, children }: Props = $props()
13
+ let { id, label, allowLive = false, children }: Props = $props()
12
14
 
13
15
  const { refreshRates } = useMachineSettings()
14
- const rate = $derived(refreshRates.get(name))
16
+ const rate = $derived(refreshRates.get(id))
15
17
  </script>
16
18
 
17
19
  <label class="flex flex-col gap-1">
18
- {name}
20
+ {label}
19
21
  <Select
20
22
  onchange={(event: InputEvent) => {
21
23
  if (event.target instanceof HTMLSelectElement) {
22
24
  const { value } = event.target
23
- refreshRates.set(name, Number.parseInt(value, 10))
25
+ refreshRates.set(id, Number.parseInt(value, 10))
24
26
  }
25
27
  }}
26
28
  value={String(rate ?? '')}
@@ -30,12 +32,15 @@
30
32
  {:else}
31
33
  <option value="-1">Do not fetch</option>
32
34
  <option value="0">Do not refresh</option>
35
+ {#if allowLive}
36
+ <option value="17">60fps</option>
37
+ <option value="33">30fps</option>
38
+ {/if}
33
39
  <option value="500">Refresh every 0.5 second</option>
34
40
  <option value="1000">Refresh every second</option>
35
41
  <option value="2000">Refresh every 2 seconds</option>
36
42
  <option value="5000">Refresh every 5 seconds</option>
37
43
  <option value="10000">Refresh every 10 seconds</option>
38
- <option value="30000">Refresh every 30 seconds</option>
39
44
  {/if}
40
45
  </Select>
41
46
  </label>
@@ -1,6 +1,8 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  interface Props {
3
- name: string;
3
+ id: string;
4
+ label: string;
5
+ allowLive?: boolean;
4
6
  children?: Snippet;
5
7
  }
6
8
  declare const RefreshRate: import("svelte").Component<Props, {}, "">;
@@ -1,4 +1,5 @@
1
1
  <script lang="ts">
2
+ import type { Snippet } from 'svelte'
2
3
  import { provideFrames } from '../hooks/useFrames.svelte'
3
4
  import { provideGeometries } from '../hooks/useGeometries.svelte'
4
5
  import { providePointclouds } from '../hooks/usePointclouds.svelte'
@@ -9,12 +10,13 @@
9
10
  import { provideDrawAPI } from '../hooks/useDrawAPI.svelte'
10
11
  import { provideMachineSettings } from '../hooks/useMachineSettings.svelte'
11
12
  import { provideTransformControls } from '../hooks/useControls.svelte'
12
- import type { Snippet } from 'svelte'
13
13
  import { provideObjects } from '../hooks/useObjects.svelte'
14
14
  import { provideMotionClient } from '../hooks/useMotionClient.svelte'
15
15
  import { provideLogs } from '../hooks/useLogs.svelte'
16
16
  import { provideOrigin } from './xr/useOrigin.svelte'
17
17
  import { provideWorldStates } from '../hooks/useWorldState.svelte'
18
+ import { provideArmClient } from '../hooks/useArmClient.svelte'
19
+ import { provideArrows } from '../hooks/useArrows.svelte'
18
20
  interface Props {
19
21
  children: Snippet<[{ focus: boolean }]>
20
22
  }
@@ -28,6 +30,7 @@
28
30
  provideMachineSettings()
29
31
  provideLogs()
30
32
 
33
+ provideArrows()
31
34
  provideOrigin()
32
35
  provideStaticGeometries()
33
36
  provideDrawAPI()
@@ -38,6 +41,7 @@
38
41
  provideMotionClient(() => partID.current)
39
42
  provideObjects()
40
43
  provideWorldStates()
44
+ provideArmClient(() => partID.current)
41
45
 
42
46
  const { focus } = provideSelection()
43
47
  </script>
@@ -59,8 +59,8 @@
59
59
  } else if (mode === 'rotate') {
60
60
  quaternionToPose(ref.getWorldQuaternion(quaternion), object.pose)
61
61
  ref.quaternion.copy(quaternion)
62
- } else if (mode === 'scale' && object.geometry?.case === 'box') {
63
- scaleToDimensions(ref.scale, object.geometry)
62
+ } else if (mode === 'scale' && object.geometry?.geometryType.case === 'box') {
63
+ scaleToDimensions(ref.scale, object.geometry.geometryType)
64
64
  ref.scale.setScalar(1)
65
65
  }
66
66
  }}