-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpatch_bake.py
233 lines (169 loc) · 7.62 KB
/
patch_bake.py
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# ------------------------------------------------------------------------------
# Patch Bake
# ------------------------------------------------------------------------------
# Bakes the selected patches to images manager.
# Works the same as patches > extract selected but for the whole channel
# and on all the selected patches.
#
# copy the script to the same location as your log folder in
# windows: C:\Users\[user_name]\Documents\Mari\Scripts
# linux: /home/[user_name]/Mari/Scripts
# Mac: /home/[Username]/Mari/Scripts
#
# Creates a menu item in Patches > Patch Bake
#
# @uthor sreenivas alapati (cg-cnu)
# ------------------------------------------------------------------------------
import mari
import os
# ------------------------------------------------------------------------------
def returnTrue(layer):
"""Returns True for any object passed to it."""
return True
# ------------------------------------------------------------------------------
def getLayerList(layer_list, criterionFn):
"""Returns a list of all of the layers in the stack that match the given criterion function, including substacks."""
matching = []
for layer in layer_list:
if criterionFn(layer):
matching.append(layer)
if hasattr(layer, 'layerStack'):
matching.extend(getLayerList(layer.layerStack().layerList(), criterionFn))
if layer.hasMaskStack():
matching.extend(getLayerList(layer.maskStack().layerList(), criterionFn))
if hasattr(layer, 'hasAdjustmentStack') and layer.hasAdjustmentStack():
matching.extend(getLayerList(layer.adjustmentStack().layerList(), criterionFn))
if layer.isGroupLayer():
matching.extend(getLayerList(layer.layerStack().layerList(), criterionFn))
if layer.isChannelLayer():
matching.extend(getLayerList(layer.channel().layerList(), criterionFn))
return matching
# ------------------------------------------------------------------------------
def findLayerSelection():
"""Searches for the current selection if mari.current.layer is not the same as layer.isSelected"""
curGeo = mari.geo.current()
curChannel = curGeo.currentChannel()
channels = curGeo.channelList()
curLayer = mari.current.layer()
layers = ()
layerSelList = []
chn_layerList = ()
layerSelect = False
if curLayer.isSelected():
# If current layer is indeed selected one just trawl through current channel to find others
layerSelect = True
chn_layerList = curChannel.layerList()
layers = getLayerList(chn_layerList,returnTrue)
for layer in layers:
if layer.isSelected():
layerSelList.append(layer)
else:
# If current layer is not selected it means that a selection sits somewhere else (non-current channel)
# so we are going trawling through the entire channel list including substacks to find it
for channel in channels:
chn_layerList = channel.layerList()
layers = getLayerList(chn_layerList,returnTrue)
for layer in layers:
if layer.isSelected():
curLayer = layer
curChannel = channel
layerSelect = True
layerSelList.append(layer)
if not layerSelect:
mari.utils.message('No Layer Selection found. \n \n Please select at least one Layer.')
return curGeo,curLayer,curChannel,layerSelList
# ------------------------------------------------------------------------------
def patchBake():
'''Bakes selected Patches to Image Manager'''
if not mari.projects.current():
mari.utils.message('No project currently open', title = 'Error')
return
# Checking for OS to determine slash handling
if mari.app.version().isWindows():
path = str(mari.resources.path("MARI_USER_PATH")).replace("\\", "/")
else:
path = str( mari.resources.path("MARI_USER_PATH") )
# Determine general Selection Info
curGeo = mari.geo.current()
curChan = curGeo.currentChannel()
# MARI 3 Only:
# colorSpace = curChan.colorspaceConfig()
curChanName = str(curChan.name())
layers = curChan.layerList()
patchList = list (curGeo.patchList() )
selPatchList = [patch for patch in patchList if patch.isSelected() ]
if len(selPatchList) == 0:
mari.utils.message('Select at least one patch', title = 'Error')
return
# Deactivate Viewport for increases Spped
deactivateViewportToggle = mari.actions.find('/Mari/Canvas/Toggle Shader Compiling')
deactivateViewportToggle.trigger()
mari.history.startMacro('Patch Bake to Image Manager')
mari.app.setWaitCursor()
for layer in layers:
layer.setSelected(True)
copyAction = mari.actions.find('/Mari/Layers/Copy')
copyAction.trigger()
pasteAction = mari.actions.find('/Mari/Layers/Paste')
pasteAction.trigger()
#running search for current selection in order to get a list of all duplicated layers
geo_data = findLayerSelection()
# Geo Data = 0 current geo, 1 current channel , 2 current layer, 3 current selection list
curSel = geo_data[3]
channelLayerLst = []
#running search from all current selected layers to get a full list of all associated layers such as masks etc.
nested_layers = getLayerList(curSel,returnTrue)
# lookin through all layers that are associated with duplicates if there are any channel layers where we duplicated channels
for layer in nested_layers:
if layer.isChannelLayer():
channelLayerLst.append(layer.channel())
# merging the duplicated layers into one
curChan.mergeLayers()
# determine new current layer (result of merge),set name and grab its image set
curLayer = curChan.currentLayer()
curLayer.setName('BakeToImageManager')
curImgSet = curLayer.imageSet()
# extract current image set to image manager
for patch in selPatchList:
try:
uv = patch.uvIndex()
curPatchIndex = str(patch.udim())
savePath = path + curChanName + '.' + curPatchIndex + '.tif'
patchImg = curImgSet.image(uv, -1)
patchImg.saveAs(savePath)
# MARI 2.6:
mari.images.load(savePath)
# MARI 3:
# mari.images.open(savePath,colorSpace)
os.remove(savePath)
except Exception:
mari.history.stopMacro()
mari.app.restoreCursor()
pass
# Running cleanup: Close newly created layer out, close any channel duplicates that may have been created as a result of copy+paste
# of channel layers
curLayer.close()
for channel in channelLayerLst:
try:
curGeo.removeChannel(channel)
except Exception:
continue
# Stop Macro, restore cursor, refresh viewport
mari.history.stopMacro()
mari.app.restoreCursor()
deactivateViewportToggle.trigger()
def patch_bake_to_imageman():
patchBake()
### Patch Bake to Image Manager UI Integration
UI_path = 'MainWindow/&Patches'
script_menu_path = 'MainWindow/Scripts/Patches'
PatchToImageMgr= mari.actions.create('Patch to Image Manager', 'patch_bake_to_imageman()')
mari.menus.addAction(PatchToImageMgr, UI_path,'UV Mask to Image Manager')
mari.menus.addAction(PatchToImageMgr, script_menu_path)
icon_filename = 'SaveToImageManager.png'
icon_path = mari.resources.path(mari.resources.ICONS) + '/' + icon_filename
PatchToImageMgr.setIconPath(icon_path)
PatchToImageMgr.setShortcut('')
# --------------------------------------------------------------------
### Menu Separator ###
mari.menus.addSeparator(UI_path,'UV Mask to Image Manager')