/* toi_alongCurve.mel * * Place markers (locators) along a curve * * Author: T. Welman, TOI TU Delft, february 2010 * version 0.1 * * * Usage: * 1. source (load) the script * 2. run toi_alongCurve() to start the interface * */ if ( `window -exists toi_alongCurveWindow` ) { deleteUI toi_alongCurveWindow; } global proc toi_alongCurve() { if ( `window -exists toi_alongCurveWindow` ) { showWindow toi_alongCurveWindow; return; } window -t "TOI Position Along Curve" -resizeToFitChildren 1 toi_alongCurveWindow; columnLayout -rs 6 toi_alongCurveMainCol; radioButtonGrp -cw3 80 80 120 -nrb 2 -l "Mode" -l1 "# positions" -l2 "parameter distance" -select 1 -on1 "floatSliderGrp -e -en 1 toi_alongCurveNumber;floatSliderGrp -e -en 0 toi_alongCurveParameter;" -on2 "floatSliderGrp -e -en 0 toi_alongCurveNumber;floatSliderGrp -e -en 1 toi_alongCurveParameter;" toi_alongCurveMode; floatSliderGrp -cw3 80 40 120 -l "# copies" -en 1 -v 10 -ss 1 -field 1 -min 2 -pre 0 toi_alongCurveNumber; floatSliderGrp -cw3 80 40 120 -l "param.dist" -en 0 -v 0.5 -ss 0.1 -field 1 -min 0.0001 -max 10 -fieldMaxValue 999 -ann "Parameter Distance. Note that this is not in Maya units!" toi_alongCurveParameter; separator -style "none" -w 240; checkBoxGrp -cw2 80 220 -l "Make uniform" -v1 1 -l1 "rebuilds curve to uniform parameter length" -ann "If your objects aren't spaced evenly, try this option. Otherwise rebuild the curve first to a (much) higher number of spans." toi_alongCurveRebuild; checkBoxGrp -cw2 80 220 -l "Orient Y" -v1 1 -l1 "rotate objects along Y axis to match curve direction" toi_alongCurveOrient; separator -style "none" -w 240; button -w 300 -l "Place markers along selected curve" -c "toi_placeAlongCurve()"; showWindow toi_alongCurveWindow; } global proc toi_placeAlongCurve () { /* This determines the distance between the objects Note that this is in PARAMETER range, so it's not in units! */ float $tolerance = 0.01; //a little tolerance for the end parameter value float $step = `floatSliderGrp -q -v toi_alongCurveParameter`; float $number = `floatSliderGrp -q -v toi_alongCurveNumber`; string $sel[] = `ls -long -flatten -sl`; if ( size($sel) == 0 ) { return; } string $curve[] = toi_getCurveStructure($sel[0]); if ( size($curve) == 0 ) { error("No valid curve selected"); } float $max = `getAttr ($curve[1]+".max")`; int $degree = `getAttr ($curve[1]+".degree")`; int $spans = `getAttr ($curve[1]+".spans")`; float $p, $r, $pos[]; string $obj[], $list[]; int $c; if ( `checkBoxGrp -q -v1 toi_alongCurveRebuild` ) { rebuildCurve -ch 0 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kep 1 -kt 0 -s $spans -d $degree $curve[0]; $max = 1; //we've rebuilt to 0-1 } if ( `radioButtonGrp -q -select toi_alongCurveMode` == 1 ) { $step = float($max) / ($number-1); } while ( $p <= $max + $tolerance ) { if ( $p > $max ) { //due to rounding errors, sometimes the last position is a little off $p = $max; } $r = parameterRotation($curve[0], $p); $pos = `pointOnCurve -p -pr $p $curve[0]`; $obj = `spaceLocator -position 0 0 0`; move -a $pos[0] $pos[1] $pos[2] $obj[0]; //position it on the curve if ( `checkBoxGrp -q -v1 toi_alongCurveOrient` ) { rotate -a 0 $r 0 $obj; //rotate it } $list[$c++] = $obj[0]; $p += $step; } if ( $c > 0 ) { group $list; } } global proc float parameterRotation( string $curve, float $parameter ) { float $v[]; // vector van de normaal float $angle[]; $v = `pointOnCurve -nt -pr $parameter $curve`; $angle = `angleBetween -euler -v1 1 0 0 -v2 $v[0] $v[1] $v[2]`; return $angle[1]; } global proc string[] toi_getCurveStructure ( string $obj ) { string $r[], $tmp[]; string $type = `objectType $obj`; if ( $type == "nurbsCurve" ) { $tmp = `listRelatives -fullPath -type "transform" -parent $obj`; if ( size($tmp) > 0 ) { $r[0] = $tmp[0]; $r[1] = $obj; } } else if ( $type == "transform" ) { $tmp = `listRelatives -fullPath -type "nurbsCurve" -shapes $obj`; if ( size($tmp) > 0 ) { $r[0] = $obj; $r[1] = $tmp[0]; } } return $r; }