cesium.js 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/view/document extends a view interface up to the browser document. When vwf/view/document
  15. /// is active, scripts on the main page may make (reflected) kernel calls:
  16. ///
  17. /// window.vwf_view.createNode( nodeID, childID, childExtendsID, childImplementsIDs,
  18. /// childSource, childType, childName, function( childID ) {
  19. /// ...
  20. /// } );
  21. ///
  22. /// And receive view calls:
  23. ///
  24. /// window.vwf_view.createdNode = function( nodeID, childID, childExtendsID, childImplementsIDs,
  25. /// childSource, childType, childName, callback /- ( ready ) -/ ) {
  26. /// ...
  27. /// }
  28. ///
  29. /// @module vwf/view/cesium
  30. /// @requires vwf/view
  31. define( [ "module", "vwf/view", "vwf/utility", "vwf/model/cesium/Cesium", "jquery" ], function( module, view, utility, Cesium, jQuery ) {
  32. return view.load( module, {
  33. // == Module Definition ====================================================================
  34. initialize: function( options ) {
  35. if ( !this.state ) {
  36. this.state = {};
  37. }
  38. if ( !this.state.scenes ) {
  39. this.state.scenes = {};
  40. }
  41. if ( !this.state.nodes ) {
  42. this.state.nodes = {};
  43. }
  44. if ( options === undefined ) { options = {}; }
  45. // html creation options
  46. this.parentDiv = options.parentDiv || 'body';
  47. this.parentClass = options.parentClass || 'cesium-main-div';
  48. this.containerClass = options.containerClass || 'fullSize';
  49. this.container = options.container || { "create": true, "divName": "cesiumContainer" } ;
  50. // Context and WebGL creation properties corresponding to options passed to Scene.
  51. this.canvasOptions = options.canvasOptions;
  52. this.invertMouse = options.invertMouse || {};
  53. this.cesiumType = options.cesium || 'widget'; // 'widget', 'viewer', manual - anything else
  54. // CesiumWidget options, will accept all defaults
  55. this.cesiumTypeOptions = options.widget || {
  56. //"clock": false,
  57. //"imageryProvider": 'OpenStreetMapImageryProvider',
  58. //"terrainProvider": 'CesiumTerrainProvider',
  59. //"skyBox": {},
  60. "sceneMode": Cesium.SceneMode.SCENE3D,
  61. "scene3DOnly": false,
  62. "orderIndependentTranslucency": true,
  63. //"mapProjection": GeographicProjection || WebMercatorProjection
  64. "useDefaultRenderLoop": true,
  65. //"targetFrameRate": '?',
  66. "showRenderLoopErrors": true,
  67. //"contextOptions": {}, // Canvas options
  68. //"creditContainer": undefined, // DOM element or ID of where the credits go
  69. };
  70. this.height = 600;
  71. this.width = 800;
  72. if ( window ) {
  73. if ( window.innerHeight ) this.height = window.innerHeight - 20;
  74. if ( window.innerWidth ) this.width = window.innerWidth - 20;
  75. this.window = window;
  76. }
  77. this.state.clientControl = {
  78. event: undefined, // probably not needed but this will contain the
  79. controller: "", // this is the moniker of the
  80. locked: false
  81. };
  82. },
  83. createdNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  84. childSource, childType, childIndex, childName, callback /* ( ready ) */ ) {
  85. if ( childExtendsID === undefined )
  86. return;
  87. //this.logger.infox( "createdNode", nodeID, childID, childExtendsID, childImplementsIDs, childSource, childType, childName );
  88. var createNode = function() {
  89. return {
  90. parentID: nodeID,
  91. ID: childID,
  92. extendsID: childExtendsID,
  93. implementsIDs: childImplementsIDs,
  94. source: childSource,
  95. type: childType,
  96. name: childName,
  97. loadComplete: callback
  98. };
  99. };
  100. var kernel = this.kernel;
  101. var protos = getPrototypes.call( this, childExtendsID )
  102. var node = undefined;
  103. if ( isCesiumDefinition.call( this, protos ) ) {
  104. if ( this.container.create ) {
  105. //var cesiumCont = "<div class='cesuim-container' id='" + this.container.divName + "'></div>";
  106. var cesiumCont = "<div class='"+ this.containerClass +"' id='" + this.container.divName + "'></div>";
  107. if ( this.parentDiv == 'body' ) {
  108. jQuery( this.parentDiv ).append( cesiumCont );
  109. } else {
  110. var outDiv;
  111. if ( this.parentClass !== undefined ) {
  112. outDiv = "<div id='"+this.parentDiv+"' class='"+this.parentClass+"'>"+cesiumCont+"</div>";
  113. } else {
  114. outDiv = "<div id='"+this.parentDiv+"'>"+cesiumCont+"</div>"
  115. }
  116. jQuery( 'body' ).append( outDiv );
  117. }
  118. }
  119. if ( this.state.scenes[ childID ] === undefined ) {
  120. this.state.scenes[ childID ] = node = createNode();
  121. } else {
  122. node = this.state.scenes[ childID ];
  123. }
  124. var view = this;
  125. var forceResizeDelay = 60;
  126. var scene, canvas;
  127. // options for oneToOne below
  128. //var cesiumOptions = { "contextOptions": { "alpha": true }, };
  129. var options = this.cesiumTypeOptions;
  130. switch ( this.cesiumType ) {
  131. case 'widget':
  132. options.clock && this.state.createClock( options );
  133. options.imageryProvider && this.state.createImageryProvider( options );
  134. options.terrainProvider && this.state.createTerrainProvider( options );
  135. options.skyBox && this.state.createSkyBox( options );
  136. options.sceneMode && this.state.setSceneMode( options );
  137. options.mapProjection && this.state.createMapProjection( options );
  138. node.cesiumWidget = new Cesium.CesiumWidget( this.container.divName, options );
  139. node.scene = scene = node.cesiumWidget.scene;
  140. node.globe = scene.globe;
  141. break;
  142. case 'viewer':
  143. node.cesiumViewer = new Cesium.Viewer( this.container.divName, this.cesiumTypeOptions );
  144. node.cesiumWidget = node.cesiumViewer.cesiumWidget;
  145. node.scene = scene = node.cesiumViewer.scene;
  146. node.globe = scene.globe;
  147. break;
  148. default:
  149. // the manual creation, has an error with the
  150. // camera syncronization
  151. canvas = document.createElement( 'canvas' );
  152. canvas.className = 'fullSize';
  153. document.getElementById( this.container.divName ).appendChild( canvas );
  154. canvas.setAttribute( 'height', this.height );
  155. canvas.setAttribute( 'width', this.width );
  156. node.scene = scene = new Cesium.Scene( canvas, cesiumOptions.contextOptions );
  157. var bing = new Cesium.BingMapsImageryProvider({
  158. url : 'http://dev.virtualearth.net',
  159. mapStyle : Cesium.BingMapsStyle.AERIAL,
  160. // Some versions of Safari support WebGL, but don't correctly implement
  161. // cross-origin image loading, so we need to load Bing imagery using a proxy.
  162. proxy : Cesium.FeatureDetection.supportsCrossOriginImagery() ? undefined : new Cesium.DefaultProxy('/proxy/')
  163. });
  164. var primitives = scene.getPrimitives();
  165. var ellipsoid = Cesium.Ellipsoid.WGS84;
  166. node.globe = new Cesium.Globe( ellipsoid );
  167. node.globe.getImageryLayers().addImageryProvider( bing );
  168. primitives.setGlobe( node.globe );
  169. node.transitioner = new Cesium.SceneTransitioner( scene, ellipsoid );
  170. break;
  171. }
  172. node.imageryProvider = 'bingAerial';
  173. node.canvas = scene._canvas;
  174. scene.vwfID = childID;
  175. initializeMouseEvents.call( this, scene, node );
  176. var camera = scene._camera;
  177. ( function tick() {
  178. if ( view.state.cameraInfo ) {
  179. if ( view.state.clientControl.controller == view.kernel.moniker() ) {
  180. var diffs = view.state.cameraInfo.diff( camera );
  181. if ( diffs !== undefined ){
  182. broadcastCameraViewData.call( view, diffs );
  183. }
  184. }
  185. } else {
  186. view.state.cameraInfo = {
  187. "initialized": false,
  188. "direction": undefined,
  189. "position": undefined,
  190. "up": undefined,
  191. "right": undefined,
  192. //"earthDistance": 0,
  193. "equals": function( v1, v2 ) {
  194. return ( ( Math.round( v1.x ) == Math.round( v2.x ) ) && ( Math.round( v1.y ) == Math.round( v2.y ) ) && ( Math.round( v1.z ) == Math.round( v2.z ) ) );
  195. },
  196. "diff": function( cam ) {
  197. var retObj = undefined;
  198. if ( this.initialized ) {
  199. if ( !Cesium.Cartesian3.equals( this.direction, cam.direction ) ){
  200. retObj = { "direction": [ cam.direction.x, cam.direction.y, cam.direction.z ] };
  201. }
  202. if ( !this.equals( this.position, cam.position ) ) {
  203. if ( retObj === undefined ) {
  204. retObj = { "position": [ cam.position.x, cam.position.y, cam.position.z ] };
  205. } else {
  206. retObj.position = [ cam.position.x, cam.position.y, cam.position.z ];
  207. }
  208. //var dist = Math.round( this.calcDistanceToOrigin( cam ) );
  209. //var tolerance = 2;
  210. //if ( dist <= this.earthDistance - tolerance || dist >= this.earthDistance + tolerance ) {
  211. // is there a way to fire an event from here?
  212. // console.info( "change in the distance to earth:" + this.earthDistance );
  213. //}
  214. //this.earthDistance = dist;
  215. }
  216. if ( !Cesium.Cartesian3.equals( this.up, cam.up ) ) {
  217. if ( retObj === undefined ) {
  218. retObj = { "up": [ cam.up.x, cam.up.y, cam.up.z ] };
  219. } else {
  220. retObj.up = [ cam.up.x, cam.up.y, cam.up.z ];
  221. }
  222. }
  223. if ( !Cesium.Cartesian3.equals( this.right, cam.right ) ) {
  224. if ( retObj === undefined ) {
  225. retObj = { "right": [ cam.right.x, cam.right.y, cam.right.z ] };
  226. } else {
  227. retObj.right = [ cam.right.x, cam.right.y, cam.right.z ];
  228. }
  229. }
  230. }
  231. return retObj;
  232. },
  233. // "calcDistanceToOrigin": function( obj ) {
  234. // if ( obj.position ){
  235. // var p = obj.position;
  236. // return Math.sqrt( ( p.x * p.x ) + ( p.y * p.y ) + ( p.z * p.z ) );
  237. // }
  238. // return undefined;
  239. // },
  240. "getCurrent": function( cam ) {
  241. this.direction = camera.direction.clone();
  242. this.position = camera.position.clone();
  243. this.up = camera.up.clone();
  244. this.right = camera.right.clone();
  245. },
  246. "isInitialized": function() {
  247. this.initialized = ( ( this.direction != undefined ) &&
  248. ( this.position != undefined ) &&
  249. ( this.up != undefined ) &&
  250. ( this.right != undefined ) );
  251. }
  252. };
  253. }
  254. if ( forceResizeDelay ) {
  255. forceResizeDelay--;
  256. if ( forceResizeDelay == 0 ) {
  257. node.cesiumWidget.resize();
  258. forceResizeDelay = undefined;
  259. view.state.cameraInfo.initialized = true;
  260. }
  261. }
  262. scene.initializeFrame();
  263. scene.render();
  264. Cesium.requestAnimationFrame( tick );
  265. if ( forceResizeDelay === undefined ) {
  266. view.state.cameraInfo.getCurrent( camera );
  267. }
  268. }());
  269. if ( !this.useCesiumWidget ) {
  270. var onResize = function () {
  271. var width = node.canvas.clientWidth;
  272. var height = node.canvas.clientHeight;
  273. if ( node.canvas.width === width && node.canvas.height === height ) {
  274. return;
  275. }
  276. node.canvas.width = width;
  277. node.canvas.height = height;
  278. camera.frustum.aspectRatio = width / height;
  279. };
  280. window.addEventListener( 'resize', onResize, false );
  281. onResize();
  282. //document.oncontextmenu = function() { return false; };
  283. }
  284. }
  285. },
  286. //deletedNode: function (nodeID) {
  287. //},
  288. //createdProperty: function (nodeID, propertyName, propertyValue) {
  289. //},
  290. //initializedProperty: function (nodeID, propertyName, propertyValue) {
  291. //},
  292. satProperty: function( nodeID, propertyName, propertyValue ) {
  293. switch ( propertyName ) {
  294. }
  295. },
  296. //gotProperty: function( nodeID, propertyName, propertyValue ) {
  297. //}
  298. } );
  299. function getPrototypes( extendsID ) {
  300. var prototypes = [];
  301. var id = extendsID;
  302. while ( id !== undefined ) {
  303. prototypes.push( id );
  304. id = this.kernel.prototype( id );
  305. }
  306. return prototypes;
  307. }
  308. function isCesiumDefinition( prototypes ) {
  309. var foundCesium = false;
  310. if ( prototypes ) {
  311. var len = prototypes.length;
  312. for ( var i = 0; i < len && !foundCesium; i++ ) {
  313. foundCesium = ( prototypes[i] == "http://vwf.example.com/cesium.vwf" );
  314. }
  315. }
  316. return foundCesium;
  317. }
  318. function isSunDefinition( prototypes ) {
  319. var foundCesium = false;
  320. if ( prototypes ) {
  321. var len = prototypes.length;
  322. for ( var i = 0; i < len && !foundCesium; i++ ) {
  323. foundCesium = ( prototypes[i] == "http://vwf.example.com/cesium/sun.vwf" );
  324. }
  325. }
  326. return foundCesium;
  327. }
  328. function isAtmosphereDefinition( prototypes ) {
  329. var foundCesium = false;
  330. if ( prototypes ) {
  331. var len = prototypes.length;
  332. for ( var i = 0; i < len && !foundCesium; i++ ) {
  333. foundCesium = ( prototypes[i] == "http://vwf.example.com/cesium/atmosphere.vwf" );
  334. }
  335. }
  336. return foundCesium;
  337. }
  338. function isSkyBoxDefinition( prototypes ) {
  339. var foundCesium = false;
  340. if ( prototypes ) {
  341. var len = prototypes.length;
  342. for ( var i = 0; i < len && !foundCesium; i++ ) {
  343. foundCesium = ( prototypes[i] == "http://vwf.example.com/cesium/skybox.vwf" );
  344. }
  345. }
  346. return foundCesium;
  347. }
  348. function broadcastCameraViewData(cameraData) {
  349. var nodeID, scene;
  350. if ( this.kernel.find( "", "//" ).length > 0 ) {
  351. nodeID = this.kernel.find( "", "//" )[ 0 ];
  352. this.kernel.setProperty( nodeID, "cameraViewData", cameraData );
  353. }
  354. }
  355. function initializeMouseEvents( scene, node ) {
  356. this.state.mouse = {
  357. "enabled": true,
  358. "handler": undefined,
  359. "leftDown": false,
  360. "leftDownID": undefined,
  361. "middleDown": false ,
  362. "middleDownID": undefined,
  363. "rightDown": false,
  364. "rightDownID": undefined,
  365. "pinching": false,
  366. "zooming": false,
  367. "scene": scene,
  368. "lastPosition": [ -1, -1 ],
  369. "initialDown": undefined,
  370. "controlState": undefined,
  371. "enable": function( value ) {
  372. if ( value != this.enabled ) {
  373. if ( value ) {
  374. this.restoreControlState();
  375. } else {
  376. this.captureControlState();
  377. this.setControlState( false );
  378. }
  379. this.enabled = value;
  380. }
  381. },
  382. "active": function() {
  383. return this.leftDown || this.middleDown || this.rightDown || this.zooming || this.pinching;
  384. },
  385. "buttonDown": function() {
  386. if ( this.leftDown ) {
  387. return "left";
  388. } else if ( this.rightDown ) {
  389. return "right";
  390. } else if ( this.middleDown ) {
  391. return "middle";
  392. }
  393. return undefined;
  394. },
  395. "setControlState": function( value ) {
  396. if ( this.handler ) {
  397. this.handler.enableLook = value;
  398. this.handler.enableRotate = value;
  399. this.handler.enableTilt = value;
  400. this.handler.enableTranslate = value;
  401. this.handler.enableZoom = value;
  402. }
  403. this.controlState = undefined;
  404. },
  405. "captureControlState": function() {
  406. this.controlState = {
  407. "look": this.handler.enableLook,
  408. "rotate": this.handler.enableRotate,
  409. "tilt": this.handler.enableTilt,
  410. "translate": this.handler.enableTranslate,
  411. "zoom": this.handler.enableZoom
  412. };
  413. },
  414. "restoreControlState": function() {
  415. if ( this.controlState ) {
  416. this.handler.enableLook = this.controlState.look;
  417. this.handler.enableRotate = this.controlState.rotate;
  418. this.handler.enableTilt = this.controlState.tilt;
  419. this.handler.enableTranslate = this.controlState.translate;
  420. this.handler.enableZoom = this.controlState.zoom;
  421. }
  422. this.controlState = undefined;
  423. }
  424. };
  425. var overID = undefined;
  426. var downID = undefined;
  427. var lastOverID = undefined;
  428. var sceneCanvas = scene._canvas;
  429. var rootID = this.kernel.find( "", "/" )[0];
  430. this.state.mouse.handler = new Cesium.ScreenSpaceEventHandler( sceneCanvas );
  431. if ( this.state.mouse.handler ) {
  432. var mouse = this.state.mouse.handler;
  433. var self = this;
  434. var getMousePosition = function( pos ) {
  435. var posRet = { "x": pos.x, "y": pos.y };
  436. if ( self.invertMouse.x !== undefined ) {
  437. posRet.x = sceneCanvas.width - posRet.x;
  438. }
  439. if ( self.invertMouse.y !== undefined ) {
  440. posRet.y = sceneCanvas.height - posRet.y;
  441. }
  442. return posRet;
  443. }
  444. var pick = function( button, clickCount, event, position ) {
  445. var pos = getMousePosition( position );
  446. var height = scene._canvas.height;
  447. var width = scene._canvas.width;
  448. var eventObj = self.state.mouse.scene.pick( pos );
  449. var ellipsoid = scene._globe._ellipsoid;
  450. var globePoint = scene._camera.pickEllipsoid( pos, ellipsoid );
  451. var camPos = scene._camera.position;
  452. var eventID;
  453. if ( eventObj ) {
  454. eventID = eventObj.vwfID;
  455. } else if ( globePoint !== undefined ) {
  456. eventID = self.kernel.find( rootID, "earth" )[0];
  457. } else {
  458. eventID = rootID;
  459. }
  460. var eData = {
  461. "eventData": [ {
  462. "button": button,
  463. "clicks": clickCount,
  464. "buttons": {
  465. "left": self.state.mouse.leftDown,
  466. "middle": self.state.mouse.middleDown,
  467. "right": self.state.mouse.rightDown
  468. },
  469. "modifiers": {
  470. "alt": false,
  471. "ctrl": false,
  472. "shift": false,
  473. "meta": false
  474. },
  475. "position": [ pos.x / width, pos.y / height ],
  476. "screenPosition": [ pos.x, pos.y ]
  477. } ],
  478. "eventNodeData": { "": [ {
  479. "distance": undefined,
  480. "origin": [ camPos.x, camPos.y, camPos.z ],
  481. "id": eventID,
  482. "globalPosition": globePoint ? [ globePoint.x, globePoint.y, globePoint.z ] : undefined,
  483. "globalNormal": undefined,
  484. "globalSource": [ camPos.x, camPos.y, camPos.z ],
  485. } ] },
  486. };
  487. if ( event == "down" ) {
  488. switch( button ) {
  489. case "left":
  490. self.state.mouse.leftDownID = eventID;
  491. break;
  492. case "middle":
  493. self.state.mouse.middleDownID = eventID;
  494. break;
  495. case "right":
  496. self.state.mouse.rightDownID = eventID;
  497. break;
  498. }
  499. downID = eventID;
  500. } else if ( ( event == "up" ) || ( event == "drag" ) ) {
  501. switch( button ) {
  502. case "left":
  503. if ( self.state.mouse.leftDownID !== undefined ) {
  504. eventID = self.state.mouse.leftDownID;
  505. }
  506. break;
  507. case "middle":
  508. if ( self.state.mouse.middleDownID !== undefined ) {
  509. eventID = self.state.mouse.middleDownID;
  510. }
  511. break;
  512. case "right":
  513. if ( self.state.mouse.rightDownID !== undefined ) {
  514. eventID = self.state.mouse.rightDownID;
  515. }
  516. break;
  517. }
  518. } else if ( event == "move" ) {
  519. overID = eventID;
  520. }
  521. if ( eventID && eventID != rootID ) {
  522. var id = eventID;
  523. while ( id && id != rootID ) {
  524. eData.eventNodeData[ id ] = [ {
  525. "distance": undefined,
  526. "origin": scene._camera.position,
  527. "globalPosition": globePoint ? [ globePoint.x, globePoint.y, globePoint.z ] : undefined,
  528. "globalNormal": undefined,
  529. "globalSource": scene._camera.position,
  530. } ];
  531. //id = undefined;
  532. if ( self.state.nodes[ id ] ) {
  533. id = self.state.nodes[ id ].parentID;
  534. } else {
  535. id = undefined;
  536. }
  537. }
  538. }
  539. return eData;
  540. }
  541. // left click
  542. mouse.setInputAction( function( movement ) {
  543. var eData = pick( "left", 1, "click", movement.position );
  544. self.kernel.dispatchEvent( downID, "pointerClick", eData.eventData, eData.eventNodeData );
  545. }, Cesium.ScreenSpaceEventType.LEFT_CLICK );
  546. // left double click
  547. mouse.setInputAction( function( movement ) {
  548. var eData = pick( "left", 2, "click", movement.position );
  549. self.kernel.dispatchEvent( downID, "pointerDoubleClick", eData.eventData, eData.eventNodeData );
  550. }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK );
  551. // left up
  552. mouse.setInputAction( function( movement ) {
  553. self.state.mouse.leftDown = false;
  554. var eData = pick( "left", 0, "up", movement.position );
  555. if ( downID !== undefined ) {
  556. self.kernel.dispatchEvent( downID, "pointerUp", eData.eventData, eData.eventNodeData );
  557. }
  558. self.kernel.setProperty( rootID, "clientControl", { event: 'left', controller: self.kernel.moniker(), locked: false } );
  559. self.state.mouse.leftDownID = undefined;
  560. }, Cesium.ScreenSpaceEventType.LEFT_UP );
  561. // left down
  562. mouse.setInputAction( function( movement ) {
  563. self.kernel.setProperty( rootID, "clientControl", { event: 'left', controller: self.kernel.moniker(), locked: true } );
  564. self.state.mouse.leftDown = true;
  565. var eData = pick( "left", 0, "down", movement.position );
  566. self.kernel.dispatchEvent( downID, "pointerDown", eData.eventData, eData.eventNodeData );
  567. }, Cesium.ScreenSpaceEventType.LEFT_DOWN );
  568. // mouse move
  569. mouse.setInputAction( function( movement ) {
  570. var bd = self.state.mouse.buttonDown();
  571. if ( bd ) {
  572. var eData = pick( bd, 0, "drag", movement.endPosition );
  573. self.kernel.dispatchEvent( downID, "pointerMove", eData.eventData, eData.eventNodeData );
  574. } else {
  575. var eData = pick( "", 0, "move", movement.endPosition );
  576. if ( lastOverID === undefined && overID !== undefined ) {
  577. self.kernel.dispatchEvent( overID, "pointerEnter", eData.eventData, eData.eventNodeData );
  578. lastOverID = overID;
  579. } else if ( overID ) {
  580. if ( overID !== lastOverID ) {
  581. self.kernel.dispatchEvent( lastOverID, "pointerLeave", eData.eventData, eData.eventNodeData );
  582. self.kernel.dispatchEvent( overID, "pointerEnter", eData.eventData, eData.eventNodeData );
  583. lastOverID = overID;
  584. } else {
  585. self.kernel.dispatchEvent( overID, "pointerOver", eData.eventData, eData.eventNodeData );
  586. }
  587. }
  588. }
  589. }, Cesium.ScreenSpaceEventType.MOUSE_MOVE );
  590. // middle click
  591. mouse.setInputAction( function( movement ) {
  592. var eData = pick( "middle", 1, "click", movement.position );
  593. self.kernel.dispatchEvent( downID, "pointerClick", eData.eventData, eData.eventNodeData );
  594. }, Cesium.ScreenSpaceEventType.MIDDLE_CLICK );
  595. // middle double click
  596. mouse.setInputAction( function( movement ) {
  597. var eData = pick( "middle", 2, "click", movement.position );
  598. self.kernel.dispatchEvent( downID, "pointerDoubleClick", eData.eventData, eData.eventNodeData );
  599. }, Cesium.ScreenSpaceEventType.MIDDLE_DOUBLE_CLICK );
  600. // middle up
  601. mouse.setInputAction( function( movement ) {
  602. self.state.mouse.middleDown = false;
  603. var eData = pick( "middle", 1, "up", movement.position );
  604. self.kernel.dispatchEvent( downID, "pointerUp", eData.eventData, eData.eventNodeData );
  605. self.state.mouse.middleDownID = undefined;
  606. self.kernel.setProperty( rootID, "clientControl", { event: 'middle', controller: self.kernel.moniker(), locked: false } );
  607. }, Cesium.ScreenSpaceEventType.MIDDLE_UP );
  608. // middle down
  609. mouse.setInputAction( function( movement ) {
  610. self.kernel.setProperty( rootID, "clientControl", { event: 'middle', controller: self.kernel.moniker(), locked: true } );
  611. self.state.mouse.middleDown = true;
  612. var eData = pick( "middle", 0, "down", movement.position );
  613. self.kernel.dispatchEvent( downID, "pointerDown", eData.eventData, eData.eventNodeData );
  614. }, Cesium.ScreenSpaceEventType.MIDDLE_DOWN );
  615. // right click
  616. mouse.setInputAction( function( movement ) {
  617. var eData = pick( "right", 1, "click", movement.position );
  618. self.kernel.dispatchEvent( downID, "pointerClick", eData.eventData, eData.eventNodeData );
  619. }, Cesium.ScreenSpaceEventType.RIGHT_CLICK );
  620. // right double click
  621. mouse.setInputAction( function( movement ) {
  622. var eData = pick( "right", 2, "click", movement.position );
  623. self.kernel.dispatchEvent( downID, "pointerDoubleClick", eData.eventData, eData.eventNodeData );
  624. }, Cesium.ScreenSpaceEventType.RIGHT_DOUBLE_CLICK );
  625. // right up
  626. mouse.setInputAction( function( movement ) {
  627. self.state.mouse.rightDown = false;
  628. var eData = pick( "right", 0, "up", movement.position );
  629. self.kernel.dispatchEvent( downID, "pointerUp", eData.eventData, eData.eventNodeData );
  630. self.state.mouse.rightDownID = undefined;
  631. self.kernel.setProperty( rootID, "clientControl", { event: 'right', controller: self.kernel.moniker(), locked: false } );
  632. }, Cesium.ScreenSpaceEventType.RIGHT_UP );
  633. // right down
  634. mouse.setInputAction( function( movement ) {
  635. self.kernel.setProperty( rootID, "clientControl", { event: 'right', controller: self.kernel.moniker(), locked: true } );
  636. self.state.mouse.rightDown = true;
  637. var eData = pick( "right", 0, "down", movement.position );
  638. self.kernel.dispatchEvent( downID, "pointerDown", eData.eventData, eData.eventNodeData );
  639. }, Cesium.ScreenSpaceEventType.RIGHT_DOWN );
  640. // pinch start
  641. mouse.setInputAction( function( movement ) {
  642. self.kernel.setProperty( rootID, "clientControl", { event: 'pinch', controller: self.kernel.moniker(), locked: true } );
  643. self.state.mouse.pinching = true;
  644. }, Cesium.ScreenSpaceEventType.PINCH_START );
  645. // pinch move
  646. mouse.setInputAction( function( movement ) {
  647. }, Cesium.ScreenSpaceEventType.PINCH_MOVE );
  648. // pinch end
  649. mouse.setInputAction( function( movement ) {
  650. self.state.mouse.pinching = false;
  651. self.kernel.setProperty( rootID, "clientControl", { event: 'pinch', controller: self.kernel.moniker(), locked: false } );
  652. }, Cesium.ScreenSpaceEventType.PINCH_END );
  653. // wheel
  654. mouse.setInputAction( function( movement ) {
  655. self.kernel.setProperty( rootID, "clientControl", { event: 'wheel', controller: self.kernel.moniker(), locked: false } );
  656. }, Cesium.ScreenSpaceEventType.WHEEL );
  657. }
  658. }
  659. } );