cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
121 lines (120 loc) • 3.9 kB
JavaScript
import { Texture } from "../../../../_three@0.150.1@three/build/three.module.mjs";
import { clone } from "../../../../_three@0.150.1@three/examples/jsm/utils/SkeletonUtils.mjs";
/* @license
* Copyright 2020 Google LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const $prepared = Symbol("prepared");
const $prepare = Symbol("prepare");
const $preparedGLTF = Symbol("preparedGLTF");
const $clone = Symbol("clone");
class GLTFInstance {
constructor(preparedGLTF) {
this[$preparedGLTF] = preparedGLTF;
}
static prepare(source) {
if (source.scene == null) {
throw new Error("Model does not have a scene");
}
if (source[$prepared]) {
return source;
}
const prepared = this[$prepare](source);
prepared[$prepared] = true;
return prepared;
}
static [$prepare](source) {
const { scene } = source;
const scenes = [scene];
return Object.assign(Object.assign({}, source), { scene, scenes });
}
get parser() {
return this[$preparedGLTF].parser;
}
get animations() {
return this[$preparedGLTF].animations;
}
get scene() {
return this[$preparedGLTF].scene;
}
get scenes() {
return this[$preparedGLTF].scenes;
}
get cameras() {
return this[$preparedGLTF].cameras;
}
get asset() {
return this[$preparedGLTF].asset;
}
get userData() {
return this[$preparedGLTF].userData;
}
clone() {
const GLTFInstanceConstructor = this.constructor;
const clonedGLTF = this[$clone]();
return new GLTFInstanceConstructor(clonedGLTF);
}
dispose() {
this.scenes.forEach((scene) => {
scene.traverse((object) => {
if (!object.isMesh) {
return;
}
const mesh = object;
const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];
materials.forEach((material) => {
for (const propertyName in material) {
const texture = material[propertyName];
if (texture instanceof Texture) {
const image = texture.source.data;
if (image.close != null) {
image.close();
}
texture.dispose();
}
}
material.dispose();
});
mesh.geometry.dispose();
});
});
}
[$clone]() {
const source = this[$preparedGLTF];
const scene = clone(this.scene);
cloneVariantMaterials(scene, this.scene);
const scenes = [scene];
const userData = source.userData ? Object.assign({}, source.userData) : {};
return Object.assign(Object.assign({}, source), { scene, scenes, userData });
}
}
const cloneVariantMaterials = (dst, src) => {
traversePair(dst, src, (dst2, src2) => {
if (src2.userData.variantMaterials !== void 0) {
dst2.userData.variantMaterials = new Map(src2.userData.variantMaterials);
}
if (src2.userData.variantData !== void 0) {
dst2.userData.variantData = src2.userData.variantData;
}
if (src2.userData.originalMaterial !== void 0) {
dst2.userData.originalMaterial = src2.userData.originalMaterial;
}
});
};
const traversePair = (obj1, obj2, callback) => {
callback(obj1, obj2);
for (let i = 0; i < obj1.children.length; i++) {
traversePair(obj1.children[i], obj2.children[i], callback);
}
};
export { $clone, $prepare, $prepared, $preparedGLTF, GLTFInstance };