TransformationTool.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * TransformationTool.js
  3. *
  4. * @author realor
  5. */
  6. import { Tool } from './Tool.js'
  7. import { I18N } from '../i18n/I18N.js'
  8. import { PointSelector } from '../utils/PointSelector.js'
  9. import * as THREE from '../lib/three.module.js'
  10. class TransformationTool extends Tool {
  11. constructor(application, options) {
  12. super(application)
  13. this.panel = null
  14. this.stage = 0
  15. this.objectMatrices = new Map()
  16. this._onPointerUp = this.onPointerUp.bind(this)
  17. this._onPointerMove = this.onPointerMove.bind(this)
  18. this._onContextMenu = this.onContextMenu.bind(this)
  19. this.axisMatrixWorld = new THREE.Matrix4()
  20. this._matrix1 = new THREE.Matrix4()
  21. this._matrix2 = new THREE.Matrix4()
  22. this._matrix3 = new THREE.Matrix4()
  23. application.addEventListener('scene', event => {
  24. if (event.type === 'structureChanged' && event.objects[0] instanceof THREE.Scene) {
  25. this.resetTool()
  26. }
  27. })
  28. application.addEventListener('tool', event => {
  29. const tool = event.tool
  30. const type = event.type
  31. if (type === 'activated' && tool instanceof TransformationTool && tool !== this) {
  32. this.resetTool()
  33. }
  34. })
  35. }
  36. createPanel() {
  37. console.warn('abstract method')
  38. }
  39. activate() {
  40. this.panel.visible = true
  41. const container = this.application.container
  42. container.addEventListener('contextmenu', this._onContextMenu, false)
  43. container.addEventListener('pointerup', this._onPointerUp, false)
  44. container.addEventListener('pointermove', this._onPointerMove, false)
  45. this.setStage(this.stage)
  46. }
  47. deactivate() {
  48. this.panel.visible = false
  49. const container = this.application.container
  50. container.removeEventListener('contextmenu', this._onContextMenu, false)
  51. container.removeEventListener('pointerup', this._onPointerUp, false)
  52. container.removeEventListener('pointermove', this._onPointerMove, false)
  53. this.application.pointSelector.deactivate()
  54. }
  55. setStage(stage) {
  56. console.warn('abstract method')
  57. }
  58. onPointerUp(event) {}
  59. onPointerMove(event) {}
  60. onContextMenu(event) {
  61. const pointSelector = this.application.pointSelector
  62. if (!pointSelector.isPointSelectionEvent(event)) return
  63. event.preventDefault()
  64. }
  65. transformObjects(transformMatrixWorld, changedProperties) {
  66. const application = this.application
  67. const roots = application.selection.roots
  68. const localMoveMatrix = this._matrix2
  69. const parentMatrixInverse = this._matrix3
  70. for (let object of roots) {
  71. let objectMatrix = this.objectMatrices.get(object)
  72. if (objectMatrix === undefined) {
  73. objectMatrix = object.matrix.clone()
  74. this.objectMatrices.set(object, objectMatrix)
  75. }
  76. object.parent.updateMatrix()
  77. object.parent.updateMatrixWorld()
  78. localMoveMatrix.copy(object.parent.matrixWorld)
  79. localMoveMatrix.premultiply(transformMatrixWorld)
  80. parentMatrixInverse.copy(object.parent.matrixWorld).invert()
  81. localMoveMatrix.premultiply(parentMatrixInverse)
  82. localMoveMatrix.multiply(objectMatrix)
  83. localMoveMatrix.decompose(object.position, object.quaternion, object.scale)
  84. object.updateMatrix()
  85. object.updateMatrixWorld()
  86. }
  87. application.notifyObjectsChanged(roots, this, 'nodeChanged', changedProperties)
  88. }
  89. resetTool() {
  90. this.objectMatrices.clear()
  91. this.stage = 0
  92. }
  93. }
  94. export { TransformationTool }