cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
273 lines (272 loc) • 10.3 kB
JavaScript
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 };