214 lines
7.6 KiB
JavaScript
214 lines
7.6 KiB
JavaScript
//v9
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const canvas = document.getElementById('unity-canvas');
|
|
if (!canvas) {
|
|
console.error("Canvas element with id='unity-canvas' not found!");
|
|
return;
|
|
}
|
|
|
|
// Track lock state
|
|
window.isPointerLocked = false;
|
|
|
|
// Track if unadjustedMovement is supported (assume yes until proven otherwise)
|
|
let unadjustedMovementSupported = true;
|
|
|
|
// Utility: Check if pointer lock API is available
|
|
function hasPointerLockAPI() {
|
|
return !!(canvas.requestPointerLock ||
|
|
canvas.webkitRequestPointerLock ||
|
|
canvas.mozRequestPointerLock);
|
|
}
|
|
|
|
// Safari detection
|
|
function isSafari() {
|
|
// This UA check excludes Chrome on iOS
|
|
return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
|
}
|
|
|
|
// Called when pointer lock state changes
|
|
function onPointerLockChange() {
|
|
const doc = document;
|
|
const locked = (
|
|
doc.pointerLockElement === canvas ||
|
|
doc.webkitPointerLockElement === canvas ||
|
|
doc.mozPointerLockElement === canvas
|
|
);
|
|
window.isPointerLocked = locked;
|
|
|
|
if (locked) {
|
|
console.log("----cursor locking----");
|
|
canvas.style.cursor = "none";
|
|
} else {
|
|
console.log("----cursor unlocking----");
|
|
canvas.style.cursor = "default";
|
|
}
|
|
|
|
sendLockStateToUnity(locked);
|
|
}
|
|
|
|
// Called when pointer lock errors out
|
|
function onPointerLockError(event) {
|
|
console.error("----pointer lock error----", event);
|
|
sendLockStateToUnity(false);
|
|
// For macOS Safari: add a one-time mousedown fallback if pointer isn't locked.
|
|
if (isSafari() && !window.isPointerLocked) {
|
|
console.log("----Safari fallback: adding one-time mousedown listener for pointer lock----");
|
|
addOneTimeMouseDownListener();
|
|
}
|
|
}
|
|
|
|
// Helper to add a one-time mousedown listener for fallback pointer lock
|
|
function addOneTimeMouseDownListener() {
|
|
// Use a named function so we can remove it if needed
|
|
function fallbackMouseDown(e) {
|
|
console.log("----Fallback mousedown triggered, retrying pointer lock----");
|
|
canvas.removeEventListener('mousedown', fallbackMouseDown);
|
|
lockPointerNow();
|
|
}
|
|
canvas.addEventListener('mousedown', fallbackMouseDown, false);
|
|
}
|
|
|
|
// Listen for pointer lock changes/errors (all vendor prefixes)
|
|
document.addEventListener('pointerlockchange', onPointerLockChange, false);
|
|
document.addEventListener('webkitpointerlockchange', onPointerLockChange, false);
|
|
document.addEventListener('mozpointerlockchange', onPointerLockChange, false);
|
|
|
|
document.addEventListener('pointerlockerror', onPointerLockError, false);
|
|
document.addEventListener('webkitpointerlockerror', onPointerLockError, false);
|
|
document.addEventListener('mozpointerlockerror', onPointerLockError, false);
|
|
|
|
// Send pointer lock state back to Unity
|
|
function sendLockStateToUnity(isLocked) {
|
|
if (typeof unityInstance !== 'undefined' && unityInstance && unityInstance.SendMessage) {
|
|
try {
|
|
unityInstance.SendMessage('CursorController', 'OnLockChange', isLocked ? 'true' : 'false');
|
|
} catch (e) {
|
|
console.warn("----Failed to send lock state to Unity----", e);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Request pointer lock without options (basic fallback)
|
|
function requestPointerLockBasic() {
|
|
if (canvas.requestPointerLock) {
|
|
canvas.requestPointerLock();
|
|
} else if (canvas.webkitRequestPointerLock) {
|
|
canvas.webkitRequestPointerLock();
|
|
} else if (canvas.mozRequestPointerLock) {
|
|
canvas.mozRequestPointerLock();
|
|
}
|
|
}
|
|
|
|
// Request pointer lock with unadjustedMovement option
|
|
async function requestPointerLockWithOptions() {
|
|
if (canvas.requestPointerLock) {
|
|
return canvas.requestPointerLock({ unadjustedMovement: true });
|
|
} else if (canvas.webkitRequestPointerLock) {
|
|
return canvas.webkitRequestPointerLock({ unadjustedMovement: true });
|
|
} else if (canvas.mozRequestPointerLock) {
|
|
return canvas.mozRequestPointerLock({ unadjustedMovement: true });
|
|
}
|
|
}
|
|
|
|
// Attempt to lock pointer
|
|
async function lockPointerNow() {
|
|
console.log("----attempting pointer lock----");
|
|
|
|
if (!hasPointerLockAPI()) {
|
|
console.warn("----Pointer lock API not supported in this browser----");
|
|
sendLockStateToUnity(false);
|
|
return;
|
|
}
|
|
|
|
// If Safari, skip the options param entirely
|
|
if (isSafari()) {
|
|
console.log("----Safari detected; skipping unadjustedMovement param----");
|
|
try {
|
|
requestPointerLockBasic();
|
|
} catch (err) {
|
|
console.error("----Safari pointer lock request failed----", err);
|
|
sendLockStateToUnity(false);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Non-Safari browsers
|
|
// Check permissions if available (non-blocking, just for logging)
|
|
if (navigator.permissions && navigator.permissions.query) {
|
|
try {
|
|
const permStatus = await navigator.permissions.query({ name: 'pointer-lock' });
|
|
console.log("----pointer lock permission state: " + permStatus.state + "----");
|
|
} catch (permError) {
|
|
// Permissions API may not support pointer-lock query - that's fine
|
|
console.log("----Permissions API query not supported for pointer-lock----");
|
|
}
|
|
}
|
|
|
|
// Try with unadjustedMovement if supported, otherwise use basic request
|
|
if (unadjustedMovementSupported) {
|
|
try {
|
|
await requestPointerLockWithOptions();
|
|
console.log("----pointer lock request initiated with unadjustedMovement----");
|
|
} catch (err) {
|
|
// Check if error is due to unadjustedMovement not being supported
|
|
if (err && (err.name === 'NotSupportedError' || err.name === 'TypeError')) {
|
|
console.warn("----unadjustedMovement not supported, falling back to basic pointer lock----");
|
|
unadjustedMovementSupported = false;
|
|
// Retry immediately with basic request
|
|
try {
|
|
requestPointerLockBasic();
|
|
console.log("----pointer lock request initiated (basic fallback)----");
|
|
} catch (fallbackErr) {
|
|
console.error("----pointer lock request failed (basic fallback)----", fallbackErr);
|
|
sendLockStateToUnity(false);
|
|
}
|
|
} else {
|
|
console.error("----pointer lock request failed (non-Safari)----", err);
|
|
sendLockStateToUnity(false);
|
|
}
|
|
}
|
|
} else {
|
|
// We already know unadjustedMovement isn't supported, use basic request
|
|
try {
|
|
requestPointerLockBasic();
|
|
console.log("----pointer lock request initiated (basic, cached)----");
|
|
} catch (err) {
|
|
console.error("----pointer lock request failed (basic)----", err);
|
|
sendLockStateToUnity(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Attempt to unlock pointer
|
|
function unlockPointerNow() {
|
|
console.log("----attempting pointer unlock----");
|
|
const doc = document;
|
|
if (doc.pointerLockElement === canvas ||
|
|
doc.webkitPointerLockElement === canvas ||
|
|
doc.mozpointerLockElement === canvas) {
|
|
if (doc.exitPointerLock) {
|
|
doc.exitPointerLock();
|
|
} else if (doc.webkitExitPointerLock) {
|
|
doc.webkitExitPointerLock();
|
|
} else if (doc.mozExitPointerLock) {
|
|
doc.mozExitPointerLock();
|
|
}
|
|
console.log("----pointer unlock request sent----");
|
|
} else {
|
|
console.warn("----pointer is not locked to the canvas----");
|
|
sendLockStateToUnity(false);
|
|
}
|
|
}
|
|
|
|
// Expose lock/unlock globally for Unity ExternalCall usage
|
|
window.lockPointerNow = lockPointerNow;
|
|
window.unlockPointerNow = unlockPointerNow;
|
|
|
|
// Expose a function to change cursor style
|
|
window.setCursor = function setCursor(cursorStyle) {
|
|
if (canvas) {
|
|
canvas.style.cursor = cursorStyle;
|
|
}
|
|
};
|
|
});
|