| <!DOCTYPE html> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="../resources/webxr_util.js"></script> |
| <script src="../resources/webxr_test_constants.js"></script> |
| |
| <script> |
| let testName = "WebXR InputSource's gamepad properly registers input"; |
| |
| let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; |
| |
| let testFunction = function(session, fakeDeviceController, t) { |
| |
| // There should only be one input source change event, which is from adding |
| // the input source at the start of the test. |
| let inputChangeEvents = 0; |
| function onInputSourcesChange(event) { |
| assert_equals(inputChangeEvents, 0, |
| "Gamepad button or input axis value changes should not fire an input source change event."); |
| inputChangeEvents++; |
| } |
| |
| session.addEventListener('inputsourceschange', onInputSourcesChange, false); |
| |
| // Create our input source and immediately toggle the primary input so that |
| // it appears as already needing to send a click event when it appears. |
| let input_source = fakeDeviceController.simulateInputSourceConnection({ |
| handedness: "right", |
| targetRayMode: "tracked-pointer", |
| pointerOrigin: VALID_POINTER_TRANSFORM, |
| profiles: [], |
| supportedButtons: [ |
| { |
| buttonType: 'grip', |
| pressed: false, |
| touched: false, |
| pressedValue: 0 |
| }, |
| { |
| buttonType: 'touchpad', |
| pressed: false, |
| touched: false, |
| pressedValue: 0 |
| } |
| ] |
| }); |
| |
| let cached_input_source = null; |
| let cached_gamepad = null; |
| |
| function assertSameObjects() { |
| assert_equals(session.inputSources[0], cached_input_source); |
| assert_equals(cached_input_source.gamepad, cached_gamepad); |
| |
| // Also make sure that WebXR gamepads have the index and id values required |
| // by the spec. |
| assert_equals(cached_gamepad.index, -1); |
| assert_equals(cached_gamepad.id, ""); |
| } |
| |
| // Input events and gamepad state changes (button presses, axis movements) |
| // need one frame to propagate, so this does (in order and running a rAF after |
| // each step): |
| // 1) Press the mock gamepad's button (so we can verify the button press makes |
| // its way to the WebXR gamepad and that it does not fire an |
| // inputsourceschange event). |
| // 2) Update the mock gamepad's input axes values (so we can verify the |
| // updated values make their way to the WebXR gamepad and that it does not |
| // fire an inputsourceschange event). |
| return new Promise((resolve) => { |
| requestSkipAnimationFrame(session, () => { |
| // Make sure the exposed gamepad has the number of buttons and axes we |
| // requested. |
| // 3 Buttons: trigger, grip, touchpad |
| // 2 Axes from the touchpad |
| cached_input_source = session.inputSources[0]; |
| cached_gamepad = cached_input_source.gamepad; |
| t.step(() => { |
| assert_equals(cached_gamepad.index, -1); |
| assert_equals(cached_gamepad.id, ""); |
| assert_equals(cached_gamepad.buttons.length, 3); |
| assert_equals(cached_gamepad.axes.length, 2); |
| // Initially, the button should not be pressed and the axes values should |
| // be set to 0. |
| assert_false(cached_gamepad.buttons[1].pressed); |
| assert_equals(cached_gamepad.axes[0], 0); |
| assert_equals(cached_gamepad.axes[1], 0); |
| }, "Verify initial state"); |
| // Simulate button press. |
| input_source.updateButtonState({ |
| buttonType: 'grip', |
| pressed: true, |
| touched: true, |
| value: 1.0 |
| }); |
| session.requestAnimationFrame(() => { |
| t.step(() => { |
| assertSameObjects(); |
| assert_true(cached_gamepad.buttons[1].pressed); |
| }, "Gamepad is updated in place when a button is pressed"); |
| |
| // Simulate input axes movement. |
| input_source.updateButtonState({ |
| buttonType: 'touchpad', |
| pressed: false, |
| touched: true, |
| value: 0, |
| xValue: 0.5, |
| yValue: -0.5 |
| }); |
| session.requestAnimationFrame(() => { |
| // Input source and gamepad should not be re-created. They should be |
| // updated in place when input axes values change. |
| t.step(() => { |
| assertSameObjects(); |
| assert_equals(cached_gamepad.axes[0], 0.5); |
| assert_equals(cached_gamepad.axes[1], -0.5); |
| // Button that was pressed last frame should still be pressed. |
| assert_true(cached_gamepad.buttons[1].pressed); |
| }, "Gamepad is updated in place when axes values change"); |
| resolve(); |
| }); |
| }); |
| }); |
| }); |
| }; |
| |
| xr_session_promise_test( |
| testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); |
| </script> |