//***********Replicate as Spine, version 2
//  this script will take a selected solid and replicate it upward into an animatable spine;
//  each vertebra is parented to the one below it, and each vertebra above the lowermost (base) vertebra
//  has an expression that is linked to the base vertebra's x rotation.
//***********//
var cancelledOut = false;

function askForNumber(thePrompt, theDefault) {
   gotANum = false;
   while (! gotANum) {
      p = prompt(thePrompt, theDefault);
      if (p == null) {
         cancelledOut = true;
         gotANum = true;//just to get us out of loop
      } else {
         if (! isNaN(p)) {
               gotANum = true;
         }
      }
   }
   //needs to NOT be a string, so we parseFloat:
   return parseFloat(p);
}

function mainSpine()
{
	// make sure a comp is selected
	var activeItem = app.project.activeItem;
	if (activeItem == null || !(activeItem instanceof CompItem)){
		alert("You need to select one layer first.");
	} else {

		// make sure just one layer is selected
		var selectedLayers = activeItem.selectedLayers;
		var selNum = activeItem.selectedLayers.length;
		if (!(selNum == 1)) {
			if (selNum == 0) {selNum = "No"} 
			alert(selNum + " layers selected. You need to select just one layer first.");
		} else {
			
			// make sure it is not a light, camera; must be solid or footage item
			if (selectedLayers[0].adjustmentLayer == undefined) {
            
            alert("Selected layer not valid (must not be a camera or light).");
            
			} else {
            
            vn = 0;
            while (vn < 2) {
              vn = askForNumber("Enter number of vertebrae:", "10");
            }
            if (! cancelledOut) {
               vOlap = askForNumber("Enter overlap amount (in pixels. Zero means no overlap; negative number creates spacing):", "2");
               if (! cancelledOut) {
                  app.beginUndoGroup("spine creation");
                  
                  vNa = "vertabra";
                  vShy = true;
                  
                  baseLayer = selectedLayers[0];
                  
                  // (if not 3D layer, make it one)
                  if (!baseLayer.threeDLayer) {baseLayer.threeDLayer = true} ;
                  
                  // rename to 'base vertebra'
                  vZeroName = ("base " + vNa);
                  baseLayer.name = vZeroName;
                  
                  
                  lastLayer = baseLayer;
                  lastLayerHtOffset = lastLayer.height;
                  
                  //change anchor point to bottom of layer
                  ap = lastLayer.property("Anchor Point").value;
                  lastLayer.property("Anchor Point").setValue( [ap[0], (lastLayerHtOffset), ap[2]] );
                  
                  newLayer = baseLayer.duplicate();
                  newLayer.name = (vNa + "_" + "1");
                  
                  for (i = 1; i < (vn); ++i) {
                     /////LAYER ITEM ADJUSTMENTS/////
                     
                     if (i > 1) {
                        newLayer = newLayer.duplicate();
                        newLayer.name = (vNa + "_" + i);
                                                
                        //move new layer to above last layer
                        newLayer.moveBefore(lastLayer);
                     }
                     
                     /////PROPERTY ADJUSTMENTS/////
                     
                     //this is a little inefficient, but i want to use it for nonreplicating
                     //version (which uses selected layer group, with layers possibly at different heights):
                     
                     p = lastLayer.property("Position").value;
                     
                     newLayer.property("Position").setValue([ p[0], (p[1] - lastLayerHtOffset + vOlap), p[2] ]);
                     
                     //add x rot expression to new layer
                     newLayer.property("rotationX").expression = 'thisComp.layer("' +  vZeroName + '").rotationX;';
                     
                     lastLayer = newLayer;  ///// now we have a reference to this layer to use at next iteration as last layer
                     lastLayerHtOffset = lastLayer.height;
                  }
                  
                  baseIndex = baseLayer.index;
                  
                  for (n = baseIndex; n > (baseIndex - (vn - 1)); --n) {
                     childL = activeItem.layer(n - 1);
                     parentL = activeItem.layer(n);
                     childL.parent = parentL;
                     if (vShy == true) {childL.shy = true} ;
                  }
                  
                  app.endUndoGroup();
               }
            }
         }
      }
	}
}

mainSpine();

