<template>
  <div ref="threeDom" id="counter">
    <div id="alert-css2"></div>
  </div>
</template>

<script>
import * as THREE from "three";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/examples/jsm/renderers/CSS2DRenderer";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min";
class PositionGUI {
  constructor(obj, name) {
    this.obj = obj;
    this.name = name;
  }
  get modify() {
    return this.obj[this.name];
  }
  set modify(v) {
    this.obj[this.name] = v;
  }
}
export default {
  props: {
    // 楼层
    lv: {
      type: String,
      default: "1",
    },
    // 楼层图接口数据
    floorArr: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      keyobj: {}, //窗口模型
      modlObj: {}, //保存模型对象
      checkedMesh: null, //选中模型
      cloneMttl: null, //窗口材质备份
      FPS: 30,
      timeS: 0,
      renderer: "",
      camera: {},
      scene: "",
      controls: "",
      labelRenderer: "",
      Tips: "",
      ambientLight: "",
      directionalLight: "",
      TWEENN: "",
      SpotLight: "",
      threeDate: {
        isloading: true,
        floorList: {}, //楼层图
        floosrNum: "1",
        checkWind: {}, //选中窗口
      },
    };
  },
  watch: {
    lv(newVal) {
      this.modlObj[this.threeDate.floosrNum].obj.visible = false; //隐藏未选中模型
      this.modlObj[e].obj.visible = true; //显示选中模型
      this.threeDate.floosrNum = newVal;
      // this.css2DOM()
    },
    // floorArr: {
    //   handler: (newVal) => {
    //     console.log(this);
    //     let obj = {}; //转换成key为楼层的对象
    //     newVal.forEach((v) => {
    //       obj[v.lv] = v;
    //     });
    //     this.threeDate.floorList = obj;
    //     if (this.camera) {
    //       this._3Dloder();
    //     } else {
    //       this._initTree();
    //     }
    //   },
    //   deep: true,
    // },
    floorArr(newVal) {
      let obj = {}; //转换成key为楼层的对象
      newVal.forEach((v) => {
        obj[v.lv] = v;
      });
      this.threeDate.floorList = obj;
      if (this.camera) {
        this._3Dloder();
      } else {
        this._initTree();
      }
    },
  },
  mounted() {
    this._initTree();
  },
  methods: {
    updateCamera() {
      this.camera.updateProjectionMatrix();
    },
    // 渲染
    animation() {
      // TWEEN.update()
      let clock = new THREE.Clock();
      requestAnimationFrame(this.animation);
      let T = clock.getDelta();
      this.timeS = this.timeS + T;
      let renderT = 1 / this.FPS;
      // requestAnimationFrame默认调用render函数60次，通过时间判断，降低renderer.render执行频率
      if (this.timeS > renderT) {
        // 控制台查看渲染器渲染方法的调用周期，也就是间隔时间是多少
        // console.log(`调用.render时间间隔`,timeS*1000+'毫秒');
        this.controls.update();
        this.renderer.render(this.scene, this.camera);
        this.labelRenderer.render(this.scene, this.camera);
        //renderer.render每执行一次，timeS置0
        this.timeS = 0;
      }
    },
    // 灯光
    _Light() {
      this.ambientLight = new THREE.AmbientLight(0xffffff, 1);
      this.ambientLight.position.set(0, 0, 0);
      this.scene.add(this.ambientLight);
      this.directionalLight = new THREE.DirectionalLight(0xffffff, 1);
      this.directionalLight.castShadow = true;
      this.directionalLight.position.set(5, 10, 7.5);
      this.scene.add(this.directionalLight);
    },
    //3d loader
    _3Dloder() {
      let threeDate = this.threeDate;
      let _this = this;
      let MTLLoaders = new MTLLoader();
      let OBJLoaders = new OBJLoader();
      let GLTFLoaders = new GLTFLoader();
      OBJLoaders.setCrossOrigin("Anonymous"); //跨域问题
      const { floorList } = threeDate;
      for (const iterator in floorList) {
        const mtl = floorList[iterator].mtl_url;
        const obj = floorList[iterator].obj_url;
        if (obj.search(/.obj/i) >= 0) {
          // 模型
          MTLLoaders.load(
            "http://192.168.0.98:8090" + mtl,
            function (materials) {
              //obj的模型会和MaterialCreator包含的材质对应起来
              OBJLoaders.setMaterials(materials);
              OBJLoaders.load("http://192.168.0.98:8090" + obj, function (obj) {
                if (_this.lv !== iterator) {
                  obj.visible = false;
                }

                _this.modlObj[iterator] = {
                  position: {
                    x: 0,
                    y: 0,
                    z: 0,
                  },
                  obj: obj,
                };
                threeDate.isloading = false;
                _this.scene.add(obj); //返回的组对象插入场景中
              });
            }
          );
        } else if (obj.search(/.gltf/i) >= 0) {
          GLTFLoaders.load("http://192.168.0.98:8090" + obj, function (obj) {
            console.log(obj, "@@@@@@@");
            const children = obj.scene.children[0].children;
            children.forEach((element) => {
              let objname = element.name;
              // 窗口
              if (/^\d_/.test(objname)) {
                // 获取外部模型具体点击位置  obj模型没有位置
                element.geometry.computeBoundingSphere();
                // 球体中心点
                let realPosition = element.geometry.boundingSphere.center;
                element["positions"] = realPosition;
                _this.keyobj[objname] = element;
              }
            });

            if (_this.lv !== iterator) {
              obj.scene.visible = false;
            }
            _this.modlObj[iterator] = {
              position: {
                x: 0,
                y: 0,
                z: 0,
              },
              obj: obj.scene,
            };
            console.log(obj.scene, iterator, _this.lv, "#########");
            _this.scene.add(obj.scene); //返回的组对象插入场景中
            threeDate.isloading = false;
          });
        }
      }
    },
    // 初始化相机
    _initCamera() {
      this.camera.position.x = -500;
      this.camera.position.y = 500;
      this.camera.position.z = 1000;
    },
    // css2render
    css2renderer() {
      let threeDom = this.$refs.threeDom;
      let screenW = threeDom.clientWidth;
      let screenH = threeDom.clientHeight;
      let css2dom = document.getElementById("alert-css2");
      this.Tips = new CSS2DObject(css2dom);
      this.Tips.position.set(0, 0, 0); //文字地址
      this.Tips.visible = false;
      this.scene.add(this.Tips);
      this.labelRenderer = new CSS2DRenderer(); //新建CSS2DRenderer
      this.labelRenderer.setSize(screenW, screenH);
      this.labelRenderer.domElement.style.position = "absolute";
      this.labelRenderer.domElement.style.top = 0;
      threeDom.appendChild(this.labelRenderer.domElement);
    },
    // css2
    css2controls() {
      this.css2renderer();
      this.controls = new OrbitControls(
        this.camera,
        this.labelRenderer.domElement
      );
      const counter = document.getElementById("counter");
      counter.appendChild(this.renderer.domElement);
    },
    // 调试模式
    initGui() {
      let datGui = new GUI();
      //声明一个保存需求修改的相关数据的对象
      let gui = {
        ambientLight: "#9b9ba3", //环境光源
        directionalLight: "#0xffc288", //点光源
        intensity: 1, //灯光强度
        visible: true, //是否可见
        castShadow: true,
        exponent: 30,
        target: "plane",
        debug: false,
      };

      //将设置属性添加到gui当中，gui.add(对象，属性，最小值，最大值）
      datGui.addColor(gui, "ambientLight").onChange(function (e) {
        this.ambientLight.color = new THREE.Color(e);
      });
      datGui.add(gui, "intensity", 0, 5).onChange(function (e) {
        this.ambientLight.intensity = e;
      });
      datGui.addColor(gui, "directionalLight").onChange(function (e) {
        this.directionalLight.color = new THREE.Color(e);
      });
      datGui.add(gui, "intensity", 0, 5).onChange(function (e) {
        this.directionalLight.intensity = e;
      });
      datGui.add(gui, "visible").onChange(function (e) {
        this.directionalLight.visible = e;
      });
      datGui.add(gui, "castShadow").onChange(function (e) {
        this.directionalLight.castShadow = e;
      });
      datGui.add(gui, "debug").onChange(function (e) {
        if (e) {
          let debug = new THREE.CameraHelper(
            this.directionalLight.shadow.camera
          );
          debug.name = "debug";
          this.scene.add(debug);
        } else {
          // let debug = this.scene.getObjectByName("debug");
          // this.scene.remove(debug);
        }
      });
      datGui.add(this.camera, "fov", 1, 18000).onChange(this.updateCamera);
      datGui.add(this.camera, "near", 1, 20000).onChange(this.updateCamera);
      datGui.add(this.camera, "far", 1, 20000).onChange(this.updateCamera);

      const folder = datGui.addFolder("全局Position");
      folder
        .add(new PositionGUI(this.camera.position, "x"), "modify", 0, 20000)
        .name("x");
      folder
        .add(new PositionGUI(this.camera.position, "y"), "modify", 0, 20000)
        .name("y");
      folder
        .add(new PositionGUI(this.camera.position, "z"), "modify", 0, 20000)
        .name("z");
    },
    // 初始化
    _initTree() {
      let threeDom = this.$refs.threeDom;
      this.scene = new THREE.Scene();
      let screenW = threeDom.clientWidth;
      let screenH = threeDom.clientHeight;
      this.camera = new THREE.PerspectiveCamera(
        25,
        screenW / screenH,
        0.01,
        20000
      );
      this._initCamera();
      this.camera.lookAt(this.scene.position);

      this.renderer = new THREE.WebGLRenderer({
        antialias: true, //开启抗锯齿
        logarithmicDepthBuffer: true, //对数深度缓存解决模型重叠
        alpha: true, //背景透明
      });
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 设置投影类型, 这边的柔和投影
      this.renderer.setSize(screenW, screenH);
      threeDom.appendChild(this.renderer.domElement);

      this._Light();
      this.css2controls();
      // controls.autoRotate = true
      this.controls.minDistance = 500;
      this.controls.maxDistance = 1000;
      this.controls.maxPolarAngle = 1.3;
      this.controls.minPolarAngle = 0.5;
      // if(process.env.NODE_ENV == 'development'){
      //     // this.initGui()
      // }
      // initGui()
      this.animation();
    },
  },
};
</script>

<style lang="less" scoped>
#counter {
  position: relative;
}
</style>