Hexbased CA Script-Kokkugia
From scripting
http://www.kokkugia.com/wiki/scriptLibrary/mel/CA_Script.mel
/* this series of scripts creates a hex-grid cellular automaton and a springs net which can be driven by the 'brains' of the cellular automaton. these two things were created in order to then act as an input for the distortion of far more complex geometries in the formation of a facade or screen wall element. created by roland snooks and dave pigram fall 2005 (parts of the code use the logic of cory clarke's - life.mel - nthd.org) this version last modified: 28 october 2005 procedures: there are four main procedures which can be run independantly. each of these main procedures calls a second series of procedures shown indented below (a full description of all procedures follws): - hexCA_create - hexCA_run - hexCA_check - life_keyframe - hexCA_status - springCA_create - springCA_attach - hex_associate example of appropriate inputs: hexCA_create 20 10 1 30; (int $xSize, int $ySize, float $hexSize, float $randCut) hexCA_run 20 10 20 1; (int $xSize, int $ySize, int $steps, int $proliferate) springCA_create 20 10 1; (int $xSize, int $ySize, float $hexSize) hex_associate 0.08; (float $scale) description of input variables: $xSize = the number of hexagons in the x-axis numbered left to right $ySize = the number of hexagons in the y-axis numbered top to bottom $hexSize = the shortest distance from edge to edge of the chosen hexagon size $randCut = the percentage (as an integer between 1 and 100) of the hex-grid that starts at full size (the remainding cells start at the minimum size) $proliferate = 0 or 1 switches between modes of proliferation (of copies of generations): 0 = no proliferation (any other integer besides 1 will also result in no proliferation) 1 = proliferation in a stack along the z axis (perpendicular to the 2 CA dimensions x and y) $scale = a scale factor to tune the spring length inputs of the hex_associate procedure to the particular characteristics of the springs net full descriptions of all procedures: - hexCA_create creates a hex-grid $xSize by $ySize with each hexagon $hexSize wide and numbers all the cells logically. an initial state is also generated by randomly switching a percentage ($randCut) of cells to the maximum size. this procedure must be run before the hexCA_run or the life_keyframe, or else these procedures will have no meaning. - hexCA_run as the name indicates, this procedure uses a pre-determined rule-set to calculate and represent future generational states for the the hex-grid (from its initial state) generated by the hexCA_create procedure. for each hex-cell in turn this procedure calls the hexCA_check procedure which checks the size of all adjacent cells (its 'neigbours' - including itself) the average size is returned and then compared against a series of axiomatic conditions. if the average of the result is too high the cell 'dies' due to 'overcrowding'; if it is too low the cell 'dies' of 'loneliness'. in this case 'dying' means becoming zero scale, there is nothing to prevent the cell being 're-born' in a future generation. if the cell survives the initial culling process it then adopts the average size of its neighbours and itself. all calculations are done on a per-generation basis i.e the calcualtions for all cells are completed before any size changes are made, then the process is repeated after all scaling is complete. lastly, as the above described system has a tendency towards an even distribution of middle-sized cells, an additional 'switch' has been added as a means of re-injecting 'energy' or disequilibrium into the system. when the average size of a hex-cells neighbours approaches the middle of the possible range that cell is either given a maximum or minimum scale in the next generation. if the avaerage is slightly less than the middle the cell gets a maximum size; when the average is slightly higher it receives a minimum scale. - hexCA_check as described above this procedure is called by the hexCA-run procedure, with the average of all neighbouring cell sizes returned (becoming $tmp) to the the hexCA_run script. - life_keyframe this procedure is also called by the hexCA-run procedure, it adds keyframes so that the CA can be watched changing states as an animation. the keyframes occur at set intervals and represent each complete generation. the set interval between keyfames is equal to the $frameNoPerCalc variable which can be found at the beginning of the hexCA_run procedure. - hexCA_status a very simple procedure which literally returns the value of the .status attribute for a particular hex-cell when called by the hexCA_run procedure. - springCA_create this procedure creates a cube on every node of an $xSize x $ySize hex-grid. each cube is named according to the adjacent hex-cells from top to bottom and from left to right. the hex-cells are also named from top to bottom and from left to right in the form: hex_$y_$x where $y is the row number and $x is the cell number within that row. example: the cube named: "cube1_1__1_2__2_1" is between hec-cells: "hex_1_1" , "hex_1_2" and "hex_2_1" - springCA_attach this procedure is called by the springCA_create procedure and attaches springs to cubes that represent each vertex of a $xSize x $ySize hex-grid the cubes are created by the springCA_create script - the inputs are $xSize and $ySize. for every spring a line is drawn in the same place for later use in diagrams and animations. - hex_associate this procedure calculates the average scale of the two hexes which are adjacent to all internal springs and then uses this value to set that springs rest length. when the simulation is played the springs attempt to find the new equilibrium state for network thus distorting the previously regular hex-grid geometry. through experience this operation is most successful when the cubes on the outside edge of the springs net are set to active = 0 (off). note: the programming style adopted priveledges readablility and maintainability rather than pure code efficiency this approach was selected both because the script is being created and edited by two people and because the intention is that certain sections of code can be cut out as modules for use in future projects. */ //____________________________________________________________________________________________________________________ global proc hexCA_create (int $xSize, int $ySize, float $hexSize, float $randCut){ // if uncommented these lines select and delete all objects and keyframes remaining from previous iterations /* select -all; delete; */ //loop for each cell row following $ySize int $y = 0; while ($y < $ySize){ //loop for each cell column following $xSize int $x = 0; while ($x < $xSize){ // set up values for moving each created hex-grid object to its correct place in the hex-grid // a check of oddness, fascilitates the staggering of every second row to the right // $stagger will equal zero for the even rows, and half $hexSize for the odd rows int $isOdd = $y%2; float $stagger = $isOdd * $hexSize/2; float $moveX = $x*$hexSize + $stagger; float $moveY = $y*$hexSize*-cosd(30); //create a unique name for each object that refers to its position $name = "hex_" + $y + "_" + $x; //create the object, give it the unique name and then move it into position float $radius = abs(($hexSize/2)/cosd(30)); $tmp = `circle -n $name -c 0 0 0 -nr 0 0 1 -sw 360 -r $radius -d 1 -ut 0 -tol 0.1 -s 6 -ch 1`; move $moveX $moveY 0; // add custom attributes that will store information about the hex-grid object addAttr -ln status -at double $name; addAttr -ln oncount -at double $name; // the following section of code was used to connect the CA to different geometry based on clusters earlier // in the project - it remains (commented out) to facilitate a possible renewal of the exploration into that // type of geometry // set driven keys - assign the scale of the hex cell to the scale of the clusters /* setAttr ($name + ".scaleX") 1; setAttr ("cluster_" + $y + "_" + $x + ".scaleX") 1; setAttr ("cluster_" + $y + "_" + $x + ".scaleY") 1; setAttr ("cluster_" + $y + "_" + $x + ".scaleZ") 1; setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleX"); setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleY"); setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleZ"); setAttr ($name + ".scaleX") 0; setAttr ("cluster_" + $y + "_" + $x + ".scaleX") 0; setAttr ("cluster_" + $y + "_" + $x + ".scaleY") 0; setAttr ("cluster_" + $y + "_" + $x + ".scaleZ") 0; setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleX"); setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleY"); setDrivenKeyframe -cd ($name + ".scaleX") ("cluster_" + $y + "_" + $x + ".scaleZ"); */ //randomly turn some on $random = rand(0,100); if($random < $randCut) { //setAttr ($tmp[0] + ".visibility") on; setAttr ($tmp[0] + ".status") 1; setAttr ($tmp[0] + ".scale") 1 1 1; setAttr ($tmp[0] + ".oncount") 1; setKeyframe ($tmp[0] + ".scale"); setKeyframe ($tmp[0] + ".status"); }else{ //setAttr ($tmp[0] + ".visibility") off; setAttr ($tmp[0] + ".status") 0; setAttr ($tmp[0] + ".scale") 0 0 0; setAttr ($tmp[0] + ".oncount") 0; setKeyframe ($tmp[0] + ".scale"); setKeyframe ($tmp[0] + ".status"); } $x++; } $y++; } //keyframe all at 0 currentTime 0; //life_keyframe(); } print("hexCA_create loaded ..... Enjoy!\n"); ; //____________________________________________________________________________________________________________________ global proc hexCA_run(int $xSize, int $ySize, int $steps, int $proliferate){ int $step = 1; float $maxoncount = 1.0; int $frameNoPerCalc = 20; while($step < $steps){ //check each box and store in list to turn on or off int $x; int $y; int $check; string $onarray[]; string $offarray[]; string $onset; string $offset; select -cl; $onset = `sets`; select -cl; $offset = `sets`; $y =0; while($y < $ySize){ $x = 0; while($x < $xSize){ // this is where the axioms of the cellular automata appear and determine the behaviour of the system // the first rule determines if the cell being checked is 'lonely' float $tmp = hexCA_check($x,$y,$xSize,$ySize); print("this is the temp" + $tmp + "!"); if($tmp > 0 && $tmp < 0.45){ $string = "hex_" + $y + "_" + $x; print("on " + $string); sets -add $onset $string; setAttr ("hex_" + $y + "_" + $x + ".status") $tmp; setAttr ("hex_" + $y + "_" + $x + ".scale") $tmp $tmp $tmp; setKeyframe ("hex_" + $y + "_" + $x + ".scale"); setKeyframe ("hex_" + $y + "_" + $x + ".status"); } else if ($tmp >= 0.45 && $tmp < 0.55){ $string = "hex_" + $y + "_" + $x; print("middle " + $string); sets -add $onset $string; setAttr ("hex_" + $y + "_" + $x + ".status") 1; setAttr ("hex_" + $y + "_" + $x + ".scale") 1 1 1; setKeyframe ("hex_" + $y + "_" + $x + ".scale") ; setKeyframe ("hex_" + $y + "_" + $x + ".status"); } else if ($tmp >= 0.55 && $tmp < 0.65){ $string = "hex_" + $y + "_" + $x; sets -add $offset $string; setAttr ("hex_" + $y + "_" + $x + ".status") 0; setAttr ("hex_" + $y + "_" + $x + ".scale") 0 0 0; setKeyframe ("hex_" + $y + "_" + $x + ".scale") ; setKeyframe ("hex_" + $y + "_" + $x + ".status"); } else if ($tmp >= 0.65 && $tmp <= 0.9){ $string = "hex_" + $y + "_" + $x; print("on " + $string); sets -add $onset $string; setAttr ("hex_" + $y + "_" + $x + ".status") $tmp; setAttr ("hex_" + $y + "_" + $x + ".scale") $tmp $tmp $tmp; setKeyframe ("hex_" + $y + "_" + $x + ".scale") ; setKeyframe ("hex_" + $y + "_" + $x + ".status"); }else{ $string = "hex_" + $y + "_" + $x; sets -add $offset $string; setAttr ("hex_" + $y + "_" + $x + ".status") 0; setAttr ("hex_" + $y + "_" + $x + ".scale") 0 0 0; setKeyframe ("hex_" + $y + "_" + $x + ".scale") ; setKeyframe ("hex_" + $y + "_" + $x + ".status"); } $x++; } $y++; } $onarray = `sets -q $onset`; $offarray = `sets -q $offset`; print("Frame: " + ($step * 20) + "\n"); currentTime ($step * 20); // this part of the script creates copies of each state/generation that are then distributed as a // layered history of the life of the CA - or in order to be laser cut if (and only if) $proliferate // is set to 1 or 2 respectively. // check $proliferate state if($proliferate == 1 || $proliferate == 12){ // first create a new group for each genaration ready to receive copies of each cell in that genearation string $genGroupName = "gen_" + $step; group -n $genGroupName -em; // loop to select each hex-cell in turn, // then duplicate it and name its copy. // and then parent the copy to the group named according to its generation $y =0; while($y < $ySize){ $x = 0; while($x < $xSize){ string $hexCopyName = $genGroupName + "_hex_" + $y + "_" + $x; select ("hex_" + $y + "_" + $x); duplicate -n $hexCopyName; parent $hexCopyName $genGroupName; $x++; } $y++; } // test which proliferation mode and move entire generation accordingly // first test is for direct proliferation of each generation along the z-axis if($proliferate == 1){ nurbsSquare -c 9.6 -4 -2 -nr 0 0 1 -sl1 12 -sl2 24 -sps 1 -d 3 -ch 1 ; select -add $genGroupName; move 0 0 (2*$step); } } $step++; } } //____________________________________________________________________________________________________________________ global proc life_keyframe(){ select -all; $list = `ls -sl -tr`; $j = 0; while($j < size($list)){ setKeyframe ($list[$j] + ".v"); $j++; } } //____________________________________________________________________________________________________________________ global proc float hexCA_check(int $x, int $y,int $xSize, int $ySize){ float $total; float $lowerLimit = 0.1; float $upperLimit = 0.9; $plusx = (($x+1) % $xSize); if($x >= 1) $minusx = ($x-1); if($x < 1) $minusx = ($xSize-1); $plusy = (($y+1) % $ySize); if($y >= 1) $minusy = ($y-1); if($y < 1) $minusy = ($ySize-1); // calculate the neighbours of the hex cell $a = "hex_" + $minusy + "_" + $plusx; $b = "hex_" + $y + "_" + $plusx; $c = "hex_" + $plusy + "_" + $plusx; $d = "hex_" + $plusy + "_" + $x; $e = "hex_" + $y + "_" + $minusx; $f = "hex_" + $minusy + "_" + $x; $g = "hex_" + $y + "_" + $x; // rules for hex cell life // rule 01 - based on how many neighbours are on or off float $total = (hexCA_status($a) + hexCA_status($b) + hexCA_status($c) + hexCA_status($d) + hexCA_status($e) + hexCA_status($f) + hexCA_status($g))/7; if($total > $lowerLimit && $total < $upperLimit){ //print("total" + ($total) + "\n"); return $total; }else{ return 0; } return 0; } //____________________________________________________________________________________________________________________ global proc float hexCA_status(string $hexCell){ // this global procedure returns the status of each hex-cell float $v = `getAttr ($hexCell + ".status")`; return $v; } //__________________________________________________________________________________________________________________ global proc springCA_create (int $xSize, int $ySize, float $hexSize){ // if uncommented these lines select and delete all objects and keyframes remaining from previous iterations /* select -all; delete; */ // loop for each cell row following $ySize (note that the cell rows referred to here are the hex-cells // for this orientation of the hex-cells (point up) there are actually four rows of cubes (which make // up the vertices of each hex) for each row of hex-cells, but because two overlap, after the first row // of hex-cells the rest have only two rows of cubes each int $y = 1; while ($y <= $ySize) { //int $modulor = $y%2; //print("row" + $y + //loop for each cell column following $xSize int $x = 1; while ($x <= $xSize + 1) { // create a cube for each vertex of the hex grid and name it according to the three adjacent hex_cells // trigonometry is used to calculate the movement of each cube relative to the entered $hexSize // calculate trigonometric values for movement float $adj = $hexSize * 0.5; float $hyp = $adj / (cosd(30)); float $opp = $adj * tand(30); // calculate a stagger value (again for movement) that includes a test and allowance for odd rows float $stagger = (($y+1)%2) * 0.5 * $hexSize; // set up naming variables - minus signs will be represented by an underscore // as spacers: "_" appears between y and x, and "__" appears between hex-cell pairs string $cellRef = $y + "_" + $x; string $cellLeftRef = $y + "_" + ($x-1); string $cellRightRef = $y + "_" + ($x+1); string $cellBelowLeftRef = ($y+1) + "_" + ($x-1); string $cellBelowRightRef = ($y+1) + "_" + $x; string $cellAboveLeftRef = ($y-1) + "_" + ($x-1); string $cellAboveRightRef = ($y-1) + "_" + $x; // the first two rows of cubes (occuring on hex-cell row zero) have no neighbouring cells // above and so are created first as special cases // make the first 'special' row - there is one less cube in this row so exclude x = $xSize if ($y == 1 && $x != $xSize + 1){ string $cubeName = "cube" + $cellAboveLeftRef + "__" + $cellAboveRightRef + "__" + $cellRef; float $moveX = $x * $hexSize - $hexSize; float $moveY = -$y * cosd(30) * $hexSize + $hyp + $hexSize; $tmp = `polyCube -n $cubeName -w .1 -h .1 -d .1`; move $moveX $moveY 0; print("first row" + $x + "\n"); } // make the second 'special' row if ($y == 1){ $cubeName = "cube" + $cellAboveLeftRef + "__" + $cellLeftRef + "__" + $cellRef; $moveX = ($x - 0.5) * $hexSize - $hexSize; $moveY = -$y * cosd(30) * $hexSize + $opp + $hexSize; $tmp = `polyCube -n $cubeName -w .1 -h .1 -d .1`; move $moveX $moveY 0; } // now that the 'special cases' of the first two rows are done, make the rest of the rows of cubes // make the first standard row // the if stagger > 0 statement establishes whether the row is odd and changes the name if necessary $cubeName = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowLeftRef; if ($stagger > 0){ print("row is even" + $y + "\n"); $cubeName = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowRightRef; } $moveX = ($x - 0.5) * $hexSize + $stagger - $hexSize; $moveY = -$y * cosd(30) * $hexSize - $opp + $hexSize; $tmp = `polyCube -n $cubeName -w .1 -h .1 -d .1`; move $moveX $moveY 0; // next make the second standard row of cubes // the if/else statement prevents the additional cube that would be created in the last row int $lastRow = ($ySize); if(($y == $lastRow) && ($x == 1)){ print ("skipping cube!\n"); }else{ $cubeName = "cube" + $cellRef + "__" + $cellBelowLeftRef + "__" + $cellBelowRightRef; if ($stagger > 0){ print("row is even" + $y + "\n"); $cubeName = "cube" + $cellLeftRef + "__" + $cellBelowLeftRef + "__" + $cellBelowRightRef; } $moveX = $x * $hexSize - $stagger - $hexSize; $moveY = -$y * cosd(30) * $hexSize - $hyp + $hexSize; $tmp = `polyCube -n $cubeName -w .1 -h .1 -d .1`; move $moveX $moveY 0; } $x++; } $y++; } print ("springCA_create loaded ..... \n"); print ("\n"); print ("loading: springCA_attach .....\n"); print ("\n"); // call springCA_attach global procedure to attach springs to the cubes just created springCA_attach $xSize $ySize; } //__________________________________________________________________________________________________________________ global proc springCA_attach (int $xSize, int $ySize){ float $damping = 40; float $stiffness = 50; int $y = 1; while ($y <= $ySize) { //loop for each cell column following $xSize int $x = 1; while ($x <= $xSize+1) { // set up naming variables - minus signs will be represented by an underscore // as spacers: "_" appears between y and x, and "__" appears between hex-cell pairs string $cellRef = $y + "_" + $x; string $cellLeftRef = $y + "_" + ($x-1); string $cellRightRef = $y + "_" + ($x+1); string $cellBelowLeftRef = ($y+1) + "_" + ($x-1); string $cellBelowRightRef = ($y+1) + "_" + $x; string $cellAboveLeftRef = ($y-1) + "_" + ($x-1); string $cellAboveRightRef = ($y-1) + "_" + $x; string $cellBelowFarRightRef = ($y-1) + "_" + ($x+1); int $oddness = $y%2; // the first row of springs has no neighbours above it and so is added first as a special case // attach first special row of springs to existing cubes // there are two springs per cell in the first special row so exclude last loop ($x = $xSize + 1) if ($y == 1 && $x != $xSize + 1){ // in each loop connect spring for top left side of hex until all springs are added for the row string $cube01 = "cube" + $cellAboveLeftRef + "__" + $cellLeftRef + "__" + $cellRef; string $cube02 = "cube" + $cellAboveLeftRef + "__" + $cellAboveRightRef + "__" + $cellRef; string $cube03 = "cube" + $cellAboveRightRef + "__" + $cellRef + "__" + $cellRightRef; string $springName01 = "spring_" + $cellAboveLeftRef + "__" + $cellRef; string $springName02 = "spring_" + $cellAboveRightRef + "__" + $cellRef; select -r $cube01 $cube02; constrain -spring -st $stiffness -d $damping -i 0 -n $springName01; // do the same for the top right side of each hex select -r $cube02 $cube03; constrain -spring -st $stiffness -d $damping -i 0 -n $springName02; } // now attach the first standard row of springs // they run vertically and there is one more spring than there are hexes in each row (loop $x = $xSize remains) // reference names following conventions for odd rows $cube01 = "cube" + $cellAboveLeftRef + "__" + $cellLeftRef + "__" + $cellRef; $cube02 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowLeftRef; $springName01 = "spring_" + $cellLeftRef + "__" + $cellRef; // test if row is even and if so rename cube references so that the right cubes are joined by the springs if($oddness == 0){ $cube01 = "cube" + $cellAboveRightRef + "__" + $cellLeftRef + "__" + $cellRef; $cube02 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowRightRef; } select -r $cube01 $cube02; constrain -spring -st $stiffness -d $damping -i 0 -n $springName01; // now attach the second standard row of springs // there are two springs per cell this row so again exclude last loop ($x = $xSize) if($x != $xSize + 1){ // references for cubes in odd rows $cube01 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowLeftRef; $cube02 = "cube" + $cellRef + "__" + $cellBelowLeftRef + "__" + $cellBelowRightRef; $cube03 = "cube" + $cellRef + "__" + $cellRightRef + "__" + $cellBelowRightRef; $springName01 = "spring_" + $cellRef + "__" + $cellBelowLeftRef; $springName02 = "spring_" + $cellRef + "__" + $cellBelowRightRef; // test if row is even and if so rename cube references so that the right cubes are joined by the springs if($oddness == 0){ $cube01 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowRightRef; $cube02 = "cube" + $cellRef + "__" + $cellBelowRightRef + "__" + ($y+1) + "_" + ($x+1); $cube03 = "cube" + $cellRef + "__" + $cellRightRef + "__" + ($y+1) + "_" + ($x+1); $springName01 = "spring_" + $cellRef + "__" + $cellBelowRightRef; $springName02 = "spring_" + $cellRef + "__" + $cellBelowFarRightRef; } select -r $cube01 $cube02; constrain -spring -st $stiffness -d $damping -i 0 -n $springName01; select -r $cube02 $cube03; constrain -spring -st $stiffness -d $damping -i 0 -n $springName02; } // there is one spring that is not added at either end depending on whether the row is even or odd // add this spring if($oddness == 1 && $x == $xSize + 1){ $cube01 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowLeftRef; $cube02 = "cube" + $cellRef + "__" + $cellBelowLeftRef + "__" + $cellBelowRightRef; $springName01 = "spring_" + $cellRef + "__" + $cellBelowLeftRef; select -r $cube01 $cube02; constrain -spring -st $stiffness -d $damping -i 0 -n $springName01; } if($oddness == 0 && $x == 1 && $y != $ySize){ $cube01 = "cube" + $cellLeftRef + "__" + $cellBelowLeftRef + "__" + $cellBelowRightRef; $cube02 = "cube" + $cellLeftRef + "__" + $cellRef + "__" + $cellBelowRightRef; $springName01 = "spring_" + $cellLeftRef + "__" + $cellBelowRightRef; select -r $cube01 $cube02; constrain -spring -st $stiffness -d $damping -i 0 -n $springName01; } $x++; } $y++; } select -r "cluster*"; group -n allClusters; select -r "curve*"; group -n allCurves; print ("springCA_attach loaded ..... Enjoy!\n"); } //____________________________________________________________________________________________________________________ global proc hex_associate(float $scale){ // this procedure associates the scale of the adjacent hexes to the spring length int $numOfTokens; string $springName[]; string $springNameArray[]; float $hexScale01; float $hexScale02; float $hexValue; string $hex01; string $hex02; // get an array of the springs select -r "spring*"; $springName = `ls -sl`; print $springName; $i = 0; while( $i < size($springName)){ // tokenise $numOfTokens = tokenize ($springName[$i], "_", $springNameArray); print $springNameArray; // if it isn't on the edge then assign a rest length $hex01 = ("hex_" + $springNameArray[1] + "_" + $springNameArray[2]); $hex02 = ("hex_" + $springNameArray[3] + "_" + $springNameArray[4]); if(`objExists $hex01` && `objExists $hex02`){ // get hex scales $hexScale01 = `getAttr ("hex_" + $springNameArray[1] + "_" + $springNameArray[2] + ".scaleX")`; $hexScale02 = `getAttr ("hex_" + $springNameArray[3] + "_" + $springNameArray[4] + ".scaleX")`; $hexValue = ($scale*(($hexScale01 + $hexScale02) / 2)); // assign hex scale to spring rest length setAttr ($springName[$i] + ".springRestLength") $hexValue; } $i++; } print ("hex_associate loaded ..... Enjoy!\n"); } print ("hex_CA suite loaded ..... Enjoy!\n"); //____________________________________________________________________________________________________________________ // uncomment the next lines to allow the scripts to run automatically /* hexCA_create 20 10 1 35; hexCA_run 20 10 50 0; */ //or /* springCA_create 20 10 1; */ //or /* hex_associate 1; */