Skip to content

Commit 4f96828

Browse files
committed
imp: improve touch and ui pointer handling
1 parent d53c22e commit 4f96828

File tree

2 files changed

+49
-59
lines changed

2 files changed

+49
-59
lines changed

src/core/entities/PlayerLocal.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ export class PlayerLocal extends Entity {
280280
if (!this.stick && touch.position.x < this.control.screen.width / 2) {
281281
this.stick = {
282282
center: touch.position.clone(),
283+
active: false,
283284
touch,
284285
}
285286
} else if (!this.pan) {
@@ -745,6 +746,11 @@ export class PlayerLocal extends Entity {
745746
this.avatar.visible = true
746747
}
747748

749+
// stick movement threshold
750+
if (this.stick && !this.stick.active) {
751+
this.stick.active = this.stick.center.distanceTo(this.stick.touch.position) > 3
752+
}
753+
748754
// watch jump presses to either fly or air-jump
749755
this.jumpDown = isXR ? this.control.xrRightBtn1.down : this.control.space.down || this.control.touchA.down
750756
if (isXR ? this.control.xrRightBtn1.pressed : this.control.space.pressed || this.control.touchA.pressed) {
@@ -757,7 +763,7 @@ export class PlayerLocal extends Entity {
757763
// in xr use controller input
758764
this.moveDir.x = this.control.xrLeftStick.value.x
759765
this.moveDir.z = this.control.xrLeftStick.value.z
760-
} else if (this.stick) {
766+
} else if (this.stick?.active) {
761767
// if we have a touch joystick use that
762768
const touchX = this.stick.touch.position.x
763769
const touchY = this.stick.touch.position.y
@@ -799,7 +805,7 @@ export class PlayerLocal extends Entity {
799805
}
800806

801807
// determine if we're "running"
802-
if (this.stick || isXR) {
808+
if (this.stick?.active || isXR) {
803809
// touch/xr joysticks at full extent
804810
this.running = this.moving && this.moveDir.length() > 0.9
805811
} else {

src/core/systems/ClientControls.js

Lines changed: 41 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { isTouch } from '../../client/utils'
12
import { bindRotations } from '../extras/bindRotations'
23
import { buttons, codeToProp } from '../extras/buttons'
34
import * as THREE from '../extras/three'
@@ -225,18 +226,16 @@ export class ClientControls extends System {
225226
async init({ viewport }) {
226227
if (!isBrowser) return
227228
this.viewport = viewport
229+
this.viewport.style.touchAction = 'none' // we use a unified 'pointer' event system
228230
this.screen.width = this.viewport.offsetWidth
229231
this.screen.height = this.viewport.offsetHeight
230232
window.addEventListener('keydown', this.onKeyDown)
231233
window.addEventListener('keyup', this.onKeyUp)
232234
document.addEventListener('pointerlockchange', this.onPointerLockChange)
233235
this.viewport.addEventListener('pointerdown', this.onPointerDown)
234236
window.addEventListener('pointermove', this.onPointerMove)
235-
this.viewport.addEventListener('touchstart', this.onTouchStart)
236-
this.viewport.addEventListener('touchmove', this.onTouchMove)
237-
this.viewport.addEventListener('touchend', this.onTouchEnd)
238-
this.viewport.addEventListener('touchcancel', this.onTouchEnd)
239237
this.viewport.addEventListener('pointerup', this.onPointerUp)
238+
this.viewport.addEventListener('pointercancel', this.onPointerUp)
240239
this.viewport.addEventListener('wheel', this.onScroll, { passive: false })
241240
document.body.addEventListener('contextmenu', this.onContextMenu)
242241
window.addEventListener('resize', this.onResize)
@@ -455,11 +454,37 @@ export class ClientControls extends System {
455454

456455
onPointerDown = e => {
457456
if (e.isCoreUI) return
457+
if (e.pointerType === 'touch') {
458+
e.preventDefault()
459+
const info = {
460+
id: e.pointerId,
461+
position: new THREE.Vector3(e.clientX, e.clientY, 0),
462+
prevPosition: new THREE.Vector3(e.clientX, e.clientY, 0),
463+
delta: new THREE.Vector3(),
464+
pointerType: e.pointerType,
465+
}
466+
this.touches.set(e.pointerId, info)
467+
for (const control of this.controls) {
468+
const consume = control.options.onTouch?.(info)
469+
if (consume) break
470+
}
471+
}
458472
this.checkPointerChanges(e)
459473
}
460474

461475
onPointerMove = e => {
462476
if (e.isCoreUI) return
477+
if (e.pointerType === 'touch') {
478+
const info = this.touches.get(e.pointerId)
479+
if (info) {
480+
info.delta.x += e.clientX - info.prevPosition.x
481+
info.delta.y += e.clientY - info.prevPosition.y
482+
info.position.x = e.clientX
483+
info.position.y = e.clientY
484+
info.prevPosition.x = e.clientX
485+
info.prevPosition.y = e.clientY
486+
}
487+
}
463488
// this.checkPointerChanges(e)
464489
const rect = this.viewport.getBoundingClientRect()
465490
const offsetX = e.pageX - rect.left
@@ -474,6 +499,16 @@ export class ClientControls extends System {
474499

475500
onPointerUp = e => {
476501
if (e.isCoreUI) return
502+
if (e.pointerType === 'touch') {
503+
const info = this.touches.get(e.pointerId)
504+
if (info) {
505+
for (const control of this.controls) {
506+
const consume = control.options.onTouchEnd?.(info)
507+
if (consume) break
508+
}
509+
this.touches.delete(e.pointerId)
510+
}
511+
}
477512
this.checkPointerChanges(e)
478513
}
479514

@@ -537,6 +572,7 @@ export class ClientControls extends System {
537572
}
538573

539574
async lockPointer() {
575+
if (isTouch) return
540576
this.pointer.shouldLock = true
541577
try {
542578
await this.viewport.requestPointerLock()
@@ -589,55 +625,6 @@ export class ClientControls extends System {
589625
e.preventDefault()
590626
}
591627

592-
onTouchStart = e => {
593-
if (e.isCoreUI) return
594-
e.preventDefault()
595-
for (let i = 0; i < e.changedTouches.length; i++) {
596-
const touch = e.changedTouches[i]
597-
const info = {
598-
id: touch.identifier,
599-
position: new THREE.Vector3(touch.clientX, touch.clientY, 0),
600-
prevPosition: new THREE.Vector3(touch.clientX, touch.clientY, 0),
601-
delta: new THREE.Vector3(),
602-
}
603-
this.touches.set(info.id, info)
604-
for (const control of this.controls) {
605-
const consume = control.options.onTouch?.(info)
606-
if (consume) break
607-
}
608-
}
609-
}
610-
611-
onTouchMove = e => {
612-
if (e.isCoreUI) return
613-
for (let i = 0; i < e.changedTouches.length; i++) {
614-
const touch = e.changedTouches[i]
615-
const info = this.touches.get(touch.identifier)
616-
if (!info) continue
617-
const currentX = touch.clientX
618-
const currentY = touch.clientY
619-
info.delta.x += currentX - info.prevPosition.x
620-
info.delta.y += currentY - info.prevPosition.y
621-
info.position.x = currentX
622-
info.position.y = currentY
623-
info.prevPosition.x = currentX
624-
info.prevPosition.y = currentY
625-
}
626-
}
627-
628-
onTouchEnd = e => {
629-
if (e.isCoreUI) return
630-
for (let i = 0; i < e.changedTouches.length; i++) {
631-
const touch = e.changedTouches[i]
632-
const info = this.touches.get(touch.identifier)
633-
for (const control of this.controls) {
634-
const consume = control.options.onTouchEnd?.(info)
635-
if (consume) break
636-
}
637-
this.touches.delete(touch.identifier)
638-
}
639-
}
640-
641628
onResize = () => {
642629
this.screen.width = this.viewport.offsetWidth
643630
this.screen.height = this.viewport.offsetHeight
@@ -666,11 +653,8 @@ export class ClientControls extends System {
666653
document.removeEventListener('pointerlockchange', this.onPointerLockChange)
667654
this.viewport.removeEventListener('pointerdown', this.onPointerDown)
668655
window.removeEventListener('pointermove', this.onPointerMove)
669-
this.viewport.removeEventListener('touchstart', this.onTouchStart)
670-
this.viewport.removeEventListener('touchmove', this.onTouchMove)
671-
this.viewport.removeEventListener('touchend', this.onTouchEnd)
672-
this.viewport.removeEventListener('touchcancel', this.onTouchEnd)
673656
this.viewport.removeEventListener('pointerup', this.onPointerUp)
657+
this.viewport.removeEventListener('pointercancel', this.onPointerUp)
674658
this.viewport.removeEventListener('wheel', this.onScroll, { passive: false })
675659
document.body.removeEventListener('contextmenu', this.onContextMenu)
676660
window.removeEventListener('resize', this.onResize)

0 commit comments

Comments
 (0)