@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 11.6 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.19/LICENSE.txt */
import{__decorate as t}from"tslib";import e from"../../../../../core/Accessor.js";import{multiplyOpacityToUnitRGBA as a}from"../../../../../core/colorUtils.js";import{cyclicalPI as o}from"../../../../../core/Cyclical.js";import{EventEmitter as i}from"../../../../../core/Evented.js";import"../../../../../core/has.js";import{clamp as r,rad2deg as s}from"../../../../../core/mathUtils.js";import{destroyMaybe as n}from"../../../../../core/maybe.js";import{watch as l,initial as c}from"../../../../../core/reactiveUtils.js";import{addFrameTask as d}from"../../../../../core/scheduling.js";import{createScreenPointArray as h}from"../../../../../core/screenUtils.js";import{property as u,subclass as p}from"../../../../../core/accessorSupport/decorators.js";import{fromRotation as g,fromScaling as m,multiply as f,scale as _,rotate as D}from"../../../../../core/libs/gl-matrix-2/math/mat4.js";import{create as M}from"../../../../../core/libs/gl-matrix-2/factories/mat4f64.js";import{set as v,subtract as S,length as b,squaredDistance as y,cross as j,add as R}from"../../../../../core/libs/gl-matrix-2/math/vec3.js";import{fromValues as w,clone as A}from"../../../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{fromPositionAndNormal as I,create as F,getNormal as k}from"../../../../../geometry/support/plane.js";import{wrap as E,distance2 as O}from"../../../../../geometry/support/ray.js";import{sm4d as P,sv3d as T}from"../../../../../geometry/support/vectorStacks.js";import{Manipulator3D as x}from"../../Manipulator3D.js";import{calculateInputRotationTransform as U}from"../../manipulatorUtils.js";import{RenderObject as L}from"../../RenderObject.js";import{screenToRenderPlane as C}from"../dragEventPipeline3D.js";import{ringIndicatorDelayMs as H,rotateIndicatorArrowPlacementPercentage as z,ringThickness as G,ringRadius as q,innerIndicatorRadius as B,outerIndicatorRadius as J,rotateIndicatorArrowTipRadius as K,rotateIndicatorArrowTipLength as N,scaleIndicatorOffset1 as Q,scaleIndicatorOffset2 as V,indicatorThickness as W,geometrySegments as X,rotateIndicatorArcLength as Y,scaleIndicatorArcLength as Z,rotateIndicatorDirectionBuffer as $,scaleIndicatorDirectionBuffer as tt,ringHeight as et,dragThresholdPx as at,ringResetAnimationSpeedFactor as ot}from"../manipulations/config.js";import{createExtrudedTriangle as it,transformInPlace as rt,createPathExtrusionGeometry as st}from"../../../webgl-engine/lib/GeometryUtil.js";import{ColorMaterial as nt}from"../../../webgl-engine/materials/ColorMaterial.js";import{createManipulatorDragEventPipeline as lt}from"../../../../interactive/dragEventPipeline.js";const ct={ScaleIn:32,ScaleOut:64,RotateLeft:128,RotateRight:256,Unlocked:1024,DelayedFocused:2048};let dt=class extends e{get angle(){return this.adapter.angle}get scale(){return this.adapter.scale}set location(t){this._ringManipulator.location=t}set elevationAlignedLocation(t){this._ringManipulator.elevationAlignedLocation=t}get grabbing(){return this._ringManipulator.grabbing}set interactive(t){this._ringManipulator.interactive=t}get updating(){return!!this._activeAnimation}constructor(t){super(t),this.mode=null,this._scaleRotateDragData=null,this._activeAnimation=null,this._ringIndicatorDelayMs=H,this.events=new i,this.getFocused=()=>this._ringManipulator.focused,this.getScale=()=>"scale"===this._scaleRotateDragData?.mode?this.adapter.scale:1}initialize(){this._createManipulator(),this._updateDragState(),this._updateManipulatorTransform(),this.addHandles([l(()=>{const{adapter:t}=this;return[t.angle,t.scale]},()=>this._updateManipulatorTransform())])}destroy(){this._activeAnimation?.frameTask.remove(),this._activeAnimation=null,this.tool.manipulators.remove(this._ringManipulator),this._ringManipulator=null}startAnimation(t){this.cancelActiveAnimation(),t.start();const e=d({update:({deltaTime:e})=>{t.update(e)&&this.cancelActiveAnimation()}});this._activeAnimation={...t,frameTask:e}}cancelActiveAnimation(){this._activeAnimation?.frameTask.remove(),this._activeAnimation=n(this._activeAnimation)}forEachManipulator(t){t(this._ringManipulator,4)}_createManipulator(){const t=this._createRingManipulator();this._ringManipulator=t,this.tool.manipulators.add(t);const e=this.tool.object,a=lt(t,(t,a,i)=>{this._scaleRotateDragData=null;const n=this.adapter.startInteraction(),l={mode:"none",origin:A(t.renderLocation),initialAngle:this.adapter.angle,angle:0,angleDir:0,scaleDir:0};this._scaleRotateDragData=l,this._updateDragState();const c=T.get();this.tool.view.renderCoordsHelper.worldUpAtPosition(t.renderLocation,c),a.next(C(this.tool.view,I(t.renderLocation,c,F()))).next(t=>{const a=k(t.plane),i=U(t.renderStart,t.renderEnd,l.origin,a),c=o.shortestSignedDiff(l.angle,i);l.angleDir=r(l.angleDir+c,-.3,$),l.angle=i;const d=ht(l,t),h=d-this.adapter.scale;if(l.scaleDir=r(l.scaleDir+h,-.2,tt),this._onScaleChanged(),"none"===l.mode){const a=this.mode||ut(t,t.plane,l.origin,this.tool.view.state.camera);if(null!=a){switch(a){case"rotate":this.tool.events.emit("rotate-start",{object:e,angle:0}),this.tool.events.emit("record-undo",{updates:[this.adapter.createUndoRecord()]});break;case"scale":this.tool.events.emit("scale-start",{object:e,xScale:1,yScale:1}),this.tool.events.emit("record-undo",{updates:[this.adapter.createUndoRecord()]})}l.mode=a}}switch(l.mode){case"rotate":n.state.angle=l.initialAngle+i;break;case"scale":n.state.scale=d,this._onScaleChanged()}switch(this._updateDragState(),this._updateManipulatorTransform(),t.action){case"start":case"update":switch(l.mode){case"rotate":this.tool.events.emit("rotate",{object:e,angle:s(l.angle)});break;case"scale":this.tool.events.emit("scale",{object:e,xScale:d,yScale:d})}break;case"end":switch(l.mode){case"rotate":this.tool.events.emit("rotate-stop",{object:e,angle:s(l.angle)});break;case"scale":this.tool.events.emit("scale-stop",{object:e,xScale:d,yScale:d})}}return"end"===t.action&&(this.startAnimation(gt(this,()=>this._onScaleChanged())),this._scaleRotateDragData=null,this._updateDragState(),n.done()),t}),i.next(()=>{if(n.cancel(),null!=this._scaleRotateDragData){switch(this._scaleRotateDragData.mode){case"none":break;case"rotate":this.tool.events.emit("rotate-stop",{object:e,angle:0});break;case"scale":this.tool.events.emit("scale-stop",{object:e,xScale:1,yScale:1})}this.startAnimation(gt(this,()=>this._onScaleChanged())),this._scaleRotateDragData=null,this._updateDragState()}})});this.addHandles([a,t.events.on("focus-changed",t=>{"focus"===t.action?this.startAnimation(mt(this,()=>this._updateDelayedFocusedState(),{delayMs:this._ringIndicatorDelayMs})):this._updateDelayedFocusedState()}),t.events.on("immediate-click",t=>{t.stopPropagation()}),l(()=>this.tool.object.visible,t=>this._ringManipulator.available=t,c)])}_onScaleChanged(){this.events.emit("scale-changed"),this._updateManipulatorTransform()}_updateDelayedFocusedState(){this._ringManipulator.updateStateEnabled(ct.DelayedFocused,this.getFocused())}_updateDragState(){if(this._ringManipulator.updateStateEnabled(ct.Unlocked,!(null!=this._scaleRotateDragData&&"none"!==this._scaleRotateDragData?.mode)),null!=this._scaleRotateDragData)switch(this._scaleRotateDragData.mode){case"rotate":this._ringManipulator.updateStateEnabled(ct.ScaleIn|ct.ScaleOut,!1),this._ringManipulator.updateStateEnabled(ct.RotateLeft,this._scaleRotateDragData.angleDir<0),this._ringManipulator.updateStateEnabled(ct.RotateRight,this._scaleRotateDragData.angleDir>=0);break;case"scale":this._ringManipulator.updateStateEnabled(ct.RotateLeft|ct.RotateRight,!1),this._ringManipulator.updateStateEnabled(ct.ScaleIn,this._scaleRotateDragData.scaleDir<0),this._ringManipulator.updateStateEnabled(ct.ScaleOut,this._scaleRotateDragData.scaleDir>=0)}else this._ringManipulator.updateStateEnabled(ct.ScaleIn|ct.ScaleOut|ct.RotateLeft|ct.RotateRight,!1)}_updateManipulatorTransform(){const t=g(P.get(),this.adapter.angle,w(0,0,1));if(null==t)return;const e=this.getScale(),a=m(P.get(),v(T.get(),e,e,e));this._ringManipulator.modelTransform=f(P.get(),a,t)}_createRingManipulator(){const t=(t,e,a)=>{const o=[],i=Math.ceil(X*(e-t)/(2*Math.PI));for(let r=0;r<i+1;r++){const s=t+r*(e-t)/i;o.push(w(a*Math.cos(s),a*Math.sin(s),0))}return o},e=e=>t(0,2*Math.PI,e),a=t=>[[-t/2,0],[t/2,0],[t/2,et/2],[-t/2,et/2]],o=this._createMaterial(1),i=(t,e,i=o)=>st(i,a(e),t,[],[],!1),r=e(q),s=i(r,G),n={left:new Array,right:new Array},l=[];for(let w=0;w<2;w++){const e=w*Math.PI-Math.PI/4,a=Math.PI/2-Y,r=e+a,s=e+Math.PI/2-a,c=t(r,s,B),d=i(c,W);l.push(c),l.push(t(r,s,J-G/2)),n.left.push(d),n.right.push(d.instantiate());for(let t=0;t<2;t++){const e=0===t,a=M();if(e){_(a,a,[1,-1,1]),D(a,a,-r,[0,0,1]);const t=Math.round(z*(c.length-1));a[12]=c[t][0],a[13]=c[t][1],a[14]=c[t][2]}else{D(a,a,s,[0,0,1]);const t=Math.round((1-z)*(c.length-1));a[12]=c[t][0],a[13]=c[t][1],a[14]=c[t][2]}const i=it(o,N,0,K,et);rt(i,a),(e?n.left:n.right).push(i)}}const c=[];for(let _=0;_<2;_++){const e=_*Math.PI-Math.PI/4,a=Math.PI/2-Z,o=e+a,r=e+Math.PI/2-a,s=t(o,r,J);c.push(i(s,W))}const d=this._createMaterial(.66),h=this._createMaterial(.5),u=this._createMaterial(.33),p=e(q+Q),g=e(q+V),m=i(p,W,d),f=i(g,W,u),v=e(q-Q),S=e(q-V),b=i(v,W,d),y=i(S,W,u);let j=[new L(s,ct.DelayedFocused),new L(s.instantiate({material:h}),0)];this.mode&&"scale"!==this.mode||(j=j.concat([...c.map(t=>new L(t,ct.DelayedFocused|ct.Unlocked)),new L(m,ct.DelayedFocused|ct.ScaleIn),new L(f,ct.DelayedFocused|ct.ScaleIn),new L(b,ct.DelayedFocused|ct.ScaleOut),new L(y,ct.DelayedFocused|ct.ScaleOut)])),this.mode&&"rotate"!==this.mode||(j=j.concat([...n.right.map(t=>new L(t.instantiate(),ct.DelayedFocused|ct.Unlocked)),...n.left.map(t=>new L(t,ct.DelayedFocused|ct.RotateLeft)),...n.right.map(t=>new L(t,ct.DelayedFocused|ct.RotateRight))]));const R=[r,...l];return new x({view:this.tool.view,renderObjects:j,autoScaleRenderObjects:!1,worldOriented:!0,radius:G,focusMultiplier:1,touchMultiplier:1.5,elevationInfo:this.tool.object.elevationInfo,collisionType:{type:"ribbon",paths:R,direction:w(0,0,1)}})}_createMaterial(t){const e=new nt({cullFace:2,renderOccluded:2,isDecoration:!0});return this.addHandles(l(()=>a(this.tool.view.effectiveTheme.accentColor,t),t=>e.setParameters({color:t}),c)),e}get test(){}};function ht(t,e){const a=S(T.get(),e.renderStart,t.origin),o=S(T.get(),e.renderEnd,t.origin),i=b(a),r=b(o);return 0===i?0:r/i}function ut(t,e,a,o){const{renderStart:i,renderEnd:r}=t,s=pt(i,o,T.get()),n=pt(r,o,T.get());if(y(s,n)<at*at)return null;const l=S(T.get(),i,a),c=j(T.get(),l,k(e)),d=i,h=R(T.get(),d,c),u=pt(a,o,T.get()),p=s,g=pt(h,o,T.get()),m=S(T.get(),g,p),f=S(T.get(),s,u),_=E(p,m),D=E(u,f);return O(_,n)<O(D,n)?"rotate":"scale"}function pt(t,e,a){return e.projectToScreen(t,ft),v(a,ft[0],ft[1],0)}function gt(t,e){let a=null,o=1;const i=()=>o;return{start:()=>{o=t.getScale(),a=t.getScale,t.getScale=i,e()},update:t=>(o+=((o+1)/2-o)*Math.min(t*ot,1),e(),Math.abs(o-1)<.01?1:0),destroy:()=>{a&&(t.getScale=a),e()}}}function mt(t,e,a){let o=0,i=null;const r=()=>!1;return{start:()=>{i=t.getFocused,t.getFocused=r,o=0,e()},update:t=>(o+=t,!i?.()||o>=a.delayMs?1:0),destroy:()=>{i&&(t.getFocused=i),e()}}}t([u({constructOnly:!0})],dt.prototype,"tool",void 0),t([u({constructOnly:!0})],dt.prototype,"adapter",void 0),t([u({constructOnly:!0})],dt.prototype,"sketchOptions",void 0),t([u()],dt.prototype,"mode",void 0),t([u()],dt.prototype,"_activeAnimation",void 0),t([u()],dt.prototype,"updating",null),dt=t([p("esri.views.3d.interactive.editingTools.transform.ScaleRotateTransform")],dt);const ft=h();export{dt as ScaleRotateTransform};