UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

154 lines (153 loc) 4.42 kB
import { platform } from "../../core/platform.js"; import { EventHandler } from "../../core/event-handler.js"; import { isMousePointerLocked, MouseEvent } from "./mouse-event.js"; class Mouse extends EventHandler { static EVENT_MOUSEMOVE = "mousemove"; static EVENT_MOUSEDOWN = "mousedown"; static EVENT_MOUSEUP = "mouseup"; static EVENT_MOUSEWHEEL = "mousewheel"; _lastX = 0; _lastY = 0; _buttons = [false, false, false]; _lastbuttons = [false, false, false]; _target = null; _attached = false; _upHandler; _downHandler; _moveHandler; _wheelHandler; _contextMenuHandler; constructor(element) { super(); this._upHandler = this._handleUp.bind(this); this._downHandler = this._handleDown.bind(this); this._moveHandler = this._handleMove.bind(this); this._wheelHandler = this._handleWheel.bind(this); this._contextMenuHandler = (event) => { event.preventDefault(); }; this.attach(element); } static isPointerLocked() { return isMousePointerLocked(); } attach(element) { this._target = element; if (this._attached) return; this._attached = true; const passiveOptions = { passive: false }; const options = platform.passiveEvents ? passiveOptions : false; window.addEventListener("mouseup", this._upHandler, options); window.addEventListener("mousedown", this._downHandler, options); window.addEventListener("mousemove", this._moveHandler, options); window.addEventListener("wheel", this._wheelHandler, options); } detach() { if (!this._attached) return; this._attached = false; this._target = null; const passiveOptions = { passive: false }; const options = platform.passiveEvents ? passiveOptions : false; window.removeEventListener("mouseup", this._upHandler, options); window.removeEventListener("mousedown", this._downHandler, options); window.removeEventListener("mousemove", this._moveHandler, options); window.removeEventListener("wheel", this._wheelHandler, options); } disableContextMenu() { if (!this._target) return; this._target.addEventListener("contextmenu", this._contextMenuHandler); } enableContextMenu() { if (!this._target) return; this._target.removeEventListener("contextmenu", this._contextMenuHandler); } enablePointerLock(success, error) { if (!document.body.requestPointerLock) { if (error) { error(); } return; } const s = () => { success(); document.removeEventListener("pointerlockchange", s); }; const e = () => { error(); document.removeEventListener("pointerlockerror", e); }; if (success) { document.addEventListener("pointerlockchange", s, false); } if (error) { document.addEventListener("pointerlockerror", e, false); } document.body.requestPointerLock(); } disablePointerLock(success) { if (!document.exitPointerLock) { return; } const s = () => { success(); document.removeEventListener("pointerlockchange", s); }; if (success) { document.addEventListener("pointerlockchange", s, false); } document.exitPointerLock(); } update() { this._lastbuttons[0] = this._buttons[0]; this._lastbuttons[1] = this._buttons[1]; this._lastbuttons[2] = this._buttons[2]; } isPressed(button) { return this._buttons[button]; } wasPressed(button) { return this._buttons[button] && !this._lastbuttons[button]; } wasReleased(button) { return !this._buttons[button] && this._lastbuttons[button]; } _handleUp(event) { this._buttons[event.button] = false; const e = new MouseEvent(this, event); if (!e.event) return; this.fire("mouseup", e); } _handleDown(event) { this._buttons[event.button] = true; const e = new MouseEvent(this, event); if (!e.event) return; this.fire("mousedown", e); } _handleMove(event) { const e = new MouseEvent(this, event); if (!e.event) return; this.fire("mousemove", e); this._lastX = e.x; this._lastY = e.y; } _handleWheel(event) { const e = new MouseEvent(this, event); if (!e.event) return; this.fire("mousewheel", e); } _getTargetCoords(event) { const rect = this._target.getBoundingClientRect(); const left = Math.floor(rect.left); const top = Math.floor(rect.top); if (event.clientX < left || event.clientX >= left + this._target.clientWidth || event.clientY < top || event.clientY >= top + this._target.clientHeight) { return null; } return { x: event.clientX - left, y: event.clientY - top }; } } export { Mouse };