3dexperiments/src/engine/input.js

223 lines
4.2 KiB
JavaScript

const specialKeyMap = {
backspace: 8,
tab: 9,
enter: 13,
shift: 16,
ctrl: 17,
alt: 18,
pausebreak: 19,
capslock: 20,
escape: 27,
pgup: 33,
pgdown: 34,
end: 35,
home: 36,
left: 37,
up: 38,
right: 39,
down: 40,
insert: 45,
delete: 46,
'left-window': 91,
'right-window': 92,
select: 93,
numpad0: 96,
numpad1: 97,
numpad2: 98,
numpad3: 99,
numpad4: 100,
numpad5: 101,
numpad6: 102,
numpad7: 103,
numpad8: 104,
numpad9: 105,
multiply: 106,
add: 107,
subtract: 109,
decimal: 110,
divide: 111,
f1: 112,
f2: 113,
f3: 114,
f4: 115,
f5: 116,
f6: 117,
f7: 118,
f8: 119,
f9: 120,
f10: 121,
f11: 122,
f12: 123,
numlock: 144,
scrolllock: 145,
'semi-colon': 186,
equals: 187,
comma: 188,
dash: 189,
period: 190,
fwdslash: 191,
grave: 192,
'open-bracket': 219,
bkslash: 220,
'close-braket': 221,
'single-quote': 222
}
class Input {
constructor (canvas) {
this.keyList = {}
this.previousKeyList = {}
this.canvas = canvas
this.mouse = {
pos: { x: 0, y: 0 },
frame: { x: 0, y: 0 },
previous: { x: 0, y: 0 }
}
window.addEventListener('keydown', (e) => this.keyDown(e), false)
window.addEventListener('keyup', (e) => this.keyUp(e), false)
canvas.addEventListener('mousemove', (e) => {
let x
let y
if (e.changedTouches) {
const touch = e.changedTouches[0]
if (touch) {
e.pageX = touch.pageX
e.pageY = touch.pageY
}
}
if (e.pageX || e.pageY) {
x = e.pageX
y = e.pageY
} else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop
}
x -= canvas.offsetLeft
y -= canvas.offsetTop
this.mouse.frame.x = x
this.mouse.frame.y = y
}, false)
canvas.addEventListener('mousedown', (e) => {
e.preventDefault()
this.mouse['btn' + e.button] = true
})
canvas.addEventListener('mouseup', (e) => {
e.preventDefault()
this.mouse['btn' + e.button] = false
})
canvas.addEventListener('contextmenu', (e) => {
e.preventDefault()
})
}
get mousePos () {
return this.mouse.pos
}
get mouseMoved () {
return (this.mouse.pos.x !== this.mouse.previous.x ||
this.mouse.pos.y !== this.mouse.previous.y)
}
get mouseOffset () {
return {
x: this.mouse.previous.x - this.mouse.pos.x,
y: this.mouse.previous.y - this.mouse.pos.y
}
}
toggleKey (keyCode, on) {
// Find key in special key list
let key = null
for (const k in specialKeyMap) {
const val = specialKeyMap[k]
if (keyCode === val) {
key = k
break
}
}
// Use fromCharCode
if (!key) {
key = String.fromCharCode(keyCode).toLowerCase()
}
this.keyList[key] = (on === true)
}
keyDown (e) {
let keycode
if (window.event) {
keycode = window.event.keyCode
} else if (e) {
keycode = e.which
}
this.toggleKey(keycode, true)
}
keyUp (e) {
let keycode
if (window.event) {
keycode = window.event.keyCode
} else if (e) {
keycode = e.which
}
this.toggleKey(keycode, false)
}
down (key) {
return this.keyList[key] != null ? this.keyList[key] : false
}
downLast (key) {
return this.previousKeyList[key] != null ? this.previousKeyList[key] : false
}
isDown (key) {
return this.down(key) && this.downLast(key)
}
isUp (key) {
return !this.isDown(key)
}
isPressed (key) {
return this.down(key) === true && this.downLast(key) === false
}
update () {
this.previousKeyList = {}
for (const k in this.keyList) {
if (this.keyList[k] === true) {
this.previousKeyList[k] = true
}
}
// Mouse positions in the previous frame
this.mouse.previous.x = this.mouse.pos.x
this.mouse.previous.y = this.mouse.pos.y
// Mouse positions in the current frame
// Convert to OpenGL coordinate system
this.mouse.pos.x = this.mouse.frame.x / this.canvas.width * 2 - 1
this.mouse.pos.y = this.mouse.frame.y / this.canvas.height * 2 - 1
}
}
export default Input