@realitycollective/babylon-interactions 0.1.1-preview.2 → 0.1.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/CHANGELOG.md +29 -2
- package/README.md +6 -3
- package/dist/babylon-types.d.ts +104 -0
- package/dist/babylon-types.js +2 -0
- package/dist/babylon-types.js.map +1 -1
- package/dist/hit-tester.d.ts +6 -0
- package/dist/hit-tester.js +25 -2
- package/dist/hit-tester.js.map +1 -1
- package/dist/host.d.ts +63 -3
- package/dist/host.js +49 -2
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/physics-facility.d.ts +77 -0
- package/dist/physics-facility.js +199 -0
- package/dist/physics-facility.js.map +1 -0
- package/dist/pointer-visuals.d.ts +105 -0
- package/dist/pointer-visuals.js +149 -0
- package/dist/pointer-visuals.js.map +1 -0
- package/dist/provider.d.ts +16 -1
- package/dist/provider.js +49 -4
- package/dist/provider.js.map +1 -1
- package/dist/transform-port.d.ts +30 -2
- package/dist/transform-port.js +23 -0
- package/dist/transform-port.js.map +1 -1
- package/package.json +7 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform-port.js","sourceRoot":"","sources":["../src/transform-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BabylonTransformPort - the read/write surface of one interactable's\n * Babylon node, honouring the core's FROM-REST semantics: the rest pose is\n * captured at construction and offsets and rotations apply relative to it,\n * so a behaviour composes with anything else animating the same node.\n *\n * Every write mutates the node's existing `Vector3`/`Quaternion` in place.\n * Babylon compares the live values against its cache to decide whether the\n * world matrix needs recomputing, so in-place writes are seen; assigning a\n * plain object in their place would break Babylon, which calls methods on\n * them.\n */\nimport type { PoseTuple, QuatTuple, Vec3Tuple } from \"@realitycollective/webxr-input\";\nimport {\n quatConjugate,\n quatMultiply,\n vAdd,\n vApplyQuat,\n vSub,\n type HoldRelease,\n type TransformPort,\n} from \"@realitycollective/webxr-interactions\";\nimport {\n nodeWorldPose,\n parentOf,\n toQuat,\n toVec3,\n writeQuat,\n writeVec3,\n type BabylonMaterialLike,\n type BabylonQuaternionLike,\n type BabylonTransformNodeLike,\n type BabylonVector3Like,\n} from \"./babylon-types.js\";\n\nexport interface BabylonTransformPortOptions {\n /**\n * Builds the `Quaternion` written to a node whose `rotationQuaternion` is\n * null - a node still driven by Euler `rotation`, which is Babylon's\n * default. Pass `() => Quaternion.Identity()` from `@babylonjs/core`.\n *\n * The fallback is a plain `{ x, y, z, w }` object, which carries the\n * numbers correctly but is NOT a Babylon `Quaternion` and will fail as\n * soon as Babylon calls a method on it. So: either give a node a real\n * `rotationQuaternion` before registering it, or supply this factory.\n * A node that already has one needs neither - it is mutated in place.\n */\n createQuaternion?: () => BabylonQuaternionLike;\n /**\n * The two `PhysicsMotionType` values `beginHold`/`endHold` switch a held\n * node's `physicsBody` between - pass Babylon's own\n * `{ animated: PhysicsMotionType.ANIMATED, dynamic: PhysicsMotionType.DYNAMIC }`.\n * This package holds no Babylon values, only shapes, so the app supplies\n * the actual enum members, the same idea as `createQuaternion`.\n *\n * `beginHold`/`endHold` exist on the port only when BOTH this option and\n * `node.physicsBody` are present at construction - a node with no\n * physics body, or a construction with no motion types, gets neither\n * member and behaves exactly as before.\n */\n physicsMotionTypes?: { animated: unknown; dynamic: unknown };\n}\n\nexport class BabylonTransformPort implements TransformPort {\n private readonly node: BabylonTransformNodeLike;\n private readonly createQuaternion: () => BabylonQuaternionLike;\n private restPosition: Vec3Tuple = [0, 0, 0];\n private restQuaternion: QuatTuple = [0, 0, 0, 1];\n private restScale: Vec3Tuple = [1, 1, 1];\n private held = false;\n /** The material's `emissiveColor` before any pulse, captured on first use. */\n private baseEmissiveColor: Vec3Tuple | null = null;\n /** PBRMaterial's `emissiveIntensity` before any pulse, captured on first use - StandardMaterial has none. */\n private baseEmissiveIntensity: number | null = null;\n\n readonly beginHold?: () => void;\n readonly endHold?: (release: HoldRelease) => void;\n\n constructor(node: BabylonTransformNodeLike, options: BabylonTransformPortOptions = {}) {\n this.node = node;\n this.createQuaternion = options.createQuaternion ?? (() => ({ x: 0, y: 0, z: 0, w: 1 }));\n this.recaptureRest();\n\n const body = node.physicsBody;\n const motionTypes = options.physicsMotionTypes;\n if (body && motionTypes) {\n this.beginHold = () => {\n this.held = true;\n // Node-drives-physics: our setWorldPose writes below now stick,\n // and gravity/collisions stop moving the node - see\n // BabylonPhysicsBodyLike's own comment.\n body.disablePreStep = true;\n body.setMotionType(motionTypes.animated);\n };\n this.endHold = (release) => {\n this.held = false;\n body.setMotionType(motionTypes.dynamic);\n body.disablePreStep = false;\n body.setLinearVelocity(vector3Like(release.linearVelocity));\n body.setAngularVelocity(vector3Like(release.angularVelocity));\n };\n }\n }\n\n /** Re-read the node's current local transform as the new rest. */\n recaptureRest(): void {\n this.restPosition = toVec3(this.node.position) ?? [0, 0, 0];\n this.restQuaternion = toQuat(this.node.rotationQuaternion);\n this.restScale = toVec3(this.node.scaling) ?? [1, 1, 1];\n }\n\n /** The node's LIVE world pose, from its absolute position and rotation. */\n getWorldPose(): PoseTuple {\n this.node.computeWorldMatrix?.(true);\n return nodeWorldPose(this.node);\n }\n\n /**\n * The captured rest pose in world space, resolved through the parent's\n * absolute position and rotation. Parent SCALE is ignored, the same\n * simplification as {@link setWorldPose}.\n */\n getRestWorldPose(): PoseTuple {\n const parent = parentOf(this.node);\n if (!parent) {\n return { position: [...this.restPosition], quaternion: [...this.restQuaternion] };\n }\n parent.computeWorldMatrix?.(true);\n const parentPose = nodeWorldPose(parent);\n return {\n position: vAdd(parentPose.position, vApplyQuat(this.restPosition, parentPose.quaternion)),\n quaternion: quatMultiply(parentPose.quaternion, this.restQuaternion),\n };\n }\n\n getLocalOffset(): Vec3Tuple {\n const delta = vSub(toVec3(this.node.position) ?? [0, 0, 0], this.restPosition);\n return vApplyQuat(delta, quatConjugate(this.restQuaternion));\n }\n\n setLocalOffset(offset: Vec3Tuple): void {\n writeVec3(this.node.position, vAdd(this.restPosition, vApplyQuat(offset, this.restQuaternion)));\n }\n\n setLocalRotation(quaternion: QuatTuple): void {\n this.writeRotation(quatMultiply(this.restQuaternion, quaternion));\n }\n\n /**\n * Follow a world pose while grabbed, or place the node directly the rest\n * of the time (reset / teleport) - see `TransformPort.setWorldPose`'s own\n * comment for what the two mean on a node with physics. With a parent,\n * the pose is resolved into the parent's frame through its absolute\n * position and rotation.\n *\n * Simplification: parent SCALE is ignored. A grabbed object under a scaled\n * parent tracks the hand at the wrong distance. Grabbables are expected to\n * sit under an unscaled parent, which is how the demos build them.\n */\n setWorldPose(pose: PoseTuple): void {\n const parent = parentOf(this.node);\n if (!parent) {\n writeVec3(this.node.position, pose.position);\n this.writeRotation(pose.quaternion);\n } else {\n const parentPose = nodeWorldPose(parent);\n const inverse = quatConjugate(parentPose.quaternion);\n writeVec3(this.node.position, vApplyQuat(vSub(pose.position, parentPose.position), inverse));\n this.writeRotation(quatMultiply(inverse, pose.quaternion));\n }\n // Not held: a physics-enabled node teleports and comes to rest, rather\n // than carrying whatever velocity it had a moment before (\"back to the\n // tee\"). A DYNAMIC body already picks up a direct node write on its\n // next pre-step (the same sync `beginHold`'s ANIMATED switch disables),\n // so all a reset needs on top of the write above is clearing velocity.\n const body = this.node.physicsBody;\n if (body && !this.held) {\n body.setLinearVelocity(ZERO_VECTOR3);\n body.setAngularVelocity(ZERO_VECTOR3);\n }\n }\n\n /**\n * Uniform scale about the rest scale, and - mirroring the IWSDK and\n * three.js ports - a pulse of light: `emissiveColor` is scaled by\n * `1 + effect.emissive` about its own base colour (StandardMaterial and\n * PBRMaterial both carry it), and on a PBRMaterial `emissiveIntensity` is\n * ALSO set to its base plus `effect.emissive`, the same additive rule\n * three.js's `emissiveIntensity` follows - PBRMaterial's field is that\n * one's Babylon analogue. A node with no material, or a material with no\n * `emissiveColor`, is left alone. Base values are captured on first use,\n * so a later `recaptureRest()`-style re-read is not needed for this part.\n */\n setEffect(effect: { scale?: number; emissive?: number }): void {\n if (effect.scale !== undefined) {\n const scaling = this.node.scaling;\n if (scaling) {\n writeVec3(scaling, [\n this.restScale[0] * effect.scale,\n this.restScale[1] * effect.scale,\n this.restScale[2] * effect.scale,\n ]);\n }\n }\n if (effect.emissive !== undefined) {\n const material = this.firstMaterial();\n if (material?.emissiveColor) {\n if (this.baseEmissiveColor === null) this.baseEmissiveColor = toVec3(material.emissiveColor) ?? [0, 0, 0];\n const factor = 1 + effect.emissive;\n writeVec3(material.emissiveColor, [\n this.baseEmissiveColor[0] * factor,\n this.baseEmissiveColor[1] * factor,\n this.baseEmissiveColor[2] * factor,\n ]);\n if (material.emissiveIntensity !== undefined) {\n if (this.baseEmissiveIntensity === null) this.baseEmissiveIntensity = material.emissiveIntensity;\n material.emissiveIntensity = this.baseEmissiveIntensity + effect.emissive;\n }\n }\n }\n }\n\n /** The node's first material slot - `AbstractMesh.material`, single or the first of an array. */\n private firstMaterial(): BabylonMaterialLike | null {\n const material = this.node.material;\n if (!material) return null;\n return Array.isArray(material) ? (material[0] ?? null) : material;\n }\n\n /** Write a quaternion, creating the node's `rotationQuaternion` if needed. */\n private writeRotation(value: QuatTuple): void {\n let target = this.node.rotationQuaternion;\n if (!target) {\n target = this.createQuaternion();\n this.node.rotationQuaternion = target;\n }\n writeQuat(target, value);\n }\n}\n\n/** A fresh plain `{ x, y, z }` - `setLinearVelocity`/`setAngularVelocity` only ever read it. */\nfunction vector3Like(v: Vec3Tuple): BabylonVector3Like {\n return { x: v[0], y: v[1], z: v[2] };\n}\n\nconst ZERO_VECTOR3: BabylonVector3Like = { x: 0, y: 0, z: 0 };\n"]}
|
|
1
|
+
{"version":3,"file":"transform-port.js","sourceRoot":"","sources":["../src/transform-port.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * BabylonTransformPort - the read/write surface of one interactable's\n * Babylon node, honouring the core's FROM-REST semantics: the rest pose is\n * captured at construction and offsets and rotations apply relative to it,\n * so a behaviour composes with anything else animating the same node.\n *\n * Every write mutates the node's existing `Vector3`/`Quaternion` in place.\n * Babylon compares the live values against its cache to decide whether the\n * world matrix needs recomputing, so in-place writes are seen; assigning a\n * plain object in their place would break Babylon, which calls methods on\n * them.\n *\n * A node's held pose comes from one of two independent mechanisms. With\n * `options.physics` (a platform `PhysicsFacility` and the node's body id -\n * see `BabylonPhysicsFacility`), the port drives the core's held-pose rule\n * through it: `beginHold`/`endHold` suspend and resume the body there, and\n * every write that moves the node (`setWorldPose`, `setLocalOffset`,\n * `setLocalRotation`) keeps the body's own pose in step. Without it, a node\n * with a bare `node.physicsBody` and `options.physicsMotionTypes` keeps the\n * older, narrower hold this port has always had - see that option's own\n * comment. A construction never needs both.\n */\nimport type { PoseTuple, QuatTuple, Vec3Tuple } from \"@realitycollective/webxr-input\";\nimport {\n quatConjugate,\n quatMultiply,\n vAdd,\n vApplyQuat,\n vSub,\n type HoldRelease,\n type PhysicsFacility,\n type TransformPort,\n} from \"@realitycollective/webxr-interactions\";\nimport {\n nodeWorldPose,\n parentOf,\n toQuat,\n toVec3,\n writeQuat,\n writeVec3,\n type BabylonMaterialLike,\n type BabylonQuaternionLike,\n type BabylonTransformNodeLike,\n type BabylonVector3Like,\n} from \"./babylon-types.js\";\n\nexport interface BabylonTransformPortOptions {\n /**\n * Builds the `Quaternion` written to a node whose `rotationQuaternion` is\n * null - a node still driven by Euler `rotation`, which is Babylon's\n * default. Pass `() => Quaternion.Identity()` from `@babylonjs/core`.\n *\n * The fallback is a plain `{ x, y, z, w }` object, which carries the\n * numbers correctly but is NOT a Babylon `Quaternion` and will fail as\n * soon as Babylon calls a method on it. So: either give a node a real\n * `rotationQuaternion` before registering it, or supply this factory.\n * A node that already has one needs neither - it is mutated in place.\n */\n createQuaternion?: () => BabylonQuaternionLike;\n /**\n * The two `PhysicsMotionType` values `beginHold`/`endHold` switch a held\n * node's `physicsBody` between - pass Babylon's own\n * `{ animated: PhysicsMotionType.ANIMATED, dynamic: PhysicsMotionType.DYNAMIC }`.\n * This package holds no Babylon values, only shapes, so the app supplies\n * the actual enum members, the same idea as `createQuaternion`.\n *\n * `beginHold`/`endHold` exist on the port only when BOTH this option and\n * `node.physicsBody` are present at construction - a node with no\n * physics body, or a construction with no motion types, gets neither\n * member and behaves exactly as before. Ignored when `physics` is given.\n */\n physicsMotionTypes?: { animated: unknown; dynamic: unknown };\n /**\n * Drive the held-pose rule through the platform's physics facility\n * instead of `node.physicsBody` directly - the body id is the same\n * string id the node was registered under. Present, `beginHold`/`endHold`\n * suspend and resume the body there, and `setWorldPose`, `setLocalOffset`\n * and `setLocalRotation` all keep the body's pose in step with the node's.\n * Takes precedence over `physicsMotionTypes` when both are given.\n */\n physics?: BabylonTransformPortPhysics;\n}\n\n/** The body a port drives through the platform's `PhysicsFacility`. */\nexport interface BabylonTransformPortPhysics {\n facility: PhysicsFacility;\n /** The body's id in the facility - the interactable's own id. */\n bodyId: string;\n}\n\nexport class BabylonTransformPort implements TransformPort {\n private readonly node: BabylonTransformNodeLike;\n private readonly createQuaternion: () => BabylonQuaternionLike;\n private restPosition: Vec3Tuple = [0, 0, 0];\n private restQuaternion: QuatTuple = [0, 0, 0, 1];\n private restScale: Vec3Tuple = [1, 1, 1];\n private held = false;\n /** The material's `emissiveColor` before any pulse, captured on first use. */\n private baseEmissiveColor: Vec3Tuple | null = null;\n /** PBRMaterial's `emissiveIntensity` before any pulse, captured on first use - StandardMaterial has none. */\n private baseEmissiveIntensity: number | null = null;\n private readonly physics: BabylonTransformPortPhysics | undefined;\n\n readonly beginHold?: () => void;\n readonly endHold?: (release: HoldRelease) => void;\n\n constructor(node: BabylonTransformNodeLike, options: BabylonTransformPortOptions = {}) {\n this.node = node;\n this.createQuaternion = options.createQuaternion ?? (() => ({ x: 0, y: 0, z: 0, w: 1 }));\n this.recaptureRest();\n\n this.physics = options.physics;\n if (this.physics) {\n const { facility, bodyId } = this.physics;\n this.beginHold = () => facility.suspend(bodyId);\n this.endHold = (release) => facility.resume(bodyId, release);\n return;\n }\n\n const body = node.physicsBody;\n const motionTypes = options.physicsMotionTypes;\n if (body && motionTypes) {\n this.beginHold = () => {\n this.held = true;\n // Node-drives-physics: our setWorldPose writes below now stick,\n // and gravity/collisions stop moving the node - see\n // BabylonPhysicsBodyLike's own comment.\n body.disablePreStep = true;\n body.setMotionType(motionTypes.animated);\n };\n this.endHold = (release) => {\n this.held = false;\n body.setMotionType(motionTypes.dynamic);\n body.disablePreStep = false;\n body.setLinearVelocity(vector3Like(release.linearVelocity));\n body.setAngularVelocity(vector3Like(release.angularVelocity));\n };\n }\n }\n\n /** Re-read the node's current local transform as the new rest. */\n recaptureRest(): void {\n this.restPosition = toVec3(this.node.position) ?? [0, 0, 0];\n this.restQuaternion = toQuat(this.node.rotationQuaternion);\n this.restScale = toVec3(this.node.scaling) ?? [1, 1, 1];\n }\n\n /** The node's LIVE world pose, from its absolute position and rotation. */\n getWorldPose(): PoseTuple {\n this.node.computeWorldMatrix?.(true);\n return nodeWorldPose(this.node);\n }\n\n /**\n * The captured rest pose in world space, resolved through the parent's\n * absolute position and rotation. Parent SCALE is ignored, the same\n * simplification as {@link setWorldPose}.\n */\n getRestWorldPose(): PoseTuple {\n const parent = parentOf(this.node);\n if (!parent) {\n return { position: [...this.restPosition], quaternion: [...this.restQuaternion] };\n }\n parent.computeWorldMatrix?.(true);\n const parentPose = nodeWorldPose(parent);\n return {\n position: vAdd(parentPose.position, vApplyQuat(this.restPosition, parentPose.quaternion)),\n quaternion: quatMultiply(parentPose.quaternion, this.restQuaternion),\n };\n }\n\n getLocalOffset(): Vec3Tuple {\n const delta = vSub(toVec3(this.node.position) ?? [0, 0, 0], this.restPosition);\n return vApplyQuat(delta, quatConjugate(this.restQuaternion));\n }\n\n setLocalOffset(offset: Vec3Tuple): void {\n writeVec3(this.node.position, vAdd(this.restPosition, vApplyQuat(offset, this.restQuaternion)));\n this.syncBody();\n }\n\n setLocalRotation(quaternion: QuatTuple): void {\n this.writeRotation(quatMultiply(this.restQuaternion, quaternion));\n this.syncBody();\n }\n\n /** A behaviour's write to the node reaches its facility-driven body too, as a placement (velocity cleared). */\n private syncBody(): void {\n if (!this.physics) return;\n this.physics.facility.setBodyPose(this.physics.bodyId, this.getWorldPose());\n }\n\n /**\n * Follow a world pose while grabbed, or place the node directly the rest\n * of the time (reset / teleport) - see `TransformPort.setWorldPose`'s own\n * comment for what the two mean on a node with physics. With a parent,\n * the pose is resolved into the parent's frame through its absolute\n * position and rotation.\n *\n * Simplification: parent SCALE is ignored. A grabbed object under a scaled\n * parent tracks the hand at the wrong distance. Grabbables are expected to\n * sit under an unscaled parent, which is how the demos build them.\n */\n setWorldPose(pose: PoseTuple): void {\n // With a facility-driven body, the facility owns its pose and velocity\n // and also places the node itself; the write below runs regardless, so\n // the node never lags the body even if the facility placed it slightly\n // differently (a scaled parent, for one - see BabylonPhysicsFacility's\n // own resolution).\n if (this.physics) this.physics.facility.setBodyPose(this.physics.bodyId, pose);\n const parent = parentOf(this.node);\n if (!parent) {\n writeVec3(this.node.position, pose.position);\n this.writeRotation(pose.quaternion);\n } else {\n const parentPose = nodeWorldPose(parent);\n const inverse = quatConjugate(parentPose.quaternion);\n writeVec3(this.node.position, vApplyQuat(vSub(pose.position, parentPose.position), inverse));\n this.writeRotation(quatMultiply(inverse, pose.quaternion));\n }\n // Not held: a physics-enabled node teleports and comes to rest, rather\n // than carrying whatever velocity it had a moment before (\"back to the\n // tee\"). A DYNAMIC body already picks up a direct node write on its\n // next pre-step (the same sync `beginHold`'s ANIMATED switch disables),\n // so all a reset needs on top of the write above is clearing velocity.\n const body = this.node.physicsBody;\n if (body && !this.held) {\n body.setLinearVelocity(ZERO_VECTOR3);\n body.setAngularVelocity(ZERO_VECTOR3);\n }\n }\n\n /**\n * Uniform scale about the rest scale, and - mirroring the IWSDK and\n * three.js ports - a pulse of light: `emissiveColor` is scaled by\n * `1 + effect.emissive` about its own base colour (StandardMaterial and\n * PBRMaterial both carry it), and on a PBRMaterial `emissiveIntensity` is\n * ALSO set to its base plus `effect.emissive`, the same additive rule\n * three.js's `emissiveIntensity` follows - PBRMaterial's field is that\n * one's Babylon analogue. A node with no material, or a material with no\n * `emissiveColor`, is left alone. Base values are captured on first use,\n * so a later `recaptureRest()`-style re-read is not needed for this part.\n */\n setEffect(effect: { scale?: number; emissive?: number }): void {\n if (effect.scale !== undefined) {\n const scaling = this.node.scaling;\n if (scaling) {\n writeVec3(scaling, [\n this.restScale[0] * effect.scale,\n this.restScale[1] * effect.scale,\n this.restScale[2] * effect.scale,\n ]);\n }\n }\n if (effect.emissive !== undefined) {\n const material = this.firstMaterial();\n if (material?.emissiveColor) {\n if (this.baseEmissiveColor === null) this.baseEmissiveColor = toVec3(material.emissiveColor) ?? [0, 0, 0];\n const factor = 1 + effect.emissive;\n writeVec3(material.emissiveColor, [\n this.baseEmissiveColor[0] * factor,\n this.baseEmissiveColor[1] * factor,\n this.baseEmissiveColor[2] * factor,\n ]);\n if (material.emissiveIntensity !== undefined) {\n if (this.baseEmissiveIntensity === null) this.baseEmissiveIntensity = material.emissiveIntensity;\n material.emissiveIntensity = this.baseEmissiveIntensity + effect.emissive;\n }\n }\n }\n }\n\n /** The node's first material slot - `AbstractMesh.material`, single or the first of an array. */\n private firstMaterial(): BabylonMaterialLike | null {\n const material = this.node.material;\n if (!material) return null;\n return Array.isArray(material) ? (material[0] ?? null) : material;\n }\n\n /** Write a quaternion, creating the node's `rotationQuaternion` if needed. */\n private writeRotation(value: QuatTuple): void {\n let target = this.node.rotationQuaternion;\n if (!target) {\n target = this.createQuaternion();\n this.node.rotationQuaternion = target;\n }\n writeQuat(target, value);\n }\n}\n\n/** A fresh plain `{ x, y, z }` - `setLinearVelocity`/`setAngularVelocity` only ever read it. */\nfunction vector3Like(v: Vec3Tuple): BabylonVector3Like {\n return { x: v[0], y: v[1], z: v[2] };\n}\n\nconst ZERO_VECTOR3: BabylonVector3Like = { x: 0, y: 0, z: 0 };\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@realitycollective/babylon-interactions",
|
|
3
|
-
"version": "0.1.1
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Babylon.js adapter for the Reality Collective Interaction Extensions - maps a Babylon WebXR experience (WebXRDefaultExperience controllers, motion controller components, hand-tracking joints) into the engine-free @realitycollective/webxr-interactions core, with a scene pointer fallback on desktop. Structurally typed: no @babylonjs/core import. Re-exports the core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"realitycollective",
|
|
@@ -10,7 +10,10 @@
|
|
|
10
10
|
"xr",
|
|
11
11
|
"interaction",
|
|
12
12
|
"input",
|
|
13
|
-
"typescript"
|
|
13
|
+
"typescript",
|
|
14
|
+
"physics",
|
|
15
|
+
"pointer",
|
|
16
|
+
"eye-gaze"
|
|
14
17
|
],
|
|
15
18
|
"license": "MIT",
|
|
16
19
|
"author": "Reality Collective",
|
|
@@ -33,8 +36,8 @@
|
|
|
33
36
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
34
37
|
},
|
|
35
38
|
"dependencies": {
|
|
36
|
-
"@realitycollective/webxr-input": "^0.1.
|
|
37
|
-
"@realitycollective/webxr-interactions": "^0.1.1
|
|
39
|
+
"@realitycollective/webxr-input": "^0.1.8",
|
|
40
|
+
"@realitycollective/webxr-interactions": "^0.1.1"
|
|
38
41
|
},
|
|
39
42
|
"repository": {
|
|
40
43
|
"type": "git",
|