import {
  ConeGeometry,
  MeshBasicMaterial,
  Mesh,
  LineLoop,
  Group,
  Vector3,
  Box3,
  BufferAttribute,
  BufferGeometry,
  OctahedronBufferGeometry,
  DoubleSide,
  PlaneGeometry,
  Quaternion,
  MathUtils,
  Vector2,
  Plane as Plane$1,
  PlaneHelper,
  Raycaster as Raycaster$1,
  Object3D, EllipseCurve, LineBasicMaterial, CylinderGeometry, TorusGeometry } from '../../../build/three.module.js'

const DEFAULT_LINE_HEIGHT = 0.5
const DEFAULT_RADIAL_SEGMENTS = 32
const DEFAULT_CONE_HEIGHT = 0.55
const DEFAULT_CONE_RADIUS = 0.25
const DEFAULT_OCTAHEDRON_RADIUS = 0.07
const DEFAULT_PLANE_WIDTH = 0.5
const DEFAULT_PLANE_HEIGHT = 0.5
const DEFAULT_PLANE_SEGMENTS = 32
const DEFAULT_RING_NUM_POINTS = 64
const DEFAULT_RING_RADIUS = 1
const DEFAULT_CONTROLS_SEPARATION = 0.5
const DEFAULT_ROTATION_RADIUS_SCALE = 1
const DEFAULT_EYE_ROTATION_SCALE = 1.25
const DEFAULT_PLANE_SIZE_SCALE = 1
const DEFAULT_TRANSLATION_DISTANCE_SCALE = 1
const DEFAULT_COLOR_ARROW = '#f0ff00'
const DEFAULT_COLOR_RING = '#f0ff00'
const DEFAULT_COLOR_PLANE = '#f0ff00'
const DEFAULT_CONTROLS_OPACITY = 1
let transformScene
let controlObject
let transformMode = 'local'
const objectUUID = ''
let objectScale
const PICK_PLANE_OPACITY = {}

PICK_PLANE_OPACITY[PICK_PLANE_OPACITY['ACTIVE'] = 0.75] = 'ACTIVE'
PICK_PLANE_OPACITY[PICK_PLANE_OPACITY['INACTIVE'] = 0.3] = 'INACTIVE'
/**
 * Names for default handles
 */
const DEFAULT_HANDLE_GROUP_NAME = {}
DEFAULT_HANDLE_GROUP_NAME['XPT'] = 'xpt_handle'
DEFAULT_HANDLE_GROUP_NAME['YPT'] = 'ypt_handle'
DEFAULT_HANDLE_GROUP_NAME['ZPT'] = 'zpt_handle'
DEFAULT_HANDLE_GROUP_NAME['XNT'] = 'xnt_handle'
DEFAULT_HANDLE_GROUP_NAME['YNT'] = 'ynt_handle'
DEFAULT_HANDLE_GROUP_NAME['ZNT'] = 'znt_handle'
DEFAULT_HANDLE_GROUP_NAME['XR'] = 'xr_handle'
DEFAULT_HANDLE_GROUP_NAME['YR'] = 'yr_handle'
DEFAULT_HANDLE_GROUP_NAME['ZR'] = 'zr_handle'
DEFAULT_HANDLE_GROUP_NAME['ER'] = 'er_handle'
DEFAULT_HANDLE_GROUP_NAME['PICK'] = 'pick_handle'
DEFAULT_HANDLE_GROUP_NAME['PICK_PLANE_XY'] = 'pick_plane_xy_handle'
DEFAULT_HANDLE_GROUP_NAME['PICK_PLANE_YZ'] = 'pick_plane_yz_handle'
DEFAULT_HANDLE_GROUP_NAME['PICK_PLANE_ZX'] = 'pick_plane_zx_handle'

const ANCHOR_MODE = {}
ANCHOR_MODE['FIXED'] = 'fixed'
ANCHOR_MODE['INHERIT'] = 'inherit'

const EVENTS = {}
EVENTS['DRAG_START'] = 'DRAG_START'
EVENTS['DRAG'] = 'DRAG'
EVENTS['DRAG_STOP'] = 'DRAG_STOP'
EVENTS['change'] = 'change'
EVENTS['objectChange'] = 'objectChange'

/**
 * 箭头
 */
class Cone extends Mesh {
  constructor(color) {
    super()
    this.geometry = new ConeGeometry(DEFAULT_CONE_RADIUS, DEFAULT_CONE_HEIGHT, DEFAULT_RADIAL_SEGMENTS)
    this.material = new MeshBasicMaterial({
      color: color,
      depthTest: false,
      depthWrite: false,
      transparent: true,
      toneMapped: false
    })
    this.material.transparent = true
    this.material.opacity = DEFAULT_CONTROLS_OPACITY
    this.renderOrder = Infinity
    return this
  }
}

/**
 * 直线
 */
class Line extends LineLoop {
  constructor(color, geometry) {
    super()
    this.geometry = geometry
    this.material = new LineBasicMaterial({
      color: color,
      depthTest: false,
      depthWrite: false,
      transparent: true,
      linewidth: 1,
      fog: false,
      toneMapped: false
    })
    this.material.transparent = true
    this.material.opacity = DEFAULT_CONTROLS_OPACITY
    this.renderOrder = Infinity
    return this
  }
}

/**
 * Base class for all handles
 * @noInheritDoc
 */
class HandleGroup extends Group {
  constructor() {
    super()
    return this
  }
}

class TranslationGroup extends HandleGroup {
  constructor() {
    super()
    this.up = new Vector3()
    return this
  }
}

/**
 * This class can be extended to create custom rotation handles.
 * It requires setting the property `up`.
 */
class RotationGroup extends HandleGroup {
  constructor() {
    super()
    this.up = new Vector3()
    return this
  }
}

/**
 * This class can be extended to create custom pick handle (translates in eye-plane).
 */
class PickGroup extends HandleGroup {
  constructor() {
    super()
    return this
  }
}

/**
 * This class can be extended to create custom pick plane handles.
 * It requires setting the property `up`.
 */
class PickPlaneGroup extends HandleGroup {
  constructor() {
    super()
    /**
		 * This is a unit vector that is perpendicular to the plane handles.
		 * For example, in case of [[Controls.pickPlaneXY]], it is
		 * `THREE.Vector3(0,0,1)` (along the z-axis).
		 */
    this.up = new Vector3()
    return this
  }
}

class Translation extends TranslationGroup {
  constructor(color, lineHeight) {
    super()
    if (color === void 0) { color = DEFAULT_COLOR_ARROW }
    this.parallel = new Vector3(0, 1, 0)
    /**
		 * @hidden
		 */
    this.getInteractiveObjects = function() {
      return [this.cone]
    }
    this.setColor = function(color) {
      const coneMaterial = this.cone.material
      const lineMaterial = this.line.material
      coneMaterial.color.set(color)
      lineMaterial.color.set(color)
    }
    this.cone = new Cone(color)
    // let lineGeometry = new BufferGeometry()
    // let vertices = new Float32Array( [
    // 	0, 0, 0,
    // 	0, DEFAULT_LINE_HEIGHT, 0
    // ] )
    // lineGeometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) )
    const matInvisible = new MeshBasicMaterial({
      depthTest: false,
      depthWrite: false,
      fog: false,
      toneMapped: false,
      transparent: true,
      color: color
    })
    // lineGeometry.vertices.push(new Vector3(0, 0, 0))
    // lineGeometry.vertices.push(new Vector3(0, DEFAULT_LINE_HEIGHT, 0))
    // this.line = new Line(color, lineGeometry)
    this.line = new Mesh(new CylinderGeometry(0.02, 0.02, 1, 4), matInvisible), [0.3, 0, 0], [0, 0, -Math.PI / 2]
    this.cone.geometry.scale(DEFAULT_CONE_RADIUS, DEFAULT_CONE_HEIGHT, DEFAULT_CONE_RADIUS)
    this.cone.translateY(DEFAULT_LINE_HEIGHT)
    this.add(this.cone)
    this.add(this.line)
    this.renderOrder = Infinity
    return this
  }
}

class Octahedron extends Mesh {
  constructor(color) {
    super()
    this.geometry = new OctahedronBufferGeometry(DEFAULT_OCTAHEDRON_RADIUS, 0)
    this.material = new MeshBasicMaterial({
      color: color,
      depthTest: false,
      transparent: true,
      side: DoubleSide,
      depthWrite: false,
      toneMapped: false
    })
    this.renderOrder = Infinity
    return this
  }
}

class Torus extends Mesh {
  constructor(ringRadius, color) {
    super()
    this.geometry = new TorusGeometry(0.6, 0.015, 32, 32, ringRadius * Math.PI)
    this.material = new MeshBasicMaterial({
      color: color,
      depthTest: false,
      transparent: true,
      side: DoubleSide,
      depthWrite: false,
      toneMapped: false
    })
    this.renderOrder = Infinity
    return this
  }
}

class Rotation extends RotationGroup {
  constructor(color, ringRadius, name) {
    super()
    // if (color === void 0) { color = DEFAULT_COLOR_RING }
    // if (ringRadius === void 0) { ringRadius = DEFAULT_RING_RADIUS }
    this.getInteractiveObjects = function() {
      return [this.handlebar]
    }
    this.setColor = function(color) {
      const ringMaterial = this.ring.material
      const handlebarMaterial = this.handlebar.material
      ringMaterial.color.set(color)
      handlebarMaterial.color.set(color)
    }
    // let ringNumberOfPoints = DEFAULT_RING_NUM_POINTS
    // let ringGeometry = new BufferGeometry()
    // let angle = (2 * Math.PI) / ringNumberOfPoints
    // let verticesGroup = []
    // for (let i = 1; i < ringNumberOfPoints + 1; i++) {
    // 	verticesGroup.push(ringRadius * Math.cos(i * angle), ringRadius * Math.sin(i * angle), 0)
    // 	// ringGeometry.vertices.push(new Vector3(ringRadius * Math.cos(i * angle), ringRadius * Math.sin(i * angle), 0))
    // }
    // console.log(ringRadius)
    // let vertices = new Float32Array( verticesGroup )
    // ringGeometry.setAttribute( 'position', new BufferAttribute( vertices, 3 ) )

    // this.ring = new Line(color, ringGeometry)
    const matInvisible = new MeshBasicMaterial({
      depthTest: false,
      depthWrite: false,
      fog: false,
      toneMapped: false,
      transparent: true,
      color: color
    })

    this.ring = new Torus(ringRadius, color)
    this.handlebar = new Octahedron(color)

    // switch (name) {
    //   case 'X':
    //     this.handlebar.position.set(0, Math.sqrt(ringRadius)/2,-Math.sqrt(ringRadius)/2)
    //     break
    //   case 'Y':
    //     // this.handlebar.position.set(Math.sqrt(ringRadius)/2,0, Math.sqrt(ringRadius)/2)
    //     break
    //   case 'Z':
    //     this.handlebar.position.set(Math.sqrt(ringRadius)/2, Math.sqrt(ringRadius)/2,0)
    //     break
    //   default:
    //     break
    // }

    // this.handlebar.position.set(0,Math.sqrt(ringRadius)/2,0)
    this.handlebar.position.y = ringRadius / Math.abs(ringRadius) * Math.sqrt(0.6 * 0.6 / 2)
    this.handlebar.position.x = Math.sqrt(0.6 * 0.6 / 2)
    // this.handlebar.position.z = Math.sqrt(ringRadius)/2
    this.add(this.ring)
    this.add(this.handlebar)
    this.renderOrder = Infinity
    return this
  }
}

class Pick extends PickGroup {
  constructor() {
    super()
    /**
		 * @hidden
		 */
    this.getInteractiveObjects = function() {
      return [this.octahedron]
    }
    this.setColor = function(color) {
      const octahedronMaterial = this.octahedron.material
      octahedronMaterial.color.set(color)
    }
    this.octahedron = new Octahedron('white')
    this.add(this.octahedron)
    return this
  }
}

class Plane extends Mesh {
  constructor(color, width, height) {
    super()
    if (color === void 0) { color = DEFAULT_COLOR_RING }
    if (width === void 0) { width = DEFAULT_PLANE_WIDTH }
    if (height === void 0) { height = DEFAULT_PLANE_HEIGHT }

    this.geometry = new PlaneGeometry(width, height, DEFAULT_PLANE_SEGMENTS)
    this.material = new MeshBasicMaterial({
      color: color,
      depthTest: false,
      side: DoubleSide,
      transparent: true
    })
    this.material.opacity = PICK_PLANE_OPACITY.INACTIVE
    this.renderOrder = Infinity
    return this
  }
}

class PickPlane extends PickPlaneGroup {
  constructor(color, width, height, name) {
    super()
    if (color === void 0) { color = DEFAULT_COLOR_PLANE }
    if (width === void 0) { width = DEFAULT_PLANE_WIDTH }
    if (height === void 0) { height = DEFAULT_PLANE_HEIGHT }

    height = Math.sqrt(height / 4)
    width = Math.sqrt(width / 4)
    /**
		 * @hidden
		 */
    this.getInteractiveObjects = function() {
      return [this.plane]
    }
    this.setColor = function(color) {
      const planeMaterial = this.plane.material
      const boundaryMaterial = this.boundary.material
      planeMaterial.color.set(color)
      boundaryMaterial.color.set(color)
    }
    const boundaryGeometry = new BufferGeometry()
    const crossXGeometry = new BufferGeometry()
    const crossYGeometry = new BufferGeometry()
    const vertexMaxX = width / 2
    const vertexMaxY = height / 2

    const vertices = new Float32Array([
      vertexMaxX, vertexMaxY, 0,
      vertexMaxX, -vertexMaxY, 0,
      -vertexMaxX, -vertexMaxY, 0,
      -vertexMaxX, vertexMaxY, 0
      // 0, vertexMaxY, 0,
      // 0, -vertexMaxY, 0,
      // -vertexMaxX, 0, 0,
      // vertexMaxX, 0, 0,
    ])
    boundaryGeometry.setAttribute('position', new BufferAttribute(vertices, 3))
    //
    // boundaryGeometry.vertices.push(new Vector3(vertexMaxX, vertexMaxY, 0))
    // boundaryGeometry.vertices.push(new Vector3(vertexMaxX, -vertexMaxY, 0))
    // boundaryGeometry.vertices.push(new Vector3(-vertexMaxX, -vertexMaxY, 0))
    // boundaryGeometry.vertices.push(new Vector3(-vertexMaxX, vertexMaxY, 0))
    //
    //
    // crossXGeometry.vertices.push(new Vector3(0, vertexMaxY, 0))
    // crossXGeometry.vertices.push(new Vector3(0, -vertexMaxY, 0))
    // crossYGeometry.vertices.push(new Vector3(-vertexMaxX, 0, 0))
    // crossYGeometry.vertices.push(new Vector3(vertexMaxX, 0, 0))

    this.boundary = new Line(color, boundaryGeometry)
    this.crossX = new Line('black', crossXGeometry)
    this.crossY = new Line('black', crossYGeometry)
    this.plane = new Plane(color, width, height)
    this.add(this.plane)
    this.add(this.boundary)
    this.add(this.crossX)
    this.add(this.crossY)
    switch (name) {
      case 'XY':
        this.position.set(width / 2, width / 2, 0)
        break
      case 'YZ':
        this.position.set(0, width / 2, width / 2)
        break
      case 'ZX':
        this.position.set(width / 2, 0, width / 2)
        break
      default:
        break
    }
    this.renderOrder = Infinity
    return this
  }
}

class RotationEye extends Rotation {
  constructor(color, radius) {
    super()
    if (color === void 0) { color = DEFAULT_COLOR_RING }
    if (radius === void 0) { radius = DEFAULT_RING_RADIUS }
    this.camera = null
    this.controlsWorldOrientation = new Quaternion()
    this._temp1 = new Vector3()
    this._temp2 = new Vector3()
    this._temp3 = new Quaternion()
    this.worldPosition = new Vector3()
    return this
  }
  updateMatrixWorld(force) {
    let _a
    if (this.camera !== null) {
      (_a = this.parent) === null || _a === void 0 ? void 0 : _a.matrixWorld.decompose(this._temp1, this.controlsWorldOrientation, this._temp2)
      this.matrixWorld.decompose(this.worldPosition, this._temp3, this._temp2)
      this.camera.getWorldQuaternion(this.quaternion).premultiply(this.controlsWorldOrientation.invert())
      this.camera.getWorldPosition(this.up).sub(this.worldPosition)
    }
    Rotation.prototype.updateMatrixWorld.call(this, force)
  }
}

/**
 * Controls is the main class in this library.
 * It is a subclass of THREE.Group, so its properties like `position` and
 * `quaternion` can be modified as desired.
 * The `children` are the control handles (like `rotationX`).
 * All translations and rotations are setup with respect to the global coordinate system.
 * @noInheritDoc
 */

class Controls extends Group {
  constructor(object, camera, options) {
    super()
    let _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3
    this.object = object
    transformScene = camera.parent
    controlObject = object
    this.handleTargetQuaternion = new Quaternion()
    this.objectWorldPosition = new Vector3()
    this.objectTargetPosition = new Vector3()
    this.objectTargetQuaternion = new Quaternion()
    this.objectParentWorldPosition = new Vector3()
    this.objectParentWorldQuaternion = new Quaternion()
    this.objectParentWorldScale = new Vector3()
    this.deltaPosition = new Vector3()
    this.normalizedHandleParallelVectorCache = new Vector3()
    this.touch1 = new Vector3()
    this.touch2 = new Vector3()
    this.boundingSphereRadius = 0
    this.dragStartPoint = new Vector3()
    this.dragIncrementalStartPoint = new Vector3()
    this.handles = new Set()
    this.isBeingDraggedTranslation = false
    this.isBeingDraggedRotation = false
    this.dampingFactor = 0.8
    this.initialSelfQuaternion = new Quaternion()
    this.minTranslationCache = new Vector3()
    this.maxTranslationCache = new Vector3()
    this.translationLimit = false
    this.translationAnchor = null
    this.size = 1

    this.setupDefaultPickPlane = function() {
      this.pickPlaneXY.name = DEFAULT_HANDLE_GROUP_NAME.PICK_PLANE_XY
      this.pickPlaneYZ.name = DEFAULT_HANDLE_GROUP_NAME.PICK_PLANE_YZ
      this.pickPlaneZX.name = DEFAULT_HANDLE_GROUP_NAME.PICK_PLANE_ZX
      this.pickPlaneYZ.up = new Vector3(1, 0, 0)
      this.pickPlaneZX.up = new Vector3(0, 1, 0)
      this.pickPlaneXY.up = new Vector3(0, 0, 1)

      this.pickPlaneYZ.rotateY(Math.PI / 2)
      this.pickPlaneZX.rotateX(Math.PI / 2)
      this.setupHandle(this.pickPlaneXY)
      this.setupHandle(this.pickPlaneYZ)
      this.setupHandle(this.pickPlaneZX)
    }
    this.setupHandle = function(handle) {
      this.handles.add(handle)
      this.add(handle)
    }
    this.setupDefaultPick = function() {
      this.pick.name = DEFAULT_HANDLE_GROUP_NAME.PICK
      this.setupHandle(this.pick)
    }
    // _this.setupDefaultEyeRotation = function () {
    //     _this.rotationEye.name = DEFAULT_HANDLE_GROUP_NAME.ER
    //     _this.rotationEye.camera = _this.camera
    //     _this.setupHandle(_this.rotationEye)
    // }
    this.setupDefaultTranslation = function() {
      // 屏蔽的部分是 反方向的箭头
      this.translationXP.name = DEFAULT_HANDLE_GROUP_NAME.XPT
      this.translationYP.name = DEFAULT_HANDLE_GROUP_NAME.YPT
      this.translationZP.name = DEFAULT_HANDLE_GROUP_NAME.ZPT
      // _this.translationXN.name = DEFAULT_HANDLE_GROUP_NAME.XNT
      // _this.translationYN.name = DEFAULT_HANDLE_GROUP_NAME.YNT
      // _this.translationZN.name = DEFAULT_HANDLE_GROUP_NAME.ZNT
      this.translationXP.translateX(this.boundingSphereRadius * this.translationDistanceScale)
      this.translationYP.translateY(this.boundingSphereRadius * this.translationDistanceScale)
      this.translationZP.translateZ(this.boundingSphereRadius * this.translationDistanceScale)
      // _this.translationXN.translateX(-_this.boundingSphereRadius * _this.translationDistanceScale)
      // _this.translationYN.translateY(-_this.boundingSphereRadius * _this.translationDistanceScale)
      // _this.translationZN.translateZ(-_this.boundingSphereRadius * _this.translationDistanceScale)
      this.translationXP.rotateZ(-Math.PI / 2)
      this.translationZP.rotateX(Math.PI / 2)
      // _this.translationXN.rotateZ(Math.PI / 2)
      // _this.translationYN.rotateX(Math.PI)
      // _this.translationZN.rotateX(-Math.PI / 2)
      this.translationXP.up = new Vector3(0, 1, 0)
      this.translationYP.up = new Vector3(0, 0, 1)
      this.translationZP.up = new Vector3(0, 1, 0)
      // _this.translationXN.up = new Vector3(0, -1, 0)
      // _this.translationYN.up = new Vector3(0, 0, -1)
      // _this.translationZN.up = new Vector3(0, -1, 0)
      this.translationXP.parallel = new Vector3(1, 0, 0)
      this.translationYP.parallel = new Vector3(0, 1, 0)
      this.translationZP.parallel = new Vector3(0, 0, 1)
      // _this.translationXN.parallel = new Vector3(-1, 0, 0)
      // _this.translationYN.parallel = new Vector3(0, -1, 0)
      // _this.translationZN.parallel = new Vector3(0, 0, -1)
      this.setupHandle(this.translationXP)
      this.setupHandle(this.translationYP)
      this.setupHandle(this.translationZP)
      // _this.setupHandle(_this.translationXN)
      // _this.setupHandle(_this.translationYN)
      // _this.setupHandle(_this.translationZN)
    }
    this.setupDefaultRotation = function() {
      this.rotationX.name = DEFAULT_HANDLE_GROUP_NAME.XR
      this.rotationY.name = DEFAULT_HANDLE_GROUP_NAME.YR
      this.rotationZ.name = DEFAULT_HANDLE_GROUP_NAME.ZR
      this.rotationX.up = new Vector3(1, 0, 0)
      this.rotationY.up = new Vector3(0, 1, 0)
      this.rotationZ.up = new Vector3(0, 0, 1)
      this.rotationY.rotateX(Math.PI / 2)
      this.rotationX.rotateY(Math.PI / 2)
      this.rotationX.rotateZ(Math.PI)
      this.setupHandle(this.rotationX)
      this.setupHandle(this.rotationY)
      this.setupHandle(this.rotationZ)
    }
    this.computeObjectBounds = function() {
      let _a
      let radius
      if (this.useComputedBounds) {
        if (this.object.type === 'Mesh') {
          const geometry = this.object.geometry
          geometry.computeBoundingSphere()
          const boundingSphere = geometry.boundingSphere
          radius = (_a = boundingSphere === null || boundingSphere === void 0 ? void 0 : boundingSphere.radius) !== null && _a !== void 0 ? _a : 0
          this.boundingSphereRadius = radius / 2 + this.separation
          return
        } else {
          const bbox = new Box3().setFromObject(this.object)
          radius = Math.abs(bbox.max.distanceTo(bbox.min) / 5)
          radius = (_a = bbox === void 0 ? void 1 : radius) !== null && _a !== void 0 ? _a : 1
          this.boundingSphereRadius = radius
          return
          // console.warn("Bounds can only be computed for object of type THREE.Mesh,\n          received object with type: " + _this.object.type + ". Falling back to using\n          default separation.\n        ")
        }
      }
      this.boundingSphereRadius = this.separation
    }
    /**
		 * Puts a limit on the object's translation anchored at the current position.
		 *
		 * `{ x: [-1, 2], y: false, z: false }` - sets the translation limit to `-1` unit
		 * in the -x-direction, `+2` units in the +x-direction, and no limit on the
		 * y and z-direction.
		 *
		 * Setting the limit to `false` disables the limit in all directions.
		 * @param limit
		 */
    this.setTranslationLimit = function(limit) {
      this.translationLimit = limit
      this.translationAnchor = limit ? this.position.clone() : null
    }
    /**
		 * @hidden
		 */
    this.processDragStart = function(args) {
      const point = args.point; const handle = args.handle
      this.dragStartPoint.copy(point)
      this.dragIncrementalStartPoint.copy(point)
      this.isBeingDraggedTranslation =
				handle instanceof TranslationGroup ||
				handle instanceof PickGroup ||
				handle instanceof PickPlaneGroup
      this.isBeingDraggedRotation = handle instanceof RotationGroup
    }
    /**
		 * @hidden
		 */
    this.processDragEnd = function(args) {
      const handle = args.handle
      const _a = this.snapTranslation; const xSnap = _a.x; const ySnap = _a.y; const zSnap = _a.z
      const snap = [xSnap, ySnap, zSnap]
      if (handle instanceof TranslationGroup || handle instanceof PickPlaneGroup || handle instanceof PickGroup) {
        const xyz = this.object.position.toArray()
        const floor_1 = xyz.map(Math.floor)
        const ceil_1 = xyz.map(Math.ceil)
        const snapFloor_1 = xyz.map(function(p, index) { return ceil_1[index] - p >= p - floor_1[index] })
        const position = xyz.map((p, index) => {
          if (!snap[index]) return p
          return snapFloor_1[index] ? floor_1[index] : ceil_1[index]
        })
        this.object.position.fromArray(position)
      }
      this.isBeingDraggedTranslation = false
      this.isBeingDraggedRotation = false
    }
    /**
		 * Only takes effect if [[IControlsOptions.isDampingEnabled]] is true.
		 * @param dampingFactor - value between 0 and 1, acts like a weight on the controls
		 */
    this.setDampingFactor = function(dampingFactor) {
      if (dampingFactor === void 0) dampingFactor = 0
      return (this.dampingFactor = MathUtils.clamp(dampingFactor, 0, 1))
    }
    /**
		 * @hidden
		 */
    this.processDrag = function(args) {
      const point = args.point; const handle = args.handle; const _a = args.dragRatio; const dragRatio = _a === void 0 ? 1 : _a
      const k = Math.exp(-this.dampingFactor * Math.abs(Math.pow(dragRatio, 3)))
      if (handle instanceof TranslationGroup) {
        this.deltaPosition.copy(point).sub(this.dragIncrementalStartPoint)
        this.normalizedHandleParallelVectorCache.copy(handle.parallel.normalize()).applyQuaternion(this.quaternion)
        const delta = this.deltaPosition.dot(this.normalizedHandleParallelVectorCache)
        if (delta === 0) return
        if (isNaN(delta)) return
        this.deltaPosition.copy(this.normalizedHandleParallelVectorCache).multiplyScalar(this.isDampingEnabled ? k * delta : delta)
        this.position.copy(this.getLimitedTranslation(this.deltaPosition))
      } else if (handle instanceof PickGroup || handle instanceof PickPlaneGroup) {
        this.deltaPosition.copy(point).sub(this.dragIncrementalStartPoint).multiplyScalar(this.isDampingEnabled ? k : 1)
        this.position.copy(this.getLimitedTranslation(this.deltaPosition))
      } else {
        if (this.dragIncrementalStartPoint.x === 0 && this.dragIncrementalStartPoint.y === 0 && this.dragIncrementalStartPoint.z === 0) return
        this.touch1.copy(this.dragIncrementalStartPoint).sub(this.objectWorldPosition).normalize()
        this.touch2.copy(point).sub(this.objectWorldPosition).normalize()
        this.handleTargetQuaternion.setFromUnitVectors(this.touch1, this.touch2)
        if (this.mode === ANCHOR_MODE.FIXED) this.detachHandleUpdateQuaternionAttach(handle, this.handleTargetQuaternion)
      }
      this.objectTargetQuaternion.premultiply(this.handleTargetQuaternion)
      this.dragIncrementalStartPoint.copy(point)
    }
    this.getLimitedTranslation = function(translation) {
      const position = translation.add(this.position)
      if (!this.translationAnchor || !this.translationLimit) return position
      const _a = this.translationLimit; const xLimit = _a.x; const yLimit = _a.y; const zLimit = _a.z
      const _b = this.translationAnchor; const xAnchor = _b.x; const yAnchor = _b.y; const zAnchor = _b.z
      const x = position.x; const y = position.y; const z = position.z
      this.minTranslationCache.set(xLimit ? xAnchor + xLimit[0] : x, yLimit ? yAnchor + yLimit[0] : y, zLimit ? zAnchor + zLimit[0] : z)
      this.maxTranslationCache.set(xLimit ? xAnchor + xLimit[1] : x, yLimit ? yAnchor + yLimit[1] : y, zLimit ? zAnchor + zLimit[1] : z)
      return position.clamp(this.minTranslationCache, this.maxTranslationCache)
    }

    this.detachObjectUpdatePositionAttach = function(parent, object) {
      if (parent !== null && this.parent !== null && this.parent.parent !== null) {
        const scene = this.parent.parent
        if (scene.type !== 'Scene') throw new Error('控制器必须添加到场景中！')
        scene.attach(object)
        object.position.copy(this.objectTargetPosition)
        parent.attach(object)
      }
    }
    this.detachHandleUpdateQuaternionAttach = function(handle, quaternion) {
      if (this.parent !== null && this.parent.parent) {
        const scene = this.parent.parent
        if (scene.type !== 'Scene') throw new Error('控制器必须添加到场景中！')
        scene.attach(handle)
        handle.applyQuaternion(quaternion)
        this.attach(handle)
      }
    }

    /**
		 * Applies supplied visibility to the supplied handle names.
		 * Individual handle's visibility can also be changed by modifying the `visibility`
		 * property on the handle directly.
		 * @param handleNames
		 * @param visibility
		 */
    this.showByNames = function(handleNames, visibility) {
      if (visibility === void 0) { visibility = true }
      const handleNamesMap = {}
      this.handles.forEach((handle) => { handleNamesMap[handle.name] = handle })
      handleNames.map((handleName) => {
        const handle = handleNamesMap[handleName]
        if (handle === undefined) throw new Error('handle: ' + handleName + ' not found!')
        handle.visible = visibility
      })
    }

    /**
		 * Applies supplied visibility to all handles
		 * @param visibility
		 */
    this.showAll = function(visibility) {
      if (visibility === void 0) { visibility = true }
      this.handles.forEach((handle) => { handle.visible = visibility })
    }

    /**
		 * @hidden
		 */
    this.updateMatrixWorld = function(force) {
      let factor
      if (camera.isOrthographicCamera) {
        factor = (camera.top - camera.bottom) / camera.zoom
      } else {
        factor = this.objectWorldPosition.distanceTo(camera.position) * Math.min(1.9 * Math.tan(Math.PI * camera.fov / 360) / camera.zoom, 7)
      }
      this.scale.set(1, 1, 1).multiplyScalar(factor * this.size / 7)

      this.object.updateMatrixWorld(force)
      this.object.getWorldPosition(this.objectWorldPosition)
      const parent = this.object.parent
      if (parent !== null) parent.matrixWorld.decompose(this.objectParentWorldPosition, this.objectParentWorldQuaternion, this.objectParentWorldScale)

      this.objectParentWorldQuaternion.invert()
      this.objectTargetPosition.copy(this.position)
      this.objectTargetQuaternion.premultiply(this.objectParentWorldQuaternion)
      if (this.isBeingDraggedTranslation) {
        this.detachObjectUpdatePositionAttach(parent, this.object)
      } else if (this.isBeingDraggedRotation) {
        this.object.quaternion.copy(this.objectTargetQuaternion)
      } else {
        this.position.copy(this.objectWorldPosition)
      }
      this.object.getWorldQuaternion(this.objectTargetQuaternion)
      transformMode === 'world' ? this.quaternion.copy(this.initialSelfQuaternion) : this.quaternion.copy(this.initialSelfQuaternion).premultiply(this.objectTargetQuaternion)
      Group.prototype.updateMatrixWorld.call(this, force)
    }
    this.options = options || {}
    transformMode = (_3 = (_2 = this.options) === null || _2 === void 0 ? void 0 : _2.tranformMode) !== null && _3 !== void 0 ? _3 : 'local'
    this.mode = (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.mode) !== null && _b !== void 0 ? _b : ANCHOR_MODE.FIXED
    this.hideOtherHandlesOnDrag = (_d = (_c = this.options) === null || _c === void 0 ? void 0 : _c.hideOtherHandlesOnDrag) !== null && _d !== void 0 ? _d : true
    this.hideOtherControlsInstancesOnDrag = (_f = (_e = this.options) === null || _e === void 0 ? void 0 : _e.hideOtherControlsInstancesOnDrag) !== null && _f !== void 0 ? _f : true
    this.showHelperPlane = (_h = (_g = this.options) === null || _g === void 0 ? void 0 : _g.showHelperPlane) !== null && _h !== void 0 ? _h : false
    this.highlightAxis = (_k = (_j = this.options) === null || _j === void 0 ? void 0 : _j.highlightAxis) !== null && _k !== void 0 ? _k : true
    this.useComputedBounds = (_m = (_l = this.options) === null || _l === void 0 ? void 0 : _l.useComputedBounds) !== null && _m !== void 0 ? _m : false
    this.snapTranslation = (_p = (_o = this.options) === null || _o === void 0 ? void 0 : _o.snapTranslation) !== null && _p !== void 0 ? _p : {
      x: false,
      y: false,
      z: false
    }
    this.separation = (_r = (_q = this.options) === null || _q === void 0 ? void 0 : _q.separation) !== null && _r !== void 0 ? _r : DEFAULT_CONTROLS_SEPARATION
    this.isDampingEnabled = (_t = (_s = this.options) === null || _s === void 0 ? void 0 : _s.isDampingEnabled) !== null && _t !== void 0 ? _t : true
    this.rotationRadiusScale = (_v = (_u = this.options) === null || _u === void 0 ? void 0 : _u.rotationRadiusScale) !== null && _v !== void 0 ? _v : DEFAULT_ROTATION_RADIUS_SCALE
    this.eyeRotationRadiusScale = (_x = (_w = this.options) === null || _w === void 0 ? void 0 : _w.eyeRotationRadiusScale) !== null && _x !== void 0 ? _x : DEFAULT_EYE_ROTATION_SCALE
    this.pickPlaneSizeScale = (_z = (_y = this.options) === null || _y === void 0 ? void 0 : _y.pickPlaneSizeScale) !== null && _z !== void 0 ? _z : DEFAULT_PLANE_SIZE_SCALE
    this.translationDistanceScale = (_1 = (_0 = this.options) === null || _0 === void 0 ? void 0 : _0.translationDistanceScale) !== null && _1 !== void 0 ? _1 : DEFAULT_TRANSLATION_DISTANCE_SCALE
    if (this.options.orientation !== undefined) {
      const _2 = this.options.orientation; const x = _2.x; const y = _2.y; const z = _2.z; const w = _2.w
      this.initialSelfQuaternion.set(x, y, z, w).normalize()
      this.quaternion.copy(this.initialSelfQuaternion)
    }
    this.computeObjectBounds()
    this.pick = new Pick()
    this.pickPlaneXY = new PickPlane('yellow', this.boundingSphereRadius * this.pickPlaneSizeScale, this.boundingSphereRadius * this.pickPlaneSizeScale, 'XY')
    this.pickPlaneYZ = new PickPlane('cyan', this.boundingSphereRadius * this.pickPlaneSizeScale, this.boundingSphereRadius * this.pickPlaneSizeScale, 'YZ')
    this.pickPlaneZX = new PickPlane('pink', this.boundingSphereRadius * this.pickPlaneSizeScale, this.boundingSphereRadius * this.pickPlaneSizeScale, 'ZX')
    this.translationXP = new Translation('#ff0000', this.boundingSphereRadius)
    this.translationYP = new Translation('#00d400', this.boundingSphereRadius)
    this.translationZP = new Translation('#0000ff', this.boundingSphereRadius)
    this.rotationX = new Rotation('#ff0000', -this.boundingSphereRadius * this.rotationRadiusScale, 'X')
    this.rotationY = new Rotation('#00d400', this.boundingSphereRadius * this.rotationRadiusScale, 'Y')
    this.rotationZ = new Rotation('#0000ff', this.boundingSphereRadius * this.rotationRadiusScale, 'Z')
    // _this.rotationEye = new RotationEye("yellow", _this.boundingSphereRadius * this.eyeRotationRadiusScale)
    this.setupDefaultTranslation()
    this.setupDefaultRotation()
    // _this.setupDefaultEyeRotation()
    this.setupDefaultPickPlane()
    this.setupDefaultPick()
    return this
  }
  getInteractiveObjects() {
    const interactiveObjects = []
    this.handles.forEach((handle) => {
      if (!handle.visible) return
      interactiveObjects.push.apply(interactiveObjects, handle.getInteractiveObjects())
    })
    return interactiveObjects
  }
}

function createCommonjsModule(fn) {
  const module = { exports: {}}
  return fn(module, module.exports), module.exports
}

const nanoevents = createCommonjsModule(function(module) {
  (
  /**
	 * Interface for event subscription.
	 *
	 * @example
	 * let NanoEvents = require('nanoevents')
	 *
	 * class Ticker {
	 *   constructor() {
	 *     this.emitter = new NanoEvents()
	 *   }
	 *   on() {
	 *     return this.emitter.on.apply(this.events, arguments)
	 *   }
	 *   tick() {
	 *     this.emitter.emit('tick')
	 *   }
	 * }
	 *
	 * @alias NanoEvents
	 * @class
	 */
    module.exports = function NanoEvents() {
      /**
		 * Event names in keys and arrays with listeners in values.
		 * @type {object}
		 *
		 * @example
		 * Object.keys(ee.events)
		 *
		 * @alias NanoEvents#events
		 */
      this.events = {}
    }
  ).prototype = {
    /**
	 * Calls each of the listeners registered for a given event.
	 *
	 * @param {string} event The event name.
	 * @param {...*} arguments The arguments for listeners.
	 *
	 * @return {undefined}
	 *
	 * @example
	 * ee.emit('tick', tickType, tickDuration)
	 *
	 * @alias NanoEvents#emit
	 * @method
	 */
    emit: function emit(event) {
      const args = [].slice.call(arguments, 1)
		;[].slice.call(this.events[event] || []).filter(function(i) {
        i.apply(null, args)
      })
    },

    /**
	 * Add a listener for a given event.
	 *
	 * @param {string} event The event name.
	 * @param {function} cb The listener function.
	 *
	 * @return {function} Unbind listener from event.
	 *
	 * @example
	 * const unbind = ee.on('tick', (tickType, tickDuration) => {
	 *   count += 1
	 * })
	 *
	 * disable () {
	 *   unbind()
	 * }
	 *
	 * @alias NanoEvents#on
	 * @method
	 */
    on: function on(event, cb) {
      (this.events[event] = this.events[event] || []).push(cb)
      return function() {
        this.events[event] = this.events[event].filter(function(i) {
          return i !== cb
        })
      }.bind(this)
    }
  }
})

/**
 * Removes all listeners.
 *
 * @param {NanoEvents} emitter NanoEvents instance.
 *
 * @returns {undefined}
 *
 * @example
 * unbindAll(emitter)
 */
function unbindAll(emitter) {
  emitter.events = { }
}
const unbindAll_1 = unbindAll
const emitter = new nanoevents()
const unbindAll$1 = function() { return unbindAll_1(emitter) }

const getPointFromEvent = function(event) {
  let clientX = 0
  let clientY = 0
  if (event instanceof MouseEvent) {
    clientX = event.clientX
    clientY = event.clientY
  } else if (event instanceof TouchEvent) {
    if (event.touches.length === 0) return null
    clientX = event.touches[0].clientX
    clientY = event.touches[0].clientY
  }
  return { clientX: clientX, clientY: clientY }
}
const addEventListener = function(element, eventNames, callback, options) {
  if (options === void 0) { options = false }
  eventNames.forEach(function(name) {
    element.addEventListener(name, callback, options)
  })
}
const removeEventListener = function(element, eventNames, callback, options) {
  if (options === void 0) { options = false }
  eventNames.forEach(function(name) {
    element.removeEventListener(name, callback, options)
  })
}

/**
 * @hidden
 * The Raycaster listens on the mouse and touch events globally and
 * dispatches DRAG_START, DRAG, and DRAG_STOP events.
 */

class Raycaster extends Raycaster$1 {
  constructor(camera, domElement, controls, editor) {
    super()
    const _this = this
    _this.camera = camera
    _this.editor = editor
    _this.scene = camera.parent
    _this.domElement = domElement
    _this.controls = controls
    _this.mouse = new Vector2()
    _this.cameraPosition = new Vector3()
    _this.activeHandle = null
    _this.activePlane = null
    _this.point = new Vector3()
    _this.normal = new Vector3()
    _this.visibleHandles = []
    _this.visibleControls = []
    _this.helperPlane = null
    _this.controlsWorldQuaternion = new Quaternion()
    _this.clientDiagonalLength = 1
    _this.previousScreenPoint = new Vector2()
    _this.currentScreenPoint = new Vector2()
    _this.isActivePlaneFlipped = false
    _this.createAxisLine = function() {
      const geometry = new BufferGeometry()
      const vertices = new Float32Array([
        0, 0, -100,
        0, 0, 100
      ])
      geometry.setAttribute('position', new BufferAttribute(vertices, 3))
      // geometry.vertices.push(new Vector3(0, 0, -100))
      // geometry.vertices.push(new Vector3(0, 0, 100))
      return new Line('white', geometry)
    }
    _this.pointerDownListener = function(event) {
      let _a
      if (event.button === 2 || event.button === 1) return // 阻止鼠标右键、中键点击事件
      const point = getPointFromEvent(event)
      // touches can be empty
      if (!point) return
      const clientX = point.clientX; const clientY = point.clientY
      _this.setRayDirection(clientX, clientY)
      // useful for calculating dragRatio (used in dampingFactor calculation)
      _this.clientDiagonalLength = Math.sqrt(Math.pow(event.target.clientWidth, 2) + Math.pow(event.target.clientHeight, 2))
      _this.previousScreenPoint.set(clientX, clientY)
      const interactiveObjects = []
      Object.values(_this.controls).map(function(controls) {
        interactiveObjects.push.apply(interactiveObjects, controls.getInteractiveObjects())
      })
      _this.activeHandle = _this.resolveHandleGroup(_this.intersectObjects(interactiveObjects, true)[0])
      if ((_a = _this.activeHandle) === null || _a === void 0 ? void 0 : _a.parent) {
        const controls = _this.activeHandle.parent
        // hiding other controls and handles instances if asked
        if (controls.hideOtherControlsInstancesOnDrag) {
          Object.values(_this.controls).forEach(function(x) {
            if (x.visible) _this.visibleControls.push(x)
            x.visible = false
          })
          controls.visible = true
        }
        if (controls.hideOtherHandlesOnDrag) {
          controls.children.map(function(handle) {
            if (handle.visible) _this.visibleHandles.push(handle)
            handle.visible = false
          })
          _this.activeHandle.visible = true
        }
        if (_this.activeHandle instanceof PickPlane) _this.setPickPlaneOpacity(PICK_PLANE_OPACITY.ACTIVE)

        /**
				 * creating the activePlane - the plane on which intersection actions
				 * take place. mouse movements are translated to points on the activePlane
				 */
        _this.activePlane = new Plane$1()
        const eyePlaneNormal = _this.getEyePlaneNormal(_this.activeHandle)
        controls.getWorldQuaternion(_this.controlsWorldQuaternion)
        _this.normal.copy(_this.activeHandle instanceof PickGroup ? eyePlaneNormal : _this.activeHandle.up)
        if (!(_this.activeHandle instanceof RotationEye || _this.activeHandle instanceof PickGroup)) {
          _this.normal.applyQuaternion(_this.controlsWorldQuaternion)
        }
        /*
				  if the angle between the eye-normal and the normal to the activePlane is
				  too small, a small mouse movement makes a large projection on the activePlane,
				  causing the object to jump big distances. To avoid this, the activePlane
				  is flipped by 90 degrees about the parallel vector of the handle.
				  This problem only requires mitigation in the TranslationGroup handle case.
				 */
        if (_this.activeHandle instanceof TranslationGroup) {
          const dot = eyePlaneNormal.dot(_this.normal) / eyePlaneNormal.length()
          // arccos(0.25) ~= 75 degrees
          // this is the threshold to make the plane normal flip
          _this.isActivePlaneFlipped = Math.abs(dot) < 0.25
          if (_this.isActivePlaneFlipped) {
            _this.isActivePlaneFlipped = true
            _this.normal.applyAxisAngle(_this.activeHandle.parallel, Math.PI / 2)
          }
        }
        if (_this.activeHandle instanceof TranslationGroup) {
          _this.activePlane.setFromNormalAndCoplanarPoint(_this.normal, _this.activeHandle.position)
        } else {
          _this.activePlane.setFromNormalAndCoplanarPoint(_this.normal, controls.position)
        }
        // find initial intersection
        const initialIntersectionPoint = new Vector3()
        if (_this.activeHandle instanceof PickGroup) {
          _this.activeHandle.getWorldPosition(initialIntersectionPoint)
        } else {
          _this.ray.intersectPlane(_this.activePlane, initialIntersectionPoint)
        }
        // activate the helper plane if asked
        // available only for TranslationGroup and RotationGroup
        // (except RotationEye - plane of rotation is obvious)
        const scene = controls.parent
        if (controls.showHelperPlane && (_this.activeHandle instanceof TranslationGroup || _this.activeHandle instanceof RotationGroup) && !(_this.activeHandle instanceof RotationEye)) {
          _this.helperPlane = new PlaneHelper(_this.activePlane, 1)
          scene.add(_this.helperPlane)
        }
        /**
				 * activate the highlightAxis if asked
				 * available only for TranslationGroup and RotationGroup
				 * (except RotationEye - plane of rotation is obvious)
				 */
        if (controls.highlightAxis && (_this.activeHandle instanceof TranslationGroup || _this.activeHandle instanceof RotationGroup) && !(_this.activeHandle instanceof RotationEye)) {
          _this.activeHandle.getWorldPosition(_this.highlightAxisLine.position)
          const direction = _this.highlightAxisLine.position.clone()
          if (_this.activeHandle instanceof TranslationGroup) {
            direction.add(_this.activeHandle.parallel)
          } else {
            direction.add(_this.activeHandle.up)
          }
          _this.highlightAxisLine.lookAt(direction)
          scene.add(_this.highlightAxisLine)
        }
        // switch event listeners and dispatch DRAG_START
        removeEventListener(_this.domElement, ['pointerdown', 'touchstart'], _this.pointerDownListener, {
          capture: true
        })
        emitter.emit(EVENTS.DRAG_START, {
          point: initialIntersectionPoint,
          handle: _this.activeHandle
        })
        addEventListener(_this.domElement, ['pointermove', 'touchmove'], _this.pointerMoveListener, {
          passive: false,
          capture: true
        })
      } else {
        _this.activePlane = null
      }
    }
    _this.getEyePlaneNormal = function(object) {
      _this.cameraPosition.copy(_this.camera.position)
      return _this.cameraPosition.sub(object.position)
    }
    _this.setRayDirection = function(clientX, clientY) {
      const rect = _this.domElement.getBoundingClientRect()
      const _a = _this.domElement; const clientHeight = _a.clientHeight; const clientWidth = _a.clientWidth
      _this.mouse.x = ((clientX - rect.left) / clientWidth) * 2 - 1
      _this.mouse.y = -((clientY - rect.top) / clientHeight) * 2 + 1
      _this.setFromCamera(_this.mouse, _this.camera)
    }
    _this.pointerMoveListener = function(event) {
      if (_this.activeHandle === null || _this.activePlane === null) return
      if (_this.editor.craftType === 2) {
        if (!_this.editor.isDragRobot) return
      }
      const point = getPointFromEvent(event)
      if (!point) return
      const clientX = point.clientX; const clientY = point.clientY
      _this.setRayDirection(clientX, clientY)
      _this.ray.intersectPlane(_this.activePlane, _this.point)
      _this.currentScreenPoint.set(clientX, clientY)
      const distance = _this.currentScreenPoint.distanceTo(_this.previousScreenPoint)
      const dragRatio = distance / (_this.clientDiagonalLength || 1)
      emitter.emit(EVENTS.DRAG, {
        point: _this.point,
        handle: _this.activeHandle,
        dragRatio: dragRatio
      })
      _this.editor.isDragRobot = false
      _this.previousScreenPoint.set(clientX, clientY)
    }
    _this.pointerUpListener = function() {
      let _a, _b, _c, _d
      removeEventListener(_this.domElement, ['pointermove', 'touchmove'], _this.pointerMoveListener, {
        capture: true
      })
      addEventListener(_this.domElement, ['pointerdown', 'touchstart'], _this.pointerDownListener, {
        passive: false,
        capture: true
      })
      emitter.emit(EVENTS.DRAG_STOP, { point: _this.point, handle: _this.activeHandle })
      if (((_a = _this.activeHandle) === null || _a === void 0 ? void 0 : _a.parent) &&
				_this.activeHandle.parent.hideOtherControlsInstancesOnDrag) {
        _this.visibleControls.forEach(function(controls) {
          controls.visible = true
        })
        _this.visibleControls = []
      }
      if (((_b = _this.activeHandle) === null || _b === void 0 ? void 0 : _b.parent) &&
				_this.activeHandle.parent.hideOtherHandlesOnDrag) {
        _this.visibleHandles.forEach(function(handle) {
          handle.visible = true
        })
        _this.visibleHandles = []
      }
      if (_this.activeHandle instanceof PickPlane) _this.setPickPlaneOpacity(PICK_PLANE_OPACITY.INACTIVE)
      const scene = (_d = (_c = _this.activeHandle) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.parent
      if (scene) {
        if (_this.helperPlane) scene.remove(_this.helperPlane)
        scene.remove(_this.highlightAxisLine)
      }
      _this.activeHandle = null
      _this.activePlane = null
    }
    _this.resolveHandleGroup = function(intersectedObject) {
      if (intersectedObject === undefined) return null
      return intersectedObject.object.parent
    }
    _this.destroy = function() {
      _this.activePlane = null
      _this.activeHandle = null
      removeEventListener(_this.domElement, ['pointerdown', 'touchstart'], _this.pointerDownListener, {
        capture: true
      })
      removeEventListener(_this.domElement, ['pointermove', 'touchmove'], _this.pointerMoveListener, {
        capture: true
      })
      removeEventListener(_this.domElement, ['pointerup', 'touchend'], _this.pointerUpListener, {
        capture: true
      })
    }
    _this.highlightAxisLine = _this.createAxisLine()
    /**
		 * mousedown and touchstart are used instead of pointerdown because
		 * pointermove seems to stop firing after some a few events in chrome mobile
		 * this could be because of some capture/passive setting but couldn't find
		 * anything useful. using touch(*) events works.
		 */
    addEventListener(_this.domElement, ['pointerdown', 'touchstart'], _this.pointerDownListener, {
      passive: false,
      capture: true
    })
    addEventListener(_this.domElement, ['pointerup', 'touchend'], _this.pointerUpListener, {
      passive: false,
      capture: true
    })
    return _this
  }
  setPickPlaneOpacity(opacity) {
    if (!(this.activeHandle instanceof PickPlane)) return
    const material = this.activeHandle.plane.material
    if (Array.isArray(material)) {
      material.map(function(m) {
        m.opacity = opacity
        m.needsUpdate = true
      })
    } else {
      material.opacity = opacity
      material.needsUpdate = true
    }
  }
}

/**
 * The ControlsManagerCraft provides helper functions to create Controls instances
 * and link them up with a Raycaster instance (reused across multiple Controls
 * instances).
 * @noInheritDoc
 */

class ControlsManagerCraft extends Object3D {
  constructor(camera, domElement, editor) {
    super()
    let _a
    const _this = this
    _this.camera = camera
    _this.editor = editor
    _this.domElement = domElement
    _this.objects = {}
    _this.controls = {}
    _this.moveDelta = 0
    _this.eventListeners = (_a = {},
    _a[EVENTS.DRAG_START] = [],
    _a[EVENTS.DRAG] = [],
    _a[EVENTS.DRAG_STOP] = [],
    _a[EVENTS.change] = [],
    _a[EVENTS.objectChange] = [],
    _a)
    _this.listenToEvents = function() {
      emitter.on(EVENTS.DRAG_START, function(_a) {
        const point = _a.point; const handle = _a.handle
        if (handle === null) return
        const controls = handle.parent
        if (controls === null) return
        // _this.editor.isDragRobot = true
        controls.processDragStart({ point: point, handle: handle })
        _this.eventListeners[EVENTS.DRAG_START].map((callback) => {
          callback(controls.object, handle.name)
        })
      })
      emitter.on(EVENTS.DRAG, function(_a) {
        const point = _a.point; const handle = _a.handle; const dragRatio = _a.dragRatio
        if (handle === null) return
        const controls = handle.parent
        if (controls === null) return
        controls.processDrag({ point: point, handle: handle, dragRatio: dragRatio })
        _this.eventListeners[EVENTS.DRAG].map((callback) => {
          callback(controls.object, handle.name)
        })
        _this.eventListeners[EVENTS.change].map((callback) => {
          callback(controls.object, handle.name)
        })
        _this.eventListeners[EVENTS.objectChange].map((callback) => {
          callback(controls.object, handle.name)
        })
      })
      emitter.on(EVENTS.DRAG_STOP, (_a) => {
        const handle = _a.handle
        if (handle === null) return
        const controls = handle.parent
        if (controls === null) return
        controls.processDragEnd({ handle: handle })
        _this.eventListeners[EVENTS.DRAG_STOP].map((callback) => {
          callback(controls.object, handle.name)
        })
      })
    }
    /**
		 * Creates a Controls instance and attaches it to the provided THREE.js object
		 *
		 * @param object - the object provided by the user
		 * @param options
		 */
    _this.anchor = function(object, options) {
      if (!object) return
      const controls = _this.addControls(object, options)
      _this.objects[object.id] = object
      return controls
    }
    /**
		 * Detaches the Controls instance from the provided THREE.js object
		 *
		 * @param object - the object provided by the user
		 * @param controls - the controls instance anchored on the object
		 */
    _this.detach = function(object, controls) {
      if (!_this.objects.hasOwnProperty(object.id)) {
        console.log('object should be attached first')
        return
      }
      _this.remove(controls)
      _this.dispose(controls)
      delete _this.objects[object.id]
      delete _this.controls[controls.id]
    }
    _this.addControls = function(object, options) {
      Object.keys(_this.controls).forEach(function(key) {
        // 让场景中只有一个控制器
        _this.detach(_this.controls[key].object, _this.controls[key])
      })
      const controls = new Controls(object, _this.camera, options)
      _this.controls[controls.id] = controls
      _this.add(controls)
      return controls
    }
    /**
		 * Adds an event listener. Note that there is another method `addEventListener`
		 * on THREE.Object3D from which this class extends but that is specific to the
		 * internals of THREE.js, but not this library
		 * @param event
		 * @param callback - by default the second argument is the default group name
		 * for the Handle involved; for a custom handle, it is the `name` property
		 * set on the handle
		 */
    _this.listen = function(event, callback) {
      _this.eventListeners[event].push(callback)
    }
    /**
		 * Removes the event listener.
		 * @param event
		 * @param callback
		 */
    _this.removeListen = function(event, callback) {
      const index = _this.eventListeners[event].findIndex(function(x) { return x === callback })
      if (index !== -1) _this.eventListeners[event].splice(index, 1)
    }
    _this.dispose = function(object) {
      if (object instanceof Mesh) {
        object.geometry.dispose()
        if (Array.isArray(object.material)) {
          object.material.map(function(material) { return material.dispose() })
        } else {
          object.material.dispose()
        }
      }
      while (object.children.length > 0) {
        object.children.map((child) => {
          _this.dispose(child)
          object.remove(child)
        })
      }
    }
    /**
		 * Destroys all Controls instances and removes all event listeners
		 */
    _this.destroy = function() {
      let _a
      unbindAll$1()
      const scene = _this.parent
      if (scene !== null) scene.remove(_this)
      _this.dispose(_this)
      Object.values(_this.controls).map((control) => { _this.dispose(control) })
      _this.rayCaster.destroy()
      _this.objects = {}
      _this.controls = {}
      _this.eventListeners = (_a = {},
      _a[EVENTS.DRAG_START] = [],
      _a[EVENTS.DRAG] = [],
      _a[EVENTS.DRAG_STOP] = [],
      _a)
    }
    _this.rayCaster = new Raycaster(_this.camera, _this.domElement, _this.controls, _this.editor)
    _this.listenToEvents()
    _this.changeAxisMode = function(spaceName) {
      if (!controlObject) throw new Error('模型不存在')
      transformMode = spaceName
      Object.keys(_this.controls).forEach((key) => {
        // 让场景中只有一个控制器
        _this.controls[key].transformMode = spaceName
      })
    }
    return _this
  }
}

export { ANCHOR_MODE, ControlsManagerCraft, DEFAULT_HANDLE_GROUP_NAME, EVENTS, Pick, PickPlane, PickPlaneGroup, Rotation, RotationGroup, Translation, TranslationGroup }

