08: transfer channel box attributes (also anim)
string $sel[] = `ls -sl`; string $source = $sel[0]; string $targets[]; clear $targets; for ( $i=1; $i<size($sel); $i++){ $targets[size( $targets )] = $sel[$i] ; } string $attrs[] = `channelBox -q -sma mainChannelBox` ; for ( $attr in $attrs) { float $myFloat = `getAttr ( $source + "." + $attr )` ; for ( $target in $targets ){ setAttr ( $target + "." + $attr ) $myFloat ; } }
So you want to copy values from something to something else, ey? Well, there is the ancient way of copy/paste.. But that's very tedious, going back and forth between objects, transferring attribute by attribute.
Above is the main body of code (or the important bit) that lets you select a source, then target(s), then select attributes in the channel box and click a shelf button to transfer all the selected attributes' values across at the same time. However, it will only work on float values on the selected transform, and that's half assed. We don't do half assed here in this blog, so read on to find out how to get it working for all channel box attributes.
The important part of code in this script is the channelBox command.
From the docs: "This command creates a channel box, which is sensitive to the active list. It displays certain attributes (channels) of the last node on the active list, and provides a two-way connection to keep the widget up to date...."
Yawn... But the exciting thing about it is that it is queryable! And the two flags we will be querying is -selectedMainAttributes (-sma) and -selectedShapeAttributes (-ssa) which will return the selected attributes in the top section and the middle (shape) section of the channel box respectively.
With this data, it is easy to do a for loop and, based on what type of data the attribute holds (since we need to declare varibles of the same type to store the attribute values), use getAttr and setAttr to transfer the values across to the target objects.
Using getAttr with the -typ flag we get the data type of the attribute. Most attributes are either floats (most attributes holding numerical values) or checkboxes (booleans) or pull down menus (enumerated values), both of the latter stored as int values.
In the first example I only used -sma, but a lot of times you want to transfer shape attributes, i.e. dynamics nodes, and then we need to use the -ssa flag. And also we need to know the source's and targets' and shape's names.
So, after having run through the selected transform attributes, we'll get the shape name and run through the shape attributes in a new loop:
string $sourceShape[] = `listRelatives -s -f $source`; string $mySsa[] = `channelBox -q -ssa mainChannelBox`; for ( $attribute in $mySsa){ string $type = `getAttr -typ ($sourceShape[0] + "." + $attribute )`; if ($type == "double" || $type == "doubleAngle" || $type == "float" ){ $myFloat = `getAttr ($sourceShape[0] + "." + $attribute)`; for ( $target in $targets ){ string $targetShape[] = `listRelatives -s $target`; setAttr ($targetShape[0] + "." + $attribute) $myFloat; } }else if ($type == "bool" || $type == "enum" ){ $myInt = `getAttr ($sourceShape[0] + "." + $attribute)`; for ( $target in $targets ){ string $targetShape[] = `listRelatives -s $target `; setAttr ($targetShape[0] + "." + $attribute) $myInt; } } }
So there you go.
"OH NO! Some of my source attributes were animated! And you promised this script wouldn't be half assed. So why arent my target attributes animated after the transfer as well?!"
Easy. They are! Because in the script you also looked to see if the attributes were animated using listConnections:
string $incomingConn[] = `listConnections -d off -s on ($source + "." + $attribute)`;
So if ( !`size($incomingConn)` ) you ran the above loops and if they HAD any connections you ran
else{ // We identify what is connected. If it is an animation curve or an expression, you want to duplicate it and connect it so the target attribute is animated as well, but if it is a direct connection, like "time1.outTime" or a controller's attribute (these are the pale yellow coloured attributes) you just want to copy the connection. string $incomingNodeType = `nodeType $incomingConn[0]`; if ( $incomingNodeType == "animCurveTU" || $incomingNodeType == "expression" ){ select -r $incomingConn[0]; duplicate -rr; string $dup[] = `ls -sl`; string $sourceAttr[] = `listConnections -p 1 ($source + "." + $attribute)`; string $buf[]; tokenize $sourceAttr[0] "." $buf; string $attr = $buf[size($buf)-1]; connectAttr ( $dup[0] + "." + $attr ) ($target + "." + $attribute); } string $sourceAttr[] = `listConnections -p on ($source + "." + $attribute)`; connectAttr $sourceAttr[0] ($target + "." + $attribute); }
The full script would look something like this:
string $sel[] = `ls -sl`; if (size($sel) == 2){ string $source = $sel[0]; string $targets[]; clear $targets; for ( $i=1; $i<size($sel); $i++){ $targets[size($targets)] = $sel[$i]; } string $sourceShape[] = `listRelatives -s $source`; string $mySma[] = `channelBox -q -sma mainChannelBox`; string $mySsa[] = `channelBox -q -ssa mainChannelBox`; string $myString; int $myInt; float $myFloat; if (size($mySma) + size($mySsa)>0){ if (size($mySma)>0){ for ( $attribute in $mySma ) { string $incomingConn[] = `listConnections -d off -s on ($source + "." + $attribute)`; if (!`size($incomingConn)`) { string $type = `getAttr -typ ($source + "." + $attribute)`; if ($type == "double" || $type == "doubleAngle" || $type == "float" ){ $myFloat = `getAttr ($source + "." + $attribute)`; for ( $target in $targets ){ setAttr ($target + "." + $attribute) $myFloat; } }else if ($type == "bool"){ $myInt = `getAttr ($source + "." + $attribute)`; for ( $target in $targets ){ setAttr ($target + "." + $attribute) $myInt; } } }else{ string $sourceAttr[] = `listConnections -p on ($source + "." + $attribute)`; for ( $target in $targets ) connectAttr $sourceAttr[0] ($target + "." + $attribute); } } } if (size($mySsa)>0){ for ( $attribute in $mySsa ) { string $incomingConn[] = `listConnections -d off -s on ($sourceShape[0] + "." + $attribute)`; if (!`size($incomingConn)`){ string $type = `getAttr -typ ($sourceShape[0] + "." + $attribute)`; if ($type == "double" || $type == "doubleAngle" || $type == "float" ){ $myFloat = `getAttr ($sourceShape[0] + "." + $attribute)`; for ( $target in $targets ){ string $targetShape[] = `listRelatives -s $target`; setAttr ($targetShape[0] + "." + $attribute) $myFloat; } }else if ($type == "bool" || $type == "enum" ){ $myInt = `getAttr ($sourceShape[0] + "." + $attribute)`; for ($target in $targets){ string $targetShape[] = `listRelatives -s $target`; setAttr ($targetShape[0] + "." + $attribute) $myInt; } } }else{ string $incomingNodeType = `nodeType $incomingConn[0]`; if ( $incomingNodeType == "animCurveTU" || $incomingNodeType == "expression"){ select -r $incomingConn[0]; duplicate -rr; string $dup[] = `ls -sl`; string $sourceAttr[] = `listConnections -p 1 ($source + "." + $attribute)`; string $buf[]; tokenize $sourceAttr[0] "." $buf; string $attr = $buf[size($buf)-1]; for ($target in $targets) connectAttr ( $dup[0] + "." + $attr ) ($target + "." + $attribute); }else{ string $sourceAttr[] = `listConnections -p on ($source + "." + $attribute)`; for ($target in $targets) connectAttr $sourceAttr[0] ($target + "." + $attribute); } } } } }else{ print "select attributes in the Channel Box.\n"; } }else{ print "you need to select at least TWO objects. One source, and minimum one targets.\n"; }















