UNPKG

mylingo3d

Version:

Lingo3D is a React/Vue 3d game development framework that ships with a complete visual editor

142 lines (125 loc) 5.07 kB
import CameraBase from "." import { container } from "../../../engine/renderLoop/renderSetup" import { PerspectiveCamera } from "three" import { getCameraPointerLock, setCameraPointerLock } from "../../../states/useCameraPointerLock" import { mouseEvents } from "../../../api/mouse" import { getCameraRendered } from "../../../states/useCameraRendered" import isMobile from "../../../api/utils/isMobile" import { getEditing } from "../../../states/useEditing" export default function (this: CameraBase<PerspectiveCamera>) { if (this.done) return this.createEffect(() => { if ( getCameraRendered() !== this.camera || !this.mouseControlState.get() ) return if (getCameraPointerLock() === this.camera) { const handleMove = (e: MouseEvent) => this.gyrate(e.movementX, e.movementY) document.addEventListener("mousemove", handleMove) return () => { document.removeEventListener("mousemove", handleMove) } } let started = false let identifier: number | undefined let xOld: number | undefined let yOld: number | undefined const handleDown = () => { started = true ;[xOld, yOld] = [undefined, undefined] } const handleUp = () => (started = false) const handleMove = (e: MouseEvent | Touch) => { xOld === undefined && (xOld = e.clientX) yOld === undefined && (yOld = e.clientY) const [movementX, movementY] = [e.clientX - xOld, e.clientY - yOld] ;[xOld, yOld] = [e.clientX, e.clientY] started && this.gyrate( (movementX / window.innerWidth) * 3000, (movementY / window.innerHeight) * 3000 ) } if (isMobile) { const handleTouchStart = (e: TouchEvent) => { if (identifier !== undefined) return identifier = e.changedTouches[e.changedTouches.length - 1].identifier handleDown() } container.addEventListener("touchstart", handleTouchStart) const handleTouchEnd = (e: TouchEvent) => { if (identifier === undefined) return if ( e.changedTouches[e.changedTouches.length - 1].identifier === identifier ) { identifier = undefined handleUp() } } container.addEventListener("touchend", handleTouchEnd) const handleTouchMove = (e: TouchEvent) => { if (identifier === undefined) return let touch: Touch | undefined for (let i = 0; i < e.changedTouches.length; ++i) { const t = e.changedTouches[i] if (t.identifier === identifier) { touch = t break } } touch && handleMove(touch) } container.addEventListener("touchmove", handleTouchMove) return () => { container.removeEventListener("touchstart", handleTouchStart) container.removeEventListener("touchend", handleTouchEnd) container.removeEventListener("touchmove", handleTouchMove) identifier = undefined started = false } } const handle0 = mouseEvents.on("down", handleDown) const handle1 = mouseEvents.on("up", handleUp) container.addEventListener("mousemove", handleMove) return () => { handle0.cancel() handle1.cancel() container.removeEventListener("mousemove", handleMove) identifier = undefined started = false } }, [this.mouseControlState.get, getCameraRendered, getCameraPointerLock]) this.createEffect(() => { const camera = getCameraRendered() if ( this.mouseControlState.get() !== true || camera !== this.camera || getEditing() ) return const onClick = () => container.requestPointerLock?.() const onPointerLockChange = () => { if (document.pointerLockElement === container) setCameraPointerLock(camera) else setCameraPointerLock(undefined) } container.addEventListener("click", onClick) document.addEventListener("pointerlockchange", onPointerLockChange) return () => { container.removeEventListener("click", onClick) document.removeEventListener( "pointerlockchange", onPointerLockChange ) document.exitPointerLock() setCameraPointerLock(undefined) } }, [this.mouseControlState.get, getCameraRendered, getEditing]) }