note_ui_UI.js

import { Element } from '../note';

import { checkParentChild } from '@ud-viz/utils_browser';
import * as THREE from 'three';
import { ScriptBase } from '@ud-viz/game_browser';
import { ExternalScriptComponent } from '@ud-viz/game_shared';
import { constant } from '@ud-viz/game_shared_template';

import './style.css';

/** @classdesc - Manage global ui of the note feature */
export class UI extends ScriptBase {
  init() {
    const domElement = document.createElement('div');
    domElement.classList.add('root_note_ui');
    this.context.frame3D.domElementUI.appendChild(domElement);

    const foldButton = document.createElement('div');
    foldButton.classList.add('fold_button_note_ui');
    domElement.appendChild(foldButton);

    let fold = false;
    foldButton.onclick = () => {
      if (fold) {
        domElement.style.transform = 'translate(0%,0%)';
      } else {
        domElement.style.transform = 'translate(-100%,0%)';
      }
      fold = !fold;
    };

    this.uiContainer = document.createElement('div');
    this.uiContainer.classList.add('container_note_ui');
    domElement.appendChild(this.uiContainer);

    // instruction
    const intructionsHtml = document.createElement('div');
    intructionsHtml.innerHTML =
      'n : Add Note<br>- : Decrease pointer scale<br>+ : Increase pointer scale';
    this.uiContainer.appendChild(intructionsHtml);

    // allow to click on note
    const raycaster = new THREE.Raycaster();
    this.context.inputManager.addMouseInput(
      this.context.frame3D.domElementWebGL,
      'click',
      (event) => {
        if (checkParentChild(event.target, this.context.frame3D.ui)) return;

        const mouse = new THREE.Vector2(
          -1 +
            (2 * event.offsetX) /
              (this.context.frame3D.domElementWebGL.clientWidth -
                parseInt(this.context.frame3D.domElementWebGL.offsetLeft)),
          1 -
            (2 * event.offsetY) /
              (this.context.frame3D.domElementWebGL.clientHeight -
                parseInt(this.context.frame3D.domElementWebGL.offsetTop))
        );

        raycaster.setFromCamera(mouse, this.context.frame3D.camera);

        let minDist = Infinity;
        let closestNote = null;
        this.context.object3D.traverse((child) => {
          if (!child.userData.isNote) return;
          const i = raycaster.intersectObject(child, true);
          if (i.length && i[0].distance < minDist) {
            minDist = i[0].distance;
            closestNote = child;
          }
        });

        if (closestNote) {
          const externalScriptComp = closestNote.getComponent(
            ExternalScriptComponent.TYPE
          );
          externalScriptComp
            .getController()
            .scripts.get(Element.ID_SCRIPT)
            .displayNoteMessageHtml();
        }
      }
    );
  }

  appendToHtml(el) {
    this.uiContainer.appendChild(el);
  }

  static get ID_SCRIPT() {
    return constant.ID_SCRIPT.NOTE_UI;
  }
}