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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
|
// Shave and a Haircut
// (c) 2019 Epic Games
// US Patent 6720962
global string $shavePresetWin_fileVersion = "$Revision$";
// global float $gAEAttrPresetBlend contains blend fraction
// global string $gAEAttrPresetCurrentTarget contains name of target node
//
// Then just execute the .mel file.
//
proc string getShavePresetDir(string $basePath)
{
string $paths[];
// 'basePath' may be a list of paths, so split them apart.
if (`about -win`)
tokenize $basePath ";" $paths;
else
tokenize $basePath ":" $paths;
// Look for a path which contains some shaveHair preset files.
string $path;
for ($path in $paths)
{
$path += "/attrPresets/shaveHair/";
string $files[] = `getFileList -folder $path -fs "*.mel"`;
if (size($files) > 0) return $path;
}
return "";
}
proc string getSwatchName(string $preset, string $tabName)
{
//
// Maya's icon caching ignores the directory portion of the icon's
// pathname, so we have to ensure that icons, even in different
// directories, have different names.
//
// We do this by inserting the first char of the tab name into the
// icon's file name, so make sure that your tab names are distinct in
// the first char.
//
return ($preset + "_" + substring($tabName, 1, 1) + "_swatch.xpm");
}
proc int isAProcedure(string $variable)
{
int $length = size($variable);
if ($length < 2)
{
// Too short to have "()" in it.
//
return false;
}
int $secondLast = $length -1;
if (`substring $variable $secondLast $length` == "()")
{
return true;
}
return false;
}
global proc shavePreset_doCallback(string $preset)
{
global string $shavePreset_callbackCmd;
if ($shavePreset_callbackCmd != "")
evalEcho($shavePreset_callbackCmd + " \"" + $preset + "\"");
if (`window -exists shavePresetWindow`) {
// Maya bug: The button that the user clicked on still has some
// outstanding internal events. If we destroy it here then those
// events will be referencing a deleted button and Maya may crash.
// So we put the destruction of the window onto the idle queue so
// that it won't happen until after the button's events have
// finished up.
evalDeferred("deleteUI shavePresetWindow");
}
}
proc int createTab(string $tabName, string $dir)
{
string $presets[] = `getFileList -folder $dir -fs "*.mel"`;
int $numPresets = size($presets);
string $scrollLayout = "shave" + $tabName + "Presets";
string $gridLayout = $scrollLayout + "Grid";
//
// Create a grid layout capable of holding all the presets and add it
// to the window's tab layout.
//
scrollLayout -p shavePresetTabs $scrollLayout;
tabLayout -e -tabLabel $scrollLayout $tabName shavePresetTabs;
if ($numPresets > 0)
{
gridLayout -nc 5 -cwh 100 120 -autoGrow true -p $scrollLayout $gridLayout;
//
// Find the default swatch, just in case we need it.
//
string $searchPath = getenv("XBMLANGPATH");
string $searchDirs[];
if (`about -nt`)
tokenize($searchPath, "%B;", $searchDirs);
else
tokenize($searchPath, "%B:", $searchDirs);
string $defaultSwatch = searchPathArray(
"shaveDefaultSwatch.xpm", $searchDirs
);
//
// Step through each preset and add a button for it to the row layout.
//
string $preset;
for ($preset in $presets)
{
$preset = basename($preset, ".mel");
//
// If we can't find a swatch specific to this preset, then use
// the default.
//
string $icon = $dir + getSwatchName($preset, $tabName);
if (!`filetest -r $icon`) $icon = $defaultSwatch;
//
// Create the button.
//
iconTextButton -p $gridLayout
-st "iconAndTextVertical" -l $preset
-width 100 -height 120 -i1 $icon
-c ("shavePreset_doCallback(\"" + $dir + $preset + ".mel\")");
}
}
else
{
gridLayout -p $scrollLayout $gridLayout;
}
return $numPresets;
}
global proc shavePresetWin(string $cmd)
{
global string $shavePreset_callbackCmd;
$shavePreset_callbackCmd = $cmd;
if (`window -exists shavePresetWindow`) deleteUI shavePresetWindow;
//does not seem help
//if (`window -exists shavePresetWindow`) {
// // Maya bug: The button that the user clicked on still has some
// // outstanding internal events. If we destroy it here then those
// // events will be referencing a deleted button and Maya may crash.
// // So we put the destruction of the window onto the idle queue so
// // that it won't happen until after the button's events have
// // finished up.
// evalDeferred("deleteUI shavePresetWindow");
// }
window shavePresetWindow;
tabLayout -cc "shavePreset_tabChanged" shavePresetTabs;
string $dir;
//
// Has the user provided an override for the Shave presets?
//
$dir = getenv("SHAVE_COMMON_PRESET_PATH");
if ($dir == "")
{
//
// Okay, how about a generic override for the location of all
// Shave-related files?
//
$dir = getenv("SHAVE_LOCATION");
if ($dir != "")
{
//
// They might have overridden SHAVE_LOCATION for some reason
// other than presets, so let's make sure that the presets are
// actually there.
//
$dir = getShavePresetDir($dir + "/presets");
}
if ($dir == "")
{
// Check MAYA_PRESET_PATH
$dir = getShavePresetDir(getenv("MAYA_PRESET_PATH"));
if ($dir == "")
{
// No overrides, so go with Maya's default location.
$dir = getenv("MAYA_LOCATION") + "/presets/attrPresets/shaveHair/";
}
}
}
else
{
if (substring($dir, size($dir), size($dir)) != "/")
$dir += "/";
}
int $numCommonPresets = createTab("Common", $dir);
$dir = `internalVar -userPrefDir`;
$dir = substitute("prefs", $dir, "presets/attrPresets");
$dir += "shaveHair/";
int $numPersonalPresets = createTab("Personal", $dir);
//
// Return the user to whichever tab zie was last on. If this is the
// first time and there is no current tab, then default to the user's
// personal tab, if it exists, otherwise to the common tab.
//
string $curTab = "";
if (`optionVar -exists shavePreset_curTab`)
$curTab = `optionVar -q shavePreset_curTab`;
if (($curTab != "shaveCommonPresets")
&& ($curTab != "shavePersonalPresets"))
{
if (($numPersonalPresets == 0) && ($numCommonPresets > 0))
$curTab = "shaveCommonPresets";
else
$curTab = "shavePersonalPresets";
}
tabLayout -e -selectTab $curTab shavePresetTabs;
optionVar -sv shavePreset_curTab $curTab;
showWindow shavePresetWindow;
//
// Make sure that all the button icons are up-to-date.
//
shavePreset_synchIcons();
}
global proc shavePreset_synchIcons()
{
if (`window -exists shavePresetWindow`)
{
string $buttons[] = `gridLayout -q -ca shaveCommonPresetsGrid`;
int $numButtons = size($buttons);
int $i;
for ($i = 0; $i < $numButtons; $i++)
{
string $icon = `iconTextButton -q -i1 $buttons[$i]`;
if (`shaveIcon -needsReload $icon`)
reloadImage $icon $buttons[$i];
}
$buttons = `gridLayout -q -ca shavePersonalPresetsGrid`;
$numButtons = size($buttons);
for ($i = 0; $i < $numButtons; $i++)
{
string $icon = `iconTextButton -q -i1 $buttons[$i]`;
if (`shaveIcon -needsReload $icon`)
reloadImage $icon $buttons[$i];
}
}
}
global proc shavePreset_tabChanged()
{
if (`tabLayout -exists shavePresetTabs`)
{
string $curTab = `tabLayout -q -selectTab shavePresetTabs`;
optionVar -sv shavePreset_curTab $curTab;
}
}
global proc shavePreset_apply(string $preset, string $shaveNode)
{
global float $gAEAttrPresetBlend;
global string $gAEAttrPresetCurrentTarget;
$gAEAttrPresetBlend = 1.0;
$gAEAttrPresetCurrentTarget = $shaveNode;
eval("source \"" + $preset + "\"");
//need to set guide thinkess param
//float $thick = getAttr($shaveNode + ".rootThickness");
//setAttr($shaveNode + ".displayGuideThick") $thick;
}
//
// psWinSavePreset is a procedure defined in Maya's saveAttrPresetWin.mel
// script file. It is called whenever a new preset is saved.
//
// We override it here with our own version which is a duplicate of Maya's
// (as of Maya 6.0 thru 7.0) except that if the node is a shaveNode, then we
// also generate a swatch for it.
//
global proc psWinSavePreset()
{
global string $gTmpAttrPresetNameField;
global string $gTmpAttrPresetNodeName;
// We use a nodeName ending with "()" to indicate that
// instead of a node, we passed a procedure for creating
// the node on the fly, and we want the node to be deleted
// after it is used.
//
int $needToDeleteNode = false;
if (isAProcedure($gTmpAttrPresetNodeName))
{
// suspect we don't ever use the temp node any more
$gTmpAttrPresetNodeName = eval($gTmpAttrPresetNodeName);
$needToDeleteNode = true;
}
if (objExists($gTmpAttrPresetNodeName)) {
string $presetName = `textFieldGrp -q -text $gTmpAttrPresetNameField`;
string $actualName = `saveAttrPreset $gTmpAttrPresetNodeName $presetName false`;
// if we saved something, close the window
// otherwise the user might want a different name
if (size($actualName) > 0) {
window -e -visible false attrPresetWin;
string $nodeType = nodeType($gTmpAttrPresetNodeName);
if ($nodeType == "shaveHair")
{
//
// The final name of the preset may not be the same as what we
// originally requested, so extract the preset name from the
// output file name.
//
$presetName = basename($actualName, ".mel");
string $swatch = `internalVar -userPrefDir`;
$swatch = substitute("prefs", $swatch, "presets/attrPresets");
$swatch = $swatch + $nodeType + "/" + getSwatchName($presetName, "Personal");
waitCursor -state on;
shaveRender -swatch $gTmpAttrPresetNodeName 100 $swatch;
waitCursor -state off;
//
// If the preset window is up, refresh it.
//
if (`window -exists shavePresetWindow`)
{
global string $shavePreset_callbackCmd;
shavePresetWin $shavePreset_callbackCmd;
}
}
}
} else {
warning "Nothing selected, can't save attribute preset.";
window -e -visible false attrPresetWin;
}
if ($needToDeleteNode && $gTmpAttrPresetNodeName != "")
{
delete $gTmpAttrPresetNodeName;
}
}
//
// deleteSelectedAttrPresets is a procedure defined in Maya's
// attrPresetEditWin.mel script file. It is called whenever an existing
// preset is deleted.
//
// We override it here with our own version which is a duplicate of Maya's
// (as of Maya 6.0 thru 7.0) except that if the node is a shaveNode, then we
// also delete its swatch, if present.
//
global proc deleteSelectedAttrPresets(){
global string $gApeWinPresetList;
global string $gApeWinNodeType;
if( "" == $gApeWinPresetList ){
return;
}
if( "" == $gApeWinNodeType ){
return;
}
string $nodeType = $gApeWinNodeType;
string $ppath = `internalVar -userPrefDir`;
$ppath = substitute("prefs", $ppath, "presets/attrPresets");
$ppath = $ppath + $nodeType;
string $selectedPresets[] = `textScrollList -q -si $gApeWinPresetList`;
string $preset;
string $someWereShaveNodes = false;
for ( $preset in $selectedPresets ){
sysFile -delete ($ppath + "/" + $preset + ".mel");
if ($nodeType == "shaveHair")
{
string $swatchFile;
$someWereShaveNodes = true;
$swatchFile = $ppath + "/" + getSwatchName($preset, "Personal");
if (`filetest -r $swatchFile`) sysFile -delete $swatchFile;
}
}
if (size($selectedPresets) > 0){
updateAPEWinNodetype($nodeType);
}
if ($someWereShaveNodes && `window -exists shavePresetWindow`)
{
global string $shavePreset_callbackCmd;
shavePresetWin $shavePreset_callbackCmd;
}
}
|