Skip to main content
Participant
June 12, 2014
Answered

adobe script for rotation and position

  • June 12, 2014
  • 3 replies
  • 1825 views

I am new to adobe script and actions (very new. like starting today, right now).

First I just want to know if what I'm trying to do it even possible.

Imagine a simple rectangle in photoshop.

I have a table of angles and coordinates (could be an an excel file or any kind of text file). let's say 10 rows. column A = angles and columns B and C are x and y coordinates, respectively.

I want to somehow have photoshop read this list, and make 10 layers that have the rectangle at the position and angle specified by each row of the table.

then, I want a timeline with 10 frames, each one having only the appropriate, sequential layer visible.

Is that possible?

If so, does anyone have any suggestions. I've never written script in adobe, but do have some programming experience in other oldschool languages.

and maybe a link that explain how to use the script once it's written?

thanks

This topic has been closed for replies.
Correct answer c.pfaffenbichler

Thank you for the tips.

So far I have been able to do basically what I need to do.

I have an xml file that has xy coordinates.

I have a layer with a circle.

I have successfully made a script that reads the xml file, duplicates the circle layer, names it 'nextcircle' + a number, moves it to the 'circles' group of layers, and then moves it to the correct xy location, loped for the number of coordinates. Right now I'm skipping the rotating because I'm practicing with a circle. After I get this done I'll try an ellipse add rotation angles to each pair of coordinates. I think I can handle that at this point.

But, I want to set up a timeline of frames and I can't seem to find any documentation about accessing the timeline in script.

Here's what i want to do. make a time line in with each of my layers in sequentially visible. So, in frame 1, only nextcircle1 is visible, in frame 2 only nextcircle2 is visible. etc.

Here is my code. There's probably a better way, but this is working mostly (although in reality I have to break it up into 10 coordinates at a time so that my photoshop didn't crash)

var doc=app.activeDocument

var circleLayer= doc.artLayers.getByName ("circle") //my circle that I will move around

var cLayer=[];

var baseName= "nextcircle" // the name for each duplicated layer

doc.activeLayer=circleLayer 

var circleSet = doc.layerSets.getByName ("circles"); I have a layer group called circles in which i will put each new layer

var f = new File('C:/Users/[me]/Documents/Adobe Scripts/path.xml')  // my xml file with coordinates for my circle to travel

f.open('r')

var pathxml = new XML(f.read())

f.close()

pathLen=pathxml.circlex.length() // gets the number of coordinates (

for (var i =1; i <=pathLen; i++){  // loops through the coordinate list

    var nm= baseName.concat(i.toString()); // name of new layer

    cLayer=circleLayer.duplicate (doc, ElementPlacement.PLACEATBEGINNING) //duplicates my circle

        with(cLayer) {

            name = nm  // names it

            }

     cLayer.moveToEnd(circleSet)  // moves the new layer to the top of the circles group

     var posx = Number(pathxml.circlex[i-1])  //extracts the x pos for the ith-1 value

     var posy = Number(pathxml.circley[i-1])  //extracts the y pos for the ith-1 value

     MoveLayerTo(cLayer,posx,posy)  //moves to the new location (I copied this function from somewhere)

     }

function MoveLayerTo(fLayer,fX,fY) {

  var Position = fLayer.bounds;

  Position[0] = fX - Position[0];

  Position[1] = fY - Position[1];

  fLayer.translate(-Position[0],-Position[1]);

}


This would create a frame animated based on the Layers inside the topmost LayerSet.

It assumes that the file does not have animation yet.

// 2014, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var myDocument = app.activeDocument;

// define the layers;

var theLayers = myDocument.layerSets[0].layers;

// hide all except topmost layer;

hideOthers (theLayers[0], myDocument);

// make frame animation;

// =======================================================

var idmakeFrameAnimation = stringIDToTypeID( "makeFrameAnimation" );

executeAction( idmakeFrameAnimation, undefined, DialogModes.NO );

// set frame rate;

// =======================================================

var idsetd = charIDToTypeID( "setd" );

    var desc10 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref9 = new ActionReference();

        var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref9.putEnumerated( idanimationFrameClass, idOrdn, idTrgt );

    desc10.putReference( idnull, ref9 );

    var idT = charIDToTypeID( "T  " );

        var desc11 = new ActionDescriptor();

        var idanimationFrameDelay = stringIDToTypeID( "animationFrameDelay" );

        desc11.putDouble( idanimationFrameDelay, 0.100000 );

    var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

    desc10.putObject( idT, idanimationFrameClass, desc11 );

executeAction( idsetd, desc10, DialogModes.NO );

// work through layers;

for (var m = 1; m < theLayers.length; m++) {

// =======================================================

var idDplc = charIDToTypeID( "Dplc" );

    var desc7 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref6 = new ActionReference();

        var idanimationFrameClass = stringIDToTypeID( "animationFrameClass" );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref6.putEnumerated( idanimationFrameClass, idOrdn, idTrgt );

    desc7.putReference( idnull, ref6 );

executeAction( idDplc, desc7, DialogModes.NO );

// hide others;

hideOthers (myDocument.activeLayer, myDocument);

hideOthers (theLayers, myDocument);

};

};

////// toggle visibility of others //////

function hideOthers (theLayer, myDocument) {

theLayer.visible = true;

myDocument.activeLayer = theLayer;

// =======================================================

var idShw = charIDToTypeID( "Shw " );

    var desc10 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var list4 = new ActionList();

            var ref7 = new ActionReference();

            var idLyr = charIDToTypeID( "Lyr " );

            var idOrdn = charIDToTypeID( "Ordn" );

            var idTrgt = charIDToTypeID( "Trgt" );

            ref7.putEnumerated( idLyr, idOrdn, idTrgt );

        list4.putReference( ref7 );

    desc10.putList( idnull, list4 );

    var idTglO = charIDToTypeID( "TglO" );

    desc10.putBoolean( idTglO, true );

executeAction( idShw, desc10, DialogModes.NO );

};

3 replies

c.pfaffenbichler
Community Expert
Community Expert
June 14, 2014

What is the content of the text file exactly?

Inspiring
June 13, 2014

Reading in a text file is straight forward:

var dataPath = "C:\\temp";

var list = "myTextFile.txt";

// read the master array and put it to an array

var textArray = readFile(dataPath, list);

alert(textArray[0]);

function readFile(inPath, inFile)

{

    //read in file

    var theFile = new File(inPath + "/" + inFile);

    // declare new empty array

    var myArray = new Array();

    var textFile = new File(theFile);

    // read the file

    textFile.open('r');

    while(!textFile.eof)

    {

      var line = textFile.readln();

      if (line != null && line.length >0)

      {

        myArray.push(line);

      }

    }

    // close the file

    textFile.close();

    return myArray

}

anp12Author
Participant
June 12, 2014

ok, so I've gotten this far. Rotating and moving layers seems easy enough. Soon I'll figure out how to copy layers.

var doc=app.activeDocument

var rectangleLayer= doc.artLayers.getByName ("rectangle")

var myAnchor = rectangleLayer.anchor

doc.activeLayer=rectangleLayer

rectangleLayer.rotate (36, mouseAnchor) /*rotate 36 degrees*/

MoveLayer(mouseLayer,200,200)         /* move to (200,200), based on the rulers. in my case, pixels */

function MoveLayer(fLayer,fX,fY) {

  var Position = fLayer.bounds;

  Position[0] = fX - Position[0];

  Position[1] = fY - Position[1];

  fLayer.translate(-Position[0],-Position[1]);

}

But, I'm still not sure how to import the values for the positions and the angles

c.pfaffenbichler
Community Expert
Community Expert
June 13, 2014

It is not so good to provide the first post in a thread one has started oneself. Edit: At least that’s my opinion on this issue.

The Forum has been made worse recently in some regards, one of which makes it less easy to notice that the OP has posted a reply and not someone else.

Anyways, maybe this helps.

It uses and array or arrays of the basis of the transformation of the active layer.

// 2014, use it at your own risk;

#target photoshop

if (app.documents.length > 0) {

var originalRulerUnits = app.preferences.rulerUnits;

app.preferences.rulerUnits = Units.PIXELS;

var myDocument = app.activeDocument;

var theLayer = smartify2010 (myDocument.activeLayer);

var theW = theLayer.bounds[2] - theLayer.bounds[0];

var theH = theLayer.bounds[3] - theLayer.bounds[1];

var theCenter = [theLayer.bounds[0] + theW/2, theLayer.bounds[1] + theH/2];

var theValues = [[0, 0, 15], [100, 100, 30], [300, 300, 45]];

for (var m = 0; m < theValues.length; m++) {

myDocument.activeLayer = theLayer;

duplicateMoveRotateScale (theValues[0] - Number(theCenter[0]), theValues[1] - Number(theCenter[1]), 100, 100, theValues[2]);

};

app.preferences.rulerUnits = originalRulerUnits;

};

////// duplicate and transform layer //////

function duplicateMoveRotateScale (theX, theY, theScaleX, theScaleY, theRotation) {

try{

// =======================================================

var idTrnf = charIDToTypeID( "Trnf" );

    var desc10 = new ActionDescriptor();

    var idnull = charIDToTypeID( "null" );

        var ref6 = new ActionReference();

        var idLyr = charIDToTypeID( "Lyr " );

        var idOrdn = charIDToTypeID( "Ordn" );

        var idTrgt = charIDToTypeID( "Trgt" );

        ref6.putEnumerated( idLyr, idOrdn, idTrgt );

    desc10.putReference( idnull, ref6 );

    var idFTcs = charIDToTypeID( "FTcs" );

    var idQCSt = charIDToTypeID( "QCSt" );

    var idQcsa = charIDToTypeID( "Qcsa" );

    desc10.putEnumerated( idFTcs, idQCSt, idQcsa );

    var idOfst = charIDToTypeID( "Ofst" );

        var desc11 = new ActionDescriptor();

        var idHrzn = charIDToTypeID( "Hrzn" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc11.putUnitDouble( idHrzn, idPxl, theX );

        var idVrtc = charIDToTypeID( "Vrtc" );

        var idPxl = charIDToTypeID( "#Pxl" );

        desc11.putUnitDouble( idVrtc, idPxl, theY );

    var idOfst = charIDToTypeID( "Ofst" );

    desc10.putObject( idOfst, idOfst, desc11 );

    var idWdth = charIDToTypeID( "Wdth" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc10.putUnitDouble( idWdth, idPrc, theScaleX );

    var idHght = charIDToTypeID( "Hght" );

    var idPrc = charIDToTypeID( "#Prc" );

    desc10.putUnitDouble( idHght, idPrc, theScaleY );

    var idAngl = charIDToTypeID( "Angl" );

    var idAng = charIDToTypeID( "#Ang" );

    desc10.putUnitDouble( idAngl, idAng, theRotation );

    var idIntr = charIDToTypeID( "Intr" );

    var idIntp = charIDToTypeID( "Intp" );

    var idbicubicAutomatic = stringIDToTypeID( "bicubicAutomatic" );

    desc10.putEnumerated( idIntr, idIntp, idbicubicAutomatic );

    var idCpy = charIDToTypeID( "Cpy " );

    desc10.putBoolean( idCpy, true );

executeAction( idTrnf, desc10, DialogModes.NO );

} catch (e) {}

};

////// function to smartify if not //////

function smartify2010 (theLayer) {

// make layers smart objects if they are not already;

  app.activeDocument.activeLayer = theLayer;

// process pixel-layers and groups;

      if (theLayer.kind == "LayerKind.GRADIENTFILL" || theLayer.kind == "LayerKind.LAYER3D" || theLayer.kind == "LayerKind.NORMAL" ||

      theLayer.kind == "LayerKind.PATTERNFILL" || theLayer.kind == "LayerKind.SOLIDFILL" ||

      theLayer.kind == "LayerKind.TEXT" || theLayer.kind == "LayerKind.VIDEO" || theLayer.typename == "LayerSet") {

  var id557 = charIDToTypeID( "slct" );

  var desc108 = new ActionDescriptor();

  var id558 = charIDToTypeID( "null" );

  var ref77 = new ActionReference();

  var id559 = charIDToTypeID( "Mn  " );

  var id560 = charIDToTypeID( "MnIt" );

  var id561 = stringIDToTypeID( "newPlacedLayer" );

  ref77.putEnumerated( id559, id560, id561 );

  desc108.putReference( id558, ref77 );

  executeAction( id557, desc108, DialogModes.NO )

  return app.activeDocument.activeLayer

  }

  if (theLayer.kind == LayerKind.SMARTOBJECT || theLayer.kind == "LayerKind.VIDEO") {return theLayer};

  };