mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-25 15:08:11 +00:00
ControlsManager
This commit is contained in:
parent
1ae0b7c7c2
commit
f902e79cfd
@ -36,7 +36,7 @@ class BaseControls extends THREE.EventDispatcher {
|
||||
* @param {THREE.Object3D} target 目标
|
||||
*/
|
||||
focus(target) {
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,7 +1,52 @@
|
||||
import BaseControls from './BaseControls';
|
||||
|
||||
class ControlsManager extends BaseControls {
|
||||
import EditorControls from './EditorControls';
|
||||
import FreeControls from './FreeControls';
|
||||
|
||||
const Controls = {
|
||||
EditorControls,
|
||||
FreeControls
|
||||
};
|
||||
|
||||
/**
|
||||
* 控制器管理器
|
||||
*/
|
||||
class ControlsManager extends BaseControls {
|
||||
constructor(camera, domElement) {
|
||||
super(camera, domElement);
|
||||
|
||||
this.current = new EditorControls();
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变控制器模式
|
||||
* @param {String} modeName 模式
|
||||
*/
|
||||
changeMode(modeName) {
|
||||
if (!Controls[modeName]) {
|
||||
console.warn(`ControlsManager: ${modeName} is not defined.`);
|
||||
return;
|
||||
}
|
||||
this.current.disable();
|
||||
this.current = Controls[modeName];
|
||||
this.current.enable();
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.current && this.current.enabled();
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.current && this.current.disable();
|
||||
}
|
||||
|
||||
focus(target) {
|
||||
this.current && this.current.focus(target);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
this.current && this.current.disable();
|
||||
}
|
||||
}
|
||||
|
||||
export default ControlsManager;
|
||||
@ -1,3 +1,5 @@
|
||||
import BaseControls from './BaseControls';
|
||||
|
||||
/**
|
||||
* @author qiao / https://github.com/qiao
|
||||
* @author mrdoob / http://mrdoob.com
|
||||
@ -312,7 +314,7 @@ function EditorControls(object, domElement) {
|
||||
|
||||
}
|
||||
|
||||
EditorControls.prototype = Object.create(THREE.EventDispatcher.prototype);
|
||||
EditorControls.prototype.constructor = EditorControls;
|
||||
EditorControls.prototype = Object.create(BaseControls.prototype);
|
||||
EditorControls.prototype.constructor = BaseControls;
|
||||
|
||||
export default EditorControls;
|
||||
@ -1,310 +1,10 @@
|
||||
function FreeControls(object, domElement) {
|
||||
import BaseControls from './BaseControls';
|
||||
|
||||
domElement = domElement !== undefined ? domElement : document;
|
||||
|
||||
// API
|
||||
|
||||
this.enabled = true;
|
||||
this.center = new THREE.Vector3();
|
||||
this.panSpeed = 0.002;
|
||||
this.zoomSpeed = 0.1;
|
||||
this.rotationSpeed = 0.005;
|
||||
|
||||
// internals
|
||||
|
||||
var scope = this;
|
||||
var vector = new THREE.Vector3();
|
||||
var delta = new THREE.Vector3();
|
||||
var box = new THREE.Box3();
|
||||
|
||||
var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2 };
|
||||
var state = STATE.NONE;
|
||||
|
||||
var center = this.center;
|
||||
var normalMatrix = new THREE.Matrix3();
|
||||
var pointer = new THREE.Vector2();
|
||||
var pointerOld = new THREE.Vector2();
|
||||
var spherical = new THREE.Spherical();
|
||||
var sphere = new THREE.Sphere();
|
||||
|
||||
// events
|
||||
|
||||
var changeEvent = { type: 'change' };
|
||||
|
||||
this.focus = function (target) {
|
||||
|
||||
var distance;
|
||||
|
||||
box.setFromObject(target);
|
||||
|
||||
if (box.isEmpty() === false) {
|
||||
|
||||
box.getCenter(center);
|
||||
distance = box.getBoundingSphere(sphere).radius;
|
||||
|
||||
} else {
|
||||
|
||||
// Focusing on an Group, AmbientLight, etc
|
||||
|
||||
center.setFromMatrixPosition(target.matrixWorld);
|
||||
distance = 0.1;
|
||||
|
||||
}
|
||||
|
||||
delta.set(0, 0, 1);
|
||||
delta.applyQuaternion(object.quaternion);
|
||||
delta.multiplyScalar(distance * 4);
|
||||
|
||||
object.position.copy(center).add(delta);
|
||||
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
};
|
||||
|
||||
this.pan = function (delta) {
|
||||
|
||||
var distance = object.position.distanceTo(center);
|
||||
|
||||
delta.multiplyScalar(distance * scope.panSpeed);
|
||||
delta.applyMatrix3(normalMatrix.getNormalMatrix(object.matrix));
|
||||
|
||||
object.position.add(delta);
|
||||
center.add(delta);
|
||||
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
};
|
||||
|
||||
this.zoom = function (delta) {
|
||||
|
||||
var distance = object.position.distanceTo(center);
|
||||
|
||||
delta.multiplyScalar(distance * scope.zoomSpeed);
|
||||
|
||||
if (delta.length() > distance) return;
|
||||
|
||||
delta.applyMatrix3(normalMatrix.getNormalMatrix(object.matrix));
|
||||
|
||||
object.position.add(delta);
|
||||
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
};
|
||||
|
||||
this.rotate = function (delta) {
|
||||
|
||||
vector.copy(object.position).sub(center);
|
||||
|
||||
spherical.setFromVector3(vector);
|
||||
|
||||
spherical.theta += delta.x * scope.rotationSpeed;
|
||||
spherical.phi += delta.y * scope.rotationSpeed;
|
||||
|
||||
spherical.makeSafe();
|
||||
|
||||
vector.setFromSpherical(spherical);
|
||||
|
||||
object.position.copy(center).add(vector);
|
||||
|
||||
object.lookAt(center);
|
||||
|
||||
scope.dispatchEvent(changeEvent);
|
||||
|
||||
};
|
||||
|
||||
// mouse
|
||||
|
||||
function onMouseDown(event) {
|
||||
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
if (event.button === 0) {
|
||||
|
||||
state = STATE.ROTATE;
|
||||
|
||||
} else if (event.button === 1) {
|
||||
|
||||
state = STATE.ZOOM;
|
||||
|
||||
} else if (event.button === 2) {
|
||||
|
||||
state = STATE.PAN;
|
||||
|
||||
}
|
||||
|
||||
pointerOld.set(event.clientX, event.clientY);
|
||||
|
||||
domElement.addEventListener('mousemove', onMouseMove, false);
|
||||
domElement.addEventListener('mouseup', onMouseUp, false);
|
||||
domElement.addEventListener('mouseout', onMouseUp, false);
|
||||
domElement.addEventListener('dblclick', onMouseUp, false);
|
||||
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
pointer.set(event.clientX, event.clientY);
|
||||
|
||||
var movementX = pointer.x - pointerOld.x;
|
||||
var movementY = pointer.y - pointerOld.y;
|
||||
|
||||
if (state === STATE.ROTATE) {
|
||||
|
||||
scope.rotate(delta.set(- movementX, - movementY, 0));
|
||||
|
||||
} else if (state === STATE.ZOOM) {
|
||||
|
||||
scope.zoom(delta.set(0, 0, movementY));
|
||||
|
||||
} else if (state === STATE.PAN) {
|
||||
|
||||
scope.pan(delta.set(- movementX, movementY, 0));
|
||||
|
||||
}
|
||||
|
||||
pointerOld.set(event.clientX, event.clientY);
|
||||
|
||||
}
|
||||
|
||||
function onMouseUp(event) {
|
||||
|
||||
domElement.removeEventListener('mousemove', onMouseMove, false);
|
||||
domElement.removeEventListener('mouseup', onMouseUp, false);
|
||||
domElement.removeEventListener('mouseout', onMouseUp, false);
|
||||
domElement.removeEventListener('dblclick', onMouseUp, false);
|
||||
|
||||
state = STATE.NONE;
|
||||
|
||||
}
|
||||
|
||||
function onMouseWheel(event) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// Normalize deltaY due to https://bugzilla.mozilla.org/show_bug.cgi?id=1392460
|
||||
scope.zoom(delta.set(0, 0, event.deltaY > 0 ? 1 : - 1));
|
||||
|
||||
}
|
||||
|
||||
function contextmenu(event) {
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
}
|
||||
|
||||
this.dispose = function () {
|
||||
|
||||
domElement.removeEventListener('contextmenu', contextmenu, false);
|
||||
domElement.removeEventListener('mousedown', onMouseDown, false);
|
||||
domElement.removeEventListener('wheel', onMouseWheel, false);
|
||||
|
||||
domElement.removeEventListener('mousemove', onMouseMove, false);
|
||||
domElement.removeEventListener('mouseup', onMouseUp, false);
|
||||
domElement.removeEventListener('mouseout', onMouseUp, false);
|
||||
domElement.removeEventListener('dblclick', onMouseUp, false);
|
||||
|
||||
domElement.removeEventListener('touchstart', touchStart, false);
|
||||
domElement.removeEventListener('touchmove', touchMove, false);
|
||||
|
||||
};
|
||||
|
||||
domElement.addEventListener('contextmenu', contextmenu, false);
|
||||
domElement.addEventListener('mousedown', onMouseDown, false);
|
||||
domElement.addEventListener('wheel', onMouseWheel, false);
|
||||
|
||||
// touch
|
||||
|
||||
var touches = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
|
||||
var prevTouches = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
|
||||
|
||||
var prevDistance = null;
|
||||
|
||||
function touchStart(event) {
|
||||
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
switch (event.touches.length) {
|
||||
|
||||
case 1:
|
||||
touches[0].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
touches[1].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
touches[0].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
touches[1].set(event.touches[1].pageX, event.touches[1].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
prevDistance = touches[0].distanceTo(touches[1]);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
prevTouches[0].copy(touches[0]);
|
||||
prevTouches[1].copy(touches[1]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
function touchMove(event) {
|
||||
|
||||
if (scope.enabled === false) return;
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
function getClosest(touch, touches) {
|
||||
|
||||
var closest = touches[0];
|
||||
|
||||
for (var i in touches) {
|
||||
|
||||
if (closest.distanceTo(touch) > touches[i].distanceTo(touch)) closest = touches[i];
|
||||
|
||||
}
|
||||
|
||||
return closest;
|
||||
|
||||
}
|
||||
|
||||
switch (event.touches.length) {
|
||||
|
||||
case 1:
|
||||
touches[0].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
touches[1].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
scope.rotate(touches[0].sub(getClosest(touches[0], prevTouches)).multiplyScalar(- 1));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
touches[0].set(event.touches[0].pageX, event.touches[0].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
touches[1].set(event.touches[1].pageX, event.touches[1].pageY, 0).divideScalar(window.devicePixelRatio);
|
||||
var distance = touches[0].distanceTo(touches[1]);
|
||||
scope.zoom(delta.set(0, 0, prevDistance - distance));
|
||||
prevDistance = distance;
|
||||
|
||||
|
||||
var offset0 = touches[0].clone().sub(getClosest(touches[0], prevTouches));
|
||||
var offset1 = touches[1].clone().sub(getClosest(touches[1], prevTouches));
|
||||
offset0.x = - offset0.x;
|
||||
offset1.x = - offset1.x;
|
||||
|
||||
scope.pan(offset0.add(offset1));
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
prevTouches[0].copy(touches[0]);
|
||||
prevTouches[1].copy(touches[1]);
|
||||
|
||||
}
|
||||
|
||||
domElement.addEventListener('touchstart', touchStart, false);
|
||||
domElement.addEventListener('touchmove', touchMove, false);
|
||||
/**
|
||||
* 自由控制器
|
||||
*/
|
||||
class FreeControls extends BaseControls {
|
||||
|
||||
}
|
||||
|
||||
EditorControls.prototype = Object.create(THREE.EventDispatcher.prototype);
|
||||
EditorControls.prototype.constructor = EditorControls;
|
||||
|
||||
export default EditorControls;
|
||||
export default FreeControls;
|
||||
Loading…
x
Reference in New Issue
Block a user