/************************************************************ * * TOI Boolean Tool * * Author: T. Welman, TOI TU Delft, september 2008 * version 1.4.1 * * This script enables you to quickly enable or disable booleans * related to a specific object. * * Usage: * 1. Load the script (source script) * 2. Launch the interface using the command: toi_booleanTool(); * 3. Select the object to be used and click Use selected * 4. Enable or disable booleans in the list shown in the UI * You can also change this wireframe display color of de object * used for the boolean and show or hide it. * */ // make sure the windows are reset at load, so the UI is always up-to-date if ( `window -exists toi_booleanTool_window` ) { deleteUI toi_booleanTool_window; } global proc toi_booleanTool ( ) { if ( !`window -exists toi_booleanTool_window` ) { window -t "Boolean Tool" -w 600 -h 400 -retain toi_booleanTool_window; string $form = `formLayout -numberOfDivisions 100`; columnLayout -rs 5 toi_bt_controlsCol; text -l "Specify the object to use:"; rowLayout -nc 2 -cw2 80 200; button -w 80-l "Use selected" -c "toi_bt_useSelected(\"toi_bt_object\");toi_bt_reload_booleans(\"toi_bt_booleansCol\")"; textFieldGrp -cw2 50 150 -l "Object" -cc "toi_bt_reload_booleans(\"toi_bt_booleansCol\")" toi_bt_object; setParent ..; button -w 280 -l "Reload booleans" -c "toi_bt_reload_booleans(\"toi_bt_booleansCol\")"; text - l ""; setParent ..; setParent ..; scrollLayout toi_bt_booleansScroll; columnLayout toi_bt_booleansCol; formLayout -edit -attachForm "toi_bt_booleansScroll" "bottom" 2 -attachForm "toi_bt_booleansScroll" "left" 2 -attachForm "toi_bt_booleansScroll" "right" 2 -attachControl "toi_bt_booleansScroll" "top" 2 toi_bt_controlsCol -attachForm "toi_bt_controlsCol" "top" 2 -attachForm "toi_bt_controlsCol" "left" 2 -attachForm "toi_bt_controlsCol" "right" 2 $form; } showWindow toi_booleanTool_window; } global proc toi_bt_useSelected( string $field) { string $sel[] = `ls -long -sl`; textFieldGrp -e -tx $sel[0] $field; } global proc string[] toi_bt_getObjectBooleans( string $object) { string $result[],$tmp[],$boolean; int $c,$hasPrevious; // make sure $object is the shape! if ( `objectType $object` == "transform" ) { $tmp = `listRelatives -fullPath -shapes -children -type mesh $object`; if ( size($tmp) == 0 ) { print ("BooleanToolDebug: "+$object+" does not seem to be a mesh\n"); return $result; } $object = $tmp[0]; } $tmp = `listConnections -s 1 -d 0 -type polyBoolOp ($object+".inMesh")`; if ( size($tmp) == 0 || $tmp[0] == "" ) { //alternatively check for groupParts connections which are also used in booleans $tmp = `listConnections -s 1 -d 0 -type groupParts ($object+".inMesh")`; if ( size($tmp) == 0 || $tmp[0] == "" ) { print ("BooleanToolDebug: "+$object+" does not have a boolean input\n"); return $result; } $tmp = `listConnections -s 1 -d 0 -type polyBoolOp ($tmp[0]+".inputGeometry")`; if ( size($tmp) == 0 || $tmp[0] == "" ) { print ("BooleanToolDebug: "+$object+" groupParts does not have a boolean input\n"); return $result; } } $boolean = $tmp[0]; $result[$c++] = $boolean; $hasPrevious = 1; //print ("Debug: looking into: "+$boolean+"\n"); while ( $hasPrevious == 1 ) { $tmp = toi_bt_getBooleanInput ( $boolean); if ( $tmp[2] == "" ) { $hasPrevious = 0; } else { $boolean = $tmp[2]; $result[$c++] = $boolean; } } return $result; } global proc toi_bt_reload_booleans ( string $col ) { string $child; string $children[] = `columnLayout -q -childArray $col`; string $object = `textFieldGrp -q -tx toi_bt_object`; int $onlyOne; if ( ! objExists($object) ) { error("No object specified"); } if ( `objectTypeUI $col` == "columnLayout" ) { columnLayout -e -visible 0 $col; //temporarily hide entire column to prevent flickering } for ( $child in $children ) { deleteUI $child; } string $bNodes[],$bDisabledNodes[],$showNodes[],$master; $bNodes = toi_bt_getObjectBooleans($object); if ( size($bNodes) > 0 ) { $master = toi_bt_getBooleanMaster( $bNodes[0] ); $bDisabledNodes = toi_bt_getDisabledBooleans($master); if ( size($bNodes) == 1 ) { $onlyOne = 1; } } $showNodes = stringArrayCatenate($bNodes, $bDisabledNodes); $showNodes = stringArrayRemoveDuplicates($showNodes); $showNodes = sort($showNodes); toi_bt_listBooleans( $col, $showNodes, $onlyOne ); } global proc string[] toi_bt_getDisabledBooleans ( string $master ) { string $bNodes[],$boolean,$result[],$mval; int $c; $bNodes = `ls -type polyBoolOp`; for ( $boolean in $bNodes ) { if ( attributeExists ("toiBoolMaster", $boolean) ) { $mval = `getAttr ($boolean+".toiBoolMaster")`; if ( $mval == $master ) { $result[$c++] = $boolean; } } } return $result; } global proc toi_bt_listBooleans ( string $parent, string $bNodes[], int $onlyOne ) { int $is_enabled,$visible,$overrideColor,$checkBoxEnabled,$enable_col; string $boolean,$colorControl; // set the parent to the proper layout setParent $parent; for ( $boolean in $bNodes ) { $data = toi_bt_getBooleanChain($boolean); $visible = toi_bt_getBooleanVisibility($boolean); $overrideColor = `getAttr ($data[11]+".overrideColor")`; //debug //print ( $data[0] + " generates poly: " + $data[2] + " using "+ $data[1] +" as input. Next boolean is: "+$data[3]+", previous is: "+$data[5]+" using "+$data[4]+" as a base\n"); if ( $data[10] == "" ) { $is_enabled = 0; } else { $is_enabled = 1; } if ( $onlyOne == 1 && $is_enabled == 1 ) { $checkBoxEnabled = 0; } else { $checkBoxEnabled = 1; } rowLayout -nc 4 -cw4 60 40 120 250; if ( $visible == 0 ) { button -w 60 -l "Show" -c ("toi_bt_setBooleanVisibility(\""+$boolean+"\",1); toi_bt_reload_booleans(\""+$parent+"\")"); } else if ( $visible == 1) { button -w 60 -l "Outlines" -c ("toi_bt_setBooleanVisibility(\""+$boolean+"\",2); toi_bt_reload_booleans(\""+$parent+"\")"); } else { button -w 60 -l "Hide" -c ("toi_bt_setBooleanVisibility(\""+$boolean+"\",0); toi_bt_reload_booleans(\""+$parent+"\")"); } //print ($data[11]+".overrideColor\n"); checkBoxGrp -enable $checkBoxEnabled -ncb 1 -l "" -ann "enable" -v1 $is_enabled -cw2 5 30 -onCommand1 ("toi_bt_enableBoolean(\""+$boolean+"\"); toi_bt_reload_booleans(\""+$parent+"\")") -offCommand1 ("toi_bt_disableBoolean(\""+$boolean+"\"); toi_bt_reload_booleans(\""+$parent+"\")"); nameField -w 120 -object $boolean; // -changeCommand ("toi_bt_reload_booleans(\""+$parent+"\")"); //do not auto reload... it may crash Maya $colorControl = `colorIndexSliderGrp -cw4 5 60 160 5 -label "" -v ($overrideColor+1)-min 1 -max 32`; setParent ..; // add the change command for the color colorIndexSliderGrp -e -cc ("toi_bt_changeOverridecolor(\""+$data[11]+"\",\""+$colorControl+"\")") $colorControl; } if ( `objectTypeUI $parent` == "columnLayout" ) { columnLayout -e -visible 1 $parent; //show hidden columnLayout } } global proc toi_bt_changeOverridecolor ( string $node, string $control ) { int $val = `colorIndexSliderGrp -q -v $control`; setAttr ($node+".overrideColor") ($val - 1 );//note the weird 1 offset... some inconsistency in Maya.... } global proc toi_bt_toggleBooleanVisibility ( string $boolean ) { if ( toi_bt_getBooleanVisibility($boolean) == 1 ) { toi_bt_setBooleanVisibility($boolean,0); } else { toi_bt_setBooleanVisibility($boolean,1); } } global proc int toi_bt_getBooleanVisibility ( string $boolean ) { /* 0 - invisible 1 - visible (not templated) 2 - outlined */ string $data[]; $data = toi_bt_getBooleanInput($boolean); // 0 holds the shape, 5 holds the transform if ( `getAttr ($data[5]+".visibility")` == 1 && `getAttr ($data[0]+".intermediateObject")` == 0 ) { if ( `getAttr ($data[5]+".overrideEnabled")` == 1 && `getAttr ($data[5]+".overrideShading")` == 0 ) { return 2; } return 1; } return 0; } global proc toi_bt_setBooleanVisibility ( string $boolean, int $status ) { string $data[]; $data = toi_bt_getBooleanInput($boolean); // 0 holds the shape, 5 holds the transform if ( $status == 2 ) { setAttr ($data[0]+".intermediateObject") 0; setAttr ($data[5]+".visibility") 1; setAttr ($data[5]+".overrideEnabled") 1; setAttr ($data[5]+".overrideShading") 0; } else if ( $status == 1 ) { setAttr ($data[0]+".intermediateObject") 0; setAttr ($data[5]+".visibility") 1; setAttr ($data[5]+".overrideEnabled") 0; setAttr ($data[5]+".overrideShading") 1; } else { setAttr ($data[5]+".visibility") 0; setAttr ($data[0]+".intermediateObject") 1; setAttr ($data[5]+".overrideEnabled") 0; setAttr ($data[5]+".overrideShading") 1; } } global proc toi_bt_disableBoolean ( string $thisBool ) { /* disconnect: inputPolyShape.worldMatrix[0] -> thisBoolOp.inputMat[0] inputPolyShape.outMesh -> thisBoolOp.inputPoly[0] resultingPolyShape.worldMatrix[0] -> nextBoolOp.inputMat[0] resultingPolyShape.outMesh -> nextBoolOp.inputPoly[0] connect: inputPolyShape.worldMatrix[0] -> nextBoolOp.inputMat[0] inputPolyShape.outMesh -> nextBoolOp.inputPoly[0] */ string $data[],$tmp[],$inputPoly,$inputBase,$resultingPoly,$nextBool,$prevBool,$boolMaster,$prevGroupParts,$nextGroupParts; $data = toi_bt_getBooleanChain ( $thisBool ); $tmp = `ls -long $data[4]`; $inputPoly = $tmp[0]; $tmp= `ls -long $data[2]`; $resultingPoly = $tmp[0]; $nextBool = $data[3]; $inputBase = $data[4]; $prevBool = $data[5]; $prevGroupParts = $data[6]; $nextGroupParts = $data[7]; $boolMaster = toi_bt_getBooleanMaster($thisBool); if ( $prevBool == "" && $nextBool == "" ) { warning("Cannot disable this boolean. Minumum of 1 has been reached."); return; } else if ( $prevBool == "" ) { //a little different approach disconnectAttr ( $thisBool+".output" ) ( $nextGroupParts+".inputGeometry" ); disconnectAttr ( $inputBase+".worldMatrix[0]" ) ( $thisBool+".inputMat[0]" ); disconnectAttr ( $inputBase+".outMesh" ) ( $thisBool+".inputPoly[0]" ); disconnectAttr ( $resultingPoly+".worldMatrix[0]" ) ( $nextBool+".inputMat[0]" ); disconnectAttr ( $resultingPoly+".outMesh" ) ( $nextBool+".inputPoly[0]" ); disconnectAttr ( $nextGroupParts+".outputGeometry" ) ( $resultingPoly+".inMesh" ); connectAttr ( $inputBase+".worldMatrix[0]" ) ( $nextBool+".inputMat[0]" ); connectAttr ( $inputBase+".outMesh" ) ( $nextBool+".inputPoly[0]" ); connectAttr ( $resultingPoly+".worldMatrix[0]" ) ( $thisBool+".inputMat[0]" ); connectAttr ( $resultingPoly+".outMesh" ) ( $thisBool+".inputPoly[0]" ); connectAttr ( $nextGroupParts+".outputGeometry" ) ( $resultingPoly+".inMesh" ); } else if ( $nextBool == "" ) { $tmp = `listConnections -d 1 -s 0 ( $thisBool+".output" )`; if ( size($tmp) == 0 ) { //unhandled exception } else { if ( `objectType - isType "mesh" $tmp[0]` ) { disconnectAttr ( $thisBool+".output" ) ( $tmp[0]+".inMesh" ); disconnectAttr ( $prevBool+".output" ) ( $prevGroupParts+".inputGeometry" ); connectAttr ( $prevBool+".output" ) ( $tmp[0]+".inMesh" ); } else if ( `objectType - isType "groupParts" $tmp[0]` ) { disconnectAttr ( $thisBool+".output" ) ( $tmp[0]+".inputGeometry" ); disconnectAttr ( $prevBool+".output" ) ( $prevGroupParts+".inputGeometry" ); connectAttr ( $prevBool+".output" ) ( $tmp[0]+".inputGeometry" ); } } } else { disconnectAttr ( $thisBool+".output" ) ( $nextGroupParts+".inputGeometry" ); disconnectAttr ( $prevBool+".output" ) ( $prevGroupParts+".inputGeometry" ); connectAttr ( $prevBool+".output" ) ( $nextGroupParts+".inputGeometry" ); } if ( ! attributeExists ("toiBoolMaster", $thisBool) ) { addAttr -dt "string" -shortName toibm -longName toiBoolMaster $thisBool; } // store the master object this boolean belongs to. setAttr ($thisBool+".toiBoolMaster") -type "string" $boolMaster; } global proc toi_bt_enableBoolean ( string $thisBool ) { /* disconnect: boolMasterShape.worldMatrix[0] -> nextBoolOp.inputMat[0] boolMasterShape.outMesh -> nextBoolOp.inputPoly[0] connect: boolMasterShape.worldMatrix[0] -> thisBoolOp.inputMat[0] boolMasterShape.outMesh -> thisBoolOp.inputPoly[0] resultingPolyShape.worldMatrix[0] -> nextBoolOp.inputMat[0] resultingPolyShape.outMesh -> nextBoolOp.inputPoly[0] */ if ( ! attributeExists ("toiBoolMaster", $thisBool) ) { error("This boolean is orphaned!"); } string $tmp[],$firstBool,$secondBool,$thisBoolGroupParts,$secondGroupParts,$boolMaster; $boolMaster = `getAttr ($thisBool+".toiBoolMaster")`; $firstBool = toi_bt_getMasterNextBoolean($boolMaster); $tmp = toi_bt_getBooleanOutput($firstBool); $secondBool = $tmp[1]; $secondGroupParts = $tmp[2]; $tmp = toi_bt_getBooleanInput($thisBool); $thisBoolGroupParts = $tmp[3]; if ( $secondBool == "" ) { // only one boolean left. Connecting between boolean and output geometry $tmp = `listConnections -s 0 -d 1 ($firstBool+".output")`; if ( size($tmp) == 0 ) { //unhandled exception? } else { if ( `objectType -isType "mesh" $tmp[0]` ) { disconnectAttr ( $firstBool+".output" ) ( $tmp[0]+".inMesh" ); connectAttr ( $firstBool+".output" ) ( $thisBoolGroupParts+".inputGeometry"); connectAttr ( $thisBool+".output" ) ( $tmp[0]+".inMesh" ); } else if ( `objectType -isType "groupParts" $tmp[0]` ) { disconnectAttr ( $firstBool+".output" ) ( $tmp[0]+".inputGeometry" ); connectAttr ( $firstBool+".output" ) ( $thisBoolGroupParts+".inputGeometry"); connectAttr ( $thisBool+".output" ) ( $tmp[0]+".inputGeometry" ); } } } else { // multiple booleans present. Connecting between boolean 1 and boolean 2 disconnectAttr ( $firstBool+".output" ) ( $secondGroupParts+".inputGeometry" ); connectAttr ( $firstBool+".output" ) ( $thisBoolGroupParts+".inputGeometry"); connectAttr ( $thisBool+".output" ) ( $secondGroupParts+".inputGeometry" ); } } global proc string toi_bt_getBooleanMaster ( string $boolean) { string $prevData[],$booleanMaster; $prevData = toi_bt_getBooleanInput($boolean); $booleanMaster = $prevData[1]; while ( size($prevData[2]) > 0 ) { $prevData = toi_bt_getBooleanInput($prevData[2]); $booleanMaster = $prevData[1]; } return $booleanMaster; } global proc string toi_bt_getMasterNextBoolean ( string $shape ) { string $tmp[] = `listConnections -type polyBoolOp -s 0 -d 1 -sh 1 ($shape+".outMesh")`; return $tmp[0]; } global proc string[] toi_bt_getBooleanChain ( string $boolean) { /* returns an array with: 0 - thisBoolean 1 - inputPoly ( the object with which the boolean is performed on the subject) 2 - resultingPoly 3 - nextBoolean 4 - inputBase (the poly that is 'first' in the boolean, so the subject) 5 - previousBoolean 6 - previousGroupParts 7 - groupParts 8 - previousGroupId 9 - GroupId 10 - isActive (polyBoolOp.output has a connection) 11 - boolean input object transform 12 - boolean input subject transform */ string $tmp[],$rPoly,$inputObject,$nextBool,$inputSubject,$prevBool,$prevGroupParts,$nextGroupParts,$prevGroupId,$nextGroupId,$isActive,$inputObjectTransform,$inputSubjectTransform; $tmp = toi_bt_getBooleanInput($boolean); $inputObject = $tmp[0]; $inputSubject = $tmp[1]; $prevBool = $tmp[2]; $prevGroupParts = $tmp[3]; $prevGroupId = $tmp[4]; $inputObjectTransform = $tmp[5]; $inputSubjectTransform = $tmp[6]; $tmp = toi_bt_getBooleanOutput($boolean); $rPoly = $tmp[0]; $nextBool = $tmp[1]; $nextGroupParts = $tmp[2]; $nextGroupId = $tmp[3]; $isActive = $tmp[4]; return { $boolean , $inputObject , $rPoly , $nextBool , $inputSubject, $prevBool, $prevGroupParts, $nextGroupParts, $prevGroupId, $nextGroupId, $isActive, $inputObjectTransform, $inputSubjectTransform }; } global proc string[] toi_bt_getBooleanInput ( string $boolean ) { /* returns an array with: 0 - boolean input object shape 1 - boolean input subject shape 2 - previous boolean 3 - previous groupParts node 4 - previous groupId node 5 - boolean input object transform 6 - boolean input subject transform */ string $prevBool[],$gParts[],$groupId[],$inputObjectTransform[],$inputSubjectTransform[]; string $inputObject[] = `listConnections -type mesh -s 1 -d 0 -sh 1 ($boolean+".inputPoly[1]")`; if ( size( $inputObject ) > 0 ) { $inputObjectTransform = `listRelatives -p -type transform -f $inputObject[0]`; } else { $inputObjectTransform[0] = ""; } string $inputSubject[] = `listConnections -type mesh -s 1 -d 0 -sh 1 ($boolean+".inputPoly[0]")`; if ( size( $inputSubject ) > 0 ) { $gParts = `listConnections -type groupParts -s 1 -d 0 $inputSubject[0]`; if ( size($gParts) > 0 ) { $prevBool = `listConnections -type polyBoolOp -s 1 -d 0 ($gParts[0])`; $groupId = `listConnections -type groupId -s 1 -d 0 ($gParts[0]+".groupId")`; $inputSubjectTransform = `listRelatives -p -type transform -f $inputSubject[0]`; } else { //print ("caught an exception\n"); $gParts[0] = ""; $prevBool[0] = ""; $groupId[0] = ""; $inputSubjectTransform[0] = ""; } } else { $gParts[0] = ""; $prevBool[0] = ""; $groupId[0] = ""; $inputSubjectTransform[0] = ""; } return { $inputObject[0], $inputSubject[0], $prevBool[0], $gParts[0], $groupId[0], $inputObjectTransform[0], $inputSubjectTransform[0] }; } global proc string[] toi_bt_getBooleanOutput ( string $boolean ) { /* returns an array with: 0 - boolean output Mesh 1 - next boolean 2 - groupParts node 3 - groupID node 4 - hasOutput */ string $rPoly[],$nextBool[],$groupId[],$hasOutput; string $gParts[] = `listConnections -type groupParts -s 0 -d 1 $boolean`; if ( size($gParts) == 0 ) { $rPoly = `listConnections -s 0 -d 1 -type mesh $boolean`; $nextBool[0] = ""; $groupId[0] = ""; } else { $rPoly = `listConnections -s 0 -d 1 -sh 1 $gParts[0]`; $nextBool = `listConnections -type polyBoolOp -s 1 -d 1 ($rPoly[0]+".outMesh")`; $groupId = `listConnections -type groupId -s 1 -d 0 ($gParts[0]+".groupId")`; } if ( size( `listConnections -s 0 -d 1 ($boolean+".output")` ) > 0 ) { $hasOutput = "1"; } else { $hasOutput = ""; } return { $rPoly[0], $nextBool[0], $gParts[0], $groupId[0], $hasOutput }; }