diff --git a/CHANGES.md b/CHANGES.md index 6e1cc900642c..3d3a16f4fa23 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ Change Log ### 1.43 - 2018-03-01 +##### Additions :tada: +* Added support for a promise to a resource for `CesiumTerrainProvider`, `createTileMapServiceImageryProvider` and `Cesium3DTileset` [#6204](https://github.com/AnalyticalGraphicsInc/cesium/pull/6204) + ##### Fixes :wrench: * Fixed bug where AxisAlignedBoundingBox did not copy over center value when cloning an undefined result. [#6183](https://github.com/AnalyticalGraphicsInc/cesium/pull/6183) * Fixed `Resource.fetch` when called with no arguments [#6206](https://github.com/AnalyticalGraphicsInc/cesium/issues/6206) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 613c0b95e708..3be6b183b4b2 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -68,7 +68,7 @@ define([ * @constructor * * @param {Object} options Object with the following properties: - * @param {Resource|String} options.url The URL of the Cesium terrain server. + * @param {Resource|String|Promise|Promise} options.url The URL of the Cesium terrain server. * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available. * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available. * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used. @@ -112,11 +112,6 @@ define([ deprecationWarning('CesiumTerrainProvider.proxy', 'The options.proxy parameter has been deprecated. Specify options.url as a Resource instance and set the proxy property there.'); } - var resource = Resource.createIfNeeded(options.url, { - proxy: options.proxy - }); - resource.appendForwardSlash(); - this._tilingScheme = new GeographicTilingScheme({ numberOfLevelZeroTilesX : 2, numberOfLevelZeroTilesY : 1, @@ -156,20 +151,34 @@ define([ this._availability = undefined; + var deferred = when.defer(); this._ready = false; - this._readyPromise = when.defer(); - - var lastResource = resource; - var metadataResource = lastResource.getDerivedResource({ - url: 'layer.json' - }); + this._readyPromise = deferred; var that = this; + var lastResource; + var metadataResource; var metadataError; var layers = this._layers = []; var attribution = ''; var overallAvailability = []; + when(options.url) + .then(function(url) { + var resource = Resource.createIfNeeded(url, { + proxy: options.proxy + }); + resource.appendForwardSlash(); + lastResource = resource; + metadataResource = lastResource.getDerivedResource({ + url: 'layer.json' + }); + + requestMetadata(); + }) + .otherwise(function(e) { + deferred.reject(e); + }); function parseMetadataSuccess(data) { var message; @@ -343,11 +352,10 @@ define([ } function requestMetadata() { - var metadata = metadataResource.fetchJson(); - when(metadata, metadataSuccess, metadataFailure); + when(metadataResource.fetchJson()) + .then(metadataSuccess) + .otherwise(metadataFailure); } - - requestMetadata(); } /** diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 81ee88ae968b..200e480cc7f1 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -94,7 +94,7 @@ define([ * @constructor * * @param {Object} options Object with the following properties: - * @param {Resource|String} options.url The url to a tileset.json file or to a directory containing a tileset.json file. + * @param {Resource|String|Promise|Promise} options.url The url to a tileset.json file or to a directory containing a tileset.json file. * @param {Boolean} [options.show=true] Determines if the tileset will be shown. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] A 4x4 transformation matrix that transforms the tileset's root tile. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the tileset casts or receives shadows from each light source. @@ -165,26 +165,9 @@ define([ Check.defined('options.url', options.url); //>>includeEnd('debug'); - var resource = Resource.createIfNeeded(options.url); - - var tilesetResource = resource; - var basePath; - - if (resource.extension === 'json') { - basePath = resource.getBaseUri(true); - } else if (resource.isDataUri) { - basePath = ''; - } else { - resource.appendForwardSlash(); - tilesetResource = resource.getDerivedResource({ - url: 'tileset.json' - }); - basePath = resource.url; - } - - this._url = resource.url; - this._tilesetUrl = tilesetResource.url; - this._basePath = basePath; + this._url = undefined; + this._tilesetUrl = undefined; + this._basePath = undefined; this._root = undefined; this._asset = undefined; // Metadata for the entire tileset this._properties = undefined; // Metadata for per-model/point/etc properties @@ -699,9 +682,33 @@ define([ this._brokenUrlWorkaround = false; var that = this; + var tilesetResource; + when(options.url) + .then(function(url) { + var basePath; + var resource = Resource.createIfNeeded(url); + + tilesetResource = resource; + + if (resource.extension === 'json') { + basePath = resource.getBaseUri(true); + } else if (resource.isDataUri) { + basePath = ''; + } else { + resource.appendForwardSlash(); + tilesetResource = resource.getDerivedResource({ + url: 'tileset.json' + }); + basePath = resource.url; + } - // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now - Cesium3DTileset.loadJson(tilesetResource) + that._url = resource.url; + that._tilesetUrl = tilesetResource.url; + that._basePath = basePath; + + // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now + return Cesium3DTileset.loadJson(tilesetResource); + }) .then(function(tilesetJson) { return detectBrokenUrlWorkaround(that, tilesetResource, tilesetJson); }) diff --git a/Source/Scene/createTileMapServiceImageryProvider.js b/Source/Scene/createTileMapServiceImageryProvider.js index cf1667f0211a..8034a0b6a871 100644 --- a/Source/Scene/createTileMapServiceImageryProvider.js +++ b/Source/Scene/createTileMapServiceImageryProvider.js @@ -37,7 +37,7 @@ define([ * @exports createTileMapServiceImageryProvider * * @param {Object} [options] Object with the following properties: - * @param {Resource|String} [options.url='.'] Path to image tiles on server. + * @param {Resource|String|Promise|Promise} [options.url='.'] Path to image tiles on server. * @param {String} [options.fileExtension='png'] The file extension for images on the server. * @param {Credit|String} [options.credit=''] A credit for the data source, which is displayed on the canvas. * @param {Number} [options.minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying @@ -95,19 +95,28 @@ define([ deprecationWarning('createTileMapServiceImageryProvider.proxy', 'The options.proxy parameter has been deprecated. Specify options.url as a Resource instance and set the proxy property there.'); } - var resource = Resource.createIfNeeded(options.url, { - proxy : options.proxy - }); - resource.appendForwardSlash(); - - var xmlResource = resource.getDerivedResource({ - url: 'tilemapresource.xml' - }); - var deferred = when.defer(); var imageryProvider = new UrlTemplateImageryProvider(deferred.promise); var metadataError; + var resource; + var xmlResource; + when(options.url) + .then(function(url) { + resource = Resource.createIfNeeded(url, { + proxy : options.proxy + }); + resource.appendForwardSlash(); + + xmlResource = resource.getDerivedResource({ + url: 'tilemapresource.xml' + }); + + requestMetadata(); + }) + .otherwise(function(e) { + deferred.reject(e); + }); function metadataSuccess(xml) { var tileFormatRegex = /tileformat/i; @@ -282,7 +291,6 @@ define([ xmlResource.fetchXML().then(metadataSuccess).otherwise(metadataFailure); } - requestMetadata(); return imageryProvider; } diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index 9a1e8935f272..3fd9b5aee1fa 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -139,6 +139,17 @@ defineSuite([ }); }); + it('resolves readyPromise when url promise is used', function() { + var provider = new CesiumTerrainProvider({ + url : when.resolve('made/up/url') + }); + + return provider.readyPromise.then(function (result) { + expect(result).toBe(true); + expect(provider.ready).toBe(true); + }); + }); + it('resolves readyPromise with Resource', function() { var resource = new Resource({ url : 'made/up/url' @@ -154,6 +165,21 @@ defineSuite([ }); }); + it('rejects readyPromise when url rejects', function() { + var error = new Error(); + var provider = new CesiumTerrainProvider({ + url: when.reject(error) + }); + return provider.readyPromise + .then(function() { + fail('should not resolve'); + }) + .otherwise(function(result) { + expect(result).toBe(error); + expect(provider.ready).toBe(false); + }); + }); + it('uses geographic tiling scheme by default', function() { returnHeightmapTileJson(); diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index c3e2a7fce4d1..7c9160d52220 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -255,6 +255,23 @@ defineSuite([ }); }); + it('Constructor works with promise to resource', function() { + var resource = new Resource({ + url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets' + }); + + // setup tileset with invalid url (overridden loadJson should replace invalid url with correct url) + var tileset = new Cesium3DTileset({ + url : when.resolve(resource) + }); + + return tileset.readyPromise.then(function() { + expect(tileset.ready).toEqual(true); + }).otherwise(function(error) { + fail('should not fail'); + }); + }); + it('Constructor works with directory resource', function() { var resource = new Resource({ url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets' diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js index c9db47dc9ce0..85fd375219d5 100644 --- a/Specs/Scene/createTileMapServiceImageryProviderSpec.js +++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js @@ -1,47 +1,47 @@ defineSuite([ - 'Scene/createTileMapServiceImageryProvider', - 'Core/Cartesian2', - 'Core/Cartographic', - 'Core/DefaultProxy', - 'Core/GeographicProjection', - 'Core/GeographicTilingScheme', - 'Core/getAbsoluteUri', - 'Core/loadImage', - 'Core/loadWithXhr', - 'Core/Math', - 'Core/Rectangle', - 'Core/RequestScheduler', - 'Core/Resource', - 'Core/WebMercatorProjection', - 'Core/WebMercatorTilingScheme', - 'Scene/Imagery', - 'Scene/ImageryLayer', - 'Scene/ImageryState', - 'Scene/UrlTemplateImageryProvider', - 'Specs/pollToPromise', - 'ThirdParty/when' - ], function( - createTileMapServiceImageryProvider, - Cartesian2, - Cartographic, - DefaultProxy, - GeographicProjection, - GeographicTilingScheme, - getAbsoluteUri, - loadImage, - loadWithXhr, - CesiumMath, - Rectangle, - RequestScheduler, - Resource, - WebMercatorProjection, - WebMercatorTilingScheme, - Imagery, - ImageryLayer, - ImageryState, - UrlTemplateImageryProvider, - pollToPromise, - when) { + 'Scene/createTileMapServiceImageryProvider', + 'Core/Cartesian2', + 'Core/Cartographic', + 'Core/DefaultProxy', + 'Core/GeographicProjection', + 'Core/GeographicTilingScheme', + 'Core/getAbsoluteUri', + 'Core/loadImage', + 'Core/loadWithXhr', + 'Core/Math', + 'Core/Rectangle', + 'Core/RequestScheduler', + 'Core/Resource', + 'Core/WebMercatorProjection', + 'Core/WebMercatorTilingScheme', + 'Scene/Imagery', + 'Scene/ImageryLayer', + 'Scene/ImageryState', + 'Scene/UrlTemplateImageryProvider', + 'Specs/pollToPromise', + 'ThirdParty/when' +], function( + createTileMapServiceImageryProvider, + Cartesian2, + Cartographic, + DefaultProxy, + GeographicProjection, + GeographicTilingScheme, + getAbsoluteUri, + loadImage, + loadWithXhr, + CesiumMath, + Rectangle, + RequestScheduler, + Resource, + WebMercatorProjection, + WebMercatorTilingScheme, + Imagery, + ImageryLayer, + ImageryState, + UrlTemplateImageryProvider, + pollToPromise, + when) { 'use strict'; beforeEach(function() { @@ -55,7 +55,7 @@ defineSuite([ it('return a UrlTemplateImageryProvider', function() { var provider = createTileMapServiceImageryProvider({ - url: 'made/up/tms/server/' + url : 'made/up/tms/server/' }); expect(provider).toBeInstanceOf(UrlTemplateImageryProvider); }); @@ -71,9 +71,20 @@ defineSuite([ }); }); + it('resolves readyPromise when promise url is used', function() { + var provider = createTileMapServiceImageryProvider({ + url : when.resolve('made/up/tms/server/') + }); + + return provider.readyPromise.then(function(result) { + expect(result).toBe(true); + expect(provider.ready).toBe(true); + }); + }); + it('resolves readyPromise with Resource', function() { var resource = new Resource({ - url: 'made/up/tms/server/' + url : 'made/up/tms/server/' }); var provider = createTileMapServiceImageryProvider({ @@ -86,6 +97,19 @@ defineSuite([ }); }); + it('rejects readyPromise if options.url rejects', function() { + var error = new Error(); + var provider = createTileMapServiceImageryProvider({ + url : when.reject(error) + }); + return provider.readyPromise.then(function() { + fail('should not resolve'); + }).otherwise(function(result) { + expect(result).toBe(error); + expect(provider.ready).toBe(false); + }); + }); + it('rejects readyPromise on error', function() { loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { // We can't resolve the promise immediately, because then the error would be raised @@ -116,7 +140,7 @@ defineSuite([ return provider.readyPromise.then(function() { fail('should not resolve'); - }).otherwise(function (e) { + }).otherwise(function(e) { expect(provider.ready).toBe(false); expect(e.message).toContain('unsupported profile'); }); @@ -151,7 +175,7 @@ defineSuite([ return provider.readyPromise.then(function() { fail('should not resolve'); - }).otherwise(function (e) { + }).otherwise(function(e) { expect(provider.ready).toBe(false); expect(e.message).toContain('expected tilesets or bbox attributes'); }); @@ -161,6 +185,7 @@ defineSuite([ function createWithoutUrl() { return createTileMapServiceImageryProvider({}); } + expect(createWithoutUrl).toThrowDeveloperError(); }); @@ -276,9 +301,9 @@ defineSuite([ url : 'made/up/tms/server' }); return pollToPromise(function() { - return provider.ready; + return provider.ready; }).then(function() { - expect(provider.credit).toBeUndefined(); + expect(provider.credit).toBeUndefined(); }); }); @@ -288,9 +313,9 @@ defineSuite([ credit : 'Thanks to our awesome made up source of this imagery!' }); return pollToPromise(function() { - return providerWithCredit.ready; + return providerWithCredit.ready; }).then(function() { - expect(providerWithCredit.credit).toBeDefined(); + expect(providerWithCredit.credit).toBeDefined(); }); });