import { Color, DoubleSide, FrontSide, Vector2 } from "../../../../../../../three@0.154.0/node_modules/three/build/three.module.js";
import { PBRMetallicRoughness } from "./pbr-metallic-roughness.js";
import { TextureInfo, TextureUsage } from "./texture-info.js";
import { ThreeDOMElement, $correlatedObjects, $onUpdate } from "./three-dom-element.js";
/* @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;
const $pbrMetallicRoughness = Symbol("pbrMetallicRoughness");
const $normalTexture = Symbol("normalTexture");
const $occlusionTexture = Symbol("occlusionTexture");
const $emissiveTexture = Symbol("emissiveTexture");
const $backingThreeMaterial = Symbol("backingThreeMaterial");
const $applyAlphaCutoff = Symbol("applyAlphaCutoff");
const $getAlphaMode = Symbol("getAlphaMode");
const $lazyLoadGLTFInfo = Symbol("lazyLoadGLTFInfo");
const $initialize = Symbol("initialize");
const $getLoadedMaterial = Symbol("getLoadedMaterial");
const $ensureMaterialIsLoaded = Symbol("ensureMaterialIsLoaded");
const $gltfIndex = Symbol("gltfIndex");
const $setActive = Symbol("setActive");
const $variantIndices = Symbol("variantIndices");
const $isActive = Symbol("isActive");
const $variantSet = Symbol("variantSet");
const $modelVariants = Symbol("modelVariants");
const $name = Symbol("name");
const $pbrTextures = Symbol("pbrTextures");
class Material extends ThreeDOMElement {
  constructor(onUpdate, gltfIndex, isActive, modelVariants, correlatedMaterials, name, lazyLoadInfo = void 0) {
    super(onUpdate, correlatedMaterials);
    this[_a] = /* @__PURE__ */ new Set();
    this[_b] = /* @__PURE__ */ new Map();
    this[$gltfIndex] = gltfIndex;
    this[$isActive] = isActive;
    this[$modelVariants] = modelVariants;
    this[$name] = name;
    if (lazyLoadInfo == null) {
      this[$initialize]();
    } else {
      this[$lazyLoadGLTFInfo] = lazyLoadInfo;
    }
  }
  get [(_a = $variantSet, _b = $pbrTextures, $backingThreeMaterial)]() {
    return this[$correlatedObjects].values().next().value;
  }
  [$initialize]() {
    const onUpdate = this[$onUpdate];
    const correlatedMaterials = this[$correlatedObjects];
    this[$pbrMetallicRoughness] = new PBRMetallicRoughness(onUpdate, correlatedMaterials);
    const { normalMap, aoMap, emissiveMap } = correlatedMaterials.values().next().value;
    this[$normalTexture] = new TextureInfo(onUpdate, TextureUsage.Normal, normalMap, correlatedMaterials);
    this[$occlusionTexture] = new TextureInfo(onUpdate, TextureUsage.Occlusion, aoMap, correlatedMaterials);
    this[$emissiveTexture] = new TextureInfo(onUpdate, TextureUsage.Emissive, emissiveMap, correlatedMaterials);
    const createTextureInfo = (usage) => {
      this[$pbrTextures].set(usage, new TextureInfo(onUpdate, usage, null, correlatedMaterials));
    };
    createTextureInfo(TextureUsage.Clearcoat);
    createTextureInfo(TextureUsage.ClearcoatRoughness);
    createTextureInfo(TextureUsage.ClearcoatNormal);
    createTextureInfo(TextureUsage.SheenColor);
    createTextureInfo(TextureUsage.SheenRoughness);
    createTextureInfo(TextureUsage.Transmission);
    createTextureInfo(TextureUsage.Thickness);
    createTextureInfo(TextureUsage.Specular);
    createTextureInfo(TextureUsage.SpecularColor);
    createTextureInfo(TextureUsage.Iridescence);
    createTextureInfo(TextureUsage.IridescenceThickness);
    createTextureInfo(TextureUsage.Anisotropy);
  }
  async [$getLoadedMaterial]() {
    if (this[$lazyLoadGLTFInfo] != null) {
      const { set, material } = await this[$lazyLoadGLTFInfo].doLazyLoad();
      this[$correlatedObjects] = set;
      this[$initialize]();
      this[$lazyLoadGLTFInfo] = void 0;
      this.ensureLoaded = async () => {
      };
      return material;
    }
    return this[$correlatedObjects].values().next().value;
  }
  colorFromRgb(rgb) {
    const color = new Color();
    if (rgb instanceof Array) {
      color.fromArray(rgb);
    } else {
      color.set(rgb);
    }
    return color;
  }
  [$ensureMaterialIsLoaded]() {
    if (this[$lazyLoadGLTFInfo] == null) {
      return;
    }
    throw new Error(`Material "${this.name}" has not been loaded, call 'await
    myMaterial.ensureLoaded()' before using an unloaded material.`);
  }
  async ensureLoaded() {
    await this[$getLoadedMaterial]();
  }
  get isLoaded() {
    return this[$lazyLoadGLTFInfo] == null;
  }
  get isActive() {
    return this[$isActive];
  }
  [$setActive](isActive) {
    this[$isActive] = isActive;
  }
  get name() {
    return this[$name] || "";
  }
  set name(name) {
    this[$name] = name;
    if (this[$correlatedObjects] != null) {
      for (const threeMaterial of this[$correlatedObjects]) {
        threeMaterial.name = name;
      }
    }
  }
  get pbrMetallicRoughness() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrMetallicRoughness];
  }
  get normalTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$normalTexture];
  }
  get occlusionTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$occlusionTexture];
  }
  get emissiveTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$emissiveTexture];
  }
  get emissiveFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].emissive.toArray();
  }
  get index() {
    return this[$gltfIndex];
  }
  [$variantIndices]() {
    return this[$variantSet];
  }
  hasVariant(name) {
    const variantData = this[$modelVariants].get(name);
    return variantData != null && this[$variantSet].has(variantData.index);
  }
  setEmissiveFactor(rgb) {
    this[$ensureMaterialIsLoaded]();
    const color = this.colorFromRgb(rgb);
    for (const material of this[$correlatedObjects]) {
      material.emissive.set(color);
    }
    this[$onUpdate]();
  }
  [$getAlphaMode]() {
    if (this[$backingThreeMaterial].transparent) {
      return "BLEND";
    } else {
      if (this[$backingThreeMaterial].alphaTest > 0) {
        return "MASK";
      }
    }
    return "OPAQUE";
  }
  [$applyAlphaCutoff]() {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      if (this[$getAlphaMode]() === "MASK") {
        if (material.alphaTest == void 0) {
          material.alphaTest = 0.5;
        }
      } else {
        material.alphaTest = void 0;
      }
      material.needsUpdate = true;
    }
  }
  setAlphaCutoff(cutoff) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.alphaTest = cutoff;
      material.needsUpdate = true;
    }
    this[$applyAlphaCutoff]();
    this[$onUpdate]();
  }
  getAlphaCutoff() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].alphaTest;
  }
  setDoubleSided(doubleSided) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.side = doubleSided ? DoubleSide : FrontSide;
      material.needsUpdate = true;
    }
    this[$onUpdate]();
  }
  getDoubleSided() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].side == DoubleSide;
  }
  setAlphaMode(alphaMode) {
    this[$ensureMaterialIsLoaded]();
    const enableTransparency = (material, enabled) => {
      material.transparent = enabled;
      material.depthWrite = !enabled;
    };
    for (const material of this[$correlatedObjects]) {
      enableTransparency(material, alphaMode === "BLEND");
      if (alphaMode === "MASK") {
        material.alphaTest = 0.5;
      } else {
        material.alphaTest = void 0;
      }
      material.needsUpdate = true;
    }
    this[$onUpdate]();
  }
  getAlphaMode() {
    this[$ensureMaterialIsLoaded]();
    return this[$getAlphaMode]();
  }
  /**
   * PBR Next properties.
   */
  // KHR_materials_emissive_strength
  get emissiveStrength() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].emissiveIntensity;
  }
  setEmissiveStrength(emissiveStrength) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.emissiveIntensity = emissiveStrength;
    }
    this[$onUpdate]();
  }
  // KHR_materials_clearcoat
  get clearcoatFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].clearcoat;
  }
  get clearcoatRoughnessFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].clearcoatRoughness;
  }
  get clearcoatTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Clearcoat);
  }
  get clearcoatRoughnessTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.ClearcoatRoughness);
  }
  get clearcoatNormalTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.ClearcoatNormal);
  }
  get clearcoatNormalScale() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].clearcoatNormalScale.x;
  }
  setClearcoatFactor(clearcoatFactor) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.clearcoat = clearcoatFactor;
    }
    this[$onUpdate]();
  }
  setClearcoatRoughnessFactor(clearcoatRoughnessFactor) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.clearcoatRoughness = clearcoatRoughnessFactor;
    }
    this[$onUpdate]();
  }
  setClearcoatNormalScale(clearcoatNormalScale) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.clearcoatNormalScale = new Vector2(clearcoatNormalScale, clearcoatNormalScale);
    }
    this[$onUpdate]();
  }
  // KHR_materials_ior
  get ior() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].ior;
  }
  setIor(ior) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.ior = ior;
    }
    this[$onUpdate]();
  }
  // KHR_materials_sheen
  get sheenColorFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].sheenColor.toArray();
  }
  get sheenColorTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.SheenColor);
  }
  get sheenRoughnessFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].sheenRoughness;
  }
  get sheenRoughnessTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.SheenRoughness);
  }
  setSheenColorFactor(rgb) {
    this[$ensureMaterialIsLoaded]();
    const color = this.colorFromRgb(rgb);
    for (const material of this[$correlatedObjects]) {
      material.sheenColor.set(color);
      material.sheen = 1;
    }
    this[$onUpdate]();
  }
  setSheenRoughnessFactor(roughness) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.sheenRoughness = roughness;
      material.sheen = 1;
    }
    this[$onUpdate]();
  }
  // KHR_materials_transmission
  get transmissionFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].transmission;
  }
  get transmissionTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Transmission);
  }
  setTransmissionFactor(transmission) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.transmission = transmission;
    }
    this[$onUpdate]();
  }
  // KHR_materials_volume
  get thicknessFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].thickness;
  }
  get thicknessTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Thickness);
  }
  get attenuationDistance() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].attenuationDistance;
  }
  get attenuationColor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].attenuationColor.toArray();
  }
  setThicknessFactor(thickness) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.thickness = thickness;
    }
    this[$onUpdate]();
  }
  setAttenuationDistance(attenuationDistance) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.attenuationDistance = attenuationDistance;
    }
    this[$onUpdate]();
  }
  setAttenuationColor(rgb) {
    this[$ensureMaterialIsLoaded]();
    const color = this.colorFromRgb(rgb);
    for (const material of this[$correlatedObjects]) {
      material.attenuationColor.set(color);
    }
    this[$onUpdate]();
  }
  // KHR_materials_specular
  get specularFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].specularIntensity;
  }
  get specularTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Specular);
  }
  get specularColorFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].specularColor.toArray();
  }
  get specularColorTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.SheenColor);
  }
  setSpecularFactor(specularFactor) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.specularIntensity = specularFactor;
    }
    this[$onUpdate]();
  }
  setSpecularColorFactor(rgb) {
    this[$ensureMaterialIsLoaded]();
    const color = this.colorFromRgb(rgb);
    for (const material of this[$correlatedObjects]) {
      material.specularColor.set(color);
    }
    this[$onUpdate]();
  }
  // KHR_materials_iridescence
  get iridescenceFactor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].iridescence;
  }
  get iridescenceTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Iridescence);
  }
  get iridescenceIor() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].iridescenceIOR;
  }
  get iridescenceThicknessMinimum() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].iridescenceThicknessRange[0];
  }
  get iridescenceThicknessMaximum() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].iridescenceThicknessRange[1];
  }
  get iridescenceThicknessTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.IridescenceThickness);
  }
  setIridescenceFactor(iridescence) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.iridescence = iridescence;
    }
    this[$onUpdate]();
  }
  setIridescenceIor(ior) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.iridescenceIOR = ior;
    }
    this[$onUpdate]();
  }
  setIridescenceThicknessMinimum(thicknessMin) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.iridescenceThicknessRange[0] = thicknessMin;
    }
    this[$onUpdate]();
  }
  setIridescenceThicknessMaximum(thicknessMax) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.iridescenceThicknessRange[1] = thicknessMax;
    }
    this[$onUpdate]();
  }
  // KHR_materials_anisotropy
  get anisotropyStrength() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].anisotropy;
  }
  get anisotropyRotation() {
    this[$ensureMaterialIsLoaded]();
    return this[$backingThreeMaterial].anisotropyRotation;
  }
  get anisotropyTexture() {
    this[$ensureMaterialIsLoaded]();
    return this[$pbrTextures].get(TextureUsage.Anisotropy);
  }
  setAnisotropyStrength(strength) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.anisotropy = strength;
    }
    this[$onUpdate]();
  }
  setAnisotropyRotation(rotation) {
    this[$ensureMaterialIsLoaded]();
    for (const material of this[$correlatedObjects]) {
      material.anisotropyRotation = rotation;
    }
    this[$onUpdate]();
  }
}
export {
  $ensureMaterialIsLoaded,
  $getLoadedMaterial,
  $gltfIndex,
  $lazyLoadGLTFInfo,
  $setActive,
  $variantIndices,
  $variantSet,
  Material
};
//# sourceMappingURL=material.js.map
