diff --git a/.changeset/kind-hats-shop.md b/.changeset/kind-hats-shop.md new file mode 100644 index 000000000..ee115730f --- /dev/null +++ b/.changeset/kind-hats-shop.md @@ -0,0 +1,5 @@ +--- +'@viamrobotics/motion-tools': patch +--- + +Add plugin docs and make plugin dependencies optional diff --git a/docs/src/content/docs/plugins/draw-service.mdx b/docs/src/content/docs/plugins/draw-service.mdx index ccb3dbc64..a7a5b93a8 100644 --- a/docs/src/content/docs/plugins/draw-service.mdx +++ b/docs/src/content/docs/plugins/draw-service.mdx @@ -1,6 +1,81 @@ --- title: -description: Stream draw-server output into an embedded motion-tools visualizer. +description: Stream a running draw server's output into an embedded motion-tools visualizer. --- -Documentation coming soon. +`` connects an embedded `` to a running draw server over WebSocket so any `client/api` calls made elsewhere render in this instance live. Skip it if you only render snapshots — snapshots are entirely client-side and don't need the server. + +The plugin is **headless**: it provides the connection context and starts the stream; it doesn't render anything itself. + +The Connect RPC client is required for the ``. + +## Install + +```bash +pnpm add @connectrpc/connect @connectrpc/connect-web +``` + +## Usage + +```svelte + + +
+ + + +
+``` + +## Props + +| Prop | Type | Description | +| -------- | ---------------------------------------------- | ------------------------------------------------------------- | +| `config` | `{ backendIP: string; websocketPort: string }` | Host and port of the draw server. Default dev port is `3030`. | + +The `config` prop is reactive — change it and the plugin reconnects to the new endpoint. + +## Running a draw server + +`` is a client — it needs a draw server to talk to. You have three options: + +### Use the motion-tools local app + +The fastest path: run motion-tools locally (`make up` or `pnpm dev`). The local app already hosts a draw server on port `3030`, and `client/api` calls to the same host land in it. + +### Host the Go `DrawService` yourself + +Motion-tools exports a ready-made `DrawService` from `github.com/viam-labs/motion-tools/draw` — the same Connect-RPC handler the local app uses. Wire it up to your own HTTP server: + +```go +package main + +import ( + "log" + "net/http" + + "connectrpc.com/connect" + "github.com/viam-labs/motion-tools/draw" + "github.com/viam-labs/motion-tools/draw/v1/drawv1connect" +) + +func main() { + svc := draw.NewDrawService("") // "" = use os.TempDir for chunked buffers + + mux := http.NewServeMux() + mux.Handle(drawv1connect.NewDrawServiceHandler(svc)) + + log.Fatal(http.ListenAndServe(":3030", mux)) +} +``` + +Your `client/api` producer code then points at this server, and `` in the browser subscribes to its stream. + +### Implement your own server + +If you need a custom backend (different language, different storage, extra side effects), the proto definitions are published under `github.com/viam-labs/motion-tools/draw/v1` (Go) and ship as `.proto` files in the source tree under `protos/draw/v1/`. Implement the `DrawService` RPCs (`AddEntity`, `UpdateEntity`, `RemoveEntity`, `StreamEntityChanges`, …) in whichever language you like; `` just needs a Connect-RPC server at the configured host:port. + +See the [`client/api`](../../api/client-api/) reference for the producer-side calls regardless of which server you use. diff --git a/docs/src/content/docs/plugins/selection.mdx b/docs/src/content/docs/plugins/selection.mdx index 5c2eccef7..d22e6ae4f 100644 --- a/docs/src/content/docs/plugins/selection.mdx +++ b/docs/src/content/docs/plugins/selection.mdx @@ -1,6 +1,66 @@ --- title: -description: Lasso-pick points and geometries inside a motion-tools visualizer. +description: Lasso- or ellipse-pick points and geometries inside a motion-tools visualizer. --- -Documentation coming soon. +`` adds a selection mode to the visualizer — a dashboard toggle plus an on-canvas lasso or ellipse tool that captures the points and geometries inside the drawn region. Selected entities are exposed via the `useSelectionPlugin` hook so you can react to them from your own UI. + +Selection mode automatically switches the camera to orthographic so 2D screen-space picking maps cleanly to the scene. + +The polygon-triangulation `earcut` library is required for the ``. + +## Install + +```bash +pnpm add earcut +``` + +## Usage + +```svelte + + +
+ + + +
+``` + +A new toggle appears in the top dashboard; clicking it enters selection mode. The popover next to it switches between **Lasso** and **Ellipse** tools. + +## Props + +| Prop | Type | Default | Description | +| ----------------------- | --------- | ------- | --------------------------------------------------------------------------------------------- | +| `enabled` | `boolean` | `false` | Enter selection mode automatically on mount. | +| `autoSelectNewEntities` | `boolean` | `false` | Auto-select the most recently created selection entity (sets it as the focused entity). | +| `children` | `Snippet` | — | Rendered only while selection mode is active — useful for overlays scoped to the active tool. | + +## Reading the selection + +Use `useSelectionPlugin` to read the current set of selected entities from anywhere inside ``: + +```svelte + + +

Selected {selection.current.length} entities

+ +``` + +The hook also exposes `clearSelections()` to remove all selection-marker entities from the world. + +## Traits + +For lower-level access to selection state (e.g. querying which points fall inside a selected region), the plugin exports its Koota traits under the `selectionTraits` namespace: + +```ts +import { selectionTraits } from '@viamrobotics/motion-tools/plugins' +``` diff --git a/docs/src/content/docs/plugins/skybox.mdx b/docs/src/content/docs/plugins/skybox.mdx index dafdbc2ad..6febf183b 100644 --- a/docs/src/content/docs/plugins/skybox.mdx +++ b/docs/src/content/docs/plugins/skybox.mdx @@ -3,4 +3,33 @@ title: description: Render an equirectangular skybox dome around the motion-tools scene. --- -Documentation coming soon. +`` wraps the scene in a [grounded skybox dome](https://threejs.org/examples/?q=skybox#webgl_materials_envmaps_groundprojected) loaded from an equirectangular image, anchoring the lower hemisphere to the world XY plane so geometry sits convincingly on the ground. + +Use it to add real-world context to a snapshot — a warehouse, a lab, or any 360° photo of the environment the robot operates in. + +## Usage + +```svelte + + +
+ + + +
+``` + +The image should be a 2:1 equirectangular projection (the standard format for 360° photos). Drop it in your app's `public/` directory or point `url` at any reachable HTTP endpoint. + +## Props + +| Prop | Type | Default | Description | +| ---------- | ----------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `url` | `string` | — | URL of the equirectangular image. Required. | +| `position` | `[x: number, y: number, z: number]` | `[0, 0, height]` | World-space center of the dome. Default anchors the ground plane at world Z=0. | +| `rotation` | `[x: number, y: number, z: number]` | `[Math.PI / 2, 0, 0]` | Euler rotation in radians. Default aligns the image's vertical axis (+Y) with this scene's vertical axis (+Z); the Z component then acts as yaw. | +| `height` | `number` | `15` | Camera height above ground when the source photo was taken. Larger values magnify the lower portion of the image. | +| `radius` | `number` | `100` | Dome radius. Must exceed the scene camera's reach so the camera stays inside the dome. | diff --git a/package.json b/package.json index 8b60ba91d..908a69789 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,8 @@ "@ag-grid-community/core": "32.3.9", "@ag-grid-community/styles": "32.3.9", "@changesets/cli": "2.29.6", + "@connectrpc/connect": "1.7.0", + "@connectrpc/connect-web": "1.7.0", "@dimforge/rapier3d-compat": "0.18.2", "@eslint/compat": "2.0.2", "@eslint/js": "10.0.1", @@ -86,6 +88,7 @@ "@zag-js/tree-view": "1.22.1", "camera-controls": "3.1.0", "concurrently": "^9.2.1", + "earcut": "^3.0.2", "esbuild": "^0.27.3", "eslint": "10.0.2", "eslint-config-prettier": "10.1.8", @@ -121,6 +124,8 @@ "@ag-grid-community/client-side-row-model": ">=32.3.0", "@ag-grid-community/core": ">=32.3.0", "@ag-grid-community/styles": ">=32.3.0", + "@connectrpc/connect": ">=1", + "@connectrpc/connect-web": ">=1", "@dimforge/rapier3d-compat": ">=0.17", "@tanstack/svelte-query-devtools": ">=6", "@threlte/core": ">=8", @@ -139,6 +144,7 @@ "@zag-js/toggle-group": ">=1", "@zag-js/tree-view": ">=1", "camera-controls": ">=3", + "earcut": ">=3", "idb-keyval": ">=6", "lucide-svelte": ">=0.511", "runed": ">=0.28", @@ -147,8 +153,17 @@ "svelte-virtuallists": ">=1" }, "peerDependenciesMeta": { + "@connectrpc/connect": { + "optional": true + }, + "@connectrpc/connect-web": { + "optional": true + }, "@tanstack/svelte-query-devtools": { "optional": true + }, + "earcut": { + "optional": true } }, "pnpm": { @@ -193,10 +208,7 @@ ], "dependencies": { "@bufbuild/protobuf": "1.10.1", - "@connectrpc/connect": "1.7.0", - "@connectrpc/connect-web": "1.7.0", "@neodrag/svelte": "^2.3.3", - "earcut": "^3.0.2", "filtrex": "^3.1.0", "koota": "0.6.5", "lodash-es": "4.18.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1317fc9c..920c11f7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,21 +15,12 @@ importers: '@bufbuild/protobuf': specifier: 1.10.1 version: 1.10.1 - '@connectrpc/connect': - specifier: 1.7.0 - version: 1.7.0(@bufbuild/protobuf@1.10.1) - '@connectrpc/connect-web': - specifier: 1.7.0 - version: 1.7.0(@bufbuild/protobuf@1.10.1)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.1)) '@neodrag/svelte': specifier: ^2.3.3 version: 2.3.3(svelte@5.55.7) '@zag-js/dialog': specifier: '>=1.31' version: 1.32.0 - earcut: - specifier: ^3.0.2 - version: 3.0.2 filtrex: specifier: ^3.1.0 version: 3.1.0 @@ -58,6 +49,12 @@ importers: '@changesets/cli': specifier: 2.29.6 version: 2.29.6(@types/node@25.6.0) + '@connectrpc/connect': + specifier: 1.7.0 + version: 1.7.0(@bufbuild/protobuf@1.10.1) + '@connectrpc/connect-web': + specifier: 1.7.0 + version: 1.7.0(@bufbuild/protobuf@1.10.1)(@connectrpc/connect@1.7.0(@bufbuild/protobuf@1.10.1)) '@dimforge/rapier3d-compat': specifier: 0.18.2 version: 0.18.2 @@ -187,6 +184,9 @@ importers: concurrently: specifier: ^9.2.1 version: 9.2.1 + earcut: + specifier: ^3.0.2 + version: 3.0.2 esbuild: specifier: ^0.27.3 version: 0.27.3