@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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
4
|
+
import { useThrelte } from '@threlte/core'
|
|
5
|
+
import { Switch } from '@viamrobotics/prime-core'
|
|
6
|
+
|
|
7
|
+
import { traits, useTrait } from '../../../ecs'
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
entity: Entity
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { entity }: Props = $props()
|
|
14
|
+
|
|
15
|
+
const { invalidate } = useThrelte()
|
|
16
|
+
|
|
17
|
+
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
18
|
+
|
|
19
|
+
const handleToggle = (next: boolean) => {
|
|
20
|
+
if (next) entity.add(traits.ShowAxesHelper)
|
|
21
|
+
else entity.remove(traits.ShowAxesHelper)
|
|
22
|
+
invalidate()
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div class="flex items-center justify-between">
|
|
27
|
+
<strong class="font-semibold">show axes helper</strong>
|
|
28
|
+
<Switch
|
|
29
|
+
on={showAxesHelper.current === true}
|
|
30
|
+
on:change={(event) => handleToggle(event.detail)}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
4
|
+
import { useThrelte } from '@threlte/core'
|
|
5
|
+
import { Color, type ColorChangeEvent, type ColorValueRgbObject } from 'svelte-tweakpane-ui'
|
|
6
|
+
|
|
7
|
+
import { traits, useTrait } from '../../../ecs'
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
entity: Entity
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { entity }: Props = $props()
|
|
14
|
+
|
|
15
|
+
const { invalidate } = useThrelte()
|
|
16
|
+
const color = useTrait(() => entity, traits.Color)
|
|
17
|
+
|
|
18
|
+
const handleColorChange = (event: ColorChangeEvent) => {
|
|
19
|
+
if (event.detail.origin !== 'internal') return
|
|
20
|
+
const next = event.detail.value as ColorValueRgbObject
|
|
21
|
+
entity.set(traits.Color, { r: next.r, g: next.g, b: next.b })
|
|
22
|
+
invalidate()
|
|
23
|
+
}
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
{#if color.current}
|
|
27
|
+
<div>
|
|
28
|
+
<strong class="font-semibold">color</strong>
|
|
29
|
+
<Color
|
|
30
|
+
value={color.current}
|
|
31
|
+
type="float"
|
|
32
|
+
on:change={handleColorChange}
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
4
|
+
import { useThrelte } from '@threlte/core'
|
|
5
|
+
import {
|
|
6
|
+
Point,
|
|
7
|
+
type PointChangeEvent,
|
|
8
|
+
type PointValue3dObject,
|
|
9
|
+
Slider,
|
|
10
|
+
type SliderChangeEvent,
|
|
11
|
+
} from 'svelte-tweakpane-ui'
|
|
12
|
+
|
|
13
|
+
import { traits, useTrait } from '../../../ecs'
|
|
14
|
+
|
|
15
|
+
interface Props {
|
|
16
|
+
entity: Entity
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { entity }: Props = $props()
|
|
20
|
+
|
|
21
|
+
const { invalidate } = useThrelte()
|
|
22
|
+
const box = useTrait(() => entity, traits.Box)
|
|
23
|
+
const sphere = useTrait(() => entity, traits.Sphere)
|
|
24
|
+
const capsule = useTrait(() => entity, traits.Capsule)
|
|
25
|
+
|
|
26
|
+
const handleBoxChange = (event: PointChangeEvent) => {
|
|
27
|
+
if (event.detail.origin !== 'internal') return
|
|
28
|
+
const next = event.detail.value as PointValue3dObject
|
|
29
|
+
entity.set(traits.Box, { x: next.x, y: next.y, z: next.z })
|
|
30
|
+
invalidate()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const handleSphereRChange = (event: SliderChangeEvent) => {
|
|
34
|
+
if (event.detail.origin !== 'internal') return
|
|
35
|
+
entity.set(traits.Sphere, { r: event.detail.value })
|
|
36
|
+
invalidate()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const handleCapsuleRChange = (event: SliderChangeEvent) => {
|
|
40
|
+
if (event.detail.origin !== 'internal') return
|
|
41
|
+
const current = capsule.current
|
|
42
|
+
if (!current) return
|
|
43
|
+
entity.set(traits.Capsule, { r: event.detail.value, l: current.l })
|
|
44
|
+
invalidate()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const handleCapsuleLChange = (event: SliderChangeEvent) => {
|
|
48
|
+
if (event.detail.origin !== 'internal') return
|
|
49
|
+
const current = capsule.current
|
|
50
|
+
if (!current) return
|
|
51
|
+
entity.set(traits.Capsule, { r: current.r, l: event.detail.value })
|
|
52
|
+
invalidate()
|
|
53
|
+
}
|
|
54
|
+
</script>
|
|
55
|
+
|
|
56
|
+
{#if box.current}
|
|
57
|
+
<div>
|
|
58
|
+
<strong class="font-semibold">dimensions</strong>
|
|
59
|
+
<span class="text-subtle-2">(box) (mm)</span>
|
|
60
|
+
<div aria-label="mutable box dimensions">
|
|
61
|
+
<Point
|
|
62
|
+
value={{
|
|
63
|
+
x: box.current.x,
|
|
64
|
+
y: box.current.y,
|
|
65
|
+
z: box.current.z,
|
|
66
|
+
}}
|
|
67
|
+
min={0}
|
|
68
|
+
on:change={handleBoxChange}
|
|
69
|
+
/>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
{:else if sphere.current}
|
|
73
|
+
<div>
|
|
74
|
+
<strong class="font-semibold">dimensions</strong>
|
|
75
|
+
<span class="text-subtle-2">(sphere) (mm)</span>
|
|
76
|
+
<div aria-label="mutable sphere dimensions">
|
|
77
|
+
<Slider
|
|
78
|
+
label="r"
|
|
79
|
+
value={sphere.current.r}
|
|
80
|
+
min={0}
|
|
81
|
+
on:change={handleSphereRChange}
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
{:else if capsule.current}
|
|
86
|
+
<div>
|
|
87
|
+
<strong class="font-semibold">dimensions</strong>
|
|
88
|
+
<span class="text-subtle-2">(capsule) (mm)</span>
|
|
89
|
+
<div aria-label="mutable capsule dimensions">
|
|
90
|
+
<Slider
|
|
91
|
+
label="r"
|
|
92
|
+
value={capsule.current.r}
|
|
93
|
+
min={0}
|
|
94
|
+
on:change={handleCapsuleRChange}
|
|
95
|
+
/>
|
|
96
|
+
<Slider
|
|
97
|
+
label="l"
|
|
98
|
+
value={capsule.current.l}
|
|
99
|
+
min={0}
|
|
100
|
+
on:change={handleCapsuleLChange}
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
4
|
+
import { useThrelte } from '@threlte/core'
|
|
5
|
+
import {
|
|
6
|
+
Color,
|
|
7
|
+
type ColorChangeEvent,
|
|
8
|
+
type ColorValueRgbObject,
|
|
9
|
+
Point,
|
|
10
|
+
type PointValue3dObject,
|
|
11
|
+
Slider,
|
|
12
|
+
type SliderChangeEvent,
|
|
13
|
+
} from 'svelte-tweakpane-ui'
|
|
14
|
+
|
|
15
|
+
import { traits, useTrait } from '../../../../ecs'
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
appendLinePosition as appendLinePositionPure,
|
|
19
|
+
removeLinePosition as removeLinePositionPure,
|
|
20
|
+
writeLinePosition as writeLinePositionPure,
|
|
21
|
+
} from './linePositions'
|
|
22
|
+
|
|
23
|
+
interface Props {
|
|
24
|
+
entity: Entity
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const { entity }: Props = $props()
|
|
28
|
+
|
|
29
|
+
const { invalidate } = useThrelte()
|
|
30
|
+
const linePositions = useTrait(() => entity, traits.LinePositions)
|
|
31
|
+
const lineWidth = useTrait(() => entity, traits.LineWidth)
|
|
32
|
+
const lineColor = useTrait(() => entity, traits.Color)
|
|
33
|
+
const dotSize = useTrait(() => entity, traits.DotSize)
|
|
34
|
+
const dotColors = useTrait(() => entity, traits.DotColors)
|
|
35
|
+
|
|
36
|
+
const linePositionList = $derived.by<PointValue3dObject[]>(() => {
|
|
37
|
+
const positions = linePositions.current
|
|
38
|
+
if (!positions) return []
|
|
39
|
+
const out: PointValue3dObject[] = []
|
|
40
|
+
for (let i = 0; i + 2 < positions.length; i += 3) {
|
|
41
|
+
out.push({ x: positions[i]!, y: positions[i + 1]!, z: positions[i + 2]! })
|
|
42
|
+
}
|
|
43
|
+
return out
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const dotColorValue = $derived.by<ColorValueRgbObject | undefined>(() => {
|
|
47
|
+
const colors = dotColors.current
|
|
48
|
+
if (!colors || colors.length < 3) return undefined
|
|
49
|
+
return { r: colors[0]! / 255, g: colors[1]! / 255, b: colors[2]! / 255 }
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
const writeLinePosition = (index: number, value: PointValue3dObject) => {
|
|
53
|
+
const current = linePositions.current
|
|
54
|
+
if (!current) return
|
|
55
|
+
entity.set(
|
|
56
|
+
traits.LinePositions,
|
|
57
|
+
writeLinePositionPure(current, index, value.x, value.y, value.z)
|
|
58
|
+
)
|
|
59
|
+
invalidate()
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const appendLinePosition = () => {
|
|
63
|
+
entity.set(
|
|
64
|
+
traits.LinePositions,
|
|
65
|
+
appendLinePositionPure(linePositions.current ?? new Float32Array())
|
|
66
|
+
)
|
|
67
|
+
invalidate()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const removeLinePosition = (index: number) => {
|
|
71
|
+
const current = linePositions.current
|
|
72
|
+
if (!current) return
|
|
73
|
+
const next = removeLinePositionPure(current, index)
|
|
74
|
+
if (next === current) return
|
|
75
|
+
entity.set(traits.LinePositions, next)
|
|
76
|
+
invalidate()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleLineWidthChange = (event: SliderChangeEvent) => {
|
|
80
|
+
if (event.detail.origin !== 'internal') return
|
|
81
|
+
entity.set(traits.LineWidth, event.detail.value)
|
|
82
|
+
invalidate()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const handleLineColorChange = (event: ColorChangeEvent) => {
|
|
86
|
+
if (event.detail.origin !== 'internal') return
|
|
87
|
+
const next = event.detail.value as ColorValueRgbObject
|
|
88
|
+
entity.set(traits.Color, { r: next.r, g: next.g, b: next.b })
|
|
89
|
+
invalidate()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const handleDotSizeChange = (event: SliderChangeEvent) => {
|
|
93
|
+
if (event.detail.origin !== 'internal') return
|
|
94
|
+
entity.set(traits.DotSize, event.detail.value)
|
|
95
|
+
invalidate()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const handleDotColorChange = (event: ColorChangeEvent) => {
|
|
99
|
+
if (event.detail.origin !== 'internal') return
|
|
100
|
+
const next = event.detail.value as ColorValueRgbObject
|
|
101
|
+
entity.set(
|
|
102
|
+
traits.DotColors,
|
|
103
|
+
new Uint8Array([Math.round(next.r * 255), Math.round(next.g * 255), Math.round(next.b * 255)])
|
|
104
|
+
)
|
|
105
|
+
invalidate()
|
|
106
|
+
}
|
|
107
|
+
</script>
|
|
108
|
+
|
|
109
|
+
{#if linePositions.current}
|
|
110
|
+
<details>
|
|
111
|
+
<summary class="cursor-pointer select-none">
|
|
112
|
+
<strong class="font-semibold">line positions</strong>
|
|
113
|
+
<span class="text-subtle-2">(m, {linePositionList.length})</span>
|
|
114
|
+
</summary>
|
|
115
|
+
<div
|
|
116
|
+
aria-label="mutable line positions"
|
|
117
|
+
class="mt-1"
|
|
118
|
+
>
|
|
119
|
+
<div class="flex max-h-48 flex-col gap-1 overflow-y-auto">
|
|
120
|
+
{#each linePositionList as position, index (index)}
|
|
121
|
+
<div class="flex items-end gap-1">
|
|
122
|
+
<div class="flex-1">
|
|
123
|
+
<Point
|
|
124
|
+
value={position}
|
|
125
|
+
on:change={(event) => {
|
|
126
|
+
if (event.detail.origin !== 'internal') return
|
|
127
|
+
writeLinePosition(index, event.detail.value as PointValue3dObject)
|
|
128
|
+
}}
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
<button
|
|
132
|
+
class="text-subtle-2 px-1 py-0.5 text-[10px] hover:text-red-500"
|
|
133
|
+
type="button"
|
|
134
|
+
aria-label={`remove position ${index + 1}`}
|
|
135
|
+
disabled={linePositionList.length <= 2}
|
|
136
|
+
onclick={() => removeLinePosition(index)}
|
|
137
|
+
>
|
|
138
|
+
×
|
|
139
|
+
</button>
|
|
140
|
+
</div>
|
|
141
|
+
{/each}
|
|
142
|
+
</div>
|
|
143
|
+
<button
|
|
144
|
+
class="border-medium hover:bg-light mt-1 border px-2 py-1 text-xs"
|
|
145
|
+
type="button"
|
|
146
|
+
onclick={appendLinePosition}
|
|
147
|
+
>
|
|
148
|
+
Add position
|
|
149
|
+
</button>
|
|
150
|
+
</div>
|
|
151
|
+
</details>
|
|
152
|
+
|
|
153
|
+
<div>
|
|
154
|
+
<strong class="font-semibold">line width</strong>
|
|
155
|
+
<Slider
|
|
156
|
+
value={lineWidth.current ?? 5}
|
|
157
|
+
min={0.1}
|
|
158
|
+
max={50}
|
|
159
|
+
step={0.1}
|
|
160
|
+
on:change={handleLineWidthChange}
|
|
161
|
+
/>
|
|
162
|
+
</div>
|
|
163
|
+
|
|
164
|
+
{#if lineColor.current}
|
|
165
|
+
<div>
|
|
166
|
+
<strong class="font-semibold">line color</strong>
|
|
167
|
+
<Color
|
|
168
|
+
value={lineColor.current}
|
|
169
|
+
type="float"
|
|
170
|
+
on:change={handleLineColorChange}
|
|
171
|
+
/>
|
|
172
|
+
</div>
|
|
173
|
+
{/if}
|
|
174
|
+
|
|
175
|
+
<div>
|
|
176
|
+
<strong class="font-semibold">dot size</strong>
|
|
177
|
+
<Slider
|
|
178
|
+
value={dotSize.current ?? 10}
|
|
179
|
+
min={0}
|
|
180
|
+
max={50}
|
|
181
|
+
step={0.1}
|
|
182
|
+
on:change={handleDotSizeChange}
|
|
183
|
+
/>
|
|
184
|
+
</div>
|
|
185
|
+
|
|
186
|
+
{#if dotColorValue}
|
|
187
|
+
<div>
|
|
188
|
+
<strong class="font-semibold">dot color</strong>
|
|
189
|
+
<Color
|
|
190
|
+
value={dotColorValue}
|
|
191
|
+
type="float"
|
|
192
|
+
on:change={handleDotColorChange}
|
|
193
|
+
/>
|
|
194
|
+
</div>
|
|
195
|
+
{/if}
|
|
196
|
+
{/if}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const writeLinePosition: (source: Float32Array, index: number, x: number, y: number, z: number) => Float32Array;
|
|
2
|
+
export declare const appendLinePosition: (source: Float32Array) => Float32Array;
|
|
3
|
+
export declare const removeLinePosition: (source: Float32Array, index: number) => Float32Array;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const writeLinePosition = (source, index, x, y, z) => {
|
|
2
|
+
if (index * 3 + 2 >= source.length)
|
|
3
|
+
return new Float32Array(source);
|
|
4
|
+
const next = new Float32Array(source);
|
|
5
|
+
next[index * 3 + 0] = x;
|
|
6
|
+
next[index * 3 + 1] = y;
|
|
7
|
+
next[index * 3 + 2] = z;
|
|
8
|
+
return next;
|
|
9
|
+
};
|
|
10
|
+
export const appendLinePosition = (source) => {
|
|
11
|
+
const next = new Float32Array(source.length + 3);
|
|
12
|
+
next.set(source);
|
|
13
|
+
const lastIndex = source.length - 3;
|
|
14
|
+
if (lastIndex >= 0) {
|
|
15
|
+
next[source.length + 0] = source[lastIndex] + 0.1;
|
|
16
|
+
next[source.length + 1] = source[lastIndex + 1];
|
|
17
|
+
next[source.length + 2] = source[lastIndex + 2];
|
|
18
|
+
}
|
|
19
|
+
return next;
|
|
20
|
+
};
|
|
21
|
+
export const removeLinePosition = (source, index) => {
|
|
22
|
+
if (source.length <= 6)
|
|
23
|
+
return source;
|
|
24
|
+
if (index * 3 + 2 >= source.length)
|
|
25
|
+
return source;
|
|
26
|
+
const next = new Float32Array(source.length - 3);
|
|
27
|
+
next.set(source.subarray(0, index * 3), 0);
|
|
28
|
+
next.set(source.subarray((index + 1) * 3), index * 3);
|
|
29
|
+
return next;
|
|
30
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
4
|
+
import { useThrelte } from '@threlte/core'
|
|
5
|
+
import { Slider, type SliderChangeEvent } from 'svelte-tweakpane-ui'
|
|
6
|
+
|
|
7
|
+
import { traits, useTrait } from '../../../ecs'
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
entity: Entity
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const { entity }: Props = $props()
|
|
14
|
+
|
|
15
|
+
const { invalidate } = useThrelte()
|
|
16
|
+
|
|
17
|
+
const opacity = useTrait(() => entity, traits.Opacity)
|
|
18
|
+
const opacityValue = $derived(opacity.current ?? 0.7)
|
|
19
|
+
|
|
20
|
+
const handleOpacityChange = (event: SliderChangeEvent) => {
|
|
21
|
+
if (event.detail.origin !== 'internal') return
|
|
22
|
+
const next = event.detail.value
|
|
23
|
+
if (entity.has(traits.Opacity)) {
|
|
24
|
+
entity.set(traits.Opacity, next)
|
|
25
|
+
} else {
|
|
26
|
+
entity.add(traits.Opacity(next))
|
|
27
|
+
}
|
|
28
|
+
invalidate()
|
|
29
|
+
}
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<div>
|
|
33
|
+
<strong class="font-semibold">opacity</strong>
|
|
34
|
+
<div aria-label="mutable opacity">
|
|
35
|
+
<Slider
|
|
36
|
+
value={opacityValue}
|
|
37
|
+
min={0}
|
|
38
|
+
max={1}
|
|
39
|
+
step={0.01}
|
|
40
|
+
format={(v) => v.toFixed(2)}
|
|
41
|
+
on:change={handleOpacityChange}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<script
|
|
2
|
+
module
|
|
3
|
+
lang="ts"
|
|
4
|
+
>
|
|
5
|
+
import { Euler, MathUtils, Quaternion } from 'three'
|
|
6
|
+
|
|
7
|
+
import { OrientationVector } from '../../../three/OrientationVector'
|
|
8
|
+
|
|
9
|
+
const quaternionUtil = new Quaternion()
|
|
10
|
+
const ovUtil = new OrientationVector()
|
|
11
|
+
const eulerUtil = new Euler()
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<script lang="ts">
|
|
15
|
+
import type { Pose } from '@viamrobotics/sdk'
|
|
16
|
+
import type { Entity } from 'koota'
|
|
17
|
+
|
|
18
|
+
import { useThrelte } from '@threlte/core'
|
|
19
|
+
import {
|
|
20
|
+
List,
|
|
21
|
+
type ListChangeEvent,
|
|
22
|
+
Point,
|
|
23
|
+
type PointChangeEvent,
|
|
24
|
+
type PointValue3dObject,
|
|
25
|
+
type PointValue4dObject,
|
|
26
|
+
RotationEuler,
|
|
27
|
+
type RotationEulerChangeEvent,
|
|
28
|
+
type RotationEulerValueObject,
|
|
29
|
+
TabGroup,
|
|
30
|
+
TabPage,
|
|
31
|
+
} from 'svelte-tweakpane-ui'
|
|
32
|
+
|
|
33
|
+
import { traits, useParentName, useTrait } from '../../../ecs'
|
|
34
|
+
import { createPose, matrixToPose } from '../../../transform'
|
|
35
|
+
|
|
36
|
+
interface Props {
|
|
37
|
+
entity: Entity
|
|
38
|
+
parentOptions: Array<{ value: string; text: string }>
|
|
39
|
+
onPoseChange: (patch: Partial<Pose>) => void
|
|
40
|
+
onParentChange: (parent: string) => void
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { entity, parentOptions, onPoseChange, onParentChange }: Props = $props()
|
|
44
|
+
|
|
45
|
+
const { invalidate } = useThrelte()
|
|
46
|
+
|
|
47
|
+
const matrix = useTrait(() => entity, traits.Matrix)
|
|
48
|
+
const editedMatrix = useTrait(() => entity, traits.EditedMatrix)
|
|
49
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
50
|
+
const center = useTrait(() => entity, traits.Center)
|
|
51
|
+
const parent = useParentName(() => entity)
|
|
52
|
+
|
|
53
|
+
const localPose = $derived.by<Pose | undefined>(() => {
|
|
54
|
+
const source = editedMatrix.current ?? matrix.current
|
|
55
|
+
if (source) return matrixToPose(source, createPose())
|
|
56
|
+
if (center.current) return createPose(center.current)
|
|
57
|
+
return undefined
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const worldPose = $derived.by<Pose | undefined>(() => {
|
|
61
|
+
if (!worldMatrix.current) return
|
|
62
|
+
return matrixToPose(worldMatrix.current, createPose())
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const eulerValue = $derived.by<RotationEulerValueObject>(() => {
|
|
66
|
+
if (!localPose) return { x: 0, y: 0, z: 0 }
|
|
67
|
+
ovUtil.set(localPose.oX, localPose.oY, localPose.oZ, MathUtils.degToRad(localPose.theta))
|
|
68
|
+
ovUtil.toEuler(eulerUtil)
|
|
69
|
+
return {
|
|
70
|
+
x: MathUtils.radToDeg(eulerUtil.x),
|
|
71
|
+
y: MathUtils.radToDeg(eulerUtil.y),
|
|
72
|
+
z: MathUtils.radToDeg(eulerUtil.z),
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
const applyLocal = (patch: Partial<Pose>) => {
|
|
77
|
+
onPoseChange(patch)
|
|
78
|
+
invalidate()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const handlePositionChange = (event: PointChangeEvent) => {
|
|
82
|
+
if (event.detail.origin !== 'internal') return
|
|
83
|
+
const next = event.detail.value as PointValue3dObject
|
|
84
|
+
applyLocal({ x: next.x, y: next.y, z: next.z })
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const handleOrientationOVChange = (event: PointChangeEvent) => {
|
|
88
|
+
if (event.detail.origin !== 'internal') return
|
|
89
|
+
const next = event.detail.value as PointValue4dObject
|
|
90
|
+
applyLocal({ oX: next.x, oY: next.y, oZ: next.z, theta: next.w })
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const handleParentChange = (event: ListChangeEvent) => {
|
|
94
|
+
if (event.detail.origin !== 'internal') return
|
|
95
|
+
const value = event.detail.value as string
|
|
96
|
+
if (value === parent.current) return
|
|
97
|
+
onParentChange(value)
|
|
98
|
+
invalidate()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const handleOrientationEulerChange = (event: RotationEulerChangeEvent) => {
|
|
102
|
+
if (event.detail.origin !== 'internal') return
|
|
103
|
+
const next = event.detail.value as RotationEulerValueObject
|
|
104
|
+
eulerUtil.set(
|
|
105
|
+
MathUtils.degToRad(next.x),
|
|
106
|
+
MathUtils.degToRad(next.y),
|
|
107
|
+
MathUtils.degToRad(next.z),
|
|
108
|
+
'ZYX'
|
|
109
|
+
)
|
|
110
|
+
quaternionUtil.setFromEuler(eulerUtil)
|
|
111
|
+
ovUtil.setFromQuaternion(quaternionUtil)
|
|
112
|
+
applyLocal({ oX: ovUtil.x, oY: ovUtil.y, oZ: ovUtil.z, theta: MathUtils.radToDeg(ovUtil.th) })
|
|
113
|
+
}
|
|
114
|
+
</script>
|
|
115
|
+
|
|
116
|
+
<div class="flex flex-col gap-2.5 text-xs">
|
|
117
|
+
<div>
|
|
118
|
+
<strong class="font-semibold">parent</strong>
|
|
119
|
+
{#key entity}
|
|
120
|
+
<div aria-label="mutable parent">
|
|
121
|
+
<List
|
|
122
|
+
options={parentOptions}
|
|
123
|
+
value={parent.current ?? 'world'}
|
|
124
|
+
on:change={handleParentChange}
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
{/key}
|
|
128
|
+
</div>
|
|
129
|
+
|
|
130
|
+
<div>
|
|
131
|
+
<strong class="font-semibold">world position</strong>
|
|
132
|
+
<span class="text-subtle-2">(mm)</span>
|
|
133
|
+
<div class="flex gap-3">
|
|
134
|
+
<div><span class="text-subtle-2">x</span> {(worldPose?.x ?? 0).toFixed(2)}</div>
|
|
135
|
+
<div><span class="text-subtle-2">y</span> {(worldPose?.y ?? 0).toFixed(2)}</div>
|
|
136
|
+
<div><span class="text-subtle-2">z</span> {(worldPose?.z ?? 0).toFixed(2)}</div>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div>
|
|
141
|
+
<strong class="font-semibold">world orientation</strong>
|
|
142
|
+
<span class="text-subtle-2">(deg)</span>
|
|
143
|
+
<div class="flex gap-3">
|
|
144
|
+
<div><span class="text-subtle-2">x</span> {(worldPose?.oX ?? 0).toFixed(2)}</div>
|
|
145
|
+
<div><span class="text-subtle-2">y</span> {(worldPose?.oY ?? 0).toFixed(2)}</div>
|
|
146
|
+
<div><span class="text-subtle-2">z</span> {(worldPose?.oZ ?? 0).toFixed(2)}</div>
|
|
147
|
+
<div><span class="text-subtle-2">th</span> {(worldPose?.theta ?? 0).toFixed(2)}</div>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
{#if localPose}
|
|
152
|
+
<div>
|
|
153
|
+
<strong class="font-semibold">local position</strong>
|
|
154
|
+
<span class="text-subtle-2">(mm)</span>
|
|
155
|
+
<div aria-label="mutable local position">
|
|
156
|
+
<Point
|
|
157
|
+
value={{ x: localPose.x, y: localPose.y, z: localPose.z }}
|
|
158
|
+
on:change={handlePositionChange}
|
|
159
|
+
/>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
|
|
163
|
+
<div>
|
|
164
|
+
<strong class="font-semibold">local orientation</strong>
|
|
165
|
+
<div aria-label="mutable local orientation">
|
|
166
|
+
<TabGroup>
|
|
167
|
+
<TabPage title="OV (deg)">
|
|
168
|
+
<Point
|
|
169
|
+
value={{
|
|
170
|
+
x: localPose.oX,
|
|
171
|
+
y: localPose.oY,
|
|
172
|
+
z: localPose.oZ,
|
|
173
|
+
w: localPose.theta,
|
|
174
|
+
}}
|
|
175
|
+
on:change={handleOrientationOVChange}
|
|
176
|
+
/>
|
|
177
|
+
</TabPage>
|
|
178
|
+
<TabPage title="Euler">
|
|
179
|
+
<RotationEuler
|
|
180
|
+
value={eulerValue}
|
|
181
|
+
unit="deg"
|
|
182
|
+
on:change={handleOrientationEulerChange}
|
|
183
|
+
/>
|
|
184
|
+
</TabPage>
|
|
185
|
+
</TabGroup>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
{/if}
|
|
189
|
+
</div>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Pose } from '@viamrobotics/sdk';
|
|
2
|
+
import type { Entity } from 'koota';
|
|
3
|
+
interface Props {
|
|
4
|
+
entity: Entity;
|
|
5
|
+
parentOptions: Array<{
|
|
6
|
+
value: string;
|
|
7
|
+
text: string;
|
|
8
|
+
}>;
|
|
9
|
+
onPoseChange: (patch: Partial<Pose>) => void;
|
|
10
|
+
onParentChange: (parent: string) => void;
|
|
11
|
+
}
|
|
12
|
+
declare const PoseDetails: import("svelte").Component<Props, {}, "">;
|
|
13
|
+
type PoseDetails = ReturnType<typeof PoseDetails>;
|
|
14
|
+
export default PoseDetails;
|