Add existing to tracked
This commit is contained in:
+331
@@ -0,0 +1,331 @@
|
||||
import {
|
||||
Frozen,
|
||||
defined,
|
||||
DeveloperError,
|
||||
EllipsoidTerrainProvider,
|
||||
ImageryLayer,
|
||||
Terrain,
|
||||
} from "@cesium/engine";
|
||||
import knockout from "../ThirdParty/knockout.js";
|
||||
import createCommand from "../createCommand.js";
|
||||
|
||||
/**
|
||||
* The view model for {@link BaseLayerPicker}.
|
||||
* @alias BaseLayerPickerViewModel
|
||||
* @constructor
|
||||
*
|
||||
* @param {object} options Object with the following properties:
|
||||
* @param {Globe} options.globe The Globe to use.
|
||||
* @param {ProviderViewModel[]} [options.imageryProviderViewModels=[]] The array of ProviderViewModel instances to use for imagery.
|
||||
* @param {ProviderViewModel} [options.selectedImageryProviderViewModel] The view model for the current base imagery layer, if not supplied the first available imagery layer is used.
|
||||
* @param {ProviderViewModel[]} [options.terrainProviderViewModels=[]] The array of ProviderViewModel instances to use for terrain.
|
||||
* @param {ProviderViewModel} [options.selectedTerrainProviderViewModel] The view model for the current base terrain layer, if not supplied the first available terrain layer is used.
|
||||
*
|
||||
* @exception {DeveloperError} imageryProviderViewModels must be an array.
|
||||
* @exception {DeveloperError} terrainProviderViewModels must be an array.
|
||||
*/
|
||||
function BaseLayerPickerViewModel(options) {
|
||||
options = options ?? Frozen.EMPTY_OBJECT;
|
||||
|
||||
const globe = options.globe;
|
||||
const imageryProviderViewModels =
|
||||
options.imageryProviderViewModels ?? Frozen.EMPTY_ARRAY;
|
||||
const terrainProviderViewModels =
|
||||
options.terrainProviderViewModels ?? Frozen.EMPTY_ARRAY;
|
||||
|
||||
//>>includeStart('debug', pragmas.debug);
|
||||
if (!defined(globe)) {
|
||||
throw new DeveloperError("globe is required");
|
||||
}
|
||||
//>>includeEnd('debug');
|
||||
|
||||
this._globe = globe;
|
||||
|
||||
/**
|
||||
* Gets or sets an array of ProviderViewModel instances available for imagery selection.
|
||||
* This property is observable.
|
||||
* @type {ProviderViewModel[]}
|
||||
*/
|
||||
this.imageryProviderViewModels = imageryProviderViewModels.slice(0);
|
||||
|
||||
/**
|
||||
* Gets or sets an array of ProviderViewModel instances available for terrain selection.
|
||||
* This property is observable.
|
||||
* @type {ProviderViewModel[]}
|
||||
*/
|
||||
this.terrainProviderViewModels = terrainProviderViewModels.slice(0);
|
||||
|
||||
/**
|
||||
* Gets or sets whether the imagery selection drop-down is currently visible.
|
||||
* @type {boolean}
|
||||
* @default false
|
||||
*/
|
||||
this.dropDownVisible = false;
|
||||
|
||||
knockout.track(this, [
|
||||
"imageryProviderViewModels",
|
||||
"terrainProviderViewModels",
|
||||
"dropDownVisible",
|
||||
]);
|
||||
|
||||
const imageryObservable = knockout.getObservable(
|
||||
this,
|
||||
"imageryProviderViewModels",
|
||||
);
|
||||
const imageryProviders = knockout.pureComputed(function () {
|
||||
const providers = imageryObservable();
|
||||
const categories = {};
|
||||
let i;
|
||||
for (i = 0; i < providers.length; i++) {
|
||||
const provider = providers[i];
|
||||
const category = provider.category;
|
||||
if (defined(categories[category])) {
|
||||
categories[category].push(provider);
|
||||
} else {
|
||||
categories[category] = [provider];
|
||||
}
|
||||
}
|
||||
const allCategoryNames = Object.keys(categories);
|
||||
|
||||
const result = [];
|
||||
for (i = 0; i < allCategoryNames.length; i++) {
|
||||
const name = allCategoryNames[i];
|
||||
result.push({
|
||||
name: name,
|
||||
providers: categories[name],
|
||||
});
|
||||
}
|
||||
return result;
|
||||
});
|
||||
this._imageryProviders = imageryProviders;
|
||||
|
||||
const terrainObservable = knockout.getObservable(
|
||||
this,
|
||||
"terrainProviderViewModels",
|
||||
);
|
||||
const terrainProviders = knockout.pureComputed(function () {
|
||||
const providers = terrainObservable();
|
||||
const categories = {};
|
||||
let i;
|
||||
for (i = 0; i < providers.length; i++) {
|
||||
const provider = providers[i];
|
||||
const category = provider.category;
|
||||
if (defined(categories[category])) {
|
||||
categories[category].push(provider);
|
||||
} else {
|
||||
categories[category] = [provider];
|
||||
}
|
||||
}
|
||||
const allCategoryNames = Object.keys(categories);
|
||||
|
||||
const result = [];
|
||||
for (i = 0; i < allCategoryNames.length; i++) {
|
||||
const name = allCategoryNames[i];
|
||||
result.push({
|
||||
name: name,
|
||||
providers: categories[name],
|
||||
});
|
||||
}
|
||||
return result;
|
||||
});
|
||||
this._terrainProviders = terrainProviders;
|
||||
|
||||
/**
|
||||
* Gets the button tooltip. This property is observable.
|
||||
* @type {string}
|
||||
*/
|
||||
this.buttonTooltip = undefined;
|
||||
knockout.defineProperty(this, "buttonTooltip", function () {
|
||||
const selectedImagery = this.selectedImagery;
|
||||
const selectedTerrain = this.selectedTerrain;
|
||||
|
||||
const imageryTip = defined(selectedImagery)
|
||||
? selectedImagery.name
|
||||
: undefined;
|
||||
const terrainTip = defined(selectedTerrain)
|
||||
? selectedTerrain.name
|
||||
: undefined;
|
||||
|
||||
if (defined(imageryTip) && defined(terrainTip)) {
|
||||
return `${imageryTip}\n${terrainTip}`;
|
||||
} else if (defined(imageryTip)) {
|
||||
return imageryTip;
|
||||
}
|
||||
return terrainTip;
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets the button background image. This property is observable.
|
||||
* @type {string}
|
||||
*/
|
||||
this.buttonImageUrl = undefined;
|
||||
knockout.defineProperty(this, "buttonImageUrl", function () {
|
||||
const selectedImagery = this.selectedImagery;
|
||||
if (defined(selectedImagery)) {
|
||||
return selectedImagery.iconUrl;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets or sets the currently selected imagery. This property is observable.
|
||||
* @type {ProviderViewModel}
|
||||
* @default undefined
|
||||
*/
|
||||
this.selectedImagery = undefined;
|
||||
const selectedImageryViewModel = knockout.observable();
|
||||
|
||||
this._currentImageryLayers = [];
|
||||
knockout.defineProperty(this, "selectedImagery", {
|
||||
get: function () {
|
||||
return selectedImageryViewModel();
|
||||
},
|
||||
set: function (value) {
|
||||
if (selectedImageryViewModel() === value) {
|
||||
this.dropDownVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let i;
|
||||
const currentImageryLayers = this._currentImageryLayers;
|
||||
const currentImageryLayersLength = currentImageryLayers.length;
|
||||
const imageryLayers = this._globe.imageryLayers;
|
||||
let hadExistingBaseLayer = false;
|
||||
for (i = 0; i < currentImageryLayersLength; i++) {
|
||||
const layersLength = imageryLayers.length;
|
||||
for (let x = 0; x < layersLength; x++) {
|
||||
const layer = imageryLayers.get(x);
|
||||
if (layer === currentImageryLayers[i]) {
|
||||
imageryLayers.remove(layer);
|
||||
hadExistingBaseLayer = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defined(value)) {
|
||||
const newProviders = value.creationCommand();
|
||||
if (Array.isArray(newProviders)) {
|
||||
const newProvidersLength = newProviders.length;
|
||||
this._currentImageryLayers = [];
|
||||
for (i = newProvidersLength - 1; i >= 0; i--) {
|
||||
const layer = ImageryLayer.fromProviderAsync(newProviders[i]);
|
||||
imageryLayers.add(layer, 0);
|
||||
this._currentImageryLayers.push(layer);
|
||||
}
|
||||
} else {
|
||||
this._currentImageryLayers = [];
|
||||
const layer = ImageryLayer.fromProviderAsync(newProviders);
|
||||
layer.name = value.name;
|
||||
if (hadExistingBaseLayer) {
|
||||
imageryLayers.add(layer, 0);
|
||||
} else {
|
||||
const baseLayer = imageryLayers.get(0);
|
||||
if (defined(baseLayer)) {
|
||||
imageryLayers.remove(baseLayer);
|
||||
}
|
||||
imageryLayers.add(layer, 0);
|
||||
}
|
||||
this._currentImageryLayers.push(layer);
|
||||
}
|
||||
}
|
||||
selectedImageryViewModel(value);
|
||||
this.dropDownVisible = false;
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets or sets the currently selected terrain. This property is observable.
|
||||
* @type {ProviderViewModel}
|
||||
* @default undefined
|
||||
*/
|
||||
this.selectedTerrain = undefined;
|
||||
const selectedTerrainViewModel = knockout.observable();
|
||||
|
||||
knockout.defineProperty(this, "selectedTerrain", {
|
||||
get: function () {
|
||||
return selectedTerrainViewModel();
|
||||
},
|
||||
set: function (value) {
|
||||
if (selectedTerrainViewModel() === value) {
|
||||
this.dropDownVisible = false;
|
||||
return;
|
||||
}
|
||||
|
||||
let newProvider;
|
||||
if (defined(value)) {
|
||||
newProvider = value.creationCommand();
|
||||
}
|
||||
|
||||
// If this is not a promise, we must set this synchronously to avoid overriding depthTestAgainstTerrain
|
||||
// See https://github.com/CesiumGS/cesium/issues/6991
|
||||
if (defined(newProvider) && !defined(newProvider.then)) {
|
||||
this._globe.depthTestAgainstTerrain = !(
|
||||
newProvider instanceof EllipsoidTerrainProvider
|
||||
);
|
||||
this._globe.terrainProvider = newProvider;
|
||||
} else if (defined(newProvider)) {
|
||||
let cancelUpdate = false;
|
||||
const removeCancelListener =
|
||||
this._globe.terrainProviderChanged.addEventListener(() => {
|
||||
cancelUpdate = true;
|
||||
removeCancelListener();
|
||||
});
|
||||
|
||||
const terrain = new Terrain(newProvider);
|
||||
const removeEventListener = terrain.readyEvent.addEventListener(
|
||||
(terrainProvider) => {
|
||||
if (cancelUpdate) {
|
||||
// Early return in case something has changed outside of the picker.
|
||||
return;
|
||||
}
|
||||
|
||||
this._globe.depthTestAgainstTerrain = !(
|
||||
terrainProvider instanceof EllipsoidTerrainProvider
|
||||
);
|
||||
this._globe.terrainProvider = terrainProvider;
|
||||
removeEventListener();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
selectedTerrainViewModel(value);
|
||||
this.dropDownVisible = false;
|
||||
},
|
||||
});
|
||||
|
||||
const that = this;
|
||||
this._toggleDropDown = createCommand(function () {
|
||||
that.dropDownVisible = !that.dropDownVisible;
|
||||
});
|
||||
|
||||
this.selectedImagery =
|
||||
options.selectedImageryProviderViewModel ?? imageryProviderViewModels[0];
|
||||
this.selectedTerrain = options.selectedTerrainProviderViewModel;
|
||||
}
|
||||
|
||||
Object.defineProperties(BaseLayerPickerViewModel.prototype, {
|
||||
/**
|
||||
* Gets the command to toggle the visibility of the drop down.
|
||||
* @memberof BaseLayerPickerViewModel.prototype
|
||||
*
|
||||
* @type {Command}
|
||||
*/
|
||||
toggleDropDown: {
|
||||
get: function () {
|
||||
return this._toggleDropDown;
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the globe.
|
||||
* @memberof BaseLayerPickerViewModel.prototype
|
||||
*
|
||||
* @type {Globe}
|
||||
*/
|
||||
globe: {
|
||||
get: function () {
|
||||
return this._globe;
|
||||
},
|
||||
},
|
||||
});
|
||||
export default BaseLayerPickerViewModel;
|
||||
Reference in New Issue
Block a user