playcanvas
Version:
PlayCanvas WebGL game engine
316 lines (313 loc) • 10.3 kB
JavaScript
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 };