@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
2 lines (1 loc) • 6.37 kB
JavaScript
import{math as t}from"../../core/math/math.js";import{Color as e}from"../../core/math/color.js";import{Quat as s}from"../../core/math/quat.js";import{Mat4 as i}from"../../core/math/mat4.js";import{Vec3 as o}from"../../core/math/vec3.js";import{PROJECTION_PERSPECTIVE as a}from"../../scene/constants.js";import{ArcShape as n}from"./shape/arc-shape.js";import{GIZMOAXIS_Z as r,GIZMOAXIS_X as h,GIZMOAXIS_Y as c,GIZMOAXIS_FACE as l,GIZMOSPACE_LOCAL as _}from"./constants.js";import{TransformGizmo as d}from"./transform-gizmo.js";const g=new o,u=new o,p=new o,m=new o,A=new i,R=new s,f=new s,y=new e(0,0,0,.3);class x extends d{constructor(t,e){super(t,e),this._shapes={z:new n(this._device,{axis:r,layers:[this._layer.id],shading:this._shading,rotation:new o(90,0,90),defaultColor:this._meshColors.axis.z,hoverColor:this._meshColors.hover.z,sectorAngle:180}),x:new n(this._device,{axis:h,layers:[this._layer.id],shading:this._shading,rotation:new o(0,0,-90),defaultColor:this._meshColors.axis.x,hoverColor:this._meshColors.hover.x,sectorAngle:180}),y:new n(this._device,{axis:c,layers:[this._layer.id],shading:this._shading,rotation:new o(0,0,0),defaultColor:this._meshColors.axis.y,hoverColor:this._meshColors.hover.y,sectorAngle:180}),face:new n(this._device,{axis:l,layers:[this._layer.id],shading:this._shading,rotation:this._getLookAtEulerAngles(this._camera.entity.getPosition()),defaultColor:this._meshColors.axis.f,hoverColor:this._meshColors.hover.f,ringRadius:.55})},this._selectionStartAngle=0,this._nodeLocalRotations=new Map,this._nodeRotations=new Map,this._nodeOffsets=new Map,this._guideAngleStartColor=y.clone(),this._guideAngleStart=new o,this._guideAngleEnd=new o,this.snapIncrement=5,this.orbitRotation=!1,this._createTransform(),this.on(d.EVENT_TRANSFORMSTART,((t,e,s)=>{this._selectionStartAngle=this._calculateAngle(t,e,s),this._storeNodeRotations(),this._storeGuidePoints(),this._drag(!0)})),this.on(d.EVENT_TRANSFORMMOVE,((t,e,s)=>{const i=this._selectedAxis;let o=this._calculateAngle(t,e,s)-this._selectionStartAngle;this.snap&&(o=Math.round(o/this.snapIncrement)*this.snapIncrement),this._setNodeRotations(i,o),this._updateGuidePoints(o)})),this.on(d.EVENT_TRANSFORMEND,(()=>{this._drag(!1)})),this.on(d.EVENT_NODESDETACH,(()=>{this._nodeLocalRotations.clear(),this._nodeRotations.clear(),this._nodeOffsets.clear()})),this._app.on("prerender",(()=>{if(this._shapesLookAtCamera(),this._dragging){const t=this.root.getPosition();this._drawGuideAngleLine(t,this._selectedAxis,this._guideAngleStart,this._guideAngleStartColor),this._drawGuideAngleLine(t,this._selectedAxis,this._guideAngleEnd)}}))}set xyzTubeRadius(t){this._setDiskProp("tubeRadius",t)}get xyzTubeRadius(){return this._shapes.x.tubeRadius}set xyzRingRadius(t){this._setDiskProp("ringRadius",t)}get xyzRingRadius(){return this._shapes.x.ringRadius}set faceTubeRadius(t){this._shapes.face.tubeRadius=t}get faceTubeRadius(){return this._shapes.face.tubeRadius}set faceRingRadius(t){this._shapes.face.ringRadius=t}get faceRingRadius(){return this._shapes.face.ringRadius}set ringTolerance(t){this._setDiskProp("tolerance",t),this._shapes.face.tolerance=t}get ringTolerance(){return this._shapes.x.tolerance}_setDiskProp(t,e){this._shapes.x[t]=e,this._shapes.y[t]=e,this._shapes.z[t]=e}_storeGuidePoints(){const t=this.root.getPosition(),e=this._selectedAxis===l?this.faceRingRadius:this.xyzRingRadius;this._guideAngleStart.copy(this._selectionStartPoint).sub(t).normalize(),this._guideAngleStart.mulScalar(e),this._guideAngleEnd.copy(this._guideAngleStart)}_updateGuidePoints(t){const e=this._selectedAxis;e===l?g.copy(this.facing):(g.set(0,0,0),g[e]=1,this._rootStartRot.transformVector(g,g)),R.setFromAxisAngle(g,t),R.transformVector(this._guideAngleStart,this._guideAngleEnd)}_drawGuideAngleLine(t,e,s,i=this._guideColors[e]){g.set(0,0,0),u.copy(s).mulScalar(this._scale),this._app.drawLine(g.add(t),u.add(t),i,!1,this._layer)}_getLookAtEulerAngles(t){return g.set(0,0,0),A.setLookAt(g,t,o.UP),R.setFromMat4(A),R.getEulerAngles(g),g.x+=90,g}_shapesLookAtCamera(){this._camera.projection===a?(this._shapes.face.entity.lookAt(this._camera.entity.getPosition()),this._shapes.face.entity.rotateLocal(90,0,0)):(R.copy(this._camera.entity.getRotation()).getEulerAngles(g),this._shapes.face.entity.setEulerAngles(g),this._shapes.face.entity.rotateLocal(-90,0,0));const e=g.copy(this.facing);R.copy(this.root.getRotation()).invert().transformVector(e,e);let s=Math.atan2(e.z,e.y)*t.RAD_TO_DEG;this._shapes.x.entity.setLocalEulerAngles(0,s-90,-90),s=Math.atan2(e.x,e.z)*t.RAD_TO_DEG,this._shapes.y.entity.setLocalEulerAngles(0,s,0),s=Math.atan2(e.y,e.x)*t.RAD_TO_DEG,this._shapes.z.entity.setLocalEulerAngles(90,0,s+90)}_drag(t){for(const e in this._shapes){const s=this._shapes[e];e===this._selectedAxis?s.drag(t):s.hide(t)}this.fire(d.EVENT_RENDERUPDATE)}_storeNodeRotations(){const t=this.root.getPosition();for(let e=0;e<this.nodes.length;e++){const s=this.nodes[e];this._nodeLocalRotations.set(s,s.getLocalRotation().clone()),this._nodeRotations.set(s,s.getRotation().clone()),this._nodeOffsets.set(s,s.getPosition().clone().sub(t))}}_setNodeRotations(t,e){const s=this.root.getPosition(),i=t===l;R.setFromAxisAngle(this._dirFromAxis(t,g),e);for(let t=0;t<this.nodes.length;t++){const e=this.nodes[t];if(i||this._coordSpace!==_){const t=this._nodeRotations.get(e);if(!t)continue;const i=this._nodeOffsets.get(e);if(!i)continue;g.copy(i),R.transformVector(g,g),f.copy(R).mul(t),e.setEulerAngles(f.getEulerAngles()),e.setPosition(g.add(s))}else{const t=this._nodeLocalRotations.get(e);if(!t)continue;f.copy(t).mul(R),e.setLocalRotation(f)}}this._coordSpace===_&&this._updateRotation()}_screenToPoint(t,e){const s=this._camera.screenToWorld(t,e,1),i=this._selectedAxis,a=this._createRay(s),n=this._createPlane(i,i===l,!1),r=new o;return n.intersectsRay(a,r),r}_calculateAngle(e,s,i){const o=this.root.getPosition(),a=this._selectedAxis,n=this._createPlane(a,a===l,!1);let r=0;const h=u.copy(this.facing),c=n.normal.dot(h);return this.orbitRotation||Math.abs(c)>.9?(g.sub2(e,o),R.copy(this._camera.entity.getRotation()).invert().transformVector(g,g),r=Math.sign(c)*Math.atan2(g.y,g.x)*t.RAD_TO_DEG):(g.copy(o),u.cross(n.normal,h).normalize().add(o),this._camera.worldToScreen(g,p),this._camera.worldToScreen(u,m),g.sub2(m,p).normalize(),u.set(s,i,0),r=g.dot(u)),r}}export{x as RotateGizmo};