-
-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathtracked-controls.js
142 lines (125 loc) · 4.65 KB
/
tracked-controls.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
var AXIS_LABELS = ['x', 'y', 'z', 'w'];
/**
* Called on controller component `.play` handlers.
* Check if controller matches parameters and inject tracked-controls component.
* Handle event listeners.
* Generate controllerconnected or controllerdisconnected events.
*
* @param {object} component - Tracked controls component.
* @param {object} idPrefix - Prefix to match in gamepad id if any.
* @param {object} queryObject - Map of values to match.
*/
module.exports.checkControllerPresentAndSetup = function (component, idPrefix, queryObject) {
var el = component.el;
var controller;
var isControllerPresent = isControllerPresentWebXR;
var isPresent;
controller = isControllerPresent(component, idPrefix, queryObject);
isPresent = !!controller;
// Nothing changed, no need to do anything.
if (isPresent === component.controllerPresent) { return isPresent; }
component.controllerPresent = isPresent;
// Update controller presence.
if (isPresent) {
component.addEventListeners();
component.injectTrackedControls(controller);
el.emit('controllerconnected', {name: component.name, component: component});
} else {
component.removeEventListeners();
el.emit('controllerdisconnected', {name: component.name, component: component});
}
};
/**
*
* @param {object} component - Tracked controls component.
*/
function isControllerPresentWebXR (component, id, queryObject) {
var controllers;
var sceneEl = component.el.sceneEl;
var trackedControlsSystem = sceneEl && sceneEl.systems['tracked-controls'];
if (!trackedControlsSystem) { return false; }
controllers = trackedControlsSystem.controllers;
if (!controllers || !controllers.length) { return false; }
return findMatchingControllerWebXR(
controllers, id,
queryObject.hand, queryObject.index, queryObject.iterateControllerProfiles, queryObject.handTracking);
}
module.exports.isControllerPresentWebXR = isControllerPresentWebXR;
function findMatchingControllerWebXR (controllers, idPrefix, handedness, index, iterateProfiles, handTracking) {
var i;
var j;
var controller;
var controllerMatch = false;
var controllerHasHandedness;
var profiles;
for (i = 0; i < controllers.length; i++) {
controller = controllers[i];
profiles = controller.profiles;
if (handTracking) {
controllerMatch = controller.hand;
} else {
if (iterateProfiles) {
for (j = 0; j < profiles.length; j++) {
controllerMatch = profiles[j].startsWith(idPrefix);
if (controllerMatch) { break; }
}
} else {
controllerMatch = profiles.length > 0 && profiles[0].startsWith(idPrefix);
}
}
if (!controllerMatch) { continue; }
// Vive controllers are assigned handedness at runtime and it might not be always available.
controllerHasHandedness = controller.handedness === 'right' || controller.handedness === 'left';
if (controllerHasHandedness) {
if (controller.handedness === handedness) { return controllers[i]; }
} else { // Fallback to index if controller has no handedness.
if ((i === index)) { return controllers[i]; }
}
}
return undefined;
}
module.exports.findMatchingControllerWebXR = findMatchingControllerWebXR;
/**
* Emit specific `moved` event(s) if axes changed based on original axismove event.
*
* @param {object} component - Controller component in use.
* @param {array} axesMapping - For example `{thumbstick: [0, 1]}`.
* @param {object} evt - Event to process.
*/
module.exports.emitIfAxesChanged = function (component, axesMapping, evt) {
var axes;
var buttonType;
var changed;
var detail;
var j;
for (buttonType in axesMapping) {
axes = axesMapping[buttonType];
changed = false;
for (j = 0; j < axes.length; j++) {
if (evt.detail.changed[axes[j]]) { changed = true; }
}
if (!changed) { continue; }
// Axis has changed. Emit the specific moved event with axis values in detail.
detail = {};
for (j = 0; j < axes.length; j++) {
detail[AXIS_LABELS[j]] = evt.detail.axis[axes[j]];
}
component.el.emit(buttonType + 'moved', detail);
}
};
/**
* Handle a button event and reemits the events.
*
* @param {string} id - id of the button.
* @param {string} evtName - name of the reemitted event
* @param {object} component - reference to the component
* @param {string} hand - handedness of the controller: left or right.
*/
module.exports.onButtonEvent = function (id, evtName, component, hand) {
var mapping = hand ? component.mapping[hand] : component.mapping;
var buttonName = mapping.buttons[id];
component.el.emit(buttonName + evtName);
if (component.updateModel) {
component.updateModel(buttonName, evtName);
}
};