@viamrobotics/motion-tools 0.14.0 → 0.14.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.
- package/dist/components/Details.svelte +29 -26
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/Tree/AddFrames.svelte +7 -5
- package/dist/components/Tree/Tree.svelte +1 -4
- package/dist/hooks/useFrames.svelte.js +2 -4
- package/dist/hooks/usePartConfig.svelte.js +21 -16
- package/dist/hooks/usePose.svelte.js +7 -0
- package/package.json +1 -1
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<script lang="ts">
|
|
14
14
|
import { Check, Copy } from 'lucide-svelte'
|
|
15
15
|
import { useTask } from '@threlte/core'
|
|
16
|
-
import { Button, Icon } from '@viamrobotics/prime-core'
|
|
16
|
+
import { Button, Icon, Select, Input } from '@viamrobotics/prime-core'
|
|
17
17
|
import {
|
|
18
18
|
useSelectedObject,
|
|
19
19
|
useFocusedObject,
|
|
@@ -106,15 +106,18 @@
|
|
|
106
106
|
value,
|
|
107
107
|
ariaLabel,
|
|
108
108
|
}: {
|
|
109
|
-
label
|
|
109
|
+
label?: string
|
|
110
110
|
value: string
|
|
111
111
|
ariaLabel: string
|
|
112
112
|
})}
|
|
113
113
|
<div>
|
|
114
114
|
<span
|
|
115
115
|
class="text-subtle-2"
|
|
116
|
-
aria-label={`immutable ${ariaLabel}`}
|
|
116
|
+
aria-label={`immutable ${ariaLabel}`}
|
|
117
117
|
>
|
|
118
|
+
{label}
|
|
119
|
+
</span>
|
|
120
|
+
|
|
118
121
|
{value}
|
|
119
122
|
</div>
|
|
120
123
|
{/snippet}
|
|
@@ -130,14 +133,16 @@
|
|
|
130
133
|
ariaLabel: string
|
|
131
134
|
onInput: (value: string) => void
|
|
132
135
|
})}
|
|
133
|
-
<
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
<div class="flex items-center gap-1">
|
|
137
|
+
<span class="text-subtle-2">{label}</span>
|
|
138
|
+
<Input
|
|
139
|
+
type="number"
|
|
140
|
+
aria-label={`mutable ${ariaLabel}`}
|
|
141
|
+
class="max-w-24 min-w-0 flex-1 rounded border px-1 py-0.5 text-xs"
|
|
142
|
+
{value}
|
|
143
|
+
on:input={(event) => onInput((event.target as HTMLInputElement).value)}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
141
146
|
{/snippet}
|
|
142
147
|
|
|
143
148
|
{#snippet DropDownField({
|
|
@@ -151,16 +156,15 @@
|
|
|
151
156
|
options: string[]
|
|
152
157
|
onChange: (value: string) => void
|
|
153
158
|
})}
|
|
154
|
-
<
|
|
159
|
+
<Select
|
|
155
160
|
aria-label={`dropdown ${ariaLabel}`}
|
|
156
|
-
class="w-full rounded border border-gray-300 px-2 py-1 text-sm"
|
|
157
161
|
{value}
|
|
158
|
-
|
|
162
|
+
on:input={(event) => onChange((event.target as HTMLSelectElement).value)}
|
|
159
163
|
>
|
|
160
164
|
{#each options as option (option)}
|
|
161
165
|
<option value={option}>{option}</option>
|
|
162
166
|
{/each}
|
|
163
|
-
</
|
|
167
|
+
</Select>
|
|
164
168
|
{/snippet}
|
|
165
169
|
|
|
166
170
|
{#if object}
|
|
@@ -259,7 +263,6 @@
|
|
|
259
263
|
<strong class="font-semibold">parent frame</strong>
|
|
260
264
|
<div class="flex gap-3">
|
|
261
265
|
{@render ParentFrame({
|
|
262
|
-
label: 'name',
|
|
263
266
|
ariaLabel: 'parent frame name',
|
|
264
267
|
value: referenceFrame,
|
|
265
268
|
options: referenceFrameOptions,
|
|
@@ -494,16 +497,6 @@
|
|
|
494
497
|
|
|
495
498
|
<h3 class="text-subtle-2 pt-3 pb-2">Actions</h3>
|
|
496
499
|
|
|
497
|
-
<WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
|
|
498
|
-
{#if isFrameNode}
|
|
499
|
-
<Button
|
|
500
|
-
variant="danger"
|
|
501
|
-
class="mb-2 w-full"
|
|
502
|
-
onclick={() => detailConfigUpdater.deleteFrame()}>Delete Frame</Button
|
|
503
|
-
>
|
|
504
|
-
{/if}
|
|
505
|
-
</WeblabActive>
|
|
506
|
-
|
|
507
500
|
{#if focused.current}
|
|
508
501
|
<Button
|
|
509
502
|
class="w-full"
|
|
@@ -522,5 +515,15 @@
|
|
|
522
515
|
Enter object view
|
|
523
516
|
</Button>
|
|
524
517
|
{/if}
|
|
518
|
+
|
|
519
|
+
<WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
|
|
520
|
+
{#if isFrameNode}
|
|
521
|
+
<Button
|
|
522
|
+
variant="danger"
|
|
523
|
+
class="mt-2 w-full"
|
|
524
|
+
onclick={() => detailConfigUpdater.deleteFrame()}>Delete Frame</Button
|
|
525
|
+
>
|
|
526
|
+
{/if}
|
|
527
|
+
</WeblabActive>
|
|
525
528
|
</div>
|
|
526
529
|
{/if}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { provideWorldStates } from '../hooks/useWorldState.svelte'
|
|
18
18
|
import { provideArmClient } from '../hooks/useArmClient.svelte'
|
|
19
19
|
import { provideArrows } from '../hooks/useArrows.svelte'
|
|
20
|
+
import { provideFramelessComponents } from '../hooks/useFramelessComponents.svelte'
|
|
20
21
|
interface Props {
|
|
21
22
|
children: Snippet<[{ focus: boolean }]>
|
|
22
23
|
}
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
provideObjects()
|
|
43
44
|
provideWorldStates()
|
|
44
45
|
provideArmClient(() => partID.current)
|
|
46
|
+
provideFramelessComponents()
|
|
45
47
|
|
|
46
48
|
const { focus } = provideSelection()
|
|
47
49
|
</script>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { IconButton } from '@viamrobotics/prime-core'
|
|
2
3
|
import Drawer from './Drawer.svelte'
|
|
3
4
|
import { usePartConfig } from '../../hooks/usePartConfig.svelte'
|
|
4
5
|
import { useFramelessComponents } from '../../hooks/useFramelessComponents.svelte'
|
|
@@ -12,12 +13,13 @@
|
|
|
12
13
|
{#if framelessComponents.current.length > 0}
|
|
13
14
|
<ul class="space-y-1">
|
|
14
15
|
{#each framelessComponents.current as component (component)}
|
|
15
|
-
<li class="text-
|
|
16
|
+
<li class="flex items-center gap-2 text-xs text-gray-700">
|
|
16
17
|
{component}
|
|
17
|
-
<
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
<IconButton
|
|
19
|
+
label="Add frame"
|
|
20
|
+
icon="plus"
|
|
21
|
+
onclick={() => partConfig.createFrame(component)}
|
|
22
|
+
/>
|
|
21
23
|
</li>
|
|
22
24
|
{/each}
|
|
23
25
|
</ul>
|
|
@@ -156,10 +156,7 @@
|
|
|
156
156
|
<h3 {...api.getLabelProps() as object}>{rootNode.name}</h3>
|
|
157
157
|
</div>
|
|
158
158
|
|
|
159
|
-
<div
|
|
160
|
-
{...api.getTreeProps()}
|
|
161
|
-
class="w-60"
|
|
162
|
-
>
|
|
159
|
+
<div {...api.getTreeProps()}>
|
|
163
160
|
{#if rootChildren.length === 0}
|
|
164
161
|
<p class="text-subtle-2 px-2 py-4">No objects displayed</p>
|
|
165
162
|
{:else if rootChildren.length > 200}
|
|
@@ -19,10 +19,8 @@ export const provideFrames = (partID) => {
|
|
|
19
19
|
const partConfig = usePartConfig();
|
|
20
20
|
const environment = useEnvironment();
|
|
21
21
|
observe.pre(() => [revision], () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
logs.add('Fetching frames...');
|
|
25
|
-
}
|
|
22
|
+
untrack(() => query.current).refetch();
|
|
23
|
+
logs.add('Fetching frames...');
|
|
26
24
|
});
|
|
27
25
|
observe.pre(() => [partConfig.isDirty], () => {
|
|
28
26
|
if (partConfig.isDirty) {
|
|
@@ -254,30 +254,35 @@ export class StandalonePartConfig {
|
|
|
254
254
|
this._localPartConfig = Struct.fromJson(configJson);
|
|
255
255
|
this._partName = partResponse?.part?.name;
|
|
256
256
|
const componentNameToFragmentId = {};
|
|
257
|
-
const
|
|
257
|
+
const fragmentRequests = [];
|
|
258
258
|
if (configJson.fragments) {
|
|
259
259
|
for (const fragmentId of configJson.fragments) {
|
|
260
|
-
|
|
260
|
+
fragmentRequests.push(standalonePartConfigProps.viamClient()?.appClient.getFragment(fragmentId));
|
|
261
261
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
262
|
+
try {
|
|
263
|
+
const fragementResponses = await Promise.all(fragmentRequests);
|
|
264
|
+
for (const fragmentResponse of fragementResponses) {
|
|
265
|
+
const fragmentId = fragmentResponse?.id;
|
|
266
|
+
if (!fragmentId) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
const components = fragmentResponse?.fragment?.fields['components'].kind;
|
|
270
|
+
if (components?.case === 'listValue') {
|
|
271
|
+
for (const component of components.value.values) {
|
|
272
|
+
if (component.kind.case === 'structValue') {
|
|
273
|
+
const componentName = component.kind.value.fields['name'].kind;
|
|
274
|
+
if (componentName.case === 'stringValue') {
|
|
275
|
+
componentNameToFragmentId[componentName.value] = fragmentId;
|
|
276
|
+
}
|
|
275
277
|
}
|
|
276
278
|
}
|
|
277
279
|
}
|
|
278
280
|
}
|
|
281
|
+
this._componentNameToFragmentId = componentNameToFragmentId;
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
/* Do nothing */
|
|
279
285
|
}
|
|
280
|
-
this._componentNameToFragmentId = componentNameToFragmentId;
|
|
281
286
|
}
|
|
282
287
|
};
|
|
283
288
|
initLocalConfig();
|
|
@@ -6,6 +6,8 @@ import { RefreshRates, useMachineSettings } from './useMachineSettings.svelte';
|
|
|
6
6
|
import { fromStore, toStore } from 'svelte/store';
|
|
7
7
|
import { useMotionClient } from './useMotionClient.svelte';
|
|
8
8
|
import { useEnvironment } from './useEnvironment.svelte';
|
|
9
|
+
import { observe } from '@threlte/core';
|
|
10
|
+
import { untrack } from 'svelte';
|
|
9
11
|
export const usePose = (name, parent) => {
|
|
10
12
|
const { refreshRates } = useMachineSettings();
|
|
11
13
|
const partID = usePartID();
|
|
@@ -40,6 +42,11 @@ export const usePose = (name, parent) => {
|
|
|
40
42
|
},
|
|
41
43
|
}));
|
|
42
44
|
const query = fromStore(createQuery(toStore(() => options)));
|
|
45
|
+
observe.pre(() => [environment.current.viewerMode], () => {
|
|
46
|
+
if (environment.current.viewerMode === 'monitor') {
|
|
47
|
+
untrack(() => query.current).refetch();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
43
50
|
return {
|
|
44
51
|
get current() {
|
|
45
52
|
if (resource?.subtype === 'arm') {
|