@viamrobotics/motion-tools 0.14.6 → 0.14.7
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/FrameConfigUpdater.svelte.d.ts +1 -0
- package/dist/FrameConfigUpdater.svelte.js +31 -0
- package/dist/components/Details.svelte +8 -7
- package/dist/components/Tree/TreeContainer.svelte +3 -1
- package/dist/hooks/usePartConfig.svelte.d.ts +5 -0
- package/dist/hooks/usePartConfig.svelte.js +15 -0
- package/dist/transform.js +1 -1
- package/package.json +1 -1
|
@@ -14,6 +14,11 @@ export class FrameConfigUpdater {
|
|
|
14
14
|
const object = this.object();
|
|
15
15
|
if (!object)
|
|
16
16
|
return;
|
|
17
|
+
x = this.sanatizeFloatValue(x);
|
|
18
|
+
y = this.sanatizeFloatValue(y);
|
|
19
|
+
z = this.sanatizeFloatValue(z);
|
|
20
|
+
if (x === undefined && y === undefined && z === undefined)
|
|
21
|
+
return;
|
|
17
22
|
object.localEditedPose.x = x ?? object.localEditedPose.x;
|
|
18
23
|
object.localEditedPose.y = y ?? object.localEditedPose.y;
|
|
19
24
|
object.localEditedPose.z = z ?? object.localEditedPose.z;
|
|
@@ -31,6 +36,12 @@ export class FrameConfigUpdater {
|
|
|
31
36
|
const object = this.object();
|
|
32
37
|
if (!object)
|
|
33
38
|
return;
|
|
39
|
+
oX = this.sanatizeFloatValue(oX);
|
|
40
|
+
oY = this.sanatizeFloatValue(oY);
|
|
41
|
+
oZ = this.sanatizeFloatValue(oZ);
|
|
42
|
+
theta = this.sanatizeFloatValue(theta);
|
|
43
|
+
if (oX === undefined && oY === undefined && oZ === undefined && theta === undefined)
|
|
44
|
+
return;
|
|
34
45
|
object.localEditedPose.oX = oX ?? object.localEditedPose.oX;
|
|
35
46
|
object.localEditedPose.oY = oY ?? object.localEditedPose.oY;
|
|
36
47
|
object.localEditedPose.oZ = oZ ?? object.localEditedPose.oZ;
|
|
@@ -52,6 +63,11 @@ export class FrameConfigUpdater {
|
|
|
52
63
|
let geometryObject;
|
|
53
64
|
if (geometry?.type === 'box') {
|
|
54
65
|
const currentGeometry = object.geometry?.geometryType.value;
|
|
66
|
+
geometry.x = this.sanatizeFloatValue(geometry.x);
|
|
67
|
+
geometry.y = this.sanatizeFloatValue(geometry.y);
|
|
68
|
+
geometry.z = this.sanatizeFloatValue(geometry.z);
|
|
69
|
+
if (geometry.x === undefined && geometry.y === undefined && geometry.z === undefined)
|
|
70
|
+
return;
|
|
55
71
|
geometryObject = {
|
|
56
72
|
type: 'box',
|
|
57
73
|
x: geometry.x ?? currentGeometry?.dimsMm?.x,
|
|
@@ -61,6 +77,9 @@ export class FrameConfigUpdater {
|
|
|
61
77
|
}
|
|
62
78
|
else if (geometry?.type === 'sphere') {
|
|
63
79
|
const currentGeometry = object.geometry?.geometryType.value;
|
|
80
|
+
geometry.r = this.sanatizeFloatValue(geometry.r);
|
|
81
|
+
if (geometry.r === undefined)
|
|
82
|
+
return;
|
|
64
83
|
geometryObject = {
|
|
65
84
|
type: 'sphere',
|
|
66
85
|
r: geometry.r ?? currentGeometry?.radiusMm,
|
|
@@ -68,6 +87,10 @@ export class FrameConfigUpdater {
|
|
|
68
87
|
}
|
|
69
88
|
else if (geometry?.type === 'capsule') {
|
|
70
89
|
const currentGeometry = object.geometry?.geometryType.value;
|
|
90
|
+
geometry.r = this.sanatizeFloatValue(geometry.r);
|
|
91
|
+
geometry.l = this.sanatizeFloatValue(geometry.l);
|
|
92
|
+
if (geometry.r === undefined && geometry.l === undefined)
|
|
93
|
+
return;
|
|
71
94
|
geometryObject = {
|
|
72
95
|
type: 'capsule',
|
|
73
96
|
r: geometry.r ?? currentGeometry?.radiusMm,
|
|
@@ -113,4 +136,12 @@ export class FrameConfigUpdater {
|
|
|
113
136
|
}, { type: 'capsule', r: 20, l: 100 });
|
|
114
137
|
}
|
|
115
138
|
};
|
|
139
|
+
sanatizeFloatValue = (value) => {
|
|
140
|
+
if (value === undefined)
|
|
141
|
+
return undefined;
|
|
142
|
+
const num = parseFloat(value.toFixed(2));
|
|
143
|
+
if (isNaN(num))
|
|
144
|
+
return undefined;
|
|
145
|
+
return num;
|
|
146
|
+
};
|
|
116
147
|
}
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
const isFrameNode = $derived(
|
|
56
56
|
frames.current.find((frame) => frame.name === object?.name) !== undefined
|
|
57
57
|
)
|
|
58
|
+
const showEditFrameOptions = $derived(isFrameNode && partConfig.hasEditPermissions)
|
|
58
59
|
let copied = $state(false)
|
|
59
60
|
|
|
60
61
|
const draggable = useDraggable('details')
|
|
@@ -215,7 +216,7 @@
|
|
|
215
216
|
|
|
216
217
|
{#if object}
|
|
217
218
|
<div
|
|
218
|
-
class="border-medium bg-extralight absolute top-0 right-0 z-1000 m-2 {
|
|
219
|
+
class="border-medium bg-extralight absolute top-0 right-0 z-1000 m-2 {showEditFrameOptions
|
|
219
220
|
? 'w-80'
|
|
220
221
|
: 'w-60'} border p-2 text-xs"
|
|
221
222
|
style:transform="translate({draggable.current.x}px, {draggable.current.y}px)"
|
|
@@ -303,7 +304,7 @@
|
|
|
303
304
|
{/if}
|
|
304
305
|
|
|
305
306
|
<WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
|
|
306
|
-
{@const ParentFrame =
|
|
307
|
+
{@const ParentFrame = showEditFrameOptions ? DropDownField : ImmutableField}
|
|
307
308
|
|
|
308
309
|
<div>
|
|
309
310
|
<strong class="font-semibold">parent frame</strong>
|
|
@@ -318,7 +319,7 @@
|
|
|
318
319
|
</div>
|
|
319
320
|
|
|
320
321
|
{#if localPose}
|
|
321
|
-
{@const PoseAttribute =
|
|
322
|
+
{@const PoseAttribute = showEditFrameOptions ? MutableField : ImmutableField}
|
|
322
323
|
<div>
|
|
323
324
|
<strong class="font-semibold">local position</strong>
|
|
324
325
|
|
|
@@ -349,7 +350,7 @@
|
|
|
349
350
|
|
|
350
351
|
<div>
|
|
351
352
|
<strong class="font-semibold">local orientation</strong>
|
|
352
|
-
<div class="flex {
|
|
353
|
+
<div class="flex {showEditFrameOptions ? 'gap-2' : 'gap-3'}">
|
|
353
354
|
{@render PoseAttribute({
|
|
354
355
|
label: 'x',
|
|
355
356
|
ariaLabel: 'local orientation x coordinate',
|
|
@@ -382,7 +383,7 @@
|
|
|
382
383
|
</div>
|
|
383
384
|
{/if}
|
|
384
385
|
|
|
385
|
-
{#if
|
|
386
|
+
{#if showEditFrameOptions}
|
|
386
387
|
<div>
|
|
387
388
|
<strong class="font-semibold">geometry</strong>
|
|
388
389
|
<div class="grid grid-cols-4 gap-1">
|
|
@@ -410,7 +411,7 @@
|
|
|
410
411
|
</div>
|
|
411
412
|
{/if}
|
|
412
413
|
{#if geometryType !== 'none'}
|
|
413
|
-
{@const GeometryAttribute =
|
|
414
|
+
{@const GeometryAttribute = showEditFrameOptions ? MutableField : ImmutableField}
|
|
414
415
|
{#if geometryType === 'box'}
|
|
415
416
|
{@const { dimsMm } = object?.geometry?.geometryType.value as {
|
|
416
417
|
dimsMm: { x: number; y: number; z: number }
|
|
@@ -563,7 +564,7 @@
|
|
|
563
564
|
{/if}
|
|
564
565
|
|
|
565
566
|
<WeblabActive experiment="MOTION_TOOLS_EDIT_FRAME">
|
|
566
|
-
{#if
|
|
567
|
+
{#if showEditFrameOptions}
|
|
567
568
|
<Button
|
|
568
569
|
variant="danger"
|
|
569
570
|
class="mt-2 w-full"
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
import AddFrames from './AddFrames.svelte'
|
|
15
15
|
import { useEnvironment } from '../../hooks/useEnvironment.svelte'
|
|
16
16
|
import { usePartID } from '../../hooks/usePartID.svelte'
|
|
17
|
+
import { usePartConfig } from '../../hooks/usePartConfig.svelte'
|
|
17
18
|
const { ...rest } = $props()
|
|
18
19
|
|
|
19
20
|
provideTreeExpandedContext()
|
|
@@ -24,6 +25,7 @@
|
|
|
24
25
|
const draggable = useDraggable('treeview')
|
|
25
26
|
const worldStates = useWorldStates()
|
|
26
27
|
const environment = useEnvironment()
|
|
28
|
+
const partConfig = usePartConfig()
|
|
27
29
|
|
|
28
30
|
let rootNode = $state<TreeNode>({
|
|
29
31
|
id: 'world',
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
/>
|
|
59
61
|
{/key}
|
|
60
62
|
|
|
61
|
-
{#if environment.current.isStandalone && partID.current}
|
|
63
|
+
{#if environment.current.isStandalone && partID.current && partConfig.hasEditPermissions}
|
|
62
64
|
<AddFrames />
|
|
63
65
|
{/if}
|
|
64
66
|
|
|
@@ -24,11 +24,13 @@ interface PartConfigContext {
|
|
|
24
24
|
componentNameToFragmentId: Record<string, string>;
|
|
25
25
|
localPartConfig: Struct;
|
|
26
26
|
isDirty: boolean;
|
|
27
|
+
hasEditPermissions: boolean;
|
|
27
28
|
}
|
|
28
29
|
export declare const providePartConfig: (params: PartConfigParams) => void;
|
|
29
30
|
export declare const usePartConfig: () => PartConfigContext;
|
|
30
31
|
interface LocalPartConfig {
|
|
31
32
|
isDirty: () => boolean;
|
|
33
|
+
hasEditPermissions: () => boolean;
|
|
32
34
|
getLocalPartConfig: () => Struct;
|
|
33
35
|
setLocalPartConfig: (config: Struct) => void;
|
|
34
36
|
componentNameToFragmentId: () => Record<string, string>;
|
|
@@ -48,6 +50,7 @@ export declare class AppEmbeddedPartConfig implements LocalPartConfig {
|
|
|
48
50
|
getLocalPartConfig(): Struct;
|
|
49
51
|
setLocalPartConfig(config: Struct): void;
|
|
50
52
|
componentNameToFragmentId(): Record<string, string>;
|
|
53
|
+
hasEditPermissions(): boolean;
|
|
51
54
|
}
|
|
52
55
|
interface StandalonePartConfigProps {
|
|
53
56
|
viamClient: () => ViamClient | undefined;
|
|
@@ -56,6 +59,7 @@ interface StandalonePartConfigProps {
|
|
|
56
59
|
export declare class StandalonePartConfig implements LocalPartConfig {
|
|
57
60
|
private _standalonePartConfigProps;
|
|
58
61
|
private _isDirty;
|
|
62
|
+
private _hasEditPermissions;
|
|
59
63
|
private _networkPartConfig;
|
|
60
64
|
private _localPartConfig;
|
|
61
65
|
private _partName;
|
|
@@ -64,6 +68,7 @@ export declare class StandalonePartConfig implements LocalPartConfig {
|
|
|
64
68
|
getLocalPartConfig(): Struct;
|
|
65
69
|
setLocalPartConfig(config: Struct): void;
|
|
66
70
|
isDirty(): boolean;
|
|
71
|
+
hasEditPermissions(): boolean;
|
|
67
72
|
componentNameToFragmentId(): Record<string, string>;
|
|
68
73
|
saveLocalPartConfig(): Promise<void>;
|
|
69
74
|
resetLocalPartConfig(): Promise<void>;
|
|
@@ -209,6 +209,9 @@ export const providePartConfig = (params) => {
|
|
|
209
209
|
get isDirty() {
|
|
210
210
|
return _localPartConfig.isDirty();
|
|
211
211
|
},
|
|
212
|
+
get hasEditPermissions() {
|
|
213
|
+
return _localPartConfig.hasEditPermissions();
|
|
214
|
+
},
|
|
212
215
|
});
|
|
213
216
|
};
|
|
214
217
|
export const usePartConfig = () => {
|
|
@@ -231,10 +234,14 @@ export class AppEmbeddedPartConfig {
|
|
|
231
234
|
componentNameToFragmentId() {
|
|
232
235
|
return this._appEmbeddedPartConfigProps.getComponentToFragId();
|
|
233
236
|
}
|
|
237
|
+
hasEditPermissions() {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
234
240
|
}
|
|
235
241
|
export class StandalonePartConfig {
|
|
236
242
|
_standalonePartConfigProps;
|
|
237
243
|
_isDirty = $state(false);
|
|
244
|
+
_hasEditPermissions = $state(false);
|
|
238
245
|
_networkPartConfig = $state();
|
|
239
246
|
_localPartConfig = $state();
|
|
240
247
|
_partName = $state();
|
|
@@ -246,6 +253,11 @@ export class StandalonePartConfig {
|
|
|
246
253
|
const partResponse = await standalonePartConfigProps
|
|
247
254
|
.viamClient()
|
|
248
255
|
?.appClient.getRobotPart(standalonePartConfigProps.partID());
|
|
256
|
+
if (JSON.parse(partResponse?.configJson ?? 'null') === null) {
|
|
257
|
+
// no config returned here indicates this api key has no permission to update config
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
this._hasEditPermissions = true;
|
|
249
261
|
const configJson = JSON.parse(partResponse?.configJson ?? '{}');
|
|
250
262
|
this._networkPartConfig = Struct.fromJson(configJson);
|
|
251
263
|
this._localPartConfig = Struct.fromJson(configJson);
|
|
@@ -292,6 +304,9 @@ export class StandalonePartConfig {
|
|
|
292
304
|
isDirty() {
|
|
293
305
|
return this._isDirty;
|
|
294
306
|
}
|
|
307
|
+
hasEditPermissions() {
|
|
308
|
+
return this._hasEditPermissions;
|
|
309
|
+
}
|
|
295
310
|
componentNameToFragmentId() {
|
|
296
311
|
return this._componentNameToFragmentId ?? {};
|
|
297
312
|
}
|
package/dist/transform.js
CHANGED
|
@@ -27,7 +27,7 @@ export const createPoseFromFrame = (frame) => {
|
|
|
27
27
|
else if (frame.orientation.type === 'ov_radians') {
|
|
28
28
|
ov.copy(frame.orientation.value);
|
|
29
29
|
}
|
|
30
|
-
else
|
|
30
|
+
else {
|
|
31
31
|
const th = MathUtils.degToRad(frame.orientation.value.th);
|
|
32
32
|
ov.set(frame.orientation.value.x, frame.orientation.value.y, frame.orientation.value.z, th);
|
|
33
33
|
}
|