@viamrobotics/motion-tools 1.30.0 → 1.32.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.
Files changed (76) hide show
  1. package/dist/components/App.svelte +51 -46
  2. package/dist/components/App.svelte.d.ts +1 -1
  3. package/dist/components/Entities/Arrows/Arrows.svelte +4 -7
  4. package/dist/components/Entities/hooks/useEntityEvents.svelte.d.ts +0 -1
  5. package/dist/components/Entities/hooks/useEntityEvents.svelte.js +30 -16
  6. package/dist/components/InputBindings.svelte +0 -43
  7. package/dist/components/KeyboardBindings.svelte +38 -0
  8. package/dist/components/KeyboardBindings.svelte.d.ts +18 -0
  9. package/dist/components/PointerMissBox.svelte +6 -3
  10. package/dist/components/Scene.svelte +34 -45
  11. package/dist/components/SceneProviders.svelte +2 -4
  12. package/dist/components/SceneProviders.svelte.d.ts +1 -3
  13. package/dist/components/Selected.svelte +20 -27
  14. package/dist/components/SelectedTransformControls.svelte +10 -8
  15. package/dist/components/StaticGeometries.svelte +3 -5
  16. package/dist/components/hover/HoveredEntities.svelte +15 -14
  17. package/dist/components/hover/HoveredEntities.svelte.d.ts +17 -2
  18. package/dist/components/hover/HoveredEntity.svelte +8 -5
  19. package/dist/components/hover/HoveredEntity.svelte.d.ts +5 -1
  20. package/dist/components/hover/LinkedHoveredEntity.svelte +7 -11
  21. package/dist/components/hover/LinkedHoveredEntity.svelte.d.ts +1 -0
  22. package/dist/components/overlay/Details.svelte +24 -38
  23. package/dist/components/overlay/Details.svelte.d.ts +3 -1
  24. package/dist/components/overlay/controls/Controls.svelte +0 -2
  25. package/dist/components/overlay/dashboard/Button.svelte +5 -3
  26. package/dist/components/overlay/dashboard/Button.svelte.d.ts +1 -1
  27. package/dist/components/overlay/left-pane/Tree.svelte +13 -10
  28. package/dist/components/overlay/left-pane/TreeContainer.svelte +9 -4
  29. package/dist/components/overlay/left-pane/TreeNode.svelte +6 -4
  30. package/dist/draw.d.ts +1 -0
  31. package/dist/draw.js +1 -1
  32. package/dist/ecs/index.d.ts +1 -0
  33. package/dist/ecs/index.js +1 -0
  34. package/dist/ecs/traits.d.ts +22 -5
  35. package/dist/ecs/traits.js +33 -4
  36. package/dist/ecs/useTag.svelte.d.ts +5 -0
  37. package/dist/ecs/useTag.svelte.js +43 -0
  38. package/dist/hooks/useConfigFrames.svelte.js +1 -1
  39. package/dist/hooks/useEnvironment.svelte.d.ts +1 -1
  40. package/dist/hooks/useLinked.svelte.js +7 -8
  41. package/dist/hooks/useMouseRaycaster.svelte.d.ts +4 -3
  42. package/dist/hooks/useMouseRaycaster.svelte.js +1 -0
  43. package/dist/hooks/useSettings.svelte.d.ts +1 -1
  44. package/dist/lib.d.ts +1 -0
  45. package/dist/lib.js +1 -0
  46. package/dist/loaders/pcd/worker.inline.d.ts +1 -1
  47. package/dist/loaders/pcd/worker.inline.js +1 -1
  48. package/dist/loaders/pcd/worker.js +3 -1
  49. package/dist/plugins/Focus/Focus.svelte +45 -0
  50. package/dist/plugins/Focus/Focus.svelte.d.ts +3 -0
  51. package/dist/plugins/Focus/FocusBox.svelte +75 -0
  52. package/dist/plugins/Focus/FocusBox.svelte.d.ts +3 -0
  53. package/dist/plugins/Focus/provideFocus.svelte.d.ts +1 -0
  54. package/dist/plugins/Focus/provideFocus.svelte.js +61 -0
  55. package/dist/{components → plugins}/MeasureTool/MeasureTool.svelte +6 -8
  56. package/dist/plugins/Selection/Ellipse.svelte +21 -16
  57. package/dist/plugins/Selection/Lasso.svelte +21 -16
  58. package/dist/plugins/Selection/SelectionTool.svelte +10 -3
  59. package/dist/plugins/Selection/relations.d.ts +6 -0
  60. package/dist/plugins/Selection/relations.js +7 -0
  61. package/dist/plugins/Selection/traits.d.ts +0 -5
  62. package/dist/plugins/Selection/traits.js +1 -6
  63. package/dist/plugins/index.d.ts +3 -0
  64. package/dist/plugins/index.js +3 -0
  65. package/dist/snapshot.d.ts +14 -0
  66. package/dist/snapshot.js +23 -0
  67. package/dist/three/arrow.d.ts +2 -0
  68. package/dist/three/arrow.js +3 -1
  69. package/package.json +17 -5
  70. package/dist/components/Focus.svelte +0 -46
  71. package/dist/components/Focus.svelte.d.ts +0 -7
  72. package/dist/hooks/useSelection.svelte.d.ts +0 -33
  73. package/dist/hooks/useSelection.svelte.js +0 -94
  74. /package/dist/{components → plugins}/MeasureTool/MeasurePoint.svelte +0 -0
  75. /package/dist/{components → plugins}/MeasureTool/MeasurePoint.svelte.d.ts +0 -0
  76. /package/dist/{components → plugins}/MeasureTool/MeasureTool.svelte.d.ts +0 -0
@@ -6,6 +6,7 @@ import { ColorFormat } from '../buf/draw/v1/metadata_pb';
6
6
  import { createBox, createCapsule, createSphere } from '../geometry';
7
7
  import { parsePcdInWorker } from '../loaders/pcd';
8
8
  import { parsePlyInput } from '../ply';
9
+ import { createPose, matrixToPose, poseToMatrix } from '../transform';
9
10
  export const Name = trait(() => '');
10
11
  export const UUID = trait(() => '');
11
12
  /**
@@ -61,6 +62,13 @@ export const InstancedMatrix = trait(() => ({
61
62
  }));
62
63
  export const Hovered = trait(() => true);
63
64
  export const Invisible = trait(() => true);
65
+ /**
66
+ * Suppresses the default frame-style world/local pose and parent-frame blocks
67
+ * in the details panel. Entities that render their own pose UI via the
68
+ * `details-extensions` portal target (e.g. gizmo plugin entities) opt in by
69
+ * adding this trait.
70
+ */
71
+ export const CustomDetails = trait(() => true);
64
72
  /**
65
73
  * True when the entity itself, or any of its parents up the `ChildOf`
66
74
  * chain, has `Invisible`. Maintained by `provideInheritedInvisible`;
@@ -72,11 +80,14 @@ export const InheritedInvisible = trait(() => true);
72
80
  * Represents that an entity is composed of many instances, so that the treeview and
73
81
  * details panel may display all instances
74
82
  */
75
- export const Instanced = trait(() => true);
83
+ export const InstanceId = trait(() => -1);
76
84
  export const Instance = trait({
77
85
  meshID: -1,
78
86
  instanceID: -1,
79
87
  });
88
+ export const Instances = trait({
89
+ count: 0,
90
+ });
80
91
  export const RenderOrder = trait(() => 0);
81
92
  export const Opacity = trait(() => 1);
82
93
  /**
@@ -100,9 +111,6 @@ export const Colors = trait(() => new Uint8Array());
100
111
  * Per-vertex opacity values packed as uint8 (0-255).
101
112
  */
102
113
  export const Opacities = trait(() => new Uint8Array());
103
- export const Instances = trait({
104
- count: 0,
105
- });
106
114
  export const Arrows = trait({
107
115
  headAtPose: true,
108
116
  });
@@ -175,6 +183,10 @@ export const ReferenceFrame = trait(() => true);
175
183
  */
176
184
  export const ChunkProgress = trait({ loaded: 0, total: 0 });
177
185
  export const SelectToolInteractionLayer = trait(() => true);
186
+ /**
187
+ * This entity is selected by the user
188
+ */
189
+ export const Selected = trait();
178
190
  /**
179
191
  * This entity can be safely removed from the scene by the user
180
192
  */
@@ -250,6 +262,23 @@ export const updateGeometryTrait = (entity, geometry) => {
250
262
  updatePointCloud(entity, geometry.geometryType.value.pointCloud);
251
263
  }
252
264
  };
265
+ /**
266
+ * Patches an entity's `Matrix` trait in-place via the `Pose` round-trip
267
+ * (`matrixToPose` → merge → `poseToMatrix`), then signals `entity.changed(Matrix)`.
268
+ * No-ops silently if the entity has no `Matrix` trait.
269
+ */
270
+ export const writeMatrix = (entity, patch) => {
271
+ const matrix = entity.get(Matrix);
272
+ if (!matrix)
273
+ return;
274
+ const pose = matrixToPose(matrix, createPose());
275
+ const filtered = Object.fromEntries(Object.entries(patch).filter(([, v]) => v !== undefined));
276
+ if (Object.keys(filtered).length === 0)
277
+ return;
278
+ Object.assign(pose, filtered);
279
+ poseToMatrix(pose, matrix);
280
+ entity.changed(Matrix);
281
+ };
253
282
  const updatePointCloud = (entity, pointCloud) => {
254
283
  parsePcdInWorker(new Uint8Array(pointCloud))
255
284
  .then((parsed) => {
@@ -0,0 +1,5 @@
1
+ import { type Entity, type TagTrait, type World } from 'koota';
2
+ export declare function isWorld(target: Entity | World): target is World;
3
+ export declare function useTag(target: () => Entity | World | undefined | null, tag: TagTrait): {
4
+ readonly current: boolean;
5
+ };
@@ -0,0 +1,43 @@
1
+ import { $internal as internal } from 'koota';
2
+ import { useWorld } from './useWorld';
3
+ export function isWorld(target) {
4
+ return typeof target?.spawn === 'function';
5
+ }
6
+ export function useTag(target, tag) {
7
+ const contextWorld = useWorld();
8
+ let value = $state(false);
9
+ $effect(() => {
10
+ const t = target();
11
+ if (!t) {
12
+ value = false;
13
+ return;
14
+ }
15
+ const world = isWorld(t) ? t : contextWorld;
16
+ // ???
17
+ // eslint-disable-next-line prefer-const
18
+ let entity;
19
+ /**
20
+ * Subscribe before reading worldEntity: world.onAdd triggers lazy
21
+ * registration so worldEntity is guaranteed to exist after this.
22
+ */
23
+ const onAddUnsub = world.onAdd(tag, (e) => {
24
+ if (e === entity)
25
+ value = true;
26
+ });
27
+ const onRemoveUnsub = world.onRemove(tag, (e) => {
28
+ if (e === entity)
29
+ value = false;
30
+ });
31
+ entity = isWorld(t) ? t[internal].worldEntity : t;
32
+ value = entity.has(tag);
33
+ return () => {
34
+ onAddUnsub();
35
+ onRemoveUnsub();
36
+ };
37
+ });
38
+ return {
39
+ get current() {
40
+ return value;
41
+ },
42
+ };
43
+ }
@@ -25,7 +25,7 @@ export const provideConfigFrames = () => {
25
25
  });
26
26
  const [fragmentFrames, fragmentUnsetFrameNames] = $derived.by(() => {
27
27
  const { fragment_mods: fragmentMods = [] } = partConfig.current;
28
- const fragmentDefinedComponents = Object.keys(partConfig.componentNameToFragmentInfo);
28
+ const fragmentDefinedComponents = Object.keys(partConfig.componentNameToFragmentInfo ?? {});
29
29
  const results = {};
30
30
  const unsetResults = [];
31
31
  // deal with fragment defined components
@@ -1,6 +1,6 @@
1
1
  export declare const ENVIRONMENT_CONTEXT_KEY: unique symbol;
2
2
  interface Environemnt {
3
- viewerMode: 'edit' | 'monitor' | 'focus';
3
+ viewerMode: 'edit' | 'monitor';
4
4
  isStandalone: boolean;
5
5
  inputBindingsEnabled: boolean;
6
6
  }
@@ -1,20 +1,19 @@
1
1
  import { getContext, setContext } from 'svelte';
2
- import { relations, useWorld } from '../ecs';
3
- import { useFocusedEntity, useSelectedEntity } from './useSelection.svelte';
2
+ import { relations, traits, useQuery, useWorld } from '../ecs';
4
3
  const linkedKey = Symbol('linked-context');
5
4
  export const provideLinkedEntities = () => {
6
5
  const world = useWorld();
7
- const selectedEntity = useSelectedEntity();
8
- const focusedEntity = useFocusedEntity();
9
- const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current);
10
- let linkedEntities = $derived(displayEntity?.targetsFor(relations.SubEntityLink) ?? []);
6
+ const selected = useQuery(traits.Selected);
7
+ let linkedEntities = $derived(selected.current
8
+ .flatMap((entity) => entity.targetFor(relations.SubEntityLink))
9
+ .filter((entity) => entity !== undefined));
11
10
  const unsubAdd = world.onAdd(relations.SubEntityLink, (entity, target) => {
12
- if (entity === displayEntity) {
11
+ if (selected.current.includes(entity)) {
13
12
  linkedEntities = [...linkedEntities, target];
14
13
  }
15
14
  });
16
15
  const unsubRemove = world.onRemove(relations.SubEntityLink, (entity, target) => {
17
- if (entity === displayEntity) {
16
+ if (selected.current.includes(entity)) {
18
17
  linkedEntities = linkedEntities.filter((e) => e !== target);
19
18
  }
20
19
  });
@@ -5,9 +5,10 @@ interface RaycastEvent<T extends EventNames> {
5
5
  intersections: Intersection[];
6
6
  }
7
7
  type Callback<T extends EventNames> = (event: RaycastEvent<T>) => void;
8
- export declare const useMouseRaycaster: (getOptions?: () => {
9
- enabled: boolean;
10
- }) => {
8
+ interface MouseRaycasterOptions {
9
+ enabled?: boolean;
10
+ }
11
+ export declare const useMouseRaycaster: (getOptions?: () => MouseRaycasterOptions) => {
11
12
  raycaster: Raycaster;
12
13
  onclick: (cb: Callback<"click">) => void;
13
14
  onmove: (cb: Callback<"move">) => void;
@@ -69,6 +69,7 @@ export const useMouseRaycaster = (getOptions) => {
69
69
  if (!options.enabled) {
70
70
  return;
71
71
  }
72
+ raycaster.firstHitOnly = true;
72
73
  dom.addEventListener('pointermove', onPointerMove, { passive: true });
73
74
  dom.addEventListener('pointerdown', onPointerDown, { passive: true });
74
75
  dom.addEventListener('pointerup', onPointerUp, { passive: true });
@@ -1,7 +1,7 @@
1
1
  import type { ColorRepresentation } from 'three';
2
2
  export interface Settings {
3
3
  cameraMode: 'orthographic' | 'perspective';
4
- interactionMode: 'navigate' | 'measure' | 'select';
4
+ interactionMode: 'navigate' | 'measure' | 'select' | 'gizmo';
5
5
  refreshRates: {
6
6
  poses: number;
7
7
  pointclouds: number;
package/dist/lib.d.ts CHANGED
@@ -7,3 +7,4 @@ export { OrientationVector } from './three/OrientationVector';
7
7
  export { parsePcdInWorker } from './loaders/pcd';
8
8
  export { createBinaryPCD } from './pcd';
9
9
  export { metadataFromStruct } from './metadata';
10
+ export { decodeDrawnSnapshotPointClouds } from './snapshot';
package/dist/lib.js CHANGED
@@ -13,3 +13,4 @@ export { OrientationVector } from './three/OrientationVector';
13
13
  export { parsePcdInWorker } from './loaders/pcd';
14
14
  export { createBinaryPCD } from './pcd';
15
15
  export { metadataFromStruct } from './metadata';
16
+ export { decodeDrawnSnapshotPointClouds } from './snapshot';