"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const three_module = require("../../../../../../three@0.154.0/node_modules/three/build/three.module.js");
const CSS2DRenderer = require("../../../../../../three@0.154.0/node_modules/three/examples/jsm/renderers/CSS2DRenderer.js");
const conversions = require("../styles/conversions.js");
const parsers = require("../styles/parsers.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.
 */
const a = new three_module.Vector3();
const b = new three_module.Vector3();
const c = new three_module.Vector3();
const mat = new three_module.Matrix3();
const triangle = new three_module.Triangle();
const quat = new three_module.Quaternion();
class Hotspot extends CSS2DRenderer.CSS2DObject {
  constructor(config) {
    super(document.createElement("div"));
    this.normal = new three_module.Vector3(0, 1, 0);
    this.initialized = false;
    this.referenceCount = 1;
    this.pivot = document.createElement("div");
    this.slot = document.createElement("slot");
    this.element.classList.add("annotation-wrapper");
    this.slot.name = config.name;
    this.element.appendChild(this.pivot);
    this.pivot.appendChild(this.slot);
    this.updatePosition(config.position);
    this.updateNormal(config.normal);
    this.surface = config.surface;
  }
  get facingCamera() {
    return !this.element.classList.contains("hide");
  }
  /**
   * Sets the hotspot to be in the highly visible foreground state.
   */
  show() {
    if (!this.facingCamera || !this.initialized) {
      this.updateVisibility(true);
    }
  }
  /**
   * Sets the hotspot to be in the diminished background state.
   */
  hide() {
    if (this.facingCamera || !this.initialized) {
      this.updateVisibility(false);
    }
  }
  /**
   * Call this when adding elements to the same slot to keep track.
   */
  increment() {
    this.referenceCount++;
  }
  /**
   * Call this when removing elements from the slot; returns true when the slot
   * is unused.
   */
  decrement() {
    if (this.referenceCount > 0) {
      --this.referenceCount;
    }
    return this.referenceCount === 0;
  }
  /**
   * Change the position of the hotspot to the input string, in the same format
   * as the data-position attribute.
   */
  updatePosition(position) {
    if (position == null)
      return;
    const positionNodes = parsers.parseExpressions(position)[0].terms;
    for (let i = 0; i < 3; ++i) {
      this.position.setComponent(i, conversions.normalizeUnit(positionNodes[i]).number);
    }
    this.updateMatrixWorld();
  }
  /**
   * Change the hotspot's normal to the input string, in the same format as the
   * data-normal attribute.
   */
  updateNormal(normal) {
    if (normal == null)
      return;
    const normalNodes = parsers.parseExpressions(normal)[0].terms;
    for (let i = 0; i < 3; ++i) {
      this.normal.setComponent(i, normalNodes[i].number);
    }
  }
  updateSurface(forceUpdate) {
    if (!forceUpdate && this.initialized) {
      return;
    }
    const { mesh, tri, bary } = this;
    if (mesh == null || tri == null || bary == null) {
      return;
    }
    mesh.getVertexPosition(tri.x, a);
    mesh.getVertexPosition(tri.y, b);
    mesh.getVertexPosition(tri.z, c);
    a.toArray(mat.elements, 0);
    b.toArray(mat.elements, 3);
    c.toArray(mat.elements, 6);
    this.position.copy(bary).applyMatrix3(mat);
    const target = this.parent;
    target.worldToLocal(mesh.localToWorld(this.position));
    triangle.set(a, b, c);
    triangle.getNormal(this.normal).transformDirection(mesh.matrixWorld);
    const scene = target.parent;
    quat.setFromAxisAngle(a.set(0, 1, 0), -scene.yaw);
    this.normal.applyQuaternion(quat);
  }
  orient(radians) {
    this.pivot.style.transform = `rotate(${radians}rad)`;
  }
  updateVisibility(show) {
    if (show) {
      this.element.classList.remove("hide");
    } else {
      this.element.classList.add("hide");
    }
    this.slot.assignedNodes().forEach((node) => {
      if (node.nodeType !== Node.ELEMENT_NODE) {
        return;
      }
      const element = node;
      const visibilityAttribute = element.dataset.visibilityAttribute;
      if (visibilityAttribute != null) {
        const attributeName = `data-${visibilityAttribute}`;
        if (show) {
          element.setAttribute(attributeName, "");
        } else {
          element.removeAttribute(attributeName);
        }
      }
      element.dispatchEvent(new CustomEvent("hotspot-visibility", {
        detail: {
          visible: show
        }
      }));
    });
    this.initialized = true;
  }
}
exports.Hotspot = Hotspot;
//# sourceMappingURL=Hotspot.js.map
