UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

264 lines (261 loc) 8.29 kB
import { Vec3 } from '../../core/math/vec3.js'; import { Quat } from '../../core/math/quat.js'; import { GIZMOSPACE_LOCAL, GIZMOAXIS_FACE, GIZMOAXIS_X, GIZMOAXIS_Y, GIZMOAXIS_Z } from './constants.js'; import { TransformGizmo } from './transform-gizmo.js'; import { PlaneShape } from './shape/plane-shape.js'; import { ArrowShape } from './shape/arrow-shape.js'; import { SphereShape } from './shape/sphere-shape.js'; var tmpV1 = new Vec3(); var tmpV2 = new Vec3(); var tmpQ1 = new Quat(); var GLANCE_EPSILON = 0.98; class TranslateGizmo extends TransformGizmo { set axisGap(value) { this._setArrowProp('gap', value); } get axisGap() { return this._shapes.x.gap; } set axisLineThickness(value) { this._setArrowProp('lineThickness', value); } get axisLineThickness() { return this._shapes.x.lineThickness; } set axisLineLength(value) { this._setArrowProp('lineLength', value); } get axisLineLength() { return this._shapes.x.lineLength; } set axisLineTolerance(value) { this._setArrowProp('tolerance', value); } get axisLineTolerance() { return this._shapes.x.tolerance; } set axisArrowThickness(value) { this._setArrowProp('arrowThickness', value); } get axisArrowThickness() { return this._shapes.x.arrowThickness; } set axisArrowLength(value) { this._setArrowProp('arrowLength', value); } get axisArrowLength() { return this._shapes.x.arrowLength; } set axisPlaneSize(value) { this._setPlaneProp('size', value); } get axisPlaneSize() { return this._shapes.yz.size; } set axisPlaneGap(value) { this._setPlaneProp('gap', value); } get axisPlaneGap() { return this._shapes.yz.gap; } set axisCenterSize(value) { this._shapes.face.size = value; } get axisCenterSize() { return this._shapes.face.size; } set axisCenterTolerance(value) { this._shapes.face.tolerance = value; } get axisCenterTolerance() { return this._shapes.face.tolerance; } _setArrowProp(prop, value) { this._shapes.x[prop] = value; this._shapes.y[prop] = value; this._shapes.z[prop] = value; } _setPlaneProp(prop, value) { this._shapes.yz[prop] = value; this._shapes.xz[prop] = value; this._shapes.xy[prop] = value; } _shapesLookAtCamera() { var facingDir = this.facing; var dot = facingDir.dot(this.root.right); this._shapes.x.entity.enabled = Math.abs(dot) < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.x.flipped = dot < 0; } dot = facingDir.dot(this.root.up); this._shapes.y.entity.enabled = Math.abs(dot) < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.y.flipped = dot < 0; } dot = facingDir.dot(this.root.forward); this._shapes.z.entity.enabled = Math.abs(dot) < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.z.flipped = dot > 0; } tmpV1.cross(facingDir, this.root.right); this._shapes.yz.entity.enabled = tmpV1.length() < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.yz.flipped = tmpV2.set(0, +(tmpV1.dot(this.root.forward) < 0), +(tmpV1.dot(this.root.up) < 0)); } tmpV1.cross(facingDir, this.root.forward); this._shapes.xy.entity.enabled = tmpV1.length() < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.xy.flipped = tmpV2.set(+(tmpV1.dot(this.root.up) < 0), +(tmpV1.dot(this.root.right) > 0), 0); } tmpV1.cross(facingDir, this.root.up); this._shapes.xz.entity.enabled = tmpV1.length() < GLANCE_EPSILON; if (this.flipShapes) { this._shapes.xz.flipped = tmpV2.set(+(tmpV1.dot(this.root.forward) > 0), 0, +(tmpV1.dot(this.root.right) > 0)); } } _storeNodePositions() { for(var i = 0; i < this.nodes.length; i++){ var node = this.nodes[i]; this._nodeLocalPositions.set(node, node.getLocalPosition().clone()); this._nodePositions.set(node, node.getPosition().clone()); } } _setNodePositions(pointDelta) { for(var i = 0; i < this.nodes.length; i++){ var node = this.nodes[i]; if (this._coordSpace === GIZMOSPACE_LOCAL) { var _node_parent; var pos = this._nodeLocalPositions.get(node); if (!pos) { continue; } tmpV1.copy(pointDelta); (_node_parent = node.parent) == null ? undefined : _node_parent.getWorldTransform().getScale(tmpV2); tmpV2.x = 1 / tmpV2.x; tmpV2.y = 1 / tmpV2.y; tmpV2.z = 1 / tmpV2.z; tmpQ1.copy(node.getLocalRotation()).transformVector(tmpV1, tmpV1); tmpV1.mul(tmpV2); node.setLocalPosition(tmpV1.add(pos)); } else { var pos1 = this._nodePositions.get(node); if (!pos1) { continue; } node.setPosition(tmpV1.copy(pointDelta).add(pos1)); } } this._updatePosition(); } _screenToPoint(x, y) { var mouseWPos = this._camera.screenToWorld(x, y, 1); var axis = this._selectedAxis; var isPlane = this._selectedIsPlane; var ray = this._createRay(mouseWPos); var plane = this._createPlane(axis, axis === GIZMOAXIS_FACE, !isPlane); var point = new Vec3(); var angle = 0; plane.intersectsRay(ray, point); tmpQ1.copy(this._rootStartRot).invert().transformVector(point, point); if (!isPlane && axis !== GIZMOAXIS_FACE) { this._projectToAxis(point, axis); } return { point, angle }; } constructor(camera, layer){ super(camera, layer), this._shapes = { face: new SphereShape(this._device, { axis: GIZMOAXIS_FACE, layers: [ this._layer.id ], shading: this._shading, defaultColor: this._meshColors.axis.xyz, hoverColor: this._meshColors.hover.xyz }), yz: new PlaneShape(this._device, { axis: GIZMOAXIS_X, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(0, 0, -90), defaultColor: this._meshColors.axis.x, hoverColor: this._meshColors.hover.x }), xz: new PlaneShape(this._device, { axis: GIZMOAXIS_Y, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(0, 0, 0), defaultColor: this._meshColors.axis.y, hoverColor: this._meshColors.hover.y }), xy: new PlaneShape(this._device, { axis: GIZMOAXIS_Z, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(90, 0, 0), defaultColor: this._meshColors.axis.z, hoverColor: this._meshColors.hover.z }), x: new ArrowShape(this._device, { axis: GIZMOAXIS_X, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(0, 0, -90), defaultColor: this._meshColors.axis.x, hoverColor: this._meshColors.hover.x }), y: new ArrowShape(this._device, { axis: GIZMOAXIS_Y, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(0, 0, 0), defaultColor: this._meshColors.axis.y, hoverColor: this._meshColors.hover.y }), z: new ArrowShape(this._device, { axis: GIZMOAXIS_Z, layers: [ this._layer.id ], shading: this._shading, rotation: new Vec3(90, 0, 0), defaultColor: this._meshColors.axis.z, hoverColor: this._meshColors.hover.z }) }, this._nodeLocalPositions = new Map(), this._nodePositions = new Map(), this.snapIncrement = 1, this.flipShapes = true; this._createTransform(); this.on(TransformGizmo.EVENT_TRANSFORMSTART, ()=>{ this._storeNodePositions(); }); this.on(TransformGizmo.EVENT_TRANSFORMMOVE, (pointDelta)=>{ if (this.snap) { pointDelta.mulScalar(1 / this.snapIncrement); pointDelta.round(); pointDelta.mulScalar(this.snapIncrement); } this._setNodePositions(pointDelta); }); this.on(TransformGizmo.EVENT_NODESDETACH, ()=>{ this._nodeLocalPositions.clear(); this._nodePositions.clear(); }); this._app.on('prerender', ()=>{ this._shapesLookAtCamera(); }); } } export { TranslateGizmo };