|
import { getConfig } from './config.js'; |
|
import { EventEmitter, EventTypes } from './event.js'; |
|
import { InputHandler, LayerHandler } from './handler.js'; |
|
|
|
export function createInputHandler(canvas, scene) { |
|
const eventEmitter = new EventEmitter(); |
|
const inputHandler = new InputHandler(canvas); |
|
let cameraControlsEnabled = true; |
|
|
|
|
|
function attachDomEvents() { |
|
window.addEventListener('keydown', (e) => { |
|
eventEmitter.emit(EventTypes.KEY_DOWN, e); |
|
}); |
|
window.addEventListener('keyup', (e) => { |
|
eventEmitter.emit(EventTypes.KEY_UP, e); |
|
}); |
|
window.addEventListener('keypress', (e) => { |
|
eventEmitter.emit(EventTypes.KEY_PRESS, e); |
|
|
|
if (e.key.length === 1) { |
|
eventEmitter.emit(EventTypes.TEXT_INPUT, e.key); |
|
} |
|
}); |
|
canvas.addEventListener('mousemove', (e) => { |
|
eventEmitter.emit(EventTypes.MOUSE_MOVE, e); |
|
}); |
|
canvas.addEventListener('mousedown', (e) => { |
|
eventEmitter.emit(EventTypes.MOUSE_DOWN, e); |
|
}); |
|
canvas.addEventListener('mouseup', (e) => { |
|
eventEmitter.emit(EventTypes.MOUSE_UP, e); |
|
}); |
|
canvas.addEventListener('wheel', (e) => { |
|
eventEmitter.emit(EventTypes.MOUSE_WHEEL, e); |
|
}, { passive: false }); |
|
canvas.addEventListener('click', (e) => { |
|
eventEmitter.emit(EventTypes.CLICK, e); |
|
}); |
|
} |
|
|
|
function setupCameraControls() { |
|
const config = getConfig(); |
|
const moveSpeed = config?.camera?.moveSpeed || 10; |
|
const zoomSpeed = config?.camera?.zoomSpeed || 0.1; |
|
const inverted = config?.controls?.inverted || false; |
|
const moveDir = inverted ? 1 : -1; |
|
|
|
eventEmitter.on(EventTypes.KEY_DOWN, (e) => { |
|
if (!cameraControlsEnabled) return; |
|
switch (e.key.toLowerCase()) { |
|
case 'w': scene.camera.moveBy(0, moveSpeed * moveDir); break; |
|
case 's': scene.camera.moveBy(0, -moveSpeed * moveDir); break; |
|
case 'a': scene.camera.moveBy(-moveSpeed * moveDir, 0); break; |
|
case 'd': scene.camera.moveBy(moveSpeed * moveDir, 0); break; |
|
case '+': |
|
case '=': scene.camera.zoomBy(1 + zoomSpeed); break; |
|
case '-': |
|
case '_': scene.camera.zoomBy(1 - zoomSpeed); break; |
|
} |
|
}); |
|
|
|
eventEmitter.on(EventTypes.MOUSE_WHEEL, (e) => { |
|
if (!cameraControlsEnabled) return; |
|
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1; |
|
scene.camera.zoomBy(zoomFactor); |
|
e.preventDefault(); |
|
}); |
|
} |
|
|
|
function setupLayerHandlers() { |
|
scene.getLayers().forEach(layer => { |
|
const handlers = [ |
|
new LayerHandler(EventTypes.KEY_DOWN, (e, layer) => layer.handleKeyDown?.(e)), |
|
new LayerHandler(EventTypes.MOUSE_MOVE, (e, layer) => { |
|
const pos = inputHandler.getMousePosition(e); |
|
layer.handleMouseMove?.(pos.x, pos.y); |
|
}), |
|
new LayerHandler(EventTypes.CLICK, (e, layer) => { |
|
const pos = inputHandler.getMousePosition(e); |
|
layer.handleClick?.(pos.x, pos.y, scene.camera); |
|
}), |
|
new LayerHandler(EventTypes.MOUSE_WHEEL, (e, layer) => layer.handleWheel?.(e)) |
|
]; |
|
|
|
handlers.forEach(handler => { |
|
handler.bind(layer); |
|
inputHandler.addHandler(handler.eventType, handler); |
|
}); |
|
}); |
|
} |
|
|
|
attachDomEvents(); |
|
setupCameraControls(); |
|
setupLayerHandlers(); |
|
|
|
return { |
|
listenForKey: (key, callback) => eventEmitter.on(EventTypes.KEY_DOWN, (e) => { |
|
if (e.key === key) callback(e); |
|
}), |
|
removeKeyListener: (key, callback) => eventEmitter.off(EventTypes.KEY_DOWN, (e) => { |
|
if (e.key === key) callback(e); |
|
}), |
|
addTextInputListener: (callback) => eventEmitter.on(EventTypes.TEXT_INPUT, callback), |
|
removeTextInputListener: (callback) => eventEmitter.off(EventTypes.TEXT_INPUT, callback), |
|
removeAllListeners: () => eventEmitter.clear(), |
|
enableCameraControls: () => { cameraControlsEnabled = true; }, |
|
disableCameraControls: () => { cameraControlsEnabled = false; }, |
|
on: (event, callback) => eventEmitter.on(event, callback), |
|
off: (event, callback) => eventEmitter.off(event, callback), |
|
cleanup: () => { |
|
eventEmitter.clear(); |
|
inputHandler.disable(); |
|
} |
|
}; |
|
} |
|
|