summaryrefslogtreecommitdiffstats
path: root/tools/MayaTools/Maya4.0/scripts/SimpsonsArt/forceUniqueNames.mel
blob: c939c2d711ec412aad443c780ce3c99e8ec2e935 (plain) (blame)
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
//===========================================================================
// Copyright ©2002 Radical Entertainment Ltd.  All rights reserved.
//
// Created:     26 March, 2002
//
// Description: Forces unique names for all nodes in the scene, and ensures
//              that each Shape node derives its name (and numerical suffix)
//              from its Transform.
//
// Constraints: 
//
// Creator:     Bryan Ewert
//
//===========================================================================

//===========================================================================
// version
//===========================================================================
// Description: Returns the current version for this MEL script.
//              Used for version control.
//
// Constraints: 
//
//===========================================================================
proc float version()
{
    return ( 1.1 );     // 01 May 2002
}

//===========================================================================
// depth
//===========================================================================
// Description: Determines the depth of the specified DAG; e.g. the depth
//              for "|group1|transform2|transformShape2" is 3.
//
// Constraints: 
//
//  Parameters: string $node: The full path to the node.
//
//      Return: (int): The depth of the path.
//
//===========================================================================
proc int depth( string $node )
{
    int $depth = 0;
    
    if ( `objExists $node` )
    {
        string $longA[] = `ls -l $node`;
        
        string $tokens[];
        $depth = `tokenize $longA[0] "|" $tokens`;
    }

    return $depth;    
}

//===========================================================================
// nameNoPath
//===========================================================================
// Description: Returns the short name for the specified node.
//              "|group1|transform2|transformShape2" would return 
//              "transformShape2"
//
// Constraints: The pathless name may not be unique, and may not be 
//              sufficient for Maya to resolve the DAG!  This name is 
//              intended for use in a rename operation, and not for 
//              performing edit operations on the object.
//
//  Parameters: string $node: The full path to the node.
//
//      Return: (string): The short path for the node.
//
//===========================================================================
proc string nameNoPath( string $node )
{
    return `match "[^|]*$" $node`;
}

//===========================================================================
// isUnique
//===========================================================================
// Description: Determines if the specified node has a unique name.
//
// Constraints: 
//
//  Parameters: string $node: Name of the node (may be full path, may not).
//
//      Return: (int): TRUE (non-zero) if name is unique; else FALSE (zero).
//
//===========================================================================
proc int isUnique( string $node )
{
    int $isUnique = true;
    
    string $noPath = nameNoPath( $node );
    string $wildcard = ( "*" + $noPath );
    string $potentials[] = `ls $wildcard`;
    
    int $numMatches = 0;
    for ( $p in $potentials )
    {
        string $tokens[];
        int $numTokens = `tokenize $p "|" $tokens`;
        if ( $tokens[$numTokens-1] == $noPath )
        {
            $numMatches++;
        }
    }
    
    $isUnique = ( $numMatches < 2 );
    
    return $isUnique;
}

//===========================================================================
// getUniqueName
//===========================================================================
// Description: Builds a unique name for the specified node by generating
//              a numerical suffix for the node.  An existing numerical
//              suffix is stripped and replaced if the node's name is not
//              already unique.
//
// Constraints: The returned name does _not_ contain a path and may not be 
//              sufficient for Maya to resolve the DAG!  This name is 
//              intended for use in a rename operation, and not for 
//              performing edit operations on the object.
//
//  Parameters: string $node: The full path to the node.
//
//      Return: (string): A unique name for the node.
//
//===========================================================================
proc string getUniqueName( string $node )
{
    string $shortNode = nameNoPath( $node );
    string $unique = $shortNode;
    
    if ( !isUnique( $shortNode ) )
    {
        // strip numeric suffix
        string $suffix = `match "[0-9]*$" $shortNode`;
        int $sizeShortNode = `size $shortNode`;
        int $sizeSuffix = `size $suffix`;
        $shortNode = `substring $shortNode 1 ( $sizeShortNode - $sizeSuffix )`;

        if ( !`objExists $shortNode` )
        {
            $unique = $shortNode;
        }
        else
        {
            string $newNode;
            int $u = 1;
            do
            {
                $newNode = ( $shortNode + ($u++) );
            } while ( `objExists $newNode` );

            $unique = $newNode;
        }
    }
    
    return $unique;
}

//===========================================================================
// getShape
//===========================================================================
// Description: Returns the shape node, if any, for the specified transform.
//
// Constraints: Considers only a single shape.
//
//  Parameters: string $xform: The transform node.
//
//      Return: (string): The shape node.
//
//===========================================================================
proc string getShape( string $xform )
{
    string $shapes[];
    
    $shapes[0] = $xform;
    
    string $isTransform[] = `ls -transforms $xform`;
    
    if ( `size $isTransform` > 0 )
    // If given node is not a transform, assume it is a shape 
    // and pass it through
    {
        $shapes = `listRelatives -fullPath -shapes $xform`;
    }
    
    return $shapes[0];
}

//===========================================================================
// getShapeName
//===========================================================================
// Description: Derives a name for the shape node given the specified 
//              transform name.  For example if the $node specified is
//              "pCube23" the shape name will be "pCubeShape23".
//
// Constraints: No checking is done to verify that $node is a transform.
//
//  Parameters: string $node: The name for the transform node.
//
//      Return: (string): The name for the shape node.
//
//===========================================================================
proc string getShapeName( string $node )
{
    string $numeric = `match "[0-9]+$" $node`;

    int $strlen = `size $node`;
    int $numlen = `size $numeric`;
    string $alpha = `substring $node 1 ( $strlen - $numlen )`;
    
    string $shapeName = ( $alpha + "Shape" + $numeric );
    
    return $shapeName;
}

//===========================================================================
// performRename
//===========================================================================
// Description: Does the work for the rename operation -- generates unique
//              names for the transform and shape nodes, assesses whether
//              the names are non-unique and, if necessary, renames the 
//              nodes.
//
// Constraints: Read-only nodes (such as Maya's startup cameras) are a real
//              pain in the keister because there is no way to detect them
//              reliably ('ls -readOnly' doesn't work for this).  Currently
//              the workaround is to assess whether my "unique" name is
//              the same as Maya's current name and, if so, don't bother
//              attempting a rename operation.
//
//  Parameters: string $node: The full path to the node being renamed.
//
//      Return: (int): TRUE (non-zero) if successful; else FALSE.
//                     TRUE doesn't necessary mean it was renamed; it may
//                     also mean it did not need to be renamed.
//
//===========================================================================
proc int performRename( string $node )
{
    int $bSuccess = false;
 
    if ( `objExists $node` )
    {
        string $unique = getUniqueName( $node );
        string $shape = getShape( $node );

        if ( $shape != "" )
        {
            string $uniqueShape = getShapeName( $unique );
            if ( $uniqueShape != nameNoPath( $shape ) )
            {
                eval( "rename " + $shape + " " + $uniqueShape );
            }
        }

        if ( $unique != nameNoPath( $node ) )
        {
            eval( "rename " + $node + " " + $unique );
        }
        
        $bSuccess = true;
    }

    return $bSuccess;    
}
    
//===========================================================================
// performUniqueNames
//===========================================================================
// Description: Recursive procedure for assessing the scene and looping 
//              through the transform nodes.  The renaming is performed
//              from the top-down, and if a top-level node is renamed the
//              path to its children will no longer be valid.  The cheap
//              way around this is to detect an invalid path and signal
//              a recursive call to this function.  The number of retries
//              is capped to prevent any possibility of infinite recursion.
//
// Constraints: 
//
//  Parameters: int $progress: The current progress; i.e. the number of 
//                             nodes successfully processed so far.
//              int $retry: Number of retries (recursions) remaining.
//
//      Return: (none)
//
//===========================================================================
proc performUniqueNames( int $progress, int $retry )
{
    $retry = max( $retry, 0 );
    
    int $bSuccess = true;
    
    string $transforms[] = `ls -long -transforms`;
    int $depth[];
    int $maxDepth = 0;
    
    for ( $t = 0; $t < `size $transforms`; $t++ )
    {
        $depth[$t] = depth( $transforms[$t] );
        $maxDepth = max( $maxDepth, $depth[$t] );
    }

    for ( $d = 1; $d <= $maxDepth; $d++ )
    {
        for ( $t = 0; $t < `size $transforms`; $t++ )
        {
            if ( $depth[$t] == $d )
            {
                $bSuccess = performRename( $transforms[$t] ) && $bSuccess;
                
                if ( $bSuccess ) $progress++;
            }
            
            progressWindow -e -progress $progress;
        }
    }
    
    if ( !$bSuccess && $retry ) performUniqueNames( $progress, --$retry );
}

//===========================================================================
// forceUniqueNames
//===========================================================================
// Description: Entry point for this script.
//
//              Forces unique names for all nodes in the scene, and ensures
//              that each Shape node derives its name (and numerical suffix)
//              from its Transform.
//
// Constraints: 
//
//  Parameters: (none)
//
//      Return: (none)
//
//===========================================================================
global proc forceUniqueNames()
{
    int $numRetries = 8;

    waitCursor -state on;

    string $transforms[] = `ls -l -type "transform"`;

    int $allProgress = ( `size $transforms` );
    int $progress = 0;
    int $progressThreshold = 256;   // no progress window for fewer items.

    if ( $allProgress > $progressThreshold )
    {
        progressWindow 
            -ii false       // not interruptable, sorry.
            -min 0
            -max $allProgress
            -title "Force Unique Names"
            -status "Scanning for non-unique names."
            ;
    }

    performUniqueNames( $progress, $numRetries );

    if ( $allProgress > $progressThreshold )
    {
        progressWindow -endProgress;
    }

    waitCursor -state off;
}


/* 
source forceUniqueNames; forceUniqueNames; 
*/