From 104813e73ce8f801d4da9eb8c0178cf9bc35e8fa Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Mon, 23 Mar 2015 23:03:36 -0400 Subject: [PATCH 1/4] Experiment with event-based entity.show support --- .../Sandcastle/gallery/Custom DataSource.html | 6 +- Source/DataSources/BillboardVisualizer.js | 2 +- Source/DataSources/Entity.js | 102 ++++++++++++++++-- Source/DataSources/LabelVisualizer.js | 2 +- Source/DataSources/ModelVisualizer.js | 2 +- Source/DataSources/PathVisualizer.js | 2 +- Source/DataSources/PointVisualizer.js | 2 +- .../DataSources/StaticGeometryColorBatch.js | 42 +++++++- Source/Widgets/Viewer/Viewer.js | 2 +- 9 files changed, 143 insertions(+), 19 deletions(-) diff --git a/Apps/Sandcastle/gallery/Custom DataSource.html b/Apps/Sandcastle/gallery/Custom DataSource.html index 357c1856f104..af2defb2d817 100644 --- a/Apps/Sandcastle/gallery/Custom DataSource.html +++ b/Apps/Sandcastle/gallery/Custom DataSource.html @@ -156,14 +156,14 @@ set : function(value) { this._seriesToDisplay = value; - //Iterate over all polylines and set their show property + //Iterate over all entities and set their show property //to true only if they are part of the current series. var collection = this._entityCollection; var entities = collection.values; collection.suspendEvents(); for (var i = 0; i < entities.length; i++) { var entity = entities[i]; - entity.polyline.show.setValue(value === entity.seriesName); + entity.show = value === entity.seriesName; } collection.resumeEvents(); } @@ -287,7 +287,6 @@ //WebGL Globe only contains lines, so that's the only graphics we create. var polyline = new Cesium.PolylineGraphics(); - polyline.show = new Cesium.ConstantProperty(show); polyline.material = new Cesium.ColorMaterialProperty(color); polyline.width = new Cesium.ConstantProperty(2); polyline.followSurface = new Cesium.ConstantProperty(false); @@ -296,6 +295,7 @@ //The polyline instance itself needs to be on an entity. var entity = new Cesium.Entity({ id : seriesName + ' index ' + i.toString(), + show : show, polyline : polyline, seriesName : seriesName //Custom property to indicate series name }); diff --git a/Source/DataSources/BillboardVisualizer.js b/Source/DataSources/BillboardVisualizer.js index bfe6aba20056..7540a78f535c 100644 --- a/Source/DataSources/BillboardVisualizer.js +++ b/Source/DataSources/BillboardVisualizer.js @@ -105,7 +105,7 @@ define([ var billboardGraphics = entity._billboard; var textureValue; var billboard = item.billboard; - var show = entity.isAvailable(time) && Property.getValueOrDefault(billboardGraphics._show, time, true); + var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(billboardGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index 269ee647870c..b5e98738aba8 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -133,6 +133,7 @@ define([ this._id = id; this._definitionChanged = new Event(); this._name = undefined; + this._show = true; this._parent = options.parent; this._propertyNames = ['billboard', 'box', 'corridor', 'cylinder', 'description', 'ellipse', // 'ellipsoid', 'label', 'model', 'orientation', 'path', 'point', 'polygon', // @@ -176,10 +177,26 @@ define([ this._viewFromSubscription = undefined; this._wall = undefined; this._wallSubscription = undefined; + this._children = []; this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); }; + function updateShow(entity, isShowing) { + var children = entity._children; + var length = children.length; + for (var i = 0; i < length; i++) { + var child = children[i]; + var childShow = child._show; + var oldValue = !isShowing && childShow; + var newValue = isShowing && childShow; + if (oldValue !== newValue) { + child._definitionChanged.raiseEvent(child, 'isShowing', newValue, oldValue); + } + } + entity._definitionChanged.raiseEvent(entity, 'isShowing', isShowing, !isShowing); + } + defineProperties(Entity.prototype, { /** * The availability, if any, associated with this object. @@ -219,17 +236,48 @@ define([ * @memberof Entity.prototype * @type {String} */ - name : { - configurable : false, + name : createRawPropertyDescriptor('name'), + /** + * Gets or sets the name of the object. The name is intended for end-user + * consumption and does not need to be unique. + * @memberof Entity.prototype + * @type {Boolean} + */ + show : { get : function() { - return this._name; + return this._show; }, set : function(value) { - var oldValue = this._name; - if (oldValue !== value) { - this._name = value; - this._definitionChanged.raiseEvent(this, 'name', value, oldValue); + //>>includeStart('debug', pragmas.debug); + if (!defined(value)) { + throw new DeveloperError('value is required.'); + } + //>>includeEnd('debug'); + + if (value === this._show) { + return; } + + var wasShowing = this.isShowing; + this._show = value; + var isShowing = this.isShowing; + + if (wasShowing !== isShowing) { + updateShow(this, isShowing); + } + + this._definitionChanged.raiseEvent(this, 'show', value, !value); + } + }, + /** + * Gets or sets the name of the object. The name is intended for end-user + * consumption and does not need to be unique. + * @memberof Entity.prototype + * @type {Boolean} + */ + isShowing : { + get : function() { + return this._show && (!defined(this._parent) || this._parent._show); } }, /** @@ -237,7 +285,35 @@ define([ * @memberof Entity.prototype * @type {Entity} */ - parent : createRawPropertyDescriptor('parent'), + parent : { + get : function() { + return this._parent; + }, + set : function(value) { + var oldValue = this._parent; + + if (oldValue === value) { + return; + } + + var wasShowing = this.isShowing; + if (defined(oldValue)) { + var index = oldValue._children.indexOf(this); + oldValue._children.splice(index, 1); + } + + this._parent = value; + value._children.push(value); + + var isShowing = this.isShowing; + + if (wasShowing !== isShowing) { + updateShow(this, isShowing); + } + + this._definitionChanged.raiseEvent(this, 'parent', value, oldValue); + } + }, /** * Gets the names of all properties registered on this instance. * @memberof Entity.prototype @@ -382,6 +458,16 @@ define([ return !defined(availability) || availability.contains(time); }; + /** + * Given a time, returns true if this entity should be displayed at that time. + * + * @param {JulianDate} time The time to check availability for. + * @returns true if this entity should be displayed during the provided time, false otherwise. + */ + Entity.prototype.isAvailableAndShowing = function(time) { + return this._show && this.isAvailable(time) && (!defined(this._parent) || this._parent.isAvailableAndShowing(time)); + }; + /** * Adds a property to this object. Once a property is added, it can be * observed with {@link Entity#definitionChanged} and composited diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index 1ea368210912..ad38f987e98e 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -108,7 +108,7 @@ define([ var labelGraphics = entity._label; var text; var label = item.label; - var show = entity.isAvailable(time) && Property.getValueOrDefault(labelGraphics._show, time, true); + var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(labelGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index c2a6d92bab1e..56e534291a81 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -84,7 +84,7 @@ define([ var uri; var modelData = modelHash[entity.id]; - var show = entity.isAvailable(time) && Property.getValueOrDefault(modelGraphics._show, time, true); + var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(modelGraphics._show, time, true); var modelMatrix; if (show) { diff --git a/Source/DataSources/PathVisualizer.js b/Source/DataSources/PathVisualizer.js index eefd2e564000..f70c2ebab5fa 100644 --- a/Source/DataSources/PathVisualizer.js +++ b/Source/DataSources/PathVisualizer.js @@ -293,7 +293,7 @@ define([ var sampleStop; var showProperty = pathGraphics._show; var polyline = item.polyline; - var show = !defined(showProperty) || showProperty.getValue(time); + var show = entity.isAvailableAndShowing(time) && (!defined(showProperty) || showProperty.getValue(time)); //While we want to show the path, there may not actually be anything to show //depending on lead/trail settings. Compute the interval of the path to diff --git a/Source/DataSources/PointVisualizer.js b/Source/DataSources/PointVisualizer.js index 919edaf69232..ede21d5b5660 100644 --- a/Source/DataSources/PointVisualizer.js +++ b/Source/DataSources/PointVisualizer.js @@ -91,7 +91,7 @@ define([ var entity = item.entity; var pointGraphics = entity._point; var billboard = item.billboard; - var show = entity.isAvailable(time) && Property.getValueOrDefault(pointGraphics._show, time, true); + var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(pointGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); show = defined(position); diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index ee34a12c8e89..4a88255282a0 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -31,6 +31,8 @@ define([ this.updaters = new AssociativeArray(); this.updatersWithAttributes = new AssociativeArray(); this.attributes = new AssociativeArray(); + this.subscriptions = new AssociativeArray(); + this.showsUpdated = new AssociativeArray(); this.itemsToRemove = []; }; @@ -41,14 +43,27 @@ define([ this.updaters.set(id, updater); if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant) { this.updatersWithAttributes.set(id, updater); + } else { + var that = this; + this.subscriptions.set(id, updater.entity.definitionChanged.addEventListener(function(entity, propertyName, newValue, oldValue) { + if (propertyName === 'isShowing') { + that.showsUpdated.set(entity.id, updater); + } + })); } }; Batch.prototype.remove = function(updater) { var id = updater.entity.id; this.createPrimitive = this.geometry.remove(id) || this.createPrimitive; - this.updaters.remove(id); - this.updatersWithAttributes.remove(id); + if (this.updaters.remove(id)) { + this.updatersWithAttributes.remove(id); + var unsubscribe = this.subscriptions.get(id); + if (defined(unsubscribe)) { + unsubscribe(); + this.subscriptions.remove(id); + } + } }; Batch.prototype.update = function(time) { @@ -117,6 +132,8 @@ define([ } } } + + this.updateShows(primitive); } else if (defined(primitive) && !primitive.ready) { isUpdated = false; } @@ -124,6 +141,27 @@ define([ return isUpdated; }; + Batch.prototype.updateShows = function(primitive) { + var showsUpdated = this.showsUpdated.values; + var length = showsUpdated.length; + for (var i = 0; i < length; i++) { + var updater = showsUpdated[i]; + var instance = this.geometry.get(updater.entity.id); + + var attributes = this.attributes.get(instance.id.id); + if (!defined(attributes)) { + attributes = primitive.getGeometryInstanceAttributes(instance.id); + this.attributes.set(instance.id.id, attributes); + } + + var show = updater.entity.isShowing; + var currentShow = attributes.show[0] === 1; + if (show !== currentShow) { + attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); + } + } + }; + Batch.prototype.contains = function(entity) { return this.updaters.contains(entity.id); }; diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index aeed8016fe45..b4616ec657b1 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -1298,7 +1298,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to var selectedEntity = this.selectedEntity; var showSelection = defined(selectedEntity) && this._enableInfoOrSelection; - if (showSelection && selectedEntity.isAvailable(time)) { + if (showSelection && selectedEntity.isAvailableAndShowing(time)) { var state = this._dataSourceDisplay.getBoundingSphere(selectedEntity, true, boundingSphereScratch); if (state !== BoundingSphereState.FAILED) { position = boundingSphereScratch.center; From 362e275e4e1ce04222a9d72e2d0a822efa67f3d4 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 24 Mar 2015 20:50:24 -0400 Subject: [PATCH 2/4] Ongoing Entity.show work 1. Tests for Entity show/isShowing and events 2. Get rid of `isAvailableAndShowing`, which won't actually be needed in the long run. --- Source/DataSources/BillboardVisualizer.js | 2 +- Source/DataSources/Entity.js | 15 +--- Source/DataSources/LabelVisualizer.js | 2 +- Source/DataSources/ModelVisualizer.js | 2 +- Source/DataSources/PathVisualizer.js | 2 +- Source/DataSources/PointVisualizer.js | 2 +- .../DataSources/StaticGeometryColorBatch.js | 1 + Source/Widgets/Viewer/Viewer.js | 2 +- Specs/DataSources/EntitySpec.js | 89 +++++++++++++++++++ 9 files changed, 99 insertions(+), 18 deletions(-) diff --git a/Source/DataSources/BillboardVisualizer.js b/Source/DataSources/BillboardVisualizer.js index 7540a78f535c..50ec0c5a2548 100644 --- a/Source/DataSources/BillboardVisualizer.js +++ b/Source/DataSources/BillboardVisualizer.js @@ -105,7 +105,7 @@ define([ var billboardGraphics = entity._billboard; var textureValue; var billboard = item.billboard; - var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(billboardGraphics._show, time, true); + var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(billboardGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index b5e98738aba8..451a62dd771c 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -303,7 +303,7 @@ define([ } this._parent = value; - value._children.push(value); + value._children.push(this); var isShowing = this.isShowing; @@ -458,16 +458,6 @@ define([ return !defined(availability) || availability.contains(time); }; - /** - * Given a time, returns true if this entity should be displayed at that time. - * - * @param {JulianDate} time The time to check availability for. - * @returns true if this entity should be displayed during the provided time, false otherwise. - */ - Entity.prototype.isAvailableAndShowing = function(time) { - return this._show && this.isAvailable(time) && (!defined(this._parent) || this._parent.isAvailableAndShowing(time)); - }; - /** * Adds a property to this object. Once a property is added, it can be * observed with {@link Entity#definitionChanged} and composited @@ -534,9 +524,10 @@ define([ } //>>includeEnd('debug'); - //Name and availability are not Property objects and are currently handled differently. + //Name, show, and availability are not Property objects and are currently handled differently. this.name = defaultValue(this.name, source.name); this.availability = defaultValue(source.availability, this.availability); + this.show = defaultValue(source.show, this.show); var propertyNames = this._propertyNames; var sourcePropertyNames = defined(source._propertyNames) ? source._propertyNames : Object.keys(source); diff --git a/Source/DataSources/LabelVisualizer.js b/Source/DataSources/LabelVisualizer.js index ad38f987e98e..83b334942a7d 100644 --- a/Source/DataSources/LabelVisualizer.js +++ b/Source/DataSources/LabelVisualizer.js @@ -108,7 +108,7 @@ define([ var labelGraphics = entity._label; var text; var label = item.label; - var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(labelGraphics._show, time, true); + var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(labelGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index 56e534291a81..cd40d0761c8e 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -84,7 +84,7 @@ define([ var uri; var modelData = modelHash[entity.id]; - var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(modelGraphics._show, time, true); + var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(modelGraphics._show, time, true); var modelMatrix; if (show) { diff --git a/Source/DataSources/PathVisualizer.js b/Source/DataSources/PathVisualizer.js index f70c2ebab5fa..718c17610901 100644 --- a/Source/DataSources/PathVisualizer.js +++ b/Source/DataSources/PathVisualizer.js @@ -293,7 +293,7 @@ define([ var sampleStop; var showProperty = pathGraphics._show; var polyline = item.polyline; - var show = entity.isAvailableAndShowing(time) && (!defined(showProperty) || showProperty.getValue(time)); + var show = entity.isShowing && (!defined(showProperty) || showProperty.getValue(time)); //While we want to show the path, there may not actually be anything to show //depending on lead/trail settings. Compute the interval of the path to diff --git a/Source/DataSources/PointVisualizer.js b/Source/DataSources/PointVisualizer.js index ede21d5b5660..ff86978db82a 100644 --- a/Source/DataSources/PointVisualizer.js +++ b/Source/DataSources/PointVisualizer.js @@ -91,7 +91,7 @@ define([ var entity = item.entity; var pointGraphics = entity._point; var billboard = item.billboard; - var show = entity.isAvailableAndShowing(time) && Property.getValueOrDefault(pointGraphics._show, time, true); + var show = entity.isShowing && entity.isAvailable(time) && Property.getValueOrDefault(pointGraphics._show, time, true); if (show) { position = Property.getValueOrUndefined(entity._position, time, position); show = defined(position); diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index 4a88255282a0..70d50911f5fb 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -160,6 +160,7 @@ define([ attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); } } + this.showsUpdated.removeAll(); }; Batch.prototype.contains = function(entity) { diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index b4616ec657b1..4e56a5820c04 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -1298,7 +1298,7 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to var selectedEntity = this.selectedEntity; var showSelection = defined(selectedEntity) && this._enableInfoOrSelection; - if (showSelection && selectedEntity.isAvailableAndShowing(time)) { + if (showSelection && selectedEntity.isShowing && selectedEntity.isAvailable(time)) { var state = this._dataSourceDisplay.getBoundingSphere(selectedEntity, true, boundingSphereScratch); if (state !== BoundingSphereState.FAILED) { position = boundingSphereScratch.center; diff --git a/Specs/DataSources/EntitySpec.js b/Specs/DataSources/EntitySpec.js index c606b856c5f3..57e5a5e5facb 100644 --- a/Specs/DataSources/EntitySpec.js +++ b/Specs/DataSources/EntitySpec.js @@ -83,6 +83,7 @@ defineSuite([ var options = { id : 'someId', name : 'bob', + show : false, availability : new TimeIntervalCollection(), parent : new Entity(), customProperty : {}, @@ -110,6 +111,7 @@ defineSuite([ entity = new Entity(options); expect(entity.id).toEqual(options.id); expect(entity.name).toEqual(options.name); + expect(entity.show).toBe(options.show); expect(entity.availability).toBe(options.availability); expect(entity.parent).toBe(options.parent); expect(entity.customProperty).toBe(options.customProperty); @@ -357,4 +359,91 @@ defineSuite([ entity.removeProperty('name'); }).toThrowDeveloperError(); }); + + it('isShowing works without parent.', function() { + var entity = new Entity({ + show : false + }); + expect(entity.isShowing).toBe(false); + + var listener = jasmine.createSpy('listener'); + entity.definitionChanged.addEventListener(listener); + + entity.show = true; + expect(listener.calls.count()).toBe(2); + expect(listener.calls.argsFor(0)).toEqual([entity, 'isShowing', true, false]); + expect(listener.calls.argsFor(1)).toEqual([entity, 'show', true, false]); + expect(entity.isShowing).toBe(true); + + listener.calls.reset(); + + entity.show = false; + expect(listener.calls.count()).toBe(2); + expect(listener.calls.argsFor(0)).toEqual([entity, 'isShowing', false, true]); + expect(listener.calls.argsFor(1)).toEqual([entity, 'show', false, true]); + expect(entity.isShowing).toBe(false); + }); + + it('isShowing works with parent.', function() { + var entity = new Entity(); + entity.parent = new Entity(); + + var listener = jasmine.createSpy('listener'); + entity.definitionChanged.addEventListener(listener); + + entity.parent.show = false; + + //Setting entity.parent show to false causes entity to raise + //its own isShowing event, but not the show event. + expect(listener.calls.count()).toBe(1); + expect(listener.calls.argsFor(0)).toEqual([entity, 'isShowing', false, true]); + expect(entity.show).toBe(true); + expect(entity.isShowing).toBe(false); + + listener.calls.reset(); + + //Since isShowing is already false, setting show to false causes the show event + //but not the isShowing event to be raised + entity.show = false; + expect(entity.show).toBe(false); + expect(listener.calls.count()).toBe(1); + expect(listener.calls.argsFor(0)).toEqual([entity, 'show', false, true]); + + listener.calls.reset(); + + //Setting parent show to true does not trigger the entity.isShowing event + //because entity.show is false; + entity.parent.show = true; + expect(entity.show).toBe(false); + expect(entity.isShowing).toBe(false); + expect(listener.calls.count()).toBe(0); + + listener.calls.reset(); + + //Setting entity.show to try now causes both events to be raised + //because the parent is also showing. + entity.show = true; + expect(listener.calls.count()).toBe(2); + expect(listener.calls.argsFor(0)).toEqual([entity, 'isShowing', true, false]); + expect(listener.calls.argsFor(1)).toEqual([entity, 'show', true, false]); + expect(entity.show).toBe(true); + expect(entity.isShowing).toBe(true); + }); + + it('isShowing works when replacing parent.', function() { + var entity = new Entity(); + entity.parent = new Entity(); + + var listener = jasmine.createSpy('listener'); + entity.definitionChanged.addEventListener(listener); + + entity.parent = new Entity({ + show : false + }); + + expect(listener.calls.count()).toBe(2); + expect(listener.calls.argsFor(0)).toEqual([entity, 'isShowing', false, true]); + expect(entity.show).toBe(true); + expect(entity.isShowing).toBe(false); + }); }); \ No newline at end of file From 0af5d03cc02489ed0038898595df8e9374083e27 Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 24 Mar 2015 22:47:08 -0400 Subject: [PATCH 3/4] Finish up Entity.show work. 1. Update CHANGES and reference documentation. 2. Add support for KML Feature `visibility` element. 3. Make dynamic updates obey Entity.isShowing. 4. Make static material and outline geometry obey Entity.isShowing. 5. Update specs. 6. Add Sandcastle example 7. To support the Sandcastle example, chaned `viewer.zoomTo` and `viewer.flyTo` to be "best effort" functions, rather than failing if any one entity is not displayed. This was both requested on the mailing list and is needed to zoom to a data source on load or with time-dynamic data. --- .../gallery/Show or Hide Entities.html | 95 ++++++++++++++++++ .../gallery/Show or Hide Entities.jpg | Bin 0 -> 19775 bytes CHANGES.md | 4 + Source/Core/AssociativeArray.js | 7 +- Source/DataSources/BoxGeometryUpdater.js | 2 +- Source/DataSources/CorridorGeometryUpdater.js | 2 +- Source/DataSources/CylinderGeometryUpdater.js | 2 +- Source/DataSources/EllipseGeometryUpdater.js | 2 +- .../DataSources/EllipsoidGeometryUpdater.js | 2 +- Source/DataSources/Entity.js | 20 ++-- Source/DataSources/KmlDataSource.js | 4 +- Source/DataSources/PolygonGeometryUpdater.js | 2 +- Source/DataSources/PolylineGeometryUpdater.js | 2 +- .../PolylineVolumeGeometryUpdater.js | 2 +- .../DataSources/RectangleGeometryUpdater.js | 2 +- .../DataSources/StaticGeometryColorBatch.js | 5 +- .../StaticGeometryPerMaterialBatch.js | 59 +++++++++-- .../DataSources/StaticOutlineGeometryBatch.js | 48 ++++++++- Source/DataSources/WallGeometryUpdater.js | 2 +- .../dynamicGeometryGetBoundingSphere.js | 4 +- Source/Widgets/Viewer/Viewer.js | 7 +- Specs/DataSources/BoxGeometryUpdaterSpec.js | 5 + .../CorridorGeometryUpdaterSpec.js | 5 + .../CylinderGeometryUpdaterSpec.js | 5 + .../DataSources/EllipseGeometryUpdaterSpec.js | 5 + Specs/DataSources/KmlDataSourceSpec.js | 12 +++ .../DataSources/PolygonGeometryUpdaterSpec.js | 5 + .../PolylineVolumeGeometryUpdaterSpec.js | 5 + .../RectangleGeometryUpdaterSpec.js | 5 + Specs/DataSources/WallGeometryUpdaterSpec.js | 5 + 30 files changed, 279 insertions(+), 46 deletions(-) create mode 100644 Apps/Sandcastle/gallery/Show or Hide Entities.html create mode 100644 Apps/Sandcastle/gallery/Show or Hide Entities.jpg diff --git a/Apps/Sandcastle/gallery/Show or Hide Entities.html b/Apps/Sandcastle/gallery/Show or Hide Entities.html new file mode 100644 index 000000000000..632b227a4e77 --- /dev/null +++ b/Apps/Sandcastle/gallery/Show or Hide Entities.html @@ -0,0 +1,95 @@ + + + + + + + + + Cesium Demo + + + + + + +
+

Loading...

+
+ + + diff --git a/Apps/Sandcastle/gallery/Show or Hide Entities.jpg b/Apps/Sandcastle/gallery/Show or Hide Entities.jpg new file mode 100644 index 0000000000000000000000000000000000000000..55907638f8a9a6e0f0d4bcbd4b4f16b2a5e8c4ba GIT binary patch literal 19775 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℘ZhrjoB?mXeRci@Q1*$KGi6v$F@4S2|i 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 0) { + this._hash = {}; + array.length = 0; + } }; return AssociativeArray; diff --git a/Source/DataSources/BoxGeometryUpdater.js b/Source/DataSources/BoxGeometryUpdater.js index 3df3b7bc9387..14f4628e5691 100644 --- a/Source/DataSources/BoxGeometryUpdater.js +++ b/Source/DataSources/BoxGeometryUpdater.js @@ -509,7 +509,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var box = entity.box; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(box.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(box.show, time, true)) { return; } diff --git a/Source/DataSources/CorridorGeometryUpdater.js b/Source/DataSources/CorridorGeometryUpdater.js index fd69e0545208..43e08de143b8 100644 --- a/Source/DataSources/CorridorGeometryUpdater.js +++ b/Source/DataSources/CorridorGeometryUpdater.js @@ -529,7 +529,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var corridor = entity.corridor; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(corridor.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(corridor.show, time, true)) { return; } diff --git a/Source/DataSources/CylinderGeometryUpdater.js b/Source/DataSources/CylinderGeometryUpdater.js index 924f2887e39c..ab66c94360e6 100644 --- a/Source/DataSources/CylinderGeometryUpdater.js +++ b/Source/DataSources/CylinderGeometryUpdater.js @@ -529,7 +529,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var cylinder = entity.cylinder; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(cylinder.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(cylinder.show, time, true)) { return; } diff --git a/Source/DataSources/EllipseGeometryUpdater.js b/Source/DataSources/EllipseGeometryUpdater.js index 6ccbf208e6be..754a052ba329 100644 --- a/Source/DataSources/EllipseGeometryUpdater.js +++ b/Source/DataSources/EllipseGeometryUpdater.js @@ -541,7 +541,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var ellipse = entity.ellipse; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(ellipse.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(ellipse.show, time, true)) { return; } diff --git a/Source/DataSources/EllipsoidGeometryUpdater.js b/Source/DataSources/EllipsoidGeometryUpdater.js index 858669ef58a9..fd030e46069c 100644 --- a/Source/DataSources/EllipsoidGeometryUpdater.js +++ b/Source/DataSources/EllipsoidGeometryUpdater.js @@ -535,7 +535,7 @@ define([ var entity = this._entity; var ellipsoid = entity.ellipsoid; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(ellipsoid.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(ellipsoid.show, time, true)) { if (defined(this._primitive)) { this._primitive.show = false; } diff --git a/Source/DataSources/Entity.js b/Source/DataSources/Entity.js index 451a62dd771c..20b00c590ddd 100644 --- a/Source/DataSources/Entity.js +++ b/Source/DataSources/Entity.js @@ -92,6 +92,7 @@ define([ * @param {Object} [options] Object with the following properties: * @param {String} [options.id] A unique identifier for this object. If none is provided, a GUID is generated. * @param {String} [options.name] A human readable name to display to users. It does not have to be unique. + * @param {Boolean} [options.show] A boolean value indicating if the entity and its children are displayed. * @param {Property} [options.description] A string Property specifying an HTML description for this entity. * @param {PositionProperty} [options.position] A Property specifying the entity position. * @param {Property} [options.orientation] A Property specifying the entity orientation. @@ -132,9 +133,9 @@ define([ this._availability = undefined; this._id = id; this._definitionChanged = new Event(); - this._name = undefined; - this._show = true; - this._parent = options.parent; + this._name = options.name; + this._show = defaultValue(options.show, true); + this._parent = undefined; this._propertyNames = ['billboard', 'box', 'corridor', 'cylinder', 'description', 'ellipse', // 'ellipsoid', 'label', 'model', 'orientation', 'path', 'point', 'polygon', // 'polyline', 'polylineVolume', 'position', 'rectangle', 'viewFrom', 'wall']; @@ -179,7 +180,8 @@ define([ this._wallSubscription = undefined; this._children = []; - this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT)); + this.parent = options.parent; + this.merge(options); }; function updateShow(entity, isShowing) { @@ -238,8 +240,8 @@ define([ */ name : createRawPropertyDescriptor('name'), /** - * Gets or sets the name of the object. The name is intended for end-user - * consumption and does not need to be unique. + * Gets or sets whether this entity should be displayed. When set to true, + * the entity is only displayed if the parent entity's show property is also true. * @memberof Entity.prototype * @type {Boolean} */ @@ -270,8 +272,8 @@ define([ } }, /** - * Gets or sets the name of the object. The name is intended for end-user - * consumption and does not need to be unique. + * Gets whether this entity is being displayed, taking into account + * the visibility of any ancestor entities. * @memberof Entity.prototype * @type {Boolean} */ @@ -525,9 +527,9 @@ define([ //>>includeEnd('debug'); //Name, show, and availability are not Property objects and are currently handled differently. + //source.show is intentionally ignored because this.show always has a value. this.name = defaultValue(this.name, source.name); this.availability = defaultValue(source.availability, this.availability); - this.show = defaultValue(source.show, this.show); var propertyNames = this._propertyNames; var sourcePropertyNames = defined(source._propertyNames) ? source._propertyNames : Object.keys(source); diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index c2feb8089684..a4759abcc3fc 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -1299,8 +1299,8 @@ define([ } entity.availability = availability; - //var visibility = queryBooleanValue(featureNode, 'visibility', namespaces.kml); - //entity.uiShow = defaultValue(visibility, true); + var visibility = queryBooleanValue(featureNode, 'visibility', namespaces.kml); + entity.show = defaultValue(visibility, true); //var open = queryBooleanValue(featureNode, 'open', namespaces.kml); var authorNode = queryFirstNode(featureNode, 'author', namespaces.atom); diff --git a/Source/DataSources/PolygonGeometryUpdater.js b/Source/DataSources/PolygonGeometryUpdater.js index ea0739b3e025..f9ab20c0e8b4 100644 --- a/Source/DataSources/PolygonGeometryUpdater.js +++ b/Source/DataSources/PolygonGeometryUpdater.js @@ -542,7 +542,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var polygon = entity.polygon; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(polygon.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(polygon.show, time, true)) { return; } diff --git a/Source/DataSources/PolylineGeometryUpdater.js b/Source/DataSources/PolylineGeometryUpdater.js index 54ea6adffaa0..3793cbdffb16 100644 --- a/Source/DataSources/PolylineGeometryUpdater.js +++ b/Source/DataSources/PolylineGeometryUpdater.js @@ -460,7 +460,7 @@ define([ var polyline = entity.polyline; var line = this._line; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(polyline._show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(polyline._show, time, true)) { line.show = false; return; } diff --git a/Source/DataSources/PolylineVolumeGeometryUpdater.js b/Source/DataSources/PolylineVolumeGeometryUpdater.js index 48d5d8df37b2..03b28c993446 100644 --- a/Source/DataSources/PolylineVolumeGeometryUpdater.js +++ b/Source/DataSources/PolylineVolumeGeometryUpdater.js @@ -516,7 +516,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var polylineVolume = entity.polylineVolume; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(polylineVolume.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(polylineVolume.show, time, true)) { return; } diff --git a/Source/DataSources/RectangleGeometryUpdater.js b/Source/DataSources/RectangleGeometryUpdater.js index 2781f1c4fd9a..2e608b033427 100644 --- a/Source/DataSources/RectangleGeometryUpdater.js +++ b/Source/DataSources/RectangleGeometryUpdater.js @@ -537,7 +537,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var rectangle = entity.rectangle; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(rectangle.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(rectangle.show, time, true)) { return; } diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index 70d50911f5fb..2509fa498ab2 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -125,7 +125,7 @@ define([ } if (!updater.hasConstantFill) { - var show = updater.isFilled(time); + var show = updater.entity.isShowing && updater.isFilled(time); var currentShow = attributes.show[0] === 1; if (show !== currentShow) { attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); @@ -173,8 +173,7 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere) ||// - (defined(attributes.show) && attributes.show[0] === 0)) { + if (!defined(attributes) || !defined(attributes.boundingSphere)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/StaticGeometryPerMaterialBatch.js b/Source/DataSources/StaticGeometryPerMaterialBatch.js index 9bbac9f6c6d5..32646291e8be 100644 --- a/Source/DataSources/StaticGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGeometryPerMaterialBatch.js @@ -30,6 +30,8 @@ define([ this.attributes = new AssociativeArray(); this.invalidated = false; this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(Batch.prototype.onMaterialChanged, this); + this.subscriptions = new AssociativeArray(); + this.showsUpdated = new AssociativeArray(); }; Batch.prototype.onMaterialChanged = function() { @@ -54,16 +56,32 @@ define([ this.geometry.set(id, updater.createFillGeometryInstance(time)); if (!updater.hasConstantFill || !updater.fillMaterialProperty.isConstant) { this.updatersWithAttributes.set(id, updater); + } else { + var that = this; + this.subscriptions.set(id, updater.entity.definitionChanged.addEventListener(function(entity, propertyName, newValue, oldValue) { + if (propertyName === 'isShowing') { + that.showsUpdated.set(entity.id, updater); + } + })); } this.createPrimitive = true; }; Batch.prototype.remove = function(updater) { var id = updater.entity.id; - this.createPrimitive = this.updaters.remove(id); - this.geometry.remove(id); - this.updatersWithAttributes.remove(id); - return this.createPrimitive; + var createPrimitive = this.updaters.remove(id); + + if (createPrimitive) { + this.geometry.remove(id); + this.updatersWithAttributes.remove(id); + var unsubscribe = this.subscriptions.get(id); + if (defined(unsubscribe)) { + unsubscribe(); + this.subscriptions.remove(id); + } + } + this.createPrimitive = createPrimitive; + return createPrimitive; }; Batch.prototype.update = function(time) { @@ -109,7 +127,8 @@ define([ var length = updatersWithAttributes.length; for (var i = 0; i < length; i++) { var updater = updatersWithAttributes[i]; - var instance = this.geometry.get(updater.entity.id); + var entity = updater.entity; + var instance = this.geometry.get(entity.id); var attributes = this.attributes.get(instance.id.id); if (!defined(attributes)) { @@ -118,19 +137,44 @@ define([ } if (!updater.hasConstantFill) { - var show = updater.isFilled(time); + var show = entity.isShowing && updater.isFilled(time); var currentShow = attributes.show[0] === 1; if (show !== currentShow) { attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); } } } + + this.updateShows(primitive); } else if (defined(primitive) && !primitive.ready) { isUpdated = false; } return isUpdated; }; + Batch.prototype.updateShows = function(primitive) { + var showsUpdated = this.showsUpdated.values; + var length = showsUpdated.length; + for (var i = 0; i < length; i++) { + var updater = showsUpdated[i]; + var entity = updater.entity; + var instance = this.geometry.get(entity.id); + + var attributes = this.attributes.get(instance.id.id); + if (!defined(attributes)) { + attributes = primitive.getGeometryInstanceAttributes(instance.id); + this.attributes.set(instance.id.id, attributes); + } + + var show = entity.isShowing; + var currentShow = attributes.show[0] === 1; + if (show !== currentShow) { + attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); + } + } + this.showsUpdated.removeAll(); + }; + Batch.prototype.contains = function(entity) { return this.updaters.contains(entity.id); }; @@ -141,8 +185,7 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere) ||// - (defined(attributes.show) && attributes.show[0] === 0)) { + if (!defined(attributes) || !defined(attributes.boundingSphere)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/StaticOutlineGeometryBatch.js b/Source/DataSources/StaticOutlineGeometryBatch.js index 13c6baa6abd2..70b3cbba8618 100644 --- a/Source/DataSources/StaticOutlineGeometryBatch.js +++ b/Source/DataSources/StaticOutlineGeometryBatch.js @@ -31,6 +31,8 @@ define([ this.attributes = new AssociativeArray(); this.itemsToRemove = []; this.width = width; + this.subscriptions = new AssociativeArray(); + this.showsUpdated = new AssociativeArray(); }; Batch.prototype.add = function(updater, instance) { @@ -40,14 +42,27 @@ define([ this.updaters.set(id, updater); if (!updater.hasConstantOutline || !updater.outlineColorProperty.isConstant) { this.updatersWithAttributes.set(id, updater); + } else { + var that = this; + this.subscriptions.set(id, updater.entity.definitionChanged.addEventListener(function(entity, propertyName, newValue, oldValue) { + if (propertyName === 'isShowing') { + that.showsUpdated.set(entity.id, updater); + } + })); } }; Batch.prototype.remove = function(updater) { var id = updater.entity.id; this.createPrimitive = this.geometry.remove(id) || this.createPrimitive; - this.updaters.remove(id); - this.updatersWithAttributes.remove(id); + if (this.updaters.remove(id)) { + this.updatersWithAttributes.remove(id); + var unsubscribe = this.subscriptions.get(id); + if (defined(unsubscribe)) { + unsubscribe(); + this.subscriptions.remove(id); + } + } }; var colorScratch = new Color(); @@ -115,13 +130,15 @@ define([ } if (!updater.hasConstantOutline) { - var show = updater.isOutlineVisible(time); + var show = updater.entity.isShowing && updater.isOutlineVisible(time); var currentShow = attributes.show[0] === 1; if (show !== currentShow) { attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); } } } + + this.updateShows(primitive); } else if (defined(primitive) && !primitive.ready) { isUpdated = false; } @@ -130,6 +147,28 @@ define([ return isUpdated; }; + Batch.prototype.updateShows = function(primitive) { + var showsUpdated = this.showsUpdated.values; + var length = showsUpdated.length; + for (var i = 0; i < length; i++) { + var updater = showsUpdated[i]; + var instance = this.geometry.get(updater.entity.id); + + var attributes = this.attributes.get(instance.id.id); + if (!defined(attributes)) { + attributes = primitive.getGeometryInstanceAttributes(instance.id); + this.attributes.set(instance.id.id, attributes); + } + + var show = updater.entity.isShowing; + var currentShow = attributes.show[0] === 1; + if (show !== currentShow) { + attributes.show = ShowGeometryInstanceAttribute.toValue(show, attributes.show); + } + } + this.showsUpdated.removeAll(); + }; + Batch.prototype.contains = function(entity) { return this.updaters.contains(entity.id); }; @@ -140,8 +179,7 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere) ||// - (defined(attributes.show) && attributes.show[0] === 0)) { + if (!defined(attributes) || !defined(attributes.boundingSphere)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/WallGeometryUpdater.js b/Source/DataSources/WallGeometryUpdater.js index 3dafe16ab952..68997bc9f415 100644 --- a/Source/DataSources/WallGeometryUpdater.js +++ b/Source/DataSources/WallGeometryUpdater.js @@ -519,7 +519,7 @@ define([ var geometryUpdater = this._geometryUpdater; var entity = geometryUpdater._entity; var wall = entity.wall; - if (!entity.isAvailable(time) || !Property.getValueOrDefault(wall.show, time, true)) { + if (!entity.isShowing || !entity.isAvailable(time) || !Property.getValueOrDefault(wall.show, time, true)) { return; } diff --git a/Source/DataSources/dynamicGeometryGetBoundingSphere.js b/Source/DataSources/dynamicGeometryGetBoundingSphere.js index 30d5559e4a2b..6d122b046971 100644 --- a/Source/DataSources/dynamicGeometryGetBoundingSphere.js +++ b/Source/DataSources/dynamicGeometryGetBoundingSphere.js @@ -27,7 +27,7 @@ define([ var attributes; //Outline and Fill geometries have the same bounding sphere, so just use whichever one is defined and ready - if (defined(primitive) && primitive.show && primitive.ready) { + if (defined(primitive) && primitive.ready) { attributes = primitive.getGeometryInstanceAttributes(entity); if (defined(attributes) && defined(attributes.boundingSphere)) { BoundingSphere.transform(attributes.boundingSphere, primitive.modelMatrix, result); @@ -35,7 +35,7 @@ define([ } } - if (defined(outlinePrimitive) && outlinePrimitive.show && outlinePrimitive.ready) { + if (defined(outlinePrimitive) && outlinePrimitive.ready) { attributes = outlinePrimitive.getGeometryInstanceAttributes(entity); if (defined(attributes) && defined(attributes.boundingSphere)) { BoundingSphere.transform(attributes.boundingSphere, outlinePrimitive.modelMatrix, result); diff --git a/Source/Widgets/Viewer/Viewer.js b/Source/Widgets/Viewer/Viewer.js index 4e56a5820c04..f189352be69f 100644 --- a/Source/Widgets/Viewer/Viewer.js +++ b/Source/Widgets/Viewer/Viewer.js @@ -1561,12 +1561,9 @@ Either specify options.terrainProvider instead or set options.baseLayerPicker to if (state === BoundingSphereState.PENDING) { return; - } else if (state === BoundingSphereState.FAILED) { - cancelZoom(viewer); - return; + } else if (state !== BoundingSphereState.FAILED) { + boundingSpheres.push(BoundingSphere.clone(boundingSphereScratch)); } - - boundingSpheres.push(BoundingSphere.clone(boundingSphereScratch)); } if (boundingSpheres.length === 0) { diff --git a/Specs/DataSources/BoxGeometryUpdaterSpec.js b/Specs/DataSources/BoxGeometryUpdaterSpec.js index 7e87e2c16935..a8115a85217d 100644 --- a/Specs/DataSources/BoxGeometryUpdaterSpec.js +++ b/Specs/DataSources/BoxGeometryUpdaterSpec.js @@ -298,6 +298,11 @@ defineSuite([ expect(dynamicUpdater._options.id).toBe(entity); expect(dynamicUpdater._options.dimensions).toEqual(box.dimensions.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + box.show.setValue(false); dynamicUpdater.update(JulianDate.now()); expect(primitives.length).toBe(0); diff --git a/Specs/DataSources/CorridorGeometryUpdaterSpec.js b/Specs/DataSources/CorridorGeometryUpdaterSpec.js index bb04911a2525..a0441bfb3a9e 100644 --- a/Specs/DataSources/CorridorGeometryUpdaterSpec.js +++ b/Specs/DataSources/CorridorGeometryUpdaterSpec.js @@ -400,6 +400,11 @@ defineSuite([ expect(options.granularity).toEqual(corridor.granularity.getValue()); expect(options.cornerType).toEqual(corridor.cornerType.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + //If a dynamic show returns false, the primitive should go away. corridor.show.setValue(false); dynamicUpdater.update(time); diff --git a/Specs/DataSources/CylinderGeometryUpdaterSpec.js b/Specs/DataSources/CylinderGeometryUpdaterSpec.js index 5bfbd3e7a47e..52a5825b72b4 100644 --- a/Specs/DataSources/CylinderGeometryUpdaterSpec.js +++ b/Specs/DataSources/CylinderGeometryUpdaterSpec.js @@ -384,6 +384,11 @@ defineSuite([ expect(dynamicUpdater._options.topRadius).toEqual(cylinder.topRadius.getValue()); expect(dynamicUpdater._options.bottomRadius).toEqual(cylinder.bottomRadius.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + cylinder.show.setValue(false); dynamicUpdater.update(JulianDate.now()); expect(primitives.length).toBe(0); diff --git a/Specs/DataSources/EllipseGeometryUpdaterSpec.js b/Specs/DataSources/EllipseGeometryUpdaterSpec.js index 72a5e0689b5a..5f5fa040df80 100644 --- a/Specs/DataSources/EllipseGeometryUpdaterSpec.js +++ b/Specs/DataSources/EllipseGeometryUpdaterSpec.js @@ -436,6 +436,11 @@ defineSuite([ expect(dynamicUpdater._options.semiMajorAxis).toEqual(ellipse.semiMajorAxis.getValue()); expect(dynamicUpdater._options.semiMinorAxis).toEqual(ellipse.semiMinorAxis.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + ellipse.show.setValue(false); dynamicUpdater.update(JulianDate.now()); expect(primitives.length).toBe(0); diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index e0334d374827..7d16b0f754a7 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -527,6 +527,18 @@ defineSuite([ }); }); + it('Feature: visibility works', function() { + var kml = '\ + \ + 0\ + '; + + return KmlDataSource.load(parser.parseFromString(kml, "text/xml")).then(function(dataSource) { + var entity = dataSource.entities.values[0]; + expect(entity.show).toBe(false); + }); + }); + it('Feature: TimeStamp gracefully handles empty fields', function() { var kml = '\ \ diff --git a/Specs/DataSources/PolygonGeometryUpdaterSpec.js b/Specs/DataSources/PolygonGeometryUpdaterSpec.js index 5832d353fd23..6e57d843ff59 100644 --- a/Specs/DataSources/PolygonGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolygonGeometryUpdaterSpec.js @@ -395,6 +395,11 @@ defineSuite([ expect(options.granularity).toEqual(polygon.granularity.getValue()); expect(options.stRotation).toEqual(polygon.stRotation.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + //If a dynamic show returns false, the primitive should go away. polygon.show.setValue(false); dynamicUpdater.update(time); diff --git a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js index 9d146a243b08..a66bacd65dfe 100644 --- a/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js +++ b/Specs/DataSources/PolylineVolumeGeometryUpdaterSpec.js @@ -354,6 +354,11 @@ defineSuite([ expect(options.granularity).toEqual(polylineVolume.granularity.getValue()); expect(options.cornerType).toEqual(polylineVolume.cornerType.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + //If a dynamic show returns false, the primitive should go away. polylineVolume.show.setValue(false); dynamicUpdater.update(time); diff --git a/Specs/DataSources/RectangleGeometryUpdaterSpec.js b/Specs/DataSources/RectangleGeometryUpdaterSpec.js index 4091609e1193..150c3e62a511 100644 --- a/Specs/DataSources/RectangleGeometryUpdaterSpec.js +++ b/Specs/DataSources/RectangleGeometryUpdaterSpec.js @@ -399,6 +399,11 @@ defineSuite([ expect(options.granularity).toEqual(rectangle.granularity.getValue()); expect(options.stRotation).toEqual(rectangle.stRotation.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + //If a dynamic show returns false, the primitive should go away. rectangle.show.setValue(false); dynamicUpdater.update(time); diff --git a/Specs/DataSources/WallGeometryUpdaterSpec.js b/Specs/DataSources/WallGeometryUpdaterSpec.js index 981026b529ea..7f4201ede4d2 100644 --- a/Specs/DataSources/WallGeometryUpdaterSpec.js +++ b/Specs/DataSources/WallGeometryUpdaterSpec.js @@ -361,6 +361,11 @@ defineSuite([ expect(options.maximumHeights).toEqual(wall.maximumHeights.getValue()); expect(options.granularity).toEqual(wall.granularity.getValue()); + entity.show = false; + dynamicUpdater.update(JulianDate.now()); + expect(primitives.length).toBe(0); + entity.show = true; + //If a dynamic show returns false, the primitive should go away. wall.show.setValue(false); dynamicUpdater.update(time); From e584966eef68e31c0a0c3fb439240b740e3474ee Mon Sep 17 00:00:00 2001 From: Matthew Amato Date: Tue, 24 Mar 2015 23:17:37 -0400 Subject: [PATCH 4/4] On second though, don't zoom to invisible geometry. While it's possible, it would create inconsistency with all other viz. --- Source/DataSources/StaticGeometryColorBatch.js | 3 ++- Source/DataSources/StaticGeometryPerMaterialBatch.js | 3 ++- Source/DataSources/StaticOutlineGeometryBatch.js | 3 ++- Source/DataSources/dynamicGeometryGetBoundingSphere.js | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Source/DataSources/StaticGeometryColorBatch.js b/Source/DataSources/StaticGeometryColorBatch.js index 2509fa498ab2..900fdc81d448 100644 --- a/Source/DataSources/StaticGeometryColorBatch.js +++ b/Source/DataSources/StaticGeometryColorBatch.js @@ -173,7 +173,8 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere)) { + if (!defined(attributes) || !defined(attributes.boundingSphere) ||// + (defined(attributes.show) && attributes.show[0] === 0)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/StaticGeometryPerMaterialBatch.js b/Source/DataSources/StaticGeometryPerMaterialBatch.js index 32646291e8be..2f13bb54c524 100644 --- a/Source/DataSources/StaticGeometryPerMaterialBatch.js +++ b/Source/DataSources/StaticGeometryPerMaterialBatch.js @@ -185,7 +185,8 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere)) { + if (!defined(attributes) || !defined(attributes.boundingSphere) ||// + (defined(attributes.show) && attributes.show[0] === 0)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/StaticOutlineGeometryBatch.js b/Source/DataSources/StaticOutlineGeometryBatch.js index 70b3cbba8618..6b1f0715d419 100644 --- a/Source/DataSources/StaticOutlineGeometryBatch.js +++ b/Source/DataSources/StaticOutlineGeometryBatch.js @@ -179,7 +179,8 @@ define([ return BoundingSphereState.PENDING; } var attributes = primitive.getGeometryInstanceAttributes(entity); - if (!defined(attributes) || !defined(attributes.boundingSphere)) { + if (!defined(attributes) || !defined(attributes.boundingSphere) ||// + (defined(attributes.show) && attributes.show[0] === 0)) { return BoundingSphereState.FAILED; } attributes.boundingSphere.clone(result); diff --git a/Source/DataSources/dynamicGeometryGetBoundingSphere.js b/Source/DataSources/dynamicGeometryGetBoundingSphere.js index 6d122b046971..30d5559e4a2b 100644 --- a/Source/DataSources/dynamicGeometryGetBoundingSphere.js +++ b/Source/DataSources/dynamicGeometryGetBoundingSphere.js @@ -27,7 +27,7 @@ define([ var attributes; //Outline and Fill geometries have the same bounding sphere, so just use whichever one is defined and ready - if (defined(primitive) && primitive.ready) { + if (defined(primitive) && primitive.show && primitive.ready) { attributes = primitive.getGeometryInstanceAttributes(entity); if (defined(attributes) && defined(attributes.boundingSphere)) { BoundingSphere.transform(attributes.boundingSphere, primitive.modelMatrix, result); @@ -35,7 +35,7 @@ define([ } } - if (defined(outlinePrimitive) && outlinePrimitive.ready) { + if (defined(outlinePrimitive) && outlinePrimitive.show && outlinePrimitive.ready) { attributes = outlinePrimitive.getGeometryInstanceAttributes(entity); if (defined(attributes) && defined(attributes.boundingSphere)) { BoundingSphere.transform(attributes.boundingSphere, outlinePrimitive.modelMatrix, result);