Skip to content

Commit 0fbf6ca

Browse files
committed
Switch unit tests to WebXR and fix vive(-focus)-controls
1 parent 3128eb5 commit 0fbf6ca

12 files changed

+156
-369
lines changed

src/components/vive-controls.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var isWebXRAvailable = require('../utils/').device.isWebXRAvailable;
1414
var GAMEPAD_ID_WEBXR = 'htc-vive';
1515
var GAMEPAD_ID_WEBVR = 'OpenVR ';
1616

17-
// Prefix for Gen1 and Gen2 Oculus Touch Controllers.
17+
// Prefix for HTC Vive Controllers.
1818
var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;
1919

2020
/**
@@ -44,16 +44,16 @@ var INPUT_MAPPING_WEBVR = {
4444
* Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/htc/htc-vive.json
4545
*/
4646
var INPUT_MAPPING_WEBXR = {
47-
axes: {thumbstick: [0, 1]},
48-
buttons: ['trigger', 'grip', 'trackpad', 'none', 'menu']
47+
axes: {touchpad: [0, 1]},
48+
buttons: ['trigger', 'grip', 'touchpad', 'none']
4949
};
5050

5151
var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;
5252

5353
/**
5454
* Vive controls.
5555
* Interface with Vive controllers and map Gamepad events to controller buttons:
56-
* trackpad, trigger, grip, menu, system
56+
* touchpad, trigger, grip, menu, system
5757
* Load a controller model and highlight the pressed buttons.
5858
*/
5959
module.exports.Component = registerComponent('vive-controls', {
@@ -209,6 +209,7 @@ module.exports.Component = registerComponent('vive-controls', {
209209
buttonMeshes.menu = controllerObject3D.getObjectByName('menubutton');
210210
buttonMeshes.system = controllerObject3D.getObjectByName('systembutton');
211211
buttonMeshes.trackpad = controllerObject3D.getObjectByName('touchpad');
212+
buttonMeshes.touchpad = controllerObject3D.getObjectByName('touchpad');
212213
buttonMeshes.trigger = controllerObject3D.getObjectByName('trigger');
213214

214215
// Set default colors.

src/components/vive-focus-controls.js

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,40 @@ var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresent
55
var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;
66
var onButtonEvent = trackedControlsUtils.onButtonEvent;
77

8-
var GAMEPAD_ID_PREFIX = 'HTC Vive Focus';
9-
108
var AFRAME_CDN_ROOT = require('../constants').AFRAME_CDN_ROOT;
119
var VIVE_FOCUS_CONTROLLER_MODEL_URL = AFRAME_CDN_ROOT + 'controllers/vive/focus-controller/focus-controller.gltf';
1210

11+
var isWebXRAvailable = require('../utils/').device.isWebXRAvailable;
12+
13+
var GAMEPAD_ID_WEBXR = 'htc-vive-focus';
14+
var GAMEPAD_ID_WEBVR = 'HTC Vive Focus ';
15+
16+
// Prefix for HTC Vive Focus Controllers.
17+
var GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;
18+
19+
/**
20+
* Button IDs:
21+
* 0 - trackpad
22+
* 1 - trigger
23+
*/
24+
var INPUT_MAPPING_WEBVR = {
25+
axes: {trackpad: [0, 1]},
26+
buttons: ['trackpad', 'trigger']
27+
};
28+
29+
/**
30+
* Button IDs:
31+
* 0 - trigger
32+
* 2 - touchpad
33+
* 4 - menu
34+
*/
35+
var INPUT_MAPPING_WEBXR = {
36+
axes: {touchpad: [0, 1]},
37+
buttons: ['trigger', 'none', 'touchpad', 'none', 'menu']
38+
};
39+
40+
var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;
41+
1342
/**
1443
* Vive Focus controls.
1544
* Interface with Vive Focus controller and map Gamepad events to
@@ -26,15 +55,7 @@ module.exports.Component = registerComponent('vive-focus-controls', {
2655
armModel: {default: true}
2756
},
2857

29-
/**
30-
* Button IDs:
31-
* 0 - trackpad
32-
* 1 - trigger
33-
*/
34-
mapping: {
35-
axes: {trackpad: [0, 1]},
36-
buttons: ['trackpad', 'trigger']
37-
},
58+
mapping: INPUT_MAPPING,
3859

3960
bindMethods: function () {
4061
this.onModelLoaded = this.onModelLoaded.bind(this);

src/utils/device.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var supportsARSession = false;
88
* Oculus Browser 7 doesn't support the WebXR gamepads module.
99
* We fallback to WebVR API and will hotfix when implementation is complete.
1010
*/
11-
var isWebXRAvailable = module.exports.isWebXRAvailable = !window.debug && navigator.xr !== undefined;
11+
var isWebXRAvailable = module.exports.isWebXRAvailable = navigator.xr !== undefined;
1212

1313
// Catch vrdisplayactivate early to ensure we can enter VR mode after the scene loads.
1414
window.addEventListener('vrdisplayactivate', function (evt) {

tests/__init.test.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
/* global sinon, setup, teardown */
1+
/* global EventTarget, sinon, setup, teardown */
22

33
/**
44
* __init.test.js is run before every test case.
55
*/
66
window.debug = true;
77

8+
/* WebVR Stub */
89
navigator.getVRDisplays = function () {
910
var resolvePromise = Promise.resolve();
1011
var mockVRDisplay = {
@@ -19,6 +20,16 @@ navigator.getVRDisplays = function () {
1920
return Promise.resolve([mockVRDisplay]);
2021
};
2122

23+
/* WebXR Stub */
24+
navigator.xr = navigator.xr || {};
25+
navigator.xr.isSessionSupported = function (_sessionType) { return Promise.resolve(true); };
26+
navigator.xr.requestSession = function (_mode) {
27+
const xrSession = new EventTarget();
28+
xrSession.supportedFrameRates = [90];
29+
xrSession.requestReferenceSpace = function () { return Promise.resolve(); };
30+
return Promise.resolve(xrSession);
31+
};
32+
2233
const AFRAME = require('index');
2334
var AScene = require('core/scene/a-scene').AScene;
2435
// Make sure WebGL context is not created since CI runs headless.
@@ -28,7 +39,7 @@ AScene.prototype.setupRenderer = function () {};
2839
setup(function () {
2940
window.AFRAME = AFRAME;
3041
this.sinon = sinon.createSandbox();
31-
// Stubs to not create a WebGL context since Travis CI runs headless.
42+
// Stubs to not create a WebGL context since CI runs headless.
3243
this.sinon.stub(AScene.prototype, 'render');
3344
this.sinon.stub(AScene.prototype, 'setupRenderer');
3445
// Mock renderer.

tests/components/oculus-go-controls.test.js

Lines changed: 11 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,9 @@ suite('oculus-go-controls', function () {
1111
component.controllers = [];
1212
// Our Mock data for enabling the controllers.
1313
component.controllersWhenPresent = [{
14-
id: 'Oculus Go Controller',
15-
index: 0,
16-
hand: 'right',
17-
axes: [0, 0],
18-
buttons: [
19-
{value: 0, pressed: false, touched: false},
20-
{value: 0, pressed: false, touched: false}
21-
],
22-
pose: {orientation: [1, 0, 0, 0], position: null}
14+
profiles: ['oculus-go'],
15+
handedness: 'right'
2316
}];
24-
el.parentEl.renderer.xr.getStandingMatrix = function () {};
2517
done();
2618
};
2719
if (el.hasLoaded) { callback(); }
@@ -37,7 +29,7 @@ suite('oculus-go-controls', function () {
3729

3830
setup(function (done) {
3931
component = this.el.components['oculus-go-controls'];
40-
controllerSystem = this.el.sceneEl.systems['tracked-controls-webvr'];
32+
controllerSystem = this.el.sceneEl.systems['tracked-controls-webxr'];
4133
addEventListenersSpy = sinon.spy(component, 'addEventListeners');
4234
injectTrackedControlsSpy = sinon.spy(component, 'injectTrackedControls');
4335
removeEventListenersSpy = sinon.spy(component, 'removeEventListeners');
@@ -117,14 +109,14 @@ suite('oculus-go-controls', function () {
117109
});
118110

119111
suite('axismove', function () {
120-
test('emits trackpadmoved on axismove', function (done) {
112+
test('emits touchpadmoved on axismove', function (done) {
121113
var el = this.el;
122114
setupTestControllers(el);
123115

124116
// Configure the event state for which we'll use the axis state for verification.
125117
const eventState = {axis: [0.1, 0.2], changed: [true, false]};
126118

127-
el.addEventListener('trackpadmoved', function (evt) {
119+
el.addEventListener('touchpadmoved', function (evt) {
128120
assert.equal(evt.detail.x, eventState.axis[0]);
129121
assert.equal(evt.detail.y, eventState.axis[1]);
130122
done();
@@ -133,13 +125,13 @@ suite('oculus-go-controls', function () {
133125
el.emit('axismove', eventState);
134126
});
135127

136-
test('does not emit trackpadmoved on axismove with no changes', function (done) {
128+
test('does not emit touchpadmoved on axismove with no changes', function (done) {
137129
var el = this.el;
138130
setupTestControllers(el);
139131

140132
// Fail purposely.
141-
el.addEventListener('trackpadmoved', function (evt) {
142-
assert.fail('trackpadmoved was called when there was no change.');
133+
el.addEventListener('touchpadmoved', function (evt) {
134+
assert.fail('touchpadmoved was called when there was no change.');
143135
});
144136

145137
el.emit('axismove', {axis: [0.1, 0.2], changed: [false, false]});
@@ -148,8 +140,8 @@ suite('oculus-go-controls', function () {
148140
});
149141

150142
suite('buttonchanged', function () {
151-
[{ button: 'trackpad', id: 0 },
152-
{ button: 'trigger', id: 1 }
143+
[{ button: 'trigger', id: 0 },
144+
{ button: 'touchpad', id: 2 }
153145
].forEach(function (buttonDescription) {
154146
test('if we get buttonchanged for button ' + buttonDescription.id + ', emit ' + buttonDescription.button + 'changed', function (done) {
155147
var el = this.el;
@@ -190,69 +182,14 @@ suite('oculus-go-controls', function () {
190182
});
191183
});
192184

193-
suite('armModel', function () {
194-
test('does not apply armModel if armModel disabled', function () {
195-
var el = this.el;
196-
el.setAttribute('oculus-go-controls', 'armModel', false);
197-
setupTestControllers(el);
198-
199-
var trackedControls = el.components['tracked-controls-webvr'];
200-
var applyArmModelSpy = sinon.spy(trackedControls, 'applyArmModel');
201-
trackedControls.tick();
202-
203-
// Verify that the function which applies arm model is not called when disabled.
204-
sinon.assert.notCalled(applyArmModelSpy);
205-
206-
// Additionally verify that no other offsets have been applied.
207-
assert.strictEqual(el.object3D.position.x, 0);
208-
assert.strictEqual(el.object3D.position.y, 0);
209-
assert.strictEqual(el.object3D.position.z, 0);
210-
});
211-
212-
test('applies armModel if armModel enabled', function () {
213-
var el = this.el;
214-
el.setAttribute('oculus-go-controls', 'armModel', true);
215-
setupTestControllers(el);
216-
217-
var trackedControls = el.components['tracked-controls-webvr'];
218-
var applyArmModelSpy = sinon.spy(trackedControls, 'applyArmModel');
219-
trackedControls.tick();
220-
221-
// Verify that the function which applies arm model is called.
222-
sinon.assert.calledOnce(applyArmModelSpy);
223-
});
224-
225-
test('verifies armModel position is applied for the right hand', function () {
226-
var el = this.el;
227-
el.setAttribute('oculus-go-controls', 'armModel', true);
228-
setupTestControllers(el);
229-
230-
var trackedControls = el.components['tracked-controls-webvr'];
231-
trackedControls.tick();
232-
assert.ok(el.object3D.position.x > 0);
233-
});
234-
235-
test('verifies armModel position is applied for the left hand', function () {
236-
var el = this.el;
237-
el.setAttribute('oculus-go-controls', 'armModel', true);
238-
el.setAttribute('oculus-go-controls', 'hand', 'left');
239-
el.components['oculus-go-controls'].controllersWhenPresent[0].hand = 'left';
240-
setupTestControllers(el);
241-
242-
var trackedControls = el.components['tracked-controls-webvr'];
243-
trackedControls.tick();
244-
assert.ok(el.object3D.position.x < 0);
245-
});
246-
});
247-
248185
/**
249186
* Establishes the baseline set of controllers needed for the tests to run.
250187
*
251188
* @param {object} el - The current entity factory.
252189
*/
253190
function setupTestControllers (el) {
254191
var component = el.components['oculus-go-controls'];
255-
el.sceneEl.systems['tracked-controls-webvr'].controllers = component.controllersWhenPresent;
192+
el.sceneEl.systems['tracked-controls-webxr'].controllers = component.controllersWhenPresent;
256193
component.checkIfControllerPresent();
257194
}
258195
});

tests/components/oculus-touch-controls.test.js

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ suite('oculus-touch-controls', function () {
1414
component.controllers = [];
1515
// Our Mock data for enabling the controllers.
1616
component.controllersWhenPresent = [{
17-
id: 'Oculus Touch',
18-
index: 0,
19-
hand: 'left',
20-
pose: {}
17+
profiles: ['oculus-touch'],
18+
handedness: 'left'
2119
}];
2220
done();
2321
};
@@ -34,7 +32,7 @@ suite('oculus-touch-controls', function () {
3432

3533
setup(function (done) {
3634
component = this.el.components['oculus-touch-controls'];
37-
controllerSystem = this.el.sceneEl.systems['tracked-controls-webvr'];
35+
controllerSystem = this.el.sceneEl.systems['tracked-controls-webxr'];
3836
controllerSystem.vrDisplay = true;
3937
addEventListenersSpy = sinon.spy(component, 'addEventListeners');
4038
injectTrackedControlsSpy = sinon.spy(component, 'injectTrackedControls');
@@ -118,7 +116,7 @@ suite('oculus-touch-controls', function () {
118116
var controllerSystem;
119117

120118
setup(function (done) {
121-
controllerSystem = this.el.sceneEl.systems['tracked-controls-webvr'];
119+
controllerSystem = this.el.sceneEl.systems['tracked-controls-webxr'];
122120
controllerSystem.controllers = component.controllersWhenPresent;
123121
controllerSystem.vrDisplay = true;
124122
done();
@@ -128,11 +126,11 @@ suite('oculus-touch-controls', function () {
128126
// Do the check.
129127
component.checkIfControllerPresent();
130128
// Set up the event details.
131-
const eventDetails = {axis: [0.1, 0.2], changed: [true, false]};
129+
const eventDetails = {axis: [0.1, 0.2, 0.3, 0.4], changed: [false, false, true, false]};
132130
// Install event handler listening for thumbstickmoved.
133131
this.el.addEventListener('thumbstickmoved', function (evt) {
134-
assert.equal(evt.detail.x, eventDetails.axis[0]);
135-
assert.equal(evt.detail.y, eventDetails.axis[1]);
132+
assert.equal(evt.detail.x, eventDetails.axis[2]);
133+
assert.equal(evt.detail.y, eventDetails.axis[3]);
136134
done();
137135
});
138136
// Emit axismove.
@@ -147,15 +145,14 @@ suite('oculus-touch-controls', function () {
147145
assert.fail('thumbstickmoved should not be called');
148146
});
149147
// Emit axismove with no changes.
150-
this.el.emit('axismove', {axis: [0.1, 0.2], changed: [false, false]});
148+
this.el.emit('axismove', {axis: [0.1, 0.2, 0.3, 0.4], changed: [false, false, false, false]});
151149
setTimeout(() => { done(); });
152150
});
153151
});
154152

155153
suite('buttonchanged', function () {
156154
test('can emit triggerchanged', function (done) {
157-
el.sceneEl.systems['tracked-controls-webvr'].controllers = component.controllersWhenPresent;
158-
el.sceneEl.systems['tracked-controls-webvr'].vrDisplay = true;
155+
el.sceneEl.systems['tracked-controls-webxr'].controllers = component.controllersWhenPresent;
159156
// Do the check.
160157
component.checkIfControllerPresent();
161158
// Prepare the event details
@@ -166,7 +163,7 @@ suite('oculus-touch-controls', function () {
166163
done();
167164
});
168165
// Emit buttonchanged.
169-
el.emit('buttonchanged', {id: 1, state: eventState});
166+
el.emit('buttonchanged', {id: 0, state: eventState});
170167
});
171168
});
172169
});

tests/components/scene/xr-mode-ui.test.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
/* global assert, process, setup, suite, test */
22
var entityFactory = require('../../helpers').entityFactory;
3-
var utils = require('index').utils;
43

54
var UI_CLASSES = ['.a-orientation-modal', '.a-enter-vr-button'];
65

76
suite('xr-mode-ui', function () {
87
setup(function (done) {
98
this.entityEl = entityFactory();
109
var el = this.el = this.entityEl.parentNode;
11-
this.sinon.stub(utils.device, 'getVRDisplay').returns({
12-
requestPresent: function () {
13-
return Promise.resolve();
14-
}
15-
});
1610
el.addEventListener('loaded', function () { done(); });
1711
});
1812

@@ -38,7 +32,6 @@ suite('xr-mode-ui', function () {
3832
el: {object3D: {}},
3933
updateProjectionMatrix: function () {}
4034
};
41-
window.hasNativeWebVRImplementation = false;
4235
scene.enterVR();
4336
UI_CLASSES.forEach(function (uiClass) {
4437
assert.ok(scene.querySelector(uiClass).className.indexOf('a-hidden'));
@@ -52,7 +45,6 @@ suite('xr-mode-ui', function () {
5245
el: {object3D: {}, getAttribute: function () { return {spectator: false}; }},
5346
updateProjectionMatrix: function () {}
5447
};
55-
window.hasNativeWebVRImplementation = false;
5648
scene.enterVR();
5749
scene.exitVR();
5850

0 commit comments

Comments
 (0)