diff --git a/CHANGES.md b/CHANGES.md index a506b76ca36d..a3f5cec25e85 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Change Log * Added `Matrix3.getRotation` to get the rotational component of a matrix with scaling removed. [#8182](https://github.com/AnalyticalGraphicsInc/cesium/pull/8182) * Added ability to create partial ellipsoids using both the Entity API and CZML. New ellipsoid geometry properties: `innerRadii`, `minimumClock`, `maximumClock`, `minimumCone`, and `maximumCone`. This affects both `EllipsoidGeometry` and `EllipsoidOutlineGeometry`. See the updated [Sandcastle example](https://cesiumjs.org/Cesium/Apps/Sandcastle/?src=Partial%20Ellipsoids.html&label=Geometries). [#5995](https://github.com/AnalyticalGraphicsInc/cesium/pull/5995) * Added `TileMapResourceImageryProvider` and `OpenStreetMapImageryProvider` classes to improve API consistency: [#4812](https://github.com/AnalyticalGraphicsInc/cesium/issues/4812) +* Added `credit` parameter to `CzmlDataSource`, `GeoJsonDataSource`, `KmlDataSource` and `Model`. [#8173](https://github.com/AnalyticalGraphicsInc/cesium/pull/8173) ##### Fixes :wrench: * `Camera.flyTo` flies to the correct location in 2D when the destination crosses the international date line [#7909](https://github.com/AnalyticalGraphicsInc/cesium/pull/7909) diff --git a/Source/DataSources/CzmlDataSource.js b/Source/DataSources/CzmlDataSource.js index 7562cc37f7ed..69b507e3288e 100644 --- a/Source/DataSources/CzmlDataSource.js +++ b/Source/DataSources/CzmlDataSource.js @@ -9,6 +9,7 @@ define([ '../Core/Color', '../Core/CornerType', '../Core/createGuid', + '../Core/Credit', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', @@ -102,6 +103,7 @@ define([ Color, CornerType, createGuid, + Credit, defaultValue, defined, defineProperties, @@ -2155,11 +2157,28 @@ define([ var promise = czml; var sourceUri = options.sourceUri; + // User specified credit + var credit = options.credit; + if (typeof credit === 'string') { + credit = new Credit(credit); + } + dataSource._credit = credit; + // If the czml is a URL if (typeof czml === 'string' || (czml instanceof Resource)) { czml = Resource.createIfNeeded(czml); promise = czml.fetchJson(); sourceUri = defaultValue(sourceUri, czml.clone()); + + // Add resource credits to our list of credits to display + var resourceCredits = dataSource._resourceCredits; + var credits = czml.credits; + if (defined(credits)) { + var length = credits.length; + for (var i = 0; i < length; i++) { + resourceCredits.push(credits[i]); + } + } } sourceUri = Resource.createIfNeeded(sourceUri); @@ -2232,6 +2251,8 @@ define([ this._version = undefined; this._entityCollection = new EntityCollection(this); this._entityCluster = new EntityCluster(); + this._credit = undefined; + this._resourceCredits = []; } /** @@ -2240,6 +2261,7 @@ define([ * @param {Resource|String|Object} czml A url or CZML object to be processed. * @param {Object} [options] An object with the following properties: * @param {Resource|String} [options.sourceUri] Overrides the url to use for resolving relative links. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * @returns {Promise.} A promise that resolves to the new instance once the data is processed. */ CzmlDataSource.load = function(czml, options) { @@ -2351,6 +2373,16 @@ define([ //>>includeEnd('debug'); this._entityCluster = value; } + }, + /** + * Gets the credit that will be displayed for the data source + * @memberof CzmlDataSource.prototype + * @type {Credit} + */ + credit : { + get : function() { + return this._credit; + } } }); @@ -2400,6 +2432,7 @@ define([ * @param {Resource|String|Object} czml A url or CZML object to be processed. * @param {Object} [options] An object with the following properties: * @param {String} [options.sourceUri] Overrides the url to use for resolving relative links. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * @returns {Promise.} A promise that resolves to this instances once the data is processed. */ CzmlDataSource.prototype.load = function(czml, options) { diff --git a/Source/DataSources/DataSourceDisplay.js b/Source/DataSources/DataSourceDisplay.js index 2f065f247576..d33fbd874ec5 100644 --- a/Source/DataSources/DataSourceDisplay.js +++ b/Source/DataSources/DataSourceDisplay.js @@ -73,6 +73,7 @@ define([ this._eventHelper.add(dataSourceCollection.dataSourceAdded, this._onDataSourceAdded, this); this._eventHelper.add(dataSourceCollection.dataSourceRemoved, this._onDataSourceRemoved, this); this._eventHelper.add(dataSourceCollection.dataSourceMoved, this._onDataSourceMoved, this); + this._eventHelper.add(scene.postRender, this._postRender, this); this._dataSourceCollection = dataSourceCollection; this._scene = scene; @@ -284,6 +285,30 @@ define([ return result; }; + DataSourceDisplay.prototype._postRender = function() { + // Adds credits for all datasources + var frameState = this._scene.frameState; + var dataSources = this._dataSourceCollection; + var length = dataSources.length; + for (var i = 0; i < length; i++) { + var dataSource = dataSources.get(i); + + var credit = dataSource.credit; + if (defined(credit)) { + frameState.creditDisplay.addCredit(credit); + } + + // Credits from the resource that the user can't remove + var credits = dataSource._resourceCredits; + if (defined(credits)) { + var creditCount = credits.length; + for (var c = 0; c < creditCount; c++) { + frameState.creditDisplay.addCredit(credits[c]); + } + } + } + }; + var getBoundingSphereArrayScratch = []; var getBoundingSphereBoundingSphereScratch = new BoundingSphere(); diff --git a/Source/DataSources/GeoJsonDataSource.js b/Source/DataSources/GeoJsonDataSource.js index c0f090ac9794..d849ef4ba2b7 100644 --- a/Source/DataSources/GeoJsonDataSource.js +++ b/Source/DataSources/GeoJsonDataSource.js @@ -3,6 +3,7 @@ define([ '../Core/Cartesian3', '../Core/Color', '../Core/createGuid', + '../Core/Credit', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', @@ -32,6 +33,7 @@ define([ Cartesian3, Color, createGuid, + Credit, defaultValue, defined, defineProperties, @@ -511,6 +513,8 @@ define([ this._promises = []; this._pinBuilder = new PinBuilder(); this._entityCluster = new EntityCluster(); + this._credit = undefined; + this._resourceCredits = []; } /** @@ -526,6 +530,7 @@ define([ * @param {Number} [options.strokeWidth=GeoJsonDataSource.strokeWidth] The default width of polylines and polygon outlines. * @param {Color} [options.fill=GeoJsonDataSource.fill] The default color for polygon interiors. * @param {Boolean} [options.clampToGround=GeoJsonDataSource.clampToGround] true if we want the geometry features (polygons or linestrings) clamped to the ground. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @returns {Promise.} A promise that will resolve when the data is loaded. */ @@ -786,6 +791,16 @@ define([ //>>includeEnd('debug'); this._entityCluster = value; } + }, + /** + * Gets the credit that will be displayed for the data source + * @memberof GeoJsonDataSource.prototype + * @type {Credit} + */ + credit : { + get : function() { + return this._credit; + } } }); @@ -804,6 +819,7 @@ define([ * @param {Number} [options.strokeWidth=GeoJsonDataSource.strokeWidth] The default width of polylines and polygon outlines. * @param {Color} [options.fill=GeoJsonDataSource.fill] The default color for polygon interiors. * @param {Boolean} [options.clampToGround=GeoJsonDataSource.clampToGround] true if we want the features clamped to the ground. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @returns {Promise.} a promise that will resolve when the GeoJSON is loaded. */ @@ -815,16 +831,31 @@ define([ //>>includeEnd('debug'); DataSource.setLoading(this, true); + options = defaultValue(options, defaultValue.EMPTY_OBJECT); + + // User specified credit + var credit = options.credit; + if (typeof credit === 'string') { + credit = new Credit(credit); + } + this._credit = credit; var promise = data; - options = defaultValue(options, defaultValue.EMPTY_OBJECT); var sourceUri = options.sourceUri; if (typeof data === 'string' || (data instanceof Resource)) { data = Resource.createIfNeeded(data); - promise = data.fetchJson(); - sourceUri = defaultValue(sourceUri, data.getUrlComponent()); + + // Add resource credits to our list of credits to display + var resourceCredits = this._resourceCredits; + var credits = data.credits; + if (defined(credits)) { + var length = credits.length; + for (var i = 0; i < length; i++) { + resourceCredits.push(credits[i]); + } + } } options = { diff --git a/Source/DataSources/KmlDataSource.js b/Source/DataSources/KmlDataSource.js index 83535db08e29..8e1b80cba250 100644 --- a/Source/DataSources/KmlDataSource.js +++ b/Source/DataSources/KmlDataSource.js @@ -9,6 +9,7 @@ define([ '../Core/ClockStep', '../Core/Color', '../Core/createGuid', + '../Core/Credit', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', @@ -75,6 +76,7 @@ define([ ClockStep, Color, createGuid, + Credit, defaultValue, defined, defineProperties, @@ -2392,6 +2394,16 @@ define([ data = Resource.createIfNeeded(data); promise = data.fetchBlob(); sourceUri = defaultValue(sourceUri, data.clone()); + + // Add resource credits to our list of credits to display + var resourceCredits = dataSource._resourceCredits; + var credits = data.credits; + if (defined(credits)) { + var length = credits.length; + for (var i = 0; i < length; i++) { + resourceCredits.push(credits[i]); + } + } } else { sourceUri = defaultValue(sourceUri, Resource.DEFAULT.clone()); } @@ -2473,6 +2485,7 @@ define([ * @param {Camera} options.camera The camera that is used for viewRefreshModes and sending camera properties to network links. * @param {Canvas} options.canvas The canvas that is used for sending viewer properties to network links. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The global ellipsoid used for geographical calculations. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @see {@link http://www.opengeospatial.org/standards/kml/|Open Geospatial Consortium KML Standard} * @see {@link https://developers.google.com/kml/|Google KML Documentation} @@ -2526,6 +2539,16 @@ define([ }; this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84); + + // User specified credit + var credit = options.credit; + if (typeof credit === 'string') { + credit = new Credit(credit); + } + this._credit = credit; + + // Create a list of Credit's from the resource that the user can't remove + this._resourceCredits = []; } /** @@ -2538,6 +2561,7 @@ define([ * @param {String} [options.sourceUri] Overrides the url to use for resolving relative links and other KML network features. * @param {Boolean} [options.clampToGround=false] true if we want the geometry features (Polygons, LineStrings and LinearRings) clamped to the ground. * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The global ellipsoid used for geographical calculations. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @returns {Promise.} A promise that will resolve to a new KmlDataSource instance once the KML is loaded. */ @@ -2679,6 +2703,16 @@ define([ //>>includeEnd('debug'); this._entityCluster = value; } + }, + /** + * Gets the credit that will be displayed for the data source + * @memberof KmlDataSource.prototype + * @type {Credit} + */ + credit : { + get : function() { + return this._credit; + } } }); diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index e185a46c7d58..75268e7ae5fa 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -9,6 +9,7 @@ define([ '../Core/Color', '../Core/combine', '../Core/createGuid', + '../Core/Credit', '../Core/defaultValue', '../Core/defined', '../Core/defineProperties', @@ -87,6 +88,7 @@ define([ Color, combine, createGuid, + Credit, defaultValue, defined, defineProperties, @@ -301,6 +303,7 @@ define([ * @param {Number} [options.luminanceAtZenith=0.5] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map. * @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting. * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps. + * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * @see Model.fromGltf * @@ -356,6 +359,16 @@ define([ var basePath = defaultValue(options.basePath, ''); this._resource = Resource.createIfNeeded(basePath); + // User specified credit + var credit = options.credit; + if (typeof credit === 'string') { + credit = new Credit(credit); + } + this._credit = credit; + + // Create a list of Credit's so they can be added from the Resource later + this._resourceCredits = []; + /** * Determines if the model primitive will be shown. * @@ -1245,6 +1258,16 @@ define([ this._shouldUpdateSpecularMapAtlas = this._shouldUpdateSpecularMapAtlas || value !== this._specularEnvironmentMaps; this._specularEnvironmentMaps = value; } + }, + /** + * Gets the credit that will be displayed for the model + * @memberof Model.prototype + * @type {Credit} + */ + credit : { + get : function() { + return this._credit; + } } }); @@ -1342,6 +1365,7 @@ define([ * @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels. * @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model. * @param {Boolean} [options.dequantizeInShader=true] Determines if a {@link https://github.com/google/draco|Draco} encoded model is dequantized on the GPU. This decreases total memory usage for encoded models. + * @param {Credit|String} [options.credit] A credit for the model, which is displayed on the canvas. * * @returns {Model} The newly created model. * @@ -1432,6 +1456,15 @@ define([ var json = getStringFromTypedArray(array); cachedGltf.makeReady(JSON.parse(json)); } + + var resourceCredits = model._resourceCredits; + var credits = modelResource.credits; + if (defined(credits)) { + var length = credits.length; + for (var i = 0; i < length; i++) { + resourceCredits.push(credits[i]); + } + } }).otherwise(ModelUtility.getFailedLoadFunction(model, 'model', modelResource.url)); } else if (!cachedGltf.ready) { // Cache hit but the fetchArrayBuffer() or fetchText() request is still pending @@ -4949,6 +4982,17 @@ define([ } } } + + var credit = this._credit; + if (defined(credit)) { + frameState.creditDisplay.addCredit(credit); + } + + var resourceCredits = this._resourceCredits; + var creditCount = resourceCredits.length; + for (var c = 0; c < creditCount; c++) { + frameState.creditDisplay.addCredit(resourceCredits[c]); + } }; function destroyIfNotCached(rendererResources, cachedRendererResources) { diff --git a/Source/Scene/Scene.js b/Source/Scene/Scene.js index 728c5c985e58..f5e8c03507e9 100644 --- a/Source/Scene/Scene.js +++ b/Source/Scene/Scene.js @@ -3255,8 +3255,6 @@ define([ } frameState.backgroundColor = backgroundColor; - frameState.creditDisplay.beginFrame(); - scene.fog.update(frameState); us.update(frameState); @@ -3302,7 +3300,6 @@ define([ } } - frameState.creditDisplay.endFrame(); context.endFrame(); } @@ -3379,6 +3376,7 @@ define([ if (shouldRender) { this._preRender.raiseEvent(this, time); + frameState.creditDisplay.beginFrame(); tryAndCatchError(this, render); } @@ -3396,6 +3394,7 @@ define([ if (shouldRender) { this._postRender.raiseEvent(this, time); + frameState.creditDisplay.endFrame(); } }; diff --git a/Specs/DataSources/CzmlDataSourceSpec.js b/Specs/DataSources/CzmlDataSourceSpec.js index 10423b4d0683..989b85f89f5a 100644 --- a/Specs/DataSources/CzmlDataSourceSpec.js +++ b/Specs/DataSources/CzmlDataSourceSpec.js @@ -7,6 +7,7 @@ define([ 'Core/ClockStep', 'Core/Color', 'Core/CornerType', + 'Core/Credit', 'Core/DistanceDisplayCondition', 'Core/Event', 'Core/ExtrapolationType', @@ -55,6 +56,7 @@ define([ ClockStep, Color, CornerType, + Credit, DistanceDisplayCondition, Event, ExtrapolationType, @@ -213,6 +215,7 @@ describe('DataSources/CzmlDataSource', function() { expect(dataSource.entities).toBeInstanceOf(EntityCollection); expect(dataSource.entities.values.length).toEqual(0); expect(dataSource.show).toEqual(true); + expect(dataSource.credit).toBeUndefined(); }); it('show sets underlying entity collection show.', function() { @@ -241,6 +244,14 @@ describe('DataSources/CzmlDataSource', function() { }); }); + it('credit gets set from options', function() { + return CzmlDataSource.load(nameCzml, { + credit: 'This is my credit' + }).then(function(dataSource) { + expect(dataSource.credit).toBeInstanceOf(Credit); + }); + }); + it('does not overwrite existing name if CZML name is undefined', function() { var name = 'myName'; var dataSource = new CzmlDataSource(name); diff --git a/Specs/DataSources/GeoJsonDataSourceSpec.js b/Specs/DataSources/GeoJsonDataSourceSpec.js index cc8b98bd76ba..b6f5aa72deca 100644 --- a/Specs/DataSources/GeoJsonDataSourceSpec.js +++ b/Specs/DataSources/GeoJsonDataSourceSpec.js @@ -1,6 +1,7 @@ define([ 'Core/Cartesian3', 'Core/Color', + 'Core/Credit', 'Core/Event', 'Core/JulianDate', 'Core/PolygonHierarchy', @@ -14,6 +15,7 @@ define([ ], function( Cartesian3, Color, + Credit, Event, JulianDate, PolygonHierarchy, @@ -279,6 +281,15 @@ describe('DataSources/GeoJsonDataSource', function() { expect(dataSource.entities).toBeInstanceOf(EntityCollection); expect(dataSource.entities.values.length).toEqual(0); expect(dataSource.show).toBe(true); + expect(dataSource.credit).toBeUndefined(); + }); + + it('credit gets set from options', function() { + return GeoJsonDataSource.load(point, { + credit: 'This is my credit' + }).then(function(dataSource) { + expect(dataSource.credit).toBeInstanceOf(Credit); + }); }); it('setting name raises changed event', function() { diff --git a/Specs/DataSources/KmlDataSourceSpec.js b/Specs/DataSources/KmlDataSourceSpec.js index 20e6d657599b..faba7c66274a 100644 --- a/Specs/DataSources/KmlDataSourceSpec.js +++ b/Specs/DataSources/KmlDataSourceSpec.js @@ -7,6 +7,7 @@ define([ 'Core/ClockStep', 'Core/Color', 'Core/combine', + 'Core/Credit', 'Core/Ellipsoid', 'Core/Event', 'Core/HeadingPitchRange', @@ -46,6 +47,7 @@ define([ ClockStep, Color, combine, + Credit, Ellipsoid, Event, HeadingPitchRange, @@ -151,7 +153,8 @@ describe('DataSources/KmlDataSource', function() { canvas : { clientWidth : 512, clientHeight : 512 - } + }, + credit: 'This is my credit' }; options.camera.frustum.fov = CesiumMath.PI_OVER_FOUR; options.camera.frustum.aspectRatio = 1.0; @@ -172,6 +175,7 @@ describe('DataSources/KmlDataSource', function() { expect(dataSource.loadingEvent).toBeInstanceOf(Event); expect(dataSource.unsupportedNodeEvent).toBeInstanceOf(Event); expect(dataSource.show).toBe(true); + expect(dataSource.credit).toBeInstanceOf(Credit); }); it('setting name raises changed event', function() { diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index 92baa62c4dc4..26c746821af8 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -5,6 +5,7 @@ define([ 'Core/CesiumTerrainProvider', 'Core/Color', 'Core/combine', + 'Core/Credit', 'Core/defaultValue', 'Core/defined', 'Core/defineProperties', @@ -43,6 +44,7 @@ define([ CesiumTerrainProvider, Color, combine, + Credit, defaultValue, defined, defineProperties, @@ -296,6 +298,7 @@ describe('Scene/Model', function() { expect(texturedBoxModel.color).toEqual(Color.WHITE); expect(texturedBoxModel.colorBlendMode).toEqual(ColorBlendMode.HIGHLIGHT); expect(texturedBoxModel.colorBlendAmount).toEqual(0.5); + expect(texturedBoxModel.credit).toBeUndefined(); }); it('preserves query string in url', function() { @@ -335,6 +338,15 @@ describe('Scene/Model', function() { expect(Resource._Implementations.loadWithXhr.calls.argsFor(0)[0]).toEqual(url.url); }); + it('fromGltf takes a credit', function() { + var url = texturedBoxBasePathUrl; + var model = Model.fromGltf({ + url: url, + credit: 'This is my model credit' + }); + expect(model.credit).toBeInstanceOf(Credit); + }); + it('renders', function() { verifyRender(texturedBoxModel); });