From 5da40cab853ec622a8c7b153bc8dcf653cbb1307 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 12 Jan 2015 14:02:02 -0500 Subject: [PATCH 1/3] Make it easier to stop tracking an entity 1. When you track an entity by clicking on the track button in the InfoBox, you can now stop tracking by clicking the button a second time. 2. Setting `viewer.trackedEntity` to `undefined` will now restore the camera controls to their default states. --- CHANGES.md | 2 ++ Source/Widgets/InfoBox/InfoBox.js | 4 ++-- Source/Widgets/InfoBox/InfoBoxViewModel.js | 2 +- Source/Widgets/Viewer/Viewer.js | 19 +++++++++++++------ 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 95d07f133d0d..02c1a1bba6d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,8 @@ Change Log * `ConstantProperty` can now hold any value; previously it was limited to values that implemented `equals` and `clones` functions, as well as a few special cases. * Fixed a bug in `EllipsoidGeodesic` that caused it to modify the `height` of the positions passed to the constructor or to to `setEndPoints`. * Instead of throwing an exception when there are not enough unique positions to define a geometry, creating a `Primitive` will succeed, but not render. [#2375](https://github.com/AnalyticalGraphicsInc/cesium/issues/2375) +* When you track an entity by clicking on the track button in the InfoBox, you can now stop tracking by clicking the button a second time. +* Setting `viewer.trackedEntity` to `undefined` will now restore the camera controls to their default states. ### 1.5 - 2015-01-05 diff --git a/Source/Widgets/InfoBox/InfoBox.js b/Source/Widgets/InfoBox/InfoBox.js index 27ddceffd64e..0568fab5eee1 100644 --- a/Source/Widgets/InfoBox/InfoBox.js +++ b/Source/Widgets/InfoBox/InfoBox.js @@ -55,7 +55,7 @@ css: { "cesium-infoBox-visible" : showInfo, "cesium-infoBox-bodyless" : _bodyles cameraElement.className = 'cesium-button cesium-infoBox-camera'; cameraElement.setAttribute('data-bind', '\ attr: { title: "Focus camera on object" },\ -click: function () { cameraClicked.raiseEvent(); },\ +click: function () { cameraClicked.raiseEvent(this); },\ enable: enableCamera,\ cesiumSvgPath: { path: cameraIconPath, width: 32, height: 32 }'); infoElement.appendChild(cameraElement); @@ -64,7 +64,7 @@ cesiumSvgPath: { path: cameraIconPath, width: 32, height: 32 }'); closeElement.type = 'button'; closeElement.className = 'cesium-infoBox-close'; closeElement.setAttribute('data-bind', '\ -click: function () { closeClicked.raiseEvent(); }'); +click: function () { closeClicked.raiseEvent(this); }'); closeElement.innerHTML = '×'; infoElement.appendChild(closeElement); diff --git a/Source/Widgets/InfoBox/InfoBoxViewModel.js b/Source/Widgets/InfoBox/InfoBoxViewModel.js index 9ecc758dc3e8..afef534e1e46 100644 --- a/Source/Widgets/InfoBox/InfoBoxViewModel.js +++ b/Source/Widgets/InfoBox/InfoBoxViewModel.js @@ -118,7 +118,7 @@ define([ this.cameraIconPath = undefined; knockout.defineProperty(this, 'cameraIconPath', { get : function() { - return (this.enableCamera || this.isCameraTracking) ? cameraEnabledPath : cameraDisabledPath; + return (!this.enableCamera || this.isCameraTracking) ? cameraDisabledPath : cameraEnabledPath; } }); diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index a45f97df5a17..2207ecda7429 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -7,6 +7,7 @@ define([ '../../Core/destroyObject', '../../Core/DeveloperError', '../../Core/EventHelper', + '../../Core/Matrix4', '../../Core/ScreenSpaceEventType', '../../DataSources/ConstantPositionProperty', '../../DataSources/DataSourceCollection', @@ -41,6 +42,7 @@ define([ destroyObject, DeveloperError, EventHelper, + Matrix4, ScreenSpaceEventType, ConstantPositionProperty, DataSourceCollection, @@ -382,8 +384,8 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to infoBox = new InfoBox(infoBoxContainer); var infoBoxViewModel = infoBox.viewModel; - eventHelper.add(infoBoxViewModel.cameraClicked, Viewer.prototype._trackSelectedEntity, this); - eventHelper.add(infoBoxViewModel.closeClicked, Viewer.prototype._clearSelectedEntity, this); + eventHelper.add(infoBoxViewModel.cameraClicked, Viewer.prototype._onInfoBoxCameraClicked, this); + eventHelper.add(infoBoxViewModel.closeClicked, Viewer.prototype._onInfoBoxClockClicked, this); } // Main Toolbar @@ -949,6 +951,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to this._entityView = new EntityView(value, scene, this.scene.globe.ellipsoid); } else { this._entityView = undefined; + this.camera.setTransform(Matrix4.IDENTITY); } } } @@ -1262,7 +1265,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to if (selectedEntity.isAvailable(time)) { if (defined(selectedEntity.position)) { position = selectedEntity.position.getValue(time, oldPosition); - enableCamera = defined(position) && (this.trackedEntity !== this.selectedEntity); + enableCamera = defined(position); } // else "position" is undefined and "enableCamera" is false. } @@ -1313,8 +1316,12 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to /** * @private */ - Viewer.prototype._trackSelectedEntity = function() { - this.trackedEntity = this.selectedEntity; + Viewer.prototype._onInfoBoxCameraClicked = function(infoBoxViewModel) { + if (infoBoxViewModel.isCameraTracking && (this.trackedEntity === this.selectedEntity)) { + this.trackedEntity = undefined; + } else { + this.trackedEntity = this.selectedEntity; + } }; /** @@ -1327,7 +1334,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to /** * @private */ - Viewer.prototype._clearSelectedEntity = function() { + Viewer.prototype._onInfoBoxClockClicked = function(infoBoxViewModel) { this.selectedEntity = undefined; }; From 5e406bf2504d07eff98b4b56aba387d129f78f1a Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 12 Jan 2015 19:01:40 -0500 Subject: [PATCH 2/3] Don't zoom home when the trackedEntity is removed. --- Source/Widgets/Viewer/Viewer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index 2207ecda7429..63fecb4414ba 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -1226,7 +1226,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to if (defined(this.trackedEntity)) { if (entityCollection.getById(this.trackedEntity.id) === this.trackedEntity) { - this.homeButton.viewModel.command(); + this.trackedEntity = undefined; } } @@ -1305,7 +1305,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to for (var i = 0; i < length; i++) { var removedObject = removed[i]; if (this.trackedEntity === removedObject) { - this.homeButton.viewModel.command(); + this.trackedEntity = undefined; } if (this.selectedEntity === removedObject) { this.selectedEntity = undefined; From 04c86965bf37181b6c5b8161b2cffe55bf33335a Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Wed, 14 Jan 2015 16:07:26 -0500 Subject: [PATCH 3/3] Fix tests. Update Viewer and InfoBox specs to match new behavior. --- Specs/Widgets/InfoBox/InfoBoxViewModelSpec.js | 17 +++++-- Specs/Widgets/Viewer/ViewerSpec.js | 46 +++++++++---------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/Specs/Widgets/InfoBox/InfoBoxViewModelSpec.js b/Specs/Widgets/InfoBox/InfoBoxViewModelSpec.js index a426c76ccaca..e79c416ea7e5 100644 --- a/Specs/Widgets/InfoBox/InfoBoxViewModelSpec.js +++ b/Specs/Widgets/InfoBox/InfoBoxViewModelSpec.js @@ -84,10 +84,21 @@ defineSuite([ it('camera icon changes when tracking is not available, unless due to active tracking', function() { var viewModel = new InfoBoxViewModel(); viewModel.enableCamera = true; - var enabledCameraPath = viewModel.cameraIconPath; + viewModel.isCameraTracking = false; + var enabledTrackingPath = viewModel.cameraIconPath; + + viewModel.enableCamera = false; + viewModel.isCameraTracking = false; + expect(viewModel.cameraIconPath).not.toBe(enabledTrackingPath); + + var disableTrackingPath = viewModel.cameraIconPath; + + viewModel.enableCamera = true; + viewModel.isCameraTracking = true; + expect(viewModel.cameraIconPath).toBe(disableTrackingPath); + viewModel.enableCamera = false; - expect(viewModel.cameraIconPath).not.toBe(enabledCameraPath); viewModel.isCameraTracking = true; - expect(viewModel.cameraIconPath).toBe(enabledCameraPath); + expect(viewModel.cameraIconPath).toBe(disableTrackingPath); }); }); \ No newline at end of file diff --git a/Specs/Widgets/Viewer/ViewerSpec.js b/Specs/Widgets/Viewer/ViewerSpec.js index 54cdc55e12ac..7cab27af34a9 100644 --- a/Specs/Widgets/Viewer/ViewerSpec.js +++ b/Specs/Widgets/Viewer/ViewerSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/ClockStep', 'Core/EllipsoidTerrainProvider', 'Core/JulianDate', + 'Core/Matrix4', 'Core/WebMercatorProjection', 'DataSources/ConstantPositionProperty', 'DataSources/ConstantProperty', @@ -36,6 +37,7 @@ defineSuite([ ClockStep, EllipsoidTerrainProvider, JulianDate, + Matrix4, WebMercatorProjection, ConstantPositionProperty, ConstantProperty, @@ -770,44 +772,38 @@ defineSuite([ expect(viewer.trackedEntity).toBeUndefined(); }); - it('returns to home when a tracked object is removed', function() { + it('stops tracking when tracked object is removed', function() { viewer = new Viewer(container); - //one data source that is added before mixing in - var preMixinDataSource = new MockDataSource(); - viewer.dataSources.add(preMixinDataSource); - - var beforeEntity = new Entity(); - beforeEntity.position = new ConstantProperty(new Cartesian3(123456, 123456, 123456)); - preMixinDataSource.entities.add(beforeEntity); - - //one data source that is added after mixing in - var postMixinDataSource = new MockDataSource(); - viewer.dataSources.add(postMixinDataSource); - var entity = new Entity(); entity.position = new ConstantProperty(new Cartesian3(123456, 123456, 123456)); - postMixinDataSource.entities.add(entity); + var dataSource = new MockDataSource(); + dataSource.entities.add(entity); + + viewer.dataSources.add(dataSource); viewer.trackedEntity = entity; + expect(viewer.trackedEntity).toBe(entity); + viewer.render(); + expect(Matrix4.getTranslation(viewer.scene.camera.transform, new Cartesian3())).toEqual(entity.position.getValue()); - // spy on the home button's command - Object.defineProperty(viewer.homeButton.viewModel, 'command', { - value : jasmine.createSpy('command') - }); + dataSource.entities.remove(entity); - postMixinDataSource.entities.remove(entity); + expect(viewer.trackedEntity).toBeUndefined(); + expect(viewer.scene.camera.transform).toEqual(Matrix4.IDENTITY); - expect(viewer.homeButton.viewModel.command).toHaveBeenCalled(); + dataSource.entities.add(entity); + viewer.trackedEntity = entity; - // reset the spy before removing the other entity - viewer.homeButton.viewModel.command.reset(); + expect(viewer.trackedEntity).toBe(entity); + viewer.render(); + expect(Matrix4.getTranslation(viewer.scene.camera.transform, new Cartesian3())).toEqual(entity.position.getValue()); - viewer.trackedEntity = beforeEntity; - preMixinDataSource.entities.remove(beforeEntity); + viewer.dataSources.remove(dataSource); - expect(viewer.homeButton.viewModel.command).toHaveBeenCalled(); + expect(viewer.trackedEntity).toBeUndefined(); + expect(viewer.scene.camera.transform).toEqual(Matrix4.IDENTITY); }); it('removes data source listeners when destroyed', function() {