-
Notifications
You must be signed in to change notification settings - Fork 12
/
Object3DWidgetsPlugin.ts
112 lines (98 loc) · 3.41 KB
/
Object3DWidgetsPlugin.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 {UiObjectConfig} from 'uiconfig.js'
import {IWidget} from '../../core'
import {AViewerPluginSync, ThreeViewer} from '../../viewer'
import {IEvent, onChange} from 'ts-browser-helpers'
import {Object3D} from 'three'
import {CameraHelper2, DirectionalLightHelper2, PointLightHelper2, SpotLightHelper2} from '../../three'
export interface IObject3DHelper<T extends Object3D&IWidget = Object3D&IWidget>{
Create: (o: Object3D)=>T,
Check: (o: Object3D)=>boolean,
}
/**
* Adds light and camera helpers/gizmos in the viewer.
* A helper is automatically created when any supported light or camera is added to the scene.
* @category Plugin
*/
export class Object3DWidgetsPlugin extends AViewerPluginSync<''> {
@onChange(Object3DWidgetsPlugin.prototype.setDirty)
enabled = true
public static readonly PluginType = 'Object3DWidgetsPlugin'
helpers: IObject3DHelper[] = [
DirectionalLightHelper2,
SpotLightHelper2,
PointLightHelper2,
CameraHelper2,
]
setDirty() {
this.widgets?.forEach(w => w.visible = !this.isDisabled())
this._viewer?.setDirty()
}
toJSON: any = null
constructor(enabled = true) {
super()
this.enabled = enabled
}
private _widgetRoot = new Object3D()
onAdded(viewer: ThreeViewer) {
super.onAdded(viewer)
viewer.scene.addEventListener('addSceneObject', this._addSceneObject)
viewer.scene.addObject(this._widgetRoot)
}
onRemove(viewer: ThreeViewer) {
viewer.scene.removeEventListener('addSceneObject', this._addSceneObject)
this.widgets.forEach(w => w.dispose && w.dispose())
this.widgets = []
this._widgetRoot.removeFromParent()
this._widgetRoot.clear()
super.onRemove(viewer)
}
private _addSceneObject = (e: any)=>{
this._createWidgets(e.object)
}
refresh() {
this._createWidgets(this._viewer?.scene.modelRoot)
}
widgets: (IWidget&Object3D)[] = []
private _widgetDisposed = (e: IEvent<any>)=> this._unregisterWidget(e.target)
private _registerWidget(w: IWidget&Object3D) {
this.widgets.push(w)
w.addEventListener('dispose', this._widgetDisposed) // todo: maybe unregister when removed from parent, dispose makes little sense.
}
private _unregisterWidget(w: IWidget&Object3D) {
w.removeEventListener('dispose', this._widgetDisposed)
const i = this.widgets.indexOf(w)
if (i >= 0) this.widgets.splice(i, 1)
}
private _createWidgets(o?: Object3D) {
o?.traverse((l: any) => {
const widget = this.widgets.find(w => w.object === l)
if (widget) {
widget.update && widget.update()
return
}
const helpers = this.helpers.filter(h => h.Check(l))
helpers.forEach(h => {
const w = h.Create(l)
w.visible = !this.isDisabled()
this._widgetRoot.add(w)
this._registerWidget(w)
})
})
}
uiConfig: UiObjectConfig = {
type: 'folder',
label: 'Widgets',
children: [
{
type: 'checkbox',
label: 'Enabled',
property: [this, 'enabled'],
},
{
type: 'button',
label: 'Refresh',
value: ()=>this.refresh(),
},
],
}
}