Skip to content

Commit

Permalink
refactor: simplify pointerlock
Browse files Browse the repository at this point in the history
  • Loading branch information
segunadebayo committed Apr 13, 2022
1 parent e697d5a commit fd4fbbc
Showing 1 changed file with 18 additions and 53 deletions.
71 changes: 18 additions & 53 deletions packages/utilities/dom/src/pointerlock.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,56 @@
import { pipe } from "@zag-js/utils"
import { addDomEvent } from "./listener"

type PointerLockHandlers = {
onPointerLock?: VoidFunction
onPointerUnlock?: VoidFunction
}

export function addPointerlockChangeListener(doc: Document, fn: VoidFunction) {
doc.addEventListener("webkitpointerlockchange", fn, false)
doc.addEventListener("mozpointerlockchange", fn, false)
doc.addEventListener("pointerlockchange", fn, false)
return function cleaup() {
doc.removeEventListener("mozpointerlockchange", fn, false)
doc.removeEventListener("pointerlockchange", fn, false)
}
return addDomEvent(doc, "pointerlockchange", fn, false)
}

export function addPointerlockErrorListener(doc: Document, fn: (e: Event) => void) {
doc.addEventListener("webkitpointerlockerror", fn, false)
doc.addEventListener("mozpointerlockerror", fn, false)
doc.addEventListener("pointerlockerror", fn, false)
return function cleanup() {
doc.removeEventListener("webkitpointerlockerror", fn, false)
doc.removeEventListener("mozpointerlockerror", fn, false)
doc.removeEventListener("pointerlockerror", fn, false)
}
}

function getPointerlockFunc(el: HTMLElement) {
return el.requestPointerLock || (el as any).mozRequestPointerLock || (el as any).webkitRequestPointerLock
}

function getRemovePointerlockFunc(doc: Document) {
return doc.exitPointerLock || (doc as any).mozExitPointerLock || (doc as any).webkitExitPointerLock
}

export function getPointerlockElement(doc: Document) {
return doc.pointerLockElement || (doc as any).mozPointerLockElement || (doc as any).webkitPointerLockElement
}

export function requestPointerLock(doc: Document, handlers: PointerLockHandlers = {}) {
const { onPointerLock, onPointerUnlock } = handlers
const body = doc.body

function isSupported() {
return "pointerLockElement" in doc || "mozPointerLockElement" in doc || "webkitPointerLockElement" in doc
}

function hasLockElement() {
return !!doc.pointerLockElement
}
const supported = "pointerLockElement" in doc || "mozPointerLockElement" in doc
const locked = !!doc.pointerLockElement

function onPointerChange() {
if (hasLockElement()) onPointerLock?.()
if (locked) onPointerLock?.()
else onPointerUnlock?.()
}

function onPointerError(event: Event) {
const isLocked = hasLockElement()
if (isLocked) onPointerUnlock?.()
if (locked) onPointerUnlock?.()
console.error("PointerLock error occured:", event)
exit()
}

function exit() {
doc.exitPointerLock = getRemovePointerlockFunc(doc)
doc.exitPointerLock()
}

const cleanups: Set<Function> = new Set()
if (!supported) return

function addEventListeners() {
cleanups.add(addPointerlockChangeListener(doc, onPointerChange))
cleanups.add(addPointerlockErrorListener(doc, onPointerError))
}
body.requestPointerLock()

function dispose() {
if (!isSupported()) return
cleanups.forEach((fn) => fn())
cleanups.clear()
exit()
}
const cleanup = pipe(
addPointerlockChangeListener(doc, onPointerChange),
addPointerlockErrorListener(doc, onPointerError),
)

function setup() {
if (!isSupported() || !hasLockElement()) return
body.requestPointerLock = getPointerlockFunc(body)
body.requestPointerLock()
addEventListeners()
return function dispose() {
if (!supported) return
cleanup()
exit()
}

setup()
return dispose
}

0 comments on commit fd4fbbc

Please sign in to comment.