@viamrobotics/motion-tools 0.7.0 → 0.8.0
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/WorldObject.d.ts +2 -0
- package/dist/components/CameraControls.svelte +10 -0
- package/dist/components/Geometry.svelte +1 -1
- package/dist/components/Line.svelte +40 -0
- package/dist/components/Line.svelte.d.ts +7 -0
- package/dist/components/Shapes.svelte +5 -0
- package/dist/components/Tree/Settings.svelte +25 -0
- package/dist/hooks/useObjects.svelte.js +1 -0
- package/dist/hooks/useSettings.svelte.d.ts +2 -0
- package/dist/hooks/useSettings.svelte.js +3 -1
- package/dist/hooks/useShapes.svelte.d.ts +7 -0
- package/dist/hooks/useShapes.svelte.js +58 -0
- package/package.json +1 -1
package/dist/WorldObject.d.ts
CHANGED
|
@@ -4,10 +4,20 @@
|
|
|
4
4
|
import KeyboardControls from './KeyboardControls.svelte'
|
|
5
5
|
import Portal from './portal/Portal.svelte'
|
|
6
6
|
import Button from './dashboard/Button.svelte'
|
|
7
|
+
import { useShapes } from '../hooks/useShapes.svelte'
|
|
7
8
|
|
|
9
|
+
const shapes = useShapes()
|
|
8
10
|
const transformControls = useTransformControls()
|
|
9
11
|
|
|
10
12
|
let ref = $state.raw<CameraControlsRef>()
|
|
13
|
+
|
|
14
|
+
$effect(() => {
|
|
15
|
+
if (shapes.camera) {
|
|
16
|
+
const { position, lookAt, animate } = shapes.camera
|
|
17
|
+
ref?.setPosition(position.x, position.y, position.z, animate)
|
|
18
|
+
ref?.setLookAt(position.x, position.y, position.z, lookAt.x, lookAt.y, lookAt.z, animate)
|
|
19
|
+
}
|
|
20
|
+
})
|
|
11
21
|
</script>
|
|
12
22
|
|
|
13
23
|
<Portal id="dashboard">
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { T } from '@threlte/core'
|
|
3
|
+
import { Instance, InstancedMesh } from '@threlte/extras'
|
|
4
|
+
import Frame from './Frame.svelte'
|
|
5
|
+
import type { WorldObject } from '../WorldObject'
|
|
6
|
+
import { useSettings } from '../hooks/useSettings.svelte'
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
object: WorldObject
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { object }: Props = $props()
|
|
13
|
+
|
|
14
|
+
const settings = useSettings()
|
|
15
|
+
$inspect(object.metadata.points)
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<Frame
|
|
19
|
+
{...object}
|
|
20
|
+
metadata={{
|
|
21
|
+
...object.metadata,
|
|
22
|
+
lineWidth: settings.current.lineWidth,
|
|
23
|
+
}}
|
|
24
|
+
/>
|
|
25
|
+
|
|
26
|
+
{#if object.metadata.lineDotColor && object.metadata.points}
|
|
27
|
+
<InstancedMesh frustumCulled={false}>
|
|
28
|
+
<T.SphereGeometry />
|
|
29
|
+
<T.MeshBasicMaterial color={object.metadata.lineDotColor} />
|
|
30
|
+
|
|
31
|
+
{#each object.metadata.points as { x, y, z }, i (i)}
|
|
32
|
+
<Instance
|
|
33
|
+
position.x={x}
|
|
34
|
+
position.y={y}
|
|
35
|
+
position.z={z}
|
|
36
|
+
scale={Number(settings.current.lineDotSize)}
|
|
37
|
+
/>
|
|
38
|
+
{/each}
|
|
39
|
+
</InstancedMesh>
|
|
40
|
+
{/if}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { useShapes } from '../hooks/useShapes.svelte'
|
|
5
5
|
import WorldObject from './WorldObject.svelte'
|
|
6
6
|
import Frame from './Frame.svelte'
|
|
7
|
+
import Line from './Line.svelte'
|
|
7
8
|
|
|
8
9
|
const shapes = useShapes()
|
|
9
10
|
</script>
|
|
@@ -47,3 +48,7 @@
|
|
|
47
48
|
<PortalTarget id={object.name} />
|
|
48
49
|
</WorldObject>
|
|
49
50
|
{/each}
|
|
51
|
+
|
|
52
|
+
{#each shapes.lines as object (object.uuid)}
|
|
53
|
+
<Line {object} />
|
|
54
|
+
{/each}
|
|
@@ -108,6 +108,31 @@
|
|
|
108
108
|
</label>
|
|
109
109
|
</div>
|
|
110
110
|
|
|
111
|
+
<h3 class="text-base"><strong>Lines</strong></h3>
|
|
112
|
+
<div class="flex flex-col gap-2.5">
|
|
113
|
+
<label class="flex items-center justify-between gap-2">
|
|
114
|
+
Thickness
|
|
115
|
+
|
|
116
|
+
<div class="w-20">
|
|
117
|
+
<Input
|
|
118
|
+
bind:value={settings.current.lineWidth}
|
|
119
|
+
on:keydown={(event) => event.stopImmediatePropagation()}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
</label>
|
|
123
|
+
|
|
124
|
+
<label class="flex items-center justify-between gap-2">
|
|
125
|
+
Dot size
|
|
126
|
+
|
|
127
|
+
<div class="w-20">
|
|
128
|
+
<Input
|
|
129
|
+
bind:value={settings.current.lineDotSize}
|
|
130
|
+
on:keydown={(event) => event.stopImmediatePropagation()}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
</label>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
111
136
|
<h3 class="text-base"><strong>Misc</strong></h3>
|
|
112
137
|
<div class="flex flex-col gap-2.5">
|
|
113
138
|
<label class="flex items-center justify-between gap-2">
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { Vector3 } from 'three';
|
|
1
2
|
import { BatchedArrow } from '../three/BatchedArrow';
|
|
2
3
|
import { WorldObject, type PointsGeometry } from '../WorldObject';
|
|
3
4
|
type ConnectionStatus = 'connecting' | 'open' | 'closed';
|
|
4
5
|
interface Context {
|
|
5
6
|
points: WorldObject<PointsGeometry>[];
|
|
7
|
+
lines: WorldObject[];
|
|
6
8
|
meshes: WorldObject[];
|
|
7
9
|
poses: WorldObject[];
|
|
8
10
|
nurbs: WorldObject[];
|
|
@@ -11,6 +13,11 @@ interface Context {
|
|
|
11
13
|
object3ds: {
|
|
12
14
|
batchedArrow: BatchedArrow;
|
|
13
15
|
};
|
|
16
|
+
camera: {
|
|
17
|
+
position: Vector3;
|
|
18
|
+
lookAt: Vector3;
|
|
19
|
+
animate: boolean;
|
|
20
|
+
} | undefined;
|
|
14
21
|
}
|
|
15
22
|
export declare const provideShapes: () => void;
|
|
16
23
|
export declare const useShapes: () => Context;
|
|
@@ -39,10 +39,12 @@ export const provideShapes = () => {
|
|
|
39
39
|
const maxReconnectDelay = 5_000;
|
|
40
40
|
let ws;
|
|
41
41
|
const points = $state([]);
|
|
42
|
+
const lines = $state([]);
|
|
42
43
|
const meshes = $state([]);
|
|
43
44
|
const poses = $state([]);
|
|
44
45
|
const nurbs = $state([]);
|
|
45
46
|
const models = $state([]);
|
|
47
|
+
let camera = $state();
|
|
46
48
|
let connectionStatus = $state('connecting');
|
|
47
49
|
const color = new Color();
|
|
48
50
|
const direction = new Vector3();
|
|
@@ -177,6 +179,40 @@ export const provideShapes = () => {
|
|
|
177
179
|
value: positions,
|
|
178
180
|
}, metadata));
|
|
179
181
|
};
|
|
182
|
+
const addLine = async (reader) => {
|
|
183
|
+
// Read label length
|
|
184
|
+
const labelLen = reader.read();
|
|
185
|
+
let label = '';
|
|
186
|
+
for (let i = 0; i < labelLen; i++) {
|
|
187
|
+
label += String.fromCharCode(reader.read());
|
|
188
|
+
}
|
|
189
|
+
// Read counts
|
|
190
|
+
const nPoints = reader.read();
|
|
191
|
+
// Read default color
|
|
192
|
+
const lineR = reader.read();
|
|
193
|
+
const lineG = reader.read();
|
|
194
|
+
const lineB = reader.read();
|
|
195
|
+
const dotR = reader.read();
|
|
196
|
+
const dotG = reader.read();
|
|
197
|
+
const dotB = reader.read();
|
|
198
|
+
// Read positions
|
|
199
|
+
const positions = new Float32Array(nPoints * 3);
|
|
200
|
+
for (let i = 0; i < nPoints * 3; i++) {
|
|
201
|
+
positions[i] = reader.read();
|
|
202
|
+
}
|
|
203
|
+
const points = [];
|
|
204
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
205
|
+
points.push(new Vector3(positions[i], positions[i + 1], positions[i + 2]));
|
|
206
|
+
}
|
|
207
|
+
lines.push(new WorldObject(label, undefined, undefined, {
|
|
208
|
+
case: 'line',
|
|
209
|
+
value: positions,
|
|
210
|
+
}, {
|
|
211
|
+
points,
|
|
212
|
+
color: lineR === -1 ? undefined : new Color().setRGB(lineR, lineG, lineB),
|
|
213
|
+
lineDotColor: dotR === -1 ? undefined : new Color().setRGB(dotR, dotG, dotB),
|
|
214
|
+
}));
|
|
215
|
+
};
|
|
180
216
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
181
217
|
const addGeometries = (geometries, colors, parent) => {
|
|
182
218
|
let i = 0;
|
|
@@ -224,10 +260,16 @@ export const provideShapes = () => {
|
|
|
224
260
|
models.splice(index, 1);
|
|
225
261
|
continue;
|
|
226
262
|
}
|
|
263
|
+
index = lines.findIndex((m) => m.name === name);
|
|
264
|
+
if (index !== -1) {
|
|
265
|
+
lines.splice(index, 1);
|
|
266
|
+
continue;
|
|
267
|
+
}
|
|
227
268
|
}
|
|
228
269
|
};
|
|
229
270
|
const removeAll = () => {
|
|
230
271
|
points.splice(0, points.length);
|
|
272
|
+
lines.splice(0, lines.length);
|
|
231
273
|
meshes.splice(0, meshes.length);
|
|
232
274
|
nurbs.splice(0, nurbs.length);
|
|
233
275
|
models.splice(0, models.length);
|
|
@@ -270,6 +312,9 @@ export const provideShapes = () => {
|
|
|
270
312
|
return addPoses(reader);
|
|
271
313
|
}
|
|
272
314
|
else if (type === 2) {
|
|
315
|
+
return addLine(reader);
|
|
316
|
+
}
|
|
317
|
+
else if (type === 3) {
|
|
273
318
|
return addPCD(reader.buffer);
|
|
274
319
|
}
|
|
275
320
|
else {
|
|
@@ -279,6 +324,13 @@ export const provideShapes = () => {
|
|
|
279
324
|
const data = tryParse(event.data);
|
|
280
325
|
if (!data)
|
|
281
326
|
return;
|
|
327
|
+
if ('setCameraPose' in data) {
|
|
328
|
+
camera = {
|
|
329
|
+
position: new Vector3(data.Position.X, data.Position.Y, data.Position.Z),
|
|
330
|
+
lookAt: new Vector3(data.LookAt.X, data.LookAt.Y, data.LookAt.Z),
|
|
331
|
+
animate: data.Animate,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
282
334
|
if ('geometries' in data) {
|
|
283
335
|
return addGeometries(data.geometries, data.colors, data.parent);
|
|
284
336
|
}
|
|
@@ -310,6 +362,9 @@ export const provideShapes = () => {
|
|
|
310
362
|
get points() {
|
|
311
363
|
return points;
|
|
312
364
|
},
|
|
365
|
+
get lines() {
|
|
366
|
+
return lines;
|
|
367
|
+
},
|
|
313
368
|
get meshes() {
|
|
314
369
|
return meshes;
|
|
315
370
|
},
|
|
@@ -328,6 +383,9 @@ export const provideShapes = () => {
|
|
|
328
383
|
object3ds: {
|
|
329
384
|
batchedArrow,
|
|
330
385
|
},
|
|
386
|
+
get camera() {
|
|
387
|
+
return camera;
|
|
388
|
+
},
|
|
331
389
|
});
|
|
332
390
|
};
|
|
333
391
|
export const useShapes = () => {
|