UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

3 lines (2 loc) • 18.6 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{__decorate as e}from"tslib";import t from"../../../Camera.js";import i from"../../../Viewpoint.js";import r from"../../../core/Accessor.js";import a from"../../../core/Logger.js";import{destroyMaybe as s}from"../../../core/maybe.js";import{on as n,watch as o,sync as h,when as l}from"../../../core/reactiveUtils.js";import{addFrameTask as c}from"../../../core/scheduling.js";import{createScreenPoint as p}from"../../../core/screenUtils.js";import{Milliseconds as m}from"../../../core/time.js";import{property as d,subclass as v}from"../../../core/accessorSupport/decorators.js";import{runUntracked as u}from"../../../core/accessorSupport/tracking.js";import{squaredDistance as w}from"../../../core/libs/gl-matrix-2/math/vec3.js";import{fromArray as g}from"../../../core/libs/gl-matrix-2/factories/vec3f64.js";import{set as _}from"../../../core/libs/gl-matrix-2/math/vec4.js";import{create as y}from"../../../core/libs/gl-matrix-2/factories/vec4f64.js";import f from"../../../geometry/Extent.js";import C from"../../../geometry/Point.js";import x from"../../../geometry/Polygon.js";import{isLoadedOrLoadFor as R,requiresLoad as P}from"../../../geometry/projectionUtils.js";import{fromRenderCamera as S,toRenderCamera as O}from"../webgl.js";import{applyAll as b}from"../camera/constraintUtils.js";import{cameraOnContentAlongViewDirection as T,surfaceElevationBelowRenderLocation as j}from"../camera/intersectionUtils.js";import{ConstraintsManager as z}from"./ConstraintsManager.js";import{Frustum as M}from"./Frustum.js";import{GoToOperation as I}from"./GoToOperation.js";import{SurfaceCollisionCorrectionController as H}from"./controllers/SurfaceCollisionCorrectionController.js";import{toArea as E,toExtent as V,applyTiltAdjustToScale as B,scaleToZoom as L,fromExtentSync as A,getObserverForPointAtDistanceSync as U,viewScaleToCameraDistance as F,zoomToScale as D}from"../support/cameraUtils.js";import{fromCamera as k,toCameraSync as N}from"../support/viewpointUtils.js";import G from"../webgl/RenderCamera.js";import{PropertiesPool as q}from"../../support/PropertiesPool.js";import{ensureAttachmentMaxSize as W}from"../../webgl/FramebufferObject.js";let Z=class extends r{constructor(e){super(e),this.ready=!1,this._windowDevicePixelRatio=1,this._devicePixelRatioOverride=null,this._idleTimeout=re,this.test={viewStateManager:this,contentCameraResetState:new Map,setDevicePixelRatio:e=>this._devicePixelRatioOverride=e,getDevicePixelRatioOverride:()=>this._devicePixelRatioOverride,renderState:null,get maximumPixelRatio(){return this.viewStateManager.view.qualitySettings.maximumPixelRatio},get updatingIgnoreRenderState(){return null!=this.renderState},get idleTimeoutEnabled(){return this.viewStateManager._idleTimeout>0},set idleTimeoutEnabled(e){this.viewStateManager._idleTimeout=e?re:0}},this._propertiesPool=new q({frustum:()=>new M(null)},this),this._cameraSetByUser=!1,this._gotoOperation=null,this._cameraChangeTime=0,this._tmpCanvasSize=new J}initialize(){this._cameraChangeTime=performance.now(),this.addHandles([n(()=>this.view.state.events,"before-camera-change",({camera:e})=>e&&this._updateElevation(e)),o(()=>this.view.state?.camera,(e,t)=>this._cameraChangedHandler(e,t),h)]),l(()=>this.view.state?.camera,e=>this._updateElevation(e),{once:!0,sync:!0}),this.addHandles([c({prepare:e=>this._prepareFrame(e.time)}),o(()=>this.view.state.cameraController,()=>{this._cameraSetByUser=!0,this.removeHandles(te)}),n(()=>this.view.state.events,"camera-projection-changed",()=>this.notifyChange("scale"))])}destroy(){this.exit(),this._propertiesPool=s(this._propertiesPool)}get camera(){const e=this._get("camera");if(!this.ready)return e;const{view:t}=this,i=t.state.camera;return u(()=>{const r=S(t,i,Y);return r&&e&&r.equals(e)?e:r.clone()})}set camera(e){if(this._updatePropertyBeforeReady("camera",e))return;this.view.elevationProvider.enableCache(!0);const t=O(this.view,e);t?this.setStateCamera(t,{applyConstraints:!1})||a.getLogger(this).warnOnce("#camera=","There is a currently active camera controller that has priority."):a.getLogger(this).error("#camera=","Invalid camera",e),this.view.elevationProvider.enableCache(!1)}get contentCamera(){const e=this._get("contentCamera");if(!this.ready)return e;const{view:t}=this,i=t.state.contentCamera;return u(()=>{const r=S(t,i,Y);return r&&e&&r.equals(e)?e:r.clone()})}set contentCamera(e){if(this._updatePropertyBeforeReady("contentCamera",e))return;const t=O(this.view,e);this.view.state.contentCamera=null!=t?t:null}installContentCameraReset(e){if(this.removeHandles(ie),this.test.contentCameraResetState.clear(),!this.view.state.fixedContentCamera)return!1;const t=this.zoom,i=this.view.state.camera.distance**2,r=g(this.view.state.camera.center),a=e.sticky?this.contentCamera.clone():null;return this.addHandles([o(()=>this.contentCamera,()=>{e.sticky||(this.removeHandles(ie),this.test.contentCameraResetState.clear())}),o(()=>this.zoom,e=>{void 0!==e&&void 0!==t&&(this.test.contentCameraResetState.set("view.zoom",Math.abs(e-t)/2),Math.abs(e-t)>2?this.contentCamera=null:this.view.state.fixedContentCamera||(this.contentCamera=a))}),o(()=>this.view.state.camera,e=>{const t=w(r,e.center);this.test.contentCameraResetState.set("camera.center",t/i),t>i?this.contentCamera=null:this.view.state.fixedContentCamera||(this.contentCamera=a)})],ie),!0}get center(){return this.ready?this.view.pointsOfInterest.centerOnContent.location:this._get("center")}set center(e){this._updatePropertyBeforeReady("center",e)||(e?this.isCompatible(e)?this.setStateCamera(this._centerToCamera(e),{applyConstraints:!0})?this.view.pointsOfInterest.centerOnContent.runTask():a.getLogger(this).error("#center=","Invalid center",e):a.getLogger(this).error("#center=","Center has an incompatible spatial reference (center: "+(e.spatialReference?e.spatialReference.wkid:"none")+", view: "+this.view.spatialReference?.wkid+")",e):a.getLogger(this).error("#center=","Center may not be null or undefined"))}get visibleArea(){if(!this.ready){const e=this._get("extent");return e?x.fromExtent(e):null}return E(this.view,this.view.pointsOfInterest.focus.renderLocation)}get extent(){if(!this.ready)return this._get("extent");const e=this.view,t=V(e,e.state.camera,e.pointsOfInterest.centerOnContent.renderLocation);return null!=t?t:this._get("extent")}set extent(e){this._updatePropertyBeforeReady("extent",e)||(e?this.isCompatible(e)?this.setStateCamera(this._extentToCamera(e),{applyConstraints:!0})||a.getLogger(this).error("#extent=","Invalid extent",e):a.getLogger(this).error("#extent=","Extent has an incompatible spatial reference (extent: "+(e.spatialReference?e.spatialReference.wkid:"none")+", view: "+this.view.spatialReference?.wkid+")",e):a.getLogger(this).error("#extent=","Extent may not be null or undefined"))}get frustum(){const e=this._propertiesPool.get("frustum");return e.renderCoordsHelper=this.view.renderCoordsHelper,e.update(this.view.state.camera),e}get constraintsManager(){return this._constraintsManager}get _initialViewpoint(){const e=this.view.map;return e&&"initialViewProperties"in e?e.initialViewProperties?.viewpoint:void 0}get hasInitialView(){return!!this._initialViewpoint}get scale(){if(!this.ready)return this._get("scale");const e=this.view.basemapTerrain.tilingScheme,t=this.view.pointsOfInterest.cameraOnSurface.scale;return e&&t?B(this.view,t,this.view.state.contentCamera,e):this._get("scale")}set scale(e){this._updatePropertyBeforeReady("scale",e)||this.setStateCamera(this._scaleToCamera(e),{applyConstraints:!0})||a.getLogger(this).error("#scale=","Invalid scale",e)}get padding(){if(!this.ready)return this._get("padding");const e=this.view.state.camera,t=e.padding,i=e.pixelRatio,r=this._get("padding"),a=Math.round(t[0]/i),s=Math.round(t[1]/i),n=Math.round(t[2]/i),o=Math.round(t[3]/i);return null!=r&&r.top===a&&r.right===s&&r.bottom===n&&r.left===o?r:{top:a,right:s,bottom:n,left:o}}set padding(e){this._updatePropertyBeforeReady("padding",e)||(this._paddingToArray(e,this.view.state.camera.pixelRatio,ee),this.view.state.updateCamera(e=>e.padding=ee))}_paddingToArray(e,t,i){e?_(i,e.top||0,e.right||0,e.bottom||0,e.left||0):_(i,0,0,0,0);for(let r=0;r<4;r++)i[r]=Math.round(i[r]*t)}get screenCenter(){const e=this.padding;return p((this.view.width-(e.left+e.right))/2+e.left,(this.view.height-(e.top+e.bottom))/2+e.top)}get viewpoint(){return this.ready?k(this.view,this.camera):this._get("viewpoint")}set viewpoint(e){if(!this._updatePropertyBeforeReady("viewpoint",e))if(e){if(!this.isCompatible(e)){const t=null!=e.camera?e.camera.position:e.targetGeometry,i=null!=t&&t.spatialReference;return void a.getLogger(this).error("#viewpoint=","Viewpoint has an incompatible spatial reference (viewpoint: "+(i?i.wkid:"none")+", view: "+this.view.spatialReference?.wkid+")",e)}this.setStateCamera(this._viewpointToCamera(e),{applyConstraints:!e.camera})||a.getLogger(this).error("#viewpoint=","Invalid viewpoint",e)}else a.getLogger(this).error("#viewpoint=","Viewpoint may not be null or undefined")}get zoom(){return this.ready?L(this.view,this.scale):this._get("zoom")}set zoom(e){this._updatePropertyBeforeReady("zoom",e)||void 0===e||this.setStateCamera(this._zoomToCamera(e),{applyConstraints:!0})||a.getLogger(this).error("#zoom=","Invalid zoom",e)}_computeCanvasSize(){if(this._devicePixelRatioOverride)return this.view.state.contentPixelRatio=this._devicePixelRatioOverride,this._tmpCanvasSize.width=Math.round(this.view.surface.clientWidth*this._devicePixelRatioOverride),this._tmpCanvasSize.height=Math.round(this.view.surface.clientHeight*this._devicePixelRatioOverride),this._tmpCanvasSize.pixelRatio=this._devicePixelRatioOverride,this._tmpCanvasSize;const e=Math.min(this._windowDevicePixelRatio,this.view.qualitySettings.maximumPixelRatio),t=(this._usePhysicalPixelRendering?this._windowDevicePixelRatio:e)*this.view.resolutionScale;this._tmpCanvasSize.width=Math.round(this.view.surface.clientWidth*t),this._tmpCanvasSize.height=Math.round(this.view.surface.clientHeight*t);const i=this.view.stage.renderView.renderingContext?.parameters.maxTextureSize;return i&&W(this._tmpCanvasSize,i),this._tmpCanvasSize.pixelRatio=this._tmpCanvasSize.width>0?this._tmpCanvasSize.width/this.view.surface.clientWidth*.5+this._tmpCanvasSize.height/this.view.surface.clientHeight*.5:t,this.view.state&&(this.view.state.contentPixelRatio=Math.min(this._windowDevicePixelRatio,this.view.qualitySettings.maximumPixelRatio)),this._tmpCanvasSize}get _rasterPixelRatio(){return null!=this._devicePixelRatioOverride?this._devicePixelRatioOverride:this._usePhysicalPixelRenderingAny?this._windowDevicePixelRatio:Math.min(this._windowDevicePixelRatio,this.view.qualitySettings.maximumPixelRatio)}get _usePhysicalPixelRendering(){return this.view?.stage?.renderer.isFeatureEnabled(9)??!1}get _usePhysicalPixelRenderingAny(){const e=this.view?.stage?.renderer;return e&&(e.isFeatureEnabled(9,2)||e.isFeatureEnabled(9,1)||e.isFeatureEnabled(9,0))}preinit(e){return!(this._isOverridden("center")&&!R(this.center.spatialReference,e))&&(!(this._isOverridden("camera")&&!R(this.camera.position.spatialReference,e))&&(!(this._isOverridden("extent")&&!R(this.extent.spatialReference,e))&&!!(!this._isOverridden("viewpoint")||R(this.viewpoint.targetGeometry?.spatialReference,e)&&R(this.viewpoint.camera?.position?.spatialReference,e))))}init(){this._constraintsManager=new z({view:this.view}),this._prepareFrame(m(0));const e=this._getInitialProperties();this._cameraSetByUser=!1,this._set("ready",!0);for(const t of e)this.set(t.name,t.value);if(!this._cameraSetByUser){const e=this._initialViewpoint||this.view.initialExtent;e&&this.isCompatible(e)?this._setInitialView(e):2===this.view.state.viewingMode&&this.addHandles(l(()=>this.view.groundView.ready,()=>{this.removeHandles(te),this._setInitialView(this.view.dataExtent)},{once:!0,initial:!0}),te)}}exit(){this._cancelGoToOperation(),this.ready&&(this._override("padding",this.padding),this._set("ready",!1),this._clearOverride("hasInitialView"),this._cameraSetByUser=!1,this.removeHandles(te),this._constraintsManager=s(this._constraintsManager))}async goTo(e,t){return t={animate:this.view.state.animationsEnabled,...t},null!=this._gotoOperation&&this._gotoOperation.abort(t.animate),this._gotoOperation=new I(e,t,this.view),this.view.resourceController.scheduler.stopFrame(),this._gotoOperation.promise}debugSetCameraOnContent(){this.setStateCamera(T(this.view),{applyConstraints:!1})}step(e){const t=this.view.state?.cameraController;t?.stepController&&this.view.state.updateCamera(i=>t.stepController(e,i))}_cancelGoToOperation(){null!=this._gotoOperation&&(this._gotoOperation.abort(),this._gotoOperation=null)}_getInitialProperties(){const e=new Set,t=[];for(const{propertyName:i,overrides:r}of Q){const a=e.has(i),s=this._isOverridden(i);!a&&s&&t.push({name:i,value:this._get(i)}),this._clearOverride(i),(a||s)&&r.forEach(t=>e.add(t))}return t}_setInitialView(e){if(null==e||this._cameraSetByUser)return;if(e instanceof t)return void this.setStateCamera(O(this.view,e),{applyConstraints:!1});if(e instanceof i){if(e.targetGeometry instanceof f){const t=A(this.view,e.targetGeometry,0,.5,0);return void(null!=t&&this.setStateCamera(O(this.view,t),{applyConstraints:!0}))}const t={applyConstraints:!e.camera},i=this._viewpointToCamera(e);return void this.setStateCamera(i,t)}const r=A(this.view,e,0,.5,0);null!=r&&this.setStateCamera(O(this.view,r),{applyConstraints:!0})}_updatePropertyBeforeReady(e,t){return!this.ready&&(this._override(e,t),t&&K.has(e)&&this._override("hasInitialView",!0),!0)}isCompatible(e){return null!=e&&(e instanceof i?e.camera?this.isCompatible(e.camera):this.isCompatible(e.targetGeometry):e instanceof t?this.isCompatible(e.position):e.spatialReference&&!P(e.spatialReference,this.view.spatialReference))}_getPreservingHeadingTilt(e=X){return this._cameraSetByUser?(e.heading=this.camera.heading,e.tilt=this.camera.tilt):(e.heading=0,e.tilt=.5),e}_centerPointAtDistanceToCamera(e,t,i=$){const{heading:r,tilt:a}=this._getPreservingHeadingTilt(),s=U(this.view,r,a,e,t,1);return null==s?null:(i.copyFrom(this.view.state.camera),i.eye=s.eye,i.center=s.center,i.up=s.up,i)}_centerToCamera(e){let t;if(e.hasZ)t=this.view.state.camera.distance;else{const{centerOnContent:e}=this.view.pointsOfInterest;e.runTask(),t=e.distance}return this._centerPointAtDistanceToCamera(e,t)}_extentToCamera(e){const{heading:t,tilt:i}=this._getPreservingHeadingTilt(),r=A(this.view,e,t,i,1,Y);return r?O(this.view,r):null}_scaleToCamera(e){if(null==e)return null;const t=this.view,i=t.pointsOfInterest.centerOnContent;i.runTask();const r=i.renderLocation,a=t.pointsOfInterest.cameraOnSurface.renderLocation,s=F(t,e,r,a);return this._centerPointAtDistanceToCamera(r,s)}_zoomToCamera(e){return this._scaleToCamera(D(this.view,e))}_viewpointToCamera(e){return O(this.view,N(this.view,e))}setStateCamera(e,t){return!(null==e||!this.view.state.stopActiveCameraController())&&(this._cameraSetByUser=!0,t.doNotCancelGoToOperation||this._cancelGoToOperation(),this.view.state.updateCamera(i=>{t.positionAndOrientationOnly?(i.eye=e.eye,i.center=e.center,i.up=e.up,i.fov=e.fov):i.copyFrom(e),t.applyConstraints&&b(this.view,i)}),t.applyConstraints||(this.view.state.cameraController=new H({view:this.view,desiredCamera:e})),!0)}_prepareFrame(e){const{surface:t,canvas:i,stage:r}=this.view;if(!t||!i||!r||r.destroyed||r.destroying)return;this._windowDevicePixelRatio=window.devicePixelRatio;const a=this._computeCanvasSize();if(0!==a.width&&0!==a.height&&(i.width===a.width&&i.height===a.height||(i.width=a.width,i.height=a.height),this.view.state)){const t=this.view.state.camera;t.fullWidth===a.width&&t.fullHeight===a.height&&t.pixelRatio===a.pixelRatio||($.copyFrom(t),$.pixelRatio!==a.pixelRatio&&(this._paddingToArray(this.padding,a.pixelRatio,ee),$.padding=ee),$.fullWidth=a.width,$.fullHeight=a.height,$.pixelRatio=a.pixelRatio,this.view.state.camera=$),this._updateState(),this.view.state.occludedFragmentOpacity?.update(this.view,this.view.state.mode,e)}}_updateElevation(e){const t=this.view.renderCoordsHelper?.getAltitude(e.eye)??0,i=this.view.basemapTerrain?.spatialReference,r=i?j(this.view,e.eye):0;e.relativeElevation=t-r}_updateState(){null!=this.test.renderState?this.view.state.mode=this.test.renderState:this.view.animation?this.view.state.mode=0:this.view.interacting?this.view.state.mode=1:(0===this.view.state.mode&&(this._cameraChangeTime=0),performance.now()-this._cameraChangeTime<this._idleTimeout?this.view.state.mode=1:this.view.state.mode=2),this.view.state.rasterPixelRatio=this._rasterPixelRatio}_cameraChangedHandler(e,t){e&&t&&e.almostEquals(t)||(this._cameraChangeTime=performance.now(),this._updateState())}};e([d({type:t})],Z.prototype,"camera",null),e([d({type:t})],Z.prototype,"contentCamera",null),e([d({type:C})],Z.prototype,"center",null),e([d()],Z.prototype,"visibleArea",null),e([d({type:f})],Z.prototype,"extent",null),e([d({readOnly:!0})],Z.prototype,"frustum",null),e([d()],Z.prototype,"_constraintsManager",void 0),e([d({readOnly:!0})],Z.prototype,"constraintsManager",null),e([d()],Z.prototype,"_initialViewpoint",null),e([d({readOnly:!0})],Z.prototype,"hasInitialView",null),e([d({readOnly:!0,type:Boolean})],Z.prototype,"ready",void 0),e([d({type:Number})],Z.prototype,"scale",null),e([d()],Z.prototype,"padding",null),e([d({readOnly:!0})],Z.prototype,"screenCenter",null),e([d({constructOnly:!0})],Z.prototype,"view",void 0),e([d({type:i})],Z.prototype,"viewpoint",null),e([d({type:Number})],Z.prototype,"zoom",null),e([d({readOnly:!0})],Z.prototype,"_rasterPixelRatio",null),e([d({readOnly:!0})],Z.prototype,"_usePhysicalPixelRendering",null),e([d({readOnly:!0})],Z.prototype,"_usePhysicalPixelRenderingAny",null),e([d()],Z.prototype,"_windowDevicePixelRatio",void 0),e([d()],Z.prototype,"_devicePixelRatioOverride",void 0),Z=e([v("esri.views.3d.state.ViewStateManager")],Z);class J{constructor(){this.width=0,this.height=0,this.pixelRatio=1}}const K=new Set(["camera","viewpoint","extent","scale","center","zoom"]),Q=[{propertyName:"camera",overrides:["viewpoint"]},{propertyName:"viewpoint",overrides:["extent"]},{propertyName:"extent",overrides:["center","scale"]},{propertyName:"center",overrides:[]},{propertyName:"scale",overrides:["zoom"]},{propertyName:"zoom",overrides:[]},{propertyName:"padding",overrides:[]}],X={heading:0,tilt:0};let Y=new t,$=new G;const ee=y(),te="pending-initial-view",ie="content-camera-reset",re=300,ae=100;function se(){Y=new t,$=new G}export{Z as ViewStateManager,se as cleanupViewStateManager,ae as interactingTimeout};