//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; } }; });