@viamrobotics/motion-tools 0.19.2 → 1.0.2
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 +56 -26
- package/dist/FrameConfigUpdater.svelte.d.ts +11 -17
- package/dist/FrameConfigUpdater.svelte.js +109 -109
- package/dist/WorldObject.svelte.js +2 -15
- package/dist/common/v1/common_pb.d.ts +950 -0
- package/dist/common/v1/common_pb.js +1399 -0
- package/dist/components/App.svelte +37 -21
- package/dist/components/App.svelte.d.ts +1 -0
- package/dist/components/BatchedArrows.svelte +102 -0
- package/dist/components/BatchedArrows.svelte.d.ts +3 -0
- package/dist/components/CameraControls.svelte +2 -3
- package/dist/components/Details.svelte +364 -365
- package/dist/components/Entities.svelte +73 -0
- package/dist/components/{WorldObjects.svelte.d.ts → Entities.svelte.d.ts} +3 -3
- package/dist/components/FileDrop.svelte +9 -23
- package/dist/components/Focus.svelte +2 -3
- package/dist/components/Frame.svelte +41 -22
- package/dist/components/Frame.svelte.d.ts +4 -6
- package/dist/components/GLTF.svelte +36 -0
- package/dist/components/GLTF.svelte.d.ts +11 -0
- package/dist/components/Geometry2.svelte +201 -0
- package/dist/components/Geometry2.svelte.d.ts +18 -0
- package/dist/components/KeyboardControls.svelte +3 -3
- package/dist/components/Line.svelte +10 -13
- package/dist/components/Line.svelte.d.ts +2 -2
- package/dist/components/LiveUpdatesBanner.svelte +51 -15
- package/dist/components/MeasureTool.svelte +4 -5
- package/dist/components/Pointcloud.svelte +27 -14
- package/dist/components/Pointcloud.svelte.d.ts +2 -2
- package/dist/components/PointerMissBox.svelte +3 -3
- package/dist/components/Pose.svelte +31 -6
- package/dist/components/Pose.svelte.d.ts +2 -2
- package/dist/components/Scene.svelte +7 -6
- package/dist/components/SceneProviders.svelte +0 -6
- package/dist/components/Selected.svelte +22 -16
- package/dist/components/StaticGeometries.svelte +51 -27
- package/dist/components/Tree/Tree.svelte +28 -22
- package/dist/components/Tree/Tree.svelte.d.ts +2 -3
- package/dist/components/Tree/TreeContainer.svelte +72 -40
- package/dist/components/Tree/Widgets.svelte +2 -5
- package/dist/components/Tree/buildTree.d.ts +3 -6
- package/dist/components/Tree/buildTree.js +19 -39
- package/dist/components/__tests__/__fixtures__/entity.d.ts +2 -0
- package/dist/components/__tests__/__fixtures__/entity.js +20 -0
- package/dist/components/__tests__/__fixtures__/resource.d.ts +17 -0
- package/dist/components/__tests__/__fixtures__/resource.js +13 -0
- package/dist/components/dashboard/Dashboard.svelte +5 -3
- package/dist/components/dashboard/Dashboard.svelte.d.ts +7 -2
- package/dist/components/widgets/ArmPositions.svelte +19 -7
- package/dist/draw/v1/drawing_pb.d.ts +341 -0
- package/dist/draw/v1/drawing_pb.js +417 -0
- package/dist/draw/v1/metadata_pb.d.ts +23 -0
- package/dist/draw/v1/metadata_pb.js +39 -0
- package/dist/draw/v1/scene_pb.d.ts +230 -0
- package/dist/draw/v1/scene_pb.js +298 -0
- package/dist/draw/v1/snapshot_pb.d.ts +42 -0
- package/dist/draw/v1/snapshot_pb.js +61 -0
- package/dist/draw/v1/transforms_pb.d.ts +23 -0
- package/dist/draw/v1/transforms_pb.js +39 -0
- package/dist/ecs/index.d.ts +4 -0
- package/dist/ecs/index.js +4 -0
- package/dist/ecs/traits.d.ts +128 -0
- package/dist/ecs/traits.js +81 -0
- package/dist/ecs/useQuery.svelte.d.ts +4 -0
- package/dist/ecs/useQuery.svelte.js +49 -0
- package/dist/ecs/useTrait.svelte.d.ts +19 -0
- package/dist/ecs/useTrait.svelte.js +40 -0
- package/dist/ecs/useWorld.d.ts +4 -0
- package/dist/ecs/useWorld.js +10 -0
- package/dist/geometry.js +6 -6
- package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte +41 -0
- package/dist/hooks/__tests__/fixtures/ResizableTestWrapper.svelte.d.ts +6 -0
- package/dist/hooks/use3DModels.svelte.js +6 -4
- package/dist/hooks/useDrawAPI.svelte.d.ts +0 -10
- package/dist/hooks/useDrawAPI.svelte.js +143 -267
- package/dist/hooks/useFramelessComponents.svelte.js +1 -1
- package/dist/hooks/useFrames.svelte.d.ts +6 -2
- package/dist/hooks/useFrames.svelte.js +123 -19
- package/dist/hooks/useGeometries.svelte.d.ts +0 -2
- package/dist/hooks/useGeometries.svelte.js +49 -25
- package/dist/hooks/useObjectEvents.svelte.d.ts +3 -2
- package/dist/hooks/useObjectEvents.svelte.js +11 -7
- package/dist/hooks/usePartConfig.svelte.d.ts +1 -1
- package/dist/hooks/usePartConfig.svelte.js +2 -1
- package/dist/hooks/usePointclouds.svelte.d.ts +0 -2
- package/dist/hooks/usePointclouds.svelte.js +52 -21
- package/dist/hooks/usePose.svelte.js +15 -7
- package/dist/hooks/useResizable.svelte.d.ts +12 -0
- package/dist/hooks/useResizable.svelte.js +45 -0
- package/dist/hooks/useResourceByName.svelte.js +8 -5
- package/dist/hooks/useSelection.svelte.d.ts +13 -23
- package/dist/hooks/useSelection.svelte.js +45 -65
- package/dist/hooks/useVisibility.svelte.d.ts +2 -1
- package/dist/hooks/useWeblabs.svelte.d.ts +0 -1
- package/dist/hooks/useWeblabs.svelte.js +0 -1
- package/dist/hooks/useWorldState.svelte.d.ts +9 -0
- package/dist/hooks/useWorldState.svelte.js +158 -107
- package/dist/lib.d.ts +1 -0
- package/dist/lib.js +2 -0
- package/dist/three/BatchedArrow.d.ts +2 -3
- package/dist/three/BatchedArrow.js +3 -11
- package/dist/three/CapsuleGeometry.d.ts +1 -1
- package/dist/three/CapsuleGeometry.js +3 -1
- package/dist/transform.js +0 -15
- package/package.json +12 -7
- package/dist/components/WorldObject.svelte +0 -28
- package/dist/components/WorldObject.svelte.d.ts +0 -11
- package/dist/components/WorldObjects.svelte +0 -159
- package/dist/components/WorldState.svelte +0 -92
- package/dist/components/WorldState.svelte.d.ts +0 -7
- package/dist/components/__tests__/__fixtures__/worldObject.svelte.d.ts +0 -2
- package/dist/components/__tests__/__fixtures__/worldObject.svelte.js +0 -35
- package/dist/components/portal/Portal.svelte +0 -25
- package/dist/components/portal/Portal.svelte.d.ts +0 -8
- package/dist/components/portal/PortalTarget.svelte +0 -18
- package/dist/components/portal/PortalTarget.svelte.d.ts +0 -6
- package/dist/components/portal/index.d.ts +0 -2
- package/dist/components/portal/index.js +0 -2
- package/dist/components/portal/usePortalContext.svelte.d.ts +0 -5
- package/dist/components/portal/usePortalContext.svelte.js +0 -5
- package/dist/hooks/useArrows.svelte.d.ts +0 -3
- package/dist/hooks/useArrows.svelte.js +0 -9
- package/dist/hooks/useDraggable.svelte.d.ts +0 -10
- package/dist/hooks/useDraggable.svelte.js +0 -36
- package/dist/hooks/useObjects.svelte.d.ts +0 -7
- package/dist/hooks/useObjects.svelte.js +0 -35
- package/dist/hooks/usePersistentUUIDs.svelte.d.ts +0 -5
- package/dist/hooks/usePersistentUUIDs.svelte.js +0 -13
- package/dist/hooks/useResourceByName.svelte.d.ts +0 -7
- package/dist/hooks/useStaticGeometries.svelte.d.ts +0 -9
- package/dist/hooks/useStaticGeometries.svelte.js +0 -47
- package/dist/workers/worldStateWorker.d.ts +0 -1
- package/dist/workers/worldStateWorker.js +0 -114
- package/dist/world-state-messages.d.ts +0 -23
- package/dist/world-state-messages.js +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useResourceNames } from '@viamrobotics/svelte-sdk';
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
|
-
const
|
|
4
|
-
export const
|
|
3
|
+
export const RESOURCE_BY_NAME_CONTEXT_KEY = Symbol('resource-by-name-context');
|
|
4
|
+
export const createResourceByName = (partID) => {
|
|
5
5
|
const resourceNames = useResourceNames(partID);
|
|
6
6
|
const resourceByName = $derived.by(() => {
|
|
7
7
|
const results = {};
|
|
@@ -10,12 +10,15 @@ export const provideResourceByName = (partID) => {
|
|
|
10
10
|
}
|
|
11
11
|
return results;
|
|
12
12
|
});
|
|
13
|
-
|
|
13
|
+
return {
|
|
14
14
|
get current() {
|
|
15
15
|
return resourceByName;
|
|
16
16
|
},
|
|
17
|
-
}
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export const provideResourceByName = (partID) => {
|
|
20
|
+
setContext(RESOURCE_BY_NAME_CONTEXT_KEY, createResourceByName(partID));
|
|
18
21
|
};
|
|
19
22
|
export const useResourceByName = () => {
|
|
20
|
-
return getContext(
|
|
23
|
+
return getContext(RESOURCE_BY_NAME_CONTEXT_KEY);
|
|
21
24
|
};
|
|
@@ -1,35 +1,25 @@
|
|
|
1
1
|
import { Object3D } from 'three';
|
|
2
|
-
import type {
|
|
3
|
-
interface
|
|
4
|
-
readonly current:
|
|
5
|
-
set(
|
|
2
|
+
import type { Entity } from 'koota';
|
|
3
|
+
interface SelectedEntityContext {
|
|
4
|
+
readonly current: Entity | undefined;
|
|
5
|
+
set(entity?: Entity): void;
|
|
6
6
|
}
|
|
7
|
-
interface
|
|
8
|
-
readonly current:
|
|
9
|
-
set(
|
|
7
|
+
interface FocusedEntityContext {
|
|
8
|
+
readonly current: Entity | undefined;
|
|
9
|
+
set(entity?: Entity): void;
|
|
10
10
|
}
|
|
11
11
|
export declare const provideSelection: () => {
|
|
12
12
|
selection: {
|
|
13
|
-
readonly current:
|
|
14
|
-
set(
|
|
13
|
+
readonly current: Entity | undefined;
|
|
14
|
+
set(entity: Entity): void;
|
|
15
15
|
};
|
|
16
16
|
focus: {
|
|
17
|
-
readonly current:
|
|
18
|
-
set(
|
|
17
|
+
readonly current: Entity | undefined;
|
|
18
|
+
set(entity: Entity): void;
|
|
19
19
|
};
|
|
20
|
-
hover: {
|
|
21
|
-
readonly current: string | undefined;
|
|
22
|
-
set(value?: string): void;
|
|
23
|
-
};
|
|
24
|
-
};
|
|
25
|
-
export declare const useSelected: () => SelectionContext;
|
|
26
|
-
export declare const useFocused: () => FocusContext;
|
|
27
|
-
export declare const useFocusedObject: () => {
|
|
28
|
-
current: WorldObject | undefined;
|
|
29
|
-
};
|
|
30
|
-
export declare const useSelectedObject: () => {
|
|
31
|
-
current: WorldObject | undefined;
|
|
32
20
|
};
|
|
21
|
+
export declare const useFocusedEntity: () => FocusedEntityContext;
|
|
22
|
+
export declare const useSelectedEntity: () => SelectedEntityContext;
|
|
33
23
|
export declare const useFocusedObject3d: () => {
|
|
34
24
|
current: Object3D | undefined;
|
|
35
25
|
};
|
|
@@ -1,65 +1,47 @@
|
|
|
1
1
|
import { isInstanceOf, useThrelte } from '@threlte/core';
|
|
2
2
|
import { getContext, setContext } from 'svelte';
|
|
3
|
-
import { Matrix4, Object3D } from 'three';
|
|
4
|
-
import {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const focusKey = Symbol('focus-context');
|
|
8
|
-
const selectedObjectKey = Symbol('selected-frame-context');
|
|
9
|
-
const focusedObjectKey = Symbol('focused-frame-context');
|
|
3
|
+
import { BatchedMesh, Matrix4, Object3D } from 'three';
|
|
4
|
+
import { traits, useTrait, useWorld } from '../ecs';
|
|
5
|
+
const selectedKey = Symbol('selected-frame-context');
|
|
6
|
+
const focusedKey = Symbol('focused-frame-context');
|
|
10
7
|
const focusedObject3dKey = Symbol('focused-object-3d-context');
|
|
11
8
|
export const provideSelection = () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
let
|
|
15
|
-
|
|
9
|
+
const world = useWorld();
|
|
10
|
+
const { scene } = useThrelte();
|
|
11
|
+
let selected = $state.raw();
|
|
12
|
+
let focused = $state.raw();
|
|
13
|
+
$effect(() => {
|
|
14
|
+
return world.onRemove(traits.Name, (entity) => {
|
|
15
|
+
if (entity === selected)
|
|
16
|
+
selected = undefined;
|
|
17
|
+
if (entity === focused)
|
|
18
|
+
focused = undefined;
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
const selectedEntityContext = {
|
|
16
22
|
get current() {
|
|
17
23
|
return selected;
|
|
18
24
|
},
|
|
19
|
-
set(
|
|
20
|
-
selected =
|
|
25
|
+
set(entity) {
|
|
26
|
+
selected = entity;
|
|
21
27
|
},
|
|
22
28
|
};
|
|
23
|
-
setContext(
|
|
24
|
-
const
|
|
29
|
+
setContext(selectedKey, selectedEntityContext);
|
|
30
|
+
const focusedEntityContext = {
|
|
25
31
|
get current() {
|
|
26
32
|
return focused;
|
|
27
33
|
},
|
|
28
|
-
set(
|
|
29
|
-
focused =
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
setContext(focusKey, focusContext);
|
|
33
|
-
const hoverContext = {
|
|
34
|
-
get current() {
|
|
35
|
-
return hovered;
|
|
36
|
-
},
|
|
37
|
-
set(value) {
|
|
38
|
-
hovered = value;
|
|
39
|
-
},
|
|
40
|
-
};
|
|
41
|
-
setContext(hoverKey, hoverContext);
|
|
42
|
-
const objects = useObjects();
|
|
43
|
-
const selectedObject = $derived(objects.current.find((object) => object.uuid === selected));
|
|
44
|
-
const selectedObjectContext = {
|
|
45
|
-
get current() {
|
|
46
|
-
return selectedObject;
|
|
34
|
+
set(entity) {
|
|
35
|
+
focused = entity;
|
|
47
36
|
},
|
|
48
37
|
};
|
|
49
|
-
setContext(
|
|
50
|
-
const focusedObject = $derived(objects.current.find((object) => object.uuid === focused));
|
|
51
|
-
const focusedObjectContext = {
|
|
52
|
-
get current() {
|
|
53
|
-
return focusedObject;
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
setContext(focusedObjectKey, focusedObjectContext);
|
|
57
|
-
const { scene } = useThrelte();
|
|
58
|
-
const uuid = $derived(focusedObject?.uuid);
|
|
38
|
+
setContext(focusedKey, focusedEntityContext);
|
|
59
39
|
const focusedObject3d = $derived.by(() => {
|
|
60
|
-
|
|
40
|
+
const name = focused?.get(traits.Name);
|
|
41
|
+
if (!name) {
|
|
61
42
|
return;
|
|
62
|
-
|
|
43
|
+
}
|
|
44
|
+
const object = scene.getObjectByName(name)?.clone();
|
|
63
45
|
object?.traverse((child) => {
|
|
64
46
|
if (isInstanceOf(child, 'LineSegments')) {
|
|
65
47
|
child.raycast = () => null;
|
|
@@ -73,42 +55,40 @@ export const provideSelection = () => {
|
|
|
73
55
|
},
|
|
74
56
|
});
|
|
75
57
|
return {
|
|
76
|
-
selection:
|
|
77
|
-
focus:
|
|
78
|
-
hover: hoverContext,
|
|
58
|
+
selection: selectedEntityContext,
|
|
59
|
+
focus: focusedEntityContext,
|
|
79
60
|
};
|
|
80
61
|
};
|
|
81
|
-
export const
|
|
82
|
-
return getContext(
|
|
62
|
+
export const useFocusedEntity = () => {
|
|
63
|
+
return getContext(focusedKey);
|
|
83
64
|
};
|
|
84
|
-
export const
|
|
85
|
-
return getContext(
|
|
86
|
-
};
|
|
87
|
-
export const useFocusedObject = () => {
|
|
88
|
-
return getContext(focusedObjectKey);
|
|
89
|
-
};
|
|
90
|
-
export const useSelectedObject = () => {
|
|
91
|
-
return getContext(selectedObjectKey);
|
|
65
|
+
export const useSelectedEntity = () => {
|
|
66
|
+
return getContext(selectedKey);
|
|
92
67
|
};
|
|
93
68
|
export const useFocusedObject3d = () => {
|
|
94
69
|
return getContext(focusedObject3dKey);
|
|
95
70
|
};
|
|
96
71
|
const matrix = new Matrix4();
|
|
97
72
|
export const useSelectedObject3d = () => {
|
|
98
|
-
const
|
|
73
|
+
const selectedEntity = useSelectedEntity();
|
|
99
74
|
const { scene } = useThrelte();
|
|
75
|
+
const name = useTrait(() => selectedEntity.current, traits.Name);
|
|
76
|
+
const instance = useTrait(() => selectedEntity.current, traits.Instance);
|
|
100
77
|
const object = $derived.by(() => {
|
|
101
|
-
if (!
|
|
78
|
+
if (!selectedEntity.current) {
|
|
102
79
|
return;
|
|
103
80
|
}
|
|
104
|
-
if (
|
|
81
|
+
if (instance.current) {
|
|
105
82
|
const proxy = new Object3D();
|
|
106
|
-
const
|
|
107
|
-
|
|
83
|
+
const mesh = scene.getObjectById(instance.current.meshID);
|
|
84
|
+
mesh?.getMatrixAt(instance.current.instanceID, matrix);
|
|
108
85
|
proxy.applyMatrix4(matrix);
|
|
109
86
|
return proxy;
|
|
110
87
|
}
|
|
111
|
-
|
|
88
|
+
if (!name.current) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
return scene.getObjectByName(name.current);
|
|
112
92
|
});
|
|
113
93
|
return {
|
|
114
94
|
get current() {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Entity } from 'koota';
|
|
1
2
|
import { SvelteMap } from 'svelte/reactivity';
|
|
2
|
-
type Context = SvelteMap<
|
|
3
|
+
type Context = SvelteMap<Entity, boolean>;
|
|
3
4
|
export declare const provideVisibility: () => void;
|
|
4
5
|
export declare const useVisibility: () => Context;
|
|
5
6
|
export {};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { getContext, setContext } from 'svelte';
|
|
2
2
|
import { SvelteSet } from 'svelte/reactivity';
|
|
3
3
|
export const WEBLABS_EXPERIMENTS = {
|
|
4
|
-
MOTION_TOOLS_EDIT_FRAME: 'MOTION_TOOLS_EDIT_FRAME',
|
|
5
4
|
MOTION_TOOLS_RENDER_ARM_MODELS: 'MOTION_TOOLS_RENDER_ARM_MODELS',
|
|
6
5
|
};
|
|
7
6
|
export const WEBLABS_CONTEXT_KEY = Symbol('weblabs-context');
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type TransformChangeEvent, type TransformWithUUID } from '@viamrobotics/sdk';
|
|
2
|
+
export type ChangeMessage = {
|
|
3
|
+
type: 'change';
|
|
4
|
+
events: TransformChangeEvent[];
|
|
5
|
+
};
|
|
6
|
+
export type TransformEvent = TransformChangeEvent & {
|
|
7
|
+
transform: TransformWithUUID;
|
|
8
|
+
};
|
|
9
|
+
export declare const provideWorldStates: () => void;
|
|
@@ -1,85 +1,125 @@
|
|
|
1
|
-
import { WorldStateStoreClient, TransformChangeType,
|
|
1
|
+
import { WorldStateStoreClient, TransformChangeType, } from '@viamrobotics/sdk';
|
|
2
2
|
import { createResourceClient, createResourceQuery, createResourceStream, useResourceNames, } from '@viamrobotics/svelte-sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { parseMetadata } from '../WorldObject.svelte';
|
|
4
4
|
import { usePartID } from './usePartID.svelte';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
});
|
|
5
|
+
import { traits, useWorld } from '../ecs';
|
|
6
|
+
import { createPose } from '../transform';
|
|
7
|
+
import { useThrelte } from '@threlte/core';
|
|
8
|
+
import { createBox, createCapsule, createSphere } from '../geometry';
|
|
9
|
+
import { parsePlyInput } from '../ply';
|
|
11
10
|
export const provideWorldStates = () => {
|
|
12
11
|
const partID = usePartID();
|
|
13
12
|
const resourceNames = useResourceNames(() => partID.current, 'world_state_store');
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
13
|
+
const clients = $derived(resourceNames.current.map(({ name }) => createResourceClient(WorldStateStoreClient, () => partID.current, () => name)));
|
|
14
|
+
$effect(() => {
|
|
15
|
+
const cleanups = [];
|
|
16
|
+
for (const client of clients) {
|
|
17
|
+
cleanups.push(createWorldState(client));
|
|
18
|
+
}
|
|
19
|
+
return () => {
|
|
20
|
+
for (const cleanup of cleanups) {
|
|
21
|
+
cleanup();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
25
24
|
});
|
|
26
25
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
26
|
+
const createWorldState = (client) => {
|
|
27
|
+
const { invalidate } = useThrelte();
|
|
28
|
+
const world = useWorld();
|
|
29
|
+
const entities = new Map();
|
|
30
|
+
const spawnEntity = (transform) => {
|
|
31
|
+
if (entities.has(transform.uuidString)) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const metadata = parseMetadata(transform.metadata?.fields);
|
|
35
|
+
const pose = createPose(transform.poseInObserverFrame?.pose);
|
|
36
|
+
const entityTraits = [];
|
|
37
|
+
const parent = transform.poseInObserverFrame?.referenceFrame;
|
|
38
|
+
if (parent && parent !== 'world') {
|
|
39
|
+
entityTraits.push(traits.Parent(parent));
|
|
40
|
+
}
|
|
41
|
+
if (metadata.color) {
|
|
42
|
+
entityTraits.push(traits.Color(metadata.color));
|
|
43
|
+
}
|
|
44
|
+
if (metadata.colors) {
|
|
45
|
+
entityTraits.push(traits.VertexColors(metadata.colors));
|
|
46
|
+
}
|
|
47
|
+
if (transform.physicalObject) {
|
|
48
|
+
entityTraits.push(traits.Geometry(transform.physicalObject));
|
|
49
|
+
}
|
|
50
|
+
if (metadata.shape === 'line' && metadata.points) {
|
|
51
|
+
entityTraits.push(traits.LineGeometry(metadata.points), traits.DottedLineColor(metadata.lineDotColor));
|
|
52
|
+
}
|
|
53
|
+
if (metadata.gltf) {
|
|
54
|
+
entityTraits.push(traits.GLTF(metadata.gltf));
|
|
55
|
+
}
|
|
56
|
+
if (metadata.shape === 'arrow') {
|
|
57
|
+
entityTraits.push(traits.Arrow);
|
|
58
|
+
}
|
|
59
|
+
entityTraits.push(traits.Name(transform.referenceFrame), traits.Pose(pose), traits.WorldStateStoreAPI);
|
|
60
|
+
const entity = world.spawn(...entityTraits);
|
|
61
|
+
entities.set(transform.uuidString, entity);
|
|
62
|
+
};
|
|
63
|
+
const destroyEntity = (uuid) => {
|
|
64
|
+
const entity = entities.get(uuid);
|
|
65
|
+
if (!entity)
|
|
66
|
+
return;
|
|
67
|
+
entity.destroy();
|
|
68
|
+
entities.delete(uuid);
|
|
69
|
+
};
|
|
70
|
+
const updateEntity = (transform, changes) => {
|
|
71
|
+
const entity = entities.get(transform.uuidString);
|
|
72
|
+
if (!entity)
|
|
73
|
+
return;
|
|
74
|
+
for (const path of changes) {
|
|
75
|
+
if (typeof path === 'string') {
|
|
76
|
+
if (path.startsWith('poseInObserverFrame.pose')) {
|
|
77
|
+
entity.set(traits.Pose, transform.poseInObserverFrame?.pose ?? createPose());
|
|
78
|
+
}
|
|
79
|
+
else if (path.startsWith('physicalObject') && transform.physicalObject) {
|
|
80
|
+
const { geometryType } = transform.physicalObject;
|
|
81
|
+
if (geometryType.case === 'box') {
|
|
82
|
+
entity.set(traits.Box, createBox(geometryType.value));
|
|
83
|
+
}
|
|
84
|
+
else if (geometryType.case === 'capsule') {
|
|
85
|
+
entity.set(traits.Capsule, createCapsule(geometryType.value));
|
|
86
|
+
}
|
|
87
|
+
else if (geometryType.case === 'sphere') {
|
|
88
|
+
entity.set(traits.Sphere, createSphere(geometryType.value));
|
|
89
|
+
}
|
|
90
|
+
else if (geometryType.case === 'mesh') {
|
|
91
|
+
entity.set(traits.BufferGeometry, parsePlyInput(geometryType.value.mesh));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
let initialized = false;
|
|
40
98
|
let flushScheduled = false;
|
|
99
|
+
let pendingEvents = [];
|
|
41
100
|
const listUUIDs = createResourceQuery(client, 'listUUIDs');
|
|
42
|
-
const
|
|
101
|
+
const getTransformQueries = $derived(listUUIDs.data?.map((uuid) => {
|
|
43
102
|
return createResourceQuery(client, 'getTransform', () => [uuid], () => ({ refetchInterval: false }));
|
|
44
103
|
}));
|
|
45
104
|
const changeStream = createResourceStream(client, 'streamTransformChanges', {
|
|
46
105
|
refetchMode: 'replace',
|
|
47
106
|
});
|
|
48
|
-
const initialize = (initial) => {
|
|
49
|
-
const next = { ...transforms };
|
|
50
|
-
for (const transform of initial) {
|
|
51
|
-
next[transform.uuidString] = transform;
|
|
52
|
-
}
|
|
53
|
-
transforms = next;
|
|
54
|
-
initialized = true;
|
|
55
|
-
};
|
|
56
107
|
const applyEvents = (events) => {
|
|
57
|
-
if (events.length === 0)
|
|
58
|
-
return;
|
|
59
|
-
const next = { ...transforms };
|
|
60
108
|
for (const event of events) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!toUpdate)
|
|
73
|
-
continue;
|
|
74
|
-
for (const [path, value] of event.changes) {
|
|
75
|
-
toUpdate = setInUnsafe(toUpdate, path, value);
|
|
76
|
-
}
|
|
77
|
-
next[event.uuidString] = toUpdate;
|
|
78
|
-
break;
|
|
79
|
-
}
|
|
109
|
+
if (event.changeType === TransformChangeType.ADDED) {
|
|
110
|
+
spawnEntity(event.transform);
|
|
111
|
+
}
|
|
112
|
+
else if (event.changeType === TransformChangeType.REMOVED) {
|
|
113
|
+
destroyEntity(event.transform.uuidString);
|
|
114
|
+
}
|
|
115
|
+
else if (event.changeType === TransformChangeType.UPDATED) {
|
|
116
|
+
updateEntity(event.transform, event.updatedFields?.paths ?? []);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
console.error('Unspecified change type.', event);
|
|
80
120
|
}
|
|
81
121
|
}
|
|
82
|
-
|
|
122
|
+
invalidate();
|
|
83
123
|
};
|
|
84
124
|
const scheduleFlush = () => {
|
|
85
125
|
if (flushScheduled)
|
|
@@ -87,64 +127,75 @@ const createWorldState = (partID, resourceName) => {
|
|
|
87
127
|
flushScheduled = true;
|
|
88
128
|
requestAnimationFrame(() => {
|
|
89
129
|
const toApply = pendingEvents;
|
|
90
|
-
if (toApply.length === 0)
|
|
91
|
-
return;
|
|
92
130
|
applyEvents(toApply);
|
|
93
131
|
flushScheduled = false;
|
|
94
132
|
pendingEvents = [];
|
|
95
133
|
});
|
|
96
134
|
};
|
|
97
135
|
$effect(() => {
|
|
98
|
-
if (!
|
|
136
|
+
if (!getTransformQueries)
|
|
99
137
|
return;
|
|
100
138
|
if (initialized)
|
|
101
139
|
return;
|
|
102
|
-
if (
|
|
140
|
+
if (getTransformQueries.some((query) => query?.isLoading))
|
|
103
141
|
return;
|
|
104
|
-
const
|
|
105
|
-
.flatMap((query) => query?.data
|
|
142
|
+
const transforms = getTransformQueries
|
|
143
|
+
.flatMap((query) => query?.data)
|
|
106
144
|
.filter((transform) => transform !== undefined);
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
145
|
+
for (const transform of transforms) {
|
|
146
|
+
spawnEntity(transform);
|
|
147
|
+
}
|
|
148
|
+
invalidate();
|
|
149
|
+
initialized = true;
|
|
110
150
|
});
|
|
111
151
|
$effect(() => {
|
|
112
|
-
worker.onmessage = (e) => {
|
|
113
|
-
if (e.data.type !== 'process')
|
|
114
|
-
return;
|
|
115
|
-
const { events } = e.data ?? { events: [] };
|
|
116
|
-
if (events.length === 0)
|
|
117
|
-
return;
|
|
118
|
-
pendingEvents.push(...events);
|
|
119
|
-
scheduleFlush();
|
|
120
|
-
};
|
|
121
|
-
return () => {
|
|
122
|
-
worker.terminate();
|
|
123
|
-
};
|
|
124
|
-
});
|
|
125
|
-
$effect.pre(() => {
|
|
126
152
|
if (changeStream?.data === undefined)
|
|
127
153
|
return;
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
154
|
+
const eventsByUUID = new Map();
|
|
155
|
+
for (const event of changeStream.data) {
|
|
156
|
+
if (!event.transform) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const uuid = event.transform.uuidString;
|
|
160
|
+
const existing = eventsByUUID.get(uuid);
|
|
161
|
+
if (!existing) {
|
|
162
|
+
eventsByUUID.set(uuid, event);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
switch (event.changeType) {
|
|
166
|
+
case TransformChangeType.REMOVED:
|
|
167
|
+
eventsByUUID.set(uuid, event);
|
|
168
|
+
break;
|
|
169
|
+
case TransformChangeType.ADDED:
|
|
170
|
+
if (existing.changeType !== TransformChangeType.REMOVED) {
|
|
171
|
+
eventsByUUID.set(uuid, event);
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case TransformChangeType.UPDATED:
|
|
175
|
+
// merge with existing updated event
|
|
176
|
+
if (existing.changeType === TransformChangeType.UPDATED) {
|
|
177
|
+
existing.updatedFields ??= { paths: [] };
|
|
178
|
+
const paths = event.updatedFields?.paths ?? [];
|
|
179
|
+
for (const path of paths) {
|
|
180
|
+
if (existing.updatedFields.paths.includes(path)) {
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
existing.updatedFields.paths.push(path);
|
|
184
|
+
}
|
|
185
|
+
existing.transform = event.transform;
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
eventsByUUID.set(uuid, event);
|
|
189
|
+
}
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
pendingEvents.push(...eventsByUUID.values());
|
|
194
|
+
scheduleFlush();
|
|
132
195
|
});
|
|
133
|
-
return {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
get transforms() {
|
|
138
|
-
return transformsList;
|
|
139
|
-
},
|
|
140
|
-
get worldObjects() {
|
|
141
|
-
return worldObjectsList;
|
|
142
|
-
},
|
|
143
|
-
get listUUIDs() {
|
|
144
|
-
return listUUIDs;
|
|
145
|
-
},
|
|
146
|
-
get getTransforms() {
|
|
147
|
-
return getTransforms;
|
|
148
|
-
},
|
|
196
|
+
return () => {
|
|
197
|
+
for (const [, entity] of entities) {
|
|
198
|
+
entity.destroy();
|
|
199
|
+
}
|
|
149
200
|
};
|
|
150
201
|
};
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { default as Geometry } from './components/Geometry.svelte';
|
|
2
2
|
export { default as AxesHelper } from './components/AxesHelper.svelte';
|
|
3
|
+
export { Snapshot } from './draw/v1/snapshot_pb';
|
|
3
4
|
export { BatchedArrow } from './three/BatchedArrow';
|
|
4
5
|
export { CapsuleGeometry } from './three/CapsuleGeometry';
|
|
5
6
|
export { OrientationVector } from './three/OrientationVector';
|
package/dist/lib.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// ensure you write a corresponding unit test to assert the component works in absence of parent providers in /src/lib/__tests__/PureComponents.svelte.spec.ts
|
|
4
4
|
export { default as Geometry } from './components/Geometry.svelte';
|
|
5
5
|
export { default as AxesHelper } from './components/AxesHelper.svelte';
|
|
6
|
+
// Draw
|
|
7
|
+
export { Snapshot } from './draw/v1/snapshot_pb';
|
|
6
8
|
// Classes
|
|
7
9
|
export { BatchedArrow } from './three/BatchedArrow';
|
|
8
10
|
export { CapsuleGeometry } from './three/CapsuleGeometry';
|
|
@@ -7,10 +7,9 @@ export declare class BatchedArrow {
|
|
|
7
7
|
_ids: Set<number>;
|
|
8
8
|
_max: number;
|
|
9
9
|
constructor();
|
|
10
|
-
addArrow(direction: Vector3, origin: Vector3,
|
|
10
|
+
addArrow(direction: Vector3, origin: Vector3, color?: Color): number;
|
|
11
11
|
removeArrow(instanceId: number): void;
|
|
12
12
|
clear(): void;
|
|
13
13
|
getBoundingBoxAt(instanceId: number, target: OBB): OBB;
|
|
14
|
-
updateArrow(instanceId: number, origin: Vector3, direction: Vector3,
|
|
15
|
-
get object3d(): BatchedMesh;
|
|
14
|
+
updateArrow(instanceId: number, origin: Vector3, direction: Vector3, color?: Color): import("three").Quaternion | undefined;
|
|
16
15
|
}
|
|
@@ -3,7 +3,6 @@ import { createArrowGeometry } from './arrow';
|
|
|
3
3
|
const black = new Color('black');
|
|
4
4
|
const axis = new Vector3();
|
|
5
5
|
const object3d = new Object3D();
|
|
6
|
-
const vec3 = new Vector3();
|
|
7
6
|
const box1 = new Box3();
|
|
8
7
|
const col = new Color();
|
|
9
8
|
let index = 0;
|
|
@@ -23,14 +22,14 @@ export class BatchedArrow {
|
|
|
23
22
|
this.mesh.frustumCulled = false;
|
|
24
23
|
this._geometryId = this.mesh.addGeometry(geometry);
|
|
25
24
|
}
|
|
26
|
-
addArrow(direction, origin,
|
|
25
|
+
addArrow(direction, origin, color = black) {
|
|
27
26
|
if (this.mesh.instanceCount >= this._max) {
|
|
28
27
|
this._max += 20_000;
|
|
29
28
|
this.mesh.setInstanceCount(this._max);
|
|
30
29
|
}
|
|
31
30
|
const instanceId = this._pool.pop() ?? this.mesh.addInstance(this._geometryId);
|
|
32
31
|
this._ids.add(instanceId);
|
|
33
|
-
this.updateArrow(instanceId, origin, direction,
|
|
32
|
+
this.updateArrow(instanceId, origin, direction, color);
|
|
34
33
|
return instanceId;
|
|
35
34
|
}
|
|
36
35
|
removeArrow(instanceId) {
|
|
@@ -50,11 +49,7 @@ export class BatchedArrow {
|
|
|
50
49
|
}
|
|
51
50
|
return target;
|
|
52
51
|
}
|
|
53
|
-
updateArrow(instanceId, origin, direction,
|
|
54
|
-
if (arrowHeadAtPose) {
|
|
55
|
-
// Compute the base position so the arrow ends at the origin
|
|
56
|
-
origin.sub(vec3.copy(direction).multiplyScalar(length));
|
|
57
|
-
}
|
|
52
|
+
updateArrow(instanceId, origin, direction, color) {
|
|
58
53
|
direction.normalize();
|
|
59
54
|
object3d.position.copy(origin);
|
|
60
55
|
if (direction.y > 0.99999)
|
|
@@ -72,7 +67,4 @@ export class BatchedArrow {
|
|
|
72
67
|
}
|
|
73
68
|
this.mesh.setVisibleAt(instanceId, true);
|
|
74
69
|
}
|
|
75
|
-
get object3d() {
|
|
76
|
-
return this.mesh;
|
|
77
|
-
}
|
|
78
70
|
}
|
|
@@ -6,5 +6,5 @@ import { LatheGeometry } from 'three';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class CapsuleGeometry extends LatheGeometry {
|
|
8
8
|
type: string;
|
|
9
|
-
constructor(
|
|
9
|
+
constructor(r?: number, l?: number, capSegments?: number, radialSegments?: number);
|
|
10
10
|
}
|