"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const property = require("../../../../../../@lit_reactive-element@1.6.3/node_modules/@lit/reactive-element/decorators/property.js");
require("../../../../../../@lit_reactive-element@1.6.3/node_modules/@lit/reactive-element/decorators/query-assigned-elements.js");
const three_module = require("../../../../../../three@0.154.0/node_modules/three/build/three.module.js");
const GLTFExporter = require("../../../../../../three@0.154.0/node_modules/three/examples/jsm/exporters/GLTFExporter.js");
const modelViewerBase = require("../model-viewer-base.js");
const VariantMaterialExporterPlugin = require("../three-components/gltf-instance/VariantMaterialExporterPlugin.js");
const model = require("./scene-graph/model.js");
const texture = require("./scene-graph/texture.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 __decorate = globalThis && globalThis.__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;
};
const $currentGLTF = Symbol("currentGLTF");
const $originalGltfJson = Symbol("originalGltfJson");
const $model = Symbol("model");
const $getOnUpdateMethod = Symbol("getOnUpdateMethod");
const $buildTexture = Symbol("buildTexture");
const SceneGraphMixin = (ModelViewerElement) => {
  var _a, _b, _c;
  class SceneGraphModelViewerElement extends ModelViewerElement {
    constructor() {
      super(...arguments);
      this[_a] = void 0;
      this[_b] = null;
      this[_c] = null;
      this.variantName = null;
      this.orientation = "0 0 0";
      this.scale = "1 1 1";
    }
    // Scene-graph API:
    /** @export */
    get model() {
      return this[$model];
    }
    get availableVariants() {
      return this.model ? this.model[model.$availableVariants]() : [];
    }
    /**
     * Returns a deep copy of the gltf JSON as loaded. It will not reflect
     * changes to the scene-graph, nor will editing it have any effect.
     */
    get originalGltfJson() {
      return this[$originalGltfJson];
    }
    [(_a = $model, _b = $currentGLTF, _c = $originalGltfJson, $getOnUpdateMethod)]() {
      return () => {
        this[modelViewerBase.$needsRender]();
      };
    }
    [$buildTexture](texture$1) {
      texture$1.encoding = three_module.sRGBEncoding;
      texture$1.wrapS = three_module.RepeatWrapping;
      texture$1.wrapT = three_module.RepeatWrapping;
      return new texture.Texture(this[$getOnUpdateMethod](), texture$1);
    }
    async createTexture(uri, type = "image/png") {
      const { textureUtils } = this[modelViewerBase.$renderer];
      const texture2 = await textureUtils.loadImage(uri);
      texture2.userData.mimeType = type;
      return this[$buildTexture](texture2);
    }
    async createLottieTexture(uri, quality = 1) {
      const { textureUtils } = this[modelViewerBase.$renderer];
      const texture2 = await textureUtils.loadLottie(uri, quality);
      return this[$buildTexture](texture2);
    }
    createVideoTexture(uri) {
      const video = document.createElement("video");
      video.src = uri;
      video.muted = true;
      video.playsInline = true;
      video.loop = true;
      video.play();
      const texture2 = new three_module.VideoTexture(video);
      return this[$buildTexture](texture2);
    }
    createCanvasTexture() {
      const canvas = document.createElement("canvas");
      const texture2 = new three_module.CanvasTexture(canvas);
      return this[$buildTexture](texture2);
    }
    async updated(changedProperties) {
      super.updated(changedProperties);
      if (changedProperties.has("variantName")) {
        const updateVariantProgress = this[modelViewerBase.$progressTracker].beginActivity();
        updateVariantProgress(0.1);
        const model$1 = this[$model];
        const { variantName } = this;
        if (model$1 != null) {
          await model$1[model.$switchVariant](variantName);
          this[modelViewerBase.$needsRender]();
          this.dispatchEvent(new CustomEvent("variant-applied"));
        }
        updateVariantProgress(1);
      }
      if (changedProperties.has("orientation") || changedProperties.has("scale")) {
        if (!this.loaded) {
          return;
        }
        const scene = this[modelViewerBase.$scene];
        scene.applyTransform();
        scene.updateBoundingBox();
        scene.updateShadow();
        this[modelViewerBase.$renderer].arRenderer.onUpdateScene();
        this[modelViewerBase.$needsRender]();
      }
    }
    [modelViewerBase.$onModelLoad]() {
      super[modelViewerBase.$onModelLoad]();
      const { currentGLTF } = this[modelViewerBase.$scene];
      if (currentGLTF != null) {
        const { correlatedSceneGraph } = currentGLTF;
        if (correlatedSceneGraph != null && currentGLTF !== this[$currentGLTF]) {
          this[$model] = new model.Model(correlatedSceneGraph, this[$getOnUpdateMethod]());
          this[$originalGltfJson] = JSON.parse(JSON.stringify(correlatedSceneGraph.gltf));
        }
        if ("variants" in currentGLTF.userData) {
          this.requestUpdate("variantName");
        }
      }
      this[$currentGLTF] = currentGLTF;
    }
    /** @export */
    async exportScene(options) {
      const scene = this[modelViewerBase.$scene];
      return new Promise(async (resolve, reject) => {
        const opts = {
          binary: true,
          onlyVisible: true,
          maxTextureSize: Infinity,
          includeCustomExtensions: false,
          forceIndices: false
        };
        Object.assign(opts, options);
        opts.animations = scene.animations;
        opts.truncateDrawRange = true;
        const shadow = scene.shadow;
        let visible = false;
        if (shadow != null) {
          visible = shadow.visible;
          shadow.visible = false;
        }
        await this[$model][model.$prepareVariantsForExport]();
        const exporter = new GLTFExporter.GLTFExporter().register((writer) => new VariantMaterialExporterPlugin(writer));
        exporter.parse(scene.model, (gltf) => {
          return resolve(new Blob([opts.binary ? gltf : JSON.stringify(gltf)], {
            type: opts.binary ? "application/octet-stream" : "application/json"
          }));
        }, () => {
          return reject("glTF export failed");
        }, opts);
        if (shadow != null) {
          shadow.visible = visible;
        }
      });
    }
    materialFromPoint(pixelX, pixelY) {
      const model$1 = this[$model];
      if (model$1 == null) {
        return null;
      }
      const scene = this[modelViewerBase.$scene];
      const ndcCoords = scene.getNDC(pixelX, pixelY);
      const hit = scene.hitFromPoint(ndcCoords);
      if (hit == null || hit.face == null) {
        return null;
      }
      return model$1[model.$materialFromPoint](hit);
    }
  }
  __decorate([
    property.property({ type: String, attribute: "variant-name" })
  ], SceneGraphModelViewerElement.prototype, "variantName", void 0);
  __decorate([
    property.property({ type: String, attribute: "orientation" })
  ], SceneGraphModelViewerElement.prototype, "orientation", void 0);
  __decorate([
    property.property({ type: String, attribute: "scale" })
  ], SceneGraphModelViewerElement.prototype, "scale", void 0);
  return SceneGraphModelViewerElement;
};
exports.$currentGLTF = $currentGLTF;
exports.$model = $model;
exports.$originalGltfJson = $originalGltfJson;
exports.SceneGraphMixin = SceneGraphMixin;
//# sourceMappingURL=scene-graph.js.map
