@weasel-js/kernel3d 1.9.4 → 1.10.1

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 CHANGED
@@ -31,7 +31,7 @@ numbers: a 3D host passes the dispatcher an identity `clientToWorld`, so
31
31
  `ctx.world` is the screen point, and each dep rebuilds the ray itself. Tools,
32
32
  the select tool included, transfer untouched.
33
33
 
34
- One thing does not, and the kernel says so rather than guessing:
34
+ One thing does not:
35
35
 
36
36
  - **`ViewApi` has no orientation**, so an orbit camera cannot travel through
37
37
  the kit's `view`. The kernel declares a `camera3d` dep of its own.
@@ -46,7 +46,7 @@ away it is.
46
46
 
47
47
  **The answer is "as far as it already was."** Both resolve the rectangle on the
48
48
  plane through the pose they were handed, facing the camera, so neither changes
49
- depth. Two consequences worth knowing before you build on them:
49
+ depth. Two consequences:
50
50
 
51
51
  - A resize scales uniformly. The rectangle names two extents and a pose has
52
52
  three, so the factor is the geometric mean of the two it names.
package/dist/index.d.ts CHANGED
@@ -140,14 +140,9 @@ declare function projectAabbToScreen(box: Aabb, viewProjection: Mat4, rect: Scre
140
140
  /**
141
141
  * The kit's deps, implemented against a 3D world.
142
142
  *
143
- * Every one of these takes its camera from a thunk rather than an argument.
144
- * That is the kernel's central claim in code: the dispatcher keeps handing
145
- * actions two numbers, and what makes them mean something in 3D is the camera
146
- * each dep already closes over. `InvocationCtx` needs no widening, and none of
147
- * these needs a ray passed in.
148
- *
149
- * Where a kit contract cannot be honored, the implementation throws rather than
150
- * guessing. A guess would report a fit the kernel does not have.
143
+ * Every one of these takes its camera from a thunk rather than an argument:
144
+ * the dispatcher keeps handing actions two numbers, and what makes them mean
145
+ * something in 3D is the camera each dep already closes over.
151
146
  */
152
147
 
153
148
  /** The camera and the pane it draws into; `width`/`height` are the pane's
@@ -171,11 +166,9 @@ type Scene3d<TData, TLayer extends string> = Scene<TData, TLayer, Pose3>;
171
166
  /** A node of a `Scene3d`. */
172
167
  type Node3d<TData, TLayer extends string> = SceneNode<TData, TLayer, Pose3>;
173
168
  /**
174
- * The world box a node occupies. The kernel cannot answer this, and the reason
175
- * is sharper than "it does not know the mesh": a sphere's box is the same under
176
- * every rotation, and no transform of a local box reproduces that — rotate a
177
- * cube and it widens. Asking for the world box directly is what lets a
178
- * primitive answer for its own symmetry.
169
+ * The world box a node occupies, rather than a local box to transform: a
170
+ * sphere's box is the same under every rotation, and no transform of a local
171
+ * box reproduces that — rotate a cube and it widens.
179
172
  *
180
173
  * Omitted, a node is a unit cube carried by its pose.
181
174
  */
@@ -220,9 +213,9 @@ interface Footprint {
220
213
  * implies is the consumer's answer — the kernel does not know what it is
221
214
  * inserting.
222
215
  *
223
- * The kit's `InsertDep.commit` hands over a screen-space AABB and nothing else,
224
- * which turns out to be enough: the depth the 2D contract cannot express comes
225
- * from the plane, not from the caller.
216
+ * The kit's `InsertDep.commit` hands over a screen-space AABB and nothing else:
217
+ * the depth the 2D contract cannot express comes from the plane, not from the
218
+ * caller.
226
219
  */
227
220
  declare function createInsert(opts: {
228
221
  viewport: ViewportSource;
@@ -233,33 +226,29 @@ declare function createInsert(opts: {
233
226
  }): InsertDep;
234
227
  /**
235
228
  * `PoseDescriptor` over a 3D pose, with `Bounds` read as the screen box the
236
- * node covers. Chrome and marquee math work unchanged; the two methods that
237
- * run the other way cannot.
229
+ * node covers.
238
230
  *
239
- * `forNode` is what lets a sphere bound itself as a sphere: every node is a
240
- * `Pose3`, so the shape lives on `node.data` and nothing but the node can say
241
- * which one this is. Unspecialized — the kit calling with only a pose in hand —
231
+ * `forNode` is what lets a sphere bound itself as a sphere: the shape lives
232
+ * on `node.data`. Unspecialized — the kit calling with only a pose in hand —
242
233
  * it answers with the default local box, which is the looser of the two.
243
234
  *
244
- * The two methods that run the other way — `remapBounds` and `fromBounds` —
245
- * take a screen rectangle, which names a pose only once something supplies a
246
- * depth. Both resolve it against the plane through the pose they were handed,
247
- * facing the camera, so nothing they produce changes depth. See
248
- * `viewPlaneAt`.
235
+ * `remapBounds` and `fromBounds` take a screen rectangle, which names a pose
236
+ * only once something supplies a depth. Both resolve it against the plane
237
+ * through the pose they were handed, facing the camera, so nothing they
238
+ * produce changes depth.
249
239
  */
250
240
  declare function createPoseDescriptor<TData, TLayer extends string>(world: World3d<TData, TLayer>): PoseDescriptor<Pose3, Node3d<TData, TLayer>>;
251
241
 
252
242
  /**
253
243
  * What a host paints for a gesture that proposes chrome rather than a pose.
254
244
  *
255
- * A marquee sweep and a box-drag both publish an `OngoingOverlay`, which used
256
- * to reach paint only through core's own 2D layer. `resolveOverlays` hands back
257
- * world geometry with no renderer in it, so the same call `<SceneCanvas>` makes
258
- * serves a consumer-owned 3D renderer.
245
+ * A marquee sweep and a box-drag both publish an `OngoingOverlay`.
246
+ * `resolveOverlays` hands back world geometry with no renderer in it, so the
247
+ * same call `<SceneCanvas>` makes serves a consumer-owned 3D renderer.
259
248
  *
260
249
  * A 3D host's `clientToWorld` is identity, so an overlay's world bounds are the
261
250
  * client rect the deps already work in, and the pane origin comes off exactly
262
- * once. Only the rectangular variants resolve here: a lasso, a pencil and a run
251
+ * once. Only the rectangular variants resolve here: a lasso, a pencil, and a run
263
252
  * of points are paths, and a path is geometry this cannot flatten to a box.
264
253
  */
265
254
 
@@ -287,7 +276,7 @@ declare const orbitAction: Action;
287
276
  declare const dollyAction: Action;
288
277
  /** A tool that binds drag to `camera.orbit`. Register `orbitAction` alongside
289
278
  * it; the tool only declares the binding. */
290
- declare function useOrbitTool(): Tool<null>;
279
+ declare function useOrbitTool(): Tool;
291
280
 
292
281
  /**
293
282
  * The kernel's one new dep.
package/dist/index.js CHANGED
@@ -379,11 +379,7 @@ function createPoseDescriptor(world) {
379
379
  scale: sub(box.max, box.min)
380
380
  };
381
381
  },
382
- /**
383
- * Screen-space deltas resolve against the plane the node already sits on,
384
- * so the two numbers the kit passes are enough: the camera that turns
385
- * them into a world position is the one this dep closed over.
386
- */
382
+ /** Screen-space deltas resolve against the plane the node already sits on. */
387
383
  translate(pose, dx, dy) {
388
384
  const vp = castableViewport();
389
385
  if (!vp) return pose;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/camera.ts","../src/pose3.ts","../src/screen.ts","../src/deps.ts","../src/overlays.ts","../src/tools.ts"],"names":["normalize","sub","scaleBy","quatIdentity"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * An orbit camera: a target, two angles and a distance. Immutable — every\n * gesture returns a new one, so it can live in instrument state.\n *\n * This is the shape `ViewApi` cannot hold, and the reason the kernel declares a\n * `camera3d` dep of its own rather than reusing the kit's `view`.\n */\n\nimport {\n lookAt,\n multiply,\n perspective,\n type Mat4,\n type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** An orbit camera. The eye sits `distance` world units from `target` at\n * `yaw`/`pitch`; `fov` is the vertical field of view in radians, and\n * `near`/`far` the clip distances. */\nexport interface Camera3d {\n target: Vec3;\n /** Radians about +y, measured from +z. */\n yaw: number;\n /** Radians above the xz plane. */\n pitch: number;\n distance: number;\n fov: number;\n near: number;\n far: number;\n}\n\n/** Short of vertical: at exactly ±π/2 the eye lands on the up axis and `lookAt` degenerates. */\nexport const MAX_PITCH = Math.PI / 2 - 0.01;\nconst MIN_DISTANCE = 0.5;\nconst MAX_DISTANCE = 500;\nconst UP: Vec3 = { x: 0, y: 1, z: 0 };\n\n/** A camera with defaults for every field not given: origin target, level at\n * yaw 0, distance 10, fov π/4, near 0.1, far 1000. */\nexport function createCamera(init: Partial<Camera3d>): Camera3d {\n return {\n target: init.target ?? { x: 0, y: 0, z: 0 },\n yaw: init.yaw ?? 0,\n pitch: init.pitch ?? 0,\n distance: init.distance ?? 10,\n fov: init.fov ?? Math.PI / 4,\n near: init.near ?? 0.1,\n far: init.far ?? 1000,\n };\n}\n\n/** The eye's world position. */\nexport function cameraEye(camera: Camera3d): Vec3 {\n const { target, yaw, pitch, distance } = camera;\n const horizontal = Math.cos(pitch) * distance;\n return {\n x: target.x + horizontal * Math.sin(yaw),\n y: target.y + Math.sin(pitch) * distance,\n z: target.z + horizontal * Math.cos(yaw),\n };\n}\n\n/** World-to-view matrix, with +y up. */\nexport function cameraView(camera: Camera3d): Mat4 {\n return lookAt(cameraEye(camera), camera.target, UP);\n}\n\n/** World-to-clip matrix for a pane of the given width/height `aspect`. */\nexport function cameraViewProjection(camera: Camera3d, aspect: number): Mat4 {\n return multiply(perspective(camera.fov, aspect, camera.near, camera.far), cameraView(camera));\n}\n\n/** The camera turned about its target by the given radians. Pitch is clamped\n * to ±`MAX_PITCH`; yaw is not wrapped. */\nexport function orbitBy(camera: Camera3d, deltaYaw: number, deltaPitch: number): Camera3d {\n return {\n ...camera,\n yaw: camera.yaw + deltaYaw,\n pitch: Math.max(-MAX_PITCH, Math.min(MAX_PITCH, camera.pitch + deltaPitch)),\n };\n}\n\n/** The camera with its distance multiplied by `factor`, clamped to 0.5..500. */\nexport function dollyBy(camera: Camera3d, factor: number): Camera3d {\n return {\n ...camera,\n distance: Math.max(MIN_DISTANCE, Math.min(MAX_DISTANCE, camera.distance * factor)),\n };\n}\n","/**\n * A 3D pose, and the two things every consumer of one needs: its matrix, and\n * the world box it occupies.\n *\n * `Scene<TData, TLayer, Pose3>` is the whole of how this reaches weasel —\n * `Scene` is generic over its pose and holds this one with no adapter, no\n * subclass and no special case.\n */\n\nimport {\n compose, quatIdentity, transformAabb, type Aabb, type Mat4, type Quat, type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** Position, rotation and scale of a 3D node. */\nexport interface Pose3 {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n}\n\n/** The box a primitive occupies before its pose. A unit primitive centred on\n * its own origin — which is what the kernel assumes nothing about — is\n * `UNIT_CUBE`. */\nexport const UNIT_CUBE: Aabb = {\n min: { x: -0.5, y: -0.5, z: -0.5 },\n max: { x: 0.5, y: 0.5, z: 0.5 },\n};\n\n/** A pose at `position`, unscaled and unrotated unless given. */\nexport function pose3(\n position: Vec3,\n scale: Vec3 = { x: 1, y: 1, z: 1 },\n rotation: Quat = quatIdentity(),\n): Pose3 {\n return { position, rotation, scale };\n}\n\n/** The pose as a matrix: scale, then rotation, then translation to\n * `position`. */\nexport function poseMatrix(pose: Pose3): Mat4 {\n return compose(pose.position, pose.rotation, pose.scale);\n}\n\n/**\n * The world box a posed primitive occupies, given the box it occupies in its\n * own space.\n *\n * Which local box a primitive has is the consumer's answer, not the kernel's:\n * a sphere's is rotation-invariant and a mesh's comes from its vertices, and\n * neither is something a pose can tell you.\n */\nexport function aabbOfPose(pose: Pose3, local: Aabb = UNIT_CUBE): Aabb {\n return transformAabb(poseMatrix(pose), local);\n}\n","/**\n * The screen side of the kernel: where a pointer points, and what rectangle a\n * world box covers. This is the seam weasel's 2D chrome meets — everything\n * here speaks `Bounds`-shaped screen rectangles, which is why a 3D host can\n * pass the dispatcher's world point through unchanged.\n */\n\nimport {\n invert,\n normalize,\n sub,\n transformPoint,\n transformPoint4,\n type Aabb,\n type Mat4,\n type Ray,\n type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** A screen rectangle in CSS pixels, in the shape core's `Bounds` uses. Both\n * a pane's own rect and a projected world box are this — one spelling, so the\n * two never need converting between. */\nexport interface ScreenBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A `ScreenBox` a host is being asked to outline. `tint` says why: warm for\n * what is selected, cool for what the gesture in hand is proposing. */\nexport interface ChromeBox extends ScreenBox {\n tint?: 'selection' | 'gesture';\n}\n\n/** Screen point (y down, rect-relative) to normalized device coordinates (y up). */\nexport function screenToNdc(\n point: { x: number; y: number },\n rect: ScreenBox,\n): { x: number; y: number } {\n return {\n x: ((point.x - rect.x) / rect.width) * 2 - 1,\n y: 1 - ((point.y - rect.y) / rect.height) * 2,\n };\n}\n\n/** Inverse of `screenToNdc`: normalized device coordinates (y up) to a point\n * in `rect`'s space (y down). */\nexport function ndcToScreen(\n ndc: { x: number; y: number },\n rect: ScreenBox,\n): { x: number; y: number } {\n return {\n x: rect.x + (ndc.x * 0.5 + 0.5) * rect.width,\n y: rect.y + (1 - (ndc.y * 0.5 + 0.5)) * rect.height,\n };\n}\n\n/**\n * The ray a screen point names, given the camera that drew the rect. This is\n * the whole of what 3D picking needs from a pointer — which is why the world\n * point the dispatcher carries stays two numbers.\n *\n * `null` when the point names no ray: the view-projection has no inverse (a\n * camera on its own target, a degenerate projection) or the pane has no area.\n */\nexport function rayThroughScreenPoint(\n point: { x: number; y: number },\n rect: ScreenBox,\n viewProjection: Mat4,\n eye: Vec3,\n): Ray | null {\n const inv = invert(viewProjection);\n if (!inv) return null;\n const ndc = screenToNdc(point, rect);\n const near = transformPoint(inv, { x: ndc.x, y: ndc.y, z: -1 });\n const far = transformPoint(inv, { x: ndc.x, y: ndc.y, z: 1 });\n const direction = normalize(sub(far, near));\n // normalize answers zero for a non-finite difference, which is no direction.\n if (direction.x === 0 && direction.y === 0 && direction.z === 0) return null;\n return { origin: eye, direction };\n}\n\ntype Clip = readonly [number, number, number, number];\n\n/** Signed distance to the near plane in clip space; `>= 0` is in front of it.\n * GL puts the near plane at `z = -w`. */\nfunction nearSide(p: Clip): number {\n return p[2] + p[3];\n}\n\nfunction lerpClip(a: Clip, b: Clip, t: number): Clip {\n return [\n a[0] + (b[0] - a[0]) * t,\n a[1] + (b[1] - a[1]) * t,\n a[2] + (b[2] - a[2]) * t,\n a[3] + (b[3] - a[3]) * t,\n ];\n}\n\n/** The three edges leaving corner `i` toward a higher bit, as bit masks. */\nconst EDGE_BITS = [1, 2, 4] as const;\n\n/**\n * The screen rectangle a world-space box covers — the currency weasel's chrome\n * and `PoseDescriptor.getBounds` speak in. `null` when the box is entirely\n * behind the near plane.\n *\n * Each of the twelve edges is clipped against the near plane before it is\n * projected, rather than dropping the corners behind it. Dropping them reports\n * a box that is too small for anything straddling the near plane, and the error\n * grows as the camera moves in: a solid the pointer is inside of would outline\n * as a sliver, or as nothing.\n */\nexport function projectAabbToScreen(\n box: Aabb,\n viewProjection: Mat4,\n rect: ScreenBox,\n): ScreenBox | null {\n const corners: Clip[] = [];\n for (let i = 0; i < 8; i++) {\n const corner: Vec3 = {\n x: i & 1 ? box.max.x : box.min.x,\n y: i & 2 ? box.max.y : box.min.y,\n z: i & 4 ? box.max.z : box.min.z,\n };\n corners.push(transformPoint4(viewProjection, corner));\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n let any = false;\n\n const extend = (p: Clip): void => {\n if (!(p[3] > 0)) return;\n const screen = ndcToScreen({ x: p[0] / p[3], y: p[1] / p[3] }, rect);\n minX = Math.min(minX, screen.x);\n minY = Math.min(minY, screen.y);\n maxX = Math.max(maxX, screen.x);\n maxY = Math.max(maxY, screen.y);\n any = true;\n };\n\n for (let i = 0; i < 8; i++) {\n for (const bit of EDGE_BITS) {\n if (i & bit) continue;\n let a = corners[i];\n let b = corners[i | bit];\n const da = nearSide(a);\n const db = nearSide(b);\n if (da < 0 && db < 0) continue;\n if (da < 0) a = lerpClip(a, b, da / (da - db));\n else if (db < 0) b = lerpClip(b, a, db / (db - da));\n extend(a);\n extend(b);\n }\n }\n\n if (!any) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n","/**\n * The kit's deps, implemented against a 3D world.\n *\n * Every one of these takes its camera from a thunk rather than an argument.\n * That is the kernel's central claim in code: the dispatcher keeps handing\n * actions two numbers, and what makes them mean something in 3D is the camera\n * each dep already closes over. `InvocationCtx` needs no widening, and none of\n * these needs a ray passed in.\n *\n * Where a kit contract cannot be honored, the implementation throws rather than\n * guessing. A guess would report a fit the kernel does not have.\n */\n\nimport type {\n AreaSelectDep,\n InsertDep,\n InsertExtras,\n NodeAtPointDep,\n NodeId,\n PoseDescriptor,\n Scene,\n SceneNode,\n SnapDep,\n} from '@weasel-js/core';\nimport {\n add,\n dot,\n intersectRayAabb,\n intersectRayPlane,\n len,\n normalize,\n quatIdentity,\n scale as scaleBy,\n sub,\n type Aabb,\n type Ray,\n type Vec3,\n} from '@weasel-js/geom/3d';\nimport { cameraEye, cameraViewProjection, type Camera3d } from './camera';\nimport { aabbOfPose, type Pose3 } from './pose3';\nimport {\n projectAabbToScreen,\n rayThroughScreenPoint,\n type ScreenBox,\n} from './screen';\n\n/** The camera and the pane it draws into; `width`/`height` are the pane's\n * size in the same units as the pointer points. */\nexport interface Viewport3d {\n camera: Camera3d;\n width: number;\n height: number;\n /**\n * Where the pane sits in client coordinates. A 3D host works in one space\n * from the event to the ray — it passes the dispatcher an identity\n * `clientToWorld` — so the deps subtract this rather than the dispatcher.\n */\n originX?: number;\n originY?: number;\n}\n\n/** Read on every dep call, so a dep always sees the current camera and pane. */\nexport type ViewportSource = () => Viewport3d;\n\n/** A 3D scene is core's scene with a `Pose3`. Nothing wraps it. */\nexport type Scene3d<TData, TLayer extends string> = Scene<TData, TLayer, Pose3>;\n/** A node of a `Scene3d`. */\nexport type Node3d<TData, TLayer extends string> = SceneNode<TData, TLayer, Pose3>;\n\n/**\n * The world box a node occupies. The kernel cannot answer this, and the reason\n * is sharper than \"it does not know the mesh\": a sphere's box is the same under\n * every rotation, and no transform of a local box reproduces that — rotate a\n * cube and it widens. Asking for the world box directly is what lets a\n * primitive answer for its own symmetry.\n *\n * Omitted, a node is a unit cube carried by its pose.\n */\nexport type NodeBounds<TData, TLayer extends string> = (\n node: Node3d<TData, TLayer>,\n) => Aabb;\n\n/** What every 3D dep is built from: the scene, the viewport, and optionally\n * each node's world box. */\nexport interface World3d<TData, TLayer extends string> {\n scene: Scene3d<TData, TLayer>;\n viewport: ViewportSource;\n bounds?: NodeBounds<TData, TLayer>;\n /** The axis gestures resolve against. Default `+y`. */\n up?: Vec3;\n}\n\nconst DEFAULT_UP: Vec3 = { x: 0, y: 1, z: 0 };\n\nfunction boundsOfNode<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n node: Node3d<TData, TLayer>,\n): Aabb {\n return world.bounds ? world.bounds(node) : aabbOfPose(node.pose);\n}\n\n/** The pane, in the coordinate space the host's points arrive in. The origin\n * defaults to the client origin — a host that fills the window passes none. */\nfunction rectOf(viewport: Viewport3d): ScreenBox {\n return {\n x: viewport.originX ?? 0,\n y: viewport.originY ?? 0,\n width: viewport.width,\n height: viewport.height,\n };\n}\n\nfunction viewProjectionOf(viewport: Viewport3d) {\n return cameraViewProjection(viewport.camera, viewport.width / Math.max(1, viewport.height));\n}\n\nfunction rayAt(viewport: Viewport3d, point: { x: number; y: number }): Ray | null {\n return rayThroughScreenPoint(\n point,\n rectOf(viewport),\n viewProjectionOf(viewport),\n cameraEye(viewport.camera),\n );\n}\n\n/**\n * The plane through `p` that faces the camera.\n *\n * This is the depth choice the kit's reverse contracts need: a screen\n * rectangle names a pose only once something says how far away it is, and the\n * answer is \"as far as it already was\". Nothing resolved on this plane changes\n * depth, and one screen pixel is the same world distance everywhere on it.\n */\nfunction viewPlaneAt(camera: Camera3d, p: Vec3): { normal: Vec3; offset: number } {\n const normal = normalize(sub(camera.target, cameraEye(camera)));\n return { normal, offset: dot(normal, p) };\n}\n\n/** Where a screen point lands on `plane`, or `null` when it casts no ray. */\nfunction onPlane(\n vp: Viewport3d,\n plane: { normal: Vec3; offset: number },\n point: { x: number; y: number },\n): Vec3 | null {\n const ray = rayAt(vp, point);\n if (!ray) return null;\n const t = intersectRayPlane(ray, plane.normal, plane.offset);\n return t === null ? null : pointOnRay(ray, t);\n}\n\n/** The world box containing `points`. */\nfunction aabbOfPoints(points: readonly Vec3[]): Aabb {\n const min = { x: Infinity, y: Infinity, z: Infinity };\n const max = { x: -Infinity, y: -Infinity, z: -Infinity };\n for (const p of points) {\n for (const axis of ['x', 'y', 'z'] as const) {\n if (p[axis] < min[axis]) min[axis] = p[axis];\n if (p[axis] > max[axis]) max[axis] = p[axis];\n }\n }\n return { min, max };\n}\n\nfunction pointOnRay(ray: Ray, t: number): Vec3 {\n return {\n x: ray.origin.x + ray.direction.x * t,\n y: ray.origin.y + ray.direction.y * t,\n z: ray.origin.z + ray.direction.z * t,\n };\n}\n\nfunction overlaps(a: ScreenBox, b: ScreenBox): boolean {\n return (\n a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n );\n}\n\n/** The screen box a node covers, or null when it projects to nothing visible. */\nexport function screenBoxOf<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n id: NodeId,\n viewport: Viewport3d,\n): ScreenBox | null {\n const node = world.scene.get(id) as Node3d<TData, TLayer> | undefined;\n if (!node) return null;\n return projectAabbToScreen(\n boundsOfNode(world, node),\n viewProjectionOf(viewport),\n rectOf(viewport),\n );\n}\n\n/**\n * Nearest node along the ray the screen point names.\n *\n * The kit calls this with what it believes is a world point; a 3D host feeds\n * the dispatcher an identity `clientToWorld`, so it is the pane-relative screen\n * point, which is exactly what a ray needs.\n */\nexport function createNodeAtPoint<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n): NodeAtPointDep {\n return (point, exclude) => {\n const excluded = exclude ? new Set(exclude) : null;\n const vp = world.viewport();\n const ray = rayAt(vp, point);\n if (!ray) return null;\n let best: NodeId | null = null;\n let bestT = Infinity;\n for (const node of world.scene.renderOrderNodes() as readonly Node3d<TData, TLayer>[]) {\n if (excluded?.has(node.id)) continue;\n const { min, max } = boundsOfNode(world, node);\n const t = intersectRayAabb(ray, min, max);\n if (t !== null && t < bestT) {\n bestT = t;\n best = node.id;\n }\n }\n return best;\n };\n}\n\n/** Marquee: the nodes whose projected box the screen rectangle touches. */\nexport function createAreaSelect<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n selection: { get(): readonly NodeId[]; set(ids: NodeId[]): void },\n): AreaSelectDep {\n return {\n hitTestArea(bounds) {\n const vp = world.viewport();\n const hits: NodeId[] = [];\n for (const node of world.scene.renderOrderNodes()) {\n const box = screenBoxOf(world, node.id, vp);\n if (box && overlaps(box, bounds)) hits.push(node.id);\n }\n return hits;\n },\n getSelection: () => [...selection.get()],\n setSelection: (ids) => selection.set([...ids]),\n };\n}\n\n/** No grid in 3D yet; the identity keeps `insertAction` happy without lying. */\nexport function createSnap(): SnapDep {\n return { point: (p) => p };\n}\n\n/** The ground-plane rectangle a drag swept out, in world units. */\nexport interface Footprint {\n /** Centre of the swept rectangle, on the ground plane. */\n center: Vec3;\n /** Extent along the two axes the up axis is not. */\n width: number;\n depth: number;\n}\n\n/**\n * A drag rectangle becomes a footprint on the ground plane: its four corners\n * are cast onto the plane and the hit points give the extent. What node that\n * implies is the consumer's answer — the kernel does not know what it is\n * inserting.\n *\n * The kit's `InsertDep.commit` hands over a screen-space AABB and nothing else,\n * which turns out to be enough: the depth the 2D contract cannot express comes\n * from the plane, not from the caller.\n */\nexport function createInsert(opts: {\n viewport: ViewportSource;\n up?: Vec3;\n /** Smallest footprint a click-sized drag produces. Default 0.25. */\n minExtent?: number;\n mint(footprint: Footprint, extras: InsertExtras): NodeId | null;\n}): InsertDep {\n const up = opts.up ?? DEFAULT_UP;\n const minExtent = opts.minExtent ?? 0.25;\n // The two axes the up axis is not, so a footprint reads the same whichever\n // way up the world is.\n const axes: readonly ['x' | 'y' | 'z', 'x' | 'y' | 'z'] =\n up.y !== 0 ? ['x', 'z'] : up.x !== 0 ? ['y', 'z'] : ['x', 'y'];\n\n return {\n commit(bounds, extras) {\n const vp = opts.viewport();\n const corners = [\n { x: bounds.x, y: bounds.y },\n { x: bounds.x + bounds.width, y: bounds.y },\n { x: bounds.x, y: bounds.y + bounds.height },\n { x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n const hits: Vec3[] = [];\n for (const corner of corners) {\n const ray = rayAt(vp, corner);\n if (!ray) continue;\n const t = intersectRayPlane(ray, up, 0);\n if (t !== null) hits.push(pointOnRay(ray, t));\n }\n if (hits.length === 0) return null;\n\n const [u, v] = axes;\n let minU = Infinity, maxU = -Infinity, minV = Infinity, maxV = -Infinity;\n for (const h of hits) {\n minU = Math.min(minU, h[u]); maxU = Math.max(maxU, h[u]);\n minV = Math.min(minV, h[v]); maxV = Math.max(maxV, h[v]);\n }\n\n const center = { x: 0, y: 0, z: 0 };\n center[u] = (minU + maxU) / 2;\n center[v] = (minV + maxV) / 2;\n return opts.mint(\n {\n center,\n width: Math.max(minExtent, maxU - minU),\n depth: Math.max(minExtent, maxV - minV),\n },\n extras,\n );\n },\n };\n}\n\n/**\n * `PoseDescriptor` over a 3D pose, with `Bounds` read as the screen box the\n * node covers. Chrome and marquee math work unchanged; the two methods that\n * run the other way cannot.\n *\n * `forNode` is what lets a sphere bound itself as a sphere: every node is a\n * `Pose3`, so the shape lives on `node.data` and nothing but the node can say\n * which one this is. Unspecialized — the kit calling with only a pose in hand —\n * it answers with the default local box, which is the looser of the two.\n *\n * The two methods that run the other way — `remapBounds` and `fromBounds` —\n * take a screen rectangle, which names a pose only once something supplies a\n * depth. Both resolve it against the plane through the pose they were handed,\n * facing the camera, so nothing they produce changes depth. See\n * `viewPlaneAt`.\n */\nexport function createPoseDescriptor<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n): PoseDescriptor<Pose3, Node3d<TData, TLayer>> {\n const up = world.up ?? DEFAULT_UP;\n const upAxis = up.y !== 0 ? 'y' : up.x !== 0 ? 'x' : 'z';\n const specialized = new WeakMap<object, PoseDescriptor<Pose3, Node3d<TData, TLayer>>>();\n\n // A drag whose camera stops casting rays mid-gesture keeps moving through the\n // last one that did, rather than snapping the node back.\n let lastCastable: Viewport3d | null = null;\n function castableViewport(): Viewport3d | null {\n const vp = world.viewport();\n const rect = rectOf(vp);\n if (rayAt(vp, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 })) lastCastable = vp;\n return lastCastable;\n }\n\n function build(worldBox: (pose: Pose3) => Aabb): PoseDescriptor<Pose3, Node3d<TData, TLayer>> {\n const boundsIn = (vp: Viewport3d, pose: Pose3) =>\n projectAabbToScreen(worldBox(pose), viewProjectionOf(vp), rectOf(vp));\n const boundsOf = (pose: Pose3) => boundsIn(world.viewport(), pose);\n\n const descriptor: PoseDescriptor<Pose3, Node3d<TData, TLayer>> = {\n forNode(node) {\n let d = specialized.get(node);\n if (!d) {\n // The pose arriving here is often an in-flight override rather than\n // `node.pose`, so the consumer is asked about that pose on this node\n // rather than about the node as committed.\n d = build((pose) => boundsOfNode(world, { ...node, pose }));\n specialized.set(node, d);\n }\n return d;\n },\n\n getBounds(pose) {\n return boundsOf(pose) ?? { x: 0, y: 0, width: 0, height: 0 };\n },\n\n /**\n * The src→dst screen map, applied at the pose's own depth: the node's\n * screen anchor moves the way the rectangle does, and both ends of that\n * move are read back off the plane through its position, so the world\n * delta is exact rather than a scaled screen one.\n *\n * The scale is uniform. The rectangle names two extents and a pose has\n * three, so there is no reading in which a screen box resizes a solid\n * per-axis; the geometric mean is the one factor that agrees with both\n * of the extents it does name.\n */\n remapBounds(pose, src, dst) {\n const vp = castableViewport();\n if (!vp) return pose;\n const box = boundsIn(vp, pose);\n if (!box) return pose;\n\n const kx = src.width === 0 ? 1 : dst.width / src.width;\n const ky = src.height === 0 ? 1 : dst.height / src.height;\n const from = { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n const to = {\n x: dst.x + (from.x - src.x) * kx,\n y: dst.y + (from.y - src.y) * ky,\n };\n\n const plane = viewPlaneAt(vp.camera, pose.position);\n const before = onPlane(vp, plane, from);\n const after = onPlane(vp, plane, to);\n if (!before || !after) return pose;\n\n const k = Math.sqrt(Math.abs(kx * ky));\n return {\n ...pose,\n position: add(pose.position, sub(after, before)),\n scale: scaleBy(pose.scale, k),\n };\n },\n\n /**\n * The world box the rectangle covers at the template's depth, as a pose.\n *\n * The rectangle is flat and a box is not, so the third extent — the one\n * no screen rectangle names — is the mean of the two it does. The result\n * is world-axis-aligned and unrotated: the pose carries none of the\n * template's shape, which is the contract, and it takes only its depth.\n *\n * Extents are written as `scale`, so this reads a pose as carrying a\n * unit primitive — the same assumption `aabbOfPose` makes by default.\n */\n fromBounds(bounds, template) {\n const vp = castableViewport();\n if (!vp) return template;\n const plane = viewPlaneAt(vp.camera, template.position);\n\n const corners: Vec3[] = [];\n for (const [x, y] of [\n [bounds.x, bounds.y],\n [bounds.x + bounds.width, bounds.y],\n [bounds.x, bounds.y + bounds.height],\n [bounds.x + bounds.width, bounds.y + bounds.height],\n ]) {\n const corner = onPlane(vp, plane, { x, y });\n if (!corner) return template;\n corners.push(corner);\n }\n\n const width = len(sub(corners[1]!, corners[0]!));\n const height = len(sub(corners[2]!, corners[0]!));\n const half = Math.sqrt(width * height) / 2;\n const box = aabbOfPoints(\n corners.flatMap((c) => [\n add(c, scaleBy(plane.normal, half)),\n sub(c, scaleBy(plane.normal, half)),\n ]),\n );\n return {\n position: scaleBy(add(box.min, box.max), 0.5),\n rotation: quatIdentity(),\n scale: sub(box.max, box.min),\n };\n },\n\n /**\n * Screen-space deltas resolve against the plane the node already sits on,\n * so the two numbers the kit passes are enough: the camera that turns\n * them into a world position is the one this dep closed over.\n */\n translate(pose, dx, dy) {\n const vp = castableViewport();\n if (!vp) return pose;\n const box = boundsIn(vp, pose);\n if (!box) return pose;\n const from = { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n const to = { x: from.x + dx, y: from.y + dy };\n const offset = pose.position[upAxis];\n\n const ray = rayAt(vp, to);\n if (!ray) return pose;\n const t = intersectRayPlane(ray, up, offset);\n if (t === null) return pose;\n\n const anchorRay = rayAt(vp, from);\n if (!anchorRay) return pose;\n const anchorT = intersectRayPlane(anchorRay, up, offset);\n if (anchorT === null) return pose;\n\n const delta = sub(pointOnRay(ray, t), pointOnRay(anchorRay, anchorT));\n const position = {\n x: pose.position.x + delta.x,\n y: pose.position.y + delta.y,\n z: pose.position.z + delta.z,\n };\n position[upAxis] = pose.position[upAxis];\n return { ...pose, position };\n },\n\n supportsRotation() {\n return false;\n },\n };\n\n return descriptor;\n }\n\n return build((pose) => aabbOfPose(pose));\n}\n","/**\n * What a host paints for a gesture that proposes chrome rather than a pose.\n *\n * A marquee sweep and a box-drag both publish an `OngoingOverlay`, which used\n * to reach paint only through core's own 2D layer. `resolveOverlays` hands back\n * world geometry with no renderer in it, so the same call `<SceneCanvas>` makes\n * serves a consumer-owned 3D renderer.\n *\n * A 3D host's `clientToWorld` is identity, so an overlay's world bounds are the\n * client rect the deps already work in, and the pane origin comes off exactly\n * once. Only the rectangular variants resolve here: a lasso, a pencil and a run\n * of points are paths, and a path is geometry this cannot flatten to a box.\n */\n\nimport { resolveOverlays, type OngoingHandle } from '@weasel-js/core';\nimport type { ChromeBox } from './screen';\n\n/** Gesture chrome, in CSS pixels relative to the pane's top-left. */\nexport function collectOverlayBoxes(\n handles: Iterable<OngoingHandle>,\n origin: { x: number; y: number },\n): ChromeBox[] {\n const overlays = [];\n for (const handle of handles) {\n const ov = handle.overlay?.();\n if (ov) overlays.push(ov);\n }\n\n const boxes: ChromeBox[] = [];\n for (const resolved of resolveOverlays(overlays)) {\n if (resolved.kind !== 'marquee' && resolved.kind !== 'insertPreview') continue;\n const { x, y, width, height } = resolved.bounds;\n boxes.push({ x: x - origin.x, y: y - origin.y, width, height, tint: 'gesture' });\n }\n return boxes;\n}\n","/**\n * Camera tools and their actions.\n *\n * Shape tools transfer from the kit untouched — a 3D host mounts core's own\n * `useSelectTool` and a rectangle-style insert binding and neither notices the\n * dimension. Only the viewport tools are written here, which is the one\n * exception the kernel doc predicted: `useHandTool` routes to\n * `viewport.dragPan`, and that wants the 2D `view`.\n */\n\nimport { useMemo } from 'react';\nimport { defineTool, type Action, type Tool } from '@weasel-js/core';\nimport { dollyBy, orbitBy, type Camera3d } from './camera';\n\n/** Radians per CSS pixel of drag. A full pane width is a bit over half a turn. */\nconst ORBIT_RATE = 0.006;\nconst DOLLY_RATE = 0.0015;\n\n/** `camera.orbit`: an ongoing drag that turns the `camera3d` dep about its\n * target, relative to the camera as it was when the drag began. */\nexport const orbitAction: Action = {\n id: 'camera.orbit',\n label: 'Orbit',\n requires: ['camera3d'],\n invoker: {\n timing: 'ongoing',\n start(ctx) {\n const dep = ctx.deps.camera3d;\n const origin: Camera3d | undefined = dep?.get();\n return {\n kind: 'orbit',\n onMove(move) {\n if (!dep || !origin) return;\n // `drag.delta` runs from the drag origin, not the previous move, so\n // this composes against the camera as it was when the drag began.\n //\n // The fallback is only sound here because a 3D host's `clientToWorld`\n // is identity (see `overlays.ts`), so the world delta already is the\n // client one. Don't copy this pair to a host with a 2D view — there\n // the two spaces differ by the zoom.\n const delta = move.drag?.screenDelta ?? move.drag?.delta;\n if (!delta) return;\n dep.set(orbitBy(origin, -delta.x * ORBIT_RATE, delta.y * ORBIT_RATE));\n },\n };\n },\n },\n};\n\n/** `camera.dolly`: moves the `camera3d` dep toward or away from its target by\n * the wheel's `deltaY`. Bound to the wheel by default, in every tool. */\nexport const dollyAction: Action = {\n id: 'camera.dolly',\n label: 'Dolly',\n group: 'viewport',\n // Wheel, in any tool — the dispatcher merges the event's deltas into params.\n defaultBinding: [{ spec: { kind: 'wheel' }, opts: {} }],\n requires: ['camera3d'],\n invoker: {\n timing: 'immediate',\n run(deps, params) {\n const dep = deps.camera3d;\n if (!dep) return;\n const amount = typeof params?.deltaY === 'number' ? params.deltaY : 0;\n dep.set(dollyBy(dep.get(), Math.exp(amount * DOLLY_RATE)));\n },\n },\n};\n\n/** A tool that binds drag to `camera.orbit`. Register `orbitAction` alongside\n * it; the tool only declares the binding. */\nexport function useOrbitTool(): Tool<null> {\n return useMemo(() => defineTool<null>({\n id: 'orbit',\n hookName: 'useOrbitTool',\n cursor: 'grab',\n presentation: { label: 'Orbit', group: 'viewport' },\n bindings: [{ spec: { kind: 'drag' }, actionId: 'camera.orbit' }],\n }), []);\n}\n"]}
1
+ {"version":3,"sources":["../src/camera.ts","../src/pose3.ts","../src/screen.ts","../src/deps.ts","../src/overlays.ts","../src/tools.ts"],"names":["normalize","sub","scaleBy","quatIdentity"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * An orbit camera: a target, two angles and a distance. Immutable — every\n * gesture returns a new one, so it can live in instrument state.\n *\n * This is the shape `ViewApi` cannot hold, and the reason the kernel declares a\n * `camera3d` dep of its own rather than reusing the kit's `view`.\n */\n\nimport {\n lookAt,\n multiply,\n perspective,\n type Mat4,\n type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** An orbit camera. The eye sits `distance` world units from `target` at\n * `yaw`/`pitch`; `fov` is the vertical field of view in radians, and\n * `near`/`far` the clip distances. */\nexport interface Camera3d {\n target: Vec3;\n /** Radians about +y, measured from +z. */\n yaw: number;\n /** Radians above the xz plane. */\n pitch: number;\n distance: number;\n fov: number;\n near: number;\n far: number;\n}\n\n/** Short of vertical: at exactly ±π/2 the eye lands on the up axis and `lookAt` degenerates. */\nexport const MAX_PITCH = Math.PI / 2 - 0.01;\nconst MIN_DISTANCE = 0.5;\nconst MAX_DISTANCE = 500;\nconst UP: Vec3 = { x: 0, y: 1, z: 0 };\n\n/** A camera with defaults for every field not given: origin target, level at\n * yaw 0, distance 10, fov π/4, near 0.1, far 1000. */\nexport function createCamera(init: Partial<Camera3d>): Camera3d {\n return {\n target: init.target ?? { x: 0, y: 0, z: 0 },\n yaw: init.yaw ?? 0,\n pitch: init.pitch ?? 0,\n distance: init.distance ?? 10,\n fov: init.fov ?? Math.PI / 4,\n near: init.near ?? 0.1,\n far: init.far ?? 1000,\n };\n}\n\n/** The eye's world position. */\nexport function cameraEye(camera: Camera3d): Vec3 {\n const { target, yaw, pitch, distance } = camera;\n const horizontal = Math.cos(pitch) * distance;\n return {\n x: target.x + horizontal * Math.sin(yaw),\n y: target.y + Math.sin(pitch) * distance,\n z: target.z + horizontal * Math.cos(yaw),\n };\n}\n\n/** World-to-view matrix, with +y up. */\nexport function cameraView(camera: Camera3d): Mat4 {\n return lookAt(cameraEye(camera), camera.target, UP);\n}\n\n/** World-to-clip matrix for a pane of the given width/height `aspect`. */\nexport function cameraViewProjection(camera: Camera3d, aspect: number): Mat4 {\n return multiply(perspective(camera.fov, aspect, camera.near, camera.far), cameraView(camera));\n}\n\n/** The camera turned about its target by the given radians. Pitch is clamped\n * to ±`MAX_PITCH`; yaw is not wrapped. */\nexport function orbitBy(camera: Camera3d, deltaYaw: number, deltaPitch: number): Camera3d {\n return {\n ...camera,\n yaw: camera.yaw + deltaYaw,\n pitch: Math.max(-MAX_PITCH, Math.min(MAX_PITCH, camera.pitch + deltaPitch)),\n };\n}\n\n/** The camera with its distance multiplied by `factor`, clamped to 0.5..500. */\nexport function dollyBy(camera: Camera3d, factor: number): Camera3d {\n return {\n ...camera,\n distance: Math.max(MIN_DISTANCE, Math.min(MAX_DISTANCE, camera.distance * factor)),\n };\n}\n","/**\n * A 3D pose, and the two things every consumer of one needs: its matrix, and\n * the world box it occupies.\n *\n * `Scene<TData, TLayer, Pose3>` is the whole of how this reaches weasel —\n * `Scene` is generic over its pose and holds this one with no adapter, no\n * subclass and no special case.\n */\n\nimport {\n compose, quatIdentity, transformAabb, type Aabb, type Mat4, type Quat, type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** Position, rotation and scale of a 3D node. */\nexport interface Pose3 {\n position: Vec3;\n rotation: Quat;\n scale: Vec3;\n}\n\n/** The box a primitive occupies before its pose. A unit primitive centred on\n * its own origin — which is what the kernel assumes nothing about — is\n * `UNIT_CUBE`. */\nexport const UNIT_CUBE: Aabb = {\n min: { x: -0.5, y: -0.5, z: -0.5 },\n max: { x: 0.5, y: 0.5, z: 0.5 },\n};\n\n/** A pose at `position`, unscaled and unrotated unless given. */\nexport function pose3(\n position: Vec3,\n scale: Vec3 = { x: 1, y: 1, z: 1 },\n rotation: Quat = quatIdentity(),\n): Pose3 {\n return { position, rotation, scale };\n}\n\n/** The pose as a matrix: scale, then rotation, then translation to\n * `position`. */\nexport function poseMatrix(pose: Pose3): Mat4 {\n return compose(pose.position, pose.rotation, pose.scale);\n}\n\n/**\n * The world box a posed primitive occupies, given the box it occupies in its\n * own space.\n *\n * Which local box a primitive has is the consumer's answer, not the kernel's:\n * a sphere's is rotation-invariant and a mesh's comes from its vertices, and\n * neither is something a pose can tell you.\n */\nexport function aabbOfPose(pose: Pose3, local: Aabb = UNIT_CUBE): Aabb {\n return transformAabb(poseMatrix(pose), local);\n}\n","/**\n * The screen side of the kernel: where a pointer points, and what rectangle a\n * world box covers. This is the seam weasel's 2D chrome meets — everything\n * here speaks `Bounds`-shaped screen rectangles, which is why a 3D host can\n * pass the dispatcher's world point through unchanged.\n */\n\nimport {\n invert,\n normalize,\n sub,\n transformPoint,\n transformPoint4,\n type Aabb,\n type Mat4,\n type Ray,\n type Vec3,\n} from '@weasel-js/geom/3d';\n\n/** A screen rectangle in CSS pixels, in the shape core's `Bounds` uses. Both\n * a pane's own rect and a projected world box are this — one spelling, so the\n * two never need converting between. */\nexport interface ScreenBox {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** A `ScreenBox` a host is being asked to outline. `tint` says why: warm for\n * what is selected, cool for what the gesture in hand is proposing. */\nexport interface ChromeBox extends ScreenBox {\n tint?: 'selection' | 'gesture';\n}\n\n/** Screen point (y down, rect-relative) to normalized device coordinates (y up). */\nexport function screenToNdc(\n point: { x: number; y: number },\n rect: ScreenBox,\n): { x: number; y: number } {\n return {\n x: ((point.x - rect.x) / rect.width) * 2 - 1,\n y: 1 - ((point.y - rect.y) / rect.height) * 2,\n };\n}\n\n/** Inverse of `screenToNdc`: normalized device coordinates (y up) to a point\n * in `rect`'s space (y down). */\nexport function ndcToScreen(\n ndc: { x: number; y: number },\n rect: ScreenBox,\n): { x: number; y: number } {\n return {\n x: rect.x + (ndc.x * 0.5 + 0.5) * rect.width,\n y: rect.y + (1 - (ndc.y * 0.5 + 0.5)) * rect.height,\n };\n}\n\n/**\n * The ray a screen point names, given the camera that drew the rect. This is\n * the whole of what 3D picking needs from a pointer — which is why the world\n * point the dispatcher carries stays two numbers.\n *\n * `null` when the point names no ray: the view-projection has no inverse (a\n * camera on its own target, a degenerate projection) or the pane has no area.\n */\nexport function rayThroughScreenPoint(\n point: { x: number; y: number },\n rect: ScreenBox,\n viewProjection: Mat4,\n eye: Vec3,\n): Ray | null {\n const inv = invert(viewProjection);\n if (!inv) return null;\n const ndc = screenToNdc(point, rect);\n const near = transformPoint(inv, { x: ndc.x, y: ndc.y, z: -1 });\n const far = transformPoint(inv, { x: ndc.x, y: ndc.y, z: 1 });\n const direction = normalize(sub(far, near));\n // normalize answers zero for a non-finite difference, which is no direction.\n if (direction.x === 0 && direction.y === 0 && direction.z === 0) return null;\n return { origin: eye, direction };\n}\n\ntype Clip = readonly [number, number, number, number];\n\n/** Signed distance to the near plane in clip space; `>= 0` is in front of it.\n * GL puts the near plane at `z = -w`. */\nfunction nearSide(p: Clip): number {\n return p[2] + p[3];\n}\n\nfunction lerpClip(a: Clip, b: Clip, t: number): Clip {\n return [\n a[0] + (b[0] - a[0]) * t,\n a[1] + (b[1] - a[1]) * t,\n a[2] + (b[2] - a[2]) * t,\n a[3] + (b[3] - a[3]) * t,\n ];\n}\n\n/** The three edges leaving corner `i` toward a higher bit, as bit masks. */\nconst EDGE_BITS = [1, 2, 4] as const;\n\n/**\n * The screen rectangle a world-space box covers — the currency weasel's chrome\n * and `PoseDescriptor.getBounds` speak in. `null` when the box is entirely\n * behind the near plane.\n *\n * Each of the twelve edges is clipped against the near plane before it is\n * projected, rather than dropping the corners behind it. Dropping them reports\n * a box that is too small for anything straddling the near plane, and the error\n * grows as the camera moves in: a solid the pointer is inside of would outline\n * as a sliver, or as nothing.\n */\nexport function projectAabbToScreen(\n box: Aabb,\n viewProjection: Mat4,\n rect: ScreenBox,\n): ScreenBox | null {\n const corners: Clip[] = [];\n for (let i = 0; i < 8; i++) {\n const corner: Vec3 = {\n x: i & 1 ? box.max.x : box.min.x,\n y: i & 2 ? box.max.y : box.min.y,\n z: i & 4 ? box.max.z : box.min.z,\n };\n corners.push(transformPoint4(viewProjection, corner));\n }\n\n let minX = Number.POSITIVE_INFINITY;\n let minY = Number.POSITIVE_INFINITY;\n let maxX = Number.NEGATIVE_INFINITY;\n let maxY = Number.NEGATIVE_INFINITY;\n let any = false;\n\n const extend = (p: Clip): void => {\n if (!(p[3] > 0)) return;\n const screen = ndcToScreen({ x: p[0] / p[3], y: p[1] / p[3] }, rect);\n minX = Math.min(minX, screen.x);\n minY = Math.min(minY, screen.y);\n maxX = Math.max(maxX, screen.x);\n maxY = Math.max(maxY, screen.y);\n any = true;\n };\n\n for (let i = 0; i < 8; i++) {\n for (const bit of EDGE_BITS) {\n if (i & bit) continue;\n let a = corners[i];\n let b = corners[i | bit];\n const da = nearSide(a);\n const db = nearSide(b);\n if (da < 0 && db < 0) continue;\n if (da < 0) a = lerpClip(a, b, da / (da - db));\n else if (db < 0) b = lerpClip(b, a, db / (db - da));\n extend(a);\n extend(b);\n }\n }\n\n if (!any) return null;\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n","/**\n * The kit's deps, implemented against a 3D world.\n *\n * Every one of these takes its camera from a thunk rather than an argument:\n * the dispatcher keeps handing actions two numbers, and what makes them mean\n * something in 3D is the camera each dep already closes over.\n */\n\nimport type {\n AreaSelectDep,\n InsertDep,\n InsertExtras,\n NodeAtPointDep,\n NodeId,\n PoseDescriptor,\n Scene,\n SceneNode,\n SnapDep,\n} from '@weasel-js/core';\nimport {\n add,\n dot,\n intersectRayAabb,\n intersectRayPlane,\n len,\n normalize,\n quatIdentity,\n scale as scaleBy,\n sub,\n type Aabb,\n type Ray,\n type Vec3,\n} from '@weasel-js/geom/3d';\nimport { cameraEye, cameraViewProjection, type Camera3d } from './camera';\nimport { aabbOfPose, type Pose3 } from './pose3';\nimport {\n projectAabbToScreen,\n rayThroughScreenPoint,\n type ScreenBox,\n} from './screen';\n\n/** The camera and the pane it draws into; `width`/`height` are the pane's\n * size in the same units as the pointer points. */\nexport interface Viewport3d {\n camera: Camera3d;\n width: number;\n height: number;\n /**\n * Where the pane sits in client coordinates. A 3D host works in one space\n * from the event to the ray — it passes the dispatcher an identity\n * `clientToWorld` — so the deps subtract this rather than the dispatcher.\n */\n originX?: number;\n originY?: number;\n}\n\n/** Read on every dep call, so a dep always sees the current camera and pane. */\nexport type ViewportSource = () => Viewport3d;\n\n/** A 3D scene is core's scene with a `Pose3`. Nothing wraps it. */\nexport type Scene3d<TData, TLayer extends string> = Scene<TData, TLayer, Pose3>;\n/** A node of a `Scene3d`. */\nexport type Node3d<TData, TLayer extends string> = SceneNode<TData, TLayer, Pose3>;\n\n/**\n * The world box a node occupies, rather than a local box to transform: a\n * sphere's box is the same under every rotation, and no transform of a local\n * box reproduces that — rotate a cube and it widens.\n *\n * Omitted, a node is a unit cube carried by its pose.\n */\nexport type NodeBounds<TData, TLayer extends string> = (\n node: Node3d<TData, TLayer>,\n) => Aabb;\n\n/** What every 3D dep is built from: the scene, the viewport, and optionally\n * each node's world box. */\nexport interface World3d<TData, TLayer extends string> {\n scene: Scene3d<TData, TLayer>;\n viewport: ViewportSource;\n bounds?: NodeBounds<TData, TLayer>;\n /** The axis gestures resolve against. Default `+y`. */\n up?: Vec3;\n}\n\nconst DEFAULT_UP: Vec3 = { x: 0, y: 1, z: 0 };\n\nfunction boundsOfNode<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n node: Node3d<TData, TLayer>,\n): Aabb {\n return world.bounds ? world.bounds(node) : aabbOfPose(node.pose);\n}\n\n/** The pane, in the coordinate space the host's points arrive in. The origin\n * defaults to the client origin — a host that fills the window passes none. */\nfunction rectOf(viewport: Viewport3d): ScreenBox {\n return {\n x: viewport.originX ?? 0,\n y: viewport.originY ?? 0,\n width: viewport.width,\n height: viewport.height,\n };\n}\n\nfunction viewProjectionOf(viewport: Viewport3d) {\n return cameraViewProjection(viewport.camera, viewport.width / Math.max(1, viewport.height));\n}\n\nfunction rayAt(viewport: Viewport3d, point: { x: number; y: number }): Ray | null {\n return rayThroughScreenPoint(\n point,\n rectOf(viewport),\n viewProjectionOf(viewport),\n cameraEye(viewport.camera),\n );\n}\n\n/**\n * The plane through `p` that faces the camera.\n *\n * This is the depth choice the kit's reverse contracts need: a screen\n * rectangle names a pose only once something says how far away it is, and the\n * answer is \"as far as it already was\". Nothing resolved on this plane changes\n * depth, and one screen pixel is the same world distance everywhere on it.\n */\nfunction viewPlaneAt(camera: Camera3d, p: Vec3): { normal: Vec3; offset: number } {\n const normal = normalize(sub(camera.target, cameraEye(camera)));\n return { normal, offset: dot(normal, p) };\n}\n\n/** Where a screen point lands on `plane`, or `null` when it casts no ray. */\nfunction onPlane(\n vp: Viewport3d,\n plane: { normal: Vec3; offset: number },\n point: { x: number; y: number },\n): Vec3 | null {\n const ray = rayAt(vp, point);\n if (!ray) return null;\n const t = intersectRayPlane(ray, plane.normal, plane.offset);\n return t === null ? null : pointOnRay(ray, t);\n}\n\n/** The world box containing `points`. */\nfunction aabbOfPoints(points: readonly Vec3[]): Aabb {\n const min = { x: Infinity, y: Infinity, z: Infinity };\n const max = { x: -Infinity, y: -Infinity, z: -Infinity };\n for (const p of points) {\n for (const axis of ['x', 'y', 'z'] as const) {\n if (p[axis] < min[axis]) min[axis] = p[axis];\n if (p[axis] > max[axis]) max[axis] = p[axis];\n }\n }\n return { min, max };\n}\n\nfunction pointOnRay(ray: Ray, t: number): Vec3 {\n return {\n x: ray.origin.x + ray.direction.x * t,\n y: ray.origin.y + ray.direction.y * t,\n z: ray.origin.z + ray.direction.z * t,\n };\n}\n\nfunction overlaps(a: ScreenBox, b: ScreenBox): boolean {\n return (\n a.x < b.x + b.width && a.x + a.width > b.x && a.y < b.y + b.height && a.y + a.height > b.y\n );\n}\n\n/** The screen box a node covers, or null when it projects to nothing visible. */\nexport function screenBoxOf<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n id: NodeId,\n viewport: Viewport3d,\n): ScreenBox | null {\n const node = world.scene.get(id) as Node3d<TData, TLayer> | undefined;\n if (!node) return null;\n return projectAabbToScreen(\n boundsOfNode(world, node),\n viewProjectionOf(viewport),\n rectOf(viewport),\n );\n}\n\n/**\n * Nearest node along the ray the screen point names.\n *\n * The kit calls this with what it believes is a world point; a 3D host feeds\n * the dispatcher an identity `clientToWorld`, so it is the pane-relative screen\n * point, which is exactly what a ray needs.\n */\nexport function createNodeAtPoint<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n): NodeAtPointDep {\n return (point, exclude) => {\n const excluded = exclude ? new Set(exclude) : null;\n const vp = world.viewport();\n const ray = rayAt(vp, point);\n if (!ray) return null;\n let best: NodeId | null = null;\n let bestT = Infinity;\n for (const node of world.scene.renderOrderNodes() as readonly Node3d<TData, TLayer>[]) {\n if (excluded?.has(node.id)) continue;\n const { min, max } = boundsOfNode(world, node);\n const t = intersectRayAabb(ray, min, max);\n if (t !== null && t < bestT) {\n bestT = t;\n best = node.id;\n }\n }\n return best;\n };\n}\n\n/** Marquee: the nodes whose projected box the screen rectangle touches. */\nexport function createAreaSelect<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n selection: { get(): readonly NodeId[]; set(ids: NodeId[]): void },\n): AreaSelectDep {\n return {\n hitTestArea(bounds) {\n const vp = world.viewport();\n const hits: NodeId[] = [];\n for (const node of world.scene.renderOrderNodes()) {\n const box = screenBoxOf(world, node.id, vp);\n if (box && overlaps(box, bounds)) hits.push(node.id);\n }\n return hits;\n },\n getSelection: () => [...selection.get()],\n setSelection: (ids) => selection.set([...ids]),\n };\n}\n\n/** No grid in 3D yet; the identity keeps `insertAction` happy without lying. */\nexport function createSnap(): SnapDep {\n return { point: (p) => p };\n}\n\n/** The ground-plane rectangle a drag swept out, in world units. */\nexport interface Footprint {\n /** Centre of the swept rectangle, on the ground plane. */\n center: Vec3;\n /** Extent along the two axes the up axis is not. */\n width: number;\n depth: number;\n}\n\n/**\n * A drag rectangle becomes a footprint on the ground plane: its four corners\n * are cast onto the plane and the hit points give the extent. What node that\n * implies is the consumer's answer — the kernel does not know what it is\n * inserting.\n *\n * The kit's `InsertDep.commit` hands over a screen-space AABB and nothing else:\n * the depth the 2D contract cannot express comes from the plane, not from the\n * caller.\n */\nexport function createInsert(opts: {\n viewport: ViewportSource;\n up?: Vec3;\n /** Smallest footprint a click-sized drag produces. Default 0.25. */\n minExtent?: number;\n mint(footprint: Footprint, extras: InsertExtras): NodeId | null;\n}): InsertDep {\n const up = opts.up ?? DEFAULT_UP;\n const minExtent = opts.minExtent ?? 0.25;\n // The two axes the up axis is not, so a footprint reads the same whichever\n // way up the world is.\n const axes: readonly ['x' | 'y' | 'z', 'x' | 'y' | 'z'] =\n up.y !== 0 ? ['x', 'z'] : up.x !== 0 ? ['y', 'z'] : ['x', 'y'];\n\n return {\n commit(bounds, extras) {\n const vp = opts.viewport();\n const corners = [\n { x: bounds.x, y: bounds.y },\n { x: bounds.x + bounds.width, y: bounds.y },\n { x: bounds.x, y: bounds.y + bounds.height },\n { x: bounds.x + bounds.width, y: bounds.y + bounds.height },\n ];\n\n const hits: Vec3[] = [];\n for (const corner of corners) {\n const ray = rayAt(vp, corner);\n if (!ray) continue;\n const t = intersectRayPlane(ray, up, 0);\n if (t !== null) hits.push(pointOnRay(ray, t));\n }\n if (hits.length === 0) return null;\n\n const [u, v] = axes;\n let minU = Infinity, maxU = -Infinity, minV = Infinity, maxV = -Infinity;\n for (const h of hits) {\n minU = Math.min(minU, h[u]); maxU = Math.max(maxU, h[u]);\n minV = Math.min(minV, h[v]); maxV = Math.max(maxV, h[v]);\n }\n\n const center = { x: 0, y: 0, z: 0 };\n center[u] = (minU + maxU) / 2;\n center[v] = (minV + maxV) / 2;\n return opts.mint(\n {\n center,\n width: Math.max(minExtent, maxU - minU),\n depth: Math.max(minExtent, maxV - minV),\n },\n extras,\n );\n },\n };\n}\n\n/**\n * `PoseDescriptor` over a 3D pose, with `Bounds` read as the screen box the\n * node covers.\n *\n * `forNode` is what lets a sphere bound itself as a sphere: the shape lives\n * on `node.data`. Unspecialized — the kit calling with only a pose in hand —\n * it answers with the default local box, which is the looser of the two.\n *\n * `remapBounds` and `fromBounds` take a screen rectangle, which names a pose\n * only once something supplies a depth. Both resolve it against the plane\n * through the pose they were handed, facing the camera, so nothing they\n * produce changes depth.\n */\nexport function createPoseDescriptor<TData, TLayer extends string>(\n world: World3d<TData, TLayer>,\n): PoseDescriptor<Pose3, Node3d<TData, TLayer>> {\n const up = world.up ?? DEFAULT_UP;\n const upAxis = up.y !== 0 ? 'y' : up.x !== 0 ? 'x' : 'z';\n const specialized = new WeakMap<object, PoseDescriptor<Pose3, Node3d<TData, TLayer>>>();\n\n // A drag whose camera stops casting rays mid-gesture keeps moving through the\n // last one that did, rather than snapping the node back.\n let lastCastable: Viewport3d | null = null;\n function castableViewport(): Viewport3d | null {\n const vp = world.viewport();\n const rect = rectOf(vp);\n if (rayAt(vp, { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 })) lastCastable = vp;\n return lastCastable;\n }\n\n function build(worldBox: (pose: Pose3) => Aabb): PoseDescriptor<Pose3, Node3d<TData, TLayer>> {\n const boundsIn = (vp: Viewport3d, pose: Pose3) =>\n projectAabbToScreen(worldBox(pose), viewProjectionOf(vp), rectOf(vp));\n const boundsOf = (pose: Pose3) => boundsIn(world.viewport(), pose);\n\n const descriptor: PoseDescriptor<Pose3, Node3d<TData, TLayer>> = {\n forNode(node) {\n let d = specialized.get(node);\n if (!d) {\n // The pose arriving here is often an in-flight override rather than\n // `node.pose`, so the consumer is asked about that pose on this node\n // rather than about the node as committed.\n d = build((pose) => boundsOfNode(world, { ...node, pose }));\n specialized.set(node, d);\n }\n return d;\n },\n\n getBounds(pose) {\n return boundsOf(pose) ?? { x: 0, y: 0, width: 0, height: 0 };\n },\n\n /**\n * The src→dst screen map, applied at the pose's own depth: the node's\n * screen anchor moves the way the rectangle does, and both ends of that\n * move are read back off the plane through its position, so the world\n * delta is exact rather than a scaled screen one.\n *\n * The scale is uniform. The rectangle names two extents and a pose has\n * three, so there is no reading in which a screen box resizes a solid\n * per-axis; the geometric mean is the one factor that agrees with both\n * of the extents it does name.\n */\n remapBounds(pose, src, dst) {\n const vp = castableViewport();\n if (!vp) return pose;\n const box = boundsIn(vp, pose);\n if (!box) return pose;\n\n const kx = src.width === 0 ? 1 : dst.width / src.width;\n const ky = src.height === 0 ? 1 : dst.height / src.height;\n const from = { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n const to = {\n x: dst.x + (from.x - src.x) * kx,\n y: dst.y + (from.y - src.y) * ky,\n };\n\n const plane = viewPlaneAt(vp.camera, pose.position);\n const before = onPlane(vp, plane, from);\n const after = onPlane(vp, plane, to);\n if (!before || !after) return pose;\n\n const k = Math.sqrt(Math.abs(kx * ky));\n return {\n ...pose,\n position: add(pose.position, sub(after, before)),\n scale: scaleBy(pose.scale, k),\n };\n },\n\n /**\n * The world box the rectangle covers at the template's depth, as a pose.\n *\n * The rectangle is flat and a box is not, so the third extent — the one\n * no screen rectangle names — is the mean of the two it does. The result\n * is world-axis-aligned and unrotated: the pose carries none of the\n * template's shape, which is the contract, and it takes only its depth.\n *\n * Extents are written as `scale`, so this reads a pose as carrying a\n * unit primitive — the same assumption `aabbOfPose` makes by default.\n */\n fromBounds(bounds, template) {\n const vp = castableViewport();\n if (!vp) return template;\n const plane = viewPlaneAt(vp.camera, template.position);\n\n const corners: Vec3[] = [];\n for (const [x, y] of [\n [bounds.x, bounds.y],\n [bounds.x + bounds.width, bounds.y],\n [bounds.x, bounds.y + bounds.height],\n [bounds.x + bounds.width, bounds.y + bounds.height],\n ]) {\n const corner = onPlane(vp, plane, { x, y });\n if (!corner) return template;\n corners.push(corner);\n }\n\n const width = len(sub(corners[1]!, corners[0]!));\n const height = len(sub(corners[2]!, corners[0]!));\n const half = Math.sqrt(width * height) / 2;\n const box = aabbOfPoints(\n corners.flatMap((c) => [\n add(c, scaleBy(plane.normal, half)),\n sub(c, scaleBy(plane.normal, half)),\n ]),\n );\n return {\n position: scaleBy(add(box.min, box.max), 0.5),\n rotation: quatIdentity(),\n scale: sub(box.max, box.min),\n };\n },\n\n /** Screen-space deltas resolve against the plane the node already sits on. */\n translate(pose, dx, dy) {\n const vp = castableViewport();\n if (!vp) return pose;\n const box = boundsIn(vp, pose);\n if (!box) return pose;\n const from = { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n const to = { x: from.x + dx, y: from.y + dy };\n const offset = pose.position[upAxis];\n\n const ray = rayAt(vp, to);\n if (!ray) return pose;\n const t = intersectRayPlane(ray, up, offset);\n if (t === null) return pose;\n\n const anchorRay = rayAt(vp, from);\n if (!anchorRay) return pose;\n const anchorT = intersectRayPlane(anchorRay, up, offset);\n if (anchorT === null) return pose;\n\n const delta = sub(pointOnRay(ray, t), pointOnRay(anchorRay, anchorT));\n const position = {\n x: pose.position.x + delta.x,\n y: pose.position.y + delta.y,\n z: pose.position.z + delta.z,\n };\n position[upAxis] = pose.position[upAxis];\n return { ...pose, position };\n },\n\n supportsRotation() {\n return false;\n },\n };\n\n return descriptor;\n }\n\n return build((pose) => aabbOfPose(pose));\n}\n","/**\n * What a host paints for a gesture that proposes chrome rather than a pose.\n *\n * A marquee sweep and a box-drag both publish an `OngoingOverlay`.\n * `resolveOverlays` hands back world geometry with no renderer in it, so the\n * same call `<SceneCanvas>` makes serves a consumer-owned 3D renderer.\n *\n * A 3D host's `clientToWorld` is identity, so an overlay's world bounds are the\n * client rect the deps already work in, and the pane origin comes off exactly\n * once. Only the rectangular variants resolve here: a lasso, a pencil, and a run\n * of points are paths, and a path is geometry this cannot flatten to a box.\n */\n\nimport { resolveOverlays, type OngoingHandle } from '@weasel-js/core';\nimport type { ChromeBox } from './screen';\n\n/** Gesture chrome, in CSS pixels relative to the pane's top-left. */\nexport function collectOverlayBoxes(\n handles: Iterable<OngoingHandle>,\n origin: { x: number; y: number },\n): ChromeBox[] {\n const overlays = [];\n for (const handle of handles) {\n const ov = handle.overlay?.();\n if (ov) overlays.push(ov);\n }\n\n const boxes: ChromeBox[] = [];\n for (const resolved of resolveOverlays(overlays)) {\n if (resolved.kind !== 'marquee' && resolved.kind !== 'insertPreview') continue;\n const { x, y, width, height } = resolved.bounds;\n boxes.push({ x: x - origin.x, y: y - origin.y, width, height, tint: 'gesture' });\n }\n return boxes;\n}\n","/**\n * Camera tools and their actions.\n *\n * Shape tools transfer from the kit untouched — a 3D host mounts core's own\n * `useSelectTool` and a rectangle-style insert binding and neither notices the\n * dimension. Only the viewport tools are written here, which is the one\n * exception the kernel doc predicted: `useHandTool` routes to\n * `viewport.dragPan`, and that wants the 2D `view`.\n */\n\nimport { useMemo } from 'react';\nimport { defineTool, type Action, type Tool } from '@weasel-js/core';\nimport { dollyBy, orbitBy, type Camera3d } from './camera';\n\n/** Radians per CSS pixel of drag. A full pane width is a bit over half a turn. */\nconst ORBIT_RATE = 0.006;\nconst DOLLY_RATE = 0.0015;\n\n/** `camera.orbit`: an ongoing drag that turns the `camera3d` dep about its\n * target, relative to the camera as it was when the drag began. */\nexport const orbitAction: Action = {\n id: 'camera.orbit',\n label: 'Orbit',\n requires: ['camera3d'],\n invoker: {\n timing: 'ongoing',\n start(ctx) {\n const dep = ctx.deps.camera3d;\n const origin: Camera3d | undefined = dep?.get();\n return {\n kind: 'orbit',\n onMove(move) {\n if (!dep || !origin) return;\n // `drag.delta` runs from the drag origin, not the previous move, so\n // this composes against the camera as it was when the drag began.\n //\n // The fallback is only sound here because a 3D host's `clientToWorld`\n // is identity (see `overlays.ts`), so the world delta already is the\n // client one. Don't copy this pair to a host with a 2D view — there\n // the two spaces differ by the zoom.\n const delta = move.drag?.screenDelta ?? move.drag?.delta;\n if (!delta) return;\n dep.set(orbitBy(origin, -delta.x * ORBIT_RATE, delta.y * ORBIT_RATE));\n },\n };\n },\n },\n};\n\n/** `camera.dolly`: moves the `camera3d` dep toward or away from its target by\n * the wheel's `deltaY`. Bound to the wheel by default, in every tool. */\nexport const dollyAction: Action = {\n id: 'camera.dolly',\n label: 'Dolly',\n group: 'viewport',\n // Wheel, in any tool — the dispatcher merges the event's deltas into params.\n defaultBinding: [{ spec: { kind: 'wheel' }, opts: {} }],\n requires: ['camera3d'],\n invoker: {\n timing: 'immediate',\n run(deps, params) {\n const dep = deps.camera3d;\n if (!dep) return;\n const amount = typeof params?.deltaY === 'number' ? params.deltaY : 0;\n dep.set(dollyBy(dep.get(), Math.exp(amount * DOLLY_RATE)));\n },\n },\n};\n\n/** A tool that binds drag to `camera.orbit`. Register `orbitAction` alongside\n * it; the tool only declares the binding. */\nexport function useOrbitTool(): Tool {\n return useMemo(() => defineTool({\n id: 'orbit',\n hookName: 'useOrbitTool',\n cursor: 'grab',\n presentation: { label: 'Orbit', group: 'viewport' },\n bindings: [{ spec: { kind: 'drag' }, actionId: 'camera.orbit' }],\n }), []);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/kernel3d",
3
- "version": "1.9.4",
3
+ "version": "1.10.1",
4
4
  "description": "3D kernel for weasel: poses, orbit camera, ray picking and screen-projected chrome geometry over core's scene graph and dispatcher. Hosts a renderer rather than owning one.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,10 +37,10 @@
37
37
  "build": "tsup"
38
38
  },
39
39
  "dependencies": {
40
- "@weasel-js/geom": "1.9.4"
40
+ "@weasel-js/geom": "1.10.1"
41
41
  },
42
42
  "peerDependencies": {
43
- "@weasel-js/core": "1.9.4",
43
+ "@weasel-js/core": "1.10.1",
44
44
  "react": ">=18"
45
45
  },
46
46
  "publishConfig": {