threepipe
Version:
A modern 3D viewer framework built on top of three.js, written in TypeScript, designed to make creating high-quality, modular, and extensible 3D experiences on the web simple and enjoyable.
142 lines • 6.08 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { AViewerPluginSync } from '../../viewer';
import { onChange, serialize } from 'ts-browser-helpers';
import { GLTFMaterialsVariantsExtensionImport, khrMaterialsVariantsGLTF, } from './helpers/GLTFMaterialsVariantsExtensionImport';
import { gltfExporterMaterialsVariantsExtensionExport } from './helpers/GLTFMaterialsVariantsExtensionExport';
/**
* GLTF khr_material_variants plugin
*
* This plugin allows to import and export gltf files with KHR_materials_variants extension.
* The material data is stored in the object userData. The plugin also provides a UI to select the variant.
*
* @category Plugins
*/
export class GLTFKHRMaterialVariantsPlugin extends AViewerPluginSync {
constructor() {
super();
this.enabled = true;
this.variants = {}; // dont serialize this
/**
* The selected variant. Changing this will automatically apply the variant to the objects.
*/
this.selectedVariant = '';
/**
* If true, the first variant will be applied to the objects when object is added and nothing is selected.
*/
this.applyFirstVariantOnLoad = true;
this._objectAdded = (ev) => {
const object = ev.object;
if (!object?.isObject3D)
return;
if (!this._viewer)
return;
object.traverse((obj) => {
if (obj.userData._variantMaterials) {
for (const val of Object.values(obj.userData._variantMaterials)) {
if (val?.material)
val.material = this._viewer?.materialManager.convertToIMaterial(val.material, {}) || val.material;
}
}
const d = obj.userData?.__importData?.[khrMaterialsVariantsGLTF];
if (!d)
return;
const names = d.names || [];
for (const name of names) {
if (!this.variants[name])
this.variants[name] = [];
this.variants[name].push(obj);
}
delete obj.userData.__importData[khrMaterialsVariantsGLTF];
});
if (!this.selectedVariant && this.applyFirstVariantOnLoad) {
this.selectedVariant = Object.keys(this.variants)[0] || '';
}
this.uiConfig.uiRefresh?.();
return;
};
this.uiConfig = {
type: 'folder',
label: 'KHR Material Variants',
children: [
() => ({
children: [null, ...Object.keys(this.variants)].map((label) => !label ? { label: 'none', value: '' } : { label }),
type: 'dropdown',
label: 'Variant',
property: [this, 'selectedVariant'],
}),
],
};
}
onAdded(v) {
super.onAdded(v);
// v.addEventListener('preRender', this._preRender)
v.scene.addEventListener('addSceneObject', this._objectAdded);
v.assetManager.registerGltfExtension(khrMaterialVariantsGLTFExtension);
}
onRemove(v) {
v.scene.removeEventListener('addSceneObject', this._objectAdded);
v.assetManager.unregisterGltfExtension(khrMaterialVariantsGLTFExtension.name);
this.variants = {};
return super.onRemove(v);
}
_variantChanged() {
this.applyVariant(this.selectedVariant || '', true);
}
/**
* Apply the variant to objects.
* It will also change the `selectedVariant` if `root` is not provided.
* @param name
* @param force
* @param root
* @param doTraverse
*/
applyVariant(name, force = false, root, doTraverse = true) {
if (!force && !root && this.selectedVariant === name)
return;
if (!name)
return;
if (!root)
this.selectedVariant = name;
const objects = root ?
Array.isArray(root) ? root : [root] :
name ? this.variants[name] || [] : Object.values(this.variants).flat();
for (const object of objects) {
const done = new Set();
const apply = (obj) => {
if (!obj.userData._variantMaterials || done.has(obj))
return;
const va = name ? obj.userData._variantMaterials[name]?.material : obj.userData._originalMaterial;
if (va) {
if (!obj.userData._originalMaterial)
obj.userData._originalMaterial = obj.material;
obj.material = va;
}
done.add(obj);
};
if (doTraverse)
object.traverse(apply);
else
apply(object);
}
}
}
GLTFKHRMaterialVariantsPlugin.PluginType = 'GLTFKHRMaterialVariantsPlugin';
__decorate([
onChange(GLTFKHRMaterialVariantsPlugin.prototype._variantChanged),
serialize()
], GLTFKHRMaterialVariantsPlugin.prototype, "selectedVariant", void 0);
__decorate([
serialize()
], GLTFKHRMaterialVariantsPlugin.prototype, "applyFirstVariantOnLoad", void 0);
export const khrMaterialVariantsGLTFExtension = {
name: khrMaterialsVariantsGLTF,
import: (p) => new GLTFMaterialsVariantsExtensionImport(p),
export: gltfExporterMaterialsVariantsExtensionExport,
// textures: undefined,
};
//# sourceMappingURL=GLTFKHRMaterialVariantsPlugin.js.map