move 3d clicking and touching for placing from renderer into controls
This commit is contained in:
parent
e74b3f923b
commit
1768dd88bf
|
@ -27,6 +27,13 @@ import {
|
||||||
THREE_CANVAS_HEIGHT,
|
THREE_CANVAS_HEIGHT,
|
||||||
VIEW_UPDATE_DELAY,
|
VIEW_UPDATE_DELAY,
|
||||||
} from '../core/constants';
|
} from '../core/constants';
|
||||||
|
import {
|
||||||
|
getDiff,
|
||||||
|
getTapOrClickCenter,
|
||||||
|
} from '../core/utils';
|
||||||
|
import {
|
||||||
|
selectHoverColor,
|
||||||
|
} from '../store/actions';
|
||||||
|
|
||||||
const STORE_UPDATE_DELAY = VIEW_UPDATE_DELAY / 2;
|
const STORE_UPDATE_DELAY = VIEW_UPDATE_DELAY / 2;
|
||||||
// Mouse buttons
|
// Mouse buttons
|
||||||
|
@ -126,6 +133,14 @@ class VoxelPainterControls {
|
||||||
vec = new Vector3();
|
vec = new Vector3();
|
||||||
// forcing next update
|
// forcing next update
|
||||||
forceNextUpdate = false;
|
forceNextUpdate = false;
|
||||||
|
// start of touch or click
|
||||||
|
clickTapStartTime = 0;
|
||||||
|
// on touch: true if current tab was ever more than one figher at any time
|
||||||
|
wasEverMultiTap = false;
|
||||||
|
// screen coords of where a tap/click started
|
||||||
|
clickTapStartCoords = [0, 0];
|
||||||
|
// on touch: timeout to detect long-press
|
||||||
|
tapTimeout = null;
|
||||||
|
|
||||||
constructor(renderer, camera, target, domElement, store) {
|
constructor(renderer, camera, target, domElement, store) {
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
|
@ -276,9 +291,6 @@ class VoxelPainterControls {
|
||||||
panStart.copy(panEnd);
|
panStart.copy(panEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
|
||||||
handleMouseUp() {}
|
|
||||||
|
|
||||||
handleMouseWheel(event) {
|
handleMouseWheel(event) {
|
||||||
const scaleDelta = 0.95 ** zoomSpeed;
|
const scaleDelta = 0.95 ** zoomSpeed;
|
||||||
if (event.deltaY < 0) {
|
if (event.deltaY < 0) {
|
||||||
|
@ -394,8 +406,102 @@ class VoxelPainterControls {
|
||||||
if (enableRotate) this.handleTouchMoveRotate(event);
|
if (enableRotate) this.handleTouchMoveRotate(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line class-methods-use-this
|
placeVoxelOnScreen(screenCoords, allowedDistance) {
|
||||||
handleTouchEnd() {}
|
const intersect = this.renderer.castRay(screenCoords);
|
||||||
|
if (!intersect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = intersect.point.clone()
|
||||||
|
.add(intersect.face.normal.multiplyScalar(0.5))
|
||||||
|
.floor()
|
||||||
|
.addScalar(0.5)
|
||||||
|
.floor();
|
||||||
|
if (target.clone().sub(this.camera.position).length() < allowedDistance) {
|
||||||
|
const [x, y, z] = target.toArray();
|
||||||
|
this.renderer.placeVoxel(x, y, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteVoxelOnScreen(screenCoords, allowedDistance) {
|
||||||
|
const intersect = this.renderer.castRay(screenCoords);
|
||||||
|
if (!intersect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const target = intersect.point.clone()
|
||||||
|
.add(intersect.face.normal.multiplyScalar(-0.5))
|
||||||
|
.floor()
|
||||||
|
.addScalar(0.5)
|
||||||
|
.floor();
|
||||||
|
if (target.y < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (target.clone().sub(this.camera.position).length() < allowedDistance) {
|
||||||
|
const [x, y, z] = target.toArray();
|
||||||
|
this.renderer.placeVoxel(x, y, z, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectColorOnScreen(screenCoords) {
|
||||||
|
// selectHoverColor doesn't actually do anything with the coords
|
||||||
|
this.store.dispatch(selectHoverColor(screenCoords));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseUp(event) {
|
||||||
|
if (!this.clickTapStartTime
|
||||||
|
|| Date.now() - this.clickTapStartTime > 300
|
||||||
|
|| this.store.getState().fetching.fetchingPixel
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const screenCoords = getTapOrClickCenter(event);
|
||||||
|
if (getDiff(screenCoords, this.clickTapStartCoords) > 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (event.button) {
|
||||||
|
case 0:
|
||||||
|
// left
|
||||||
|
this.placeVoxelOnScreen(screenCoords, 120);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
// middle
|
||||||
|
this.selectColorOnScreen(screenCoords);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
// right
|
||||||
|
this.deleteVoxelOnScreen(screenCoords, 120);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTouchEnd(event) {
|
||||||
|
if (event.touches.length
|
||||||
|
|| !this.clickTapStartTime
|
||||||
|
|| Date.now() - this.clickTapStartTime > 300
|
||||||
|
|| this.store.getState().fetching.fetchingPixel
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const screenCoords = getTapOrClickCenter(event);
|
||||||
|
if (getDiff(screenCoords, this.clickTapStartCoords) > 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.placeVoxelOnScreen(screenCoords, 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
onLongTap(event) {
|
||||||
|
if (!this.clickTapStartTime
|
||||||
|
|| this.store.getState().fetching.fetchingPixel
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const screenCoords = getTapOrClickCenter(event);
|
||||||
|
if (getDiff(screenCoords, this.clickTapStartCoords) > 6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.deleteVoxelOnScreen(screenCoords, 90);
|
||||||
|
}
|
||||||
|
|
||||||
onMouseMove(event) {
|
onMouseMove(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
@ -417,6 +523,7 @@ class VoxelPainterControls {
|
||||||
|
|
||||||
onMouseUp(event) {
|
onMouseUp(event) {
|
||||||
this.handleMouseUp(event);
|
this.handleMouseUp(event);
|
||||||
|
this.clickTapStartTime = 0;
|
||||||
document.removeEventListener('mousemove', this.onMouseMove, false);
|
document.removeEventListener('mousemove', this.onMouseMove, false);
|
||||||
document.removeEventListener('mouseup', this.onMouseUp, false);
|
document.removeEventListener('mouseup', this.onMouseUp, false);
|
||||||
this.state = STATE.NONE;
|
this.state = STATE.NONE;
|
||||||
|
@ -439,6 +546,17 @@ class VoxelPainterControls {
|
||||||
onTouchStart(event) {
|
onTouchStart(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (event.touches.length === 1) {
|
||||||
|
this.clickTapStartTime = Date.now();
|
||||||
|
this.clickTapStartCoords = getTapOrClickCenter(event);
|
||||||
|
this.tapTimeout = setTimeout(() => {
|
||||||
|
this.onLongTap(event);
|
||||||
|
}, 600);
|
||||||
|
} else {
|
||||||
|
this.clickTapStartTime = 0;
|
||||||
|
clearTimeout(this.tapTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
switch (event.touches.length) {
|
switch (event.touches.length) {
|
||||||
case 1:
|
case 1:
|
||||||
switch (TOUCHES.ONE) {
|
switch (TOUCHES.ONE) {
|
||||||
|
@ -489,6 +607,12 @@ class VoxelPainterControls {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
|
const screenCoords = getTapOrClickCenter(event);
|
||||||
|
if (getDiff(screenCoords, this.clickTapStartCoords) > 6) {
|
||||||
|
clearTimeout(this.tapTimeout);
|
||||||
|
this.clickTapStartTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (this.state) {
|
switch (this.state) {
|
||||||
case STATE.TOUCH_ROTATE:
|
case STATE.TOUCH_ROTATE:
|
||||||
if (!enableRotate) {
|
if (!enableRotate) {
|
||||||
|
@ -520,7 +644,12 @@ class VoxelPainterControls {
|
||||||
}
|
}
|
||||||
|
|
||||||
onTouchEnd(event) {
|
onTouchEnd(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!event.touches.length) {
|
||||||
|
clearTimeout(this.tapTimeout);
|
||||||
this.handleTouchEnd(event);
|
this.handleTouchEnd(event);
|
||||||
|
this.clickTapStartTime = 0;
|
||||||
|
}
|
||||||
this.state = STATE.NONE;
|
this.state = STATE.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,6 +661,8 @@ class VoxelPainterControls {
|
||||||
onMouseDown(event) {
|
onMouseDown(event) {
|
||||||
// Prevent the browser from scrolling.
|
// Prevent the browser from scrolling.
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
this.clickTapStartTime = Date.now();
|
||||||
|
this.clickTapStartCoords = getTapOrClickCenter(event);
|
||||||
|
|
||||||
// Manually set the focus since calling preventDefault above
|
// Manually set the focus since calling preventDefault above
|
||||||
// prevents the browser from setting it automatically.
|
// prevents the browser from setting it automatically.
|
||||||
|
|
|
@ -636,6 +636,20 @@ export function getDateKeyOfTs(ts) {
|
||||||
return `${year}${month}${day}`;
|
return `${year}${month}${day}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get largest distance between axes of array
|
||||||
|
*/
|
||||||
|
export function getDiff(arr1, arr2) {
|
||||||
|
let largest = 0;
|
||||||
|
for (let i = 0; i < arr1.length; i += 1) {
|
||||||
|
const length = Math.abs(arr1[i] - arr2[i]);
|
||||||
|
if (length > largest) {
|
||||||
|
largest = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return largest;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get screen coords of touch / mouse event
|
* get screen coords of touch / mouse event
|
||||||
* @param event MouseEvent or TouchEvent
|
* @param event MouseEvent or TouchEvent
|
||||||
|
|
|
@ -409,6 +409,7 @@ class Renderer2D extends Renderer {
|
||||||
context.fillRect(x, y, TILE_SIZE, TILE_SIZE);
|
context.fillRect(x, y, TILE_SIZE, TILE_SIZE);
|
||||||
} else {
|
} else {
|
||||||
chunk = this.chunkLoader.getChunk(tiledZoom, cx, cy);
|
chunk = this.chunkLoader.getChunk(tiledZoom, cx, cy);
|
||||||
|
// TODO is chunk nnow an object or image? it doesnt make any sense
|
||||||
if (chunk) {
|
if (chunk) {
|
||||||
context.drawImage(chunk, x, y);
|
context.drawImage(chunk, x, y);
|
||||||
if (touch) {
|
if (touch) {
|
||||||
|
|
|
@ -28,7 +28,6 @@ import ChunkLoader from './ChunkLoader3D';
|
||||||
import {
|
import {
|
||||||
getChunkOfPixel,
|
getChunkOfPixel,
|
||||||
getOffsetOfPixel,
|
getOffsetOfPixel,
|
||||||
getTapOrClickCenter,
|
|
||||||
} from '../core/utils';
|
} from '../core/utils';
|
||||||
import {
|
import {
|
||||||
THREE_TILE_SIZE,
|
THREE_TILE_SIZE,
|
||||||
|
@ -36,7 +35,6 @@ import {
|
||||||
import {
|
import {
|
||||||
setHover,
|
setHover,
|
||||||
unsetHover,
|
unsetHover,
|
||||||
selectHoverColor,
|
|
||||||
} from '../store/actions';
|
} from '../store/actions';
|
||||||
import pixelTransferController from './PixelTransferController';
|
import pixelTransferController from './PixelTransferController';
|
||||||
|
|
||||||
|
@ -64,14 +62,7 @@ class Renderer3D extends Renderer {
|
||||||
// temp variables for mouse events
|
// temp variables for mouse events
|
||||||
mouse = new Vector2();
|
mouse = new Vector2();
|
||||||
raycaster = new Raycaster();
|
raycaster = new Raycaster();
|
||||||
pressTime;
|
|
||||||
pressCdTime;
|
|
||||||
multitap = 0;
|
|
||||||
lastIntersect = 0;
|
lastIntersect = 0;
|
||||||
// on touch: true if current tab was ever more than one figher at any time
|
|
||||||
wasEverMultiTap = false;
|
|
||||||
// screen coords of where a tap/click started
|
|
||||||
clickTapStartCoords = [0, 0];
|
|
||||||
|
|
||||||
constructor(store) {
|
constructor(store) {
|
||||||
super(store);
|
super(store);
|
||||||
|
@ -194,26 +185,9 @@ class Renderer3D extends Renderer {
|
||||||
|
|
||||||
this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this);
|
this.onDocumentMouseMove = this.onDocumentMouseMove.bind(this);
|
||||||
this.onDocumentTouchMove = this.onDocumentTouchMove.bind(this);
|
this.onDocumentTouchMove = this.onDocumentTouchMove.bind(this);
|
||||||
// eslint-disable-next-line max-len
|
|
||||||
this.onDocumentMouseDownOrTouchStart = this.onDocumentMouseDownOrTouchStart.bind(this);
|
|
||||||
this.onDocumentMouseUp = this.onDocumentMouseUp.bind(this);
|
|
||||||
this.onWindowResize = this.onWindowResize.bind(this);
|
this.onWindowResize = this.onWindowResize.bind(this);
|
||||||
this.onDocumentTouchEnd = this.onDocumentTouchEnd.bind(this);
|
|
||||||
this.multiTapEnd = this.multiTapEnd.bind(this);
|
|
||||||
domElement.addEventListener('mousemove', this.onDocumentMouseMove, false);
|
domElement.addEventListener('mousemove', this.onDocumentMouseMove, false);
|
||||||
domElement.addEventListener('touchmove', this.onDocumentTouchMove, false);
|
domElement.addEventListener('touchmove', this.onDocumentTouchMove, false);
|
||||||
domElement.addEventListener(
|
|
||||||
'mousedown',
|
|
||||||
this.onDocumentMouseDownOrTouchStart,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
domElement.addEventListener(
|
|
||||||
'touchstart',
|
|
||||||
this.onDocumentMouseDownOrTouchStart,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
domElement.addEventListener('touchend', this.onDocumentTouchEnd, false);
|
|
||||||
domElement.addEventListener('mouseup', this.onDocumentMouseUp, false);
|
|
||||||
window.addEventListener('resize', this.onWindowResize, false);
|
window.addEventListener('resize', this.onWindowResize, false);
|
||||||
|
|
||||||
this.updateCanvasData(state);
|
this.updateCanvasData(state);
|
||||||
|
@ -511,25 +485,34 @@ class Renderer3D extends Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocumentMouseMove(event) {
|
onDocumentMouseMove(event) {
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
this.updateRollOverMesh(
|
this.updateRollOverMesh(
|
||||||
(event.clientX / window.innerWidth) * 2 - 1,
|
(event.clientX / window.innerWidth) * 2 - 1,
|
||||||
-(event.clientY / window.innerHeight) * 2 + 1,
|
-(event.clientY / window.innerHeight) * 2 + 1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocumentMouseDownOrTouchStart(event) {
|
onDocumentTouchMove(event) {
|
||||||
this.pressTime = Date.now();
|
if (this.rollOverMesh.position.y !== -10) {
|
||||||
this.clickTapStartCoords = getTapOrClickCenter(event);
|
console.log('unset hover');
|
||||||
this.wasEverMultiTap = (event.touches?.length > 1);
|
this.store.dispatch(unsetHover());
|
||||||
|
this.rollOverMesh.position.y = -10;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDocumentTouchMove(event) {
|
castRay([clientX, clientY]) {
|
||||||
if (event.touches?.length > 1) {
|
const {
|
||||||
this.wasEverMultiTap = true;
|
mouse, camera, raycaster, objects,
|
||||||
|
} = this;
|
||||||
|
mouse.set(
|
||||||
|
(clientX / window.innerWidth) * 2 - 1,
|
||||||
|
-(clientY / window.innerHeight) * 2 + 1,
|
||||||
|
);
|
||||||
|
raycaster.setFromCamera(mouse, camera);
|
||||||
|
const intersects = raycaster.intersectObjects(objects);
|
||||||
|
if (intersects.length > 0) {
|
||||||
|
return intersects[0];
|
||||||
}
|
}
|
||||||
this.updateRollOverMesh(0, 0);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getPointedColor() {
|
getPointedColor() {
|
||||||
|
@ -540,7 +523,6 @@ class Renderer3D extends Renderer {
|
||||||
camera,
|
camera,
|
||||||
} = this;
|
} = this;
|
||||||
raycaster.setFromCamera(mouse, camera);
|
raycaster.setFromCamera(mouse, camera);
|
||||||
|
|
||||||
const intersects = raycaster.intersectObjects(objects);
|
const intersects = raycaster.intersectObjects(objects);
|
||||||
if (intersects.length <= 0) {
|
if (intersects.length <= 0) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -586,188 +568,6 @@ class Renderer3D extends Renderer {
|
||||||
curColor,
|
curColor,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
multiTapEnd(event) {
|
|
||||||
const {
|
|
||||||
store,
|
|
||||||
multitap,
|
|
||||||
} = this;
|
|
||||||
this.multitap = 0;
|
|
||||||
const state = store.getState();
|
|
||||||
|
|
||||||
if (!state.canvas.hover || this.wasEverMultiTap) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
|
||||||
const { clickTapStartCoords } = this;
|
|
||||||
const coordsDiff = [
|
|
||||||
clickTapStartCoords[0] - clientX,
|
|
||||||
clickTapStartCoords[1] - clientY,
|
|
||||||
].map(Math.abs);
|
|
||||||
if (coordsDiff[0] > 5 || coordsDiff[1] > 5) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (multitap) {
|
|
||||||
case 1: {
|
|
||||||
// single tap
|
|
||||||
// Place Voxel
|
|
||||||
if (this.rollOverMesh.position.y < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.placeVoxel(...state.canvas.hover);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
// double tap
|
|
||||||
// Remove Voxel
|
|
||||||
const {
|
|
||||||
mouse,
|
|
||||||
raycaster,
|
|
||||||
camera,
|
|
||||||
objects,
|
|
||||||
} = this;
|
|
||||||
mouse.set(0, 0);
|
|
||||||
raycaster.setFromCamera(mouse, camera);
|
|
||||||
const intersects = raycaster.intersectObjects(objects);
|
|
||||||
if (intersects.length > 0) {
|
|
||||||
const intersect = intersects[0];
|
|
||||||
const target = intersect.point.clone()
|
|
||||||
.add(intersect.face.normal.multiplyScalar(-0.5))
|
|
||||||
.floor()
|
|
||||||
.addScalar(0.5)
|
|
||||||
.floor();
|
|
||||||
if (target.y < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (target.clone().sub(camera.position).length() <= 50) {
|
|
||||||
const [x, y, z] = target.toArray();
|
|
||||||
this.placeVoxel(x, y, z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDocumentTouchEnd(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (event.touches.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const curTime = Date.now();
|
|
||||||
if (curTime - this.pressTime > 600) {
|
|
||||||
this.multitap = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if we want to do something with triple tap,
|
|
||||||
// we should reset on every tap
|
|
||||||
// but we don't need that right now...
|
|
||||||
if (this.multitap === 0) {
|
|
||||||
setTimeout(() => this.multiTapEnd(event), 500);
|
|
||||||
}
|
|
||||||
this.multitap += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDocumentMouseUp(event) {
|
|
||||||
const curTime = Date.now();
|
|
||||||
if (curTime - this.pressCdTime < 200) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (curTime - this.pressTime > 500) {
|
|
||||||
this.pressCdTime = curTime;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = this.store.getState();
|
|
||||||
const {
|
|
||||||
isOnMobile,
|
|
||||||
} = state.user;
|
|
||||||
const {
|
|
||||||
fetchingPixel,
|
|
||||||
} = state.fetching;
|
|
||||||
if (fetchingPixel || isOnMobile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!state.canvas.hover) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [clientX, clientY] = getTapOrClickCenter(event);
|
|
||||||
const { clickTapStartCoords } = this;
|
|
||||||
const coordsDiff = [
|
|
||||||
clickTapStartCoords[0] - clientX,
|
|
||||||
clickTapStartCoords[1] - clientY,
|
|
||||||
].map(Math.abs);
|
|
||||||
if (coordsDiff[0] > 5 || coordsDiff[1] > 5) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
const { button } = event;
|
|
||||||
const {
|
|
||||||
innerWidth,
|
|
||||||
innerHeight,
|
|
||||||
} = window;
|
|
||||||
const {
|
|
||||||
store,
|
|
||||||
mouse,
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
mouse.set(
|
|
||||||
(clientX / innerWidth) * 2 - 1,
|
|
||||||
-(clientY / innerHeight) * 2 + 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (button === 1) {
|
|
||||||
// middle mouse button
|
|
||||||
store.dispatch(selectHoverColor());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
camera,
|
|
||||||
objects,
|
|
||||||
raycaster,
|
|
||||||
} = this;
|
|
||||||
|
|
||||||
raycaster.setFromCamera(mouse, camera);
|
|
||||||
|
|
||||||
const intersects = raycaster.intersectObjects(objects);
|
|
||||||
if (intersects.length > 0) {
|
|
||||||
const intersect = intersects[0];
|
|
||||||
|
|
||||||
if (button === 0) {
|
|
||||||
// left mouse button
|
|
||||||
const target = intersect.point.clone()
|
|
||||||
.add(intersect.face.normal.multiplyScalar(0.5))
|
|
||||||
.floor()
|
|
||||||
.addScalar(0.5)
|
|
||||||
.floor();
|
|
||||||
if (target.clone().sub(camera.position).length() < 120) {
|
|
||||||
const [x, y, z] = target.toArray();
|
|
||||||
this.placeVoxel(x, y, z);
|
|
||||||
}
|
|
||||||
} else if (button === 2) {
|
|
||||||
// right mouse button
|
|
||||||
const target = intersect.point.clone()
|
|
||||||
.add(intersect.face.normal.multiplyScalar(-0.5))
|
|
||||||
.floor()
|
|
||||||
.addScalar(0.5)
|
|
||||||
.floor();
|
|
||||||
if (target.y < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (target.clone().sub(camera.position).length() < 120) {
|
|
||||||
const [x, y, z] = target.toArray();
|
|
||||||
this.placeVoxel(x, y, z, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Renderer3D;
|
export default Renderer3D;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user