mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 16:33:15 +01:00
183 lines
No EOL
4.8 KiB
JavaScript
183 lines
No EOL
4.8 KiB
JavaScript
import {BufferGeometry, Line, LineBasicMaterial, MeshBasicMaterial, Object3D, Vector3} from 'three';
|
|
|
|
|
|
import CSysObject3D from './csysObject';
|
|
import {NOOP} from 'gems/func';
|
|
import {createExpensiveSetter, createReactiveState} from 'scene/utils/stateUpdater';
|
|
|
|
export default class DatumObject3D extends Object3D {
|
|
|
|
static AXIS = {
|
|
X: 1,
|
|
Y: 2,
|
|
Z: 3,
|
|
};
|
|
|
|
constructor(csys, viewer) {
|
|
super();
|
|
this.viewer = viewer;
|
|
this.csys = csys.clone();
|
|
this.csysObj = new CSysObject3D(this.csys, this.viewer.sceneSetup, {
|
|
createHandle: true,
|
|
handleMaterial: () => new MeshBasicMaterial({
|
|
transparent: true,
|
|
opacity: 0.5,
|
|
color: 0xAA8439,
|
|
visible: false
|
|
})
|
|
});
|
|
addOnHoverBehaviour(this.csysObj.xAxis.handle, this.viewer);
|
|
addOnHoverBehaviour(this.csysObj.yAxis.handle, this.viewer);
|
|
addOnHoverBehaviour(this.csysObj.zAxis.handle, this.viewer);
|
|
this.add(this.csysObj);
|
|
this.exitEditMode = NOOP;
|
|
this.beingDraggedAxis = null;
|
|
this.freezeDragging = false;
|
|
}
|
|
|
|
setMoveMode(axis) {
|
|
this.exitEditMode();
|
|
let dir, color;
|
|
if (axis === DatumObject3D.AXIS.X) {
|
|
dir = this.csys.x;
|
|
color = 0xff0000;
|
|
} else if (axis === DatumObject3D.AXIS.Y) {
|
|
dir = this.csys.y;
|
|
color = 0x00ff00;
|
|
} else if (axis === DatumObject3D.AXIS.Z) {
|
|
dir = this.csys.z;
|
|
color = 0x0000ff;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
this.beingDraggedAxis = dir;
|
|
|
|
const ext = dir.multiply(this.viewer.sceneSetup.workingSphere);
|
|
|
|
const material = new LineBasicMaterial({color});
|
|
const geometry = new BufferGeometry().setFromPoints( [
|
|
new Vector3().copy(this.csys.origin.minus(ext)),
|
|
new Vector3().copy(this.csys.origin.plus(ext))
|
|
]);
|
|
|
|
const line = new Line(geometry, material);
|
|
this.add(line);
|
|
|
|
this.exitEditMode = () => {
|
|
this.beingDraggedAxis = null;
|
|
this.remove(line);
|
|
geometry.dispose();
|
|
material.dispose();
|
|
this.exitEditMode = NOOP;
|
|
}
|
|
}
|
|
|
|
dragStart(e, axis) {
|
|
this.dragInfo = {
|
|
csysOrigin: this.csys.origin.copy(),
|
|
originViewCoord: this.viewer.sceneSetup.modelToScreen(this.csys.origin),
|
|
startX: e.offsetX,
|
|
startY: e.offsetY,
|
|
};
|
|
switch (axis) {
|
|
case this.csysObj.xAxis:
|
|
this.setMoveMode(DatumObject3D.AXIS.X);
|
|
break;
|
|
case this.csysObj.yAxis:
|
|
this.setMoveMode(DatumObject3D.AXIS.Y);
|
|
break;
|
|
case this.csysObj.zAxis:
|
|
default:
|
|
this.setMoveMode(DatumObject3D.AXIS.Z);
|
|
break;
|
|
}
|
|
}
|
|
|
|
dragMove({mouseEvent: e}) {
|
|
if (this.beingDraggedAxis) {
|
|
const dir = this.beingDraggedAxis;
|
|
|
|
const traveledX = e.offsetX - this.dragInfo.startX;
|
|
const traveledY = e.offsetY - this.dragInfo.startY;
|
|
|
|
const raycaster = this.viewer.sceneSetup.createRaycaster(this.dragInfo.originViewCoord.x + traveledX, this.dragInfo.originViewCoord.y + traveledY);
|
|
|
|
this.csys.origin.setV(this.dragInfo.csysOrigin);
|
|
|
|
//see nurbs-ext - rays intersection
|
|
const zRef = dir.cross(raycaster.ray.direction);
|
|
|
|
const n2 = zRef.cross(raycaster.ray.direction)._normalize();
|
|
|
|
const u = n2.dot(this.csys.origin.minus(raycaster.ray.origin)._negate()) / n2.dot(dir);
|
|
|
|
const delta = dir.multiply(u);
|
|
this.csys.origin._plus(delta);
|
|
|
|
if (e.shiftKey) {
|
|
roundVector(this.csys.origin);
|
|
}
|
|
|
|
this.viewer.requestRender();
|
|
|
|
this.onMove(this.dragInfo.csysOrigin, this.csys.origin, delta);
|
|
}
|
|
}
|
|
|
|
onMove(begin, end, delta) {
|
|
}
|
|
|
|
dragDrop() {
|
|
this.exitEditMode();
|
|
this.viewer.requestRender();
|
|
}
|
|
|
|
dispose() {
|
|
this.exitEditMode();
|
|
this.csysObj.dispose();
|
|
}
|
|
}
|
|
|
|
function addOnHoverBehaviour(handle, viewer) {
|
|
handle.onMouseDown = function(e) {
|
|
const datum = this.parent.parent.parent;
|
|
if (datum.freezeDragging) {
|
|
return;
|
|
}
|
|
e.startDrag(datum);
|
|
datum.dragStart(e.mouseEvent, this.parent);
|
|
};
|
|
|
|
const defaultColor = handle.material.color.getHex();
|
|
const setColor = createExpensiveSetter(color => handle.material.color.setHex(color));
|
|
|
|
const handleState = createReactiveState({
|
|
selected: null,
|
|
visible: true
|
|
},
|
|
state => {
|
|
if (state.selected !== null) {
|
|
handle.material.visible = true;
|
|
setColor(state.selected);
|
|
} else {
|
|
setColor(defaultColor);
|
|
handle.material.visible = state.hovered;
|
|
}
|
|
viewer.requestRender();
|
|
});
|
|
|
|
handle.onMouseEnter = function() {
|
|
handleState('hovered', true);
|
|
};
|
|
handle.onMouseLeave = function() {
|
|
handleState('hovered', false);
|
|
};
|
|
handle.setSelected = value => handleState('selected', value);
|
|
}
|
|
|
|
function roundVector(v) {
|
|
v.x = Math.round(v.x);
|
|
v.y = Math.round(v.y);
|
|
v.z = Math.round(v.z);
|
|
} |