@viamrobotics/motion-tools 0.9.2 → 0.9.4
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/README.md +2 -1
- package/dist/components/App.svelte +15 -1
- package/dist/components/App.svelte.d.ts +1 -0
- package/dist/components/Camera.svelte +7 -1
- package/dist/components/Camera.svelte.d.ts +1 -0
- package/dist/components/CameraControls.svelte +15 -1
- package/dist/components/PointerMissBox.svelte +34 -0
- package/dist/components/PointerMissBox.svelte.d.ts +18 -0
- package/dist/components/Scene.svelte +2 -0
- package/dist/components/SceneProviders.svelte +0 -2
- package/dist/components/Selected.svelte +37 -29
- package/dist/components/Tree/Settings.svelte +3 -0
- package/dist/components/portal/usePortalContext.svelte.js +2 -5
- package/dist/hooks/useObjectEvents.svelte.d.ts +0 -1
- package/dist/hooks/useObjectEvents.svelte.js +0 -6
- package/dist/hooks/useSettings.svelte.d.ts +4 -2
- package/dist/hooks/useSettings.svelte.js +6 -2
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## motion-tools
|
|
2
2
|
|
|
3
|
-
`motion-tools`
|
|
3
|
+
`motion-tools` aims to provide a visualization interface for any spatial information using Viam's APIs. This typically means motion-related monitoring, testing, and debugging.
|
|
4
4
|
|
|
5
5
|
### Getting started
|
|
6
6
|
|
|
@@ -30,6 +30,7 @@ VITE_CONFIGS='
|
|
|
30
30
|
"signalingAddress": "https://app.viam.com:443"
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
'
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
### Executing drawing commands
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte'
|
|
3
3
|
import { Canvas } from '@threlte/core'
|
|
4
|
+
import { SvelteQueryDevtools } from '@tanstack/svelte-query-devtools'
|
|
5
|
+
|
|
4
6
|
import Scene from './Scene.svelte'
|
|
5
7
|
import TreeContainer from './Tree/TreeContainer.svelte'
|
|
6
8
|
import Details from './Details.svelte'
|
|
@@ -10,19 +12,31 @@
|
|
|
10
12
|
import { createPartIDContext } from '../hooks/usePartID.svelte'
|
|
11
13
|
import Dashboard from './dashboard/Dashboard.svelte'
|
|
12
14
|
import { domPortal } from '../portal'
|
|
15
|
+
import { provideSettings } from '../hooks/useSettings.svelte'
|
|
13
16
|
|
|
14
17
|
interface Props {
|
|
15
18
|
partID?: string
|
|
19
|
+
enableKeybindings?: boolean
|
|
16
20
|
children?: Snippet
|
|
17
21
|
}
|
|
18
22
|
|
|
19
|
-
let { partID = '', children: appChildren }: Props = $props()
|
|
23
|
+
let { partID = '', enableKeybindings = true, children: appChildren }: Props = $props()
|
|
24
|
+
|
|
25
|
+
const settings = provideSettings()
|
|
26
|
+
|
|
27
|
+
$effect(() => {
|
|
28
|
+
settings.current.enableKeybindings = enableKeybindings
|
|
29
|
+
})
|
|
20
30
|
|
|
21
31
|
createPartIDContext(() => partID)
|
|
22
32
|
|
|
23
33
|
let root = $state.raw<HTMLElement>()
|
|
24
34
|
</script>
|
|
25
35
|
|
|
36
|
+
{#if settings.current.enableQueryDevtools}
|
|
37
|
+
<SvelteQueryDevtools initialIsOpen />
|
|
38
|
+
{/if}
|
|
39
|
+
|
|
26
40
|
<div
|
|
27
41
|
class="relative h-full w-full overflow-hidden"
|
|
28
42
|
bind:this={root}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { T } from '@threlte/core'
|
|
2
|
+
import { T, useThrelte } from '@threlte/core'
|
|
3
3
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
4
|
+
import type { Camera } from 'three'
|
|
4
5
|
|
|
5
6
|
let { children, ...rest } = $props()
|
|
6
7
|
|
|
8
|
+
const { camera } = useThrelte()
|
|
7
9
|
const settings = useSettings()
|
|
8
10
|
const mode = $derived(settings.current.cameraMode)
|
|
11
|
+
|
|
12
|
+
$effect(() => {
|
|
13
|
+
;(window as unknown as { camera: Camera }).camera = $camera
|
|
14
|
+
})
|
|
9
15
|
</script>
|
|
10
16
|
|
|
11
17
|
{#if mode === 'perspective'}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { MathUtils } from 'three'
|
|
2
3
|
import { CameraControls, type CameraControlsRef, Gizmo } from '@threlte/extras'
|
|
3
4
|
import { useTransformControls } from '../hooks/useControls.svelte'
|
|
4
5
|
import KeyboardControls from './KeyboardControls.svelte'
|
|
5
6
|
import Portal from './portal/Portal.svelte'
|
|
6
7
|
import Button from './dashboard/Button.svelte'
|
|
7
8
|
import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
|
|
9
|
+
import { useSettings } from '../hooks/useSettings.svelte'
|
|
8
10
|
|
|
11
|
+
const settings = useSettings()
|
|
9
12
|
const drawAPI = useDrawAPI()
|
|
10
13
|
const transformControls = useTransformControls()
|
|
11
14
|
|
|
15
|
+
const enableKeybindings = $derived(settings.current.enableKeybindings)
|
|
16
|
+
|
|
12
17
|
let ref = $state.raw<CameraControlsRef>()
|
|
13
18
|
|
|
14
19
|
$effect(() => {
|
|
@@ -19,6 +24,13 @@
|
|
|
19
24
|
drawAPI.clearCamera()
|
|
20
25
|
}
|
|
21
26
|
})
|
|
27
|
+
|
|
28
|
+
$effect(() => {
|
|
29
|
+
if (ref) {
|
|
30
|
+
;(window as unknown as { MathUtils: typeof MathUtils }).MathUtils = MathUtils
|
|
31
|
+
;(window as unknown as { cameraControls: CameraControlsRef }).cameraControls = ref
|
|
32
|
+
}
|
|
33
|
+
})
|
|
22
34
|
</script>
|
|
23
35
|
|
|
24
36
|
<Portal id="dashboard">
|
|
@@ -39,7 +51,9 @@
|
|
|
39
51
|
enabled={!transformControls.active}
|
|
40
52
|
>
|
|
41
53
|
{#snippet children({ ref }: { ref: CameraControlsRef })}
|
|
42
|
-
|
|
54
|
+
{#if enableKeybindings}
|
|
55
|
+
<KeyboardControls cameraControls={ref} />
|
|
56
|
+
{/if}
|
|
43
57
|
<Gizmo />
|
|
44
58
|
{/snippet}
|
|
45
59
|
</CameraControls>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { BackSide, Vector3 } from 'three'
|
|
3
|
+
import { T, useThrelte } from '@threlte/core'
|
|
4
|
+
import { MeshDiscardMaterial } from '@threlte/extras'
|
|
5
|
+
import { useSelected } from '../hooks/useSelection.svelte'
|
|
6
|
+
import { useTransformControls } from '../hooks/useControls.svelte'
|
|
7
|
+
|
|
8
|
+
const { camera } = useThrelte()
|
|
9
|
+
const selected = useSelected()
|
|
10
|
+
const transformControls = useTransformControls()
|
|
11
|
+
const cameraDown = new Vector3()
|
|
12
|
+
|
|
13
|
+
const size = 1_000
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<T.Mesh
|
|
17
|
+
onpointerdown={() => {
|
|
18
|
+
cameraDown.copy(camera.current.position)
|
|
19
|
+
}}
|
|
20
|
+
onpointerup={() => {
|
|
21
|
+
if (transformControls.active) {
|
|
22
|
+
return
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (cameraDown.distanceToSquared(camera.current.position) > 0.2) {
|
|
26
|
+
return
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
selected.set()
|
|
30
|
+
}}
|
|
31
|
+
>
|
|
32
|
+
<T.BoxGeometry args={[size, size, size]} />
|
|
33
|
+
<MeshDiscardMaterial side={BackSide} />
|
|
34
|
+
</T.Mesh>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const PointerMissBox: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type PointerMissBox = InstanceType<typeof PointerMissBox>;
|
|
18
|
+
export default PointerMissBox;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
17
17
|
import CameraControls from './CameraControls.svelte'
|
|
18
18
|
import MeasureTool from './MeasureTool.svelte'
|
|
19
|
+
import PointerMissBox from './PointerMissBox.svelte'
|
|
19
20
|
|
|
20
21
|
interface Props {
|
|
21
22
|
children?: Snippet
|
|
@@ -66,6 +67,7 @@
|
|
|
66
67
|
<StaticGeometries />
|
|
67
68
|
|
|
68
69
|
<WorldObjects />
|
|
70
|
+
<PointerMissBox />
|
|
69
71
|
|
|
70
72
|
<Selected />
|
|
71
73
|
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
import { provideObjects } from '../hooks/useObjects.svelte'
|
|
14
14
|
import { provideMotionClient } from '../hooks/useMotionClient.svelte'
|
|
15
15
|
import { provideLogs } from '../hooks/useLogs.svelte'
|
|
16
|
-
import { provideSettings } from '../hooks/useSettings.svelte'
|
|
17
16
|
import { provideOrigin } from './xr/useOrigin.svelte'
|
|
18
17
|
|
|
19
18
|
interface Props {
|
|
@@ -24,7 +23,6 @@
|
|
|
24
23
|
|
|
25
24
|
const partID = usePartID()
|
|
26
25
|
|
|
27
|
-
provideSettings()
|
|
28
26
|
provideTransformControls()
|
|
29
27
|
provideVisibility()
|
|
30
28
|
provideMachineSettings()
|
|
@@ -1,48 +1,56 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Box3, Object3D } from 'three'
|
|
3
|
-
import { T, useTask
|
|
4
|
-
import { useSelectedObject } from '../hooks/useSelection.svelte'
|
|
3
|
+
import { T, useTask } from '@threlte/core'
|
|
4
|
+
import { useSelectedObject, useSelectedObject3d } from '../hooks/useSelection.svelte'
|
|
5
5
|
import { BoxHelper } from '../three/BoxHelper'
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const box3 = new Box3()
|
|
9
8
|
const box = new BoxHelper(new Object3D(), 0x000000)
|
|
10
9
|
const selected = useSelectedObject()
|
|
10
|
+
const selectedObject3d = useSelectedObject3d()
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
// Create a clone so that our bounding box doesn't include children
|
|
13
|
+
const clone = $derived.by(() => {
|
|
14
|
+
if (selected.current?.metadata.batched) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
return selectedObject3d.current?.clone(false)
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const { start, stop } = useTask(
|
|
22
|
+
() => {
|
|
23
|
+
if (selected.current === undefined) {
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (selected.current.metadata.batched) {
|
|
28
|
+
selected.current.metadata.getBoundingBoxAt?.(box3)
|
|
29
|
+
box.setFromBox3(box3)
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (clone) {
|
|
34
|
+
selectedObject3d.current?.getWorldPosition(clone.position)
|
|
35
|
+
selectedObject3d.current?.getWorldQuaternion(clone.quaternion)
|
|
36
|
+
box.setFromObject(clone)
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{ autoStart: false }
|
|
40
|
+
)
|
|
15
41
|
|
|
16
42
|
$effect.pre(() => {
|
|
17
43
|
if (selected.current) {
|
|
18
44
|
start()
|
|
45
|
+
box.visible = true
|
|
19
46
|
} else {
|
|
20
47
|
stop()
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
$effect.pre(() => {
|
|
25
|
-
if (!selected.current) {
|
|
26
48
|
box.visible = false
|
|
27
|
-
return
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
box.visible = true
|
|
31
|
-
|
|
32
|
-
if (selected.current.metadata.batched) {
|
|
33
|
-
selected.current.metadata.getBoundingBoxAt?.(box3)
|
|
34
|
-
box.setFromBox3(box3)
|
|
35
|
-
} else {
|
|
36
|
-
const object3d = scene.getObjectByProperty('uuid', selected.current.uuid)
|
|
37
|
-
if (object3d) {
|
|
38
|
-
// Create a clone so that our bounding box doesn't include children
|
|
39
|
-
const clone = object3d.clone(false)
|
|
40
|
-
object3d.getWorldPosition(clone.position)
|
|
41
|
-
object3d.getWorldQuaternion(clone.quaternion)
|
|
42
|
-
box.setFromObject(clone)
|
|
43
|
-
}
|
|
44
49
|
}
|
|
45
50
|
})
|
|
46
51
|
</script>
|
|
47
52
|
|
|
48
|
-
<T
|
|
53
|
+
<T
|
|
54
|
+
is={box}
|
|
55
|
+
raycast={() => null}
|
|
56
|
+
/>
|
|
@@ -155,6 +155,9 @@
|
|
|
155
155
|
|
|
156
156
|
<h3 class="pt-2 text-sm"><strong>Misc</strong></h3>
|
|
157
157
|
<div class="flex flex-col gap-2.5">
|
|
158
|
+
<label class="flex items-center justify-between gap-2">
|
|
159
|
+
Query devtools <Switch bind:on={settings.current.enableQueryDevtools} />
|
|
160
|
+
</label>
|
|
158
161
|
<label class="flex items-center justify-between gap-2">
|
|
159
162
|
Render stats <Switch bind:on={settings.current.renderStats} />
|
|
160
163
|
</label>
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { useThrelteUserContext } from '@threlte/core';
|
|
2
1
|
import { SvelteMap, SvelteSet } from 'svelte/reactivity';
|
|
3
|
-
const
|
|
4
|
-
return new SvelteMap();
|
|
5
|
-
};
|
|
2
|
+
const context = new SvelteMap();
|
|
6
3
|
export const usePortalContext = () => {
|
|
7
|
-
return
|
|
4
|
+
return context;
|
|
8
5
|
};
|
|
@@ -6,5 +6,4 @@ export declare const useObjectEvents: (uuid: () => string) => {
|
|
|
6
6
|
ondblclick: (event: IntersectionEvent<MouseEvent>) => void;
|
|
7
7
|
onpointerdown: (event: IntersectionEvent<MouseEvent>) => void;
|
|
8
8
|
onclick: (event: IntersectionEvent<MouseEvent>) => void;
|
|
9
|
-
onpointermissed: () => void;
|
|
10
9
|
};
|
|
@@ -11,14 +11,16 @@ interface Settings {
|
|
|
11
11
|
pointColor: string;
|
|
12
12
|
lineWidth: number;
|
|
13
13
|
lineDotSize: number;
|
|
14
|
-
enableXR: boolean;
|
|
15
14
|
enableMeasure: boolean;
|
|
16
15
|
enableLabels: boolean;
|
|
16
|
+
enableKeybindings: boolean;
|
|
17
|
+
enableQueryDevtools: boolean;
|
|
18
|
+
enableXR: boolean;
|
|
17
19
|
renderStats: boolean;
|
|
18
20
|
}
|
|
19
21
|
interface Context {
|
|
20
22
|
current: Settings;
|
|
21
23
|
}
|
|
22
|
-
export declare const provideSettings: () =>
|
|
24
|
+
export declare const provideSettings: () => Context;
|
|
23
25
|
export declare const useSettings: () => Context;
|
|
24
26
|
export {};
|
|
@@ -16,6 +16,8 @@ const defaults = () => ({
|
|
|
16
16
|
lineDotSize: 0.01,
|
|
17
17
|
enableMeasure: false,
|
|
18
18
|
enableLabels: false,
|
|
19
|
+
enableKeybindings: true,
|
|
20
|
+
enableQueryDevtools: false,
|
|
19
21
|
enableXR: false,
|
|
20
22
|
renderStats: false,
|
|
21
23
|
});
|
|
@@ -29,11 +31,13 @@ export const provideSettings = () => {
|
|
|
29
31
|
$effect(() => {
|
|
30
32
|
set('motion-tools-settings', $state.snapshot(settings));
|
|
31
33
|
});
|
|
32
|
-
|
|
34
|
+
const context = {
|
|
33
35
|
get current() {
|
|
34
36
|
return settings;
|
|
35
37
|
},
|
|
36
|
-
}
|
|
38
|
+
};
|
|
39
|
+
setContext(key, context);
|
|
40
|
+
return context;
|
|
37
41
|
};
|
|
38
42
|
export const useSettings = () => {
|
|
39
43
|
return getContext(key);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viamrobotics/motion-tools",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Motion visualization with Viam",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -87,7 +87,6 @@
|
|
|
87
87
|
"svelte": ">=5",
|
|
88
88
|
"svelte-virtuallists": ">=1"
|
|
89
89
|
},
|
|
90
|
-
"packageManager": "pnpm@8.15.6+sha256.01c01eeb990e379b31ef19c03e9d06a14afa5250b82e81303f88721c99ff2e6f",
|
|
91
90
|
"svelte": "./dist/index.js",
|
|
92
91
|
"types": "./dist/index.d.ts",
|
|
93
92
|
"exports": {
|