@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.
Files changed (132) hide show
  1. package/dist/components/App.svelte +17 -11
  2. package/dist/components/App.svelte.d.ts +14 -7
  3. package/dist/components/Entities/Entities.svelte +18 -25
  4. package/dist/components/Entities/Entities.svelte.d.ts +2 -17
  5. package/dist/components/Entities/Label.svelte +79 -13
  6. package/dist/components/Entities/Label.svelte.d.ts +2 -1
  7. package/dist/components/Entities/Labels.svelte +36 -0
  8. package/dist/components/Entities/Labels.svelte.d.ts +3 -0
  9. package/dist/components/Entities/LineDots.svelte +8 -3
  10. package/dist/components/Entities/labelLayout/applyTeleports.d.ts +9 -0
  11. package/dist/components/Entities/labelLayout/applyTeleports.js +39 -0
  12. package/dist/components/Entities/labelLayout/buildNeighborhood.d.ts +8 -0
  13. package/dist/components/Entities/labelLayout/buildNeighborhood.js +26 -0
  14. package/dist/components/Entities/labelLayout/cameraHash.d.ts +8 -0
  15. package/dist/components/Entities/labelLayout/cameraHash.js +25 -0
  16. package/dist/components/Entities/labelLayout/cost.d.ts +44 -0
  17. package/dist/components/Entities/labelLayout/cost.js +126 -0
  18. package/dist/components/Entities/labelLayout/createLabelLayout.d.ts +27 -0
  19. package/dist/components/Entities/labelLayout/createLabelLayout.js +194 -0
  20. package/dist/components/Entities/labelLayout/geometry.d.ts +20 -0
  21. package/dist/components/Entities/labelLayout/geometry.js +151 -0
  22. package/dist/components/Entities/labelLayout/labelStore.svelte.d.ts +17 -0
  23. package/dist/components/Entities/labelLayout/labelStore.svelte.js +28 -0
  24. package/dist/components/Entities/labelLayout/measure.d.ts +13 -0
  25. package/dist/components/Entities/labelLayout/measure.js +42 -0
  26. package/dist/components/Entities/labelLayout/slots.d.ts +11 -0
  27. package/dist/components/Entities/labelLayout/slots.js +47 -0
  28. package/dist/components/Entities/labelLayout/solve.d.ts +11 -0
  29. package/dist/components/Entities/labelLayout/solve.js +93 -0
  30. package/dist/components/Entities/labelLayout/spatialHash.d.ts +15 -0
  31. package/dist/components/Entities/labelLayout/spatialHash.js +53 -0
  32. package/dist/components/Entities/labelLayout/types.d.ts +105 -0
  33. package/dist/components/Entities/labelLayout/types.js +19 -0
  34. package/dist/components/Entities/labelLayout/writeBack.d.ts +20 -0
  35. package/dist/components/Entities/labelLayout/writeBack.js +51 -0
  36. package/dist/components/Scene.svelte +42 -48
  37. package/dist/components/SceneProviders.svelte +0 -3
  38. package/dist/components/SelectedTransformControls.svelte +65 -47
  39. package/dist/components/overlay/Details.svelte +198 -224
  40. package/dist/components/overlay/Details.svelte.d.ts +1 -1
  41. package/dist/components/overlay/Popover.svelte +6 -4
  42. package/dist/components/overlay/Popover.svelte.d.ts +6 -2
  43. package/dist/components/overlay/dashboard/Button.svelte +7 -2
  44. package/dist/components/overlay/dashboard/Button.svelte.d.ts +2 -1
  45. package/dist/components/overlay/details/AxesHelperDetails.svelte +32 -0
  46. package/dist/components/overlay/details/AxesHelperDetails.svelte.d.ts +7 -0
  47. package/dist/components/overlay/details/ColorDetails.svelte +35 -0
  48. package/dist/components/overlay/details/ColorDetails.svelte.d.ts +7 -0
  49. package/dist/components/overlay/details/GeometryDetails.svelte +104 -0
  50. package/dist/components/overlay/details/GeometryDetails.svelte.d.ts +7 -0
  51. package/dist/components/overlay/details/LineDetails/LineDetails.svelte +196 -0
  52. package/dist/components/overlay/details/LineDetails/LineDetails.svelte.d.ts +7 -0
  53. package/dist/components/overlay/details/LineDetails/linePositions.d.ts +3 -0
  54. package/dist/components/overlay/details/LineDetails/linePositions.js +30 -0
  55. package/dist/components/overlay/details/OpacityDetails.svelte +44 -0
  56. package/dist/components/overlay/details/OpacityDetails.svelte.d.ts +7 -0
  57. package/dist/components/overlay/details/PoseDetails.svelte +189 -0
  58. package/dist/components/overlay/details/PoseDetails.svelte.d.ts +14 -0
  59. package/dist/components/overlay/settings/ConnectionSettings.svelte +42 -0
  60. package/dist/components/overlay/settings/ConnectionSettings.svelte.d.ts +18 -0
  61. package/dist/components/overlay/settings/DebugSettings.svelte +13 -0
  62. package/dist/components/{xr/frame-configure/Controllers.svelte.d.ts → overlay/settings/DebugSettings.svelte.d.ts} +3 -3
  63. package/dist/components/overlay/settings/PointcloudSettings.svelte +61 -0
  64. package/dist/components/overlay/settings/PointcloudSettings.svelte.d.ts +3 -0
  65. package/dist/components/overlay/settings/SceneSettings.svelte +110 -0
  66. package/dist/components/overlay/settings/SceneSettings.svelte.d.ts +18 -0
  67. package/dist/components/overlay/settings/Settings.svelte +27 -312
  68. package/dist/components/overlay/settings/Settings.svelte.d.ts +8 -1
  69. package/dist/components/overlay/settings/Tabs.svelte +5 -3
  70. package/dist/components/overlay/settings/Tabs.svelte.d.ts +3 -3
  71. package/dist/components/overlay/settings/VisionSettings.svelte +31 -0
  72. package/dist/components/overlay/settings/VisionSettings.svelte.d.ts +3 -0
  73. package/dist/components/overlay/settings/WeblabSettings.svelte +27 -0
  74. package/dist/components/overlay/settings/WeblabSettings.svelte.d.ts +18 -0
  75. package/dist/components/overlay/settings/WidgetSettings.svelte +49 -0
  76. package/dist/components/overlay/settings/WidgetSettings.svelte.d.ts +3 -0
  77. package/dist/components/overlay/widgets/FramePov.svelte +1 -12
  78. package/dist/ecs/traits.d.ts +1 -1
  79. package/dist/ecs/traits.js +1 -1
  80. package/dist/hooks/useWorldState.svelte.js +39 -50
  81. package/dist/{components/xr → plugins/XR}/ArmTeleop.svelte +3 -5
  82. package/dist/plugins/XR/DebugPanel.svelte +29 -0
  83. package/dist/plugins/XR/DebugPanel.svelte.d.ts +3 -0
  84. package/dist/plugins/XR/OriginMarker.svelte +341 -0
  85. package/dist/plugins/XR/PendingEditsPanel.svelte +60 -0
  86. package/dist/plugins/XR/PendingEditsPanel.svelte.d.ts +18 -0
  87. package/dist/plugins/XR/WristDisplay.svelte +60 -0
  88. package/dist/plugins/XR/WristDisplay.svelte.d.ts +19 -0
  89. package/dist/{components/xr → plugins/XR}/XR.svelte +69 -23
  90. package/dist/plugins/XR/XRPlugins.svelte +9 -0
  91. package/dist/plugins/XR/XRPlugins.svelte.d.ts +26 -0
  92. package/dist/plugins/XR/XRSettings.svelte +240 -0
  93. package/dist/plugins/XR/XRSettings.svelte.d.ts +3 -0
  94. package/dist/{components/xr → plugins/XR}/XRToast.svelte +6 -9
  95. package/dist/plugins/XR/debug.svelte.d.ts +7 -0
  96. package/dist/plugins/XR/debug.svelte.js +13 -0
  97. package/dist/plugins/XR/frame-configure/Controllers.svelte +413 -0
  98. package/dist/plugins/XR/teleop/Controllers.svelte.d.ts +3 -0
  99. package/dist/{components/xr → plugins/XR}/useAnchors.svelte.d.ts +4 -0
  100. package/dist/{components/xr → plugins/XR}/useAnchors.svelte.js +22 -0
  101. package/dist/plugins/XR/useOrigin.svelte.d.ts +24 -0
  102. package/dist/plugins/XR/useOrigin.svelte.js +50 -0
  103. package/dist/plugins/index.d.ts +2 -0
  104. package/dist/plugins/index.js +2 -0
  105. package/dist/three/OBBHelper.js +1 -0
  106. package/package.json +3 -1
  107. package/dist/components/xr/OriginMarker.svelte +0 -151
  108. package/dist/components/xr/XRControllerSettings.svelte +0 -242
  109. package/dist/components/xr/XRControllerSettings.svelte.d.ts +0 -3
  110. package/dist/components/xr/frame-configure/Controllers.svelte +0 -6
  111. package/dist/components/xr/useOrigin.svelte.d.ts +0 -9
  112. package/dist/components/xr/useOrigin.svelte.js +0 -27
  113. /package/dist/{components/xr → plugins/XR}/ArmTeleop.svelte.d.ts +0 -0
  114. /package/dist/{components/xr → plugins/XR}/BentPlaneGeometry.svelte +0 -0
  115. /package/dist/{components/xr → plugins/XR}/BentPlaneGeometry.svelte.d.ts +0 -0
  116. /package/dist/{components/xr → plugins/XR}/CameraFeed.svelte +0 -0
  117. /package/dist/{components/xr → plugins/XR}/CameraFeed.svelte.d.ts +0 -0
  118. /package/dist/{components/xr → plugins/XR}/JointLimitsWidget.svelte +0 -0
  119. /package/dist/{components/xr → plugins/XR}/JointLimitsWidget.svelte.d.ts +0 -0
  120. /package/dist/{components/xr → plugins/XR}/OriginMarker.svelte.d.ts +0 -0
  121. /package/dist/{components/xr → plugins/XR}/PointDistance.svelte +0 -0
  122. /package/dist/{components/xr → plugins/XR}/PointDistance.svelte.d.ts +0 -0
  123. /package/dist/{components/xr → plugins/XR}/XR.svelte.d.ts +0 -0
  124. /package/dist/{components/xr → plugins/XR}/XRConfigPanel.svelte +0 -0
  125. /package/dist/{components/xr → plugins/XR}/XRConfigPanel.svelte.d.ts +0 -0
  126. /package/dist/{components/xr → plugins/XR}/XRToast.svelte.d.ts +0 -0
  127. /package/dist/{components/xr/teleop → plugins/XR/frame-configure}/Controllers.svelte.d.ts +0 -0
  128. /package/dist/{components/xr → plugins/XR}/math.d.ts +0 -0
  129. /package/dist/{components/xr → plugins/XR}/math.js +0 -0
  130. /package/dist/{components/xr → plugins/XR}/teleop/Controllers.svelte +0 -0
  131. /package/dist/{components/xr → plugins/XR}/toasts.svelte.d.ts +0 -0
  132. /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,7 @@
1
+ import type { Entity } from 'koota';
2
+ interface Props {
3
+ entity: Entity;
4
+ }
5
+ declare const AxesHelperDetails: import("svelte").Component<Props, {}, "">;
6
+ type AxesHelperDetails = ReturnType<typeof AxesHelperDetails>;
7
+ export default AxesHelperDetails;
@@ -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,7 @@
1
+ import type { Entity } from 'koota';
2
+ interface Props {
3
+ entity: Entity;
4
+ }
5
+ declare const ColorDetails: import("svelte").Component<Props, {}, "">;
6
+ type ColorDetails = ReturnType<typeof ColorDetails>;
7
+ export default ColorDetails;
@@ -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,7 @@
1
+ import type { Entity } from 'koota';
2
+ interface Props {
3
+ entity: Entity;
4
+ }
5
+ declare const GeometryDetails: import("svelte").Component<Props, {}, "">;
6
+ type GeometryDetails = ReturnType<typeof GeometryDetails>;
7
+ export default GeometryDetails;
@@ -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,7 @@
1
+ import type { Entity } from 'koota';
2
+ interface Props {
3
+ entity: Entity;
4
+ }
5
+ declare const LineDetails: import("svelte").Component<Props, {}, "">;
6
+ type LineDetails = ReturnType<typeof LineDetails>;
7
+ export default LineDetails;
@@ -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,7 @@
1
+ import type { Entity } from 'koota';
2
+ interface Props {
3
+ entity: Entity;
4
+ }
5
+ declare const OpacityDetails: import("svelte").Component<Props, {}, "">;
6
+ type OpacityDetails = ReturnType<typeof OpacityDetails>;
7
+ export default OpacityDetails;
@@ -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;