Doodle3D-Core/src/d3/transformers/BaseTransformer.js
2018-01-10 14:15:09 +01:00

142 lines
4.4 KiB
JavaScript

import * as THREE from 'three';
import * as actions from '../../actions/index.js';
import { EventObject3D } from '../EventScene.js';
import transposeEvents from '../../utils/transposeEvents.js';
const RAY_CASTER = new THREE.Raycaster();
const MOUSE = new THREE.Vector2();
export default class BaseTransformer extends EventObject3D {
constructor(dispatch, scene, camera, DOMNode, renderRequest) {
super();
// enable hit detection by default because it is needed for toggling selection
this.enableHitDetection = true;
this.dispatch = dispatch;
this.scene = scene;
this.camera = camera;
this.DOMNode = DOMNode;
this.renderRequest = renderRequest;
}
dragStart({ position, preDrags, intersections }) {
this.dispatch(actions.d3DragStart(position, preDrags, intersections));
}
drag({ position, previousPosition }) {
this.dispatch(actions.d3Drag(position, previousPosition));
}
dragEnd({ position }) {
this.dispatch(actions.d3DragEnd(position));
}
secondDragStart({ position, preDrags, intersections }) {
this.dispatch(actions.d3SecondDragStart(position, preDrags, intersections));
}
secondDrag({ position, previousPosition }) {
this.dispatch(actions.d3SecondDrag(position, previousPosition));
}
secondDragEnd({ position }) {
this.dispatch(actions.d3DragEnd(position));
}
tap({ position, intersections }) {
// perhaps better to do this in a more general location
// but currently this is the only place we have access to intersections
this.select(intersections);
this.dispatch(actions.d3Tap(position, intersections));
}
wheel({ position, wheelDelta }) {
this.dispatch(actions.d3MouseWheel(position, wheelDelta));
}
multitouchStart({ positions, preDrags }) {
this.dispatch(actions.d3MultitouchStart(positions, preDrags));
}
multitouch({ positions, previousPositions }) {
this.dispatch(actions.d3Multitouch(positions, previousPositions));
}
multitouchEnd({ positions }) {
this.dispatch(actions.d3MultitouchEnd(positions));
}
select(intersections) {
const mesh = intersections.find(({ object }) => object.isShapeMesh);
const bed = intersections.find(({ object }) => object.isBedPlane);
if (mesh) {
this.dispatch(actions.toggleSelect(mesh.object.name));
} else {
if (bed) {
this.dispatch(actions.bedSelect());
}
this.dispatch(actions.deselectAll());
}
}
onEvent(event) {
switch (event.type) {
case 'dragstart':
this._previousPosition = event.position;
break;
case 'drag':
event.previousPosition = this._previousPosition;
this._previousPosition = event.position;
break;
case 'seconddragstart':
this._previousSecondPosition = event.position;
break;
case 'seconddrag':
event.previousPosition = this._previousSecondPosition;
this._previousSecondPosition = event.position;
break;
case 'multitouchstart':
this._previousMultitouchPositions = event.positions;
break;
case 'multitouch':
event.previousPositions = this._previousMultitouchPositions;
this._previousMultitouchPositions = event.positions;
break;
default:
break;
}
event.intersections = [];
if (this.enableHitDetection) {
if (event.type === 'tap' || event.type === 'dragstart' || event.type === 'seconddragstart') {
event.intersections = this.findHit(event.position);
}
}
transposeEvents.call(this, event);
super.onEvent(event);
}
getRayCaster({ x, y }) {
MOUSE.setX((x / this.DOMNode.offsetWidth) * 2 - 1);
MOUSE.setY(-(y / this.DOMNode.offsetHeight) * 2 + 1);
RAY_CASTER.setFromCamera(MOUSE, this.camera);
return RAY_CASTER;
}
findHit(mouse) {
if (!this.enableHitDetection || this.scene.children.length === 0) return [];
const rayCaster = this.getRayCaster(mouse);
const intersections = rayCaster.intersectObjects(this.scene.children, true);
return intersections;
}
updateSpriteScale() {
for (const sprite of this.children) {
if (!(sprite.isUIHandle) || !sprite.material.map) continue;
const scale = sprite.position.distanceTo(this.camera.getWorldPosition()) / 2000.0;
const { width, height } = sprite.material.map.image;
sprite.scale.set(width * scale, height * scale, 0); // TODO only if changed
}
}
destroy() {}
}