@viamrobotics/motion-tools 0.5.5 → 0.5.6

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.
@@ -1,5 +1,16 @@
1
- <script lang="ts">
1
+ <script
2
+ module
3
+ lang="ts"
4
+ >
5
+ import { OrientationVector } from '../three/OrientationVector'
2
6
  import { Quaternion, Vector3 } from 'three'
7
+
8
+ const vec3 = new Vector3()
9
+ const quaternion = new Quaternion()
10
+ const ov = new OrientationVector()
11
+ </script>
12
+
13
+ <script lang="ts">
3
14
  import { Check, Copy } from 'lucide-svelte'
4
15
  import { Button, Icon } from '@viamrobotics/prime-core'
5
16
  import {
@@ -10,7 +21,7 @@
10
21
  useSelectedObject3d,
11
22
  } from '../hooks/useSelection.svelte'
12
23
  import { useDraggable } from '../hooks/useDraggable.svelte'
13
- import { OrientationVector } from '../three/OrientationVector'
24
+ import { useTask } from '@threlte/core'
14
25
 
15
26
  const focused = useFocused()
16
27
  const focusedObject = useFocusedObject()
@@ -21,15 +32,42 @@
21
32
 
22
33
  const object = $derived(focusedObject.current ?? selectedObject.current)
23
34
  const object3d = $derived(focusedObject3d.current ?? selectedObject3d.current)
24
- const worldPosition = $derived(object3d?.getWorldPosition(new Vector3()))
25
- const worldQuaternion = $derived(object3d?.getWorldQuaternion(new Quaternion()))
26
- const worldOrientation = $derived(
27
- worldQuaternion ? new OrientationVector().setFromQuaternion(worldQuaternion) : undefined
28
- )
35
+ const worldPosition = $state({ x: 0, y: 0, z: 0 })
36
+ const worldOrientation = $state({ x: 0, y: 0, z: 1, th: 0 })
29
37
 
30
38
  let copied = $state(false)
31
39
 
32
40
  const draggable = useDraggable('details')
41
+
42
+ const { start, stop } = useTask(
43
+ () => {
44
+ object3d?.getWorldPosition(vec3)
45
+ if (!vec3.equals(worldPosition)) {
46
+ worldPosition.x = vec3.x
47
+ worldPosition.y = vec3.y
48
+ worldPosition.z = vec3.z
49
+ }
50
+
51
+ object3d?.getWorldQuaternion(quaternion)
52
+ ov.setFromQuaternion(quaternion)
53
+
54
+ if (!ov.equals(worldOrientation)) {
55
+ worldOrientation.x = ov.x
56
+ worldOrientation.y = ov.y
57
+ worldOrientation.z = ov.z
58
+ worldOrientation.th = ov.th
59
+ }
60
+ },
61
+ { autoStart: false }
62
+ )
63
+
64
+ $effect.pre(() => {
65
+ if (object3d) {
66
+ start()
67
+ } else {
68
+ stop()
69
+ }
70
+ })
33
71
  </script>
34
72
 
35
73
  {#if object}
@@ -1,12 +1,14 @@
1
1
  <script lang="ts">
2
2
  import { T } from '@threlte/core'
3
3
  import { TrackballControls, Gizmo } from '@threlte/extras'
4
- import { useFocusedObject3d } from '../hooks/useSelection.svelte'
5
- import { Box3, Vector3 } from 'three'
4
+ import { Box3, type Object3D, Vector3 } from 'three'
6
5
  import Camera from './Camera.svelte'
7
6
 
8
- const focusedObject = useFocusedObject3d()
9
- const object3d = $derived(focusedObject.current)
7
+ interface Props {
8
+ object3d: Object3D
9
+ }
10
+
11
+ let { object3d }: Props = $props()
10
12
 
11
13
  const box = new Box3()
12
14
  const vec = new Vector3()
@@ -14,22 +16,18 @@
14
16
  let center = $state.raw<[number, number, number]>([0, 0, 0])
15
17
  let size = $state.raw<[number, number, number]>([0, 0, 0])
16
18
 
17
- $effect(() => {
18
- if (object3d) {
19
- box.setFromObject(object3d)
20
- size = box.getSize(vec).toArray()
21
- center = box.getCenter(vec).toArray()
22
- }
19
+ $effect.pre(() => {
20
+ box.setFromObject(object3d)
21
+ size = box.getSize(vec).toArray()
22
+ center = box.getCenter(vec).toArray()
23
23
  })
24
24
  </script>
25
25
 
26
- <Camera position={[size[0], 0, 0]}>
26
+ <Camera position={[0, 0, size[0] + 1]}>
27
27
  <TrackballControls target={center}>
28
28
  <Gizmo />
29
29
  </TrackballControls>
30
30
  </Camera>
31
31
 
32
- {#if object3d}
33
- <T is={object3d} />
34
- <T.BoxHelper args={[object3d, 'red']} />
35
- {/if}
32
+ <T is={object3d} />
33
+ <T.BoxHelper args={[object3d, 'red']} />
@@ -1,3 +1,7 @@
1
- declare const Focus: import("svelte").Component<Record<string, never>, {}, "">;
1
+ import { type Object3D } from 'three';
2
+ interface Props {
3
+ object3d: Object3D;
4
+ }
5
+ declare const Focus: import("svelte").Component<Props, {}, "">;
2
6
  type Focus = ReturnType<typeof Focus>;
3
7
  export default Focus;
@@ -16,7 +16,7 @@
16
16
  import StaticGeometries from './StaticGeometries.svelte'
17
17
  import Shapes from './Shapes.svelte'
18
18
  import Camera from './Camera.svelte'
19
- import { useFocused } from '../hooks/useSelection.svelte'
19
+ import { useFocusedObject3d } from '../hooks/useSelection.svelte'
20
20
  import type { Snippet } from 'svelte'
21
21
  import { useXR } from '@threlte/xr'
22
22
  import { useTransformControls } from '../hooks/useControls.svelte'
@@ -39,10 +39,12 @@
39
39
  },
40
40
  })
41
41
 
42
- const focused = useFocused()
42
+ const focusedObject3d = useFocusedObject3d()
43
43
  const transformControls = useTransformControls()
44
44
  const origin = useOrigin()
45
45
 
46
+ const object3d = $derived(focusedObject3d.current)
47
+
46
48
  const { isPresenting } = useXR()
47
49
  </script>
48
50
 
@@ -56,7 +58,9 @@
56
58
  rotation.x={$isPresenting ? -Math.PI / 2 : 0}
57
59
  rotation.z={origin.rotation}
58
60
  >
59
- {#if focused.current === undefined}
61
+ {#if object3d}
62
+ <Focus {object3d} />
63
+ {:else}
60
64
  {#if !$isPresenting}
61
65
  <Camera position={[3, 3, 3]}>
62
66
  <CameraControls enabled={!transformControls.active}>
@@ -88,8 +92,6 @@
88
92
  fadeDistance={25}
89
93
  />
90
94
  {/if}
91
- {:else}
92
- <Focus />
93
95
  {/if}
94
96
 
95
97
  {@render children?.()}
@@ -39,7 +39,9 @@
39
39
  <TransformControls
40
40
  object={ref}
41
41
  {mode}
42
- onmouseDown={() => transformControls.setActive(true)}
42
+ onmouseDown={() => {
43
+ transformControls.setActive(true)
44
+ }}
43
45
  onmouseUp={() => {
44
46
  transformControls.setActive(false)
45
47
 
@@ -33,6 +33,8 @@ export const useObjectEvents = (uuid) => {
33
33
  selected.set(uuid());
34
34
  }
35
35
  },
36
- onpointermissed: () => selected.set(),
36
+ onpointermissed: () => {
37
+ selected.set();
38
+ },
37
39
  };
38
40
  };
@@ -7,6 +7,7 @@ const selectionKey = Symbol('selection-context');
7
7
  const focusKey = Symbol('focus-context');
8
8
  const selectedObjectKey = Symbol('selected-frame-context');
9
9
  const focusedObjectKey = Symbol('focused-frame-context');
10
+ const focusedObject3dKey = Symbol('focused-object-3d-context');
10
11
  export const provideSelection = () => {
11
12
  let selected = $state();
12
13
  let focused = $state();
@@ -46,13 +47,21 @@ export const provideSelection = () => {
46
47
  },
47
48
  };
48
49
  setContext(selectedObjectKey, selectedObjectContext);
49
- const focusedFrame = $derived(objects.current.find((object) => object.uuid === focused));
50
- const focusedFrameContext = {
50
+ const focusedObject = $derived(objects.current.find((object) => object.uuid === focused));
51
+ const focusedObjectContext = {
51
52
  get current() {
52
- return focusedFrame;
53
+ return focusedObject;
53
54
  },
54
55
  };
55
- setContext(focusedObjectKey, focusedFrameContext);
56
+ setContext(focusedObjectKey, focusedObjectContext);
57
+ const { scene } = useThrelte();
58
+ const uuid = $derived(focusedObject?.uuid);
59
+ const focusedObject3d = $derived(uuid ? scene.getObjectByProperty('uuid', uuid)?.clone() : undefined);
60
+ setContext(focusedObject3dKey, {
61
+ get current() {
62
+ return focusedObject3d;
63
+ },
64
+ });
56
65
  return {
57
66
  selection: selectionContext,
58
67
  focus: focusContext,
@@ -72,16 +81,7 @@ export const useSelectedObject = () => {
72
81
  return getContext(selectedObjectKey);
73
82
  };
74
83
  export const useFocusedObject3d = () => {
75
- const focusedObject = useFocusedObject();
76
- const { scene } = useThrelte();
77
- const object = $derived(focusedObject.current
78
- ? scene.getObjectByProperty('uuid', focusedObject.current.uuid)?.clone()
79
- : undefined);
80
- return {
81
- get current() {
82
- return object;
83
- },
84
- };
84
+ return getContext(focusedObject3dKey);
85
85
  };
86
86
  const matrix = new Matrix4();
87
87
  export const useSelectedObject3d = () => {
@@ -1,5 +1,11 @@
1
1
  import { Euler, Quaternion } from 'three';
2
2
  export declare const EPSILON = 0.0001;
3
+ type OrientationVectorLike = OrientationVector | {
4
+ x: number;
5
+ y: number;
6
+ z: number;
7
+ th: number;
8
+ };
3
9
  /**
4
10
  * Golang: https://github.com/viamrobotics/rdk/blob/main/spatialmath/orientationVector.go
5
11
  * Rust: https://github.com/viamrobotics/rust-utils/blob/main/src/spatialmath/utils.rs
@@ -62,6 +68,7 @@ export declare class OrientationVector {
62
68
  * Copies value of ov to this orientation vector.
63
69
  */
64
70
  copy(ov: OrientationVector): this;
71
+ equals(orientationVector: OrientationVectorLike): boolean;
65
72
  fromArray(array: number[], offset?: number): this;
66
73
  toArray(array?: number[], offset?: number): number[];
67
74
  toJson(): number[];
@@ -69,3 +76,4 @@ export declare class OrientationVector {
69
76
  toQuaternion(dest: Quaternion): Quaternion;
70
77
  toEuler(dest: Euler): Euler;
71
78
  }
79
+ export {};
@@ -151,6 +151,12 @@ export class OrientationVector {
151
151
  this.#onChangeCallback?.();
152
152
  return this;
153
153
  }
154
+ equals(orientationVector) {
155
+ return (this.x === orientationVector.x &&
156
+ this.y === orientationVector.y &&
157
+ this.z === orientationVector.z &&
158
+ this.th === orientationVector.th);
159
+ }
154
160
  fromArray(array, offset = 0) {
155
161
  this.#vec.set(array[offset] ?? 0, array[offset + 1] ?? 0, array[offset + 2] ?? 0);
156
162
  this.th = array[offset + 3] ?? 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -13,9 +13,9 @@
13
13
  "@eslint/compat": "1.3.1",
14
14
  "@eslint/js": "9.30.1",
15
15
  "@playwright/test": "1.53.2",
16
- "@sentry/sveltekit": "9.34.0",
17
- "@skeletonlabs/skeleton": "3.1.3",
18
- "@skeletonlabs/skeleton-svelte": "1.2.3",
16
+ "@sentry/sveltekit": "9.35.0",
17
+ "@skeletonlabs/skeleton": "3.1.4",
18
+ "@skeletonlabs/skeleton-svelte": "1.2.4",
19
19
  "@sveltejs/adapter-static": "3.0.8",
20
20
  "@sveltejs/kit": "2.22.2",
21
21
  "@sveltejs/package": "2.3.12",
@@ -26,21 +26,21 @@
26
26
  "@tanstack/svelte-query-devtools": "5.81.5",
27
27
  "@testing-library/jest-dom": "6.6.3",
28
28
  "@testing-library/svelte": "5.2.8",
29
- "@threlte/core": "8.0.5",
30
- "@threlte/extras": "9.4.0",
29
+ "@threlte/core": "8.1.2",
30
+ "@threlte/extras": "9.4.2",
31
31
  "@threlte/rapier": "3.1.4",
32
32
  "@threlte/xr": "1.0.8",
33
- "@types/bun": "1.2.17",
33
+ "@types/bun": "1.2.18",
34
34
  "@types/lodash-es": "4.17.12",
35
35
  "@types/three": "0.178.0",
36
- "@typescript-eslint/eslint-plugin": "8.35.1",
37
- "@typescript-eslint/parser": "8.35.1",
36
+ "@typescript-eslint/eslint-plugin": "8.36.0",
37
+ "@typescript-eslint/parser": "8.36.0",
38
38
  "@viamrobotics/prime-core": "0.1.5",
39
- "@viamrobotics/sdk": "0.45.0",
39
+ "@viamrobotics/sdk": "0.46.0",
40
40
  "@viamrobotics/svelte-sdk": "0.4.1",
41
41
  "@vitejs/plugin-basic-ssl": "2.1.0",
42
- "@zag-js/svelte": "1.18.1",
43
- "@zag-js/tree-view": "1.18.1",
42
+ "@zag-js/svelte": "1.18.2",
43
+ "@zag-js/tree-view": "1.18.2",
44
44
  "camera-controls": "2.10.1",
45
45
  "eslint": "9.30.1",
46
46
  "eslint-config-prettier": "10.1.5",
@@ -54,8 +54,8 @@
54
54
  "prettier-plugin-svelte": "3.4.0",
55
55
  "prettier-plugin-tailwindcss": "0.6.13",
56
56
  "publint": "0.3.12",
57
- "runed": "0.29.1",
58
- "svelte": "5.34.8",
57
+ "runed": "0.30.0",
58
+ "svelte": "5.35.4",
59
59
  "svelte-check": "4.2.2",
60
60
  "svelte-virtuallists": "1.4.2",
61
61
  "tailwindcss": "4.1.11",
@@ -63,7 +63,7 @@
63
63
  "threlte-uikit": "1.2.0",
64
64
  "tsx": "4.20.3",
65
65
  "typescript": "5.8.3",
66
- "typescript-eslint": "8.35.1",
66
+ "typescript-eslint": "8.36.0",
67
67
  "vite": "6.3.5",
68
68
  "vite-plugin-devtools-json": "0.2.1",
69
69
  "vite-plugin-mkcert": "1.17.8",