Skip to content

Commit

Permalink
Merge pull request #3489 from chenzlabs/simple-fix-for-gearvr-touch
Browse files Browse the repository at this point in the history
simple fix for Gear VR and Oculus Touch controller issues (fixes #3447 and #3483)
  • Loading branch information
ngokevin committed Mar 23, 2018
2 parents d872aed + f47a61f commit f69494d
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 45 deletions.
17 changes: 1 addition & 16 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module.exports.entity = require('./entity');
module.exports.forceCanvasResizeSafariMobile = require('./forceCanvasResizeSafariMobile');
module.exports.material = require('./material');
module.exports.objectPool = objectPool;
module.exports.split = require('./split').split;
module.exports.styleParser = require('./styleParser');
module.exports.trackedControls = require('./tracked-controls');

Expand Down Expand Up @@ -322,19 +323,3 @@ module.exports.findAllScenes = function (el) {

// Must be at bottom to avoid circular dependency.
module.exports.srcLoader = require('./src-loader');

/**
* String split with cached result.
*/
module.exports.split = (function () {
var splitCache = {};

return function (str, delimiter) {
if (!(delimiter in splitCache)) { splitCache[delimiter] = {}; }

if (str in splitCache[delimiter]) { return splitCache[delimiter][str]; }

splitCache[delimiter][str] = str.split(delimiter);
return splitCache[delimiter][str];
};
})();
15 changes: 15 additions & 0 deletions src/utils/split.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* String split with cached result.
*/
module.exports.split = (function () {
var splitCache = {};

return function (str, delimiter) {
if (!(delimiter in splitCache)) { splitCache[delimiter] = {}; }

if (str in splitCache[delimiter]) { return splitCache[delimiter][str]; }

splitCache[delimiter][str] = str.split(delimiter);
return splitCache[delimiter][str];
};
})();
78 changes: 49 additions & 29 deletions src/utils/tracked-controls.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
var split = require('./split').split;

var DEFAULT_HANDEDNESS = require('../constants').DEFAULT_HANDEDNESS;
var AXIS_LABELS = ['x', 'y', 'z', 'w'];
var NUM_HANDS = 2; // Number of hands in a pair. Should always be 2.
var NUM_HANDS = 2; // Number of hands in a pair. Should always be 2.

/**
* Called on controller component `.play` handlers.
Expand Down Expand Up @@ -60,65 +62,85 @@ function isControllerPresent (component, idPrefix, queryObject) {
gamepads = trackedControlsSystem.controllers;
if (!gamepads.length) { return false; }

return !!findMatchingController(gamepads, null, idPrefix, queryObject.hand, filterControllerIndex);
return !!findMatchingController(gamepads, null, idPrefix, queryObject.hand,
filterControllerIndex);
}

module.exports.isControllerPresent = isControllerPresent;

/**
* Walk through the given controllers to find any where the device ID equals filterIdExact, or startWith filterIdPrefix.
* Walk through the given controllers to find any where the device ID equals
* filterIdExact, or startWith filterIdPrefix.
* A controller where this considered true is considered a 'match'.
*
* For each matching controller:
* If filterHand is set, and the controller:
* is handed, we further verify that controller.hand equals filterHand.
* is unhanded (controller.hand is ''), we skip until we have found a number of matching controllers that equals filterControllerIndex
* If filterHand is not set, we skip until we have found the nth matching controller, where n equals filterControllerIndex
* is unhanded (controller.hand is ''), we skip until we have found a
* number of matching controllers that equals filterControllerIndex
* If filterHand is not set, we skip until we have found the nth matching
* controller, where n equals filterControllerIndex
*
* The method should be called with one of: [filterIdExact, filterIdPrefix] AND one or both of: [filterHand, filterControllerIndex]
* The method should be called with one of: [filterIdExact, filterIdPrefix] AND
* one or both of: [filterHand, filterControllerIndex]
*
* @param {object} controllers - Array of gamepads to search
* @param {string} filterIdExact - If set, used to find controllers with id === this value
* @param {string} filterIdPrefix - If set, used to find controllers with id startsWith this value
* @param {object} filterHand - If set, further filters controllers with matching 'hand' property
* @param {object} filterControllerIndex - Find the nth matching controller, where n equals filterControllerIndex. defaults to 0.
* @param {object} filterControllerIndex - Find the nth matching controller,
* where n equals filterControllerIndex. defaults to 0.
*/
function findMatchingController (controllers, filterIdExact, filterIdPrefix, filterHand, filterControllerIndex) {
function findMatchingController (controllers, filterIdExact, filterIdPrefix, filterHand,
filterControllerIndex) {
var controller;
var filterIdPrefixes;
var i;
var j;
var matches;
var matchingControllerOccurence = 0;
var prefix;
var targetControllerMatch = filterControllerIndex || 0;
var filterIdPrefixes;

// Check whether multiple prefixes.
if (filterIdPrefix && filterIdPrefix.indexOf('|') >= 0) {
filterIdPrefixes = filterIdPrefix.split('|');
filterIdPrefixes = split(filterIdPrefix, '|');
}

for (i = 0; i < controllers.length; i++) {
controller = controllers[i];
// Determine if the controller ID matches our criteria

// Determine if the controller ID matches our criteria.
if (filterIdPrefixes) {
var matches = false;
for (var prefix in filterIdPrefixes) {
if (prefix && controller.id.indexOf(prefix) === -1) { matches = true; }
matches = false;
for (j = 0; j < filterIdPrefixes.length; j++) {
prefix = filterIdPrefixes[j];
if (prefix && controller.id.startsWith(prefix)) {
matches = true;
break;
}
}
if (!matches) { continue; }
} else
if (filterIdPrefix && controller.id.indexOf(filterIdPrefix) === -1) { continue; }
} else if (filterIdPrefix && controller.id.indexOf(filterIdPrefix)) {
continue;
}

if (!filterIdPrefix && controller.id !== filterIdExact) { continue; }

// If the hand filter and controller handedness are defined we compare them.
if (filterHand && controller.hand && filterHand !== controller.hand) { continue; }

// If we have detected an unhanded controller and the component was asking for a particular hand,
// we need to treat the controllers in the array as pairs of controllers. This effectively means that we
// need to skip NUM_HANDS matches for each controller number, instead of 1.
// If we have detected an unhanded controller and the component was asking
// for a particular hand, we need to treat the controllers in the array as
// pairs of controllers. This effectively means that we need to skip
// NUM_HANDS matches for each controller number, instead of 1.
if (filterHand && !controller.hand) {
targetControllerMatch = NUM_HANDS * filterControllerIndex + ((filterHand === DEFAULT_HANDEDNESS) ? 0 : 1);
}

// We are looking for the nth occurence of a matching controller (n equals targetControllerMatch).
if (matchingControllerOccurence === targetControllerMatch) {
return controller;
}
// We are looking for the nth occurence of a matching controller
// (n equals targetControllerMatch).
if (matchingControllerOccurence === targetControllerMatch) { return controller; }
++matchingControllerOccurence;
}
return undefined;
Expand All @@ -135,15 +157,13 @@ module.exports.findMatchingController = findMatchingController;
*/
module.exports.emitIfAxesChanged = function (component, axesMapping, evt) {
var axes;
var buttonTypes;
var buttonType;
var changed;
var detail;
var i;
var j;

buttonTypes = Object.keys(axesMapping);
for (i = 0; i < buttonTypes.length; i++) {
axes = axesMapping[buttonTypes[i]];
for (buttonType in axesMapping) {
axes = axesMapping[buttonType];

changed = false;
for (j = 0; j < axes.length; j++) {
Expand All @@ -157,7 +177,7 @@ module.exports.emitIfAxesChanged = function (component, axesMapping, evt) {
for (j = 0; j < axes.length; j++) {
detail[AXIS_LABELS[j]] = evt.detail.axis[axes[j]];
}
component.el.emit(buttonTypes[i] + 'moved', detail);
component.el.emit(buttonType + 'moved', detail);
}
};

Expand Down

0 comments on commit f69494d

Please sign in to comment.