freeblox/packages/editor/src/editor/core/mouse.ts

114 lines
3.7 KiB
TypeScript

import { EngineComponent, EventEmitter, Renderer } from '@freeblox/engine';
import { EditorEvents, SelectEvent } from '../types/events';
import { Object3D, Raycaster, Vector2 } from 'three';
type MouseMap = [boolean, boolean, boolean];
type EventMap = [string, Function];
export class EditorMouse extends EngineComponent {
private helpers!: Object3D;
private world!: Object3D;
private mouseButtons: MouseMap = [false, false, false];
private mouseButtonsLast: MouseMap = [false, false, false];
private mousePosition = new Vector2(0, 0);
private mousePositionGL = new Vector2(0, 0);
private mousePositionLast = new Vector2(0, 0);
private mousePositionGLLast = new Vector2(0, 0);
private boundEvents: EventMap[] = [];
private ray = new Raycaster();
constructor(
protected renderer: Renderer,
protected events: EventEmitter<EditorEvents>
) {
super(renderer, events);
}
get canvas() {
return this.renderer.renderer.domElement;
}
initialize(): void {
this.helpers = this.renderer.scene.getObjectByName('_helpers')!;
this.world = this.renderer.scene.getObjectByName('_world')!;
const mouseDown = (ev: MouseEvent) => {
const [object] = this.ray.intersectObjects(this.world.children, true);
this.mouseButtons[ev.button] = true;
this.events.emit('mouseDown', {
position: this.mousePosition,
positionGL: this.mousePositionGL,
button: ev.button,
target: object,
shift: ev.shiftKey,
control: ev.ctrlKey,
alt: ev.altKey,
});
};
const mouseUp = (ev: MouseEvent) => {
const [object] = this.ray.intersectObjects(this.world.children, true);
this.mouseButtons[ev.button] = false;
this.events.emit('mouseUp', {
position: this.mousePosition,
positionGL: this.mousePositionGL,
button: ev.button,
target: object,
});
};
const mouseMove = (ev: MouseEvent) => {
this.mousePositionLast = this.mousePosition.clone();
this.mousePositionGLLast = this.mousePositionGL.clone();
this.mousePosition.set(ev.clientX, ev.clientY);
this.mousePositionGL.set(
(this.mousePosition.x / this.renderer.resolution.x) * 2 - 1,
-(this.mousePosition.y / this.renderer.resolution.y) * 2 + 1
);
this.events.emit('mouseMove', {
position: this.mousePosition,
positionGL: this.mousePositionGL,
offset: this.mousePositionLast.clone().sub(this.mousePosition),
offsetGL: this.mousePositionGLLast.clone().sub(this.mousePositionGL),
});
};
const contextMenu = (ev: MouseEvent) => ev.preventDefault();
this.canvas.addEventListener('mousedown', mouseDown);
this.canvas.addEventListener('mousemove', mouseMove);
this.canvas.addEventListener('mouseup', mouseUp);
this.canvas.addEventListener('contextmenu', contextMenu);
this.boundEvents.push(
['mousedown', mouseDown],
['mousemove', mouseMove],
['mouseup', mouseUp],
['contextmenu', contextMenu]
);
}
update(delta: number): void {
this.ray.setFromCamera(this.mousePositionGL, this.renderer.camera);
this.mouseButtonsLast = [...this.mouseButtons];
}
cleanUp(): void {
for (const [event, handler] of this.boundEvents) {
this.canvas.removeEventListener(event, handler as EventListener);
}
}
// private realMousePos(vec: Vector2, x: number, y: number) {
// const rect = this.renderer.renderer.domElement.getBoundingClientRect();
// const scaleX = this.renderer.renderer.domElement.width / rect.width;
// const scaleY = this.renderer.renderer.domElement.height / rect.height;
// vec.set((x - rect.left) * scaleX, (y - rect.top) * scaleY);
// }
}