Commit 2cd325a0 authored by Alex Cooper's avatar Alex Cooper Committed by Commit Bot

Implement Input portions of webxr-test-api

This change implements the input related portions of the webxr-test-api
and updates internal tests to use those methods/constants/inits.
Most of the logic is ported from xr-internal-device-mocking.js and just
converted from attributes to a pair of set/clear properties.  No tests
were actually using the getters, so those were just deleted.  Because
the webxr-test-api does not yet support gamepads, all of that logic was
left in the internal mock.

It also forces/fixes a potential bug where a device with no inputs may
opt to set the "InputStates" value of the mojom to null rather than an
empty array. (The device code typically sets this to an empty array)

Rather than risk losing/confusing the diff to the updated tests, future
work will move these tests to the external WPTs

Bug: 979318
Change-Id: I846831a561217abd66ab841326a5e5472f38afeb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1699505Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
Cr-Commit-Position: refs/heads/master@{#677061}
parent 7af663f4
......@@ -332,9 +332,13 @@ void XRFrameProvider::ProcessScheduledFrame(
}
if (immersive_session_) {
if (frame_pose_ && frame_pose_->input_state.has_value()) {
immersive_session_->OnInputStateChange(frame_id_,
frame_pose_->input_state.value());
if (frame_pose_) {
base::span<const device::mojom::blink::XRInputSourceStatePtr>
input_states;
if (frame_pose_->input_state.has_value())
input_states = frame_pose_->input_state.value();
immersive_session_->OnInputStateChange(frame_id_, input_states);
}
// Check if immersive session is still set as OnInputStateChange may have
......@@ -395,9 +399,13 @@ void XRFrameProvider::ProcessScheduledFrame(
if (session->ended())
continue;
if (frame_pose_ && frame_pose_->input_state.has_value()) {
session->OnInputStateChange(frame_id_,
frame_pose_->input_state.value());
if (frame_pose_) {
base::span<const device::mojom::blink::XRInputSourceStatePtr>
input_states;
if (frame_pose_->input_state.has_value())
input_states = frame_pose_->input_state.value();
session->OnInputStateChange(frame_id_, input_states);
}
// If the input state change caused this session to end, we should stop
......
......@@ -16,6 +16,35 @@ const default_stage_parameters = {
bounds: null
};
function getMatrixFromTransform(transform) {
let x = transform.orientation[0];
let y = transform.orientation[1];
let z = transform.orientation[2];
let w = transform.orientation[3];
let m11 = 1.0 - 2.0 * (y * y + z * z);
let m21 = 2.0 * (x * y + z * w);
let m31 = 2.0 * (x * z - y * w);
let m12 = 2.0 * (x * y - z * w);
let m22 = 1.0 - 2.0 * (x * x + z * z);
let m32 = 2.0 * (y * z + x * w);
let m13 = 2.0 * (x * z + y * w);
let m23 = 2.0 * (y * z - x * w);
let m33 = 1.0 - 2.0 * (x * x + y * y);
let m14 = transform.position[0];
let m24 = transform.position[1];
let m34 = transform.position[2];
// Column-major linearized order is expected.
return [m11, m21, m31, 0,
m12, m22, m32, 0,
m13, m23, m33, 0,
m14, m24, m34, 1];
}
class ChromeXRTest {
constructor() {
this.mockVRService_ = new MockVRService(mojo.frameInterfaces);
......@@ -178,6 +207,9 @@ class MockRuntime {
this.framesOfReference = {};
this.input_sources_ = [];
this.next_input_source_index_ = 1;
// Initialize DisplayInfo first to set the defaults, then override with
// anything from the deviceInit
if (fakeDeviceInit.supportsImmersive) {
......@@ -288,7 +320,7 @@ class MockRuntime {
this.displayInfo_.stageParameters.standingTransform = new gfx.mojom.Transform();
this.displayInfo_.stageParameters.standingTransform.matrix =
this.getMatrixFromTransform(transform);
getMatrixFromTransform(transform);
if (this.sessionClient_.ptr.isBound()) {
this.sessionClient_.onChanged(this.displayInfo_);
......@@ -309,35 +341,16 @@ class MockRuntime {
this.send_pose_reset_ = true;
}
// Helper methods
getMatrixFromTransform(transform) {
let x = transform.orientation[0];
let y = transform.orientation[1];
let z = transform.orientation[2];
let w = transform.orientation[3];
let m11 = 1.0 - 2.0 * (y * y + z * z);
let m21 = 2.0 * (x * y + z * w);
let m31 = 2.0 * (x * z - y * w);
let m12 = 2.0 * (x * y - z * w);
let m22 = 1.0 - 2.0 * (x * x + z * z);
let m32 = 2.0 * (y * z + x * w);
let m13 = 2.0 * (x * z + y * w);
let m23 = 2.0 * (y * z - x * w);
let m33 = 1.0 - 2.0 * (x * x + y * y);
let m14 = transform.position[0];
let m24 = transform.position[1];
let m34 = transform.position[2];
// Column-major linearized order is expected.
return [m11, m21, m31, 0,
m12, m22, m32, 0,
m13, m23, m33, 0,
m14, m24, m34, 1];
simulateInputSourceConnection(fakeInputSourceInit) {
let index = this.next_input_source_index_;
this.next_input_source_index_++;
let source = new MockXRInputSource(fakeInputSourceInit, index, this);
this.input_sources_.push(source);
return source;
}
// Helper methods
getNonImmersiveDisplayInfo() {
let displayInfo = this.getImmersiveDisplayInfo();
......@@ -418,6 +431,21 @@ class MockRuntime {
};
}
// These methods are intended to be used by MockXRInputSource only.
addInputSource(source) {
let index = this.input_sources_.indexOf(source);
if (index == -1) {
this.input_sources_.push(source);
}
}
removeInputSource(source) {
let index = this.input_sources_.indexOf(source);
if (index >= 0) {
this.input_sources_.splice(index, 1);
}
}
// Mojo function implementations.
// XRFrameDataProvider implementation.
......@@ -426,6 +454,19 @@ class MockRuntime {
this.pose_.poseIndex++;
this.pose_.poseReset = this.send_pose_reset_;
this.send_pose_reset_ = false;
// Setting the input_state to null tests a slightly different path than
// the browser tests where if the last input source is removed, the device
// code always sends up an empty array, but it's also valid mojom to send
// up a null array.
if (this.input_sources_.length > 0) {
this.pose_.inputState = [];
for (let i = 0; i < this.input_sources_.length; i++) {
this.pose_.inputState.push(this.input_sources_[i].getInputSourceState());
}
} else {
this.pose_.inputState = null;
}
}
// Convert current document time to monotonic time.
......@@ -516,6 +557,147 @@ class MockRuntime {
};
}
class MockXRInputSource {
constructor(fakeInputSourceInit, id, pairedDevice) {
this.source_id_ = id;
this.pairedDevice_ = pairedDevice;
this.handedness_ = fakeInputSourceInit.handedness;
this.target_ray_mode_ = fakeInputSourceInit.targetRayMode;
this.setPointerOrigin(fakeInputSourceInit.pointerOrigin);
this.primary_input_pressed_ = false;
if (fakeInputSourceInit.selectionStarted != null) {
this.primary_input_pressed_ = fakeInputSourceInit.selectionStarted;
}
this.primary_input_clicked_ = false;
if (fakeInputSourceInit.selectionClicked != null) {
this.primary_input_clicked_ = fakeInputSourceInit.selectionClicked;
}
this.grip_ = null;
if (fakeInputSourceInit.gripOrigin != null) {
this.setGripOrigin(fakeInputSourceInit.gripOrigin);
}
this.gamepad_ = null;
this.emulated_position_ = false;
this.desc_dirty_ = true;
}
// Webxr-test-api
setHandedness(handedness) {
if (this.handedness_ != handedness) {
this.desc_dirty_ = true;
this.handedness_ = handedness;
}
}
setTargetRayMode(targetRayMode) {
if (this.target_ray_mode_ != targetRayMode) {
this.desc_dirty_ = true;
this.target_ray_mode_ = targetRayMode;
}
}
setProfiles(profiles) {
// Profiles are not yet implemented by chromium
}
setGripOrigin(transform, emulatedPosition = false) {
this.grip_ = new gfx.mojom.Transform();
this.grip_.matrix = getMatrixFromTransform(transform);
this.emulated_position_ = emulatedPosition;
}
clearGripOrigin() {
if (this.grip_ != null) {
this.grip_ = null;
this.emulated_position_ = false;
}
}
setPointerOrigin(transform, emulatedPosition = false) {
this.desc_dirty_ = true;
this.pointer_offset_ = new gfx.mojom.Transform();
this.pointer_offset_.matrix = getMatrixFromTransform(transform);
}
disconnect() {
this.pairedDevice_.removeInputSource(this);
}
reconnect() {
this.pairedDevice_.addInputSource(this);
}
startSelection() {
this.primary_input_pressed_ = true;
}
endSelection() {
if (!this.primary_input_pressed_) {
throw new Error("Attempted to end selection which was not started");
}
this.primary_input_pressed_ = false;
this.primary_input_clicked_ = true;
}
simulateSelect() {
this.primary_input_clicked_ = true;
}
// Helpers for Mojom
getInputSourceState() {
let input_state = new device.mojom.XRInputSourceState();
input_state.sourceId = this.source_id_;
input_state.primaryInputPressed = this.primary_input_pressed_;
input_state.primaryInputClicked = this.primary_input_clicked_;
input_state.grip = this.grip_;
input_state.gamepad = this.gamepad_;
if (this.desc_dirty_) {
let input_desc = new device.mojom.XRInputSourceDescription();
input_desc.emulatedPosition = this.emulated_position_;
switch (this.target_ray_mode_) {
case 'gaze':
input_desc.targetRayMode = device.mojom.XRTargetRayMode.GAZING;
break;
case 'tracked-pointer':
input_desc.targetRayMode = device.mojom.XRTargetRayMode.POINTING;
break;
}
switch (this.handedness_) {
case 'left':
input_desc.handedness = device.mojom.XRHandedness.LEFT;
break;
case 'right':
input_desc.handedness = device.mojom.XRHandedness.RIGHT;
break;
default:
input_desc.handedness = device.mojom.XRHandedness.NONE;
break;
}
input_desc.pointerOffset = this.pointer_offset_;
input_state.description = input_desc;
this.desc_dirty_ = false;
}
return input_state;
}
}
// Mojo helper classes
class MockXRPresentationProvider {
constructor() {
......
......@@ -29,10 +29,26 @@ const VALID_PROJECTION_MATRIX =
[1, 0, 0, 0, 0, 1, 0, 0, 3, 2, -1, -1, 0, 0, -0.2, 0];
// A valid input grip matrix for when we don't care about specific values
const VALID_GRIP = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1];
const VALID_GRIP = [1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
4, 3, 2, 1];
const VALID_GRIP_TRANSFORM = {
position: [4, 3, 2],
orientation: [0, 0, 0, 1]
};
// A valid input pointer offset for when we don't care about specific values
const VALID_POINTER_OFFSET = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1];
const VALID_POINTER_OFFSET = [1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 1, 1];
const VALID_POINTER_TRANSFORM = {
position: [0, 0, 1],
orientation: [0, 0, 0, 1]
};
const VALID_GRIP_WITH_POINTER_OFFSET =
[1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 3, 1];
......@@ -105,3 +121,17 @@ const VALID_NON_IMMERSIVE_DEVICE = {
views: NON_IMMERSIVE_VIEWS,
viewerOrigin: IDENTITY_TRANSFORM
};
const VALID_CONTROLLER = {
handedness: "none",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: []
};
const RIGHT_CONTROLLER = {
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: []
}
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -98,17 +97,22 @@ let testFunction = function(session, t, fakeDeviceController) {
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
// 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 = new MockXRInputSource();
fakeDeviceController.addInputSource(input_source);
// Create a gaze based input source with no handedness that we can change
// to validate SameObject properties.
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "none",
targetRayMode: "gaze",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: []
});
// Make our input source change after one frame, and wait an additional
// frame for that change to propogate.
// Two changes made in total.
session.requestAnimationFrame((time, xrFrame) => {
input_source.targetRayMode = "tracked-pointer";
input_source.setTargetRayMode("tracked-pointer");
session.requestAnimationFrame((time, xrFrame) => {
input_source.handedness = "left";
input_source.setHandedness("left");
session.requestAnimationFrame((time, xrFrame) => {});
});
});
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -82,18 +81,19 @@ let testFunction = function(session, t, fakeDeviceController) {
// 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 = new MockXRInputSource();
input_source.primaryInputPressed = true;
input_source.primaryInputPressed = false;
fakeDeviceController.addInputSource(input_source);
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: [],
selectionClicked: true
});
// Make our input source disappear after one frame, and wait an additional
// frame for that disappearance to propogate.
session.requestAnimationFrame((time, xrFrame) => {
fakeDeviceController.removeInputSource(input_source);
session.requestAnimationFrame((time, xrFrame) => {
});
input_source.disconnect();
session.requestAnimationFrame((time, xrFrame) => {});
});
return eventPromise;
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -74,10 +73,8 @@ let testFunction = function(session, t, fakeDeviceController) {
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
let input_source = new MockXRInputSource();
fakeDeviceController.addInputSource(input_source);
let input_source =
fakeDeviceController.simulateInputSourceConnection(VALID_CONTROLLER);
let currentReferenceSpace = null;
session.requestReferenceSpace('viewer').then(function(viewerSpace) {
......@@ -88,10 +85,10 @@ let testFunction = function(session, t, fakeDeviceController) {
// Press the primary input button and then release it a short time later.
session.requestAnimationFrame((time, xrFrame) => {
input_source.primaryInputPressed = true;
input_source.startSelection();
session.requestAnimationFrame((time, xrFrame) => {
input_source.primaryInputPressed = false;
input_source.endSelection();
session.requestAnimationFrame((time, xrFrame) => {
// Need to process one more frame to allow select to propegate.
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -57,14 +56,11 @@ let testFunction = function(session, t, fakeDeviceController) {
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
let input_source = new MockXRInputSource();
fakeDeviceController.addInputSource(input_source);
let input_source = fakeDeviceController.simulateInputSourceConnection(VALID_CONTROLLER);
// Press the primary input button and then release it a short time later.
session.requestAnimationFrame((time, xrFrame) => {
input_source.primaryInputPressed = true;
input_source.primaryInputPressed = false;
input_source.simulateSelect();
session.requestAnimationFrame((time, xrFrame) => {
// Need to process one more frame to allow select to propegate.
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -23,13 +22,15 @@ let testFunction =
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
input_source.handedness = "right";
// Don't set a grip matrix yet
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: IDENTITY_TRANSFORM,
profiles: []
});
fakeDeviceController.addInputSource(input_source);
// Don't set a grip matrix yet
// Must have a reference space to get input poses. eye-level doesn't apply
// any transforms to the given matrix.
......@@ -45,7 +46,7 @@ let testFunction =
assert_equals(grip_pose, null);
});
input_source.grip = VALID_GRIP;
input_source.setGripOrigin(VALID_GRIP_TRANSFORM);
session.requestAnimationFrame(CheckValidGrip);
}
......@@ -68,7 +69,7 @@ let testFunction =
"Grip matrix is not equal to target ray matrix.");
});
input_source.pointerOffset = VALID_POINTER_OFFSET;
input_source.setPointerOrigin(VALID_POINTER_TRANSFORM);
session.requestAnimationFrame(CheckValidGripAndPointer);
}
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -22,10 +21,12 @@ let testFunction =
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
fakeDeviceController.addInputSource(input_source);
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "none",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: []
});
function CheckNone(time, xrFrame) {
let source = session.inputSources[0];
......@@ -36,7 +37,7 @@ let testFunction =
assert_equals(source.handedness, "none");
});
input_source.handedness = "right"
input_source.setHandedness("right");
session.requestAnimationFrame(CheckRight);
}
......@@ -50,7 +51,7 @@ let testFunction =
assert_equals(source.handedness, "right");
});
input_source.handedness = "left";
input_source.setHandedness("left");
session.requestAnimationFrame(CheckLeft);
}
......@@ -64,7 +65,7 @@ let testFunction =
assert_equals(source.handedness, "left");
});
input_source.handedness = "none";
input_source.setHandedness("none");
session.requestAnimationFrame(CheckNoneAgain);
}
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -22,12 +21,13 @@ let testFunction =
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
input_source.handedness = "right";
input_source.grip = VALID_GRIP;
fakeDeviceController.addInputSource(input_source);
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: IDENTITY_TRANSFORM,
profiles: [],
gripOrigin: VALID_GRIP_TRANSFORM
});
// Must have a reference space to get input poses. eye-level doesn't apply
// any transforms to the given matrix.
......@@ -59,7 +59,7 @@ let testFunction =
assert_equals(targetRay.direction.w, 0.0);
}, "Target ray computed properly with no pointer offset");
input_source.pointerOffset = VALID_POINTER_OFFSET;
input_source.setPointerOrigin(VALID_POINTER_TRANSFORM);
session.requestAnimationFrame(CheckTargetRayOffset);
}
......
......@@ -3,47 +3,6 @@
/* This file contains extensions to the base mocking from the WebPlatform tests
* for interal tests. The main mocked objects are found in
* ../external/wpt/resources/chromium/webxr-test.js. */
MockRuntime.prototype.base_getFrameData = MockRuntime.prototype.getFrameData;
MockRuntime.prototype.getFrameData = function() {
return this.base_getFrameData().then((result) => {
if (result.frameData && result.frameData.pose && this.input_sources_) {
let input_states = [];
for (let i = 0; i < this.input_sources_.length; ++i) {
input_states.push(this.input_sources_[i].getInputSourceState());
}
result.frameData.pose.inputState = input_states;
}
return result;
});
};
MockRuntime.prototype.addInputSource = function(source) {
if (!this.input_sources_) {
this.input_sources_ = [];
this.next_input_source_index_ = 1;
}
let index = this.next_input_source_index_;
source.source_id_ = index;
this.next_input_source_index_++;
this.input_sources_.push(source);
};
MockRuntime.prototype.removeInputSource = function(source) {
if (!this.input_sources_)
return;
for (let i = 0; i < this.input_sources_.length; ++i) {
if (source.source_id_ == this.input_sources_[i].source_id_) {
this.input_sources_.splice(i, 1);
break;
}
}
};
MockRuntime.prototype.setHitTestResults = function(results) {
this.hittest_results_ = results;
};
......@@ -79,191 +38,42 @@ MockRuntime.prototype.getMissingFrameCount = function() {
return this.presentation_provider_.missing_frame_count_;
};
class MockXRInputSource {
constructor() {
this.source_id_ = 0;
this.primary_input_pressed_ = false;
this.primary_input_clicked_ = false;
this.grip_ = null;
this.gamepad_ = null;
this.target_ray_mode_ = 'gaze';
this.pointer_offset_ = null;
this.emulated_position_ = false;
this.handedness_ = '';
this.desc_dirty_ = true;
}
get primaryInputPressed() {
return this.primary_input_pressed_;
}
set primaryInputPressed(value) {
if (this.primary_input_pressed_ && !value) {
this.primary_input_clicked_ = true;
}
this.primary_input_pressed_ = value;
}
set primaryInputClicked(value) {
this.primary_input_clicked_ = value;
}
get grip() {
if (this.grip_) {
return this.grip_.matrix;
}
return null;
}
set grip(value) {
if (!value) {
this.grip_ = null;
return;
}
this.grip_ = new gfx.mojom.Transform();
this.grip_.matrix = new Float32Array(value);
}
get targetRayMode() {
return this.target_ray_mode_;
}
set targetRayMode(value) {
if (this.target_ray_mode_ != value) {
this.desc_dirty_ = true;
this.target_ray_mode_ = value;
}
}
get pointerOffset() {
if (this.pointer_offset_) {
return this.pointer_offset_.matrix;
}
return null;
}
set pointerOffset(value) {
this.desc_dirty_ = true;
if (!value) {
this.pointer_offset_ = null;
return;
}
this.pointer_offset_ = new gfx.mojom.Transform();
this.pointer_offset_.matrix = new Float32Array(value);
}
get emulatedPosition() {
return this.emulated_position_;
}
set emulatedPosition(value) {
if (this.emulated_position_ != value) {
this.desc_dirty_ = true;
this.emulated_position_ = value;
}
}
get handedness() {
return this.handedness_;
}
set handedness(value) {
if (this.handedness_ != value) {
this.desc_dirty_ = true;
this.handedness_ = value;
}
}
get gamepad() {
return this.gamepad_;
}
connectGamepad() {
// Mojo complains if some of the properties on Gamepad are null, so set
// everything to reasonable defaults that tests can override.
this.gamepad_ = new device.mojom.Gamepad();
this.gamepad_.connected = true;
this.gamepad_.id = "unknown";
this.gamepad_.timestamp = 0;
this.gamepad_.axes = [];
this.gamepad_.buttons = [];
this.gamepad_.mapping = "";
this.gamepad_.display_id = 0;
this.gamepad_.hand = device.mojom.GamepadHand.GamepadHandNone;
}
disconnectGamepad() {
this.gamepad_ = null;
}
setGamepadButtonCount(button_count) {
this.gamepad_.buttons = [];
for (let i = 0; i < button_count; ++i) {
this.gamepad_.buttons.push(new device.mojom.GamepadButton());
}
}
MockXRInputSource.prototype.connectGamepad = function() {
// Mojo complains if some of the properties on Gamepad are null, so set
// everything to reasonable defaults that tests can override.
this.gamepad_ = new device.mojom.Gamepad();
this.gamepad_.connected = true;
this.gamepad_.id = "unknown";
this.gamepad_.timestamp = 0;
this.gamepad_.axes = [];
this.gamepad_.buttons = [];
this.gamepad_.mapping = "";
this.gamepad_.display_id = 0;
this.gamepad_.hand = device.mojom.GamepadHand.GamepadHandNone;
};
setGamepadAxesCount(axes_count) {
this.gamepad_.axes = [];
for (let i = 0; i < axes_count; ++i) {
this.gamepad_.axes.push(0);
}
}
MockXRInputSource.prototype.disconnectGamepad = function() {
this.gamepad_ = null;
};
setGamepadButtonPressed(button_index, is_pressed) {
this.gamepad_.buttons[button_index].pressed = is_pressed;
MockXRInputSource.prototype.setGamepadButtonCount = function(button_count) {
this.gamepad_.buttons = [];
for (let i = 0; i < button_count; ++i) {
this.gamepad_.buttons.push(new device.mojom.GamepadButton());
}
};
setGamepadAxisValue(index, value) {
this.gamepad_.axes[index] = value;
MockXRInputSource.prototype.setGamepadAxesCount = function(axes_count) {
this.gamepad_.axes = [];
for (let i = 0; i < axes_count; ++i) {
this.gamepad_.axes.push(0);
}
};
getInputSourceState() {
let input_state = new device.mojom.XRInputSourceState();
input_state.sourceId = this.source_id_;
input_state.primaryInputPressed = this.primary_input_pressed_;
input_state.primaryInputClicked = this.primary_input_clicked_;
input_state.grip = this.grip_;
input_state.gamepad = this.gamepad_;
if (this.desc_dirty_) {
let input_desc = new device.mojom.XRInputSourceDescription();
input_desc.emulatedPosition = this.emulated_position_;
switch (this.target_ray_mode_) {
case 'gaze':
input_desc.targetRayMode = device.mojom.XRTargetRayMode.GAZING;
break;
case 'tracked-pointer':
input_desc.targetRayMode = device.mojom.XRTargetRayMode.POINTING;
break;
}
switch (this.handedness_) {
case 'left':
input_desc.handedness = device.mojom.XRHandedness.LEFT;
break;
case 'right':
input_desc.handedness = device.mojom.XRHandedness.RIGHT;
break;
default:
input_desc.handedness = device.mojom.XRHandedness.NONE;
break;
}
input_desc.pointerOffset = this.pointer_offset_;
input_state.description = input_desc;
this.desc_dirty_ = false;
}
MockXRInputSource.prototype.setGamepadButtonPressed = function(button_index, is_pressed) {
this.gamepad_.buttons[button_index].pressed = is_pressed;
};
return input_state;
}
}
MockXRInputSource.prototype.setGamepadAxisValue = function(index, value) {
this.gamepad_.axes[index] = value;
};
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -28,11 +27,7 @@ let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) =
assert_equals(input_sources.length, 0);
});
let input_source_1 = new MockXRInputSource();
input_source_1.targetRayMode = "tracked-pointer";
input_source_1.handedness = "right";
fakeDeviceController.addInputSource(input_source_1);
let input_source_1 = fakeDeviceController.simulateInputSourceConnection(RIGHT_CONTROLLER);
session.requestAnimationFrame((time, xrFrame) => {
let input_sources = session.inputSources;
......@@ -43,10 +38,12 @@ let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) =
assert_equals(input_sources[0].handedness, "right");
});
let input_source_2 = new MockXRInputSource();
input_source_2.targetRayMode = "gaze";
input_source_2.emulatedPosition = "true";
fakeDeviceController.addInputSource(input_source_2);
let input_source_2 = fakeDeviceController.simulateInputSourceConnection({
handedness: "none",
targetRayMode: "gaze",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: []
});
session.requestAnimationFrame((time, xrFrame) => {
let input_sources = session.inputSources;
......
......@@ -101,9 +101,8 @@ let testFunction = function(session, t, fakeDeviceController) {
// 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 = new MockXRInputSource();
let input_source = fakeDeviceController.simulateInputSourceConnection(RIGHT_CONTROLLER);
input_source.connectGamepad();
fakeDeviceController.addInputSource(input_source);
// Input events need one frame to propagate, so this does (in order and running
// a rAF after each step:
......@@ -119,9 +118,9 @@ let testFunction = function(session, t, fakeDeviceController) {
session.requestAnimationFrame(() => {
input_source.connectGamepad();
session.requestAnimationFrame(() => {
fakeDeviceController.removeInputSource(input_source);
input_source.disconnect();
session.requestAnimationFrame(() => {
fakeDeviceController.addInputSource(input_source);
input_source.reconnect();
session.requestAnimationFrame(() => {
eventPromise.then(() => {
session.end().then(() => {
......
......@@ -34,11 +34,10 @@ let testFunction = function(session, t, fakeDeviceController) {
// 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 = new MockXRInputSource();
let input_source = fakeDeviceController.simulateInputSourceConnection(RIGHT_CONTROLLER);
input_source.connectGamepad();
input_source.setGamepadButtonCount(1);
input_source.setGamepadAxesCount(2);
fakeDeviceController.addInputSource(input_source);
let cached_input_source = null;
let cached_gamepad = null;
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -45,26 +44,22 @@ let testFunction =
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
const GRIP_MATRIX_WITH_ROTATION = [
0, 0, -1, 0, // 1st col
0, 1, 0, 0, // 2nd col
1, 0, 0, 0, // 3rd col
1, 2, 3, 1 // 4th col
];
const POINTER_OFFSET_WITH_ROTATION = [
0, 1, 0, 0, // 1st col
-1, 0, 0, 0, // 2nd col
0, 0, 1, 0, // 3rd col
2, 0, 1, 1 // 4th col
];
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
input_source.handedness = "right";
input_source.grip = GRIP_MATRIX_WITH_ROTATION;
input_source.pointerOffset = POINTER_OFFSET_WITH_ROTATION;
fakeDeviceController.addInputSource(input_source);
const GRIP_TRANSFORM_WITH_ROTATION = {
position: [1, 2, 3],
orientation: [0, 0.7071, 0, 0.7071]
};
const POINTER_TRANSFORM_WITH_ROTATION = {
position: [2, 0, 1],
orientation: [0, 0, 0.7071, 0.7071]
};
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: POINTER_TRANSFORM_WITH_ROTATION,
gripOrigin: GRIP_TRANSFORM_WITH_ROTATION
});
const RADIANS_90D = Math.PI / 2;
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -56,27 +55,22 @@ function testFunction(session, t, fakeDeviceController) {
// Session must have a baseLayer or frame requests will be ignored.
session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) });
const INITIAL_GRIP_MATRIX = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
1, 2, 3, 1,
];
const LOCAL_POINTER_OFFSET = [
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0.01, 0.02, 0.03, 1,
];
let input_source = new MockXRInputSource();
input_source.targetRayMode = "tracked-pointer";
input_source.handedness = "right";
input_source.grip = INITIAL_GRIP_MATRIX;
input_source.pointerOffset = LOCAL_POINTER_OFFSET;
fakeDeviceController.addInputSource(input_source);
const INITIAL_GRIP_TRANSFORM = {
position: [1, 2, 3],
orientation: [0, 0, 0, 1]
};
const LOCAL_POINTER_TRANSFORM = {
position: [0.01, 0.02, 0.03],
orientation: [0, 0, 0, 1]
}
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: LOCAL_POINTER_TRANSFORM,
gripOrigin: INITIAL_GRIP_TRANSFORM
});
return new Promise((resolve, reject) => {
session.requestAnimationFrame((time, frame) => {
......
......@@ -5,7 +5,6 @@
<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script>
<script src="../external/wpt/resources/chromium/webxr-test.js"></script>
<script src="../external/wpt/webxr/resources/webxr_test_constants.js"></script>
<script src="../xr/resources/xr-internal-device-mocking.js"></script>
<script src="../xr/resources/xr-test-utils.js"></script>
<canvas id="webgl-canvas"></canvas>
......@@ -35,9 +34,13 @@ let testFunction = function(session, t, fakeDeviceController) {
// from event watchers, we just need to trigger the add/click to make the
// event listeners callback.
function sendClick(session) {
let input_source = new MockXRInputSource();
input_source.primaryInputClicked = true;
fakeDeviceController.addInputSource(input_source);
let input_source = fakeDeviceController.simulateInputSourceConnection({
handedness: "right",
targetRayMode: "tracked-pointer",
pointerOrigin: VALID_POINTER_TRANSFORM,
profiles: [],
selectionClicked: true
});
session.requestAnimationFrame(() => {});
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment