remove jQuery dependencies
This commit is contained in:
parent
eca6c946f6
commit
ea8d03386d
51
css/main.css
51
css/main.css
@ -120,15 +120,10 @@ body.unsupported #gamepad {
|
|||||||
align-self: center;
|
align-self: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay > span {
|
#overlay>span {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlay #color,
|
|
||||||
#overlay #triggers {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
#overlay select {
|
#overlay select {
|
||||||
padding: 4px 0;
|
padding: 4px 0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@ -212,7 +207,7 @@ body.unsupported #gamepad {
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popout table > thead > tr > th {
|
.popout table>thead>tr>th {
|
||||||
border-bottom: 2px solid #ddd;
|
border-bottom: 2px solid #ddd;
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
@ -252,13 +247,11 @@ kbd {
|
|||||||
inset 0 -0.05em 0.4em rgb(80, 80, 80), 0 0.1em 0 rgb(30, 30, 30),
|
inset 0 -0.05em 0.4em rgb(80, 80, 80), 0 0.1em 0 rgb(30, 30, 30),
|
||||||
0 0.1em 0.1em rgba(0, 0, 0, 0.3);
|
0 0.1em 0.1em rgba(0, 0, 0, 0.3);
|
||||||
background: -moz-linear-gradient(top, rgb(60, 60, 60), rgb(80, 80, 80));
|
background: -moz-linear-gradient(top, rgb(60, 60, 60), rgb(80, 80, 80));
|
||||||
background: -webkit-gradient(
|
background: -webkit-gradient(linear,
|
||||||
linear,
|
left top,
|
||||||
left top,
|
left bottom,
|
||||||
left bottom,
|
from(rgb(60, 60, 60)),
|
||||||
from(rgb(60, 60, 60)),
|
to(rgb(80, 80, 80)));
|
||||||
to(rgb(80, 80, 80))
|
|
||||||
);
|
|
||||||
background: rgb(80, 80, 80);
|
background: rgb(80, 80, 80);
|
||||||
box-shadow: inset 0 0 1px rgb(150, 150, 150),
|
box-shadow: inset 0 0 1px rgb(150, 150, 150),
|
||||||
inset 0 -0.05em 0.4em rgb(80, 80, 80), 0 0.1em 0 rgb(30, 30, 30),
|
inset 0 -0.05em 0.4em rgb(80, 80, 80), 0 0.1em 0 rgb(30, 30, 30),
|
||||||
@ -266,3 +259,33 @@ kbd {
|
|||||||
color: rgb(250, 250, 250);
|
color: rgb(250, 250, 250);
|
||||||
text-shadow: -1px -1px 0 rgb(70, 70, 70);
|
text-shadow: -1px -1px 0 rgb(70, 70, 70);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fadeIn {
|
||||||
|
animation: fadeIn 300ms;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fadeOut {
|
||||||
|
animation: fadeOut 1s;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -113,13 +113,13 @@
|
|||||||
<option value="magenta">Magenta</option>
|
<option value="magenta">Magenta</option>
|
||||||
</select>
|
</select>
|
||||||
</span>
|
</span>
|
||||||
<span id="color">
|
<span id="color" style="display: none;">
|
||||||
<label for="color">Color</label>
|
<label for="color">Color</label>
|
||||||
<select name="color">
|
<select name="color">
|
||||||
<option value="">Default</option>
|
<option value="">Default</option>
|
||||||
</select>
|
</select>
|
||||||
</span>
|
</span>
|
||||||
<span id="triggers">
|
<span id="triggers" style="display: none;">
|
||||||
<label for="triggers">Triggers</label>
|
<label for="triggers">Triggers</label>
|
||||||
<select name="triggers">
|
<select name="triggers">
|
||||||
<option value="opacity">Opacity</option>
|
<option value="opacity">Opacity</option>
|
||||||
@ -213,7 +213,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/jquery.min.js"></script>
|
|
||||||
<script src="js/gamepad.js"></script>
|
<script src="js/gamepad.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
467
js/gamepad.js
467
js/gamepad.js
@ -9,21 +9,21 @@ class Gamepad {
|
|||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
// cached DOM references
|
// cached DOM references
|
||||||
this.$body = $('body');
|
this.$body = document.querySelector('body');
|
||||||
this.$instructions = $('#instructions');
|
this.$instructions = document.querySelector('#instructions');
|
||||||
this.$placeholder = $('#placeholder');
|
this.$placeholder = document.querySelector('#placeholder');
|
||||||
this.$gamepad = $('#gamepad');
|
this.$gamepad = document.querySelector('#gamepad');
|
||||||
this.$overlay = $('#overlay');
|
this.$overlay = document.querySelector('#overlay');
|
||||||
this.$gamepadSelect = $('select[name=gamepad-id]');
|
this.$gamepadSelect = document.querySelector('select[name=gamepad-id]');
|
||||||
this.$skinSelect = $('select[name=skin]');
|
this.$skinSelect = document.querySelector('select[name=skin]');
|
||||||
this.$backgroundSelect = $('select[name=background]');
|
this.$backgroundSelect = document.querySelector('select[name=background]');
|
||||||
this.$colorOverlay = this.$overlay.find('#color');
|
this.$colorOverlay = this.$overlay.querySelector('#color');
|
||||||
this.$colorSelect = this.$colorOverlay.find('select[name=color]');
|
this.$colorSelect = this.$colorOverlay.querySelector('select[name=color]');
|
||||||
this.$triggersOverlay = this.$overlay.find('#triggers');
|
this.$triggersOverlay = this.$overlay.querySelector('#triggers');
|
||||||
this.$triggersSelect = this.$triggersOverlay.find('select[name=triggers]');
|
this.$triggersSelect = this.$triggersOverlay.querySelector('select[name=triggers]');
|
||||||
this.$helpPopout = $('#help.popout');
|
this.$helpPopout = document.querySelector('#help.popout');
|
||||||
this.$helpPopoutClose = this.$helpPopout.find('.close');
|
this.$helpPopoutClose = this.$helpPopout.querySelector('.close');
|
||||||
this.$gamepadList = $('#gamepad-list');
|
this.$gamepadList = document.querySelector('#gamepad-list');
|
||||||
|
|
||||||
// ensure the GamePad API is available on this browser
|
// ensure the GamePad API is available on this browser
|
||||||
this.assertGamepadAPI();
|
this.assertGamepadAPI();
|
||||||
@ -172,16 +172,16 @@ class Gamepad {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (backgroundStyleIndex) {
|
||||||
if (backgroundStyleIndex)
|
|
||||||
this.changeBackgroundStyle(backgroundStyleIndex);
|
this.changeBackgroundStyle(backgroundStyleIndex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// by default, enqueue a delayed display of the placeholder animation
|
// by default, enqueue a delayed display of the placeholder animation
|
||||||
this.displayPlaceholder();
|
this.displayPlaceholder();
|
||||||
|
|
||||||
// listen for keyboard events
|
// listen for keyboard events
|
||||||
this.$helpPopoutClose.on('click', this.toggleHelp.bind(this));
|
this.$helpPopoutClose.addEventListener('click', this.toggleHelp.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,7 +194,7 @@ class Gamepad {
|
|||||||
? () => navigator.webkitGetGamepads()
|
? () => navigator.webkitGetGamepads()
|
||||||
: null;
|
: null;
|
||||||
if (!getGamepadsFn) {
|
if (!getGamepadsFn) {
|
||||||
this.$body.addClass('unsupported');
|
this.$body.classList.add('unsupported');
|
||||||
throw new Error('Unsupported gamepad API');
|
throw new Error('Unsupported gamepad API');
|
||||||
}
|
}
|
||||||
this.getNavigatorGamepads = getGamepadsFn;
|
this.getNavigatorGamepads = getGamepadsFn;
|
||||||
@ -204,23 +204,65 @@ class Gamepad {
|
|||||||
* Initialises the overlay selectors
|
* Initialises the overlay selectors
|
||||||
*/
|
*/
|
||||||
initOverlaySelectors() {
|
initOverlaySelectors() {
|
||||||
this.$gamepadSelect.on('change', () =>
|
this.$gamepadSelect.addEventListener('change', () =>
|
||||||
this.changeGamepad(this.$gamepadSelect.val())
|
this.changeGamepad(this.$gamepadSelect.value)
|
||||||
);
|
);
|
||||||
this.$skinSelect.on('change', () =>
|
this.$skinSelect.addEventListener('change', () =>
|
||||||
this.changeSkin(this.$skinSelect.val())
|
this.changeSkin(this.$skinSelect.value)
|
||||||
);
|
);
|
||||||
this.$backgroundSelect.on('change', () =>
|
this.$backgroundSelect.addEventListener('change', () =>
|
||||||
this.changeBackgroundStyle(this.$backgroundSelect.val())
|
this.changeBackgroundStyle(this.$backgroundSelect.value)
|
||||||
);
|
);
|
||||||
this.$colorSelect.on('change', () =>
|
this.$colorSelect.addEventListener('change', () =>
|
||||||
this.changeGamepadColor(this.$colorSelect.val())
|
this.changeGamepadColor(this.$colorSelect.value)
|
||||||
);
|
);
|
||||||
this.$triggersSelect.on('change', () =>
|
this.$triggersSelect.addEventListener('change', () =>
|
||||||
this.toggleTriggersMeter(this.$triggersSelect.val() === 'meter')
|
this.toggleTriggersMeter(this.$triggersSelect.value === 'meter')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an HTML element
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} $element
|
||||||
|
*/
|
||||||
|
show($element) {
|
||||||
|
$element.style.removeProperty('display');
|
||||||
|
$element.classList.remove('fadeIn', 'fadeOut');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides an HTML element
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} $element
|
||||||
|
*/
|
||||||
|
hide($element) {
|
||||||
|
$element.style.setProperty('display', 'none');
|
||||||
|
$element.classList.remove('fadeIn', 'fadeOut');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades in an HTML element
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} $element
|
||||||
|
*/
|
||||||
|
fadeIn($element) {
|
||||||
|
$element.style.removeProperty('display');
|
||||||
|
$element.classList.remove('fadeOut');
|
||||||
|
$element.classList.add('fadeIn');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades out an HTML element
|
||||||
|
*
|
||||||
|
* @param {HTMLElement} $element
|
||||||
|
*/
|
||||||
|
fadeOut($element) {
|
||||||
|
$element.style.removeProperty('display');
|
||||||
|
$element.classList.remove('fadeIn');
|
||||||
|
$element.classList.add('fadeOut');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the instructions
|
* Displays the instructions
|
||||||
*/
|
*/
|
||||||
@ -228,10 +270,8 @@ class Gamepad {
|
|||||||
// do not display help if we have an active gamepad
|
// do not display help if we have an active gamepad
|
||||||
if (null !== this.index) return;
|
if (null !== this.index) return;
|
||||||
|
|
||||||
// cancel the queued display of the instructions animation, if any
|
|
||||||
window.clearTimeout(this.instructionsTimeout);
|
|
||||||
// show the instructions
|
// show the instructions
|
||||||
this.$instructions.show();
|
this.fadeIn(this.$instructions);
|
||||||
|
|
||||||
// enqueue a delayed display of the instructions animation
|
// enqueue a delayed display of the instructions animation
|
||||||
this.hideInstructions();
|
this.hideInstructions();
|
||||||
@ -243,15 +283,20 @@ class Gamepad {
|
|||||||
* @param {boolean} [hideNow=false]
|
* @param {boolean} [hideNow=false]
|
||||||
*/
|
*/
|
||||||
hideInstructions(hideNow = false) {
|
hideInstructions(hideNow = false) {
|
||||||
|
// cancel the queued display of the instructions animation, if any
|
||||||
|
window.clearTimeout(this.instructionsTimeout);
|
||||||
|
|
||||||
// hide the message right away if needed
|
// hide the message right away if needed
|
||||||
if (hideNow) {
|
if (hideNow) {
|
||||||
this.$instructions.hide();
|
this.hide(this.$instructions);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide instructions animation if no gamepad is active after X ms
|
// hide instructions animation if no gamepad is active after X ms
|
||||||
this.instructionsTimeout = window.setTimeout(() => {
|
this.instructionsTimeout = window.setTimeout(
|
||||||
this.$instructions.fadeOut();
|
() => this.fadeOut(this.$instructions),
|
||||||
}, this.instructionsDelay);
|
this.instructionsDelay
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,10 +306,8 @@ class Gamepad {
|
|||||||
// do not display help if we have an active gamepad
|
// do not display help if we have an active gamepad
|
||||||
if (null !== this.index) return;
|
if (null !== this.index) return;
|
||||||
|
|
||||||
// cancel the queued display of the placeholder animation, if any
|
|
||||||
window.clearTimeout(this.placeholderTimeout);
|
|
||||||
// show the placeholder
|
// show the placeholder
|
||||||
this.$placeholder.show();
|
this.fadeIn(this.$placeholder);
|
||||||
|
|
||||||
// enqueue a delayed display of the placeholder animation
|
// enqueue a delayed display of the placeholder animation
|
||||||
this.hidePlaceholder();
|
this.hidePlaceholder();
|
||||||
@ -276,25 +319,28 @@ class Gamepad {
|
|||||||
* @param {boolean} [hideNow=false]
|
* @param {boolean} [hideNow=false]
|
||||||
*/
|
*/
|
||||||
hidePlaceholder(hideNow = false) {
|
hidePlaceholder(hideNow = false) {
|
||||||
|
// cancel the queued display of the placeholder animation, if any
|
||||||
|
window.clearTimeout(this.placeholderTimeout);
|
||||||
|
|
||||||
// hide the animation right away if needed
|
// hide the animation right away if needed
|
||||||
if (hideNow) {
|
if (hideNow) {
|
||||||
this.$placeholder.hide();
|
this.hide(this.$placeholder);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide placeholder animation if no gamepad is active after X ms
|
// hide placeholder animation if no gamepad is active after X ms
|
||||||
this.placeholderTimeout = window.setTimeout(() => {
|
this.placeholderTimeout = window.setTimeout(
|
||||||
this.$placeholder.fadeOut();
|
() => this.fadeOut(this.$placeholder),
|
||||||
}, this.placeholderDelay);
|
this.placeholderDelay
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the overlay animation on screen
|
* Displays the overlay animation on screen
|
||||||
*/
|
*/
|
||||||
displayOverlay() {
|
displayOverlay() {
|
||||||
// cancel the queued display of the overlay animation, if any
|
|
||||||
window.clearTimeout(this.overlayTimeout);
|
|
||||||
// show the overlay
|
// show the overlay
|
||||||
this.$overlay.show();
|
this.fadeIn(this.$overlay);
|
||||||
|
|
||||||
// enqueue a delayed display of the overlay animation
|
// enqueue a delayed display of the overlay animation
|
||||||
this.hideOverlay();
|
this.hideOverlay();
|
||||||
@ -306,15 +352,20 @@ class Gamepad {
|
|||||||
* @param {boolean} [hideNow=false]
|
* @param {boolean} [hideNow=false]
|
||||||
*/
|
*/
|
||||||
hideOverlay(hideNow = false) {
|
hideOverlay(hideNow = false) {
|
||||||
|
// cancel the queued display of the overlay animation, if any
|
||||||
|
window.clearTimeout(this.overlayTimeout);
|
||||||
|
|
||||||
// hide the message right away if needed
|
// hide the message right away if needed
|
||||||
if (hideNow) {
|
if (hideNow) {
|
||||||
this.$overlay.hide();
|
this.hide(this.$overlay);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hide overlay animation if no gamepad is active after X ms
|
// hide overlay animation if no gamepad is active after X ms
|
||||||
this.overlayTimeout = window.setTimeout(() => {
|
this.overlayTimeout = window.setTimeout(
|
||||||
this.$overlay.fadeOut();
|
() => this.fadeOut(this.$overlay),
|
||||||
}, this.overlayDelay);
|
this.overlayDelay
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,19 +382,17 @@ class Gamepad {
|
|||||||
* Updates the list of connected gamepads in the overlay
|
* Updates the list of connected gamepads in the overlay
|
||||||
*/
|
*/
|
||||||
updateGamepadList() {
|
updateGamepadList() {
|
||||||
this.$gamepadSelect.find('.entry').remove();
|
this.$gamepadSelect.querySelectorAll('.entry').forEach($entry => $entry.remove());
|
||||||
const $options = [];
|
const $options = [];
|
||||||
for (let key = 0; key < this.gamepads.length; key++) {
|
for (let key = 0; key < this.gamepads.length; key++) {
|
||||||
const gamepad = this.gamepads[key];
|
const gamepad = this.gamepads[key];
|
||||||
if (!gamepad) {
|
if (!gamepad) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const { name } = this.toGamepadInfo(gamepad.id);
|
const { name } = this.toGamepadInfo(gamepad.id);
|
||||||
$options.push(
|
$options.push(
|
||||||
`<option class='entry' value='${gamepad.id}'>${name}</option>`
|
`<option class='entry' value='${gamepad.id}'>${name}</option>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.$gamepadSelect.append($options.join(''));
|
this.$gamepadSelect.innerHTML += $options.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -351,21 +400,21 @@ class Gamepad {
|
|||||||
*/
|
*/
|
||||||
updateColors() {
|
updateColors() {
|
||||||
if (!this.type) {
|
if (!this.type) {
|
||||||
this.$colorOverlay.hide();
|
this.hide(this.$colorOverlay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const colors = this.identifiers[this.type].colors;
|
const colors = this.identifiers[this.type].colors;
|
||||||
if (!colors) {
|
if (!colors) {
|
||||||
this.$colorOverlay.hide();
|
this.hide(this.$colorOverlay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const colorOptions = colors.map(
|
const colorOptions = colors.map(
|
||||||
(color) => `<option value='${color}'>${color.charAt(0).toUpperCase()}${color.slice(1)}</option>`
|
(color) => `<option value='${color}'>${color.charAt(0).toUpperCase()}${color.slice(1)}</option>`
|
||||||
);
|
);
|
||||||
this.$colorSelect.html(colorOptions);
|
this.$colorSelect.innerHTML = colorOptions.join('');
|
||||||
this.$colorOverlay.fadeIn();
|
this.show(this.$colorOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -373,17 +422,17 @@ class Gamepad {
|
|||||||
*/
|
*/
|
||||||
updateTriggers() {
|
updateTriggers() {
|
||||||
if (!this.type) {
|
if (!this.type) {
|
||||||
this.$triggersOverlay.hide();
|
this.hide(this.$triggersOverlay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggers = this.identifiers[this.type].triggers;
|
const triggers = this.identifiers[this.type].triggers;
|
||||||
if (!triggers) {
|
if (!triggers) {
|
||||||
this.$triggersOverlay.hide();
|
this.hide(this.$triggersOverlay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$triggersOverlay.fadeIn();
|
this.show(this.$triggersOverlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -416,7 +465,7 @@ class Gamepad {
|
|||||||
|
|
||||||
if (e.gamepad.index === this.index) {
|
if (e.gamepad.index === this.index) {
|
||||||
// display a disconnection indicator
|
// display a disconnection indicator
|
||||||
this.$gamepad.addClass('disconnected');
|
this.$gamepad.classList.add('disconnected');
|
||||||
this.disconnectedIndex = e.gamepad.index;
|
this.disconnectedIndex = e.gamepad.index;
|
||||||
|
|
||||||
// refresh gamepad list on help, if displayed
|
// refresh gamepad list on help, if displayed
|
||||||
@ -500,6 +549,9 @@ class Gamepad {
|
|||||||
// get fresh information from DOM about gamepads
|
// get fresh information from DOM about gamepads
|
||||||
const gamepads = this.getNavigatorGamepads();
|
const gamepads = this.getNavigatorGamepads();
|
||||||
if (gamepads !== this.gamepads) this.gamepads = gamepads;
|
if (gamepads !== this.gamepads) this.gamepads = gamepads;
|
||||||
|
|
||||||
|
// when visible, refresh gamepad list with latest data
|
||||||
|
if (this.helpVisible) this.buildHelpGamepadList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -509,19 +561,16 @@ class Gamepad {
|
|||||||
const $tbody = [];
|
const $tbody = [];
|
||||||
for (let key = 0; key < this.gamepads.length; key++) {
|
for (let key = 0; key < this.gamepads.length; key++) {
|
||||||
const gamepad = this.gamepads[key];
|
const gamepad = this.gamepads[key];
|
||||||
if (!gamepad) {
|
if (!gamepad) continue;
|
||||||
continue;
|
$tbody.push(`<tr><td>${gamepad.index}</td><td>${gamepad.id}</td></tr>`);
|
||||||
}
|
|
||||||
|
|
||||||
$tbody.push(
|
|
||||||
`<tr><td>${gamepad.index}</td><td>${gamepad.id}</td></tr>'`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tbody.length === 0) {
|
if ($tbody.length === 0) {
|
||||||
$tbody.push('<tr><td colspan="2">No gamepad detected.</td></tr>');
|
this.$gamepadList.innerHTML = '<tr><td colspan="2">No gamepad detected.</td></tr>';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$gamepadList.html($tbody.join(''));
|
this.$gamepadList.innerHTML = $tbody.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -583,20 +632,16 @@ class Gamepad {
|
|||||||
if (
|
if (
|
||||||
null !== this.disconnectedIndex &&
|
null !== this.disconnectedIndex &&
|
||||||
index !== this.disconnectedIndex
|
index !== this.disconnectedIndex
|
||||||
)
|
) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
const gamepad = this.gamepads[index];
|
const gamepad = this.gamepads[index];
|
||||||
if (!gamepad) continue;
|
if (!gamepad) continue;
|
||||||
|
|
||||||
// check the parameters for a selected gamepad
|
// check the parameters for a selected gamepad
|
||||||
const gamepadId = this.getUrlParam('gamepad');
|
const gamepadId = this.getUrlParam('gamepad');
|
||||||
if (gamepadId) {
|
if (gamepadId === gamepad.id) {
|
||||||
const [vendor, product] = gamepadId.split('-');
|
this.map(gamepad.index);
|
||||||
if (gamepad.id.includes(vendor) && gamepad.id.includes(product)) {
|
return;
|
||||||
this.map(gamepad.index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the gamepad buttons
|
// read the gamepad buttons
|
||||||
@ -642,13 +687,12 @@ class Gamepad {
|
|||||||
|
|
||||||
// hide the help messages
|
// hide the help messages
|
||||||
this.hideInstructions(true);
|
this.hideInstructions(true);
|
||||||
this.$helpPopout.removeClass('active');
|
|
||||||
this.hidePlaceholder(true);
|
this.hidePlaceholder(true);
|
||||||
|
|
||||||
// update local references
|
// update local references
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.disconnectedIndex = null;
|
this.disconnectedIndex = null;
|
||||||
this.$gamepad.removeClass('disconnected');
|
this.$gamepad.classList.remove('disconnected');
|
||||||
const gamepad = this.getActive();
|
const gamepad = this.getActive();
|
||||||
|
|
||||||
// ensure that a gamepad was actually found for this index
|
// ensure that a gamepad was actually found for this index
|
||||||
@ -670,16 +714,12 @@ class Gamepad {
|
|||||||
this.identifier = this.identifiers[this.type];
|
this.identifier = this.identifiers[this.type];
|
||||||
|
|
||||||
// update the overlay selectors
|
// update the overlay selectors
|
||||||
this.$gamepadSelect.val(`${gamepad.id}`);
|
this.$gamepadSelect.value = gamepad.id;
|
||||||
this.updateColors();
|
this.updateColors();
|
||||||
this.updateTriggers();
|
this.updateTriggers();
|
||||||
|
|
||||||
// load the HTML template file
|
// load the HTML template file
|
||||||
this.loadTemplate(gamepad);
|
this.loadTemplate();
|
||||||
|
|
||||||
// hide the help before displaying the template
|
|
||||||
this.hideInstructions();
|
|
||||||
this.hidePlaceholder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -704,6 +744,9 @@ class Gamepad {
|
|||||||
// ensure we have something to disconnect
|
// ensure we have something to disconnect
|
||||||
if (this.index === null) return;
|
if (this.index === null) return;
|
||||||
|
|
||||||
|
// clear the current template
|
||||||
|
this.clearTemplate();
|
||||||
|
|
||||||
// clear associated data
|
// clear associated data
|
||||||
this.index = null;
|
this.index = null;
|
||||||
this.disconnectedIndex = null;
|
this.disconnectedIndex = null;
|
||||||
@ -714,73 +757,123 @@ class Gamepad {
|
|||||||
this.colorIndex = null;
|
this.colorIndex = null;
|
||||||
this.colorName = null;
|
this.colorName = null;
|
||||||
this.zoomLevel = 1;
|
this.zoomLevel = 1;
|
||||||
this.$gamepad.empty();
|
this.$gamepad.innerHTML = '';
|
||||||
this.$gamepadSelect.val('auto')
|
this.$gamepad.classList.remove('fadeIn');
|
||||||
|
this.$gamepadSelect.value = 'auto';
|
||||||
this.updateColors();
|
this.updateColors();
|
||||||
this.updateTriggers();
|
this.updateTriggers();
|
||||||
this.clearUrlParams();
|
this.clearUrlParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the HTML template file for the active gamepad
|
* Loads the template script and stylesheet
|
||||||
*
|
|
||||||
* @param {*} gamepad
|
|
||||||
*/
|
*/
|
||||||
loadTemplate(gamepad) {
|
loadTemplateAssets() {
|
||||||
// hide the gamepad while we prepare it
|
const script = document.createElement('script');
|
||||||
this.$gamepad.hide();
|
script.async = true;
|
||||||
|
script.src = `templates/${this.type}/template.js`;
|
||||||
$.ajax(`templates/${this.type}/template.html`).done((template) => {
|
script.onload = () => {
|
||||||
// inject the template HTML
|
// initialize the template
|
||||||
this.$gamepad.html(template);
|
new this.template();
|
||||||
|
|
||||||
// read for parameters to apply:
|
|
||||||
const identifier = this.identifiers[this.type];
|
|
||||||
// - color
|
|
||||||
if (identifier.colors) {
|
|
||||||
this.changeGamepadColor(this.getUrlParam('color'));
|
|
||||||
} else {
|
|
||||||
this.updateUrlParams({ color: undefined });
|
|
||||||
}
|
|
||||||
// - triggers mode
|
|
||||||
if (identifier.triggers) {
|
|
||||||
this.toggleTriggersMeter(this.getUrlParam('triggers') === 'meter');
|
|
||||||
} else {
|
|
||||||
this.updateUrlParams({ triggers: undefined });
|
|
||||||
}
|
|
||||||
// - zoom
|
|
||||||
if (identifier.zoom) {
|
|
||||||
window.setTimeout(() =>
|
|
||||||
this.changeZoom(
|
|
||||||
this.type === 'debug'
|
|
||||||
? 'auto'
|
|
||||||
: this.getUrlParam('zoom') || 'auto'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.updateUrlParams({ zoom: undefined });
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the buttons mapping of this template
|
|
||||||
this.mapping.buttons = [];
|
|
||||||
for (let index = 0; index < gamepad.buttons.length; index++) {
|
|
||||||
this.mapping.buttons[index] = $(`[data-button='${index}']`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// save the axes mapping of this template
|
|
||||||
this.mapping.axes = [];
|
|
||||||
for (let index = 0; index < gamepad.axes.length; index++) {
|
|
||||||
this.mapping.axes[index] = $(
|
|
||||||
`[data-axis=${index}], [data-axis-x=${index}], [data-axis-y=${index}], [data-axis-z=${index}]`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// enqueue the initial display refresh
|
// enqueue the initial display refresh
|
||||||
this.pollStatus(true);
|
this.startTemplate();
|
||||||
|
}
|
||||||
|
this.$gamepad.appendChild(script);
|
||||||
|
|
||||||
// once fully loaded, display the gamepad
|
const link = document.createElement('link');
|
||||||
this.$gamepad.fadeIn();
|
link.rel = 'stylesheet';
|
||||||
});
|
link.href = `templates/${this.type}/template.css`;
|
||||||
|
this.$gamepad.appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the HTML template file for the active gamepad
|
||||||
|
*/
|
||||||
|
loadTemplate() {
|
||||||
|
// hide the gamepad while we prepare it
|
||||||
|
this.$gamepad.style.setProperty('display', 'none');
|
||||||
|
|
||||||
|
fetch(`templates/${this.type}/template.html`)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((template) => {
|
||||||
|
// inject the template HTML
|
||||||
|
this.$gamepad.innerHTML = template;
|
||||||
|
this.loadTemplateAssets();
|
||||||
|
|
||||||
|
// read for parameters to apply:
|
||||||
|
const identifier = this.identifiers[this.type];
|
||||||
|
// - color
|
||||||
|
if (identifier.colors) {
|
||||||
|
this.changeGamepadColor(this.getUrlParam('color'));
|
||||||
|
} else {
|
||||||
|
this.updateUrlParams({ color: undefined });
|
||||||
|
}
|
||||||
|
// - triggers mode
|
||||||
|
if (identifier.triggers) {
|
||||||
|
this.toggleTriggersMeter(this.getUrlParam('triggers') === 'meter');
|
||||||
|
} else {
|
||||||
|
this.updateUrlParams({ triggers: undefined });
|
||||||
|
}
|
||||||
|
// - zoom
|
||||||
|
if (identifier.zoom) {
|
||||||
|
window.setTimeout(() =>
|
||||||
|
this.changeZoom(
|
||||||
|
this.type === 'debug'
|
||||||
|
? 'auto'
|
||||||
|
: this.getUrlParam('zoom') || 'auto'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.updateUrlParams({ zoom: undefined });
|
||||||
|
}
|
||||||
|
|
||||||
|
// once fully loaded, display the gamepad
|
||||||
|
this.$gamepad.style.removeProperty('display');
|
||||||
|
this.$gamepad.classList.remove('fadeOut');
|
||||||
|
this.$gamepad.classList.add('fadeIn');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the template
|
||||||
|
*/
|
||||||
|
startTemplate() {
|
||||||
|
// get the active gamepad
|
||||||
|
const activeGamepad = this.getActive();
|
||||||
|
|
||||||
|
// save the buttons mapping of this template
|
||||||
|
this.mapping.buttons = [];
|
||||||
|
for (let index = 0; index < activeGamepad.buttons.length; index++) {
|
||||||
|
const $button = document.querySelector(`[data-button='${index}']`);
|
||||||
|
if (!$button) break;
|
||||||
|
this.mapping.buttons[index] = $button;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the axes mapping of this template
|
||||||
|
this.mapping.axes = [];
|
||||||
|
for (let index = 0; index < activeGamepad.axes.length; index++) {
|
||||||
|
const $axis = document.querySelector(
|
||||||
|
`[data-axis='${index}'], [data-axis-x='${index}'], [data-axis-y='${index}'], [data-axis-z='${index}']`
|
||||||
|
);
|
||||||
|
if (!$axis) break;
|
||||||
|
this.mapping.axes[index] = $axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enqueue the initial display refresh
|
||||||
|
this.pollStatus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the template
|
||||||
|
*/
|
||||||
|
clearTemplate() {
|
||||||
|
// ensure that a tempalte is currently loaded
|
||||||
|
if (!this.template) return;
|
||||||
|
|
||||||
|
// destruct and clear the template
|
||||||
|
if (this.template.destructor) this.template.destructor();
|
||||||
|
delete this.template;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -815,6 +908,9 @@ class Gamepad {
|
|||||||
* @param {*} gamepad
|
* @param {*} gamepad
|
||||||
*/
|
*/
|
||||||
updateButtons(gamepad) {
|
updateButtons(gamepad) {
|
||||||
|
// ensure we have a button updater callback
|
||||||
|
if ('function' !== typeof this.updateButton) return;
|
||||||
|
|
||||||
// update the buttons
|
// update the buttons
|
||||||
for (let index = 0; index < gamepad.buttons.length; index++) {
|
for (let index = 0; index < gamepad.buttons.length; index++) {
|
||||||
// find the DOM element
|
// find the DOM element
|
||||||
@ -828,13 +924,11 @@ class Gamepad {
|
|||||||
const button = gamepad.buttons[index];
|
const button = gamepad.buttons[index];
|
||||||
|
|
||||||
// update the display values
|
// update the display values
|
||||||
$button.attr('data-pressed', button.pressed);
|
$button.setAttribute('data-pressed', button.pressed);
|
||||||
$button.attr('data-value', button.value);
|
$button.setAttribute('data-value', button.value);
|
||||||
|
|
||||||
// hook the template defined button update method
|
// hook the template defined button update method
|
||||||
if ('function' === typeof this.updateButton) {
|
this.updateButton($button);
|
||||||
this.updateButton($button);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,6 +938,9 @@ class Gamepad {
|
|||||||
* @param {*} gamepad
|
* @param {*} gamepad
|
||||||
*/
|
*/
|
||||||
updateAxes(gamepad) {
|
updateAxes(gamepad) {
|
||||||
|
// ensure we have an axis updater callback
|
||||||
|
if ('function' !== typeof this.updateAxis) return;
|
||||||
|
|
||||||
// update the axes
|
// update the axes
|
||||||
for (let index = 0; index < gamepad.axes.length; index++) {
|
for (let index = 0; index < gamepad.axes.length; index++) {
|
||||||
// find the DOM element
|
// find the DOM element
|
||||||
@ -857,23 +954,21 @@ class Gamepad {
|
|||||||
const axis = gamepad.axes[index];
|
const axis = gamepad.axes[index];
|
||||||
|
|
||||||
// update the display values
|
// update the display values
|
||||||
if ($axis.is('[data-axis=' + index + ']')) {
|
if ($axis.matches(`[data-axis='${index}']`)) {
|
||||||
$axis.attr('data-value', axis);
|
$axis.setAttribute('data-value', axis);
|
||||||
}
|
}
|
||||||
if ($axis.is('[data-axis-x=' + index + ']')) {
|
if ($axis.matches(`[data-axis-x='${index}']`)) {
|
||||||
$axis.attr('data-value-x', axis);
|
$axis.setAttribute('data-value-x', axis);
|
||||||
}
|
}
|
||||||
if ($axis.is('[data-axis-y=' + index + ']')) {
|
if ($axis.matches(`[data-axis-y='${index}']`)) {
|
||||||
$axis.attr('data-value-y', axis);
|
$axis.setAttribute('data-value-y', axis);
|
||||||
}
|
}
|
||||||
if ($axis.is('[data-axis-z=' + index + ']')) {
|
if ($axis.matches(`[data-axis-z='${index}']`)) {
|
||||||
$axis.attr('data-value-z', axis);
|
$axis.setAttribute('data-value-z', axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hook the template defined axis update method
|
// hook the template defined axis update method
|
||||||
if ('function' === typeof this.updateAxis) {
|
this.updateAxis($axis);
|
||||||
this.updateAxis($axis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -884,11 +979,7 @@ class Gamepad {
|
|||||||
*/
|
*/
|
||||||
changeGamepad(gamepadId) {
|
changeGamepad(gamepadId) {
|
||||||
// get the index corresponding to the identifier of the gamepad
|
// get the index corresponding to the identifier of the gamepad
|
||||||
const index = this.gamepads.findIndex(g => {
|
const index = this.gamepads.findIndex(g => g && gamepadId === g.id);
|
||||||
if (!g) return false;
|
|
||||||
const { vendor, product } = this.toGamepadInfo(g.id);
|
|
||||||
return `${vendor}-${product}` === gamepadId;
|
|
||||||
});
|
|
||||||
|
|
||||||
// set the selected gamepad
|
// set the selected gamepad
|
||||||
this.updateUrlParams({ gamepad: gamepadId !== 'auto' ? gamepadId : undefined });
|
this.updateUrlParams({ gamepad: gamepadId !== 'auto' ? gamepadId : undefined });
|
||||||
@ -901,8 +992,11 @@ class Gamepad {
|
|||||||
* @param {any} skin
|
* @param {any} skin
|
||||||
*/
|
*/
|
||||||
changeSkin(skin) {
|
changeSkin(skin) {
|
||||||
|
// clear the current template
|
||||||
|
this.clearTemplate();
|
||||||
|
|
||||||
// update the visual skin selector
|
// update the visual skin selector
|
||||||
this.$skinSelect.val(skin);
|
this.$skinSelect.value = skin;
|
||||||
|
|
||||||
// set the selected skin
|
// set the selected skin
|
||||||
this.debug = skin === 'debug';
|
this.debug = skin === 'debug';
|
||||||
@ -931,17 +1025,17 @@ class Gamepad {
|
|||||||
this.backgroundStyleName =
|
this.backgroundStyleName =
|
||||||
this.backgroundStyle[this.backgroundStyleIndex];
|
this.backgroundStyle[this.backgroundStyleIndex];
|
||||||
|
|
||||||
this.$body.css({
|
this.$body.style.setProperty(
|
||||||
background:
|
'background',
|
||||||
this.backgroundStyleName === 'checkered'
|
this.backgroundStyleName === 'checkered'
|
||||||
? 'url(css/transparent-bg.png)'
|
? 'url(css/transparent-bg.png)'
|
||||||
: this.backgroundStyleName,
|
: this.backgroundStyleName
|
||||||
color: this.textColors[this.backgroundStyleIndex],
|
);
|
||||||
});
|
this.$body.style.setProperty('color', this.textColors[this.backgroundStyleIndex]);
|
||||||
|
|
||||||
// update current settings
|
// update current settings
|
||||||
this.updateUrlParams({ background: this.backgroundStyleName });
|
this.updateUrlParams({ background: this.backgroundStyleName });
|
||||||
this.$backgroundSelect.val(this.backgroundStyleName);
|
this.$backgroundSelect.value = this.backgroundStyleName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -983,11 +1077,11 @@ class Gamepad {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
// update the DOM with the color value
|
// update the DOM with the color value
|
||||||
this.$gamepad.attr('data-color', this.colorName);
|
this.$gamepad.setAttribute('data-color', this.colorName);
|
||||||
|
|
||||||
// update current settings
|
// update current settings
|
||||||
this.updateUrlParams({ color: this.colorName });
|
this.updateUrlParams({ color: this.colorName });
|
||||||
this.$colorSelect.val(this.colorName);
|
this.$colorSelect.value = this.colorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1006,9 +1100,10 @@ class Gamepad {
|
|||||||
|
|
||||||
if (this.zoomMode === 'auto') {
|
if (this.zoomMode === 'auto') {
|
||||||
// 'auto' means a 'contained in window' zoom, with a max zoom of 1
|
// 'auto' means a 'contained in window' zoom, with a max zoom of 1
|
||||||
|
const { width, height } = this.$gamepad.getBoundingClientRect();
|
||||||
this.zoomLevel = Math.min(
|
this.zoomLevel = Math.min(
|
||||||
window.innerWidth / this.$gamepad.width(),
|
window.innerWidth / width,
|
||||||
window.innerHeight / this.$gamepad.height(),
|
window.innerHeight / height,
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
} else if (level === 0) {
|
} else if (level === 0) {
|
||||||
@ -1029,7 +1124,7 @@ class Gamepad {
|
|||||||
this.zoomLevel = +this.zoomLevel.toFixed(2);
|
this.zoomLevel = +this.zoomLevel.toFixed(2);
|
||||||
|
|
||||||
// update the DOM with the zoom value
|
// update the DOM with the zoom value
|
||||||
this.$gamepad.css(
|
this.$gamepad.style.setProperty(
|
||||||
'transform',
|
'transform',
|
||||||
`translate(-50%, -50%) scale(${this.zoomLevel}, ${this.zoomLevel})`
|
`translate(-50%, -50%) scale(${this.zoomLevel}, ${this.zoomLevel})`
|
||||||
);
|
);
|
||||||
@ -1084,13 +1179,9 @@ class Gamepad {
|
|||||||
* Toggles the on-screen help message
|
* Toggles the on-screen help message
|
||||||
*/
|
*/
|
||||||
toggleHelp() {
|
toggleHelp() {
|
||||||
// refresh gamepad list with latest data
|
|
||||||
this.pollGamepads();
|
|
||||||
this.buildHelpGamepadList();
|
|
||||||
|
|
||||||
// display the help popout
|
// display the help popout
|
||||||
this.$helpPopout.toggleClass('active');
|
this.$helpPopout.classList.toggle('active');
|
||||||
this.helpVisible = this.$helpPopout.is('.active');
|
this.helpVisible = this.$helpPopout.classList.contains('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1102,14 +1193,14 @@ class Gamepad {
|
|||||||
|
|
||||||
this.triggersMeter =
|
this.triggersMeter =
|
||||||
useMeter !== undefined ? useMeter : !this.triggersMeter;
|
useMeter !== undefined ? useMeter : !this.triggersMeter;
|
||||||
this.$gamepad[this.triggersMeter ? 'addClass' : 'removeClass'](
|
this.$gamepad.classList[this.triggersMeter ? 'add' : 'remove'](
|
||||||
'triggers-meter'
|
'triggers-meter'
|
||||||
);
|
);
|
||||||
|
|
||||||
// update current settings
|
// update current settings
|
||||||
const triggers = this.triggersMeter ? 'meter' : 'opacity';
|
const triggers = this.triggersMeter ? 'meter' : 'opacity';
|
||||||
this.updateUrlParams({ triggers });
|
this.updateUrlParams({ triggers });
|
||||||
this.$triggersSelect.val(triggers);
|
this.$triggersSelect.value = triggers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
2
js/jquery.min.js
vendored
2
js/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,5 +1,3 @@
|
|||||||
<link rel="stylesheet" href="templates/debug/template.css">
|
|
||||||
<script async src="templates/debug/template.js"></script>
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="info-name" class="box extra-large">
|
<div id="info-name" class="box extra-large">
|
||||||
|
@ -1,88 +1,121 @@
|
|||||||
function DebugTemplate(gamepad) {
|
window.gamepad.template = class DebugTemplate {
|
||||||
return {
|
/**
|
||||||
$name: $('#info-name .value'),
|
* Instanciates a new debug template
|
||||||
$vendor: $('#info-vendor'),
|
*/
|
||||||
$product: $('#info-product'),
|
constructor() {
|
||||||
$id: $('#info-id'),
|
this.gamepad = window.gamepad;
|
||||||
$timestamp: $('#info-timestamp .value'),
|
this.init();
|
||||||
$index: $('#info-index .value'),
|
this.gamepad.updateButton = ($button) => this.updateElem($button);
|
||||||
$mapping: $('#info-mapping .value'),
|
this.gamepad.updateAxis = ($axis) => this.updateElem($axis, 6);
|
||||||
$rumble: $('#info-rumble .value'),
|
}
|
||||||
$axes: $('.axes .container'),
|
|
||||||
$buttons: $('.buttons .container'),
|
/**
|
||||||
activeGamepad: gamepad.getActive(),
|
* Destroys the template
|
||||||
init: function () {
|
*/
|
||||||
if (!this.activeGamepad) {
|
destructor() {
|
||||||
return;
|
delete this.gamepad.updateButton;
|
||||||
}
|
delete this.gamepad.updateAxis;
|
||||||
const { name, vendor, product, id } = gamepad.toGamepadInfo(this.activeGamepad.id);
|
}
|
||||||
this.$name.html(name).attr('title', name);
|
|
||||||
if (vendor && product) {
|
/**
|
||||||
this.$vendor.css({display: 'block'}).find('.value').html(vendor);
|
* Initializes the template
|
||||||
this.$product.css({display: 'block'}).find('.value').html(product);
|
*/
|
||||||
} else {
|
init() {
|
||||||
this.$id.css({display: 'block'}).find('.value').html(id);
|
this.$name = document.querySelector('#info-name .value');
|
||||||
}
|
this.$vendor = document.querySelector('#info-vendor');
|
||||||
this.updateTimestamp();
|
this.$product = document.querySelector('#info-product');
|
||||||
this.$index.html(this.activeGamepad.index);
|
this.$id = document.querySelector('#info-id');
|
||||||
this.$mapping.html(this.activeGamepad.mapping || 'N/A');
|
this.$timestamp = document.querySelector('#info-timestamp .value');
|
||||||
this.$rumble.html(
|
this.$index = document.querySelector('#info-index .value');
|
||||||
this.activeGamepad.vibrationActuator
|
this.$mapping = document.querySelector('#info-mapping .value');
|
||||||
? this.activeGamepad.vibrationActuator.type
|
this.$rumble = document.querySelector('#info-rumble .value');
|
||||||
: 'N/A'
|
this.$axes = document.querySelector('.axes .container');
|
||||||
);
|
this.$buttons = document.querySelector('.buttons .container');
|
||||||
this.initAxes();
|
const activeGamepad = this.gamepad.getActive();
|
||||||
this.initButtons();
|
const { name, vendor, product, id } = this.gamepad.toGamepadInfo(activeGamepad.id);
|
||||||
gamepad.updateButton = ($button) => this.updateElem($button);
|
this.$name.innerHTML = name;
|
||||||
gamepad.updateAxis = ($axis) => this.updateElem($axis, 6);
|
this.$name.setAttribute('title', activeGamepad.id);
|
||||||
},
|
if (vendor && product) {
|
||||||
initAxes: function () {
|
this.$vendor.querySelector('.value').innerHTML = vendor;
|
||||||
for (
|
this.$product.querySelector('.value').innerHTML = product;
|
||||||
let axisIndex = 0;
|
this.$vendor.style.setProperty('display', 'block');
|
||||||
axisIndex < this.activeGamepad.axes.length;
|
this.$product.style.setProperty('display', 'block');
|
||||||
axisIndex++
|
} else {
|
||||||
) {
|
this.$id.querySelector('.value').innerHTML = id;
|
||||||
this.$axes.append(`
|
this.$id.style.setProperty('display', 'block');
|
||||||
<div class="box medium">
|
}
|
||||||
|
this.updateTimestamp();
|
||||||
|
this.$index.innerHTML = this.activeGamepad.index;
|
||||||
|
this.$mapping.innerHTML = this.activeGamepad.mapping || 'N/A';
|
||||||
|
this.$rumble.innerHTML = this.activeGamepad.vibrationActuator
|
||||||
|
? this.activeGamepad.vibrationActuator.type
|
||||||
|
: 'N/A';
|
||||||
|
this.initAxes();
|
||||||
|
this.initButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the axes
|
||||||
|
*/
|
||||||
|
initAxes() {
|
||||||
|
for (
|
||||||
|
let axisIndex = 0;
|
||||||
|
axisIndex < this.activeGamepad.axes.length;
|
||||||
|
axisIndex++
|
||||||
|
) {
|
||||||
|
this.$axes.innerHTML += `
|
||||||
|
<div class="box medium">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="label">Axis ${axisIndex}</div>
|
<div class="label">Axis ${axisIndex}</div>
|
||||||
<div class="value" data-axis="${axisIndex}"></div>
|
<div class="value" data-axis="${axisIndex}"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
initButtons: function () {
|
|
||||||
for (
|
/**
|
||||||
let buttonIndex = 0;
|
* Initializes the buttons
|
||||||
buttonIndex < this.activeGamepad.buttons.length;
|
*/
|
||||||
buttonIndex++
|
initButtons() {
|
||||||
) {
|
for (
|
||||||
this.$buttons.append(`
|
let buttonIndex = 0;
|
||||||
<div class="box small">
|
buttonIndex < this.activeGamepad.buttons.length;
|
||||||
|
buttonIndex++
|
||||||
|
) {
|
||||||
|
this.$buttons.innerHTML += `
|
||||||
|
<div class="box small">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="label">B${buttonIndex}</div>
|
<div class="label">B${buttonIndex}</div>
|
||||||
<div class="value" data-button="${buttonIndex}"></div>
|
<div class="value" data-button="${buttonIndex}"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
updateElem: function ($elem, precision = 2) {
|
|
||||||
this.updateTimestamp();
|
|
||||||
let value = parseFloat($elem.attr('data-value'), 10).toFixed(precision);
|
|
||||||
$elem.html(value);
|
|
||||||
let color = Math.floor(255 * 0.3 + 255 * 0.7 * Math.abs(value));
|
|
||||||
$elem.css({ color: `rgb(${color}, ${color}, ${color})` });
|
|
||||||
},
|
|
||||||
updateTimestamp: function () {
|
|
||||||
this.activeGamepad = gamepad.getActive();
|
|
||||||
if (!this.activeGamepad) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$timestamp.html(parseFloat(this.activeGamepad.timestamp).toFixed(3));
|
|
||||||
},
|
|
||||||
}.init();
|
|
||||||
};
|
|
||||||
|
|
||||||
new DebugTemplate(window.gamepad);
|
/**
|
||||||
|
* Updates the value of an element
|
||||||
|
*
|
||||||
|
* @param {Element} $elem
|
||||||
|
* @param {Number} precision
|
||||||
|
*/
|
||||||
|
updateElem($elem, precision = 2) {
|
||||||
|
this.updateTimestamp();
|
||||||
|
let value = parseFloat($elem.attributes['data-value'].value, 10).toFixed(precision);
|
||||||
|
$elem.innerHTML = value;
|
||||||
|
let color = Math.floor(255 * 0.3 + 255 * 0.7 * Math.abs(value));
|
||||||
|
$elem.style.setProperty('color', `rgb(${color}, ${color}, ${color})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the timestamp
|
||||||
|
*/
|
||||||
|
updateTimestamp() {
|
||||||
|
this.activeGamepad = this.gamepad.getActive();
|
||||||
|
if (!this.activeGamepad) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$timestamp.innerHTML = parseFloat(this.activeGamepad.timestamp).toFixed(3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
<link rel="stylesheet" href="templates/ds4/template.css">
|
|
||||||
<script async src="templates/ds4/template.js"></script>
|
|
||||||
<div class="triggers">
|
<div class="triggers">
|
||||||
<span class="trigger left" data-button="6"></span>
|
<span class="trigger left" data-button="6"></span>
|
||||||
<span class="trigger right" data-button="7"></span>
|
<span class="trigger right" data-button="7"></span>
|
||||||
|
@ -1,37 +1,34 @@
|
|||||||
function DualShock4Template(gamepad) {
|
window.gamepad.template = class DualShock4Template {
|
||||||
return {
|
/**
|
||||||
init: function () {
|
* Instanciates a new DualShock 4 controller template
|
||||||
gamepad.updateButton = function ($button) {
|
*/
|
||||||
const value = parseFloat($button.attr('data-value'), 10);
|
constructor() {
|
||||||
if ($button.is('.trigger')) {
|
this.gamepad = window.gamepad;
|
||||||
$button.css(
|
this.gamepad.updateButton = ($button) => this.updateButton($button);
|
||||||
gamepad.triggersMeter
|
this.gamepad.updateAxis = ($axis) => this.updateAxis($axis);
|
||||||
? {
|
}
|
||||||
opacity: 1,
|
|
||||||
'clip-path': `inset(${(1 - value) * 100}% 0px 0px 0pc)`,
|
/**
|
||||||
}
|
* Destroys the template
|
||||||
: {
|
*/
|
||||||
opacity: `${value * 100}%`,
|
destructor() {
|
||||||
'clip-path': 'none',
|
delete this.gamepad.updateButton;
|
||||||
}
|
delete this.gamepad.updateAxis;
|
||||||
);
|
}
|
||||||
}
|
|
||||||
};
|
updateButton($button) {
|
||||||
gamepad.updateAxis = function ($axis) {
|
if (!$button.matches('.trigger')) return;
|
||||||
const axisX = $axis.attr('data-value-x');
|
const value = parseFloat($button.getAttribute('data-value'), 10);
|
||||||
const axisY = $axis.attr('data-value-y');
|
$button.style.setProperty('opacity', this.gamepad.triggersMeter ? 1 : `${value * 100}%`);
|
||||||
if ($axis.is('.stick')) {
|
$button.style.setProperty('clip-path', this.gamepad.triggersMeter ? `inset(${100 - value * 100}% 0px 0px 0pc)` : 'none');
|
||||||
$axis.css({
|
}
|
||||||
'margin-top': axisY * 25,
|
|
||||||
'margin-left': axisX * 25,
|
updateAxis($axis) {
|
||||||
transform: `rotateX(${-parseFloat(
|
if (!$axis.matches('.stick')) return;
|
||||||
axisY * 30,
|
const axisX = $axis.getAttribute('data-value-x');
|
||||||
8
|
const axisY = $axis.getAttribute('data-value-y');
|
||||||
)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`,
|
$axis.style.setProperty('margin-top', `${axisY * 25}px`);
|
||||||
});
|
$axis.style.setProperty('margin-left', `${axisX * 25}px`);
|
||||||
}
|
$axis.style.setProperty('transform', `rotateX(${-parseFloat(axisY * 30, 8)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`);
|
||||||
};
|
}
|
||||||
},
|
|
||||||
}.init();
|
|
||||||
};
|
};
|
||||||
new DualShock4Template(window.gamepad);
|
|
||||||
|
45
templates/dualsense/base-white.svg
Normal file
45
templates/dualsense/base-white.svg
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 698">
|
||||||
|
<path fill="#e6e6e6"
|
||||||
|
d="M344.3 131c-9 1.9-21.5 6.9-32.1 12.9-11.5 6.4-15.8 10.3-16.8 14.9-.3 1.5-.7 3.7-1 4.8-.3 1.6-1.6 2.5-4.8 3.3-4.2 1-4.8 1.6-10.6 10.9-8.3 13.3-21.7 40.6-28.9 58.7-23.5 59.6-36.7 124.8-43.3 213.5-1.7 22.5-1.7 106.2 0 130 .7 9.6 1.5 21.4 1.8 26.2.5 7.6 1 9.4 4.2 14.8 9.3 15.8 28.1 29.1 45.7 32.6 3.8.7 11.9 2.4 17.9 3.8 5.9 1.4 13.8 2.8 17.5 3.2 7.4.7 9.2-.3 10.5-6.1 1.4-5.5 9.6-27.2 17.5-46.2 18.1-43.5 31.9-72.5 44.3-93.5 10.8-18.4 26.7-33.8 40.1-39.1 6.5-2.5 18.2-2.6 48.7-.3 32.9 2.4 265.1 2.3 288.5-.2 23.8-2.5 36.1-2.2 45.9 1.2 4.3 1.5 9.8 4 12.1 5.6 5.7 3.9 21.5 22 27.7 31.6 12 18.8 27 53.5 48.4 112.4 7.6 20.7 10.5 27 14.3 30.4 1.8 1.7 3.5 1.8 18.8 1.4 16.5-.4 17-.5 28.5-4.5 16.8-5.8 28.2-13.2 37.6-24.7 8.2-9.9 9-12.4 10.2-30.6 4.3-67.2 3.6-131.6-2-185.5-6.9-67-20.4-126-40.1-176-7.2-18.1-20.6-45.4-28.9-58.7-5-8.1-6.6-9.9-9.3-10.6-2.8-.7-3.3-1.4-4.3-5.8-2.2-9.2-2.9-9.9-19.5-18.8-11.9-6.3-21.3-9.9-30.9-11.6-7.4-1.4-48.3-.4-51.3 1.2-2.9 1.5-5.7 7-5.7 11v3.7l-18.2-.5c-22.7-.6-28.6-1-30.1-2.2-2.8-2.3-47.9-6.4-90-8.2-29.7-1.3-119.7-1.3-132.9 0-5.7.6-15.2 1.5-21.3 2.1-6 .6-14.4 1.4-18.5 1.9s-12.9 1.4-19.5 2c-6.6.7-13.7 1.8-15.7 2.6-2.7 1-10 1.4-25 1.6l-21.3.3-.1-3.7c-.1-4.1-2.3-8-5.7-10.2-2.7-1.7-45.6-3-52.4-1.6z" />
|
||||||
|
<path fill="#1a1a1a"
|
||||||
|
d="M398.1 121.37q-48.86-8.04-97.8.15 4.84-24.2 11.45-45.52 1.69-5.44 4.72-12.11 8.27-18.18 26.78-24.64 6.77-2.36 13.97-1.62 4.95.51 9.9 3.4 5.03 2.94 10.19 7.16 4.69 3.83 7.39 7.65 8.11 11.47 10.05 25.41 1.42 10.19 3.35 40.12Zm-35.24-13.34q.86-1.03 3.08-2.59 3.49-2.46 2.17-5.66-1.05-2.52-3.89-3.14-4.14-.91-5.58 3.88a.68.65-65.1 0 0 .26.77q1.91 1.22 2.79-1.1 1.02-2.7 2.75-1.13 1.51 1.38.95 2.95-.29.8-1.82 1.97-2.76 2.11-4.58 5.21a1.19 1.19 15.7 0 0 1.01 1.8q3.56.05 6.72-.03.92-.03 1.37-.34.82-.58.34-1.62a.87.76-9.9 0 0-.75-.45l-4.62-.1q-.54-.01-.2-.42Zm-17.7-10.34-.12 12.18a1.16 1.12.2 0 0 1.16 1.13h7.03q1.03 0 1.5-.25.96-.52.43-1.74a.81.76-9.9 0 0-.72-.47l-5.73-.04a.71.69 0 0 1-.71-.69V97.75a.98.84-76.7 0 0-.41-.8q-.99-.61-1.98-.05a.95.88 76.8 0 0-.45.79Zm550.82 23.71q-19.2-2.44-38.55-3.43-10.39-.53-19.99-.2-13.21.46-22.25 1.79-8.43 1.25-16.9 2.19 1.39-22.42 3.21-38.5 3.02-26.67 26.06-40.94 11.55-7.15 24.21-2.98 18.59 6.12 27.15 22.2 2.69 5.06 6.93 18.72 6.19 19.96 10.13 41.15Zm-64.44-15.49q5.49-1.61 5.14 4.09-.12 1.91 2.69 1.39a.46.43-9.1 0 0 .37-.48l-.48-4.35a1.66.98 32.1 0 0-.44-.85q-1.14-1.24.17-2.04a1.52.96-16.5 0 0 .61-.7q1.76-5.6-4.34-5.87-3.38-.15-6.62-.1a.65.65-.4 0 0-.64.65q0 6.23-.22 12.09-.08 2.35 2.6 1.66a.86.84 83.1 0 0 .63-.83l.03-4.01a.7.67-8.7 0 1 .5-.65Zm16.38 2.42q1.33-1.31 2.73-2.55 1.77-1.57 2.32-2.85 1.32-3.1-1.28-4.88-1.93-1.33-4.23-1.08-3.32.37-3.62 4.21a.73.67-78 0 0 .43.72q1.38.53 2.04-.54.61-1 .64-1.03 2.33-2.71 3.41.69a1.37 1.32-42.4 0 1-.06.95q-1.09 2.45-3.41 3.96-2.5 1.62-3.32 5a.46.46 6.9 0 0 .45.57h8.48a1.01.82 13.2 0 0 .8-.39q.65-1-.02-1.92a1.16.91-13.6 0 0-.85-.39l-4.37-.1q-.5-.01-.14-.37Z" />
|
||||||
|
<path fill="#2c2c2c"
|
||||||
|
d="m363.06 108.45 4.62.1a.87.76-9.9 0 1 .75.45q.48 1.04-.34 1.62-.45.31-1.37.34-3.16.08-6.72.03a1.19 1.19 15.7 0 1-1.01-1.8q1.82-3.1 4.58-5.21 1.53-1.17 1.82-1.97.56-1.57-.95-2.95-1.73-1.57-2.75 1.13-.88 2.32-2.79 1.1a.68.65-65.1 0 1-.26-.77q1.44-4.79 5.58-3.88 2.84.62 3.89 3.14 1.32 3.2-2.17 5.66-2.22 1.56-3.08 2.59-.34.41.2.42ZM345.61 96.9q.99-.56 1.98.05a.98.84-76.7 0 1 .41.8v10.06a.71.69 0 0 0 .71.69l5.73.04a.81.76-9.9 0 1 .72.47q.53 1.22-.43 1.74-.47.25-1.5.25h-7.03a1.16 1.12.2 0 1-1.16-1.13l.12-12.18a.95.88 76.8 0 1 .45-.79Zm485.43 9.66-.03 4.01a.86.84 83.1 0 1-.63.83q-2.68.69-2.6-1.66.22-5.86.22-12.09a.65.65-.4 0 1 .64-.65q3.24-.05 6.62.1 6.1.27 4.34 5.87a1.52.96-16.5 0 1-.61.7q-1.31.8-.17 2.04a1.66.98 32.1 0 1 .44.85l.48 4.35a.46.43-9.1 0 1-.37.48q-2.81.52-2.69-1.39.35-5.7-5.14-4.09a.7.67-8.7 0 0-.5.65Zm5.87-5.66a1.39 1.39 0 0 0-1.39-1.39h-3.2a1.39 1.39 0 0 0-1.39 1.39v.96a1.39 1.39 0 0 0 1.39 1.39h3.2a1.39 1.39 0 0 0 1.39-1.39v-.96Zm11.15 7.8 4.37.1a1.16.91-13.6 0 1 .85.39q.67.92.02 1.92a1.01.82 13.2 0 1-.8.39h-8.48a.46.46 6.9 0 1-.45-.57q.82-3.38 3.32-5 2.32-1.51 3.41-3.96a1.37 1.32-42.4 0 0 .06-.95q-1.08-3.4-3.41-.69-.03.03-.64 1.03-.66 1.07-2.04.54a.73.67-78 0 1-.43-.72q.3-3.84 3.62-4.21 2.3-.25 4.23 1.08 2.6 1.78 1.28 4.88-.55 1.28-2.32 2.85-1.4 1.24-2.73 2.55-.36.36.14.37Z" />
|
||||||
|
<path fill="#1a1a1a"
|
||||||
|
d="M836.91 101.86a1.39 1.39 0 0 1-1.39 1.39h-3.2a1.39 1.39 0 0 1-1.39-1.39v-.96a1.39 1.39 0 0 1 1.39-1.39h3.2a1.39 1.39 0 0 1 1.39 1.39v.96Z" />
|
||||||
|
<path
|
||||||
|
d="m398.1 121.37.69 6.17a.91.89-.7 0 1-.98.98q-11.67-.92-23.05-1.63-21.63-1.34-43.26-.07-15.89.94-32.42 2.49a.4.38 2.9 0 1-.44-.46l1.66-7.33q48.94-8.19 97.8-.15Zm497.88.03 1.75 7.45a.62.58-3.2 0 1-.67.7q-17.06-1.51-33.82-2.5-10.59-.63-19.98-.5-22.23.32-44.48 2.4a.94.87-.7 0 1-1.03-.93l.54-6.27q8.47-.94 16.9-2.19 9.04-1.33 22.25-1.79 9.6-.33 19.99.2 19.35.99 38.55 3.43Z" />
|
||||||
|
<path fill="#232323"
|
||||||
|
d="M392.5 133.29q3.22.48.34 2.08-2 1.11-4.24 1.53-1.98.38-2.06.4-22.73 5.27-45.52 10.27-14.4 3.17-35.52 5.93-2.81.37-2.79-2.25 6.94-4.32 16.98-9.56 14.1-7.37 29.33-9.13 6.07-.71 19.97-.16 11.76.46 23.51.89Zm503.86 18.79q-2.56 1.3-4.11 1.17-15.22-1.24-30.11-4.55-10.19-2.26-10.32-2.28-14.26-3.01-28.48-6.25-1.34-.31-10.21-2.19-7.28-1.54-10.07-2.79-2.03-.91.01-1.86 10.31-.47 20.43-.8 17.43-.55 20-.43 15.44.7 29.56 7.34 11.3 5.31 23.3 12.64Z" />
|
||||||
|
<path fill="#1a1a1a"
|
||||||
|
d="M392.5 133.29q3.3-.13 4.69 1.02 6.61 5.5 5.31 14.4-54.64 6.44-108.2 18.95.44-5.01 1.2-7.66 1.64-5.72 7.21-8.75-.02 2.62 2.79 2.25 21.12-2.76 35.52-5.93 22.79-5 45.52-10.27.08-.02 2.06-.4 2.24-.42 4.24-1.53 2.88-1.6-.34-2.08Zm410.57.04q-2.04.95-.01 1.86 2.79 1.25 10.07 2.79 8.87 1.88 10.21 2.19 14.22 3.24 28.48 6.25.13.02 10.32 2.28 14.89 3.31 30.11 4.55 1.55.13 4.11-1.17 7.16 6.06 6.58 15.91-43.18-9.46-74.94-14.74-11.88-1.97-32.86-4.05-2.23-11.53 7.93-15.87Z" />
|
||||||
|
<path fill="#0170bb"
|
||||||
|
d="M749.8 147.21q3.75-.57 6.54.71 5.97 6.72 8.85 13.14 2.51 5.62 1.56 10.69-4.85 25.85-14 64.75-2.02 8.57-4.79 22.75-4.05 3.49-8.21.21 8.39-41.35 17.19-82.6.55-2.57.57-5.28.02-2.67.07-5.33.23-11.29-7.78-19.04Zm-304.63-.3q-9.38 9.43-8.21 21.84.49 5.14 1.65 10.17l1.2 5.2q7.4 34.93 14.58 69.88-.08 4.76-4.22 4.82-1.19.01-2.09-.78-.89-.79-1.54-1.79-8.35-36.97-16.19-74.06-2.2-10.35-2.2-10.38-.59-5.68 1.66-10.75 2.74-6.15 8.69-13.02l6.67-1.13Z" />
|
||||||
|
<path fill="#818081"
|
||||||
|
d="M795.929 162.798a.54.54 0 0 1-.546.535l-10.06-.106a.54.54 0 0 1-.534-.545l.002-.18a.54.54 0 0 1 .546-.535l10.06.106a.54.54 0 0 1 .534.545l-.002.18Zm-393.287 8.551a.67.67 0 0 1-.408.855l-.057.02a.67.67 0 0 1-.855-.408l-2.884-8.144a.67.67 0 0 1 .408-.856l.057-.02a.67.67 0 0 1 .855.408l2.884 8.144Zm2.994-.513a.56.56 0 0 1-.686.396l-.077-.02a.56.56 0 0 1-.396-.686l1.507-5.622a.56.56 0 0 1 .686-.396l.077.02a.56.56 0 0 1 .396.686l-1.507 5.622Zm390.088-4.843a.27.27 0 0 1-.275.264l-10.158-.195a.27.27 0 0 1-.265-.275l.01-.5a.27.27 0 0 1 .275-.264l10.158.195a.27.27 0 0 1 .265.275l-.01.5Zm.256 2.917a.35.35 0 0 1-.351.35l-10.54-.02a.35.35 0 0 1-.35-.35l.001-.54a.35.35 0 0 1 .351-.35l10.54.02a.35.35 0 0 1 .35.35l-.001.54Zm-396.328 4.24a3.68.72 37.7 0 1-3.352-1.68 3.68.72 37.7 0 1-2.472-2.82 3.68.72 37.7 0 1 3.352 1.68 3.68.72 37.7 0 1 2.472 2.82Zm22.601 31.13a9.73 9.73 0 0 1-7.231 11.707l-.915.216a9.73 9.73 0 0 1-11.707-7.23l-4.873-20.613a9.73 9.73 0 0 1 7.231-11.707l.915-.216a9.73 9.73 0 0 1 11.707 7.23l4.873 20.613Zm-6.34-20.202a8.29 8.29 0 0 0-9.964-6.178l-.74.173a8.29 8.29 0 0 0-6.178 9.964l4.796 20.445a8.29 8.29 0 0 0 9.964 6.178l.74-.173a8.29 8.29 0 0 0 6.178-9.964l-4.796-20.445Z" />
|
||||||
|
<path fill="#777677"
|
||||||
|
d="M793.067 208.91a9.67 9.67 0 0 1-11.648 7.166l-.895-.213a9.67 9.67 0 0 1-7.165-11.648l4.894-20.545a9.67 9.67 0 0 1 11.648-7.166l.895.213a9.67 9.67 0 0 1 7.165 11.648l-4.894 20.545Zm3.469-20.904a8.39 8.39 0 0 0-6.253-10.084l-.7-.164a8.39 8.39 0 0 0-10.085 6.252l-4.814 20.524a8.39 8.39 0 0 0 6.253 10.084l.7.164a8.39 8.39 0 0 0 10.085-6.252l4.814-20.524Z" />
|
||||||
|
<path fill="#d8d8d8"
|
||||||
|
d="M791.722 208.53a8.39 8.39 0 0 1-10.084 6.252l-.701-.164a8.39 8.39 0 0 1-6.253-10.084l4.814-20.524a8.39 8.39 0 0 1 10.084-6.252l.701.164a8.39 8.39 0 0 1 6.253 10.084l-4.814 20.524Zm-371.013-4.007a8.29 8.29 0 0 1-6.178 9.964l-.74.173a8.29 8.29 0 0 1-9.964-6.178l-4.796-20.445a8.29 8.29 0 0 1 6.178-9.964l.74-.173a8.29 8.29 0 0 1 9.964 6.178l4.796 20.445Z" />
|
||||||
|
<path fill="#2e3940"
|
||||||
|
d="M454.39 254q2.5 16.22 8.23 31.48-1.37-.24-2.37.82a1.18 1.13 19.1 0 1-.81.37l-8 .32-1.15-6.48a1.24.49 86.1 0 0-.4-.84q-.26-.16-.6-.17l-2.75-23.25q.65 1 1.54 1.79.9.79 2.09.78 4.14-.06 4.22-4.82Z" />
|
||||||
|
<path fill="#2e3940"
|
||||||
|
d="M747.96 259.25q-2.22 14.17-2.25 28.5-.98-.3-1.27.69-1.1 3.68-3.99 7.72-10.12 14.17-25.51 22.28-6.5 3.42-14.18 4.06-.15.01-14.53-.01-90.23-.14-180.46.22-12.52.05-17.45-1.15-8.65-2.11-16.01-7.87-13.81-10.82-20.87-26.7l8-.32a1.18 1.13 19.1 0 0 .81-.37q1-1.06 2.37-.82 7.01 13.56 16.94 21.96 2.9 2.45 7.09 3.7 2.87.86 7.8.86h206.27q.87 0 1.69-.29 13.13-4.7 22.55-14.13 4.46-4.46 7.14-9.41 2.93-5.42 4.09-11.23 2.94-14.77 3.56-17.48 4.16 3.28 8.21-.21Z" />
|
||||||
|
<path fill="#1e1e1e"
|
||||||
|
d="M449.29 279.5q.34.01.6.17a1.24.49 86.1 0 1 .4.84l1.15 6.48q7.06 15.88 20.87 26.7 7.36 5.76 16.01 7.87 4.93 1.2 17.45 1.15 90.23-.36 180.46-.22 14.38.02 14.53.01 7.68-.64 14.18-4.06 15.39-8.11 25.51-22.28 2.89-4.04 3.99-7.72.29-.99 1.27-.69.42 8.74 3.85 14.19 5.57 8.82 15.85 21.55 9.42 11.66 9.46 11.72 15.37 19.36 23.44 29.98 2.87 3.77 6.54 9.34 2.68 4.06 5.92 9.73 7.37 12.89 14.73 25.78 18.82 33.63 35.29 68.46 15.42 35.19 29.21 71.04 12.53 32.24 22.89 65.24 3.67 11.69 8.19 23.07 3.17 7.97 8.23 13.84 2.71 3.13 7.49 3.62-21.62 6.52-44.2 3.67-7.23-17.6-9.6-23.98-18.09-48.79-39.87-96.03-2.39-7.8-7.3-14.31-3-5.59-9.52-15.72-.81-1.26-1.35-.44-10.1-12.16-18.52-20.94-3.42-3.56-8.6-6.05-19.16-9.22-40.34-5.76-5.88.96-23 2.25-9.35.7-31.99.59-16.22-.09-20.02-.09h-178.9l-7.67.03q-27.57.11-58.42-2.78-9.45-.88-20.43-.35-6.39.31-10.87 2.07-6.99 2.76-13.51 7.97-14 11.16-22.73 24.81-.91.03-1.41.8-6.18 9.61-11.38 19.79-22.14 43.37-40.23 88.6-9.77 24.42-14.78 41.51-2.74 1.37-5.66 1.05-16.86-1.85-36.25-7.21 4.13-.89 6.81-4.73 3.94-5.63 6-10.5 4.84-11.43 8.59-23.26 11.35-35.82 25.06-70.8 14.55-38.67 31.79-76.21 14.9-30.25 31.25-59.75 7.72-13.32 15.31-26.73 3.34-5.89 7.93-12.49 3.04-4.38 8.9-11.82 31.49-39.99 38.3-48.81 1.38-1.79 4.06-5.96 2.19-3.39 3.13-6.45 2.67-8.6 1.91-17.78Zm181.98 57.13a3.78 3.78 0 0 0-3.78-3.78 3.78 3.78 0 0 0-3.78 3.78 3.78 3.78 0 0 0 3.78 3.78 3.78 3.78 0 0 0 3.78-3.78Zm-58.81 0a3.78 3.78 0 0 0-3.78-3.78 3.78 3.78 0 0 0-3.78 3.78 3.78 3.78 0 0 0 3.78 3.78 3.78 3.78 0 0 0 3.78-3.78Zm14.36.02a3.77 3.77 0 0 0-3.77-3.77 3.77 3.77 0 0 0-3.77 3.77 3.77 3.77 0 0 0 3.77 3.77 3.77 3.77 0 0 0 3.77-3.77Zm15.07.01a3.79 3.79 0 0 0-3.79-3.79 3.79 3.79 0 0 0-3.79 3.79 3.79 3.79 0 0 0 3.79 3.79 3.79 3.79 0 0 0 3.79-3.79Zm14.32 0a3.78 3.78 0 0 0-3.78-3.78 3.78 3.78 0 0 0-3.78 3.78 3.78 3.78 0 0 0 3.78 3.78 3.78 3.78 0 0 0 3.78-3.78Zm-95.26 58.02a52.16 52.16 0 0 0-52.16-52.16 52.16 52.16 0 0 0-52.16 52.16 52.16 52.16 0 0 0 52.16 52.16 52.16 52.16 0 0 0 52.16-52.16Zm258.63-.01a52.17 52.17 0 0 0-52.17-52.17 52.17 52.17 0 0 0-52.17 52.17 52.17 52.17 0 0 0 52.17 52.17 52.17 52.17 0 0 0 52.17-52.17Zm-201.35-45.13a3.11 3.11 0 0 0-3.11-3.11 3.11 3.11 0 0 0-3.11 3.11 3.11 3.11 0 0 0 3.11 3.11 3.11 3.11 0 0 0 3.11-3.11Zm15.13 0a3.12 3.12 0 0 0-3.12-3.12 3.12 3.12 0 0 0-3.12 3.12 3.12 3.12 0 0 0 3.12 3.12 3.12 3.12 0 0 0 3.12-3.12Zm14.36-.01a3.12 3.12 0 0 0-3.12-3.12 3.12 3.12 0 0 0-3.12 3.12 3.12 3.12 0 0 0 3.12 3.12 3.12 3.12 0 0 0 3.12-3.12Zm15.13-.03a3.16 3.16 0 0 0-3.16-3.16 3.16 3.16 0 0 0-3.16 3.16 3.16 3.16 0 0 0 3.16 3.16 3.16 3.16 0 0 0 3.16-3.16Zm-6.14 86.89a3.62 3.62 0 0 0-3.62-3.62h-30.5a3.62 3.62 0 0 0-3.62 3.62v.5a3.62 3.62 0 0 0 3.62 3.62h30.5a3.62 3.62 0 0 0 3.62-3.62v-.5Z" />
|
||||||
|
<path fill="#070707"
|
||||||
|
d="M631.27 336.63a3.78 3.78 0 0 1-3.78 3.78 3.78 3.78 0 0 1-3.78-3.78 3.78 3.78 0 0 1 3.78-3.78 3.78 3.78 0 0 1 3.78 3.78Zm-58.81 0a3.78 3.78 0 0 1-3.78 3.78 3.78 3.78 0 0 1-3.78-3.78 3.78 3.78 0 0 1 3.78-3.78 3.78 3.78 0 0 1 3.78 3.78Zm14.36.02a3.77 3.77 0 0 1-3.77 3.77 3.77 3.77 0 0 1-3.77-3.77 3.77 3.77 0 0 1 3.77-3.77 3.77 3.77 0 0 1 3.77 3.77Zm15.07.01a3.79 3.79 0 0 1-3.79 3.79 3.79 3.79 0 0 1-3.79-3.79 3.79 3.79 0 0 1 3.79-3.79 3.79 3.79 0 0 1 3.79 3.79Zm14.32 0a3.78 3.78 0 0 1-3.78 3.78 3.78 3.78 0 0 1-3.78-3.78 3.78 3.78 0 0 1 3.78-3.78 3.78 3.78 0 0 1 3.78 3.78Z" />
|
||||||
|
<path fill="#0c0c0c"
|
||||||
|
d="M520.95 394.68a52.16 52.16 0 0 1-52.16 52.16 52.16 52.16 0 0 1-52.16-52.16 52.16 52.16 0 0 1 52.16-52.16 52.16 52.16 0 0 1 52.16 52.16Zm-8.3.05a43.89 43.89 0 0 0-43.89-43.89 43.89 43.89 0 0 0-43.89 43.89 43.89 43.89 0 0 0 43.89 43.89 43.89 43.89 0 0 0 43.89-43.89Zm266.93-.06a52.17 52.17 0 0 1-52.17 52.17 52.17 52.17 0 0 1-52.17-52.17 52.17 52.17 0 0 1 52.17-52.17 52.17 52.17 0 0 1 52.17 52.17Zm-8.35.03a43.85 43.85 0 0 0-43.85-43.85 43.85 43.85 0 0 0-43.85 43.85 43.85 43.85 0 0 0 43.85 43.85 43.85 43.85 0 0 0 43.85-43.85Z" />
|
||||||
|
<path fill="#070707"
|
||||||
|
d="M578.23 349.54a3.11 3.11 0 0 1-3.11 3.11 3.11 3.11 0 0 1-3.11-3.11 3.11 3.11 0 0 1 3.11-3.11 3.11 3.11 0 0 1 3.11 3.11Zm15.13 0a3.12 3.12 0 0 1-3.12 3.12 3.12 3.12 0 0 1-3.12-3.12 3.12 3.12 0 0 1 3.12-3.12 3.12 3.12 0 0 1 3.12 3.12Zm14.36-.01a3.12 3.12 0 0 1-3.12 3.12 3.12 3.12 0 0 1-3.12-3.12 3.12 3.12 0 0 1 3.12-3.12 3.12 3.12 0 0 1 3.12 3.12Zm15.13-.03a3.16 3.16 0 0 1-3.16 3.16 3.16 3.16 0 0 1-3.16-3.16 3.16 3.16 0 0 1 3.16-3.16 3.16 3.16 0 0 1 3.16 3.16Z" />
|
||||||
|
<path fill="#161616"
|
||||||
|
d="M512.65 394.73a43.89 43.89 0 0 1-43.89 43.89 43.89 43.89 0 0 1-43.89-43.89 43.89 43.89 0 0 1 43.89-43.89 43.89 43.89 0 0 1 43.89 43.89Zm-10.12-.09a33.76 33.76 0 0 0-33.76-33.76 33.76 33.76 0 0 0-33.76 33.76 33.76 33.76 0 0 0 33.76 33.76 33.76 33.76 0 0 0 33.76-33.76Zm268.7.06a43.85 43.85 0 0 1-43.85 43.85 43.85 43.85 0 0 1-43.85-43.85 43.85 43.85 0 0 1 43.85-43.85 43.85 43.85 0 0 1 43.85 43.85Zm-10.07-.07a33.75 33.75 0 0 0-33.75-33.75 33.75 33.75 0 0 0-33.75 33.75 33.75 33.75 0 0 0 33.75 33.75 33.75 33.75 0 0 0 33.75-33.75Z" />
|
||||||
|
<path fill="#1e1e1e"
|
||||||
|
d="M502.53 394.64a33.76 33.76 0 0 1-33.76 33.76 33.76 33.76 0 0 1-33.76-33.76 33.76 33.76 0 0 1 33.76-33.76 33.76 33.76 0 0 1 33.76 33.76Zm258.63-.01a33.75 33.75 0 0 1-33.75 33.75 33.75 33.75 0 0 1-33.75-33.75 33.75 33.75 0 0 1 33.75-33.75 33.75 33.75 0 0 1 33.75 33.75Z" />
|
||||||
|
<path fill="#070707"
|
||||||
|
d="M616.71 436.89a3.62 3.62 0 0 1-3.62 3.62h-30.5a3.62 3.62 0 0 1-3.62-3.62v-.5a3.62 3.62 0 0 1 3.62-3.62h30.5a3.62 3.62 0 0 1 3.62 3.62v.5Z" />
|
||||||
|
<path fill="#090806" fill-opacity=".514" d="m843.13 538.97-7.3-14.31q4.91 6.51 7.3 14.31Z" />
|
||||||
|
<path fill="#e6e6e6"
|
||||||
|
d="M369.96 510.25q-18.67 53.58-41.01 105.73-7 16.35-15.5 31.96-1.05 1.94-6.26 9.5-1.99 2.88-5.03 3.51 5.01-17.09 14.78-41.51 18.09-45.23 40.23-88.6 5.2-10.18 11.38-19.79.5-.77 1.41-.8ZM835.83 524.66l7.3 14.31Q864.91 586.21 883 635q2.37 6.38 9.6 23.98-5.34-3.66-8.6-9.48-12.23-21.85-21.04-43.02-20.19-48.53-38-97.98.54-.82 1.35.44 6.52 10.13 9.52 15.72Z" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 15 KiB |
@ -1,5 +1,3 @@
|
|||||||
<link rel="stylesheet" href="templates/dualsense/template.css">
|
|
||||||
<script async src="templates/dualsense/template.js"></script>
|
|
||||||
<div class="triggers">
|
<div class="triggers">
|
||||||
<span class="trigger left" data-button="6"></span>
|
<span class="trigger left" data-button="6"></span>
|
||||||
<span class="trigger right" data-button="7"></span>
|
<span class="trigger right" data-button="7"></span>
|
||||||
|
@ -1,37 +1,34 @@
|
|||||||
function DualShock4Template(gamepad) {
|
window.gamepad.template = class DualSenseTemplate {
|
||||||
return {
|
/**
|
||||||
init: function () {
|
* Instanciates a new DualSense controller template
|
||||||
gamepad.updateButton = function ($button) {
|
*/
|
||||||
const value = parseFloat($button.attr('data-value'), 10);
|
constructor() {
|
||||||
if ($button.is('.trigger')) {
|
this.gamepad = window.gamepad;
|
||||||
$button.css(
|
this.gamepad.updateButton = ($button) => this.updateButton($button);
|
||||||
gamepad.triggersMeter
|
this.gamepad.updateAxis = ($axis) => this.updateAxis($axis);
|
||||||
? {
|
}
|
||||||
opacity: 1,
|
|
||||||
'clip-path': `inset(${(1 - value) * 100}% 0px 0px 0pc)`,
|
/**
|
||||||
}
|
* Destroys the template
|
||||||
: {
|
*/
|
||||||
opacity: `${value * 100}%`,
|
destructor() {
|
||||||
'clip-path': 'none',
|
delete this.gamepad.updateButton;
|
||||||
}
|
delete this.gamepad.updateAxis;
|
||||||
);
|
}
|
||||||
}
|
|
||||||
};
|
updateButton($button) {
|
||||||
gamepad.updateAxis = function ($axis) {
|
if (!$button.matches('.trigger')) return;
|
||||||
const axisX = $axis.attr('data-value-x');
|
const value = parseFloat($button.getAttribute('data-value'), 10);
|
||||||
const axisY = $axis.attr('data-value-y');
|
$button.style.setProperty('opacity', this.gamepad.triggersMeter ? 1 : `${value * 100}%`);
|
||||||
if ($axis.is('.stick')) {
|
$button.style.setProperty('clip-path', this.gamepad.triggersMeter ? `inset(${100 - value * 100}% 0px 0px 0pc)` : 'none');
|
||||||
$axis.css({
|
}
|
||||||
'margin-top': axisY * 25,
|
|
||||||
'margin-left': axisX * 25,
|
updateAxis($axis) {
|
||||||
transform: `rotateX(${-parseFloat(
|
if (!$axis.matches('.stick')) return;
|
||||||
axisY * 30,
|
const axisX = $axis.getAttribute('data-value-x');
|
||||||
8
|
const axisY = $axis.getAttribute('data-value-y');
|
||||||
)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`,
|
$axis.style.setProperty('margin-top', `${axisY * 25}px`);
|
||||||
});
|
$axis.style.setProperty('margin-left', `${axisX * 25}px`);
|
||||||
}
|
$axis.style.setProperty('transform', `rotateX(${-parseFloat(axisY * 30, 8)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`);
|
||||||
};
|
}
|
||||||
},
|
|
||||||
}.init();
|
|
||||||
};
|
};
|
||||||
new DualShock4Template(window.gamepad);
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
<link rel="stylesheet" href="templates/telemetry/template.css">
|
<div id="fps"></div>
|
||||||
<script src="https://www.gstatic.com/charts/loader.js"></script>
|
|
||||||
<script src="templates/telemetry/template.js"></script>
|
|
||||||
<div id="telemetry">
|
<div id="telemetry">
|
||||||
<div id="chart"></div>
|
<div id="chart"></div>
|
||||||
<div id="meters">
|
<div id="meters">
|
||||||
|
@ -1,124 +1,213 @@
|
|||||||
function TelemetryTemplate(gamepad) {
|
window.gamepad.template = class TelemetryTemplate {
|
||||||
return {
|
/**
|
||||||
$clutchBar: document.querySelector('#clutch .bar'),
|
* Instanciates a new telemetry template
|
||||||
$clutchValue: document.querySelector('#clutch .value'),
|
*/
|
||||||
$brakeBar: document.querySelector('#brake .bar'),
|
constructor() {
|
||||||
$brakeValue: document.querySelector('#brake .value'),
|
this.gamepad = window.gamepad;
|
||||||
$throttleBar: document.querySelector('#throttle .bar'),
|
this.init();
|
||||||
$throttleValue: document.querySelector('#throttle .value'),
|
}
|
||||||
$directionIndicator: document.querySelector('#direction .indicator'),
|
|
||||||
AXES: ['clutch', 'brake', 'throttle', 'direction'],
|
/**
|
||||||
frequency: gamepad.getUrlParam('fps') || 60,
|
* Destroys the template
|
||||||
historyLength: gamepad.getUrlParam('history') || 5000,
|
*/
|
||||||
index: 0,
|
destructor() {
|
||||||
init: function () {
|
this.running = false;
|
||||||
this.interval = 1000 / this.frequency;
|
}
|
||||||
this.length = this.historyLength / this.interval;
|
|
||||||
this.loadAxes();
|
/**
|
||||||
this.initChart();
|
* Converts a value to a percentage
|
||||||
},
|
*
|
||||||
toPercentage: function (value, min, max) {
|
* @param {Number} value
|
||||||
return value !== undefined
|
* @param {Number} min
|
||||||
? Math.round((value - min) * (100 / (max - min)))
|
* @param {Number} max
|
||||||
: 0;
|
* @returns {Number}
|
||||||
},
|
*/
|
||||||
toDegrees: function (value, min, max) {
|
toPercentage(value, min, max) {
|
||||||
const percentage = this.toPercentage(value, min, max);
|
return value !== undefined
|
||||||
return (this.directionDegrees) * (percentage - 50) / 100;
|
? Math.round((value - min) * (100 / (max - min)))
|
||||||
},
|
: 0;
|
||||||
toAxisValue: function (gamepad, axis) {
|
}
|
||||||
const { [`${axis}Type`]: type, [`${axis}Index`]: index, [`${axis}Min`]: min, [`${axis}Max`]: max } = this[axis];
|
|
||||||
const value = type === 'button' ? gamepad.buttons[index].value : gamepad.axes[index];
|
/**
|
||||||
return axis === 'direction' ? this.toDegrees(value, min, max) : this.toPercentage(value, min, max);
|
* Converts a value to degrees
|
||||||
},
|
*
|
||||||
loadAxes: function () {
|
* @param {Number} value
|
||||||
this.AXES.forEach((axis) => {
|
* @param {Number} min
|
||||||
this[axis] = {
|
* @param {Number} max
|
||||||
[`${axis}Type`]: (gamepad.getUrlParam(`${axis}Type`) || 'axis').replace('axis', 'axe'),
|
* @returns {Number}
|
||||||
[`${axis}Index`]: gamepad.getUrlParam(`${axis}Index`),
|
*/
|
||||||
[`${axis}Min`]: gamepad.getUrlParam(`${axis}Min`) || -1,
|
toDegrees(value, min, max) {
|
||||||
[`${axis}Max`]: gamepad.getUrlParam(`${axis}Max`) || 1,
|
const percentage = this.toPercentage(value, min, max);
|
||||||
}
|
return (this.directionDegrees) * (percentage - 50) / 100;
|
||||||
});
|
}
|
||||||
this.directionDegrees = gamepad.getUrlParam('directionDegrees') || 360;
|
|
||||||
},
|
/**
|
||||||
initChart: function () {
|
* Set the value of an axis
|
||||||
if (!window.google) {
|
*
|
||||||
window.setTimeout(this.loadGoogleCharts.bind(this), 100);
|
* @param {object} gamepad
|
||||||
|
* @param {string} axis
|
||||||
|
* @returns {Number}
|
||||||
|
*/
|
||||||
|
toAxisValue(gamepad, axis) {
|
||||||
|
const { [`${axis}Type`]: type, [`${axis}Index`]: index, [`${axis}Min`]: min, [`${axis}Max`]: max } = this[axis];
|
||||||
|
const value = type === 'button' ? gamepad.buttons[index].value : gamepad.axes[index];
|
||||||
|
return axis === 'direction' ? this.toDegrees(value, min, max) : this.toPercentage(value, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the axes
|
||||||
|
*/
|
||||||
|
loadAxes() {
|
||||||
|
this.AXES.forEach((axis) => {
|
||||||
|
this[axis] = {
|
||||||
|
[`${axis}Type`]: (gamepad.getUrlParam(`${axis}Type`) || 'axis').replace('axis', 'axe'),
|
||||||
|
[`${axis}Index`]: gamepad.getUrlParam(`${axis}Index`),
|
||||||
|
[`${axis}Min`]: gamepad.getUrlParam(`${axis}Min`) || -1,
|
||||||
|
[`${axis}Max`]: gamepad.getUrlParam(`${axis}Max`) || 1,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.directionDegrees = gamepad.getUrlParam('directionDegrees') || 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the template
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
this.$fps = document.querySelector('#fps');
|
||||||
|
this.$clutchBar = document.querySelector('#clutch .bar');
|
||||||
|
this.$clutchValue = document.querySelector('#clutch .value');
|
||||||
|
this.$brakeBar = document.querySelector('#brake .bar');
|
||||||
|
this.$brakeValue = document.querySelector('#brake .value');
|
||||||
|
this.$throttleBar = document.querySelector('#throttle .bar');
|
||||||
|
this.$throttleValue = document.querySelector('#throttle .value');
|
||||||
|
this.$directionIndicator = document.querySelector('#direction .indicator');
|
||||||
|
this.AXES = ['clutch', 'brake', 'throttle', 'direction'];
|
||||||
|
this.frequency = gamepad.getUrlParam('fps') || 60;
|
||||||
|
this.historyLength = gamepad.getUrlParam('history') || 5000;
|
||||||
|
this.index = 0;
|
||||||
|
this.interval = 1000 / this.frequency;
|
||||||
|
this.length = this.historyLength / this.interval;
|
||||||
|
this.loadAxes();
|
||||||
|
this.initChart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the live chart
|
||||||
|
*/
|
||||||
|
initChart() {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.async = true;
|
||||||
|
script.src = `https://www.gstatic.com/charts/loader.js`;
|
||||||
|
script.onload = () => {
|
||||||
|
if (!google || !google.visualization) {
|
||||||
|
this.loadGoogleCharts();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.drawChart();
|
this.drawChart();
|
||||||
},
|
};
|
||||||
loadGoogleCharts: function () {
|
this.gamepad.$gamepad.appendChild(script);
|
||||||
google.charts.load('current', { packages: ['corechart', 'line'], });
|
}
|
||||||
google.charts.setOnLoadCallback(this.drawChart.bind(this));
|
|
||||||
},
|
|
||||||
drawChart: function () {
|
|
||||||
this.initialData = [['time', 'clutch', 'brake', 'throttle']];
|
|
||||||
for (this.index = 0; this.index < this.length; this.index++) {
|
|
||||||
this.initialData.push([this.index, 0, 0, 0]);
|
|
||||||
}
|
|
||||||
this.data = google.visualization.arrayToDataTable(this.initialData);
|
|
||||||
this.options = {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
chartArea: {
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
},
|
|
||||||
hAxis: {
|
|
||||||
textPosition: 'none',
|
|
||||||
gridlines: {
|
|
||||||
color: 'transparent',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
vAxis: {
|
|
||||||
textPosition: 'none',
|
|
||||||
gridlines: {
|
|
||||||
color: 'transparent',
|
|
||||||
},
|
|
||||||
minValue: 0,
|
|
||||||
maxValue: 100,
|
|
||||||
viewWindow: {
|
|
||||||
min: 2,
|
|
||||||
max: 102,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors: ['#2D64B9', '#A52725', '#0CA818'],
|
|
||||||
legend: 'none'
|
|
||||||
};
|
|
||||||
this.chart = new google.visualization.LineChart(document.querySelector('#chart'));
|
|
||||||
this.chart.draw(this.data, this.options);
|
|
||||||
this.update();
|
|
||||||
},
|
|
||||||
update: function () {
|
|
||||||
const activeGamepad = gamepad.getActive();
|
|
||||||
if (!activeGamepad) return;
|
|
||||||
const [clutch, brake, throttle, direction] = this.AXES.map((axis) => this.toAxisValue(activeGamepad, axis));
|
|
||||||
this.updateChart(clutch, brake, throttle);
|
|
||||||
this.updateMeters(clutch, brake, throttle, direction);
|
|
||||||
window.setTimeout(this.update.bind(this), this.interval);
|
|
||||||
},
|
|
||||||
updateChart: function (clutch, brake, throttle) {
|
|
||||||
this.data.removeRows(0, 1);
|
|
||||||
this.data.addRow([this.index, clutch, brake, throttle]);
|
|
||||||
this.chart.draw(this.data, this.options);
|
|
||||||
this.index++;
|
|
||||||
},
|
|
||||||
updateMeters: function (clutch, brake, throttle, direction) {
|
|
||||||
Object.entries({ clutch, brake, throttle, direction }).forEach(([axis, value]) => {
|
|
||||||
if (axis === 'direction') {
|
|
||||||
this.$directionIndicator.style.transform = `rotate(${value}deg)`;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this[`$${axis}Value`].innerHTML = value;
|
|
||||||
this[`$${axis}Value`].style.opacity = `${Math.round(33 + (value / 1.5))}%`;
|
|
||||||
this[`$${axis}Bar`].style.height = `${value}%`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}.init();
|
|
||||||
};
|
|
||||||
|
|
||||||
new TelemetryTemplate(window.gamepad);
|
/**
|
||||||
|
* Loads the Google Charts library
|
||||||
|
*/
|
||||||
|
loadGoogleCharts() {
|
||||||
|
google.charts.load('current', { packages: ['corechart', 'line'], });
|
||||||
|
google.charts.setOnLoadCallback(this.drawChart.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the live chart with the initial data
|
||||||
|
*/
|
||||||
|
drawChart() {
|
||||||
|
this.initialData = [['time', 'clutch', 'brake', 'throttle']];
|
||||||
|
for (this.index = 0; this.index < this.length; this.index++) {
|
||||||
|
this.initialData.push([this.index, 0, 0, 0]);
|
||||||
|
}
|
||||||
|
this.data = google.visualization.arrayToDataTable(this.initialData);
|
||||||
|
this.options = {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
chartArea: {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
hAxis: {
|
||||||
|
textPosition: 'none',
|
||||||
|
gridlines: {
|
||||||
|
color: 'transparent',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
vAxis: {
|
||||||
|
textPosition: 'none',
|
||||||
|
gridlines: {
|
||||||
|
color: 'transparent',
|
||||||
|
},
|
||||||
|
minValue: 0,
|
||||||
|
maxValue: 100,
|
||||||
|
viewWindow: {
|
||||||
|
min: 2,
|
||||||
|
max: 102,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors: ['#2D64B9', '#A52725', '#0CA818'],
|
||||||
|
legend: 'none'
|
||||||
|
};
|
||||||
|
this.chart = new google.visualization.LineChart(document.querySelector('#chart'));
|
||||||
|
this.chart.draw(this.data, this.options);
|
||||||
|
|
||||||
|
this.running = true;
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the live chart and the meters
|
||||||
|
*/
|
||||||
|
update() {
|
||||||
|
if (!this.running) return;
|
||||||
|
|
||||||
|
const activeGamepad = this.gamepad.getActive();
|
||||||
|
if (!activeGamepad) return;
|
||||||
|
const [clutch, brake, throttle, direction] = this.AXES.map((axis) => this.toAxisValue(activeGamepad, axis));
|
||||||
|
this.updateChart(clutch, brake, throttle);
|
||||||
|
this.updateMeters(clutch, brake, throttle, direction);
|
||||||
|
|
||||||
|
window.setTimeout(this.update.bind(this), this.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the live chart with the latest data
|
||||||
|
*
|
||||||
|
* @param {Number} clutch
|
||||||
|
* @param {Number} brake
|
||||||
|
* @param {Number} throttle
|
||||||
|
*/
|
||||||
|
updateChart(clutch, brake, throttle) {
|
||||||
|
this.data.removeRows(0, 1);
|
||||||
|
this.data.addRow([this.index, clutch, brake, throttle]);
|
||||||
|
this.chart.draw(this.data, this.options);
|
||||||
|
this.index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the meters with the latest data
|
||||||
|
*
|
||||||
|
* @param {Number} clutch
|
||||||
|
* @param {Number} brake
|
||||||
|
* @param {Number} throttle
|
||||||
|
* @param {Number} direction
|
||||||
|
*/
|
||||||
|
updateMeters(clutch, brake, throttle, direction) {
|
||||||
|
Object.entries({ clutch, brake, throttle, direction }).forEach(([axis, value]) => {
|
||||||
|
if (axis === 'direction') {
|
||||||
|
this.$directionIndicator.style.transform = `rotate(${value}deg)`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this[`$${axis}Value`].innerHTML = value;
|
||||||
|
this[`$${axis}Value`].style.opacity = `${Math.round(33 + (value / 1.5))}%`;
|
||||||
|
this[`$${axis}Bar`].style.height = `${value}%`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
<link rel="stylesheet" href="templates/xbox-one/template.css">
|
|
||||||
<script async src="templates/xbox-one/template.js"></script>
|
|
||||||
<div class="triggers">
|
<div class="triggers">
|
||||||
<span class="trigger left" data-button="6"></span>
|
<span class="trigger left" data-button="6"></span>
|
||||||
<span class="trigger right" data-button="7"></span>
|
<span class="trigger right" data-button="7"></span>
|
||||||
|
@ -1,37 +1,34 @@
|
|||||||
function XboxOneTemplate(gamepad) {
|
window.gamepad.template = class XboxOneTemplate {
|
||||||
return {
|
/**
|
||||||
init: function () {
|
* Instanciates a new Xbox One controller template
|
||||||
gamepad.updateButton = function ($button) {
|
*/
|
||||||
const value = parseFloat($button.attr('data-value'), 10);
|
constructor() {
|
||||||
if ($button.is('.trigger')) {
|
this.gamepad = window.gamepad;
|
||||||
$button.css(
|
this.gamepad.updateButton = ($button) => this.updateButton($button);
|
||||||
gamepad.triggersMeter
|
this.gamepad.updateAxis = ($axis) => this.updateAxis($axis);
|
||||||
? {
|
}
|
||||||
opacity: 1,
|
|
||||||
'clip-path': `inset(${(1 - value) * 100}% 0px 0px 0pc)`,
|
/**
|
||||||
}
|
* Destroys the template
|
||||||
: {
|
*/
|
||||||
opacity: `${value * 100}%`,
|
destructor() {
|
||||||
'clip-path': 'none',
|
delete this.gamepad.updateButton;
|
||||||
}
|
delete this.gamepad.updateAxis;
|
||||||
);
|
}
|
||||||
}
|
|
||||||
};
|
updateButton($button) {
|
||||||
gamepad.updateAxis = function ($axis) {
|
if (!$button.matches('.trigger')) return;
|
||||||
const axisX = $axis.attr('data-value-x');
|
const value = parseFloat($button.getAttribute('data-value'), 10);
|
||||||
const axisY = $axis.attr('data-value-y');
|
$button.style.setProperty('opacity', this.gamepad.triggersMeter ? 1 : `${value * 100}%`);
|
||||||
if ($axis.is('.stick')) {
|
$button.style.setProperty('clip-path', this.gamepad.triggersMeter ? `inset(${100 - value * 100}% 0px 0px 0pc)` : 'none');
|
||||||
$axis.css({
|
}
|
||||||
'margin-top': axisY * 25,
|
|
||||||
'margin-left': axisX * 25,
|
updateAxis($axis) {
|
||||||
transform: `rotateX(${-parseFloat(
|
if (!$axis.matches('.stick')) return;
|
||||||
axisY * 30,
|
const axisX = $axis.getAttribute('data-value-x');
|
||||||
8
|
const axisY = $axis.getAttribute('data-value-y');
|
||||||
)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`,
|
$axis.style.setProperty('margin-top', `${axisY * 25}px`);
|
||||||
});
|
$axis.style.setProperty('margin-left', `${axisX * 25}px`);
|
||||||
}
|
$axis.style.setProperty('transform', `rotateX(${-parseFloat(axisY * 30, 8)}deg) rotateY(${parseFloat(axisX * 30, 8)}deg)`);
|
||||||
};
|
}
|
||||||
},
|
|
||||||
}.init();
|
|
||||||
};
|
};
|
||||||
new XboxOneTemplate(window.gamepad);
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user