itowns
Version:
A JS/WebGL framework for 3D geospatial data visualization
97 lines (96 loc) • 3.58 kB
JavaScript
function disposeSingleMaterialAndTextures(material) {
material.dispose();
// dispose textures
for (const key of Object.keys(material)) {
const val = material[key];
if (val && val.isTexture) {
val.dispose();
}
}
}
export default {
/**
* Cleanup obj to release three.js allocated resources
* @param {Object3D} obj object to release
*/
cleanup(obj) {
obj.layer = null;
// THREE.Scene dispose function displays a deprecation message
if (!obj.isScene && typeof obj.dispose === 'function') {
obj.dispose();
} else {
if (obj.geometry) {
obj.geometry.dispose();
// the Object Removal Helper causes inconsistencies
// when it assigns null to a geometry present in the Cache.
// Actually, the cache can provide a mesh whose geometry is null.
// see https://github.com/iTowns/itowns/issues/869
// obj.geometry = null;
}
if (obj.material) {
if (Array.isArray(obj.material)) {
for (const material of obj.material) {
disposeSingleMaterialAndTextures(material);
}
} else {
disposeSingleMaterialAndTextures(obj.material);
}
}
obj.dispatchEvent({
type: 'dispose'
});
}
},
/**
* Remove obj's children belonging to a layer.
* Neither obj nor its children will be disposed!
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
* @param {Object3D} obj The Object3D we want to clean
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
*/
removeChildren(layer, obj) {
const toRemove = obj.children.filter(c => (c.layer && c.layer.id) === layer.id);
obj.remove(...toRemove);
return toRemove;
},
/**
* Remove an obj and all its children belonging to a layer and only cleanup the obj (and not its children).
* obj will be disposed but its children **won't**!
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
* @param {Object3D} obj The Object3D we want to clean
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
*/
removeChildrenAndCleanup(layer, obj) {
const toRemove = obj.children.filter(c => (c.layer && c.layer.id) === layer.id);
obj.remove(...toRemove);
if (obj.layer === layer) {
this.cleanup(obj);
}
return toRemove;
},
/**
* Recursively remove an obj and all its children belonging to a layer.
* All removed obj will have their geometry/material disposed.
* @param {Layer} layer The layer that objects must belong to. Other object are ignored
* @param {Object3D} obj The Object3D we want to clean
* @return {Array} an array of removed Object3D from obj (not including the recursive removals)
*/
removeChildrenAndCleanupRecursively(layer, obj) {
// Objects are filtered by id because the obj hierarchy may also contain labels that have been added as childs
// of the objects which have their own removal logic
let toRemove = obj.children.filter(c => c.layer && c.layer.id === layer.id);
const linked = obj.link && obj.link[layer.id];
if (linked?.children.length) {
toRemove = toRemove.concat(linked.children);
delete obj.link[layer.id];
}
for (const c of toRemove) {
this.removeChildrenAndCleanupRecursively(layer, c);
}
obj.remove(...toRemove);
if (obj.layer && obj.layer.id === layer.id) {
this.cleanup(obj);
}
return toRemove;
}
};