@viamrobotics/motion-tools 0.19.2 → 1.0.3

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 (150) hide show
  1. package/README.md +56 -26
  2. package/dist/FrameConfigUpdater.svelte.d.ts +11 -17
  3. package/dist/FrameConfigUpdater.svelte.js +109 -109
  4. package/dist/WorldObject.svelte.js +2 -15
  5. package/dist/common/v1/common_pb.d.ts +950 -0
  6. package/dist/common/v1/common_pb.js +1399 -0
  7. package/dist/components/App.svelte +38 -22
  8. package/dist/components/App.svelte.d.ts +1 -0
  9. package/dist/components/BatchedArrows.svelte +102 -0
  10. package/dist/components/BatchedArrows.svelte.d.ts +3 -0
  11. package/dist/components/CameraControls.svelte +2 -3
  12. package/dist/components/Details.svelte +364 -365
  13. package/dist/components/Entities.svelte +80 -0
  14. package/dist/components/{WorldObjects.svelte.d.ts → Entities.svelte.d.ts} +3 -3
  15. package/dist/components/FileDrop/FileDrop.svelte +96 -0
  16. package/dist/components/FileDrop/FileDrop.svelte.d.ts +4 -0
  17. package/dist/components/FileDrop/file-dropper.d.ts +36 -0
  18. package/dist/components/FileDrop/file-dropper.js +6 -0
  19. package/dist/components/FileDrop/file-names.d.ts +27 -0
  20. package/dist/components/FileDrop/file-names.js +85 -0
  21. package/dist/components/FileDrop/pcd-dropper.d.ts +2 -0
  22. package/dist/components/FileDrop/pcd-dropper.js +27 -0
  23. package/dist/components/FileDrop/ply-dropper.d.ts +2 -0
  24. package/dist/components/FileDrop/ply-dropper.js +27 -0
  25. package/dist/components/FileDrop/snapshot-dropper.d.ts +2 -0
  26. package/dist/components/FileDrop/snapshot-dropper.js +96 -0
  27. package/dist/components/FileDrop/useFileDrop.svelte.d.ts +9 -0
  28. package/dist/components/FileDrop/useFileDrop.svelte.js +97 -0
  29. package/dist/components/Focus.svelte +2 -3
  30. package/dist/components/Frame.svelte +41 -22
  31. package/dist/components/Frame.svelte.d.ts +4 -6
  32. package/dist/components/GLTF.svelte +36 -0
  33. package/dist/components/GLTF.svelte.d.ts +11 -0
  34. package/dist/components/Geometry2.svelte +206 -0
  35. package/dist/components/Geometry2.svelte.d.ts +18 -0
  36. package/dist/components/KeyboardControls.svelte +3 -3
  37. package/dist/components/Line.svelte +15 -14
  38. package/dist/components/Line.svelte.d.ts +2 -2
  39. package/dist/components/LiveUpdatesBanner.svelte +51 -15
  40. package/dist/components/MeasureTool.svelte +4 -5
  41. package/dist/components/Pointcloud.svelte +27 -14
  42. package/dist/components/Pointcloud.svelte.d.ts +2 -2
  43. package/dist/components/PointerMissBox.svelte +3 -3
  44. package/dist/components/Pose.svelte +31 -6
  45. package/dist/components/Pose.svelte.d.ts +2 -2
  46. package/dist/components/Scene.svelte +7 -6
  47. package/dist/components/SceneProviders.svelte +0 -6
  48. package/dist/components/Selected.svelte +22 -16
  49. package/dist/components/StaticGeometries.svelte +51 -27
  50. package/dist/components/Tree/Tree.svelte +51 -38
  51. package/dist/components/Tree/Tree.svelte.d.ts +3 -4
  52. package/dist/components/Tree/TreeContainer.svelte +75 -40
  53. package/dist/components/Tree/Widgets.svelte +2 -5
  54. package/dist/components/Tree/buildTree.d.ts +7 -6
  55. package/dist/components/Tree/buildTree.js +22 -41
  56. package/dist/components/__tests__/__fixtures__/entity.d.ts +2 -0
  57. package/dist/components/__tests__/__fixtures__/entity.js +20 -0
  58. package/dist/components/__tests__/__fixtures__/resource.d.ts +17 -0
  59. package/dist/components/__tests__/__fixtures__/resource.js +13 -0
  60. package/dist/components/dashboard/Dashboard.svelte +5 -3
  61. package/dist/components/dashboard/Dashboard.svelte.d.ts +7 -2
  62. package/dist/components/widgets/ArmPositions.svelte +19 -7
  63. package/dist/draw/v1/drawing_pb.d.ts +341 -0
  64. package/dist/draw/v1/drawing_pb.js +417 -0
  65. package/dist/draw/v1/metadata_pb.d.ts +23 -0
  66. package/dist/draw/v1/metadata_pb.js +39 -0
  67. package/dist/draw/v1/scene_pb.d.ts +230 -0
  68. package/dist/draw/v1/scene_pb.js +298 -0
  69. package/dist/draw/v1/snapshot_pb.d.ts +42 -0
  70. package/dist/draw/v1/snapshot_pb.js +61 -0
  71. package/dist/draw/v1/transforms_pb.d.ts +23 -0
  72. package/dist/draw/v1/transforms_pb.js +39 -0
  73. package/dist/ecs/index.d.ts +4 -0
  74. package/dist/ecs/index.js +4 -0
  75. package/dist/ecs/traits.d.ts +132 -0
  76. package/dist/ecs/traits.js +85 -0
  77. package/dist/ecs/useQuery.svelte.d.ts +4 -0
  78. package/dist/ecs/useQuery.svelte.js +49 -0
  79. package/dist/ecs/useTrait.svelte.d.ts +19 -0
  80. package/dist/ecs/useTrait.svelte.js +40 -0
  81. package/dist/ecs/useWorld.d.ts +4 -0
  82. package/dist/ecs/useWorld.js +10 -0
  83. package/dist/geometry.js +6 -6
  84. package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte +41 -0
  85. package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte.d.ts +6 -0
  86. package/dist/hooks/use3DModels.svelte.js +6 -4
  87. package/dist/hooks/useDrawAPI.svelte.d.ts +0 -10
  88. package/dist/hooks/useDrawAPI.svelte.js +143 -267
  89. package/dist/hooks/useFramelessComponents.svelte.js +1 -1
  90. package/dist/hooks/useFrames.svelte.d.ts +6 -2
  91. package/dist/hooks/useFrames.svelte.js +123 -19
  92. package/dist/hooks/useGeometries.svelte.d.ts +0 -2
  93. package/dist/hooks/useGeometries.svelte.js +49 -25
  94. package/dist/hooks/useObjectEvents.svelte.d.ts +3 -2
  95. package/dist/hooks/useObjectEvents.svelte.js +11 -7
  96. package/dist/hooks/usePartConfig.svelte.d.ts +1 -1
  97. package/dist/hooks/usePartConfig.svelte.js +2 -1
  98. package/dist/hooks/usePointclouds.svelte.d.ts +0 -2
  99. package/dist/hooks/usePointclouds.svelte.js +52 -21
  100. package/dist/hooks/usePose.svelte.js +15 -7
  101. package/dist/hooks/useResizable.svelte.d.ts +12 -0
  102. package/dist/hooks/useResizable.svelte.js +45 -0
  103. package/dist/hooks/useResourceByName.svelte.js +8 -5
  104. package/dist/hooks/useSelection.svelte.d.ts +13 -23
  105. package/dist/hooks/useSelection.svelte.js +45 -65
  106. package/dist/hooks/useVisibility.svelte.d.ts +2 -1
  107. package/dist/hooks/useWeblabs.svelte.d.ts +0 -1
  108. package/dist/hooks/useWeblabs.svelte.js +0 -1
  109. package/dist/hooks/useWorldState.svelte.d.ts +9 -0
  110. package/dist/hooks/useWorldState.svelte.js +158 -107
  111. package/dist/lib.d.ts +1 -0
  112. package/dist/lib.js +2 -0
  113. package/dist/three/BatchedArrow.d.ts +2 -3
  114. package/dist/three/BatchedArrow.js +3 -11
  115. package/dist/three/CapsuleGeometry.d.ts +1 -1
  116. package/dist/three/CapsuleGeometry.js +3 -1
  117. package/dist/transform.js +0 -15
  118. package/package.json +13 -7
  119. package/dist/components/FileDrop.svelte +0 -158
  120. package/dist/components/FileDrop.svelte.d.ts +0 -3
  121. package/dist/components/WorldObject.svelte +0 -28
  122. package/dist/components/WorldObject.svelte.d.ts +0 -11
  123. package/dist/components/WorldObjects.svelte +0 -159
  124. package/dist/components/WorldState.svelte +0 -92
  125. package/dist/components/WorldState.svelte.d.ts +0 -7
  126. package/dist/components/__tests__/__fixtures__/worldObject.svelte.d.ts +0 -2
  127. package/dist/components/__tests__/__fixtures__/worldObject.svelte.js +0 -35
  128. package/dist/components/portal/Portal.svelte +0 -25
  129. package/dist/components/portal/Portal.svelte.d.ts +0 -8
  130. package/dist/components/portal/PortalTarget.svelte +0 -18
  131. package/dist/components/portal/PortalTarget.svelte.d.ts +0 -6
  132. package/dist/components/portal/index.d.ts +0 -2
  133. package/dist/components/portal/index.js +0 -2
  134. package/dist/components/portal/usePortalContext.svelte.d.ts +0 -5
  135. package/dist/components/portal/usePortalContext.svelte.js +0 -5
  136. package/dist/hooks/useArrows.svelte.d.ts +0 -3
  137. package/dist/hooks/useArrows.svelte.js +0 -9
  138. package/dist/hooks/useDraggable.svelte.d.ts +0 -10
  139. package/dist/hooks/useDraggable.svelte.js +0 -36
  140. package/dist/hooks/useObjects.svelte.d.ts +0 -7
  141. package/dist/hooks/useObjects.svelte.js +0 -35
  142. package/dist/hooks/usePersistentUUIDs.svelte.d.ts +0 -5
  143. package/dist/hooks/usePersistentUUIDs.svelte.js +0 -13
  144. package/dist/hooks/useResourceByName.svelte.d.ts +0 -7
  145. package/dist/hooks/useStaticGeometries.svelte.d.ts +0 -9
  146. package/dist/hooks/useStaticGeometries.svelte.js +0 -47
  147. package/dist/workers/worldStateWorker.d.ts +0 -1
  148. package/dist/workers/worldStateWorker.js +0 -114
  149. package/dist/world-state-messages.d.ts +0 -23
  150. package/dist/world-state-messages.js +0 -1
@@ -6,7 +6,9 @@ import { LatheGeometry, Path } from 'three';
6
6
  */
7
7
  export class CapsuleGeometry extends LatheGeometry {
8
8
  type = 'CapsuleGeometry';
9
- constructor(radius = 1, length = 1, capSegments = 4, radialSegments = 8) {
9
+ constructor(r = 1, l = 1, capSegments = 4, radialSegments = 8) {
10
+ const radius = Math.max(0.0001, r);
11
+ const length = Math.max(0.0001, l);
10
12
  const path = new Path();
11
13
  const midsectionLength = length - 2 * radius;
12
14
  path.absarc(0, -midsectionLength / 2, radius, Math.PI * 1.5, 0);
package/dist/transform.js CHANGED
@@ -83,21 +83,6 @@ export const poseToDirection = (pose) => {
83
83
  ov.set(pose.oX, pose.oY, pose.oZ, MathUtils.degToRad(pose.theta));
84
84
  return new Vector3(ov.x, ov.y, ov.z);
85
85
  };
86
- export const scaleToDimensions = (scale, geometry) => {
87
- if (geometry.case === 'box') {
88
- geometry.value.dimsMm ??= { x: 0, y: 0, z: 0 };
89
- geometry.value.dimsMm.x *= scale.x;
90
- geometry.value.dimsMm.y *= scale.y;
91
- geometry.value.dimsMm.z *= scale.z;
92
- }
93
- else if (geometry.case === 'capsule') {
94
- geometry.value.radiusMm *= scale.x;
95
- geometry.value.lengthMm *= scale.y;
96
- }
97
- else if (geometry.case === 'sphere') {
98
- geometry.value.radiusMm *= scale.x;
99
- }
100
- };
101
86
  export const poseToMatrix = (pose) => {
102
87
  ov.set(pose.oX, pose.oY, pose.oZ, MathUtils.degToRad(pose.theta));
103
88
  ov.toQuaternion(quaternion);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viamrobotics/motion-tools",
3
- "version": "0.19.2",
3
+ "version": "1.0.3",
4
4
  "description": "Motion visualization with Viam",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -24,14 +24,15 @@
24
24
  "@tailwindcss/vite": "4.1.13",
25
25
  "@testing-library/jest-dom": "6.8.0",
26
26
  "@testing-library/svelte": "5.2.8",
27
+ "@testing-library/user-event": "^14.6.1",
27
28
  "@thi.ng/paths": "5.2.21",
28
- "@threlte/core": "8.1.5",
29
- "@threlte/extras": "9.5.4",
30
- "@threlte/rapier": "3.1.5",
29
+ "@threlte/core": "8.3.0",
30
+ "@threlte/extras": "9.7.0",
31
+ "@threlte/rapier": "3.2.0",
31
32
  "@threlte/xr": "1.0.8",
32
33
  "@types/bun": "1.2.21",
33
34
  "@types/lodash-es": "4.17.12",
34
- "@types/three": "0.179.0",
35
+ "@types/three": "0.181.0",
35
36
  "@typescript-eslint/eslint-plugin": "8.42.0",
36
37
  "@typescript-eslint/parser": "8.42.0",
37
38
  "@viamrobotics/prime-core": "0.1.5",
@@ -48,6 +49,7 @@
48
49
  "globals": "16.3.0",
49
50
  "idb-keyval": "6.2.2",
50
51
  "jsdom": "26.1.0",
52
+ "koota": "^0.5.3",
51
53
  "lodash-es": "4.17.21",
52
54
  "lucide-svelte": "0.542.0",
53
55
  "prettier": "3.6.2",
@@ -55,11 +57,11 @@
55
57
  "prettier-plugin-tailwindcss": "0.6.14",
56
58
  "publint": "0.3.12",
57
59
  "runed": "0.31.1",
58
- "svelte": "5.43.0",
60
+ "svelte": "5.45.9",
59
61
  "svelte-check": "4.3.1",
60
62
  "svelte-virtuallists": "1.4.2",
61
63
  "tailwindcss": "4.1.13",
62
- "three": "0.180.0",
64
+ "three": "0.182.0",
63
65
  "three-mesh-bvh": "^0.9.1",
64
66
  "threlte-uikit": "1.2.1",
65
67
  "tsx": "4.20.5",
@@ -117,6 +119,8 @@
117
119
  "!dist/**/*.spec.*"
118
120
  ],
119
121
  "dependencies": {
122
+ "@bufbuild/protobuf": "1.10.1",
123
+ "@neodrag/svelte": "^2.3.3",
120
124
  "@tanstack/svelte-query-devtools": "^6.0.2",
121
125
  "uuid-tool": "^2.0.3"
122
126
  },
@@ -130,9 +134,11 @@
130
134
  "lint": "prettier --check . && eslint .",
131
135
  "test:unit": "vitest",
132
136
  "test:client": "go test ./client/... -count=1",
137
+ "test:draw": "go test ./draw/... -count=1",
133
138
  "test": "pnpm test:unit -- --run",
134
139
  "test:coverage": "npx vitest run --coverage",
135
140
  "test:e2e": "playwright test",
141
+ "test:e2e-ui": "playwright test --ui",
136
142
  "model-pipeline:run": "node scripts/model-pipeline.js",
137
143
  "release": "changeset publish"
138
144
  }
@@ -1,158 +0,0 @@
1
- <script lang="ts">
2
- import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
3
- import { parsePcdInWorker, WorldObject } from '../lib'
4
- import { useToast, ToastVariant } from '@viamrobotics/prime-core'
5
- import { PLYLoader } from 'three/examples/jsm/Addons.js'
6
-
7
- let { ...rest } = $props()
8
-
9
- const { addPoints, addMesh } = useDrawAPI()
10
-
11
- type DropStates = 'inactive' | 'hovering' | 'loading'
12
-
13
- let dropState = $state<DropStates>('inactive')
14
-
15
- // prevent default to allow drop
16
- const ondragenter = (event: DragEvent) => {
17
- event.preventDefault()
18
- dropState = 'hovering'
19
- }
20
-
21
- // prevent default to allow drop
22
- const ondragover = (event: DragEvent) => {
23
- event.preventDefault()
24
- }
25
-
26
- const ondragleave = (event: DragEvent) => {
27
- // only deactivate if really leaving the window
28
- if (event.relatedTarget === null) {
29
- dropState = 'inactive'
30
- }
31
- }
32
-
33
- const toast = useToast()
34
-
35
- const extensions = {
36
- PCD: 'pcd',
37
- PLY: 'ply',
38
- }
39
- const supportedFiles = [extensions.PCD, extensions.PLY]
40
-
41
- const ondrop = (event: DragEvent) => {
42
- event.preventDefault()
43
-
44
- if (event.dataTransfer === null) {
45
- return
46
- }
47
-
48
- let completed = 0
49
-
50
- const { files } = event.dataTransfer
51
-
52
- for (const file of files) {
53
- const ext = file.name.split('.').at(-1)
54
-
55
- if (!ext) {
56
- toast({
57
- message: `Could not determine file extension.`,
58
- variant: ToastVariant.Danger,
59
- })
60
-
61
- continue
62
- }
63
-
64
- if (!supportedFiles.includes(ext)) {
65
- toast({
66
- message: `Only ${supportedFiles.map((file) => `.${file}`).join(', ')} files are supported.`,
67
- variant: ToastVariant.Danger,
68
- })
69
-
70
- continue
71
- }
72
-
73
- const reader = new FileReader()
74
-
75
- reader.addEventListener('loadend', () => {
76
- completed += 1
77
-
78
- if (completed === files.length) {
79
- dropState = 'inactive'
80
- }
81
- })
82
-
83
- reader.addEventListener('error', () => {
84
- toast({
85
- message: `${file.name} failed to load.`,
86
- variant: ToastVariant.Danger,
87
- })
88
- })
89
-
90
- reader.addEventListener('load', async (event) => {
91
- const arrayBuffer = event.target?.result
92
-
93
- if (!arrayBuffer || typeof arrayBuffer === 'string') {
94
- toast({
95
- message: `${file.name} failed to load.`,
96
- variant: ToastVariant.Danger,
97
- })
98
-
99
- return
100
- }
101
-
102
- if (ext === extensions.PCD) {
103
- const result = await parsePcdInWorker(new Uint8Array(arrayBuffer))
104
-
105
- addPoints(
106
- new WorldObject(
107
- file.name,
108
- undefined,
109
- undefined,
110
- {
111
- center: undefined,
112
- geometryType: {
113
- case: 'points',
114
- value: result.positions,
115
- },
116
- },
117
- result.colors ? { colors: result.colors } : undefined
118
- )
119
- )
120
-
121
- toast({ message: `Loaded ${file.name}`, variant: ToastVariant.Success })
122
- } else if (ext === extensions.PLY) {
123
- const result = new PLYLoader().parse(arrayBuffer)
124
- const worldObject = new WorldObject(file.name, undefined, undefined, {
125
- center: undefined,
126
- geometryType: { case: 'bufferGeometry', value: result },
127
- })
128
-
129
- addMesh(worldObject)
130
-
131
- toast({ message: `Loaded ${file.name}`, variant: ToastVariant.Success })
132
- }
133
- })
134
-
135
- reader.readAsArrayBuffer(file)
136
-
137
- dropState = 'loading'
138
- }
139
- }
140
- </script>
141
-
142
- <svelte:window
143
- {ondragenter}
144
- {ondragleave}
145
- {ondragover}
146
- />
147
-
148
- <div
149
- class={{
150
- 'fixed inset-0 z-9999 ': true,
151
- 'pointer-events-none': dropState === 'inactive',
152
- 'bg-black/10': dropState !== 'inactive',
153
- }}
154
- role="region"
155
- aria-label="File drop zone"
156
- {ondrop}
157
- {...rest}
158
- ></div>
@@ -1,3 +0,0 @@
1
- declare const FileDrop: import("svelte").Component<Record<string, any>, {}, "">;
2
- type FileDrop = ReturnType<typeof FileDrop>;
3
- export default FileDrop;
@@ -1,28 +0,0 @@
1
- <script lang="ts">
2
- import { T, type Props as ThrelteProps } from '@threlte/core'
3
- import type { Snippet } from 'svelte'
4
- import type { Object3D } from 'three'
5
- import type { WorldObject } from '../WorldObject.svelte'
6
- import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
7
-
8
- interface Props extends ThrelteProps<Object3D> {
9
- object: WorldObject
10
- children?: Snippet
11
- }
12
-
13
- let { object, children, ...rest }: Props = $props()
14
-
15
- const objectProps = useObjectEvents(() => object.uuid)
16
- </script>
17
-
18
- {#if object.metadata.gltf?.scene}
19
- <T
20
- is={object.metadata.gltf.scene}
21
- uuid={object.uuid}
22
- name={object.name}
23
- {...objectProps}
24
- {...rest}
25
- >
26
- {@render children?.()}
27
- </T>
28
- {/if}
@@ -1,11 +0,0 @@
1
- import { type Props as ThrelteProps } from '@threlte/core';
2
- import type { Snippet } from 'svelte';
3
- import type { Object3D } from 'three';
4
- import type { WorldObject } from '../WorldObject.svelte';
5
- interface Props extends ThrelteProps<Object3D> {
6
- object: WorldObject;
7
- children?: Snippet;
8
- }
9
- declare const WorldObject: import("svelte").Component<Props, {}, "">;
10
- type WorldObject = ReturnType<typeof WorldObject>;
11
- export default WorldObject;
@@ -1,159 +0,0 @@
1
- <script lang="ts">
2
- import { T } from '@threlte/core'
3
- import { Portal, PortalTarget } from './portal'
4
- import { useFrames } from '../hooks/useFrames.svelte'
5
- import { useGeometries } from '../hooks/useGeometries.svelte'
6
- import { usePointClouds } from '../hooks/usePointclouds.svelte'
7
- import { useDrawAPI } from '../hooks/useDrawAPI.svelte'
8
- import { useWorldStates } from '../hooks/useWorldState.svelte'
9
- import { useArrows } from '../hooks/useArrows.svelte'
10
- import Pose from './Pose.svelte'
11
- import Frame from './Frame.svelte'
12
- import Line from './Line.svelte'
13
- import Pointcloud from './Pointcloud.svelte'
14
- import Model from './WorldObject.svelte'
15
- import Label from './Label.svelte'
16
- import WorldState from './WorldState.svelte'
17
- import { determinePose } from '../WorldObject.svelte'
18
- import { useWeblabs } from '../hooks/useWeblabs.svelte'
19
- import type { WorldObject } from '../WorldObject.svelte'
20
- import type { Pose as ViamPose } from '@viamrobotics/sdk'
21
- import { WEBLABS_EXPERIMENTS } from '../hooks/useWeblabs.svelte'
22
- const points = usePointClouds()
23
- const drawAPI = useDrawAPI()
24
- const frames = useFrames()
25
- const geometries = useGeometries()
26
- const worldStates = useWorldStates()
27
- const batchedArrow = useArrows()
28
- const weblabs = useWeblabs()
29
-
30
- const weblabedDeterminePose = (object: WorldObject, pose: ViamPose | undefined) => {
31
- if (weblabs.isActive(WEBLABS_EXPERIMENTS.MOTION_TOOLS_EDIT_FRAME)) {
32
- return determinePose(object, pose)
33
- }
34
- return pose ?? object.pose
35
- }
36
- </script>
37
-
38
- {#each frames.current as object (object.uuid)}
39
- <Pose
40
- name={object.name}
41
- parent={object.referenceFrame}
42
- >
43
- {#snippet children({ pose })}
44
- {@const framePose = weblabedDeterminePose(object, pose)}
45
- <Portal id={object.referenceFrame}>
46
- <Frame
47
- uuid={object.uuid}
48
- name={object.name}
49
- pose={framePose}
50
- geometry={object.geometry}
51
- metadata={object.metadata}
52
- >
53
- <PortalTarget id={object.name} />
54
- <Label text={object.name} />
55
- </Frame>
56
- </Portal>
57
- {/snippet}
58
- </Pose>
59
- {/each}
60
-
61
- {#each geometries.current as object (object.uuid)}
62
- <Portal id={object.referenceFrame}>
63
- <Frame
64
- uuid={object.uuid}
65
- name={object.name}
66
- pose={object.pose}
67
- geometry={object.geometry}
68
- metadata={object.metadata}
69
- >
70
- <PortalTarget id={object.name} />
71
- <Label text={object.name} />
72
- </Frame>
73
- </Portal>
74
- {/each}
75
-
76
- {#each worldStates.names as { name } (name)}
77
- <WorldState worldObjects={worldStates.current[name].worldObjects} />
78
- {/each}
79
-
80
- {#each points.current as object (object.uuid)}
81
- <Portal id={object.referenceFrame}>
82
- <Pointcloud {object}>
83
- <Label text={object.name} />
84
- </Pointcloud>
85
- </Portal>
86
- {/each}
87
-
88
- {#each drawAPI.frames as object (object.uuid)}
89
- <Portal id={object.referenceFrame}>
90
- <Frame
91
- uuid={object.uuid}
92
- name={object.name}
93
- pose={object.pose}
94
- geometry={object.geometry}
95
- metadata={object.metadata}
96
- >
97
- <PortalTarget id={object.name} />
98
- <Label text={object.name} />
99
- </Frame>
100
- </Portal>
101
- {/each}
102
-
103
- {#each drawAPI.points as object (object.uuid)}
104
- <Portal id={object.referenceFrame}>
105
- <Pointcloud {object}>
106
- <Label text={object.name} />
107
- </Pointcloud>
108
- </Portal>
109
- {/each}
110
-
111
- <T
112
- name={batchedArrow.object3d.name}
113
- is={batchedArrow.object3d}
114
- dispose={false}
115
- bvh={{ enabled: false }}
116
- />
117
-
118
- {#each drawAPI.meshes as object (object.uuid)}
119
- <Portal id={object.referenceFrame}>
120
- <Frame
121
- uuid={object.uuid}
122
- name={object.name}
123
- pose={object.pose}
124
- geometry={object.geometry}
125
- metadata={object.metadata}
126
- >
127
- <PortalTarget id={object.name} />
128
- <Label text={object.name} />
129
- </Frame>
130
- </Portal>
131
- {/each}
132
-
133
- {#each drawAPI.nurbs as object (object.uuid)}
134
- <Portal id={object.referenceFrame}>
135
- <Frame
136
- uuid={object.uuid}
137
- name={object.name}
138
- pose={object.pose}
139
- geometry={object.geometry}
140
- metadata={object.metadata}
141
- >
142
- <PortalTarget id={object.name} />
143
- <Label text={object.name} />
144
- </Frame>
145
- </Portal>
146
- {/each}
147
-
148
- {#each drawAPI.models as object (object.uuid)}
149
- <Model {object}>
150
- <PortalTarget id={object.name} />
151
- <Label text={object.name} />
152
- </Model>
153
- {/each}
154
-
155
- {#each drawAPI.lines as object (object.uuid)}
156
- <Line {object}>
157
- <Label text={object.name} />
158
- </Line>
159
- {/each}
@@ -1,92 +0,0 @@
1
- <script lang="ts">
2
- import { Color, Vector3 } from 'three'
3
-
4
- import Frame from './Frame.svelte'
5
- import Label from './Label.svelte'
6
- import Portal from './portal/Portal.svelte'
7
- import PortalTarget from './portal/PortalTarget.svelte'
8
- import { WorldObject } from '../WorldObject.svelte'
9
- import { poseToDirection } from '../transform'
10
- import { BatchedArrow } from '../three/BatchedArrow'
11
- import { T } from '@threlte/core'
12
-
13
- interface Props {
14
- worldObjects: WorldObject[]
15
- }
16
-
17
- let { worldObjects }: Props = $props()
18
-
19
- const currentArrows: Record<string, { id: number; arrow: WorldObject }> = {}
20
- const arrowBatches = $state<Record<string, BatchedArrow>>({})
21
-
22
- const arrows = $derived(worldObjects.filter((object) => object.metadata?.shape === 'arrow'))
23
- const objects = $derived(worldObjects.filter((object) => object.metadata?.shape !== 'arrow'))
24
-
25
- const getArrows = () => ({ ...currentArrows })
26
- const getArrow = (referenceFrame: string, uuid: string) =>
27
- currentArrows[`${referenceFrame}:${uuid}`]
28
-
29
- const removeArrow = (referenceFrame: string, uuid: string) => {
30
- delete currentArrows[`${referenceFrame}:${uuid}`]
31
- }
32
-
33
- const setArrow = (arrow: WorldObject) => {
34
- const referenceFrame = arrow.referenceFrame ?? 'world'
35
- const currentArrow = getArrow(referenceFrame, arrow.uuid)
36
- const color = arrow.metadata?.color ?? new Color('yellow')
37
- const direction = poseToDirection(arrow.pose)
38
- const position = new Vector3(arrow.pose.x, arrow.pose.y, arrow.pose.z)
39
-
40
- arrowBatches[referenceFrame] ??= new BatchedArrow()
41
- const batchedArrow = arrowBatches[referenceFrame]
42
-
43
- if (currentArrow) {
44
- batchedArrow.updateArrow(currentArrow.id, direction, position, 0.1, color, true)
45
- currentArrows[`${referenceFrame}:${arrow.uuid}`] = { id: currentArrow.id, arrow }
46
- } else {
47
- const id = batchedArrow.addArrow(direction, position, 0.1, color, true)
48
- currentArrows[`${referenceFrame}:${arrow.uuid}`] = { id, arrow }
49
- }
50
- }
51
-
52
- $effect(() => {
53
- const toRemove = getArrows()
54
- arrows.forEach((arrow) => {
55
- setArrow(arrow)
56
- const referenceFrame = arrow.referenceFrame ?? 'world'
57
- delete toRemove[`${referenceFrame}:${arrow.uuid}`]
58
- })
59
-
60
- Object.values(toRemove).forEach(({ id, arrow }) => {
61
- const referenceFrame = arrow.referenceFrame ?? 'world'
62
- arrowBatches[referenceFrame].removeArrow(id)
63
- removeArrow(referenceFrame, arrow.uuid)
64
- })
65
- })
66
- </script>
67
-
68
- {#each Object.entries(arrowBatches) as [referenceFrame, batch] (referenceFrame)}
69
- <Portal id={referenceFrame}>
70
- <T
71
- name={batch.object3d.name}
72
- is={batch.object3d}
73
- dispose={false}
74
- bvh={{ enabled: false }}
75
- />
76
- </Portal>
77
- {/each}
78
-
79
- {#each objects as object (object.uuid)}
80
- <Portal id={object.referenceFrame}>
81
- <Frame
82
- uuid={object.uuid}
83
- name={object.name}
84
- pose={object.pose}
85
- geometry={object.geometry}
86
- metadata={object.metadata}
87
- >
88
- <PortalTarget id={object.name} />
89
- <Label text={object.name} />
90
- </Frame>
91
- </Portal>
92
- {/each}
@@ -1,7 +0,0 @@
1
- import { WorldObject } from '../WorldObject.svelte';
2
- interface Props {
3
- worldObjects: WorldObject[];
4
- }
5
- declare const WorldState: import("svelte").Component<Props, {}, "">;
6
- type WorldState = ReturnType<typeof WorldState>;
7
- export default WorldState;
@@ -1,2 +0,0 @@
1
- import { WorldObject } from '../../../WorldObject.svelte';
2
- export declare const createWorldObjectFixture: () => WorldObject<import("../../../WorldObject.svelte").Geometries>;
@@ -1,35 +0,0 @@
1
- import { WorldObject } from '../../../WorldObject.svelte';
2
- export const createWorldObjectFixture = () => {
3
- const object = new WorldObject();
4
- object.name = 'Test Object';
5
- object.uuid = '1234-5678';
6
- object.referenceFrame = 'parent_frame';
7
- object.pose = {
8
- x: 10,
9
- y: 20,
10
- z: 30,
11
- oX: 0.1,
12
- oY: 0.2,
13
- oZ: 0.3,
14
- theta: 0.4,
15
- };
16
- object.geometry = {
17
- label: 'my geometry',
18
- geometryType: {
19
- case: 'box',
20
- value: {
21
- dimsMm: { x: 10, y: 20, z: 30 },
22
- },
23
- },
24
- };
25
- object.localEditedPose = {
26
- x: 10,
27
- y: 20,
28
- z: 30,
29
- oX: 0.1,
30
- oY: 0.2,
31
- oZ: 0.3,
32
- theta: 0.4,
33
- };
34
- return object;
35
- };
@@ -1,25 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte'
3
- import { usePortalContext } from './usePortalContext.svelte'
4
- import { SvelteSet } from 'svelte/reactivity'
5
-
6
- interface Props {
7
- id?: string
8
- children?: Snippet
9
- }
10
-
11
- let { id = 'default', children }: Props = $props()
12
-
13
- const portals = usePortalContext()
14
-
15
- $effect.pre(() => {
16
- if (!children) return
17
-
18
- if (!portals.has(id)) {
19
- portals.set(id, new SvelteSet())
20
- }
21
-
22
- portals.get(id)?.add(children)
23
- return () => portals.get(id)?.delete(children)
24
- })
25
- </script>
@@ -1,8 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- interface Props {
3
- id?: string;
4
- children?: Snippet;
5
- }
6
- declare const Portal: import("svelte").Component<Props, {}, "">;
7
- type Portal = ReturnType<typeof Portal>;
8
- export default Portal;
@@ -1,18 +0,0 @@
1
- <script lang="ts">
2
- import { usePortalContext } from './usePortalContext.svelte'
3
-
4
- interface Props {
5
- id?: string
6
- }
7
-
8
- let { id = 'default' }: Props = $props()
9
-
10
- const portals = usePortalContext()
11
- const childrenArray = $derived(portals.get(id))
12
- </script>
13
-
14
- {#if childrenArray !== undefined}
15
- {#each childrenArray as children (children)}
16
- {@render children()}
17
- {/each}
18
- {/if}
@@ -1,6 +0,0 @@
1
- interface Props {
2
- id?: string;
3
- }
4
- declare const PortalTarget: import("svelte").Component<Props, {}, "">;
5
- type PortalTarget = ReturnType<typeof PortalTarget>;
6
- export default PortalTarget;
@@ -1,2 +0,0 @@
1
- export { default as Portal } from './Portal.svelte';
2
- export { default as PortalTarget } from './PortalTarget.svelte';
@@ -1,2 +0,0 @@
1
- export { default as Portal } from './Portal.svelte';
2
- export { default as PortalTarget } from './PortalTarget.svelte';
@@ -1,5 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import { SvelteMap, SvelteSet } from 'svelte/reactivity';
3
- type PortalContext = SvelteMap<string, SvelteSet<Snippet>>;
4
- export declare const usePortalContext: () => PortalContext;
5
- export {};