313 lines
8.8 KiB
JavaScript
313 lines
8.8 KiB
JavaScript
function simulateGamepad() {
|
|
const app = window.app;
|
|
app.chrome.showCursor = true;
|
|
let cursorPos = [0, 0];
|
|
let intTabIndex = 0;
|
|
const cursorSpeedPvt = 8;
|
|
const cursorSize = 16;
|
|
let scrollSpeed = 8;
|
|
let buttonPressDelay = 500;
|
|
let stickDeadZone = 0.2;
|
|
let scrollGroup = null;
|
|
let scrollGroupY = null;
|
|
let elementFocusEnabled = true;
|
|
let start;
|
|
|
|
let cursorSpeed = cursorSpeedPvt;
|
|
|
|
let lastButtonPress = {};
|
|
|
|
var sounds = {
|
|
Confirm: new Audio("./sounds/confirm.ogg"),
|
|
Menu: new Audio("./sounds/btn1.ogg"),
|
|
Hover: new Audio("./sounds/hover.ogg"),
|
|
};
|
|
|
|
let element = document.elementFromPoint(0, 0);
|
|
let elementType = 0;
|
|
|
|
function appLoop() {
|
|
var gamepads = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : [];
|
|
if (!gamepads) {
|
|
return;
|
|
}
|
|
|
|
var gp = gamepads[0];
|
|
|
|
// LEFT STICK
|
|
if (gp.axes[0] > stickDeadZone) {
|
|
cursorPos[0] += gp.axes[0] * cursorSpeed;
|
|
} else if (gp.axes[0] < -stickDeadZone) {
|
|
cursorPos[0] += gp.axes[0] * cursorSpeed;
|
|
}
|
|
|
|
if (gp.axes[1] > stickDeadZone) {
|
|
cursorPos[1] += gp.axes[1] * cursorSpeed;
|
|
} else if (gp.axes[1] < -stickDeadZone) {
|
|
cursorPos[1] += gp.axes[1] * cursorSpeed;
|
|
}
|
|
|
|
if (cursorPos[0] < cursorSize) {
|
|
cursorPos[0] = cursorSize;
|
|
}
|
|
if (cursorPos[1] < cursorSize) {
|
|
cursorPos[1] = cursorSize;
|
|
}
|
|
if (cursorPos[0] > window.innerWidth - cursorSize) {
|
|
cursorPos[0] = window.innerWidth - cursorSize;
|
|
}
|
|
if (cursorPos[1] > window.innerHeight - cursorSize) {
|
|
cursorPos[1] = window.innerHeight - cursorSize;
|
|
}
|
|
|
|
// RIGHT STICK.
|
|
if (scrollGroupY) {
|
|
if (gp.axes[3] > stickDeadZone) {
|
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + gp.axes[3] * scrollSpeed);
|
|
elementFocusEnabled = false;
|
|
} else if (gp.axes[3] < -stickDeadZone) {
|
|
$(scrollGroupY).scrollTop($(scrollGroupY).scrollTop() + gp.axes[3] * scrollSpeed);
|
|
elementFocusEnabled = false;
|
|
} else {
|
|
elementFocusEnabled = true;
|
|
}
|
|
}
|
|
|
|
if (scrollGroup) {
|
|
if (gp.axes[2] > stickDeadZone) {
|
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + gp.axes[2] * scrollSpeed);
|
|
elementFocusEnabled = false;
|
|
} else if (gp.axes[2] < -stickDeadZone) {
|
|
$(scrollGroup).scrollLeft($(scrollGroup).scrollLeft() + gp.axes[2] * scrollSpeed);
|
|
elementFocusEnabled = false;
|
|
} else {
|
|
elementFocusEnabled = true;
|
|
}
|
|
}
|
|
|
|
$(".cursor").css({
|
|
top: cursorPos[1] + "px",
|
|
left: cursorPos[0] + "px",
|
|
display: "block",
|
|
});
|
|
|
|
// A BUTTON
|
|
if (gp.buttons[0].pressed) {
|
|
if (!lastButtonPress["A"]) {
|
|
lastButtonPress["A"] = 0;
|
|
}
|
|
if (Date.now() - lastButtonPress["A"] > buttonPressDelay) {
|
|
lastButtonPress["A"] = Date.now();
|
|
sounds.Confirm.play();
|
|
if (elementType == 0) {
|
|
document.activeElement.dispatchEvent(new Event("click"));
|
|
document.activeElement.dispatchEvent(new Event("controller-click"));
|
|
} else {
|
|
element.dispatchEvent(new Event("click"));
|
|
element.dispatchEvent(new Event("controller-click"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// B BUTTON
|
|
if (gp.buttons[1].pressed) {
|
|
if (!lastButtonPress["B"]) {
|
|
lastButtonPress["B"] = 0;
|
|
}
|
|
if (Date.now() - lastButtonPress["B"] > buttonPressDelay) {
|
|
lastButtonPress["B"] = Date.now();
|
|
if (elementType == 0) {
|
|
document.activeElement.dispatchEvent(new Event("contextmenu"));
|
|
setTimeout(() => {
|
|
if ($(".menu-option").length > 0) {
|
|
let bounds = $(".menu-option")[0].getBoundingClientRect();
|
|
cursorPos[0] = bounds.left + bounds.width / 2;
|
|
cursorPos[1] = bounds.top + bounds.height / 2;
|
|
}
|
|
}, 100);
|
|
} else {
|
|
element.dispatchEvent(new Event("contextmenu"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// right bumper
|
|
if (gp.buttons[5].pressed) {
|
|
if (!lastButtonPress["RB"]) {
|
|
lastButtonPress["RB"] = 0;
|
|
}
|
|
if (Date.now() - lastButtonPress["RB"] > buttonPressDelay) {
|
|
lastButtonPress["RB"] = Date.now();
|
|
app.navigateForward();
|
|
}
|
|
}
|
|
|
|
// left bumper
|
|
if (gp.buttons[4].pressed) {
|
|
if (!lastButtonPress["LB"]) {
|
|
lastButtonPress["LB"] = 0;
|
|
}
|
|
if (Date.now() - lastButtonPress["LB"] > buttonPressDelay) {
|
|
lastButtonPress["LB"] = Date.now();
|
|
app.navigateBack();
|
|
}
|
|
}
|
|
|
|
// cursor hover
|
|
if (elementFocusEnabled) {
|
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1]);
|
|
}
|
|
|
|
if (element) {
|
|
let closest = element.closest("[tabindex], input, button, a");
|
|
|
|
// VERT SCROLL
|
|
let scrollGroupCloY = element.closest(`[scrollaxis="y"]`);
|
|
if (scrollGroupCloY) {
|
|
scrollGroupY = scrollGroupCloY;
|
|
}
|
|
|
|
// HOZ SCROLL
|
|
let scrollGroupClo = element.closest(".v-hl-container");
|
|
|
|
if (scrollGroupClo) {
|
|
if (scrollGroupClo.classList.contains("v-hl-container")) {
|
|
scrollGroup = scrollGroupClo;
|
|
scrollGroup.style["scroll-snap-type"] = "unset";
|
|
} else {
|
|
scrollGroup.style["scroll-snap-type"] = "";
|
|
scrollGroup = null;
|
|
}
|
|
}
|
|
|
|
if (closest) {
|
|
elementType = 0;
|
|
closest.focus();
|
|
} else {
|
|
if (closest) {
|
|
closest.blur();
|
|
}
|
|
elementType = 1;
|
|
element.focus();
|
|
}
|
|
cursorSpeed = cursorSpeedPvt;
|
|
if (!element.classList.contains("app-chrome") && !element.classList.contains("app-content")) {
|
|
cursorSpeed = cursorSpeedPvt;
|
|
}
|
|
// console.log($._data($(element), "events"))
|
|
} else {
|
|
cursorSpeed = 12;
|
|
}
|
|
// console.log(gp.axes[0], gp.axes[1])
|
|
start = requestAnimationFrame(appLoop);
|
|
}
|
|
|
|
// controller pairing
|
|
notyf.error("Press the button on your controller to pair it to Cider.");
|
|
window.addEventListener(
|
|
"gamepadconnected",
|
|
function (e) {
|
|
console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", e.gamepad.index, e.gamepad.id, e.gamepad.buttons.length, e.gamepad.axes.length);
|
|
notyf.success("Pairing successful!");
|
|
appLoop();
|
|
},
|
|
{ once: true }
|
|
);
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
sounds.Confirm.currentTime = 0;
|
|
sounds.Menu.currentTime = 0;
|
|
sounds.Hover.currentTime = 0;
|
|
let tabbable = $("[tabindex]");
|
|
console.log(e.key);
|
|
switch (e.key) {
|
|
default:
|
|
break;
|
|
case "ArrowLeft":
|
|
e.preventDefault();
|
|
|
|
cursorPos[0] -= cursorSpeed;
|
|
break;
|
|
case "ArrowRight":
|
|
e.preventDefault();
|
|
|
|
cursorPos[0] += cursorSpeed;
|
|
break;
|
|
case "ArrowUp":
|
|
e.preventDefault();
|
|
|
|
cursorPos[1] -= cursorSpeed;
|
|
// sounds.Hover.play()
|
|
// if (intTabIndex <= 0) {
|
|
// intTabIndex = 0
|
|
// } else {
|
|
// intTabIndex--
|
|
// }
|
|
// $(tabbable[intTabIndex]).focus()
|
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
|
break;
|
|
case "ArrowDown":
|
|
e.preventDefault();
|
|
|
|
cursorPos[1] += cursorSpeed;
|
|
// if (intTabIndex < tabbable.length) {
|
|
// intTabIndex++
|
|
// } else {
|
|
// intTabIndex = tabbable.length
|
|
// }
|
|
// $(tabbable[intTabIndex]).focus()
|
|
// $("#app-content").scrollTop($(document.activeElement).offset().top)
|
|
break;
|
|
case "c":
|
|
app.resetState();
|
|
break;
|
|
case "x":
|
|
// set cursorPos to the top right of the screen
|
|
// sounds.Menu.play()
|
|
if (elementType == 0) {
|
|
document.activeElement.dispatchEvent(new Event("contextmenu"));
|
|
} else {
|
|
element.dispatchEvent(new Event("contextmenu"));
|
|
}
|
|
|
|
e.preventDefault();
|
|
break;
|
|
case "z":
|
|
sounds.Confirm.play();
|
|
if (elementType == 0) {
|
|
document.activeElement.dispatchEvent(new Event("click"));
|
|
document.activeElement.dispatchEvent(new Event("controller-click"));
|
|
} else {
|
|
element.dispatchEvent(new Event("click"));
|
|
element.dispatchEvent(new Event("controller-click"));
|
|
}
|
|
|
|
e.preventDefault();
|
|
break;
|
|
}
|
|
|
|
$(".cursor").css({
|
|
top: cursorPos[1] + "px",
|
|
left: cursorPos[0] + "px",
|
|
});
|
|
function lerp(a, b, n) {
|
|
return (1 - n) * a + n * b;
|
|
}
|
|
|
|
element = document.elementFromPoint(cursorPos[0], cursorPos[1]);
|
|
|
|
if (element) {
|
|
let closest = element.closest("[tabindex], input, button, a");
|
|
if (closest) {
|
|
elementType = 0;
|
|
closest.focus();
|
|
} else {
|
|
elementType = 1;
|
|
element.focus();
|
|
}
|
|
}
|
|
console.log(element);
|
|
});
|
|
}
|
|
|
|
export { simulateGamepad };
|