@viamrobotics/motion-tools 1.32.0 → 1.33.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/App.svelte +17 -11
- package/dist/components/App.svelte.d.ts +14 -7
- package/dist/components/Entities/Entities.svelte +18 -25
- package/dist/components/Entities/Entities.svelte.d.ts +2 -17
- package/dist/components/Entities/Label.svelte +79 -13
- package/dist/components/Entities/Label.svelte.d.ts +2 -1
- package/dist/components/Entities/Labels.svelte +36 -0
- package/dist/components/Entities/Labels.svelte.d.ts +3 -0
- package/dist/components/Entities/LineDots.svelte +8 -3
- package/dist/components/Entities/labelLayout/applyTeleports.d.ts +9 -0
- package/dist/components/Entities/labelLayout/applyTeleports.js +39 -0
- package/dist/components/Entities/labelLayout/buildNeighborhood.d.ts +8 -0
- package/dist/components/Entities/labelLayout/buildNeighborhood.js +26 -0
- package/dist/components/Entities/labelLayout/cameraHash.d.ts +8 -0
- package/dist/components/Entities/labelLayout/cameraHash.js +25 -0
- package/dist/components/Entities/labelLayout/cost.d.ts +44 -0
- package/dist/components/Entities/labelLayout/cost.js +126 -0
- package/dist/components/Entities/labelLayout/createLabelLayout.d.ts +27 -0
- package/dist/components/Entities/labelLayout/createLabelLayout.js +194 -0
- package/dist/components/Entities/labelLayout/geometry.d.ts +20 -0
- package/dist/components/Entities/labelLayout/geometry.js +151 -0
- package/dist/components/Entities/labelLayout/labelStore.svelte.d.ts +17 -0
- package/dist/components/Entities/labelLayout/labelStore.svelte.js +28 -0
- package/dist/components/Entities/labelLayout/measure.d.ts +13 -0
- package/dist/components/Entities/labelLayout/measure.js +42 -0
- package/dist/components/Entities/labelLayout/slots.d.ts +11 -0
- package/dist/components/Entities/labelLayout/slots.js +47 -0
- package/dist/components/Entities/labelLayout/solve.d.ts +11 -0
- package/dist/components/Entities/labelLayout/solve.js +93 -0
- package/dist/components/Entities/labelLayout/spatialHash.d.ts +15 -0
- package/dist/components/Entities/labelLayout/spatialHash.js +53 -0
- package/dist/components/Entities/labelLayout/types.d.ts +105 -0
- package/dist/components/Entities/labelLayout/types.js +19 -0
- package/dist/components/Entities/labelLayout/writeBack.d.ts +20 -0
- package/dist/components/Entities/labelLayout/writeBack.js +51 -0
- package/dist/components/Scene.svelte +42 -48
- package/dist/components/SceneProviders.svelte +0 -3
- package/dist/components/SelectedTransformControls.svelte +65 -47
- package/dist/components/overlay/Details.svelte +198 -224
- package/dist/components/overlay/Details.svelte.d.ts +1 -1
- package/dist/components/overlay/Popover.svelte +6 -4
- package/dist/components/overlay/Popover.svelte.d.ts +6 -2
- package/dist/components/overlay/dashboard/Button.svelte +7 -2
- package/dist/components/overlay/dashboard/Button.svelte.d.ts +2 -1
- package/dist/components/overlay/details/AxesHelperDetails.svelte +32 -0
- package/dist/components/overlay/details/AxesHelperDetails.svelte.d.ts +7 -0
- package/dist/components/overlay/details/ColorDetails.svelte +35 -0
- package/dist/components/overlay/details/ColorDetails.svelte.d.ts +7 -0
- package/dist/components/overlay/details/GeometryDetails.svelte +104 -0
- package/dist/components/overlay/details/GeometryDetails.svelte.d.ts +7 -0
- package/dist/components/overlay/details/LineDetails/LineDetails.svelte +196 -0
- package/dist/components/overlay/details/LineDetails/LineDetails.svelte.d.ts +7 -0
- package/dist/components/overlay/details/LineDetails/linePositions.d.ts +3 -0
- package/dist/components/overlay/details/LineDetails/linePositions.js +30 -0
- package/dist/components/overlay/details/OpacityDetails.svelte +44 -0
- package/dist/components/overlay/details/OpacityDetails.svelte.d.ts +7 -0
- package/dist/components/overlay/details/PoseDetails.svelte +189 -0
- package/dist/components/overlay/details/PoseDetails.svelte.d.ts +14 -0
- package/dist/components/overlay/settings/ConnectionSettings.svelte +42 -0
- package/dist/components/overlay/settings/ConnectionSettings.svelte.d.ts +18 -0
- package/dist/components/overlay/settings/DebugSettings.svelte +13 -0
- package/dist/components/{xr/frame-configure/Controllers.svelte.d.ts → overlay/settings/DebugSettings.svelte.d.ts} +3 -3
- package/dist/components/overlay/settings/PointcloudSettings.svelte +61 -0
- package/dist/components/overlay/settings/PointcloudSettings.svelte.d.ts +3 -0
- package/dist/components/overlay/settings/SceneSettings.svelte +110 -0
- package/dist/components/overlay/settings/SceneSettings.svelte.d.ts +18 -0
- package/dist/components/overlay/settings/Settings.svelte +27 -312
- package/dist/components/overlay/settings/Settings.svelte.d.ts +8 -1
- package/dist/components/overlay/settings/Tabs.svelte +5 -3
- package/dist/components/overlay/settings/Tabs.svelte.d.ts +3 -3
- package/dist/components/overlay/settings/VisionSettings.svelte +31 -0
- package/dist/components/overlay/settings/VisionSettings.svelte.d.ts +3 -0
- package/dist/components/overlay/settings/WeblabSettings.svelte +27 -0
- package/dist/components/overlay/settings/WeblabSettings.svelte.d.ts +18 -0
- package/dist/components/overlay/settings/WidgetSettings.svelte +49 -0
- package/dist/components/overlay/settings/WidgetSettings.svelte.d.ts +3 -0
- package/dist/components/overlay/widgets/FramePov.svelte +1 -12
- package/dist/ecs/traits.d.ts +1 -1
- package/dist/ecs/traits.js +1 -1
- package/dist/hooks/useWorldState.svelte.js +39 -50
- package/dist/{components/xr → plugins/XR}/ArmTeleop.svelte +3 -5
- package/dist/plugins/XR/DebugPanel.svelte +29 -0
- package/dist/plugins/XR/DebugPanel.svelte.d.ts +3 -0
- package/dist/plugins/XR/OriginMarker.svelte +341 -0
- package/dist/plugins/XR/PendingEditsPanel.svelte +60 -0
- package/dist/plugins/XR/PendingEditsPanel.svelte.d.ts +18 -0
- package/dist/plugins/XR/WristDisplay.svelte +60 -0
- package/dist/plugins/XR/WristDisplay.svelte.d.ts +19 -0
- package/dist/{components/xr → plugins/XR}/XR.svelte +69 -23
- package/dist/plugins/XR/XRPlugins.svelte +9 -0
- package/dist/plugins/XR/XRPlugins.svelte.d.ts +26 -0
- package/dist/plugins/XR/XRSettings.svelte +240 -0
- package/dist/plugins/XR/XRSettings.svelte.d.ts +3 -0
- package/dist/{components/xr → plugins/XR}/XRToast.svelte +6 -9
- package/dist/plugins/XR/debug.svelte.d.ts +7 -0
- package/dist/plugins/XR/debug.svelte.js +13 -0
- package/dist/plugins/XR/frame-configure/Controllers.svelte +413 -0
- package/dist/plugins/XR/teleop/Controllers.svelte.d.ts +3 -0
- package/dist/{components/xr → plugins/XR}/useAnchors.svelte.d.ts +4 -0
- package/dist/{components/xr → plugins/XR}/useAnchors.svelte.js +22 -0
- package/dist/plugins/XR/useOrigin.svelte.d.ts +24 -0
- package/dist/plugins/XR/useOrigin.svelte.js +50 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +2 -0
- package/dist/three/OBBHelper.js +1 -0
- package/package.json +3 -1
- package/dist/components/xr/OriginMarker.svelte +0 -151
- package/dist/components/xr/XRControllerSettings.svelte +0 -242
- package/dist/components/xr/XRControllerSettings.svelte.d.ts +0 -3
- package/dist/components/xr/frame-configure/Controllers.svelte +0 -6
- package/dist/components/xr/useOrigin.svelte.d.ts +0 -9
- package/dist/components/xr/useOrigin.svelte.js +0 -27
- /package/dist/{components/xr → plugins/XR}/ArmTeleop.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/BentPlaneGeometry.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/BentPlaneGeometry.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/CameraFeed.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/CameraFeed.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/JointLimitsWidget.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/JointLimitsWidget.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/OriginMarker.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/PointDistance.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/PointDistance.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/XR.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/XRConfigPanel.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/XRConfigPanel.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/XRToast.svelte.d.ts +0 -0
- /package/dist/{components/xr/teleop → plugins/XR/frame-configure}/Controllers.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/math.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/math.js +0 -0
- /package/dist/{components/xr → plugins/XR}/teleop/Controllers.svelte +0 -0
- /package/dist/{components/xr → plugins/XR}/toasts.svelte.d.ts +0 -0
- /package/dist/{components/xr → plugins/XR}/toasts.svelte.js +0 -0
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
|
|
14
14
|
<script lang="ts">
|
|
15
15
|
import type { Pose } from '@viamrobotics/sdk'
|
|
16
|
-
import type { Entity } from 'koota'
|
|
17
16
|
import type { Snippet } from 'svelte'
|
|
18
17
|
import type { HTMLAttributes } from 'svelte/elements'
|
|
19
18
|
|
|
20
19
|
import { draggable } from '@neodrag/svelte'
|
|
21
20
|
import { isInstanceOf, useThrelte } from '@threlte/core'
|
|
21
|
+
import { PortalTarget } from '@threlte/extras'
|
|
22
22
|
import { Button, Icon, Tooltip } from '@viamrobotics/prime-core'
|
|
23
|
+
import { type Entity } from 'koota'
|
|
23
24
|
import { Check, Copy } from 'lucide-svelte'
|
|
24
25
|
import {
|
|
25
26
|
List,
|
|
@@ -38,7 +39,9 @@
|
|
|
38
39
|
} from 'svelte-tweakpane-ui'
|
|
39
40
|
|
|
40
41
|
import AddRelationship from './AddRelationship.svelte'
|
|
41
|
-
import
|
|
42
|
+
import AxesHelperDetails from './details/AxesHelperDetails.svelte'
|
|
43
|
+
import OpacityDetails from './details/OpacityDetails.svelte'
|
|
44
|
+
import { hierarchy, relations, traits, useParentName, useTag, useTrait, useWorld } from '../../ecs'
|
|
42
45
|
import { FrameConfigUpdater } from '../../FrameConfigUpdater.svelte'
|
|
43
46
|
import { useConfigFrames } from '../../hooks/useConfigFrames.svelte'
|
|
44
47
|
import { useCameraControls } from '../../hooks/useControls.svelte'
|
|
@@ -58,7 +61,7 @@
|
|
|
58
61
|
const { entity, details, ...rest }: Props = $props()
|
|
59
62
|
|
|
60
63
|
const world = useWorld()
|
|
61
|
-
const { scene
|
|
64
|
+
const { scene } = useThrelte()
|
|
62
65
|
const controls = useCameraControls()
|
|
63
66
|
const resourceByName = useResourceByName()
|
|
64
67
|
const configFrames = useConfigFrames()
|
|
@@ -82,9 +85,9 @@
|
|
|
82
85
|
const removable = useTrait(() => entity, traits.Removable)
|
|
83
86
|
const points = useTrait(() => entity, traits.Points)
|
|
84
87
|
const arrows = useTrait(() => entity, traits.Arrows)
|
|
85
|
-
const opacity = useTrait(() => entity, traits.Opacity)
|
|
86
88
|
const framesAPI = useTrait(() => entity, traits.FramesAPI)
|
|
87
89
|
const geometriesAPI = useTrait(() => entity, traits.GeometriesAPI)
|
|
90
|
+
const customDetails = useTag(() => entity, traits.CustomDetails)
|
|
88
91
|
|
|
89
92
|
const localPose = $derived.by<Pose | undefined>(() => {
|
|
90
93
|
const source = editedMatrix.current ?? matrix.current
|
|
@@ -112,7 +115,7 @@
|
|
|
112
115
|
const resourceName = $derived(name.current ? resourceByName.current[name.current] : undefined)
|
|
113
116
|
const displayType = $derived(isFrameNode ? resourceName?.subtype : isGeometry ? 'geometry' : '')
|
|
114
117
|
|
|
115
|
-
|
|
118
|
+
const geometryType = $derived.by(() => {
|
|
116
119
|
if (box.current) return 'box'
|
|
117
120
|
if (sphere.current) return 'sphere'
|
|
118
121
|
if (capsule.current) return 'capsule'
|
|
@@ -126,11 +129,10 @@
|
|
|
126
129
|
$effect(() => {
|
|
127
130
|
// setGeometryType guards against no-ops, so this is safe to fire on every
|
|
128
131
|
// tab-index change (whether user-initiated or trait-derived).
|
|
129
|
-
setGeometryType(geometryTypes[geometryTabIndex])
|
|
132
|
+
detailConfigUpdater.setGeometryType(entity, geometryTypes[geometryTabIndex])
|
|
130
133
|
})
|
|
131
134
|
|
|
132
135
|
let copied = $state(false)
|
|
133
|
-
|
|
134
136
|
let dragElement = $state.raw<HTMLElement>()
|
|
135
137
|
|
|
136
138
|
const eulerValue = $derived.by<RotationEulerValueObject>(() => {
|
|
@@ -212,23 +214,6 @@
|
|
|
212
214
|
detailConfigUpdater.updateGeometry(entity, { type: 'capsule', l: event.detail.value })
|
|
213
215
|
}
|
|
214
216
|
|
|
215
|
-
const opacityValue = $derived(opacity.current ?? 1)
|
|
216
|
-
|
|
217
|
-
const handleOpacityChange = (event: SliderChangeEvent) => {
|
|
218
|
-
if (event.detail.origin !== 'internal' || !entity) return
|
|
219
|
-
const next = event.detail.value
|
|
220
|
-
// No trait === fully opaque, so drop the trait when the user returns to 1
|
|
221
|
-
// instead of leaving an Opacity(1) entry on the entity.
|
|
222
|
-
if (next >= 1) {
|
|
223
|
-
entity.remove(traits.Opacity)
|
|
224
|
-
} else if (entity.has(traits.Opacity)) {
|
|
225
|
-
entity.set(traits.Opacity, next)
|
|
226
|
-
} else {
|
|
227
|
-
entity.add(traits.Opacity(next))
|
|
228
|
-
}
|
|
229
|
-
invalidate()
|
|
230
|
-
}
|
|
231
|
-
|
|
232
217
|
const handleParentChange = (event: ListChangeEvent) => {
|
|
233
218
|
if (event.detail.origin !== 'internal' || !entity) return
|
|
234
219
|
const value = event.detail.value as string
|
|
@@ -237,18 +222,6 @@
|
|
|
237
222
|
detailConfigUpdater.setFrameParent(entity, value)
|
|
238
223
|
}
|
|
239
224
|
|
|
240
|
-
const setGeometryType = (type: 'none' | 'box' | 'sphere' | 'capsule') => {
|
|
241
|
-
if (type === geometryType) {
|
|
242
|
-
return
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
geometryType = type
|
|
246
|
-
|
|
247
|
-
if (entity) {
|
|
248
|
-
detailConfigUpdater.setGeometryType(entity, type)
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
225
|
const getCopyClipboardText = () => {
|
|
253
226
|
return JSON.stringify(
|
|
254
227
|
{
|
|
@@ -327,6 +300,7 @@
|
|
|
327
300
|
bind:this={dragElement}
|
|
328
301
|
>
|
|
329
302
|
<div class="flex w-[90%] items-center gap-1">
|
|
303
|
+
<PortalTarget id="details-header-icon" />
|
|
330
304
|
<strong class="overflow-hidden text-nowrap text-ellipsis">{name.current}</strong>
|
|
331
305
|
<span class="text-subtle-2">{displayType}</span>
|
|
332
306
|
</div>
|
|
@@ -411,6 +385,32 @@
|
|
|
411
385
|
<p slot="description">Remove from scene</p>
|
|
412
386
|
</Tooltip>
|
|
413
387
|
{/if}
|
|
388
|
+
|
|
389
|
+
<Tooltip
|
|
390
|
+
let:tooltipID
|
|
391
|
+
location="bottom"
|
|
392
|
+
>
|
|
393
|
+
<button
|
|
394
|
+
class="text-subtle-2"
|
|
395
|
+
aria-describedby={tooltipID}
|
|
396
|
+
onclick={async () => {
|
|
397
|
+
try {
|
|
398
|
+
await navigator.clipboard.writeText(getCopyClipboardText())
|
|
399
|
+
} catch {
|
|
400
|
+
// clipboard unavailable (non-secure context or permission denied)
|
|
401
|
+
}
|
|
402
|
+
copied = true
|
|
403
|
+
setTimeout(() => (copied = false), 1000)
|
|
404
|
+
}}
|
|
405
|
+
>
|
|
406
|
+
{#if copied}
|
|
407
|
+
<Check size={14} />
|
|
408
|
+
{:else}
|
|
409
|
+
<Copy size={14} />
|
|
410
|
+
{/if}
|
|
411
|
+
</button>
|
|
412
|
+
<p slot="description">Copy details to clipboard</p>
|
|
413
|
+
</Tooltip>
|
|
414
414
|
</div>
|
|
415
415
|
|
|
416
416
|
<div class="border-medium -mx-2 w-[100%+0.5rem] border-b"></div>
|
|
@@ -425,75 +425,57 @@
|
|
|
425
425
|
</p>
|
|
426
426
|
{/if}
|
|
427
427
|
|
|
428
|
-
<h3
|
|
429
|
-
class="text-subtle-2 flex justify-between py-2"
|
|
430
|
-
data-testid="details-header"
|
|
431
|
-
>
|
|
432
|
-
Details
|
|
433
|
-
|
|
434
|
-
<button
|
|
435
|
-
onclick={async () => {
|
|
436
|
-
navigator.clipboard.writeText(getCopyClipboardText())
|
|
437
|
-
copied = true
|
|
438
|
-
setTimeout(() => (copied = false), 1000)
|
|
439
|
-
}}
|
|
440
|
-
>
|
|
441
|
-
{#if copied}
|
|
442
|
-
<Check size={14} />
|
|
443
|
-
{:else}
|
|
444
|
-
<Copy size={14} />
|
|
445
|
-
{/if}
|
|
446
|
-
</button>
|
|
447
|
-
</h3>
|
|
428
|
+
<h3 class="text-subtle-2 pt-3 pb-2">Details</h3>
|
|
448
429
|
|
|
449
430
|
<div class="flex flex-col gap-2.5">
|
|
450
|
-
|
|
451
|
-
<
|
|
452
|
-
|
|
431
|
+
{#if !customDetails.current}
|
|
432
|
+
<div>
|
|
433
|
+
<strong class="font-semibold">world position</strong>
|
|
434
|
+
<span class="text-subtle-2">(mm)</span>
|
|
453
435
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
436
|
+
<div class="flex gap-3">
|
|
437
|
+
<div>
|
|
438
|
+
<span class="text-subtle-2">x</span>
|
|
439
|
+
{(worldPose?.x ?? 0).toFixed(2)}
|
|
440
|
+
</div>
|
|
441
|
+
<div>
|
|
442
|
+
<span class="text-subtle-2">y</span>
|
|
443
|
+
{(worldPose?.y ?? 0).toFixed(2)}
|
|
444
|
+
</div>
|
|
445
|
+
<div>
|
|
446
|
+
<span class="text-subtle-2">z</span>
|
|
447
|
+
{(worldPose?.z ?? 0).toFixed(2)}
|
|
448
|
+
</div>
|
|
466
449
|
</div>
|
|
467
450
|
</div>
|
|
468
|
-
</div>
|
|
469
451
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
452
|
+
<div>
|
|
453
|
+
<strong class="font-semibold">world orientation</strong>
|
|
454
|
+
<span class="text-subtle-2">(deg)</span>
|
|
455
|
+
<div class="flex gap-3">
|
|
456
|
+
<div>
|
|
457
|
+
<span class="text-subtle-2">x</span>
|
|
458
|
+
{(worldPose?.oX ?? 0).toFixed(2)}
|
|
459
|
+
</div>
|
|
460
|
+
<div>
|
|
461
|
+
<span class="text-subtle-2">y</span>
|
|
462
|
+
{(worldPose?.oY ?? 0).toFixed(2)}
|
|
463
|
+
</div>
|
|
464
|
+
<div>
|
|
465
|
+
<span class="text-subtle-2">z</span>
|
|
466
|
+
{(worldPose?.oZ ?? 0).toFixed(2)}
|
|
467
|
+
</div>
|
|
468
|
+
<div>
|
|
469
|
+
<span class="text-subtle-2">th</span>
|
|
470
|
+
{(worldPose?.theta ?? 0).toFixed(2)}
|
|
471
|
+
</div>
|
|
489
472
|
</div>
|
|
490
473
|
</div>
|
|
491
|
-
</div>
|
|
492
474
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
475
|
+
<div>
|
|
476
|
+
<strong class="font-semibold">parent frame</strong>
|
|
477
|
+
{#if showEditFrameOptions}
|
|
478
|
+
<!--
|
|
497
479
|
Remount on entity change. svelte-tweakpane-ui's List runs
|
|
498
480
|
`listBlade.value = value` on the still-mounted blade before its
|
|
499
481
|
`options` prop has propagated, so the new entity's parent name
|
|
@@ -502,113 +484,114 @@
|
|
|
502
484
|
event that handleParentChange interprets as a user pick — silently
|
|
503
485
|
reparenting the clicked frame.
|
|
504
486
|
-->
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
{:else}
|
|
515
|
-
<div class="mt-0.5 flex gap-3">
|
|
516
|
-
{@render ImmutableField({
|
|
517
|
-
ariaLabel: 'parent frame name',
|
|
518
|
-
value: parent.current ?? 'world',
|
|
519
|
-
})}
|
|
520
|
-
</div>
|
|
521
|
-
{/if}
|
|
522
|
-
</div>
|
|
523
|
-
|
|
524
|
-
{#if localPose}
|
|
525
|
-
<div>
|
|
526
|
-
<strong class="font-semibold">local position</strong>
|
|
527
|
-
<span class="text-subtle-2">(mm)</span>
|
|
528
|
-
|
|
529
|
-
{#if showEditFrameOptions}
|
|
530
|
-
<div aria-label="mutable local position">
|
|
531
|
-
<Point
|
|
532
|
-
value={{
|
|
533
|
-
x: localPose.x,
|
|
534
|
-
y: localPose.y,
|
|
535
|
-
z: localPose.z,
|
|
536
|
-
}}
|
|
537
|
-
on:change={handlePositionChange}
|
|
538
|
-
/>
|
|
539
|
-
</div>
|
|
487
|
+
{#key entity}
|
|
488
|
+
<div aria-label="mutable parent frame">
|
|
489
|
+
<List
|
|
490
|
+
options={configFrames.getParentFrameOptions(name.current ?? '') ?? []}
|
|
491
|
+
value={parent.current ?? 'world'}
|
|
492
|
+
on:change={handleParentChange}
|
|
493
|
+
/>
|
|
494
|
+
</div>
|
|
495
|
+
{/key}
|
|
540
496
|
{:else}
|
|
541
497
|
<div class="mt-0.5 flex gap-3">
|
|
542
498
|
{@render ImmutableField({
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
value: localPose.x,
|
|
546
|
-
})}
|
|
547
|
-
{@render ImmutableField({
|
|
548
|
-
label: 'y',
|
|
549
|
-
ariaLabel: 'local position y coordinate',
|
|
550
|
-
value: localPose.y,
|
|
551
|
-
})}
|
|
552
|
-
{@render ImmutableField({
|
|
553
|
-
label: 'z',
|
|
554
|
-
ariaLabel: 'local position z coordinate',
|
|
555
|
-
value: localPose.z,
|
|
499
|
+
ariaLabel: 'parent frame name',
|
|
500
|
+
value: parent.current ?? 'world',
|
|
556
501
|
})}
|
|
557
502
|
</div>
|
|
558
503
|
{/if}
|
|
559
504
|
</div>
|
|
560
505
|
|
|
561
|
-
|
|
562
|
-
<
|
|
506
|
+
{#if localPose}
|
|
507
|
+
<div>
|
|
508
|
+
<strong class="font-semibold">local position</strong>
|
|
509
|
+
<span class="text-subtle-2">(mm)</span>
|
|
510
|
+
|
|
511
|
+
{#if showEditFrameOptions}
|
|
512
|
+
<div aria-label="mutable local position">
|
|
513
|
+
<Point
|
|
514
|
+
value={{
|
|
515
|
+
x: localPose.x,
|
|
516
|
+
y: localPose.y,
|
|
517
|
+
z: localPose.z,
|
|
518
|
+
}}
|
|
519
|
+
on:change={handlePositionChange}
|
|
520
|
+
/>
|
|
521
|
+
</div>
|
|
522
|
+
{:else}
|
|
523
|
+
<div class="mt-0.5 flex gap-3">
|
|
524
|
+
{@render ImmutableField({
|
|
525
|
+
label: 'x',
|
|
526
|
+
ariaLabel: 'local position x coordinate',
|
|
527
|
+
value: localPose.x,
|
|
528
|
+
})}
|
|
529
|
+
{@render ImmutableField({
|
|
530
|
+
label: 'y',
|
|
531
|
+
ariaLabel: 'local position y coordinate',
|
|
532
|
+
value: localPose.y,
|
|
533
|
+
})}
|
|
534
|
+
{@render ImmutableField({
|
|
535
|
+
label: 'z',
|
|
536
|
+
ariaLabel: 'local position z coordinate',
|
|
537
|
+
value: localPose.z,
|
|
538
|
+
})}
|
|
539
|
+
</div>
|
|
540
|
+
{/if}
|
|
541
|
+
</div>
|
|
563
542
|
|
|
564
|
-
|
|
565
|
-
<
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
543
|
+
<div>
|
|
544
|
+
<strong class="font-semibold">local orientation</strong>
|
|
545
|
+
|
|
546
|
+
{#if showEditFrameOptions}
|
|
547
|
+
<div aria-label="mutable local orientation">
|
|
548
|
+
<TabGroup>
|
|
549
|
+
<TabPage title="OV (deg)">
|
|
550
|
+
<Point
|
|
551
|
+
value={{
|
|
552
|
+
x: localPose.oX,
|
|
553
|
+
y: localPose.oY,
|
|
554
|
+
z: localPose.oZ,
|
|
555
|
+
w: localPose.theta,
|
|
556
|
+
}}
|
|
557
|
+
on:change={handleOrientationOVChange}
|
|
558
|
+
/>
|
|
559
|
+
</TabPage>
|
|
560
|
+
<TabPage title="Euler">
|
|
561
|
+
<RotationEuler
|
|
562
|
+
value={eulerValue}
|
|
563
|
+
unit="deg"
|
|
564
|
+
on:change={handleOrientationEulerChange}
|
|
565
|
+
/>
|
|
566
|
+
</TabPage>
|
|
567
|
+
</TabGroup>
|
|
568
|
+
</div>
|
|
569
|
+
{:else}
|
|
570
|
+
<div class="mt-0.5 flex gap-3">
|
|
571
|
+
{@render ImmutableField({
|
|
572
|
+
label: 'x',
|
|
573
|
+
ariaLabel: 'local orientation x coordinate',
|
|
574
|
+
value: localPose.oX,
|
|
575
|
+
})}
|
|
576
|
+
{@render ImmutableField({
|
|
577
|
+
label: 'y',
|
|
578
|
+
ariaLabel: 'local orientation y coordinate',
|
|
579
|
+
value: localPose.oY,
|
|
580
|
+
})}
|
|
581
|
+
{@render ImmutableField({
|
|
582
|
+
label: 'z',
|
|
583
|
+
ariaLabel: 'local orientation z coordinate',
|
|
584
|
+
value: localPose.oZ,
|
|
585
|
+
})}
|
|
586
|
+
{@render ImmutableField({
|
|
587
|
+
label: 'th',
|
|
588
|
+
ariaLabel: 'local orientation theta degrees',
|
|
589
|
+
value: localPose.theta,
|
|
590
|
+
})}
|
|
591
|
+
</div>
|
|
592
|
+
{/if}
|
|
593
|
+
</div>
|
|
594
|
+
{/if}
|
|
612
595
|
{/if}
|
|
613
596
|
|
|
614
597
|
{#if showEditFrameOptions}
|
|
@@ -718,20 +701,6 @@
|
|
|
718
701
|
</div>
|
|
719
702
|
{/if}
|
|
720
703
|
|
|
721
|
-
<div>
|
|
722
|
-
<strong class="font-semibold">opacity</strong>
|
|
723
|
-
<div aria-label="mutable opacity">
|
|
724
|
-
<Slider
|
|
725
|
-
value={opacityValue}
|
|
726
|
-
min={0}
|
|
727
|
-
max={1}
|
|
728
|
-
step={0.01}
|
|
729
|
-
format={(v) => v.toFixed(2)}
|
|
730
|
-
on:change={handleOpacityChange}
|
|
731
|
-
/>
|
|
732
|
-
</div>
|
|
733
|
-
</div>
|
|
734
|
-
|
|
735
704
|
{#if isInstanceOf(object3d, 'Points')}
|
|
736
705
|
<div>
|
|
737
706
|
<strong class="font-semibold">points</strong>
|
|
@@ -744,27 +713,32 @@
|
|
|
744
713
|
})}
|
|
745
714
|
</div>
|
|
746
715
|
{/if}
|
|
716
|
+
|
|
717
|
+
<PortalTarget id="details-extensions" />
|
|
718
|
+
|
|
719
|
+
{#if !customDetails.current}
|
|
720
|
+
<OpacityDetails {entity} />
|
|
721
|
+
<AxesHelperDetails {entity} />
|
|
722
|
+
{/if}
|
|
747
723
|
</div>
|
|
748
724
|
|
|
749
725
|
{#if linkedEntities.current.length > 0}
|
|
750
726
|
<h3 class="text-subtle-2 pt-3 pb-2">Relationships</h3>
|
|
751
727
|
|
|
752
|
-
<div>
|
|
753
|
-
<
|
|
754
|
-
|
|
755
|
-
{
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
<
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
{/each}
|
|
767
|
-
</div>
|
|
728
|
+
<div class="mt-0.5 flex flex-col gap-1">
|
|
729
|
+
<strong class="font-semibold">Linked entities</strong>
|
|
730
|
+
{#each linkedEntities.current as linkedEntity (linkedEntity)}
|
|
731
|
+
{@const linkedEntityName = linkedEntity.get(traits.Name)}
|
|
732
|
+
{@const linkType = entity.get(relations.SubEntityLink(linkedEntity))?.type}
|
|
733
|
+
<div class="flex items-center gap-1">
|
|
734
|
+
<span class="text-primary">{linkedEntityName} ({linkType})</span>
|
|
735
|
+
<Icon
|
|
736
|
+
name="trash-can-outline"
|
|
737
|
+
class="h-6 cursor-pointer px-2 py-1 text-xs text-red-500"
|
|
738
|
+
onclick={() => entity.remove(relations.SubEntityLink(linkedEntity))}
|
|
739
|
+
/>
|
|
740
|
+
</div>
|
|
741
|
+
{/each}
|
|
768
742
|
</div>
|
|
769
743
|
{/if}
|
|
770
744
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Entity } from 'koota';
|
|
2
1
|
import type { Snippet } from 'svelte';
|
|
3
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Entity } from 'koota';
|
|
4
4
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
5
|
entity: Entity;
|
|
6
6
|
details?: Snippet<[{
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
import { normalizeProps, portal, useMachine } from '@zag-js/svelte'
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
|
-
trigger: Snippet<[HTMLButtonAttributes]>
|
|
10
|
-
children: Snippet
|
|
9
|
+
trigger: Snippet<[HTMLButtonAttributes, { isOpen: boolean }]>
|
|
10
|
+
children: Snippet<[{ close: () => void }]>
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
let { children, trigger }: Props = $props()
|
|
@@ -15,15 +15,17 @@
|
|
|
15
15
|
const id = $props.id()
|
|
16
16
|
const service = useMachine(popover.machine, { id })
|
|
17
17
|
const api = $derived(popover.connect(service, normalizeProps))
|
|
18
|
+
|
|
19
|
+
const close = () => api.setOpen(false)
|
|
18
20
|
</script>
|
|
19
21
|
|
|
20
|
-
{@render trigger(api.getTriggerProps())}
|
|
22
|
+
{@render trigger(api.getTriggerProps(), { isOpen: api.open })}
|
|
21
23
|
|
|
22
24
|
<div
|
|
23
25
|
use:portal={{ disabled: !api.portalled }}
|
|
24
26
|
{...api.getPositionerProps()}
|
|
25
27
|
>
|
|
26
28
|
<div {...api.getContentProps()}>
|
|
27
|
-
{@render children()}
|
|
29
|
+
{@render children({ close })}
|
|
28
30
|
</div>
|
|
29
31
|
</div>
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
|
3
3
|
interface Props {
|
|
4
|
-
trigger: Snippet<[HTMLButtonAttributes
|
|
5
|
-
|
|
4
|
+
trigger: Snippet<[HTMLButtonAttributes, {
|
|
5
|
+
isOpen: boolean;
|
|
6
|
+
}]>;
|
|
7
|
+
children: Snippet<[{
|
|
8
|
+
close: () => void;
|
|
9
|
+
}]>;
|
|
6
10
|
}
|
|
7
11
|
declare const Popover: import("svelte").Component<Props, {}, "">;
|
|
8
12
|
type Popover = ReturnType<typeof Popover>;
|
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements'
|
|
3
3
|
|
|
4
4
|
import { Icon, type IconName, Tooltip } from '@viamrobotics/prime-core'
|
|
5
|
-
import { Focus, MousePointer2, Ruler } from 'lucide-svelte'
|
|
5
|
+
import { Focus, MousePointer2, Ruler, Shapes } from 'lucide-svelte'
|
|
6
6
|
|
|
7
7
|
interface Props extends HTMLButtonAttributes {
|
|
8
|
-
icon: IconName | 'ruler' | 'mouse-pointer' | 'focus'
|
|
8
|
+
icon: IconName | 'ruler' | 'mouse-pointer' | 'shapes' | 'focus'
|
|
9
9
|
active?: boolean
|
|
10
10
|
description: string
|
|
11
11
|
hotkey?: string
|
|
12
12
|
class?: ClassValue | null | undefined
|
|
13
13
|
tooltipLocation?: 'bottom' | 'right' | 'left' | 'top'
|
|
14
|
+
disableTooltip?: boolean
|
|
14
15
|
onclick?: MouseEventHandler<HTMLButtonElement> | null | undefined
|
|
15
16
|
}
|
|
16
17
|
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
hotkey = '',
|
|
22
23
|
class: className = '',
|
|
23
24
|
tooltipLocation,
|
|
25
|
+
disableTooltip = false,
|
|
24
26
|
onclick,
|
|
25
27
|
...rest
|
|
26
28
|
}: Props = $props()
|
|
@@ -29,6 +31,7 @@
|
|
|
29
31
|
<Tooltip
|
|
30
32
|
let:tooltipID
|
|
31
33
|
location={tooltipLocation ?? 'bottom'}
|
|
34
|
+
state={disableTooltip ? 'invisible' : undefined}
|
|
32
35
|
>
|
|
33
36
|
<label
|
|
34
37
|
class={[
|
|
@@ -50,6 +53,8 @@
|
|
|
50
53
|
<Ruler size="16" />
|
|
51
54
|
{:else if icon === 'mouse-pointer'}
|
|
52
55
|
<MousePointer2 size="16" />
|
|
56
|
+
{:else if icon === 'shapes'}
|
|
57
|
+
<Shapes size="16" />
|
|
53
58
|
{:else if icon === 'focus'}
|
|
54
59
|
<Focus size="16" />
|
|
55
60
|
{:else}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
|
2
2
|
import { type IconName } from '@viamrobotics/prime-core';
|
|
3
3
|
interface Props extends HTMLButtonAttributes {
|
|
4
|
-
icon: IconName | 'ruler' | 'mouse-pointer' | 'focus';
|
|
4
|
+
icon: IconName | 'ruler' | 'mouse-pointer' | 'shapes' | 'focus';
|
|
5
5
|
active?: boolean;
|
|
6
6
|
description: string;
|
|
7
7
|
hotkey?: string;
|
|
8
8
|
class?: ClassValue | null | undefined;
|
|
9
9
|
tooltipLocation?: 'bottom' | 'right' | 'left' | 'top';
|
|
10
|
+
disableTooltip?: boolean;
|
|
10
11
|
onclick?: MouseEventHandler<HTMLButtonElement> | null | undefined;
|
|
11
12
|
}
|
|
12
13
|
declare const Button: import("svelte").Component<Props, {}, "">;
|