-
Notifications
You must be signed in to change notification settings - Fork 22
/
MaterialConfiguratorPlugin.ts
108 lines (96 loc) · 4.73 KB
/
MaterialConfiguratorPlugin.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
import {CustomContextMenu, MaterialConfiguratorBasePlugin, MaterialVariations} from 'threepipe'
import {GridItemListPlugin} from './GridItemListPlugin'
/**
* Material Configurator Plugin (Basic UI)
* This plugin allows you to create variations of materials mapped to material names or uuids in the scene.
* These variations can be applied to the materials in the scene. (This copies the properties to the same material instances instead of assigning new materials)
* The plugin interfaces with the picking plugin and also provides uiConfig to show and edit the variations.
* This functionality is inherited from `MaterialConfiguratorBasePlugin`
*
* Additionally this plugin adds a Grid UI using {@link GridItemListPlugin} in the DOM over the viewer canvas to show various material variations and allow the user to apply them.
* The UI can also be used in the editor to edit the variations and apply them.
*/
export class MaterialConfiguratorPlugin extends MaterialConfiguratorBasePlugin {
public static PluginType = 'MaterialConfiguratorPlugin'
enableEditContextMenus = false
dependencies = [GridItemListPlugin]
// must be called from preFrame
protected async _refreshUi(): Promise<boolean> {
if (!await super._refreshUi()) return false
const grid = this._viewer?.getPlugin(GridItemListPlugin)
if (!grid) return false
grid.removeAll(MaterialConfiguratorPlugin.PluginType)
for (const variation of this.variations) {
const container = grid.create(MaterialConfiguratorPlugin.PluginType,
variation.title + (this.enableEditContextMenus ? ' (' + variation.uuid + ')' : ''),
5,
20, 0,
variation.materials.map(m => {
const image = this.getPreview(m, variation.preview)
return {
id: m.uuid,
image, // : (m as any).map?.image ? imageBitmapToBase64((m as any).map.image, 100) : makeColorSvg((m as any).color ?? '#ffffff'),
onClick: (id:string) => this.applyVariation(variation, id),
tooltip: m.name || m.uuid,
}
}), (d, item)=> {
// todo test in shadow dom.
d.oncontextmenu = (e) => {
if (!this.enableEditContextMenus) return
e.preventDefault()
e.stopPropagation()
const menu = CustomContextMenu.Create(this.materialContextMenuItems(variation, item.id), e.clientX, e.clientY)
document.body.appendChild(menu)
}
})
container.oncontextmenu = (e) => {
if (!this.enableEditContextMenus) return
e.preventDefault()
e.stopPropagation()
const menu = CustomContextMenu.Create(this.variationsContextMenuItems(variation), e.clientX, e.clientY)
document.body.appendChild(menu)
}
}
grid.rebuildUi()
return true
}
materialContextMenuItems = (variation: MaterialVariations, uuid: string)=>({
['Remove']: async()=>{
const conf = await this._viewer?.dialog.confirm('Remove material: Remove material from this variation list?')
if (!conf) return
variation.materials = variation.materials.filter(m => m.uuid !== uuid)
this.refreshUi()
CustomContextMenu.Remove()
},
// todo set icon url
})
variationsContextMenuItems = (variation: MaterialVariations)=>({
['Rename mapping']: async() => {
const name = await this._viewer?.dialog.prompt('Change name: New material name to map to', variation.uuid, true)
if (name) {
variation.uuid = name
this.refreshUi()
}
},
['Rename title']: async() => {
const name = await this._viewer?.dialog.prompt('Change name: New material name to map to', variation.title, true)
if (name) {
variation.title = name
this.refreshUi()
}
},
['Clear Materials']: async()=>{
const conf = await this._viewer?.dialog.confirm('Remove all: Remove all materials from this variation list?')
if (!conf) return
variation.materials = []
this.refreshUi()
CustomContextMenu.Remove()
},
['Remove Section']: async()=>{
const conf = await this._viewer?.dialog.confirm('Remove variations: Remove this category of variations?')
if (!conf) return
this.removeVariation(variation)
CustomContextMenu.Remove()
},
})
}