Skip to main content
Participating Frequently
April 17, 2019
質問

Rotate layers incremental script

  • April 17, 2019
  • 返信数 1.
  • 4349 ビュー

hello!

I have 8 layers (photos) each one rotated 45º.

I want counter rotate all layers automatically but I don’t know how do a script that rotate each layer incrementally

something like:

layer.index * 45

result

layer0 = 0º

layer1 = 45º

layer2 = 90º

layer3 = 135º

...

layer8 = 315º

it would be nice a menu to indicate angle of rotation and a checkbox for clockwise or counterclockwise

Thanks!

このトピックへの返信は締め切られました。

返信数 1

JJMack
Community Expert
Community Expert
April 17, 2019

It is easy to rotate a layer about a point.  You need to know what x,y point  and the angle.  You can use layer bounds to get the anchor points for the layer.  The rotation point can be any x,y point you want to use.  Make the layer the active layer and use a function like this this rotate the layer.  To code your dialog will be much more complex.

function rotateAroundPosition(_angle,x,y) { 

    var desc1 = new ActionDescriptor(); 

    var desc2 = new ActionDescriptor(); 

    var ref1 = new ActionReference(); 

    ref1.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt')); 

    desc1.putReference(charIDToTypeID('null'), ref1); 

    desc1.putEnumerated(charIDToTypeID('FTcs'), charIDToTypeID('QCSt'), stringIDToTypeID("QCSIndependent")); 

    desc2.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x); 

    desc2.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y); 

    desc1.putObject(charIDToTypeID('Pstn'), charIDToTypeID('Pnt '), desc2); 

    desc1.putUnitDouble(charIDToTypeID('Angl'), charIDToTypeID('#Ang'), _angle); 

    desc1.putEnumerated(charIDToTypeID('Intr'), charIDToTypeID('Intp'), charIDToTypeID('Bcbc')); 

    executeAction(charIDToTypeID('Trnf'), desc1, DialogModes.NO); 

}

JJMack
edene8699004作成者
Participating Frequently
April 17, 2019

Wow thanks for your response and time!

I did not thought that was need too much code only for rotate a layer from center point! Amazing

Your code will rotate all layers selected incrementally automatically? I mean if I selected 7 layers of my 8 layers (layer 0 no need be rotated), each layer will rotate 45º incrementally: layer 1 = 45º, Layer 2 = 90º, Layer 3 = 135º .... Layer 7 = 315º ?

I tried to put your code to a .js file, select a layer and launch but seems that nothing happen. Maybe I need to change something in script to work...

Thanks!

JJMack
Community Expert
Community Expert
April 17, 2019

You need to pass the function three variables +-Angle the X point position and the y point position. anf the layer yow want toe be rotated need to be the document active layer.

The function is used in my rotate layers about script.  A script the duplicates a layer and rotate it about poins  a number of times to do full 360 rotation.

// 2015  John J. McAssey (JJMack)

// ======================================================= */

// This script is supplied as is. It is provided as freeware.

// The author accepts no liability for any problems arising from its use.

// enable double-clicking from Mac Finder or Windows Explorer

#target photoshop // this command only works in Photoshop CS2 and higher

// bring application forward for double-click events

app.bringToFront();

// ensure at least one document open

if (!documents.length) alert('There are no documents open.', 'No Document');

else {

//Set First Time Defaults here

var dfltCpys = 12; // default number of copies including the original

var dfltPos = 4; // default Middle Center

//End Defaults

var Prefs ={}; //Object to hold preferences.

var prefsFile = File(Folder.temp + "/RotateLayerAboutPreferences.dat");

//If preferences do not exit use Defaults from above

if(!prefsFile.exists){

Prefs.Cpys  = dfltCpys;

Prefs.Pos  = dfltPos;

prefsFile.open('w');

prefsFile.write(Prefs.toSource());

prefsFile.close();

}

else{//Preferences exist so open them

prefsFile.open('r');

Prefs = eval(prefsFile.read());

prefsFile.close();

}

try {

function createDialog(){

// begin dialog layout

var DupRotateDialog = new Window('dialog');

DupRotateDialog.text = 'Duplicate and Rotate Layer';

DupRotateDialog.frameLocation = [78, 100];

DupRotateDialog.alignChildren = 'center';

DupRotateDialog.NumLayerPnl = DupRotateDialog.add('panel', [2, 2, 300, 56], 'Number of Layers and Rotation Anchor Point');

DupRotateDialog.NumLayerPnl.add('statictext', [10, 16, 50, 48], 'Copies ');

DupRotateDialog.NumLayerPnl.imgCpysEdt = DupRotateDialog.NumLayerPnl.add('edittext', [50, 13, 90, 34], Prefs.Cpys, {name:'imgCpys'});

DupRotateDialog.NumLayerPnl.imgCpysEdt.helpTip = 'Number of copies of selected Layer';

DupRotateDialog.NumLayerPnl.add('statictext',[96, 16, 240, 48],'Location');

var position =['Top Left','Top Center','Top Right','Center Left','Center','Center Right','Bottom Left','Bottom Center','Bottom Right','Doc Center','Samples','Path Points'];

DupRotateDialog.NumLayerPnl.dd1 = DupRotateDialog.NumLayerPnl.add('dropdownlist',[150, 13, 260, 34],position);

DupRotateDialog.NumLayerPnl.dd1.selection=Prefs.Pos;

var buttons = DupRotateDialog.add('group');

buttons.orientation = 'row';

var okBtn = buttons.add('button');

okBtn.text = 'OK';

okBtn.properties = {name: 'ok'};

var cancelBtn = buttons.add('button');

cancelBtn.text = 'Cancel';

cancelBtn.properties = {name: 'cancel'};

return DupRotateDialog;

}

dispdlg(createDialog());

function dispdlg(DupRotateDialog){

// display dialog and only continues on OK button press (OK = 1, Cancel = 2)

DupRotateDialog.onShow = function() {

var ww = DupRotateDialog.bounds.width; 

var hh = DupRotateDialog.bounds.height; 

DupRotateDialog.bounds.x  = 78; 

DupRotateDialog.bounds.y  = 100; 

DupRotateDialog.bounds.width  = ww; 

DupRotateDialog.bounds.height  = hh; 

}

if (DupRotateDialog.show() == 1) {

//variables passed from user interface

var copies = String(DupRotateDialog.NumLayerPnl.imgCpys.text); if (copies=="") { copies = Prefs.Cpys;}

if (isNaN(copies)) { alert("Non numeric value entered"); dispdlg(createDialog());}

else {

if (copies<2 || copies>360) { alert("Number of layer allow is 2 to 360"); dispdlg(createDialog());}  // Not in range

else {

var AnchorPoint = Number(DupRotateDialog.NumLayerPnl.dd1.selection.index) + 1;

cTID = function(s) { return app.charIDToTypeID(s); };

sTID = function(s) { return app.stringIDToTypeID(s); };

// Save the current preferences

Prefs.Cpys  = copies;

Prefs.Pos  = Number(DupRotateDialog.NumLayerPnl.dd1.selection.index);

prefsFile.open('w');

prefsFile.write(Prefs.toSource());

prefsFile.close();

var startRulerUnits = app.preferences.rulerUnits;

var startTypeUnits = app.preferences.typeUnits;

var startDisplayDialogs = app.displayDialogs;

// Set Photoshop to use pixels and display no dialogs

app.preferences.rulerUnits = Units.PIXELS;

app.preferences.typeUnits = TypeUnits.PIXELS;

app.displayDialogs = DialogModes.NO;

app.togglePalettes();

try { app.activeDocument.suspendHistory('RotateLayerAbout','main(copies, AnchorPoint)' );}

catch(e) {alert(e + ': on line ' + e.line);}

// Return the app preferences

app.togglePalettes();

app.preferences.rulerUnits = startRulerUnits;

app.preferences.typeUnits = startTypeUnits;

app.displayDialogs = startDisplayDialogs;

}

}

}

else {

//alert('Operation Canceled.');

}

}

}

catch(err){

// Lot's of things can go wrong, Give a generic alert and see if they want the details

if ( confirm("Sorry, something major happened and I can't continue! Would you like to see more info?" ) ) { alert(err + ': on line ' + err.line ); }

}

}

function main(stemsAmount, Position) {

if  (  Position == 11 && app.activeDocument.colorSamplers.length==0 ) {

alert("No Color Sampler set");

return;

}

if  (  Position == 12 ) {

var thePath = selectedPath();

if (thePath == undefined) {

alert("No Path Selected");

return;

}

var myPathInfo = extractSubPathInfo(thePath); 

}

// Save selected layer to variable:

var originalStem = app.activeDocument.activeLayer;

// Run the copying process

if(stemsAmount != null){

// Calculate the rotation angle

var angle = 360 / parseInt(stemsAmount);

// Create a group for stems

var stemsGroup = app.activeDocument.layerSets.add();

stemsGroup.name = originalStem.name + " ("+stemsAmount+" stems)";

// Place original layer in group

originalStem.move(stemsGroup, ElementPlacement.INSIDE);

// Duplicate and rotate layers:

for(var i = 1; i < stemsAmount; i++){

// Duplicate original layer and save it to the variable

var newStem = originalStem.duplicate();

// Rotate new layer

switch (Position){

case 1 : newStem.rotate(angle * i, AnchorPosition.TOPLEFT); break;

case 2 : newStem.rotate(angle * i, AnchorPosition.TOPCENTER); break;

case 3 : newStem.rotate(angle * i, AnchorPosition.TOPRIGHT); break;

case 4 : newStem.rotate(angle * i, AnchorPosition.MIDDLELEFT); break;

case 5 : newStem.rotate(angle * i, AnchorPosition.MIDDLECENTER); break;

case 6 : newStem.rotate(angle * i, AnchorPosition.MIDDLERIGHT); break;

case 7 : newStem.rotate(angle * i, AnchorPosition.BOTTOMLEFT); break;

case 8 : newStem.rotate(angle * i, AnchorPosition.BOTTOMCENTER); break;

case 9 : newStem.rotate(angle * i, AnchorPosition.BOTTOMRIGHT); break;

case 10 : app.activeDocument.activeLayer = newStem; rotateAroundPosition(angle * i,activeDocument.width/2,activeDocument.height/2); break;

case 11 : for (var s=0,len=app.activeDocument.colorSamplers.length;s<len;s++) {

if (s!=0) {

// Duplicate original layer and save it to the variable

var newStem = originalStem.duplicate();

}

newStem.name = originalStem.name + " " + (i+1) + " p" + (s+1) ;

app.activeDocument.activeLayer = newStem;

var colorSamplerRef = app.activeDocument.colorSamplers;

//alert("angle=" + (angle * i) +  " ,x=" + colorSamplerRef.position[0].value + " ,y=" + colorSamplerRef.position[1].value);

rotateAroundPosition(angle * i,colorSamplerRef.position[0].value,colorSamplerRef.position[1].value);

newStem.move(stemsGroup, ElementPlacement.PLACEATEND);

                };

break;

case 12 : for(var k=0;k<myPathInfo.length;k++){ 

for(var j=0;j<myPathInfo.entireSubPath.length;j++){

if (k!=0 || j!=0) {

// Duplicate original layer and save it to the variable

var newStem = originalStem.duplicate();

}

newStem.name = originalStem.name + " " + (i+1) + " p" + (j+1) ;

app.activeDocument.activeLayer = newStem;

rotateAroundPosition(angle * i,myPathInfo.entireSubPath.anchor[0],myPathInfo.entireSubPath.anchor[1]);

newStem.move(stemsGroup, ElementPlacement.PLACEATEND);

}

}

break;

default : break;

}

// Add index to new layers

if (Position!=11) {

newStem.name = originalStem.name + " " + (i+1);

// Place new layer inside stems group

newStem.move(stemsGroup, ElementPlacement.PLACEATEND);

}

};

// Add index to the original layer

if (Position!=11) originalStem.name += " 1";

else originalStem.name += " 1 p1";

};

activeDocument.activeLayer = activeDocument.layers[0]; // Target top

var groupname = app.activeDocument.activeLayer.name // remember name of group 

var idungroupLayersEvent = stringIDToTypeID( "ungroupLayersEvent" ); // this part from  Script Listene -- ungroup group 

var desc14 = new ActionDescriptor(); 

var idnull = charIDToTypeID( "null" ); 

var ref13 = new ActionReference(); 

var idLyr = charIDToTypeID( "Lyr " ); 

var idOrdn = charIDToTypeID( "Ordn" ); 

var idTrgt = charIDToTypeID( "Trgt" ); 

ref13.putEnumerated( idLyr, idOrdn, idTrgt ); 

desc14.putReference( idnull, ref13 ); 

executeAction( idungroupLayersEvent, desc14, DialogModes.NO ); 

var idMk = charIDToTypeID( "Mk  " ); // this part from  Script Listene --  group selected layers 

var desc15 = new ActionDescriptor(); 

var idnull = charIDToTypeID( "null" ); 

var ref14 = new ActionReference(); 

var idlayerSection = stringIDToTypeID( "layerSection" ); 

ref14.putClass( idlayerSection ); 

desc15.putReference( idnull, ref14 ); 

var idFrom = charIDToTypeID( "From" ); 

var ref15 = new ActionReference(); 

var idLyr = charIDToTypeID( "Lyr " ); 

var idOrdn = charIDToTypeID( "Ordn" ); 

var idTrgt = charIDToTypeID( "Trgt" ); 

ref15.putEnumerated( idLyr, idOrdn, idTrgt ); 

desc15.putReference( idFrom, ref15 ); 

executeAction( idMk, desc15, DialogModes.NO ); 

app.activeDocument.activeLayer.name = groupname // recall group name 

}

function rotateAroundPosition(_angle,x,y) { 

    var desc1 = new ActionDescriptor(); 

    var desc2 = new ActionDescriptor(); 

    var ref1 = new ActionReference(); 

    ref1.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt')); 

    desc1.putReference(charIDToTypeID('null'), ref1); 

    desc1.putEnumerated(charIDToTypeID('FTcs'), charIDToTypeID('QCSt'), stringIDToTypeID("QCSIndependent")); 

    desc2.putUnitDouble(charIDToTypeID('Hrzn'), charIDToTypeID('#Pxl'), x); 

    desc2.putUnitDouble(charIDToTypeID('Vrtc'), charIDToTypeID('#Pxl'), y); 

    desc1.putObject(charIDToTypeID('Pstn'), charIDToTypeID('Pnt '), desc2); 

    desc1.putUnitDouble(charIDToTypeID('Angl'), charIDToTypeID('#Ang'), _angle); 

    desc1.putEnumerated(charIDToTypeID('Intr'), charIDToTypeID('Intp'), charIDToTypeID('Bcbc')); 

    executeAction(charIDToTypeID('Trnf'), desc1, DialogModes.NO); 

}

////// determine selected path //////

function selectedPath () {

try {

var ref = new ActionReference();

ref.putEnumerated( charIDToTypeID("Path"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );

var desc = executeActionGet(ref);

var theName = desc.getString(charIDToTypeID("PthN"));

return app.activeDocument.pathItems.getByName(theName)

}

catch (e) {

return undefined

}

};

////// michael l hale’s code //////

function extractSubPathInfo(pathObj){ 

    var pathArray = new Array();// each element can be used as the second arugment in pathItems.add ie doc.pathItems.add("myPath1", [pathArray[0]]); 

    var pl = pathObj.subPathItems.length; 

    for(var s=0;s<pl;s++){ 

        var pArray = new Array(); 

          for(var i=0;i<pathObj.subPathItems.pathPoints.length;i++){ 

             pArray = new PathPointInfo; 

             pArray.kind = pathObj.subPathItems.pathPoints.kind; 

             pArray.anchor = pathObj.subPathItems.pathPoints.anchor; 

//alert("Anchor " + pathObj.subPathItems.pathPoints.anchor );

             pArray.leftDirection = pathObj.subPathItems.pathPoints.leftDirection; 

             pArray.rightDirection = pathObj.subPathItems.pathPoints.rightDirection; 

          }; 

        pathArray[pathArray.length] = new Array(); 

        pathArray[pathArray.length - 1] = new SubPathInfo(); 

        pathArray[pathArray.length - 1].operation = pathObj.subPathItems.operation; 

        pathArray[pathArray.length - 1].closed = pathObj.subPathItems.closed; 

        pathArray[pathArray.length - 1].entireSubPath = pArray; 

    }; 

    return pathArray; 

};

Higher resolution work better

JJMack