UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

273 lines (272 loc) 10.3 kB
import { Mesh } from "../../../../../_three@0.150.1@three/build/three.module.mjs"; import { Material, $setActive, $variantSet } from "./material.mjs"; import { PrimitiveNode, Node } from "./nodes/primitive-node.mjs"; import { $correlatedObjects, $sourceObject } from "./three-dom-element.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. */ var _a, _b, _c, _d, _e, _f; const $materials = Symbol("materials"); const $hierarchy = Symbol("hierarchy"); const $roots = Symbol("roots"); const $primitivesList = Symbol("primitives"); const $correlatedSceneGraph = Symbol("correlatedSceneGraph"); const $prepareVariantsForExport = Symbol("prepareVariantsForExport"); const $switchVariant = Symbol("switchVariant"); const $materialFromPoint = Symbol("materialFromPoint"); const $nodeFromPoint = Symbol("nodeFromPoint"); const $nodeFromIndex = Symbol("nodeFromIndex"); const $variantData = Symbol("variantData"); const $availableVariants = Symbol("availableVariants"); const $modelOnUpdate = Symbol("modelOnUpdate"); const $cloneMaterial = Symbol("cloneMaterial"); class LazyLoader { constructor(gltf, gltfElementMap, mapKey, doLazyLoad) { this.gltf = gltf; this.gltfElementMap = gltfElementMap; this.mapKey = mapKey; this.doLazyLoad = doLazyLoad; } } class Model { constructor(correlatedSceneGraph, onUpdate = () => { }) { this[_a] = new Array(); this[_b] = new Array(); this[_c] = new Array(); this[_d] = new Array(); this[_e] = () => { }; this[_f] = /* @__PURE__ */ new Map(); this[$modelOnUpdate] = onUpdate; this[$correlatedSceneGraph] = correlatedSceneGraph; const { gltf, threeGLTF, gltfElementMap } = correlatedSceneGraph; for (const [i, material] of gltf.materials.entries()) { const correlatedMaterial = gltfElementMap.get(material); if (correlatedMaterial != null) { this[$materials].push(new Material(onUpdate, gltf, material, i, true, this[$variantData], correlatedMaterial)); } else { const elementArray = gltf["materials"] || []; const gltfMaterialDef = elementArray[i]; const capturedMatIndex = i; const materialLoadCallback = async () => { const threeMaterial = await threeGLTF.parser.getDependency("material", capturedMatIndex); const threeMaterialSet = /* @__PURE__ */ new Set(); gltfElementMap.set(gltfMaterialDef, threeMaterialSet); threeMaterialSet.add(threeMaterial); return { set: threeMaterialSet, material: threeMaterial }; }; this[$materials].push(new Material(onUpdate, gltf, gltfMaterialDef, i, false, this[$variantData], correlatedMaterial, new LazyLoader(gltf, gltfElementMap, gltfMaterialDef, materialLoadCallback))); } } const parentMap = /* @__PURE__ */ new Map(); const nodeStack = new Array(); for (const object of threeGLTF.scene.children) { nodeStack.push(object); } while (nodeStack.length > 0) { const object = nodeStack.pop(); let node = null; if (object instanceof Mesh) { node = new PrimitiveNode(object, this.materials, this[$variantData], correlatedSceneGraph); this[$primitivesList].push(node); } else { node = new Node(object.name); } const parent = parentMap.get(object); if (parent != null) { parent.children.push(node); } else { this[$roots].push(node); } this[$hierarchy].push(node); for (const child of object.children) { nodeStack.push(child); parentMap.set(object, node); } } } get materials() { return this[$materials]; } [(_a = $materials, _b = $hierarchy, _c = $roots, _d = $primitivesList, _e = $modelOnUpdate, _f = $variantData, $availableVariants)]() { const variants = Array.from(this[$variantData].values()); variants.sort((a, b) => { return a.index - b.index; }); return variants.map((data) => { return data.name; }); } getMaterialByName(name) { const matches = this[$materials].filter((material) => { return material.name === name; }); if (matches.length > 0) { return matches[0]; } return null; } [$nodeFromIndex](mesh, primitive) { const found = this[$hierarchy].find((node) => { if (node instanceof PrimitiveNode) { const { meshes, primitives } = node.mesh.userData.associations; if (meshes == mesh && primitives == primitive) { return true; } } return false; }); return found == null ? null : found; } [$nodeFromPoint](hit) { return this[$hierarchy].find((node) => { if (node instanceof PrimitiveNode) { const primitive = node; if (primitive.mesh === hit.object) { return true; } } return false; }); } [$materialFromPoint](hit) { return this[$nodeFromPoint](hit).getActiveMaterial(); } async [$switchVariant](variantName) { for (const primitive of this[$primitivesList]) { await primitive.enableVariant(variantName); } for (const material of this.materials) { material[$setActive](false); } for (const primitive of this[$primitivesList]) { this.materials[primitive.getActiveMaterial().index][$setActive](true); } } async [$prepareVariantsForExport]() { const promises = new Array(); for (const primitive of this[$primitivesList]) { promises.push(primitive.instantiateVariants()); } await Promise.all(promises); } [$cloneMaterial](index, newMaterialName) { const material = this.materials[index]; if (!material.isLoaded) { console.error(`Cloning an unloaded material, call 'material.ensureLoaded() before cloning the material.`); } const threeMaterialSet = material[$correlatedObjects]; const gltfSourceMaterial = JSON.parse(JSON.stringify(material[$sourceObject])); gltfSourceMaterial.name = newMaterialName; const gltf = this[$correlatedSceneGraph].gltf; gltf.materials.push(gltfSourceMaterial); const clonedSet = /* @__PURE__ */ new Set(); for (const [i, threeMaterial] of threeMaterialSet.entries()) { const clone = threeMaterial.clone(); clone.name = newMaterialName + (threeMaterialSet.size > 1 ? "_inst" + i : ""); clonedSet.add(clone); } const clonedMaterial = new Material( this[$modelOnUpdate], this[$correlatedSceneGraph].gltf, gltfSourceMaterial, this[$materials].length, false, this[$variantData], clonedSet ); this[$materials].push(clonedMaterial); return clonedMaterial; } createMaterialInstanceForVariant(originalMaterialIndex, newMaterialName, variantName, activateVariant = true) { let variantMaterialInstance = null; for (const primitive of this[$primitivesList]) { const variantData = this[$variantData].get(variantName); if (variantData != null && primitive.variantInfo.has(variantData.index)) { continue; } if (primitive.getMaterial(originalMaterialIndex) == null) { continue; } if (!this.hasVariant(variantName)) { this.createVariant(variantName); } if (variantMaterialInstance == null) { variantMaterialInstance = this[$cloneMaterial](originalMaterialIndex, newMaterialName); } primitive.addVariant(variantMaterialInstance, variantName); } if (activateVariant && variantMaterialInstance != null) { variantMaterialInstance[$setActive](true); this.materials[originalMaterialIndex][$setActive](false); for (const primitive of this[$primitivesList]) { primitive.enableVariant(variantName); } } return variantMaterialInstance; } createVariant(variantName) { if (!this[$variantData].has(variantName)) { this[$variantData].set(variantName, { name: variantName, index: this[$variantData].size }); } else { console.warn(`Variant '${variantName}'' already exists`); } } hasVariant(variantName) { return this[$variantData].has(variantName); } setMaterialToVariant(materialIndex, targetVariantName) { if (this[$availableVariants]().find((name) => name === targetVariantName) == null) { console.warn(`Can't add material to '${targetVariantName}', the variant does not exist.'`); return; } if (materialIndex < 0 || materialIndex >= this.materials.length) { console.error(`setMaterialToVariant(): materialIndex is out of bounds.`); return; } for (const primitive of this[$primitivesList]) { const material = primitive.getMaterial(materialIndex); if (material != null) { primitive.addVariant(material, targetVariantName); } } } updateVariantName(currentName, newName) { const variantData = this[$variantData].get(currentName); if (variantData == null) { return; } variantData.name = newName; this[$variantData].set(newName, variantData); this[$variantData].delete(currentName); } deleteVariant(variantName) { const variant = this[$variantData].get(variantName); if (variant == null) { return; } for (const material of this.materials) { if (material.hasVariant(variantName)) { material[$variantSet].delete(variant.index); } } for (const primitive of this[$primitivesList]) { primitive.deleteVariant(variant.index); } this[$variantData].delete(variantName); } } export { $availableVariants, $correlatedSceneGraph, $materialFromPoint, $materials, $nodeFromIndex, $nodeFromPoint, $prepareVariantsForExport, $primitivesList, $switchVariant, $variantData, LazyLoader, Model };