UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

316 lines (313 loc) 10.3 kB
import { math } from '../../core/math/math.js'; import { Color } from '../../core/math/color.js'; import { Quat } from '../../core/math/quat.js'; import { Vec3 } from '../../core/math/vec3.js'; import { Ray } from '../../core/shape/ray.js'; import { Plane } from '../../core/shape/plane.js'; import { PROJECTION_PERSPECTIVE } from '../../scene/constants.js'; import { color4from3, color3from4, COLOR_GRAY, COLOR_YELLOW, COLOR_BLUE, COLOR_GREEN, COLOR_RED } from './color.js'; import { GIZMOAXIS_X, GIZMOAXIS_Y, GIZMOAXIS_Z, GIZMOAXIS_FACE, GIZMOAXIS_XYZ } from './constants.js'; import { Gizmo } from './gizmo.js'; var tmpV1 = new Vec3(); var tmpV2 = new Vec3(); var tmpQ1 = new Quat(); var tmpR1 = new Ray(); var tmpP1 = new Plane(); var VEC3_AXES = Object.keys(tmpV1); class TransformGizmo extends Gizmo { set shading(value) { this._shading = this.root.enabled && value; for(var name in this._shapes){ this._shapes[name].shading = this._shading; } } get shading() { return this._shading; } set snap(value) { this._snap = this.root.enabled && value; } get snap() { return this._snap; } set xAxisColor(value) { this._updateAxisColor(GIZMOAXIS_X, value); } get xAxisColor() { return this._meshColors.axis.x; } set yAxisColor(value) { this._updateAxisColor(GIZMOAXIS_Y, value); } get yAxisColor() { return this._meshColors.axis.y; } set zAxisColor(value) { this._updateAxisColor(GIZMOAXIS_Z, value); } get zAxisColor() { return this._meshColors.axis.z; } set colorAlpha(value) { this._colorAlpha = math.clamp(value, 0, 1); this._meshColors.axis.x.copy(this._colorSemi(this._meshColors.axis.x)); this._meshColors.axis.y.copy(this._colorSemi(this._meshColors.axis.y)); this._meshColors.axis.z.copy(this._colorSemi(this._meshColors.axis.z)); this._meshColors.axis.xyz.copy(this._colorSemi(this._meshColors.axis.xyz)); this._meshColors.axis.f.copy(this._colorSemi(this._meshColors.axis.f)); for(var name in this._shapes){ this._shapes[name].hover(!!this._hoverAxis); } } get colorAlpha() { return this._colorAlpha; } _colorSemi(color) { return color4from3(color, this._colorAlpha); } _updateAxisColor(axis, value) { var color3 = color3from4(value); var color4 = this._colorSemi(value); this._guideColors[axis].copy(color3); this._meshColors.axis[axis].copy(color4); this._meshColors.hover[axis].copy(color3); for(var name in this._shapes){ this._shapes[name].hover(!!this._hoverAxis); } } _getAxis(meshInstance) { if (!meshInstance) { return ''; } return meshInstance.node.name.split(':')[1]; } _getIsPlane(meshInstance) { if (!meshInstance) { return false; } return meshInstance.node.name.indexOf('plane') !== -1; } _hover(meshInstance) { if (this._dragging) { return; } this._hoverAxis = this._getAxis(meshInstance); this._hoverIsPlane = this._getIsPlane(meshInstance); var _this__shapeMap_get; var shape = meshInstance ? (_this__shapeMap_get = this._shapeMap.get(meshInstance)) != null ? _this__shapeMap_get : null : null; if (shape === this._hoverShape) { return; } if (this._hoverShape) { this._hoverShape.hover(false); this._hoverShape = null; } if (shape) { shape.hover(true); this._hoverShape = shape; } this.fire(Gizmo.EVENT_RENDERUPDATE); } _createRay(mouseWPos) { if (this._camera.projection === PROJECTION_PERSPECTIVE) { tmpR1.origin.copy(this._camera.entity.getPosition()); tmpR1.direction.sub2(mouseWPos, tmpR1.origin).normalize(); return tmpR1; } var orthoDepth = this._camera.farClip - this._camera.nearClip; tmpR1.origin.sub2(mouseWPos, tmpV1.copy(this._camera.entity.forward).mulScalar(orthoDepth)); tmpR1.direction.copy(this._camera.entity.forward); return tmpR1; } _createPlane(axis, isFacing, isLine) { var facingDir = tmpV1.copy(this.facing); var normal = tmpP1.normal.set(0, 0, 0); if (isFacing) { normal.copy(facingDir); } else { normal[axis] = 1; this._rootStartRot.transformVector(normal, normal); if (isLine) { tmpV2.cross(normal, facingDir).normalize(); normal.cross(tmpV2, normal).normalize(); } } return tmpP1.setFromPointNormal(this._rootStartPos, normal); } _dirFromAxis(axis, dir) { if (axis === GIZMOAXIS_FACE) { dir.copy(this._camera.entity.forward).mulScalar(-1); } else { dir.set(0, 0, 0); dir[axis] = 1; } return dir; } _projectToAxis(point, axis) { tmpV1.set(0, 0, 0); tmpV1[axis] = 1; point.copy(tmpV1.mulScalar(tmpV1.dot(point))); var v = point[axis]; point.set(0, 0, 0); point[axis] = v; } _screenToPoint(x, y, isFacing, isLine) { if (isFacing === void 0) isFacing = false; if (isLine === void 0) isLine = false; var mouseWPos = this._camera.screenToWorld(x, y, 1); var axis = this._selectedAxis; var ray = this._createRay(mouseWPos); var plane = this._createPlane(axis, isFacing, isLine); var point = new Vec3(); plane.intersectsRay(ray, point); return point; } _drawGuideLines() { var gizmoPos = this.root.getPosition(); var gizmoRot = tmpQ1.copy(this.root.getRotation()); var checkAxis = this._hoverAxis || this._selectedAxis; var checkIsPlane = this._hoverIsPlane || this._selectedIsPlane; for(var i = 0; i < VEC3_AXES.length; i++){ var axis = VEC3_AXES[i]; if (checkAxis === GIZMOAXIS_XYZ) { this._drawSpanLine(gizmoPos, gizmoRot, axis); continue; } if (checkIsPlane) { if (axis !== checkAxis) { this._drawSpanLine(gizmoPos, gizmoRot, axis); } } else { if (axis === checkAxis) { this._drawSpanLine(gizmoPos, gizmoRot, axis); } } } } _drawSpanLine(pos, rot, axis) { tmpV1.set(0, 0, 0); tmpV1[axis] = 1; tmpV1.mulScalar(this._camera.farClip - this._camera.nearClip); tmpV2.copy(tmpV1).mulScalar(-1); rot.transformVector(tmpV1, tmpV1); rot.transformVector(tmpV2, tmpV2); this._app.drawLine(tmpV1.add(pos), tmpV2.add(pos), this._guideColors[axis], true); } _createTransform() { for(var key in this._shapes){ var shape = this._shapes[key]; this.root.addChild(shape.entity); this.intersectShapes.push(shape); for(var i = 0; i < shape.meshInstances.length; i++){ this._shapeMap.set(shape.meshInstances[i], shape); } } } enableShape(shapeAxis, enabled) { if (!this._shapes.hasOwnProperty(shapeAxis)) { return; } this._shapes[shapeAxis].disabled = !enabled; } isShapeEnabled(shapeAxis) { if (!this._shapes.hasOwnProperty(shapeAxis)) { return false; } return !this._shapes[shapeAxis].disabled; } destroy() { super.destroy(); for(var key in this._shapes){ this._shapes[key].destroy(); } } constructor(camera, layer){ super(camera, layer), this._colorAlpha = 0.6, this._meshColors = { axis: { x: this._colorSemi(COLOR_RED), y: this._colorSemi(COLOR_GREEN), z: this._colorSemi(COLOR_BLUE), xyz: this._colorSemi(Color.WHITE), f: this._colorSemi(Color.WHITE) }, hover: { x: COLOR_RED.clone(), y: COLOR_GREEN.clone(), z: COLOR_BLUE.clone(), xyz: Color.WHITE.clone(), f: COLOR_YELLOW.clone() }, disabled: COLOR_GRAY.clone() }, this._guideColors = { x: COLOR_RED.clone(), y: COLOR_GREEN.clone(), z: COLOR_BLUE.clone(), f: COLOR_YELLOW.clone() }, this._rootStartPos = new Vec3(), this._rootStartRot = new Quat(), this._shading = false, this._shapes = {}, this._shapeMap = new Map(), this._hoverShape = null, this._hoverAxis = '', this._hoverIsPlane = false, this._noSelection = false, this._selectedAxis = '', this._selectedIsPlane = false, this._selectionStartPoint = new Vec3(), this._dragging = false, this._snap = false, this.snapIncrement = 1; this._app.on('prerender', ()=>{ if (!this.root.enabled) { return; } this._drawGuideLines(); }); this.on(Gizmo.EVENT_POINTERDOWN, (x, y, meshInstance)=>{ var shape = this._shapeMap.get(meshInstance); if (shape == null ? void 0 : shape.disabled) { return; } if (this._dragging) { return; } if (!meshInstance) { this._noSelection = true; return; } this._selectedAxis = this._getAxis(meshInstance); this._selectedIsPlane = this._getIsPlane(meshInstance); this._rootStartPos.copy(this.root.getPosition()); this._rootStartRot.copy(this.root.getRotation()); var point = this._screenToPoint(x, y); this._selectionStartPoint.copy(point); this._dragging = true; this.fire(TransformGizmo.EVENT_TRANSFORMSTART, point, x, y); }); this.on(Gizmo.EVENT_POINTERMOVE, (x, y, meshInstance)=>{ var shape = this._shapeMap.get(meshInstance); if (shape == null ? void 0 : shape.disabled) { return; } if (!this._noSelection) { this._hover(meshInstance); } if (!this._dragging) { return; } var point = this._screenToPoint(x, y); this.fire(TransformGizmo.EVENT_TRANSFORMMOVE, point, x, y); this._hoverAxis = ''; this._hoverIsPlane = false; }); this.on(Gizmo.EVENT_POINTERUP, (x, y, meshInstance)=>{ this._noSelection = false; this._hover(meshInstance); if (!this._dragging) { return; } this._dragging = false; this.fire(TransformGizmo.EVENT_TRANSFORMEND); this._selectedAxis = ''; this._selectedIsPlane = false; }); this.on(Gizmo.EVENT_NODESDETACH, ()=>{ this.snap = false; this._hoverAxis = ''; this._hoverIsPlane = false; this._hover(); this.fire(Gizmo.EVENT_POINTERUP); }); } } TransformGizmo.EVENT_TRANSFORMSTART = 'transform:start'; TransformGizmo.EVENT_TRANSFORMMOVE = 'transform:move'; TransformGizmo.EVENT_TRANSFORMEND = 'transform:end'; export { TransformGizmo };