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