import Check from "../Core/Check.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import PrimitiveCollection from "./PrimitiveCollection.js";
/**
* A primitive collection for helping maintain the order or ground primitives based on a z-index
*
* @private
*/
function OrderedGroundPrimitiveCollection() {
this._length = 0;
this._collections = {};
this._collectionsArray = [];
this.show = true;
}
Object.defineProperties(OrderedGroundPrimitiveCollection.prototype, {
/**
* Gets the number of primitives in the collection.
*
* @memberof OrderedGroundPrimitiveCollection.prototype
*
* @type {number}
* @readonly
*/
length: {
get: function () {
return this._length;
},
},
});
/**
* Adds a primitive to the collection.
*
* @param {GroundPrimitive} primitive The primitive to add.
* @param {number} [zIndex = 0] The index of the primitive
* @returns {GroundPrimitive} The primitive added to the collection.
*/
OrderedGroundPrimitiveCollection.prototype.add = function (primitive, zIndex) {
//>>includeStart('debug', pragmas.debug);
Check.defined("primitive", primitive);
if (defined(zIndex)) {
Check.typeOf.number("zIndex", zIndex);
}
//>>includeEnd('debug');
zIndex = defaultValue(zIndex, 0);
let collection = this._collections[zIndex];
if (!defined(collection)) {
collection = new PrimitiveCollection({ destroyPrimitives: false });
collection._zIndex = zIndex;
this._collections[zIndex] = collection;
const array = this._collectionsArray;
let i = 0;
while (i < array.length && array[i]._zIndex < zIndex) {
i++;
}
array.splice(i, 0, collection);
}
collection.add(primitive);
this._length++;
primitive._zIndex = zIndex;
return primitive;
};
/**
* Adjusts the z-index
* @param {GroundPrimitive} primitive
* @param {number} zIndex
*/
OrderedGroundPrimitiveCollection.prototype.set = function (primitive, zIndex) {
//>>includeStart('debug', pragmas.debug);
Check.defined("primitive", primitive);
Check.typeOf.number("zIndex", zIndex);
//>>includeEnd('debug');
if (zIndex === primitive._zIndex) {
return primitive;
}
this.remove(primitive, true);
this.add(primitive, zIndex);
return primitive;
};
/**
* Removes a primitive from the collection.
*
* @param {object} primitive The primitive to remove.
* @param {boolean} [doNotDestroy = false]
* @returns {boolean} true
if the primitive was removed; false
if the primitive is undefined
or was not found in the collection.
*/
OrderedGroundPrimitiveCollection.prototype.remove = function (
primitive,
doNotDestroy
) {
if (this.contains(primitive)) {
const index = primitive._zIndex;
const collection = this._collections[index];
let result;
if (doNotDestroy) {
result = collection.remove(primitive);
} else {
result = collection.removeAndDestroy(primitive);
}
if (result) {
this._length--;
}
if (collection.length === 0) {
this._collectionsArray.splice(
this._collectionsArray.indexOf(collection),
1
);
this._collections[index] = undefined;
collection.destroy();
}
return result;
}
return false;
};
/**
* Removes all primitives in the collection.
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*
* @see OrderedGroundPrimitiveCollection#destroyPrimitives
*/
OrderedGroundPrimitiveCollection.prototype.removeAll = function () {
const collections = this._collectionsArray;
for (let i = 0; i < collections.length; i++) {
const collection = collections[i];
collection.destroyPrimitives = true;
collection.destroy();
}
this._collections = {};
this._collectionsArray = [];
this._length = 0;
};
/**
* Determines if this collection contains a primitive.
*
* @param {object} primitive The primitive to check for.
* @returns {boolean} true
if the primitive is in the collection; false
if the primitive is undefined
or was not found in the collection.
*/
OrderedGroundPrimitiveCollection.prototype.contains = function (primitive) {
if (!defined(primitive)) {
return false;
}
const collection = this._collections[primitive._zIndex];
return defined(collection) && collection.contains(primitive);
};
/**
* @private
*/
OrderedGroundPrimitiveCollection.prototype.update = function (frameState) {
if (!this.show) {
return;
}
const collections = this._collectionsArray;
for (let i = 0; i < collections.length; i++) {
collections[i].update(frameState);
}
};
/**
* Returns true if this object was destroyed; otherwise, false.
*
* If this object was destroyed, it should not be used; calling any function other than
* isDestroyed
will result in a {@link DeveloperError} exception.
*
* @returns {boolean} True if this object was destroyed; otherwise, false.
*
* @see OrderedGroundPrimitiveCollection#destroy
*/
OrderedGroundPrimitiveCollection.prototype.isDestroyed = function () {
return false;
};
/**
* Destroys the WebGL resources held by each primitive in this collection. Explicitly destroying this
* collection allows for deterministic release of WebGL resources, instead of relying on the garbage
* collector to destroy this collection.
*
* Since destroying a collection destroys all the contained primitives, only destroy a collection
* when you are sure no other code is still using any of the contained primitives.
*
* Once this collection is destroyed, it should not be used; calling any function other than
* isDestroyed
will result in a {@link DeveloperError} exception. Therefore,
* assign the return value (undefined
) to the object as done in the example.
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*
*
* @example
* primitives = primitives && primitives.destroy();
*
* @see OrderedGroundPrimitiveCollection#isDestroyed
*/
OrderedGroundPrimitiveCollection.prototype.destroy = function () {
this.removeAll();
return destroyObject(this);
};
export default OrderedGroundPrimitiveCollection;