/
TransformControlsPlugin.ts
112 lines (98 loc) · 4.65 KB
/
TransformControlsPlugin.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import {uiButton, uiConfig, uiPanelContainer, uiToggle} from 'uiconfig.js'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {OrbitControls3, TransformControls2} from '../../three'
import {PickingPlugin} from './PickingPlugin'
import {onChange} from 'ts-browser-helpers'
import {TransformControls} from '../../three/controls/TransformControls'
import {UnlitLineMaterial, UnlitMaterial} from '../../core'
@uiPanelContainer('Transform Controls')
export class TransformControlsPlugin extends AViewerPluginSync<''> {
public static readonly PluginType = 'TransformControlsPlugin'
@uiToggle()
@onChange(TransformControlsPlugin.prototype.setDirty)
enabled = true
private _pickingWidgetDisabled = false
setDirty() { // todo rename to refresh or setEnabledDirty?
if (!this._viewer) return
const picking = this._viewer.getPlugin(PickingPlugin)!
const enabled = !this.isDisabled()
if (enabled && picking.widgetEnabled) {
picking.widgetEnabled = false
this._pickingWidgetDisabled = true
} else if (!enabled && this._pickingWidgetDisabled) {
picking.widgetEnabled = true
this._pickingWidgetDisabled = false
}
if (this.transformControls) {
if (enabled && picking.getSelectedObject()) this.transformControls.attach(picking.getSelectedObject()!)
else this.transformControls.detach()
}
this._viewer.setDirty()
}
constructor(enabled = true) {
super()
TransformControls.ObjectConstructors.MeshBasicMaterial = UnlitMaterial as any
TransformControls.ObjectConstructors.LineBasicMaterial = UnlitLineMaterial as any
this.enabled = enabled
}
toJSON: any = undefined
dependencies = [PickingPlugin]
@uiConfig(undefined, {expanded: true})
transformControls: TransformControls2 | undefined
protected _isInteracting = false
protected _viewerListeners = {
postFrame: ()=>{
if (!this.transformControls || !this._viewer) return
// this._viewer.scene.mainCamera.setInteractions(!this._isInteracting, TransformControlsPlugin.PluginType)
},
}
onAdded(viewer: ThreeViewer) {
super.onAdded(viewer)
this.setDirty()
this.transformControls = new TransformControls2(viewer.scene.mainCamera, viewer.canvas)
this._mainCameraChange = this._mainCameraChange.bind(this)
viewer.scene.addEventListener('mainCameraChange', this._mainCameraChange)
this.transformControls.addEventListener('dragging-changed', (event) => {
if (!this?._viewer) return
const controls = this._viewer.scene.mainCamera.controls
if (typeof (controls as any)?.stopDamping === 'function' && controls?.enabled) (controls as OrbitControls3).stopDamping()
this._viewer.scene.mainCamera.setInteractions(!event.value, TransformControlsPlugin.PluginType)
// this._viewer.scene.mainCamera.autoNearFar = !event.value // todo: maintain state
})
this.transformControls.addEventListener('axis-changed', (event) => {
if (!this?._viewer) return
this._isInteracting = !!event.value
const controls = this._viewer.scene.mainCamera.controls
if (typeof (controls as any)?.stopDamping === 'function' && controls?.enabled) (controls as OrbitControls3).stopDamping()
this._viewer.setDirty() // rerender for color change
})
viewer.scene.addObject(this.transformControls, {addToRoot: true})
const picking = viewer.getPlugin(PickingPlugin)!
picking.addEventListener('selectedObjectChanged', (event) => {
if (!this.transformControls) return
if (this.isDisabled()) {
if (this.transformControls.object) this.transformControls.detach()
return
}
event.object ? this.transformControls.attach(event.object) : this.transformControls.detach()
})
}
onRemove(viewer: ThreeViewer) {
viewer.scene.removeEventListener('mainCameraChange', this._mainCameraChange)
if (this.transformControls) {
this.transformControls.detach()
viewer.scene.remove(this.transformControls)
this.transformControls.dispose()
}
this.transformControls = undefined
super.onRemove(viewer)
}
private _mainCameraChange = () => {
if (!this.transformControls || !this._viewer) return
this.transformControls.camera = this._viewer.scene.mainCamera
}
@uiButton('Center All Meshes')
centerAllMeshes() {
this._viewer?.scene.centerAllGeometries(true)
}
}