Skip to content

Commit a768c6b

Browse files
felixtrzmeta-codesync[bot]
authored andcommitted
Fix hand tracking visuals by deduplicating input sources across session arrays
Summary: Fixed an issue where hand tracking visuals were not displayed due to some WebXR runtimes including the same hands in both session.inputSources and session.trackedSources as different objects. Processing duplicates from trackedSources would overwrite the isPrimary flag, hiding hand visuals. The fix adds deduplication logic to skip reprocessing duplicates, preserving the correct isPrimary status. Reviewed By: zjm-meta Differential Revision: D86931308 Privacy Context Container: L1334777 fbshipit-source-id: 5ebb295cd7fae786753d1c892c2e41330a25e201
1 parent e418a89 commit a768c6b

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

packages/xr-input/src/xr-input-manager.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ export class XRInputManager {
100100
private scene: Scene;
101101
private hadSession = false;
102102

103+
private processedInputSourceKeys = new Set<string>();
104+
103105
constructor(options: XRInputOptions) {
104106
const { scene, camera, assetLoader } = options;
105107
this.xrOrigin = new XROrigin();
@@ -227,13 +229,41 @@ export class XRInputManager {
227229
this.primaryInputSources.right = undefined;
228230
}
229231

232+
/**
233+
* Updates the active input sources from the XR session.
234+
*
235+
* IMPORTANT: This method handles a platform quirk where some runtimes
236+
* include the same hands in BOTH session.inputSources AND session.trackedSources.
237+
* The duplicate entries represent the same physical hands but as different XRInputSource objects
238+
* with different properties (e.g., different gamepad.buttons lengths).
239+
*
240+
* To prevent the trackedSources from overwriting the isPrimary status set by inputSources,
241+
* we track which handedness+type combinations have already been processed and skip
242+
* re-processing duplicates from trackedSources.
243+
*
244+
* Without this deduplication:
245+
* - Hands from inputSources would be marked as isPrimary=true
246+
* - Then the same hands from trackedSources would overwrite with isPrimary=false
247+
* - This causes hand visuals to not be displayed (since visibility is tied to isPrimary)
248+
*/
230249
private updateActiveInputSources(session: XRSession): void {
250+
this.processedInputSourceKeys.clear();
251+
252+
// Process inputSources (these are primary)
231253
for (const inputSource of session.inputSources) {
232254
this.assignInputSource(inputSource, true);
255+
const key = `${inputSource.handedness}-${inputSource.hand ? 'hand' : 'controller'}`;
256+
this.processedInputSourceKeys.add(key);
233257
}
258+
259+
// Process trackedSources (these are non-primary)
260+
// Skip any that were already in inputSources to avoid overwriting isPrimary
234261
if (session.trackedSources) {
235262
for (const inputSource of session.trackedSources) {
236-
this.assignInputSource(inputSource, false);
263+
const key = `${inputSource.handedness}-${inputSource.hand ? 'hand' : 'controller'}`;
264+
if (!this.processedInputSourceKeys.has(key)) {
265+
this.assignInputSource(inputSource, false);
266+
}
237267
}
238268
}
239269
}

0 commit comments

Comments
 (0)