@iwsdk/core 1.0.0-rc.0 → 1.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asset/asset-manager.js.map +1 -1
- package/dist/asset/cache-manager.js.map +1 -1
- package/dist/asset/loaders/audio-loader.js.map +1 -1
- package/dist/asset/loaders/cached-asset-load.js.map +1 -1
- package/dist/asset/loaders/gltf-loader.js.map +1 -1
- package/dist/asset/loaders/hdr-texture-loader.js.map +1 -1
- package/dist/asset/loaders/texture-loader.js.map +1 -1
- package/dist/asset/loaders/uikitml-loader.js.map +1 -1
- package/dist/audio/audio-pool.js.map +1 -1
- package/dist/audio/audio-system.js.map +1 -1
- package/dist/audio/audio-utils.js.map +1 -1
- package/dist/audio/audio.js.map +1 -1
- package/dist/camera/camera-source.js.map +1 -1
- package/dist/camera/camera-system.js.map +1 -1
- package/dist/camera/camera-utils.js.map +1 -1
- package/dist/camera/types.js.map +1 -1
- package/dist/depth/depth-occludable.js.map +1 -1
- package/dist/depth/depth-sensing-system.js.map +1 -1
- package/dist/depth/depth-textures.js.map +1 -1
- package/dist/depth/occlusion/preprocessing-pass.js.map +1 -1
- package/dist/depth/occlusion/preprocessing-shader.glsl.js.map +1 -1
- package/dist/ecs/builtin-components.js.map +1 -1
- package/dist/ecs/component-editor-metadata.js.map +1 -1
- package/dist/ecs/component-manifest.js.map +1 -1
- package/dist/ecs/entity.js.map +1 -1
- package/dist/ecs/system.js.map +1 -1
- package/dist/ecs/world.js.map +1 -1
- package/dist/environment/dome-gradient.js.map +1 -1
- package/dist/environment/dome-texture.js.map +1 -1
- package/dist/environment/environment-system.js.map +1 -1
- package/dist/environment/gradient-environment.js.map +1 -1
- package/dist/environment/ibl-gradient.js.map +1 -1
- package/dist/environment/ibl-texture.js.map +1 -1
- package/dist/environment/scene-ar-environment.js.map +1 -1
- package/dist/environment-raycast/environment-raycast.js.map +1 -1
- package/dist/environment-raycast/raycast-target.js.map +1 -1
- package/dist/gaze/gaze-system.d.ts +207 -0
- package/dist/gaze/gaze-system.d.ts.map +1 -0
- package/dist/gaze/gaze-system.js +168 -0
- package/dist/gaze/gaze-system.js.map +1 -0
- package/dist/gaze/index.d.ts +8 -0
- package/dist/gaze/index.d.ts.map +1 -0
- package/dist/grab/distance-grabbable.js.map +1 -1
- package/dist/grab/grab-helpers.d.ts +7 -6
- package/dist/grab/grab-helpers.d.ts.map +1 -1
- package/dist/grab/grab-helpers.js +12 -7
- package/dist/grab/grab-helpers.js.map +1 -1
- package/dist/grab/grab-system.d.ts.map +1 -1
- package/dist/grab/grab-system.js +2 -1
- package/dist/grab/grab-system.js.map +1 -1
- package/dist/grab/grab-warnings.js.map +1 -1
- package/dist/grab/grabbed.js.map +1 -1
- package/dist/grab/handles.d.ts +10 -1
- package/dist/grab/handles.d.ts.map +1 -1
- package/dist/grab/handles.js +29 -6
- package/dist/grab/handles.js.map +1 -1
- package/dist/grab/index.js.map +1 -1
- package/dist/grab/one-hand-grabbable.js.map +1 -1
- package/dist/grab/pointer-events-patch.js.map +1 -1
- package/dist/grab/two-hands-grabbable.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/init/browser-camera.js.map +1 -1
- package/dist/init/player-camera.js.map +1 -1
- package/dist/init/session-grant.js.map +1 -1
- package/dist/init/world-initializer.d.ts +49 -0
- package/dist/init/world-initializer.d.ts.map +1 -1
- package/dist/init/world-initializer.js +23 -11
- package/dist/init/world-initializer.js.map +1 -1
- package/dist/init/xr.d.ts +14 -0
- package/dist/init/xr.d.ts.map +1 -1
- package/dist/init/xr.js +19 -0
- package/dist/init/xr.js.map +1 -1
- package/dist/input/canvas-pointer-system.js.map +1 -1
- package/dist/input/input-actions.js.map +1 -1
- package/dist/input/input-manager.js.map +1 -1
- package/dist/input/input-system.d.ts +3 -0
- package/dist/input/input-system.d.ts.map +1 -1
- package/dist/input/input-system.js +72 -6
- package/dist/input/input-system.js.map +1 -1
- package/dist/input/state-tags.d.ts.map +1 -1
- package/dist/input/state-tags.js +2 -0
- package/dist/input/state-tags.js.map +1 -1
- package/dist/input/stateful-browser-gamepad.js.map +1 -1
- package/dist/input/stateful-keyboard.js.map +1 -1
- package/dist/layers/xr-cylinder-layer.js.map +1 -1
- package/dist/layers/xr-layer-init.js.map +1 -1
- package/dist/layers/xr-layer-state.js.map +1 -1
- package/dist/layers/xr-layer-system.js.map +1 -1
- package/dist/layers/xr-layer-transform.js.map +1 -1
- package/dist/layers/xr-quad-layer.js.map +1 -1
- package/dist/level/level-component-applier.js.map +1 -1
- package/dist/level/level-player-rig.js.map +1 -1
- package/dist/level/level-root.js.map +1 -1
- package/dist/level/level-scene-environment.js.map +1 -1
- package/dist/level/level-scene-json-importer.js.map +1 -1
- package/dist/level/level-scene-material.js.map +1 -1
- package/dist/level/level-scene-object.js.map +1 -1
- package/dist/level/level-scene-primitive.js.map +1 -1
- package/dist/level/level-system.js.map +1 -1
- package/dist/level/level-tag.js.map +1 -1
- package/dist/lighting/light-binding.js.map +1 -1
- package/dist/lighting/light-components.js.map +1 -1
- package/dist/lighting/light-system.js.map +1 -1
- package/dist/locomotion/geometries/beveled-cylinder.js.map +1 -1
- package/dist/locomotion/locomotion-environment.js.map +1 -1
- package/dist/locomotion/locomotion-input-provider.js.map +1 -1
- package/dist/locomotion/locomotion.js.map +1 -1
- package/dist/locomotion/materials/line.js.map +1 -1
- package/dist/locomotion/slide.js.map +1 -1
- package/dist/locomotion/teleport.js.map +1 -1
- package/dist/locomotion/turn.js.map +1 -1
- package/dist/mcp/ecs-debug-tools.js.map +1 -1
- package/dist/mcp/mcp-runtime.js.map +1 -1
- package/dist/mcp/scene-tools.js.map +1 -1
- package/dist/mcp/ui-debug-tools.js.map +1 -1
- package/dist/physics/physics-runtime.js.map +1 -1
- package/dist/physics/physics-system.js.map +1 -1
- package/dist/physics/physics-transport.js.map +1 -1
- package/dist/physics/physics-worker-protocol.js.map +1 -1
- package/dist/physics/physics-worker-utils.js.map +1 -1
- package/dist/physics/physics-worker.js.map +1 -1
- package/dist/physics/physicsBody.js.map +1 -1
- package/dist/physics/physicsManipulation.js.map +1 -1
- package/dist/physics/physicsShape.js.map +1 -1
- package/dist/physics/utils.js.map +1 -1
- package/dist/project/normalize.d.ts.map +1 -1
- package/dist/project/normalize.js +11 -0
- package/dist/project/normalize.js.map +1 -1
- package/dist/project/paths.js.map +1 -1
- package/dist/project/types.d.ts +32 -2
- package/dist/project/types.d.ts.map +1 -1
- package/dist/project/types.js.map +1 -1
- package/dist/project/validation.d.ts.map +1 -1
- package/dist/project/validation.js +65 -1
- package/dist/project/validation.js.map +1 -1
- package/dist/runtime/three.js.map +1 -1
- package/dist/scene-understanding/anchor.js.map +1 -1
- package/dist/scene-understanding/mesh.js.map +1 -1
- package/dist/scene-understanding/plane.js.map +1 -1
- package/dist/scene-understanding/scene-understanding-system.js.map +1 -1
- package/dist/schemas/iwsdk-project.v1.schema.json +45 -3
- package/dist/transform/synced-euler.js.map +1 -1
- package/dist/transform/synced-quaternion.js.map +1 -1
- package/dist/transform/synced-vector3.js.map +1 -1
- package/dist/transform/transform-component.js.map +1 -1
- package/dist/transform/transform-utils.js.map +1 -1
- package/dist/transform/transform.js.map +1 -1
- package/dist/ui/document.js.map +1 -1
- package/dist/ui/follow-component.js.map +1 -1
- package/dist/ui/follow.js.map +1 -1
- package/dist/ui/panel-components.js.map +1 -1
- package/dist/ui/screenspace-component.js.map +1 -1
- package/dist/ui/screenspace.js.map +1 -1
- package/dist/ui/ui.js.map +1 -1
- package/dist/ui/uikitml-asset.js.map +1 -1
- package/dist/ui/uikitml.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/visibility/visibility-component.js.map +1 -1
- package/dist/visibility/visibility.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { GazeConecaster } from '@iwsdk/xr-input';
|
|
2
|
+
import { createSystem } from '../ecs/system.js';
|
|
3
|
+
import '../ecs/world.js';
|
|
4
|
+
import { Types } from 'elics';
|
|
5
|
+
import '@iwsdk/scene-composition';
|
|
6
|
+
import '../ecs/builtin-components.js';
|
|
7
|
+
import '../ecs/entity.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
11
|
+
*
|
|
12
|
+
* This source code is licensed under the MIT license found in the
|
|
13
|
+
* LICENSE file in the root directory of this source tree.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* GazeSystem — wires the global {@link GazePointer} to ECS interactables.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* - Owns configuration and diagnostics only. The pointer itself lives on
|
|
20
|
+
* {@link XRInputManager} (as `input.xr.gazePointer`) so `GrabSystem` can
|
|
21
|
+
* identify the selecting hand; registering this system is what flips
|
|
22
|
+
* `input.xr.gazeEnabled` and makes gaze cost anything at all.
|
|
23
|
+
* - Candidates come from the same ray-target snapshot used by hand rays.
|
|
24
|
+
* - The pointer samples the WebXR gaze target ray itself each frame;
|
|
25
|
+
* `logDiagnostics` explains missing sources and invalid poses.
|
|
26
|
+
* - Selection is committed by either hand's pinch, with per-hand mutual
|
|
27
|
+
* exclusion (the hand that started the pinch owns it until release).
|
|
28
|
+
* - Hover and selection flow through ordinary ray pointer events, so
|
|
29
|
+
* {@link InputSystem} owns the shared `Hovered` / `Pressed` state.
|
|
30
|
+
* - Hand/controller far rays are disabled while gaze is available. Gaze is
|
|
31
|
+
* optionally suppressed when a near touch/grab pointer is active, so direct
|
|
32
|
+
* manipulation wins without an incidental far-ray hit stealing focus.
|
|
33
|
+
*
|
|
34
|
+
* @category Input
|
|
35
|
+
*/
|
|
36
|
+
class GazeSystem extends createSystem({}, {
|
|
37
|
+
/**
|
|
38
|
+
* If true, gaze is suppressed whenever a near touch/grab pointer is in
|
|
39
|
+
* HOVER or SELECT. Set false to allow gaze to remain active concurrently.
|
|
40
|
+
* @default true
|
|
41
|
+
*/
|
|
42
|
+
suppressWhenDirectPointerActive: { type: Types.Boolean, default: true },
|
|
43
|
+
/**
|
|
44
|
+
* 1€ filter min cutoff (lower = smoother, higher = more responsive).
|
|
45
|
+
* @default 1.5
|
|
46
|
+
*/
|
|
47
|
+
filterMinCutoff: { type: Types.Float32, default: 1.5 },
|
|
48
|
+
/**
|
|
49
|
+
* 1€ filter beta (higher = less smoothing during fast saccades).
|
|
50
|
+
* @default 0.05
|
|
51
|
+
*/
|
|
52
|
+
filterBeta: { type: Types.Float32, default: 0.05 },
|
|
53
|
+
/**
|
|
54
|
+
* Dwell window in seconds for consensus voting. `0` disables consensus.
|
|
55
|
+
* @default 0.15
|
|
56
|
+
*/
|
|
57
|
+
dwellWindowSeconds: { type: Types.Float32, default: 0.15 },
|
|
58
|
+
/**
|
|
59
|
+
* Half-angle of the gaze selection cone, in degrees. Widening it makes
|
|
60
|
+
* small targets easier to acquire at the cost of more ambiguity between
|
|
61
|
+
* neighbours.
|
|
62
|
+
* @default 5
|
|
63
|
+
*/
|
|
64
|
+
coneAngle: { type: Types.Float32, default: 5 },
|
|
65
|
+
/** Maximum gaze cone/raycast distance in meters. @default 30 */
|
|
66
|
+
maxRayLength: { type: Types.Float32, default: 30 },
|
|
67
|
+
/**
|
|
68
|
+
* On select commit, treat the pinching hand's ray space as the pointer
|
|
69
|
+
* origin instead of the eyes, so a gaze-initiated drag tracks the hand.
|
|
70
|
+
* @default true
|
|
71
|
+
*/
|
|
72
|
+
pointerTransformFollowsHand: { type: Types.Boolean, default: true },
|
|
73
|
+
/**
|
|
74
|
+
* Emit `[iwsdk][gaze]` console diagnostics explaining why gaze is or isn't
|
|
75
|
+
* tracked, and whether the runtime's gaze ray actually separates from the
|
|
76
|
+
* head ray. Each message fires at most once per state change.
|
|
77
|
+
* @default true
|
|
78
|
+
*/
|
|
79
|
+
logDiagnostics: { type: Types.Boolean, default: true },
|
|
80
|
+
/** Show a developer-only gaze hit reticle. @default false */
|
|
81
|
+
showDebugReticle: { type: Types.Boolean, default: false },
|
|
82
|
+
/** Keep gaze mode active briefly after tracking becomes invalid. @default 5 */
|
|
83
|
+
trackingLossGraceSeconds: { type: Types.Float32, default: 5 },
|
|
84
|
+
}) {
|
|
85
|
+
constructor() {
|
|
86
|
+
super(...arguments);
|
|
87
|
+
/** One-shot latch for {@link GazeSystem.warnMissingFrame}. */
|
|
88
|
+
this.warnedMissingFrame = false;
|
|
89
|
+
}
|
|
90
|
+
init() {
|
|
91
|
+
// Registering this system is the opt-in: until now the pointer existed but
|
|
92
|
+
// never sampled a pose or cast a cone.
|
|
93
|
+
this.input.xr.gazeEnabled = true;
|
|
94
|
+
this.cleanupFuncs.push(() => {
|
|
95
|
+
this.input.xr.gazeEnabled = false;
|
|
96
|
+
});
|
|
97
|
+
this.applyGazeConfig();
|
|
98
|
+
// Re-push on every config change so the editor's live tweaks land without
|
|
99
|
+
// rebuilding the pointer.
|
|
100
|
+
for (const key of [
|
|
101
|
+
'suppressWhenDirectPointerActive',
|
|
102
|
+
'filterMinCutoff',
|
|
103
|
+
'filterBeta',
|
|
104
|
+
'dwellWindowSeconds',
|
|
105
|
+
'coneAngle',
|
|
106
|
+
'maxRayLength',
|
|
107
|
+
'pointerTransformFollowsHand',
|
|
108
|
+
'logDiagnostics',
|
|
109
|
+
'showDebugReticle',
|
|
110
|
+
'trackingLossGraceSeconds',
|
|
111
|
+
]) {
|
|
112
|
+
this.cleanupFuncs.push(this.config[key].subscribe(() => this.applyGazeConfig()));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Push system config onto the shared pointer and its candidate provider.
|
|
117
|
+
*
|
|
118
|
+
* Cone geometry and dwell live on the provider rather than the pointer, and
|
|
119
|
+
* only the default {@link GazeConecaster} understands them — a custom
|
|
120
|
+
* provider installed via `setCandidateProvider` keeps its own tuning.
|
|
121
|
+
*/
|
|
122
|
+
applyGazeConfig() {
|
|
123
|
+
const pointer = this.input.xr.gazePointer;
|
|
124
|
+
pointer.suppressWhenDirectPointerActive =
|
|
125
|
+
this.config.suppressWhenDirectPointerActive.peek();
|
|
126
|
+
pointer.pointerTransformFollowsHand =
|
|
127
|
+
this.config.pointerTransformFollowsHand.peek();
|
|
128
|
+
pointer.diagnosticsEnabled = this.config.logDiagnostics.peek();
|
|
129
|
+
pointer.showDebugReticle = this.config.showDebugReticle.peek();
|
|
130
|
+
pointer.trackingLossGraceSeconds =
|
|
131
|
+
this.config.trackingLossGraceSeconds.peek();
|
|
132
|
+
pointer.filter.minCutoff = this.config.filterMinCutoff.peek();
|
|
133
|
+
pointer.filter.beta = this.config.filterBeta.peek();
|
|
134
|
+
const provider = pointer.provider;
|
|
135
|
+
if (provider instanceof GazeConecaster) {
|
|
136
|
+
// The conecaster works in radians; the config is in degrees.
|
|
137
|
+
provider.coneAngle = (this.config.coneAngle.peek() * Math.PI) / 180;
|
|
138
|
+
provider.coneLength = this.config.maxRayLength.peek();
|
|
139
|
+
provider.dwellWindowSeconds = this.config.dwellWindowSeconds.peek();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
update() {
|
|
143
|
+
const session = this.xrManager.getSession();
|
|
144
|
+
if (!session) {
|
|
145
|
+
this.warnedMissingFrame = false;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
if (!this.xrManager.getFrame() || !this.xrManager.getReferenceSpace()) {
|
|
149
|
+
this.warnMissingFrame();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* There's a session but no frame or reference space, so the gaze pose can't
|
|
154
|
+
* be sampled at all this frame. Normally a one-frame startup blip; if it
|
|
155
|
+
* persists, gaze is unavailable and the developer should know.
|
|
156
|
+
*/
|
|
157
|
+
warnMissingFrame() {
|
|
158
|
+
if (this.warnedMissingFrame || !this.config.logDiagnostics.peek()) {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
this.warnedMissingFrame = true;
|
|
162
|
+
console.warn('[iwsdk][gaze] in an XR session but the renderer has no XRFrame or ' +
|
|
163
|
+
'reference space yet, so XR input cannot be sampled until this resolves.');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export { GazeSystem };
|
|
168
|
+
//# sourceMappingURL=gaze-system.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaze-system.js","sources":["../../src/gaze/gaze-system.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { GazeConecaster } from '@iwsdk/xr-input';\nimport { createSystem, Types } from '../ecs/index.js';\n\n/**\n * GazeSystem — wires the global {@link GazePointer} to ECS interactables.\n *\n * @remarks\n * - Owns configuration and diagnostics only. The pointer itself lives on\n * {@link XRInputManager} (as `input.xr.gazePointer`) so `GrabSystem` can\n * identify the selecting hand; registering this system is what flips\n * `input.xr.gazeEnabled` and makes gaze cost anything at all.\n * - Candidates come from the same ray-target snapshot used by hand rays.\n * - The pointer samples the WebXR gaze target ray itself each frame;\n * `logDiagnostics` explains missing sources and invalid poses.\n * - Selection is committed by either hand's pinch, with per-hand mutual\n * exclusion (the hand that started the pinch owns it until release).\n * - Hover and selection flow through ordinary ray pointer events, so\n * {@link InputSystem} owns the shared `Hovered` / `Pressed` state.\n * - Hand/controller far rays are disabled while gaze is available. Gaze is\n * optionally suppressed when a near touch/grab pointer is active, so direct\n * manipulation wins without an incidental far-ray hit stealing focus.\n *\n * @category Input\n */\nexport class GazeSystem extends createSystem(\n {},\n {\n /**\n * If true, gaze is suppressed whenever a near touch/grab pointer is in\n * HOVER or SELECT. Set false to allow gaze to remain active concurrently.\n * @default true\n */\n suppressWhenDirectPointerActive: { type: Types.Boolean, default: true },\n /**\n * 1€ filter min cutoff (lower = smoother, higher = more responsive).\n * @default 1.5\n */\n filterMinCutoff: { type: Types.Float32, default: 1.5 },\n /**\n * 1€ filter beta (higher = less smoothing during fast saccades).\n * @default 0.05\n */\n filterBeta: { type: Types.Float32, default: 0.05 },\n /**\n * Dwell window in seconds for consensus voting. `0` disables consensus.\n * @default 0.15\n */\n dwellWindowSeconds: { type: Types.Float32, default: 0.15 },\n /**\n * Half-angle of the gaze selection cone, in degrees. Widening it makes\n * small targets easier to acquire at the cost of more ambiguity between\n * neighbours.\n * @default 5\n */\n coneAngle: { type: Types.Float32, default: 5 },\n /** Maximum gaze cone/raycast distance in meters. @default 30 */\n maxRayLength: { type: Types.Float32, default: 30 },\n /**\n * On select commit, treat the pinching hand's ray space as the pointer\n * origin instead of the eyes, so a gaze-initiated drag tracks the hand.\n * @default true\n */\n pointerTransformFollowsHand: { type: Types.Boolean, default: true },\n /**\n * Emit `[iwsdk][gaze]` console diagnostics explaining why gaze is or isn't\n * tracked, and whether the runtime's gaze ray actually separates from the\n * head ray. Each message fires at most once per state change.\n * @default true\n */\n logDiagnostics: { type: Types.Boolean, default: true },\n /** Show a developer-only gaze hit reticle. @default false */\n showDebugReticle: { type: Types.Boolean, default: false },\n /** Keep gaze mode active briefly after tracking becomes invalid. @default 5 */\n trackingLossGraceSeconds: { type: Types.Float32, default: 5 },\n },\n) {\n /** One-shot latch for {@link GazeSystem.warnMissingFrame}. */\n private warnedMissingFrame = false;\n\n init(): void {\n // Registering this system is the opt-in: until now the pointer existed but\n // never sampled a pose or cast a cone.\n this.input.xr.gazeEnabled = true;\n this.cleanupFuncs.push(() => {\n this.input.xr.gazeEnabled = false;\n });\n\n this.applyGazeConfig();\n // Re-push on every config change so the editor's live tweaks land without\n // rebuilding the pointer.\n for (const key of [\n 'suppressWhenDirectPointerActive',\n 'filterMinCutoff',\n 'filterBeta',\n 'dwellWindowSeconds',\n 'coneAngle',\n 'maxRayLength',\n 'pointerTransformFollowsHand',\n 'logDiagnostics',\n 'showDebugReticle',\n 'trackingLossGraceSeconds',\n ] as const) {\n this.cleanupFuncs.push(\n this.config[key].subscribe(() => this.applyGazeConfig()),\n );\n }\n }\n\n /**\n * Push system config onto the shared pointer and its candidate provider.\n *\n * Cone geometry and dwell live on the provider rather than the pointer, and\n * only the default {@link GazeConecaster} understands them — a custom\n * provider installed via `setCandidateProvider` keeps its own tuning.\n */\n private applyGazeConfig(): void {\n const pointer = this.input.xr.gazePointer;\n pointer.suppressWhenDirectPointerActive =\n this.config.suppressWhenDirectPointerActive.peek();\n pointer.pointerTransformFollowsHand =\n this.config.pointerTransformFollowsHand.peek();\n pointer.diagnosticsEnabled = this.config.logDiagnostics.peek();\n pointer.showDebugReticle = this.config.showDebugReticle.peek();\n pointer.trackingLossGraceSeconds =\n this.config.trackingLossGraceSeconds.peek();\n pointer.filter.minCutoff = this.config.filterMinCutoff.peek();\n pointer.filter.beta = this.config.filterBeta.peek();\n\n const provider = pointer.provider;\n if (provider instanceof GazeConecaster) {\n // The conecaster works in radians; the config is in degrees.\n provider.coneAngle = (this.config.coneAngle.peek() * Math.PI) / 180;\n provider.coneLength = this.config.maxRayLength.peek();\n provider.dwellWindowSeconds = this.config.dwellWindowSeconds.peek();\n }\n }\n\n update(): void {\n const session = this.xrManager.getSession();\n if (!session) {\n this.warnedMissingFrame = false;\n return;\n }\n if (!this.xrManager.getFrame() || !this.xrManager.getReferenceSpace()) {\n this.warnMissingFrame();\n }\n }\n\n /**\n * There's a session but no frame or reference space, so the gaze pose can't\n * be sampled at all this frame. Normally a one-frame startup blip; if it\n * persists, gaze is unavailable and the developer should know.\n */\n private warnMissingFrame(): void {\n if (this.warnedMissingFrame || !this.config.logDiagnostics.peek()) {\n return;\n }\n this.warnedMissingFrame = true;\n console.warn(\n '[iwsdk][gaze] in an XR session but the renderer has no XRFrame or ' +\n 'reference space yet, so XR input cannot be sampled until this resolves.',\n );\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
export * from './gaze-system.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gaze/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,kBAAkB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distance-grabbable.js","sources":["../../src/grab/distance-grabbable.ts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"distance-grabbable.js","sources":["../../src/grab/distance-grabbable.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { Types, createComponent } from '../ecs/component.js';\nimport { MovementMode } from './handles.js';\n\n/**\n * Component for enabling distance‑based object grabbing and manipulation.\n *\n * @remarks\n * - Allows users to grab and manipulate objects from a distance through ray casting.\n * - Supports three movement modes: MoveTowardsTarget, MoveAtSource, and RotateAtSource.\n * - **MoveTowardsTarget**: Object smoothly moves toward the input source that's grabbing.\n * - **MoveAtSource**: Object moves relative to hand movement while maintaining distance.\n * - **RotateAtSource**: Object rotates in place without translation or scaling.\n * - Optional `returnToOrigin` makes objects snap back to their original position when released.\n * - Supports rotation, translation, and scaling with per‑axis constraints.\n * - Configure target position and rotation offsets relative to the input source for MoveTowardsTarget mode.\n * - Works with the {@link GrabSystem} to create specialized distance grab handles.\n * - Grab components are mutually exclusive per entity. Choose exactly one of\n * {@link OneHandGrabbable}, {@link TwoHandsGrabbable}, or\n * {@link DistanceGrabbable}; {@link GrabSystem} creates only one handle and\n * ignores additional grab components. Do not rely on which component wins\n * when multiple modes are present.\n * - Perfect for telekinetic‑style interactions and remote object manipulation.\n *\n * @example Basic distance grabbable object\n * ```ts\n * entity.addComponent(DistanceGrabbable, {\n * movementMode: MovementMode.MoveTowardsTarget,\n * })\n * ```\n *\n * @example Telekinetic manipulation that returns to origin\n * ```ts\n * entity.addComponent(DistanceGrabbable, {\n * rotate: true,\n * translate: true,\n * scale: false,\n * movementMode: MovementMode.MoveAtSource,\n * returnToOrigin: true\n * })\n * ```\n *\n * @example Rotation‑only distance interaction\n * ```ts\n * entity.addComponent(DistanceGrabbable, {\n * movementMode: MovementMode.RotateAtSource,\n * })\n * ```\n *\n * @example Distance grabbable with offset (object stays 0.3m in front of controller)\n * ```ts\n * entity.addComponent(DistanceGrabbable, {\n * movementMode: MovementMode.MoveTowardsTarget,\n * targetPositionOffset: [0, 0, -0.3], // 0.3m forward in controller space\n * targetQuaternionOffset: [0, 0, 0, 1], // no rotation offset\n * })\n * ```\n *\n * @category Grab\n * @see {@link GrabSystem}\n * @see {@link OneHandGrabbable}\n * @see {@link TwoHandsGrabbable}\n * @see {@link MovementMode}\n */\nexport const DistanceGrabbable = createComponent(\n 'DistanceGrabbable',\n {\n /** A boolean value to set whether rotating the object is allowed. */\n rotate: { type: Types.Boolean, default: true },\n /** An optional vector to define the maximum angle of the allowed rotation in [x, y, z] axes. */\n rotateMax: {\n type: Types.Vec3,\n default: [Infinity, Infinity, Infinity],\n },\n /** An optional vector to define the minimum angle of the allowed rotation in [x, y, z] axes. */\n rotateMin: {\n type: Types.Vec3,\n default: [-Infinity, -Infinity, -Infinity],\n },\n /** A boolean value to set whether moving the object's position is allowed. */\n translate: { type: Types.Boolean, default: true },\n /** An optional vector to define the maximum allowed position in [x, y, z] axes. */\n translateMax: {\n type: Types.Vec3,\n default: [Infinity, Infinity, Infinity],\n },\n /** An optional vector to define the minimum allowed position in [x, y, z] axes. */\n translateMin: {\n type: Types.Vec3,\n default: [-Infinity, -Infinity, -Infinity],\n },\n /** A boolean value to set whether scaling the object up and down is allowed. */\n scale: { type: Types.Boolean, default: true },\n /** An optional vector to define the maximum allowed scaling in [x, y, z] axes. */\n scaleMax: {\n type: Types.Vec3,\n default: [Infinity, Infinity, Infinity],\n },\n /** An optional vector to define the minimum allowed scaling in [x, y, z] axes. */\n scaleMin: {\n type: Types.Vec3,\n default: [-Infinity, -Infinity, -Infinity],\n },\n /** The movement mode of the grabbable. More details in {@link MovementMode}. */\n movementMode: {\n type: Types.Enum,\n enum: MovementMode,\n default: MovementMode.MoveTowardsTarget,\n },\n /** A boolean value to set whether the object snap back to its original position and rotation. */\n returnToOrigin: { type: Types.Boolean, default: false },\n /** A boolean value to set whether the object will be detached from its parent and attach to the scene/Level root when grabbed. */\n detachOnGrab: { type: Types.Boolean, default: false },\n /** Object movement and rotation speed factor for the MoveTowardsTarget movement mode with a scale from 0 to 1. */\n moveSpeedFactor: { type: Types.Float32, default: 0.1 },\n /** Target position offset relative to the input source for MoveTowardsTarget mode in [x, y, z]. */\n targetPositionOffset: {\n type: Types.Vec3,\n default: [0, 0, 0],\n },\n /** Target rotation offset as a quaternion relative to the input source for MoveTowardsTarget mode in [x, y, z, w]. */\n targetQuaternionOffset: {\n type: Types.Vec4,\n default: [0, 0, 0, 1],\n },\n },\n 'Component for distance-based object grabbing and manipulation',\n);\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAKH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DG;AACI,MAAM,iBAAiB,GAAG,eAAe,CAC9C,mBAAmB,EACnB;;IAEE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;;AAE9C,IAAA,SAAS,EAAE;QACT,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;AACxC,KAAA;;AAED,IAAA,SAAS,EAAE;QACT,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;AAC3C,KAAA;;IAED,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;;AAEjD,IAAA,YAAY,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;AACxC,KAAA;;AAED,IAAA,YAAY,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;AAC3C,KAAA;;IAED,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE;;AAE7C,IAAA,QAAQ,EAAE;QACR,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;AACxC,KAAA;;AAED,IAAA,QAAQ,EAAE;QACR,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;AAC3C,KAAA;;AAED,IAAA,YAAY,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,YAAY,CAAC,iBAAiB;AACxC,KAAA;;IAED,cAAc,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;;IAEvD,YAAY,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;;IAErD,eAAe,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE;;AAEtD,IAAA,oBAAoB,EAAE;QACpB,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACnB,KAAA;;AAED,IAAA,sBAAsB,EAAE;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACtB,KAAA;CACF,EACD,+DAA+D;;;;"}
|
|
@@ -8,8 +8,8 @@ import { HandleStore } from '@pmndrs/handle';
|
|
|
8
8
|
/**
|
|
9
9
|
* Pure helpers backing {@link GrabSystem.forceRelease} and
|
|
10
10
|
* {@link GrabSystem.getHolderHand}. Kept side-effect-free and dependency-light
|
|
11
|
-
* so they can be unit-tested without spinning up the full ECS / xr-input
|
|
12
|
-
*
|
|
11
|
+
* so they can be unit-tested without spinning up the full ECS / xr-input import
|
|
12
|
+
* chain.
|
|
13
13
|
*
|
|
14
14
|
* Not part of the public package API surface — `grab-system.ts` is the only
|
|
15
15
|
* intended caller.
|
|
@@ -31,9 +31,10 @@ export declare function cancelGrabHandle(handle: HandleStore<unknown> | undefine
|
|
|
31
31
|
* object). Passing both keeps `getHolderHand` correct across both grab
|
|
32
32
|
* styles without leaking pointer-kind selection into callers.
|
|
33
33
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* A capture from the gaze ray is attributed to the hand that initiated its
|
|
35
|
+
* current select. Returns `'left'` / `'right'` for single-hand grabs, `'left'`
|
|
36
|
+
* for two-hand grabs (deterministic), and `null` when the entity has no active
|
|
37
|
+
* grabs or none of the candidate IDs match.
|
|
37
38
|
*/
|
|
38
|
-
export declare function findHolderHand(handle: HandleStore<unknown> | undefined, leftPointerIds: readonly number[], rightPointerIds: readonly number[]): 'left' | 'right' | null;
|
|
39
|
+
export declare function findHolderHand(handle: HandleStore<unknown> | undefined, leftPointerIds: readonly number[], rightPointerIds: readonly number[], gazePointerId?: number, gazeHand?: 'left' | 'right' | null): 'left' | 'right' | null;
|
|
39
40
|
//# sourceMappingURL=grab-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grab-helpers.d.ts","sourceRoot":"","sources":["../../src/grab/grab-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS,GACvC,IAAI,CAON;AAED
|
|
1
|
+
{"version":3,"file":"grab-helpers.d.ts","sourceRoot":"","sources":["../../src/grab/grab-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C;;;;;;;;GAQG;AAEH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS,GACvC,IAAI,CAON;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS,EACxC,cAAc,EAAE,SAAS,MAAM,EAAE,EACjC,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,aAAa,CAAC,EAAE,MAAM,EACtB,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GACjC,MAAM,GAAG,OAAO,GAAG,IAAI,CAezB"}
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
/**
|
|
8
8
|
* Pure helpers backing {@link GrabSystem.forceRelease} and
|
|
9
9
|
* {@link GrabSystem.getHolderHand}. Kept side-effect-free and dependency-light
|
|
10
|
-
* so they can be unit-tested without spinning up the full ECS / xr-input
|
|
11
|
-
*
|
|
10
|
+
* so they can be unit-tested without spinning up the full ECS / xr-input import
|
|
11
|
+
* chain.
|
|
12
12
|
*
|
|
13
13
|
* Not part of the public package API surface — `grab-system.ts` is the only
|
|
14
14
|
* intended caller.
|
|
@@ -38,11 +38,12 @@ function cancelGrabHandle(handle) {
|
|
|
38
38
|
* object). Passing both keeps `getHolderHand` correct across both grab
|
|
39
39
|
* styles without leaking pointer-kind selection into callers.
|
|
40
40
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* A capture from the gaze ray is attributed to the hand that initiated its
|
|
42
|
+
* current select. Returns `'left'` / `'right'` for single-hand grabs, `'left'`
|
|
43
|
+
* for two-hand grabs (deterministic), and `null` when the entity has no active
|
|
44
|
+
* grabs or none of the candidate IDs match.
|
|
44
45
|
*/
|
|
45
|
-
function findHolderHand(handle, leftPointerIds, rightPointerIds) {
|
|
46
|
+
function findHolderHand(handle, leftPointerIds, rightPointerIds, gazePointerId, gazeHand) {
|
|
46
47
|
if (!handle || handle.inputState.size === 0) {
|
|
47
48
|
return null;
|
|
48
49
|
}
|
|
@@ -52,7 +53,11 @@ function findHolderHand(handle, leftPointerIds, rightPointerIds) {
|
|
|
52
53
|
if (rightPointerIds.some((id) => handle.inputState.has(id))) {
|
|
53
54
|
return 'right';
|
|
54
55
|
}
|
|
55
|
-
return null
|
|
56
|
+
return gazeHand != null && gazePointerId != null
|
|
57
|
+
? handle.inputState.has(gazePointerId)
|
|
58
|
+
? gazeHand
|
|
59
|
+
: null
|
|
60
|
+
: null;
|
|
56
61
|
}
|
|
57
62
|
|
|
58
63
|
export { cancelGrabHandle, findHolderHand };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grab-helpers.js","sources":["../../src/grab/grab-helpers.ts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;AAKG;AAIH;;;;;;;;AAQG;AAEH;;;;;AAKG;AACG,SAAU,gBAAgB,CAC9B,MAAwC,EAAA;IAExC,IAAI,CAAC,MAAM,EAAE;QACX;IACF;AACA,IAAA,IAAI;QACF,MAAM,CAAC,MAAM,EAAE;IACjB;IAAE,OAAA,EAAA,EAAM,EAAC;AACX;AAEA
|
|
1
|
+
{"version":3,"file":"grab-helpers.js","sources":["../../src/grab/grab-helpers.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleStore } from '@pmndrs/handle';\n\n/**\n * Pure helpers backing {@link GrabSystem.forceRelease} and\n * {@link GrabSystem.getHolderHand}. Kept side-effect-free and dependency-light\n * so they can be unit-tested without spinning up the full ECS / xr-input import\n * chain.\n *\n * Not part of the public package API surface — `grab-system.ts` is the only\n * intended caller.\n */\n\n/**\n * Cancel every active pointer on a grab `handle`. Safe to call when `handle`\n * is `undefined`, when the entity is not currently held, or when the\n * underlying `cancel()` throws (errors are swallowed to match the cleanup\n * semantics already used inside `GrabSystem` on Handle-component disqualify).\n */\nexport function cancelGrabHandle(\n handle: HandleStore<unknown> | undefined,\n): void {\n if (!handle) {\n return;\n }\n try {\n handle.cancel();\n } catch {}\n}\n\n/**\n * Determine which controller is currently holding the entity backing\n * `handle`, given the candidate pointer IDs per hand.\n *\n * Each hand contributes the IDs of every pointer kind that can capture a\n * grab handle today — near grabs use the `grab` sub-pointer, distance grabs\n * use the `ray` sub-pointer (per `pointerEventsType` on the handle's\n * object). Passing both keeps `getHolderHand` correct across both grab\n * styles without leaking pointer-kind selection into callers.\n *\n * A capture from the gaze ray is attributed to the hand that initiated its\n * current select. Returns `'left'` / `'right'` for single-hand grabs, `'left'`\n * for two-hand grabs (deterministic), and `null` when the entity has no active\n * grabs or none of the candidate IDs match.\n */\nexport function findHolderHand(\n handle: HandleStore<unknown> | undefined,\n leftPointerIds: readonly number[],\n rightPointerIds: readonly number[],\n gazePointerId?: number,\n gazeHand?: 'left' | 'right' | null,\n): 'left' | 'right' | null {\n if (!handle || handle.inputState.size === 0) {\n return null;\n }\n if (leftPointerIds.some((id) => handle.inputState.has(id))) {\n return 'left';\n }\n if (rightPointerIds.some((id) => handle.inputState.has(id))) {\n return 'right';\n }\n return gazeHand != null && gazePointerId != null\n ? handle.inputState.has(gazePointerId)\n ? gazeHand\n : null\n : null;\n}\n"],"names":[],"mappings":"AAAA;;;;;AAKG;AAIH;;;;;;;;AAQG;AAEH;;;;;AAKG;AACG,SAAU,gBAAgB,CAC9B,MAAwC,EAAA;IAExC,IAAI,CAAC,MAAM,EAAE;QACX;IACF;AACA,IAAA,IAAI;QACF,MAAM,CAAC,MAAM,EAAE;IACjB;IAAE,OAAA,EAAA,EAAM,EAAC;AACX;AAEA;;;;;;;;;;;;;;AAcG;AACG,SAAU,cAAc,CAC5B,MAAwC,EACxC,cAAiC,EACjC,eAAkC,EAClC,aAAsB,EACtB,QAAkC,EAAA;IAElC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE;AAC3C,QAAA,OAAO,IAAI;IACb;AACA,IAAA,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE;AAC1D,QAAA,OAAO,MAAM;IACf;AACA,IAAA,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE;AAC3D,QAAA,OAAO,OAAO;IAChB;AACA,IAAA,OAAO,QAAQ,IAAI,IAAI,IAAI,aAAa,IAAI;UACxC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa;AACnC,cAAE;AACF,cAAE;UACF,IAAI;AACV;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grab-system.d.ts","sourceRoot":"","sources":["../../src/grab/grab-system.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;;IAmEtC;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAJH;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtDP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,UAAW,SAAQ,eAuB/B;IACC,IAAI;IAmDJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IA4CzC;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMlC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"grab-system.d.ts","sourceRoot":"","sources":["../../src/grab/grab-system.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;;IAmEtC;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAJH;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAtDP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBAAa,UAAW,SAAQ,eAuB/B;IACC,IAAI;IAmDJ,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IA4CzC;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAMlC;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI;IAiBtD,OAAO,CAAC,uBAAuB;IAqC/B,OAAO,CAAC,wBAAwB;IAoDhC,OAAO,CAAC,wBAAwB;CA0FjC"}
|
package/dist/grab/grab-system.js
CHANGED
|
@@ -210,12 +210,13 @@ class GrabSystem extends createSystem({
|
|
|
210
210
|
getHolderHand(entity) {
|
|
211
211
|
const left = this.input.xr.multiPointers.left;
|
|
212
212
|
const right = this.input.xr.multiPointers.right;
|
|
213
|
+
const gaze = this.input.xr.gazePointer;
|
|
213
214
|
return findHolderHand(Handle.data.instance[entity.index],
|
|
214
215
|
// Near grabs capture via the `grab` sub-pointer; distance grabs capture
|
|
215
216
|
// via `ray` (see `initializeDistanceHandle` setting
|
|
216
217
|
// `pointerEventsType = { deny: 'grab' }`). Check both per hand so
|
|
217
218
|
// distance-held entities don't silently report `null`.
|
|
218
|
-
[left.getPointer('grab').id, left.getPointer('ray').id], [right.getPointer('grab').id, right.getPointer('ray').id]);
|
|
219
|
+
[left.getPointer('grab').id, left.getPointer('ray').id], [right.getPointer('grab').id, right.getPointer('ray').id], gaze.pointer.id, gaze.getHeldByHand());
|
|
219
220
|
}
|
|
220
221
|
initializeOneHandHandle(entity) {
|
|
221
222
|
if (entity.hasComponent(Handle)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grab-system.js","sources":["../../src/grab/grab-system.ts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"grab-system.js","sources":["../../src/grab/grab-system.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleStore } from '@pmndrs/handle';\nimport { PointerEventsMap } from '@pmndrs/pointer-events';\nimport { Types } from '../ecs/component.js';\nimport { Entity } from '../ecs/entity.js';\nimport { createSystem } from '../ecs/system.js';\nimport { LevelTag } from '../level/index.js';\nimport {\n Object3D,\n Object3DEventMap,\n Vector3,\n Quaternion,\n} from '../runtime/index.js';\nimport { DistanceGrabbable } from './distance-grabbable.js';\nimport { cancelGrabHandle, findHolderHand } from './grab-helpers.js';\nimport { warnIfNoRaycastableMesh } from './grab-warnings.js';\nimport { Grabbed } from './grabbed.js';\nimport { DistanceGrabHandle, MovementMode, Handle } from './handles.js';\nimport { OneHandGrabbable } from './one-hand-grabbable.js';\nimport { TwoHandsGrabbable } from './two-hands-grabbable.js';\n\n/**\n * Manages interactive object grabbing and manipulation for VR/AR experiences.\n *\n * @remarks\n * - Uses the `@pmndrs/handle` library for precise multitouch manipulation.\n * - Automatically creates handle instances for entities with grabbable components.\n * - Supports three types of grab interactions: one‑hand, two‑hand, and distance grabbing.\n * - Automatically cleans up handle instances when grabbable components are removed.\n *\n * @example Basic grab system setup\n * ```ts\n * // Add to your world to enable grab interactions\n * world.addSystem(GrabSystem)\n *\n * // Create a grabbable box\n * const box = world.createEntity()\n * box.addComponent(OneHandGrabbable, {})\n * ```\n *\n * @example Two‑handed manipulation\n * ```ts\n * // Create an object that can be scaled with two hands\n * const sculpture = world.createEntity()\n * sculpture.addComponent(TwoHandsGrabbable, {\n * scaleMin: [0.5, 0.5, 0.5],\n * scaleMax: [3, 3, 3]\n * })\n * ```\n *\n * @category Grab\n * @see {@link OneHandGrabbable}\n * @see {@link TwoHandsGrabbable}\n * @see {@link DistanceGrabbable}\n */\nexport class GrabSystem extends createSystem(\n {\n oneHandGrabbables: {\n required: [OneHandGrabbable],\n },\n twoHandsGrabbables: {\n required: [TwoHandsGrabbable],\n },\n distanceGrabbables: {\n required: [DistanceGrabbable],\n },\n handles: {\n required: [Handle],\n },\n },\n {\n /**\n * Controls whether hand pinch gestures are forwarded as squeeze events for grab interactions.\n * Set to `false` to disable pinch-to-grab and require the physical squeeze button instead.\n * @default false\n */\n useHandPinchForGrab: { type: Types.Boolean, default: false },\n },\n) {\n init() {\n // Ensure Handle component is registered in the world before queries rely on it\n if (!Handle.bitmask) {\n this.world.registerComponent(Handle);\n }\n if (!Grabbed.bitmask) {\n this.world.registerComponent(Grabbed);\n }\n\n // Reactive handle creation per grabbable type\n this.queries.oneHandGrabbables.subscribe('qualify', (entity) => {\n this.initializeOneHandHandle(entity);\n });\n this.queries.twoHandsGrabbables.subscribe('qualify', (entity) => {\n this.initializeTwoHandsHandle(entity);\n });\n this.queries.distanceGrabbables.subscribe('qualify', (entity) => {\n this.initializeDistanceHandle(entity);\n });\n\n // Unified cleanup for any handle\n this.queries.handles.subscribe('disqualify', (entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n try {\n h.cancel();\n } catch {}\n }\n if (entity.object3D) {\n entity.object3D.pointerEventsType = 'all';\n }\n });\n\n // Initial pass for already-eligible entities (qualify doesn't fire retroactively)\n this.queries.oneHandGrabbables.entities.forEach((e) =>\n this.initializeOneHandHandle(e),\n );\n this.queries.twoHandsGrabbables.entities.forEach((e) =>\n this.initializeTwoHandsHandle(e),\n );\n this.queries.distanceGrabbables.entities.forEach((e) =>\n this.initializeDistanceHandle(e),\n );\n\n // Enable grab sub-pointer per hand when GrabSystem is active\n this.input.xr.multiPointers.left.toggleSubPointer('grab', true);\n this.input.xr.multiPointers.right.toggleSubPointer('grab', true);\n }\n\n update(delta: number, time: number): void {\n // Forward hand pinch events to squeeze for grab interactions\n // Only forward if the system-level useHandPinchForGrab flag is enabled\n if (this.config.useHandPinchForGrab) {\n (['left', 'right'] as const).forEach((handedness) => {\n if (this.input.xr.isPrimary('hand', handedness)) {\n const timeStamp = time * 1000;\n if (this.input.xr.gamepads[handedness]?.getSelectStart()) {\n this.input.xr.multiPointers[handedness].routeDown(\n 'squeeze',\n 'grab',\n {\n timeStamp,\n },\n );\n }\n if (this.input.xr.gamepads[handedness]?.getSelectEnd()) {\n this.input.xr.multiPointers[handedness].routeUp('squeeze', 'grab', {\n timeStamp,\n });\n }\n }\n });\n }\n\n // Unified handle updates\n this.queries.handles.entities.forEach((entity) => {\n const h = Handle.data.instance[entity.index] as\n | HandleStore<unknown>\n | undefined;\n if (h) {\n h.update(delta);\n // Manage Grabbed tag based on active grab state\n if (h.inputState.size > 0) {\n if (!entity.hasComponent(Grabbed)) {\n entity.addComponent(Grabbed);\n }\n } else if (entity.hasComponent(Grabbed)) {\n entity.removeComponent(Grabbed);\n }\n }\n });\n }\n\n /**\n * Force-release `entity` if it is currently being held.\n *\n * @remarks\n * Cancels every active pointer on the entity's grab handle, which causes\n * `update()` on the next frame to remove the {@link Grabbed} tag. Safe to\n * call when the entity is not held or has never been grabbable — a no-op\n * in those cases.\n *\n * Useful for game-state changes that need to drop held items: level resets,\n * weapon swaps, death/respawn, cinematics, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * grab.forceRelease(weaponEntity);\n * ```\n */\n forceRelease(entity: Entity): void {\n cancelGrabHandle(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n );\n }\n\n /**\n * Identify which controller is currently holding `entity`.\n *\n * @returns `'left'` or `'right'` when a single hand holds the entity,\n * `null` when the entity is not held (or has no grab handle).\n *\n * @remarks\n * For two-handed grabs (both controllers active on the same entity), the\n * left hand is reported. Callers needing per-hand state for two-handed\n * interactions should track grab/release events themselves rather than\n * polling this method.\n *\n * Useful for hand-aware behaviors: recoil/animation that should react to\n * the holding controller, hand-specific UI prompts, etc.\n *\n * @example\n * ```ts\n * const grab = world.getSystem(GrabSystem);\n * const hand = grab.getHolderHand(gunEntity);\n * if (hand) {\n * playRecoilOn(hand);\n * }\n * ```\n */\n getHolderHand(entity: Entity): 'left' | 'right' | null {\n const left = this.input.xr.multiPointers.left;\n const right = this.input.xr.multiPointers.right;\n const gaze = this.input.xr.gazePointer;\n return findHolderHand(\n Handle.data.instance[entity.index] as HandleStore<unknown> | undefined,\n // Near grabs capture via the `grab` sub-pointer; distance grabs capture\n // via `ray` (see `initializeDistanceHandle` setting\n // `pointerEventsType = { deny: 'grab' }`). Check both per hand so\n // distance-held entities don't silently report `null`.\n [left.getPointer('grab').id, left.getPointer('ray').id],\n [right.getPointer('grab').id, right.getPointer('ray').id],\n gaze.pointer.id,\n gaze.getHeldByHand(),\n );\n }\n\n private initializeOneHandHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'OneHandGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(OneHandGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(OneHandGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(OneHandGrabbable, 'translateMax');\n const translateMin = entity.getVectorView(OneHandGrabbable, 'translateMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(OneHandGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(OneHandGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: false,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeTwoHandsHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'TwoHandsGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rotateMax = entity.getVectorView(TwoHandsGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(TwoHandsGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n TwoHandsGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(TwoHandsGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(TwoHandsGrabbable, 'scaleMin');\n const handle = new HandleStore(obj, () => ({\n rotate: entity.getValue(TwoHandsGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate: entity.getValue(TwoHandsGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale: entity.getValue(TwoHandsGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n multitouch: true,\n }));\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'ray' };\n entity.addComponent(Handle, { instance: handle });\n }\n\n private initializeDistanceHandle(entity: Entity) {\n if (entity.hasComponent(Handle)) {\n return;\n }\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n warnIfNoRaycastableMesh(entity, 'DistanceGrabbable');\n const obj = object as Object3D<PointerEventsMap & Object3DEventMap>;\n const rootEntity = entity.hasComponent(LevelTag)\n ? this.world.activeLevel.value\n : this.world.sceneEntity;\n const rotateMax = entity.getVectorView(DistanceGrabbable, 'rotateMax');\n const rotateMin = entity.getVectorView(DistanceGrabbable, 'rotateMin');\n const translateMax = entity.getVectorView(\n DistanceGrabbable,\n 'translateMax',\n );\n const translateMin = entity.getVectorView(\n DistanceGrabbable,\n 'translateMin',\n );\n const scaleMax = entity.getVectorView(DistanceGrabbable, 'scaleMax');\n const scaleMin = entity.getVectorView(DistanceGrabbable, 'scaleMin');\n const movementMode = entity.getValue(DistanceGrabbable, 'movementMode');\n const returnToOrigin = Boolean(\n entity.getValue(DistanceGrabbable, 'returnToOrigin'),\n );\n const detachOnGrab = Boolean(\n entity.getValue(DistanceGrabbable, 'detachOnGrab'),\n );\n const targetPosOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetPositionOffset',\n );\n const targetQuatOffset = entity.getVectorView(\n DistanceGrabbable,\n 'targetQuaternionOffset',\n );\n const opts = () => ({\n rotate: entity.getValue(DistanceGrabbable, 'rotate')\n ? {\n x: [rotateMin[0], rotateMax[0]] as [number, number],\n y: [rotateMin[1], rotateMax[1]] as [number, number],\n z: [rotateMin[2], rotateMax[2]] as [number, number],\n }\n : false,\n translate:\n movementMode === MovementMode.RotateAtSource\n ? ('as-rotate' as const)\n : entity.getValue(DistanceGrabbable, 'translate')\n ? {\n x: [translateMin[0], translateMax[0]] as [number, number],\n y: [translateMin[1], translateMax[1]] as [number, number],\n z: [translateMin[2], translateMax[2]] as [number, number],\n }\n : false,\n scale:\n movementMode === MovementMode.RotateAtSource\n ? false\n : entity.getValue(DistanceGrabbable, 'scale')\n ? {\n x: [scaleMin[0], scaleMax[0]] as [number, number],\n y: [scaleMin[1], scaleMax[1]] as [number, number],\n z: [scaleMin[2], scaleMax[2]] as [number, number],\n }\n : false,\n projectRays: false,\n });\n const handle = new DistanceGrabHandle(\n obj,\n rootEntity.object3D!,\n opts,\n movementMode!,\n returnToOrigin,\n entity.getValue(DistanceGrabbable, 'moveSpeedFactor') ?? 0.1,\n new Vector3(targetPosOffset[0], targetPosOffset[1], targetPosOffset[2]),\n new Quaternion(\n targetQuatOffset[0],\n targetQuatOffset[1],\n targetQuatOffset[2],\n targetQuatOffset[3],\n ),\n detachOnGrab,\n );\n handle.bind(obj);\n obj.pointerEventsType = { deny: 'grab' };\n entity.addComponent(Handle, { instance: handle });\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grab-warnings.js","sources":["../../src/grab/grab-warnings.ts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"grab-warnings.js","sources":["../../src/grab/grab-warnings.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport type { Entity } from '../ecs/entity.js';\nimport { Mesh, Object3D } from '../runtime/index.js';\n\ntype GrabComponentName =\n | 'DistanceGrabbable'\n | 'OneHandGrabbable'\n | 'TwoHandsGrabbable';\n\nlet warnedNoRaycastableMesh = new WeakMap<Object3D, Set<GrabComponentName>>();\n\nfunction shouldEmitDevWarning(): boolean {\n return (import.meta as any).env?.DEV !== false;\n}\n\nexport function hasRaycastableMesh(object: Object3D): boolean {\n let found = false;\n\n object.traverse((child) => {\n if (found) {\n return;\n }\n\n const mesh = child as Mesh;\n found =\n mesh.isMesh === true &&\n Boolean(mesh.geometry) &&\n typeof mesh.raycast === 'function';\n });\n\n return found;\n}\n\nexport function warnIfNoRaycastableMesh(\n entity: Pick<Entity, 'index' | 'object3D'>,\n componentName: GrabComponentName,\n): void {\n const object = entity.object3D;\n if (!(object instanceof Object3D)) {\n return;\n }\n\n if (!shouldEmitDevWarning() || hasRaycastableMesh(object)) {\n return;\n }\n\n let warnedComponents = warnedNoRaycastableMesh.get(object);\n if (!warnedComponents) {\n warnedComponents = new Set();\n warnedNoRaycastableMesh.set(object, warnedComponents);\n }\n\n if (warnedComponents.has(componentName)) {\n return;\n }\n\n warnedComponents.add(componentName);\n\n const entityLabel = object.name\n ? `\"${object.name}\" (index ${entity.index})`\n : `#${entity.index}`;\n\n console.warn(\n `[IWSDK] Entity ${entityLabel} has ${componentName} but no raycastable mesh in its Object3D subtree. Grab will not work. Attach a Mesh as a child or to the entity's root Object3D.`,\n );\n}\n\nexport function resetGrabWarningStateForTests(): void {\n warnedNoRaycastableMesh = new WeakMap();\n}\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAUH,IAAI,uBAAuB,GAAG,IAAI,OAAO,EAAoC;AAE7E,SAAS,oBAAoB,GAAA;;IAC3B,OAAO,CAAA,CAAA,EAAA,GAAC,MAAM,CAAC,IAAY,CAAC,GAAG,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,MAAA,GAAA,EAAA,CAAE,GAAG,MAAK,KAAK;AAChD;AAEM,SAAU,kBAAkB,CAAC,MAAgB,EAAA;IACjD,IAAI,KAAK,GAAG,KAAK;AAEjB,IAAA,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,KAAI;QACxB,IAAI,KAAK,EAAE;YACT;QACF;QAEA,MAAM,IAAI,GAAG,KAAa;QAC1B,KAAK;YACH,IAAI,CAAC,MAAM,KAAK,IAAI;AACpB,gBAAA,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtB,gBAAA,OAAO,IAAI,CAAC,OAAO,KAAK,UAAU;AACtC,IAAA,CAAC,CAAC;AAEF,IAAA,OAAO,KAAK;AACd;AAEM,SAAU,uBAAuB,CACrC,MAA0C,EAC1C,aAAgC,EAAA;AAEhC,IAAA,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ;AAC9B,IAAA,IAAI,EAAE,MAAM,YAAY,QAAQ,CAAC,EAAE;QACjC;IACF;IAEA,IAAI,CAAC,oBAAoB,EAAE,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE;QACzD;IACF;IAEA,IAAI,gBAAgB,GAAG,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC;IAC1D,IAAI,CAAC,gBAAgB,EAAE;AACrB,QAAA,gBAAgB,GAAG,IAAI,GAAG,EAAE;AAC5B,QAAA,uBAAuB,CAAC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IACvD;AAEA,IAAA,IAAI,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE;QACvC;IACF;AAEA,IAAA,gBAAgB,CAAC,GAAG,CAAC,aAAa,CAAC;AAEnC,IAAA,MAAM,WAAW,GAAG,MAAM,CAAC;UACvB,IAAI,MAAM,CAAC,IAAI,CAAA,SAAA,EAAY,MAAM,CAAC,KAAK,CAAA,CAAA;AACzC,UAAE,CAAA,CAAA,EAAI,MAAM,CAAC,KAAK,EAAE;IAEtB,OAAO,CAAC,IAAI,CACV,CAAA,eAAA,EAAkB,WAAW,CAAA,KAAA,EAAQ,aAAa,CAAA,gIAAA,CAAkI,CACrL;AACH;;;;"}
|
package/dist/grab/grabbed.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grabbed.js","sources":["../../src/grab/grabbed.ts"],"sourcesContent":[
|
|
1
|
+
{"version":3,"file":"grabbed.js","sources":["../../src/grab/grabbed.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { createComponent } from '../ecs/component.js';\n/**\n * Transient state tag indicating an entity is currently being grabbed.\n *\n * @remarks\n * - Managed by {@link GrabSystem}; do not add/remove this component manually.\n * - Added when a grab handle captures one or more pointers.\n * - Removed when all pointers are released and the grab ends.\n * - Often used to gate grab-state-specific logic (e.g. physics kinematic override).\n * - Works with {@link OneHandGrabbable}, {@link TwoHandsGrabbable}, and {@link DistanceGrabbable} entities.\n *\n * @category Grab\n * @hideineditor\n */\nexport const Grabbed = createComponent(\n 'Grabbed',\n {},\n 'A tag added by GrabSystem while the entity is actively grabbed.',\n);\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAGH;;;;;;;;;;;;AAYG;AACI,MAAM,OAAO,GAAG,eAAe,CACpC,SAAS,EACT,EAAE,EACF,iEAAiE;;;;"}
|
package/dist/grab/handles.d.ts
CHANGED
|
@@ -55,7 +55,16 @@ export declare class DistanceGrabHandle<T> extends HandleStore<T> {
|
|
|
55
55
|
constructor(target_: Object3D | {
|
|
56
56
|
current?: Object3D | null;
|
|
57
57
|
}, sceneRoot_: Object3D, getOptions: (() => HandleOptions<T>) | undefined, movementMode: string, returnToOrigin: boolean, moveSpeedFactor: number | undefined, targetPosOffset: Vector3 | undefined, targetQuatOffset: Quaternion | undefined, detachOnGrab: boolean);
|
|
58
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Bind the handle and treat pointer cancellation as an interrupted release.
|
|
60
|
+
*
|
|
61
|
+
* Older @pmndrs/handle releases only listen for pointerup. Far-ray
|
|
62
|
+
* suppression correctly emits pointercancel, so bridge that event to the
|
|
63
|
+
* handle's pointer-up path. This releases only the cancelled pointer and is
|
|
64
|
+
* harmless if a newer dependency also handles pointercancel natively.
|
|
65
|
+
*/
|
|
66
|
+
bind(handle: Object3D): () => void;
|
|
67
|
+
update(delta: number): void;
|
|
59
68
|
protected apply(target: Object3D): T;
|
|
60
69
|
}
|
|
61
70
|
//# sourceMappingURL=handles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/grab/handles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"handles.d.ts","sourceRoot":"","sources":["../../src/grab/handles.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAK5D,OAAO,EAAE,KAAK,EAAmB,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAEL,QAAQ,EAER,UAAU,EACV,OAAO,EACR,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,MAAM;;;;;EAMlB,CAAC;AAEF,iEAAiE;AACjE,eAAO,MAAM,YAAY;IACvB,oFAAoF;;IAEpF,qEAAqE;;IAErE,qFAAqF;;IAErF,8DAA8D;;CAE/D,CAAC;AAEF,qBAAa,kBAAkB,CAAC,CAAC,CAAE,SAAQ,WAAW,CAAC,CAAC,CAAC;IAmBrD,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE;IAC1D,QAAQ,CAAC,UAAU,EAAE,QAAQ;aACb,UAAU,EAAE,MAAM,aAAa,CAAC,CAAC,CAAC;aAClC,YAAY,EAAE,MAAM;aACpB,cAAc,EAAE,OAAO;aACvB,eAAe,EAAE,MAAM;aACvB,eAAe,EAAE,OAAO;aACxB,gBAAgB,EAAE,UAAU;aAC5B,YAAY,EAAE,OAAO;IA1BvC,OAAO,CAAC,qBAAqB,CAAsB;IACnD,OAAO,CAAC,SAAS,CAAkB;IACnC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,kBAAkB,CAAyB;IACnD,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAiB;IACtD,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAoB;IAC3D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAe;IACpD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAiB;IACnD,OAAO,CAAC,MAAM,CAAC,cAAc,CAAS;IACtC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAO;IACtC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAiB;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAoB;IAC3C,OAAO,CAAC,MAAM,CAAC,UAAU,CAAiB;IAC1C,OAAO,CAAC,MAAM,CAAC,WAAW,CAAoB;IAC9C,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAiB;IAChD,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAoB;gBAGzC,OAAO,EAAE,QAAQ,GAAG;QAAE,OAAO,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;KAAE,EACjD,UAAU,EAAE,QAAQ,EACb,UAAU,GAAE,MAAM,aAAa,CAAC,CAAC,CAAC,aAAa,EAC/C,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,OAAO,EACvB,eAAe,EAAE,MAAM,YAAM,EAC7B,eAAe,EAAE,OAAO,YAAuB,EAC/C,gBAAgB,EAAE,UAAU,YAA6B,EACzD,YAAY,EAAE,OAAO;IAOvC;;;;;;;OAOG;IACM,IAAI,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,IAAI;IAkB3C,MAAM,CAAC,KAAK,EAAE,MAAM;IAmJpB,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,GAAG,CAAC;CAyCrC"}
|
package/dist/grab/handles.js
CHANGED
|
@@ -44,7 +44,30 @@ class DistanceGrabHandle extends HandleStore {
|
|
|
44
44
|
this.returnTargetScale = new Vector3();
|
|
45
45
|
this.targetQuatOffset.normalize();
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Bind the handle and treat pointer cancellation as an interrupted release.
|
|
49
|
+
*
|
|
50
|
+
* Older @pmndrs/handle releases only listen for pointerup. Far-ray
|
|
51
|
+
* suppression correctly emits pointercancel, so bridge that event to the
|
|
52
|
+
* handle's pointer-up path. This releases only the cancelled pointer and is
|
|
53
|
+
* harmless if a newer dependency also handles pointercancel natively.
|
|
54
|
+
*/
|
|
55
|
+
bind(handle) {
|
|
56
|
+
const unbind = super.bind(handle);
|
|
57
|
+
const pointerTarget = handle;
|
|
58
|
+
const onPointerCancel = (event) => {
|
|
59
|
+
if (!this.capturedObjects.has(event.pointerId)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.handlers.onPointerUp(event);
|
|
63
|
+
};
|
|
64
|
+
pointerTarget.addEventListener('pointercancel', onPointerCancel);
|
|
65
|
+
return () => {
|
|
66
|
+
pointerTarget.removeEventListener('pointercancel', onPointerCancel);
|
|
67
|
+
unbind();
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
update(delta) {
|
|
48
71
|
var _a;
|
|
49
72
|
const target = this.getTarget();
|
|
50
73
|
if (this.inputState.size === 0) {
|
|
@@ -69,7 +92,7 @@ class DistanceGrabHandle extends HandleStore {
|
|
|
69
92
|
}
|
|
70
93
|
if (this.movementMode === MovementMode.RotateAtSource ||
|
|
71
94
|
this.movementMode === MovementMode.MoveFromTarget) {
|
|
72
|
-
super.update(
|
|
95
|
+
super.update(delta);
|
|
73
96
|
return;
|
|
74
97
|
}
|
|
75
98
|
const pointerAmount = this.inputState.size;
|
|
@@ -84,10 +107,10 @@ class DistanceGrabHandle extends HandleStore {
|
|
|
84
107
|
const [p1] = this.inputState.values();
|
|
85
108
|
const current = p1.pointerWorldOrigin;
|
|
86
109
|
if (this.previousPointerOrigin != undefined) {
|
|
87
|
-
const
|
|
110
|
+
const originDelta = DistanceGrabHandle._tmp
|
|
88
111
|
.copy(current)
|
|
89
112
|
.sub(this.previousPointerOrigin);
|
|
90
|
-
DistanceGrabHandle._posHelper.add(
|
|
113
|
+
DistanceGrabHandle._posHelper.add(originDelta);
|
|
91
114
|
}
|
|
92
115
|
else {
|
|
93
116
|
this.previousPointerOrigin = new Vector3().copy(current);
|
|
@@ -110,7 +133,7 @@ class DistanceGrabHandle extends HandleStore {
|
|
|
110
133
|
.copy(pointerQuaternion)
|
|
111
134
|
.multiply(this.targetQuatOffset);
|
|
112
135
|
const distance = targetPosition.distanceTo(DistanceGrabHandle._posHelper);
|
|
113
|
-
const rawInterpolationAlpha = this.moveSpeedFactor *
|
|
136
|
+
const rawInterpolationAlpha = this.moveSpeedFactor * delta * DistanceGrabHandle.MOVE_SPEED_SCALE;
|
|
114
137
|
// Invalid timing/config input must never poison the target transform.
|
|
115
138
|
// Freeze on NaN; clamp finite values and infinities to the valid lerp range.
|
|
116
139
|
const interpolationAlpha = Number.isNaN(rawInterpolationAlpha)
|
|
@@ -161,7 +184,7 @@ class DistanceGrabHandle extends HandleStore {
|
|
|
161
184
|
quaternion,
|
|
162
185
|
rotation,
|
|
163
186
|
scale,
|
|
164
|
-
time,
|
|
187
|
+
time: delta,
|
|
165
188
|
});
|
|
166
189
|
this.outputState.memo = this.apply(target);
|
|
167
190
|
this.latestMoveEvent = undefined;
|
package/dist/grab/handles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handles.js","sources":["../../src/grab/handles.ts"],"sourcesContent":[null],"names":[],"mappings":";;;;;AAAA;;;;;AAKG;AAMI,MAAM,MAAM,GAAG,eAAe,CACnC,QAAQ,EACR;IACE,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE;CACrD,EACD,kEAAkE;AAGpE;AACO,MAAM,YAAY,GAAG;;AAE1B,IAAA,cAAc,EAAE,gBAAgB;;AAEhC,IAAA,iBAAiB,EAAE,mBAAmB;;AAEtC,IAAA,YAAY,EAAE,cAAc;;AAE5B,IAAA,cAAc,EAAE,gBAAgB;;AAG5B,MAAO,kBAAsB,SAAQ,WAAc,CAAA;AAkBvD,IAAA,WAAA,CACW,OAAiD,EACjD,UAAoB,EACb,UAAA,GAAqC,OAAO,EAAE,CAAC,EAC/C,YAAoB,EACpB,cAAuB,EACvB,eAAA,GAA0B,GAAG,EAC7B,eAAA,GAA2B,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC/C,mBAA+B,IAAI,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EACzD,YAAqB,EAAA;AAErC,QAAA,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC;QAVjB,IAAA,CAAA,OAAO,GAAP,OAAO;QACP,IAAA,CAAA,UAAU,GAAV,UAAU;QACH,IAAA,CAAA,UAAU,GAAV,UAAU;QACV,IAAA,CAAA,YAAY,GAAZ,YAAY;QACZ,IAAA,CAAA,cAAc,GAAd,cAAc;QACd,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,eAAe,GAAf,eAAe;QACf,IAAA,CAAA,gBAAgB,GAAhB,gBAAgB;QAChB,IAAA,CAAA,YAAY,GAAZ,YAAY;QAzBtB,IAAA,CAAA,SAAS,GAAY,KAAK;QAC1B,IAAA,CAAA,oBAAoB,GAAG,KAAK;QAC5B,IAAA,CAAA,kBAAkB,GAAoB,IAAI;AACjC,QAAA,IAAA,CAAA,oBAAoB,GAAG,IAAI,OAAO,EAAE;AACpC,QAAA,IAAA,CAAA,sBAAsB,GAAG,IAAI,UAAU,EAAE;AACzC,QAAA,IAAA,CAAA,oBAAoB,GAAG,IAAI,KAAK,EAAE;AAClC,QAAA,IAAA,CAAA,iBAAiB,GAAG,IAAI,OAAO,EAAE;AAuBhD,QAAA,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE;IACnC;AAEA,IAAA,MAAM,CAAC,IAAY,EAAA;;AACjB,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE;QAE/B,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE;;;;;;AAM9B,YAAA,IAAI,CAAC,SAAS,GAAG,KAAK;QACxB;QAEA,IACE,MAAM,IAAI,IAAI;AACd,YAAA,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;AAC1B,aAAC,IAAI,CAAC,eAAe,IAAI,IAAI;AAC3B,gBAAA,CAAC,CAAA,EAAA,GAAA,IAAI,CAAC,UAAU,EAAE,CAAC,YAAY,MAAA,IAAA,IAAA,EAAA,KAAA,MAAA,GAAA,EAAA,GAAI,KAAK,MAAM,KAAK,CAAC,EACtD;AACA,YAAA,IAAI,IAAI,CAAC,qBAAqB,IAAI,SAAS,EAAE;AAC3C,gBAAA,IAAI,CAAC,qBAAqB,GAAG,SAAS;YACxC;YACA;QACF;AAEA,QAAA,IAAI,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU,EAAE;AACzD,YAAA,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC;QAChC;AAEA,QAAA,IACE,IAAI,CAAC,YAAY,KAAK,YAAY,CAAC,cAAc;AACjD,YAAA,IAAI,CAAC,YAAY,KAAK,YAAY,CAAC,cAAc,EACjD;AACA,YAAA,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC;YAClB;QACF;AAEA,QAAA,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI;AAC1C,QAAA,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,UAAU,CAAC;AACtD,QAAA,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,WAAW,CAAC;AACzD,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ;AAChC,QAAA,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU;AACpC,QAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ;AAChC,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK;AAE1B,QAAA,QAAQ,IAAI,CAAC,YAAY;AACvB,YAAA,KAAK,YAAY,CAAC,YAAY,EAAE;gBAC9B,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;AACrC,gBAAA,MAAM,OAAO,GAAG,EAAE,CAAC,kBAAkB;AACrC,gBAAA,IAAI,IAAI,CAAC,qBAAqB,IAAI,SAAS,EAAE;AAC3C,oBAAA,MAAM,KAAK,GAAG,kBAAkB,CAAC;yBAC9B,IAAI,CAAC,OAAO;AACZ,yBAAA,GAAG,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAClC,oBAAA,kBAAkB,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;gBAC1C;qBAAO;oBACL,IAAI,CAAC,qBAAqB,GAAG,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC1D;;AAEA,gBAAA,IAAI,CAAC,qBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC;gBACzC;YACF;AACA,YAAA,KAAK,YAAY,CAAC,iBAAiB,EAAE;gBACnC,MAAM,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;AACrC,gBAAA,MAAM,aAAa,GAAG,EAAE,CAAC,kBAAkB;AAC3C,gBAAA,MAAM,iBAAiB,GAAG,EAAE,CAAC,sBAAsB;;AAGnD,gBAAA,MAAM,cAAc,GAAG,kBAAkB,CAAC;AACvC,qBAAA,IAAI,CAAC,IAAI,CAAC,eAAe;qBACzB,eAAe,CAAC,iBAAiB;qBACjC,GAAG,CAAC,aAAa,CAAC;;AAGrB,gBAAA,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;qBACzC,IAAI,CAAC,iBAAiB;AACtB,qBAAA,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC;gBAElC,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CACxC,kBAAkB,CAAC,UAAU,CAC9B;gBACD,MAAM,qBAAqB,GACzB,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,kBAAkB,CAAC,gBAAgB;;;AAGnE,gBAAA,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB;AAC3D,sBAAE;AACF,sBAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;gBAEnD,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,QAAQ,GAAG,kBAAkB,CAAC,cAAc,EAAE;oBACnE,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAChC,cAAc,EACd,kBAAkB,CACnB;oBACD,kBAAkB,CAAC,WAAW,CAAC,KAAK,CAClC,gBAAgB,EAChB,kBAAkB,CACnB;gBACH;qBAAO;AACL,oBAAA,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;AACnB,wBAAA,IAAI,CAAC,SAAS,GAAG,IAAI;oBACvB;AACA,oBAAA,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC;AAClD,oBAAA,kBAAkB,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC;gBACvD;gBAEA;YACF;;;AAIF,QAAA,IAAI,MAAM,CAAC,MAAM,EAAE;;AAEjB,YAAA,MAAM,wBAAwB,GAAG,MAAM,CAAC,MAAM,CAAC;AAC5C,iBAAA,KAAK;AACL,iBAAA,MAAM,EAAE;;YAGX;AACG,iBAAA,IAAI,CAAC,kBAAkB,CAAC,UAAU;iBAClC,YAAY,CAAC,wBAAwB,CAAC;;AAGzC,YAAA,MAAM,4BAA4B,GAAG,MAAM,CAAC;AACzC,iBAAA,kBAAkB,CAAC,kBAAkB,CAAC,QAAQ;AAC9C,iBAAA,MAAM,EAAE;YACX;AACG,iBAAA,IAAI,CAAC,kBAAkB,CAAC,WAAW;iBACnC,WAAW,CAAC,4BAA4B,CAAC;QAC9C;aAAO;;AAEL,YAAA,QAAQ,CAAC,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC;AAC5C,YAAA,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC;QACjD;;;QAIA,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE;YAC5C,aAAa;YACb,QAAQ;YACR,UAAU;YACV,QAAQ;YACR,KAAK;YACL,IAAI;AACL,SAAA,CAAC;QACF,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AAC1C,QAAA,IAAI,CAAC,eAAe,GAAG,SAAS;IAClC;AAEU,IAAA,KAAK,CAAC,MAAgB,EAAA;QAC9B,IACE,IAAI,CAAC,cAAc;AACnB,YAAA,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;YAC1B,IAAI,CAAC,WAAW,CAAC,KAAK;AACtB,YAAA,CAAC,IAAI,CAAC,oBAAoB,EAC1B;AACA,YAAA,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,MAAM;YACvC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC/C,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;YACnD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;YAC/C,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;AACzC,YAAA,IAAI,CAAC,oBAAoB,GAAG,IAAI;QAClC;;;;QAKA,IACE,IAAI,CAAC,cAAc;YACnB,IAAI,CAAC,WAAW,CAAC,IAAI;YACrB,IAAI,CAAC,oBAAoB,EACzB;AACA,YAAA,IAAI,IAAI,CAAC,YAAY,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,kBAAkB,EAAE;AAClE,gBAAA,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,EAAE;oBACnC,MAAM,CAAC,gBAAgB,EAAE;gBAC3B;qBAAO;AACL,oBAAA,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC;gBACrC;YACF;YACA,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,CAAC;YAC/C,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,oBAAoB,CAAC,KAAK;YACvD,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC;YACnD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC;AACzC,YAAA,IAAI,CAAC,kBAAkB,GAAG,IAAI;AAC9B,YAAA,IAAI,CAAC,oBAAoB,GAAG,KAAK;;AAEjC,YAAA,OAAO,SAAyB;QAClC;AACA,QAAA,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;IAC5B;;AApNe,kBAAA,CAAA,cAAc,GAAG,KAAH;AACd,kBAAA,CAAA,gBAAgB,GAAG,GAAH;AAChB,kBAAA,CAAA,IAAI,GAAG,IAAI,OAAO,EAAE;AACpB,kBAAA,CAAA,QAAQ,GAAG,IAAI,UAAU,EAAE;AAC3B,kBAAA,CAAA,UAAU,GAAG,IAAI,OAAO,EAAE;AAC1B,kBAAA,CAAA,WAAW,GAAG,IAAI,UAAU,EAAE;AAC9B,kBAAA,CAAA,gBAAgB,GAAG,IAAI,OAAO,EAAE;AAChC,kBAAA,CAAA,iBAAiB,GAAG,IAAI,UAAU,EAAE;;;;"}
|
|
1
|
+
{"version":3,"file":"handles.js","sources":["../../src/grab/handles.ts"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { HandleOptions, HandleStore } from '@pmndrs/handle';\nimport type {\n PointerEvent as PmndrsPointerEvent,\n PointerEventsMap,\n} from '@pmndrs/pointer-events';\nimport { Types, createComponent } from '../ecs/component.js';\nimport {\n Euler,\n Object3D,\n type Object3DEventMap,\n Quaternion,\n Vector3,\n} from '../runtime/index.js';\n\nexport const Handle = createComponent(\n 'Handle',\n {\n instance: { type: Types.Object, default: undefined },\n },\n 'Internal component storing an active interaction handle instance',\n);\n\n/** MovementMode for {@link DistanceGrabbable}. @category Grab */\nexport const MovementMode = {\n /** Object smoothly moves with the ray cast end point of the grabbing controller. */\n MoveFromTarget: 'MoveFromTarget',\n /** Object smoothly moves toward the input source that's grabbing. */\n MoveTowardsTarget: 'MoveTowardsTarget',\n /** Object moves relative to controller delta movement while maintaining distance. */\n MoveAtSource: 'MoveAtSource',\n /** Object rotates in place without translation or scaling. */\n RotateAtSource: 'RotateAtSource',\n};\n\nexport class DistanceGrabHandle<T> extends HandleStore<T> {\n private previousPointerOrigin: Vector3 | undefined;\n private isSnapped: boolean = false;\n private returnOriginCaptured = false;\n private returnTargetParent: Object3D | null = null;\n private readonly returnTargetPosition = new Vector3();\n private readonly returnTargetQuaternion = new Quaternion();\n private readonly returnTargetRotation = new Euler();\n private readonly returnTargetScale = new Vector3();\n private static SNAP_THRESHOLD = 0.005;\n private static MOVE_SPEED_SCALE = 100;\n private static _tmp = new Vector3();\n private static _tmpQuat = new Quaternion();\n private static _posHelper = new Vector3();\n private static _quatHelper = new Quaternion();\n private static _offsetPosHelper = new Vector3();\n private static _offsetQuatHelper = new Quaternion();\n\n constructor(\n readonly target_: Object3D | { current?: Object3D | null },\n readonly sceneRoot_: Object3D,\n public readonly getOptions: () => HandleOptions<T> = () => ({}),\n public readonly movementMode: string,\n public readonly returnToOrigin: boolean,\n public readonly moveSpeedFactor: number = 0.1,\n public readonly targetPosOffset: Vector3 = new Vector3(0, 0, 0),\n public readonly targetQuatOffset: Quaternion = new Quaternion(0, 0, 0, 1),\n public readonly detachOnGrab: boolean,\n ) {\n super(target_, getOptions);\n\n this.targetQuatOffset.normalize();\n }\n\n /**\n * Bind the handle and treat pointer cancellation as an interrupted release.\n *\n * Older @pmndrs/handle releases only listen for pointerup. Far-ray\n * suppression correctly emits pointercancel, so bridge that event to the\n * handle's pointer-up path. This releases only the cancelled pointer and is\n * harmless if a newer dependency also handles pointercancel natively.\n */\n override bind(handle: Object3D): () => void {\n const unbind = super.bind(handle);\n const pointerTarget = handle as Object3D<\n PointerEventsMap & Object3DEventMap\n >;\n const onPointerCancel = (event: PmndrsPointerEvent) => {\n if (!this.capturedObjects.has(event.pointerId)) {\n return;\n }\n this.handlers.onPointerUp(event);\n };\n pointerTarget.addEventListener('pointercancel', onPointerCancel);\n return () => {\n pointerTarget.removeEventListener('pointercancel', onPointerCancel);\n unbind();\n };\n }\n\n update(delta: number) {\n const target = this.getTarget();\n\n if (this.inputState.size === 0) {\n // No active pointers: the grab was released, cancelled, or\n // force-released. Clear transient snap state so the next grab starts\n // unsnapped. This replaces the constructor's 'pointerup' DOM listener,\n // which was never removed (a listener leak) and also missed\n // forceRelease()/cancel() (which don't fire a DOM pointerup).\n this.isSnapped = false;\n }\n\n if (\n target == null ||\n this.inputState.size === 0 ||\n (this.latestMoveEvent == null &&\n (this.getOptions().alwaysUpdate ?? false) === false)\n ) {\n if (this.previousPointerOrigin != undefined) {\n this.previousPointerOrigin = undefined;\n }\n return;\n }\n\n if (this.detachOnGrab && target.parent != this.sceneRoot_) {\n this.sceneRoot_.attach(target);\n }\n\n if (\n this.movementMode === MovementMode.RotateAtSource ||\n this.movementMode === MovementMode.MoveFromTarget\n ) {\n super.update(delta);\n return;\n }\n\n const pointerAmount = this.inputState.size;\n target.getWorldPosition(DistanceGrabHandle._posHelper);\n target.getWorldQuaternion(DistanceGrabHandle._quatHelper);\n const position = target.position;\n const quaternion = target.quaternion;\n const rotation = target.rotation;\n const scale = target.scale;\n\n switch (this.movementMode) {\n case MovementMode.MoveAtSource: {\n const [p1] = this.inputState.values();\n const current = p1.pointerWorldOrigin;\n if (this.previousPointerOrigin != undefined) {\n const originDelta = DistanceGrabHandle._tmp\n .copy(current)\n .sub(this.previousPointerOrigin);\n DistanceGrabHandle._posHelper.add(originDelta);\n } else {\n this.previousPointerOrigin = new Vector3().copy(current);\n }\n // Update stored previous for next frame\n this.previousPointerOrigin!.copy(current);\n break;\n }\n case MovementMode.MoveTowardsTarget: {\n const [p1] = this.inputState.values();\n const pointerOrigin = p1.pointerWorldOrigin;\n const pointerQuaternion = p1.pointerWorldQuaternion;\n\n // Calculate target position by applying position offset in pointer's local space\n const targetPosition = DistanceGrabHandle._offsetPosHelper\n .copy(this.targetPosOffset)\n .applyQuaternion(pointerQuaternion)\n .add(pointerOrigin);\n\n // Calculate target rotation by multiplying pointer rotation with rotation offset\n const targetQuaternion = DistanceGrabHandle._offsetQuatHelper\n .copy(pointerQuaternion)\n .multiply(this.targetQuatOffset);\n\n const distance = targetPosition.distanceTo(\n DistanceGrabHandle._posHelper,\n );\n const rawInterpolationAlpha =\n this.moveSpeedFactor * delta * DistanceGrabHandle.MOVE_SPEED_SCALE;\n // Invalid timing/config input must never poison the target transform.\n // Freeze on NaN; clamp finite values and infinities to the valid lerp range.\n const interpolationAlpha = Number.isNaN(rawInterpolationAlpha)\n ? 0\n : Math.min(1, Math.max(0, rawInterpolationAlpha));\n\n if (!this.isSnapped && distance > DistanceGrabHandle.SNAP_THRESHOLD) {\n DistanceGrabHandle._posHelper.lerp(\n targetPosition,\n interpolationAlpha,\n );\n DistanceGrabHandle._quatHelper.slerp(\n targetQuaternion,\n interpolationAlpha,\n );\n } else {\n if (!this.isSnapped) {\n this.isSnapped = true;\n }\n DistanceGrabHandle._posHelper.copy(targetPosition);\n DistanceGrabHandle._quatHelper.copy(targetQuaternion);\n }\n\n break;\n }\n }\n\n // Convert world space transforms to local space\n if (target.parent) {\n // Get parent's inverse world matrix\n const parentWorldMatrixInverse = target.parent.matrixWorld\n .clone()\n .invert();\n\n // Transform desired world position to local space\n position\n .copy(DistanceGrabHandle._posHelper)\n .applyMatrix4(parentWorldMatrixInverse);\n\n // Transform desired world quaternion to local space\n const parentWorldQuaternionInverse = target.parent\n .getWorldQuaternion(DistanceGrabHandle._tmpQuat)\n .invert();\n quaternion\n .copy(DistanceGrabHandle._quatHelper)\n .premultiply(parentWorldQuaternionInverse);\n } else {\n // No parent, world space = local space\n position.copy(DistanceGrabHandle._posHelper);\n quaternion.copy(DistanceGrabHandle._quatHelper);\n }\n\n // Always apply during drag; if returnToOrigin is true,\n // the override in apply() will snap back on release.\n this.outputState.update(this.latestMoveEvent, {\n pointerAmount,\n position,\n quaternion,\n rotation,\n scale,\n time: delta,\n });\n this.outputState.memo = this.apply(target);\n this.latestMoveEvent = undefined;\n }\n\n protected apply(target: Object3D): T {\n if (\n this.returnToOrigin &&\n this.inputState.size === 1 &&\n this.outputState.first &&\n !this.returnOriginCaptured\n ) {\n this.returnTargetParent = target.parent;\n this.returnTargetPosition.copy(target.position);\n this.returnTargetQuaternion.copy(target.quaternion);\n this.returnTargetRotation.copy(target.rotation);\n this.returnTargetScale.copy(target.scale);\n this.returnOriginCaptured = true;\n }\n\n // HandleStore intentionally saves a new manipulation baseline whenever a\n // second pointer joins or one pointer leaves. Return-to-origin needs the\n // transform from the start of the whole gesture, not a handoff baseline.\n if (\n this.returnToOrigin &&\n this.outputState.last &&\n this.returnOriginCaptured\n ) {\n if (this.detachOnGrab && target.parent !== this.returnTargetParent) {\n if (this.returnTargetParent == null) {\n target.removeFromParent();\n } else {\n this.returnTargetParent.add(target);\n }\n }\n target.position.copy(this.returnTargetPosition);\n target.rotation.order = this.returnTargetRotation.order;\n target.quaternion.copy(this.returnTargetQuaternion);\n target.scale.copy(this.returnTargetScale);\n this.returnTargetParent = null;\n this.returnOriginCaptured = false;\n // Do not call super.apply to avoid re-applying the drag transform.\n return undefined as unknown as T;\n }\n return super.apply(target);\n }\n}\n"],"names":[],"mappings":"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"}
|